WERROR _wkssvc_NetWkstaGetInfo(struct pipes_struct *p, struct wkssvc_NetWkstaGetInfo *r) { switch (r->in.level) { case 100: /* Level 100 can be allowed from anyone including anonymous * so no access checks are needed for this case */ r->out.info->info100 = create_wks_info_100(p->mem_ctx); if (r->out.info->info100 == NULL) { return WERR_NOMEM; } break; case 101: /* Level 101 can be allowed from any logged in user */ if (!nt_token_check_sid(&global_sid_Authenticated_Users, p->session_info->security_token)) { DEBUG(1,("User not allowed for NetWkstaGetInfo level " "101\n")); DEBUGADD(3,(" - does not have sid for Authenticated " "Users %s:\n", sid_string_dbg( &global_sid_Authenticated_Users))); security_token_debug(DBGC_CLASS, 3, p->session_info->security_token); return WERR_ACCESS_DENIED; } r->out.info->info101 = create_wks_info_101(p->mem_ctx); if (r->out.info->info101 == NULL) { return WERR_NOMEM; } break; case 102: /* Level 102 Should only be allowed from a domain administrator */ if (!nt_token_check_sid(&global_sid_Builtin_Administrators, p->session_info->security_token)) { DEBUG(1,("User not allowed for NetWkstaGetInfo level " "102\n")); DEBUGADD(3,(" - does not have sid for Administrators " "group %s, sids are:\n", sid_string_dbg(&global_sid_Builtin_Administrators))); security_token_debug(DBGC_CLASS, 3, p->session_info->security_token); return WERR_ACCESS_DENIED; } r->out.info->info102 = create_wks_info_102(p->mem_ctx); if (r->out.info->info102 == NULL) { return WERR_NOMEM; } break; default: return WERR_UNKNOWN_LEVEL; } return WERR_OK; }
/** * prints a struct auth_session_info security token to debug output. */ void auth_session_info_debug(int dbg_lev, const struct auth_session_info *session_info) { if (!session_info) { DEBUG(dbg_lev, ("Session Info: (NULL)\n")); return; } security_token_debug(0, dbg_lev, session_info->security_token); }
void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, const struct security_token *token) { struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; /* Set the security context */ DEBUG(4, ("setting sec ctx (%u, %u) - sec_ctx_stack_ndx = %d\n", (unsigned int)uid, (unsigned int)gid, sec_ctx_stack_ndx)); security_token_debug(DBGC_CLASS, 5, token); debug_unix_user_token(DBGC_CLASS, 5, uid, gid, ngroups, groups); /* Change uid, gid and supplementary group list. */ set_unix_security_ctx(uid, gid, ngroups, groups); ctx_p->ut.ngroups = ngroups; SAFE_FREE(ctx_p->ut.groups); if (token && (token == ctx_p->token)) { smb_panic("DUPLICATE_TOKEN"); } TALLOC_FREE(ctx_p->token); if (ngroups) { ctx_p->ut.groups = (gid_t *)memdup(groups, sizeof(gid_t) * ngroups); if (!ctx_p->ut.groups) { smb_panic("memdup failed"); } } else { ctx_p->ut.groups = NULL; } if (token) { ctx_p->token = dup_nt_token(NULL, token); if (!ctx_p->token) { smb_panic("dup_nt_token failed"); } } else { ctx_p->token = NULL; } ctx_p->ut.uid = uid; ctx_p->ut.gid = gid; /* Update current_user stuff */ current_user.ut.uid = uid; current_user.ut.gid = gid; current_user.ut.ngroups = ngroups; current_user.ut.groups = groups; current_user.nt_user_token = ctx_p->token; }
/* drsuapi_DsReplicaGetInfo */ static WERROR dcesrv_drsuapi_DsReplicaGetInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx, struct drsuapi_DsReplicaGetInfo *r) { enum security_user_level level; if (!lp_parm_bool(dce_call->conn->dce_ctx->lp_ctx, NULL, "drs", "disable_sec_check", false)) { level = security_session_user_level(dce_call->conn->auth_state.session_info); if (level < SECURITY_ADMINISTRATOR) { DEBUG(1,(__location__ ": Administrator access required for DsReplicaGetInfo\n")); security_token_debug(2, dce_call->conn->auth_state.session_info->security_token); return WERR_DS_DRA_ACCESS_DENIED; } } dcesrv_irpc_forward_rpc_call(dce_call, mem_ctx, r, NDR_DRSUAPI_DSREPLICAGETINFO, &ndr_table_drsuapi, "kccsrv", "DsReplicaGetInfo"); return WERR_OK; }
WERROR _wkssvc_NetWkstaEnumUsers(struct pipes_struct *p, struct wkssvc_NetWkstaEnumUsers *r) { /* This with any level should only be allowed from a domain administrator */ if (!nt_token_check_sid(&global_sid_Builtin_Administrators, p->session_info->security_token)) { DEBUG(1,("User not allowed for NetWkstaEnumUsers\n")); DEBUGADD(3,(" - does not have sid for Administrators group " "%s\n", sid_string_dbg( &global_sid_Builtin_Administrators))); security_token_debug(DBGC_CLASS, 3, p->session_info->security_token); return WERR_ACCESS_DENIED; } switch (r->in.info->level) { case 0: r->out.info->ctr.user0 = create_enum_users0(p->mem_ctx); if (r->out.info->ctr.user0 == NULL) { return WERR_NOMEM; } r->out.info->level = r->in.info->level; *r->out.entries_read = r->out.info->ctr.user0->entries_read; *r->out.resume_handle = 0; break; case 1: r->out.info->ctr.user1 = create_enum_users1(p->mem_ctx); if (r->out.info->ctr.user1 == NULL) { return WERR_NOMEM; } r->out.info->level = r->in.info->level; *r->out.entries_read = r->out.info->ctr.user1->entries_read; *r->out.resume_handle = 0; break; default: return WERR_UNKNOWN_LEVEL; } return WERR_OK; }
NTSTATUS create_local_token(struct auth_serversupplied_info *server_info) { struct security_token *t; NTSTATUS status; size_t i; struct dom_sid tmp_sid; struct wbcUnixId *ids; /* * If winbind is not around, we can not make much use of the SIDs the * domain controller provided us with. Likewise if the user name was * mapped to some local unix user. */ if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) || (server_info->nss_token)) { status = create_token_from_username(server_info, server_info->unix_name, server_info->guest, &server_info->utok.uid, &server_info->utok.gid, &server_info->unix_name, &server_info->security_token); } else { status = create_local_nt_token_from_info3(server_info, server_info->guest, server_info->info3, &server_info->extra, &server_info->security_token); } if (!NT_STATUS_IS_OK(status)) { return status; } /* Convert the SIDs to gids. */ server_info->utok.ngroups = 0; server_info->utok.groups = NULL; t = server_info->security_token; ids = TALLOC_ARRAY(talloc_tos(), struct wbcUnixId, t->num_sids); if (ids == NULL) { return NT_STATUS_NO_MEMORY; } if (!sids_to_unix_ids(t->sids, t->num_sids, ids)) { TALLOC_FREE(ids); return NT_STATUS_NO_MEMORY; } /* Start at index 1, where the groups start. */ for (i=1; i<t->num_sids; i++) { if (ids[i].type != WBC_ID_TYPE_GID) { DEBUG(10, ("Could not convert SID %s to gid, " "ignoring it\n", sid_string_dbg(&t->sids[i]))); continue; } if (!add_gid_to_array_unique(server_info, ids[i].id.gid, &server_info->utok.groups, &server_info->utok.ngroups)) { return NT_STATUS_NO_MEMORY; } } /* * Add the "Unix Group" SID for each gid to catch mapped groups * and their Unix equivalent. This is to solve the backwards * compatibility problem of 'valid users = +ntadmin' where * ntadmin has been paired with "Domain Admins" in the group * mapping table. Otherwise smb.conf would need to be changed * to 'valid user = "******"'. --jerry * * For consistency we also add the "Unix User" SID, * so that the complete unix token is represented within * the nt token. */ uid_to_unix_users_sid(server_info->utok.uid, &tmp_sid); add_sid_to_array_unique(server_info->security_token, &tmp_sid, &server_info->security_token->sids, &server_info->security_token->num_sids); for ( i=0; i<server_info->utok.ngroups; i++ ) { gid_to_unix_groups_sid(server_info->utok.groups[i], &tmp_sid); add_sid_to_array_unique(server_info->security_token, &tmp_sid, &server_info->security_token->sids, &server_info->security_token->num_sids); } security_token_debug(DBGC_AUTH, 10, server_info->security_token); debug_unix_user_token(DBGC_AUTH, 10, server_info->utok.uid, server_info->utok.gid, server_info->utok.ngroups, server_info->utok.groups); status = log_nt_token(server_info->security_token); return status; }
/* form a security_unix_token from the current security_token */ NTSTATUS security_token_to_unix_token(TALLOC_CTX *mem_ctx, struct wbc_context *wbc_ctx, struct security_token *token, struct security_unix_token **sec) { uint32_t s, g; NTSTATUS status; struct id_map *ids; struct composite_context *ctx; /* we can't do unix security without a user and group */ if (token->num_sids < 2) { return NT_STATUS_ACCESS_DENIED; } *sec = talloc_zero(mem_ctx, struct security_unix_token); if (*sec == NULL) { return NT_STATUS_NO_MEMORY; } ids = talloc_zero_array(mem_ctx, struct id_map, token->num_sids); NT_STATUS_HAVE_NO_MEMORY(ids); for (s=0; s < token->num_sids; s++) { ids[s].sid = &token->sids[s]; ids[s].status = ID_UNKNOWN; } ctx = wbc_sids_to_xids_send(wbc_ctx, ids, token->num_sids, ids); NT_STATUS_HAVE_NO_MEMORY(ctx); status = wbc_sids_to_xids_recv(ctx, &ids); NT_STATUS_NOT_OK_RETURN(status); g = token->num_sids; if (ids[0].xid.type != ID_TYPE_BOTH) { g--; } (*sec)->ngroups = g; (*sec)->groups = talloc_array(*sec, gid_t, (*sec)->ngroups); NT_STATUS_HAVE_NO_MEMORY((*sec)->groups); g=0; if (ids[0].xid.type == ID_TYPE_BOTH) { (*sec)->uid = ids[0].xid.id; (*sec)->groups[g] = ids[0].xid.id; g++; } else if (ids[0].xid.type == ID_TYPE_UID) { (*sec)->uid = ids[0].xid.id; } else { char *sid_str = dom_sid_string(mem_ctx, ids[0].sid); DEBUG(0, ("Unable to convert first SID (%s) in user token to a UID. Conversion was returned as type %d, full token:\n", sid_str, (int)ids[0].xid.type)); security_token_debug(0, 0, token); talloc_free(sid_str); return NT_STATUS_INVALID_SID; } if (ids[1].xid.type == ID_TYPE_BOTH || ids[1].xid.type == ID_TYPE_GID) { (*sec)->gid = ids[1].xid.id; (*sec)->groups[g] = ids[1].xid.id; g++; } else { char *sid_str = dom_sid_string(mem_ctx, ids[1].sid); DEBUG(0, ("Unable to convert second SID (%s) in user token to a GID. Conversion was returned as type %d, full token:\n", sid_str, (int)ids[1].xid.type)); security_token_debug(0, 0, token); talloc_free(sid_str); return NT_STATUS_INVALID_SID; } for (s=2; s < token->num_sids; s++) { if (ids[s].xid.type == ID_TYPE_BOTH || ids[s].xid.type == ID_TYPE_GID) { (*sec)->groups[g] = ids[s].xid.id; g++; } else { char *sid_str = dom_sid_string(mem_ctx, ids[s].sid); DEBUG(0, ("Unable to convert SID (%s) at index %u in user token to a GID. Conversion was returned as type %d, full token:\n", sid_str, (unsigned int)s, (int)ids[s].xid.type)); security_token_debug(0, 0, token); talloc_free(sid_str); return NT_STATUS_INVALID_SID; } } DEBUG(5, ("Successfully converted security token to a unix token:")); security_token_debug(0, 5, token); TALLOC_FREE(ids); return NT_STATUS_OK; }
NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, const struct auth_serversupplied_info *server_info, DATA_BLOB *session_key, const char *smb_username, /* for ->sanitized_username, for %U subs */ struct auth_session_info **session_info_out) { struct security_token *t; NTSTATUS status; size_t i; struct dom_sid tmp_sid; struct auth_session_info *session_info; struct unixid *ids; fstring tmp; /* Ensure we can't possible take a code path leading to a * null defref. */ if (!server_info) { return NT_STATUS_LOGON_FAILURE; } session_info = talloc_zero(mem_ctx, struct auth_session_info); if (!session_info) { return NT_STATUS_NO_MEMORY; } session_info->unix_token = talloc_zero(session_info, struct security_unix_token); if (!session_info->unix_token) { TALLOC_FREE(session_info); return NT_STATUS_NO_MEMORY; } session_info->unix_token->uid = server_info->utok.uid; session_info->unix_token->gid = server_info->utok.gid; session_info->unix_info = talloc_zero(session_info, struct auth_user_info_unix); if (!session_info->unix_info) { TALLOC_FREE(session_info); return NT_STATUS_NO_MEMORY; } session_info->unix_info->unix_name = talloc_strdup(session_info, server_info->unix_name); if (!session_info->unix_info->unix_name) { TALLOC_FREE(session_info); return NT_STATUS_NO_MEMORY; } /* This is a potentially untrusted username for use in %U */ alpha_strcpy(tmp, smb_username, ". _-$", sizeof(tmp)); session_info->unix_info->sanitized_username = talloc_strdup(session_info->unix_info, tmp); if (session_key) { data_blob_free(&session_info->session_key); session_info->session_key = data_blob_talloc(session_info, session_key->data, session_key->length); if (!session_info->session_key.data && session_key->length) { return NT_STATUS_NO_MEMORY; } } else { session_info->session_key = data_blob_talloc( session_info, server_info->session_key.data, server_info->session_key.length); } /* We need to populate session_info->info with the information found in server_info->info3 */ status = make_user_info_SamBaseInfo(session_info, "", &server_info->info3->base, server_info->guest == false, &session_info->info); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("conversion of info3 into auth_user_info failed!\n")); TALLOC_FREE(session_info); return status; } if (server_info->security_token) { /* Just copy the token, it has already been finalised * (nasty hack to support a cached guest/system session_info */ session_info->security_token = dup_nt_token(session_info, server_info->security_token); if (!session_info->security_token) { TALLOC_FREE(session_info); return NT_STATUS_NO_MEMORY; } session_info->unix_token->ngroups = server_info->utok.ngroups; if (server_info->utok.ngroups != 0) { session_info->unix_token->groups = (gid_t *)talloc_memdup( session_info->unix_token, server_info->utok.groups, sizeof(gid_t)*session_info->unix_token->ngroups); } else { session_info->unix_token->groups = NULL; } *session_info_out = session_info; return NT_STATUS_OK; } /* * If winbind is not around, we can not make much use of the SIDs the * domain controller provided us with. Likewise if the user name was * mapped to some local unix user. */ if (((lp_server_role() == ROLE_DOMAIN_MEMBER) && !winbind_ping()) || (server_info->nss_token)) { char *found_username = NULL; status = create_token_from_username(session_info, server_info->unix_name, server_info->guest, &session_info->unix_token->uid, &session_info->unix_token->gid, &found_username, &session_info->security_token); if (NT_STATUS_IS_OK(status)) { session_info->unix_info->unix_name = found_username; } } else { status = create_local_nt_token_from_info3(session_info, server_info->guest, server_info->info3, &server_info->extra, &session_info->security_token); } if (!NT_STATUS_IS_OK(status)) { return status; } /* Convert the SIDs to gids. */ session_info->unix_token->ngroups = 0; session_info->unix_token->groups = NULL; t = session_info->security_token; ids = talloc_array(talloc_tos(), struct unixid, t->num_sids); if (ids == NULL) { return NT_STATUS_NO_MEMORY; } if (!sids_to_unixids(t->sids, t->num_sids, ids)) { TALLOC_FREE(ids); return NT_STATUS_NO_MEMORY; } for (i=0; i<t->num_sids; i++) { if (i == 0 && ids[i].type != ID_TYPE_BOTH) { continue; } if (ids[i].type != ID_TYPE_GID && ids[i].type != ID_TYPE_BOTH) { DEBUG(10, ("Could not convert SID %s to gid, " "ignoring it\n", sid_string_dbg(&t->sids[i]))); continue; } if (!add_gid_to_array_unique(session_info, ids[i].id, &session_info->unix_token->groups, &session_info->unix_token->ngroups)) { return NT_STATUS_NO_MEMORY; } } /* * Add the "Unix Group" SID for each gid to catch mapped groups * and their Unix equivalent. This is to solve the backwards * compatibility problem of 'valid users = +ntadmin' where * ntadmin has been paired with "Domain Admins" in the group * mapping table. Otherwise smb.conf would need to be changed * to 'valid user = "******"'. --jerry * * For consistency we also add the "Unix User" SID, * so that the complete unix token is represented within * the nt token. */ uid_to_unix_users_sid(session_info->unix_token->uid, &tmp_sid); add_sid_to_array_unique(session_info->security_token, &tmp_sid, &session_info->security_token->sids, &session_info->security_token->num_sids); for ( i=0; i<session_info->unix_token->ngroups; i++ ) { gid_to_unix_groups_sid(session_info->unix_token->groups[i], &tmp_sid); add_sid_to_array_unique(session_info->security_token, &tmp_sid, &session_info->security_token->sids, &session_info->security_token->num_sids); } security_token_debug(DBGC_AUTH, 10, session_info->security_token); debug_unix_user_token(DBGC_AUTH, 10, session_info->unix_token->uid, session_info->unix_token->gid, session_info->unix_token->ngroups, session_info->unix_token->groups); status = log_nt_token(session_info->security_token); if (!NT_STATUS_IS_OK(status)) { return status; } *session_info_out = session_info; return NT_STATUS_OK; }