NTSTATUS serverinfo_to_SamInfo3(const struct auth_serversupplied_info *server_info, struct netr_SamInfo3 *sam3) { struct netr_SamInfo3 *info3; info3 = copy_netr_SamInfo3(sam3, server_info->info3); if (!info3) { return NT_STATUS_NO_MEMORY; } if (server_info->session_key.length) { memcpy(info3->base.key.key, server_info->session_key.data, MIN(sizeof(info3->base.key.key), server_info->session_key.length)); } if (server_info->lm_session_key.length) { memcpy(info3->base.LMSessKey.key, server_info->lm_session_key.data, MIN(sizeof(info3->base.LMSessKey.key), server_info->lm_session_key.length)); } sam3->base = info3->base; sam3->sidcount = 0; sam3->sids = NULL; return NT_STATUS_OK; }
struct auth_serversupplied_info *copy_serverinfo(TALLOC_CTX *mem_ctx, const struct auth_serversupplied_info *src) { struct auth_serversupplied_info *dst; dst = make_server_info(mem_ctx); if (dst == NULL) { return NULL; } dst->guest = src->guest; dst->system = src->system; dst->utok.uid = src->utok.uid; dst->utok.gid = src->utok.gid; dst->utok.ngroups = src->utok.ngroups; if (src->utok.ngroups != 0) { dst->utok.groups = (gid_t *)TALLOC_MEMDUP( dst, src->utok.groups, sizeof(gid_t)*dst->utok.ngroups); } else { dst->utok.groups = NULL; } if (src->security_token) { dst->security_token = dup_nt_token(dst, src->security_token); if (!dst->security_token) { TALLOC_FREE(dst); return NULL; } } dst->user_session_key = data_blob_talloc( dst, src->user_session_key.data, src->user_session_key.length); dst->lm_session_key = data_blob_talloc(dst, src->lm_session_key.data, src->lm_session_key.length); dst->info3 = copy_netr_SamInfo3(dst, src->info3); if (!dst->info3) { TALLOC_FREE(dst); return NULL; } dst->extra = src->extra; dst->unix_name = talloc_strdup(dst, src->unix_name); if (!dst->unix_name) { TALLOC_FREE(dst); return NULL; } dst->sanitized_username = talloc_strdup(dst, src->sanitized_username); if (!dst->sanitized_username) { TALLOC_FREE(dst); return NULL; } return dst; }
NTSTATUS serverinfo_to_SamInfo6(struct auth_serversupplied_info *server_info, struct netr_SamInfo6 *sam6) { struct pdb_domain_info *dominfo; struct netr_SamInfo3 *info3; if ((pdb_capabilities() & PDB_CAP_ADS) == 0) { DEBUG(10,("Not adding validation info level 6 " "without ADS passdb backend\n")); return NT_STATUS_INVALID_INFO_CLASS; } dominfo = pdb_get_domain_info(sam6); if (dominfo == NULL) { return NT_STATUS_NO_MEMORY; } info3 = copy_netr_SamInfo3(sam6, server_info->info3); if (!info3) { return NT_STATUS_NO_MEMORY; } if (server_info->session_key.length) { memcpy(info3->base.key.key, server_info->session_key.data, MIN(sizeof(info3->base.key.key), server_info->session_key.length)); } if (server_info->lm_session_key.length) { memcpy(info3->base.LMSessKey.key, server_info->lm_session_key.data, MIN(sizeof(info3->base.LMSessKey.key), server_info->lm_session_key.length)); } sam6->base = info3->base; sam6->sidcount = 0; sam6->sids = NULL; sam6->dns_domainname.string = talloc_strdup(sam6, dominfo->dns_domain); if (sam6->dns_domainname.string == NULL) { return NT_STATUS_NO_MEMORY; } sam6->principal_name.string = talloc_asprintf( sam6, "%s@%s", sam6->base.account_name.string, sam6->dns_domainname.string); if (sam6->principal_name.string == NULL) { return NT_STATUS_NO_MEMORY; } return NT_STATUS_OK; }
NTSTATUS create_info3_from_pac_logon_info(TALLOC_CTX *mem_ctx, const struct PAC_LOGON_INFO *logon_info, struct netr_SamInfo3 **pp_info3) { NTSTATUS status; struct netr_SamInfo3 *info3 = copy_netr_SamInfo3(mem_ctx, &logon_info->info3); if (info3 == NULL) { return NT_STATUS_NO_MEMORY; } status = merge_resource_sids(logon_info, info3); if (!NT_STATUS_IS_OK(status)) { TALLOC_FREE(info3); return status; } *pp_info3 = info3; return NT_STATUS_OK; }
NTSTATUS serverinfo_to_SamInfo3(const struct auth_serversupplied_info *server_info, uint8_t *pipe_session_key, size_t pipe_session_key_len, struct netr_SamInfo3 *sam3) { struct netr_SamInfo3 *info3; info3 = copy_netr_SamInfo3(sam3, server_info->info3); if (!info3) { return NT_STATUS_NO_MEMORY; } if (server_info->user_session_key.length) { memcpy(info3->base.key.key, server_info->user_session_key.data, MIN(sizeof(info3->base.key.key), server_info->user_session_key.length)); if (pipe_session_key) { arcfour_crypt(info3->base.key.key, pipe_session_key, 16); } } if (server_info->lm_session_key.length) { memcpy(info3->base.LMSessKey.key, server_info->lm_session_key.data, MIN(sizeof(info3->base.LMSessKey.key), server_info->lm_session_key.length)); if (pipe_session_key) { arcfour_crypt(info3->base.LMSessKey.key, pipe_session_key, 8); } } sam3->base = info3->base; sam3->sidcount = 0; sam3->sids = NULL; return NT_STATUS_OK; }
NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx, const char *sent_nt_username, const char *domain, struct auth_serversupplied_info **server_info, struct netr_SamInfo3 *info3) { static const char zeros[16] = {0, }; NTSTATUS nt_status = NT_STATUS_OK; char *found_username = NULL; const char *nt_domain; const char *nt_username; struct dom_sid user_sid; struct dom_sid group_sid; bool username_was_mapped; struct passwd *pwd; struct auth_serversupplied_info *result; /* Here is where we should check the list of trusted domains, and verify that the SID matches. */ if (!sid_compose(&user_sid, info3->base.domain_sid, info3->base.rid)) { return NT_STATUS_INVALID_PARAMETER; } if (!sid_compose(&group_sid, info3->base.domain_sid, info3->base.primary_gid)) { return NT_STATUS_INVALID_PARAMETER; } nt_username = talloc_strdup(mem_ctx, info3->base.account_name.string); if (!nt_username) { /* If the server didn't give us one, just use the one we sent * them */ nt_username = sent_nt_username; } nt_domain = talloc_strdup(mem_ctx, info3->base.domain.string); if (!nt_domain) { /* If the server didn't give us one, just use the one we sent * them */ nt_domain = domain; } /* If getpwnam() fails try the add user script (2.2.x behavior). We use the _unmapped_ username here in an attempt to provide consistent username mapping behavior between kerberos and NTLM[SSP] authentication in domain mode security. I.E. Username mapping should be applied to the fully qualified username (e.g. DOMAIN\user) and not just the login name. Yes this means we called map_username() unnecessarily in make_user_info_map() but that is how the current code is designed. Making the change here is the least disruptive place. -- jerry */ /* this call will try to create the user if necessary */ nt_status = check_account(mem_ctx, nt_domain, sent_nt_username, &found_username, &pwd, &username_was_mapped); if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; } result = make_server_info(NULL); if (result == NULL) { DEBUG(4, ("make_server_info failed!\n")); return NT_STATUS_NO_MEMORY; } result->unix_name = talloc_strdup(result, found_username); result->sanitized_username = sanitize_username(result, result->unix_name); if (result->sanitized_username == NULL) { TALLOC_FREE(result); return NT_STATUS_NO_MEMORY; } /* copy in the info3 */ result->info3 = copy_netr_SamInfo3(result, info3); if (result->info3 == NULL) { TALLOC_FREE(result); return NT_STATUS_NO_MEMORY; } /* Fill in the unix info we found on the way */ result->utok.uid = pwd->pw_uid; result->utok.gid = pwd->pw_gid; /* ensure we are never given NULL session keys */ if (memcmp(info3->base.key.key, zeros, sizeof(zeros)) == 0) { result->user_session_key = data_blob_null; } else { result->user_session_key = data_blob_talloc( result, info3->base.key.key, sizeof(info3->base.key.key)); } if (memcmp(info3->base.LMSessKey.key, zeros, 8) == 0) { result->lm_session_key = data_blob_null; } else { result->lm_session_key = data_blob_talloc( result, info3->base.LMSessKey.key, sizeof(info3->base.LMSessKey.key)); } result->nss_token |= username_was_mapped; *server_info = result; return NT_STATUS_OK; }
/* This function MUST only used to create the cached server_info for * guest. * * This is a lossy conversion. Variables known to be lost so far * include: * * - nss_token (not needed because the only read doesn't happen * for the GUEST user, as this routine populates ->security_token * * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3()) * * - The 'server_info' parameter allows the missing 'info3' to be copied across. */ static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx, const struct auth_session_info *src, struct auth_serversupplied_info *server_info) { struct auth_serversupplied_info *dst; dst = make_server_info(mem_ctx); if (dst == NULL) { return NULL; } /* This element must be provided to convert back to an auth_serversupplied_info */ SMB_ASSERT(src->unix_info); dst->guest = true; dst->system = false; /* This element must be provided to convert back to an * auth_serversupplied_info. This needs to be from the * auth_session_info because the group values in particular * may change during create_local_token() processing */ SMB_ASSERT(src->unix_token); dst->utok.uid = src->unix_token->uid; dst->utok.gid = src->unix_token->gid; dst->utok.ngroups = src->unix_token->ngroups; if (src->unix_token->ngroups != 0) { dst->utok.groups = (gid_t *)talloc_memdup( dst, src->unix_token->groups, sizeof(gid_t)*dst->utok.ngroups); } else { dst->utok.groups = NULL; } /* We must have a security_token as otherwise the lossy * conversion without nss_token would cause create_local_token * to take the wrong path */ SMB_ASSERT(src->security_token); dst->security_token = dup_nt_token(dst, src->security_token); if (!dst->security_token) { TALLOC_FREE(dst); return NULL; } dst->session_key = data_blob_talloc( dst, src->session_key.data, src->session_key.length); /* This is OK because this functions is only used for the * GUEST account, which has all-zero keys for both values */ dst->lm_session_key = data_blob_talloc(dst, src->session_key.data, src->session_key.length); dst->info3 = copy_netr_SamInfo3(dst, server_info->info3); if (!dst->info3) { TALLOC_FREE(dst); return NULL; } dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name); if (!dst->unix_name) { TALLOC_FREE(dst); return NULL; } return dst; }