diff options
author | Jeremy Allison <jra@samba.org> | 2004-10-29 22:38:10 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:53:05 -0500 |
commit | 0772ddbae1be394c538f1d3529ea84434eadcf97 (patch) | |
tree | 8482824cfa5f0b9f157e61ac22afa045165113fd | |
parent | b57feea6d312de778e232f478d768ac5f3552b3e (diff) | |
download | samba-0772ddbae1be394c538f1d3529ea84434eadcf97.tar.gz samba-0772ddbae1be394c538f1d3529ea84434eadcf97.tar.bz2 samba-0772ddbae1be394c538f1d3529ea84434eadcf97.zip |
r3377: Merge in first part of modified patch from Nalin Dahyabhai <nalin@redhat.com>
for bug #1717.The rest of the code needed to call this patch has not yet been
checked in (that's my next task). This has not yet been tested - I'll do this
once the rest of the patch is integrated.
Jeremy.
(This used to be commit 7565019286cf44f43c8066c005b1cd5c1556435f)
-rw-r--r-- | source3/include/secrets.h | 3 | ||||
-rw-r--r-- | source3/libads/kerberos.c | 555 | ||||
-rw-r--r-- | source3/libads/krb5_setpw.c | 2 | ||||
-rw-r--r-- | source3/libsmb/cliconnect.c | 2 | ||||
-rw-r--r-- | source3/libsmb/clikrb5.c | 47 | ||||
-rw-r--r-- | source3/utils/ntlm_auth.c | 2 |
6 files changed, 592 insertions, 19 deletions
diff --git a/source3/include/secrets.h b/source3/include/secrets.h index cb4fbd043a..4b8d5db66b 100644 --- a/source3/include/secrets.h +++ b/source3/include/secrets.h @@ -32,6 +32,9 @@ /* this one is for storing trusted domain account password */ #define SECRETS_DOMTRUST_ACCT_PASS "SECRETS/$DOMTRUST.ACC" +/* Store the principal name used for Kerberos DES key salt under this key name. */ +#define SECRETS_SALTING_PRINCIPAL "SECRETS/SALTING_PRINCIPAL" + /* The domain sid and our sid are stored here even though they aren't really secret. */ #define SECRETS_DOMAIN_SID "SECRETS/SID" diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c index 327a76826e..9eb4d9da46 100644 --- a/source3/libads/kerberos.c +++ b/source3/libads/kerberos.c @@ -3,8 +3,9 @@ kerberos utility library Copyright (C) Andrew Tridgell 2001 Copyright (C) Remus Koos 2001 - - + Copyright (C) Nalin Dahyabhai 2004. + Copyright (C) Jeremy Allison 2004. + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -24,6 +25,8 @@ #ifdef HAVE_KRB5 +#define LIBADS_CCACHE_NAME "MEMORY:libads" + /* we use a prompter to avoid a crash bug in the kerberos libs when dealing with empty passwords @@ -38,7 +41,7 @@ kerb_prompter(krb5_context ctx, void *data, { if (num_prompts == 0) return 0; - memset(prompts[0].reply->data, 0, prompts[0].reply->length); + memset(prompts[0].reply->data, '\0', prompts[0].reply->length); if (prompts[0].reply->length > 0) { if (data) { strncpy(prompts[0].reply->data, data, prompts[0].reply->length-1); @@ -51,10 +54,15 @@ kerb_prompter(krb5_context ctx, void *data, } /* - simulate a kinit, putting the tgt in the default cache location + simulate a kinit, putting the tgt in the given cache location. If cache_name == NULL + place in default cache location. remus@snapserver.com */ -int kerberos_kinit_password(const char *principal, const char *password, int time_offset, time_t *expire_time) +int kerberos_kinit_password(const char *principal, + const char *password, + int time_offset, + time_t *expire_time, + const char *cache_name) { krb5_context ctx = NULL; krb5_error_code code = 0; @@ -69,7 +77,8 @@ int kerberos_kinit_password(const char *principal, const char *password, int tim krb5_set_real_time(ctx, time(NULL) + time_offset, 0); } - if ((code = krb5_cc_default(ctx, &cc))) { + if ((code = krb5_cc_resolve(ctx, cache_name ? + cache_name : krb5_cc_default_name(ctx), &cc))) { krb5_free_context(ctx); return code; } @@ -129,7 +138,8 @@ int ads_kinit_password(ADS_STRUCT *ads) return KRB5_LIBOS_CANTREADPWD; } - ret = kerberos_kinit_password(s, ads->auth.password, ads->auth.time_offset, &ads->auth.expire); + ret = kerberos_kinit_password(s, ads->auth.password, ads->auth.time_offset, + &ads->auth.expire, NULL); if (ret) { DEBUG(0,("kerberos_kinit_password %s failed: %s\n", @@ -174,4 +184,535 @@ int ads_kdestroy(const char *cc_name) return code; } +/************************************************************************ + Routine to fetch the salting principal for a service. Active + Directory may use a non-obvious principal name to generate the salt + when it determines the key to use for encrypting tickets for a service, + and hopefully we detected that when we joined the domain. + ************************************************************************/ + +static char *kerberos_secrets_fetch_salting_principal(const char *service, int enctype) +{ + char *key = NULL; + char *ret = NULL; + + asprintf(&key, "%s/%s/enctype=%d", SECRETS_SALTING_PRINCIPAL, service, enctype); + if (!key) { + return NULL; + } + ret = (char *)secrets_fetch(key, NULL); + SAFE_FREE(key); + return ret; +} + +/************************************************************************ + Routine to get the salting principal for this service. Active + Directory may use a non-obvious principal name to generate the salt + when it determines the key to use for encrypting tickets for a service, + and hopefully we detected that when we joined the domain. + Caller must free if return is not null. + ************************************************************************/ + +krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, + krb5_principal host_princ, + int enctype) +{ + char *unparsed_name = NULL, *salt_princ_s = NULL; + krb5_principal ret_princ = NULL; + + if (krb5_unparse_name(context, host_princ, &unparsed_name) != 0) { + return (krb5_principal)NULL; + } + + if ((salt_princ_s = kerberos_secrets_fetch_salting_principal(unparsed_name, enctype)) == NULL) { + krb5_free_unparsed_name(context, unparsed_name); + return (krb5_principal)NULL; + } + + if (krb5_parse_name(context, salt_princ_s, &ret_princ) != 0) { + krb5_free_unparsed_name(context, unparsed_name); + SAFE_FREE(salt_princ_s); + return (krb5_principal)NULL; + } + krb5_free_unparsed_name(context, unparsed_name); + SAFE_FREE(salt_princ_s); + return ret_princ; +} + +/************************************************************************ + Routine to set the salting principal for this service. Active + Directory may use a non-obvious principal name to generate the salt + when it determines the key to use for encrypting tickets for a service, + and hopefully we detected that when we joined the domain. + Setting principal to NULL deletes this entry. + ************************************************************************/ + +BOOL kerberos_secrets_store_salting_principal(const char *service, + int enctype, + const char *principal) +{ + char *key = NULL; + BOOL ret = False; + krb5_context context = NULL; + krb5_principal princ = NULL; + char *princ_s = NULL; + char *unparsed_name = NULL; + + krb5_init_context(&context); + if (!context) { + return False; + } + if (strchr_m(service, '@')) { + asprintf(&princ_s, "%s", service); + } else { + asprintf(&princ_s, "%s@%s", service, lp_realm()); + } + + if (krb5_parse_name(context, princ_s, &princ) != 0) { + goto out; + + } + if (krb5_unparse_name(context, princ, &unparsed_name) != 0) { + goto out; + } + + asprintf(&key, "%s/%s/enctype=%d", SECRETS_SALTING_PRINCIPAL, unparsed_name, enctype); + if (!key) { + goto out; + } + + if ((principal != NULL) && (strlen(principal) > 0)) { + ret = secrets_store(key, principal, strlen(principal) + 1); + } else { + ret = secrets_delete(key); + } + + out: + + SAFE_FREE(key); + SAFE_FREE(princ_s); + + if (unparsed_name) { + krb5_free_unparsed_name(context, unparsed_name); + } + if (context) { + krb5_free_context(context); + } + + return ret; +} + +/************************************************************************ + Routine to get initial credentials as a service ticket for the local machine. + Returns a buffer initialized with krb5_mk_req_extended. + ************************************************************************/ + +static krb5_error_code get_service_ticket(krb5_context ctx, + krb5_ccache ccache, + const char *service_principal, + int enctype, + krb5_data *p_outbuf) +{ + krb5_creds creds, *new_creds = NULL; + char *service_s = NULL; + char *machine_account = NULL, *password = NULL; + krb5_data in_data; + krb5_auth_context auth_context = NULL; + krb5_error_code err = 0; + + asprintf(&machine_account, "%s$@%s", global_myname(), lp_realm()); + if (machine_account == NULL) { + goto out; + } + password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + if (password == NULL) { + goto out; + } + if ((err = kerberos_kinit_password(machine_account, password, 0, NULL, LIBADS_CCACHE_NAME)) != 0) { + DEBUG(0,("get_service_ticket: kerberos_kinit_password %s@%s failed: %s\n", + machine_account, + lp_realm(), + error_message(err))); + goto out; + } + + /* Ok - the above call has gotten a TGT. Now we need to get a service + ticket to ourselves. */ + + /* Set up the enctype and client and server principal fields for krb5_get_credentials. */ + memset(&creds, '\0', sizeof(creds)); + kerberos_set_creds_enctype(&creds, enctype); + + if ((err = krb5_cc_get_principal(ctx, ccache, &creds.client))) { + DEBUG(3, ("get_service_ticket: krb5_cc_get_principal failed: %s\n", + error_message(err))); + goto out; + } + + if (strchr_m(service_principal, '@')) { + asprintf(&service_s, "%s", service_principal); + } else { + asprintf(&service_s, "%s@%s", service_principal, lp_realm()); + } + + if ((err = krb5_parse_name(ctx, service_s, &creds.server))) { + DEBUG(0,("get_service_ticket: krb5_parse_name %s failed: %s\n", + service_s, error_message(err))); + goto out; + } + + if ((err = krb5_get_credentials(ctx, 0, ccache, &creds, &new_creds))) { + DEBUG(5,("get_service_ticket: krb5_get_credentials for %s failed: %s\n", + service_s, error_message(err))); + goto out; + } + + memset(&in_data, '\0', sizeof(in_data)); + if ((err = krb5_mk_req_extended(ctx, &auth_context, 0, &in_data, + new_creds, p_outbuf)) != 0) { + DEBUG(0,("get_service_ticket: krb5_mk_req_extended failed: %s\n", + error_message(err))); + goto out; + } + + out: + + if (auth_context) { + krb5_auth_con_free(ctx, auth_context); + } + if (new_creds) { + krb5_free_creds(ctx, new_creds); + } + if (creds.server) { + krb5_free_principal(ctx, creds.server); + } + if (creds.client) { + krb5_free_principal(ctx, creds.client); + } + + SAFE_FREE(service_s); + SAFE_FREE(password); + SAFE_FREE(machine_account); + return err; +} + +/************************************************************************ + Check if the machine password can be used in conjunction with the salting_principal + to generate a key which will successfully decrypt the AP_REQ already + gotten as a message to the local machine. + ************************************************************************/ + +static BOOL verify_service_password(krb5_context ctx, + int enctype, + const char *salting_principal, + krb5_data *in_data) +{ + BOOL ret = False; + krb5_principal salting_kprinc = NULL; + krb5_ticket *ticket = NULL; + krb5_keyblock key; + krb5_data passdata; + char *salting_s = NULL; + char *machine_account = NULL, *password = NULL; + krb5_auth_context auth_context = NULL; + krb5_error_code err; + + memset(&passdata, '\0', sizeof(passdata)); + memset(&key, '\0', sizeof(key)); + + asprintf(&machine_account, "%s$@%s", global_myname(), lp_realm()); + if (machine_account == NULL) { + goto out; + } + password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + if (password == NULL) { + goto out; + } + + if (strchr_m(salting_principal, '@')) { + asprintf(&salting_s, "%s", salting_principal); + } else { + asprintf(&salting_s, "%s@%s", salting_principal, lp_realm()); + } + + if ((err = krb5_parse_name(ctx, salting_s, &salting_kprinc))) { + DEBUG(0,("verify_service_password: krb5_parse_name %s failed: %s\n", + salting_s, error_message(err))); + goto out; + } + + passdata.length = strlen(password); + passdata.data = (char*)password; + if ((err = create_kerberos_key_from_string_direct(ctx, salting_kprinc, &passdata, &key, enctype))) { + DEBUG(0,("verify_service_password: create_kerberos_key_from_string %d failed: %s\n", + enctype, error_message(err))); + goto out; + } + + if ((err = krb5_auth_con_init(ctx, &auth_context)) != 0) { + DEBUG(0,("verify_service_password: krb5_auth_con_init failed %s\n", error_message(err))); + goto out; + } + + if ((err = krb5_auth_con_setuseruserkey(ctx, auth_context, &key)) != 0) { + DEBUG(0,("verify_service_password: krb5_auth_con_setuseruserkey failed %s\n", error_message(err))); + goto out; + } + + if (!(err = krb5_rd_req(ctx, &auth_context, in_data, NULL, NULL, NULL, &ticket))) { + DEBUG(10,("verify_service_password: decrypted message with enctype %u salt %s!\n", + (unsigned int)enctype, salting_s)); + ret = True; + } + + out: + + memset(&passdata, 0, sizeof(passdata)); + krb5_free_keyblock_contents(ctx, &key); + if (ticket != NULL) { + krb5_free_ticket(ctx, ticket); + } + if (salting_kprinc) { + krb5_free_principal(ctx, salting_kprinc); + } + SAFE_FREE(salting_s); + SAFE_FREE(password); + SAFE_FREE(machine_account); + return ret; +} + +/************************************************************************ + * + * From the current draft of kerberos-clarifications: + * + * It is not possible to reliably generate a user's key given a pass + * phrase without contacting the KDC, since it will not be known + * whether alternate salt or parameter values are required. + * + * And because our server has a password, we have this exact problem. We + * make multiple guesses as to which principal name provides the salt which + * the KDC is using. + * + ************************************************************************/ + +static void kerberos_derive_salting_principal_for_enctype(const char *service_principal, + krb5_context ctx, + krb5_ccache ccache, + krb5_enctype enctype, + krb5_enctype *enctypes) +{ + char *salting_principals[3] = {NULL, NULL, NULL}, *second_principal = NULL; + krb5_error_code err = 0; + krb5_data outbuf; + int i, j; + + memset(&outbuf, '\0', sizeof(outbuf)); + + /* Check that the service_principal is useful. */ + if ((service_principal == NULL) || (strlen(service_principal) == 0)) { + return; + } + + /* Generate our first guess -- the principal as-given. */ + asprintf(&salting_principals[0], "%s", service_principal); + if ((salting_principals[0] == NULL) || (strlen(salting_principals[0]) == 0)) { + return; + } + + /* Generate our second guess -- the computer's principal, as Win2k3. */ + asprintf(&second_principal, "host/%s.%s", global_myname(), lp_realm()); + if (second_principal != NULL) { + strlower_m(second_principal); + asprintf(&salting_principals[1], "%s@%s", second_principal, lp_realm()); + SAFE_FREE(second_principal); + } + if ((salting_principals[1] == NULL) || (strlen(salting_principals[1]) == 0)) { + goto out; + } + + /* Generate our third guess -- the computer's principal, as Win2k. */ + asprintf(&second_principal, "HOST/%s", global_myname()); + if (second_principal != NULL) { + strlower_m(second_principal + 5); + asprintf(&salting_principals[2], "%s@%s", + second_principal, lp_realm()); + SAFE_FREE(second_principal); + } + if ((salting_principals[2] == NULL) || (strlen(salting_principals[2]) == 0)) { + goto out; + } + + /* Get a service ticket for ourselves into our memory ccache. */ + /* This will commonly fail if there is no principal by that name (and we're trying + many names). So don't print a debug 0 error. */ + + if ((err = get_service_ticket(ctx, ccache, service_principal, enctype, &outbuf)) != 0) { + DEBUG(3, ("verify_service_password: get_service_ticket failed: %s\n", + error_message(err))); + goto out; + } + + /* At this point we have a message to ourselves, salted only the KDC knows how. We + have to work out what that salting is. */ + + /* Try and find the correct salting principal. */ + for (i = 0; i < sizeof(salting_principals) / sizeof(salting_principals[i]); i++) { + if (verify_service_password(ctx, enctype, salting_principals[i], &outbuf)) { + break; + } + } + + /* If we failed to get a match, return. */ + if (i >= sizeof(salting_principals) / sizeof(salting_principals[i])) { + goto out; + } + + /* If we succeeded, store the principal for use for all enctypes which + * share the same cipher and string-to-key function. Doing this here + * allows servers which just pass a keytab to krb5_rd_req() to work + * correctly. */ + for (j = 0; enctypes[j] != 0; j++) { + if (enctype != enctypes[j]) { + /* If this enctype isn't compatible with the one which + * we used, skip it. */ + + if (!kerberos_compatible_enctypes(ctx, enctypes[j], enctype)) + continue; + } + /* If the principal which gives us the proper salt is the one + * which we would normally guess, don't bother noting anything + * in the secrets tdb. */ + if (strcmp(service_principal, salting_principals[i]) != 0) { + kerberos_secrets_store_salting_principal(service_principal, + enctypes[j], + salting_principals[i]); + } + } + + out : + + kerberos_free_data_contents(ctx, &outbuf); + SAFE_FREE(salting_principals[0]); + SAFE_FREE(salting_principals[1]); + SAFE_FREE(salting_principals[2]); + SAFE_FREE(second_principal); +} + +/************************************************************************ + Go through all the possible enctypes for this principal. + ************************************************************************/ + +void kerberos_derive_salting_principal(krb5_context context, + krb5_ccache ccache, + krb5_enctype *enctypes, + char *service_principal) +{ + int i; + + /* Try for each enctype separately, because the rules are + * different for different enctypes. */ + for (i = 0; enctypes[i] != 0; i++) { + /* Delete secrets entry first. */ + kerberos_secrets_store_salting_principal(service_principal, 0, NULL); +#ifdef ENCTYPE_ARCFOUR_HMAC + if (enctypes[i] == ENCTYPE_ARCFOUR_HMAC) { + /* Of course this'll always work, so just save + * ourselves the effort. */ + continue; + } +#endif + /* Try to figure out what's going on with this + * principal. */ + kerberos_derive_salting_principal_for_enctype(service_principal, + context, + ccache, + enctypes[i], + enctypes); + } +} + +/************************************************************************ + Core function to try and determine what salt is being used for any keytab + keys. + ************************************************************************/ + +BOOL kerberos_derive_cifs_salting_principals(void) +{ + fstring my_fqdn; + char *service = NULL; + krb5_context context = NULL; + krb5_enctype *enctypes = NULL; + krb5_ccache ccache = NULL; + krb5_error_code ret = 0; + BOOL retval = False; + + initialize_krb5_error_table(); + if ((ret = krb5_init_context(&context)) != 0) { + DEBUG(1,("kerberos_derive_cifs_salting_principals: krb5_init_context failed. %s\n", + error_message(ret))); + return False; + } + if ((ret = get_kerberos_allowed_etypes(context, &enctypes)) != 0) { + DEBUG(1,("kerberos_derive_cifs_salting_principals: get_kerberos_allowed_etypes failed. %s\n", + error_message(ret))); + goto out; + } + + if ((ret = krb5_cc_resolve(context, LIBADS_CCACHE_NAME, &ccache)) != 0) { + DEBUG(3, ("get_service_ticket: krb5_cc_resolve for %s failed: %s\n", + LIBADS_CCACHE_NAME, error_message(ret))); + goto out; + } + + if (asprintf(&service, "%s$", global_myname()) != -1) { + strlower_m(service); + kerberos_derive_salting_principal(context, ccache, enctypes, service); + SAFE_FREE(service); + } + if (asprintf(&service, "cifs/%s", global_myname()) != -1) { + strlower_m(service); + kerberos_derive_salting_principal(context, ccache, enctypes, service); + SAFE_FREE(service); + } + if (asprintf(&service, "host/%s", global_myname()) != -1) { + strlower_m(service); + kerberos_derive_salting_principal(context, ccache, enctypes, service); + SAFE_FREE(service); + } + if (asprintf(&service, "cifs/%s.%s", global_myname(), lp_realm()) != -1) { + strlower_m(service); + kerberos_derive_salting_principal(context, ccache, enctypes, service); + SAFE_FREE(service); + } + if (asprintf(&service, "host/%s.%s", global_myname(), lp_realm()) != -1) { + strlower_m(service); + kerberos_derive_salting_principal(context, ccache, enctypes, service); + SAFE_FREE(service); + } + name_to_fqdn(my_fqdn, global_myname()); + if (asprintf(&service, "cifs/%s", my_fqdn) != -1) { + strlower_m(service); + kerberos_derive_salting_principal(context, ccache, enctypes, service); + SAFE_FREE(service); + } + if (asprintf(&service, "host/%s", my_fqdn) != -1) { + strlower_m(service); + kerberos_derive_salting_principal(context, ccache, enctypes, service); + SAFE_FREE(service); + } + + retval = True; + + out: + if (enctypes) { + free_kerberos_etypes(context, enctypes); + } + if (ccache) { + krb5_cc_destroy(context, ccache); + } + if (context) { + krb5_free_context(context); + } + return retval; +} #endif diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c index 84595212e6..385c1f02aa 100644 --- a/source3/libads/krb5_setpw.c +++ b/source3/libads/krb5_setpw.c @@ -667,7 +667,7 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server, { int ret; - if ((ret = kerberos_kinit_password(auth_principal, auth_password, time_offset, NULL))) { + if ((ret = kerberos_kinit_password(auth_principal, auth_password, time_offset, NULL, NULL))) { DEBUG(1,("Failed kinit for principal %s (%s)\n", auth_principal, error_message(ret))); return ADS_ERROR_KRB5(ret); } diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 4ff60c1b1c..60691287e6 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -757,7 +757,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user, int ret; use_in_memory_ccache(); - ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL); + ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL, NULL); if (ret){ SAFE_FREE(principal); diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index 5aa1668705..32a50464e0 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/libsmb/clikrb5.c @@ -81,7 +81,7 @@ #endif #if defined(HAVE_KRB5_PRINCIPAL2SALT) && defined(HAVE_KRB5_USE_ENCTYPE) && defined(HAVE_KRB5_STRING_TO_KEY) - int create_kerberos_key_from_string(krb5_context context, + int create_kerberos_key_from_string_direct(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, @@ -102,7 +102,7 @@ return ret; } #elif defined(HAVE_KRB5_GET_PW_SALT) && defined(HAVE_KRB5_STRING_TO_KEY_SALT) - int create_kerberos_key_from_string(krb5_context context, + int create_kerberos_key_from_string_direct(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, @@ -123,6 +123,27 @@ __ERROR_XX_UNKNOWN_CREATE_KEY_FUNCTIONS #endif +int create_kerberos_key_from_string(krb5_context context, + krb5_principal host_princ, + krb5_data *password, + krb5_keyblock *key, + krb5_enctype enctype) +{ + krb5_principal salt_princ = NULL; + int ret; + /* + * Check if we've determined that the KDC is salting keys for this + * principal/enctype in a non-obvious way. If it is, try to match + * its behavior. + */ + salt_princ = kerberos_fetch_salt_princ_for_host_princ(context, host_princ, enctype); + ret = create_kerberos_key_from_string_direct(context, salt_princ ? salt_princ : host_princ, password, key, enctype); + if (salt_princ) { + krb5_free_principal(context, salt_princ); + } + return ret; +} + #if defined(HAVE_KRB5_GET_PERMITTED_ENCTYPES) krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes) @@ -251,6 +272,17 @@ } #endif +void kerberos_free_data_contents(krb5_context context, krb5_data *pdata) +{ +#if !defined(HAVE_KRB5_FREE_DATA_CONTENTS) + if (pdata->data) { + krb5_free_data_contents(context, pdata); + } +#else + SAFE_FREE(pdata->data); +#endif +} + void kerberos_set_creds_enctype(krb5_creds *pcreds, int enctype) { #if defined(HAVE_KRB5_KEYBLOCK_IN_CREDS) @@ -262,7 +294,7 @@ void kerberos_set_creds_enctype(krb5_creds *pcreds, int enctype) #endif } -krb5_boolean kerberos_compatible_enctypes(krb5_context context, +BOOL kerberos_compatible_enctypes(krb5_context context, krb5_enctype enctype1, krb5_enctype enctype2) { @@ -270,9 +302,9 @@ krb5_boolean kerberos_compatible_enctypes(krb5_context context, krb5_boolean similar = 0; krb5_c_enctype_compare(context, enctype1, enctype2, &similar); - return similar; + return similar ? True : False; #elif defined(HAVE_KRB5_ENCTYPES_COMPATIBLE_KEYS) - return krb5_enctypes_compatible_keys(context, enctype1, enctype2); + return krb5_enctypes_compatible_keys(context, enctype1, enctype2) ? True : False; #endif } @@ -447,10 +479,7 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset, *ticket = data_blob(packet.data, packet.length); -/* Hmm, heimdal dooesn't have this - what's the correct call? */ -#ifdef HAVE_KRB5_FREE_DATA_CONTENTS - krb5_free_data_contents(context, &packet); -#endif + kerberos_free_data_contents(context, &packet); failed: diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 8296ccb5fb..3d51523831 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -1184,7 +1184,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego) pstr_sprintf(user, "%s@%s", opt_username, opt_domain); if ((retval = kerberos_kinit_password(user, opt_password, - 0, NULL))) { + 0, NULL, NULL))) { DEBUG(10, ("Requesting TGT failed: %s\n", error_message(retval))); return False; } |