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; }