DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn) { DATA_BLOB blob = data_blob_null; DATA_BLOB blob_out = data_blob_null; nstring dos_name; fstring unix_name; NTSTATUS status; #ifdef DEVELOPER size_t slen; #endif struct gensec_security *gensec_security; /* See if we can get an SPNEGO blob */ status = auth_generic_prepare(talloc_tos(), sconn->remote_address, &gensec_security); if (NT_STATUS_IS_OK(status)) { status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_SPNEGO); if (NT_STATUS_IS_OK(status)) { status = gensec_update(gensec_security, ctx, NULL, data_blob_null, &blob); /* If we get the list of OIDs, the 'OK' answer * is NT_STATUS_MORE_PROCESSING_REQUIRED */ if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { DEBUG(0, ("Failed to start SPNEGO handler for negprot OID list!\n")); blob = data_blob_null; } } TALLOC_FREE(gensec_security); } sconn->smb1.negprot.spnego = true; /* strangely enough, NT does not sent the single OID NTLMSSP when not a ADS member, it sends no OIDs at all OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)" Our sessionsetup code now handles raw NTLMSSP connects, so we can go back to doing what W2K3 does here. This is needed to make PocketPC 2003 CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133 for details. JRA. */ if (blob.length == 0 || blob.data == NULL) { return data_blob_null; } blob_out = data_blob_talloc(ctx, NULL, 16 + blob.length); if (blob_out.data == NULL) { data_blob_free(&blob); return data_blob_null; } memset(blob_out.data, '\0', 16); checked_strlcpy(unix_name, lp_netbios_name(), sizeof(unix_name)); (void)strlower_m(unix_name); push_ascii_nstring(dos_name, unix_name); strlcpy((char *)blob_out.data, dos_name, 17); #ifdef DEVELOPER /* Fix valgrind 'uninitialized bytes' issue. */ slen = strlen(dos_name); if (slen < 16) { memset(blob_out.data+slen, '\0', 16 - slen); } #endif memcpy(&blob_out.data[16], blob.data, blob.length); data_blob_free(&blob); return blob_out; }
DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn) { DATA_BLOB blob = data_blob_null; DATA_BLOB blob_out = data_blob_null; nstring dos_name; fstring unix_name; NTSTATUS status; #ifdef DEVELOPER size_t slen; #endif const char *OIDs_krb5[] = {OID_KERBEROS5, OID_KERBEROS5_OLD, OID_NTLMSSP, NULL}; const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL}; struct auth_ntlmssp_state *auth_ntlmssp_state; sconn->use_gensec_hook = false; /* See if we can get an SPNEGO blob out of the gensec hook (if auth_samba4 is loaded) */ status = auth_ntlmssp_prepare(sconn->remote_address, &auth_ntlmssp_state); if (NT_STATUS_IS_OK(status)) { status = auth_generic_start(auth_ntlmssp_state, GENSEC_OID_SPNEGO); if (NT_STATUS_IS_OK(status)) { status = auth_ntlmssp_update(auth_ntlmssp_state, ctx, data_blob_null, &blob); /* If we get the list of OIDs, the 'OK' answer * is NT_STATUS_MORE_PROCESSING_REQUIRED */ if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { sconn->use_gensec_hook = true; } } TALLOC_FREE(auth_ntlmssp_state); } sconn->smb1.negprot.spnego = true; /* strangely enough, NT does not sent the single OID NTLMSSP when not a ADS member, it sends no OIDs at all OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)" Our sessionsetup code now handles raw NTLMSSP connects, so we can go back to doing what W2K3 does here. This is needed to make PocketPC 2003 CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133 for details. JRA. */ if (sconn->use_gensec_hook) { /* blob initialised above */ } else if (lp_security() != SEC_ADS && !USE_KERBEROS_KEYTAB) { #if 0 /* Code for PocketPC client */ blob = data_blob(guid, 16); #else /* Code for standalone WXP client */ blob = spnego_gen_negTokenInit(ctx, OIDs_ntlm, NULL, "NONE"); #endif } else if (!lp_send_spnego_principal()) { /* By default, Windows 2008 and later sends not_defined_in_RFC4178@please_ignore */ blob = spnego_gen_negTokenInit(ctx, OIDs_krb5, NULL, ADS_IGNORE_PRINCIPAL); } else { fstring myname; char *host_princ_s = NULL; name_to_fqdn(myname, lp_netbios_name()); strlower_m(myname); if (asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm()) == -1) { return data_blob_null; } blob = spnego_gen_negTokenInit(ctx, OIDs_krb5, NULL, host_princ_s); SAFE_FREE(host_princ_s); } if (blob.length == 0 || blob.data == NULL) { return data_blob_null; } blob_out = data_blob_talloc(ctx, NULL, 16 + blob.length); if (blob_out.data == NULL) { data_blob_free(&blob); return data_blob_null; } memset(blob_out.data, '\0', 16); checked_strlcpy(unix_name, lp_netbios_name(), sizeof(unix_name)); strlower_m(unix_name); push_ascii_nstring(dos_name, unix_name); strlcpy((char *)blob_out.data, dos_name, 17); #ifdef DEVELOPER /* Fix valgrind 'uninitialized bytes' issue. */ slen = strlen(dos_name); if (slen < 16) { memset(blob_out.data+slen, '\0', 16 - slen); } #endif memcpy(&blob_out.data[16], blob.data, blob.length); data_blob_free(&blob); return blob_out; }