r13403: Try to better handle a case where SPNEGO isn't available (allow us to
authorAndrew Bartlett <abartlet@samba.org>
Thu, 9 Feb 2006 03:04:48 +0000 (03:04 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:51:53 +0000 (13:51 -0500)
emulate the behaviour of XP standalone if required).

Andrew Bartlett
(This used to be commit 7f821097fbdbc9f35d96e05f85cf008f36c0eea3)

source4/smb_server/smb/negprot.c
source4/smb_server/smb/sesssetup.c
source4/smb_server/smb_server.h

index d7646d997a16792358f1ec85d2f5064918f4add7..e9db4f119d55ad5628a61595cf3e4ad8a567481a 100644 (file)
@@ -218,6 +218,22 @@ static void reply_lanman2(struct smbsrv_request *req, uint16_t choice)
        req_send_reply(req);
 }
 
+static void reply_nt1_orig(struct smbsrv_request *req)
+{
+       /* Create a token value and add it to the outgoing packet. */
+       if (req->smb_conn->negotiate.encrypted_passwords) {
+               req_grow_data(req, 8);
+               /* note that we do not send a challenge at all if
+                  we are using plaintext */
+               get_challenge(req->smb_conn, req->out.ptr);
+               req->out.ptr += 8;
+               SCVAL(req->out.vwv+1, VWV(16), 8);
+       }
+       req_push_str(req, NULL, lp_workgroup(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
+       req_push_str(req, NULL, lp_netbios_name(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
+       DEBUG(3,("not using SPNEGO\n"));
+}
+
 /****************************************************************************
  Reply for the nt protocol.
 ****************************************************************************/
@@ -313,23 +329,13 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice)
        SSVALS(req->out.vwv+1,VWV(15), req->smb_conn->negotiate.zone_offset/60);
        
        if (!negotiate_spnego) {
-               /* Create a token value and add it to the outgoing packet. */
-               if (req->smb_conn->negotiate.encrypted_passwords) {
-                       req_grow_data(req, 8);
-                       /* note that we do not send a challenge at all if
-                          we are using plaintext */
-                       get_challenge(req->smb_conn, req->out.ptr);
-                       req->out.ptr += 8;
-                       SCVAL(req->out.vwv+1, VWV(16), 8);
-               }
-               req_push_str(req, NULL, lp_workgroup(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
-               req_push_str(req, NULL, lp_netbios_name(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
-               DEBUG(3,("not using SPNEGO\n"));
+               reply_nt1_orig(req);
        } else {
                struct cli_credentials *server_credentials;
                struct gensec_security *gensec_security;
                DATA_BLOB null_data_blob = data_blob(NULL, 0);
                DATA_BLOB blob;
+               const char *oid;
                NTSTATUS nt_status = gensec_server_start(req->smb_conn, 
                                                         &gensec_security,
                                                         req->smb_conn->connection->event.ctx);
@@ -366,31 +372,33 @@ static void reply_nt1(struct smbsrv_request *req, uint16_t choice)
 
                gensec_set_credentials(gensec_security, server_credentials);
 
-               nt_status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_SPNEGO);
+               oid = GENSEC_OID_SPNEGO;
+               nt_status = gensec_start_mech_by_oid(gensec_security, oid);
                
                if (NT_STATUS_IS_OK(nt_status)) {
                        /* Get and push the proposed OID list into the packets */
                        nt_status = gensec_update(gensec_security, req, null_data_blob, &blob);
 
                        if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
-                               DEBUG(0, ("Failed to get SPNEGO to give us the first token: %s\n", nt_errstr(nt_status)));
-                               smbsrv_terminate_connection(req->smb_conn, "Failed to start SPNEGO - no first token\n");
-                               return;
+                               DEBUG(1, ("Failed to get SPNEGO to give us the first token: %s\n", nt_errstr(nt_status)));
                        }
-               } else {
+               }
+
+               if (!NT_STATUS_IS_OK(nt_status) && !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
                        DEBUG(5, ("Failed to start SPNEGO, falling back to NTLMSSP only: %s\n", nt_errstr(nt_status)));
-                       nt_status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_NTLMSSP);
+                       oid = GENSEC_OID_NTLMSSP;
+                       nt_status = gensec_start_mech_by_oid(gensec_security, oid);
                        
                        if (!NT_STATUS_IS_OK(nt_status)) {
                                DEBUG(0, ("Failed to start SPNEGO as well as NTLMSSP fallback: %s\n", nt_errstr(nt_status)));
-                               smbsrv_terminate_connection(req->smb_conn, "Failed to start SPNEGO and NTLMSSP");
+                               reply_nt1_orig(req);
                                return;
                        }
                        /* NTLMSSP is a client-first exchange */
                        blob = data_blob(NULL, 0);
                }
 
-               req->smb_conn->negotiate.spnego_negotiated = True;
+               req->smb_conn->negotiate.oid = oid;
        
                req_grow_data(req, blob.length + 16);
                /* a NOT very random guid, perhaps we should get it
index 225f0f7c479a53bf89cd9b946d2f2da1abd00a27..a90f709a12ecfd3d9913404cc3754539086a22ef 100644 (file)
@@ -149,7 +149,7 @@ static NTSTATUS sesssetup_nt1(struct smbsrv_request *req, union smb_sesssetup *s
                req->smb_conn->negotiate.client_caps = sess->nt1.in.capabilities;
        }
 
-       if (req->smb_conn->negotiate.spnego_negotiated) {
+       if (req->smb_conn->negotiate.oid) {
                if (sess->nt1.in.user && *sess->nt1.in.user) {
                        /* We can't accept a normal login, because we
                         * don't have a challenge */
@@ -294,9 +294,10 @@ static NTSTATUS sesssetup_spnego(struct smbsrv_request *req, union smb_sesssetup
 
                gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
 
-               status = gensec_start_mech_by_oid(gensec_ctx, GENSEC_OID_SPNEGO);
+               status = gensec_start_mech_by_oid(gensec_ctx, req->smb_conn->negotiate.oid);
                if (!NT_STATUS_IS_OK(status)) {
-                       DEBUG(1, ("Failed to start GENSEC SPNEGO server code: %s\n", nt_errstr(status)));
+                       DEBUG(1, ("Failed to start GENSEC %s server code: %s\n", 
+                                 gensec_get_name_by_oid(req->smb_conn->negotiate.oid), nt_errstr(status)));
                        return status;
                }
 
index b72c207e3bd157794b621b3ec3db13f65432163d..0c201b2b1d0038c767ef07e23f44a17f0d73fa20 100644 (file)
@@ -251,8 +251,8 @@ struct smbsrv_connection {
                /* did we tell the client we support encrypted passwords? */
                BOOL encrypted_passwords;
        
-               /* did we send an extended security negprot reply? */
-               BOOL spnego_negotiated;
+               /* Did we choose SPNEGO, or perhaps raw NTLMSSP, or even no extended security at all? */
+               const char *oid;
        
                /* client capabilities */
                uint32_t client_caps;