mirror of
https://github.com/samba-team/samba.git
synced 2025-08-24 21:49:29 +03:00
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 commit is contained in:
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user