s3-auth use auth_generic_start to get full GENSEC in Samba3 session setup
authorAndrew Bartlett <abartlet@samba.org>
Tue, 26 Jul 2011 05:11:47 +0000 (15:11 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 3 Aug 2011 08:48:04 +0000 (18:48 +1000)
This tests if the auth_generic_start() hook is available on the auth
context during the negprot, and if so it uses auth_generic_start() to
hook to GENSEC to handle the full SPNEGO blob.

Andrew Bartlett

Signed-off-by: Andrew Tridgell <tridge@samba.org>
source3/smbd/globals.h
source3/smbd/negprot.c
source3/smbd/sesssetup.c
source3/smbd/smb2_sesssetup.c

index 9e8059be19d760eae9477e5ec9868424ed4af3fd..26125ce805e78ff85414732a453decbdbff2c70b 100644 (file)
@@ -474,6 +474,9 @@ struct smbd_server_connection {
        unsigned long file_gen_counter;
        int first_file;
 
+       /* Try GENSEC hook */
+       bool use_gensec_hook;
+
        /* number of open connections (tcons) */
        int num_tcons_open;
 
index f1d2fc25457b12e4c69be013723cc27d1454f92c..a58744281c6021f7f11c07117be6a182fa2c6533 100644 (file)
 #include "../libcli/auth/spnego.h"
 #include "serverid.h"
 #include "auth.h"
+#include "ntlmssp_wrap.h"
 #include "messages.h"
 #include "smbprofile.h"
+#include "auth/gensec/gensec.h"
 
 extern fstring remote_proto;
 
@@ -187,6 +189,7 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
        DATA_BLOB blob_out = data_blob_null;
        nstring dos_name;
        fstring unix_name;
+       NTSTATUS status;
 #ifdef DEVELOPER
        size_t slen;
 #endif
@@ -195,8 +198,29 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
                                   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
 
@@ -210,7 +234,9 @@ DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
 
        */
 
-       if (lp_security() != SEC_ADS && !USE_KERBEROS_KEYTAB) {
+       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);
index 2f3bbd61719d88fc135b7355bab92fb56d87b234..020c62cad879a5dba18507c3e0111ca2926bfb59 100644 (file)
@@ -36,6 +36,7 @@
 #include "messages.h"
 #include "smbprofile.h"
 #include "../libcli/security/security.h"
+#include "auth/gensec/gensec.h"
 
 /* For split krb5 SPNEGO blobs. */
 struct pending_auth_data {
@@ -1134,27 +1135,12 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
                return;
        }
 
-       if (blob1.data[0] == ASN1_APPLICATION(0)) {
-
-               /* its a negTokenTarg packet */
-
-               reply_spnego_negotiate(req, vuid, blob1,
-                                      &vuser->auth_ntlmssp_state);
-               data_blob_free(&blob1);
-               return;
-       }
-
-       if (blob1.data[0] == ASN1_CONTEXT(1)) {
-
-               /* its a auth packet */
-
-               reply_spnego_auth(req, vuid, blob1,
-                                 &vuser->auth_ntlmssp_state);
-               data_blob_free(&blob1);
-               return;
-       }
-
-       if (blob1.length > 7 && strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) {
+       /* Handle either raw NTLMSSP or hand off the whole blob to
+        * GENSEC.  The processing at this layer is essentially
+        * identical regardless.  In particular, both rely only on the
+        * status code (not the contents of the packet) and do not
+        * wrap the result */
+       if (sconn->use_gensec_hook || (blob1.length > 7 && strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0)) {
                DATA_BLOB chal;
 
                if (!vuser->auth_ntlmssp_state) {
@@ -1170,7 +1156,11 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
 
                        auth_ntlmssp_want_feature(vuser->auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
 
-                       status = auth_ntlmssp_start(vuser->auth_ntlmssp_state);
+                       if (sconn->use_gensec_hook) {
+                               status = auth_generic_start(vuser->auth_ntlmssp_state, GENSEC_OID_SPNEGO);
+                       } else {
+                               status = auth_ntlmssp_start(vuser->auth_ntlmssp_state);
+                       }
                        if (!NT_STATUS_IS_OK(status)) {
                                /* Kill the intermediate vuid */
                                invalidate_vuid(sconn, vuid);
@@ -1193,6 +1183,26 @@ static void reply_sesssetup_and_X_spnego(struct smb_request *req)
                return;
        }
 
+       if (blob1.data[0] == ASN1_APPLICATION(0)) {
+
+               /* its a negTokenTarg packet */
+
+               reply_spnego_negotiate(req, vuid, blob1,
+                                      &vuser->auth_ntlmssp_state);
+               data_blob_free(&blob1);
+               return;
+       }
+
+       if (blob1.data[0] == ASN1_CONTEXT(1)) {
+
+               /* its a auth packet */
+
+               reply_spnego_auth(req, vuid, blob1,
+                                 &vuser->auth_ntlmssp_state);
+               data_blob_free(&blob1);
+               return;
+       }
+
        /* what sort of packet is this? */
        DEBUG(1,("Unknown packet in reply_sesssetup_and_X_spnego\n"));
 
index a3283117b450f516c1a0cb5df75c2f94c536749f..d1022cd2cfa80b2547f1be2ec4c1504514ec52e8 100644 (file)
@@ -25,6 +25,7 @@
 #include "../libcli/smb/smb_common.h"
 #include "../libcli/auth/spnego.h"
 #include "../libcli/auth/ntlmssp.h"
+#include "../auth/gensec/gensec.h"
 #include "ntlmssp_wrap.h"
 #include "../librpc/gen_ndr/krb5pac.h"
 #include "libads/kerberos_proto.h"
@@ -649,7 +650,11 @@ static NTSTATUS smbd_smb2_raw_ntlmssp_auth(struct smbd_smb2_session *session,
 
                auth_ntlmssp_want_feature(session->auth_ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
 
-               status = auth_ntlmssp_start(session->auth_ntlmssp_state);
+               if (session->sconn->use_gensec_hook) {
+                       status = auth_generic_start(session->auth_ntlmssp_state, GENSEC_OID_SPNEGO);
+               } else {
+                       status = auth_ntlmssp_start(session->auth_ntlmssp_state);
+               }
                if (!NT_STATUS_IS_OK(status)) {
                        TALLOC_FREE(session);
                        return status;
@@ -742,24 +747,30 @@ static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *smb2req,
                return NT_STATUS_REQUEST_NOT_ACCEPTED;
        }
 
-       if (in_security_buffer.data[0] == ASN1_APPLICATION(0)) {
-               return smbd_smb2_spnego_negotiate(session,
+       /* Handle either raw NTLMSSP or hand off the whole blob to
+        * GENSEC.  The processing at this layer is essentially
+        * identical regardless.  In particular, both rely only on the
+        * status code (not the contents of the packet) and do not
+        * wrap the result */
+       if (session->sconn->use_gensec_hook
+           || (in_security_buffer.length > 7 && strncmp((char *)(in_security_buffer.data), "NTLMSSP", 7) == 0)) {
+               return smbd_smb2_raw_ntlmssp_auth(session,
                                                smb2req,
                                                in_security_mode,
                                                in_security_buffer,
                                                out_session_flags,
                                                out_security_buffer,
                                                out_session_id);
-       } else if (in_security_buffer.data[0] == ASN1_CONTEXT(1)) {
-               return smbd_smb2_spnego_auth(session,
+       } else if (in_security_buffer.data[0] == ASN1_APPLICATION(0)) {
+               return smbd_smb2_spnego_negotiate(session,
                                                smb2req,
                                                in_security_mode,
                                                in_security_buffer,
                                                out_session_flags,
                                                out_security_buffer,
                                                out_session_id);
-       } else if (in_security_buffer.length > 7 && strncmp((char *)(in_security_buffer.data), "NTLMSSP", 7) == 0) {
-               return smbd_smb2_raw_ntlmssp_auth(session,
+       } else if (in_security_buffer.data[0] == ASN1_CONTEXT(1)) {
+               return smbd_smb2_spnego_auth(session,
                                                smb2req,
                                                in_security_mode,
                                                in_security_buffer,