X-Git-Url: http://git.samba.org/?p=samba.git;a=blobdiff_plain;f=lib%2Fkrb5_wrap%2Fkrb5_samba.c;h=780a7a4adf5d553e482ef3bb8e045ce908fd09bb;hp=dcd6185db9fab36dd2decb6c81cf997f9ce55cd6;hb=946f9dd1170be63b91e31ce825ea123f3c07329b;hpb=1cbdfe91fe0d835ddfcaa7fd4bd0311209c8c25c diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c index dcd6185db9f..780a7a4adf5 100644 --- a/lib/krb5_wrap/krb5_samba.c +++ b/lib/krb5_wrap/krb5_samba.c @@ -23,6 +23,7 @@ #include "includes.h" #include "system/filesys.h" #include "krb5_samba.h" +#include "lib/crypto/crypto.h" #ifdef HAVE_COM_ERR_H #include @@ -143,7 +144,7 @@ const krb5_data *krb5_princ_component(krb5_context context, * * @param[out] pkaddr A Kerberos address to store tha address in. * - * @return True on success, false if an error occured. + * @return True on success, false if an error occurred. */ bool smb_krb5_sockaddr_to_kaddr(struct sockaddr_storage *paddr, krb5_address *pkaddr) @@ -176,7 +177,7 @@ bool smb_krb5_sockaddr_to_kaddr(struct sockaddr_storage *paddr, * * @param[in] pkaddr A Kerberos address to store tha address in. * - * @return True on success, false if an error occured. + * @return True on success, false if an error occurred. */ bool smb_krb5_sockaddr_to_kaddr(struct sockaddr_storage *paddr, krb5_address *pkaddr) @@ -206,6 +207,8 @@ krb5_error_code smb_krb5_mk_error(krb5_context context, krb5_error_code error_code, const char *e_text, krb5_data *e_data, + const krb5_principal client, + const krb5_principal server, krb5_data *enc_err) { krb5_error_code code = EINVAL; @@ -214,27 +217,59 @@ krb5_error_code smb_krb5_mk_error(krb5_context context, error_code, e_text, e_data, - NULL, /* client */ - NULL, /* server */ + client, + server, NULL, /* client_time */ NULL, /* client_usec */ enc_err); #else - krb5_error dec_err = { - .error = error_code, - }; + krb5_principal unspec_server = NULL; + krb5_error errpkt; + errpkt.ctime = 0; + errpkt.cusec = 0; + + code = krb5_us_timeofday(context, + &errpkt.stime, + &errpkt.susec); + if (code != 0) { + return code; + } + + errpkt.error = error_code; + + errpkt.text.length = 0; if (e_text != NULL) { - dec_err.text.length = strlen(e_text); - dec_err.text.data = discard_const_p(char, e_text); + errpkt.text.length = strlen(e_text); + errpkt.text.data = discard_const_p(char, e_text); } + + errpkt.e_data.magic = KV5M_DATA; + errpkt.e_data.length = 0; + errpkt.e_data.data = NULL; if (e_data != NULL) { - dec_err.e_data = *e_data; + errpkt.e_data = *e_data; + } + + errpkt.client = client; + + if (server != NULL) { + errpkt.server = server; + } else { + code = smb_krb5_make_principal(context, + &unspec_server, + "", + NULL); + if (code != 0) { + return code; + } + errpkt.server = unspec_server; } code = krb5_mk_error(context, - &dec_err, + &errpkt, enc_err); + krb5_free_principal(context, unspec_server); #endif return code; } @@ -266,6 +301,42 @@ int smb_krb5_create_key_from_string(krb5_context context, return -1; } + if ((int)enctype == (int)ENCTYPE_ARCFOUR_HMAC) { + TALLOC_CTX *frame = talloc_stackframe(); + uint8_t *utf16 = NULL; + size_t utf16_size = 0; + uint8_t nt_hash[16]; + bool ok; + + ok = convert_string_talloc(frame, CH_UNIX, CH_UTF16LE, + password->data, password->length, + (void **)&utf16, &utf16_size); + if (!ok) { + if (errno == 0) { + errno = EINVAL; + } + ret = errno; + TALLOC_FREE(frame); + return ret; + } + + mdfour(nt_hash, utf16, utf16_size); + memset(utf16, 0, utf16_size); + ret = smb_krb5_keyblock_init_contents(context, + ENCTYPE_ARCFOUR_HMAC, + nt_hash, + sizeof(nt_hash), + key); + ZERO_STRUCT(nt_hash); + if (ret != 0) { + TALLOC_FREE(frame); + return ret; + } + + TALLOC_FREE(frame); + return 0; + } + #if defined(HAVE_KRB5_PRINCIPAL2SALT) && defined(HAVE_KRB5_C_STRING_TO_KEY) {/* MIT */ krb5_data _salt; @@ -989,8 +1060,8 @@ krb5_error_code smb_krb5_kt_open_relative(krb5_context context, goto out; } - if ((strncmp(keytab_name_req, "WRFILE:/", 8) == 0) || - (strncmp(keytab_name_req, "FILE:/", 6) == 0)) { + if ((strncmp(keytab_name_req, "WRFILE:", 7) == 0) || + (strncmp(keytab_name_req, "FILE:", 5) == 0)) { tmp = keytab_name_req; goto resolve; } @@ -1096,12 +1167,29 @@ krb5_error_code smb_krb5_kt_open(krb5_context context, bool write_access, krb5_keytab *keytab) { - if (keytab_name_req != NULL) { - if (keytab_name_req[0] != '/') { - return KRB5_KT_BADNAME; - } + int cmp; + + if (keytab_name_req == NULL) { + return KRB5_KT_BADNAME; + } + + if (keytab_name_req[0] == '/') { + goto open_keytab; + } + + cmp = strncmp(keytab_name_req, "FILE:/", 6); + if (cmp == 0) { + goto open_keytab; + } + + cmp = strncmp(keytab_name_req, "WRFILE:/", 8); + if (cmp == 0) { + goto open_keytab; } + return KRB5_KT_BADNAME; + +open_keytab: return smb_krb5_kt_open_relative(context, keytab_name_req, write_access, @@ -1178,17 +1266,13 @@ krb5_error_code smb_krb5_kt_seek_and_delete_old_entries(krb5_context context, { krb5_error_code ret; krb5_kt_cursor cursor; - krb5_kt_cursor zero_csr; krb5_keytab_entry kt_entry; - krb5_keytab_entry zero_kt_entry; char *ktprinc = NULL; krb5_kvno old_kvno = kvno - 1; TALLOC_CTX *tmp_ctx; ZERO_STRUCT(cursor); - ZERO_STRUCT(zero_csr); ZERO_STRUCT(kt_entry); - ZERO_STRUCT(zero_kt_entry); ret = krb5_kt_start_seq_get(context, keytab, &cursor); if (ret == KRB5_KT_END || ret == ENOENT ) { @@ -1323,10 +1407,10 @@ krb5_error_code smb_krb5_kt_seek_and_delete_old_entries(krb5_context context, out: talloc_free(tmp_ctx); - if (memcmp(&zero_kt_entry, &kt_entry, sizeof(krb5_keytab_entry))) { + if (!all_zero((uint8_t *)&kt_entry, sizeof(kt_entry))) { smb_krb5_kt_free_entry(context, &kt_entry); } - if (memcmp(&cursor, &zero_csr, sizeof(krb5_kt_cursor)) != 0) { + if (!all_zero((uint8_t *)&cursor, sizeof(cursor))) { krb5_kt_end_seq_get(context, keytab, &cursor); } return ret; @@ -1895,6 +1979,7 @@ krb5_error_code smb_krb5_kinit_s4u2_ccache(krb5_context ctx, krb5_principal target_princ; krb5_ccache tmp_cc; const char *self_realm; + const char *client_realm = NULL; krb5_principal blacklist_principal = NULL; krb5_principal whitelist_principal = NULL; @@ -2226,6 +2311,29 @@ krb5_error_code smb_krb5_kinit_s4u2_ccache(krb5_context ctx, return code; } + client_realm = krb5_principal_get_realm(ctx, store_creds.client); + if (client_realm != NULL) { + /* + * Because the CANON flag doesn't have any impact + * on the impersonate_principal => store_creds.client + * realm mapping. We need to store the credentials twice, + * once with the returned realm and once with the + * realm of impersonate_principal. + */ + code = krb5_principal_set_realm(ctx, store_creds.server, + client_realm); + if (code != 0) { + krb5_free_cred_contents(ctx, &store_creds); + return code; + } + + code = krb5_cc_store_cred(ctx, store_cc, &store_creds); + if (code != 0) { + krb5_free_cred_contents(ctx, &store_creds); + return code; + } + } + if (expire_time) { *expire_time = (time_t) store_creds.times.endtime; } @@ -2458,7 +2566,7 @@ krb5_error_code smb_krb5_make_pac_checksum(TALLOC_CTX *mem_ctx, * * @param[in] principal The principal to get the realm from. * - * @return An allocated string with the realm or NULL if an error occured. + * @return An allocated string with the realm or NULL if an error occurred. * * The caller must free the realm string with free() if not needed anymore. */ @@ -2607,7 +2715,9 @@ static char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, goto out; } - if (realm_list && realm_list[0]) { + if (realm_list != NULL && + realm_list[0] != NULL && + realm_list[0][0] != '\0') { realm = talloc_strdup(mem_ctx, realm_list[0]); } @@ -2636,7 +2746,7 @@ static char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, * @param[in] default_realm The default_realm if we cannot get it from the * hostname or netbios name. * - * @return A talloc'ed principal string or NULL if an error occured. + * @return A talloc'ed principal string or NULL if an error occurred. * * The caller needs to free the principal with talloc_free() if it isn't needed * anymore. @@ -2688,7 +2798,7 @@ char *smb_krb5_get_principal_from_service_hostname(TALLOC_CTX *mem_ctx, * * @param[in] mem_ctx The talloc context to allocate the error string on. * - * @return A talloc'ed error string or NULL if an error occured. + * @return A talloc'ed error string or NULL if an error occurred. * * The caller must free the returned error string with talloc_free() if not * needed anymore @@ -2848,6 +2958,18 @@ krb5_error_code smb_krb5_cc_copy_creds(krb5_context context, #ifdef HAVE_KRB5_CC_COPY_CACHE /* Heimdal */ return krb5_cc_copy_cache(context, incc, outcc); #elif defined(HAVE_KRB5_CC_COPY_CREDS) + krb5_error_code ret; + krb5_principal princ = NULL; + + ret = krb5_cc_get_principal(context, incc, &princ); + if (ret != 0) { + return ret; + } + ret = krb5_cc_initialize(context, outcc, princ); + krb5_free_principal(context, princ); + if (ret != 0) { + return ret; + } return krb5_cc_copy_creds(context, incc, outcc); #else #error UNKNOWN_KRB5_CC_COPY_CACHE_OR_CREDS_FUNCTION