]> git.ipfire.org Git - thirdparty/samba.git/commitdiff
Fix Kerberos interop with Mac OS X 10.5 clients.
authorBill Ricker <bricker@apple.com>
Mon, 7 Apr 2008 22:02:56 +0000 (15:02 -0700)
committerJames Peach <jpeach@samba.org>
Mon, 7 Apr 2008 22:05:51 +0000 (15:05 -0700)
Ignore optional req_flags. Use the Kerberos mechanism OID negotiated
with the client rather than hardcoding OID_KERBEROS5_OLD.

source/libsmb/clispnego.c
source/smbd/seal.c
source/smbd/sesssetup.c

index a75032a47d6a66851a57ece7dcaf1c00012711b0..fa9dba098f6e8f6361c18160c2699d7cca0b102f 100644 (file)
@@ -246,6 +246,18 @@ bool parse_negTokenTarg(DATA_BLOB blob, char *OIDs[ASN1_MAX_OIDS], DATA_BLOB *se
        asn1_end_tag(&data);
        asn1_end_tag(&data);
 
+       /* Skip any optional req_flags that are sent per RFC 4178 */
+       if (asn1_check_tag(&data, ASN1_CONTEXT(1))) {
+               uint8 flags;
+
+               asn1_start_tag(&data, ASN1_CONTEXT(1));
+               asn1_start_tag(&data, ASN1_BITFIELD);
+               while (asn1_tag_remaining(&data) > 0)
+                       asn1_read_uint8(&data, &flags);
+               asn1_end_tag(&data);
+               asn1_end_tag(&data);
+       }
+
        asn1_start_tag(&data, ASN1_CONTEXT(2));
        asn1_read_OctetString(&data,secblob);
        asn1_end_tag(&data);
index d4394e5bcae8dbbc8279e6e728610f73770f61a8..955ca471bc7f2eff9018ddb20403022f63f32002 100644 (file)
@@ -484,10 +484,11 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn,
        DATA_BLOB blob = data_blob_null;
        DATA_BLOB secblob = data_blob_null;
        bool got_kerberos_mechanism = false;
+       char *kerb_mech = NULL;
 
        blob = data_blob_const(*ppdata, *p_data_size);
 
-       status = parse_spnego_mechanisms(blob, &secblob, &got_kerberos_mechanism);
+       status = parse_spnego_mechanisms(blob, &secblob, &kerb_mech);
        if (!NT_STATUS_IS_OK(status)) {
                return nt_status_squash(status);
        }
@@ -496,7 +497,9 @@ static NTSTATUS srv_enc_spnego_negotiate(connection_struct *conn,
 
        srv_free_encryption_context(&partial_srv_trans_enc_ctx);
 
-       if (got_kerberos_mechanism) {
+       if (kerb_mech) {
+               SAFE_FREE(kerb_mech);
+
 #if defined(HAVE_GSSAPI) && defined(HAVE_KRB5)
                status = srv_enc_spnego_gss_negotiate(ppdata, p_data_size, secblob);
 #else
index e0739ef992a30cf9844481c3da10bc21dd4888d6..33a54dd0deeade52de0317eb8c81771d715543d5 100644 (file)
@@ -248,6 +248,7 @@ static bool make_krb5_skew_error(DATA_BLOB *pblob_out)
 
 static void reply_spnego_kerberos(struct smb_request *req,
                                  DATA_BLOB *secblob,
+                                 const char *mechOID,
                                  uint16 vuid,
                                  bool *p_invalidate_vuid)
 {
@@ -598,7 +599,7 @@ static void reply_spnego_kerberos(struct smb_request *req,
                ap_rep_wrapped = data_blob_null;
        }
        response = spnego_gen_auth_response(&ap_rep_wrapped, ret,
-                       OID_KERBEROS5_OLD);
+                       mechOID);
        reply_sesssetup_blob(req, response, ret);
 
        data_blob_free(&ap_rep);
@@ -709,13 +710,15 @@ static void reply_spnego_ntlmssp(struct smb_request *req,
  Is this a krb5 mechanism ?
 ****************************************************************************/
 
-NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
-               bool *p_is_krb5)
+NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in,
+               DATA_BLOB *pblob_out,
+               char **kerb_mechOID)
 {
        char *OIDs[ASN1_MAX_OIDS];
        int i;
+       NTSTATUS ret = NT_STATUS_OK;
 
-       *p_is_krb5 = False;
+       *kerb_mechOID = NULL;
 
        /* parse out the OIDs and the first sec blob */
        if (!parse_negTokenTarg(blob_in, OIDs, pblob_out)) {
@@ -735,7 +738,10 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
 #ifdef HAVE_KRB5
        if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 ||
            strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) {
-               *p_is_krb5 = True;
+               *kerb_mechOID = SMB_STRDUP(OIDs[0]);
+               if (*kerb_mechOID == NULL) {
+                       ret = NT_STATUS_NO_MEMORY;
+               }
        }
 #endif
 
@@ -743,7 +749,7 @@ NTSTATUS parse_spnego_mechanisms(DATA_BLOB blob_in, DATA_BLOB *pblob_out,
                DEBUG(5,("parse_spnego_mechanisms: Got OID %s\n", OIDs[i]));
                free(OIDs[i]);
        }
-       return NT_STATUS_OK;
+       return ret;
 }
 
 /****************************************************************************
@@ -779,11 +785,10 @@ static void reply_spnego_negotiate(struct smb_request *req,
 {
        DATA_BLOB secblob;
        DATA_BLOB chal;
-       bool got_kerberos_mechanism = False;
+       char *kerb_mech = NULL;
        NTSTATUS status;
 
-       status = parse_spnego_mechanisms(blob1, &secblob,
-                       &got_kerberos_mechanism);
+       status = parse_spnego_mechanisms(blob1, &secblob, &kerb_mech);
        if (!NT_STATUS_IS_OK(status)) {
                /* Kill the intermediate vuid */
                invalidate_vuid(vuid);
@@ -795,16 +800,17 @@ static void reply_spnego_negotiate(struct smb_request *req,
                                (unsigned long)secblob.length));
 
 #ifdef HAVE_KRB5
-       if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) ||
+       if (kerb_mech && ((lp_security()==SEC_ADS) ||
                                lp_use_kerberos_keytab()) ) {
                bool destroy_vuid = True;
-               reply_spnego_kerberos(req, &secblob, vuid,
-                                     &destroy_vuid);
+               reply_spnego_kerberos(req, &secblob, kerb_mech,
+                                     vuid, &destroy_vuid);
                data_blob_free(&secblob);
                if (destroy_vuid) {
                        /* Kill the intermediate vuid */
                        invalidate_vuid(vuid);
                }
+               SAFE_FREE(kerb_mech);
                return;
        }
 #endif
@@ -813,12 +819,12 @@ static void reply_spnego_negotiate(struct smb_request *req,
                auth_ntlmssp_end(auth_ntlmssp_state);
        }
 
-       if (got_kerberos_mechanism) {
+       if (kerb_mech) {
                data_blob_free(&secblob);
                /* The mechtoken is a krb5 ticket, but
                 * we need to fall back to NTLM. */
-               reply_spnego_downgrade_to_ntlmssp(req,
-                                       vuid);
+               reply_spnego_downgrade_to_ntlmssp(req, vuid);
+               SAFE_FREE(kerb_mech);
                return;
        }
 
@@ -872,10 +878,9 @@ static void reply_spnego_auth(struct smb_request *req,
 
        if (auth.data[0] == ASN1_APPLICATION(0)) {
                /* Might be a second negTokenTarg packet */
+               char *kerb_mech = NULL;
 
-               bool got_krb5_mechanism = False;
-               status = parse_spnego_mechanisms(auth, &secblob,
-                               &got_krb5_mechanism);
+               status = parse_spnego_mechanisms(auth, &secblob, &kerb_mech);
 
                if (!NT_STATUS_IS_OK(status)) {
                        /* Kill the intermediate vuid */
@@ -887,10 +892,10 @@ static void reply_spnego_auth(struct smb_request *req,
                DEBUG(3,("reply_spnego_auth: Got secblob of size %lu\n",
                                (unsigned long)secblob.length));
 #ifdef HAVE_KRB5
-               if ( got_krb5_mechanism && ((lp_security()==SEC_ADS) ||
+               if (kerb_mech && ((lp_security()==SEC_ADS) ||
                                        lp_use_kerberos_keytab()) ) {
                        bool destroy_vuid = True;
-                       reply_spnego_kerberos(req, &secblob,
+                       reply_spnego_kerberos(req, &secblob, kerb_mech,
                                              vuid, &destroy_vuid);
                        data_blob_free(&secblob);
                        data_blob_free(&auth);
@@ -898,13 +903,14 @@ static void reply_spnego_auth(struct smb_request *req,
                                /* Kill the intermediate vuid */
                                invalidate_vuid(vuid);
                        }
+                       SAFE_FREE(kerb_mech);
                        return;
                }
 #endif
                /* Can't blunder into NTLMSSP auth if we have
                 * a krb5 ticket. */
 
-               if (got_krb5_mechanism) {
+               if (kerb_mech) {
                        /* Kill the intermediate vuid */
                        invalidate_vuid(vuid);
                        DEBUG(3,("reply_spnego_auth: network "
@@ -913,6 +919,7 @@ static void reply_spnego_auth(struct smb_request *req,
                                "not enabled"));
                        reply_nterror(req, nt_status_squash(
                                        NT_STATUS_LOGON_FAILURE));
+                       SAFE_FREE(kerb_mech);
                }
        }