diff --git a/krb5-1.13.2/MakeKitBuild b/krb5-1.13.2/MakeKitBuild index 241586c73..29da41881 100644 --- a/krb5-1.13.2/MakeKitBuild +++ b/krb5-1.13.2/MakeKitBuild @@ -11,6 +11,8 @@ make() HEADERDEPS="openssl/opensslv.h" \ LIBDEPS="ssl crypto" \ CPPFLAGS="$KRB5_CPPFLAGS" \ + CFLAGS="-g" \ + LDFLAGS="-g" \ HEADERS='krb5.h gssapi.h gssapi/gssapi_ext.h' \ LIBS='krb5 gssapi_krb5 k5crypto' \ --enable-shared \ diff --git a/krb5-1.13.2/src/include/k5-int.h b/krb5-1.13.2/src/include/k5-int.h index d57dd6b8b..e315d2342 100644 --- a/krb5-1.13.2/src/include/k5-int.h +++ b/krb5-1.13.2/src/include/k5-int.h @@ -1772,14 +1772,38 @@ krb5int_random_string(krb5_context, char *string, unsigned int length); /* To keep happy libraries which are (for now) accessing internal stuff */ +/* !!!!!! DUPLICATION + The following are duplicated because I don't know how else to make them available. +*/ +struct srv_dns_entry { + struct srv_dns_entry *next; + int priority; + int weight; + unsigned short port; + char *host; +}; + +krb5_error_code krb5int_make_srv_query_realm(const krb5_data *realm, + const char *service, + const char *protocol, + struct srv_dns_entry **answers); +void krb5int_free_srv_dns_data(struct srv_dns_entry *); +/* !!!!!! DUPLICATION */ + /* Make sure to increment by one when changing the struct */ -#define KRB5INT_ACCESS_STRUCT_VERSION 21 +#define KRB5INT_ACCESS_STRUCT_VERSION 22 typedef struct _krb5int_access { krb5_error_code (*auth_con_get_subkey_enctype)(krb5_context, krb5_auth_context, krb5_enctype *); + krb5_error_code (*make_srv_query_realm)(const krb5_data *realm, + const char *service, + const char *protocol, + struct srv_dns_entry **answers); + void (*free_srv_dns_data)(struct srv_dns_entry *); + krb5_error_code (*clean_hostname)(krb5_context, const char *, char *, size_t); diff --git a/krb5-1.13.2/src/lib/krb5/os/accessor.c b/krb5-1.13.2/src/lib/krb5/os/accessor.c index df63b14fa..6e85438a6 100644 --- a/krb5-1.13.2/src/lib/krb5/os/accessor.c +++ b/krb5-1.13.2/src/lib/krb5/os/accessor.c @@ -55,6 +55,15 @@ krb5int_accessor(krb5int_access *internals, krb5_int32 version) S (clean_hostname, k5_clean_hostname), +#ifdef KRB5_DNS_LOOKUP +#define SC(FIELD, VAL) S(FIELD, VAL) +#else /* disable */ +#define SC(FIELD, VAL) S(FIELD, 0) +#endif + SC (make_srv_query_realm, krb5int_make_srv_query_realm), + SC (free_srv_dns_data, krb5int_free_srv_dns_data), +#undef SC + #ifndef LEAN_CLIENT #define SC(FIELD, VAL) S(FIELD, VAL) #else /* disable */ diff --git a/krb5-1.13.2/src/lib/krb5/os/dnsglue.h b/krb5-1.13.2/src/lib/krb5/os/dnsglue.h index 5ab0ad815..5ed6ade0d 100644 --- a/krb5-1.13.2/src/lib/krb5/os/dnsglue.h +++ b/krb5-1.13.2/src/lib/krb5/os/dnsglue.h @@ -155,19 +155,5 @@ int krb5int_dns_expand(struct krb5int_dns_state *, const unsigned char *, char *, int); void krb5int_dns_fini(struct krb5int_dns_state *); -struct srv_dns_entry { - struct srv_dns_entry *next; - int priority; - int weight; - unsigned short port; - char *host; -}; - -krb5_error_code krb5int_make_srv_query_realm(const krb5_data *realm, - const char *service, - const char *protocol, - struct srv_dns_entry **answers); -void krb5int_free_srv_dns_data(struct srv_dns_entry *); - #endif /* KRB5_DNS_LOOKUP */ #endif /* !defined(KRB5_DNSGLUE_H) */ diff --git a/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit.h b/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit.h index 83683b352..6177e3720 100644 --- a/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit.h +++ b/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit.h @@ -1,3 +1,4 @@ +#define DEBUG /* * COPYRIGHT (C) 2006,2007 * THE REGENTS OF THE UNIVERSITY OF MICHIGAN @@ -31,6 +32,7 @@ #ifndef _PKINIT_H #define _PKINIT_H +#include #include #include #include diff --git a/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_accessor.c b/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_accessor.c index 6bae94969..148964851 100644 --- a/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_accessor.c +++ b/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_accessor.c @@ -82,6 +82,10 @@ void KRB5_CALLCONV void (*k5int_set_prompt_types)(krb5_context, krb5_prompt_type *); +krb5_error_code (*k5int_make_srv_query_realm) + (const krb5_data *realm, const char *service, + const char *protocol, struct srv_dns_entry **answers); +void (*k5int_free_srv_dns_data)(struct srv_dns_entry *); /* * Grab internal function pointers from the krb5int_accessor @@ -118,5 +122,7 @@ pkinit_accessor_init(void) k5int.encode_krb5_pa_pk_as_rep_draft9; k5int_krb5_free_kdc_req = k5int.free_kdc_req; k5int_set_prompt_types = k5int.set_prompt_types; + k5int_make_srv_query_realm = k5int.make_srv_query_realm; + k5int_free_srv_dns_data = k5int.free_srv_dns_data; return 0; } diff --git a/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_accessor.h b/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_accessor.h index dcee3db53..1104a04fc 100644 --- a/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_accessor.h +++ b/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_accessor.h @@ -77,4 +77,10 @@ extern void KRB5_CALLCONV (*k5int_krb5_free_kdc_req) extern void (*k5int_set_prompt_types) (krb5_context, krb5_prompt_type *); +struct srv_dns_entry; +extern krb5_error_code (*k5int_make_srv_query_realm) + (const krb5_data *realm, const char *service, + const char *protocol, struct srv_dns_entry **answers); +extern void (*k5int_free_srv_dns_data)(struct srv_dns_entry *); + #endif /* _PKINIT_ACCESSOR_H */ diff --git a/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_clnt.c b/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_clnt.c index 5ad735a12..a7179e0bb 100644 --- a/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_clnt.c +++ b/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_clnt.c @@ -466,13 +466,16 @@ verify_kdc_san(krb5_context context, char **certhosts = NULL, **cfghosts = NULL, **hostptr; krb5_principal *princs = NULL, *princptr; unsigned char ***get_dns; + struct srv_dns_entry *kdc_dns_entries = NULL; + const char *kdc_realm = NULL; int i, j; *valid_san = 0; *need_eku_checking = 1; + kdc_realm = krb5_princ_realm(context, kdcprinc); retval = pkinit_libdefault_strings(context, - krb5_princ_realm(context, kdcprinc), + kdc_realm, KRB5_CONF_PKINIT_KDC_HOSTNAME, &cfghosts); if (retval || cfghosts == NULL) { @@ -496,8 +499,10 @@ verify_kdc_san(krb5_context context, retval = KRB5KDC_ERR_KDC_NAME_MISMATCH; goto out; } - for (princptr = princs; *princptr != NULL; princptr++) - TRACE_PKINIT_CLIENT_SAN_KDCCERT_PRINC(context, *princptr); + if (princs != NULL) { + for (princptr = princs; *princptr != NULL; princptr++) + TRACE_PKINIT_CLIENT_SAN_KDCCERT_PRINC(context, *princptr); + } if (certhosts != NULL) { for (hostptr = certhosts; *hostptr != NULL; hostptr++) TRACE_PKINIT_CLIENT_SAN_KDCCERT_DNSNAME(context, *hostptr); @@ -543,6 +548,46 @@ verify_kdc_san(krb5_context context, for (i = 0; certhosts[i] != NULL; i++) { for (j = 0; cfghosts != NULL && cfghosts[j] != NULL; j++) { + if (!strcmp(cfghosts[j], "")) { +#ifdef KRB5_DNS_LOOKUP + struct srv_dns_entry *entry; + + if (kdc_dns_entries == NULL) { + if (k5int_make_srv_query_realm(kdc_realm, + "_kerberos", "_tcp", &kdc_dns_entries)) { + pkiDebug("%s: DNS lookup failed\n", __FUNCTION__); + continue; + } + + /* Remove trailing dot from DNS names. */ + for (entry = kdc_dns_entries; entry != NULL; + entry = entry->next) { + char *cp = strrchr(entry->host, '.'); + + if (cp != NULL && cp[1] == '\0') { + *cp = '\0'; + } + } + } + + for (entry = kdc_dns_entries; entry != NULL; + entry = entry->next) { + pkiDebug("%s: comparing cert name '%s' with DNS name '%s'\n", + __FUNCTION__, certhosts[i], entry->host); + if (!strcasecmp(certhosts[i], entry->host)) { + pkiDebug("%s: we have a dnsName match\n", __FUNCTION__); + *valid_san = 1; + retval = 0; + goto out; + } + } +#else /* KRB5_DNS_LOOKUP */ + pkiDebug("%s: tag used but DNS lookup not enabled in build\n", + __FUNCTION__); +#endif /* KRB5_DNS_LOOKUP */ + + continue; + } pkiDebug("%s: comparing cert name '%s' with config name '%s'\n", __FUNCTION__, certhosts[i], cfghosts[j]); if (strcasecmp(certhosts[i], cfghosts[j]) == 0) { @@ -573,6 +618,9 @@ verify_kdc_san(krb5_context context, } if (cfghosts != NULL) profile_free_list(cfghosts); + if (kdc_dns_entries != NULL) { + k5int_free_srv_dns_data(kdc_dns_entries); + } pkiDebug("%s: returning retval %d, valid_san %d, need_eku_checking %d\n", __FUNCTION__, retval, *valid_san, *need_eku_checking); diff --git a/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_matching.c b/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_matching.c index a3bf3f4e2..8c616a48a 100644 --- a/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_matching.c +++ b/krb5-1.13.2/src/plugins/preauth/pkinit/pkinit_matching.c @@ -81,7 +81,8 @@ relation2string(unsigned int rel) typedef enum { kwvaltype_undefined = 0, kwvaltype_regexp = 1, - kwvaltype_list = 2 + kwvaltype_list = 2, + kwvaltype_principal = 3, } kw_value_type; static char * @@ -101,11 +102,12 @@ struct keyword_desc { keyword_type kwtype; kw_value_type kwvaltype; } matching_keywords[] = { - { "", 4, kw_ku, kwvaltype_list }, - { "", 5, kw_eku, kwvaltype_list }, - { "", 5, kw_san, kwvaltype_regexp }, - { "", 8, kw_issuer, kwvaltype_regexp }, - { "", 9, kw_subject, kwvaltype_regexp }, + { "", 4, kw_ku, kwvaltype_list }, + { "", 5, kw_eku, kwvaltype_list }, + { "", 5, kw_san, kwvaltype_regexp }, + { "", 8, kw_issuer, kwvaltype_regexp }, + { "", 9, kw_subject, kwvaltype_regexp }, + { "", 11, kw_subject, kwvaltype_principal }, { NULL, 0, kw_undefined, kwvaltype_undefined}, }; @@ -322,18 +324,19 @@ parse_rule_component(krb5_context context, else len = (*remaining); - if (len == 0) { + if (len == 0 && kw->kwvaltype != kwvaltype_principal) { pkiDebug("%s: Missing value for keyword '%s'\n", __FUNCTION__, kw->value); retval = EINVAL; goto out; + } else { + value = calloc(1, len+1); + if (value == NULL ) { + retval = ENOMEM; + goto out; + } } - value = calloc(1, len+1); - if (value == NULL) { - retval = ENOMEM; - goto out; - } memcpy(value, *rule, len); *remaining -= len; *rule += len; @@ -466,7 +469,8 @@ regexp_match(krb5_context context, rule_component *rc, char *value) static int component_match(krb5_context context, rule_component *rc, - pkinit_cert_matching_data *md) + pkinit_cert_matching_data *md, + krb5_principal princ) { int match = 0; int i; @@ -523,6 +527,29 @@ component_match(krb5_context context, break; } break; + case kwvaltype_principal: + if (md->sans == NULL) + break; +#ifdef DEBUG + krb5_unparse_name(context, princ, &princ_string); +#endif + for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i]) { +#ifdef DEBUG + char *san_string; + + krb5_unparse_name(context, p, &san_string); + pkiDebug("%s: comparing principal '%s' with cert SAN '%s'\n", + __FUNCTION__, princ_string, san_string); +#endif + if (krb5_principal_compare_flags(context, p, princ, + KRB5_PRINCIPAL_COMPARE_CASEFOLD)) { + match = 1; + break; + } + if (match) + break; + } + break; default: pkiDebug("%s: unknown keyword value type %d\n", __FUNCTION__, rc->kwval_type); @@ -554,6 +581,8 @@ check_all_certs(krb5_context context, rule_component *rc; int certs_checked = 0; pkinit_cert_matching_data *save_match = NULL; + char *princ_string = NULL; + char *princ_realm = NULL; if (match_found == NULL || matching_cert == NULL) return EINVAL; @@ -564,24 +593,34 @@ check_all_certs(krb5_context context, pkiDebug("%s: matching rule relation is %s with %d components\n", __FUNCTION__, relation2string(rs->relation), rs->num_crs); + if (princ) + { + retval = krb5_unparse_name(context, princ, &princ_string); + if (retval || princ_string == NULL) { + return EINVAL; + } + + princ_realm = strchr(princ_string, '@'); + + if (princ_realm == NULL) { + krb5_free_unparsed_name(context, princ_string); + return EINVAL; + } + + *princ_realm++ = '\0'; + } + /* * Loop through all the certs available and count * how many match the rule */ for (i = 0, md = matchdata[i]; md != NULL; md = matchdata[++i]) { pkiDebug("%s: subject: '%s'\n", __FUNCTION__, md->subject_dn); -#if 0 - pkiDebug("%s: issuer: '%s'\n", __FUNCTION__, md->subject_dn); - for (j = 0, p = md->sans[j]; p != NULL; p = md->sans[++j]) { - char *san_string; - krb5_unparse_name(context, p, &san_string); - pkiDebug("%s: san: '%s'\n", __FUNCTION__, san_string); - krb5_free_unparsed_name(context, san_string); - } -#endif + pkiDebug("%s: issuer: '%s'\n", __FUNCTION__, md->issuer_dn); + certs_checked++; for (rc = rs->crs; rc != NULL; rc = rc->next) { - comp_match = component_match(context, rc, md); + comp_match = component_match(context, rc, md, princ); if (comp_match) { pkiDebug("%s: match for keyword type %s\n", __FUNCTION__, keyword2string(rc->kw_type)); @@ -607,6 +646,11 @@ check_all_certs(krb5_context context, nextcert: continue; } + + if (princ_string) { + krb5_free_unparsed_name(context, princ_string); + } + pkiDebug("%s: After checking %d certs, we found %d matches\n", __FUNCTION__, certs_checked, total_cert_matches); if (total_cert_matches == 1) { diff --git a/lwadvapi/threaded/krbtgt.c b/lwadvapi/threaded/krbtgt.c index 833c43bfa..06c197fb3 100644 --- a/lwadvapi/threaded/krbtgt.c +++ b/lwadvapi/threaded/krbtgt.c @@ -128,7 +128,7 @@ LwKrb5GetTgtWithSmartCard( pszCcPath, pdwGoodUntilTime, pPreauthTypes, - sizeof(pPreauthTypes) / sizeof(pPreauthTypes[0]), + 0, //sizeof(pPreauthTypes) / sizeof(pPreauthTypes[0]), cbKrb5Prompter, pvPrompterData );