int register_existing_vuid(uint16 vuid, auth_serversupplied_info *server_info, DATA_BLOB response_blob, const char *smb_name) { fstring tmp; user_struct *vuser; vuser = get_partial_auth_user_struct(vuid); if (!vuser) { goto fail; } /* Use this to keep tabs on all our info from the authentication */ vuser->server_info = talloc_move(vuser, &server_info); /* This is a potentially untrusted username */ alpha_strcpy(tmp, smb_name, ". _-$", sizeof(tmp)); vuser->server_info->sanitized_username = talloc_strdup( vuser->server_info, tmp); DEBUG(10,("register_existing_vuid: (%u,%u) %s %s %s guest=%d\n", (unsigned int)vuser->server_info->utok.uid, (unsigned int)vuser->server_info->utok.gid, vuser->server_info->unix_name, vuser->server_info->sanitized_username, pdb_get_domain(vuser->server_info->sam_account), vuser->server_info->guest )); DEBUG(3, ("register_existing_vuid: User name: %s\t" "Real name: %s\n", vuser->server_info->unix_name, pdb_get_fullname(vuser->server_info->sam_account))); if (!vuser->server_info->ptok) { DEBUG(1, ("register_existing_vuid: server_info does not " "contain a user_token - cannot continue\n")); goto fail; } DEBUG(3,("register_existing_vuid: UNIX uid %d is UNIX user %s, " "and will be vuid %u\n", (int)vuser->server_info->utok.uid, vuser->server_info->unix_name, vuser->vuid)); if (!session_claim(vuser)) { DEBUG(1, ("register_existing_vuid: Failed to claim session " "for vuid=%d\n", vuser->vuid)); goto fail; } /* Register a home dir service for this user if (a) This is not a guest connection, (b) we have a home directory defined (c) there s not an existing static share by that name If a share exists by this name (autoloaded or not) reuse it . */ vuser->homes_snum = -1; if (!vuser->server_info->guest) { vuser->homes_snum = register_homes_share( vuser->server_info->unix_name); } if (srv_is_signing_negotiated() && !vuser->server_info->guest && !srv_signing_started()) { /* Try and turn on server signing on the first non-guest * sessionsetup. */ srv_set_signing(vuser->server_info->user_session_key, response_blob); } /* fill in the current_user_info struct */ set_current_user_info( vuser->server_info->sanitized_username, vuser->server_info->unix_name, pdb_get_domain(vuser->server_info->sam_account)); return vuser->vuid; fail: if (vuser) { invalidate_vuid(vuid); } return UID_FIELD_INVALID; }
bool is_partial_auth_vuid(uint16 vuid) { return (get_partial_auth_user_struct(vuid) != NULL); }
static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, char *outbuf, int length,int bufsize) { uint8 *p; DATA_BLOB blob1; int ret; size_t bufrem; fstring native_os, native_lanman, primary_domain; char *p2; uint16 data_blob_len = SVAL(inbuf, smb_vwv7); enum remote_arch_types ra_type = get_remote_arch(); int vuid = SVAL(inbuf,smb_uid); user_struct *vuser = NULL; NTSTATUS status = NT_STATUS_OK; uint16 smbpid = SVAL(inbuf,smb_pid); DEBUG(3,("Doing spnego session setup\n")); if (global_client_caps == 0) { global_client_caps = IVAL(inbuf,smb_vwv10); if (!(global_client_caps & CAP_STATUS32)) { remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); } } p = (uint8 *)smb_buf(inbuf); if (data_blob_len == 0) { /* an invalid request */ return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } bufrem = smb_bufrem(inbuf, p); /* pull the spnego blob */ blob1 = data_blob(p, MIN(bufrem, data_blob_len)); #if 0 file_save("negotiate.dat", blob1.data, blob1.length); #endif p2 = inbuf + smb_vwv13 + data_blob_len; p2 += srvstr_pull_buf(inbuf, native_os, p2, sizeof(native_os), STR_TERMINATE); p2 += srvstr_pull_buf(inbuf, native_lanman, p2, sizeof(native_lanman), STR_TERMINATE); p2 += srvstr_pull_buf(inbuf, primary_domain, p2, sizeof(primary_domain), STR_TERMINATE); DEBUG(3,("NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", native_os, native_lanman, primary_domain)); if ( ra_type == RA_WIN2K ) { /* Vista sets neither the OS or lanman strings */ if ( !strlen(native_os) && !strlen(native_lanman) ) set_remote_arch(RA_VISTA); /* Windows 2003 doesn't set the native lanman string, but does set primary domain which is a bug I think */ if ( !strlen(native_lanman) ) { ra_lanman_string( primary_domain ); } else { ra_lanman_string( native_lanman ); } } vuser = get_partial_auth_user_struct(vuid); if (!vuser) { struct pending_auth_data *pad = get_pending_auth_data(smbpid); if (pad) { DEBUG(10,("reply_sesssetup_and_X_spnego: found pending vuid %u\n", (unsigned int)pad->vuid )); vuid = pad->vuid; vuser = get_partial_auth_user_struct(vuid); } } if (!vuser) { vuid = register_vuid(NULL, data_blob(NULL, 0), data_blob(NULL, 0), NULL); if (vuid == UID_FIELD_INVALID ) { data_blob_free(&blob1); return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } vuser = get_partial_auth_user_struct(vuid); } if (!vuser) { data_blob_free(&blob1); return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } SSVAL(outbuf,smb_uid,vuid); /* Large (greater than 4k) SPNEGO blobs are split into multiple * sessionsetup requests as the Windows limit on the security blob * field is 4k. Bug #4400. JRA. */ status = check_spnego_blob_complete(smbpid, vuid, &blob1); if (!NT_STATUS_IS_OK(status)) { if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { /* Real error - kill the intermediate vuid */ invalidate_vuid(vuid); } data_blob_free(&blob1); return ERROR_NT(nt_status_squash(status)); } if (blob1.data[0] == ASN1_APPLICATION(0)) { /* its a negTokenTarg packet */ ret = reply_spnego_negotiate(conn, inbuf, outbuf, vuid, length, bufsize, blob1, &vuser->auth_ntlmssp_state); data_blob_free(&blob1); return ret; } if (blob1.data[0] == ASN1_CONTEXT(1)) { /* its a auth packet */ ret = reply_spnego_auth(conn, inbuf, outbuf, vuid, length, bufsize, blob1, &vuser->auth_ntlmssp_state); data_blob_free(&blob1); return ret; } if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) { DATA_BLOB chal; if (!vuser->auth_ntlmssp_state) { status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state); if (!NT_STATUS_IS_OK(status)) { /* Kill the intermediate vuid */ invalidate_vuid(vuid); data_blob_free(&blob1); return ERROR_NT(nt_status_squash(status)); } } status = auth_ntlmssp_update(vuser->auth_ntlmssp_state, blob1, &chal); data_blob_free(&blob1); reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, &vuser->auth_ntlmssp_state, &chal, status, False); data_blob_free(&chal); return -1; } /* what sort of packet is this? */ DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n")); data_blob_free(&blob1); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); }