Author: jra Date: 2005-08-04 03:04:58 +0000 (Thu, 04 Aug 2005) New Revision: 9039
WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=9039 Log: Added comments to 2 factor auth in sesssetup.c. We now create the reply blob for the SPNEGO ntlmssp blob - now to learn how to return it... Jeremy. Modified: trunk/source/include/ntdomain.h trunk/source/rpc_server/srv_pipe.c trunk/source/smbd/sesssetup.c Changeset: Modified: trunk/source/include/ntdomain.h =================================================================== --- trunk/source/include/ntdomain.h 2005-08-04 02:59:19 UTC (rev 9038) +++ trunk/source/include/ntdomain.h 2005-08-04 03:04:58 UTC (rev 9039) @@ -185,11 +185,6 @@ uint32 ntlmssp_seq_num; }; -/* auth state for spnego ntlmssp. */ -struct spnego_ntlmssp_auth_struct { - AUTH_NTLMSSP_STATE *auth_ntlmssp_state; -}; - /* auth state for all bind types. */ struct pipe_auth_data { @@ -197,7 +192,7 @@ union { struct ntlmssp_auth_struct *ntlmssp_auth; struct schannel_auth_struct *schannel_auth; - struct spnego_ntlmssp_auth_struct *spnego_auth; + AUTH_NTLMSSP_STATE *auth_ntlmssp_state; } a_u; void (*auth_data_free_func)(struct pipe_auth_data *); }; Modified: trunk/source/rpc_server/srv_pipe.c =================================================================== --- trunk/source/rpc_server/srv_pipe.c 2005-08-04 02:59:19 UTC (rev 9038) +++ trunk/source/rpc_server/srv_pipe.c 2005-08-04 03:04:58 UTC (rev 9039) @@ -839,6 +839,7 @@ /******************************************************************* Register commands to an RPC pipe *******************************************************************/ + NTSTATUS rpc_pipe_register_commands(int version, const char *clnt, const char *srv, const struct api_struct *cmds, int size) { struct rpc_table *rpc_entry; @@ -898,26 +899,33 @@ static void free_pipe_spnego_auth_data(struct pipe_auth_data *auth) { - AUTH_NTLMSSP_STATE *a = auth->a_u.spnego_auth->auth_ntlmssp_state; + AUTH_NTLMSSP_STATE *a = auth->a_u.auth_ntlmssp_state; if (a) { auth_ntlmssp_end(&a); } + auth->a_u.auth_ntlmssp_state = NULL; } /******************************************************************* - Handle a SPNEGO bind auth. + Handle the first part of a SPNEGO bind auth. *******************************************************************/ static BOOL pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_p, RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth) { - DATA_BLOB secblob; DATA_BLOB blob; + DATA_BLOB secblob; + DATA_BLOB response; + DATA_BLOB chal; char *OIDs[ASN1_MAX_OIDS]; int i; + NTSTATUS status; BOOL got_kerberos_mechanism = False; + AUTH_NTLMSSP_STATE *a = NULL; ZERO_STRUCT(secblob); + ZERO_STRUCT(chal); + ZERO_STRUCT(response); /* Grab the SPNEGO blob. */ blob = data_blob(NULL,p->hdr.auth_len); @@ -925,20 +933,17 @@ if (!prs_copy_data_out(blob.data, rpc_in_p, p->hdr.auth_len)) { DEBUG(0,("pipe_spnego_auth_bind_negotiate: Failed to pull %u bytes - the SPNEGO auth header.\n", (unsigned int)p->hdr.auth_len )); - data_blob_free(&blob); - return False; + goto err; } if (blob.data[0] != ASN1_APPLICATION(0)) { - data_blob_free(&blob); - return False; + goto err; } /* parse out the OIDs and the first sec blob */ if (!parse_negTokenTarg(blob, OIDs, &secblob)) { DEBUG(0,("pipe_spnego_auth_bind_negotiate: Failed to parse the security blob.\n")); - data_blob_free(&blob); - return False; + goto err; } if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) { @@ -958,35 +963,56 @@ return ret; } - if (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP && p->auth.a_u.spnego_auth) { + if (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP && p->auth.a_u.auth_ntlmssp_state) { /* Free any previous auth type. */ free_pipe_spnego_auth_data(&p->auth); } - p->auth.a_u.spnego_auth = TALLOC_P(p->pipe_state_mem_ctx, struct spnego_ntlmssp_auth_struct); - if (!p->auth.a_u.spnego_auth) { - return False; + /* Initialize the NTLM engine. */ + status = auth_ntlmssp_start(&a); + if (!NT_STATUS_IS_OK(status)) { + goto err; } + /* + * Pass the first security blob of data to it. + * This can return an error or NT_STATUS_MORE_PROCESSING_REQUIRED + * which means we need another packet to complete the bind. + */ + + status = auth_ntlmssp_update(a, secblob, &chal); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + DEBUG(3,("pipe_spnego_auth_bind_negotiate: auth_ntlmssp_update failed.\n")); + goto err; + } + + /* Generate the response blob we need for step 2 of the bind. */ + response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); + + p->auth.a_u.auth_ntlmssp_state = a; p->auth.auth_data_free_func = &free_pipe_spnego_auth_data; p->auth.auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP; + data_blob_free(&blob); + data_blob_free(&secblob); + data_blob_free(&chal); + data_blob_free(&response); + + /* We can't set pipe_bound True yet - we need a response packet... */ return False; -#if 0 - nt_status = auth_ntlmssp_start(auth_ntlmssp_state); - if (!NT_STATUS_IS_OK(nt_status)) { - return ERROR_NT(nt_status); - } - nt_status = auth_ntlmssp_update(*auth_ntlmssp_state, secblob, &chal); + err: - data_blob_free(&secblob); + data_blob_free(&blob); + data_blob_free(&secblob); + data_blob_free(&chal); + data_blob_free(&response); - reply_spnego_ntlmssp(conn, inbuf, outbuf, vuid, auth_ntlmssp_state, &chal, nt_status); - data_blob_free(&chal); - data_blob_free(&secblob); - return True; -#endif + p->auth.a_u.auth_ntlmssp_state = NULL; + p->auth.auth_type = PIPE_AUTH_TYPE_NONE; + + return False; } /******************************************************************* @@ -1015,9 +1041,6 @@ return False; } - p->auth.auth_data_free_func = NULL; - p->auth.auth_type = PIPE_AUTH_TYPE_SCHANNEL; - memset(p->auth.a_u.schannel_auth->sess_key, 0, sizeof(p->auth.a_u.schannel_auth->sess_key)); memcpy(p->auth.a_u.schannel_auth->sess_key, last_dcinfo.sess_key, sizeof(last_dcinfo.sess_key)); @@ -1053,6 +1076,9 @@ neg.domain, neg.myname)); /* We're finished with this bind - no more packets. */ + p->auth.auth_data_free_func = NULL; + p->auth.auth_type = PIPE_AUTH_TYPE_SCHANNEL; + p->pipe_bound = True; return True; @@ -1095,9 +1121,6 @@ return False; } - p->auth.auth_data_free_func = NULL; - - p->auth.auth_type = PIPE_AUTH_TYPE_NTLMSSP; p->auth.a_u.ntlmssp_auth->ntlmssp_chal_flags = SMBD_NTLMSSP_NEG_FLAGS; p->auth.a_u.ntlmssp_auth->ntlmssp_auth_requested = True; @@ -1136,6 +1159,9 @@ DEBUG(10,("pipe_ntlmssp_auth_bind: NTLMSSP auth: domain [%s] myname [%s]\n", ntlmssp_neg.domain, ntlmssp_neg.myname)); + p->auth.auth_data_free_func = NULL; + p->auth.auth_type = PIPE_AUTH_TYPE_NTLMSSP; + /* We can't set pipe_bound True yet - we need a response packet... */ return True; } Modified: trunk/source/smbd/sesssetup.c =================================================================== --- trunk/source/smbd/sesssetup.c 2005-08-04 02:59:19 UTC (rev 9038) +++ trunk/source/smbd/sesssetup.c 2005-08-04 03:04:58 UTC (rev 9039) @@ -348,6 +348,8 @@ Send a session setup reply, wrapped in SPNEGO. Get vuid and check first. End the NTLMSSP exchange context if we are OK/complete fail + This should be split into two functions, one to handle each + leg of the NTLM auth steps. ***************************************************************************/ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf, @@ -422,6 +424,7 @@ and the other end, that we are not finished yet. */ if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + /* NB. This is *NOT* an error case. JRA */ auth_ntlmssp_end(auth_ntlmssp_state); /* Kill the intermediate vuid */ invalidate_vuid(vuid);
