{
TALLOC_CTX *frame = talloc_stackframe();
struct ads_service_principal p = {0};
- struct berval *scred=NULL;
- int rc, i;
ADS_STATUS status;
- DATA_BLOB blob = data_blob_null;
- char *given_principal = NULL;
- char *OIDs[ASN1_MAX_OIDS];
-#ifdef HAVE_KRB5
- bool got_kerberos_mechanism = False;
-#endif
- const char *mech = NULL;
-
- rc = ldap_sasl_bind_s(ads->ldap.ld, NULL, "GSS-SPNEGO", NULL, NULL, NULL, &scred);
-
- if (rc != LDAP_SASL_BIND_IN_PROGRESS) {
- status = ADS_ERROR(rc);
- goto done;
- }
-
- blob = data_blob(scred->bv_val, scred->bv_len);
-
- ber_bvfree(scred);
-
-#if 0
- file_save("sasl_spnego.dat", blob.data, blob.length);
-#endif
-
- /* the server sent us the first part of the SPNEGO exchange in the negprot
- reply */
- if (!spnego_parse_negTokenInit(talloc_tos(), blob, OIDs, &given_principal, NULL) ||
- OIDs[0] == NULL) {
- status = ADS_ERROR(LDAP_OPERATIONS_ERROR);
- goto done;
- }
- TALLOC_FREE(given_principal);
+ enum credentials_use_kerberos krb5_state;
- /* make sure the server understands kerberos */
- for (i=0;OIDs[i];i++) {
- DEBUG(3,("ads_sasl_spnego_bind: got OID=%s\n", OIDs[i]));
-#ifdef HAVE_KRB5
- if (strcmp(OIDs[i], OID_KERBEROS5_OLD) == 0 ||
- strcmp(OIDs[i], OID_KERBEROS5) == 0) {
- got_kerberos_mechanism = True;
- }
-#endif
- talloc_free(OIDs[i]);
+ if (ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) {
+ krb5_state = CRED_DONT_USE_KERBEROS;
+ } else if (ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP) {
+ krb5_state = CRED_AUTO_USE_KERBEROS;
+ } else {
+ krb5_state = CRED_MUST_USE_KERBEROS;
}
status = ads_generate_service_principal(ads, &p);
goto done;
}
-#ifdef HAVE_KRB5
- if (!(ads->auth.flags & ADS_AUTH_DISABLE_KERBEROS) &&
- got_kerberos_mechanism)
- {
- mech = "KRB5";
-
- if (ads->auth.password == NULL ||
- ads->auth.password[0] == '\0')
- {
-
- status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
- CRED_MUST_USE_KERBEROS,
- p.service, p.hostname,
- blob);
- if (ADS_ERR_OK(status)) {
- ads_free_service_principal(&p);
- goto done;
- }
+ if (krb5_state == CRED_DONT_USE_KERBEROS) {
+ goto do_ntlmssp;
+ }
- DEBUG(10,("ads_sasl_spnego_gensec_bind(KRB5) failed with: %s, "
- "calling kinit\n", ads_errstr(status)));
+ if (ads->auth.password == NULL ||
+ ads->auth.password[0] == '\0')
+ {
+ status = ads_sasl_spnego_gensec_bind(ads,
+ "GSS-SPNEGO",
+ krb5_state,
+ p.service,
+ p.hostname,
+ data_blob_null);
+ if (ADS_ERR_OK(status)) {
+ goto done;
}
- status = ADS_ERROR_KRB5(ads_kinit_password(ads));
+ DEBUG(10,("ads_sasl_spnego_gensec_bind(GSS-SPNEGO): "
+ "failed with: %s, calling kinit\n",
+ ads_errstr(status)));
+ }
- if (ADS_ERR_OK(status)) {
- status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
- CRED_MUST_USE_KERBEROS,
- p.service, p.hostname,
- blob);
- if (!ADS_ERR_OK(status)) {
- DEBUG(0,("kinit succeeded but "
- "ads_sasl_spnego_gensec_bind(KRB5) failed "
- "for %s/%s with user[%s] realm[%s]: %s\n",
- p.service, p.hostname,
- ads->auth.user_name,
- ads->auth.realm,
- ads_errstr(status)));
- }
- }
+ status = ADS_ERROR_KRB5(ads_kinit_password(ads));
- /* only fallback to NTLMSSP if allowed */
- if (ADS_ERR_OK(status) ||
- !(ads->auth.flags & ADS_AUTH_ALLOW_NTLMSSP)) {
- goto done;
+ do_ntlmssp:
+ if (ADS_ERR_OK(status)) {
+ status = ads_sasl_spnego_gensec_bind(ads,
+ "GSS-SPNEGO",
+ krb5_state,
+ p.service,
+ p.hostname,
+ data_blob_null);
+ if (!ADS_ERR_OK(status)) {
+ DEBUG(0,("kinit succeeded but "
+ "ads_sasl_spnego_gensec_bind() failed: %s\n",
+ ads_errstr(status)));
}
- DEBUG(1,("ads_sasl_spnego_gensec_bind(KRB5) failed "
- "for %s/%s with user[%s] realm[%s]: %s, "
- "fallback to NTLMSSP\n",
+ DEBUG(1,("ads_sasl_spnego_gensec_bind(GSS-SPNEGO) failed "
+ "for %s/%s with user[%s] realm[%s]: %s\n",
p.service, p.hostname,
ads->auth.user_name,
ads->auth.realm,
ads_errstr(status)));
}
-#endif
-
- /* lets do NTLMSSP ... this has the big advantage that we don't need
- to sync clocks, and we don't rely on special versions of the krb5
- library for HMAC_MD4 encryption */
- mech = "NTLMSSP";
- status = ads_sasl_spnego_gensec_bind(ads, "GSS-SPNEGO",
- CRED_DONT_USE_KERBEROS,
- p.service, p.hostname,
- data_blob_null);
done:
if (!ADS_ERR_OK(status)) {
- DEBUG(1,("ads_sasl_spnego_gensec_bind(%s) failed "
- "for %s/%s with user[%s] realm=[%s]: %s\n", mech,
+ DEBUG(1,("ads_sasl_spnego_gensec_bind(GSS-SPNEGO) failed "
+ "for %s/%s with user[%s] realm=[%s]: %s\n",
p.service, p.hostname,
ads->auth.user_name,
ads->auth.realm,
}
ads_free_service_principal(&p);
TALLOC_FREE(frame);
- if (blob.data != NULL) {
- data_blob_free(&blob);
- }
return status;
}