static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx, TALLOC_CTX *mem_ctx, struct smb_krb5_context *smb_krb5_context, DATA_BLOB *pac_blob, const char *princ_name, const struct tsocket_address *remote_address, uint32_t session_info_flags, struct auth_session_info **session_info) { TALLOC_CTX *tmp_ctx; struct PAC_LOGON_INFO *logon_info = NULL; struct netr_SamInfo3 *info3_copy = NULL; bool is_mapped; bool is_guest; char *ntuser; char *ntdomain; char *username; char *rhost; struct passwd *pw; NTSTATUS status; int rc; tmp_ctx = talloc_new(mem_ctx); if (!tmp_ctx) { return NT_STATUS_NO_MEMORY; } if (pac_blob) { #ifdef HAVE_KRB5 status = kerberos_pac_logon_info(tmp_ctx, *pac_blob, NULL, NULL, NULL, NULL, 0, &logon_info); #else status = NT_STATUS_ACCESS_DENIED; #endif if (!NT_STATUS_IS_OK(status)) { goto done; } } rc = get_remote_hostname(remote_address, &rhost, tmp_ctx); if (rc < 0) { status = NT_STATUS_NO_MEMORY; goto done; } if (strequal(rhost, "UNKNOWN")) { rhost = tsocket_address_inet_addr_string(remote_address, tmp_ctx); if (rhost == NULL) { status = NT_STATUS_NO_MEMORY; goto done; } } status = get_user_from_kerberos_info(tmp_ctx, rhost, princ_name, logon_info, &is_mapped, &is_guest, &ntuser, &ntdomain, &username, &pw); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to map kerberos principal to system user " "(%s)\n", nt_errstr(status))); status = NT_STATUS_ACCESS_DENIED; goto done; } /* save the PAC data if we have it */ if (logon_info) { status = create_info3_from_pac_logon_info(tmp_ctx, logon_info, &info3_copy); if (!NT_STATUS_IS_OK(status)) { goto done; } netsamlogon_cache_store(ntuser, info3_copy); } /* setup the string used by %U */ sub_set_smb_name(username); /* reload services so that the new %U is taken into account */ lp_load_with_shares(get_dyn_CONFIGFILE()); status = make_session_info_krb5(mem_ctx, ntuser, ntdomain, username, pw, info3_copy, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */, session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n", nt_errstr(status))); status = NT_STATUS_ACCESS_DENIED; goto done; } DEBUG(5, (__location__ "OK: user: %s domain: %s client: %s\n", ntuser, ntdomain, rhost)); status = NT_STATUS_OK; done: TALLOC_FREE(tmp_ctx); return status; }
static NTSTATUS smbd_smb2_session_setup_krb5(struct smbd_smb2_session *session, struct smbd_smb2_request *smb2req, uint8_t in_security_mode, const DATA_BLOB *secblob, const char *mechOID, uint16_t *out_session_flags, DATA_BLOB *out_security_buffer, uint64_t *out_session_id) { DATA_BLOB ap_rep = data_blob_null; DATA_BLOB ap_rep_wrapped = data_blob_null; DATA_BLOB ticket = data_blob_null; DATA_BLOB session_key = data_blob_null; DATA_BLOB secblob_out = data_blob_null; uint8 tok_id[2]; struct PAC_LOGON_INFO *logon_info = NULL; char *principal = NULL; char *user = NULL; char *domain = NULL; struct passwd *pw = NULL; NTSTATUS status; char *real_username; bool username_was_mapped = false; bool map_domainuser_to_guest = false; if (!spnego_parse_krb5_wrap(talloc_tos(), *secblob, &ticket, tok_id)) { status = NT_STATUS_LOGON_FAILURE; goto fail; } status = ads_verify_ticket(smb2req, lp_realm(), 0, &ticket, &principal, &logon_info, &ap_rep, &session_key, true); if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("smb2: Failed to verify incoming ticket with error %s!\n", nt_errstr(status))); if (!NT_STATUS_EQUAL(status, NT_STATUS_TIME_DIFFERENCE_AT_DC)) { status = NT_STATUS_LOGON_FAILURE; } goto fail; } status = get_user_from_kerberos_info(talloc_tos(), session->sconn->remote_hostname, principal, logon_info, &username_was_mapped, &map_domainuser_to_guest, &user, &domain, &real_username, &pw); if (!NT_STATUS_IS_OK(status)) { goto fail; } /* save the PAC data if we have it */ if (logon_info) { netsamlogon_cache_store(user, &logon_info->info3); } /* setup the string used by %U */ sub_set_smb_name(real_username); /* reload services so that the new %U is taken into account */ reload_services(smb2req->sconn->msg_ctx, smb2req->sconn->sock, true); status = make_session_info_krb5(session, user, domain, real_username, pw, logon_info, map_domainuser_to_guest, username_was_mapped, &session_key, &session->session_info); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("smb2: make_server_info_krb5 failed\n")); goto fail; } if ((in_security_mode & SMB2_NEGOTIATE_SIGNING_REQUIRED) || lp_server_signing() == Required) { session->do_signing = true; } if (security_session_user_level(session->session_info, NULL) < SECURITY_USER) { /* we map anonymous to guest internally */ *out_session_flags |= SMB2_SESSION_FLAG_IS_GUEST; *out_session_flags |= SMB2_SESSION_FLAG_IS_NULL; /* force no signing */ session->do_signing = false; } session->session_key = session->session_info->session_key; session->compat_vuser = talloc_zero(session, user_struct); if (session->compat_vuser == NULL) { status = NT_STATUS_NO_MEMORY; goto fail; } session->compat_vuser->auth_ntlmssp_state = NULL; session->compat_vuser->homes_snum = -1; session->compat_vuser->session_info = session->session_info; session->compat_vuser->session_keystr = NULL; session->compat_vuser->vuid = session->vuid; DLIST_ADD(session->sconn->smb1.sessions.validated_users, session->compat_vuser); if (security_session_user_level(session->session_info, NULL) >= SECURITY_USER) { session->compat_vuser->homes_snum = register_homes_share(session->session_info->unix_info->unix_name); } if (!session_claim(session->sconn, session->compat_vuser)) { DEBUG(1, ("smb2: Failed to claim session " "for vuid=%d\n", session->compat_vuser->vuid)); goto fail; } session->status = NT_STATUS_OK; /* * we attach the session to the request * so that the response can be signed */ smb2req->session = session; if (session->do_signing) { smb2req->do_signing = true; } global_client_caps |= (CAP_LEVEL_II_OPLOCKS|CAP_STATUS32); status = NT_STATUS_OK; /* wrap that up in a nice GSS-API wrapping */ ap_rep_wrapped = spnego_gen_krb5_wrap(talloc_tos(), ap_rep, TOK_ID_KRB_AP_REP); secblob_out = spnego_gen_auth_response( talloc_tos(), &ap_rep_wrapped, status, mechOID); *out_security_buffer = data_blob_talloc(smb2req, secblob_out.data, secblob_out.length); if (secblob_out.data && out_security_buffer->data == NULL) { status = NT_STATUS_NO_MEMORY; goto fail; } data_blob_free(&ap_rep); data_blob_free(&ap_rep_wrapped); data_blob_free(&ticket); data_blob_free(&session_key); data_blob_free(&secblob_out); *out_session_id = session->vuid; return NT_STATUS_OK; fail: data_blob_free(&ap_rep); data_blob_free(&ap_rep_wrapped); data_blob_free(&ticket); data_blob_free(&session_key); data_blob_free(&secblob_out); ap_rep_wrapped = data_blob_null; secblob_out = spnego_gen_auth_response( talloc_tos(), &ap_rep_wrapped, status, mechOID); *out_security_buffer = data_blob_talloc(smb2req, secblob_out.data, secblob_out.length); data_blob_free(&secblob_out); return status; }