diff --git a/include/Makefile.am b/include/Makefile.am index a60ad8563..43ebe7069 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -133,6 +133,7 @@ CLEANFILES = \ wind.h \ wind_err.h \ kdc-plugin.h \ + kdc-accessors.h \ kdc-audit.h \ csr_authorizer_plugin.h \ gss_preauth_authorizer_plugin.h \ diff --git a/kdc/Makefile.am b/kdc/Makefile.am index 7fdd527dc..c7f57251f 100644 --- a/kdc/Makefile.am +++ b/kdc/Makefile.am @@ -244,7 +244,7 @@ include_HEADERS = kdc.h $(srcdir)/kdc-protos.h noinst_HEADERS = $(srcdir)/kdc-private.h krb5dir = $(includedir)/krb5 -krb5_HEADERS = kdc-audit.h kdc-plugin.h token_validator_plugin.h csr_authorizer_plugin.h gss_preauth_authorizer_plugin.h +krb5_HEADERS = kdc-audit.h kdc-plugin.h kdc-accessors.h token_validator_plugin.h csr_authorizer_plugin.h gss_preauth_authorizer_plugin.h build_HEADERZ = $(krb5_HEADERS) # XXX diff --git a/kdc/NTMakefile b/kdc/NTMakefile index 1a661b435..aca65b104 100644 --- a/kdc/NTMakefile +++ b/kdc/NTMakefile @@ -52,7 +52,8 @@ INCFILES=\ $(INCDIR)\kdc-protos.h \ $(INCDIR)\kdc-private.h \ $(INCDIR)\krb5\kdc-audit.h \ - $(INCDIR)\krb5\kdc-plugin.h + $(INCDIR)\krb5\kdc-plugin.h \ + $(INCDIR)\krb5\kdc-accessors.h all:: $(INCFILES) $(LIBKDC) $(BINPROGRAMS) $(SBINPROGRAMS) $(LIBEXECPROGRAMS) diff --git a/kdc/altsecid_gss_preauth_authorizer.c b/kdc/altsecid_gss_preauth_authorizer.c index db6f58d76..40925d2e4 100644 --- a/kdc/altsecid_gss_preauth_authorizer.c +++ b/kdc/altsecid_gss_preauth_authorizer.c @@ -397,7 +397,10 @@ authorize(void *ctx, struct altsecid_gss_preauth_authorizer_context *c = ctx; struct ad_server_tuple *server = NULL; krb5_error_code ret; - krb5_const_realm realm = krb5_principal_get_realm(r->context, r->client->principal); + krb5_context context = kdc_request_get_context((kdc_request_t)r); + const hdb_entry *client = kdc_request_get_client(r); + krb5_const_principal server_princ = kdc_request_get_server_princ(r); + krb5_const_realm realm = krb5_principal_get_realm(context, client->principal); krb5_boolean reconnect_p = FALSE; krb5_boolean is_tgs; heim_data_t requestor_sid = NULL; @@ -405,11 +408,11 @@ authorize(void *ctx, *authorized = FALSE; *mapped_name = NULL; - if (!krb5_principal_is_federated(r->context, r->client->principal) || + if (!krb5_principal_is_federated(context, client->principal) || (ret_flags & GSS_C_ANON_FLAG)) return KRB5_PLUGIN_NO_HANDLE; - is_tgs = krb5_principal_is_krbtgt(r->context, r->server_princ); + is_tgs = krb5_principal_is_krbtgt(context, server_princ); HEIM_TAILQ_FOREACH(server, &c->servers, link) { if (strcmp(realm, server->realm) == 0) @@ -419,12 +422,12 @@ authorize(void *ctx, if (server == NULL) { server = calloc(1, sizeof(*server)); if (server == NULL) - return krb5_enomem(r->context); + return krb5_enomem(context); server->realm = strdup(realm); if (server->realm == NULL) { free(server); - return krb5_enomem(r->context); + return krb5_enomem(context); } HEIM_TAILQ_INSERT_HEAD(&c->servers, server, link); @@ -432,12 +435,12 @@ authorize(void *ctx, do { if (server->ld == NULL) { - ret = ad_connect(r->context, realm, server); + ret = ad_connect(context, realm, server); if (ret) return ret; } - ret = ad_lookup(r->context, realm, server, + ret = ad_lookup(context, realm, server, initiator_name, mech_type, mapped_name, is_tgs ? &requestor_sid : NULL); if (ret == KRB5KDC_ERR_SVC_UNAVAILABLE) { @@ -472,8 +475,8 @@ finalize_pac(void *ctx, astgs_request_t r) kdc_audit_setkv_object((kdc_request_t)r, "gss_requestor_sid", requestor_sid); - return krb5_pac_add_buffer(r->context, r->pac, PAC_REQUESTOR_SID, - heim_data_get_data(requestor_sid)); + return kdc_request_add_pac_buffer(r, PAC_REQUESTOR_SID, + heim_data_get_data(requestor_sid)); } static KRB5_LIB_CALL krb5_error_code diff --git a/kdc/kdc-accessors.h b/kdc/kdc-accessors.h new file mode 100644 index 000000000..5eab2422a --- /dev/null +++ b/kdc/kdc-accessors.h @@ -0,0 +1,349 @@ +/* + * Copyright (c) 2022, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef HEIMDAL_KDC_KDC_ACCESSORS_H +#define HEIMDAL_KDC_KDC_ACCESSORS_H 1 + +/* read-only accessor */ +#ifndef _KDC_REQUEST_GET_ACCESSOR +#define _KDC_REQUEST_GET_ACCESSOR(R, T, f) \ + T \ + kdc_request_get_ ## f(R); +#endif + +#ifndef _KDC_REQUEST_SET_ACCESSOR +#define _KDC_REQUEST_SET_ACCESSOR(R, T, f) \ + void \ + kdc_request_set_ ## f(R, T); +#endif + +#ifndef KDC_REQUEST_GET_ACCESSOR +#define KDC_REQUEST_GET_ACCESSOR(T, f) \ + _KDC_REQUEST_GET_ACCESSOR(kdc_request_t, T, f) +#endif + +#ifndef KDC_REQUEST_SET_ACCESSOR +#define KDC_REQUEST_SET_ACCESSOR(T, f) \ + _KDC_REQUEST_SET_ACCESSOR(kdc_request_t, T, f) +#endif + +#ifndef ASTGS_REQUEST_GET_ACCESSOR +#define ASTGS_REQUEST_GET_ACCESSOR(T, f) \ + _KDC_REQUEST_GET_ACCESSOR(astgs_request_t, T, f) +#endif + +#ifndef ASTGS_REQUEST_SET_ACCESSOR +#define ASTGS_REQUEST_SET_ACCESSOR(T, f) \ + _KDC_REQUEST_SET_ACCESSOR(astgs_request_t, T, f) +#endif + +/* get/set accessor for pointer type */ +#ifndef _KDC_REQUEST_GET_ACCESSOR_PTR +#define _KDC_REQUEST_GET_ACCESSOR_PTR(R, T, f) \ + const T \ + kdc_request_get_ ## f(R); +#endif + +#ifndef _KDC_REQUEST_SET_ACCESSOR_PTR +#define _KDC_REQUEST_SET_ACCESSOR_PTR(R, T, t, f) \ + krb5_error_code \ + kdc_request_set_ ## f(R, const T); +#endif + +#ifndef KDC_REQUEST_GET_ACCESSOR_PTR +#define KDC_REQUEST_GET_ACCESSOR_PTR(T, f) \ + _KDC_REQUEST_GET_ACCESSOR_PTR(kdc_request_t, T, f) +#endif + +#ifndef KDC_REQUEST_SET_ACCESSOR_PTR +#define KDC_REQUEST_SET_ACCESSOR_PTR(T, t, f) \ + _KDC_REQUEST_SET_ACCESSOR_PTR(kdc_request_t, T, t, f) +#endif + +#ifndef ASTGS_REQUEST_GET_ACCESSOR_PTR +#define ASTGS_REQUEST_GET_ACCESSOR_PTR(T, f) \ + _KDC_REQUEST_GET_ACCESSOR_PTR(astgs_request_t, T, f) +#endif + +#ifndef ASTGS_REQUEST_SET_ACCESSOR_PTR +#define ASTGS_REQUEST_SET_ACCESSOR_PTR(T, t, f) \ + _KDC_REQUEST_SET_ACCESSOR_PTR(astgs_request_t, T, t, f) +#endif + +/* get/set accessor for struct type */ +#ifndef _KDC_REQUEST_GET_ACCESSOR_STRUCT +#define _KDC_REQUEST_GET_ACCESSOR_STRUCT(R, T, f) \ + const T * \ + kdc_request_get_ ## f(R); +#endif + +#ifndef _KDC_REQUEST_SET_ACCESSOR_STRUCT +#define _KDC_REQUEST_SET_ACCESSOR_STRUCT(R, T, t, f) \ + krb5_error_code \ + kdc_request_set_ ## f(R, const T *); +#endif + +#ifndef KDC_REQUEST_GET_ACCESSOR_STRUCT +#define KDC_REQUEST_GET_ACCESSOR_STRUCT(T, f) \ + _KDC_REQUEST_GET_ACCESSOR_STRUCT(kdc_request_t, T, f) +#endif + +#ifndef KDC_REQUEST_SET_ACCESSOR_STRUCT +#define KDC_REQUEST_SET_ACCESSOR_STRUCT(T, t, f) \ + _KDC_REQUEST_SET_ACCESSOR_STRUCT(kdc_request_t, T, t, f) +#endif + +#ifndef ASTGS_REQUEST_GET_ACCESSOR_STRUCT +#define ASTGS_REQUEST_GET_ACCESSOR_STRUCT(T, f) \ + _KDC_REQUEST_GET_ACCESSOR_STRUCT(astgs_request_t, T, f) +#endif + +#ifndef ASTGS_REQUEST_SET_ACCESSOR_STRUCT +#define ASTGS_REQUEST_SET_ACCESSOR_STRUCT(T, t, f) \ + _KDC_REQUEST_SET_ACCESSOR_STRUCT(astgs_request_t, T, t, f) +#endif + +/* + * krb5_context + * kdc_request_get_context(kdc_request_t); + */ + +KDC_REQUEST_GET_ACCESSOR(krb5_context, context) + +/* + * krb5_kdc_configuration * + * kdc_request_get_config(kdc_request_t); + */ + +KDC_REQUEST_GET_ACCESSOR(krb5_kdc_configuration *, config) + +/* + * heim_log_facility * + * kdc_request_get_logf(kdc_request_t); + */ + +KDC_REQUEST_GET_ACCESSOR(heim_log_facility *, logf) + +/* + * const char * + * kdc_request_get_from(kdc_request_t); + */ + +KDC_REQUEST_GET_ACCESSOR_PTR(char *, from) + +/* + * const struct sockaddr * + * kdc_request_get_addr(kdc_request_t); + */ + +KDC_REQUEST_GET_ACCESSOR_PTR(struct sockaddr *, addr) + +/* + * krb5_data + * kdc_request_get_request(kdc_request_t); + */ + +KDC_REQUEST_GET_ACCESSOR(krb5_data, request) + +/* + * struct timeval + * kdc_request_get_tv_start(kdc_request_t); + */ + +KDC_REQUEST_GET_ACCESSOR(struct timeval, tv_start) + +/* + * struct timeval + * kdc_request_get_tv_end(kdc_request_t); + */ + +KDC_REQUEST_GET_ACCESSOR(struct timeval, tv_end) + +/* + * krb5_error_code + * kdc_request_get_error_code(kdc_request_t); + */ +KDC_REQUEST_GET_ACCESSOR(krb5_error_code, error_code) + +/* + * void + * kdc_request_set_error_code(kdc_request_t, krb5_error_code); + */ +KDC_REQUEST_SET_ACCESSOR(krb5_error_code, error_code) + +/* + * const KDC_REQ * + * kdc_request_get_req(astgs_request_t); + */ + +ASTGS_REQUEST_GET_ACCESSOR_STRUCT(KDC_REQ, req) + +/* + * const KDC_REP * + * kdc_request_get_rep(astgs_request_t); + */ + +ASTGS_REQUEST_GET_ACCESSOR_STRUCT(KDC_REP, rep) + +/* + * krb5_error_code + * kdc_request_set_rep(astgs_request_t, const KDC_REP *); + */ + +ASTGS_REQUEST_SET_ACCESSOR_STRUCT(KDC_REP, KDC_REP, rep) + +/* + * const char * + * kdc_request_get_cname(kdc_request_t); + */ + +KDC_REQUEST_GET_ACCESSOR_PTR(char *, cname) + +/* + * krb5_error_code + * kdc_request_set_cname(kdc_request_t, const char *); + */ + +KDC_REQUEST_SET_ACCESSOR_PTR(char *, string_ptr, cname) + +/* + * const Principal * + * kdc_request_get_client_princ(astgs_request_t); + */ + +ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, client_princ) + +/* + * krb5_error_code + * kdc_request_set_client_princ(astgs_request_t, const Principal *); + */ + +ASTGS_REQUEST_SET_ACCESSOR_PTR(Principal *, Principal_ptr, client_princ) + +/* + * const Principal * + * kdc_request_get_canon_client_princ(astgs_request_t); + */ + +ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, canon_client_princ) + +/* + * krb5_error_code + * kdc_request_set_canon_client_princ(astgs_request_t, const Principal *); + */ + +ASTGS_REQUEST_SET_ACCESSOR_PTR(Principal *, Principal_ptr, canon_client_princ) + +/* + * const HDB * + * kdc_request_get_clientdb(astgs_request_t); + */ + +ASTGS_REQUEST_GET_ACCESSOR_PTR(HDB *, clientdb) + +/* + * const hdb_entry * + * kdc_request_get_client(astgs_request_t); + */ + +ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, client) + +/* + * See client accessors + */ + +KDC_REQUEST_GET_ACCESSOR_PTR(char *, sname) +KDC_REQUEST_SET_ACCESSOR_PTR(char *, string_ptr, sname) +ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, server_princ) +ASTGS_REQUEST_SET_ACCESSOR_PTR(Principal *, Principal_ptr, server_princ) +ASTGS_REQUEST_GET_ACCESSOR_PTR(HDB *, serverdb) +ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, server) + +/* + * See client accessors + */ + +ASTGS_REQUEST_GET_ACCESSOR_PTR(Principal *, krbtgt_princ) +ASTGS_REQUEST_SET_ACCESSOR_PTR(Principal *, Principal_ptr, krbtgt_princ) +ASTGS_REQUEST_GET_ACCESSOR_PTR(HDB *, krbtgtdb) +ASTGS_REQUEST_GET_ACCESSOR_PTR(hdb_entry *, krbtgt) + +/* + * krb5_ticket * + * kdc_request_get_ticket(astgs_request_t); + */ + +ASTGS_REQUEST_GET_ACCESSOR(krb5_ticket *, ticket) + +/* + * const krb5_keyblock * + * kdc_request_get_reply_key(astgs_request_t); + */ + +ASTGS_REQUEST_GET_ACCESSOR_STRUCT(krb5_keyblock, reply_key) + +/* + * krb5_error_code + * kdc_request_set_reply_key(astgs_request_t, const krb5_keyblock *); + */ + +ASTGS_REQUEST_SET_ACCESSOR_STRUCT(krb5_keyblock, keyblock, reply_key) + +/* + * krb5_const_pac + * kdc_request_get_pac(astgs_request_t); + */ + +ASTGS_REQUEST_GET_ACCESSOR_PTR(struct krb5_pac_data *, pac) + +/* + * krb5_error_code + * kdc_request_set_pac(astgs_request_t, krb5_const_pac); + */ + +ASTGS_REQUEST_SET_ACCESSOR_PTR(struct krb5_pac_data *, pac, pac) + +/* + * uint64_t + * kdc_request_get_pac_attributes(astgs_request_t); + */ + +ASTGS_REQUEST_GET_ACCESSOR(uint64_t, pac_attributes) + +/* + * void + * kdc_request_set_pac_attributes(astgs_request_t, uint64_t); + */ + +ASTGS_REQUEST_SET_ACCESSOR(uint64_t, pac_attributes) + +#endif /* HEIMDAL_KDC_KDC_ACCESSORS_H */ diff --git a/kdc/kdc-plugin.c b/kdc/kdc-plugin.c index 83eabfb3d..e2a114f57 100644 --- a/kdc/kdc-plugin.c +++ b/kdc/kdc-plugin.c @@ -3,6 +3,8 @@ * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * + * Portions (c) 2021, 2022 PADL Software Pty Ltd. + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -305,3 +307,189 @@ kdc_get_instance(const char *libname) return 0; } + +/* + * Plugin accessors + */ + +krb5_error_code +kdc_request_add_reply_padata(astgs_request_t r, PA_DATA *md) +{ + heim_assert(r->rep.padata != NULL, "reply padata not allocated"); + return add_METHOD_DATA(r->rep.padata, md); +} + +krb5_error_code +kdc_request_add_pac_buffer(astgs_request_t r, int32_t pactype, const krb5_data *d) +{ + krb5_error_code ret; + krb5_pac pac; + + if (r->pac == NULL) { + ret = krb5_pac_init(r->context, &pac); + if (ret) + return ret; + } else + pac = heim_retain(r->pac); + + ret = krb5_pac_add_buffer(r->context, pac, pactype, d); + if (ret == 0 && r->pac == NULL) + r->pac = pac; + else + heim_release(pac); + + return ret; +} + +#undef _KDC_REQUEST_GET_ACCESSOR +#define _KDC_REQUEST_GET_ACCESSOR(R, T, f) \ + T \ + kdc_request_get_ ## f(R r) \ + { \ + return r->f; \ + } + +#undef _KDC_REQUEST_SET_ACCESSOR +#define _KDC_REQUEST_SET_ACCESSOR(R, T, f) \ + void \ + kdc_request_set_ ## f(R r, T v) \ + { \ + r->f = v; \ + } + +#undef _KDC_REQUEST_GET_ACCESSOR_PTR +#define _KDC_REQUEST_GET_ACCESSOR_PTR(R, T, f) \ + const T \ + kdc_request_get_ ## f(R r) \ + { \ + return r->f; \ + } + +#undef _KDC_REQUEST_SET_ACCESSOR_PTR +#define _KDC_REQUEST_SET_ACCESSOR_PTR(R, T, t, f) \ + krb5_error_code \ + kdc_request_set_ ## f(R r, const T v) \ + { \ + krb5_error_code ret; \ + T tmp; \ + \ + if (v == r->f) \ + return 0; \ + else if (v) { \ + ret = copy_##t(v, &tmp); \ + if (ret) \ + return ret; \ + } else \ + tmp = NULL; \ + \ + free_##t(r->f); \ + r->f = tmp; \ + \ + return 0; \ + } + +#undef _KDC_REQUEST_GET_ACCESSOR_STRUCT +#define _KDC_REQUEST_GET_ACCESSOR_STRUCT(R, T, f) \ + const T * \ + kdc_request_get_ ## f(R r) \ + { \ + return &r->f; \ + } + +#undef _KDC_REQUEST_SET_ACCESSOR_STRUCT +#define _KDC_REQUEST_SET_ACCESSOR_STRUCT(R, T, t, f) \ + krb5_error_code \ + kdc_request_set_ ## f(R r, const T *v) \ + { \ + krb5_error_code ret; \ + T tmp; \ + \ + if (v == NULL) \ + return EINVAL; \ + else if (v == &r->f) \ + return 0; \ + \ + ret = copy_##t(v, &tmp); \ + if (ret) \ + return ret; \ + \ + free_##t(&r->f); \ + r->f = tmp; \ + \ + return 0; \ + } + +static krb5_error_code +copy_string_ptr(const char *src, char **dst) +{ + *dst = strdup(src); + if (*dst == NULL) + return ENOMEM; + + return 0; +} + +static void +free_string_ptr(char *s) +{ + free(s); +} + +static krb5_error_code +copy_Principal_ptr(krb5_const_principal src, krb5_principal *dst) +{ + krb5_error_code ret; + krb5_principal p; + + *dst = NULL; + + p = calloc(1, sizeof(*p)); + if (*dst == NULL) + return ENOMEM; + + ret = copy_Principal(src, p); + if (ret == 0) + *dst = p; + else + free(p); + + return ret; +} + +static void +free_Principal_ptr(krb5_principal p) +{ + if (p) { + free_Principal(p); + free(p); + } +} + +static krb5_error_code +copy_pac(const struct krb5_pac_data *src, struct krb5_pac_data **dst) +{ + /* FIXME use heim_copy() when it exists */ + *dst = (krb5_pac)heim_retain((heim_object_t)src); + return 0; +} + +static void +free_pac(struct krb5_pac_data *o) +{ + heim_release(o); +} + +static krb5_error_code +copy_keyblock(const EncryptionKey *src, EncryptionKey *dst) +{ + return copy_EncryptionKey(src, dst); +} + +static void +free_keyblock(EncryptionKey *key) +{ + krb5_free_keyblock_contents(NULL, key); +} + +#undef HEIMDAL_KDC_KDC_ACCESSORS_H +#include "kdc-accessors.h" diff --git a/kdc/kdc.h b/kdc/kdc.h index 27be708b2..289e7adb0 100644 --- a/kdc/kdc.h +++ b/kdc/kdc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2022 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * * Copyright (c) 2005 Andrew Bartlett @@ -46,129 +46,27 @@ #include #include -#define heim_pcontext krb5_context -#define heim_pconfig krb5_kdc_configuration * -#include - enum krb5_kdc_trpolicy { TRPOLICY_ALWAYS_CHECK, TRPOLICY_ALLOW_PER_PRINCIPAL, TRPOLICY_ALWAYS_HONOUR_REQUEST }; -typedef struct krb5_kdc_configuration { - krb5_boolean require_preauth; /* require preauth for all principals */ - time_t kdc_warn_pwexpire; /* time before expiration to print a warning */ +struct krb5_kdc_configuration; +typedef struct krb5_kdc_configuration krb5_kdc_configuration; - struct HDB **db; - int num_db; - - int num_kdc_processes; - - krb5_boolean encode_as_rep_as_tgs_rep; /* bug compatibility */ - - /* - * Windows 2019 (and earlier versions) always sends the salt - * and Samba has testsuites that check this behaviour, so a - * Samba AD DC will set this flag to match the AS-REP packet - * exactly. - */ - krb5_boolean force_include_pa_etype_salt; - - krb5_boolean tgt_use_strongest_session_key; - krb5_boolean preauth_use_strongest_session_key; - krb5_boolean svc_use_strongest_session_key; - krb5_boolean use_strongest_server_key; - - krb5_boolean check_ticket_addresses; - krb5_boolean warn_ticket_addresses; - krb5_boolean allow_null_ticket_addresses; - krb5_boolean allow_anonymous; - krb5_boolean historical_anon_realm; - krb5_boolean strict_nametypes; - enum krb5_kdc_trpolicy trpolicy; - - krb5_boolean require_pac; - krb5_boolean enable_armored_pa_enc_timestamp; - krb5_boolean enable_unarmored_pa_enc_timestamp; - - krb5_boolean enable_pkinit; - krb5_boolean pkinit_princ_in_cert; - const char *pkinit_kdc_identity; - const char *pkinit_kdc_anchors; - const char *pkinit_kdc_friendly_name; - const char *pkinit_kdc_ocsp_file; - char **pkinit_kdc_cert_pool; - char **pkinit_kdc_revoke; - int pkinit_dh_min_bits; - /* XXX Turn these into bit-fields */ - int pkinit_require_binding; - int pkinit_allow_proxy_certs; - int synthetic_clients; - int pkinit_max_life_from_cert_extension; - krb5_timestamp pkinit_max_life_from_cert; - krb5_timestamp pkinit_max_life_bound; - krb5_timestamp synthetic_clients_max_life; - krb5_timestamp synthetic_clients_max_renew; - - krb5_log_facility *logf; - - int enable_digest; - int digests_allowed; - - int enable_gss_preauth; - int enable_gss_auth_data; - gss_OID_set gss_mechanisms_allowed; - gss_OID_set gss_cross_realm_mechanisms_allowed; - - size_t max_datagram_reply_length; - - int enable_kx509; - - const char *app; -} krb5_kdc_configuration; - -#define ASTGS_REQUEST_DESC_COMMON_ELEMENTS \ - HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS; \ - \ - /* AS-REQ or TGS-REQ */ \ - KDC_REQ req; \ - \ - /* AS-REP or TGS-REP */ \ - KDC_REP rep; \ - EncTicketPart et; \ - EncKDCRepPart ek; \ - \ - /* client principal (AS) or TGT/S4U principal (TGS) */ \ - krb5_principal client_princ; \ - hdb_entry *client; \ - HDB *clientdb; \ - krb5_principal canon_client_princ; \ - \ - /* server principal */ \ - krb5_principal server_princ; \ - hdb_entry *server; \ - HDB *serverdb; \ - \ - /* presented ticket in TGS-REQ (unused by AS) */ \ - krb5_principal *krbtgt_princ; \ - hdb_entry *krbtgt; \ - HDB *krbtgtdb; \ - krb5_ticket *ticket; \ - \ - krb5_keyblock reply_key; \ - \ - krb5_pac pac; \ - uint64_t pac_attributes - -#ifndef __KDC_LOCL_H__ -struct astgs_request_desc { - ASTGS_REQUEST_DESC_COMMON_ELEMENTS; -}; -#endif +/* + * Access to request fields by plugins and other out-of-tree + * consumers should be via the functions in kdc-accessors.h. + */ +struct kdc_request_desc; typedef struct kdc_request_desc *kdc_request_t; + +struct astgs_request_desc; typedef struct astgs_request_desc *astgs_request_t; + +struct kx509_req_context_desc; typedef struct kx509_req_context_desc *kx509_req_context; struct krb5_kdc_service { @@ -179,9 +77,27 @@ struct krb5_kdc_service { krb5_error_code (*process)(kdc_request_t *, int *claim); }; +/* + * The following fields are guaranteed stable within a major + * release of Heimdal and can be manipulated by applications + * that manage KDC requests themselves using libkdc. + * + * Applications can make custom KDC configuration available + * to libkdc by using krb5_set_config(). + */ + +#define KRB5_KDC_CONFIGURATION_COMMON_ELEMENTS \ + krb5_log_facility *logf; \ + struct HDB **db; \ + size_t num_db; \ + const char *app + +#ifndef __KDC_LOCL_H__ +struct krb5_kdc_configuration { + KRB5_KDC_CONFIGURATION_COMMON_ELEMENTS; +}; +#endif + #include -#undef heim_pcontext -#undef heim_pconfig - -#endif +#endif /* __KDC_H__ */ diff --git a/kdc/kdc_locl.h b/kdc/kdc_locl.h index 3a2b4d2fd..43af59c8c 100644 --- a/kdc/kdc_locl.h +++ b/kdc/kdc_locl.h @@ -66,8 +66,105 @@ struct kdc_request_desc { struct kdc_patypes; +struct krb5_kdc_configuration { + KRB5_KDC_CONFIGURATION_COMMON_ELEMENTS; + + int num_kdc_processes; + + size_t max_datagram_reply_length; + + time_t kdc_warn_pwexpire; /* time before expiration to print a warning */ + + unsigned int require_preauth : 1; /* require preauth for all principals */ + unsigned int encode_as_rep_as_tgs_rep : 1; /* bug compatibility */ + + /* + * Windows 2019 (and earlier versions) always sends the salt + * and Samba has testsuites that check this behaviour, so a + * Samba AD DC will set this flag to match the AS-REP packet + * exactly. + */ + unsigned int force_include_pa_etype_salt : 1; + + unsigned int tgt_use_strongest_session_key : 1; + unsigned int preauth_use_strongest_session_key : 1; + unsigned int svc_use_strongest_session_key : 1; + unsigned int use_strongest_server_key : 1; + + unsigned int check_ticket_addresses : 1; + unsigned int warn_ticket_addresses : 1; + unsigned int allow_null_ticket_addresses : 1; + unsigned int allow_anonymous : 1; + unsigned int historical_anon_realm : 1; + unsigned int strict_nametypes : 1; + enum krb5_kdc_trpolicy trpolicy; + + unsigned int require_pac : 1; + unsigned int enable_armored_pa_enc_timestamp : 1; + unsigned int enable_unarmored_pa_enc_timestamp : 1; + + unsigned int enable_pkinit : 1; + unsigned int pkinit_princ_in_cert : 1; + const char *pkinit_kdc_identity; + const char *pkinit_kdc_anchors; + const char *pkinit_kdc_friendly_name; + const char *pkinit_kdc_ocsp_file; + char **pkinit_kdc_cert_pool; + char **pkinit_kdc_revoke; + int pkinit_dh_min_bits; + unsigned int pkinit_require_binding : 1; + unsigned int pkinit_allow_proxy_certs : 1; + unsigned int synthetic_clients : 1; + unsigned int pkinit_max_life_from_cert_extension : 1; + krb5_timestamp pkinit_max_life_from_cert; + krb5_timestamp pkinit_max_life_bound; + krb5_timestamp synthetic_clients_max_life; + krb5_timestamp synthetic_clients_max_renew; + + int digests_allowed; + unsigned int enable_digest : 1; + + unsigned int enable_kx509 : 1; + + unsigned int enable_gss_preauth : 1; + unsigned int enable_gss_auth_data : 1; + gss_OID_set gss_mechanisms_allowed; + gss_OID_set gss_cross_realm_mechanisms_allowed; + +}; + struct astgs_request_desc { - ASTGS_REQUEST_DESC_COMMON_ELEMENTS; + HEIM_SVC_REQUEST_DESC_COMMON_ELEMENTS; + + /* AS-REQ or TGS-REQ */ + KDC_REQ req; + + /* AS-REP or TGS-REP */ + KDC_REP rep; + EncTicketPart et; + EncKDCRepPart ek; + + /* client principal (AS) or TGT/S4U principal (TGS) */ + krb5_principal client_princ; + hdb_entry *client; + HDB *clientdb; + krb5_principal canon_client_princ; + + /* server principal */ + krb5_principal server_princ; + HDB *serverdb; + hdb_entry *server; + + /* presented ticket in TGS-REQ (unused by AS) */ + krb5_principal krbtgt_princ; + hdb_entry *krbtgt; + HDB *krbtgtdb; + krb5_ticket *ticket; + + krb5_keyblock reply_key; + + krb5_pac pac; + uint64_t pac_attributes; /* Only AS */ const struct kdc_patypes *pa_used; diff --git a/kdc/libkdc-exports.def b/kdc/libkdc-exports.def index 4421acc04..c2463c2fb 100644 --- a/kdc/libkdc-exports.def +++ b/kdc/libkdc-exports.def @@ -21,6 +21,45 @@ EXPORTS kdc_request_get_attribute kdc_request_copy_attribute kdc_request_delete_attribute + kdc_request_add_pac_buffer + kdc_request_add_reply_padata + kdc_request_get_addr + kdc_request_get_canon_client_princ + kdc_request_get_client + kdc_request_get_clientdb + kdc_request_get_client_princ + kdc_request_get_context + kdc_request_get_config + kdc_request_get_cname + kdc_request_get_error_code + kdc_request_get_from + kdc_request_get_krbtgt + kdc_request_get_krbtgtdb + kdc_request_get_krbtgt_princ + kdc_request_get_pac + kdc_request_get_pac_attributes + kdc_request_get_rep + kdc_request_get_reply_key + kdc_request_get_req + kdc_request_get_request + kdc_request_get_server + kdc_request_get_serverdb + kdc_request_get_server_princ + kdc_request_get_sname + kdc_request_get_ticket + kdc_request_get_tv_end + kdc_request_get_tv_start + kdc_request_set_canon_client_princ + kdc_request_set_client_princ + kdc_request_set_cname + kdc_request_set_error_code + kdc_request_set_krbtgt_princ + kdc_request_set_pac + kdc_request_set_pac_attributes + kdc_request_set_rep + kdc_request_set_reply_key + kdc_request_set_server_princ + kdc_request_set_sname kdc_audit_addkv kdc_audit_addkv_number kdc_audit_addkv_object diff --git a/kdc/version-script.map b/kdc/version-script.map index 8c584b38c..9aa716b7d 100644 --- a/kdc/version-script.map +++ b/kdc/version-script.map @@ -24,6 +24,45 @@ HEIMDAL_KDC_1.0 { kdc_request_get_attribute; kdc_request_copy_attribute; kdc_request_delete_attribute; + kdc_request_add_pac_buffer; + kdc_request_add_reply_padata; + kdc_request_get_addr; + kdc_request_get_canon_client_princ; + kdc_request_get_client; + kdc_request_get_clientdb; + kdc_request_get_client_princ; + kdc_request_get_context; + kdc_request_get_config; + kdc_request_get_cname; + kdc_request_get_error_code; + kdc_request_get_from; + kdc_request_get_krbtgt; + kdc_request_get_krbtgtdb; + kdc_request_get_krbtgt_princ; + kdc_request_get_pac; + kdc_request_get_pac_attributes; + kdc_request_get_rep; + kdc_request_get_reply_key; + kdc_request_get_req; + kdc_request_get_request; + kdc_request_get_server; + kdc_request_get_serverdb; + kdc_request_get_server_princ; + kdc_request_get_sname; + kdc_request_get_ticket; + kdc_request_get_tv_end; + kdc_request_get_tv_start; + kdc_request_set_canon_client_princ; + kdc_request_set_client_princ; + kdc_request_set_cname; + kdc_request_set_error_code; + kdc_request_set_krbtgt_princ; + kdc_request_set_pac; + kdc_request_set_pac_attributes; + kdc_request_set_rep; + kdc_request_set_reply_key; + kdc_request_set_server_princ; + kdc_request_set_sname; kdc_audit_addkv; kdc_audit_addkv_number; kdc_audit_addkv_object; diff --git a/lib/krb5/krb5.h b/lib/krb5/krb5.h index a80b30f20..1cf2316af 100644 --- a/lib/krb5/krb5.h +++ b/lib/krb5/krb5.h @@ -95,6 +95,7 @@ typedef struct krb5_ntlm_data *krb5_ntlm; struct krb5_pac_data; typedef struct krb5_pac_data *krb5_pac; +typedef const struct krb5_pac_data *krb5_const_pac; typedef struct krb5_rd_req_in_ctx_data *krb5_rd_req_in_ctx; typedef struct krb5_rd_req_out_ctx_data *krb5_rd_req_out_ctx; diff --git a/tests/plugin/kdc_test_plugin.c b/tests/plugin/kdc_test_plugin.c index 118ff9a57..4fcf311fd 100644 --- a/tests/plugin/kdc_test_plugin.c +++ b/tests/plugin/kdc_test_plugin.c @@ -100,10 +100,14 @@ pac_verify(void *ctx, static void logit(const char *what, astgs_request_t r) { - krb5_warnx(r->context, "%s: client %s server %s", + krb5_context context = kdc_request_get_context((kdc_request_t)r); + const char *cname = kdc_request_get_cname((kdc_request_t)r); + const char *sname = kdc_request_get_sname((kdc_request_t)r); + + krb5_warnx(context, "%s: client %s server %s", what, - r->cname ? r->cname : "", - r->sname ? r->sname : ""); + cname ? cname : "", + sname ? sname : ""); } static krb5_error_code KRB5_CALLCONV @@ -136,11 +140,12 @@ finalize_reply(void *ctx, astgs_request_t r) static krb5_error_code KRB5_CALLCONV audit(void *ctx, astgs_request_t r) { + krb5_error_code ret = kdc_request_get_error_code((kdc_request_t)r); heim_number_t n; logit("audit", r); - if (r->ret) + if (ret) return 0; /* finalize_reply only called in success */ n = kdc_request_get_attribute((kdc_request_t)r,