diff options
author | Simo Sorce <idra@samba.org> | 2012-04-21 17:26:18 -0400 |
---|---|---|
committer | Simo Sorce <idra@samba.org> | 2012-04-23 19:20:38 -0400 |
commit | 08c733d75fd83fd5e32ced9712d41dd595e0f182 (patch) | |
tree | a49d6ebbf1d6c498294862f268d6890a1e6a507f | |
parent | f7070c90b94954835478a09e89a85c03f0f85500 (diff) | |
download | samba-08c733d75fd83fd5e32ced9712d41dd595e0f182.tar.gz samba-08c733d75fd83fd5e32ced9712d41dd595e0f182.tar.bz2 samba-08c733d75fd83fd5e32ced9712d41dd595e0f182.zip |
Make krb5 wrapper library common so they can be used all over
25 files changed, 470 insertions, 522 deletions
diff --git a/auth/credentials/credentials_krb5.c b/auth/credentials/credentials_krb5.c index c8b685ea79..480d7c5951 100644 --- a/auth/credentials/credentials_krb5.c +++ b/auth/credentials/credentials_krb5.c @@ -30,6 +30,7 @@ #include "auth/kerberos/kerberos_credentials.h" #include "auth/kerberos/kerberos_srv_keytab.h" #include "auth/kerberos/kerberos_util.h" +#include "auth/kerberos/pac_utils.h" #include "param/param.h" static void cli_credentials_invalidate_client_gss_creds( diff --git a/auth/kerberos/gssapi_pac.c b/auth/kerberos/gssapi_pac.c index 05065b2725..d1a79501cc 100644 --- a/auth/kerberos/gssapi_pac.c +++ b/auth/kerberos/gssapi_pac.c @@ -21,7 +21,7 @@ #include "includes.h" #ifdef HAVE_KRB5 -#include "libcli/auth/krb5_wrap.h" +#include "lib/krb5_wrap/krb5_samba.h" #include "auth/kerberos/pac_utils.h" #if 0 @@ -271,4 +271,49 @@ NTSTATUS gssapi_get_session_key(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -#endif + +char *gssapi_error_string(TALLOC_CTX *mem_ctx, + OM_uint32 maj_stat, OM_uint32 min_stat, + const gss_OID mech) +{ + OM_uint32 disp_min_stat, disp_maj_stat; + gss_buffer_desc maj_error_message; + gss_buffer_desc min_error_message; + char *maj_error_string, *min_error_string; + OM_uint32 msg_ctx = 0; + + char *ret; + + maj_error_message.value = NULL; + min_error_message.value = NULL; + maj_error_message.length = 0; + min_error_message.length = 0; + + disp_maj_stat = gss_display_status(&disp_min_stat, maj_stat, + GSS_C_GSS_CODE, mech, + &msg_ctx, &maj_error_message); + disp_maj_stat = gss_display_status(&disp_min_stat, min_stat, + GSS_C_MECH_CODE, mech, + &msg_ctx, &min_error_message); + + maj_error_string = talloc_strndup(mem_ctx, + (char *)maj_error_message.value, + maj_error_message.length); + + min_error_string = talloc_strndup(mem_ctx, + (char *)min_error_message.value, + min_error_message.length); + + ret = talloc_asprintf(mem_ctx, "%s: %s", + maj_error_string, min_error_string); + + talloc_free(maj_error_string); + talloc_free(min_error_string); + + gss_release_buffer(&disp_min_stat, &maj_error_message); + gss_release_buffer(&disp_min_stat, &min_error_message); + + return ret; +} + +#endif /* HAVE_KRB5 */ diff --git a/auth/kerberos/pac_utils.h b/auth/kerberos/pac_utils.h index 9fe08de834..bb954597f5 100644 --- a/auth/kerberos/pac_utils.h +++ b/auth/kerberos/pac_utils.h @@ -21,7 +21,7 @@ #ifndef _PAC_UTILS_H #define _PAC_UTILS_H -#include "libcli/auth/krb5_wrap.h" +#include "lib/krb5_wrap/krb5_samba.h" struct PAC_SIGNATURE_DATA; struct PAC_DATA; @@ -47,4 +47,10 @@ NTSTATUS gssapi_get_session_key(TALLOC_CTX *mem_ctx, gss_ctx_id_t gssapi_context, DATA_BLOB *session_key, uint32_t *keytype); + +/* not the best place here, need to move to a more generic gssapi + * wrapper later */ +char *gssapi_error_string(TALLOC_CTX *mem_ctx, + OM_uint32 maj_stat, OM_uint32 min_stat, + const gss_OID mech); #endif /* _PAC_UTILS_H */ diff --git a/auth/kerberos/wscript_build b/auth/kerberos/wscript_build index f49cc517ba..97b8879c8e 100755 --- a/auth/kerberos/wscript_build +++ b/auth/kerberos/wscript_build @@ -1,4 +1,4 @@ #!/usr/bin/env python bld.SAMBA_SUBSYSTEM('KRB5_PAC', source='gssapi_pac.c kerberos_pac.c', - deps='gssapi_krb5 krb5 ndr-krb5pac com_err') + deps='gssapi_krb5 ndr-krb5pac krb5samba') diff --git a/source3/libsmb/clikrb5.c b/lib/krb5_wrap/krb5_samba.c index 792400b3ce..4e555b2853 100644 --- a/source3/libsmb/clikrb5.c +++ b/lib/krb5_wrap/krb5_samba.c @@ -1,30 +1,29 @@ -/* +/* Unix SMB/CIFS implementation. simple kerberos5 routines for active directory Copyright (C) Andrew Tridgell 2001 Copyright (C) Luke Howard 2002-2003 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 Copyright (C) Guenther Deschner 2005-2009 - + 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 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "includes.h" -#include "smb_krb5.h" -#include "../librpc/gen_ndr/krb5pac.h" -#include "../lib/util/asn1.h" -#include "libsmb/nmblib.h" +#include "krb5_samba.h" +#include "librpc/gen_ndr/krb5pac.h" +#include "lib/util/asn1.h" #ifndef KRB5_AUTHDATA_WIN2K_PAC #define KRB5_AUTHDATA_WIN2K_PAC 128 @@ -44,12 +43,17 @@ /* MIT krb5 1.7beta3 (in Ubuntu Karmic) is missing the prototype, but still has the symbol */ #if !HAVE_DECL_KRB5_AUTH_CON_SET_REQ_CKSUMTYPE -krb5_error_code krb5_auth_con_set_req_cksumtype( +krb5_error_code krb5_auth_con_set_req_cksumtype( krb5_context context, - krb5_auth_context auth_context, + krb5_auth_context auth_context, krb5_cksumtype cksumtype); #endif +#if !defined(SMB_MALLOC) +#undef malloc +#define SMB_MALLOC(s) malloc((s)) +#endif + #if !defined(HAVE_KRB5_SET_DEFAULT_TGS_KTYPES) #if defined(HAVE_KRB5_SET_DEFAULT_TGS_ENCTYPES) @@ -102,7 +106,7 @@ krb5_error_code krb5_auth_con_set_req_cksumtype( } #elif defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */ - bool setup_kaddr( krb5_address *pkaddr, struct sockaddr_storage *paddr) +bool setup_kaddr( krb5_address *pkaddr, struct sockaddr_storage *paddr) { memset(pkaddr, '\0', sizeof(krb5_address)); #if defined(HAVE_IPV6) && defined(ADDRTYPE_INET6) @@ -125,46 +129,61 @@ krb5_error_code krb5_auth_con_set_req_cksumtype( #error UNKNOWN_ADDRTYPE #endif - int create_kerberos_key_from_string(krb5_context context, - krb5_principal host_princ, - krb5_data *password, - krb5_keyblock *key, - krb5_enctype enctype, - bool no_salt) +#if defined(HAVE_KRB5_PRINCIPAL2SALT) && defined(HAVE_KRB5_C_STRING_TO_KEY) +/* MIT */ +int create_kerberos_key_from_string_direct(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. - */ - if (no_salt) { - KRB5_KEY_DATA(key) = (KRB5_KEY_DATA_CAST *)SMB_MALLOC(password->length); - if (!KRB5_KEY_DATA(key)) { - return ENOMEM; - } - memcpy(KRB5_KEY_DATA(key), password->data, password->length); - KRB5_KEY_LENGTH(key) = password->length; - KRB5_KEY_TYPE(key) = enctype; - return 0; + int ret = 0; + krb5_data salt; + + ret = krb5_principal2salt(context, host_princ, &salt); + if (ret) { + DEBUG(1,("krb5_principal2salt failed (%s)\n", error_message(ret))); + return ret; } - 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); + ret = krb5_c_string_to_key(context, enctype, password, &salt, key); + SAFE_FREE(salt.data); + + return ret; +} +#elif defined(HAVE_KRB5_GET_PW_SALT) && defined(HAVE_KRB5_STRING_TO_KEY_SALT) +/* Heimdal */ +int create_kerberos_key_from_string_direct(krb5_context context, + krb5_principal host_princ, + krb5_data *password, + krb5_keyblock *key, + krb5_enctype enctype) +{ + int ret; + krb5_salt salt; + + ret = krb5_get_pw_salt(context, host_princ, &salt); + if (ret) { + DEBUG(1,("krb5_get_pw_salt failed (%s)\n", error_message(ret))); + return ret; } + + ret = krb5_string_to_key_salt(context, enctype, (const char *)password->data, salt, key); + krb5_free_salt(context, salt); + return ret; } +#else +#error UNKNOWN_CREATE_KEY_FUNCTIONS +#endif #if defined(HAVE_KRB5_GET_PERMITTED_ENCTYPES) - krb5_error_code get_kerberos_allowed_etypes(krb5_context context, + krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes) { return krb5_get_permitted_enctypes(context, enctypes); } #elif defined(HAVE_KRB5_GET_DEFAULT_IN_TKT_ETYPES) - krb5_error_code get_kerberos_allowed_etypes(krb5_context context, + krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes) { #ifdef HAVE_KRB5_PDU_NONE_DECL @@ -186,8 +205,8 @@ krb5_error_code krb5_auth_con_set_req_cksumtype( } #endif -bool unwrap_edata_ntstatus(TALLOC_CTX *mem_ctx, - DATA_BLOB *edata, +bool unwrap_edata_ntstatus(TALLOC_CTX *mem_ctx, + DATA_BLOB *edata, DATA_BLOB *edata_out) { DATA_BLOB edata_contents; @@ -195,7 +214,7 @@ bool unwrap_edata_ntstatus(TALLOC_CTX *mem_ctx, int edata_type; if (!edata->length) { - return False; + return false; } data = asn1_init(mem_ctx); @@ -209,12 +228,12 @@ bool unwrap_edata_ntstatus(TALLOC_CTX *mem_ctx, asn1_read_Integer(data, &edata_type); if (edata_type != KRB5_PADATA_PW_SALT) { - DEBUG(0,("edata is not of required type %d but of type %d\n", + DEBUG(0,("edata is not of required type %d but of type %d\n", KRB5_PADATA_PW_SALT, edata_type)); asn1_free(data); - return False; + return false; } - + asn1_start_tag(data, ASN1_CONTEXT(2)); asn1_read_OctetString(data, talloc_tos(), &edata_contents); asn1_end_tag(data); @@ -226,11 +245,11 @@ bool unwrap_edata_ntstatus(TALLOC_CTX *mem_ctx, data_blob_free(&edata_contents); - return True; + return true; } -static bool ads_cleanup_expired_creds(krb5_context context, +static bool ads_cleanup_expired_creds(krb5_context context, krb5_ccache ccache, krb5_creds *credsp) { @@ -245,16 +264,16 @@ static bool ads_cleanup_expired_creds(krb5_context context, will expire within 10 seconds. */ if (credsp->times.endtime >= (time(NULL) + 10)) - return False; + return false; - /* heimdal won't remove creds from a file ccache, and - perhaps we shouldn't anyway, since internally we + /* heimdal won't remove creds from a file ccache, and + perhaps we shouldn't anyway, since internally we use memory ccaches, and a FILE one probably means that we're using creds obtained outside of our exectuable */ if (strequal(cc_type, "FILE")) { DEBUG(5, ("ads_cleanup_expired_creds: We do not remove creds from a %s ccache\n", cc_type)); - return False; + return false; } retval = krb5_cc_remove_cred(context, ccache, 0, credsp); @@ -264,7 +283,7 @@ static bool ads_cleanup_expired_creds(krb5_context context, /* If we have an error in this, we want to display it, but continue as though we deleted it */ } - return True; + return true; } /* Allocate and setup the auth context into the state we need. */ @@ -345,15 +364,92 @@ static krb5_error_code create_gss_checksum(krb5_data *in_data, /* [inout] */ } #endif +/************************************************************** + krb5_parse_name that takes a UNIX charset. +**************************************************************/ + +krb5_error_code smb_krb5_parse_name(krb5_context context, + const char *name, /* in unix charset */ + krb5_principal *principal) +{ + krb5_error_code ret; + char *utf8_name; + size_t converted_size; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!push_utf8_talloc(frame, &utf8_name, name, &converted_size)) { + talloc_free(frame); + return ENOMEM; + } + + ret = krb5_parse_name(context, utf8_name, principal); + TALLOC_FREE(frame); + return ret; +} + +#if !defined(HAVE_KRB5_FREE_UNPARSED_NAME) +void krb5_free_unparsed_name(krb5_context context, char *val) +{ + SAFE_FREE(val); +} +#endif + +/************************************************************** + krb5_parse_name that returns a UNIX charset name. Must + be freed with talloc_free() call. +**************************************************************/ + +krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx, + krb5_context context, + krb5_const_principal principal, + char **unix_name) +{ + krb5_error_code ret; + char *utf8_name; + size_t converted_size; + + *unix_name = NULL; + ret = krb5_unparse_name(context, principal, &utf8_name); + if (ret) { + return ret; + } + + if (!pull_utf8_talloc(mem_ctx, unix_name, utf8_name, &converted_size)) { + krb5_free_unparsed_name(context, utf8_name); + return ENOMEM; + } + krb5_free_unparsed_name(context, utf8_name); + return 0; +} + +krb5_error_code smb_krb5_parse_name_norealm(krb5_context context, + const char *name, + krb5_principal *principal) +{ + /* we are cheating here because parse_name will in fact set the realm. + * We don't care as the only caller of smb_krb5_parse_name_norealm + * ignores the realm anyway when calling + * smb_krb5_principal_compare_any_realm later - Guenther */ + + return smb_krb5_parse_name(context, name, principal); +} + +bool smb_krb5_principal_compare_any_realm(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + return krb5_principal_compare_any_realm(context, princ1, princ2); +} + /* we can't use krb5_mk_req because w2k wants the service to be in a particular format */ -static krb5_error_code ads_krb5_mk_req(krb5_context context, - krb5_auth_context *auth_context, +static krb5_error_code ads_krb5_mk_req(krb5_context context, + krb5_auth_context *auth_context, const krb5_flags ap_req_options, const char *principal, - krb5_ccache ccache, - krb5_data *outbuf, + krb5_ccache ccache, + krb5_data *outbuf, time_t *expire_time, const char *impersonate_princ_s) { @@ -363,7 +459,7 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context, krb5_creds * credsp; krb5_creds creds; krb5_data in_data; - bool creds_ready = False; + bool creds_ready = false; int i = 0, maxtries = 3; ZERO_STRUCT(in_data); @@ -386,11 +482,11 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context, /* obtain ticket & session key */ ZERO_STRUCT(creds); if ((retval = krb5_copy_principal(context, server, &creds.server))) { - DEBUG(1,("ads_krb5_mk_req: krb5_copy_principal failed (%s)\n", + DEBUG(1,("ads_krb5_mk_req: krb5_copy_principal failed (%s)\n", error_message(retval))); goto cleanup_princ; } - + if ((retval = krb5_cc_get_principal(context, ccache, &creds.client))) { /* This can commonly fail on smbd startup with no ticket in the cache. * Report at higher level than 1. */ @@ -420,7 +516,7 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context, } if (!ads_cleanup_expired_creds(context, ccache, credsp)) { - creds_ready = True; + creds_ready = true; } i++; @@ -525,7 +621,7 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context, } #endif - retval = krb5_mk_req_extended(context, auth_context, ap_req_options, + retval = krb5_mk_req_extended(context, auth_context, ap_req_options, &in_data, credsp, outbuf); if (retval) { DEBUG(1,("ads_krb5_mk_req: krb5_mk_req_extended failed (%s)\n", @@ -555,6 +651,19 @@ cleanup_princ: return retval; } +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); + } +#elif defined(HAVE_KRB5_DATA_FREE) + krb5_data_free(context, pdata); +#else + SAFE_FREE(pdata->data); +#endif +} + /* get a kerberos5 ticket for the given service */ @@ -748,7 +857,7 @@ done: if (ret) { goto done; } - + ret = krb5_cc_store_cred(context, ccache, &creds); if (expire_time) { @@ -794,10 +903,13 @@ done: return ret; } - krb5_error_code smb_krb5_gen_netbios_krb5_address(smb_krb5_addresses **kerb_addr) +#define MAX_NETBIOSNAME_LEN 16 + krb5_error_code smb_krb5_gen_netbios_krb5_address(smb_krb5_addresses **kerb_addr, + const char *netbios_name) { krb5_error_code ret = 0; - nstring buf; + char buf[MAX_NETBIOSNAME_LEN]; + int len; #if defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */ krb5_address **addrs = NULL; #elif defined(HAVE_ADDR_TYPE_IN_KRB5_ADDRESS) /* Heimdal */ @@ -809,7 +921,15 @@ done: return ENOMEM; } - put_name(buf, lp_netbios_name(), ' ', 0x20); + /* temporarily duplicate put_name() code here to avoid dependency + * issues for a 5 lines function */ + len = strlen(netbios_name); + memcpy(buf, netbios_name, + (len < MAX_NETBIOSNAME_LEN) ? len : MAX_NETBIOSNAME_LEN - 1); + if (len < MAX_NETBIOSNAME_LEN - 1) { + memset(buf + len, ' ', MAX_NETBIOSNAME_LEN - 1 - len); + } + buf[MAX_NETBIOSNAME_LEN - 1] = 0x20; #if defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */ { @@ -896,10 +1016,10 @@ done: krb5_data *packet) { krb5_error_code ret; - bool got_error_code = False; + bool got_error_code = false; DEBUG(10,("handle_krberror_packet: got error packet\n")); - + #ifdef HAVE_E_DATA_POINTER_IN_KRB5_ERROR /* Heimdal */ { krb5_error krberror; @@ -912,7 +1032,7 @@ done: if (krberror.e_data == NULL || krberror.e_data->data == NULL) { ret = (krb5_error_code) krberror.error_code; - got_error_code = True; + got_error_code = true; } smb_krb5_free_error(context, &krberror); @@ -933,7 +1053,7 @@ done: #else ret = (krb5_error_code)krberror->error; #endif - got_error_code = True; + got_error_code = true; } smb_krb5_free_error(context, krberror); } @@ -945,30 +1065,47 @@ done: return ret; } - krb5_error_code smb_krb5_get_init_creds_opt_alloc(krb5_context context, +krb5_error_code smb_krb5_get_init_creds_opt_alloc(krb5_context context, krb5_get_init_creds_opt **opt) { /* Heimdal or modern MIT version */ return krb5_get_init_creds_opt_alloc(context, opt); } - void smb_krb5_get_init_creds_opt_free(krb5_context context, +void smb_krb5_get_init_creds_opt_free(krb5_context context, krb5_get_init_creds_opt *opt) { /* Modern MIT or Heimdal version */ krb5_get_init_creds_opt_free(context, opt); } - krb5_enctype smb_get_enctype_from_kt_entry(krb5_keytab_entry *kt_entry) +krb5_enctype smb_get_enctype_from_kt_entry(krb5_keytab_entry *kt_entry) { return KRB5_KEY_TYPE(KRB5_KT_KEY(kt_entry)); } +krb5_error_code smb_krb5_kt_free_entry(krb5_context context, + krb5_keytab_entry *kt_entry) +{ +/* Try krb5_free_keytab_entry_contents first, since + * MIT Kerberos >= 1.7 has both krb5_free_keytab_entry_contents and + * krb5_kt_free_entry but only has a prototype for the first, while the + * second is considered private. + */ +#if defined(HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS) + return krb5_free_keytab_entry_contents(context, kt_entry); +#elif defined(HAVE_KRB5_KT_FREE_ENTRY) + return krb5_kt_free_entry(context, kt_entry); +#else +#error UNKNOWN_KT_FREE_FUNCTION +#endif +} + /* caller needs to free etype_s */ - krb5_error_code smb_krb5_enctype_to_string(krb5_context context, - krb5_enctype enctype, - char **etype_s) +krb5_error_code smb_krb5_enctype_to_string(krb5_context context, + krb5_enctype enctype, + char **etype_s) { #ifdef HAVE_KRB5_ENCTYPE_TO_STRING_WITH_KRB5_CONTEXT_ARG return krb5_enctype_to_string(context, enctype, etype_s); /* Heimdal */ @@ -991,7 +1128,7 @@ done: /********************************************************************** * Open a krb5 keytab with flags, handles readonly or readwrite access and * allows to process non-default keytab names. - * @param context krb5_context + * @param context krb5_context * @param keytab_name_req string * @param write_access bool if writable keytab is required * @param krb5_keytab pointer to krb5_keytab (close with krb5_kt_close()) @@ -1003,16 +1140,16 @@ done: #define MAX_KEYTAB_NAME_LEN 1100 #endif - krb5_error_code smb_krb5_open_keytab(krb5_context context, - const char *keytab_name_req, - bool write_access, - krb5_keytab *keytab) +krb5_error_code smb_krb5_open_keytab(krb5_context context, + const char *keytab_name_req, + bool write_access, + krb5_keytab *keytab) { krb5_error_code ret = 0; TALLOC_CTX *mem_ctx; char keytab_string[MAX_KEYTAB_NAME_LEN]; char *kt_str = NULL; - bool found_valid_name = False; + bool found_valid_name = false; const char *pragma = "FILE"; const char *tmp = NULL; @@ -1026,7 +1163,7 @@ done: return ENOMEM; } -#ifdef HAVE_WRFILE_KEYTAB +#ifdef HAVE_WRFILE_KEYTAB if (write_access) { pragma = "WRFILE"; } @@ -1039,7 +1176,7 @@ done: goto out; } - if ((strncmp(keytab_name_req, "WRFILE:/", 8) == 0) || + if ((strncmp(keytab_name_req, "WRFILE:/", 8) == 0) || (strncmp(keytab_name_req, "FILE:/", 6) == 0)) { tmp = keytab_name_req; goto resolve; @@ -1083,13 +1220,13 @@ done: while (next_token_talloc(mem_ctx, &tmp, &kt_str, ",")) { if (strncmp(kt_str, "WRFILE:", 7) == 0) { - found_valid_name = True; + found_valid_name = true; tmp = kt_str; tmp += 7; } if (strncmp(kt_str, "FILE:", 5) == 0) { - found_valid_name = True; + found_valid_name = true; tmp = kt_str; tmp += 5; } @@ -1545,7 +1682,8 @@ static char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, char *kerberos_get_principal_from_service_hostname(TALLOC_CTX *mem_ctx, const char *service, - const char *remote_name) + const char *remote_name, + const char *default_realm) { char *realm = NULL; char *host = NULL; @@ -1561,7 +1699,7 @@ char *kerberos_get_principal_from_service_hostname(TALLOC_CTX *mem_ctx, } if (realm == NULL || *realm == '\0') { - realm = talloc_strdup(talloc_tos(), lp_realm()); + realm = talloc_strdup(talloc_tos(), default_realm); if (!realm) { return NULL; } @@ -1581,6 +1719,25 @@ char *kerberos_get_principal_from_service_hostname(TALLOC_CTX *mem_ctx, return principal; } +char *smb_get_krb5_error_message(krb5_context context, + krb5_error_code code, + TALLOC_CTX *mem_ctx) +{ + char *ret; + +#if defined(HAVE_KRB5_GET_ERROR_MESSAGE) && defined(HAVE_KRB5_FREE_ERROR_MESSAGE) + const char *context_error = krb5_get_error_message(context, code); + if (context_error) { + ret = talloc_asprintf(mem_ctx, "%s: %s", + error_message(code), context_error); + krb5_free_error_message(context, context_error); + return ret; + } +#endif + ret = talloc_strdup(mem_ctx, error_message(code)); + return ret; +} + #else /* HAVE_KRB5 */ /* this saves a few linking headaches */ int cli_krb5_get_ticket(TALLOC_CTX *mem_ctx, diff --git a/source3/include/krb5_protos.h b/lib/krb5_wrap/krb5_samba.h index 99569998a1..3800b024ad 100644 --- a/source3/include/krb5_protos.h +++ b/lib/krb5_wrap/krb5_samba.h @@ -20,19 +20,78 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef _INCLUDE_KRB5_PROTOS_H_ -#define _INCLUDE_KRB5_PROTOS_H_ +#ifndef _KRB5_SAMBA_H +#define _KRB5_SAMBA_H -struct PAC_DATA; -struct PAC_SIGNATURE_DATA; +#ifdef HAVE_KRB5 + +#define KRB5_PRIVATE 1 /* this file uses PRIVATE interfaces! */ +/* this file uses DEPRECATED interfaces! */ + +#if defined(HAVE_KRB5_DEPRECATED_WITH_IDENTIFIER) +#define KRB5_DEPRECATED 1 +#else +#define KRB5_DEPRECATED +#endif + +#include "system/kerberos.h" +#include "system/network.h" + +#ifndef KRB5_ADDR_NETBIOS +#define KRB5_ADDR_NETBIOS 0x14 +#endif + +#ifndef KRB5KRB_ERR_RESPONSE_TOO_BIG +#define KRB5KRB_ERR_RESPONSE_TOO_BIG (-1765328332L) +#endif + +/* Heimdal uses a slightly different name */ +#if defined(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5) && !defined(HAVE_ENCTYPE_ARCFOUR_HMAC) +#define ENCTYPE_ARCFOUR_HMAC ENCTYPE_ARCFOUR_HMAC_MD5 +#endif + +/* The older versions of heimdal that don't have this + define don't seem to use it anyway. I'm told they + always use a subkey */ +#ifndef HAVE_AP_OPTS_USE_SUBKEY +#define AP_OPTS_USE_SUBKEY 0 +#endif + +typedef struct { +#if defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */ + krb5_address **addrs; +#elif defined(HAVE_KRB5_ADDRESSES) /* Heimdal */ + krb5_addresses *addrs; +#else +#error UNKNOWN_KRB5_ADDRESS_TYPE +#endif /* defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) */ +} smb_krb5_addresses; + +#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */ +#define KRB5_KT_KEY(k) (&(k)->key) +#elif HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */ +#define KRB5_KT_KEY(k) (&(k)->keyblock) +#else +#error krb5_keytab_entry has no key or keyblock member +#endif /* HAVE_KRB5_KEYTAB_ENTRY_KEY */ /* work around broken krb5.h on sles9 */ #ifdef SIZEOF_LONG #undef SIZEOF_LONG #endif +#ifdef HAVE_KRB5_KEYBLOCK_KEYVALUE /* Heimdal */ +#define KRB5_KEY_TYPE(k) ((k)->keytype) +#define KRB5_KEY_LENGTH(k) ((k)->keyvalue.length) +#define KRB5_KEY_DATA(k) ((k)->keyvalue.data) +#define KRB5_KEY_DATA_CAST void +#else /* MIT */ +#define KRB5_KEY_TYPE(k) ((k)->enctype) +#define KRB5_KEY_LENGTH(k) ((k)->length) +#define KRB5_KEY_DATA(k) ((k)->contents) +#define KRB5_KEY_DATA_CAST krb5_octet +#endif /* HAVE_KRB5_KEYBLOCK_KEYVALUE */ -#if defined(HAVE_KRB5) krb5_error_code smb_krb5_parse_name(krb5_context context, const char *name, /* in unix charset */ krb5_principal *principal); @@ -60,18 +119,26 @@ void krb5_free_unparsed_name(krb5_context ctx, char *val); #define initialize_krb5_error_table() #endif -/* The following definitions come from libsmb/clikrb5.c */ - -/* Samba wrapper function for krb5 functionality. */ +/* Samba wrapper functions for krb5 functionality. */ bool setup_kaddr( krb5_address *pkaddr, struct sockaddr_storage *paddr); -int create_kerberos_key_from_string(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype, bool no_salt); +int create_kerberos_key_from_string(krb5_context context, + krb5_principal host_princ, + krb5_data *password, + krb5_keyblock *key, + krb5_enctype enctype, + bool no_salt); +int create_kerberos_key_from_string_direct(krb5_context context, + krb5_principal host_princ, + krb5_data *password, + krb5_keyblock *key, + krb5_enctype enctype); + krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes); bool get_krb5_smb_session_key(TALLOC_CTX *mem_ctx, krb5_context context, krb5_auth_context auth_context, DATA_BLOB *session_key, bool remote); krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry); -krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, krb5_principal host_princ, int enctype); void kerberos_set_creds_enctype(krb5_creds *pcreds, int enctype); bool kerberos_compatible_enctypes(krb5_context context, krb5_enctype enctype1, krb5_enctype enctype2); void kerberos_free_data_contents(krb5_context context, krb5_data *pdata); @@ -83,7 +150,8 @@ bool smb_krb5_principal_compare_any_realm(krb5_context context, krb5_const_principal princ2); krb5_error_code smb_krb5_renew_ticket(const char *ccache_string, const char *client_string, const char *service_string, time_t *expire_time); krb5_error_code kpasswd_err_to_krb5_err(krb5_error_code res_code); -krb5_error_code smb_krb5_gen_netbios_krb5_address(smb_krb5_addresses **kerb_addr); +krb5_error_code smb_krb5_gen_netbios_krb5_address(smb_krb5_addresses **kerb_addr, + const char *netbios_name); krb5_error_code smb_krb5_free_addresses(krb5_context context, smb_krb5_addresses *addr); NTSTATUS krb5_to_nt_status(krb5_error_code kerberos_error); krb5_error_code nt_status_to_krb5(NTSTATUS nt_status); @@ -123,9 +191,12 @@ char *smb_krb5_principal_get_realm(krb5_context context, char *kerberos_get_principal_from_service_hostname(TALLOC_CTX *mem_ctx, const char *service, - const char *remote_name); + const char *remote_name, + const char *default_realm); -#endif /* HAVE_KRB5 */ +char *smb_get_krb5_error_message(krb5_context context, + krb5_error_code code, + TALLOC_CTX *mem_ctx); int cli_krb5_get_ticket(TALLOC_CTX *mem_ctx, const char *principal, time_t time_offset, @@ -138,4 +209,7 @@ bool unwrap_edata_ntstatus(TALLOC_CTX *mem_ctx, DATA_BLOB *edata, DATA_BLOB *edata_out); -#endif /* _INCLUDE_KRB5_PROTOS_H_ */ +#endif /* HAVE_KRB5 */ + + +#endif /* _KRB5_SAMBA_H */ diff --git a/lib/krb5_wrap/wscript_build b/lib/krb5_wrap/wscript_build new file mode 100755 index 0000000000..c585819834 --- /dev/null +++ b/lib/krb5_wrap/wscript_build @@ -0,0 +1,7 @@ +#!/usr/bin/env python + +bld.SAMBA_LIBRARY('krb5samba', + source='krb5_samba.c', + deps='samba-util asn1util talloc krb5 com_err', + private_library=True + ) diff --git a/libcli/auth/krb5_wrap.c b/libcli/auth/krb5_wrap.c deleted file mode 100644 index 55a224612d..0000000000 --- a/libcli/auth/krb5_wrap.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - Unix SMB/CIFS implementation. - simple kerberos5 routines for active directory - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Luke Howard 2002-2003 - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005-2011 - Copyright (C) Guenther Deschner 2005-2009 - Copyright (C) Simo Sorce 2010. - - 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#ifdef HAVE_KRB5 - -#include "libcli/auth/krb5_wrap.h" -#include "librpc/gen_ndr/krb5pac.h" - -#if defined(HAVE_KRB5_PRINCIPAL2SALT) && defined(HAVE_KRB5_C_STRING_TO_KEY) -/* MIT */ -int create_kerberos_key_from_string_direct(krb5_context context, - krb5_principal host_princ, - krb5_data *password, - krb5_keyblock *key, - krb5_enctype enctype) -{ - int ret = 0; - krb5_data salt; - - ret = krb5_principal2salt(context, host_princ, &salt); - if (ret) { - DEBUG(1,("krb5_principal2salt failed (%s)\n", error_message(ret))); - return ret; - } - ret = krb5_c_string_to_key(context, enctype, password, &salt, key); - SAFE_FREE(salt.data); - - return ret; -} -#elif defined(HAVE_KRB5_GET_PW_SALT) && defined(HAVE_KRB5_STRING_TO_KEY_SALT) -/* Heimdal */ -int create_kerberos_key_from_string_direct(krb5_context context, - krb5_principal host_princ, - krb5_data *password, - krb5_keyblock *key, - krb5_enctype enctype) -{ - int ret; - krb5_salt salt; - - ret = krb5_get_pw_salt(context, host_princ, &salt); - if (ret) { - DEBUG(1,("krb5_get_pw_salt failed (%s)\n", error_message(ret))); - return ret; - } - - ret = krb5_string_to_key_salt(context, enctype, (const char *)password->data, salt, key); - krb5_free_salt(context, salt); - - return ret; -} -#else -#error UNKNOWN_CREATE_KEY_FUNCTIONS -#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); - } -#elif defined(HAVE_KRB5_DATA_FREE) - krb5_data_free(context, pdata); -#else - SAFE_FREE(pdata->data); -#endif -} - - - krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry) -{ -/* Try krb5_free_keytab_entry_contents first, since - * MIT Kerberos >= 1.7 has both krb5_free_keytab_entry_contents and - * krb5_kt_free_entry but only has a prototype for the first, while the - * second is considered private. - */ -#if defined(HAVE_KRB5_FREE_KEYTAB_ENTRY_CONTENTS) - return krb5_free_keytab_entry_contents(context, kt_entry); -#elif defined(HAVE_KRB5_KT_FREE_ENTRY) - return krb5_kt_free_entry(context, kt_entry); -#else -#error UNKNOWN_KT_FREE_FUNCTION -#endif -} - -/************************************************************** - Wrappers around kerberos string functions that convert from - utf8 -> unix charset and vica versa. -**************************************************************/ - -/************************************************************** - krb5_parse_name that takes a UNIX charset. -**************************************************************/ - - krb5_error_code smb_krb5_parse_name(krb5_context context, - const char *name, /* in unix charset */ - krb5_principal *principal) -{ - krb5_error_code ret; - char *utf8_name; - size_t converted_size; - TALLOC_CTX *frame = talloc_stackframe(); - - if (!push_utf8_talloc(frame, &utf8_name, name, &converted_size)) { - talloc_free(frame); - return ENOMEM; - } - - ret = krb5_parse_name(context, utf8_name, principal); - TALLOC_FREE(frame); - return ret; -} - -#if !defined(HAVE_KRB5_FREE_UNPARSED_NAME) -static void krb5_free_unparsed_name(krb5_context context, char *val) -{ - SAFE_FREE(val); -} -#endif - -/************************************************************** - krb5_parse_name that returns a UNIX charset name. Must - be freed with talloc_free() call. -**************************************************************/ - -krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx, - krb5_context context, - krb5_const_principal principal, - char **unix_name) -{ - krb5_error_code ret; - char *utf8_name; - size_t converted_size; - - *unix_name = NULL; - ret = krb5_unparse_name(context, principal, &utf8_name); - if (ret) { - return ret; - } - - if (!pull_utf8_talloc(mem_ctx, unix_name, utf8_name, &converted_size)) { - krb5_free_unparsed_name(context, utf8_name); - return ENOMEM; - } - krb5_free_unparsed_name(context, utf8_name); - return 0; -} - - krb5_error_code smb_krb5_parse_name_norealm(krb5_context context, - const char *name, - krb5_principal *principal) -{ - /* we are cheating here because parse_name will in fact set the realm. - * We don't care as the only caller of smb_krb5_parse_name_norealm - * ignores the realm anyway when calling - * smb_krb5_principal_compare_any_realm later - Guenther */ - - return smb_krb5_parse_name(context, name, principal); -} - - bool smb_krb5_principal_compare_any_realm(krb5_context context, - krb5_const_principal princ1, - krb5_const_principal princ2) -{ - return krb5_principal_compare_any_realm(context, princ1, princ2); -} - -char *gssapi_error_string(TALLOC_CTX *mem_ctx, - OM_uint32 maj_stat, OM_uint32 min_stat, - const gss_OID mech) -{ - OM_uint32 disp_min_stat, disp_maj_stat; - gss_buffer_desc maj_error_message; - gss_buffer_desc min_error_message; - char *maj_error_string, *min_error_string; - OM_uint32 msg_ctx = 0; - - char *ret; - - maj_error_message.value = NULL; - min_error_message.value = NULL; - maj_error_message.length = 0; - min_error_message.length = 0; - - disp_maj_stat = gss_display_status(&disp_min_stat, maj_stat, GSS_C_GSS_CODE, - mech, &msg_ctx, &maj_error_message); - disp_maj_stat = gss_display_status(&disp_min_stat, min_stat, GSS_C_MECH_CODE, - mech, &msg_ctx, &min_error_message); - - maj_error_string = talloc_strndup(mem_ctx, (char *)maj_error_message.value, maj_error_message.length); - - min_error_string = talloc_strndup(mem_ctx, (char *)min_error_message.value, min_error_message.length); - - ret = talloc_asprintf(mem_ctx, "%s: %s", maj_error_string, min_error_string); - - talloc_free(maj_error_string); - talloc_free(min_error_string); - - gss_release_buffer(&disp_min_stat, &maj_error_message); - gss_release_buffer(&disp_min_stat, &min_error_message); - - return ret; -} - - - char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx) -{ - char *ret; - -#if defined(HAVE_KRB5_GET_ERROR_MESSAGE) && defined(HAVE_KRB5_FREE_ERROR_MESSAGE) - const char *context_error = krb5_get_error_message(context, code); - if (context_error) { - ret = talloc_asprintf(mem_ctx, "%s: %s", error_message(code), context_error); - krb5_free_error_message(context, context_error); - return ret; - } -#endif - ret = talloc_strdup(mem_ctx, error_message(code)); - return ret; -} - -#endif diff --git a/libcli/auth/krb5_wrap.h b/libcli/auth/krb5_wrap.h deleted file mode 100644 index 4c0ef93e4c..0000000000 --- a/libcli/auth/krb5_wrap.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - Unix SMB/CIFS implementation. - simple kerberos5 routines for active directory - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Luke Howard 2002-2003 - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 - Copyright (C) Guenther Deschner 2005-2009 - - 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "system/kerberos.h" - -#ifdef HAVE_KRB5_KEYBLOCK_KEYVALUE /* Heimdal */ -#define KRB5_KEY_TYPE(k) ((k)->keytype) -#define KRB5_KEY_LENGTH(k) ((k)->keyvalue.length) -#define KRB5_KEY_DATA(k) ((k)->keyvalue.data) -#define KRB5_KEY_DATA_CAST void -#else /* MIT */ -#define KRB5_KEY_TYPE(k) ((k)->enctype) -#define KRB5_KEY_LENGTH(k) ((k)->length) -#define KRB5_KEY_DATA(k) ((k)->contents) -#define KRB5_KEY_DATA_CAST krb5_octet -#endif /* HAVE_KRB5_KEYBLOCK_KEYVALUE */ - -int create_kerberos_key_from_string_direct(krb5_context context, - krb5_principal host_princ, - krb5_data *password, - krb5_keyblock *key, - krb5_enctype enctype); -void kerberos_free_data_contents(krb5_context context, krb5_data *pdata); -krb5_error_code smb_krb5_kt_free_entry(krb5_context context, krb5_keytab_entry *kt_entry); - - krb5_error_code smb_krb5_parse_name(krb5_context context, - const char *name, /* in unix charset */ - krb5_principal *principal); -krb5_error_code smb_krb5_unparse_name(TALLOC_CTX *mem_ctx, - krb5_context context, - krb5_const_principal principal, - char **unix_name); - krb5_error_code smb_krb5_parse_name_norealm(krb5_context context, - const char *name, - krb5_principal *principal); - bool smb_krb5_principal_compare_any_realm(krb5_context context, - krb5_const_principal princ1, - krb5_const_principal princ2); -char *gssapi_error_string(TALLOC_CTX *mem_ctx, - OM_uint32 maj_stat, OM_uint32 min_stat, - const gss_OID mech); -char *smb_get_krb5_error_message(krb5_context context, krb5_error_code code, TALLOC_CTX *mem_ctx); - diff --git a/libcli/auth/wscript_build b/libcli/auth/wscript_build index b4b648efa1..893cfd9d95 100644..100755 --- a/libcli/auth/wscript_build +++ b/libcli/auth/wscript_build @@ -2,7 +2,7 @@ bld.SAMBA_LIBRARY('cliauth', source='', - deps='MSRPC_PARSE LIBCLI_AUTH COMMON_SCHANNEL PAM_ERRORS SPNEGO_PARSE KRB5_WRAP errors NTLM_CHECK UTIL_LSARPC', + deps='MSRPC_PARSE LIBCLI_AUTH COMMON_SCHANNEL PAM_ERRORS SPNEGO_PARSE krb5samba errors NTLM_CHECK UTIL_LSARPC', private_library=True, grouping_library=True) @@ -37,7 +37,3 @@ bld.SAMBA_SUBSYSTEM('PAM_ERRORS', bld.SAMBA_SUBSYSTEM('SPNEGO_PARSE', source='spnego_parse.c', deps='asn1util') - -bld.SAMBA_SUBSYSTEM('KRB5_WRAP', - source='krb5_wrap.c', - deps='gssapi_krb5 krb5 ndr-krb5pac com_err KRB5_PAC') diff --git a/libcli/smb/smb_seal.c b/libcli/smb/smb_seal.c index d5bb2388bb..78af733d00 100644 --- a/libcli/smb/smb_seal.c +++ b/libcli/smb/smb_seal.c @@ -20,7 +20,7 @@ #include "includes.h" #include "smb_common.h" #if HAVE_KRB5 -#include "libcli/auth/krb5_wrap.h" +#include "lib/krb5_wrap/krb5_samba.h" #endif #include "auth/gensec/gensec.h" #include "libcli/smb/smb_seal.h" diff --git a/libcli/smb/wscript_build b/libcli/smb/wscript_build index 7a21d4a4a7..6feed445df 100644..100755 --- a/libcli/smb/wscript_build +++ b/libcli/smb/wscript_build @@ -10,7 +10,7 @@ bld.SAMBA_LIBRARY('cli_smb_common', smbXcli_base.c smb1cli_trans.c ''', - deps='LIBCRYPTO errors gssapi gensec KRB5_WRAP LIBASYNC_REQ', + deps='LIBCRYPTO errors gssapi gensec krb5samba LIBASYNC_REQ', public_deps='talloc samba-util', private_library=True, public_headers=''' diff --git a/source3/Makefile.in b/source3/Makefile.in index d48d298e72..1353bd2da8 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -559,11 +559,10 @@ LIBSMB_OBJ0 = \ ../lib/util/asn1.o \ ../libcli/auth/spnego_parse.o \ ../libcli/auth/ntlm_check.o \ - ../libcli/auth/krb5_wrap.o \ libsmb/ntlmssp.o \ libsmb/ntlmssp_wrap.o \ libsmb/auth_generic.o \ - libsmb/clikrb5.o \ + ../lib/krb5_wrap/krb5_samba.o \ libsmb/clispnego.o \ ../auth/gensec/gensec.o \ ../auth/gensec/gensec_start.o \ diff --git a/source3/include/smb_krb5.h b/source3/include/smb_krb5.h index 88e91e1670..1f66212321 100644 --- a/source3/include/smb_krb5.h +++ b/source3/include/smb_krb5.h @@ -1,82 +1 @@ -/* - Unix SMB/CIFS implementation. - simple kerberos5 routines for active directory - Copyright (C) Andrew Tridgell 2001 - Copyright (C) Luke Howard 2002-2003 - Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005 - Copyright (C) Guenther Deschner 2005-2009 - - 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 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef _HEADER_smb_krb5_h -#define _HEADER_smb_krb5_h - -#ifdef HAVE_KRB5 - -#define KRB5_PRIVATE 1 /* this file uses PRIVATE interfaces! */ -/* this file uses DEPRECATED interfaces! */ - -#if defined(HAVE_KRB5_DEPRECATED_WITH_IDENTIFIER) -#define KRB5_DEPRECATED 1 -#else -#define KRB5_DEPRECATED -#endif - -#include "libcli/auth/krb5_wrap.h" -#include "auth/kerberos/pac_utils.h" - -#ifndef KRB5_ADDR_NETBIOS -#define KRB5_ADDR_NETBIOS 0x14 -#endif - -#ifndef KRB5KRB_ERR_RESPONSE_TOO_BIG -#define KRB5KRB_ERR_RESPONSE_TOO_BIG (-1765328332L) -#endif - -/* Heimdal uses a slightly different name */ -#if defined(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5) && !defined(HAVE_ENCTYPE_ARCFOUR_HMAC) -#define ENCTYPE_ARCFOUR_HMAC ENCTYPE_ARCFOUR_HMAC_MD5 -#endif - -/* The older versions of heimdal that don't have this - define don't seem to use it anyway. I'm told they - always use a subkey */ -#ifndef HAVE_AP_OPTS_USE_SUBKEY -#define AP_OPTS_USE_SUBKEY 0 -#endif - -typedef struct { -#if defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) /* MIT */ - krb5_address **addrs; -#elif defined(HAVE_KRB5_ADDRESSES) /* Heimdal */ - krb5_addresses *addrs; -#else -#error UNKNOWN_KRB5_ADDRESS_TYPE -#endif /* defined(HAVE_MAGIC_IN_KRB5_ADDRESS) && defined(HAVE_ADDRTYPE_IN_KRB5_ADDRESS) */ -} smb_krb5_addresses; - -#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEY /* MIT */ -#define KRB5_KT_KEY(k) (&(k)->key) -#elif HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */ -#define KRB5_KT_KEY(k) (&(k)->keyblock) -#else -#error krb5_keytab_entry has no key or keyblock member -#endif /* HAVE_KRB5_KEYTAB_ENTRY_KEY */ - -#endif /* HAVE_KRB5 */ - -#include "krb5_protos.h" - -#endif /* _HEADER_smb_krb5_h */ +#include "lib/krb5_wrap/krb5_samba.h" diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c index 5a8ca28b14..cb218dd7b2 100644 --- a/source3/libads/authdata.c +++ b/source3/libads/authdata.c @@ -31,6 +31,7 @@ #include "librpc/crypto/gse.h" #include "auth/gensec/gensec.h" #include "../libcli/auth/spnego.h" +#include "auth/kerberos/pac_utils.h" #ifdef HAVE_KRB5 diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c index f1df31ca4f..7e95380011 100644 --- a/source3/libads/kerberos.c +++ b/source3/libads/kerberos.c @@ -219,7 +219,8 @@ int kerberos_kinit_password_ext(const char *principal, } #endif if (add_netbios_addr) { - if ((code = smb_krb5_gen_netbios_krb5_address(&addr))) { + if ((code = smb_krb5_gen_netbios_krb5_address(&addr, + lp_netbios_name()))) { goto out; } krb5_get_init_creds_opt_set_address_list(opt, addr->addrs); @@ -407,6 +408,7 @@ bool kerberos_secrets_store_des_salt( const char* salt ) /************************************************************************ ************************************************************************/ +static char* kerberos_secrets_fetch_des_salt( void ) { char *salt, *key; @@ -430,6 +432,7 @@ char* kerberos_secrets_fetch_des_salt( void ) to look for the older tdb keys. Caller must free if return is not null. ************************************************************************/ +static krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, krb5_principal host_princ, int enctype) @@ -462,6 +465,38 @@ krb5_principal kerberos_fetch_salt_princ_for_host_princ(krb5_context context, return ret_princ; } +int create_kerberos_key_from_string(krb5_context context, + krb5_principal host_princ, + krb5_data *password, + krb5_keyblock *key, + krb5_enctype enctype, + bool no_salt) +{ + 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. + */ + if (no_salt) { + KRB5_KEY_DATA(key) = (KRB5_KEY_DATA_CAST *)SMB_MALLOC(password->length); + if (!KRB5_KEY_DATA(key)) { + return ENOMEM; + } + memcpy(KRB5_KEY_DATA(key), password->data, password->length); + KRB5_KEY_LENGTH(key) = password->length; + KRB5_KEY_TYPE(key) = enctype; + return 0; + } + 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; +} + /************************************************************************ Routine to set the salting principal for this service. Active Directory may use a non-obvious principal name to generate the salt diff --git a/source3/libads/kerberos_proto.h b/source3/libads/kerberos_proto.h index 50c56dc081..f7470d2f81 100644 --- a/source3/libads/kerberos_proto.h +++ b/source3/libads/kerberos_proto.h @@ -30,6 +30,8 @@ #ifndef _LIBADS_KERBEROS_PROTO_H_ #define _LIBADS_KERBEROS_PROTO_H_ +#include "system/kerberos.h" + struct PAC_LOGON_INFO; #include "libads/ads_status.h" @@ -49,9 +51,6 @@ int kerberos_kinit_password_ext(const char *principal, int ads_kdestroy(const char *cc_name); char* kerberos_standard_des_salt( void ); bool kerberos_secrets_store_des_salt( const char* salt ); -char* kerberos_secrets_fetch_des_salt( void ); -char *kerberos_get_default_realm_from_ccache(TALLOC_CTX *mem_ctx); -char *kerberos_get_realm_from_hostname(TALLOC_CTX *mem_ctx, const char *hostname); bool kerberos_secrets_store_salting_principal(const char *service, int enctype, @@ -90,4 +89,13 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server, const char *target_principal, const char *new_password, int time_offset); +#ifdef HAVE_KRB5 +int create_kerberos_key_from_string(krb5_context context, + krb5_principal host_princ, + krb5_data *password, + krb5_keyblock *key, + krb5_enctype enctype, + bool no_salt); +#endif + #endif /* _LIBADS_KERBEROS_PROTO_H_ */ diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c index 447f9bcb2a..96a1240554 100644 --- a/source3/librpc/crypto/gse.c +++ b/source3/librpc/crypto/gse.c @@ -28,10 +28,10 @@ #include "auth/gensec/gensec.h" #include "auth/credentials/credentials.h" #include "../librpc/gen_ndr/dcerpc.h" +#include "auth/kerberos/pac_utils.h" #if defined(HAVE_KRB5) -#include "smb_krb5.h" #include "gse_krb5.h" static char *gse_errstr(TALLOC_CTX *mem_ctx, OM_uint32 maj, OM_uint32 min); @@ -231,8 +231,8 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, realm in particular), possibly falling back to GSS_C_NT_HOSTBASED_SERVICE */ - name_buffer.value = kerberos_get_principal_from_service_hostname(gse_ctx, - service, server); + name_buffer.value = kerberos_get_principal_from_service_hostname( + gse_ctx, service, server, lp_realm()); if (!name_buffer.value) { status = NT_STATUS_NO_MEMORY; goto err_out; diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index b9634eb402..9c1e3e1275 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -1962,7 +1962,8 @@ static ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, } else { principal = kerberos_get_principal_from_service_hostname(talloc_tos(), "cifs", - remote_name); + remote_name, + lp_realm()); } if (!principal) { diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 84457f6e52..db9e4d0ff1 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -45,6 +45,7 @@ #include "source3/include/auth.h" #include "source3/auth/proto.h" #include "nsswitch/libwbclient/wbclient.h" +#include "auth/kerberos/pac_utils.h" #ifndef PAM_WINBIND_CONFIG_FILE #define PAM_WINBIND_CONFIG_FILE "/etc/security/pam_winbind.conf" @@ -1915,7 +1916,8 @@ static bool manage_client_krb5_init(struct spnego_data spnego) principal = kerberos_get_principal_from_service_hostname(talloc_tos(), opt_target_service, - opt_target_hostname); + opt_target_hostname, + lp_realm()); if (!principal) { return false; diff --git a/source3/wscript_build b/source3/wscript_build index 0a49015071..ddd33467cc 100755 --- a/source3/wscript_build +++ b/source3/wscript_build @@ -88,7 +88,7 @@ PARAM_UTIL_SRC = '''param/util.c''' PARAM_WITHOUT_REG_SRC = '''param/loadparm.c lib/sharesec.c lib/ldap_debug_handler.c lib/util_names.c''' -KRBCLIENT_SRC = '''libads/kerberos.c libads/ads_status.c libsmb/clikrb5.c''' +KRBCLIENT_SRC = '''libads/kerberos.c libads/ads_status.c''' LIBGPO_SRC0 = '''../libgpo/gpo_ldap.c ../libgpo/gpo_ini.c ../libgpo/gpo_util.c ../libgpo/gpo_fetch.c libgpo/gpo_filesync.c ../libgpo/gpo_sec.c @@ -667,7 +667,7 @@ bld.SAMBA3_LIBRARY('nss_wins', bld.SAMBA3_LIBRARY('gse', source='librpc/crypto/gse_krb5.c librpc/crypto/gse.c', - deps='KRB5_WRAP gensec param KRBCLIENT secrets3', + deps='krb5samba gensec param KRBCLIENT secrets3', private_library=True) bld.SAMBA3_LIBRARY('msrpc3', @@ -782,7 +782,7 @@ bld.SAMBA3_LIBRARY('util_cmdline', bld.SAMBA3_SUBSYSTEM('KRBCLIENT', source=KRBCLIENT_SRC, - public_deps='KRB5_WRAP k5crypto LIBTSOCKET CLDAP LIBNMB', + public_deps='krb5samba k5crypto LIBTSOCKET CLDAP LIBNMB', vars=locals()) bld.SAMBA3_SUBSYSTEM('samba3util', @@ -869,13 +869,13 @@ bld.SAMBA3_LIBRARY('smbldap', bld.SAMBA3_LIBRARY('ads', source=LIBADS_SRC, - deps='cli-ldap-common KRB5_WRAP ldap lber KRBCLIENT param LIBNMB libsmb DCUTIL smbldap', + deps='cli-ldap-common krb5samba ldap lber KRBCLIENT param LIBNMB libsmb DCUTIL smbldap', private_library=True, vars=locals()) bld.SAMBA3_SUBSYSTEM('LIBADS_SERVER', source=LIBADS_SERVER_SRC, - deps='SERVER_MUTEX ndr-krb5pac KRB5_WRAP', + deps='SERVER_MUTEX ndr-krb5pac krb5samba', vars=locals()) bld.SAMBA3_SUBSYSTEM('LIBADS_PRINTER', @@ -997,7 +997,7 @@ bld.SAMBA3_SUBSYSTEM('LIBNET', bld.SAMBA3_LIBRARY('net_keytab', source='libnet/libnet_keytab.c', - deps='KRB5_WRAP ads', + deps='krb5samba ads', vars=locals(), private_library=True) @@ -1527,7 +1527,7 @@ bld.SAMBA3_BINARY('ntlm_auth' + bld.env.suffix3, source=NTLM_AUTH_SRC, deps=''' talloc - KRB5_WRAP + krb5samba LIBINIPARSER libsmb popt_samba3 diff --git a/source4/auth/kerberos/kerberos.h b/source4/auth/kerberos/kerberos.h index fc2195de8d..cc02aee27f 100644 --- a/source4/auth/kerberos/kerberos.h +++ b/source4/auth/kerberos/kerberos.h @@ -23,9 +23,10 @@ #if defined(HAVE_KRB5) +#include "system/kerberos.h" #include "auth/kerberos/krb5_init_context.h" #include "librpc/gen_ndr/krb5pac.h" -#include "libcli/auth/krb5_wrap.h" +#include "lib/krb5_wrap/krb5_samba.h" struct auth_user_info_dc; struct cli_credentials; diff --git a/source4/auth/kerberos/wscript_build b/source4/auth/kerberos/wscript_build index be41d1b7b3..2ba6d56410 100755 --- a/source4/auth/kerberos/wscript_build +++ b/source4/auth/kerberos/wscript_build @@ -2,14 +2,14 @@ bld.SAMBA_SUBSYSTEM('KRB_INIT_CTX', source='krb5_init_context.c', - deps='krb5 com_err' + deps='krb5samba' ) bld.SAMBA_LIBRARY('authkrb5', source='kerberos.c kerberos_heimdal.c kerberos_pac.c keytab_copy.c', autoproto='proto.h', - public_deps='krb5 ndr-krb5pac samba_socket LIBCLI_RESOLVE com_err asn1', - deps='auth_sam_reply tevent LIBPACKET ndr ldb KRB5_WRAP KRB_INIT_CTX errors', + public_deps='ndr-krb5pac krb5samba samba_socket LIBCLI_RESOLVE asn1', + deps='auth_sam_reply tevent LIBPACKET ndr ldb krb5samba KRB_INIT_CTX KRB5_PAC errors', private_library=True ) diff --git a/source4/dsdb/wscript_build b/source4/dsdb/wscript_build index 0eb4eebe1f..af0defdb28 100644..100755 --- a/source4/dsdb/wscript_build +++ b/source4/dsdb/wscript_build @@ -9,7 +9,7 @@ bld.SAMBA_LIBRARY('samdb', public_deps='krb5', public_headers='', vnum='0.0.1', - deps='ndr NDR_DRSUAPI NDR_DRSBLOBS auth_system_session LIBCLI_AUTH ndr SAMDB_SCHEMA ldbsamba samdb-common LIBCLI_DRSUAPI cli-ldap-common samba-util com_err authkrb5 samba-credentials ldbwrap errors', + deps='ndr NDR_DRSUAPI NDR_DRSBLOBS auth_system_session LIBCLI_AUTH ndr SAMDB_SCHEMA ldbsamba samdb-common LIBCLI_DRSUAPI cli-ldap-common samba-util com_err authkrb5 samba-credentials ldbwrap errors krb5samba', ) diff --git a/wscript_build b/wscript_build index 717d8b0a1a..295c1fa6d8 100644..100755 --- a/wscript_build +++ b/wscript_build @@ -133,6 +133,7 @@ bld.RECURSE('source3') bld.RECURSE('dfs_server') bld.RECURSE('file_server') bld.RECURSE('utils') +bld.RECURSE('lib/krb5_wrap') bld.RECURSE('testsuite/headers') bld.RECURSE('testsuite/libsmbclient/src') |