summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Ricker <bricker@apple.com>2008-04-07 15:02:56 -0700
committerJames Peach <jpeach@samba.org>2008-04-07 15:05:51 -0700
commitf700ee6418c7b861efdb0f8eaa61b99ad598b7c3 (patch)
tree78c875b50374d51bce2300b7f2c6a32c874623a0
parent2dfec9e829e6e4c11ebde8c204e06b81cc596a29 (diff)
downloadsamba-f700ee6418c7b861efdb0f8eaa61b99ad598b7c3.tar.gz
samba-f700ee6418c7b861efdb0f8eaa61b99ad598b7c3.tar.bz2
samba-f700ee6418c7b861efdb0f8eaa61b99ad598b7c3.zip
Fix Kerberos interop with Mac OS X 10.5 clients.
Ignore optional req_flags. Use the Kerberos mechanism OID negotiated with the client rather than hardcoding OID_KERBEROS5_OLD. (This used to be commit 59a2bcf30fef14ecc826271862b645dd3a61cb48)
-rw-r--r--source3/libsmb/clispnego.c12
-rw-r--r--source3/smbd/seal.c7
-rw-r--r--source3/smbd/sesssetup.c49
3 files changed, 45 insertions, 23 deletions
diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
index a75032a47d..fa9dba098f 100644
--- a/source3/libsmb/clispnego.c
+++ b/source3/libsmb/clispnego.c
@@ -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);
diff --git a/source3/smbd/seal.c b/source3/smbd/seal.c
index d4394e5bca..955ca471bc 100644
--- a/source3/smbd/seal.c
+++ b/source3/smbd/seal.c
@@ -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
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index e0739ef992..33a54dd0de 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -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);
}
}