void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token) { struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx]; /* Set the security context */ DEBUG(3, ("setting sec ctx (%u, %u) - sec_ctx_stack_ndx = %d\n", (unsigned int)uid, (unsigned int)gid, sec_ctx_stack_ndx)); debug_nt_user_token(DBGC_CLASS, 5, token); debug_unix_user_token(DBGC_CLASS, 5, uid, gid, ngroups, groups); gain_root(); #ifdef HAVE_SETGROUPS sys_setgroups(ngroups, groups); #endif 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; } become_id(uid, gid); 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; }
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; }
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; }
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; }