The Samba-Bugzilla – Attachment 2304 Details for
Bug 4400
4k security blob limit in SessionSetupAndX requires multiple round trip SessionSetupAndX messages
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Working server-side patch !
look (text/plain), 9.73 KB, created by
Jeremy Allison
on 2007-02-20 00:18:46 UTC
(
hide
)
Description:
Working server-side patch !
Filename:
MIME Type:
Creator:
Jeremy Allison
Created:
2007-02-20 00:18:46 UTC
Size:
9.73 KB
patch
obsolete
>Index: smbd/sesssetup.c >=================================================================== >--- smbd/sesssetup.c (revision 21459) >+++ smbd/sesssetup.c (working copy) >@@ -659,6 +659,183 @@ > } > > /**************************************************************************** >+ List to store partial SPNEGO auth fragments. >+****************************************************************************/ >+ >+static struct pending_auth_data *pd_list; >+ >+/**************************************************************************** >+ Delete an entry on the list. >+****************************************************************************/ >+ >+static void delete_partial_auth(struct pending_auth_data *pad) >+{ >+ DLIST_REMOVE(pd_list, pad); >+ data_blob_free(&pad->partial_data); >+ SAFE_FREE(pad); >+} >+ >+/**************************************************************************** >+ Search for a partial SPNEGO auth fragment matching an smbpid. >+****************************************************************************/ >+ >+static struct pending_auth_data *get_pending_auth_data(uint16 smbpid) >+{ >+ struct pending_auth_data *pad; >+ >+ for (pad = pd_list; pad; pad = pad->next) { >+ if (pad->smbpid == smbpid) { >+ break; >+ } >+ } >+ return pad; >+} >+ >+/**************************************************************************** >+ Check the size of an SPNEGO blob. If we need more return NT_STATUS_MORE_PROCESSING_REQUIRED, >+ else return NT_STATUS_OK. >+****************************************************************************/ >+ >+static NTSTATUS check_spnego_blob_complete(uint16 smbpid, uint16 vuid, DATA_BLOB *pblob) >+{ >+ struct pending_auth_data *pad; >+ ASN1_DATA data; >+ size_t needed_len = 0; >+ >+ /* Ensure we have some data. */ >+ if (pblob->length == 0) { >+ /* Caller can cope. */ >+ DEBUG(2,("check_spnego_blob_complete: zero blob length !\n")); >+ delete_partial_auth(pad); >+ return NT_STATUS_OK; >+ } >+ >+ pad = get_pending_auth_data(smbpid); >+ >+ /* Were we waiting for more data ? */ >+ if (pad) { >+ DATA_BLOB tmp_blob; >+ >+ /* Integer wrap paranoia.... */ >+ >+ if (pad->partial_data.length + pblob->length < pad->partial_data.length || >+ pad->partial_data.length + pblob->length < pblob->length) { >+ >+ DEBUG(2,("check_spnego_blob_complete: integer wrap " >+ "pad->partial_data.length = %u, " >+ "pblob->length = %u\n", >+ (unsigned int)pad->partial_data.length, >+ (unsigned int)pblob->length )); >+ >+ delete_partial_auth(pad); >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ DEBUG(10,("check_spnego_blob_complete: " >+ "pad->partial_data.length = %u, " >+ "pad->needed_len = %u, " >+ "pblob->length = %u,\n", >+ (unsigned int)pad->partial_data.length, >+ (unsigned int)pad->needed_len, >+ (unsigned int)pblob->length )); >+ >+ tmp_blob = data_blob(NULL, >+ pad->partial_data.length + pblob->length); >+ >+ /* Concatenate the two. */ >+ memcpy(tmp_blob.data, >+ pad->partial_data.data, >+ pad->partial_data.length); >+ memcpy(tmp_blob.data + pad->partial_data.length, >+ pblob->data, >+ pblob->length); >+ >+ /* Replace the partial data. */ >+ data_blob_free(&pad->partial_data); >+ pad->partial_data = tmp_blob; >+ ZERO_STRUCT(tmp_blob); >+ >+ /* Are we done ? */ >+ if (pblob->length >= pad->needed_len) { >+ /* Yes, replace pblob. */ >+ data_blob_free(pblob); >+ *pblob = pad->partial_data; >+ ZERO_STRUCT(pad->partial_data); >+ delete_partial_auth(pad); >+ return NT_STATUS_OK; >+ } >+ >+ /* Still need more data. */ >+ pad->needed_len -= pblob->length; >+ return NT_STATUS_MORE_PROCESSING_REQUIRED; >+ } >+ >+ if ((pblob->data[0] != ASN1_APPLICATION(0)) && >+ (pblob->data[0] != ASN1_CONTEXT(1))) { >+ /* Not something we can determine the >+ * length of. >+ */ >+ return NT_STATUS_OK; >+ } >+ >+ /* This is a new SPNEGO sessionsetup - see if >+ * the data given in this blob is enough. >+ */ >+ >+ asn1_load(&data, *pblob); >+ asn1_start_tag(&data, pblob->data[0]); >+ if (data.has_error || data.nesting == NULL) { >+ asn1_free(&data); >+ /* Let caller catch. */ >+ return NT_STATUS_OK; >+ } >+ >+ /* Integer wrap paranoia.... */ >+ >+ if (data.nesting->taglen + data.nesting->start < data.nesting->taglen || >+ data.nesting->taglen + data.nesting->start < data.nesting->start) { >+ >+ DEBUG(2,("check_spnego_blob_complete: integer wrap " >+ "data.nesting->taglen = %u, " >+ "data.nesting->start = %u\n", >+ (unsigned int)data.nesting->taglen, >+ (unsigned int)data.nesting->start )); >+ >+ asn1_free(&data); >+ return NT_STATUS_INVALID_PARAMETER; >+ } >+ >+ /* Total length of the needed asn1 is the tag length >+ * plus the current offset. */ >+ >+ needed_len = data.nesting->taglen + data.nesting->start; >+ asn1_free(&data); >+ >+ DEBUG(10,("check_spnego_blob_complete: needed_len = %u, " >+ "pblob->length = %u\n", >+ (unsigned int)needed_len, >+ (unsigned int)pblob->length )); >+ >+ if (needed_len <= pblob->length) { >+ /* Nothing to do - blob is complete. */ >+ return NT_STATUS_OK; >+ } >+ >+ /* We must store this blob until complete. */ >+ pad = SMB_MALLOC(sizeof(struct pending_auth_data)); >+ if (!pad) { >+ return NT_STATUS_NO_MEMORY; >+ } >+ pad->needed_len = needed_len - pblob->length; >+ pad->partial_data = data_blob(pblob->data, pblob->length); >+ pad->smbpid = smbpid; >+ pad->vuid = vuid; >+ DLIST_ADD(pd_list, pad); >+ >+ return NT_STATUS_MORE_PROCESSING_REQUIRED; >+} >+ >+/**************************************************************************** > Reply to a session setup command. > conn POINTER CAN BE NULL HERE ! > ****************************************************************************/ >@@ -677,6 +854,8 @@ > 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")); > >@@ -715,16 +894,28 @@ > /* Windows 2003 doesn't set the native lanman string, > but does set primary domain which is a bug I think */ > >- if ( !strlen(native_lanman) ) >+ if ( !strlen(native_lanman) ) { > ra_lanman_string( primary_domain ); >- else >+ } 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)); > } > >@@ -732,11 +923,27 @@ > } > > 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, >@@ -755,25 +962,24 @@ > > if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) { > DATA_BLOB chal; >- NTSTATUS nt_status; > if (!vuser->auth_ntlmssp_state) { >- nt_status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state); >- if (!NT_STATUS_IS_OK(nt_status)) { >+ status = auth_ntlmssp_start(&vuser->auth_ntlmssp_state); >+ if (!NT_STATUS_IS_OK(status)) { > /* Kill the intermediate vuid */ > invalidate_vuid(vuid); >- >- return ERROR_NT(nt_status_squash(nt_status)); >+ data_blob_free(&blob1); >+ return ERROR_NT(nt_status_squash(status)); > } > } > >- nt_status = auth_ntlmssp_update(vuser->auth_ntlmssp_state, >+ 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, nt_status, False); >+ &chal, status, False); > data_blob_free(&chal); > return -1; > } >Index: smbd/password.c >=================================================================== >--- smbd/password.c (revision 21459) >+++ smbd/password.c (working copy) >@@ -111,6 +111,7 @@ > > SAFE_FREE(vuser->groups); > TALLOC_FREE(vuser->nt_user_token); >+ > SAFE_FREE(vuser); > num_validated_vuids--; > } >Index: libsmb/asn1.c >=================================================================== >--- libsmb/asn1.c (revision 21459) >+++ libsmb/asn1.c (working copy) >@@ -23,6 +23,14 @@ > /* free an asn1 structure */ > void asn1_free(ASN1_DATA *data) > { >+ struct nesting *nesting = data->nesting; >+ >+ while (nesting) { >+ struct nesting *nnext = nesting->next; >+ free(nesting); >+ nesting = nnext; >+ }; >+ data->nesting = NULL; > SAFE_FREE(data->data); > } > >Index: include/smb.h >=================================================================== >--- include/smb.h (revision 21459) >+++ include/smb.h (working copy) >@@ -1728,6 +1728,15 @@ > fstring password; > }; > >+/* For split krb5 SPNEGO blobs. */ >+struct pending_auth_data { >+ struct pending_auth_data *prev, *next; >+ uint16 vuid; /* Tag for this entry. */ >+ uint16 smbpid; /* Alternate tag for this entry. */ >+ size_t needed_len; >+ DATA_BLOB partial_data; >+}; >+ > typedef struct user_struct { > struct user_struct *next, *prev; > uint16 vuid; /* Tag for this entry. */ >@@ -1757,7 +1766,6 @@ > struct auth_serversupplied_info *server_info; > > struct auth_ntlmssp_state *auth_ntlmssp_state; >- > } user_struct; > > struct unix_error_map {
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 4400
:
2293
|
2294
|
2295
|
2297
|
2298
|
2299
|
2300
|
2301
|
2302
|
2303
| 2304 |
2312