From 954c01728e0c7485b72c9a5d5737e5f6bd0cf0b9 Mon Sep 17 00:00:00 2001 From: Heimdal Import User Date: Mon, 11 Jul 2005 01:16:55 +0000 Subject: r8302: import mini HEIMDAL into the tree (This used to be commit 118be28a7aef233799956615a99d1a2a74dac175) --- source4/heimdal/lib/krb5/acache.c | 781 ++++ source4/heimdal/lib/krb5/add_et_list.c | 50 + source4/heimdal/lib/krb5/addr_families.c | 1180 ++++++ source4/heimdal/lib/krb5/appdefault.c | 142 + source4/heimdal/lib/krb5/asn1_glue.c | 59 + source4/heimdal/lib/krb5/auth_context.c | 517 +++ source4/heimdal/lib/krb5/build_ap_req.c | 76 + source4/heimdal/lib/krb5/build_auth.c | 205 + source4/heimdal/lib/krb5/cache.c | 657 +++ source4/heimdal/lib/krb5/changepw.c | 816 ++++ source4/heimdal/lib/krb5/codec.c | 196 + source4/heimdal/lib/krb5/config_file.c | 773 ++++ source4/heimdal/lib/krb5/config_file_netinfo.c | 180 + source4/heimdal/lib/krb5/constants.c | 43 + source4/heimdal/lib/krb5/context.c | 663 ++++ source4/heimdal/lib/krb5/copy_host_realm.c | 69 + source4/heimdal/lib/krb5/crc.c | 71 + source4/heimdal/lib/krb5/creds.c | 215 + source4/heimdal/lib/krb5/crypto.c | 4410 +++++++++++++++++++++ source4/heimdal/lib/krb5/data.c | 119 + source4/heimdal/lib/krb5/eai_to_heim_errno.c | 98 + source4/heimdal/lib/krb5/error_string.c | 109 + source4/heimdal/lib/krb5/expand_hostname.c | 153 + source4/heimdal/lib/krb5/fcache.c | 718 ++++ source4/heimdal/lib/krb5/free.c | 53 + source4/heimdal/lib/krb5/free_host_realm.c | 54 + source4/heimdal/lib/krb5/generate_seq_number.c | 62 + source4/heimdal/lib/krb5/generate_subkey.c | 72 + source4/heimdal/lib/krb5/get_addrs.c | 291 ++ source4/heimdal/lib/krb5/get_cred.c | 909 +++++ source4/heimdal/lib/krb5/get_default_principal.c | 115 + source4/heimdal/lib/krb5/get_default_realm.c | 84 + source4/heimdal/lib/krb5/get_for_creds.c | 427 ++ source4/heimdal/lib/krb5/get_host_realm.c | 220 + source4/heimdal/lib/krb5/get_in_tkt.c | 823 ++++ source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c | 99 + source4/heimdal/lib/krb5/get_port.c | 54 + source4/heimdal/lib/krb5/heim_err.et | 44 + source4/heimdal/lib/krb5/heim_threads.h | 175 + source4/heimdal/lib/krb5/init_creds.c | 331 ++ source4/heimdal/lib/krb5/init_creds_pw.c | 1554 ++++++++ source4/heimdal/lib/krb5/k524_err.et | 20 + source4/heimdal/lib/krb5/kcm.c | 1095 +++++ source4/heimdal/lib/krb5/keyblock.c | 133 + source4/heimdal/lib/krb5/keytab.c | 491 +++ source4/heimdal/lib/krb5/keytab_any.c | 256 ++ source4/heimdal/lib/krb5/keytab_file.c | 678 ++++ source4/heimdal/lib/krb5/keytab_keyfile.c | 389 ++ source4/heimdal/lib/krb5/keytab_krb4.c | 443 +++ source4/heimdal/lib/krb5/keytab_memory.c | 229 ++ source4/heimdal/lib/krb5/krb5-private.h | 358 ++ source4/heimdal/lib/krb5/krb5-protos.h | 3407 ++++++++++++++++ source4/heimdal/lib/krb5/krb5-v4compat.h | 176 + source4/heimdal/lib/krb5/krb5.h | 754 ++++ source4/heimdal/lib/krb5/krb5_ccapi.h | 215 + source4/heimdal/lib/krb5/krb5_err.et | 258 ++ source4/heimdal/lib/krb5/krb5_locl.h | 188 + source4/heimdal/lib/krb5/krbhst.c | 861 ++++ source4/heimdal/lib/krb5/log.c | 467 +++ source4/heimdal/lib/krb5/mcache.c | 353 ++ source4/heimdal/lib/krb5/misc.c | 36 + source4/heimdal/lib/krb5/mit_glue.c | 327 ++ source4/heimdal/lib/krb5/mk_error.c | 92 + source4/heimdal/lib/krb5/mk_priv.c | 153 + source4/heimdal/lib/krb5/mk_rep.c | 126 + source4/heimdal/lib/krb5/mk_req.c | 116 + source4/heimdal/lib/krb5/mk_req_ext.c | 180 + source4/heimdal/lib/krb5/n-fold.c | 126 + source4/heimdal/lib/krb5/padata.c | 66 + source4/heimdal/lib/krb5/pkinit.c | 2583 ++++++++++++ source4/heimdal/lib/krb5/principal.c | 1125 ++++++ source4/heimdal/lib/krb5/rd_cred.c | 299 ++ source4/heimdal/lib/krb5/rd_error.c | 121 + source4/heimdal/lib/krb5/rd_priv.c | 176 + source4/heimdal/lib/krb5/rd_rep.c | 133 + source4/heimdal/lib/krb5/rd_req.c | 649 +++ source4/heimdal/lib/krb5/replay.c | 304 ++ source4/heimdal/lib/krb5/send_to_kdc.c | 416 ++ source4/heimdal/lib/krb5/set_default_realm.c | 90 + source4/heimdal/lib/krb5/store-int.h | 47 + source4/heimdal/lib/krb5/store.c | 888 +++++ source4/heimdal/lib/krb5/store_emem.c | 132 + source4/heimdal/lib/krb5/store_fd.c | 95 + source4/heimdal/lib/krb5/store_mem.c | 119 + source4/heimdal/lib/krb5/ticket.c | 125 + source4/heimdal/lib/krb5/time.c | 114 + source4/heimdal/lib/krb5/transited.c | 481 +++ source4/heimdal/lib/krb5/v4_glue.c | 922 +++++ source4/heimdal/lib/krb5/version.c | 43 + source4/heimdal/lib/krb5/warn.c | 205 + 90 files changed, 38727 insertions(+) create mode 100644 source4/heimdal/lib/krb5/acache.c create mode 100644 source4/heimdal/lib/krb5/add_et_list.c create mode 100644 source4/heimdal/lib/krb5/addr_families.c create mode 100644 source4/heimdal/lib/krb5/appdefault.c create mode 100644 source4/heimdal/lib/krb5/asn1_glue.c create mode 100644 source4/heimdal/lib/krb5/auth_context.c create mode 100644 source4/heimdal/lib/krb5/build_ap_req.c create mode 100644 source4/heimdal/lib/krb5/build_auth.c create mode 100644 source4/heimdal/lib/krb5/cache.c create mode 100644 source4/heimdal/lib/krb5/changepw.c create mode 100644 source4/heimdal/lib/krb5/codec.c create mode 100644 source4/heimdal/lib/krb5/config_file.c create mode 100644 source4/heimdal/lib/krb5/config_file_netinfo.c create mode 100644 source4/heimdal/lib/krb5/constants.c create mode 100644 source4/heimdal/lib/krb5/context.c create mode 100644 source4/heimdal/lib/krb5/copy_host_realm.c create mode 100644 source4/heimdal/lib/krb5/crc.c create mode 100644 source4/heimdal/lib/krb5/creds.c create mode 100644 source4/heimdal/lib/krb5/crypto.c create mode 100644 source4/heimdal/lib/krb5/data.c create mode 100644 source4/heimdal/lib/krb5/eai_to_heim_errno.c create mode 100644 source4/heimdal/lib/krb5/error_string.c create mode 100644 source4/heimdal/lib/krb5/expand_hostname.c create mode 100644 source4/heimdal/lib/krb5/fcache.c create mode 100644 source4/heimdal/lib/krb5/free.c create mode 100644 source4/heimdal/lib/krb5/free_host_realm.c create mode 100644 source4/heimdal/lib/krb5/generate_seq_number.c create mode 100644 source4/heimdal/lib/krb5/generate_subkey.c create mode 100644 source4/heimdal/lib/krb5/get_addrs.c create mode 100644 source4/heimdal/lib/krb5/get_cred.c create mode 100644 source4/heimdal/lib/krb5/get_default_principal.c create mode 100644 source4/heimdal/lib/krb5/get_default_realm.c create mode 100644 source4/heimdal/lib/krb5/get_for_creds.c create mode 100644 source4/heimdal/lib/krb5/get_host_realm.c create mode 100644 source4/heimdal/lib/krb5/get_in_tkt.c create mode 100644 source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c create mode 100644 source4/heimdal/lib/krb5/get_port.c create mode 100644 source4/heimdal/lib/krb5/heim_err.et create mode 100755 source4/heimdal/lib/krb5/heim_threads.h create mode 100644 source4/heimdal/lib/krb5/init_creds.c create mode 100644 source4/heimdal/lib/krb5/init_creds_pw.c create mode 100644 source4/heimdal/lib/krb5/k524_err.et create mode 100644 source4/heimdal/lib/krb5/kcm.c create mode 100644 source4/heimdal/lib/krb5/keyblock.c create mode 100644 source4/heimdal/lib/krb5/keytab.c create mode 100644 source4/heimdal/lib/krb5/keytab_any.c create mode 100644 source4/heimdal/lib/krb5/keytab_file.c create mode 100644 source4/heimdal/lib/krb5/keytab_keyfile.c create mode 100644 source4/heimdal/lib/krb5/keytab_krb4.c create mode 100644 source4/heimdal/lib/krb5/keytab_memory.c create mode 100644 source4/heimdal/lib/krb5/krb5-private.h create mode 100644 source4/heimdal/lib/krb5/krb5-protos.h create mode 100644 source4/heimdal/lib/krb5/krb5-v4compat.h create mode 100644 source4/heimdal/lib/krb5/krb5.h create mode 100644 source4/heimdal/lib/krb5/krb5_ccapi.h create mode 100644 source4/heimdal/lib/krb5/krb5_err.et create mode 100644 source4/heimdal/lib/krb5/krb5_locl.h create mode 100644 source4/heimdal/lib/krb5/krbhst.c create mode 100644 source4/heimdal/lib/krb5/log.c create mode 100644 source4/heimdal/lib/krb5/mcache.c create mode 100644 source4/heimdal/lib/krb5/misc.c create mode 100755 source4/heimdal/lib/krb5/mit_glue.c create mode 100644 source4/heimdal/lib/krb5/mk_error.c create mode 100644 source4/heimdal/lib/krb5/mk_priv.c create mode 100644 source4/heimdal/lib/krb5/mk_rep.c create mode 100644 source4/heimdal/lib/krb5/mk_req.c create mode 100644 source4/heimdal/lib/krb5/mk_req_ext.c create mode 100644 source4/heimdal/lib/krb5/n-fold.c create mode 100644 source4/heimdal/lib/krb5/padata.c create mode 100755 source4/heimdal/lib/krb5/pkinit.c create mode 100644 source4/heimdal/lib/krb5/principal.c create mode 100644 source4/heimdal/lib/krb5/rd_cred.c create mode 100644 source4/heimdal/lib/krb5/rd_error.c create mode 100644 source4/heimdal/lib/krb5/rd_priv.c create mode 100644 source4/heimdal/lib/krb5/rd_rep.c create mode 100644 source4/heimdal/lib/krb5/rd_req.c create mode 100644 source4/heimdal/lib/krb5/replay.c create mode 100644 source4/heimdal/lib/krb5/send_to_kdc.c create mode 100644 source4/heimdal/lib/krb5/set_default_realm.c create mode 100644 source4/heimdal/lib/krb5/store-int.h create mode 100644 source4/heimdal/lib/krb5/store.c create mode 100644 source4/heimdal/lib/krb5/store_emem.c create mode 100644 source4/heimdal/lib/krb5/store_fd.c create mode 100644 source4/heimdal/lib/krb5/store_mem.c create mode 100644 source4/heimdal/lib/krb5/ticket.c create mode 100644 source4/heimdal/lib/krb5/time.c create mode 100644 source4/heimdal/lib/krb5/transited.c create mode 100644 source4/heimdal/lib/krb5/v4_glue.c create mode 100644 source4/heimdal/lib/krb5/version.c create mode 100644 source4/heimdal/lib/krb5/warn.c (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c new file mode 100644 index 0000000000..75f5315c71 --- /dev/null +++ b/source4/heimdal/lib/krb5/acache.c @@ -0,0 +1,781 @@ +/* + * Copyright (c) 2004 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +#include +#ifdef HAVE_DLFCN_H +#include +#endif + +RCSID("$Id: acache.c,v 1.11 2005/06/16 19:32:44 lha Exp $"); + +/* XXX should we fetch these for each open ? */ +static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; +static cc_initialize_func init_func; + +#ifdef HAVE_DLOPEN +static void *cc_handle; +#endif + +typedef struct krb5_acc { + char *cache_name; + cc_context_t context; + cc_ccache_t ccache; +} krb5_acc; + +static krb5_error_code acc_close(krb5_context, krb5_ccache); + +#define ACACHE(X) ((krb5_acc *)(X)->data.data) + +static const struct { + cc_int32 error; + krb5_error_code ret; +} cc_errors[] = { + { ccErrBadName, KRB5_CC_BADNAME }, + { ccErrCredentialsNotFound, KRB5_CC_NOTFOUND }, + { ccErrCCacheNotFound, KRB5_FCC_NOFILE }, + { ccErrContextNotFound, KRB5_CC_NOTFOUND }, + { ccIteratorEnd, KRB5_CC_END }, + { ccErrNoMem, KRB5_CC_NOMEM }, + { ccErrServerUnavailable, KRB5_CC_BADNAME }, + { ccNoError, 0 } +}; + +static krb5_error_code +translate_cc_error(krb5_context context, cc_int32 error) +{ + int i; + krb5_clear_error_string(context); + for(i = 0; i < sizeof(cc_errors)/sizeof(cc_errors[0]); i++) + if (cc_errors[i].error == error) + return cc_errors[i].ret; + return KRB5_FCC_INTERNAL; +} + +static krb5_error_code +init_ccapi(krb5_context context) +{ + const char *lib; + + HEIMDAL_MUTEX_lock(&acc_mutex); + if (init_func) { + HEIMDAL_MUTEX_unlock(&acc_mutex); + krb5_clear_error_string(context); + return 0; + } + + lib = krb5_config_get_string(context, NULL, + "libdefaults", "ccapi_library", + NULL); + if (lib == NULL) { +#ifdef __APPLE__ + lib = "/System/Library/Frameworks/Kerberos.framework/Kerberos"; +#else + lib = "/usr/lib/libkrb5_cc.so"; +#endif + } + +#ifdef HAVE_DLOPEN + cc_handle = dlopen(lib, 0); + if (cc_handle == NULL) { + HEIMDAL_MUTEX_unlock(&acc_mutex); + krb5_set_error_string(context, "Failed to load %s", lib); + return ccErrServerUnavailable; + } + + init_func = dlsym(cc_handle, "cc_initialize"); + HEIMDAL_MUTEX_unlock(&acc_mutex); + if (init_func == NULL) { + krb5_set_error_string(context, "Failed to find cc_initialize" + "in %s: %s", lib, dlerror()); + dlclose(cc_handle); + return ccErrServerUnavailable; + } + + return 0; +#else + HEIMDAL_MUTEX_unlock(&acc_mutex); + krb5_set_error_string(context, "no support for shared object"); + return ccErrServerUnavailable; +#endif +} + +static krb5_error_code +make_cred_from_ccred(krb5_context context, + const cc_credentials_v5_t *incred, + krb5_creds *cred) +{ + krb5_error_code ret; + int i; + + memset(cred, 0, sizeof(*cred)); + + ret = krb5_parse_name(context, incred->client, &cred->client); + if (ret) + goto fail; + + ret = krb5_parse_name(context, incred->server, &cred->server); + if (ret) + goto fail; + + cred->session.keytype = incred->keyblock.type; + cred->session.keyvalue.length = incred->keyblock.length; + cred->session.keyvalue.data = malloc(incred->keyblock.length); + if (cred->session.keyvalue.data == NULL) + goto nomem; + memcpy(cred->session.keyvalue.data, incred->keyblock.data, + incred->keyblock.length); + + cred->times.authtime = incred->authtime; + cred->times.starttime = incred->starttime; + cred->times.endtime = incred->endtime; + cred->times.renew_till = incred->renew_till; + + ret = krb5_data_copy(&cred->ticket, + incred->ticket.data, + incred->ticket.length); + if (ret) + goto nomem; + + ret = krb5_data_copy(&cred->second_ticket, + incred->second_ticket.data, + incred->second_ticket.length); + if (ret) + goto nomem; + + cred->authdata.val = NULL; + cred->authdata.len = 0; + + cred->addresses.val = NULL; + cred->addresses.len = 0; + + for (i = 0; incred->authdata && incred->authdata[i]; i++) + ; + + if (i) { + cred->authdata.val = malloc(sizeof(cred->authdata.val[0]) * i); + if (cred->authdata.val == NULL) + goto nomem; + cred->authdata.len = i; + memset(cred->authdata.val, 0, sizeof(cred->authdata.val[0]) * i); + for (i = 0; i < cred->authdata.len; i++) { + cred->authdata.val[i].ad_type = incred->authdata[i]->type; + ret = krb5_data_copy(&cred->authdata.val[i].ad_data, + incred->authdata[i]->data, + incred->authdata[i]->length); + if (ret) + goto nomem; + } + } + + for (i = 0; incred->addresses && incred->addresses[i]; i++) + ; + + if (i) { + cred->addresses.val = malloc(sizeof(cred->addresses.val[0]) * i); + if (cred->addresses.val == NULL) + goto nomem; + cred->addresses.len = i; + memset(cred->addresses.val, 0, sizeof(cred->addresses.val[0]) * i); + + for (i = 0; i < cred->addresses.len; i++) { + cred->addresses.val[i].addr_type = incred->addresses[i]->type; + ret = krb5_data_copy(&cred->addresses.val[i].address, + incred->addresses[i]->data, + incred->addresses[i]->length); + if (ret) + goto nomem; + } + } + + cred->flags.b = int2TicketFlags(incred->ticket_flags); /* XXX */ + return 0; + +nomem: + ret = ENOMEM; + krb5_set_error_string(context, "malloc - out of memory"); + +fail: + krb5_free_creds_contents(context, cred); + return ret; +} + +static void +free_ccred(cc_credentials_v5_t *cred) +{ + int i; + + if (cred->addresses) { + for (i = 0; cred->addresses[i] != 0; i++) { + if (cred->addresses[i]->data) + free(cred->addresses[i]->data); + free(cred->addresses[i]); + } + free(cred->addresses); + } + if (cred->server) + free(cred->server); + if (cred->client) + free(cred->client); + memset(cred, 0, sizeof(*cred)); +} + +static krb5_error_code +make_ccred_from_cred(krb5_context context, + const krb5_creds *incred, + cc_credentials_v5_t *cred) +{ + krb5_error_code ret; + int i; + + memset(cred, 0, sizeof(*cred)); + + ret = krb5_unparse_name(context, incred->client, &cred->client); + if (ret) + goto fail; + + ret = krb5_unparse_name(context, incred->server, &cred->server); + if (ret) + goto fail; + + cred->keyblock.type = incred->session.keytype; + cred->keyblock.length = incred->session.keyvalue.length; + cred->keyblock.data = incred->session.keyvalue.data; + + cred->authtime = incred->times.authtime; + cred->starttime = incred->times.starttime; + cred->endtime = incred->times.endtime; + cred->renew_till = incred->times.renew_till; + + cred->ticket.length = incred->ticket.length; + cred->ticket.data = incred->ticket.data; + + cred->second_ticket.length = incred->second_ticket.length; + cred->second_ticket.data = incred->second_ticket.data; + + /* XXX this one should also be filled in */ + cred->authdata = NULL; + + cred->addresses = calloc(incred->addresses.len + 1, + sizeof(cred->addresses[0])); + if (cred->addresses == NULL) { + + ret = ENOMEM; + goto fail; + } + + for (i = 0; i < incred->addresses.len; i++) { + cc_data *addr; + addr = malloc(sizeof(*addr)); + addr->type = incred->addresses.val[i].addr_type; + addr->length = incred->addresses.val[i].address.length; + addr->data = malloc(addr->length); + if (addr->data == NULL) { + ret = ENOMEM; + goto fail; + } + memcpy(addr->data, incred->addresses.val[i].address.data, + addr->length); + cred->addresses[i] = addr; + } + cred->addresses[i] = NULL; + + cred->ticket_flags = TicketFlags2int(incred->flags.b); /* XXX */ + return 0; + +fail: + free_ccred(cred); + + krb5_clear_error_string(context); + return ret; +} + +static char * +get_cc_name(cc_ccache_t cache) +{ + cc_string_t name; + cc_int32 error; + char *str; + + error = (*cache->func->get_name)(cache, &name); + if (error) + return NULL; + + str = strdup(name->data); + (*name->func->release)(name); + return str; +} + + +static const char* +acc_get_name(krb5_context context, + krb5_ccache id) +{ + krb5_acc *a = ACACHE(id); + static char n[255]; + char *name; + + name = get_cc_name(a->ccache); + if (name == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return NULL; + } + strlcpy(n, name, sizeof(n)); + free(name); + return n; +} + +static krb5_error_code +acc_alloc(krb5_context context, krb5_ccache *id) +{ + krb5_error_code ret; + cc_int32 error; + krb5_acc *a; + + ret = init_ccapi(context); + if (ret) + return ret; + + ret = krb5_data_alloc(&(*id)->data, sizeof(*a)); + if (ret) { + krb5_clear_error_string(context); + return ret; + } + + a = ACACHE(*id); + + error = (*init_func)(&a->context, ccapi_version_3, NULL, NULL); + if (error) { + krb5_data_free(&(*id)->data); + return translate_cc_error(context, error); + } + + a->cache_name = NULL; + + return 0; +} + +static krb5_error_code +get_default_principal(krb5_context context, char **p) +{ + krb5_error_code ret; + krb5_principal principal; + + *p = NULL; + + ret = _krb5_get_default_principal_local(context, &principal); + if (ret) + return ret; + + ret = krb5_unparse_name(context, principal, p); + krb5_free_principal(context, principal); + return ret; +} + +static krb5_error_code +acc_resolve(krb5_context context, krb5_ccache *id, const char *res) +{ + krb5_error_code ret; + cc_int32 error; + krb5_acc *a; + + ret = acc_alloc(context, id); + if (ret) + return ret; + + a = ACACHE(*id); + + if (res == NULL || res[0] == '\0') { + error = (*a->context->func->open_default_ccache)(a->context, + &a->ccache); + if (error == ccErrCCacheNotFound) { + char *p; + + ret = get_default_principal(context, &p); + if (ret == 0) { + error = (*a->context->func->create_default_ccache)(a->context, + cc_credentials_v5, + p, + &a->ccache); + free(p); + } + } + if (error == 0) + a->cache_name = get_cc_name(a->ccache); + } else { + error = (*a->context->func->open_ccache)(a->context, res, &a->ccache); + if (error == 0) + a->cache_name = strdup(res); + } + if (error != 0) { + *id = NULL; + return translate_cc_error(context, error); + } + if (a->cache_name == NULL) { + acc_close(context, *id); + *id = NULL; + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + return 0; +} + +static krb5_error_code +acc_gen_new(krb5_context context, krb5_ccache *id) +{ + krb5_error_code ret; + cc_int32 error; + krb5_acc *a; + char *p; + + ret = get_default_principal(context, &p); + + ret = acc_alloc(context, id); + if (ret) { + free(p); + return ret; + } + + a = ACACHE(*id); + + error = (*a->context->func->create_new_ccache)(a->context, + cc_credentials_v5, + p, &a->ccache); + free(p); + if (error) { + *id = NULL; + return translate_cc_error(context, error); + } + a->cache_name = get_cc_name(a->ccache); + if (a->cache_name == NULL) { + acc_close(context, *id); + *id = NULL; + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + +static krb5_error_code +acc_initialize(krb5_context context, + krb5_ccache id, + krb5_principal primary_principal) +{ + cc_credentials_iterator_t iter; + krb5_acc *a = ACACHE(id); + cc_credentials_t ccred; + krb5_error_code ret; + int32_t error; + char *name; + + ret = krb5_unparse_name(context, primary_principal, &name); + if (ret) + return ret; + + if (a->ccache == NULL) { + error = (*a->context->func->create_new_ccache)(a->context, + cc_credentials_v5, + name, + &a->ccache); + } else { + + error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter); + if (error) { + free(name); + return translate_cc_error(context, error); + } + + while (1) { + error = (*iter->func->next)(iter, &ccred); + if (error) + break; + (*a->ccache->func->remove_credentials)(a->ccache, ccred); + (*ccred->func->release)(ccred); + } + (*iter->func->release)(iter); + + error = (*a->ccache->func->set_principal)(a->ccache, + cc_credentials_v5, + name); + } + + free(name); + + return translate_cc_error(context, error); +} + +static krb5_error_code +acc_close(krb5_context context, + krb5_ccache id) +{ + krb5_acc *a = ACACHE(id); + + if (a->ccache) { + (*a->ccache->func->release)(a->ccache); + a->ccache = NULL; + } + if (a->cache_name) { + free(a->cache_name); + a->cache_name = NULL; + } + (*a->context->func->release)(a->context); + a->context = NULL; + krb5_data_free(&id->data); + return 0; +} + +static krb5_error_code +acc_destroy(krb5_context context, + krb5_ccache id) +{ + krb5_acc *a = ACACHE(id); + cc_int32 error = 0; + + if (a->ccache) { + error = (*a->ccache->func->destroy)(a->ccache); + a->ccache = NULL; + } + return translate_cc_error(context, error); +} + +static krb5_error_code +acc_store_cred(krb5_context context, + krb5_ccache id, + krb5_creds *creds) +{ + krb5_acc *a = ACACHE(id); + cc_credentials_union cred; + cc_credentials_v5_t v5cred; + krb5_error_code ret; + cc_int32 error; + + cred.version = cc_credentials_v5; + cred.credentials.credentials_v5 = &v5cred; + + ret = make_ccred_from_cred(context, + creds, + &v5cred); + if (ret) + return ret; + + error = (*a->ccache->func->store_credentials)(a->ccache, &cred); + if (error) + ret = translate_cc_error(context, error); + + free_ccred(&v5cred); + + return ret; +} + +static krb5_error_code +acc_get_principal(krb5_context context, + krb5_ccache id, + krb5_principal *principal) +{ + krb5_acc *a = ACACHE(id); + krb5_error_code ret; + int32_t error; + cc_string_t name; + + if (a->ccache == NULL) + return ENOENT; + + error = (*a->ccache->func->get_principal)(a->ccache, + cc_credentials_v5, + &name); + if (error) + return translate_cc_error(context, error); + + ret = krb5_parse_name(context, name->data, principal); + + (*name->func->release)(name); + return ret; +} + +static krb5_error_code +acc_get_first (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + cc_credentials_iterator_t iter; + krb5_acc *a = ACACHE(id); + int32_t error; + + error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter); + if (error) + return ENOENT; + *cursor = iter; + return 0; +} + + +static krb5_error_code +acc_get_next (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + cc_credentials_iterator_t iter = *cursor; + cc_credentials_t cred; + krb5_error_code ret; + int32_t error; + + while (1) { + error = (*iter->func->next)(iter, &cred); + if (error) + return translate_cc_error(context, error); + if (cred->data->version == cc_credentials_v5) + break; + (*cred->func->release)(cred); + } + + ret = make_cred_from_ccred(context, + cred->data->credentials.credentials_v5, + creds); + (*cred->func->release)(cred); + return ret; +} + +static krb5_error_code +acc_end_get (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + cc_credentials_iterator_t iter = *cursor; + (*iter->func->release)(iter); + return 0; +} + +static krb5_error_code +acc_remove_cred(krb5_context context, + krb5_ccache id, + krb5_flags which, + krb5_creds *cred) +{ + cc_credentials_iterator_t iter; + krb5_acc *a = ACACHE(id); + cc_credentials_t ccred; + krb5_error_code ret; + cc_int32 error; + char *client, *server; + + if (cred->client) { + ret = krb5_unparse_name(context, cred->client, &client); + if (ret) + return ret; + } else + client = NULL; + + ret = krb5_unparse_name(context, cred->server, &server); + if (ret) { + free(client); + return ret; + } + + error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter); + if (error) { + free(server); + free(client); + return translate_cc_error(context, error); + } + + ret = KRB5_CC_NOTFOUND; + while (1) { + cc_credentials_v5_t *v5cred; + + error = (*iter->func->next)(iter, &ccred); + if (error) + break; + + if (ccred->data->version != cc_credentials_v5) + goto next; + + v5cred = ccred->data->credentials.credentials_v5; + + if (client && strcmp(v5cred->client, client) != 0) + goto next; + + if (strcmp(v5cred->server, server) != 0) + goto next; + + (*a->ccache->func->remove_credentials)(a->ccache, ccred); + ret = 0; + next: + (*ccred->func->release)(ccred); + } + + (*iter->func->release)(iter); + + if (ret) + krb5_set_error_string(context, "Can't find credential %s in cache", + server); + free(server); + free(client); + + return ret; +} + +static krb5_error_code +acc_set_flags(krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ + return 0; +} + +static krb5_error_code +acc_get_version(krb5_context context, + krb5_ccache id) +{ + return 0; +} + +const krb5_cc_ops krb5_acc_ops = { + "API", + acc_get_name, + acc_resolve, + acc_gen_new, + acc_initialize, + acc_destroy, + acc_close, + acc_store_cred, + NULL, /* acc_retrieve */ + acc_get_principal, + acc_get_first, + acc_get_next, + acc_end_get, + acc_remove_cred, + acc_set_flags, + acc_get_version +}; diff --git a/source4/heimdal/lib/krb5/add_et_list.c b/source4/heimdal/lib/krb5/add_et_list.c new file mode 100644 index 0000000000..3b9773bebb --- /dev/null +++ b/source4/heimdal/lib/krb5/add_et_list.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: add_et_list.c,v 1.3 2004/04/13 14:33:45 lha Exp $"); + +/* + * Add a specified list of error messages to the et list in context. + * Call func (probably a comerr-generated function) with a pointer to + * the current et_list. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_add_et_list (krb5_context context, + void (*func)(struct et_list **)) +{ + (*func)(&context->et_list); + return 0; +} diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c new file mode 100644 index 0000000000..ccc97f412d --- /dev/null +++ b/source4/heimdal/lib/krb5/addr_families.c @@ -0,0 +1,1180 @@ +/* + * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: addr_families.c,v 1.49 2005/06/16 20:16:12 lha Exp $"); + +struct addr_operations { + int af; + krb5_address_type atype; + size_t max_sockaddr_size; + krb5_error_code (*sockaddr2addr)(const struct sockaddr *, krb5_address *); + krb5_error_code (*sockaddr2port)(const struct sockaddr *, int16_t *); + void (*addr2sockaddr)(const krb5_address *, struct sockaddr *, + krb5_socklen_t *sa_size, int port); + void (*h_addr2sockaddr)(const char *, struct sockaddr *, krb5_socklen_t *, int); + krb5_error_code (*h_addr2addr)(const char *, krb5_address *); + krb5_boolean (*uninteresting)(const struct sockaddr *); + void (*anyaddr)(struct sockaddr *, krb5_socklen_t *, int); + int (*print_addr)(const krb5_address *, char *, size_t); + int (*parse_addr)(krb5_context, const char*, krb5_address *); + int (*order_addr)(krb5_context, const krb5_address*, const krb5_address*); + int (*free_addr)(krb5_context, krb5_address*); + int (*copy_addr)(krb5_context, const krb5_address*, krb5_address*); + int (*mask_boundary)(krb5_context, const krb5_address*, unsigned long, + krb5_address*, krb5_address*); +}; + +/* + * AF_INET - aka IPv4 implementation + */ + +static krb5_error_code +ipv4_sockaddr2addr (const struct sockaddr *sa, krb5_address *a) +{ + const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; + unsigned char buf[4]; + + a->addr_type = KRB5_ADDRESS_INET; + memcpy (buf, &sin4->sin_addr, 4); + return krb5_data_copy(&a->address, buf, 4); +} + +static krb5_error_code +ipv4_sockaddr2port (const struct sockaddr *sa, int16_t *port) +{ + const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; + + *port = sin4->sin_port; + return 0; +} + +static void +ipv4_addr2sockaddr (const krb5_address *a, + struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct sockaddr_in tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.sin_family = AF_INET; + memcpy (&tmp.sin_addr, a->address.data, 4); + tmp.sin_port = port; + memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); + *sa_size = sizeof(tmp); +} + +static void +ipv4_h_addr2sockaddr(const char *addr, + struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct sockaddr_in tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.sin_family = AF_INET; + tmp.sin_port = port; + tmp.sin_addr = *((const struct in_addr *)addr); + memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); + *sa_size = sizeof(tmp); +} + +static krb5_error_code +ipv4_h_addr2addr (const char *addr, + krb5_address *a) +{ + unsigned char buf[4]; + + a->addr_type = KRB5_ADDRESS_INET; + memcpy(buf, addr, 4); + return krb5_data_copy(&a->address, buf, 4); +} + +/* + * Are there any addresses that should be considered `uninteresting'? + */ + +static krb5_boolean +ipv4_uninteresting (const struct sockaddr *sa) +{ + const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; + + if (sin4->sin_addr.s_addr == INADDR_ANY) + return TRUE; + + return FALSE; +} + +static void +ipv4_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port) +{ + struct sockaddr_in tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.sin_family = AF_INET; + tmp.sin_port = port; + tmp.sin_addr.s_addr = INADDR_ANY; + memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); + *sa_size = sizeof(tmp); +} + +static int +ipv4_print_addr (const krb5_address *addr, char *str, size_t len) +{ + struct in_addr ia; + + memcpy (&ia, addr->address.data, 4); + + return snprintf (str, len, "IPv4:%s", inet_ntoa(ia)); +} + +static int +ipv4_parse_addr (krb5_context context, const char *address, krb5_address *addr) +{ + const char *p; + struct in_addr a; + + p = strchr(address, ':'); + if(p) { + p++; + if(strncasecmp(address, "ip:", p - address) != 0 && + strncasecmp(address, "ip4:", p - address) != 0 && + strncasecmp(address, "ipv4:", p - address) != 0 && + strncasecmp(address, "inet:", p - address) != 0) + return -1; + } else + p = address; +#ifdef HAVE_INET_ATON + if(inet_aton(p, &a) == 0) + return -1; +#elif defined(HAVE_INET_ADDR) + a.s_addr = inet_addr(p); + if(a.s_addr == INADDR_NONE) + return -1; +#else + return -1; +#endif + addr->addr_type = KRB5_ADDRESS_INET; + if(krb5_data_alloc(&addr->address, 4) != 0) + return -1; + _krb5_put_int(addr->address.data, ntohl(a.s_addr), addr->address.length); + return 0; +} + +static int +ipv4_mask_boundary(krb5_context context, const krb5_address *inaddr, + unsigned long len, krb5_address *low, krb5_address *high) +{ + unsigned long ia; + u_int32_t l, h, m = 0xffffffff; + + if (len > 32) { + krb5_set_error_string(context, "IPv4 prefix too large (%ld)", len); + return KRB5_PROG_ATYPE_NOSUPP; + } + m = m << (32 - len); + + _krb5_get_int(inaddr->address.data, &ia, inaddr->address.length); + + l = ia & m; + h = l | ~m; + + low->addr_type = KRB5_ADDRESS_INET; + if(krb5_data_alloc(&low->address, 4) != 0) + return -1; + _krb5_put_int(low->address.data, l, low->address.length); + + high->addr_type = KRB5_ADDRESS_INET; + if(krb5_data_alloc(&high->address, 4) != 0) { + krb5_free_address(context, low); + return -1; + } + _krb5_put_int(high->address.data, h, high->address.length); + + return 0; +} + + +/* + * AF_INET6 - aka IPv6 implementation + */ + +#ifdef HAVE_IPV6 + +static krb5_error_code +ipv6_sockaddr2addr (const struct sockaddr *sa, krb5_address *a) +{ + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; + + if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { + unsigned char buf[4]; + + a->addr_type = KRB5_ADDRESS_INET; +#ifndef IN6_ADDR_V6_TO_V4 +#ifdef IN6_EXTRACT_V4ADDR +#define IN6_ADDR_V6_TO_V4(x) (&IN6_EXTRACT_V4ADDR(x)) +#else +#define IN6_ADDR_V6_TO_V4(x) ((const struct in_addr *)&(x)->s6_addr[12]) +#endif +#endif + memcpy (buf, IN6_ADDR_V6_TO_V4(&sin6->sin6_addr), 4); + return krb5_data_copy(&a->address, buf, 4); + } else { + a->addr_type = KRB5_ADDRESS_INET6; + return krb5_data_copy(&a->address, + &sin6->sin6_addr, + sizeof(sin6->sin6_addr)); + } +} + +static krb5_error_code +ipv6_sockaddr2port (const struct sockaddr *sa, int16_t *port) +{ + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; + + *port = sin6->sin6_port; + return 0; +} + +static void +ipv6_addr2sockaddr (const krb5_address *a, + struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct sockaddr_in6 tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.sin6_family = AF_INET6; + memcpy (&tmp.sin6_addr, a->address.data, sizeof(tmp.sin6_addr)); + tmp.sin6_port = port; + memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); + *sa_size = sizeof(tmp); +} + +static void +ipv6_h_addr2sockaddr(const char *addr, + struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct sockaddr_in6 tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.sin6_family = AF_INET6; + tmp.sin6_port = port; + tmp.sin6_addr = *((const struct in6_addr *)addr); + memcpy(sa, &tmp, min(sizeof(tmp), *sa_size)); + *sa_size = sizeof(tmp); +} + +static krb5_error_code +ipv6_h_addr2addr (const char *addr, + krb5_address *a) +{ + a->addr_type = KRB5_ADDRESS_INET6; + return krb5_data_copy(&a->address, addr, sizeof(struct in6_addr)); +} + +/* + * + */ + +static krb5_boolean +ipv6_uninteresting (const struct sockaddr *sa) +{ + const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa; + const struct in6_addr *in6 = (const struct in6_addr *)&sin6->sin6_addr; + + return + IN6_IS_ADDR_LINKLOCAL(in6) + || IN6_IS_ADDR_V4COMPAT(in6); +} + +static void +ipv6_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port) +{ + struct sockaddr_in6 tmp; + + memset (&tmp, 0, sizeof(tmp)); + tmp.sin6_family = AF_INET6; + tmp.sin6_port = port; + tmp.sin6_addr = in6addr_any; + *sa_size = sizeof(tmp); +} + +static int +ipv6_print_addr (const krb5_address *addr, char *str, size_t len) +{ + char buf[128], buf2[3]; +#ifdef HAVE_INET_NTOP + if(inet_ntop(AF_INET6, addr->address.data, buf, sizeof(buf)) == NULL) +#endif + { + /* XXX this is pretty ugly, but better than abort() */ + int i; + unsigned char *p = addr->address.data; + buf[0] = '\0'; + for(i = 0; i < addr->address.length; i++) { + snprintf(buf2, sizeof(buf2), "%02x", p[i]); + if(i > 0 && (i & 1) == 0) + strlcat(buf, ":", sizeof(buf)); + strlcat(buf, buf2, sizeof(buf)); + } + } + return snprintf(str, len, "IPv6:%s", buf); +} + +static int +ipv6_parse_addr (krb5_context context, const char *address, krb5_address *addr) +{ + int ret; + struct in6_addr in6; + const char *p; + + p = strchr(address, ':'); + if(p) { + p++; + if(strncasecmp(address, "ip6:", p - address) == 0 || + strncasecmp(address, "ipv6:", p - address) == 0 || + strncasecmp(address, "inet6:", p - address) == 0) + address = p; + } + + ret = inet_pton(AF_INET6, address, &in6.s6_addr); + if(ret == 1) { + addr->addr_type = KRB5_ADDRESS_INET6; + ret = krb5_data_alloc(&addr->address, sizeof(in6.s6_addr)); + if (ret) + return -1; + memcpy(addr->address.data, in6.s6_addr, sizeof(in6.s6_addr)); + return 0; + } + return -1; +} + +static int +ipv6_mask_boundary(krb5_context context, const krb5_address *inaddr, + unsigned long len, krb5_address *low, krb5_address *high) +{ + struct in6_addr addr, laddr, haddr; + u_int32_t m; + int i, sub_len; + + if (len > 128) { + krb5_set_error_string(context, "IPv6 prefix too large (%ld)", len); + return KRB5_PROG_ATYPE_NOSUPP; + } + + if (inaddr->address.length != sizeof(addr)) { + krb5_set_error_string(context, "IPv6 addr bad length"); + return KRB5_PROG_ATYPE_NOSUPP; + } + + memcpy(&addr, inaddr->address.data, inaddr->address.length); + + for (i = 0; i < 16; i++) { + sub_len = min(8, len); + + m = 0xff << (8 - sub_len); + + laddr.s6_addr[i] = addr.s6_addr[i] & m; + haddr.s6_addr[i] = (addr.s6_addr[i] & m) | ~m; + + if (len > 8) + len -= 8; + else + len = 0; + } + + low->addr_type = KRB5_ADDRESS_INET6; + if (krb5_data_alloc(&low->address, sizeof(laddr.s6_addr)) != 0) + return -1; + memcpy(low->address.data, laddr.s6_addr, sizeof(laddr.s6_addr)); + + high->addr_type = KRB5_ADDRESS_INET6; + if (krb5_data_alloc(&high->address, sizeof(haddr.s6_addr)) != 0) { + krb5_free_address(context, low); + return -1; + } + memcpy(high->address.data, haddr.s6_addr, sizeof(haddr.s6_addr)); + + return 0; +} + +#endif /* IPv6 */ + +/* + * table + */ + +#define KRB5_ADDRESS_ARANGE (-100) + +struct arange { + krb5_address low; + krb5_address high; +}; + +static int +arange_parse_addr (krb5_context context, + const char *address, krb5_address *addr) +{ + char buf[1024], *p; + krb5_address low0, high0; + struct arange *a; + krb5_error_code ret; + + if(strncasecmp(address, "RANGE:", 6) != 0) + return -1; + + address += 6; + + p = strrchr(address, '/'); + if (p) { + krb5_addresses addrmask; + char *q; + long num; + + if (strlcpy(buf, address, sizeof(buf)) > sizeof(buf)) + return -1; + buf[p - address] = '\0'; + ret = krb5_parse_address(context, buf, &addrmask); + if (ret) + return ret; + if(addrmask.len != 1) { + krb5_free_addresses(context, &addrmask); + return -1; + } + + address += p - address + 1; + + num = strtol(address, &q, 10); + if (q == address || *q != '\0' || num < 0) { + krb5_free_addresses(context, &addrmask); + return -1; + } + + ret = krb5_address_prefixlen_boundary(context, &addrmask.val[0], num, + &low0, &high0); + krb5_free_addresses(context, &addrmask); + if (ret) + return ret; + + } else { + krb5_addresses low, high; + + strsep_copy(&address, "-", buf, sizeof(buf)); + ret = krb5_parse_address(context, buf, &low); + if(ret) + return ret; + if(low.len != 1) { + krb5_free_addresses(context, &low); + return -1; + } + + strsep_copy(&address, "-", buf, sizeof(buf)); + ret = krb5_parse_address(context, buf, &high); + if(ret) { + krb5_free_addresses(context, &low); + return ret; + } + + if(high.len != 1 && high.val[0].addr_type != low.val[0].addr_type) { + krb5_free_addresses(context, &low); + krb5_free_addresses(context, &high); + return -1; + } + + ret = krb5_copy_address(context, &high.val[0], &high0); + if (ret == 0) { + ret = krb5_copy_address(context, &low.val[0], &low0); + if (ret) + krb5_free_address(context, &high0); + } + krb5_free_addresses(context, &low); + krb5_free_addresses(context, &high); + if (ret) + return ret; + } + + krb5_data_alloc(&addr->address, sizeof(*a)); + addr->addr_type = KRB5_ADDRESS_ARANGE; + a = addr->address.data; + + if(krb5_address_order(context, &low0, &high0) < 0) { + a->low = low0; + a->high = high0; + } else { + a->low = high0; + a->high = low0; + } + return 0; +} + +static int +arange_free (krb5_context context, krb5_address *addr) +{ + struct arange *a; + a = addr->address.data; + krb5_free_address(context, &a->low); + krb5_free_address(context, &a->high); + return 0; +} + + +static int +arange_copy (krb5_context context, const krb5_address *inaddr, + krb5_address *outaddr) +{ + krb5_error_code ret; + struct arange *i, *o; + + outaddr->addr_type = KRB5_ADDRESS_ARANGE; + ret = krb5_data_alloc(&outaddr->address, sizeof(*o)); + if(ret) + return ret; + i = inaddr->address.data; + o = outaddr->address.data; + ret = krb5_copy_address(context, &i->low, &o->low); + if(ret) { + krb5_data_free(&outaddr->address); + return ret; + } + ret = krb5_copy_address(context, &i->high, &o->high); + if(ret) { + krb5_free_address(context, &o->low); + krb5_data_free(&outaddr->address); + return ret; + } + return 0; +} + +static int +arange_print_addr (const krb5_address *addr, char *str, size_t len) +{ + struct arange *a; + krb5_error_code ret; + size_t l, size, ret_len; + + a = addr->address.data; + + l = strlcpy(str, "RANGE:", len); + ret_len = l; + if (l > len) + l = len; + size = l; + + ret = krb5_print_address (&a->low, str + size, len - size, &l); + if (ret) + return ret; + ret_len += l; + if (len - size > l) + size += l; + else + size = len; + + l = strlcat(str + size, "-", len - size); + ret_len += l; + if (len - size > l) + size += l; + else + size = len; + + ret = krb5_print_address (&a->high, str + size, len - size, &l); + if (ret) + return ret; + ret_len += l; + + return ret_len; +} + +static int +arange_order_addr(krb5_context context, + const krb5_address *addr1, + const krb5_address *addr2) +{ + int tmp1, tmp2, sign; + struct arange *a; + const krb5_address *a2; + + if(addr1->addr_type == KRB5_ADDRESS_ARANGE) { + a = addr1->address.data; + a2 = addr2; + sign = 1; + } else if(addr2->addr_type == KRB5_ADDRESS_ARANGE) { + a = addr2->address.data; + a2 = addr1; + sign = -1; + } else + abort(); + + if(a2->addr_type == KRB5_ADDRESS_ARANGE) { + struct arange *b = a2->address.data; + tmp1 = krb5_address_order(context, &a->low, &b->low); + if(tmp1 != 0) + return sign * tmp1; + return sign * krb5_address_order(context, &a->high, &b->high); + } else if(a2->addr_type == a->low.addr_type) { + tmp1 = krb5_address_order(context, &a->low, a2); + if(tmp1 > 0) + return sign; + tmp2 = krb5_address_order(context, &a->high, a2); + if(tmp2 < 0) + return -sign; + return 0; + } else { + return sign * (addr1->addr_type - addr2->addr_type); + } +} + +static int +addrport_print_addr (const krb5_address *addr, char *str, size_t len) +{ + krb5_error_code ret; + krb5_address addr1, addr2; + uint16_t port = 0; + size_t ret_len = 0, l, size = 0; + krb5_storage *sp; + + sp = krb5_storage_from_data((krb5_data*)rk_UNCONST(&addr->address)); + /* for totally obscure reasons, these are not in network byteorder */ + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); + + krb5_storage_seek(sp, 2, SEEK_CUR); /* skip first two bytes */ + krb5_ret_address(sp, &addr1); + + krb5_storage_seek(sp, 2, SEEK_CUR); /* skip two bytes */ + krb5_ret_address(sp, &addr2); + krb5_storage_free(sp); + if(addr2.addr_type == KRB5_ADDRESS_IPPORT && addr2.address.length == 2) { + unsigned long value; + _krb5_get_int(addr2.address.data, &value, 2); + port = value; + } + l = strlcpy(str, "ADDRPORT:", len); + ret_len += l; + if (len > l) + size += l; + else + size = len; + + ret = krb5_print_address(&addr1, str + size, len - size, &l); + if (ret) + return ret; + ret_len += l; + if (len - size > l) + size += l; + else + size = len; + + ret = snprintf(str + size, len - size, ",PORT=%u", port); + if (ret < 0) + return EINVAL; + ret_len += ret; + return ret_len; +} + +static struct addr_operations at[] = { + {AF_INET, KRB5_ADDRESS_INET, sizeof(struct sockaddr_in), + ipv4_sockaddr2addr, + ipv4_sockaddr2port, + ipv4_addr2sockaddr, + ipv4_h_addr2sockaddr, + ipv4_h_addr2addr, + ipv4_uninteresting, ipv4_anyaddr, ipv4_print_addr, ipv4_parse_addr, + NULL, NULL, NULL, ipv4_mask_boundary }, +#ifdef HAVE_IPV6 + {AF_INET6, KRB5_ADDRESS_INET6, sizeof(struct sockaddr_in6), + ipv6_sockaddr2addr, + ipv6_sockaddr2port, + ipv6_addr2sockaddr, + ipv6_h_addr2sockaddr, + ipv6_h_addr2addr, + ipv6_uninteresting, ipv6_anyaddr, ipv6_print_addr, ipv6_parse_addr, + NULL, NULL, NULL, ipv6_mask_boundary } , +#endif + {KRB5_ADDRESS_ADDRPORT, KRB5_ADDRESS_ADDRPORT, 0, + NULL, NULL, NULL, NULL, NULL, + NULL, NULL, addrport_print_addr, NULL, NULL, NULL, NULL }, + /* fake address type */ + {KRB5_ADDRESS_ARANGE, KRB5_ADDRESS_ARANGE, sizeof(struct arange), + NULL, NULL, NULL, NULL, NULL, NULL, NULL, + arange_print_addr, arange_parse_addr, + arange_order_addr, arange_free, arange_copy } +}; + +static int num_addrs = sizeof(at) / sizeof(at[0]); + +static size_t max_sockaddr_size = 0; + +/* + * generic functions + */ + +static struct addr_operations * +find_af(int af) +{ + struct addr_operations *a; + + for (a = at; a < at + num_addrs; ++a) + if (af == a->af) + return a; + return NULL; +} + +static struct addr_operations * +find_atype(int atype) +{ + struct addr_operations *a; + + for (a = at; a < at + num_addrs; ++a) + if (atype == a->atype) + return a; + return NULL; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sockaddr2address (krb5_context context, + const struct sockaddr *sa, krb5_address *addr) +{ + struct addr_operations *a = find_af(sa->sa_family); + if (a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", + sa->sa_family); + return KRB5_PROG_ATYPE_NOSUPP; + } + return (*a->sockaddr2addr)(sa, addr); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sockaddr2port (krb5_context context, + const struct sockaddr *sa, int16_t *port) +{ + struct addr_operations *a = find_af(sa->sa_family); + if (a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", + sa->sa_family); + return KRB5_PROG_ATYPE_NOSUPP; + } + return (*a->sockaddr2port)(sa, port); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_addr2sockaddr (krb5_context context, + const krb5_address *addr, + struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct addr_operations *a = find_atype(addr->addr_type); + + if (a == NULL) { + krb5_set_error_string (context, "Address type %d not supported", + addr->addr_type); + return KRB5_PROG_ATYPE_NOSUPP; + } + if (a->addr2sockaddr == NULL) { + krb5_set_error_string (context, "Can't convert address type %d to sockaddr", + addr->addr_type); + return KRB5_PROG_ATYPE_NOSUPP; + } + (*a->addr2sockaddr)(addr, sa, sa_size, port); + return 0; +} + +size_t KRB5_LIB_FUNCTION +krb5_max_sockaddr_size (void) +{ + if (max_sockaddr_size == 0) { + struct addr_operations *a; + + for(a = at; a < at + num_addrs; ++a) + max_sockaddr_size = max(max_sockaddr_size, a->max_sockaddr_size); + } + return max_sockaddr_size; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_sockaddr_uninteresting(const struct sockaddr *sa) +{ + struct addr_operations *a = find_af(sa->sa_family); + if (a == NULL || a->uninteresting == NULL) + return TRUE; + return (*a->uninteresting)(sa); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_h_addr2sockaddr (krb5_context context, + int af, + const char *addr, struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct addr_operations *a = find_af(af); + if (a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", af); + return KRB5_PROG_ATYPE_NOSUPP; + } + (*a->h_addr2sockaddr)(addr, sa, sa_size, port); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_h_addr2addr (krb5_context context, + int af, + const char *haddr, krb5_address *addr) +{ + struct addr_operations *a = find_af(af); + if (a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", af); + return KRB5_PROG_ATYPE_NOSUPP; + } + return (*a->h_addr2addr)(haddr, addr); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_anyaddr (krb5_context context, + int af, + struct sockaddr *sa, + krb5_socklen_t *sa_size, + int port) +{ + struct addr_operations *a = find_af (af); + + if (a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", af); + return KRB5_PROG_ATYPE_NOSUPP; + } + + (*a->anyaddr)(sa, sa_size, port); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_print_address (const krb5_address *addr, + char *str, size_t len, size_t *ret_len) +{ + struct addr_operations *a = find_atype(addr->addr_type); + int ret; + + if (a == NULL || a->print_addr == NULL) { + char *s; + int l; + int i; + + s = str; + l = snprintf(s, len, "TYPE_%d:", addr->addr_type); + if (l < 0 || l >= len) + return EINVAL; + s += l; + len -= l; + for(i = 0; i < addr->address.length; i++) { + l = snprintf(s, len, "%02x", ((char*)addr->address.data)[i]); + if (l < 0 || l >= len) + return EINVAL; + len -= l; + s += l; + } + if(ret_len != NULL) + *ret_len = s - str; + return 0; + } + ret = (*a->print_addr)(addr, str, len); + if (ret < 0) + return EINVAL; + if(ret_len != NULL) + *ret_len = ret; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_address(krb5_context context, + const char *string, + krb5_addresses *addresses) +{ + int i, n; + struct addrinfo *ai, *a; + int error; + int save_errno; + + for(i = 0; i < num_addrs; i++) { + if(at[i].parse_addr) { + krb5_address addr; + if((*at[i].parse_addr)(context, string, &addr) == 0) { + ALLOC_SEQ(addresses, 1); + addresses->val[0] = addr; + return 0; + } + } + } + + error = getaddrinfo (string, NULL, NULL, &ai); + if (error) { + save_errno = errno; + krb5_set_error_string (context, "%s: %s", string, gai_strerror(error)); + return krb5_eai_to_heim_errno(error, save_errno); + } + + n = 0; + for (a = ai; a != NULL; a = a->ai_next) + ++n; + + ALLOC_SEQ(addresses, n); + if (addresses->val == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + freeaddrinfo(ai); + return ENOMEM; + } + + addresses->len = 0; + for (a = ai, i = 0; a != NULL; a = a->ai_next) { + if (krb5_sockaddr2address (context, ai->ai_addr, &addresses->val[i])) + continue; + if(krb5_address_search(context, &addresses->val[i], addresses)) + continue; + addresses->len = i; + i++; + } + freeaddrinfo (ai); + return 0; +} + +int KRB5_LIB_FUNCTION +krb5_address_order(krb5_context context, + const krb5_address *addr1, + const krb5_address *addr2) +{ + /* this sucks; what if both addresses have order functions, which + should we call? this works for now, though */ + struct addr_operations *a; + a = find_atype(addr1->addr_type); + if(a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", + addr1->addr_type); + return KRB5_PROG_ATYPE_NOSUPP; + } + if(a->order_addr != NULL) + return (*a->order_addr)(context, addr1, addr2); + a = find_atype(addr2->addr_type); + if(a == NULL) { + krb5_set_error_string (context, "Address family %d not supported", + addr2->addr_type); + return KRB5_PROG_ATYPE_NOSUPP; + } + if(a->order_addr != NULL) + return (*a->order_addr)(context, addr1, addr2); + + if(addr1->addr_type != addr2->addr_type) + return addr1->addr_type - addr2->addr_type; + if(addr1->address.length != addr2->address.length) + return addr1->address.length - addr2->address.length; + return memcmp (addr1->address.data, + addr2->address.data, + addr1->address.length); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_address_compare(krb5_context context, + const krb5_address *addr1, + const krb5_address *addr2) +{ + return krb5_address_order (context, addr1, addr2) == 0; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_address_search(krb5_context context, + const krb5_address *addr, + const krb5_addresses *addrlist) +{ + int i; + + for (i = 0; i < addrlist->len; ++i) + if (krb5_address_compare (context, addr, &addrlist->val[i])) + return TRUE; + return FALSE; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_address(krb5_context context, + krb5_address *address) +{ + struct addr_operations *a = find_atype (address->addr_type); + if(a != NULL && a->free_addr != NULL) + return (*a->free_addr)(context, address); + krb5_data_free (&address->address); + memset(address, 0, sizeof(*address)); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_addresses(krb5_context context, + krb5_addresses *addresses) +{ + int i; + for(i = 0; i < addresses->len; i++) + krb5_free_address(context, &addresses->val[i]); + free(addresses->val); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_address(krb5_context context, + const krb5_address *inaddr, + krb5_address *outaddr) +{ + struct addr_operations *a = find_af (inaddr->addr_type); + if(a != NULL && a->copy_addr != NULL) + return (*a->copy_addr)(context, inaddr, outaddr); + return copy_HostAddress(inaddr, outaddr); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_addresses(krb5_context context, + const krb5_addresses *inaddr, + krb5_addresses *outaddr) +{ + int i; + ALLOC_SEQ(outaddr, inaddr->len); + if(inaddr->len > 0 && outaddr->val == NULL) + return ENOMEM; + for(i = 0; i < inaddr->len; i++) + krb5_copy_address(context, &inaddr->val[i], &outaddr->val[i]); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_append_addresses(krb5_context context, + krb5_addresses *dest, + const krb5_addresses *source) +{ + krb5_address *tmp; + krb5_error_code ret; + int i; + if(source->len > 0) { + tmp = realloc(dest->val, (dest->len + source->len) * sizeof(*tmp)); + if(tmp == NULL) { + krb5_set_error_string(context, "realloc: out of memory"); + return ENOMEM; + } + dest->val = tmp; + for(i = 0; i < source->len; i++) { + /* skip duplicates */ + if(krb5_address_search(context, &source->val[i], dest)) + continue; + ret = krb5_copy_address(context, + &source->val[i], + &dest->val[dest->len]); + if(ret) + return ret; + dest->len++; + } + } + return 0; +} + +/* + * Create an address of type KRB5_ADDRESS_ADDRPORT from (addr, port) + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_make_addrport (krb5_context context, + krb5_address **res, const krb5_address *addr, int16_t port) +{ + krb5_error_code ret; + size_t len = addr->address.length + 2 + 4 * 4; + u_char *p; + + *res = malloc (sizeof(**res)); + if (*res == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + (*res)->addr_type = KRB5_ADDRESS_ADDRPORT; + ret = krb5_data_alloc (&(*res)->address, len); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + free (*res); + return ret; + } + p = (*res)->address.data; + *p++ = 0; + *p++ = 0; + *p++ = (addr->addr_type ) & 0xFF; + *p++ = (addr->addr_type >> 8) & 0xFF; + + *p++ = (addr->address.length ) & 0xFF; + *p++ = (addr->address.length >> 8) & 0xFF; + *p++ = (addr->address.length >> 16) & 0xFF; + *p++ = (addr->address.length >> 24) & 0xFF; + + memcpy (p, addr->address.data, addr->address.length); + p += addr->address.length; + + *p++ = 0; + *p++ = 0; + *p++ = (KRB5_ADDRESS_IPPORT ) & 0xFF; + *p++ = (KRB5_ADDRESS_IPPORT >> 8) & 0xFF; + + *p++ = (2 ) & 0xFF; + *p++ = (2 >> 8) & 0xFF; + *p++ = (2 >> 16) & 0xFF; + *p++ = (2 >> 24) & 0xFF; + + memcpy (p, &port, 2); + p += 2; + + return 0; +} + +/* + * Calculate the boundary addresses of `inaddr'/`prefixlen' and store + * them in `low' and `high'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_address_prefixlen_boundary(krb5_context context, + const krb5_address *inaddr, + unsigned long prefixlen, + krb5_address *low, + krb5_address *high) +{ + struct addr_operations *a = find_atype (inaddr->addr_type); + if(a != NULL && a->mask_boundary != NULL) + return (*a->mask_boundary)(context, inaddr, prefixlen, low, high); + krb5_set_error_string(context, "Address family %d doesn't support " + "address mask operation", inaddr->addr_type); + return KRB5_PROG_ATYPE_NOSUPP; +} diff --git a/source4/heimdal/lib/krb5/appdefault.c b/source4/heimdal/lib/krb5/appdefault.c new file mode 100644 index 0000000000..03fa933b6f --- /dev/null +++ b/source4/heimdal/lib/krb5/appdefault.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: appdefault.c,v 1.10 2005/01/05 05:40:59 lukeh Exp $"); + +void KRB5_LIB_FUNCTION +krb5_appdefault_boolean(krb5_context context, const char *appname, + krb5_const_realm realm, const char *option, + krb5_boolean def_val, krb5_boolean *ret_val) +{ + + if(appname == NULL) + appname = getprogname(); + + def_val = krb5_config_get_bool_default(context, NULL, def_val, + "libdefaults", option, NULL); + if(realm != NULL) + def_val = krb5_config_get_bool_default(context, NULL, def_val, + "realms", realm, option, NULL); + + def_val = krb5_config_get_bool_default(context, NULL, def_val, + "appdefaults", + option, + NULL); + if(realm != NULL) + def_val = krb5_config_get_bool_default(context, NULL, def_val, + "appdefaults", + realm, + option, + NULL); + if(appname != NULL) { + def_val = krb5_config_get_bool_default(context, NULL, def_val, + "appdefaults", + appname, + option, + NULL); + if(realm != NULL) + def_val = krb5_config_get_bool_default(context, NULL, def_val, + "appdefaults", + appname, + realm, + option, + NULL); + } + *ret_val = def_val; +} + +void KRB5_LIB_FUNCTION +krb5_appdefault_string(krb5_context context, const char *appname, + krb5_const_realm realm, const char *option, + const char *def_val, char **ret_val) +{ + if(appname == NULL) + appname = getprogname(); + + def_val = krb5_config_get_string_default(context, NULL, def_val, + "libdefaults", option, NULL); + if(realm != NULL) + def_val = krb5_config_get_string_default(context, NULL, def_val, + "realms", realm, option, NULL); + + def_val = krb5_config_get_string_default(context, NULL, def_val, + "appdefaults", + option, + NULL); + if(realm != NULL) + def_val = krb5_config_get_string_default(context, NULL, def_val, + "appdefaults", + realm, + option, + NULL); + if(appname != NULL) { + def_val = krb5_config_get_string_default(context, NULL, def_val, + "appdefaults", + appname, + option, + NULL); + if(realm != NULL) + def_val = krb5_config_get_string_default(context, NULL, def_val, + "appdefaults", + appname, + realm, + option, + NULL); + } + if(def_val != NULL) + *ret_val = strdup(def_val); + else + *ret_val = NULL; +} + +void KRB5_LIB_FUNCTION +krb5_appdefault_time(krb5_context context, const char *appname, + krb5_const_realm realm, const char *option, + time_t def_val, time_t *ret_val) +{ + krb5_deltat t; + char *val; + + krb5_appdefault_string(context, appname, realm, option, NULL, &val); + if (val == NULL) { + *ret_val = def_val; + return; + } + if (krb5_string_to_deltat(val, &t)) + *ret_val = def_val; + else + *ret_val = t; + free(val); +} diff --git a/source4/heimdal/lib/krb5/asn1_glue.c b/source4/heimdal/lib/krb5/asn1_glue.c new file mode 100644 index 0000000000..01b5d3ee44 --- /dev/null +++ b/source4/heimdal/lib/krb5/asn1_glue.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +/* + * + */ + +#include "krb5_locl.h" + +RCSID("$Id: asn1_glue.c,v 1.9 2004/12/29 18:54:15 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_principal2principalname (PrincipalName *p, + const krb5_principal from) +{ + return copy_PrincipalName(&from->name, p); +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_principalname2krb5_principal (krb5_principal *principal, + const PrincipalName from, + const Realm realm) +{ + krb5_principal p = malloc(sizeof(*p)); + copy_PrincipalName(&from, &p->name); + p->realm = strdup(realm); + *principal = p; + return 0; +} diff --git a/source4/heimdal/lib/krb5/auth_context.c b/source4/heimdal/lib/krb5/auth_context.c new file mode 100644 index 0000000000..b8ce65d9a5 --- /dev/null +++ b/source4/heimdal/lib/krb5/auth_context.c @@ -0,0 +1,517 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: auth_context.c,v 1.62 2005/01/05 02:34:08 lukeh Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_init(krb5_context context, + krb5_auth_context *auth_context) +{ + krb5_auth_context p; + + ALLOC(p, 1); + if(!p) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memset(p, 0, sizeof(*p)); + ALLOC(p->authenticator, 1); + if (!p->authenticator) { + krb5_set_error_string(context, "malloc: out of memory"); + free(p); + return ENOMEM; + } + memset (p->authenticator, 0, sizeof(*p->authenticator)); + p->flags = KRB5_AUTH_CONTEXT_DO_TIME; + + p->local_address = NULL; + p->remote_address = NULL; + p->local_port = 0; + p->remote_port = 0; + p->keytype = KEYTYPE_NULL; + p->cksumtype = CKSUMTYPE_NONE; + *auth_context = p; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_free(krb5_context context, + krb5_auth_context auth_context) +{ + if (auth_context != NULL) { + krb5_free_authenticator(context, &auth_context->authenticator); + if(auth_context->local_address){ + free_HostAddress(auth_context->local_address); + free(auth_context->local_address); + } + if(auth_context->remote_address){ + free_HostAddress(auth_context->remote_address); + free(auth_context->remote_address); + } + krb5_free_keyblock(context, auth_context->keyblock); + krb5_free_keyblock(context, auth_context->remote_subkey); + krb5_free_keyblock(context, auth_context->local_subkey); + free (auth_context); + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setflags(krb5_context context, + krb5_auth_context auth_context, + int32_t flags) +{ + auth_context->flags = flags; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getflags(krb5_context context, + krb5_auth_context auth_context, + int32_t *flags) +{ + *flags = auth_context->flags; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_addflags(krb5_context context, + krb5_auth_context auth_context, + int32_t addflags, + int32_t *flags) +{ + if (flags) + *flags = auth_context->flags; + auth_context->flags |= addflags; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_removeflags(krb5_context context, + krb5_auth_context auth_context, + int32_t removeflags, + int32_t *flags) +{ + if (flags) + *flags = auth_context->flags; + auth_context->flags &= ~removeflags; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setaddrs(krb5_context context, + krb5_auth_context auth_context, + krb5_address *local_addr, + krb5_address *remote_addr) +{ + if (local_addr) { + if (auth_context->local_address) + krb5_free_address (context, auth_context->local_address); + else + auth_context->local_address = malloc(sizeof(krb5_address)); + krb5_copy_address(context, local_addr, auth_context->local_address); + } + if (remote_addr) { + if (auth_context->remote_address) + krb5_free_address (context, auth_context->remote_address); + else + auth_context->remote_address = malloc(sizeof(krb5_address)); + krb5_copy_address(context, remote_addr, auth_context->remote_address); + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_genaddrs(krb5_context context, + krb5_auth_context auth_context, + int fd, int flags) +{ + krb5_error_code ret; + krb5_address local_k_address, remote_k_address; + krb5_address *lptr = NULL, *rptr = NULL; + struct sockaddr_storage ss_local, ss_remote; + struct sockaddr *local = (struct sockaddr *)&ss_local; + struct sockaddr *remote = (struct sockaddr *)&ss_remote; + socklen_t len; + + if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR) { + if (auth_context->local_address == NULL) { + len = sizeof(ss_local); + if(getsockname(fd, local, &len) < 0) { + ret = errno; + krb5_set_error_string (context, "getsockname: %s", + strerror(ret)); + goto out; + } + ret = krb5_sockaddr2address (context, local, &local_k_address); + if(ret) goto out; + if(flags & KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR) { + krb5_sockaddr2port (context, local, &auth_context->local_port); + } else + auth_context->local_port = 0; + lptr = &local_k_address; + } + } + if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR) { + len = sizeof(ss_remote); + if(getpeername(fd, remote, &len) < 0) { + ret = errno; + krb5_set_error_string (context, "getpeername: %s", strerror(ret)); + goto out; + } + ret = krb5_sockaddr2address (context, remote, &remote_k_address); + if(ret) goto out; + if(flags & KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR) { + krb5_sockaddr2port (context, remote, &auth_context->remote_port); + } else + auth_context->remote_port = 0; + rptr = &remote_k_address; + } + ret = krb5_auth_con_setaddrs (context, + auth_context, + lptr, + rptr); + out: + if (lptr) + krb5_free_address (context, lptr); + if (rptr) + krb5_free_address (context, rptr); + return ret; + +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setaddrs_from_fd (krb5_context context, + krb5_auth_context auth_context, + void *p_fd) +{ + int fd = *(int*)p_fd; + int flags = 0; + if(auth_context->local_address == NULL) + flags |= KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR; + if(auth_context->remote_address == NULL) + flags |= KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR; + return krb5_auth_con_genaddrs(context, auth_context, fd, flags); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getaddrs(krb5_context context, + krb5_auth_context auth_context, + krb5_address **local_addr, + krb5_address **remote_addr) +{ + if(*local_addr) + krb5_free_address (context, *local_addr); + *local_addr = malloc (sizeof(**local_addr)); + if (*local_addr == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_copy_address(context, + auth_context->local_address, + *local_addr); + + if(*remote_addr) + krb5_free_address (context, *remote_addr); + *remote_addr = malloc (sizeof(**remote_addr)); + if (*remote_addr == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + krb5_free_address (context, *local_addr); + *local_addr = NULL; + return ENOMEM; + } + krb5_copy_address(context, + auth_context->remote_address, + *remote_addr); + return 0; +} + +static krb5_error_code +copy_key(krb5_context context, + krb5_keyblock *in, + krb5_keyblock **out) +{ + if(in) + return krb5_copy_keyblock(context, in, out); + *out = NULL; /* is this right? */ + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock **keyblock) +{ + return copy_key(context, auth_context->keyblock, keyblock); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getlocalsubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock **keyblock) +{ + return copy_key(context, auth_context->local_subkey, keyblock); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getremotesubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock **keyblock) +{ + return copy_key(context, auth_context->remote_subkey, keyblock); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock) +{ + if(auth_context->keyblock) + krb5_free_keyblock(context, auth_context->keyblock); + return copy_key(context, keyblock, &auth_context->keyblock); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setlocalsubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock) +{ + if(auth_context->local_subkey) + krb5_free_keyblock(context, auth_context->local_subkey); + return copy_key(context, keyblock, &auth_context->local_subkey); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_generatelocalsubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_keyblock *subkey; + + ret = krb5_generate_subkey_extended (context, key, + auth_context->keytype, + &subkey); + if(ret) + return ret; + if(auth_context->local_subkey) + krb5_free_keyblock(context, auth_context->local_subkey); + auth_context->local_subkey = subkey; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setremotesubkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock) +{ + if(auth_context->remote_subkey) + krb5_free_keyblock(context, auth_context->remote_subkey); + return copy_key(context, keyblock, &auth_context->remote_subkey); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setcksumtype(krb5_context context, + krb5_auth_context auth_context, + krb5_cksumtype cksumtype) +{ + auth_context->cksumtype = cksumtype; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getcksumtype(krb5_context context, + krb5_auth_context auth_context, + krb5_cksumtype *cksumtype) +{ + *cksumtype = auth_context->cksumtype; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setkeytype (krb5_context context, + krb5_auth_context auth_context, + krb5_keytype keytype) +{ + auth_context->keytype = keytype; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getkeytype (krb5_context context, + krb5_auth_context auth_context, + krb5_keytype *keytype) +{ + *keytype = auth_context->keytype; + return 0; +} + +#if 0 +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setenctype(krb5_context context, + krb5_auth_context auth_context, + krb5_enctype etype) +{ + if(auth_context->keyblock) + krb5_free_keyblock(context, auth_context->keyblock); + ALLOC(auth_context->keyblock, 1); + if(auth_context->keyblock == NULL) + return ENOMEM; + auth_context->keyblock->keytype = etype; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getenctype(krb5_context context, + krb5_auth_context auth_context, + krb5_enctype *etype) +{ + krb5_abortx(context, "unimplemented krb5_auth_getenctype called"); +} +#endif + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getlocalseqnumber(krb5_context context, + krb5_auth_context auth_context, + int32_t *seqnumber) +{ + *seqnumber = auth_context->local_seqnumber; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setlocalseqnumber (krb5_context context, + krb5_auth_context auth_context, + int32_t seqnumber) +{ + auth_context->local_seqnumber = seqnumber; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_getremoteseqnumber(krb5_context context, + krb5_auth_context auth_context, + int32_t *seqnumber) +{ + *seqnumber = auth_context->remote_seqnumber; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setremoteseqnumber (krb5_context context, + krb5_auth_context auth_context, + int32_t seqnumber) +{ + auth_context->remote_seqnumber = seqnumber; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getauthenticator(krb5_context context, + krb5_auth_context auth_context, + krb5_authenticator *authenticator) +{ + *authenticator = malloc(sizeof(**authenticator)); + if (*authenticator == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + copy_Authenticator(auth_context->authenticator, + *authenticator); + return 0; +} + + +void KRB5_LIB_FUNCTION +krb5_free_authenticator(krb5_context context, + krb5_authenticator *authenticator) +{ + free_Authenticator (*authenticator); + free (*authenticator); + *authenticator = NULL; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setuserkey(krb5_context context, + krb5_auth_context auth_context, + krb5_keyblock *keyblock) +{ + if(auth_context->keyblock) + krb5_free_keyblock(context, auth_context->keyblock); + return krb5_copy_keyblock(context, keyblock, &auth_context->keyblock); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getrcache(krb5_context context, + krb5_auth_context auth_context, + krb5_rcache *rcache) +{ + *rcache = auth_context->rcache; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setrcache(krb5_context context, + krb5_auth_context auth_context, + krb5_rcache rcache) +{ + auth_context->rcache = rcache; + return 0; +} + +#if 0 /* not implemented */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_initivector(krb5_context context, + krb5_auth_context auth_context) +{ + krb5_abortx(context, "unimplemented krb5_auth_con_initivector called"); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setivector(krb5_context context, + krb5_auth_context auth_context, + krb5_pointer ivector) +{ + krb5_abortx(context, "unimplemented krb5_auth_con_setivector called"); +} + +#endif /* not implemented */ diff --git a/source4/heimdal/lib/krb5/build_ap_req.c b/source4/heimdal/lib/krb5/build_ap_req.c new file mode 100644 index 0000000000..e11744cc3a --- /dev/null +++ b/source4/heimdal/lib/krb5/build_ap_req.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: build_ap_req.c,v 1.20 2004/05/25 21:18:17 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_ap_req (krb5_context context, + krb5_enctype enctype, + krb5_creds *cred, + krb5_flags ap_options, + krb5_data authenticator, + krb5_data *retdata) +{ + krb5_error_code ret = 0; + AP_REQ ap; + Ticket t; + size_t len; + + ap.pvno = 5; + ap.msg_type = krb_ap_req; + memset(&ap.ap_options, 0, sizeof(ap.ap_options)); + ap.ap_options.use_session_key = (ap_options & AP_OPTS_USE_SESSION_KEY) > 0; + ap.ap_options.mutual_required = (ap_options & AP_OPTS_MUTUAL_REQUIRED) > 0; + + ap.ticket.tkt_vno = 5; + copy_Realm(&cred->server->realm, &ap.ticket.realm); + copy_PrincipalName(&cred->server->name, &ap.ticket.sname); + + decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len); + copy_EncryptedData(&t.enc_part, &ap.ticket.enc_part); + free_Ticket(&t); + + ap.authenticator.etype = enctype; + ap.authenticator.kvno = NULL; + ap.authenticator.cipher = authenticator; + + ASN1_MALLOC_ENCODE(AP_REQ, retdata->data, retdata->length, + &ap, &len, ret); + if(ret == 0 && retdata->length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + free_AP_REQ(&ap); + return ret; + +} diff --git a/source4/heimdal/lib/krb5/build_auth.c b/source4/heimdal/lib/krb5/build_auth.c new file mode 100644 index 0000000000..1c38721b02 --- /dev/null +++ b/source4/heimdal/lib/krb5/build_auth.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: build_auth.c,v 1.42 2005/01/05 02:34:53 lukeh Exp $"); + +static krb5_error_code +make_etypelist(krb5_context context, + krb5_authdata **auth_data) +{ + EtypeList etypes; + krb5_error_code ret; + krb5_authdata ad; + u_char *buf; + size_t len; + size_t buf_size; + + ret = krb5_init_etype(context, &etypes.len, &etypes.val, NULL); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(EtypeList, buf, buf_size, &etypes, &len, ret); + if (ret) { + free_EtypeList(&etypes); + return ret; + } + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + free_EtypeList(&etypes); + + ALLOC_SEQ(&ad, 1); + if (ad.val == NULL) { + free(buf); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ad.val[0].ad_type = KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION; + ad.val[0].ad_data.length = len; + ad.val[0].ad_data.data = buf; + + ASN1_MALLOC_ENCODE(AD_IF_RELEVANT, buf, buf_size, &ad, &len, ret); + if (ret) { + free_AuthorizationData(&ad); + return ret; + } + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + free_AuthorizationData(&ad); + + ALLOC(*auth_data, 1); + if (*auth_data == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ALLOC_SEQ(*auth_data, 1); + if ((*auth_data)->val == NULL) { + free(buf); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + (*auth_data)->val[0].ad_type = KRB5_AUTHDATA_IF_RELEVANT; + (*auth_data)->val[0].ad_data.length = len; + (*auth_data)->val[0].ad_data.data = buf; + + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_authenticator (krb5_context context, + krb5_auth_context auth_context, + krb5_enctype enctype, + krb5_creds *cred, + Checksum *cksum, + Authenticator **auth_result, + krb5_data *result, + krb5_key_usage usage) +{ + Authenticator *auth; + u_char *buf = NULL; + size_t buf_size; + size_t len; + krb5_error_code ret; + krb5_crypto crypto; + + auth = malloc(sizeof(*auth)); + if (auth == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + memset (auth, 0, sizeof(*auth)); + auth->authenticator_vno = 5; + copy_Realm(&cred->client->realm, &auth->crealm); + copy_PrincipalName(&cred->client->name, &auth->cname); + + krb5_us_timeofday (context, &auth->ctime, &auth->cusec); + + ret = krb5_auth_con_getlocalsubkey(context, auth_context, &auth->subkey); + if(ret) + goto fail; + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + if(auth_context->local_seqnumber == 0) + krb5_generate_seq_number (context, + &cred->session, + &auth_context->local_seqnumber); + ALLOC(auth->seq_number, 1); + if(auth->seq_number == NULL) { + ret = ENOMEM; + goto fail; + } + *auth->seq_number = auth_context->local_seqnumber; + } else + auth->seq_number = NULL; + auth->authorization_data = NULL; + auth->cksum = cksum; + + if (cksum != NULL && cksum->cksumtype == CKSUMTYPE_GSSAPI) { + /* + * This is not GSS-API specific, we only enable it for + * GSS for now + */ + ret = make_etypelist(context, &auth->authorization_data); + if (ret) + goto fail; + } + + /* XXX - Copy more to auth_context? */ + + if (auth_context) { + auth_context->authenticator->ctime = auth->ctime; + auth_context->authenticator->cusec = auth->cusec; + } + + ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, auth, &len, ret); + if (ret) + goto fail; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_crypto_init(context, &cred->session, enctype, &crypto); + if (ret) + goto fail; + ret = krb5_encrypt (context, + crypto, + usage /* KRB5_KU_AP_REQ_AUTH */, + buf + buf_size - len, + len, + result); + krb5_crypto_destroy(context, crypto); + + if (ret) + goto fail; + + free (buf); + + if (auth_result) + *auth_result = auth; + else { + /* Don't free the `cksum', it's allocated by the caller */ + auth->cksum = NULL; + free_Authenticator (auth); + free (auth); + } + return ret; + fail: + free_Authenticator (auth); + free (auth); + free (buf); + return ret; +} diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c new file mode 100644 index 0000000000..f293a96ed9 --- /dev/null +++ b/source4/heimdal/lib/krb5/cache.c @@ -0,0 +1,657 @@ +/* + * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: cache.c,v 1.71 2005/06/16 20:19:57 lha Exp $"); + +/* + * Add a new ccache type with operations `ops', overwriting any + * existing one if `override'. + * Return an error code or 0. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_register(krb5_context context, + const krb5_cc_ops *ops, + krb5_boolean override) +{ + int i; + + for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) { + if(strcmp(context->cc_ops[i].prefix, ops->prefix) == 0) { + if(!override) { + krb5_set_error_string(context, + "ccache type %s already exists", + ops->prefix); + return KRB5_CC_TYPE_EXISTS; + } + break; + } + } + if(i == context->num_cc_ops) { + krb5_cc_ops *o = realloc(context->cc_ops, + (context->num_cc_ops + 1) * + sizeof(*context->cc_ops)); + if(o == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + context->num_cc_ops++; + context->cc_ops = o; + memset(context->cc_ops + i, 0, + (context->num_cc_ops - i) * sizeof(*context->cc_ops)); + } + memcpy(&context->cc_ops[i], ops, sizeof(context->cc_ops[i])); + return 0; +} + +/* + * Allocate memory for a new ccache in `id' with operations `ops' + * and name `residual'. + * Return 0 or an error code. + */ + +static krb5_error_code +allocate_ccache (krb5_context context, + const krb5_cc_ops *ops, + const char *residual, + krb5_ccache *id) +{ + krb5_error_code ret; + krb5_ccache p; + + p = malloc(sizeof(*p)); + if(p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + p->ops = ops; + *id = p; + ret = p->ops->resolve(context, id, residual); + if(ret) + free(p); + return ret; +} + +/* + * Find and allocate a ccache in `id' from the specification in `residual'. + * If the ccache name doesn't contain any colon, interpret it as a file name. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_resolve(krb5_context context, + const char *name, + krb5_ccache *id) +{ + int i; + + for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) { + size_t prefix_len = strlen(context->cc_ops[i].prefix); + + if(strncmp(context->cc_ops[i].prefix, name, prefix_len) == 0 + && name[prefix_len] == ':') { + return allocate_ccache (context, &context->cc_ops[i], + name + prefix_len + 1, + id); + } + } + if (strchr (name, ':') == NULL) + return allocate_ccache (context, &krb5_fcc_ops, name, id); + else { + krb5_set_error_string(context, "unknown ccache type %s", name); + return KRB5_CC_UNKNOWN_TYPE; + } +} + +/* + * Generate a new ccache of type `ops' in `id'. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_gen_new(krb5_context context, + const krb5_cc_ops *ops, + krb5_ccache *id) +{ + krb5_ccache p; + + p = malloc (sizeof(*p)); + if (p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + p->ops = ops; + *id = p; + return p->ops->gen_new(context, id); +} + +/* + * Generates a new unique ccache of `type` in `id'. If `type' is NULL, + * the library chooses the default credential cache type. The supplied + * `hint' (that can be NULL) is a string that the credential cache + * type can use to base the name of the credential on, this is to make + * its easier for the user to differentiate the credentials. + * + * Returns 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_new_unique(krb5_context context, const char *type, + const char *hint, krb5_ccache *id) +{ + const krb5_cc_ops *ops; + + if (type == NULL) + type = "FILE"; + + ops = krb5_cc_get_prefix_ops(context, type); + if (ops == NULL) { + krb5_set_error_string(context, "Credential cache type %s is unknown", + type); + return KRB5_CC_UNKNOWN_TYPE; + } + + return krb5_cc_gen_new(context, ops, id); +} + +/* + * Return the name of the ccache `id' + */ + +const char* KRB5_LIB_FUNCTION +krb5_cc_get_name(krb5_context context, + krb5_ccache id) +{ + return id->ops->get_name(context, id); +} + +/* + * Return the type of the ccache `id'. + */ + +const char* KRB5_LIB_FUNCTION +krb5_cc_get_type(krb5_context context, + krb5_ccache id) +{ + return id->ops->prefix; +} + +/* + * Return krb5_cc_ops of a the ccache `id'. + */ + +const krb5_cc_ops * +krb5_cc_get_ops(krb5_context context, krb5_ccache id) +{ + return id->ops; +} + +/* + * Expand variables in `str' into `res' + */ + +krb5_error_code +_krb5_expand_default_cc_name(krb5_context context, const char *str, char **res) +{ + size_t tlen, len = 0; + char *tmp, *tmp2, *append; + + *res = NULL; + + while (str && *str) { + tmp = strstr(str, "%{"); + if (tmp && tmp != str) { + append = malloc((tmp - str) + 1); + if (append) { + memcpy(append, str, tmp - str); + append[tmp - str] = '\0'; + } + str = tmp; + } else if (tmp) { + tmp2 = strchr(tmp, '}'); + if (tmp2 == NULL) { + free(*res); + *res = NULL; + krb5_set_error_string(context, "variable missing }"); + return KRB5_CONFIG_BADFORMAT; + } + if (strncasecmp(tmp, "%{uid}", 6) == 0) + asprintf(&append, "%u", (unsigned)getuid()); + else if (strncasecmp(tmp, "%{null}", 7) == 0) + append = strdup(""); + else { + free(*res); + *res = NULL; + krb5_set_error_string(context, + "expand default cache unknown " + "variable \"%.*s\"", + (int)(tmp2 - tmp) - 2, tmp + 2); + return KRB5_CONFIG_BADFORMAT; + } + str = tmp2 + 1; + } else { + append = strdup(str); + str = NULL; + } + if (append == NULL) { + free(*res); + res = NULL; + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + tlen = strlen(append); + tmp = realloc(*res, len + tlen + 1); + if (tmp == NULL) { + free(*res); + *res = NULL; + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + *res = tmp; + memcpy(*res + len, append, tlen + 1); + len = len + tlen; + free(append); + } + return 0; +} + +/* + * Set the default cc name for `context' to `name'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_set_default_name(krb5_context context, const char *name) +{ + krb5_error_code ret = 0; + char *p; + + if (name == NULL) { + const char *e = NULL; + + if(!issuid()) { + e = getenv("KRB5CCNAME"); + if (e) + p = strdup(e); + } + if (e == NULL) { + e = krb5_config_get_string(context, NULL, "libdefaults", + "default_cc_name", NULL); + if (e) { + ret = _krb5_expand_default_cc_name(context, e, &p); + if (ret) + return ret; + } + } + if (e == NULL) + asprintf(&p,"FILE:/tmp/krb5cc_%u", (unsigned)getuid()); + } else + p = strdup(name); + + if (p == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + if (context->default_cc_name) + free(context->default_cc_name); + + context->default_cc_name = p; + + return ret; +} + +/* + * Return a pointer to a context static string containing the default + * ccache name. + */ + +const char* KRB5_LIB_FUNCTION +krb5_cc_default_name(krb5_context context) +{ + if (context->default_cc_name == NULL) + krb5_cc_set_default_name(context, NULL); + + return context->default_cc_name; +} + +/* + * Open the default ccache in `id'. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_default(krb5_context context, + krb5_ccache *id) +{ + const char *p = krb5_cc_default_name(context); + + if (p == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + return krb5_cc_resolve(context, p, id); +} + +/* + * Create a new ccache in `id' for `primary_principal'. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_initialize(krb5_context context, + krb5_ccache id, + krb5_principal primary_principal) +{ + return id->ops->init(context, id, primary_principal); +} + + +/* + * Remove the ccache `id'. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_destroy(krb5_context context, + krb5_ccache id) +{ + krb5_error_code ret; + + ret = id->ops->destroy(context, id); + krb5_cc_close (context, id); + return ret; +} + +/* + * Stop using the ccache `id' and free the related resources. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_close(krb5_context context, + krb5_ccache id) +{ + krb5_error_code ret; + ret = id->ops->close(context, id); + free(id); + return ret; +} + +/* + * Store `creds' in the ccache `id'. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_store_cred(krb5_context context, + krb5_ccache id, + krb5_creds *creds) +{ + return id->ops->store(context, id, creds); +} + +/* + * Retrieve the credential identified by `mcreds' (and `whichfields') + * from `id' in `creds'. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_retrieve_cred(krb5_context context, + krb5_ccache id, + krb5_flags whichfields, + const krb5_creds *mcreds, + krb5_creds *creds) +{ + krb5_error_code ret; + krb5_cc_cursor cursor; + + if (id->ops->retrieve != NULL) { + return id->ops->retrieve(context, id, whichfields, + mcreds, creds); + } + + krb5_cc_start_seq_get(context, id, &cursor); + while((ret = krb5_cc_next_cred(context, id, &cursor, creds)) == 0){ + if(krb5_compare_creds(context, whichfields, mcreds, creds)){ + ret = 0; + break; + } + krb5_free_cred_contents (context, creds); + } + krb5_cc_end_seq_get(context, id, &cursor); + return ret; +} + +/* + * Return the principal of `id' in `principal'. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_principal(krb5_context context, + krb5_ccache id, + krb5_principal *principal) +{ + return id->ops->get_princ(context, id, principal); +} + +/* + * Start iterating over `id', `cursor' is initialized to the + * beginning. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_start_seq_get (krb5_context context, + const krb5_ccache id, + krb5_cc_cursor *cursor) +{ + return id->ops->get_first(context, id, cursor); +} + +/* + * Retrieve the next cred pointed to by (`id', `cursor') in `creds' + * and advance `cursor'. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_next_cred (krb5_context context, + const krb5_ccache id, + krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + return id->ops->get_next(context, id, cursor, creds); +} + +/* like krb5_cc_next_cred, but allow for selective retrieval */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_next_cred_match(krb5_context context, + const krb5_ccache id, + krb5_cc_cursor * cursor, + krb5_creds * creds, + krb5_flags whichfields, + const krb5_creds * mcreds) +{ + krb5_error_code ret; + while (1) { + ret = krb5_cc_next_cred(context, id, cursor, creds); + if (ret) + return ret; + if (mcreds == NULL || krb5_compare_creds(context, whichfields, mcreds, creds)) + return 0; + krb5_free_cred_contents(context, creds); + } +} + +/* + * Destroy the cursor `cursor'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_end_seq_get (krb5_context context, + const krb5_ccache id, + krb5_cc_cursor *cursor) +{ + return id->ops->end_get(context, id, cursor); +} + +/* + * Remove the credential identified by `cred', `which' from `id'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_remove_cred(krb5_context context, + krb5_ccache id, + krb5_flags which, + krb5_creds *cred) +{ + if(id->ops->remove_cred == NULL) { + krb5_set_error_string(context, + "ccache %s does not support remove_cred", + id->ops->prefix); + return EACCES; /* XXX */ + } + return (*id->ops->remove_cred)(context, id, which, cred); +} + +/* + * Set the flags of `id' to `flags'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_set_flags(krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ + return id->ops->set_flags(context, id, flags); +} + +/* + * Copy the contents of `from' to `to'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_copy_cache_match(krb5_context context, + const krb5_ccache from, + krb5_ccache to, + krb5_flags whichfields, + const krb5_creds * mcreds, + unsigned int *matched) +{ + krb5_error_code ret; + krb5_cc_cursor cursor; + krb5_creds cred; + krb5_principal princ; + + ret = krb5_cc_get_principal(context, from, &princ); + if (ret) + return ret; + ret = krb5_cc_initialize(context, to, princ); + if (ret) { + krb5_free_principal(context, princ); + return ret; + } + ret = krb5_cc_start_seq_get(context, from, &cursor); + if (ret) { + krb5_free_principal(context, princ); + return ret; + } + if (matched) + *matched = 0; + while (ret == 0 && + krb5_cc_next_cred_match(context, from, &cursor, &cred, + whichfields, mcreds) == 0) { + if (matched) + (*matched)++; + ret = krb5_cc_store_cred(context, to, &cred); + krb5_free_cred_contents(context, &cred); + } + krb5_cc_end_seq_get(context, from, &cursor); + krb5_free_principal(context, princ); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_copy_cache(krb5_context context, + const krb5_ccache from, + krb5_ccache to) +{ + return krb5_cc_copy_cache_match(context, from, to, 0, NULL, NULL); +} + +/* + * Return the version of `id'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_version(krb5_context context, + const krb5_ccache id) +{ + if(id->ops->get_version) + return id->ops->get_version(context, id); + else + return 0; +} + +/* + * Clear `mcreds' so it can be used with krb5_cc_retrieve_cred + */ + +void KRB5_LIB_FUNCTION +krb5_cc_clear_mcred(krb5_creds *mcred) +{ + memset(mcred, 0, sizeof(*mcred)); +} + +/* + * Get the cc ops that is registered in `context' to handle the + * `prefix'. Returns NULL if ops not found. + */ + +const krb5_cc_ops * +krb5_cc_get_prefix_ops(krb5_context context, const char *prefix) +{ + int i; + + for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) { + if(strcmp(context->cc_ops[i].prefix, prefix) == 0) + return &context->cc_ops[i]; + } + return NULL; +} diff --git a/source4/heimdal/lib/krb5/changepw.c b/source4/heimdal/lib/krb5/changepw.c new file mode 100644 index 0000000000..e6ef1d9d9b --- /dev/null +++ b/source4/heimdal/lib/krb5/changepw.c @@ -0,0 +1,816 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: changepw.c,v 1.53 2005/05/25 05:30:42 lha Exp $"); + +static void +str2data (krb5_data *d, + const char *fmt, + ...) __attribute__ ((format (printf, 2, 3))); + +static void +str2data (krb5_data *d, + const char *fmt, + ...) +{ + va_list args; + + va_start(args, fmt); + d->length = vasprintf ((char **)&d->data, fmt, args); + va_end(args); +} + +/* + * Change password protocol defined by + * draft-ietf-cat-kerb-chg-password-02.txt + * + * Share the response part of the protocol with MS set password + * (RFC3244) + */ + +static krb5_error_code +chgpw_send_request (krb5_context context, + krb5_auth_context *auth_context, + krb5_creds *creds, + krb5_principal targprinc, + int is_stream, + int sock, + char *passwd, + const char *host) +{ + krb5_error_code ret; + krb5_data ap_req_data; + krb5_data krb_priv_data; + krb5_data passwd_data; + size_t len; + u_char header[6]; + u_char *p; + struct iovec iov[3]; + struct msghdr msghdr; + + if (is_stream) + return KRB5_KPASSWD_MALFORMED; + + if (targprinc && + krb5_principal_compare(context, creds->client, targprinc) != TRUE) + return KRB5_KPASSWD_MALFORMED; + + krb5_data_zero (&ap_req_data); + + ret = krb5_mk_req_extended (context, + auth_context, + AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY, + NULL, /* in_data */ + creds, + &ap_req_data); + if (ret) + return ret; + + passwd_data.data = passwd; + passwd_data.length = strlen(passwd); + + krb5_data_zero (&krb_priv_data); + + ret = krb5_mk_priv (context, + *auth_context, + &passwd_data, + &krb_priv_data, + NULL); + if (ret) + goto out2; + + len = 6 + ap_req_data.length + krb_priv_data.length; + p = header; + *p++ = (len >> 8) & 0xFF; + *p++ = (len >> 0) & 0xFF; + *p++ = 0; + *p++ = 1; + *p++ = (ap_req_data.length >> 8) & 0xFF; + *p++ = (ap_req_data.length >> 0) & 0xFF; + + memset(&msghdr, 0, sizeof(msghdr)); + msghdr.msg_name = NULL; + msghdr.msg_namelen = 0; + msghdr.msg_iov = iov; + msghdr.msg_iovlen = sizeof(iov)/sizeof(*iov); +#if 0 + msghdr.msg_control = NULL; + msghdr.msg_controllen = 0; +#endif + + iov[0].iov_base = (void*)header; + iov[0].iov_len = 6; + iov[1].iov_base = ap_req_data.data; + iov[1].iov_len = ap_req_data.length; + iov[2].iov_base = krb_priv_data.data; + iov[2].iov_len = krb_priv_data.length; + + if (sendmsg (sock, &msghdr, 0) < 0) { + ret = errno; + krb5_set_error_string(context, "sendmsg %s: %s", host, strerror(ret)); + } + + krb5_data_free (&krb_priv_data); +out2: + krb5_data_free (&ap_req_data); + return ret; +} + +/* + * Set password protocol as defined by RFC3244 -- + * Microsoft Windows 2000 Kerberos Change Password and Set Password Protocols + */ + +static krb5_error_code +setpw_send_request (krb5_context context, + krb5_auth_context *auth_context, + krb5_creds *creds, + krb5_principal targprinc, + int is_stream, + int sock, + char *passwd, + const char *host) +{ + krb5_error_code ret; + krb5_data ap_req_data; + krb5_data krb_priv_data; + krb5_data pwd_data; + ChangePasswdDataMS chpw; + size_t len; + u_char header[4 + 6]; + u_char *p; + struct iovec iov[3]; + struct msghdr msghdr; + + krb5_data_zero (&ap_req_data); + + ret = krb5_mk_req_extended (context, + auth_context, + AP_OPTS_MUTUAL_REQUIRED | AP_OPTS_USE_SUBKEY, + NULL, /* in_data */ + creds, + &ap_req_data); + if (ret) + return ret; + + chpw.newpasswd.length = strlen(passwd); + chpw.newpasswd.data = passwd; + if (targprinc) { + chpw.targname = &targprinc->name; + chpw.targrealm = &targprinc->realm; + } else { + chpw.targname = NULL; + chpw.targrealm = NULL; + } + + ASN1_MALLOC_ENCODE(ChangePasswdDataMS, pwd_data.data, pwd_data.length, + &chpw, &len, ret); + if (ret) { + krb5_data_free (&ap_req_data); + return ret; + } + + if(pwd_data.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_mk_priv (context, + *auth_context, + &pwd_data, + &krb_priv_data, + NULL); + if (ret) + goto out2; + + len = 6 + ap_req_data.length + krb_priv_data.length; + p = header; + if (is_stream) { + _krb5_put_int(p, len, 4); + p += 4; + } + *p++ = (len >> 8) & 0xFF; + *p++ = (len >> 0) & 0xFF; + *p++ = 0xff; + *p++ = 0x80; + *p++ = (ap_req_data.length >> 8) & 0xFF; + *p++ = (ap_req_data.length >> 0) & 0xFF; + + memset(&msghdr, 0, sizeof(msghdr)); + msghdr.msg_name = NULL; + msghdr.msg_namelen = 0; + msghdr.msg_iov = iov; + msghdr.msg_iovlen = sizeof(iov)/sizeof(*iov); +#if 0 + msghdr.msg_control = NULL; + msghdr.msg_controllen = 0; +#endif + + iov[0].iov_base = (void*)header; + if (is_stream) + iov[0].iov_len = 10; + else + iov[0].iov_len = 6; + iov[1].iov_base = ap_req_data.data; + iov[1].iov_len = ap_req_data.length; + iov[2].iov_base = krb_priv_data.data; + iov[2].iov_len = krb_priv_data.length; + + if (sendmsg (sock, &msghdr, 0) < 0) { + ret = errno; + krb5_set_error_string(context, "sendmsg %s: %s", host, strerror(ret)); + } + + krb5_data_free (&krb_priv_data); +out2: + krb5_data_free (&ap_req_data); + krb5_data_free (&pwd_data); + return ret; +} + +static krb5_error_code +process_reply (krb5_context context, + krb5_auth_context auth_context, + int is_stream, + int sock, + int *result_code, + krb5_data *result_code_string, + krb5_data *result_string, + const char *host) +{ + krb5_error_code ret; + u_char reply[1024 * 3]; + ssize_t len; + u_int16_t pkt_len, pkt_ver; + krb5_data ap_rep_data; + int save_errno; + + len = 0; + if (is_stream) { + while (len < sizeof(reply)) { + unsigned long size; + + ret = recvfrom (sock, reply + len, sizeof(reply) - len, + 0, NULL, NULL); + if (ret < 0) { + save_errno = errno; + krb5_set_error_string(context, "recvfrom %s: %s", + host, strerror(save_errno)); + return save_errno; + } else if (ret == 0) { + krb5_set_error_string(context, "recvfrom timeout %s", host); + return 1; + } + len += ret; + if (len < 4) + continue; + _krb5_get_int(reply, &size, 4); + if (size + 4 < len) + continue; + memmove(reply, reply + 4, size); + len = size; + break; + } + if (len == sizeof(reply)) { + krb5_set_error_string(context, "message too large from %s", + host); + return ENOMEM; + } + } else { + ret = recvfrom (sock, reply, sizeof(reply), 0, NULL, NULL); + if (ret < 0) { + save_errno = errno; + krb5_set_error_string(context, "recvfrom %s: %s", + host, strerror(save_errno)); + return save_errno; + } + len = ret; + } + + if (len < 6) { + str2data (result_string, "server %s sent to too short message " + "(%ld bytes)", host, (long)len); + *result_code = KRB5_KPASSWD_MALFORMED; + return 0; + } + + pkt_len = (reply[0] << 8) | (reply[1]); + pkt_ver = (reply[2] << 8) | (reply[3]); + + if ((pkt_len != len) || (reply[1] == 0x7e || reply[1] == 0x5e)) { + KRB_ERROR error; + size_t size; + u_char *p; + + memset(&error, 0, sizeof(error)); + + ret = decode_KRB_ERROR(reply, len, &error, &size); + if (ret) + return ret; + + if (error.e_data->length < 2) { + str2data(result_string, "server %s sent too short " + "e_data to print anything usable", host); + free_KRB_ERROR(&error); + *result_code = KRB5_KPASSWD_MALFORMED; + return 0; + } + + p = error.e_data->data; + *result_code = (p[0] << 8) | p[1]; + if (error.e_data->length == 2) + str2data(result_string, "server only sent error code"); + else + krb5_data_copy (result_string, + p + 2, + error.e_data->length - 2); + free_KRB_ERROR(&error); + return 0; + } + + if (pkt_len != len) { + str2data (result_string, "client: wrong len in reply"); + *result_code = KRB5_KPASSWD_MALFORMED; + return 0; + } + if (pkt_ver != KRB5_KPASSWD_VERS_CHANGEPW) { + str2data (result_string, + "client: wrong version number (%d)", pkt_ver); + *result_code = KRB5_KPASSWD_MALFORMED; + return 0; + } + + ap_rep_data.data = reply + 6; + ap_rep_data.length = (reply[4] << 8) | (reply[5]); + + if (reply + len < (u_char *)ap_rep_data.data + ap_rep_data.length) { + str2data (result_string, "client: wrong AP len in reply"); + *result_code = KRB5_KPASSWD_MALFORMED; + return 0; + } + + if (ap_rep_data.length) { + krb5_ap_rep_enc_part *ap_rep; + krb5_data priv_data; + u_char *p; + + priv_data.data = (u_char*)ap_rep_data.data + ap_rep_data.length; + priv_data.length = len - ap_rep_data.length - 6; + + ret = krb5_rd_rep (context, + auth_context, + &ap_rep_data, + &ap_rep); + if (ret) + return ret; + + krb5_free_ap_rep_enc_part (context, ap_rep); + + ret = krb5_rd_priv (context, + auth_context, + &priv_data, + result_code_string, + NULL); + if (ret) { + krb5_data_free (result_code_string); + return ret; + } + + if (result_code_string->length < 2) { + *result_code = KRB5_KPASSWD_MALFORMED; + str2data (result_string, + "client: bad length in result"); + return 0; + } + + p = result_code_string->data; + + *result_code = (p[0] << 8) | p[1]; + krb5_data_copy (result_string, + (unsigned char*)result_code_string->data + 2, + result_code_string->length - 2); + return 0; + } else { + KRB_ERROR error; + size_t size; + u_char *p; + + ret = decode_KRB_ERROR(reply + 6, len - 6, &error, &size); + if (ret) { + return ret; + } + if (error.e_data->length < 2) { + krb5_warnx (context, "too short e_data to print anything usable"); + return 1; /* XXX */ + } + + p = error.e_data->data; + *result_code = (p[0] << 8) | p[1]; + krb5_data_copy (result_string, + p + 2, + error.e_data->length - 2); + return 0; + } +} + + +/* + * change the password using the credentials in `creds' (for the + * principal indicated in them) to `newpw', storing the result of + * the operation in `result_*' and an error code or 0. + */ + +typedef krb5_error_code (*kpwd_send_request) (krb5_context, + krb5_auth_context *, + krb5_creds *, + krb5_principal, + int, + int, + char *, + const char *); +typedef krb5_error_code (*kpwd_process_reply) (krb5_context, + krb5_auth_context, + int, + int, + int *, + krb5_data *, + krb5_data *, + const char *); + +static struct kpwd_proc { + const char *name; + int flags; +#define SUPPORT_TCP 1 +#define SUPPORT_UDP 2 + kpwd_send_request send_req; + kpwd_process_reply process_rep; +} procs[] = { + { + "MS set password", + SUPPORT_TCP|SUPPORT_UDP, + setpw_send_request, + process_reply + }, + { + "change password", + SUPPORT_UDP, + chgpw_send_request, + process_reply + }, + { NULL } +}; + +static struct kpwd_proc * +find_chpw_proto(const char *name) +{ + struct kpwd_proc *p; + for (p = procs; p->name != NULL; p++) { + if (strcmp(p->name, name) == 0) + return p; + } + return NULL; +} + +/* + * + */ + +static krb5_error_code +change_password_loop (krb5_context context, + krb5_creds *creds, + krb5_principal targprinc, + char *newpw, + int *result_code, + krb5_data *result_code_string, + krb5_data *result_string, + struct kpwd_proc *proc) +{ + krb5_error_code ret; + krb5_auth_context auth_context = NULL; + krb5_krbhst_handle handle = NULL; + krb5_krbhst_info *hi; + int sock; + int i; + int done = 0; + krb5_realm realm = creds->client->realm; + + ret = krb5_auth_con_init (context, &auth_context); + if (ret) + return ret; + + krb5_auth_con_setflags (context, auth_context, + KRB5_AUTH_CONTEXT_DO_SEQUENCE); + + ret = krb5_krbhst_init (context, realm, KRB5_KRBHST_CHANGEPW, &handle); + if (ret) + goto out; + + while (!done && (ret = krb5_krbhst_next(context, handle, &hi)) == 0) { + struct addrinfo *ai, *a; + int is_stream; + + switch (hi->proto) { + case KRB5_KRBHST_UDP: + if ((proc->flags & SUPPORT_UDP) == 0) + continue; + is_stream = 0; + break; + case KRB5_KRBHST_TCP: + if ((proc->flags & SUPPORT_TCP) == 0) + continue; + is_stream = 1; + break; + default: + continue; + } + + ret = krb5_krbhst_get_addrinfo(context, hi, &ai); + if (ret) + continue; + + for (a = ai; !done && a != NULL; a = a->ai_next) { + int replied = 0; + + sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol); + if (sock < 0) + continue; + + ret = connect(sock, a->ai_addr, a->ai_addrlen); + if (ret < 0) { + close (sock); + goto out; + } + + ret = krb5_auth_con_genaddrs (context, auth_context, sock, + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR); + if (ret) { + close (sock); + goto out; + } + + for (i = 0; !done && i < 5; ++i) { + fd_set fdset; + struct timeval tv; + + if (!replied) { + replied = 0; + + ret = (*proc->send_req) (context, + &auth_context, + creds, + targprinc, + is_stream, + sock, + newpw, + hi->hostname); + if (ret) { + close(sock); + goto out; + } + } + + if (sock >= FD_SETSIZE) { + krb5_set_error_string(context, "fd %d too large", sock); + ret = ERANGE; + close (sock); + goto out; + } + + FD_ZERO(&fdset); + FD_SET(sock, &fdset); + tv.tv_usec = 0; + tv.tv_sec = 1 + (1 << i); + + ret = select (sock + 1, &fdset, NULL, NULL, &tv); + if (ret < 0 && errno != EINTR) { + close(sock); + goto out; + } + if (ret == 1) { + ret = (*proc->process_rep) (context, + auth_context, + is_stream, + sock, + result_code, + result_code_string, + result_string, + hi->hostname); + if (ret == 0) + done = 1; + else if (i > 0 && ret == KRB5KRB_AP_ERR_MUT_FAIL) + replied = 1; + } else { + ret = KRB5_KDC_UNREACH; + } + } + close (sock); + } + } + + out: + krb5_krbhst_free (context, handle); + krb5_auth_con_free (context, auth_context); + if (done) + return 0; + else { + if (ret == KRB5_KDC_UNREACH) { + krb5_set_error_string(context, + "unable to reach any changepw server " + " in realm %s", realm); + *result_code = KRB5_KPASSWD_HARDERROR; + } + return ret; + } +} + + +/* + * change the password using the credentials in `creds' (for the + * principal indicated in them) to `newpw', storing the result of + * the operation in `result_*' and an error code or 0. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_change_password (krb5_context context, + krb5_creds *creds, + char *newpw, + int *result_code, + krb5_data *result_code_string, + krb5_data *result_string) +{ + struct kpwd_proc *p = find_chpw_proto("change password"); + + *result_code = KRB5_KPASSWD_MALFORMED; + result_code_string->data = result_string->data = NULL; + result_code_string->length = result_string->length = 0; + + if (p == NULL) + return KRB5_KPASSWD_MALFORMED; + + return change_password_loop(context, creds, NULL, newpw, + result_code, result_code_string, + result_string, p); +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_password(krb5_context context, + krb5_creds *creds, + char *newpw, + krb5_principal targprinc, + int *result_code, + krb5_data *result_code_string, + krb5_data *result_string) +{ + krb5_principal principal = NULL; + krb5_error_code ret = 0; + int i; + + *result_code = KRB5_KPASSWD_MALFORMED; + result_code_string->data = result_string->data = NULL; + result_code_string->length = result_string->length = 0; + + if (targprinc == NULL) { + ret = krb5_get_default_principal(context, &principal); + if (ret) + return ret; + } else + principal = targprinc; + + for (i = 0; procs[i].name != NULL; i++) { + *result_code = 0; + ret = change_password_loop(context, creds, targprinc, newpw, + result_code, result_code_string, + result_string, + &procs[i]); + if (ret == 0 && *result_code == 0) + break; + } + + if (targprinc == NULL) + krb5_free_principal(context, principal); + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_password_using_ccache(krb5_context context, + krb5_ccache ccache, + char *newpw, + krb5_principal targprinc, + int *result_code, + krb5_data *result_code_string, + krb5_data *result_string) +{ + krb5_creds creds, *credsp; + krb5_error_code ret; + krb5_principal principal = NULL; + + *result_code = KRB5_KPASSWD_MALFORMED; + result_code_string->data = result_string->data = NULL; + result_code_string->length = result_string->length = 0; + + memset(&creds, 0, sizeof(creds)); + + if (targprinc == NULL) { + ret = krb5_cc_get_principal(context, ccache, &principal); + if (ret) + return ret; + } else + principal = targprinc; + + ret = krb5_make_principal(context, &creds.server, + krb5_principal_get_realm(context, principal), + "kadmin", "changepw", NULL); + if (ret) + goto out; + + ret = krb5_cc_get_principal(context, ccache, &creds.client); + if (ret) { + krb5_free_principal(context, creds.server); + goto out; + } + + ret = krb5_get_credentials(context, 0, ccache, &creds, &credsp); + krb5_free_principal(context, creds.server); + krb5_free_principal(context, creds.client); + if (ret) + goto out; + + ret = krb5_set_password(context, + credsp, + newpw, + principal, + result_code, + result_code_string, + result_string); + + krb5_free_creds(context, credsp); + + return ret; + out: + if (targprinc == NULL) + krb5_free_principal(context, principal); + return ret; +} + +/* + * + */ + +const char* KRB5_LIB_FUNCTION +krb5_passwd_result_to_string (krb5_context context, + int result) +{ + static const char *strings[] = { + "Success", + "Malformed", + "Hard error", + "Auth error", + "Soft error" , + "Access denied", + "Bad version", + "Initial flag needed" + }; + + if (result < 0 || result > KRB5_KPASSWD_INITIAL_FLAG_NEEDED) + return "unknown result code"; + else + return strings[result]; +} diff --git a/source4/heimdal/lib/krb5/codec.c b/source4/heimdal/lib/krb5/codec.c new file mode 100644 index 0000000000..080e8a6511 --- /dev/null +++ b/source4/heimdal/lib/krb5/codec.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 1998 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: codec.c,v 1.9 2004/05/25 21:19:37 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncTicketPart (krb5_context context, + const void *data, + size_t length, + EncTicketPart *t, + size_t *len) +{ + return decode_EncTicketPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncTicketPart (krb5_context context, + void *data, + size_t length, + EncTicketPart *t, + size_t *len) +{ + return encode_EncTicketPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncASRepPart (krb5_context context, + const void *data, + size_t length, + EncASRepPart *t, + size_t *len) +{ + return decode_EncASRepPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncASRepPart (krb5_context context, + void *data, + size_t length, + EncASRepPart *t, + size_t *len) +{ + return encode_EncASRepPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncTGSRepPart (krb5_context context, + const void *data, + size_t length, + EncTGSRepPart *t, + size_t *len) +{ + return decode_EncTGSRepPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncTGSRepPart (krb5_context context, + void *data, + size_t length, + EncTGSRepPart *t, + size_t *len) +{ + return encode_EncTGSRepPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncAPRepPart (krb5_context context, + const void *data, + size_t length, + EncAPRepPart *t, + size_t *len) +{ + return decode_EncAPRepPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncAPRepPart (krb5_context context, + void *data, + size_t length, + EncAPRepPart *t, + size_t *len) +{ + return encode_EncAPRepPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_Authenticator (krb5_context context, + const void *data, + size_t length, + Authenticator *t, + size_t *len) +{ + return decode_Authenticator(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_Authenticator (krb5_context context, + void *data, + size_t length, + Authenticator *t, + size_t *len) +{ + return encode_Authenticator(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncKrbCredPart (krb5_context context, + const void *data, + size_t length, + EncKrbCredPart *t, + size_t *len) +{ + return decode_EncKrbCredPart(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncKrbCredPart (krb5_context context, + void *data, + size_t length, + EncKrbCredPart *t, + size_t *len) +{ + return encode_EncKrbCredPart (data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_ETYPE_INFO (krb5_context context, + const void *data, + size_t length, + ETYPE_INFO *t, + size_t *len) +{ + return decode_ETYPE_INFO(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_ETYPE_INFO (krb5_context context, + void *data, + size_t length, + ETYPE_INFO *t, + size_t *len) +{ + return encode_ETYPE_INFO (data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_ETYPE_INFO2 (krb5_context context, + const void *data, + size_t length, + ETYPE_INFO2 *t, + size_t *len) +{ + return decode_ETYPE_INFO2(data, length, t, len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_ETYPE_INFO2 (krb5_context context, + void *data, + size_t length, + ETYPE_INFO2 *t, + size_t *len) +{ + return encode_ETYPE_INFO2 (data, length, t, len); +} diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c new file mode 100644 index 0000000000..86e286c638 --- /dev/null +++ b/source4/heimdal/lib/krb5/config_file.c @@ -0,0 +1,773 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +RCSID("$Id: config_file.c,v 1.53 2005/06/16 20:22:53 lha Exp $"); + +#ifndef HAVE_NETINFO + +/* Gaah! I want a portable funopen */ +struct fileptr { + const char *s; + FILE *f; +}; + +static char * +config_fgets(char *str, size_t len, struct fileptr *ptr) +{ + /* XXX this is not correct, in that they don't do the same if the + line is longer than len */ + if(ptr->f != NULL) + return fgets(str, len, ptr->f); + else { + /* this is almost strsep_copy */ + const char *p; + ssize_t l; + if(*ptr->s == '\0') + return NULL; + p = ptr->s + strcspn(ptr->s, "\n"); + if(*p == '\n') + p++; + l = min(len, p - ptr->s); + if(len > 0) { + memcpy(str, ptr->s, l); + str[l] = '\0'; + } + ptr->s = p; + return str; + } +} + +static krb5_error_code parse_section(char *p, krb5_config_section **s, + krb5_config_section **res, + const char **error_message); +static krb5_error_code parse_binding(struct fileptr *f, unsigned *lineno, char *p, + krb5_config_binding **b, + krb5_config_binding **parent, + const char **error_message); +static krb5_error_code parse_list(struct fileptr *f, unsigned *lineno, + krb5_config_binding **parent, + const char **error_message); + +static krb5_config_section * +get_entry(krb5_config_section **parent, const char *name, int type) +{ + krb5_config_section **q; + + for(q = parent; *q != NULL; q = &(*q)->next) + if(type == krb5_config_list && + type == (*q)->type && + strcmp(name, (*q)->name) == 0) + return *q; + *q = calloc(1, sizeof(**q)); + if(*q == NULL) + return NULL; + (*q)->name = strdup(name); + (*q)->type = type; + if((*q)->name == NULL) { + free(*q); + *q = NULL; + return NULL; + } + return *q; +} + +/* + * Parse a section: + * + * [section] + * foo = bar + * b = { + * a + * } + * ... + * + * starting at the line in `p', storing the resulting structure in + * `s' and hooking it into `parent'. + * Store the error message in `error_message'. + */ + +static krb5_error_code +parse_section(char *p, krb5_config_section **s, krb5_config_section **parent, + const char **error_message) +{ + char *p1; + krb5_config_section *tmp; + + p1 = strchr (p + 1, ']'); + if (p1 == NULL) { + *error_message = "missing ]"; + return KRB5_CONFIG_BADFORMAT; + } + *p1 = '\0'; + tmp = get_entry(parent, p + 1, krb5_config_list); + if(tmp == NULL) { + *error_message = "out of memory"; + return KRB5_CONFIG_BADFORMAT; + } + *s = tmp; + return 0; +} + +/* + * Parse a brace-enclosed list from `f', hooking in the structure at + * `parent'. + * Store the error message in `error_message'. + */ + +static krb5_error_code +parse_list(struct fileptr *f, unsigned *lineno, krb5_config_binding **parent, + const char **error_message) +{ + char buf[BUFSIZ]; + krb5_error_code ret; + krb5_config_binding *b = NULL; + unsigned beg_lineno = *lineno; + + while(config_fgets(buf, sizeof(buf), f) != NULL) { + char *p; + + ++*lineno; + if (buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = '\0'; + p = buf; + while(isspace((unsigned char)*p)) + ++p; + if (*p == '#' || *p == ';' || *p == '\0') + continue; + while(isspace((unsigned char)*p)) + ++p; + if (*p == '}') + return 0; + if (*p == '\0') + continue; + ret = parse_binding (f, lineno, p, &b, parent, error_message); + if (ret) + return ret; + } + *lineno = beg_lineno; + *error_message = "unclosed {"; + return KRB5_CONFIG_BADFORMAT; +} + +/* + * + */ + +static krb5_error_code +parse_binding(struct fileptr *f, unsigned *lineno, char *p, + krb5_config_binding **b, krb5_config_binding **parent, + const char **error_message) +{ + krb5_config_binding *tmp; + char *p1, *p2; + krb5_error_code ret = 0; + + p1 = p; + while (*p && *p != '=' && !isspace((unsigned char)*p)) + ++p; + if (*p == '\0') { + *error_message = "missing ="; + return KRB5_CONFIG_BADFORMAT; + } + p2 = p; + while (isspace((unsigned char)*p)) + ++p; + if (*p != '=') { + *error_message = "missing ="; + return KRB5_CONFIG_BADFORMAT; + } + ++p; + while(isspace((unsigned char)*p)) + ++p; + *p2 = '\0'; + if (*p == '{') { + tmp = get_entry(parent, p1, krb5_config_list); + if (tmp == NULL) { + *error_message = "out of memory"; + return KRB5_CONFIG_BADFORMAT; + } + ret = parse_list (f, lineno, &tmp->u.list, error_message); + } else { + tmp = get_entry(parent, p1, krb5_config_string); + if (tmp == NULL) { + *error_message = "out of memory"; + return KRB5_CONFIG_BADFORMAT; + } + p1 = p; + p = p1 + strlen(p1); + while(p > p1 && isspace((unsigned char)*(p-1))) + --p; + *p = '\0'; + tmp->u.string = strdup(p1); + } + *b = tmp; + return ret; +} + +/* + * Parse the config file `fname', generating the structures into `res' + * returning error messages in `error_message' + */ + +static krb5_error_code +krb5_config_parse_debug (struct fileptr *f, + krb5_config_section **res, + unsigned *lineno, + const char **error_message) +{ + krb5_config_section *s = NULL; + krb5_config_binding *b = NULL; + char buf[BUFSIZ]; + krb5_error_code ret; + + while (config_fgets(buf, sizeof(buf), f) != NULL) { + char *p; + + ++*lineno; + if(buf[strlen(buf) - 1] == '\n') + buf[strlen(buf) - 1] = '\0'; + p = buf; + while(isspace((unsigned char)*p)) + ++p; + if (*p == '#' || *p == ';') + continue; + if (*p == '[') { + ret = parse_section(p, &s, res, error_message); + if (ret) + return ret; + b = NULL; + } else if (*p == '}') { + *error_message = "unmatched }"; + return EINVAL; /* XXX */ + } else if(*p != '\0') { + if (s == NULL) { + *error_message = "binding before section"; + return EINVAL; + } + ret = parse_binding(f, lineno, p, &b, &s->u.list, error_message); + if (ret) + return ret; + } + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_string_multi(krb5_context context, + const char *string, + krb5_config_section **res) +{ + const char *str; + unsigned lineno = 0; + krb5_error_code ret; + struct fileptr f; + f.f = NULL; + f.s = string; + + ret = krb5_config_parse_debug (&f, res, &lineno, &str); + if (ret) { + krb5_set_error_string (context, "%s:%u: %s", "", lineno, str); + return ret; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_file_multi (krb5_context context, + const char *fname, + krb5_config_section **res) +{ + const char *str; + unsigned lineno = 0; + krb5_error_code ret; + struct fileptr f; + f.f = fopen(fname, "r"); + f.s = NULL; + if(f.f == NULL) { + ret = errno; + krb5_set_error_string (context, "open %s: %s", fname, strerror(ret)); + return ret; + } + + ret = krb5_config_parse_debug (&f, res, &lineno, &str); + fclose(f.f); + if (ret) { + krb5_set_error_string (context, "%s:%u: %s", fname, lineno, str); + return ret; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_file (krb5_context context, + const char *fname, + krb5_config_section **res) +{ + *res = NULL; + return krb5_config_parse_file_multi(context, fname, res); +} + +#endif /* !HAVE_NETINFO */ + +static void +free_binding (krb5_context context, krb5_config_binding *b) +{ + krb5_config_binding *next_b; + + while (b) { + free (b->name); + if (b->type == krb5_config_string) + free (b->u.string); + else if (b->type == krb5_config_list) + free_binding (context, b->u.list); + else + krb5_abortx(context, "unknown binding type (%d) in free_binding", + b->type); + next_b = b->next; + free (b); + b = next_b; + } +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_file_free (krb5_context context, krb5_config_section *s) +{ + free_binding (context, s); + return 0; +} + +const void * +krb5_config_get_next (krb5_context context, + const krb5_config_section *c, + const krb5_config_binding **pointer, + int type, + ...) +{ + const char *ret; + va_list args; + + va_start(args, type); + ret = krb5_config_vget_next (context, c, pointer, type, args); + va_end(args); + return ret; +} + +static const void * +vget_next(krb5_context context, + const krb5_config_binding *b, + const krb5_config_binding **pointer, + int type, + const char *name, + va_list args) +{ + const char *p = va_arg(args, const char *); + while(b != NULL) { + if(strcmp(b->name, name) == 0) { + if(b->type == type && p == NULL) { + *pointer = b; + return b->u.generic; + } else if(b->type == krb5_config_list && p != NULL) { + return vget_next(context, b->u.list, pointer, type, p, args); + } + } + b = b->next; + } + return NULL; +} + +const void * +krb5_config_vget_next (krb5_context context, + const krb5_config_section *c, + const krb5_config_binding **pointer, + int type, + va_list args) +{ + const krb5_config_binding *b; + const char *p; + + if(c == NULL) + c = context->cf; + + if (c == NULL) + return NULL; + + if (*pointer == NULL) { + /* first time here, walk down the tree looking for the right + section */ + p = va_arg(args, const char *); + if (p == NULL) + return NULL; + return vget_next(context, c, pointer, type, p, args); + } + + /* we were called again, so just look for more entries with the + same name and type */ + for (b = (*pointer)->next; b != NULL; b = b->next) { + if(strcmp(b->name, (*pointer)->name) == 0 && b->type == type) { + *pointer = b; + return b->u.generic; + } + } + return NULL; +} + +const void * +krb5_config_get (krb5_context context, + const krb5_config_section *c, + int type, + ...) +{ + const void *ret; + va_list args; + + va_start(args, type); + ret = krb5_config_vget (context, c, type, args); + va_end(args); + return ret; +} + +const void * +krb5_config_vget (krb5_context context, + const krb5_config_section *c, + int type, + va_list args) +{ + const krb5_config_binding *foo = NULL; + + return krb5_config_vget_next (context, c, &foo, type, args); +} + +const krb5_config_binding * +krb5_config_get_list (krb5_context context, + const krb5_config_section *c, + ...) +{ + const krb5_config_binding *ret; + va_list args; + + va_start(args, c); + ret = krb5_config_vget_list (context, c, args); + va_end(args); + return ret; +} + +const krb5_config_binding * +krb5_config_vget_list (krb5_context context, + const krb5_config_section *c, + va_list args) +{ + return krb5_config_vget (context, c, krb5_config_list, args); +} + +const char* KRB5_LIB_FUNCTION +krb5_config_get_string (krb5_context context, + const krb5_config_section *c, + ...) +{ + const char *ret; + va_list args; + + va_start(args, c); + ret = krb5_config_vget_string (context, c, args); + va_end(args); + return ret; +} + +const char* KRB5_LIB_FUNCTION +krb5_config_vget_string (krb5_context context, + const krb5_config_section *c, + va_list args) +{ + return krb5_config_vget (context, c, krb5_config_string, args); +} + +const char* KRB5_LIB_FUNCTION +krb5_config_vget_string_default (krb5_context context, + const krb5_config_section *c, + const char *def_value, + va_list args) +{ + const char *ret; + + ret = krb5_config_vget_string (context, c, args); + if (ret == NULL) + ret = def_value; + return ret; +} + +const char* KRB5_LIB_FUNCTION +krb5_config_get_string_default (krb5_context context, + const krb5_config_section *c, + const char *def_value, + ...) +{ + const char *ret; + va_list args; + + va_start(args, def_value); + ret = krb5_config_vget_string_default (context, c, def_value, args); + va_end(args); + return ret; +} + +char ** KRB5_LIB_FUNCTION +krb5_config_vget_strings(krb5_context context, + const krb5_config_section *c, + va_list args) +{ + char **strings = NULL; + int nstr = 0; + const krb5_config_binding *b = NULL; + const char *p; + + while((p = krb5_config_vget_next(context, c, &b, + krb5_config_string, args))) { + char *tmp = strdup(p); + char *pos = NULL; + char *s; + if(tmp == NULL) + goto cleanup; + s = strtok_r(tmp, " \t", &pos); + while(s){ + char **tmp2 = realloc(strings, (nstr + 1) * sizeof(*strings)); + if(tmp2 == NULL) + goto cleanup; + strings = tmp2; + strings[nstr] = strdup(s); + nstr++; + if(strings[nstr-1] == NULL) + goto cleanup; + s = strtok_r(NULL, " \t", &pos); + } + free(tmp); + } + if(nstr){ + char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings)); + if(strings == NULL) + goto cleanup; + strings = tmp; + strings[nstr] = NULL; + } + return strings; +cleanup: + while(nstr--) + free(strings[nstr]); + free(strings); + return NULL; + +} + +char** +krb5_config_get_strings(krb5_context context, + const krb5_config_section *c, + ...) +{ + va_list ap; + char **ret; + va_start(ap, c); + ret = krb5_config_vget_strings(context, c, ap); + va_end(ap); + return ret; +} + +void KRB5_LIB_FUNCTION +krb5_config_free_strings(char **strings) +{ + char **s = strings; + while(s && *s){ + free(*s); + s++; + } + free(strings); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_vget_bool_default (krb5_context context, + const krb5_config_section *c, + krb5_boolean def_value, + va_list args) +{ + const char *str; + str = krb5_config_vget_string (context, c, args); + if(str == NULL) + return def_value; + if(strcasecmp(str, "yes") == 0 || + strcasecmp(str, "true") == 0 || + atoi(str)) return TRUE; + return FALSE; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_vget_bool (krb5_context context, + const krb5_config_section *c, + va_list args) +{ + return krb5_config_vget_bool_default (context, c, FALSE, args); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_get_bool_default (krb5_context context, + const krb5_config_section *c, + krb5_boolean def_value, + ...) +{ + va_list ap; + krb5_boolean ret; + va_start(ap, def_value); + ret = krb5_config_vget_bool_default(context, c, def_value, ap); + va_end(ap); + return ret; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_get_bool (krb5_context context, + const krb5_config_section *c, + ...) +{ + va_list ap; + krb5_boolean ret; + va_start(ap, c); + ret = krb5_config_vget_bool (context, c, ap); + va_end(ap); + return ret; +} + +int KRB5_LIB_FUNCTION +krb5_config_vget_time_default (krb5_context context, + const krb5_config_section *c, + int def_value, + va_list args) +{ + const char *str; + krb5_deltat t; + + str = krb5_config_vget_string (context, c, args); + if(str == NULL) + return def_value; + if (krb5_string_to_deltat(str, &t)) + return def_value; + return t; +} + +int KRB5_LIB_FUNCTION +krb5_config_vget_time (krb5_context context, + const krb5_config_section *c, + va_list args) +{ + return krb5_config_vget_time_default (context, c, -1, args); +} + +int KRB5_LIB_FUNCTION +krb5_config_get_time_default (krb5_context context, + const krb5_config_section *c, + int def_value, + ...) +{ + va_list ap; + int ret; + va_start(ap, def_value); + ret = krb5_config_vget_time_default(context, c, def_value, ap); + va_end(ap); + return ret; +} + +int KRB5_LIB_FUNCTION +krb5_config_get_time (krb5_context context, + const krb5_config_section *c, + ...) +{ + va_list ap; + int ret; + va_start(ap, c); + ret = krb5_config_vget_time (context, c, ap); + va_end(ap); + return ret; +} + + +int KRB5_LIB_FUNCTION +krb5_config_vget_int_default (krb5_context context, + const krb5_config_section *c, + int def_value, + va_list args) +{ + const char *str; + str = krb5_config_vget_string (context, c, args); + if(str == NULL) + return def_value; + else { + char *endptr; + long l; + l = strtol(str, &endptr, 0); + if (endptr == str) + return def_value; + else + return l; + } +} + +int KRB5_LIB_FUNCTION +krb5_config_vget_int (krb5_context context, + const krb5_config_section *c, + va_list args) +{ + return krb5_config_vget_int_default (context, c, -1, args); +} + +int KRB5_LIB_FUNCTION +krb5_config_get_int_default (krb5_context context, + const krb5_config_section *c, + int def_value, + ...) +{ + va_list ap; + int ret; + va_start(ap, def_value); + ret = krb5_config_vget_int_default(context, c, def_value, ap); + va_end(ap); + return ret; +} + +int KRB5_LIB_FUNCTION +krb5_config_get_int (krb5_context context, + const krb5_config_section *c, + ...) +{ + va_list ap; + int ret; + va_start(ap, c); + ret = krb5_config_vget_int (context, c, ap); + va_end(ap); + return ret; +} diff --git a/source4/heimdal/lib/krb5/config_file_netinfo.c b/source4/heimdal/lib/krb5/config_file_netinfo.c new file mode 100644 index 0000000000..6e72509ab6 --- /dev/null +++ b/source4/heimdal/lib/krb5/config_file_netinfo.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +RCSID("$Id: config_file_netinfo.c,v 1.4 2004/05/25 21:20:18 lha Exp $"); + +/* + * Netinfo implementation from Luke Howard + */ + +#ifdef HAVE_NETINFO +#include +static ni_status +ni_proplist2binding(ni_proplist *pl, krb5_config_section **ret) +{ + int i, j; + krb5_config_section **next = NULL; + + for (i = 0; i < pl->ni_proplist_len; i++) { + if (!strcmp(pl->nipl_val[i].nip_name, "name")) + continue; + + for (j = 0; j < pl->nipl_val[i].nip_val.ni_namelist_len; j++) { + krb5_config_binding *b; + + b = malloc(sizeof(*b)); + if (b == NULL) + return NI_FAILED; + + b->next = NULL; + b->type = krb5_config_string; + b->name = ni_name_dup(pl->nipl_val[i].nip_name); + b->u.string = ni_name_dup(pl->nipl_val[i].nip_val.ninl_val[j]); + + if (next == NULL) { + *ret = b; + } else { + *next = b; + } + next = &b->next; + } + } + return NI_OK; +} + +static ni_status +ni_idlist2binding(void *ni, ni_idlist *idlist, krb5_config_section **ret) +{ + int i; + ni_status nis; + krb5_config_section **next; + + for (i = 0; i < idlist->ni_idlist_len; i++) { + ni_proplist pl; + ni_id nid; + ni_idlist children; + krb5_config_binding *b; + ni_index index; + + nid.nii_instance = 0; + nid.nii_object = idlist->ni_idlist_val[i]; + + nis = ni_read(ni, &nid, &pl); + + if (nis != NI_OK) { + return nis; + } + index = ni_proplist_match(pl, "name", NULL); + b = malloc(sizeof(*b)); + if (b == NULL) return NI_FAILED; + + if (i == 0) { + *ret = b; + } else { + *next = b; + } + + b->type = krb5_config_list; + b->name = ni_name_dup(pl.nipl_val[index].nip_val.ninl_val[0]); + b->next = NULL; + b->u.list = NULL; + + /* get the child directories */ + nis = ni_children(ni, &nid, &children); + if (nis == NI_OK) { + nis = ni_idlist2binding(ni, &children, &b->u.list); + if (nis != NI_OK) { + return nis; + } + } + + nis = ni_proplist2binding(&pl, b->u.list == NULL ? &b->u.list : &b->u.list->next); + ni_proplist_free(&pl); + if (nis != NI_OK) { + return nis; + } + next = &b->next; + } + ni_idlist_free(idlist); + return NI_OK; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_file (krb5_context context, + const char *fname, + krb5_config_section **res) +{ + void *ni = NULL, *lastni = NULL; + int i; + ni_status nis; + ni_id nid; + ni_idlist children; + + krb5_config_section *s; + int ret; + + s = NULL; + + for (i = 0; i < 256; i++) { + if (i == 0) { + nis = ni_open(NULL, ".", &ni); + } else { + if (lastni != NULL) ni_free(lastni); + lastni = ni; + nis = ni_open(lastni, "..", &ni); + } + if (nis != NI_OK) + break; + nis = ni_pathsearch(ni, &nid, "/locations/kerberos"); + if (nis == NI_OK) { + nis = ni_children(ni, &nid, &children); + if (nis != NI_OK) + break; + nis = ni_idlist2binding(ni, &children, &s); + break; + } + } + + if (ni != NULL) ni_free(ni); + if (ni != lastni && lastni != NULL) ni_free(lastni); + + ret = (nis == NI_OK) ? 0 : -1; + if (ret == 0) { + *res = s; + } else { + *res = NULL; + } + return ret; +} +#endif /* HAVE_NETINFO */ diff --git a/source4/heimdal/lib/krb5/constants.c b/source4/heimdal/lib/krb5/constants.c new file mode 100644 index 0000000000..89ebc34a1a --- /dev/null +++ b/source4/heimdal/lib/krb5/constants.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: constants.c,v 1.8 2004/09/23 07:57:37 joda Exp $"); + +const char *krb5_config_file = +#ifdef __APPLE__ +"/Library/Preferences/edu.mit.Kerberos:" +#endif +SYSCONFDIR "/krb5.conf:/etc/krb5.conf"; +const char *krb5_defkeyname = KEYTAB_DEFAULT; diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c new file mode 100644 index 0000000000..62fb92d666 --- /dev/null +++ b/source4/heimdal/lib/krb5/context.c @@ -0,0 +1,663 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +#include + +RCSID("$Id: context.c,v 1.102 2005/05/18 04:20:50 lha Exp $"); + +#define INIT_FIELD(C, T, E, D, F) \ + (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ + "libdefaults", F, NULL) + +/* + * Set the list of etypes `ret_etypes' from the configuration variable + * `name' + */ + +static krb5_error_code +set_etypes (krb5_context context, + const char *name, + krb5_enctype **ret_enctypes) +{ + char **etypes_str; + krb5_enctype *etypes = NULL; + + etypes_str = krb5_config_get_strings(context, NULL, "libdefaults", + name, NULL); + if(etypes_str){ + int i, j, k; + for(i = 0; etypes_str[i]; i++); + etypes = malloc((i+1) * sizeof(*etypes)); + if (etypes == NULL) { + krb5_config_free_strings (etypes_str); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + for(j = 0, k = 0; j < i; j++) { + krb5_enctype e; + if(krb5_string_to_enctype(context, etypes_str[j], &e) != 0) + continue; + if (krb5_enctype_valid(context, e) != 0) + continue; + etypes[k++] = e; + } + etypes[k] = ETYPE_NULL; + krb5_config_free_strings(etypes_str); + } + *ret_enctypes = etypes; + return 0; +} + +/* + * read variables from the configuration file and set in `context' + */ + +static krb5_error_code +init_context_from_config_file(krb5_context context) +{ + krb5_error_code ret; + const char * tmp; + krb5_enctype *tmptypes; + + INIT_FIELD(context, time, max_skew, 5 * 60, "clockskew"); + INIT_FIELD(context, time, kdc_timeout, 3, "kdc_timeout"); + INIT_FIELD(context, int, max_retries, 3, "max_retries"); + + INIT_FIELD(context, string, http_proxy, NULL, "http_proxy"); + + ret = set_etypes (context, "default_etypes", &tmptypes); + if(ret) + return ret; + free(context->etypes); + context->etypes = tmptypes; + + ret = set_etypes (context, "default_etypes_des", &tmptypes); + if(ret) + return ret; + free(context->etypes_des); + context->etypes_des = tmptypes; + + /* default keytab name */ + tmp = NULL; + if(!issuid()) + tmp = getenv("KRB5_KTNAME"); + if(tmp != NULL) + context->default_keytab = tmp; + else + INIT_FIELD(context, string, default_keytab, + KEYTAB_DEFAULT, "default_keytab_name"); + + INIT_FIELD(context, string, default_keytab_modify, + NULL, "default_keytab_modify_name"); + + INIT_FIELD(context, string, time_fmt, + "%Y-%m-%dT%H:%M:%S", "time_format"); + + INIT_FIELD(context, string, date_fmt, + "%Y-%m-%d", "date_format"); + + INIT_FIELD(context, bool, log_utc, + FALSE, "log_utc"); + + + + /* init dns-proxy slime */ + tmp = krb5_config_get_string(context, NULL, "libdefaults", + "dns_proxy", NULL); + if(tmp) + roken_gethostby_setup(context->http_proxy, tmp); + krb5_free_host_realm (context, context->default_realms); + context->default_realms = NULL; + + { + krb5_addresses addresses; + char **adr, **a; + + krb5_set_extra_addresses(context, NULL); + adr = krb5_config_get_strings(context, NULL, + "libdefaults", + "extra_addresses", + NULL); + memset(&addresses, 0, sizeof(addresses)); + for(a = adr; a && *a; a++) { + ret = krb5_parse_address(context, *a, &addresses); + if (ret == 0) { + krb5_add_extra_addresses(context, &addresses); + krb5_free_addresses(context, &addresses); + } + } + krb5_config_free_strings(adr); + + krb5_set_ignore_addresses(context, NULL); + adr = krb5_config_get_strings(context, NULL, + "libdefaults", + "ignore_addresses", + NULL); + memset(&addresses, 0, sizeof(addresses)); + for(a = adr; a && *a; a++) { + ret = krb5_parse_address(context, *a, &addresses); + if (ret == 0) { + krb5_add_ignore_addresses(context, &addresses); + krb5_free_addresses(context, &addresses); + } + } + krb5_config_free_strings(adr); + } + + INIT_FIELD(context, bool, scan_interfaces, TRUE, "scan_interfaces"); + INIT_FIELD(context, int, fcache_vno, 0, "fcache_version"); + /* prefer dns_lookup_kdc over srv_lookup. */ + INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup"); + INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc"); + INIT_FIELD(context, int, large_msg_size, 6000, "large_message_size"); + context->default_cc_name = NULL; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_init_context(krb5_context *context) +{ + krb5_context p; + krb5_error_code ret; + char **files; + + *context = NULL; + + p = calloc(1, sizeof(*p)); + if(!p) + return ENOMEM; + + p->mutex = malloc(sizeof(HEIMDAL_MUTEX)); + if (p->mutex == NULL) { + free(p); + return ENOMEM; + } + HEIMDAL_MUTEX_init(p->mutex); + + ret = krb5_get_default_config_files(&files); + if(ret) + goto out; + ret = krb5_set_config_files(p, files); + krb5_free_config_files(files); + if(ret) + goto out; + + /* init error tables */ + krb5_init_ets(p); + + p->cc_ops = NULL; + p->num_cc_ops = 0; + krb5_cc_register(p, &krb5_acc_ops, TRUE); + krb5_cc_register(p, &krb5_fcc_ops, TRUE); + krb5_cc_register(p, &krb5_mcc_ops, TRUE); +#ifdef HAVE_KCM + krb5_cc_register(p, &krb5_kcm_ops, TRUE); +#endif + + p->num_kt_types = 0; + p->kt_types = NULL; + krb5_kt_register (p, &krb5_fkt_ops); + krb5_kt_register (p, &krb5_wrfkt_ops); + krb5_kt_register (p, &krb5_javakt_ops); + krb5_kt_register (p, &krb5_mkt_ops); + krb5_kt_register (p, &krb5_mktw_ops); + krb5_kt_register (p, &krb5_akf_ops); + krb5_kt_register (p, &krb4_fkt_ops); + krb5_kt_register (p, &krb5_srvtab_fkt_ops); + krb5_kt_register (p, &krb5_any_ops); + +out: + if(ret) { + krb5_free_context(p); + p = NULL; + } + *context = p; + return ret; +} + +void KRB5_LIB_FUNCTION +krb5_free_context(krb5_context context) +{ + if (context->default_cc_name) + free(context->default_cc_name); + free(context->etypes); + free(context->etypes_des); + krb5_free_host_realm (context, context->default_realms); + krb5_config_file_free (context, context->cf); + free_error_table (context->et_list); + free(context->cc_ops); + free(context->kt_types); + krb5_clear_error_string(context); + if(context->warn_dest != NULL) + krb5_closelog(context, context->warn_dest); + krb5_set_extra_addresses(context, NULL); + krb5_set_ignore_addresses(context, NULL); + if (context->mutex != NULL) { + HEIMDAL_MUTEX_destroy(context->mutex); + free(context->mutex); + } + memset(context, 0, sizeof(*context)); + free(context); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_config_files(krb5_context context, char **filenames) +{ + krb5_error_code ret; + krb5_config_binding *tmp = NULL; + while(filenames != NULL && *filenames != NULL && **filenames != '\0') { + ret = krb5_config_parse_file_multi(context, *filenames, &tmp); + if(ret != 0 && ret != ENOENT && ret != EACCES) { + krb5_config_file_free(context, tmp); + return ret; + } + filenames++; + } +#if 0 + /* with this enabled and if there are no config files, Kerberos is + considererd disabled */ + if(tmp == NULL) + return ENXIO; +#endif + krb5_config_file_free(context, context->cf); + context->cf = tmp; + ret = init_context_from_config_file(context); + return ret; +} + +static krb5_error_code +add_file(char ***pfilenames, int *len, char *file) +{ + char **pp = *pfilenames; + int i; + + for(i = 0; i < *len; i++) { + if(strcmp(pp[i], file) == 0) { + free(file); + return 0; + } + } + + pp = realloc(*pfilenames, (*len + 2) * sizeof(*pp)); + if (pp == NULL) { + free(file); + return ENOMEM; + } + + pp[*len] = file; + pp[*len + 1] = NULL; + *pfilenames = pp; + *len += 1; + return 0; +} + +/* + * `pq' isn't free, its up the the caller + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_prepend_config_files(const char *filelist, char **pq, char ***ret_pp) +{ + krb5_error_code ret; + const char *p, *q; + char **pp; + int len; + char *fn; + + pp = NULL; + + len = 0; + p = filelist; + while(1) { + ssize_t l; + q = p; + l = strsep_copy(&q, ":", NULL, 0); + if(l == -1) + break; + fn = malloc(l + 1); + if(fn == NULL) { + krb5_free_config_files(pp); + return ENOMEM; + } + l = strsep_copy(&p, ":", fn, l + 1); + ret = add_file(&pp, &len, fn); + if (ret) { + krb5_free_config_files(pp); + return ret; + } + } + + if (pq != NULL) { + int i; + + for (i = 0; pq[i] != NULL; i++) { + fn = strdup(pq[i]); + if (fn == NULL) { + krb5_free_config_files(pp); + return ENOMEM; + } + ret = add_file(&pp, &len, fn); + if (ret) { + krb5_free_config_files(pp); + return ret; + } + } + } + + *ret_pp = pp; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_prepend_config_files_default(const char *filelist, char ***pfilenames) +{ + krb5_error_code ret; + char **defpp, **pp = NULL; + + ret = krb5_get_default_config_files(&defpp); + if (ret) + return ret; + + ret = krb5_prepend_config_files(filelist, defpp, &pp); + krb5_free_config_files(defpp); + if (ret) { + return ret; + } + *pfilenames = pp; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_config_files(char ***pfilenames) +{ + const char *files = NULL; + + if (pfilenames == NULL) + return EINVAL; + if(!issuid()) + files = getenv("KRB5_CONFIG"); + if (files == NULL) + files = krb5_config_file; + + return krb5_prepend_config_files(files, NULL, pfilenames); +} + +void KRB5_LIB_FUNCTION +krb5_free_config_files(char **filenames) +{ + char **p; + for(p = filenames; *p != NULL; p++) + free(*p); + free(filenames); +} + +/* + * set `etype' to a malloced list of the default enctypes + */ + +static krb5_error_code +default_etypes(krb5_context context, krb5_enctype **etype) +{ + krb5_enctype p[] = { + ETYPE_AES256_CTS_HMAC_SHA1_96, + ETYPE_AES128_CTS_HMAC_SHA1_96, + ETYPE_DES3_CBC_SHA1, + ETYPE_DES3_CBC_MD5, + ETYPE_ARCFOUR_HMAC_MD5, + ETYPE_DES_CBC_MD5, + ETYPE_DES_CBC_MD4, + ETYPE_DES_CBC_CRC + }; + krb5_enctype *e = NULL, *ep; + int i, n = 0; + + for (i = 0; i < sizeof(p)/sizeof(p[0]); i++) { + if (krb5_enctype_valid(context, p[i]) != 0) + continue; + ep = realloc(e, (n + 2) * sizeof(*e)); + if (ep == NULL) { + free(e); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + e = ep; + e[n] = p[i]; + e[n + 1] = ETYPE_NULL; + n++; + } + *etype = e; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_default_in_tkt_etypes(krb5_context context, + const krb5_enctype *etypes) +{ + krb5_enctype *p = NULL; + int i; + + if(etypes) { + for (i = 0; etypes[i]; ++i) { + krb5_error_code ret; + ret = krb5_enctype_valid(context, etypes[i]); + if (ret) + return ret; + } + ++i; + ALLOC(p, i); + if(!p) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memmove(p, etypes, i * sizeof(krb5_enctype)); + } + if(context->etypes) + free(context->etypes); + context->etypes = p; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_in_tkt_etypes(krb5_context context, + krb5_enctype **etypes) +{ + krb5_enctype *p; + int i; + krb5_error_code ret; + + if(context->etypes) { + for(i = 0; context->etypes[i]; i++); + ++i; + ALLOC(p, i); + if(!p) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memmove(p, context->etypes, i * sizeof(krb5_enctype)); + } else { + ret = default_etypes(context, &p); + if (ret) + return ret; + } + *etypes = p; + return 0; +} + +const char* KRB5_LIB_FUNCTION +krb5_get_err_text(krb5_context context, krb5_error_code code) +{ + const char *p = NULL; + if(context != NULL) + p = com_right(context->et_list, code); + if(p == NULL) + p = strerror(code); + if (p == NULL) + p = "Unknown error"; + return p; +} + +void KRB5_LIB_FUNCTION +krb5_init_ets(krb5_context context) +{ + if(context->et_list == NULL){ + krb5_add_et_list(context, initialize_krb5_error_table_r); + krb5_add_et_list(context, initialize_asn1_error_table_r); + krb5_add_et_list(context, initialize_heim_error_table_r); + krb5_add_et_list(context, initialize_k524_error_table_r); + } +} + +void KRB5_LIB_FUNCTION +krb5_set_use_admin_kdc (krb5_context context, krb5_boolean flag) +{ + context->use_admin_kdc = flag; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_get_use_admin_kdc (krb5_context context) +{ + return context->use_admin_kdc; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses) +{ + + if(context->extra_addresses) + return krb5_append_addresses(context, + context->extra_addresses, addresses); + else + return krb5_set_extra_addresses(context, addresses); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses) +{ + if(context->extra_addresses) + krb5_free_addresses(context, context->extra_addresses); + + if(addresses == NULL) { + if(context->extra_addresses != NULL) { + free(context->extra_addresses); + context->extra_addresses = NULL; + } + return 0; + } + if(context->extra_addresses == NULL) { + context->extra_addresses = malloc(sizeof(*context->extra_addresses)); + if(context->extra_addresses == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + } + return krb5_copy_addresses(context, addresses, context->extra_addresses); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses) +{ + if(context->extra_addresses == NULL) { + memset(addresses, 0, sizeof(*addresses)); + return 0; + } + return krb5_copy_addresses(context,context->extra_addresses, addresses); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_add_ignore_addresses(krb5_context context, krb5_addresses *addresses) +{ + + if(context->ignore_addresses) + return krb5_append_addresses(context, + context->ignore_addresses, addresses); + else + return krb5_set_ignore_addresses(context, addresses); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses) +{ + if(context->ignore_addresses) + krb5_free_addresses(context, context->ignore_addresses); + if(addresses == NULL) { + if(context->ignore_addresses != NULL) { + free(context->ignore_addresses); + context->ignore_addresses = NULL; + } + return 0; + } + if(context->ignore_addresses == NULL) { + context->ignore_addresses = malloc(sizeof(*context->ignore_addresses)); + if(context->ignore_addresses == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + } + return krb5_copy_addresses(context, addresses, context->ignore_addresses); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_ignore_addresses(krb5_context context, krb5_addresses *addresses) +{ + if(context->ignore_addresses == NULL) { + memset(addresses, 0, sizeof(*addresses)); + return 0; + } + return krb5_copy_addresses(context, context->ignore_addresses, addresses); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_fcache_version(krb5_context context, int version) +{ + context->fcache_vno = version; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_fcache_version(krb5_context context, int *version) +{ + *version = context->fcache_vno; + return 0; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_is_thread_safe(void) +{ +#ifdef ENABLE_PTHREAD_SUPPORT + return TRUE; +#else + return FALSE; +#endif +} diff --git a/source4/heimdal/lib/krb5/copy_host_realm.c b/source4/heimdal/lib/krb5/copy_host_realm.c new file mode 100644 index 0000000000..eb77fba024 --- /dev/null +++ b/source4/heimdal/lib/krb5/copy_host_realm.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: copy_host_realm.c,v 1.5 2004/05/25 21:21:17 lha Exp $"); + +/* + * Copy the list of realms from `from' to `to'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_host_realm(krb5_context context, + const krb5_realm *from, + krb5_realm **to) +{ + int n, i; + const krb5_realm *p; + + for (n = 0, p = from; *p != NULL; ++p) + ++n; + ++n; + *to = malloc (n * sizeof(**to)); + if (*to == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + for (i = 0; i < n; ++i) + (*to)[i] = NULL; + for (i = 0, p = from; *p != NULL; ++p, ++i) { + (*to)[i] = strdup(*p); + if ((*to)[i] == NULL) { + krb5_free_host_realm (context, *to); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + } + return 0; +} diff --git a/source4/heimdal/lib/krb5/crc.c b/source4/heimdal/lib/krb5/crc.c new file mode 100644 index 0000000000..c7cedd8c9e --- /dev/null +++ b/source4/heimdal/lib/krb5/crc.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: crc.c,v 1.9 2000/08/03 01:45:14 assar Exp $"); + +static u_long table[256]; + +#define CRC_GEN 0xEDB88320L + +void +_krb5_crc_init_table(void) +{ + static int flag = 0; + unsigned long crc, poly; + int i, j; + + if(flag) return; + poly = CRC_GEN; + for (i = 0; i < 256; i++) { + crc = i; + for (j = 8; j > 0; j--) { + if (crc & 1) { + crc = (crc >> 1) ^ poly; + } else { + crc >>= 1; + } + } + table[i] = crc; + } + flag = 1; +} + +u_int32_t +_krb5_crc_update (const char *p, size_t len, u_int32_t res) +{ + while (len--) + res = table[(res ^ *p++) & 0xFF] ^ (res >> 8); + return res & 0xFFFFFFFF; +} diff --git a/source4/heimdal/lib/krb5/creds.c b/source4/heimdal/lib/krb5/creds.c new file mode 100644 index 0000000000..2afd0725f1 --- /dev/null +++ b/source4/heimdal/lib/krb5/creds.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: creds.c,v 1.20 2005/05/18 04:21:04 lha Exp $"); + +/* keep this for compatibility with older code */ +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_creds_contents (krb5_context context, krb5_creds *c) +{ + return krb5_free_cred_contents (context, c); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_cred_contents (krb5_context context, krb5_creds *c) +{ + krb5_free_principal (context, c->client); + c->client = NULL; + krb5_free_principal (context, c->server); + c->server = NULL; + krb5_free_keyblock_contents (context, &c->session); + krb5_data_free (&c->ticket); + krb5_data_free (&c->second_ticket); + free_AuthorizationData (&c->authdata); + krb5_free_addresses (context, &c->addresses); + memset(c, 0, sizeof(*c)); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_creds_contents (krb5_context context, + const krb5_creds *incred, + krb5_creds *c) +{ + krb5_error_code ret; + + memset(c, 0, sizeof(*c)); + ret = krb5_copy_principal (context, incred->client, &c->client); + if (ret) + goto fail; + ret = krb5_copy_principal (context, incred->server, &c->server); + if (ret) + goto fail; + ret = krb5_copy_keyblock_contents (context, &incred->session, &c->session); + if (ret) + goto fail; + c->times = incred->times; + ret = krb5_data_copy (&c->ticket, + incred->ticket.data, + incred->ticket.length); + if (ret) + goto fail; + ret = krb5_data_copy (&c->second_ticket, + incred->second_ticket.data, + incred->second_ticket.length); + if (ret) + goto fail; + ret = copy_AuthorizationData(&incred->authdata, &c->authdata); + if (ret) + goto fail; + ret = krb5_copy_addresses (context, + &incred->addresses, + &c->addresses); + if (ret) + goto fail; + c->flags = incred->flags; + return 0; + +fail: + krb5_free_cred_contents (context, c); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_creds (krb5_context context, + const krb5_creds *incred, + krb5_creds **outcred) +{ + krb5_creds *c; + + c = malloc (sizeof (*c)); + if (c == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memset (c, 0, sizeof(*c)); + *outcred = c; + return krb5_copy_creds_contents (context, incred, c); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_creds (krb5_context context, krb5_creds *c) +{ + krb5_free_cred_contents (context, c); + free (c); + return 0; +} + +/* XXX these do not belong here */ +static krb5_boolean +krb5_data_equal(const krb5_data *a, const krb5_data *b) +{ + if(a->length != b->length) + return FALSE; + return memcmp(a->data, b->data, a->length) == 0; +} + +static krb5_boolean +krb5_times_equal(const krb5_times *a, const krb5_times *b) +{ + return a->starttime == b->starttime && + a->authtime == b->authtime && + a->endtime == b->endtime && + a->renew_till == b->renew_till; +} + +/* + * Return TRUE if `mcreds' and `creds' are equal (`whichfields' + * determines what equal means). + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_compare_creds(krb5_context context, krb5_flags whichfields, + const krb5_creds * mcreds, const krb5_creds * creds) +{ + krb5_boolean match = TRUE; + + if (match && mcreds->server) { + if (whichfields & (KRB5_TC_DONT_MATCH_REALM | KRB5_TC_MATCH_SRV_NAMEONLY)) + match = krb5_principal_compare_any_realm (context, mcreds->server, + creds->server); + else + match = krb5_principal_compare (context, mcreds->server, + creds->server); + } + + if (match && mcreds->client) { + if(whichfields & KRB5_TC_DONT_MATCH_REALM) + match = krb5_principal_compare_any_realm (context, mcreds->client, + creds->client); + else + match = krb5_principal_compare (context, mcreds->client, + creds->client); + } + + if (match && (whichfields & KRB5_TC_MATCH_KEYTYPE)) + match = krb5_enctypes_compatible_keys(context, + mcreds->session.keytype, + creds->session.keytype); + + if (match && (whichfields & KRB5_TC_MATCH_FLAGS_EXACT)) + match = mcreds->flags.i == creds->flags.i; + + if (match && (whichfields & KRB5_TC_MATCH_FLAGS)) + match = (creds->flags.i & mcreds->flags.i) == mcreds->flags.i; + + if (match && (whichfields & KRB5_TC_MATCH_TIMES_EXACT)) + match = krb5_times_equal(&mcreds->times, &creds->times); + + if (match && (whichfields & KRB5_TC_MATCH_TIMES)) + /* compare only expiration times */ + match = (mcreds->times.renew_till <= creds->times.renew_till) && + (mcreds->times.endtime <= creds->times.endtime); + + if (match && (whichfields & KRB5_TC_MATCH_AUTHDATA)) { + unsigned int i; + if(mcreds->authdata.len != creds->authdata.len) + match = FALSE; + else + for(i = 0; match && i < mcreds->authdata.len; i++) + match = (mcreds->authdata.val[i].ad_type == + creds->authdata.val[i].ad_type) && + krb5_data_equal(&mcreds->authdata.val[i].ad_data, + &creds->authdata.val[i].ad_data); + } + if (match && (whichfields & KRB5_TC_MATCH_2ND_TKT)) + match = krb5_data_equal(&mcreds->second_ticket, &creds->second_ticket); + + if (match && (whichfields & KRB5_TC_MATCH_IS_SKEY)) + match = ((mcreds->second_ticket.length == 0) == + (creds->second_ticket.length == 0)); + + return match; +} diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c new file mode 100644 index 0000000000..2b1ac3a5c4 --- /dev/null +++ b/source4/heimdal/lib/krb5/crypto.c @@ -0,0 +1,4410 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +RCSID("$Id: crypto.c,v 1.123 2005/06/29 22:20:33 lha Exp $"); + +#undef CRYPTO_DEBUG +#ifdef CRYPTO_DEBUG +static void krb5_crypto_debug(krb5_context, int, size_t, krb5_keyblock*); +#endif + + +struct key_data { + krb5_keyblock *key; + krb5_data *schedule; +}; + +struct key_usage { + unsigned usage; + struct key_data key; +}; + +struct krb5_crypto_data { + struct encryption_type *et; + struct key_data key; + int num_key_usage; + struct key_usage *key_usage; + void *params; +}; + +#define kcrypto_oid_enc(n) { sizeof(n)/sizeof(n[0]), n } + +#define CRYPTO_ETYPE(C) ((C)->et->type) + +/* bits for `flags' below */ +#define F_KEYED 1 /* checksum is keyed */ +#define F_CPROOF 2 /* checksum is collision proof */ +#define F_DERIVED 4 /* uses derived keys */ +#define F_VARIANT 8 /* uses `variant' keys (6.4.3) */ +#define F_PSEUDO 16 /* not a real protocol type */ +#define F_SPECIAL 32 /* backwards */ +#define F_DISABLED 64 /* enctype/checksum disabled */ +#define F_PADCMS 128 /* padding done like in CMS */ + +struct salt_type { + krb5_salttype type; + const char *name; + krb5_error_code (*string_to_key)(krb5_context, krb5_enctype, krb5_data, + krb5_salt, krb5_data, krb5_keyblock*); +}; + +struct key_type { + krb5_keytype type; /* XXX */ + const char *name; + size_t bits; + size_t size; + size_t minsize; + size_t schedule_size; +#if 0 + krb5_enctype best_etype; +#endif + void (*random_key)(krb5_context, krb5_keyblock*); + void (*schedule)(krb5_context, struct key_data *, const void *); + struct salt_type *string_to_key; + void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t); + krb5_error_code (*get_params)(krb5_context, const krb5_data *, + void **, krb5_data *); + krb5_error_code (*set_params)(krb5_context, const void *, + const krb5_data *, krb5_data *); +}; + +struct checksum_type { + krb5_cksumtype type; + const char *name; + size_t blocksize; + size_t checksumsize; + unsigned flags; + void (*checksum)(krb5_context context, + struct key_data *key, + const void *buf, size_t len, + unsigned usage, + Checksum *csum); + krb5_error_code (*verify)(krb5_context context, + struct key_data *key, + const void *buf, size_t len, + unsigned usage, + Checksum *csum); +}; + +struct encryption_type { + krb5_enctype type; + const char *name; + heim_oid *oid; + size_t blocksize; + size_t padsize; + size_t confoundersize; + struct key_type *keytype; + struct checksum_type *checksum; + struct checksum_type *keyed_checksum; + unsigned flags; + krb5_error_code (*encrypt)(krb5_context context, + struct key_data *key, + void *data, size_t len, + krb5_boolean encryptp, + int usage, + void *ivec); +}; + +#define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA) +#define INTEGRITY_USAGE(U) (((U) << 8) | 0x55) +#define CHECKSUM_USAGE(U) (((U) << 8) | 0x99) + +static struct checksum_type *_find_checksum(krb5_cksumtype type); +static struct encryption_type *_find_enctype(krb5_enctype type); +static struct key_type *_find_keytype(krb5_keytype type); +static krb5_error_code _get_derived_key(krb5_context, krb5_crypto, + unsigned, struct key_data**); +static struct key_data *_new_derived_key(krb5_crypto crypto, unsigned usage); +static krb5_error_code derive_key(krb5_context context, + struct encryption_type *et, + struct key_data *key, + const void *constant, + size_t len); +static krb5_error_code hmac(krb5_context context, + struct checksum_type *cm, + const void *data, + size_t len, + unsigned usage, + struct key_data *keyblock, + Checksum *result); +static void free_key_data(krb5_context context, struct key_data *key); +static krb5_error_code usage2arcfour (krb5_context, unsigned *); +static void xor (DES_cblock *, const unsigned char *); + +/************************************************************ + * * + ************************************************************/ + +static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER; + + +static void +krb5_DES_random_key(krb5_context context, + krb5_keyblock *key) +{ + DES_cblock *k = key->keyvalue.data; + do { + krb5_generate_random_block(k, sizeof(DES_cblock)); + DES_set_odd_parity(k); + } while(DES_is_weak_key(k)); +} + +static void +krb5_DES_schedule(krb5_context context, + struct key_data *key, + const void *params) +{ + DES_set_key(key->key->keyvalue.data, key->schedule->data); +} + +static void +DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key) +{ + DES_key_schedule schedule; + int i; + int reverse = 0; + unsigned char *p; + + unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, + 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; + memset(key, 0, 8); + + p = (unsigned char*)key; + for (i = 0; i < length; i++) { + unsigned char tmp = data[i]; + if (!reverse) + *p++ ^= (tmp << 1); + else + *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4]; + if((i % 8) == 7) + reverse = !reverse; + } + DES_set_odd_parity(key); + if(DES_is_weak_key(key)) + (*key)[7] ^= 0xF0; + DES_set_key(key, &schedule); + DES_cbc_cksum((void*)data, key, length, &schedule, key); + memset(&schedule, 0, sizeof(schedule)); + DES_set_odd_parity(key); + if(DES_is_weak_key(key)) + (*key)[7] ^= 0xF0; +} + +static krb5_error_code +krb5_DES_string_to_key(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + unsigned char *s; + size_t len; + DES_cblock tmp; + + len = password.length + salt.saltvalue.length; + s = malloc(len); + if(len > 0 && s == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(s, password.data, password.length); + memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); + DES_string_to_key_int(s, len, &tmp); + key->keytype = enctype; + krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); + memset(&tmp, 0, sizeof(tmp)); + memset(s, 0, len); + free(s); + return 0; +} + +#ifdef ENABLE_AFS_STRING_TO_KEY + +/* This defines the Andrew string_to_key function. It accepts a password + * string as input and converts its via a one-way encryption algorithm to a DES + * encryption key. It is compatible with the original Andrew authentication + * service password database. + */ + +/* + * Short passwords, i.e 8 characters or less. + */ +static void +krb5_DES_AFS3_CMU_string_to_key (krb5_data pw, + krb5_data cell, + DES_cblock *key) +{ + char password[8+1]; /* crypt is limited to 8 chars anyway */ + int i; + + for(i = 0; i < 8; i++) { + char c = ((i < pw.length) ? ((char*)pw.data)[i] : 0) ^ + ((i < cell.length) ? + tolower(((unsigned char*)cell.data)[i]) : 0); + password[i] = c ? c : 'X'; + } + password[8] = '\0'; + + memcpy(key, crypt(password, "p1") + 2, sizeof(DES_cblock)); + + /* parity is inserted into the LSB so left shift each byte up one + bit. This allows ascii characters with a zero MSB to retain as + much significance as possible. */ + for (i = 0; i < sizeof(DES_cblock); i++) + ((unsigned char*)key)[i] <<= 1; + DES_set_odd_parity (key); +} + +/* + * Long passwords, i.e 9 characters or more. + */ +static void +krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw, + krb5_data cell, + DES_cblock *key) +{ + DES_key_schedule schedule; + DES_cblock temp_key; + DES_cblock ivec; + char password[512]; + size_t passlen; + + memcpy(password, pw.data, min(pw.length, sizeof(password))); + if(pw.length < sizeof(password)) { + int len = min(cell.length, sizeof(password) - pw.length); + int i; + + memcpy(password + pw.length, cell.data, len); + for (i = pw.length; i < pw.length + len; ++i) + password[i] = tolower((unsigned char)password[i]); + } + passlen = min(sizeof(password), pw.length + cell.length); + memcpy(&ivec, "kerberos", 8); + memcpy(&temp_key, "kerberos", 8); + DES_set_odd_parity (&temp_key); + DES_set_key (&temp_key, &schedule); + DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec); + + memcpy(&temp_key, &ivec, 8); + DES_set_odd_parity (&temp_key); + DES_set_key (&temp_key, &schedule); + DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec); + memset(&schedule, 0, sizeof(schedule)); + memset(&temp_key, 0, sizeof(temp_key)); + memset(&ivec, 0, sizeof(ivec)); + memset(password, 0, sizeof(password)); + + DES_set_odd_parity (key); +} + +static krb5_error_code +DES_AFS3_string_to_key(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + DES_cblock tmp; + if(password.length > 8) + krb5_DES_AFS3_Transarc_string_to_key(password, salt.saltvalue, &tmp); + else + krb5_DES_AFS3_CMU_string_to_key(password, salt.saltvalue, &tmp); + key->keytype = enctype; + krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); + memset(&key, 0, sizeof(key)); + return 0; +} +#endif /* ENABLE_AFS_STRING_TO_KEY */ + +static void +krb5_DES_random_to_key(krb5_context context, + krb5_keyblock *key, + const void *data, + size_t size) +{ + DES_cblock *k = key->keyvalue.data; + memcpy(k, data, key->keyvalue.length); + DES_set_odd_parity(k); + if(DES_is_weak_key(k)) + xor(k, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); +} + +/* + * + */ + +static void +DES3_random_key(krb5_context context, + krb5_keyblock *key) +{ + DES_cblock *k = key->keyvalue.data; + do { + krb5_generate_random_block(k, 3 * sizeof(DES_cblock)); + DES_set_odd_parity(&k[0]); + DES_set_odd_parity(&k[1]); + DES_set_odd_parity(&k[2]); + } while(DES_is_weak_key(&k[0]) || + DES_is_weak_key(&k[1]) || + DES_is_weak_key(&k[2])); +} + +static void +DES3_schedule(krb5_context context, + struct key_data *key, + const void *params) +{ + DES_cblock *k = key->key->keyvalue.data; + DES_key_schedule *s = key->schedule->data; + DES_set_key(&k[0], &s[0]); + DES_set_key(&k[1], &s[1]); + DES_set_key(&k[2], &s[2]); +} + +/* + * A = A xor B. A & B are 8 bytes. + */ + +static void +xor (DES_cblock *key, const unsigned char *b) +{ + unsigned char *a = (unsigned char*)key; + a[0] ^= b[0]; + a[1] ^= b[1]; + a[2] ^= b[2]; + a[3] ^= b[3]; + a[4] ^= b[4]; + a[5] ^= b[5]; + a[6] ^= b[6]; + a[7] ^= b[7]; +} + +static krb5_error_code +DES3_string_to_key(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + char *str; + size_t len; + unsigned char tmp[24]; + DES_cblock keys[3]; + + len = password.length + salt.saltvalue.length; + str = malloc(len); + if(len != 0 && str == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(str, password.data, password.length); + memcpy(str + password.length, salt.saltvalue.data, salt.saltvalue.length); + { + DES_cblock ivec; + DES_key_schedule s[3]; + int i; + + _krb5_n_fold(str, len, tmp, 24); + + for(i = 0; i < 3; i++){ + memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); + DES_set_odd_parity(keys + i); + if(DES_is_weak_key(keys + i)) + xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); + DES_set_key(keys + i, &s[i]); + } + memset(&ivec, 0, sizeof(ivec)); + DES_ede3_cbc_encrypt(tmp, + tmp, sizeof(tmp), + &s[0], &s[1], &s[2], &ivec, DES_ENCRYPT); + memset(s, 0, sizeof(s)); + memset(&ivec, 0, sizeof(ivec)); + for(i = 0; i < 3; i++){ + memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); + DES_set_odd_parity(keys + i); + if(DES_is_weak_key(keys + i)) + xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); + } + memset(tmp, 0, sizeof(tmp)); + } + key->keytype = enctype; + krb5_data_copy(&key->keyvalue, keys, sizeof(keys)); + memset(keys, 0, sizeof(keys)); + memset(str, 0, len); + free(str); + return 0; +} + +static krb5_error_code +DES3_string_to_key_derived(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + krb5_error_code ret; + size_t len = password.length + salt.saltvalue.length; + char *s; + + s = malloc(len); + if(len != 0 && s == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(s, password.data, password.length); + memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); + ret = krb5_string_to_key_derived(context, + s, + len, + enctype, + key); + memset(s, 0, len); + free(s); + return ret; +} + +static void +DES3_random_to_key(krb5_context context, + krb5_keyblock *key, + const void *data, + size_t size) +{ + unsigned char *x = key->keyvalue.data; + const u_char *q = data; + DES_cblock *k; + int i, j; + + memset(x, 0, sizeof(x)); + for (i = 0; i < 3; ++i) { + unsigned char foo; + for (j = 0; j < 7; ++j) { + unsigned char b = q[7 * i + j]; + + x[8 * i + j] = b; + } + foo = 0; + for (j = 6; j >= 0; --j) { + foo |= q[7 * i + j] & 1; + foo <<= 1; + } + x[8 * i + 7] = foo; + } + k = key->keyvalue.data; + for (i = 0; i < 3; i++) { + DES_set_odd_parity(&k[i]); + if(DES_is_weak_key(&k[i])) + xor(&k[i], (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); + } +} + +/* + * ARCFOUR + */ + +static void +ARCFOUR_schedule(krb5_context context, + struct key_data *kd, + const void *params) +{ + RC4_set_key (kd->schedule->data, + kd->key->keyvalue.length, kd->key->keyvalue.data); +} + +static krb5_error_code +ARCFOUR_string_to_key(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + char *s, *p; + size_t len; + int i; + MD4_CTX m; + + len = 2 * password.length; + s = malloc (len); + if (len != 0 && s == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + for (p = s, i = 0; i < password.length; ++i) { + *p++ = ((char *)password.data)[i]; + *p++ = 0; + } + MD4_Init (&m); + MD4_Update (&m, s, len); + key->keytype = enctype; + krb5_data_alloc (&key->keyvalue, 16); + MD4_Final (key->keyvalue.data, &m); + memset (s, 0, len); + free (s); + return 0; +} + +/* + * AES + */ + +/* iter is really 1 based, so iter == 0 will be 1 iteration */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_PKCS5_PBKDF2(krb5_context context, krb5_cksumtype cktype, + krb5_data password, krb5_salt salt, u_int32_t iter, + krb5_keytype type, krb5_keyblock *key) +{ + struct checksum_type *c = _find_checksum(cktype); + struct key_type *kt; + size_t datalen, leftofkey; + krb5_error_code ret; + u_int32_t keypart; + struct key_data ksign; + krb5_keyblock kb; + Checksum result; + char *data, *tmpcksum; + int i, j; + char *p; + + if (c == NULL) { + krb5_set_error_string(context, "checksum %d not supported", cktype); + return KRB5_PROG_KEYTYPE_NOSUPP; + } + + kt = _find_keytype(type); + if (kt == NULL) { + krb5_set_error_string(context, "key type %d not supported", type); + return KRB5_PROG_KEYTYPE_NOSUPP; + } + + key->keytype = type; + ret = krb5_data_alloc (&key->keyvalue, kt->bits / 8); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + return ret; + } + + ret = krb5_data_alloc (&result.checksum, c->checksumsize); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + krb5_data_free (&key->keyvalue); + return ret; + } + + tmpcksum = malloc(c->checksumsize); + if (tmpcksum == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + krb5_data_free (&key->keyvalue); + krb5_data_free (&result.checksum); + return ENOMEM; + } + + datalen = salt.saltvalue.length + 4; + data = malloc(datalen); + if (data == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + free(tmpcksum); + krb5_data_free (&key->keyvalue); + krb5_data_free (&result.checksum); + return ENOMEM; + } + + kb.keyvalue = password; + ksign.key = &kb; + + memcpy(data, salt.saltvalue.data, salt.saltvalue.length); + + keypart = 1; + leftofkey = key->keyvalue.length; + p = key->keyvalue.data; + + while (leftofkey) { + int len; + + if (leftofkey > c->checksumsize) + len = c->checksumsize; + else + len = leftofkey; + + _krb5_put_int(data + datalen - 4, keypart, 4); + + ret = hmac(context, c, data, datalen, 0, &ksign, &result); + if (ret) + krb5_abortx(context, "hmac failed"); + memcpy(p, result.checksum.data, len); + memcpy(tmpcksum, result.checksum.data, result.checksum.length); + for (i = 0; i < iter; i++) { + ret = hmac(context, c, tmpcksum, result.checksum.length, + 0, &ksign, &result); + if (ret) + krb5_abortx(context, "hmac failed"); + memcpy(tmpcksum, result.checksum.data, result.checksum.length); + for (j = 0; j < len; j++) + p[j] ^= tmpcksum[j]; + } + + p += len; + leftofkey -= len; + keypart++; + } + + free(data); + free(tmpcksum); + krb5_data_free (&result.checksum); + + return 0; +} + +int _krb5_AES_string_to_default_iterator = 4096; + +static krb5_error_code +AES_string_to_key(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + krb5_error_code ret; + u_int32_t iter; + struct encryption_type *et; + struct key_data kd; + + if (opaque.length == 0) + iter = _krb5_AES_string_to_default_iterator - 1; + else if (opaque.length == 4) { + unsigned long v; + _krb5_get_int(opaque.data, &v, 4); + iter = ((u_int32_t)v) - 1; + } else + return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */ + + + et = _find_enctype(enctype); + if (et == NULL) + return KRB5_PROG_KEYTYPE_NOSUPP; + + ret = _krb5_PKCS5_PBKDF2(context, CKSUMTYPE_SHA1, password, salt, + iter, enctype, key); + if (ret) + return ret; + + ret = krb5_copy_keyblock(context, key, &kd.key); + kd.schedule = NULL; + + ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos")); + krb5_free_keyblock_contents(context, key); + if (ret == 0) { + ret = krb5_copy_keyblock_contents(context, kd.key, key); + free_key_data(context, &kd); + } + + return ret; +} + +struct krb5_aes_schedule { + AES_KEY ekey; + AES_KEY dkey; +}; + +static void +AES_schedule(krb5_context context, + struct key_data *kd, + const void *params) +{ + struct krb5_aes_schedule *key = kd->schedule->data; + int bits = kd->key->keyvalue.length * 8; + + memset(key, 0, sizeof(*key)); + AES_set_encrypt_key(kd->key->keyvalue.data, bits, &key->ekey); + AES_set_decrypt_key(kd->key->keyvalue.data, bits, &key->dkey); +} + +/* + * RC2 + */ + +struct _RC2_params { + int maximum_effective_key; +}; + +static krb5_error_code +rc2_get_params(krb5_context context, + const krb5_data *data, + void **params, + krb5_data *ivec) +{ + RC2CBCParameter rc2params; + struct _RC2_params *p; + krb5_error_code ret; + size_t size; + + ret = decode_RC2CBCParameter(data->data, data->length, &rc2params, &size); + if (ret) { + krb5_set_error_string(context, "Can't decode RC2 parameters"); + return ret; + } + p = malloc(sizeof(*p)); + if (p == NULL) { + free_RC2CBCParameter(&rc2params); + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + /* XXX */ + switch(rc2params.rc2ParameterVersion) { + case 160: + p->maximum_effective_key = 40; + break; + case 120: + p->maximum_effective_key = 64; + break; + case 58: + p->maximum_effective_key = 128; + break; + + } + if (ivec) + ret = copy_octet_string(&rc2params.iv, ivec); + free_RC2CBCParameter(&rc2params); + *params = p; + + return ret; +} + +static krb5_error_code +rc2_set_params(krb5_context context, + const void *params, + const krb5_data *ivec, + krb5_data *data) +{ + RC2CBCParameter rc2params; + const struct _RC2_params *p = params; + int maximum_effective_key = 128; + krb5_error_code ret; + size_t size; + + memset(&rc2params, 0, sizeof(rc2params)); + + if (p) + maximum_effective_key = p->maximum_effective_key; + + /* XXX */ + switch(maximum_effective_key) { + case 40: + rc2params.rc2ParameterVersion = 160; + break; + case 64: + rc2params.rc2ParameterVersion = 120; + break; + case 128: + rc2params.rc2ParameterVersion = 58; + break; + } + ret = copy_octet_string(ivec, &rc2params.iv); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(RC2CBCParameter, data->data, data->length, + &rc2params, &size, ret); + if (ret == 0 && size != data->length) + krb5_abortx(context, "Internal asn1 encoder failure"); + free_RC2CBCParameter(&rc2params); + + return ret; +} + +static void +rc2_schedule(krb5_context context, + struct key_data *kd, + const void *params) +{ + const struct _RC2_params *p = params; + int maximum_effective_key = 128; + if (p) + maximum_effective_key = p->maximum_effective_key; + RC2_set_key (kd->schedule->data, + kd->key->keyvalue.length, + kd->key->keyvalue.data, + maximum_effective_key); +} + + +/* + * + */ + +static struct salt_type des_salt[] = { + { + KRB5_PW_SALT, + "pw-salt", + krb5_DES_string_to_key + }, +#ifdef ENABLE_AFS_STRING_TO_KEY + { + KRB5_AFS3_SALT, + "afs3-salt", + DES_AFS3_string_to_key + }, +#endif + { 0 } +}; + +static struct salt_type des3_salt[] = { + { + KRB5_PW_SALT, + "pw-salt", + DES3_string_to_key + }, + { 0 } +}; + +static struct salt_type des3_salt_derived[] = { + { + KRB5_PW_SALT, + "pw-salt", + DES3_string_to_key_derived + }, + { 0 } +}; + +static struct salt_type AES_salt[] = { + { + KRB5_PW_SALT, + "pw-salt", + AES_string_to_key + }, + { 0 } +}; + +static struct salt_type arcfour_salt[] = { + { + KRB5_PW_SALT, + "pw-salt", + ARCFOUR_string_to_key + }, + { 0 } +}; + +/* + * + */ + +static struct key_type keytype_null = { + KEYTYPE_NULL, + "null", + 0, + 0, + 0, + 0, + NULL, + NULL, + NULL +}; + +static struct key_type keytype_des = { + KEYTYPE_DES, + "des", + 56, + sizeof(DES_cblock), + sizeof(DES_cblock), + sizeof(DES_key_schedule), + krb5_DES_random_key, + krb5_DES_schedule, + des_salt, + krb5_DES_random_to_key +}; + +static struct key_type keytype_des3 = { + KEYTYPE_DES3, + "des3", + 168, + 3 * sizeof(DES_cblock), + 3 * sizeof(DES_cblock), + 3 * sizeof(DES_key_schedule), + DES3_random_key, + DES3_schedule, + des3_salt, + DES3_random_to_key +}; + +static struct key_type keytype_des3_derived = { + KEYTYPE_DES3, + "des3", + 168, + 3 * sizeof(DES_cblock), + 3 * sizeof(DES_cblock), + 3 * sizeof(DES_key_schedule), + DES3_random_key, + DES3_schedule, + des3_salt_derived, + DES3_random_to_key +}; + +static struct key_type keytype_aes128 = { + KEYTYPE_AES128, + "aes-128", + 128, + 16, + 16, + sizeof(struct krb5_aes_schedule), + NULL, + AES_schedule, + AES_salt +}; + +static struct key_type keytype_aes192 = { + KEYTYPE_AES192, + "aes-192", + 192, + 24, + 24, + sizeof(struct krb5_aes_schedule), + NULL, + AES_schedule, + AES_salt +}; + +static struct key_type keytype_aes256 = { + KEYTYPE_AES256, + "aes-256", + 256, + 32, + 32, + sizeof(struct krb5_aes_schedule), + NULL, + AES_schedule, + AES_salt +}; + +static struct key_type keytype_arcfour = { + KEYTYPE_ARCFOUR, + "arcfour", + 128, + 16, + 16, + sizeof(RC4_KEY), + NULL, + ARCFOUR_schedule, + arcfour_salt +}; + +static struct key_type keytype_rc2 = { + KEYTYPE_RC2, + "rc2", + 128, + 16, + 1, + sizeof(RC2_KEY), + NULL, + rc2_schedule, + NULL, /* XXX salt */ + NULL, + rc2_get_params, + rc2_set_params +}; + +static struct key_type *keytypes[] = { + &keytype_null, + &keytype_des, + &keytype_des3_derived, + &keytype_des3, + &keytype_aes128, + &keytype_aes192, + &keytype_aes256, + &keytype_rc2, + &keytype_arcfour +}; + +static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]); + +static struct key_type * +_find_keytype(krb5_keytype type) +{ + int i; + for(i = 0; i < num_keytypes; i++) + if(keytypes[i]->type == type) + return keytypes[i]; + return NULL; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_salttype_to_string (krb5_context context, + krb5_enctype etype, + krb5_salttype stype, + char **string) +{ + struct encryption_type *e; + struct salt_type *st; + + e = _find_enctype (etype); + if (e == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + for (st = e->keytype->string_to_key; st && st->type; st++) { + if (st->type == stype) { + *string = strdup (st->name); + if (*string == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + return 0; + } + } + krb5_set_error_string(context, "salttype %d not supported", stype); + return HEIM_ERR_SALTTYPE_NOSUPP; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_salttype (krb5_context context, + krb5_enctype etype, + const char *string, + krb5_salttype *salttype) +{ + struct encryption_type *e; + struct salt_type *st; + + e = _find_enctype (etype); + if (e == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + for (st = e->keytype->string_to_key; st && st->type; st++) { + if (strcasecmp (st->name, string) == 0) { + *salttype = st->type; + return 0; + } + } + krb5_set_error_string(context, "salttype %s not supported", string); + return HEIM_ERR_SALTTYPE_NOSUPP; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_pw_salt(krb5_context context, + krb5_const_principal principal, + krb5_salt *salt) +{ + size_t len; + int i; + krb5_error_code ret; + char *p; + + salt->salttype = KRB5_PW_SALT; + len = strlen(principal->realm); + for (i = 0; i < principal->name.name_string.len; ++i) + len += strlen(principal->name.name_string.val[i]); + ret = krb5_data_alloc (&salt->saltvalue, len); + if (ret) + return ret; + p = salt->saltvalue.data; + memcpy (p, principal->realm, strlen(principal->realm)); + p += strlen(principal->realm); + for (i = 0; i < principal->name.name_string.len; ++i) { + memcpy (p, + principal->name.name_string.val[i], + strlen(principal->name.name_string.val[i])); + p += strlen(principal->name.name_string.val[i]); + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_salt(krb5_context context, + krb5_salt salt) +{ + krb5_data_free(&salt.saltvalue); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_data (krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_principal principal, + krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_salt salt; + + ret = krb5_get_pw_salt(context, principal, &salt); + if(ret) + return ret; + ret = krb5_string_to_key_data_salt(context, enctype, password, salt, key); + krb5_free_salt(context, salt); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key (krb5_context context, + krb5_enctype enctype, + const char *password, + krb5_principal principal, + krb5_keyblock *key) +{ + krb5_data pw; + pw.data = rk_UNCONST(password); + pw.length = strlen(password); + return krb5_string_to_key_data(context, enctype, pw, principal, key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_data_salt (krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_keyblock *key) +{ + krb5_data opaque; + krb5_data_zero(&opaque); + return krb5_string_to_key_data_salt_opaque(context, enctype, password, + salt, opaque, key); +} + +/* + * Do a string -> key for encryption type `enctype' operation on + * `password' (with salt `salt' and the enctype specific data string + * `opaque'), returning the resulting key in `key' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_data_salt_opaque (krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + struct encryption_type *et =_find_enctype(enctype); + struct salt_type *st; + if(et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + enctype); + return KRB5_PROG_ETYPE_NOSUPP; + } + for(st = et->keytype->string_to_key; st && st->type; st++) + if(st->type == salt.salttype) + return (*st->string_to_key)(context, enctype, password, + salt, opaque, key); + krb5_set_error_string(context, "salt type %d not supported", + salt.salttype); + return HEIM_ERR_SALTTYPE_NOSUPP; +} + +/* + * Do a string -> key for encryption type `enctype' operation on the + * string `password' (with salt `salt'), returning the resulting key + * in `key' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_salt (krb5_context context, + krb5_enctype enctype, + const char *password, + krb5_salt salt, + krb5_keyblock *key) +{ + krb5_data pw; + pw.data = rk_UNCONST(password); + pw.length = strlen(password); + return krb5_string_to_key_data_salt(context, enctype, pw, salt, key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_salt_opaque (krb5_context context, + krb5_enctype enctype, + const char *password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + krb5_data pw; + pw.data = rk_UNCONST(password); + pw.length = strlen(password); + return krb5_string_to_key_data_salt_opaque(context, enctype, + pw, salt, opaque, key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_string(krb5_context context, + krb5_keytype keytype, + char **string) +{ + struct key_type *kt = _find_keytype(keytype); + if(kt == NULL) { + krb5_set_error_string(context, "key type %d not supported", keytype); + return KRB5_PROG_KEYTYPE_NOSUPP; + } + *string = strdup(kt->name); + if(*string == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_keytype(krb5_context context, + const char *string, + krb5_keytype *keytype) +{ + int i; + for(i = 0; i < num_keytypes; i++) + if(strcasecmp(keytypes[i]->name, string) == 0){ + *keytype = keytypes[i]->type; + return 0; + } + krb5_set_error_string(context, "key type %s not supported", string); + return KRB5_PROG_KEYTYPE_NOSUPP; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_keysize(krb5_context context, + krb5_enctype type, + size_t *keysize) +{ + struct encryption_type *et = _find_enctype(type); + if(et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + type); + return KRB5_PROG_ETYPE_NOSUPP; + } + *keysize = et->keytype->size; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_random_keyblock(krb5_context context, + krb5_enctype type, + krb5_keyblock *key) +{ + krb5_error_code ret; + struct encryption_type *et = _find_enctype(type); + if(et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + type); + return KRB5_PROG_ETYPE_NOSUPP; + } + ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); + if(ret) + return ret; + key->keytype = type; + if(et->keytype->random_key) + (*et->keytype->random_key)(context, key); + else + krb5_generate_random_block(key->keyvalue.data, + key->keyvalue.length); + return 0; +} + +static krb5_error_code +_key_schedule(krb5_context context, + struct key_data *key, + const void *params) +{ + krb5_error_code ret; + struct encryption_type *et = _find_enctype(key->key->keytype); + struct key_type *kt = et->keytype; + + if(kt->schedule == NULL) + return 0; + if (key->schedule != NULL) + return 0; + ALLOC(key->schedule, 1); + if(key->schedule == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_data_alloc(key->schedule, kt->schedule_size); + if(ret) { + free(key->schedule); + key->schedule = NULL; + return ret; + } + (*kt->schedule)(context, key, params); + return 0; +} + +/************************************************************ + * * + ************************************************************/ + +static void +NONE_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ +} + +static void +CRC32_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + u_int32_t crc; + unsigned char *r = C->checksum.data; + _krb5_crc_init_table (); + crc = _krb5_crc_update (data, len, 0); + r[0] = crc & 0xff; + r[1] = (crc >> 8) & 0xff; + r[2] = (crc >> 16) & 0xff; + r[3] = (crc >> 24) & 0xff; +} + +static void +RSA_MD4_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD4_CTX m; + + MD4_Init (&m); + MD4_Update (&m, data, len); + MD4_Final (C->checksum.data, &m); +} + +static void +RSA_MD4_DES_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *cksum) +{ + MD4_CTX md4; + DES_cblock ivec; + unsigned char *p = cksum->checksum.data; + + krb5_generate_random_block(p, 8); + MD4_Init (&md4); + MD4_Update (&md4, p, 8); + MD4_Update (&md4, data, len); + MD4_Final (p + 8, &md4); + memset (&ivec, 0, sizeof(ivec)); + DES_cbc_encrypt(p, + p, + 24, + key->schedule->data, + &ivec, + DES_ENCRYPT); +} + +static krb5_error_code +RSA_MD4_DES_verify(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD4_CTX md4; + unsigned char tmp[24]; + unsigned char res[16]; + DES_cblock ivec; + krb5_error_code ret = 0; + + memset(&ivec, 0, sizeof(ivec)); + DES_cbc_encrypt(C->checksum.data, + (void*)tmp, + C->checksum.length, + key->schedule->data, + &ivec, + DES_DECRYPT); + MD4_Init (&md4); + MD4_Update (&md4, tmp, 8); /* confounder */ + MD4_Update (&md4, data, len); + MD4_Final (res, &md4); + if(memcmp(res, tmp + 8, sizeof(res)) != 0) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } + memset(tmp, 0, sizeof(tmp)); + memset(res, 0, sizeof(res)); + return ret; +} + +static void +RSA_MD5_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD5_CTX m; + + MD5_Init (&m); + MD5_Update(&m, data, len); + MD5_Final (C->checksum.data, &m); +} + +static void +RSA_MD5_DES_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD5_CTX md5; + DES_cblock ivec; + unsigned char *p = C->checksum.data; + + krb5_generate_random_block(p, 8); + MD5_Init (&md5); + MD5_Update (&md5, p, 8); + MD5_Update (&md5, data, len); + MD5_Final (p + 8, &md5); + memset (&ivec, 0, sizeof(ivec)); + DES_cbc_encrypt(p, + p, + 24, + key->schedule->data, + &ivec, + DES_ENCRYPT); +} + +static krb5_error_code +RSA_MD5_DES_verify(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD5_CTX md5; + unsigned char tmp[24]; + unsigned char res[16]; + DES_cblock ivec; + DES_key_schedule *sched = key->schedule->data; + krb5_error_code ret = 0; + + memset(&ivec, 0, sizeof(ivec)); + DES_cbc_encrypt(C->checksum.data, + (void*)tmp, + C->checksum.length, + &sched[0], + &ivec, + DES_DECRYPT); + MD5_Init (&md5); + MD5_Update (&md5, tmp, 8); /* confounder */ + MD5_Update (&md5, data, len); + MD5_Final (res, &md5); + if(memcmp(res, tmp + 8, sizeof(res)) != 0) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } + memset(tmp, 0, sizeof(tmp)); + memset(res, 0, sizeof(res)); + return ret; +} + +static void +RSA_MD5_DES3_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD5_CTX md5; + DES_cblock ivec; + unsigned char *p = C->checksum.data; + DES_key_schedule *sched = key->schedule->data; + + krb5_generate_random_block(p, 8); + MD5_Init (&md5); + MD5_Update (&md5, p, 8); + MD5_Update (&md5, data, len); + MD5_Final (p + 8, &md5); + memset (&ivec, 0, sizeof(ivec)); + DES_ede3_cbc_encrypt(p, + p, + 24, + &sched[0], &sched[1], &sched[2], + &ivec, + DES_ENCRYPT); +} + +static krb5_error_code +RSA_MD5_DES3_verify(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + MD5_CTX md5; + unsigned char tmp[24]; + unsigned char res[16]; + DES_cblock ivec; + DES_key_schedule *sched = key->schedule->data; + krb5_error_code ret = 0; + + memset(&ivec, 0, sizeof(ivec)); + DES_ede3_cbc_encrypt(C->checksum.data, + (void*)tmp, + C->checksum.length, + &sched[0], &sched[1], &sched[2], + &ivec, + DES_DECRYPT); + MD5_Init (&md5); + MD5_Update (&md5, tmp, 8); /* confounder */ + MD5_Update (&md5, data, len); + MD5_Final (res, &md5); + if(memcmp(res, tmp + 8, sizeof(res)) != 0) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } + memset(tmp, 0, sizeof(tmp)); + memset(res, 0, sizeof(res)); + return ret; +} + +static void +SHA1_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + SHA_CTX m; + + SHA1_Init(&m); + SHA1_Update(&m, data, len); + SHA1_Final(C->checksum.data, &m); +} + +/* HMAC according to RFC2104 */ +static krb5_error_code +hmac(krb5_context context, + struct checksum_type *cm, + const void *data, + size_t len, + unsigned usage, + struct key_data *keyblock, + Checksum *result) +{ + unsigned char *ipad, *opad; + unsigned char *key; + size_t key_len; + int i; + + ipad = malloc(cm->blocksize + len); + if (ipad == NULL) + return ENOMEM; + opad = malloc(cm->blocksize + cm->checksumsize); + if (opad == NULL) { + free(ipad); + return ENOMEM; + } + memset(ipad, 0x36, cm->blocksize); + memset(opad, 0x5c, cm->blocksize); + + if(keyblock->key->keyvalue.length > cm->blocksize){ + (*cm->checksum)(context, + keyblock, + keyblock->key->keyvalue.data, + keyblock->key->keyvalue.length, + usage, + result); + key = result->checksum.data; + key_len = result->checksum.length; + } else { + key = keyblock->key->keyvalue.data; + key_len = keyblock->key->keyvalue.length; + } + for(i = 0; i < key_len; i++){ + ipad[i] ^= key[i]; + opad[i] ^= key[i]; + } + memcpy(ipad + cm->blocksize, data, len); + (*cm->checksum)(context, keyblock, ipad, cm->blocksize + len, + usage, result); + memcpy(opad + cm->blocksize, result->checksum.data, + result->checksum.length); + (*cm->checksum)(context, keyblock, opad, + cm->blocksize + cm->checksumsize, usage, result); + memset(ipad, 0, cm->blocksize + len); + free(ipad); + memset(opad, 0, cm->blocksize + cm->checksumsize); + free(opad); + + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_hmac(krb5_context context, + krb5_cksumtype cktype, + const void *data, + size_t len, + unsigned usage, + krb5_keyblock *key, + Checksum *result) +{ + struct checksum_type *c = _find_checksum(cktype); + struct key_data kd; + krb5_error_code ret; + + if (c == NULL) { + krb5_set_error_string (context, "checksum type %d not supported", + cktype); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + + kd.key = key; + kd.schedule = NULL; + + ret = hmac(context, c, data, len, usage, &kd, result); + + if (kd.schedule) + krb5_free_data(context, kd.schedule); + + return ret; + } + +static void +SP_HMAC_SHA1_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *result) +{ + struct checksum_type *c = _find_checksum(CKSUMTYPE_SHA1); + Checksum res; + char sha1_data[20]; + krb5_error_code ret; + + res.checksum.data = sha1_data; + res.checksum.length = sizeof(sha1_data); + + ret = hmac(context, c, data, len, usage, key, &res); + if (ret) + krb5_abortx(context, "hmac failed"); + memcpy(result->checksum.data, res.checksum.data, result->checksum.length); +} + +/* + * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt + */ + +static void +HMAC_MD5_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *result) +{ + MD5_CTX md5; + struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); + const char signature[] = "signaturekey"; + Checksum ksign_c; + struct key_data ksign; + krb5_keyblock kb; + unsigned char t[4]; + unsigned char tmp[16]; + unsigned char ksign_c_data[16]; + krb5_error_code ret; + + ksign_c.checksum.length = sizeof(ksign_c_data); + ksign_c.checksum.data = ksign_c_data; + ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c); + if (ret) + krb5_abortx(context, "hmac failed"); + ksign.key = &kb; + kb.keyvalue = ksign_c.checksum; + MD5_Init (&md5); + t[0] = (usage >> 0) & 0xFF; + t[1] = (usage >> 8) & 0xFF; + t[2] = (usage >> 16) & 0xFF; + t[3] = (usage >> 24) & 0xFF; + MD5_Update (&md5, t, 4); + MD5_Update (&md5, data, len); + MD5_Final (tmp, &md5); + ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result); + if (ret) + krb5_abortx(context, "hmac failed"); +} + +/* + * same as previous but being used while encrypting. + */ + +static void +HMAC_MD5_checksum_enc(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *result) +{ + struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); + Checksum ksign_c; + struct key_data ksign; + krb5_keyblock kb; + unsigned char t[4]; + unsigned char ksign_c_data[16]; + krb5_error_code ret; + + t[0] = (usage >> 0) & 0xFF; + t[1] = (usage >> 8) & 0xFF; + t[2] = (usage >> 16) & 0xFF; + t[3] = (usage >> 24) & 0xFF; + + ksign_c.checksum.length = sizeof(ksign_c_data); + ksign_c.checksum.data = ksign_c_data; + ret = hmac(context, c, t, sizeof(t), 0, key, &ksign_c); + if (ret) + krb5_abortx(context, "hmac failed"); + ksign.key = &kb; + kb.keyvalue = ksign_c.checksum; + ret = hmac(context, c, data, len, 0, &ksign, result); + if (ret) + krb5_abortx(context, "hmac failed"); +} + +static struct checksum_type checksum_none = { + CKSUMTYPE_NONE, + "none", + 1, + 0, + 0, + NONE_checksum, + NULL +}; +static struct checksum_type checksum_crc32 = { + CKSUMTYPE_CRC32, + "crc32", + 1, + 4, + 0, + CRC32_checksum, + NULL +}; +static struct checksum_type checksum_rsa_md4 = { + CKSUMTYPE_RSA_MD4, + "rsa-md4", + 64, + 16, + F_CPROOF, + RSA_MD4_checksum, + NULL +}; +static struct checksum_type checksum_rsa_md4_des = { + CKSUMTYPE_RSA_MD4_DES, + "rsa-md4-des", + 64, + 24, + F_KEYED | F_CPROOF | F_VARIANT, + RSA_MD4_DES_checksum, + RSA_MD4_DES_verify +}; +#if 0 +static struct checksum_type checksum_des_mac = { + CKSUMTYPE_DES_MAC, + "des-mac", + 0, + 0, + 0, + DES_MAC_checksum +}; +static struct checksum_type checksum_des_mac_k = { + CKSUMTYPE_DES_MAC_K, + "des-mac-k", + 0, + 0, + 0, + DES_MAC_K_checksum +}; +static struct checksum_type checksum_rsa_md4_des_k = { + CKSUMTYPE_RSA_MD4_DES_K, + "rsa-md4-des-k", + 0, + 0, + 0, + RSA_MD4_DES_K_checksum, + RSA_MD4_DES_K_verify +}; +#endif +static struct checksum_type checksum_rsa_md5 = { + CKSUMTYPE_RSA_MD5, + "rsa-md5", + 64, + 16, + F_CPROOF, + RSA_MD5_checksum, + NULL +}; +static struct checksum_type checksum_rsa_md5_des = { + CKSUMTYPE_RSA_MD5_DES, + "rsa-md5-des", + 64, + 24, + F_KEYED | F_CPROOF | F_VARIANT, + RSA_MD5_DES_checksum, + RSA_MD5_DES_verify +}; +static struct checksum_type checksum_rsa_md5_des3 = { + CKSUMTYPE_RSA_MD5_DES3, + "rsa-md5-des3", + 64, + 24, + F_KEYED | F_CPROOF | F_VARIANT, + RSA_MD5_DES3_checksum, + RSA_MD5_DES3_verify +}; +static struct checksum_type checksum_sha1 = { + CKSUMTYPE_SHA1, + "sha1", + 64, + 20, + F_CPROOF, + SHA1_checksum, + NULL +}; +static struct checksum_type checksum_hmac_sha1_des3 = { + CKSUMTYPE_HMAC_SHA1_DES3, + "hmac-sha1-des3", + 64, + 20, + F_KEYED | F_CPROOF | F_DERIVED, + SP_HMAC_SHA1_checksum, + NULL +}; + +static struct checksum_type checksum_hmac_sha1_aes128 = { + CKSUMTYPE_HMAC_SHA1_96_AES_128, + "hmac-sha1-96-aes128", + 64, + 12, + F_KEYED | F_CPROOF | F_DERIVED, + SP_HMAC_SHA1_checksum, + NULL +}; + +static struct checksum_type checksum_hmac_sha1_aes256 = { + CKSUMTYPE_HMAC_SHA1_96_AES_256, + "hmac-sha1-96-aes256", + 64, + 12, + F_KEYED | F_CPROOF | F_DERIVED, + SP_HMAC_SHA1_checksum, + NULL +}; + +static struct checksum_type checksum_hmac_md5 = { + CKSUMTYPE_HMAC_MD5, + "hmac-md5", + 64, + 16, + F_KEYED | F_CPROOF, + HMAC_MD5_checksum, + NULL +}; + +static struct checksum_type checksum_hmac_md5_enc = { + CKSUMTYPE_HMAC_MD5_ENC, + "hmac-md5-enc", + 64, + 16, + F_KEYED | F_CPROOF | F_PSEUDO, + HMAC_MD5_checksum_enc, + NULL +}; + +static struct checksum_type *checksum_types[] = { + &checksum_none, + &checksum_crc32, + &checksum_rsa_md4, + &checksum_rsa_md4_des, +#if 0 + &checksum_des_mac, + &checksum_des_mac_k, + &checksum_rsa_md4_des_k, +#endif + &checksum_rsa_md5, + &checksum_rsa_md5_des, + &checksum_rsa_md5_des3, + &checksum_sha1, + &checksum_hmac_sha1_des3, + &checksum_hmac_sha1_aes128, + &checksum_hmac_sha1_aes256, + &checksum_hmac_md5, + &checksum_hmac_md5_enc +}; + +static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]); + +static struct checksum_type * +_find_checksum(krb5_cksumtype type) +{ + int i; + for(i = 0; i < num_checksums; i++) + if(checksum_types[i]->type == type) + return checksum_types[i]; + return NULL; +} + +static krb5_error_code +get_checksum_key(krb5_context context, + krb5_crypto crypto, + unsigned usage, /* not krb5_key_usage */ + struct checksum_type *ct, + struct key_data **key) +{ + krb5_error_code ret = 0; + + if(ct->flags & F_DERIVED) + ret = _get_derived_key(context, crypto, usage, key); + else if(ct->flags & F_VARIANT) { + int i; + + *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */); + if(*key == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key); + if(ret) + return ret; + for(i = 0; i < (*key)->key->keyvalue.length; i++) + ((unsigned char*)(*key)->key->keyvalue.data)[i] ^= 0xF0; + } else { + *key = &crypto->key; + } + if(ret == 0) + ret = _key_schedule(context, *key, crypto->params); + return ret; +} + +static krb5_error_code +create_checksum (krb5_context context, + struct checksum_type *ct, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + Checksum *result) +{ + krb5_error_code ret; + struct key_data *dkey; + int keyed_checksum; + + if (ct->flags & F_DISABLED) { + krb5_clear_error_string (context); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + keyed_checksum = (ct->flags & F_KEYED) != 0; + if(keyed_checksum && crypto == NULL) { + krb5_clear_error_string (context); + return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ + } + if(keyed_checksum) { + ret = get_checksum_key(context, crypto, usage, ct, &dkey); + if (ret) + return ret; + } else + dkey = NULL; + result->cksumtype = ct->type; + krb5_data_alloc(&result->checksum, ct->checksumsize); + (*ct->checksum)(context, dkey, data, len, usage, result); + return 0; +} + +static int +arcfour_checksum_p(struct checksum_type *ct, krb5_crypto crypto) +{ + return (ct->type == CKSUMTYPE_HMAC_MD5) && + (crypto->key.key->keytype == KEYTYPE_ARCFOUR); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_create_checksum(krb5_context context, + krb5_crypto crypto, + krb5_key_usage usage, + int type, + void *data, + size_t len, + Checksum *result) +{ + struct checksum_type *ct = NULL; + unsigned keyusage; + + /* type 0 -> pick from crypto */ + if (type) { + ct = _find_checksum(type); + } else if (crypto) { + ct = crypto->et->keyed_checksum; + if (ct == NULL) + ct = crypto->et->checksum; + } + + if(ct == NULL) { + krb5_set_error_string (context, "checksum type %d not supported", + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + + if (arcfour_checksum_p(ct, crypto)) { + keyusage = usage; + usage2arcfour(context, &keyusage); + } else + keyusage = CHECKSUM_USAGE(usage); + + return create_checksum(context, ct, crypto, keyusage, + data, len, result); +} + +static krb5_error_code +verify_checksum(krb5_context context, + krb5_crypto crypto, + unsigned usage, /* not krb5_key_usage */ + void *data, + size_t len, + Checksum *cksum) +{ + krb5_error_code ret; + struct key_data *dkey; + int keyed_checksum; + Checksum c; + struct checksum_type *ct; + + ct = _find_checksum(cksum->cksumtype); + if (ct == NULL || (ct->flags & F_DISABLED)) { + krb5_set_error_string (context, "checksum type %d not supported", + cksum->cksumtype); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + if(ct->checksumsize != cksum->checksum.length) { + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */ + } + keyed_checksum = (ct->flags & F_KEYED) != 0; + if(keyed_checksum && crypto == NULL) { + krb5_clear_error_string (context); + return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ + } + if(keyed_checksum) + ret = get_checksum_key(context, crypto, usage, ct, &dkey); + else + dkey = NULL; + if(ct->verify) + return (*ct->verify)(context, dkey, data, len, usage, cksum); + + ret = krb5_data_alloc (&c.checksum, ct->checksumsize); + if (ret) + return ret; + + (*ct->checksum)(context, dkey, data, len, usage, &c); + + if(c.checksum.length != cksum->checksum.length || + memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } else { + ret = 0; + } + krb5_data_free (&c.checksum); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_checksum(krb5_context context, + krb5_crypto crypto, + krb5_key_usage usage, + void *data, + size_t len, + Checksum *cksum) +{ + struct checksum_type *ct; + unsigned keyusage; + + ct = _find_checksum(cksum->cksumtype); + if(ct == NULL) { + krb5_set_error_string (context, "checksum type %d not supported", + cksum->cksumtype); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + + if (arcfour_checksum_p(ct, crypto)) { + keyusage = usage; + usage2arcfour(context, &keyusage); + } else + keyusage = CHECKSUM_USAGE(usage); + + return verify_checksum(context, crypto, keyusage, + data, len, cksum); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_get_checksum_type(krb5_context context, + krb5_crypto crypto, + krb5_cksumtype *type) +{ + struct checksum_type *ct = NULL; + + if (crypto != NULL) { + ct = crypto->et->keyed_checksum; + if (ct == NULL) + ct = crypto->et->checksum; + } + + if (ct == NULL) { + krb5_set_error_string (context, "checksum type not found"); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + + *type = ct->type; + + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_checksumsize(krb5_context context, + krb5_cksumtype type, + size_t *size) +{ + struct checksum_type *ct = _find_checksum(type); + if(ct == NULL) { + krb5_set_error_string (context, "checksum type %d not supported", + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + *size = ct->checksumsize; + return 0; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_checksum_is_keyed(krb5_context context, + krb5_cksumtype type) +{ + struct checksum_type *ct = _find_checksum(type); + if(ct == NULL) { + if (context) + krb5_set_error_string (context, "checksum type %d not supported", + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + return ct->flags & F_KEYED; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_checksum_is_collision_proof(krb5_context context, + krb5_cksumtype type) +{ + struct checksum_type *ct = _find_checksum(type); + if(ct == NULL) { + if (context) + krb5_set_error_string (context, "checksum type %d not supported", + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + return ct->flags & F_CPROOF; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_checksum_disable(krb5_context context, + krb5_cksumtype type) +{ + struct checksum_type *ct = _find_checksum(type); + if(ct == NULL) { + if (context) + krb5_set_error_string (context, "checksum type %d not supported", + type); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + ct->flags |= F_DISABLED; + return 0; +} + +/************************************************************ + * * + ************************************************************/ + +static krb5_error_code +NULL_encrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ivec) +{ + return 0; +} + +static krb5_error_code +DES_CBC_encrypt_null_ivec(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ignore_ivec) +{ + DES_cblock ivec; + DES_key_schedule *s = key->schedule->data; + memset(&ivec, 0, sizeof(ivec)); + DES_cbc_encrypt(data, data, len, s, &ivec, encryptp); + return 0; +} + +static krb5_error_code +DES_CBC_encrypt_key_ivec(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ignore_ivec) +{ + DES_cblock ivec; + DES_key_schedule *s = key->schedule->data; + memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); + DES_cbc_encrypt(data, data, len, s, &ivec, encryptp); + return 0; +} + +static krb5_error_code +DES3_CBC_encrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ivec) +{ + DES_cblock local_ivec; + DES_key_schedule *s = key->schedule->data; + if(ivec == NULL) { + ivec = &local_ivec; + memset(local_ivec, 0, sizeof(local_ivec)); + } + DES_ede3_cbc_encrypt(data, data, len, &s[0], &s[1], &s[2], ivec, encryptp); + return 0; +} + +static krb5_error_code +DES_CFB64_encrypt_null_ivec(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ignore_ivec) +{ + DES_cblock ivec; + int num = 0; + DES_key_schedule *s = key->schedule->data; + memset(&ivec, 0, sizeof(ivec)); + + DES_cfb64_encrypt(data, data, len, s, &ivec, &num, encryptp); + return 0; +} + +static krb5_error_code +DES_PCBC_encrypt_key_ivec(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ignore_ivec) +{ + DES_cblock ivec; + DES_key_schedule *s = key->schedule->data; + memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); + + DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp); + return 0; +} + +/* + * AES draft-raeburn-krb-rijndael-krb-02 + */ + +void KRB5_LIB_FUNCTION +_krb5_aes_cts_encrypt(const unsigned char *in, unsigned char *out, + size_t len, const void *aes_key, + unsigned char *ivec, const int encryptp) +{ + unsigned char tmp[AES_BLOCK_SIZE]; + const AES_KEY *key = aes_key; /* XXX remove this when we always have AES */ + int i; + + /* + * In the framework of kerberos, the length can never be shorter + * then at least one blocksize. + */ + + if (encryptp) { + + while(len > AES_BLOCK_SIZE) { + for (i = 0; i < AES_BLOCK_SIZE; i++) + tmp[i] = in[i] ^ ivec[i]; + AES_encrypt(tmp, out, key); + memcpy(ivec, out, AES_BLOCK_SIZE); + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + for (i = 0; i < len; i++) + tmp[i] = in[i] ^ ivec[i]; + for (; i < AES_BLOCK_SIZE; i++) + tmp[i] = 0 ^ ivec[i]; + + AES_encrypt(tmp, out - AES_BLOCK_SIZE, key); + + memcpy(out, ivec, len); + memcpy(ivec, out - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + } else { + unsigned char tmp2[AES_BLOCK_SIZE]; + unsigned char tmp3[AES_BLOCK_SIZE]; + + while(len > AES_BLOCK_SIZE * 2) { + memcpy(tmp, in, AES_BLOCK_SIZE); + AES_decrypt(in, out, key); + for (i = 0; i < AES_BLOCK_SIZE; i++) + out[i] ^= ivec[i]; + memcpy(ivec, tmp, AES_BLOCK_SIZE); + len -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + len -= AES_BLOCK_SIZE; + + memcpy(tmp, in, AES_BLOCK_SIZE); /* save last iv */ + AES_decrypt(in, tmp2, key); + + memcpy(tmp3, in + AES_BLOCK_SIZE, len); + memcpy(tmp3 + len, tmp2 + len, AES_BLOCK_SIZE - len); /* xor 0 */ + + for (i = 0; i < len; i++) + out[i + AES_BLOCK_SIZE] = tmp2[i] ^ tmp3[i]; + + AES_decrypt(tmp3, out, key); + for (i = 0; i < AES_BLOCK_SIZE; i++) + out[i] ^= ivec[i]; + memcpy(ivec, tmp, AES_BLOCK_SIZE); + } +} + +static krb5_error_code +AES_CTS_encrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ivec) +{ + struct krb5_aes_schedule *aeskey = key->schedule->data; + char local_ivec[AES_BLOCK_SIZE]; + AES_KEY *k; + + if (encryptp) + k = &aeskey->ekey; + else + k = &aeskey->dkey; + + if (len < AES_BLOCK_SIZE) + krb5_abortx(context, "invalid use of AES_CTS_encrypt"); + if (len == AES_BLOCK_SIZE) { + if (encryptp) + AES_encrypt(data, data, k); + else + AES_decrypt(data, data, k); + } else { + if(ivec == NULL) { + memset(local_ivec, 0, sizeof(local_ivec)); + ivec = local_ivec; + } + _krb5_aes_cts_encrypt(data, data, len, k, ivec, encryptp); + } + + return 0; +} + +static krb5_error_code +AES_CBC_encrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ivec) +{ + struct krb5_aes_schedule *aeskey = key->schedule->data; + char local_ivec[AES_BLOCK_SIZE]; + AES_KEY *k; + + if (encryptp) + k = &aeskey->ekey; + else + k = &aeskey->dkey; + + if(ivec == NULL) { + ivec = &local_ivec; + memset(local_ivec, 0, sizeof(local_ivec)); + } + AES_cbc_encrypt(data, data, len, k, ivec, encryptp); + return 0; +} + +/* + * RC2 + */ + +static krb5_error_code +RC2_CBC_encrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ivec) +{ + unsigned char local_ivec[8]; + RC2_KEY *s = key->schedule->data; + if(ivec == NULL) { + ivec = &local_ivec; + memset(local_ivec, 0, sizeof(local_ivec)); + } + RC2_cbc_encrypt(data, data, len, s, ivec, encryptp); + return 0; +} + +/* + * section 6 of draft-brezak-win2k-krb-rc4-hmac-03 + * + * warning: not for small children + */ + +static krb5_error_code +ARCFOUR_subencrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + unsigned usage, + void *ivec) +{ + struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); + Checksum k1_c, k2_c, k3_c, cksum; + struct key_data ke; + krb5_keyblock kb; + unsigned char t[4]; + RC4_KEY rc4_key; + unsigned char *cdata = data; + unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; + krb5_error_code ret; + + t[0] = (usage >> 0) & 0xFF; + t[1] = (usage >> 8) & 0xFF; + t[2] = (usage >> 16) & 0xFF; + t[3] = (usage >> 24) & 0xFF; + + k1_c.checksum.length = sizeof(k1_c_data); + k1_c.checksum.data = k1_c_data; + + ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); + if (ret) + krb5_abortx(context, "hmac failed"); + + memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); + + k2_c.checksum.length = sizeof(k2_c_data); + k2_c.checksum.data = k2_c_data; + + ke.key = &kb; + kb.keyvalue = k2_c.checksum; + + cksum.checksum.length = 16; + cksum.checksum.data = data; + + ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); + if (ret) + krb5_abortx(context, "hmac failed"); + + ke.key = &kb; + kb.keyvalue = k1_c.checksum; + + k3_c.checksum.length = sizeof(k3_c_data); + k3_c.checksum.data = k3_c_data; + + ret = hmac(NULL, c, data, 16, 0, &ke, &k3_c); + if (ret) + krb5_abortx(context, "hmac failed"); + + RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data); + RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16); + memset (k1_c_data, 0, sizeof(k1_c_data)); + memset (k2_c_data, 0, sizeof(k2_c_data)); + memset (k3_c_data, 0, sizeof(k3_c_data)); + return 0; +} + +static krb5_error_code +ARCFOUR_subdecrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + unsigned usage, + void *ivec) +{ + struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); + Checksum k1_c, k2_c, k3_c, cksum; + struct key_data ke; + krb5_keyblock kb; + unsigned char t[4]; + RC4_KEY rc4_key; + unsigned char *cdata = data; + unsigned char k1_c_data[16], k2_c_data[16], k3_c_data[16]; + unsigned char cksum_data[16]; + krb5_error_code ret; + + t[0] = (usage >> 0) & 0xFF; + t[1] = (usage >> 8) & 0xFF; + t[2] = (usage >> 16) & 0xFF; + t[3] = (usage >> 24) & 0xFF; + + k1_c.checksum.length = sizeof(k1_c_data); + k1_c.checksum.data = k1_c_data; + + ret = hmac(NULL, c, t, sizeof(t), 0, key, &k1_c); + if (ret) + krb5_abortx(context, "hmac failed"); + + memcpy (k2_c_data, k1_c_data, sizeof(k1_c_data)); + + k2_c.checksum.length = sizeof(k2_c_data); + k2_c.checksum.data = k2_c_data; + + ke.key = &kb; + kb.keyvalue = k1_c.checksum; + + k3_c.checksum.length = sizeof(k3_c_data); + k3_c.checksum.data = k3_c_data; + + ret = hmac(NULL, c, cdata, 16, 0, &ke, &k3_c); + if (ret) + krb5_abortx(context, "hmac failed"); + + RC4_set_key (&rc4_key, k3_c.checksum.length, k3_c.checksum.data); + RC4 (&rc4_key, len - 16, cdata + 16, cdata + 16); + + ke.key = &kb; + kb.keyvalue = k2_c.checksum; + + cksum.checksum.length = 16; + cksum.checksum.data = cksum_data; + + ret = hmac(NULL, c, cdata + 16, len - 16, 0, &ke, &cksum); + if (ret) + krb5_abortx(context, "hmac failed"); + + memset (k1_c_data, 0, sizeof(k1_c_data)); + memset (k2_c_data, 0, sizeof(k2_c_data)); + memset (k3_c_data, 0, sizeof(k3_c_data)); + + if (memcmp (cksum.checksum.data, data, 16) != 0) { + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_BAD_INTEGRITY; + } else { + return 0; + } +} + +/* + * convert the usage numbers used in + * draft-ietf-cat-kerb-key-derivation-00.txt to the ones in + * draft-brezak-win2k-krb-rc4-hmac-04.txt + */ + +static krb5_error_code +usage2arcfour (krb5_context context, unsigned *usage) +{ + switch (*usage) { + case KRB5_KU_AS_REP_ENC_PART : /* 3 */ + case KRB5_KU_TGS_REP_ENC_PART_SUB_KEY : /* 9 */ + *usage = 8; + return 0; + case KRB5_KU_USAGE_SEAL : /* 22 */ + *usage = 13; + return 0; + case KRB5_KU_USAGE_SIGN : /* 23 */ + *usage = 15; + return 0; + case KRB5_KU_USAGE_SEQ: /* 24 */ + *usage = 0; + return 0; + default : + return 0; + } +} + +static krb5_error_code +ARCFOUR_encrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ivec) +{ + krb5_error_code ret; + unsigned keyusage = usage; + + if((ret = usage2arcfour (context, &keyusage)) != 0) + return ret; + + if (encryptp) + return ARCFOUR_subencrypt (context, key, data, len, keyusage, ivec); + else + return ARCFOUR_subdecrypt (context, key, data, len, keyusage, ivec); +} + + +/* + * these should currently be in reverse preference order. + * (only relevant for !F_PSEUDO) */ + +static struct encryption_type enctype_null = { + ETYPE_NULL, + "null", + NULL, + 1, + 1, + 0, + &keytype_null, + &checksum_none, + NULL, + F_DISABLED, + NULL_encrypt, +}; +static struct encryption_type enctype_des_cbc_crc = { + ETYPE_DES_CBC_CRC, + "des-cbc-crc", + NULL, + 8, + 8, + 8, + &keytype_des, + &checksum_crc32, + NULL, + 0, + DES_CBC_encrypt_key_ivec, +}; +static struct encryption_type enctype_des_cbc_md4 = { + ETYPE_DES_CBC_MD4, + "des-cbc-md4", + NULL, + 8, + 8, + 8, + &keytype_des, + &checksum_rsa_md4, + &checksum_rsa_md4_des, + 0, + DES_CBC_encrypt_null_ivec, +}; +static struct encryption_type enctype_des_cbc_md5 = { + ETYPE_DES_CBC_MD5, + "des-cbc-md5", + NULL, + 8, + 8, + 8, + &keytype_des, + &checksum_rsa_md5, + &checksum_rsa_md5_des, + 0, + DES_CBC_encrypt_null_ivec, +}; +static struct encryption_type enctype_arcfour_hmac_md5 = { + ETYPE_ARCFOUR_HMAC_MD5, + "arcfour-hmac-md5", + NULL, + 1, + 1, + 8, + &keytype_arcfour, + &checksum_hmac_md5, + NULL, + F_SPECIAL, + ARCFOUR_encrypt +}; +static struct encryption_type enctype_des3_cbc_md5 = { + ETYPE_DES3_CBC_MD5, + "des3-cbc-md5", + NULL, + 8, + 8, + 8, + &keytype_des3, + &checksum_rsa_md5, + &checksum_rsa_md5_des3, + 0, + DES3_CBC_encrypt, +}; +static struct encryption_type enctype_des3_cbc_sha1 = { + ETYPE_DES3_CBC_SHA1, + "des3-cbc-sha1", + NULL, + 8, + 8, + 8, + &keytype_des3_derived, + &checksum_sha1, + &checksum_hmac_sha1_des3, + F_DERIVED, + DES3_CBC_encrypt, +}; +static struct encryption_type enctype_old_des3_cbc_sha1 = { + ETYPE_OLD_DES3_CBC_SHA1, + "old-des3-cbc-sha1", + NULL, + 8, + 8, + 8, + &keytype_des3, + &checksum_sha1, + &checksum_hmac_sha1_des3, + 0, + DES3_CBC_encrypt, +}; +static struct encryption_type enctype_aes128_cts_hmac_sha1 = { + ETYPE_AES128_CTS_HMAC_SHA1_96, + "aes128-cts-hmac-sha1-96", + NULL, + 16, + 1, + 16, + &keytype_aes128, + &checksum_sha1, + &checksum_hmac_sha1_aes128, + F_DERIVED, + AES_CTS_encrypt, +}; +static struct encryption_type enctype_aes256_cts_hmac_sha1 = { + ETYPE_AES256_CTS_HMAC_SHA1_96, + "aes256-cts-hmac-sha1-96", + NULL, + 16, + 1, + 16, + &keytype_aes256, + &checksum_sha1, + &checksum_hmac_sha1_aes256, + F_DERIVED, + AES_CTS_encrypt, +}; +static unsigned aes_128_cbc_num[] = { 2, 16, 840, 1, 101, 3, 4, 1, 2 }; +static heim_oid aes_128_cbc_oid = kcrypto_oid_enc(aes_128_cbc_num); +static struct encryption_type enctype_aes128_cbc_none = { + ETYPE_AES128_CBC_NONE, + "aes128-cbc-none", + &aes_128_cbc_oid, + 16, + 16, + 16, + &keytype_aes128, + &checksum_none, + NULL, + F_PSEUDO|F_PADCMS, + AES_CBC_encrypt, +}; +static unsigned aes_192_cbc_num[] = { 2, 16, 840, 1, 101, 3, 4, 1, 22 }; +static heim_oid aes_192_cbc_oid = kcrypto_oid_enc(aes_192_cbc_num); +static struct encryption_type enctype_aes192_cbc_none = { + ETYPE_AES192_CBC_NONE, + "aes192-cbc-none", + &aes_192_cbc_oid, + 16, + 16, + 16, + &keytype_aes192, + &checksum_none, + NULL, + F_PSEUDO|F_PADCMS, + AES_CBC_encrypt, +}; +static unsigned aes_256_cbc_num[] = { 2, 16, 840, 1, 101, 3, 4, 1, 42 }; +static heim_oid aes_256_cbc_oid = kcrypto_oid_enc(aes_256_cbc_num); +static struct encryption_type enctype_aes256_cbc_none = { + ETYPE_AES256_CBC_NONE, + "aes256-cbc-none", + &aes_256_cbc_oid, + 16, + 16, + 16, + &keytype_aes256, + &checksum_none, + NULL, + F_PSEUDO|F_PADCMS, + AES_CBC_encrypt, +}; +static struct encryption_type enctype_des_cbc_none = { + ETYPE_DES_CBC_NONE, + "des-cbc-none", + NULL, + 8, + 8, + 0, + &keytype_des, + &checksum_none, + NULL, + F_PSEUDO, + DES_CBC_encrypt_null_ivec, +}; +static struct encryption_type enctype_des_cfb64_none = { + ETYPE_DES_CFB64_NONE, + "des-cfb64-none", + NULL, + 1, + 1, + 0, + &keytype_des, + &checksum_none, + NULL, + F_PSEUDO, + DES_CFB64_encrypt_null_ivec, +}; +static struct encryption_type enctype_des_pcbc_none = { + ETYPE_DES_PCBC_NONE, + "des-pcbc-none", + NULL, + 8, + 8, + 0, + &keytype_des, + &checksum_none, + NULL, + F_PSEUDO, + DES_PCBC_encrypt_key_ivec, +}; +static unsigned des_ede3_cbc_num[] = { 1, 2, 840, 113549, 3, 7 }; +static heim_oid des_ede3_cbc_oid = kcrypto_oid_enc(des_ede3_cbc_num); +static struct encryption_type enctype_des3_cbc_none_cms = { + ETYPE_DES3_CBC_NONE_CMS, + "des3-cbc-none-cms", + &des_ede3_cbc_oid, + 8, + 8, + 0, + &keytype_des3_derived, + &checksum_none, + NULL, + F_PSEUDO|F_PADCMS, + DES3_CBC_encrypt, +}; +static struct encryption_type enctype_des3_cbc_none = { + ETYPE_DES3_CBC_NONE, + "des3-cbc-none", + NULL, + 8, + 8, + 0, + &keytype_des3_derived, + &checksum_none, + NULL, + F_PSEUDO, + DES3_CBC_encrypt, +}; +static unsigned rc2CBC_num[] = { 1, 2, 840, 113549, 3, 2 }; +static heim_oid rc2CBC_oid = kcrypto_oid_enc(rc2CBC_num); +static struct encryption_type enctype_rc2_cbc_none = { + ETYPE_RC2_CBC_NONE, + "rc2-cbc-none", + &rc2CBC_oid, + 8, + 8, + 0, + &keytype_rc2, + &checksum_none, + NULL, + F_PSEUDO|F_PADCMS, + RC2_CBC_encrypt, +}; + +static struct encryption_type *etypes[] = { + &enctype_null, + &enctype_des_cbc_crc, + &enctype_des_cbc_md4, + &enctype_des_cbc_md5, + &enctype_arcfour_hmac_md5, + &enctype_des3_cbc_md5, + &enctype_des3_cbc_sha1, + &enctype_old_des3_cbc_sha1, + &enctype_aes128_cts_hmac_sha1, + &enctype_aes256_cts_hmac_sha1, + &enctype_aes128_cbc_none, + &enctype_aes192_cbc_none, + &enctype_aes256_cbc_none, + &enctype_des_cbc_none, + &enctype_des_cfb64_none, + &enctype_des_pcbc_none, + &enctype_des3_cbc_none, + &enctype_des3_cbc_none_cms, + &enctype_rc2_cbc_none +}; + +static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]); + + +static struct encryption_type * +_find_enctype(krb5_enctype type) +{ + int i; + for(i = 0; i < num_etypes; i++) + if(etypes[i]->type == type) + return etypes[i]; + return NULL; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_to_string(krb5_context context, + krb5_enctype etype, + char **string) +{ + struct encryption_type *e; + e = _find_enctype(etype); + if(e == NULL) { + krb5_set_error_string (context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + *string = strdup(e->name); + if(*string == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_enctype(krb5_context context, + const char *string, + krb5_enctype *etype) +{ + int i; + for(i = 0; i < num_etypes; i++) + if(strcasecmp(etypes[i]->name, string) == 0){ + *etype = etypes[i]->type; + return 0; + } + krb5_set_error_string (context, "encryption type %s not supported", + string); + return KRB5_PROG_ETYPE_NOSUPP; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_to_oid(krb5_context context, + krb5_enctype etype, + heim_oid *oid) +{ + struct encryption_type *et = _find_enctype(etype); + if(et == NULL) { + krb5_set_error_string (context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + if(et->oid == NULL) { + krb5_set_error_string (context, "%s have not oid", et->name); + return KRB5_PROG_ETYPE_NOSUPP; + } + krb5_clear_error_string(context); + return copy_oid(et->oid, oid); +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_oid_to_enctype(krb5_context context, + const heim_oid *oid, + krb5_enctype *etype) +{ + int i; + for(i = 0; i < num_etypes; i++) { + if(etypes[i]->oid && heim_oid_cmp(etypes[i]->oid, oid) == 0) { + *etype = etypes[i]->type; + return 0; + } + } + krb5_set_error_string(context, "enctype for oid not supported"); + return KRB5_PROG_ETYPE_NOSUPP; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_to_keytype(krb5_context context, + krb5_enctype etype, + krb5_keytype *keytype) +{ + struct encryption_type *e = _find_enctype(etype); + if(e == NULL) { + krb5_set_error_string (context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + *keytype = e->keytype->type; /* XXX */ + return 0; +} + +#if 0 +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctype(krb5_context context, + krb5_keytype keytype, + krb5_enctype *etype) +{ + struct key_type *kt = _find_keytype(keytype); + krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype); + if(kt == NULL) + return KRB5_PROG_KEYTYPE_NOSUPP; + *etype = kt->best_etype; + return 0; +} +#endif + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctypes (krb5_context context, + krb5_keytype keytype, + unsigned *len, + krb5_enctype **val) +{ + int i; + unsigned n = 0; + krb5_enctype *ret; + + for (i = num_etypes - 1; i >= 0; --i) { + if (etypes[i]->keytype->type == keytype + && !(etypes[i]->flags & F_PSEUDO)) + ++n; + } + ret = malloc(n * sizeof(*ret)); + if (ret == NULL && n != 0) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + n = 0; + for (i = num_etypes - 1; i >= 0; --i) { + if (etypes[i]->keytype->type == keytype + && !(etypes[i]->flags & F_PSEUDO)) + ret[n++] = etypes[i]->type; + } + *len = n; + *val = ret; + return 0; +} + +/* + * First take the configured list of etypes for `keytype' if available, + * else, do `krb5_keytype_to_enctypes'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctypes_default (krb5_context context, + krb5_keytype keytype, + unsigned *len, + krb5_enctype **val) +{ + int i, n; + krb5_enctype *ret; + + if (keytype != KEYTYPE_DES || context->etypes_des == NULL) + return krb5_keytype_to_enctypes (context, keytype, len, val); + + for (n = 0; context->etypes_des[n]; ++n) + ; + ret = malloc (n * sizeof(*ret)); + if (ret == NULL && n != 0) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + for (i = 0; i < n; ++i) + ret[i] = context->etypes_des[i]; + *len = n; + *val = ret; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_valid(krb5_context context, + krb5_enctype etype) +{ + struct encryption_type *e = _find_enctype(etype); + if(e == NULL) { + krb5_set_error_string (context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + if (e->flags & F_DISABLED) { + krb5_set_error_string (context, "encryption type %s is disabled", + e->name); + return KRB5_PROG_ETYPE_NOSUPP; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cksumtype_valid(krb5_context context, + krb5_cksumtype ctype) +{ + struct checksum_type *c = _find_checksum(ctype); + if (c == NULL) { + krb5_set_error_string (context, "checksum type %d not supported", + ctype); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + if (c->flags & F_DISABLED) { + krb5_set_error_string (context, "checksum type %s is disabled", + c->name); + return KRB5_PROG_SUMTYPE_NOSUPP; + } + return 0; +} + + +/* if two enctypes have compatible keys */ +krb5_boolean KRB5_LIB_FUNCTION +krb5_enctypes_compatible_keys(krb5_context context, + krb5_enctype etype1, + krb5_enctype etype2) +{ + struct encryption_type *e1 = _find_enctype(etype1); + struct encryption_type *e2 = _find_enctype(etype2); + return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype; +} + +static krb5_boolean +derived_crypto(krb5_context context, + krb5_crypto crypto) +{ + return (crypto->et->flags & F_DERIVED) != 0; +} + +static krb5_boolean +special_crypto(krb5_context context, + krb5_crypto crypto) +{ + return (crypto->et->flags & F_SPECIAL) != 0; +} + +#define CHECKSUMSIZE(C) ((C)->checksumsize) +#define CHECKSUMTYPE(C) ((C)->type) + +static krb5_error_code +encrypt_internal_derived(krb5_context context, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + size_t sz, block_sz, checksum_sz, total_sz; + Checksum cksum; + unsigned char *p, *q; + krb5_error_code ret; + struct key_data *dkey; + const struct encryption_type *et = crypto->et; + + checksum_sz = CHECKSUMSIZE(et->keyed_checksum); + + sz = et->confoundersize + len; + block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ + total_sz = block_sz + checksum_sz; + p = calloc(1, total_sz); + if(p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + q = p; + krb5_generate_random_block(q, et->confoundersize); /* XXX */ + q += et->confoundersize; + memcpy(q, data, len); + + ret = create_checksum(context, + et->keyed_checksum, + crypto, + INTEGRITY_USAGE(usage), + p, + block_sz, + &cksum); + if(ret == 0 && cksum.checksum.length != checksum_sz) { + free_Checksum (&cksum); + krb5_clear_error_string (context); + ret = KRB5_CRYPTO_INTERNAL; + } + if(ret) + goto fail; + memcpy(p + block_sz, cksum.checksum.data, cksum.checksum.length); + free_Checksum (&cksum); + ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); + if(ret) + goto fail; + ret = _key_schedule(context, dkey, crypto->params); + if(ret) + goto fail; +#ifdef CRYPTO_DEBUG + krb5_crypto_debug(context, 1, block_sz, dkey->key); +#endif + ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec); + if (ret) + goto fail; + result->data = p; + result->length = total_sz; + return 0; + fail: + memset(p, 0, total_sz); + free(p); + return ret; +} + + +static krb5_error_code +encrypt_internal(krb5_context context, + krb5_crypto crypto, + void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + size_t sz, block_sz, checksum_sz, padsize = 0; + Checksum cksum; + unsigned char *p, *q; + krb5_error_code ret; + const struct encryption_type *et = crypto->et; + + checksum_sz = CHECKSUMSIZE(et->checksum); + + sz = et->confoundersize + checksum_sz + len; + block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ + if ((et->flags & F_PADCMS) && et->padsize != 1) { + padsize = et->padsize - (sz % et->padsize); + if (padsize == et->padsize) + block_sz += et->padsize; + } + p = calloc(1, block_sz); + if(p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + q = p; + krb5_generate_random_block(q, et->confoundersize); /* XXX */ + q += et->confoundersize; + memset(q, 0, checksum_sz); + q += checksum_sz; + memcpy(q, data, len); + + ret = create_checksum(context, + et->checksum, + crypto, + 0, + p, + block_sz, + &cksum); + if(ret == 0 && cksum.checksum.length != checksum_sz) { + krb5_clear_error_string (context); + free_Checksum(&cksum); + ret = KRB5_CRYPTO_INTERNAL; + } + if(ret) + goto fail; + memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length); + free_Checksum(&cksum); + ret = _key_schedule(context, &crypto->key, crypto->params); + if(ret) + goto fail; + if (et->flags & F_PADCMS) { + int i; + q = p + len + checksum_sz + et->confoundersize; + for (i = 0; i < padsize; i++) + q[i] = padsize; + } +#ifdef CRYPTO_DEBUG + krb5_crypto_debug(context, 1, block_sz, crypto->key.key); +#endif + ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec); + if (ret) { + memset(p, 0, block_sz); + free(p); + return ret; + } + result->data = p; + result->length = block_sz; + return 0; + fail: + memset(p, 0, block_sz); + free(p); + return ret; +} + +static krb5_error_code +encrypt_internal_special(krb5_context context, + krb5_crypto crypto, + int usage, + void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + struct encryption_type *et = crypto->et; + size_t cksum_sz = CHECKSUMSIZE(et->checksum); + size_t sz = len + cksum_sz + et->confoundersize; + char *tmp, *p; + krb5_error_code ret; + + tmp = malloc (sz); + if (tmp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + p = tmp; + memset (p, 0, cksum_sz); + p += cksum_sz; + krb5_generate_random_block(p, et->confoundersize); + p += et->confoundersize; + memcpy (p, data, len); + ret = (*et->encrypt)(context, &crypto->key, tmp, sz, TRUE, usage, ivec); + if (ret) { + memset(tmp, 0, sz); + free(tmp); + return ret; + } + result->data = tmp; + result->length = sz; + return 0; +} + +static krb5_error_code +decrypt_internal_derived(krb5_context context, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + size_t checksum_sz; + Checksum cksum; + unsigned char *p; + krb5_error_code ret; + struct key_data *dkey; + struct encryption_type *et = crypto->et; + unsigned long l; + + checksum_sz = CHECKSUMSIZE(et->keyed_checksum); + if (len < checksum_sz) { + krb5_clear_error_string (context); + return EINVAL; /* XXX - better error code? */ + } + + if (((len - checksum_sz) % et->padsize) != 0) { + krb5_clear_error_string(context); + return KRB5_BAD_MSIZE; + } + + p = malloc(len); + if(len != 0 && p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(p, data, len); + + len -= checksum_sz; + + ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); + if(ret) { + free(p); + return ret; + } + ret = _key_schedule(context, dkey, crypto->params); + if(ret) { + free(p); + return ret; + } +#ifdef CRYPTO_DEBUG + krb5_crypto_debug(context, 0, len, dkey->key); +#endif + ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec); + if (ret) { + free(p); + return ret; + } + + cksum.checksum.data = p + len; + cksum.checksum.length = checksum_sz; + cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); + + ret = verify_checksum(context, + crypto, + INTEGRITY_USAGE(usage), + p, + len, + &cksum); + if(ret) { + free(p); + return ret; + } + l = len - et->confoundersize; + memmove(p, p + et->confoundersize, l); + result->data = realloc(p, l); + if(result->data == NULL) { + free(p); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + result->length = l; + return 0; +} + +static krb5_error_code +decrypt_internal(krb5_context context, + krb5_crypto crypto, + void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + krb5_error_code ret; + unsigned char *p; + Checksum cksum; + size_t checksum_sz, l; + struct encryption_type *et = crypto->et; + + if ((len % et->padsize) != 0) { + krb5_clear_error_string(context); + return KRB5_BAD_MSIZE; + } + + checksum_sz = CHECKSUMSIZE(et->checksum); + p = malloc(len); + if(len != 0 && p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(p, data, len); + + ret = _key_schedule(context, &crypto->key, crypto->params); + if(ret) { + free(p); + return ret; + } +#ifdef CRYPTO_DEBUG + krb5_crypto_debug(context, 0, len, crypto->key.key); +#endif + ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec); + if (ret) { + free(p); + return ret; + } + ret = krb5_data_copy(&cksum.checksum, p + et->confoundersize, checksum_sz); + if(ret) { + free(p); + return ret; + } + memset(p + et->confoundersize, 0, checksum_sz); + cksum.cksumtype = CHECKSUMTYPE(et->checksum); + ret = verify_checksum(context, NULL, 0, p, len, &cksum); + free_Checksum(&cksum); + if(ret) { + free(p); + return ret; + } + l = len - et->confoundersize - checksum_sz; + memmove(p, p + et->confoundersize + checksum_sz, l); + result->data = realloc(p, l); + if(result->data == NULL) { + free(p); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + result->length = l; + return 0; +} + +static krb5_error_code +decrypt_internal_special(krb5_context context, + krb5_crypto crypto, + int usage, + void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + struct encryption_type *et = crypto->et; + size_t cksum_sz = CHECKSUMSIZE(et->checksum); + size_t sz = len - cksum_sz - et->confoundersize; + unsigned char *p; + krb5_error_code ret; + + if ((len % et->padsize) != 0) { + krb5_clear_error_string(context); + return KRB5_BAD_MSIZE; + } + + p = malloc (len); + if (p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(p, data, len); + + ret = (*et->encrypt)(context, &crypto->key, p, len, FALSE, usage, ivec); + if (ret) { + free(p); + return ret; + } + + memmove (p, p + cksum_sz + et->confoundersize, sz); + result->data = realloc(p, sz); + if(result->data == NULL) { + free(p); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + result->length = sz; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt_ivec(krb5_context context, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + if(derived_crypto(context, crypto)) + return encrypt_internal_derived(context, crypto, usage, + data, len, result, ivec); + else if (special_crypto(context, crypto)) + return encrypt_internal_special (context, crypto, usage, + data, len, result, ivec); + else + return encrypt_internal(context, crypto, data, len, result, ivec); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt(krb5_context context, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + krb5_data *result) +{ + return krb5_encrypt_ivec(context, crypto, usage, data, len, result, NULL); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt_EncryptedData(krb5_context context, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + int kvno, + EncryptedData *result) +{ + result->etype = CRYPTO_ETYPE(crypto); + if(kvno){ + ALLOC(result->kvno, 1); + *result->kvno = kvno; + }else + result->kvno = NULL; + return krb5_encrypt(context, crypto, usage, data, len, &result->cipher); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_ivec(krb5_context context, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + krb5_data *result, + void *ivec) +{ + if(derived_crypto(context, crypto)) + return decrypt_internal_derived(context, crypto, usage, + data, len, result, ivec); + else if (special_crypto (context, crypto)) + return decrypt_internal_special(context, crypto, usage, + data, len, result, ivec); + else + return decrypt_internal(context, crypto, data, len, result, ivec); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt(krb5_context context, + krb5_crypto crypto, + unsigned usage, + void *data, + size_t len, + krb5_data *result) +{ + return krb5_decrypt_ivec (context, crypto, usage, data, len, result, + NULL); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_EncryptedData(krb5_context context, + krb5_crypto crypto, + unsigned usage, + const EncryptedData *e, + krb5_data *result) +{ + return krb5_decrypt(context, crypto, usage, + e->cipher.data, e->cipher.length, result); +} + +/************************************************************ + * * + ************************************************************/ + +#ifdef HAVE_OPENSSL +#include + +/* From openssl/crypto/rand/rand_lcl.h */ +#define ENTROPY_NEEDED 20 +static int +seed_something(void) +{ + char buf[1024], seedfile[256]; + + /* If there is a seed file, load it. But such a file cannot be trusted, + so use 0 for the entropy estimate */ + if (RAND_file_name(seedfile, sizeof(seedfile))) { + int fd; + fd = open(seedfile, O_RDONLY); + if (fd >= 0) { + ssize_t ret; + ret = read(fd, buf, sizeof(buf)); + if (ret > 0) + RAND_add(buf, ret, 0.0); + close(fd); + } else + seedfile[0] = '\0'; + } else + seedfile[0] = '\0'; + + /* Calling RAND_status() will try to use /dev/urandom if it exists so + we do not have to deal with it. */ + if (RAND_status() != 1) { + krb5_context context; + const char *p; + + /* Try using egd */ + if (!krb5_init_context(&context)) { + p = krb5_config_get_string(context, NULL, "libdefaults", + "egd_socket", NULL); + if (p != NULL) + RAND_egd_bytes(p, ENTROPY_NEEDED); + krb5_free_context(context); + } + } + + if (RAND_status() == 1) { + /* Update the seed file */ + if (seedfile[0]) + RAND_write_file(seedfile); + + return 0; + } else + return -1; +} + +void KRB5_LIB_FUNCTION +krb5_generate_random_block(void *buf, size_t len) +{ + static int rng_initialized = 0; + + HEIMDAL_MUTEX_lock(&crypto_mutex); + if (!rng_initialized) { + if (seed_something()) + krb5_abortx(NULL, "Fatal: could not seed the random number generator"); + + rng_initialized = 1; + } + HEIMDAL_MUTEX_unlock(&crypto_mutex); + RAND_bytes(buf, len); +} + +#else + +void KRB5_LIB_FUNCTION +krb5_generate_random_block(void *buf, size_t len) +{ + DES_cblock key, out; + static DES_cblock counter; + static DES_key_schedule schedule; + int i; + static int initialized = 0; + + HEIMDAL_MUTEX_lock(&crypto_mutex); + if(!initialized) { + DES_new_random_key(&key); + DES_set_key(&key, &schedule); + memset(&key, 0, sizeof(key)); + DES_new_random_key(&counter); + initialized = 1; + } + HEIMDAL_MUTEX_unlock(&crypto_mutex); + while(len > 0) { + DES_ecb_encrypt(&counter, &out, &schedule, DES_ENCRYPT); + for(i = 7; i >=0; i--) + if(counter[i]++) + break; + memcpy(buf, out, min(len, sizeof(out))); + len -= min(len, sizeof(out)); + buf = (char*)buf + sizeof(out); + } +} +#endif + +static void +DES3_postproc(krb5_context context, + unsigned char *k, size_t len, struct key_data *key) +{ + DES3_random_to_key(context, key->key, k, len); + + if (key->schedule) { + krb5_free_data(context, key->schedule); + key->schedule = NULL; + } +} + +static krb5_error_code +derive_key(krb5_context context, + struct encryption_type *et, + struct key_data *key, + const void *constant, + size_t len) +{ + unsigned char *k; + unsigned int nblocks = 0, i; + krb5_error_code ret = 0; + + struct key_type *kt = et->keytype; + /* since RC2 is only the weird crypto alg with parameter and this + * function not defined with work with RC2, this is ok */ + ret = _key_schedule(context, key, NULL); + if(ret) + return ret; + if(et->blocksize * 8 < kt->bits || + len != et->blocksize) { + nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8); + k = malloc(nblocks * et->blocksize); + if(k == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + _krb5_n_fold(constant, len, k, et->blocksize); + for(i = 0; i < nblocks; i++) { + if(i > 0) + memcpy(k + i * et->blocksize, + k + (i - 1) * et->blocksize, + et->blocksize); + (*et->encrypt)(context, key, k + i * et->blocksize, et->blocksize, + 1, 0, NULL); + } + } else { + /* this case is probably broken, but won't be run anyway */ + void *c = malloc(len); + size_t res_len = (kt->bits + 7) / 8; + + if(len != 0 && c == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(c, constant, len); + (*et->encrypt)(context, key, c, len, 1, 0, NULL); + k = malloc(res_len); + if(res_len != 0 && k == NULL) { + free(c); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + _krb5_n_fold(c, len, k, res_len); + free(c); + } + + /* XXX keytype dependent post-processing */ + switch(kt->type) { + case KEYTYPE_DES3: + DES3_postproc(context, k, nblocks * et->blocksize, key); + break; + case KEYTYPE_AES128: + case KEYTYPE_AES256: + memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length); + break; + default: + krb5_set_error_string(context, + "derive_key() called with unknown keytype (%u)", + kt->type); + ret = KRB5_CRYPTO_INTERNAL; + break; + } + if (key->schedule) { + krb5_free_data(context, key->schedule); + key->schedule = NULL; + } + memset(k, 0, nblocks * et->blocksize); + free(k); + return ret; +} + +static struct key_data * +_new_derived_key(krb5_crypto crypto, unsigned usage) +{ + struct key_usage *d = crypto->key_usage; + d = realloc(d, (crypto->num_key_usage + 1) * sizeof(*d)); + if(d == NULL) + return NULL; + crypto->key_usage = d; + d += crypto->num_key_usage++; + memset(d, 0, sizeof(*d)); + d->usage = usage; + return &d->key; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_derive_key(krb5_context context, + const krb5_keyblock *key, + krb5_enctype etype, + const void *constant, + size_t constant_len, + krb5_keyblock **derived_key) +{ + krb5_error_code ret; + struct encryption_type *et; + struct key_data d; + + et = _find_enctype (etype); + if (et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + + ret = krb5_copy_keyblock(context, key, derived_key); + if (ret) + return ret; + + d.key = *derived_key; + d.schedule = NULL; + ret = derive_key(context, et, &d, constant, constant_len); + if (ret) + return ret; + ret = krb5_copy_keyblock(context, d.key, derived_key); + return ret; +} + +static krb5_error_code +_get_derived_key(krb5_context context, + krb5_crypto crypto, + unsigned usage, + struct key_data **key) +{ + int i; + struct key_data *d; + unsigned char constant[5]; + + for(i = 0; i < crypto->num_key_usage; i++) + if(crypto->key_usage[i].usage == usage) { + *key = &crypto->key_usage[i].key; + return 0; + } + d = _new_derived_key(crypto, usage); + if(d == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_copy_keyblock(context, crypto->key.key, &d->key); + _krb5_put_int(constant, usage, 5); + derive_key(context, crypto->et, d, constant, sizeof(constant)); + *key = d; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_init(krb5_context context, + const krb5_keyblock *key, + krb5_enctype etype, + krb5_crypto *crypto) +{ + krb5_error_code ret; + ALLOC(*crypto, 1); + if(*crypto == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + if(etype == ETYPE_NULL) + etype = key->keytype; + (*crypto)->et = _find_enctype(etype); + if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) { + free(*crypto); + *crypto = NULL; + krb5_set_error_string (context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + if((*crypto)->et->keytype->minsize > key->keyvalue.length) { + free(*crypto); + *crypto = NULL; + krb5_set_error_string (context, "encryption key has bad length"); + return KRB5_BAD_KEYSIZE; + } + ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key); + if(ret) { + free(*crypto); + *crypto = NULL; + return ret; + } + (*crypto)->key.schedule = NULL; + (*crypto)->num_key_usage = 0; + (*crypto)->key_usage = NULL; + (*crypto)->params = NULL; + return 0; +} + +static void +free_key_data(krb5_context context, struct key_data *key) +{ + krb5_free_keyblock(context, key->key); + if(key->schedule) { + memset(key->schedule->data, 0, key->schedule->length); + krb5_free_data(context, key->schedule); + } +} + +static void +free_key_usage(krb5_context context, struct key_usage *ku) +{ + free_key_data(context, &ku->key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_destroy(krb5_context context, + krb5_crypto crypto) +{ + int i; + + for(i = 0; i < crypto->num_key_usage; i++) + free_key_usage(context, &crypto->key_usage[i]); + free(crypto->key_usage); + free_key_data(context, &crypto->key); + free(crypto->params); + free (crypto); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_get_params(krb5_context context, + const krb5_crypto crypto, + const krb5_data *params, + krb5_data *ivec) +{ + krb5_error_code (*gp)(krb5_context, const krb5_data *,void **,krb5_data *); + krb5_error_code ret; + + gp = crypto->et->keytype->get_params; + if (gp) { + if (crypto->params) { + krb5_set_error_string(context, + "krb5_crypto_get_params called " + "more than once"); + return KRB5_PROG_ETYPE_NOSUPP; + } + ret = (*gp)(context, params, &crypto->params, ivec); + } else { + size_t size; + if (ivec == NULL) + return 0; + ret = decode_CBCParameter(params->data, params->length, ivec, &size); + } + if (ret) + return ret; + if (ivec->length < crypto->et->blocksize) { + krb5_data_free(ivec); + krb5_set_error_string(context, "%s IV of wrong size", + crypto->et->name); + return ASN1_PARSE_ERROR; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_set_params(krb5_context context, + const krb5_crypto crypto, + const krb5_data *ivec, + krb5_data *params) +{ + krb5_error_code (*sp)(krb5_context, const void *, + const krb5_data *, krb5_data *); + krb5_error_code ret; + + sp = crypto->et->keytype->set_params; + if (sp == NULL) { + size_t size; + if (ivec == NULL) + return 0; + ASN1_MALLOC_ENCODE(CBCParameter, params->data, params->length, + ivec, &size, ret); + if (ret) + return ret; + if (size != params->length) + krb5_abortx(context, "Internal asn1 encoder failure"); + return 0; + } + if (crypto->params) { + krb5_set_error_string(context, + "krb5_crypto_set_params called " + "more than once"); + return KRB5_PROG_ETYPE_NOSUPP; + } + return (*sp)(context, crypto->params, ivec, params); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getblocksize(krb5_context context, + krb5_crypto crypto, + size_t *blocksize) +{ + *blocksize = crypto->et->blocksize; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getenctype(krb5_context context, + krb5_crypto crypto, + krb5_enctype *enctype) +{ + *enctype = crypto->et->type; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getpadsize(krb5_context context, + krb5_crypto crypto, + size_t *padsize) +{ + *padsize = crypto->et->padsize; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getconfoundersize(krb5_context context, + krb5_crypto crypto, + size_t *confoundersize) +{ + *confoundersize = crypto->et->confoundersize; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_disable(krb5_context context, + krb5_enctype enctype) +{ + struct encryption_type *et = _find_enctype(enctype); + if(et == NULL) { + if (context) + krb5_set_error_string (context, "encryption type %d not supported", + enctype); + return KRB5_PROG_ETYPE_NOSUPP; + } + et->flags |= F_DISABLED; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_derived(krb5_context context, + const void *str, + size_t len, + krb5_enctype etype, + krb5_keyblock *key) +{ + struct encryption_type *et = _find_enctype(etype); + krb5_error_code ret; + struct key_data kd; + size_t keylen = et->keytype->bits / 8; + u_char *tmp; + + if(et == NULL) { + krb5_set_error_string (context, "encryption type %d not supported", + etype); + return KRB5_PROG_ETYPE_NOSUPP; + } + ALLOC(kd.key, 1); + if(kd.key == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); + if(ret) { + free(kd.key); + return ret; + } + kd.key->keytype = etype; + tmp = malloc (keylen); + if(tmp == NULL) { + krb5_free_keyblock(context, kd.key); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + _krb5_n_fold(str, len, tmp, keylen); + kd.schedule = NULL; + DES3_postproc (context, tmp, keylen, &kd); /* XXX */ + memset(tmp, 0, keylen); + free(tmp); + ret = derive_key(context, + et, + &kd, + "kerberos", /* XXX well known constant */ + strlen("kerberos")); + ret = krb5_copy_keyblock_contents(context, kd.key, key); + free_key_data(context, &kd); + return ret; +} + +static size_t +wrapped_length (krb5_context context, + krb5_crypto crypto, + size_t data_len) +{ + struct encryption_type *et = crypto->et; + size_t padsize = et->padsize; + size_t checksumsize; + size_t res; + + if (et->keyed_checksum) + checksumsize = et->keyed_checksum->checksumsize; + else + checksumsize = et->checksum->checksumsize; + + res = et->confoundersize + checksumsize + data_len; + res = (res + padsize - 1) / padsize * padsize; + return res; +} + +static size_t +wrapped_length_dervied (krb5_context context, + krb5_crypto crypto, + size_t data_len) +{ + struct encryption_type *et = crypto->et; + size_t padsize = et->padsize; + size_t res; + + res = et->confoundersize + data_len; + res = (res + padsize - 1) / padsize * padsize; + if (et->keyed_checksum) + res += et->keyed_checksum->checksumsize; + else + res += et->checksum->checksumsize; + return res; +} + +/* + * Return the size of an encrypted packet of length `data_len' + */ + +size_t +krb5_get_wrapped_length (krb5_context context, + krb5_crypto crypto, + size_t data_len) +{ + if (derived_crypto (context, crypto)) + return wrapped_length_dervied (context, crypto, data_len); + else + return wrapped_length (context, crypto, data_len); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_random_to_key(krb5_context context, + krb5_enctype type, + const void *data, + size_t size, + krb5_keyblock *key) +{ + krb5_error_code ret; + struct encryption_type *et = _find_enctype(type); + if(et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + type); + return KRB5_PROG_ETYPE_NOSUPP; + } + if ((et->keytype->bits + 7) / 8 > size) { + krb5_set_error_string(context, "encryption key %s needs %d bytes " + "of random to make an encryption key out of it", + et->name, (int)et->keytype->size); + return KRB5_PROG_ETYPE_NOSUPP; + } + ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); + if(ret) + return ret; + key->keytype = type; + if (et->keytype->random_to_key) + (*et->keytype->random_to_key)(context, key, data, size); + else + memcpy(key->keyvalue.data, data, et->keytype->size); + + return 0; +} + +#ifdef CRYPTO_DEBUG + +static krb5_error_code +krb5_get_keyid(krb5_context context, + krb5_keyblock *key, + u_int32_t *keyid) +{ + MD5_CTX md5; + unsigned char tmp[16]; + + MD5_Init (&md5); + MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length); + MD5_Final (tmp, &md5); + *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15]; + return 0; +} + +static void +krb5_crypto_debug(krb5_context context, + int encryptp, + size_t len, + krb5_keyblock *key) +{ + u_int32_t keyid; + char *kt; + krb5_get_keyid(context, key, &keyid); + krb5_enctype_to_string(context, key->keytype, &kt); + krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)", + encryptp ? "encrypting" : "decrypting", + (unsigned long)len, + keyid, + kt); + free(kt); +} + +#endif /* CRYPTO_DEBUG */ + +#if 0 +int +main() +{ +#if 0 + int i; + krb5_context context; + krb5_crypto crypto; + struct key_data *d; + krb5_keyblock key; + char constant[4]; + unsigned usage = ENCRYPTION_USAGE(3); + krb5_error_code ret; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + key.keytype = ETYPE_NEW_DES3_CBC_SHA1; + key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8" + "\x25\xe9\x85\xab\x3e\xb5\xfb\x0e" + "\xc8\xdf\xab\x26\x86\x64\x15\x25"; + key.keyvalue.length = 24; + + krb5_crypto_init(context, &key, 0, &crypto); + + d = _new_derived_key(crypto, usage); + if(d == NULL) + return ENOMEM; + krb5_copy_keyblock(context, crypto->key.key, &d->key); + _krb5_put_int(constant, usage, 4); + derive_key(context, crypto->et, d, constant, sizeof(constant)); + return 0; +#else + int i; + krb5_context context; + krb5_crypto crypto; + struct key_data *d; + krb5_keyblock key; + krb5_error_code ret; + Checksum res; + + char *data = "what do ya want for nothing?"; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + key.keytype = ETYPE_NEW_DES3_CBC_SHA1; + key.keyvalue.data = "Jefe"; + /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */ + key.keyvalue.length = 4; + + d = calloc(1, sizeof(*d)); + + d->key = &key; + res.checksum.length = 20; + res.checksum.data = malloc(res.checksum.length); + SP_HMAC_SHA1_checksum(context, d, data, 28, &res); + + return 0; +#endif +} +#endif diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c new file mode 100644 index 0000000000..9cf1410e70 --- /dev/null +++ b/source4/heimdal/lib/krb5/data.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: data.c,v 1.19 2004/05/25 21:22:23 lha Exp $"); + +void KRB5_LIB_FUNCTION +krb5_data_zero(krb5_data *p) +{ + p->length = 0; + p->data = NULL; +} + +void KRB5_LIB_FUNCTION +krb5_data_free(krb5_data *p) +{ + if(p->data != NULL) + free(p->data); + krb5_data_zero(p); +} + +void KRB5_LIB_FUNCTION +krb5_free_data_contents(krb5_context context, krb5_data *data) +{ + krb5_data_free(data); +} + +void KRB5_LIB_FUNCTION +krb5_free_data(krb5_context context, + krb5_data *p) +{ + krb5_data_free(p); + free(p); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_data_alloc(krb5_data *p, int len) +{ + p->data = malloc(len); + if(len && p->data == NULL) + return ENOMEM; + p->length = len; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_data_realloc(krb5_data *p, int len) +{ + void *tmp; + tmp = realloc(p->data, len); + if(len && !tmp) + return ENOMEM; + p->data = tmp; + p->length = len; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_data_copy(krb5_data *p, const void *data, size_t len) +{ + if (len) { + if(krb5_data_alloc(p, len)) + return ENOMEM; + memmove(p->data, data, len); + } else + p->data = NULL; + p->length = len; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_data(krb5_context context, + const krb5_data *indata, + krb5_data **outdata) +{ + krb5_error_code ret; + ALLOC(*outdata, 1); + if(*outdata == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = copy_octet_string(indata, *outdata); + if(ret) { + krb5_clear_error_string (context); + free(*outdata); + } + return ret; +} diff --git a/source4/heimdal/lib/krb5/eai_to_heim_errno.c b/source4/heimdal/lib/krb5/eai_to_heim_errno.c new file mode 100644 index 0000000000..f0d1f51033 --- /dev/null +++ b/source4/heimdal/lib/krb5/eai_to_heim_errno.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2000 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: eai_to_heim_errno.c,v 1.5 2004/05/25 21:23:35 lha Exp $"); + +/* + * convert the getaddrinfo error code in `eai_errno' into a + * krb5_error_code. `system_error' should have the value of the errno + * after the failed call. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_eai_to_heim_errno(int eai_errno, int system_error) +{ + switch(eai_errno) { + case EAI_NOERROR: + return 0; +#ifdef EAI_ADDRFAMILY + case EAI_ADDRFAMILY: + return HEIM_EAI_ADDRFAMILY; +#endif + case EAI_AGAIN: + return HEIM_EAI_AGAIN; + case EAI_BADFLAGS: + return HEIM_EAI_BADFLAGS; + case EAI_FAIL: + return HEIM_EAI_FAIL; + case EAI_FAMILY: + return HEIM_EAI_FAMILY; + case EAI_MEMORY: + return HEIM_EAI_MEMORY; +#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME + case EAI_NODATA: + return HEIM_EAI_NODATA; +#endif + case EAI_NONAME: + return HEIM_EAI_NONAME; + case EAI_SERVICE: + return HEIM_EAI_SERVICE; + case EAI_SOCKTYPE: + return HEIM_EAI_SOCKTYPE; + case EAI_SYSTEM: + return system_error; + default: + return HEIM_EAI_UNKNOWN; /* XXX */ + } +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_h_errno_to_heim_errno(int eai_errno) +{ + switch(eai_errno) { + case 0: + return 0; + case HOST_NOT_FOUND: + return HEIM_EAI_NONAME; + case TRY_AGAIN: + return HEIM_EAI_AGAIN; + case NO_RECOVERY: + return HEIM_EAI_FAIL; + case NO_DATA: + return HEIM_EAI_NONAME; + default: + return HEIM_EAI_UNKNOWN; /* XXX */ + } +} diff --git a/source4/heimdal/lib/krb5/error_string.c b/source4/heimdal/lib/krb5/error_string.c new file mode 100644 index 0000000000..649bdd20fd --- /dev/null +++ b/source4/heimdal/lib/krb5/error_string.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: error_string.c,v 1.3 2004/05/25 21:23:55 lha Exp $"); + +#undef __attribute__ +#define __attribute__(X) + +void KRB5_LIB_FUNCTION +krb5_free_error_string(krb5_context context, char *str) +{ + HEIMDAL_MUTEX_lock(context->mutex); + if (str != context->error_buf) + free(str); + HEIMDAL_MUTEX_unlock(context->mutex); +} + +void KRB5_LIB_FUNCTION +krb5_clear_error_string(krb5_context context) +{ + HEIMDAL_MUTEX_lock(context->mutex); + if (context->error_string != NULL + && context->error_string != context->error_buf) + free(context->error_string); + context->error_string = NULL; + HEIMDAL_MUTEX_unlock(context->mutex); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_error_string(krb5_context context, const char *fmt, ...) + __attribute__((format (printf, 2, 3))) +{ + krb5_error_code ret; + va_list ap; + + va_start(ap, fmt); + ret = krb5_vset_error_string (context, fmt, ap); + va_end(ap); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vset_error_string(krb5_context context, const char *fmt, va_list args) + __attribute__ ((format (printf, 2, 0))) +{ + krb5_clear_error_string(context); + HEIMDAL_MUTEX_lock(context->mutex); + vasprintf(&context->error_string, fmt, args); + if(context->error_string == NULL) { + vsnprintf (context->error_buf, sizeof(context->error_buf), fmt, args); + context->error_string = context->error_buf; + } + HEIMDAL_MUTEX_unlock(context->mutex); + return 0; +} + +char * KRB5_LIB_FUNCTION +krb5_get_error_string(krb5_context context) +{ + char *ret; + + HEIMDAL_MUTEX_lock(context->mutex); + ret = context->error_string; + context->error_string = NULL; + HEIMDAL_MUTEX_unlock(context->mutex); + return ret; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_have_error_string(krb5_context context) +{ + char *str; + HEIMDAL_MUTEX_lock(context->mutex); + str = context->error_string; + HEIMDAL_MUTEX_unlock(context->mutex); + return str != NULL; +} diff --git a/source4/heimdal/lib/krb5/expand_hostname.c b/source4/heimdal/lib/krb5/expand_hostname.c new file mode 100644 index 0000000000..8488119552 --- /dev/null +++ b/source4/heimdal/lib/krb5/expand_hostname.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1999 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: expand_hostname.c,v 1.12 2004/05/25 21:24:14 lha Exp $"); + +static krb5_error_code +copy_hostname(krb5_context context, + const char *orig_hostname, + char **new_hostname) +{ + *new_hostname = strdup (orig_hostname); + if (*new_hostname == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + strlwr (*new_hostname); + return 0; +} + +/* + * Try to make `orig_hostname' into a more canonical one in the newly + * allocated space returned in `new_hostname'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_expand_hostname (krb5_context context, + const char *orig_hostname, + char **new_hostname) +{ + struct addrinfo *ai, *a, hints; + int error; + + memset (&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + + error = getaddrinfo (orig_hostname, NULL, &hints, &ai); + if (error) + return copy_hostname (context, orig_hostname, new_hostname); + for (a = ai; a != NULL; a = a->ai_next) { + if (a->ai_canonname != NULL) { + *new_hostname = strdup (a->ai_canonname); + freeaddrinfo (ai); + if (*new_hostname == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } else { + return 0; + } + } + } + freeaddrinfo (ai); + return copy_hostname (context, orig_hostname, new_hostname); +} + +/* + * handle the case of the hostname being unresolvable and thus identical + */ + +static krb5_error_code +vanilla_hostname (krb5_context context, + const char *orig_hostname, + char **new_hostname, + char ***realms) +{ + krb5_error_code ret; + + ret = copy_hostname (context, orig_hostname, new_hostname); + if (ret) + return ret; + strlwr (*new_hostname); + + ret = krb5_get_host_realm (context, *new_hostname, realms); + if (ret) { + free (*new_hostname); + return ret; + } + return 0; +} + +/* + * expand `hostname' to a name we believe to be a hostname in newly + * allocated space in `host' and return realms in `realms'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_expand_hostname_realms (krb5_context context, + const char *orig_hostname, + char **new_hostname, + char ***realms) +{ + struct addrinfo *ai, *a, hints; + int error; + krb5_error_code ret = 0; + + memset (&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + + error = getaddrinfo (orig_hostname, NULL, &hints, &ai); + if (error) + return vanilla_hostname (context, orig_hostname, new_hostname, + realms); + + for (a = ai; a != NULL; a = a->ai_next) { + if (a->ai_canonname != NULL) { + ret = copy_hostname (context, a->ai_canonname, new_hostname); + if (ret) { + freeaddrinfo (ai); + return ret; + } + strlwr (*new_hostname); + ret = krb5_get_host_realm (context, *new_hostname, realms); + if (ret == 0) { + freeaddrinfo (ai); + return 0; + } + free (*new_hostname); + } + } + freeaddrinfo(ai); + return vanilla_hostname (context, orig_hostname, new_hostname, realms); +} diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c new file mode 100644 index 0000000000..03848abb9a --- /dev/null +++ b/source4/heimdal/lib/krb5/fcache.c @@ -0,0 +1,718 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: fcache.c,v 1.49 2005/06/16 20:25:20 lha Exp $"); + +typedef struct krb5_fcache{ + char *filename; + int version; +}krb5_fcache; + +struct fcc_cursor { + int fd; + krb5_storage *sp; +}; + +#define KRB5_FCC_FVNO_1 1 +#define KRB5_FCC_FVNO_2 2 +#define KRB5_FCC_FVNO_3 3 +#define KRB5_FCC_FVNO_4 4 + +#define FCC_TAG_DELTATIME 1 + +#define FCACHE(X) ((krb5_fcache*)(X)->data.data) + +#define FILENAME(X) (FCACHE(X)->filename) + +#define FCC_CURSOR(C) ((struct fcc_cursor*)(C)) + +static const char* +fcc_get_name(krb5_context context, + krb5_ccache id) +{ + return FILENAME(id); +} + +int +_krb5_xlock(krb5_context context, int fd, krb5_boolean exclusive, + const char *filename) +{ + int ret; +#ifdef HAVE_FCNTL + struct flock l; + + l.l_start = 0; + l.l_len = 0; + l.l_type = exclusive ? F_WRLCK : F_RDLCK; + l.l_whence = SEEK_SET; + ret = fcntl(fd, F_SETLKW, &l); +#else + ret = flock(fd, exclusive ? LOCK_EX : LOCK_SH); +#endif + if(ret < 0) + ret = errno; + if(ret == EACCES) /* fcntl can return EACCES instead of EAGAIN */ + ret = EAGAIN; + + switch (ret) { + case 0: + break; + case EINVAL: /* filesystem doesn't support locking, let the user have it */ + ret = 0; + break; + case EAGAIN: + krb5_set_error_string(context, "timed out locking cache file %s", + filename); + break; + default: + krb5_set_error_string(context, "error locking cache file %s: %s", + filename, strerror(ret)); + break; + } + return ret; +} + +int +_krb5_xunlock(krb5_context context, int fd) +{ + int ret; +#ifdef HAVE_FCNTL_LOCK + struct flock l; + l.l_start = 0; + l.l_len = 0; + l.l_type = F_UNLCK; + l.l_whence = SEEK_SET; + ret = fcntl(fd, F_SETLKW, &l); +#else + ret = flock(fd, LOCK_UN); +#endif + if (ret < 0) + ret = errno; + switch (ret) { + case 0: + break; + case EINVAL: /* filesystem doesn't support locking, let the user have it */ + ret = 0; + break; + default: + krb5_set_error_string(context, + "Failed to unlock file: %s", strerror(ret)); + break; + } + return ret; +} + +static krb5_error_code +fcc_lock(krb5_context context, krb5_ccache id, + int fd, krb5_boolean exclusive) +{ + return _krb5_xlock(context, fd, exclusive, fcc_get_name(context, id)); +} + +static krb5_error_code +fcc_unlock(krb5_context context, int fd) +{ + return _krb5_xunlock(context, fd); +} + +static krb5_error_code +fcc_resolve(krb5_context context, krb5_ccache *id, const char *res) +{ + krb5_fcache *f; + f = malloc(sizeof(*f)); + if(f == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + f->filename = strdup(res); + if(f->filename == NULL){ + free(f); + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + f->version = 0; + (*id)->data.data = f; + (*id)->data.length = sizeof(*f); + return 0; +} + +/* + * Try to scrub the contents of `filename' safely. + */ + +static int +scrub_file (int fd) +{ + off_t pos; + char buf[128]; + + pos = lseek(fd, 0, SEEK_END); + if (pos < 0) + return errno; + if (lseek(fd, 0, SEEK_SET) < 0) + return errno; + memset(buf, 0, sizeof(buf)); + while(pos > 0) { + ssize_t tmp = write(fd, buf, min(sizeof(buf), pos)); + + if (tmp < 0) + return errno; + pos -= tmp; + } + fsync (fd); + return 0; +} + +/* + * Erase `filename' if it exists, trying to remove the contents if + * it's `safe'. We always try to remove the file, it it exists. It's + * only overwritten if it's a regular file (not a symlink and not a + * hardlink) + */ + +static krb5_error_code +erase_file(const char *filename) +{ + int fd; + struct stat sb1, sb2; + int ret; + + ret = lstat (filename, &sb1); + if (ret < 0) + return errno; + + fd = open(filename, O_RDWR | O_BINARY); + if(fd < 0) { + if(errno == ENOENT) + return 0; + else + return errno; + } + if (unlink(filename) < 0) { + close (fd); + return errno; + } + ret = fstat (fd, &sb2); + if (ret < 0) { + close (fd); + return errno; + } + + /* check if someone was playing with symlinks */ + + if (sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) { + close (fd); + return EPERM; + } + + /* there are still hard links to this file */ + + if (sb2.st_nlink != 0) { + close (fd); + return 0; + } + + ret = scrub_file (fd); + close (fd); + return ret; +} + +static krb5_error_code +fcc_gen_new(krb5_context context, krb5_ccache *id) +{ + krb5_fcache *f; + int fd; + char *file; + + f = malloc(sizeof(*f)); + if(f == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + asprintf (&file, "%sXXXXXX", KRB5_DEFAULT_CCFILE_ROOT); + if(file == NULL) { + free(f); + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + fd = mkstemp(file); + if(fd < 0) { + free(f); + free(file); + krb5_set_error_string(context, "mkstemp %s", file); + return errno; + } + close(fd); + f->filename = file; + f->version = 0; + (*id)->data.data = f; + (*id)->data.length = sizeof(*f); + return 0; +} + +static void +storage_set_flags(krb5_context context, krb5_storage *sp, int vno) +{ + int flags = 0; + switch(vno) { + case KRB5_FCC_FVNO_1: + flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS; + flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE; + flags |= KRB5_STORAGE_HOST_BYTEORDER; + break; + case KRB5_FCC_FVNO_2: + flags |= KRB5_STORAGE_HOST_BYTEORDER; + break; + case KRB5_FCC_FVNO_3: + flags |= KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE; + break; + case KRB5_FCC_FVNO_4: + break; + default: + krb5_abortx(context, + "storage_set_flags called with bad vno (%x)", vno); + } + krb5_storage_set_flags(sp, flags); +} + +static krb5_error_code +fcc_open(krb5_context context, + krb5_ccache id, + int *fd_ret, + int flags, + mode_t mode) +{ + krb5_boolean exclusive = ((flags | O_WRONLY) == flags || + (flags | O_RDWR) == flags); + krb5_error_code ret; + const char *filename = FILENAME(id); + int fd; + fd = open(filename, flags, mode); + if(fd < 0) { + ret = errno; + krb5_set_error_string(context, "open(%s): %s", filename, + strerror(ret)); + return ret; + } + + if((ret = fcc_lock(context, id, fd, exclusive)) != 0) { + close(fd); + return ret; + } + *fd_ret = fd; + return 0; +} + +static krb5_error_code +fcc_initialize(krb5_context context, + krb5_ccache id, + krb5_principal primary_principal) +{ + krb5_fcache *f = FCACHE(id); + int ret = 0; + int fd; + char *filename = f->filename; + + unlink (filename); + + ret = fcc_open(context, id, &fd, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600); + if(ret) + return ret; + { + krb5_storage *sp; + sp = krb5_storage_from_fd(fd); + krb5_storage_set_eof_code(sp, KRB5_CC_END); + if(context->fcache_vno != 0) + f->version = context->fcache_vno; + else + f->version = KRB5_FCC_FVNO_4; + ret |= krb5_store_int8(sp, 5); + ret |= krb5_store_int8(sp, f->version); + storage_set_flags(context, sp, f->version); + if(f->version == KRB5_FCC_FVNO_4 && ret == 0) { + /* V4 stuff */ + if (context->kdc_sec_offset) { + ret |= krb5_store_int16 (sp, 12); /* length */ + ret |= krb5_store_int16 (sp, FCC_TAG_DELTATIME); /* Tag */ + ret |= krb5_store_int16 (sp, 8); /* length of data */ + ret |= krb5_store_int32 (sp, context->kdc_sec_offset); + ret |= krb5_store_int32 (sp, context->kdc_usec_offset); + } else { + ret |= krb5_store_int16 (sp, 0); + } + } + ret |= krb5_store_principal(sp, primary_principal); + + krb5_storage_free(sp); + } + fcc_unlock(context, fd); + if (close(fd) < 0) + if (ret == 0) { + ret = errno; + krb5_set_error_string (context, "close %s: %s", + FILENAME(id), strerror(ret)); + } + return ret; +} + +static krb5_error_code +fcc_close(krb5_context context, + krb5_ccache id) +{ + free (FILENAME(id)); + krb5_data_free(&id->data); + return 0; +} + +static krb5_error_code +fcc_destroy(krb5_context context, + krb5_ccache id) +{ + erase_file(FILENAME(id)); + return 0; +} + +static krb5_error_code +fcc_store_cred(krb5_context context, + krb5_ccache id, + krb5_creds *creds) +{ + int ret; + int fd; + + ret = fcc_open(context, id, &fd, O_WRONLY | O_APPEND | O_BINARY, 0); + if(ret) + return ret; + { + krb5_storage *sp; + sp = krb5_storage_from_fd(fd); + krb5_storage_set_eof_code(sp, KRB5_CC_END); + storage_set_flags(context, sp, FCACHE(id)->version); + if (!krb5_config_get_bool_default(context, NULL, TRUE, + "libdefaults", + "fcc-mit-ticketflags", + NULL)) + krb5_storage_set_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER); + ret = krb5_store_creds(sp, creds); + krb5_storage_free(sp); + } + fcc_unlock(context, fd); + if (close(fd) < 0) + if (ret == 0) { + ret = errno; + krb5_set_error_string (context, "close %s: %s", + FILENAME(id), strerror(ret)); + } + return ret; +} + +static krb5_error_code +init_fcc (krb5_context context, + krb5_ccache id, + krb5_storage **ret_sp, + int *ret_fd) +{ + int fd; + int8_t pvno, tag; + krb5_storage *sp; + krb5_error_code ret; + + ret = fcc_open(context, id, &fd, O_RDONLY | O_BINARY, 0); + if(ret) + return ret; + + sp = krb5_storage_from_fd(fd); + if(sp == NULL) { + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + krb5_storage_set_eof_code(sp, KRB5_CC_END); + ret = krb5_ret_int8(sp, &pvno); + if(ret != 0) { + if(ret == KRB5_CC_END) + ret = ENOENT; /* empty file */ + krb5_clear_error_string(context); + goto out; + } + if(pvno != 5) { + krb5_set_error_string(context, "Bad version number in credential " + "cache file: %s", FILENAME(id)); + ret = KRB5_CCACHE_BADVNO; + goto out; + } + ret = krb5_ret_int8(sp, &tag); /* should not be host byte order */ + if(ret != 0) { + krb5_clear_error_string(context); + ret = KRB5_CC_FORMAT; + goto out; + } + FCACHE(id)->version = tag; + storage_set_flags(context, sp, FCACHE(id)->version); + switch (tag) { + case KRB5_FCC_FVNO_4: { + int16_t length; + + ret = krb5_ret_int16 (sp, &length); + if(ret) { + ret = KRB5_CC_FORMAT; + krb5_clear_error_string(context); + goto out; + } + while(length > 0) { + int16_t dtag, data_len; + int i; + int8_t dummy; + + ret = krb5_ret_int16 (sp, &dtag); + if(ret) { + krb5_clear_error_string(context); + ret = KRB5_CC_FORMAT; + goto out; + } + ret = krb5_ret_int16 (sp, &data_len); + if(ret) { + krb5_clear_error_string(context); + ret = KRB5_CC_FORMAT; + goto out; + } + switch (dtag) { + case FCC_TAG_DELTATIME : + ret = krb5_ret_int32 (sp, &context->kdc_sec_offset); + if(ret) { + krb5_clear_error_string(context); + ret = KRB5_CC_FORMAT; + goto out; + } + ret = krb5_ret_int32 (sp, &context->kdc_usec_offset); + if(ret) { + krb5_clear_error_string(context); + ret = KRB5_CC_FORMAT; + goto out; + } + break; + default : + for (i = 0; i < data_len; ++i) { + ret = krb5_ret_int8 (sp, &dummy); + if(ret) { + krb5_clear_error_string(context); + ret = KRB5_CC_FORMAT; + goto out; + } + } + break; + } + length -= 4 + data_len; + } + break; + } + case KRB5_FCC_FVNO_3: + case KRB5_FCC_FVNO_2: + case KRB5_FCC_FVNO_1: + break; + default : + ret = KRB5_CCACHE_BADVNO; + krb5_set_error_string(context, "Unknown version number (%d) in " + "credential cache file: %s", + (int)tag, FILENAME(id)); + goto out; + } + *ret_sp = sp; + *ret_fd = fd; + + return 0; + out: + if(sp != NULL) + krb5_storage_free(sp); + fcc_unlock(context, fd); + close(fd); + return ret; +} + +static krb5_error_code +fcc_get_principal(krb5_context context, + krb5_ccache id, + krb5_principal *principal) +{ + krb5_error_code ret; + int fd; + krb5_storage *sp; + + ret = init_fcc (context, id, &sp, &fd); + if (ret) + return ret; + ret = krb5_ret_principal(sp, principal); + if (ret) + krb5_clear_error_string(context); + krb5_storage_free(sp); + fcc_unlock(context, fd); + close(fd); + return ret; +} + +static krb5_error_code +fcc_end_get (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor); + +static krb5_error_code +fcc_get_first (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + krb5_error_code ret; + krb5_principal principal; + + *cursor = malloc(sizeof(struct fcc_cursor)); + if (*cursor == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memset(*cursor, 0, sizeof(struct fcc_cursor)); + + ret = init_fcc (context, id, &FCC_CURSOR(*cursor)->sp, + &FCC_CURSOR(*cursor)->fd); + if (ret) { + free(*cursor); + *cursor = NULL; + return ret; + } + ret = krb5_ret_principal (FCC_CURSOR(*cursor)->sp, &principal); + if(ret) { + krb5_clear_error_string(context); + fcc_end_get(context, id, cursor); + return ret; + } + krb5_free_principal (context, principal); + fcc_unlock(context, FCC_CURSOR(*cursor)->fd); + return 0; +} + +static krb5_error_code +fcc_get_next (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + krb5_error_code ret; + if((ret = fcc_lock(context, id, FCC_CURSOR(*cursor)->fd, FALSE)) != 0) + return ret; + + ret = krb5_ret_creds(FCC_CURSOR(*cursor)->sp, creds); + if (ret) + krb5_clear_error_string(context); + + fcc_unlock(context, FCC_CURSOR(*cursor)->fd); + return ret; +} + +static krb5_error_code +fcc_end_get (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + krb5_storage_free(FCC_CURSOR(*cursor)->sp); + close (FCC_CURSOR(*cursor)->fd); + free(*cursor); + *cursor = NULL; + return 0; +} + +static krb5_error_code +fcc_remove_cred(krb5_context context, + krb5_ccache id, + krb5_flags which, + krb5_creds *cred) +{ + krb5_error_code ret; + krb5_ccache copy; + + ret = krb5_cc_gen_new(context, &krb5_mcc_ops, ©); + if (ret) + return ret; + + ret = krb5_cc_copy_cache(context, id, copy); + if (ret) { + krb5_cc_destroy(context, copy); + return ret; + } + + ret = krb5_cc_remove_cred(context, copy, which, cred); + if (ret) { + krb5_cc_destroy(context, copy); + return ret; + } + + fcc_destroy(context, id); + + ret = krb5_cc_copy_cache(context, copy, id); + krb5_cc_destroy(context, copy); + + return ret; +} + +static krb5_error_code +fcc_set_flags(krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ + return 0; /* XXX */ +} + +static krb5_error_code +fcc_get_version(krb5_context context, + krb5_ccache id) +{ + return FCACHE(id)->version; +} + +const krb5_cc_ops krb5_fcc_ops = { + "FILE", + fcc_get_name, + fcc_resolve, + fcc_gen_new, + fcc_initialize, + fcc_destroy, + fcc_close, + fcc_store_cred, + NULL, /* fcc_retrieve */ + fcc_get_principal, + fcc_get_first, + fcc_get_next, + fcc_end_get, + fcc_remove_cred, + fcc_set_flags, + fcc_get_version +}; diff --git a/source4/heimdal/lib/krb5/free.c b/source4/heimdal/lib/krb5/free.c new file mode 100644 index 0000000000..84aa6f8c2c --- /dev/null +++ b/source4/heimdal/lib/krb5/free.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 1997 - 1999, 2004 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: free.c,v 1.8 2005/05/18 10:06:16 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *rep) +{ + free_KDC_REP(&rep->kdc_rep); + free_EncTGSRepPart(&rep->enc_part); + free_KRB_ERROR(&rep->error); + memset(rep, 0, sizeof(*rep)); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_xfree (void *ptr) +{ + free (ptr); + return 0; +} diff --git a/source4/heimdal/lib/krb5/free_host_realm.c b/source4/heimdal/lib/krb5/free_host_realm.c new file mode 100644 index 0000000000..27afcdbb23 --- /dev/null +++ b/source4/heimdal/lib/krb5/free_host_realm.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997, 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: free_host_realm.c,v 1.5 2004/05/25 21:25:02 lha Exp $"); + +/* + * Free all memory allocated by `realmlist' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_host_realm(krb5_context context, + krb5_realm *realmlist) +{ + krb5_realm *p; + + if(realmlist == NULL) + return 0; + for (p = realmlist; *p; ++p) + free (*p); + free (realmlist); + return 0; +} diff --git a/source4/heimdal/lib/krb5/generate_seq_number.c b/source4/heimdal/lib/krb5/generate_seq_number.c new file mode 100644 index 0000000000..f9e9cded5f --- /dev/null +++ b/source4/heimdal/lib/krb5/generate_seq_number.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: generate_seq_number.c,v 1.9 2004/05/25 21:25:22 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_seq_number(krb5_context context, + const krb5_keyblock *key, + u_int32_t *seqno) +{ + krb5_error_code ret; + krb5_keyblock *subkey; + u_int32_t q; + u_char *p; + int i; + + ret = krb5_generate_subkey (context, key, &subkey); + if (ret) + return ret; + + q = 0; + for (p = (u_char *)subkey->keyvalue.data, i = 0; + i < subkey->keyvalue.length; + ++i, ++p) + q = (q << 8) | *p; + q &= 0xffffffff; + *seqno = q; + krb5_free_keyblock (context, subkey); + return 0; +} diff --git a/source4/heimdal/lib/krb5/generate_subkey.c b/source4/heimdal/lib/krb5/generate_subkey.c new file mode 100644 index 0000000000..df4828d097 --- /dev/null +++ b/source4/heimdal/lib/krb5/generate_subkey.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: generate_subkey.c,v 1.11 2005/01/05 02:39:21 lukeh Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_subkey(krb5_context context, + const krb5_keyblock *key, + krb5_keyblock **subkey) +{ + return krb5_generate_subkey_extended(context, key, key->keytype, subkey); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_subkey_extended(krb5_context context, + const krb5_keyblock *key, + krb5_enctype etype, + krb5_keyblock **subkey) +{ + krb5_error_code ret; + + ALLOC(*subkey, 1); + if (*subkey == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + if (etype == ETYPE_NULL) + etype = key->keytype; /* use session key etype */ + + /* XXX should we use the session key as input to the RF? */ + ret = krb5_generate_random_keyblock(context, etype, *subkey); + if (ret != 0) { + free(*subkey); + *subkey = NULL; + } + + return ret; +} + diff --git a/source4/heimdal/lib/krb5/get_addrs.c b/source4/heimdal/lib/krb5/get_addrs.c new file mode 100644 index 0000000000..034516d7d4 --- /dev/null +++ b/source4/heimdal/lib/krb5/get_addrs.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: get_addrs.c,v 1.46 2004/05/25 21:26:05 lha Exp $"); + +#ifdef __osf__ +/* hate */ +struct rtentry; +struct mbuf; +#endif +#ifdef HAVE_NET_IF_H +#include +#endif +#include + +static krb5_error_code +gethostname_fallback (krb5_context context, krb5_addresses *res) +{ + krb5_error_code ret; + char hostname[MAXHOSTNAMELEN]; + struct hostent *hostent; + + if (gethostname (hostname, sizeof(hostname))) { + ret = errno; + krb5_set_error_string (context, "gethostname: %s", strerror(ret)); + return ret; + } + hostent = roken_gethostbyname (hostname); + if (hostent == NULL) { + ret = errno; + krb5_set_error_string (context, "gethostbyname %s: %s", + hostname, strerror(ret)); + return ret; + } + res->len = 1; + res->val = malloc (sizeof(*res->val)); + if (res->val == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + res->val[0].addr_type = hostent->h_addrtype; + res->val[0].address.data = NULL; + res->val[0].address.length = 0; + ret = krb5_data_copy (&res->val[0].address, + hostent->h_addr, + hostent->h_length); + if (ret) { + free (res->val); + return ret; + } + return 0; +} + +enum { + LOOP = 1, /* do include loopback interfaces */ + LOOP_IF_NONE = 2, /* include loopback if no other if's */ + EXTRA_ADDRESSES = 4, /* include extra addresses */ + SCAN_INTERFACES = 8 /* scan interfaces for addresses */ +}; + +/* + * Try to figure out the addresses of all configured interfaces with a + * lot of magic ioctls. + */ + +static krb5_error_code +find_all_addresses (krb5_context context, krb5_addresses *res, int flags) +{ + struct sockaddr sa_zero; + struct ifaddrs *ifa0, *ifa; + krb5_error_code ret = ENXIO; + int num, idx; + krb5_addresses ignore_addresses; + + res->val = NULL; + + if (getifaddrs(&ifa0) == -1) { + ret = errno; + krb5_set_error_string(context, "getifaddrs: %s", strerror(ret)); + return (ret); + } + + memset(&sa_zero, 0, sizeof(sa_zero)); + + /* First, count all the ifaddrs. */ + for (ifa = ifa0, num = 0; ifa != NULL; ifa = ifa->ifa_next, num++) + /* nothing */; + + if (num == 0) { + freeifaddrs(ifa0); + krb5_set_error_string(context, "no addresses found"); + return (ENXIO); + } + + if (flags & EXTRA_ADDRESSES) { + /* we'll remove the addresses we don't care about */ + ret = krb5_get_ignore_addresses(context, &ignore_addresses); + if(ret) + return ret; + } + + /* Allocate storage for them. */ + res->val = calloc(num, sizeof(*res->val)); + if (res->val == NULL) { + krb5_free_addresses(context, &ignore_addresses); + freeifaddrs(ifa0); + krb5_set_error_string (context, "malloc: out of memory"); + return (ENOMEM); + } + + /* Now traverse the list. */ + for (ifa = ifa0, idx = 0; ifa != NULL; ifa = ifa->ifa_next) { + if ((ifa->ifa_flags & IFF_UP) == 0) + continue; + if (ifa->ifa_addr == NULL) + continue; + if (memcmp(ifa->ifa_addr, &sa_zero, sizeof(sa_zero)) == 0) + continue; + if (krb5_sockaddr_uninteresting(ifa->ifa_addr)) + continue; + if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) { + /* We'll deal with the LOOP_IF_NONE case later. */ + if ((flags & LOOP) == 0) + continue; + } + + ret = krb5_sockaddr2address(context, ifa->ifa_addr, &res->val[idx]); + if (ret) { + /* + * The most likely error here is going to be "Program + * lacks support for address type". This is no big + * deal -- just continue, and we'll listen on the + * addresses who's type we *do* support. + */ + continue; + } + /* possibly skip this address? */ + if((flags & EXTRA_ADDRESSES) && + krb5_address_search(context, &res->val[idx], &ignore_addresses)) { + krb5_free_address(context, &res->val[idx]); + flags &= ~LOOP_IF_NONE; /* we actually found an address, + so don't add any loop-back + addresses */ + continue; + } + + idx++; + } + + /* + * If no addresses were found, and LOOP_IF_NONE is set, then find + * the loopback addresses and add them to our list. + */ + if ((flags & LOOP_IF_NONE) != 0 && idx == 0) { + for (ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next) { + if ((ifa->ifa_flags & IFF_UP) == 0) + continue; + if (ifa->ifa_addr == NULL) + continue; + if (memcmp(ifa->ifa_addr, &sa_zero, sizeof(sa_zero)) == 0) + continue; + if (krb5_sockaddr_uninteresting(ifa->ifa_addr)) + continue; + + if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) { + ret = krb5_sockaddr2address(context, + ifa->ifa_addr, &res->val[idx]); + if (ret) { + /* + * See comment above. + */ + continue; + } + if((flags & EXTRA_ADDRESSES) && + krb5_address_search(context, &res->val[idx], + &ignore_addresses)) { + krb5_free_address(context, &res->val[idx]); + continue; + } + idx++; + } + } + } + + if (flags & EXTRA_ADDRESSES) + krb5_free_addresses(context, &ignore_addresses); + freeifaddrs(ifa0); + if (ret) + free(res->val); + else + res->len = idx; /* Now a count. */ + return (ret); +} + +static krb5_error_code +get_addrs_int (krb5_context context, krb5_addresses *res, int flags) +{ + krb5_error_code ret = -1; + + if (flags & SCAN_INTERFACES) { + ret = find_all_addresses (context, res, flags); + if(ret || res->len == 0) + ret = gethostname_fallback (context, res); + } else { + res->len = 0; + res->val = NULL; + ret = 0; + } + + if(ret == 0 && (flags & EXTRA_ADDRESSES)) { + krb5_addresses a; + /* append user specified addresses */ + ret = krb5_get_extra_addresses(context, &a); + if(ret) { + krb5_free_addresses(context, res); + return ret; + } + ret = krb5_append_addresses(context, res, &a); + if(ret) { + krb5_free_addresses(context, res); + return ret; + } + krb5_free_addresses(context, &a); + } + if(res->len == 0) { + free(res->val); + res->val = NULL; + } + return ret; +} + +/* + * Try to get all addresses, but return the one corresponding to + * `hostname' if we fail. + * + * Only include loopback address if there are no other. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_all_client_addrs (krb5_context context, krb5_addresses *res) +{ + int flags = LOOP_IF_NONE | EXTRA_ADDRESSES; + + if (context->scan_interfaces) + flags |= SCAN_INTERFACES; + + return get_addrs_int (context, res, flags); +} + +/* + * Try to get all local addresses that a server should listen to. + * If that fails, we return the address corresponding to `hostname'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_all_server_addrs (krb5_context context, krb5_addresses *res) +{ + return get_addrs_int (context, res, LOOP | SCAN_INTERFACES); +} diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c new file mode 100644 index 0000000000..63fb55608c --- /dev/null +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -0,0 +1,909 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: get_cred.c,v 1.107 2005/06/16 22:57:14 lha Exp $"); + +/* + * Take the `body' and encode it into `padata' using the credentials + * in `creds'. + */ + +static krb5_error_code +make_pa_tgs_req(krb5_context context, + krb5_auth_context ac, + KDC_REQ_BODY *body, + PA_DATA *padata, + krb5_creds *creds, + krb5_key_usage usage) +{ + u_char *buf; + size_t buf_size; + size_t len; + krb5_data in_data; + krb5_error_code ret; + + ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret); + if (ret) + goto out; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + in_data.length = len; + in_data.data = buf; + ret = _krb5_mk_req_internal(context, &ac, 0, &in_data, creds, + &padata->padata_value, + KRB5_KU_TGS_REQ_AUTH_CKSUM, + usage + /* KRB5_KU_TGS_REQ_AUTH */); + out: + free (buf); + if(ret) + return ret; + padata->padata_type = KRB5_PADATA_TGS_REQ; + return 0; +} + +/* + * Set the `enc-authorization-data' in `req_body' based on `authdata' + */ + +static krb5_error_code +set_auth_data (krb5_context context, + KDC_REQ_BODY *req_body, + krb5_authdata *authdata, + krb5_keyblock *key) +{ + if(authdata->len) { + size_t len, buf_size; + unsigned char *buf; + krb5_crypto crypto; + krb5_error_code ret; + + ASN1_MALLOC_ENCODE(AuthorizationData, buf, buf_size, authdata, + &len, ret); + if (ret) + return ret; + if (buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ALLOC(req_body->enc_authorization_data, 1); + if (req_body->enc_authorization_data == NULL) { + free (buf); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + free (buf); + free (req_body->enc_authorization_data); + req_body->enc_authorization_data = NULL; + return ret; + } + krb5_encrypt_EncryptedData(context, + crypto, + KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, + /* KRB5_KU_TGS_REQ_AUTH_DAT_SESSION? */ + buf, + len, + 0, + req_body->enc_authorization_data); + free (buf); + krb5_crypto_destroy(context, crypto); + } else { + req_body->enc_authorization_data = NULL; + } + return 0; +} + +/* + * Create a tgs-req in `t' with `addresses', `flags', `second_ticket' + * (if not-NULL), `in_creds', `krbtgt', and returning the generated + * subkey in `subkey'. + */ + +static krb5_error_code +init_tgs_req (krb5_context context, + krb5_ccache ccache, + krb5_addresses *addresses, + krb5_kdc_flags flags, + Ticket *second_ticket, + krb5_creds *in_creds, + krb5_creds *krbtgt, + unsigned nonce, + krb5_keyblock **subkey, + TGS_REQ *t, + krb5_key_usage usage) +{ + krb5_error_code ret = 0; + + memset(t, 0, sizeof(*t)); + t->pvno = 5; + t->msg_type = krb_tgs_req; + if (in_creds->session.keytype) { + ALLOC_SEQ(&t->req_body.etype, 1); + if(t->req_body.etype.val == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + t->req_body.etype.val[0] = in_creds->session.keytype; + } else { + ret = krb5_init_etype(context, + &t->req_body.etype.len, + &t->req_body.etype.val, + NULL); + } + if (ret) + goto fail; + t->req_body.addresses = addresses; + t->req_body.kdc_options = flags.b; + ret = copy_Realm(&in_creds->server->realm, &t->req_body.realm); + if (ret) + goto fail; + ALLOC(t->req_body.sname, 1); + if (t->req_body.sname == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + + /* some versions of some code might require that the client be + present in TGS-REQs, but this is clearly against the spec */ + + ret = copy_PrincipalName(&in_creds->server->name, t->req_body.sname); + if (ret) + goto fail; + + /* req_body.till should be NULL if there is no endtime specified, + but old MIT code (like DCE secd) doesn't like that */ + ALLOC(t->req_body.till, 1); + if(t->req_body.till == NULL){ + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + *t->req_body.till = in_creds->times.endtime; + + t->req_body.nonce = nonce; + if(second_ticket){ + ALLOC(t->req_body.additional_tickets, 1); + if (t->req_body.additional_tickets == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + ALLOC_SEQ(t->req_body.additional_tickets, 1); + if (t->req_body.additional_tickets->val == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + ret = copy_Ticket(second_ticket, t->req_body.additional_tickets->val); + if (ret) + goto fail; + } + ALLOC(t->padata, 1); + if (t->padata == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + ALLOC_SEQ(t->padata, 1); + if (t->padata->val == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + + { + krb5_auth_context ac; + krb5_keyblock *key = NULL; + + ret = krb5_auth_con_init(context, &ac); + if(ret) + goto fail; + + if (krb5_config_get_bool_default(context, NULL, FALSE, + "realms", + krbtgt->server->realm, + "tgs_require_subkey", + NULL)) + { + ret = krb5_generate_subkey (context, &krbtgt->session, &key); + if (ret) { + krb5_auth_con_free (context, ac); + goto fail; + } + + ret = krb5_auth_con_setlocalsubkey(context, ac, key); + if (ret) { + if (key) + krb5_free_keyblock (context, key); + krb5_auth_con_free (context, ac); + goto fail; + } + } + + ret = set_auth_data (context, &t->req_body, &in_creds->authdata, + key ? key : &krbtgt->session); + if (ret) { + if (key) + krb5_free_keyblock (context, key); + krb5_auth_con_free (context, ac); + goto fail; + } + + ret = make_pa_tgs_req(context, + ac, + &t->req_body, + t->padata->val, + krbtgt, + usage); + if(ret) { + if (key) + krb5_free_keyblock (context, key); + krb5_auth_con_free(context, ac); + goto fail; + } + *subkey = key; + + krb5_auth_con_free(context, ac); + } +fail: + if (ret) { + t->req_body.addresses = NULL; + free_TGS_REQ (t); + } + return ret; +} + +krb5_error_code +_krb5_get_krbtgt(krb5_context context, + krb5_ccache id, + krb5_realm realm, + krb5_creds **cred) +{ + krb5_error_code ret; + krb5_creds tmp_cred; + + memset(&tmp_cred, 0, sizeof(tmp_cred)); + + ret = krb5_cc_get_principal(context, id, &tmp_cred.client); + if (ret) + return ret; + + ret = krb5_make_principal(context, + &tmp_cred.server, + realm, + KRB5_TGS_NAME, + realm, + NULL); + if(ret) { + krb5_free_principal(context, tmp_cred.client); + return ret; + } + ret = krb5_get_credentials(context, + KRB5_GC_CACHED, + id, + &tmp_cred, + cred); + krb5_free_principal(context, tmp_cred.client); + krb5_free_principal(context, tmp_cred.server); + if(ret) + return ret; + return 0; +} + +/* DCE compatible decrypt proc */ +static krb5_error_code +decrypt_tkt_with_subkey (krb5_context context, + krb5_keyblock *key, + krb5_key_usage usage, + krb5_const_pointer subkey, + krb5_kdc_rep *dec_rep) +{ + krb5_error_code ret; + krb5_data data; + size_t size; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + ret = krb5_decrypt_EncryptedData (context, + crypto, + usage, + &dec_rep->kdc_rep.enc_part, + &data); + krb5_crypto_destroy(context, crypto); + if(ret && subkey){ + /* DCE compat -- try to decrypt with subkey */ + ret = krb5_crypto_init(context, subkey, 0, &crypto); + if (ret) + return ret; + ret = krb5_decrypt_EncryptedData (context, + crypto, + KRB5_KU_TGS_REP_ENC_PART_SUB_KEY, + &dec_rep->kdc_rep.enc_part, + &data); + krb5_crypto_destroy(context, crypto); + } + if (ret) + return ret; + + ret = krb5_decode_EncASRepPart(context, + data.data, + data.length, + &dec_rep->enc_part, + &size); + if (ret) + ret = krb5_decode_EncTGSRepPart(context, + data.data, + data.length, + &dec_rep->enc_part, + &size); + krb5_data_free (&data); + return ret; +} + +static krb5_error_code +get_cred_kdc_usage(krb5_context context, + krb5_ccache id, + krb5_kdc_flags flags, + krb5_addresses *addresses, + krb5_creds *in_creds, + krb5_creds *krbtgt, + krb5_creds *out_creds, + krb5_key_usage usage) +{ + TGS_REQ req; + krb5_data enc; + krb5_data resp; + krb5_kdc_rep rep; + KRB_ERROR error; + krb5_error_code ret; + unsigned nonce; + krb5_keyblock *subkey = NULL; + size_t len; + Ticket second_ticket; + int send_to_kdc_flags = 0; + + krb5_data_zero(&resp); + krb5_data_zero(&enc); + + krb5_generate_random_block(&nonce, sizeof(nonce)); + nonce &= 0xffffffff; + + if(flags.b.enc_tkt_in_skey){ + ret = decode_Ticket(in_creds->second_ticket.data, + in_creds->second_ticket.length, + &second_ticket, &len); + if(ret) + return ret; + } + + ret = init_tgs_req (context, + id, + addresses, + flags, + flags.b.enc_tkt_in_skey ? &second_ticket : NULL, + in_creds, + krbtgt, + nonce, + &subkey, + &req, + usage); + if(flags.b.enc_tkt_in_skey) + free_Ticket(&second_ticket); + if (ret) + goto out; + + ASN1_MALLOC_ENCODE(TGS_REQ, enc.data, enc.length, &req, &len, ret); + if (ret) + goto out; + if(enc.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + /* don't free addresses */ + req.req_body.addresses = NULL; + free_TGS_REQ(&req); + + /* + * Send and receive + */ +again: + ret = krb5_sendto_kdc_flags (context, &enc, + &krbtgt->server->name.name_string.val[1], + &resp, + send_to_kdc_flags); + if(ret) + goto out; + + memset(&rep, 0, sizeof(rep)); + if(decode_TGS_REP(resp.data, resp.length, &rep.kdc_rep, &len) == 0){ + ret = krb5_copy_principal(context, + in_creds->client, + &out_creds->client); + if(ret) + goto out; + ret = krb5_copy_principal(context, + in_creds->server, + &out_creds->server); + if(ret) + goto out; + /* this should go someplace else */ + out_creds->times.endtime = in_creds->times.endtime; + + ret = _krb5_extract_ticket(context, + &rep, + out_creds, + &krbtgt->session, + NULL, + KRB5_KU_TGS_REP_ENC_PART_SESSION, + &krbtgt->addresses, + nonce, + TRUE, + flags.b.request_anonymous, + decrypt_tkt_with_subkey, + subkey); + krb5_free_kdc_rep(context, &rep); + } else if(krb5_rd_error(context, &resp, &error) == 0) { + ret = krb5_error_from_rd_error(context, &error, in_creds); + krb5_free_error_contents(context, &error); + + if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG && !(send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG)) { + send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; + krb5_data_free(&resp); + goto again; + } + } else if(resp.data && ((char*)resp.data)[0] == 4) { + ret = KRB5KRB_AP_ERR_V4_REPLY; + krb5_clear_error_string(context); + } else { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + krb5_clear_error_string(context); + } + +out: + krb5_data_free(&resp); + krb5_data_free(&enc); + if(subkey){ + krb5_free_keyblock_contents(context, subkey); + free(subkey); + } + return ret; + +} + +static krb5_error_code +get_cred_kdc(krb5_context context, + krb5_ccache id, + krb5_kdc_flags flags, + krb5_addresses *addresses, + krb5_creds *in_creds, + krb5_creds *krbtgt, + krb5_creds *out_creds) +{ + krb5_error_code ret; + + ret = get_cred_kdc_usage(context, id, flags, addresses, in_creds, + krbtgt, out_creds, KRB5_KU_TGS_REQ_AUTH); + if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + krb5_clear_error_string (context); + ret = get_cred_kdc_usage(context, id, flags, addresses, in_creds, + krbtgt, out_creds, KRB5_KU_AP_REQ_AUTH); + } + return ret; +} + +/* same as above, just get local addresses first */ + +static krb5_error_code +get_cred_kdc_la(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, + krb5_creds *in_creds, krb5_creds *krbtgt, + krb5_creds *out_creds) +{ + krb5_error_code ret; + krb5_addresses addresses, *addrs = &addresses; + + krb5_get_all_client_addrs(context, &addresses); + /* XXX this sucks. */ + if(addresses.len == 0) + addrs = NULL; + ret = get_cred_kdc(context, id, flags, addrs, + in_creds, krbtgt, out_creds); + krb5_free_addresses(context, &addresses); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_kdc_cred(krb5_context context, + krb5_ccache id, + krb5_kdc_flags flags, + krb5_addresses *addresses, + Ticket *second_ticket, + krb5_creds *in_creds, + krb5_creds **out_creds + ) +{ + krb5_error_code ret; + krb5_creds *krbtgt; + + *out_creds = calloc(1, sizeof(**out_creds)); + if(*out_creds == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = _krb5_get_krbtgt (context, + id, + in_creds->server->realm, + &krbtgt); + if(ret) { + free(*out_creds); + return ret; + } + ret = get_cred_kdc(context, id, flags, addresses, + in_creds, krbtgt, *out_creds); + krb5_free_creds (context, krbtgt); + if(ret) + free(*out_creds); + return ret; +} + + +static krb5_error_code +find_cred(krb5_context context, + krb5_ccache id, + krb5_principal server, + krb5_creds **tgts, + krb5_creds *out_creds) +{ + krb5_error_code ret; + krb5_creds mcreds; + + krb5_cc_clear_mcred(&mcreds); + mcreds.server = server; + ret = krb5_cc_retrieve_cred(context, id, KRB5_TC_DONT_MATCH_REALM, + &mcreds, out_creds); + if(ret == 0) + return 0; + while(tgts && *tgts){ + if(krb5_compare_creds(context, KRB5_TC_DONT_MATCH_REALM, + &mcreds, *tgts)){ + ret = krb5_copy_creds_contents(context, *tgts, out_creds); + return ret; + } + tgts++; + } + krb5_clear_error_string(context); + return KRB5_CC_NOTFOUND; +} + +static krb5_error_code +add_cred(krb5_context context, krb5_creds ***tgts, krb5_creds *tkt) +{ + int i; + krb5_error_code ret; + krb5_creds **tmp = *tgts; + + for(i = 0; tmp && tmp[i]; i++); /* XXX */ + tmp = realloc(tmp, (i+2)*sizeof(*tmp)); + if(tmp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + *tgts = tmp; + ret = krb5_copy_creds(context, tkt, &tmp[i]); + tmp[i+1] = NULL; + return ret; +} + +/* +get_cred(server) + creds = cc_get_cred(server) + if(creds) return creds + tgt = cc_get_cred(krbtgt/server_realm@any_realm) + if(tgt) + return get_cred_tgt(server, tgt) + if(client_realm == server_realm) + return NULL + tgt = get_cred(krbtgt/server_realm@client_realm) + while(tgt_inst != server_realm) + tgt = get_cred(krbtgt/server_realm@tgt_inst) + return get_cred_tgt(server, tgt) + */ + +static krb5_error_code +get_cred_from_kdc_flags(krb5_context context, + krb5_kdc_flags flags, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_creds **out_creds, + krb5_creds ***ret_tgts) +{ + krb5_error_code ret; + krb5_creds *tgt, tmp_creds; + krb5_const_realm client_realm, server_realm, try_realm; + + *out_creds = NULL; + + client_realm = krb5_principal_get_realm(context, in_creds->client); + server_realm = krb5_principal_get_realm(context, in_creds->server); + memset(&tmp_creds, 0, sizeof(tmp_creds)); + ret = krb5_copy_principal(context, in_creds->client, &tmp_creds.client); + if(ret) + return ret; + + try_realm = krb5_config_get_string(context, NULL, "capaths", + client_realm, server_realm, NULL); + +#if 1 + /* XXX remove in future release */ + if(try_realm == NULL) + try_realm = krb5_config_get_string(context, NULL, "libdefaults", + "capath", server_realm, NULL); +#endif + + if (try_realm == NULL) + try_realm = client_realm; + + ret = krb5_make_principal(context, + &tmp_creds.server, + try_realm, + KRB5_TGS_NAME, + server_realm, + NULL); + if(ret){ + krb5_free_principal(context, tmp_creds.client); + return ret; + } + { + krb5_creds tgts; + /* XXX try krb5_cc_retrieve_cred first? */ + ret = find_cred(context, ccache, tmp_creds.server, + *ret_tgts, &tgts); + if(ret == 0){ + *out_creds = calloc(1, sizeof(**out_creds)); + if(*out_creds == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + } else { + krb5_boolean noaddr; + + krb5_appdefault_boolean(context, NULL, tgts.server->realm, + "no-addresses", FALSE, &noaddr); + + if (noaddr) + ret = get_cred_kdc(context, ccache, flags, NULL, + in_creds, &tgts, *out_creds); + else + ret = get_cred_kdc_la(context, ccache, flags, + in_creds, &tgts, *out_creds); + if (ret) { + free (*out_creds); + *out_creds = NULL; + } + } + krb5_free_cred_contents(context, &tgts); + krb5_free_principal(context, tmp_creds.server); + krb5_free_principal(context, tmp_creds.client); + return ret; + } + } + if(krb5_realm_compare(context, in_creds->client, in_creds->server)) { + krb5_clear_error_string (context); + return KRB5_CC_NOTFOUND; + } + /* XXX this can loop forever */ + while(1){ + heim_general_string tgt_inst; + + ret = get_cred_from_kdc_flags(context, flags, ccache, &tmp_creds, + &tgt, ret_tgts); + if(ret) { + krb5_free_principal(context, tmp_creds.server); + krb5_free_principal(context, tmp_creds.client); + return ret; + } + ret = add_cred(context, ret_tgts, tgt); + if(ret) { + krb5_free_principal(context, tmp_creds.server); + krb5_free_principal(context, tmp_creds.client); + return ret; + } + tgt_inst = tgt->server->name.name_string.val[1]; + if(strcmp(tgt_inst, server_realm) == 0) + break; + krb5_free_principal(context, tmp_creds.server); + ret = krb5_make_principal(context, &tmp_creds.server, + tgt_inst, KRB5_TGS_NAME, server_realm, NULL); + if(ret) { + krb5_free_principal(context, tmp_creds.server); + krb5_free_principal(context, tmp_creds.client); + return ret; + } + ret = krb5_free_creds(context, tgt); + if(ret) { + krb5_free_principal(context, tmp_creds.server); + krb5_free_principal(context, tmp_creds.client); + return ret; + } + } + + krb5_free_principal(context, tmp_creds.server); + krb5_free_principal(context, tmp_creds.client); + *out_creds = calloc(1, sizeof(**out_creds)); + if(*out_creds == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + } else { + krb5_boolean noaddr; + + krb5_appdefault_boolean(context, NULL, tgt->server->realm, + "no-addresses", FALSE, &noaddr); + if (noaddr) + ret = get_cred_kdc (context, ccache, flags, NULL, + in_creds, tgt, *out_creds); + else + ret = get_cred_kdc_la(context, ccache, flags, + in_creds, tgt, *out_creds); + if (ret) { + free (*out_creds); + *out_creds = NULL; + } + } + krb5_free_creds(context, tgt); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_cred_from_kdc_opt(krb5_context context, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_creds **out_creds, + krb5_creds ***ret_tgts, + krb5_flags flags) +{ + krb5_kdc_flags f; + f.i = flags; + return get_cred_from_kdc_flags(context, f, ccache, + in_creds, out_creds, ret_tgts); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_cred_from_kdc(krb5_context context, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_creds **out_creds, + krb5_creds ***ret_tgts) +{ + return krb5_get_cred_from_kdc_opt(context, ccache, + in_creds, out_creds, ret_tgts, 0); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_credentials_with_flags(krb5_context context, + krb5_flags options, + krb5_kdc_flags flags, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_creds **out_creds) +{ + krb5_error_code ret; + krb5_creds **tgts; + krb5_creds *res_creds; + int i; + + *out_creds = NULL; + res_creds = calloc(1, sizeof(*res_creds)); + if (res_creds == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + if (in_creds->session.keytype) + options |= KRB5_TC_MATCH_KEYTYPE; + + ret = krb5_cc_retrieve_cred(context, + ccache, + options, + in_creds, res_creds); + /* + * If we got a credential, check if credential is expired before + * returning it. + */ + ret = krb5_cc_retrieve_cred(context, + ccache, + in_creds->session.keytype ? + KRB5_TC_MATCH_KEYTYPE : 0, + in_creds, res_creds); + /* + * If we got a credential, check if credential is expired before + * returning it, but only if KRB5_GC_EXPIRED_OK is not set. + */ + if (ret == 0) { + krb5_timestamp timeret; + + /* If expired ok, don't bother checking */ + if(options & KRB5_GC_EXPIRED_OK) { + *out_creds = res_creds; + return 0; + } + + krb5_timeofday(context, &timeret); + if(res_creds->times.endtime > timeret) { + *out_creds = res_creds; + return 0; + } + if(options & KRB5_GC_CACHED) + krb5_cc_remove_cred(context, ccache, 0, res_creds); + + } else if(ret != KRB5_CC_END) { + free(res_creds); + return ret; + } + free(res_creds); + if(options & KRB5_GC_CACHED) { + krb5_clear_error_string (context); + return KRB5_CC_NOTFOUND; + } + if(options & KRB5_GC_USER_USER) + flags.b.enc_tkt_in_skey = 1; + tgts = NULL; + ret = get_cred_from_kdc_flags(context, flags, ccache, + in_creds, out_creds, &tgts); + for(i = 0; tgts && tgts[i]; i++) { + krb5_cc_store_cred(context, ccache, tgts[i]); + krb5_free_creds(context, tgts[i]); + } + free(tgts); + if(ret == 0 && flags.b.enc_tkt_in_skey == 0) + krb5_cc_store_cred(context, ccache, *out_creds); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_credentials(krb5_context context, + krb5_flags options, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_creds **out_creds) +{ + krb5_kdc_flags flags; + flags.i = 0; + return krb5_get_credentials_with_flags(context, options, flags, + ccache, in_creds, out_creds); +} diff --git a/source4/heimdal/lib/krb5/get_default_principal.c b/source4/heimdal/lib/krb5/get_default_principal.c new file mode 100644 index 0000000000..03e8f0a823 --- /dev/null +++ b/source4/heimdal/lib/krb5/get_default_principal.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: get_default_principal.c,v 1.10 2005/04/20 20:53:29 lha Exp $"); + +/* + * Try to find out what's a reasonable default principal. + */ + +static const char* +get_env_user(void) +{ + const char *user = getenv("USER"); + if(user == NULL) + user = getenv("LOGNAME"); + if(user == NULL) + user = getenv("USERNAME"); + return user; +} + +/* + * Will only use operating-system dependant operation to get the + * default principal, for use of functions that in ccache layer to + * avoid recursive calls. + */ + +krb5_error_code +_krb5_get_default_principal_local (krb5_context context, + krb5_principal *princ) +{ + krb5_error_code ret; + const char *user; + uid_t uid; + + *princ = NULL; + + uid = getuid(); + if(uid == 0) { + user = getlogin(); + if(user == NULL) + user = get_env_user(); + if(user != NULL && strcmp(user, "root") != 0) + ret = krb5_make_principal(context, princ, NULL, user, "root", NULL); + else + ret = krb5_make_principal(context, princ, NULL, "root", NULL); + } else { + struct passwd *pw = getpwuid(uid); + if(pw != NULL) + user = pw->pw_name; + else { + user = get_env_user(); + if(user == NULL) + user = getlogin(); + } + if(user == NULL) { + krb5_set_error_string(context, + "unable to figure out current principal"); + return ENOTTY; /* XXX */ + } + ret = krb5_make_principal(context, princ, NULL, user, NULL); + } + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_principal (krb5_context context, + krb5_principal *princ) +{ + krb5_error_code ret; + krb5_ccache id; + + *princ = NULL; + + ret = krb5_cc_default (context, &id); + if (ret == 0) { + ret = krb5_cc_get_principal (context, id, princ); + krb5_cc_close (context, id); + if (ret == 0) + return 0; + } + + return _krb5_get_default_principal_local(context, princ); +} diff --git a/source4/heimdal/lib/krb5/get_default_realm.c b/source4/heimdal/lib/krb5/get_default_realm.c new file mode 100644 index 0000000000..bb72daf373 --- /dev/null +++ b/source4/heimdal/lib/krb5/get_default_realm.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 1997 - 2001, 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: get_default_realm.c,v 1.13 2004/05/25 21:27:17 lha Exp $"); + +/* + * Return a NULL-terminated list of default realms in `realms'. + * Free this memory with krb5_free_host_realm. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_realms (krb5_context context, + krb5_realm **realms) +{ + if (context->default_realms == NULL) { + krb5_error_code ret = krb5_set_default_realm (context, NULL); + if (ret) + return KRB5_CONFIG_NODEFREALM; + } + + return krb5_copy_host_realm (context, + context->default_realms, + realms); +} + +/* + * Return the first default realm. For compatibility. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_realm(krb5_context context, + krb5_realm *realm) +{ + krb5_error_code ret; + char *res; + + if (context->default_realms == NULL + || context->default_realms[0] == NULL) { + krb5_clear_error_string(context); + ret = krb5_set_default_realm (context, NULL); + if (ret) + return ret; + } + + res = strdup (context->default_realms[0]); + if (res == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + *realm = res; + return 0; +} diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c new file mode 100644 index 0000000000..ea0bc4ad9e --- /dev/null +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -0,0 +1,427 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: get_for_creds.c,v 1.45 2005/06/15 02:44:36 lha Exp $"); + +static krb5_error_code +add_addrs(krb5_context context, + krb5_addresses *addr, + struct addrinfo *ai) +{ + krb5_error_code ret; + unsigned n, i; + void *tmp; + struct addrinfo *a; + + n = 0; + for (a = ai; a != NULL; a = a->ai_next) + ++n; + + tmp = realloc(addr->val, (addr->len + n) * sizeof(*addr->val)); + if (tmp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto fail; + } + addr->val = tmp; + for (i = addr->len; i < (addr->len + n); ++i) { + addr->val[i].addr_type = 0; + krb5_data_zero(&addr->val[i].address); + } + i = addr->len; + for (a = ai; a != NULL; a = a->ai_next) { + krb5_address ad; + + ret = krb5_sockaddr2address (context, a->ai_addr, &ad); + if (ret == 0) { + if (krb5_address_search(context, &ad, addr)) + krb5_free_address(context, &ad); + else + addr->val[i++] = ad; + } + else if (ret == KRB5_PROG_ATYPE_NOSUPP) + krb5_clear_error_string (context); + else + goto fail; + addr->len = i; + } + return 0; +fail: + krb5_free_addresses (context, addr); + return ret; +} + +/* + * Forward credentials for `client' to host `hostname`, + * making them forwardable if `forwardable', and returning the + * blob of data to sent in `out_data'. + * If hostname == NULL, pick it from `server' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_fwd_tgt_creds (krb5_context context, + krb5_auth_context auth_context, + const char *hostname, + krb5_principal client, + krb5_principal server, + krb5_ccache ccache, + int forwardable, + krb5_data *out_data) +{ + krb5_flags flags = 0; + krb5_creds creds; + krb5_error_code ret; + krb5_const_realm client_realm; + + flags |= KDC_OPT_FORWARDED; + + if (forwardable) + flags |= KDC_OPT_FORWARDABLE; + + if (hostname == NULL && + krb5_principal_get_type(context, server) == KRB5_NT_SRV_HST) { + const char *inst = krb5_principal_get_comp_string(context, server, 0); + const char *host = krb5_principal_get_comp_string(context, server, 1); + + if (inst != NULL && + strcmp(inst, "host") == 0 && + host != NULL && + krb5_principal_get_comp_string(context, server, 2) == NULL) + hostname = host; + } + + client_realm = krb5_principal_get_realm(context, client); + + memset (&creds, 0, sizeof(creds)); + creds.client = client; + + ret = krb5_build_principal(context, + &creds.server, + strlen(client_realm), + client_realm, + KRB5_TGS_NAME, + client_realm, + NULL); + if (ret) + return ret; + + ret = krb5_get_forwarded_creds (context, + auth_context, + ccache, + flags, + hostname, + &creds, + out_data); + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_forwarded_creds (krb5_context context, + krb5_auth_context auth_context, + krb5_ccache ccache, + krb5_flags flags, + const char *hostname, + krb5_creds *in_creds, + krb5_data *out_data) +{ + krb5_error_code ret; + krb5_creds *out_creds; + krb5_addresses addrs, *paddrs; + KRB_CRED cred; + KrbCredInfo *krb_cred_info; + EncKrbCredPart enc_krb_cred_part; + size_t len; + unsigned char *buf; + size_t buf_size; + krb5_kdc_flags kdc_flags; + krb5_crypto crypto; + struct addrinfo *ai; + int save_errno; + krb5_creds *ticket; + char *realm; + + if (in_creds->client && in_creds->client->realm) + realm = in_creds->client->realm; + else + realm = in_creds->server->realm; + + addrs.len = 0; + addrs.val = NULL; + paddrs = &addrs; + + /* + * If tickets are address-less, forward address-less tickets. + */ + + ret = _krb5_get_krbtgt (context, + ccache, + realm, + &ticket); + if(ret == 0) { + if (ticket->addresses.len == 0) + paddrs = NULL; + krb5_free_creds (context, ticket); + } + + if (paddrs != NULL) { + + ret = getaddrinfo (hostname, NULL, NULL, &ai); + if (ret) { + save_errno = errno; + krb5_set_error_string(context, "resolving %s: %s", + hostname, gai_strerror(ret)); + return krb5_eai_to_heim_errno(ret, save_errno); + } + + ret = add_addrs (context, &addrs, ai); + freeaddrinfo (ai); + if (ret) + return ret; + } + + kdc_flags.b = int2KDCOptions(flags); + + ret = krb5_get_kdc_cred (context, + ccache, + kdc_flags, + paddrs, + NULL, + in_creds, + &out_creds); + krb5_free_addresses (context, &addrs); + if (ret) { + return ret; + } + + memset (&cred, 0, sizeof(cred)); + cred.pvno = 5; + cred.msg_type = krb_cred; + ALLOC_SEQ(&cred.tickets, 1); + if (cred.tickets.val == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto out2; + } + ret = decode_Ticket(out_creds->ticket.data, + out_creds->ticket.length, + cred.tickets.val, &len); + if (ret) + goto out3; + + memset (&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part)); + ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1); + if (enc_krb_cred_part.ticket_info.val == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto out4; + } + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + krb5_timestamp sec; + int32_t usec; + + krb5_us_timeofday (context, &sec, &usec); + + ALLOC(enc_krb_cred_part.timestamp, 1); + if (enc_krb_cred_part.timestamp == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto out4; + } + *enc_krb_cred_part.timestamp = sec; + ALLOC(enc_krb_cred_part.usec, 1); + if (enc_krb_cred_part.usec == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto out4; + } + *enc_krb_cred_part.usec = usec; + } else { + enc_krb_cred_part.timestamp = NULL; + enc_krb_cred_part.usec = NULL; + } + + if (auth_context->local_address && auth_context->local_port) { + krb5_boolean noaddr; + krb5_const_realm srealm; + + srealm = krb5_principal_get_realm(context, out_creds->server); + krb5_appdefault_boolean(context, NULL, srealm, "no-addresses", + paddrs == NULL, &noaddr); + if (!noaddr) { + ret = krb5_make_addrport (context, + &enc_krb_cred_part.s_address, + auth_context->local_address, + auth_context->local_port); + if (ret) + goto out4; + } + } + + if (auth_context->remote_address) { + if (auth_context->remote_port) { + krb5_boolean noaddr; + krb5_const_realm srealm; + + srealm = krb5_principal_get_realm(context, out_creds->server); + /* Is this correct, and should we use the paddrs == NULL + trick here as well? Having an address-less ticket may + indicate that we don't know our own global address, but + it does not necessary mean that we don't know the + server's. */ + krb5_appdefault_boolean(context, NULL, srealm, "no-addresses", + FALSE, &noaddr); + if (!noaddr) { + ret = krb5_make_addrport (context, + &enc_krb_cred_part.r_address, + auth_context->remote_address, + auth_context->remote_port); + if (ret) + goto out4; + } + } else { + ALLOC(enc_krb_cred_part.r_address, 1); + if (enc_krb_cred_part.r_address == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto out4; + } + + ret = krb5_copy_address (context, auth_context->remote_address, + enc_krb_cred_part.r_address); + if (ret) + goto out4; + } + } + + /* fill ticket_info.val[0] */ + + enc_krb_cred_part.ticket_info.len = 1; + + krb_cred_info = enc_krb_cred_part.ticket_info.val; + + copy_EncryptionKey (&out_creds->session, &krb_cred_info->key); + ALLOC(krb_cred_info->prealm, 1); + copy_Realm (&out_creds->client->realm, krb_cred_info->prealm); + ALLOC(krb_cred_info->pname, 1); + copy_PrincipalName(&out_creds->client->name, krb_cred_info->pname); + ALLOC(krb_cred_info->flags, 1); + *krb_cred_info->flags = out_creds->flags.b; + ALLOC(krb_cred_info->authtime, 1); + *krb_cred_info->authtime = out_creds->times.authtime; + ALLOC(krb_cred_info->starttime, 1); + *krb_cred_info->starttime = out_creds->times.starttime; + ALLOC(krb_cred_info->endtime, 1); + *krb_cred_info->endtime = out_creds->times.endtime; + ALLOC(krb_cred_info->renew_till, 1); + *krb_cred_info->renew_till = out_creds->times.renew_till; + ALLOC(krb_cred_info->srealm, 1); + copy_Realm (&out_creds->server->realm, krb_cred_info->srealm); + ALLOC(krb_cred_info->sname, 1); + copy_PrincipalName (&out_creds->server->name, krb_cred_info->sname); + ALLOC(krb_cred_info->caddr, 1); + copy_HostAddresses (&out_creds->addresses, krb_cred_info->caddr); + + krb5_free_creds (context, out_creds); + + /* encode EncKrbCredPart */ + + ASN1_MALLOC_ENCODE(EncKrbCredPart, buf, buf_size, + &enc_krb_cred_part, &len, ret); + free_EncKrbCredPart (&enc_krb_cred_part); + if (ret) { + free_KRB_CRED(&cred); + return ret; + } + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) { + cred.enc_part.etype = ENCTYPE_NULL; + cred.enc_part.kvno = NULL; + cred.enc_part.cipher.data = buf; + cred.enc_part.cipher.length = buf_size; + } else { + krb5_keyblock *key; + + if (auth_context->local_subkey) + key = auth_context->local_subkey; + else if (auth_context->remote_subkey) + key = auth_context->remote_subkey; + else + key = auth_context->keyblock; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + free(buf); + free_KRB_CRED(&cred); + return ret; + } + ret = krb5_encrypt_EncryptedData (context, + crypto, + KRB5_KU_KRB_CRED, + buf, + len, + 0, + &cred.enc_part); + free(buf); + krb5_crypto_destroy(context, crypto); + if (ret) { + free_KRB_CRED(&cred); + return ret; + } + } + + ASN1_MALLOC_ENCODE(KRB_CRED, buf, buf_size, &cred, &len, ret); + free_KRB_CRED (&cred); + if (ret) + return ret; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + out_data->length = len; + out_data->data = buf; + return 0; + out4: + free_EncKrbCredPart(&enc_krb_cred_part); + out3: + free_KRB_CRED(&cred); + out2: + krb5_free_creds (context, out_creds); + return ret; +} diff --git a/source4/heimdal/lib/krb5/get_host_realm.c b/source4/heimdal/lib/krb5/get_host_realm.c new file mode 100644 index 0000000000..d9c5bd5dc1 --- /dev/null +++ b/source4/heimdal/lib/krb5/get_host_realm.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +#include + +RCSID("$Id: get_host_realm.c,v 1.34 2005/04/19 18:52:51 lha Exp $"); + +/* To automagically find the correct realm of a host (without + * [domain_realm] in krb5.conf) add a text record for your domain with + * the name of your realm, like this: + * + * _kerberos IN TXT "FOO.SE" + * + * The search is recursive, so you can add entries for specific + * hosts. To find the realm of host a.b.c, it first tries + * _kerberos.a.b.c, then _kerberos.b.c and so on. + * + * This method is described in draft-ietf-cat-krb-dns-locate-03.txt. + * + */ + +static int +copy_txt_to_realms (struct resource_record *head, + krb5_realm **realms) +{ + struct resource_record *rr; + int n, i; + + for(n = 0, rr = head; rr; rr = rr->next) + if (rr->type == T_TXT) + ++n; + + if (n == 0) + return -1; + + *realms = malloc ((n + 1) * sizeof(krb5_realm)); + if (*realms == NULL) + return -1; + + for (i = 0; i < n + 1; ++i) + (*realms)[i] = NULL; + + for (i = 0, rr = head; rr; rr = rr->next) { + if (rr->type == T_TXT) { + char *tmp; + + tmp = strdup(rr->u.txt); + if (tmp == NULL) { + for (i = 0; i < n; ++i) + free ((*realms)[i]); + free (*realms); + return -1; + } + (*realms)[i] = tmp; + ++i; + } + } + return 0; +} + +static int +dns_find_realm(krb5_context context, + const char *domain, + krb5_realm **realms) +{ + static char *default_labels[] = { "_kerberos", NULL }; + char dom[MAXHOSTNAMELEN]; + struct dns_reply *r; + char **labels; + int i, ret; + + labels = krb5_config_get_strings(context, NULL, "libdefaults", + "dns_lookup_realm_labels", NULL); + if(labels == NULL) + labels = default_labels; + if(*domain == '.') + domain++; + for (i = 0; labels[i] != NULL; i++) { + ret = snprintf(dom, sizeof(dom), "%s.%s.", labels[i], domain); + if(ret < 0 || ret >= sizeof(dom)) + return -1; + r = dns_lookup(dom, "TXT"); + if(r != NULL) { + ret = copy_txt_to_realms (r->head, realms); + dns_free_data(r); + if(ret == 0) + return 0; + } + } + return -1; +} + +/* + * Try to figure out what realms host in `domain' belong to from the + * configuration file. + */ + +static int +config_find_realm(krb5_context context, + const char *domain, + krb5_realm **realms) +{ + char **tmp = krb5_config_get_strings (context, NULL, + "domain_realm", + domain, + NULL); + + if (tmp == NULL) + return -1; + *realms = tmp; + return 0; +} + +/* + * This function assumes that `host' is a FQDN (and doesn't handle the + * special case of host == NULL either). + * Try to find mapping in the config file or DNS and it that fails, + * fall back to guessing + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_get_host_realm_int (krb5_context context, + const char *host, + krb5_boolean use_dns, + krb5_realm **realms) +{ + const char *p, *q; + krb5_boolean dns_locate_enable; + + dns_locate_enable = krb5_config_get_bool_default(context, NULL, TRUE, + "libdefaults", "dns_lookup_realm", NULL); + for (p = host; p != NULL; p = strchr (p + 1, '.')) { + if(config_find_realm(context, p, realms) == 0) { + if(strcasecmp(*realms[0], "dns_locate") == 0) { + if(use_dns) + for (q = host; q != NULL; q = strchr(q + 1, '.')) + if(dns_find_realm(context, q, realms) == 0) + return 0; + continue; + } else + return 0; + } + else if(use_dns && dns_locate_enable) { + if(dns_find_realm(context, p, realms) == 0) + return 0; + } + } + p = strchr(host, '.'); + if(p != NULL) { + p++; + *realms = malloc(2 * sizeof(krb5_realm)); + if (*realms == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + (*realms)[0] = strdup(p); + if((*realms)[0] == NULL) { + free(*realms); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + strupr((*realms)[0]); + (*realms)[1] = NULL; + return 0; + } + krb5_set_error_string(context, "unable to find realm of host %s", host); + return KRB5_ERR_HOST_REALM_UNKNOWN; +} + +/* + * Return the realm(s) of `host' as a NULL-terminated list in `realms'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_host_realm(krb5_context context, + const char *host, + krb5_realm **realms) +{ + char hostname[MAXHOSTNAMELEN]; + + if (host == NULL) { + if (gethostname (hostname, sizeof(hostname))) + return errno; + host = hostname; + } + + return _krb5_get_host_realm_int (context, host, 1, realms); +} diff --git a/source4/heimdal/lib/krb5/get_in_tkt.c b/source4/heimdal/lib/krb5/get_in_tkt.c new file mode 100644 index 0000000000..24d6c29f52 --- /dev/null +++ b/source4/heimdal/lib/krb5/get_in_tkt.c @@ -0,0 +1,823 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: get_in_tkt.c,v 1.116 2005/06/15 02:53:20 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_init_etype (krb5_context context, + unsigned *len, + krb5_enctype **val, + const krb5_enctype *etypes) +{ + int i; + krb5_error_code ret; + krb5_enctype *tmp = NULL; + + ret = 0; + if (etypes == NULL) { + ret = krb5_get_default_in_tkt_etypes(context, + &tmp); + if (ret) + return ret; + etypes = tmp; + } + + for (i = 0; etypes[i]; ++i) + ; + *len = i; + *val = malloc(i * sizeof(**val)); + if (i != 0 && *val == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto cleanup; + } + memmove (*val, + etypes, + i * sizeof(*tmp)); +cleanup: + if (tmp != NULL) + free (tmp); + return ret; +} + + +static krb5_error_code +decrypt_tkt (krb5_context context, + krb5_keyblock *key, + krb5_key_usage usage, + krb5_const_pointer decrypt_arg, + krb5_kdc_rep *dec_rep) +{ + krb5_error_code ret; + krb5_data data; + size_t size; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + + ret = krb5_decrypt_EncryptedData (context, + crypto, + usage, + &dec_rep->kdc_rep.enc_part, + &data); + krb5_crypto_destroy(context, crypto); + + if (ret) + return ret; + + ret = krb5_decode_EncASRepPart(context, + data.data, + data.length, + &dec_rep->enc_part, + &size); + if (ret) + ret = krb5_decode_EncTGSRepPart(context, + data.data, + data.length, + &dec_rep->enc_part, + &size); + krb5_data_free (&data); + if (ret) + return ret; + return 0; +} + +int +_krb5_extract_ticket(krb5_context context, + krb5_kdc_rep *rep, + krb5_creds *creds, + krb5_keyblock *key, + krb5_const_pointer keyseed, + krb5_key_usage key_usage, + krb5_addresses *addrs, + unsigned nonce, + krb5_boolean allow_server_mismatch, + krb5_boolean ignore_cname, + krb5_decrypt_proc decrypt_proc, + krb5_const_pointer decryptarg) +{ + krb5_error_code ret; + krb5_principal tmp_principal; + int tmp; + size_t len; + time_t tmp_time; + krb5_timestamp sec_now; + + ret = _krb5_principalname2krb5_principal (&tmp_principal, + rep->kdc_rep.cname, + rep->kdc_rep.crealm); + if (ret) + goto out; + + /* compare client */ + + if (!ignore_cname) { + tmp = krb5_principal_compare (context, tmp_principal, creds->client); + if (!tmp) { + krb5_free_principal (context, tmp_principal); + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_MODIFIED; + goto out; + } + } + + krb5_free_principal (context, creds->client); + creds->client = tmp_principal; + + /* extract ticket */ + ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, + &rep->kdc_rep.ticket, &len, ret); + if(ret) + goto out; + if (creds->ticket.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + creds->second_ticket.length = 0; + creds->second_ticket.data = NULL; + + /* compare server */ + + ret = _krb5_principalname2krb5_principal (&tmp_principal, + rep->kdc_rep.ticket.sname, + rep->kdc_rep.ticket.realm); + if (ret) + goto out; + if(allow_server_mismatch){ + krb5_free_principal(context, creds->server); + creds->server = tmp_principal; + tmp_principal = NULL; + }else{ + tmp = krb5_principal_compare (context, tmp_principal, creds->server); + krb5_free_principal (context, tmp_principal); + if (!tmp) { + ret = KRB5KRB_AP_ERR_MODIFIED; + krb5_clear_error_string (context); + goto out; + } + } + + /* decrypt */ + + if (decrypt_proc == NULL) + decrypt_proc = decrypt_tkt; + + ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep); + if (ret) + goto out; + +#if 0 + /* XXX should this decode be here, or in the decrypt_proc? */ + ret = krb5_decode_keyblock(context, &rep->enc_part.key, 1); + if(ret) + goto out; +#endif + + /* compare nonces */ + + if (nonce != rep->enc_part.nonce) { + ret = KRB5KRB_AP_ERR_MODIFIED; + krb5_set_error_string(context, "malloc: out of memory"); + goto out; + } + + /* set kdc-offset */ + + krb5_timeofday (context, &sec_now); + if (rep->enc_part.flags.initial + && context->kdc_sec_offset == 0 + && krb5_config_get_bool (context, NULL, + "libdefaults", + "kdc_timesync", + NULL)) { + context->kdc_sec_offset = rep->enc_part.authtime - sec_now; + krb5_timeofday (context, &sec_now); + } + + /* check all times */ + + if (rep->enc_part.starttime) { + tmp_time = *rep->enc_part.starttime; + } else + tmp_time = rep->enc_part.authtime; + + if (creds->times.starttime == 0 + && abs(tmp_time - sec_now) > context->max_skew) { + ret = KRB5KRB_AP_ERR_SKEW; + krb5_set_error_string (context, + "time skew (%d) larger than max (%d)", + abs(tmp_time - sec_now), + (int)context->max_skew); + goto out; + } + + if (creds->times.starttime != 0 + && tmp_time != creds->times.starttime) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_MODIFIED; + goto out; + } + + creds->times.starttime = tmp_time; + + if (rep->enc_part.renew_till) { + tmp_time = *rep->enc_part.renew_till; + } else + tmp_time = 0; + + if (creds->times.renew_till != 0 + && tmp_time > creds->times.renew_till) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_MODIFIED; + goto out; + } + + creds->times.renew_till = tmp_time; + + creds->times.authtime = rep->enc_part.authtime; + + if (creds->times.endtime != 0 + && rep->enc_part.endtime > creds->times.endtime) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_MODIFIED; + goto out; + } + + creds->times.endtime = rep->enc_part.endtime; + + if(rep->enc_part.caddr) + krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses); + else if(addrs) + krb5_copy_addresses (context, addrs, &creds->addresses); + else { + creds->addresses.len = 0; + creds->addresses.val = NULL; + } + creds->flags.b = rep->enc_part.flags; + + creds->authdata.len = 0; + creds->authdata.val = NULL; + creds->session.keyvalue.length = 0; + creds->session.keyvalue.data = NULL; + creds->session.keytype = rep->enc_part.key.keytype; + ret = krb5_data_copy (&creds->session.keyvalue, + rep->enc_part.key.keyvalue.data, + rep->enc_part.key.keyvalue.length); + +out: + memset (rep->enc_part.key.keyvalue.data, 0, + rep->enc_part.key.keyvalue.length); + return ret; +} + + +static krb5_error_code +make_pa_enc_timestamp(krb5_context context, PA_DATA *pa, + krb5_enctype etype, krb5_keyblock *key) +{ + PA_ENC_TS_ENC p; + unsigned char *buf; + size_t buf_size; + size_t len; + EncryptedData encdata; + krb5_error_code ret; + int32_t usec; + int usec2; + krb5_crypto crypto; + + krb5_us_timeofday (context, &p.patimestamp, &usec); + usec2 = usec; + p.pausec = &usec2; + + ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret); + if (ret) + return ret; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + free(buf); + return ret; + } + ret = krb5_encrypt_EncryptedData(context, + crypto, + KRB5_KU_PA_ENC_TIMESTAMP, + buf, + len, + 0, + &encdata); + free(buf); + krb5_crypto_destroy(context, crypto); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret); + free_EncryptedData(&encdata); + if (ret) + return ret; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP; + pa->padata_value.length = len; + pa->padata_value.data = buf; + return 0; +} + +static krb5_error_code +add_padata(krb5_context context, + METHOD_DATA *md, + krb5_principal client, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + krb5_enctype *enctypes, + unsigned netypes, + krb5_salt *salt) +{ + krb5_error_code ret; + PA_DATA *pa2; + krb5_salt salt2; + krb5_enctype *ep; + int i; + + if(salt == NULL) { + /* default to standard salt */ + ret = krb5_get_pw_salt (context, client, &salt2); + salt = &salt2; + } + if (!enctypes) { + enctypes = context->etypes; + netypes = 0; + for (ep = enctypes; *ep != ETYPE_NULL; ep++) + netypes++; + } + pa2 = realloc (md->val, (md->len + netypes) * sizeof(*md->val)); + if (pa2 == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + md->val = pa2; + + for (i = 0; i < netypes; ++i) { + krb5_keyblock *key; + + ret = (*key_proc)(context, enctypes[i], *salt, keyseed, &key); + if (ret) + continue; + ret = make_pa_enc_timestamp (context, &md->val[md->len], + enctypes[i], key); + krb5_free_keyblock (context, key); + if (ret) + return ret; + ++md->len; + } + if(salt == &salt2) + krb5_free_salt(context, salt2); + return 0; +} + +static krb5_error_code +init_as_req (krb5_context context, + krb5_kdc_flags opts, + krb5_creds *creds, + const krb5_addresses *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *ptypes, + const krb5_preauthdata *preauth, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + unsigned nonce, + AS_REQ *a) +{ + krb5_error_code ret; + krb5_salt salt; + + memset(a, 0, sizeof(*a)); + + a->pvno = 5; + a->msg_type = krb_as_req; + a->req_body.kdc_options = opts.b; + a->req_body.cname = malloc(sizeof(*a->req_body.cname)); + if (a->req_body.cname == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + a->req_body.sname = malloc(sizeof(*a->req_body.sname)); + if (a->req_body.sname == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + ret = _krb5_principal2principalname (a->req_body.cname, creds->client); + if (ret) + goto fail; + ret = _krb5_principal2principalname (a->req_body.sname, creds->server); + if (ret) + goto fail; + ret = copy_Realm(&creds->client->realm, &a->req_body.realm); + if (ret) + goto fail; + + if(creds->times.starttime) { + a->req_body.from = malloc(sizeof(*a->req_body.from)); + if (a->req_body.from == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + *a->req_body.from = creds->times.starttime; + } + if(creds->times.endtime){ + ALLOC(a->req_body.till, 1); + *a->req_body.till = creds->times.endtime; + } + if(creds->times.renew_till){ + a->req_body.rtime = malloc(sizeof(*a->req_body.rtime)); + if (a->req_body.rtime == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + *a->req_body.rtime = creds->times.renew_till; + } + a->req_body.nonce = nonce; + ret = krb5_init_etype (context, + &a->req_body.etype.len, + &a->req_body.etype.val, + etypes); + if (ret) + goto fail; + + /* + * This means no addresses + */ + + if (addrs && addrs->len == 0) { + a->req_body.addresses = NULL; + } else { + a->req_body.addresses = malloc(sizeof(*a->req_body.addresses)); + if (a->req_body.addresses == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + + if (addrs) + ret = krb5_copy_addresses(context, addrs, a->req_body.addresses); + else { + ret = krb5_get_all_client_addrs (context, a->req_body.addresses); + if(ret == 0 && a->req_body.addresses->len == 0) { + free(a->req_body.addresses); + a->req_body.addresses = NULL; + } + } + if (ret) + return ret; + } + + a->req_body.enc_authorization_data = NULL; + a->req_body.additional_tickets = NULL; + + if(preauth != NULL) { + int i; + ALLOC(a->padata, 1); + if(a->padata == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + a->padata->val = NULL; + a->padata->len = 0; + for(i = 0; i < preauth->len; i++) { + if(preauth->val[i].type == KRB5_PADATA_ENC_TIMESTAMP){ + int j; + + for(j = 0; j < preauth->val[i].info.len; j++) { + krb5_salt *sp = &salt; + if(preauth->val[i].info.val[j].salttype) + salt.salttype = *preauth->val[i].info.val[j].salttype; + else + salt.salttype = KRB5_PW_SALT; + if(preauth->val[i].info.val[j].salt) + salt.saltvalue = *preauth->val[i].info.val[j].salt; + else + if(salt.salttype == KRB5_PW_SALT) + sp = NULL; + else + krb5_data_zero(&salt.saltvalue); + ret = add_padata(context, a->padata, creds->client, + key_proc, keyseed, + &preauth->val[i].info.val[j].etype, 1, + sp); + if (ret == 0) + break; + } + } + } + } else + /* not sure this is the way to use `ptypes' */ + if (ptypes == NULL || *ptypes == KRB5_PADATA_NONE) + a->padata = NULL; + else if (*ptypes == KRB5_PADATA_ENC_TIMESTAMP) { + ALLOC(a->padata, 1); + if (a->padata == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + a->padata->len = 0; + a->padata->val = NULL; + + /* make a v5 salted pa-data */ + add_padata(context, a->padata, creds->client, + key_proc, keyseed, a->req_body.etype.val, + a->req_body.etype.len, NULL); + + /* make a v4 salted pa-data */ + salt.salttype = KRB5_PW_SALT; + krb5_data_zero(&salt.saltvalue); + add_padata(context, a->padata, creds->client, + key_proc, keyseed, a->req_body.etype.val, + a->req_body.etype.len, &salt); + } else { + krb5_set_error_string (context, "pre-auth type %d not supported", + *ptypes); + ret = KRB5_PREAUTH_BAD_TYPE; + goto fail; + } + return 0; +fail: + free_AS_REQ(a); + return ret; +} + +static int +set_ptypes(krb5_context context, + KRB_ERROR *error, + const krb5_preauthtype **ptypes, + krb5_preauthdata **preauth) +{ + static krb5_preauthdata preauth2; + static krb5_preauthtype ptypes2[] = { KRB5_PADATA_ENC_TIMESTAMP, KRB5_PADATA_NONE }; + + if(error->e_data) { + METHOD_DATA md; + int i; + decode_METHOD_DATA(error->e_data->data, + error->e_data->length, + &md, + NULL); + for(i = 0; i < md.len; i++){ + switch(md.val[i].padata_type){ + case KRB5_PADATA_ENC_TIMESTAMP: + *ptypes = ptypes2; + break; + case KRB5_PADATA_ETYPE_INFO: + *preauth = &preauth2; + ALLOC_SEQ(*preauth, 1); + (*preauth)->val[0].type = KRB5_PADATA_ENC_TIMESTAMP; + krb5_decode_ETYPE_INFO(context, + md.val[i].padata_value.data, + md.val[i].padata_value.length, + &(*preauth)->val[0].info, + NULL); + break; + default: + break; + } + } + free_METHOD_DATA(&md); + } else { + *ptypes = ptypes2; + } + return(1); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_cred(krb5_context context, + krb5_flags options, + const krb5_addresses *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *ptypes, + const krb5_preauthdata *preauth, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + krb5_decrypt_proc decrypt_proc, + krb5_const_pointer decryptarg, + krb5_creds *creds, + krb5_kdc_rep *ret_as_reply) +{ + krb5_error_code ret; + AS_REQ a; + krb5_kdc_rep rep; + krb5_data req, resp; + size_t len; + krb5_salt salt; + krb5_keyblock *key; + size_t size; + krb5_kdc_flags opts; + PA_DATA *pa; + krb5_enctype etype; + krb5_preauthdata *my_preauth = NULL; + unsigned nonce; + int done; + + opts.i = options; + + krb5_generate_random_block (&nonce, sizeof(nonce)); + nonce &= 0xffffffff; + + do { + done = 1; + ret = init_as_req (context, + opts, + creds, + addrs, + etypes, + ptypes, + preauth, + key_proc, + keyseed, + nonce, + &a); + if (my_preauth) { + free_ETYPE_INFO(&my_preauth->val[0].info); + free (my_preauth->val); + my_preauth = NULL; + } + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(AS_REQ, req.data, req.length, &a, &len, ret); + free_AS_REQ(&a); + if (ret) + return ret; + if(len != req.length) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_sendto_kdc (context, &req, &creds->client->realm, &resp); + krb5_data_free(&req); + if (ret) + return ret; + + memset (&rep, 0, sizeof(rep)); + ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size); + if(ret) { + /* let's try to parse it as a KRB-ERROR */ + KRB_ERROR error; + int ret2; + + ret2 = krb5_rd_error(context, &resp, &error); + if(ret2 && resp.data && ((char*)resp.data)[0] == 4) + ret = KRB5KRB_AP_ERR_V4_REPLY; + krb5_data_free(&resp); + if (ret2 == 0) { + ret = krb5_error_from_rd_error(context, &error, creds); + /* if no preauth was set and KDC requires it, give it + one more try */ + if (!ptypes && !preauth + && ret == KRB5KDC_ERR_PREAUTH_REQUIRED +#if 0 + || ret == KRB5KDC_ERR_BADOPTION +#endif + && set_ptypes(context, &error, &ptypes, &my_preauth)) { + done = 0; + preauth = my_preauth; + krb5_free_error_contents(context, &error); + krb5_clear_error_string(context); + continue; + } + if(ret_as_reply) + ret_as_reply->error = error; + else + free_KRB_ERROR (&error); + return ret; + } + return ret; + } + krb5_data_free(&resp); + } while(!done); + + pa = NULL; + etype = rep.kdc_rep.enc_part.etype; + if(rep.kdc_rep.padata){ + int i = 0; + pa = krb5_find_padata(rep.kdc_rep.padata->val, rep.kdc_rep.padata->len, + KRB5_PADATA_PW_SALT, &i); + if(pa == NULL) { + i = 0; + pa = krb5_find_padata(rep.kdc_rep.padata->val, + rep.kdc_rep.padata->len, + KRB5_PADATA_AFS3_SALT, &i); + } + } + if(pa) { + salt.salttype = pa->padata_type; + salt.saltvalue = pa->padata_value; + + ret = (*key_proc)(context, etype, salt, keyseed, &key); + } else { + /* make a v5 salted pa-data */ + ret = krb5_get_pw_salt (context, creds->client, &salt); + + if (ret) + goto out; + ret = (*key_proc)(context, etype, salt, keyseed, &key); + krb5_free_salt(context, salt); + } + if (ret) + goto out; + + ret = _krb5_extract_ticket(context, + &rep, + creds, + key, + keyseed, + KRB5_KU_AS_REP_ENC_PART, + NULL, + nonce, + FALSE, + opts.b.request_anonymous, + decrypt_proc, + decryptarg); + memset (key->keyvalue.data, 0, key->keyvalue.length); + krb5_free_keyblock_contents (context, key); + free (key); + +out: + if (ret == 0 && ret_as_reply) + *ret_as_reply = rep; + else + krb5_free_kdc_rep (context, &rep); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt(krb5_context context, + krb5_flags options, + const krb5_addresses *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *ptypes, + krb5_key_proc key_proc, + krb5_const_pointer keyseed, + krb5_decrypt_proc decrypt_proc, + krb5_const_pointer decryptarg, + krb5_creds *creds, + krb5_ccache ccache, + krb5_kdc_rep *ret_as_reply) +{ + krb5_error_code ret; + krb5_kdc_flags opts; + opts.i = 0; + opts.b = int2KDCOptions(options); + + ret = krb5_get_in_cred (context, + opts.i, + addrs, + etypes, + ptypes, + NULL, + key_proc, + keyseed, + decrypt_proc, + decryptarg, + creds, + ret_as_reply); + if(ret) + return ret; + if (ccache) + ret = krb5_cc_store_cred (context, ccache, creds); + return ret; +} diff --git a/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c b/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c new file mode 100644 index 0000000000..69da6c5ea7 --- /dev/null +++ b/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: get_in_tkt_with_keytab.c,v 1.9 2005/06/17 04:56:44 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytab_key_proc (krb5_context context, + krb5_enctype enctype, + krb5_salt salt, + krb5_const_pointer keyseed, + krb5_keyblock **key) +{ + krb5_keytab_key_proc_args *args = rk_UNCONST(keyseed); + krb5_keytab keytab = args->keytab; + krb5_principal principal = args->principal; + krb5_error_code ret; + krb5_keytab real_keytab; + krb5_keytab_entry entry; + + if(keytab == NULL) + krb5_kt_default(context, &real_keytab); + else + real_keytab = keytab; + + ret = krb5_kt_get_entry (context, real_keytab, principal, + 0, enctype, &entry); + + if (keytab == NULL) + krb5_kt_close (context, real_keytab); + + if (ret) + return ret; + + ret = krb5_copy_keyblock (context, &entry.keyblock, key); + krb5_kt_free_entry(context, &entry); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt_with_keytab (krb5_context context, + krb5_flags options, + krb5_addresses *addrs, + const krb5_enctype *etypes, + const krb5_preauthtype *pre_auth_types, + krb5_keytab keytab, + krb5_ccache ccache, + krb5_creds *creds, + krb5_kdc_rep *ret_as_reply) +{ + krb5_keytab_key_proc_args a; + + a.principal = creds->client; + a.keytab = keytab; + + return krb5_get_in_tkt (context, + options, + addrs, + etypes, + pre_auth_types, + krb5_keytab_key_proc, + &a, + NULL, + NULL, + creds, + ccache, + ret_as_reply); +} diff --git a/source4/heimdal/lib/krb5/get_port.c b/source4/heimdal/lib/krb5/get_port.c new file mode 100644 index 0000000000..ba76466e06 --- /dev/null +++ b/source4/heimdal/lib/krb5/get_port.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997-2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: get_port.c,v 1.9 2004/05/25 21:29:59 lha Exp $"); + +int KRB5_LIB_FUNCTION +krb5_getportbyname (krb5_context context, + const char *service, + const char *proto, + int default_port) +{ + struct servent *sp; + + if ((sp = roken_getservbyname (service, proto)) == NULL) { +#if 0 + krb5_warnx(context, "%s/%s unknown service, using default port %d", + service, proto, default_port); +#endif + return htons(default_port); + } else + return sp->s_port; +} diff --git a/source4/heimdal/lib/krb5/heim_err.et b/source4/heimdal/lib/krb5/heim_err.et new file mode 100644 index 0000000000..3c4f06edb1 --- /dev/null +++ b/source4/heimdal/lib/krb5/heim_err.et @@ -0,0 +1,44 @@ +# +# Error messages for the krb5 library +# +# This might look like a com_err file, but is not +# +id "$Id: heim_err.et,v 1.13 2004/02/13 16:23:40 lha Exp $" + +error_table heim + +prefix HEIM_ERR + +error_code LOG_PARSE, "Error parsing log destination" +error_code V4_PRINC_NO_CONV, "Failed to convert v4 principal" +error_code SALTTYPE_NOSUPP, "Salt type is not supported by enctype" +error_code NOHOST, "Host not found" +error_code OPNOTSUPP, "Operation not supported" +error_code EOF, "End of file" +error_code BAD_MKEY, "Failed to get the master key" +error_code SERVICE_NOMATCH, "Unacceptable service used" + +index 64 +prefix HEIM_PKINIT +error_code NO_CERTIFICATE, "Certificate missing" +error_code NO_PRIVATE_KEY, "Private key missing" +error_code NO_VALID_CA, "No valid certificate authority" +error_code CERTIFICATE_INVALID, "Certificate invalid" +error_code PRIVATE_KEY_INVALID, "Private key invalid" + +index 128 +prefix HEIM_EAI +#error_code NOERROR, "no error" +error_code UNKNOWN, "unknown error from getaddrinfo" +error_code ADDRFAMILY, "address family for nodename not supported" +error_code AGAIN, "temporary failure in name resolution" +error_code BADFLAGS, "invalid value for ai_flags" +error_code FAIL, "non-recoverable failure in name resolution" +error_code FAMILY, "ai_family not supported" +error_code MEMORY, "memory allocation failure" +error_code NODATA, "no address associated with nodename" +error_code NONAME, "nodename nor servname provided, or not known" +error_code SERVICE, "servname not supported for ai_socktype" +error_code SOCKTYPE, "ai_socktype not supported" +error_code SYSTEM, "system error returned in errno" +end diff --git a/source4/heimdal/lib/krb5/heim_threads.h b/source4/heimdal/lib/krb5/heim_threads.h new file mode 100755 index 0000000000..3ebe66beee --- /dev/null +++ b/source4/heimdal/lib/krb5/heim_threads.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +/* $Id: heim_threads.h,v 1.11 2004/12/18 16:03:38 lha Exp $ */ + +/* + * Provide wrapper macros for thread synchronization primitives so we + * can use native thread functions for those operating system that + * supports it. + * + * This is so libkrb5.so (or more importantly, libgssapi.so) can have + * thread support while the program that that dlopen(3)s the library + * don't need to be linked to libpthread. + */ + +#ifndef HEIM_THREADS_H +#define HEIM_THREADS_H 1 + +/* assume headers already included */ + +#if defined(__NetBSD__) && __NetBSD_Version__ >= 106120000 && __NetBSD_Version__< 299001200 && defined(ENABLE_PTHREAD_SUPPORT) + +/* + * NetBSD have a thread lib that we can use that part of libc that + * works regardless if application are linked to pthreads or not. + * NetBSD newer then 2.99.11 just use pthread.h, and the same thing + * will happen. + */ +#include + +#define HEIMDAL_MUTEX mutex_t +#define HEIMDAL_MUTEX_INITIALIZER MUTEX_INITIALIZER +#define HEIMDAL_MUTEX_init(m) mutex_init(m, NULL) +#define HEIMDAL_MUTEX_lock(m) mutex_lock(m) +#define HEIMDAL_MUTEX_unlock(m) mutex_unlock(m) +#define HEIMDAL_MUTEX_destroy(m) mutex_destroy(m) + +#define HEIMDAL_RWLOCK rwlock_t +#define HEIMDAL_RWLOCK_INITIALIZER RWLOCK_INITIALIZER +#define HEIMDAL_RWLOCK_init(l) rwlock_init(l, NULL) +#define HEIMDAL_RWLOCK_rdlock(l) rwlock_rdlock(l) +#define HEIMDAL_RWLOCK_wrlock(l) rwlock_wrlock(l) +#define HEIMDAL_RWLOCK_tryrdlock(l) rwlock_tryrdlock(l) +#define HEIMDAL_RWLOCK_trywrlock(l) rwlock_trywrlock(l) +#define HEIMDAL_RWLOCK_unlock(l) rwlock_unlock(l) +#define HEIMDAL_RWLOCK_destroy(l) rwlock_destroy(l) + +#define HEIMDAL_thread_key thread_key_t +#define HEIMDAL_key_create(k,d,r) do { r = thr_keycreate(k,d); } while(0) +#define HEIMDAL_setspecific(k,s,r) do { r = thr_setspecific(k,s); } while(0) +#define HEIMDAL_getspecific(k) thr_getspecific(k) +#define HEIMDAL_key_delete(k) thr_keydelete(k) + +#elif defined(ENABLE_PTHREAD_SUPPORT) && (!defined(__NetBSD__) || __NetBSD_Version__ >= 299001200) + +#include + +#define HEIMDAL_MUTEX pthread_mutex_t +#define HEIMDAL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +#define HEIMDAL_MUTEX_init(m) pthread_mutex_init(m, NULL) +#define HEIMDAL_MUTEX_lock(m) pthread_mutex_lock(m) +#define HEIMDAL_MUTEX_unlock(m) pthread_mutex_unlock(m) +#define HEIMDAL_MUTEX_destroy(m) pthread_mutex_destroy(m) + +#define HEIMDAL_RWLOCK rwlock_t +#define HEIMDAL_RWLOCK_INITIALIZER RWLOCK_INITIALIZER +#define HEIMDAL_RWLOCK_init(l) pthread_rwlock_init(l, NULL) +#define HEIMDAL_RWLOCK_rdlock(l) pthread_rwlock_rdlock(l) +#define HEIMDAL_RWLOCK_wrlock(l) pthread_rwlock_wrlock(l) +#define HEIMDAL_RWLOCK_tryrdlock(l) pthread_rwlock_tryrdlock(l) +#define HEIMDAL_RWLOCK_trywrlock(l) pthread_rwlock_trywrlock(l) +#define HEIMDAL_RWLOCK_unlock(l) pthread_rwlock_unlock(l) +#define HEIMDAL_RWLOCK_destroy(l) pthread_rwlock_destroy(l) + +#define HEIMDAL_thread_key pthread_key_t +#define HEIMDAL_key_create(k,d,r) do { r = pthread_key_create(k,d); } while(0) +#define HEIMDAL_setspecific(k,s,r) do { r = pthread_setspecific(k,s); } while(0) +#define HEIMDAL_getspecific(k) pthread_getspecific(k) +#define HEIMDAL_key_delete(k) pthread_key_delete(k) + +#elif defined(HEIMDAL_DEBUG_THREADS) + +/* no threads support, just do consistency checks */ +#include + +#define HEIMDAL_MUTEX int +#define HEIMDAL_MUTEX_INITIALIZER 0 +#define HEIMDAL_MUTEX_init(m) do { (*(m)) = 0; } while(0) +#define HEIMDAL_MUTEX_lock(m) do { if ((*(m))++ != 0) abort(); } while(0) +#define HEIMDAL_MUTEX_unlock(m) do { if ((*(m))-- != 1) abort(); } while(0) +#define HEIMDAL_MUTEX_destroy(m) do {if ((*(m)) != 0) abort(); } while(0) + +#define HEIMDAL_RWLOCK rwlock_t int +#define HEIMDAL_RWLOCK_INITIALIZER 0 +#define HEIMDAL_RWLOCK_init(l) do { } while(0) +#define HEIMDAL_RWLOCK_rdlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_wrlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_tryrdlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_trywrlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_unlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_destroy(l) do { } while(0) + +#define HEIMDAL_internal_thread_key 1 + +#else /* no thread support, no debug case */ + +#define HEIMDAL_MUTEX int +#define HEIMDAL_MUTEX_INITIALIZER 0 +#define HEIMDAL_MUTEX_init(m) do { (void)(m); } while(0) +#define HEIMDAL_MUTEX_lock(m) do { (void)(m); } while(0) +#define HEIMDAL_MUTEX_unlock(m) do { (void)(m); } while(0) +#define HEIMDAL_MUTEX_destroy(m) do { (void)(m); } while(0) + +#define HEIMDAL_RWLOCK rwlock_t int +#define HEIMDAL_RWLOCK_INITIALIZER 0 +#define HEIMDAL_RWLOCK_init(l) do { } while(0) +#define HEIMDAL_RWLOCK_rdlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_wrlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_tryrdlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_trywrlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_unlock(l) do { } while(0) +#define HEIMDAL_RWLOCK_destroy(l) do { } while(0) + +#define HEIMDAL_internal_thread_key 1 + +#endif /* no thread support */ + +#ifdef HEIMDAL_internal_thread_key + +typedef struct heim_thread_key { + void *value; + void (*destructor)(void *); +} heim_thread_key; + +#define HEIMDAL_thread_key heim_thread_key +#define HEIMDAL_key_create(k,d,r) \ + do { (k)->value = NULL; (k)->destructor = (d); r = 0; } while(0) +#define HEIMDAL_setspecific(k,s,r) do { (k).value = s ; r = 0; } while(0) +#define HEIMDAL_getspecific(k) ((k).value) +#define HEIMDAL_key_delete(k) do { (*(k).destructor)((k).value); } while(0) + +#undef HEIMDAL_internal_thread_key +#endif /* HEIMDAL_internal_thread_key */ + +#endif /* HEIM_THREADS_H */ diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c new file mode 100644 index 0000000000..95c980d92c --- /dev/null +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -0,0 +1,331 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: init_creds.c,v 1.20 2004/11/09 18:50:43 lha Exp $"); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) +{ + memset (opt, 0, sizeof(*opt)); + opt->flags = 0; + opt->private = NULL; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_alloc(krb5_context context, + krb5_get_init_creds_opt **opt) +{ + krb5_get_init_creds_opt *o; + + *opt = NULL; + o = calloc(1, sizeof(*o)); + if (o == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + krb5_get_init_creds_opt_init(o); + o->private = calloc(1, sizeof(*o->private)); + if (o->private == NULL) { + krb5_set_error_string(context, "out of memory"); + free(o); + return ENOMEM; + } + o->private->refcount = 1; + *opt = o; + return 0; +} + +krb5_error_code +_krb5_get_init_creds_opt_copy(krb5_context context, + const krb5_get_init_creds_opt *in, + krb5_get_init_creds_opt **out) +{ + krb5_get_init_creds_opt *opt; + + *out = NULL; + opt = malloc(sizeof(*opt)); + if (opt == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + if (in) + *opt = *in; + if(opt->private == NULL) { + opt->private = calloc(1, sizeof(*opt->private)); + if (opt->private == NULL) { + krb5_set_error_string(context, "out of memory"); + free(opt); + return ENOMEM; + } + opt->private->refcount = 1; + } else + opt->private->refcount++; + *out = opt; + return 0; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt) +{ + if (opt->private == NULL) + return; + if (opt->private->refcount < 1) /* abort ? */ + return; + if (--opt->private->refcount == 0) { + _krb5_get_init_creds_opt_free_pkinit(opt); + free(opt->private); + } + memset(opt, 0, sizeof(*opt)); + free(opt); +} + +static int +get_config_time (krb5_context context, + const char *realm, + const char *name, + int def) +{ + int ret; + + ret = krb5_config_get_time (context, NULL, + "realms", + realm, + name, + NULL); + if (ret >= 0) + return ret; + ret = krb5_config_get_time (context, NULL, + "libdefaults", + name, + NULL); + if (ret >= 0) + return ret; + return def; +} + +static krb5_boolean +get_config_bool (krb5_context context, + const char *realm, + const char *name) +{ + return krb5_config_get_bool (context, + NULL, + "realms", + realm, + name, + NULL) + || krb5_config_get_bool (context, + NULL, + "libdefaults", + name, + NULL); +} + +/* + * set all the values in `opt' to the appropriate values for + * application `appname' (default to getprogname() if NULL), and realm + * `realm'. First looks in [appdefaults] but falls back to + * [realms] or [libdefaults] for some of the values. + */ + +static krb5_addresses no_addrs = {0, NULL}; + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_default_flags(krb5_context context, + const char *appname, + krb5_const_realm realm, + krb5_get_init_creds_opt *opt) +{ + krb5_boolean b; + time_t t; + + b = get_config_bool (context, realm, "forwardable"); + krb5_appdefault_boolean(context, appname, realm, "forwardable", b, &b); + krb5_get_init_creds_opt_set_forwardable(opt, b); + + b = get_config_bool (context, realm, "proxiable"); + krb5_appdefault_boolean(context, appname, realm, "proxiable", b, &b); + krb5_get_init_creds_opt_set_proxiable (opt, b); + + krb5_appdefault_time(context, appname, realm, "ticket_lifetime", 0, &t); + if (t == 0) + t = get_config_time (context, realm, "ticket_lifetime", 0); + if(t != 0) + krb5_get_init_creds_opt_set_tkt_life(opt, t); + + krb5_appdefault_time(context, appname, realm, "renew_lifetime", 0, &t); + if (t == 0) + t = get_config_time (context, realm, "renew_lifetime", 0); + if(t != 0) + krb5_get_init_creds_opt_set_renew_life(opt, t); + + krb5_appdefault_boolean(context, appname, realm, "no-addresses", FALSE, &b); + if (b) + krb5_get_init_creds_opt_set_address_list (opt, &no_addrs); + +#if 0 + krb5_appdefault_boolean(context, appname, realm, "anonymous", FALSE, &b); + krb5_get_init_creds_opt_set_anonymous (opt, b); + + krb5_get_init_creds_opt_set_etype_list(opt, enctype, + etype_str.num_strings); + + krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, + krb5_data *salt); + + krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, + krb5_preauthtype *preauth_list, + int preauth_list_length); +#endif +} + + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt, + krb5_deltat tkt_life) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_TKT_LIFE; + opt->tkt_life = tkt_life; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt, + krb5_deltat renew_life) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE; + opt->renew_life = renew_life; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt, + int forwardable) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_FORWARDABLE; + opt->forwardable = forwardable; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt, + int proxiable) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_PROXIABLE; + opt->proxiable = proxiable; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt, + krb5_enctype *etype_list, + int etype_list_length) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST; + opt->etype_list = etype_list; + opt->etype_list_length = etype_list_length; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt, + krb5_addresses *addresses) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST; + opt->address_list = addresses; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt, + krb5_preauthtype *preauth_list, + int preauth_list_length) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST; + opt->preauth_list_length = preauth_list_length; + opt->preauth_list = preauth_list; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, + krb5_data *salt) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT; + opt->salt = salt; +} + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_anonymous(krb5_get_init_creds_opt *opt, + int anonymous) +{ + opt->flags |= KRB5_GET_INIT_CREDS_OPT_ANONYMOUS; + opt->anonymous = anonymous; +} + +static krb5_error_code +require_ext_opt(krb5_context context, + krb5_get_init_creds_opt *opt, + const char *type) +{ + if (opt->private == NULL) { + krb5_set_error_string(context, "%s on non extendable opt", type); + return EINVAL; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_pa_password(krb5_context context, + krb5_get_init_creds_opt *opt, + const char *password, + krb5_s2k_proc key_proc) +{ + krb5_error_code ret; + ret = require_ext_opt(context, opt, "init_creds_opt_set_pa_password"); + if (ret) + return ret; + opt->private->password = password; + opt->private->key_proc = key_proc; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_pac_request(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_boolean req_pac) +{ + krb5_error_code ret; + ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req"); + if (ret) + return ret; + opt->private->req_pac = req_pac ? + KRB5_PA_PAC_REQ_TRUE : + KRB5_PA_PAC_REQ_FALSE; + return 0; +} diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c new file mode 100644 index 0000000000..8b3975f418 --- /dev/null +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -0,0 +1,1554 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: init_creds_pw.c,v 1.87 2005/06/17 04:15:20 lha Exp $"); + +typedef struct krb5_get_init_creds_ctx { + krb5_kdc_flags flags; + krb5_creds cred; + krb5_addresses *addrs; + krb5_enctype *etypes; + krb5_preauthtype *pre_auth_types; + const char *in_tkt_service; + unsigned nonce; + unsigned pk_nonce; + + AS_REQ as_req; + int pa_counter; + + const char *password; + krb5_s2k_proc key_proc; + + krb5_get_init_creds_req_pac req_pac; + + krb5_pk_init_ctx pk_init_ctx; +} krb5_get_init_creds_ctx; + +static krb5_error_code +default_s2k_func(krb5_context context, krb5_enctype type, + krb5_const_pointer keyseed, + krb5_salt salt, krb5_data *s2kparms, + krb5_keyblock **key) +{ + krb5_error_code ret; + krb5_data password; + krb5_data opaque; + + password.data = rk_UNCONST(keyseed); + password.length = strlen(keyseed); + if (s2kparms) + opaque = *s2kparms; + else + krb5_data_zero(&opaque); + + *key = malloc(sizeof(**key)); + if (*key == NULL) + return ENOMEM; + ret = krb5_string_to_key_data_salt_opaque(context, type, password, + salt, opaque, *key); + if (ret) + free(*key); + return ret; +} + +static void +free_init_creds_ctx(krb5_context context, krb5_get_init_creds_ctx *ctx) +{ + if (ctx->etypes) + free(ctx->etypes); + if (ctx->pre_auth_types) + free (ctx->pre_auth_types); + free_AS_REQ(&ctx->as_req); + memset(&ctx->as_req, 0, sizeof(ctx->as_req)); +} + +static int +get_config_time (krb5_context context, + const char *realm, + const char *name, + int def) +{ + int ret; + + ret = krb5_config_get_time (context, NULL, + "realms", + realm, + name, + NULL); + if (ret >= 0) + return ret; + ret = krb5_config_get_time (context, NULL, + "libdefaults", + name, + NULL); + if (ret >= 0) + return ret; + return def; +} + +static krb5_error_code +init_cred (krb5_context context, + krb5_creds *cred, + krb5_principal client, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *options) +{ + krb5_error_code ret; + krb5_const_realm client_realm; + int tmp; + krb5_timestamp now; + + krb5_timeofday (context, &now); + + memset (cred, 0, sizeof(*cred)); + + if (client) + krb5_copy_principal(context, client, &cred->client); + else { + ret = krb5_get_default_principal (context, + &cred->client); + if (ret) + goto out; + } + + client_realm = krb5_principal_get_realm (context, cred->client); + + if (start_time) + cred->times.starttime = now + start_time; + + if (options->flags & KRB5_GET_INIT_CREDS_OPT_TKT_LIFE) + tmp = options->tkt_life; + else + tmp = 10 * 60 * 60; + cred->times.endtime = now + tmp; + + if ((options->flags & KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE) && + options->renew_life > 0) { + cred->times.renew_till = now + options->renew_life; + } + + if (in_tkt_service) { + krb5_realm server_realm; + + ret = krb5_parse_name (context, in_tkt_service, &cred->server); + if (ret) + goto out; + server_realm = strdup (client_realm); + free (*krb5_princ_realm(context, cred->server)); + krb5_princ_set_realm (context, cred->server, &server_realm); + } else { + ret = krb5_make_principal(context, &cred->server, + client_realm, KRB5_TGS_NAME, client_realm, + NULL); + if (ret) + goto out; + } + return 0; + +out: + krb5_free_cred_contents (context, cred); + return ret; +} + +/* + * Print a message (str) to the user about the expiration in `lr' + */ + +static void +report_expiration (krb5_context context, + krb5_prompter_fct prompter, + krb5_data *data, + const char *str, + time_t now) +{ + char *p; + + asprintf (&p, "%s%s", str, ctime(&now)); + (*prompter) (context, data, NULL, p, 0, NULL); + free (p); +} + +/* + * Parse the last_req data and show it to the user if it's interesting + */ + +static void +print_expire (krb5_context context, + krb5_const_realm realm, + krb5_kdc_rep *rep, + krb5_prompter_fct prompter, + krb5_data *data) +{ + int i; + LastReq *lr = &rep->enc_part.last_req; + krb5_timestamp sec; + time_t t; + krb5_boolean reported = FALSE; + + krb5_timeofday (context, &sec); + + t = sec + get_config_time (context, + realm, + "warn_pwexpire", + 7 * 24 * 60 * 60); + + for (i = 0; i < lr->len; ++i) { + if (lr->val[i].lr_value <= t) { + switch (abs(lr->val[i].lr_type)) { + case LR_PW_EXPTIME : + report_expiration(context, prompter, data, + "Your password will expire at ", + lr->val[i].lr_value); + reported = TRUE; + break; + case LR_ACCT_EXPTIME : + report_expiration(context, prompter, data, + "Your account will expire at ", + lr->val[i].lr_value); + reported = TRUE; + break; + } + } + } + + if (!reported + && rep->enc_part.key_expiration + && *rep->enc_part.key_expiration <= t) { + report_expiration(context, prompter, data, + "Your password/account will expire at ", + *rep->enc_part.key_expiration); + } +} + +static krb5_error_code +get_init_creds_common(krb5_context context, + krb5_creds *creds, + krb5_principal client, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *options, + krb5_get_init_creds_ctx *ctx) +{ + krb5_get_init_creds_opt default_opt; + krb5_error_code ret; + krb5_enctype *etypes; + krb5_preauthtype *pre_auth_types; + + memset(ctx, 0, sizeof(*ctx)); + + if (options == NULL) { + krb5_get_init_creds_opt_init (&default_opt); + options = &default_opt; + } + + if (options->private) { + ctx->password = options->private->password; + ctx->key_proc = options->private->key_proc; + ctx->req_pac = options->private->req_pac; + ctx->pk_init_ctx = options->private->pk_init_ctx; + } else + ctx->req_pac = KRB5_PA_PAC_DONT_CARE; + + if (ctx->key_proc == NULL) + ctx->key_proc = default_s2k_func; + + ctx->pre_auth_types = NULL; + ctx->flags.i = 0; + ctx->addrs = NULL; + ctx->etypes = NULL; + ctx->pre_auth_types = NULL; + ctx->in_tkt_service = in_tkt_service; + + ret = init_cred (context, &ctx->cred, client, start_time, + in_tkt_service, options); + if (ret) + return ret; + + ctx->flags.i = 0; + + if (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE) + ctx->flags.b.forwardable = options->forwardable; + + if (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE) + ctx->flags.b.proxiable = options->proxiable; + + if (start_time) + ctx->flags.b.postdated = 1; + if (ctx->cred.times.renew_till) + ctx->flags.b.renewable = 1; + if (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST) + ctx->addrs = options->address_list; + if (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST) { + etypes = malloc((options->etype_list_length + 1) + * sizeof(krb5_enctype)); + if (etypes == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy (etypes, options->etype_list, + options->etype_list_length * sizeof(krb5_enctype)); + etypes[options->etype_list_length] = ETYPE_NULL; + ctx->etypes = etypes; + } + if (options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) { + pre_auth_types = malloc((options->preauth_list_length + 1) + * sizeof(krb5_preauthtype)); + if (pre_auth_types == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy (pre_auth_types, options->preauth_list, + options->preauth_list_length * sizeof(krb5_preauthtype)); + pre_auth_types[options->preauth_list_length] = KRB5_PADATA_NONE; + ctx->pre_auth_types = pre_auth_types; + } + if (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT) + ; /* XXX */ + if (options->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS) + ctx->flags.b.request_anonymous = options->anonymous; + return 0; +} + +static krb5_error_code +change_password (krb5_context context, + krb5_principal client, + const char *password, + char *newpw, + size_t newpw_sz, + krb5_prompter_fct prompter, + void *data, + krb5_get_init_creds_opt *old_options) +{ + krb5_prompt prompts[2]; + krb5_error_code ret; + krb5_creds cpw_cred; + char buf1[BUFSIZ], buf2[BUFSIZ]; + krb5_data password_data[2]; + int result_code; + krb5_data result_code_string; + krb5_data result_string; + char *p; + krb5_get_init_creds_opt options; + + memset (&cpw_cred, 0, sizeof(cpw_cred)); + + krb5_get_init_creds_opt_init (&options); + krb5_get_init_creds_opt_set_tkt_life (&options, 60); + krb5_get_init_creds_opt_set_forwardable (&options, FALSE); + krb5_get_init_creds_opt_set_proxiable (&options, FALSE); + if (old_options && old_options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST) + krb5_get_init_creds_opt_set_preauth_list (&options, + old_options->preauth_list, + old_options->preauth_list_length); + + krb5_data_zero (&result_code_string); + krb5_data_zero (&result_string); + + ret = krb5_get_init_creds_password (context, + &cpw_cred, + client, + password, + prompter, + data, + 0, + "kadmin/changepw", + &options); + if (ret) + goto out; + + for(;;) { + password_data[0].data = buf1; + password_data[0].length = sizeof(buf1); + + prompts[0].hidden = 1; + prompts[0].prompt = "New password: "; + prompts[0].reply = &password_data[0]; + prompts[0].type = KRB5_PROMPT_TYPE_NEW_PASSWORD; + + password_data[1].data = buf2; + password_data[1].length = sizeof(buf2); + + prompts[1].hidden = 1; + prompts[1].prompt = "Repeat new password: "; + prompts[1].reply = &password_data[1]; + prompts[1].type = KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN; + + ret = (*prompter) (context, data, NULL, "Changing password", + 2, prompts); + if (ret) { + memset (buf1, 0, sizeof(buf1)); + memset (buf2, 0, sizeof(buf2)); + goto out; + } + + if (strcmp (buf1, buf2) == 0) + break; + memset (buf1, 0, sizeof(buf1)); + memset (buf2, 0, sizeof(buf2)); + } + + ret = krb5_change_password (context, + &cpw_cred, + buf1, + &result_code, + &result_code_string, + &result_string); + if (ret) + goto out; + asprintf (&p, "%s: %.*s\n", + result_code ? "Error" : "Success", + (int)result_string.length, + result_string.length > 0 ? (char*)result_string.data : ""); + + ret = (*prompter) (context, data, NULL, p, 0, NULL); + free (p); + if (result_code == 0) { + strlcpy (newpw, buf1, newpw_sz); + ret = 0; + } else { + krb5_set_error_string (context, "failed changing password"); + ret = ENOTTY; + } + +out: + memset (buf1, 0, sizeof(buf1)); + memset (buf2, 0, sizeof(buf2)); + krb5_data_free (&result_string); + krb5_data_free (&result_code_string); + krb5_free_cred_contents (context, &cpw_cred); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keyblock_key_proc (krb5_context context, + krb5_keytype type, + krb5_data *salt, + krb5_const_pointer keyseed, + krb5_keyblock **key) +{ + return krb5_copy_keyblock (context, keyseed, key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_keytab(krb5_context context, + krb5_creds *creds, + krb5_principal client, + krb5_keytab keytab, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *options) +{ + krb5_get_init_creds_ctx ctx; + krb5_error_code ret; + krb5_keytab_key_proc_args *a; + + ret = get_init_creds_common(context, creds, client, start_time, + in_tkt_service, options, &ctx); + if (ret) + goto out; + + a = malloc (sizeof(*a)); + if (a == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + a->principal = ctx.cred.client; + a->keytab = keytab; + + ret = krb5_get_in_cred (context, + ctx.flags.i, + ctx.addrs, + ctx.etypes, + ctx.pre_auth_types, + NULL, + krb5_keytab_key_proc, + a, + NULL, + NULL, + &ctx.cred, + NULL); + free (a); + + if (ret == 0 && creds) + *creds = ctx.cred; + else + krb5_free_cred_contents (context, &ctx.cred); + + out: + free_init_creds_ctx(context, &ctx); + return ret; +} + +/* + * + */ + +static krb5_error_code +init_creds_init_as_req (krb5_context context, + krb5_kdc_flags opts, + const krb5_creds *creds, + const krb5_addresses *addrs, + const krb5_enctype *etypes, + AS_REQ *a) +{ + krb5_error_code ret; + + memset(a, 0, sizeof(*a)); + + a->pvno = 5; + a->msg_type = krb_as_req; + a->req_body.kdc_options = opts.b; + a->req_body.cname = malloc(sizeof(*a->req_body.cname)); + if (a->req_body.cname == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + a->req_body.sname = malloc(sizeof(*a->req_body.sname)); + if (a->req_body.sname == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + if (creds->client) { + ret = _krb5_principal2principalname (a->req_body.cname, creds->client); + if (ret) + goto fail; + ret = copy_Realm(&creds->client->realm, &a->req_body.realm); + if (ret) + goto fail; + } else { + krb5_realm realm; + + a->req_body.cname = NULL; + ret = krb5_get_default_realm(context, &realm); + if (ret) + goto fail; + ret = copy_Realm(&realm, &a->req_body.realm); + free(realm); + } + ret = _krb5_principal2principalname (a->req_body.sname, creds->server); + if (ret) + goto fail; + + if(creds->times.starttime) { + a->req_body.from = malloc(sizeof(*a->req_body.from)); + if (a->req_body.from == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + *a->req_body.from = creds->times.starttime; + } + if(creds->times.endtime){ + ALLOC(a->req_body.till, 1); + *a->req_body.till = creds->times.endtime; + } + if(creds->times.renew_till){ + a->req_body.rtime = malloc(sizeof(*a->req_body.rtime)); + if (a->req_body.rtime == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + *a->req_body.rtime = creds->times.renew_till; + } + a->req_body.nonce = 0; + ret = krb5_init_etype (context, + &a->req_body.etype.len, + &a->req_body.etype.val, + etypes); + if (ret) + goto fail; + + /* + * This means no addresses + */ + + if (addrs && addrs->len == 0) { + a->req_body.addresses = NULL; + } else { + a->req_body.addresses = malloc(sizeof(*a->req_body.addresses)); + if (a->req_body.addresses == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + + if (addrs) + ret = krb5_copy_addresses(context, addrs, a->req_body.addresses); + else { + ret = krb5_get_all_client_addrs (context, a->req_body.addresses); + if(ret == 0 && a->req_body.addresses->len == 0) { + free(a->req_body.addresses); + a->req_body.addresses = NULL; + } + } + if (ret) + goto fail; + } + + a->req_body.enc_authorization_data = NULL; + a->req_body.additional_tickets = NULL; + + a->padata = NULL; + + return 0; + fail: + free_AS_REQ(a); + memset(a, 0, sizeof(*a)); + return ret; +} + +struct pa_info_data { + krb5_enctype etype; + krb5_salt salt; + krb5_data *s2kparams; +}; + +static void +free_paid(krb5_context context, struct pa_info_data *ppaid) +{ + krb5_free_salt(context, ppaid->salt); + if (ppaid->s2kparams) + krb5_data_free(ppaid->s2kparams); +} + + +static krb5_error_code +set_paid(struct pa_info_data *paid, krb5_context context, + krb5_enctype etype, + krb5_salttype salttype, void *salt_string, size_t salt_len, + krb5_data *s2kparams) +{ + paid->etype = etype; + paid->salt.salttype = salttype; + paid->salt.saltvalue.data = malloc(salt_len + 1); + if (paid->salt.saltvalue.data == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + memcpy(paid->salt.saltvalue.data, salt_string, salt_len); + ((char *)paid->salt.saltvalue.data)[salt_len] = '\0'; + paid->salt.saltvalue.length = salt_len; + if (s2kparams) { + krb5_error_code ret; + + ret = krb5_copy_data(context, s2kparams, &paid->s2kparams); + if (ret) { + krb5_clear_error_string(context); + krb5_free_salt(context, paid->salt); + return ret; + } + } else + paid->s2kparams = NULL; + + return 0; +} + +static struct pa_info_data * +pa_etype_info2(krb5_context context, + const krb5_principal client, + const AS_REQ *asreq, + struct pa_info_data *paid, + heim_octet_string *data) +{ + krb5_error_code ret; + ETYPE_INFO2 e; + size_t sz; + int i, j; + + memset(&e, 0, sizeof(e)); + ret = decode_ETYPE_INFO2(data->data, data->length, &e, &sz); + if (ret) + goto out; + if (e.len == 0) + goto out; + for (j = 0; j < asreq->req_body.etype.len; j++) { + for (i = 0; i < e.len; i++) { + if (asreq->req_body.etype.val[j] == e.val[i].etype) { + krb5_salt salt; + if (e.val[i].salt == NULL) + ret = krb5_get_pw_salt(context, client, &salt); + else { + salt.saltvalue.data = *e.val[i].salt; + salt.saltvalue.length = strlen(*e.val[i].salt); + ret = 0; + } + if (ret == 0) + ret = set_paid(paid, context, e.val[i].etype, + KRB5_PW_SALT, + salt.saltvalue.data, + salt.saltvalue.length, + e.val[i].s2kparams); + if (e.val[i].salt == NULL) + krb5_free_salt(context, salt); + if (ret == 0) { + free_ETYPE_INFO2(&e); + return paid; + } + } + } + } + out: + free_ETYPE_INFO2(&e); + return NULL; +} + +static struct pa_info_data * +pa_etype_info(krb5_context context, + const krb5_principal client, + const AS_REQ *asreq, + struct pa_info_data *paid, + heim_octet_string *data) +{ + krb5_error_code ret; + ETYPE_INFO e; + size_t sz; + int i, j; + + memset(&e, 0, sizeof(e)); + ret = decode_ETYPE_INFO(data->data, data->length, &e, &sz); + if (ret) + goto out; + if (e.len == 0) + goto out; + for (j = 0; j < asreq->req_body.etype.len; j++) { + for (i = 0; i < e.len; i++) { + if (asreq->req_body.etype.val[j] == e.val[i].etype) { + krb5_salt salt; + salt.salttype = KRB5_PW_SALT; + if (e.val[i].salt == NULL) + ret = krb5_get_pw_salt(context, client, &salt); + else { + salt.saltvalue = *e.val[i].salt; + ret = 0; + } + if (e.val[i].salttype) + salt.salttype = *e.val[i].salttype; + if (ret == 0) { + ret = set_paid(paid, context, e.val[i].etype, + salt.salttype, + salt.saltvalue.data, + salt.saltvalue.length, + NULL); + if (e.val[i].salt == NULL) + krb5_free_salt(context, salt); + } + if (ret == 0) { + free_ETYPE_INFO(&e); + return paid; + } + } + } + } + out: + free_ETYPE_INFO(&e); + return NULL; +} + +static struct pa_info_data * +pa_pw_or_afs3_salt(krb5_context context, + const krb5_principal client, + const AS_REQ *asreq, + struct pa_info_data *paid, + heim_octet_string *data) +{ + krb5_error_code ret; + if (paid->etype == ENCTYPE_NULL) + return NULL; + ret = set_paid(paid, context, + paid->etype, + paid->salt.salttype, + data->data, + data->length, + NULL); + if (ret) + return NULL; + return paid; +} + + +struct pa_info { + krb5_preauthtype type; + struct pa_info_data *(*salt_info)(krb5_context, + const krb5_principal, + const AS_REQ *, + struct pa_info_data *, + heim_octet_string *); +}; + +static struct pa_info pa_prefs[] = { + { KRB5_PADATA_ETYPE_INFO2, pa_etype_info2 }, + { KRB5_PADATA_ETYPE_INFO, pa_etype_info }, + { KRB5_PADATA_PW_SALT, pa_pw_or_afs3_salt }, + { KRB5_PADATA_AFS3_SALT, pa_pw_or_afs3_salt } +}; + +static PA_DATA * +find_pa_data(const METHOD_DATA *md, int type) +{ + int i; + for (i = 0; i < md->len; i++) + if (md->val[i].padata_type == type) + return &md->val[i]; + return NULL; +} + +static struct pa_info_data * +process_pa_info(krb5_context context, + const krb5_principal client, + const AS_REQ *asreq, + struct pa_info_data *paid, + METHOD_DATA *md) +{ + struct pa_info_data *p = NULL; + int i; + + for (i = 0; p == NULL && i < sizeof(pa_prefs)/sizeof(pa_prefs[0]); i++) { + PA_DATA *pa = find_pa_data(md, pa_prefs[i].type); + if (pa == NULL) + continue; + paid->salt.salttype = pa_prefs[i].type; + p = (*pa_prefs[i].salt_info)(context, client, asreq, + paid, &pa->padata_value); + } + return p; +} + +static krb5_error_code +make_pa_enc_timestamp(krb5_context context, METHOD_DATA *md, + krb5_enctype etype, krb5_keyblock *key) +{ + PA_ENC_TS_ENC p; + unsigned char *buf; + size_t buf_size; + size_t len; + EncryptedData encdata; + krb5_error_code ret; + int32_t usec; + int usec2; + krb5_crypto crypto; + + krb5_us_timeofday (context, &p.patimestamp, &usec); + usec2 = usec; + p.pausec = &usec2; + + ASN1_MALLOC_ENCODE(PA_ENC_TS_ENC, buf, buf_size, &p, &len, ret); + if (ret) + return ret; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + free(buf); + return ret; + } + ret = krb5_encrypt_EncryptedData(context, + crypto, + KRB5_KU_PA_ENC_TIMESTAMP, + buf, + len, + 0, + &encdata); + free(buf); + krb5_crypto_destroy(context, crypto); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret); + free_EncryptedData(&encdata); + if (ret) + return ret; + if(buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_padata_add(context, md, KRB5_PADATA_ENC_TIMESTAMP, buf, len); + if (ret) + free(buf); + return ret; +} + +static krb5_error_code +add_enc_ts_padata(krb5_context context, + METHOD_DATA *md, + krb5_principal client, + krb5_s2k_proc key_proc, + krb5_const_pointer keyseed, + krb5_enctype *enctypes, + unsigned netypes, + krb5_salt *salt, + krb5_data *s2kparams) +{ + krb5_error_code ret; + krb5_salt salt2; + krb5_enctype *ep; + int i; + + if(salt == NULL) { + /* default to standard salt */ + ret = krb5_get_pw_salt (context, client, &salt2); + salt = &salt2; + } + if (!enctypes) { + enctypes = context->etypes; + netypes = 0; + for (ep = enctypes; *ep != ETYPE_NULL; ep++) + netypes++; + } + + for (i = 0; i < netypes; ++i) { + krb5_keyblock *key; + + ret = (*key_proc)(context, enctypes[i], keyseed, + *salt, s2kparams, &key); + if (ret) + continue; + ret = make_pa_enc_timestamp (context, md, enctypes[i], key); + krb5_free_keyblock (context, key); + if (ret) + return ret; + } + if(salt == &salt2) + krb5_free_salt(context, salt2); + return 0; +} + +static krb5_error_code +pa_data_to_md_ts_enc(krb5_context context, + const AS_REQ *a, + const krb5_principal client, + krb5_get_init_creds_ctx *ctx, + struct pa_info_data *ppaid, + METHOD_DATA *md) +{ + if (ctx->key_proc == NULL || ctx->password == NULL) + return 0; + + if (ppaid) { + add_enc_ts_padata(context, md, client, + ctx->key_proc, ctx->password, + &ppaid->etype, 1, + &ppaid->salt, ppaid->s2kparams); + } else { + krb5_salt salt; + + /* make a v5 salted pa-data */ + add_enc_ts_padata(context, md, client, + ctx->key_proc, ctx->password, + a->req_body.etype.val, a->req_body.etype.len, + NULL, NULL); + + /* make a v4 salted pa-data */ + salt.salttype = KRB5_PW_SALT; + krb5_data_zero(&salt.saltvalue); + add_enc_ts_padata(context, md, client, + ctx->key_proc, ctx->password, + a->req_body.etype.val, a->req_body.etype.len, + &salt, NULL); + } + return 0; +} + +static krb5_error_code +pa_data_to_key_plain(krb5_context context, + const krb5_principal client, + krb5_get_init_creds_ctx *ctx, + krb5_salt salt, + krb5_data *s2kparams, + krb5_enctype etype, + krb5_keyblock **key) +{ + krb5_error_code ret; + + ret = (*ctx->key_proc)(context, etype, ctx->password, + salt, s2kparams, key); + return ret; +} + + +static krb5_error_code +pa_data_to_md_pkinit(krb5_context context, + const AS_REQ *a, + const krb5_principal client, + krb5_get_init_creds_ctx *ctx, + METHOD_DATA *md) +{ + if (ctx->pk_init_ctx == NULL) + return 0; +#ifdef PKINIT + return _krb5_pk_mk_padata(context, + ctx->pk_init_ctx, + &a->req_body, + ctx->pk_nonce, + md); +#else + krb5_set_error_string(context, "no support for PKINIT compiled in"); + return EINVAL; +#endif +} + +static krb5_error_code +pa_data_add_pac_request(krb5_context context, + krb5_get_init_creds_ctx *ctx, + METHOD_DATA *md) +{ + size_t len, length; + krb5_error_code ret; + PA_PAC_REQUEST req; + void *buf; + + switch (ctx->req_pac) { + case KRB5_PA_PAC_DONT_CARE: + return 0; /* don't bother */ + case KRB5_PA_PAC_REQ_TRUE: + req.include_pac = 1; + break; + case KRB5_PA_PAC_REQ_FALSE: + req.include_pac = 0; + } + + ASN1_MALLOC_ENCODE(PA_PAC_REQUEST, buf, length, + &req, &len, ret); + if (ret) + return ret; + if(len != length) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_padata_add(context, md, KRB5_PADATA_PA_PAC_REQUEST, buf, len); + if (ret) + free(buf); + + return 0; +} + +/* + * Assumes caller always will free `out_md', even on error. + */ + +static krb5_error_code +process_pa_data_to_md(krb5_context context, + const krb5_creds *creds, + const AS_REQ *a, + krb5_get_init_creds_ctx *ctx, + METHOD_DATA *in_md, + METHOD_DATA **out_md, + krb5_prompter_fct prompter, + void *prompter_data) +{ + krb5_error_code ret; + + ALLOC(*out_md, 1); + if (*out_md == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + (*out_md)->len = 0; + (*out_md)->val = NULL; + + if (in_md->len != 0) { + struct pa_info_data paid, *ppaid; + + memset(&paid, 0, sizeof(paid)); + + paid.etype = ENCTYPE_NULL; + ppaid = process_pa_info(context, creds->client, a, &paid, in_md); + + pa_data_to_md_ts_enc(context, a, creds->client, ctx, ppaid, *out_md); + if (ppaid) + free_paid(context, ppaid); + } + + pa_data_add_pac_request(context, ctx, *out_md); + ret = pa_data_to_md_pkinit(context, a, creds->client, ctx, *out_md); + if (ret) + return ret; + + if ((*out_md)->len == 0) { + free(*out_md); + *out_md = NULL; + } + + return 0; +} + +static krb5_error_code +process_pa_data_to_key(krb5_context context, + krb5_get_init_creds_ctx *ctx, + krb5_creds *creds, + AS_REQ *a, + krb5_kdc_rep *rep, + krb5_keyblock **key) +{ + struct pa_info_data paid, *ppaid = NULL; + krb5_error_code ret; + krb5_enctype etype; + PA_DATA *pa; + + memset(&paid, 0, sizeof(paid)); + + etype = rep->kdc_rep.enc_part.etype; + + if (rep->kdc_rep.padata) { + paid.etype = etype; + ppaid = process_pa_info(context, creds->client, a, &paid, + rep->kdc_rep.padata); + } + if (ppaid == NULL) { + ret = krb5_get_pw_salt (context, creds->client, &paid.salt); + if (ret) + return ret; + paid.etype = etype; + paid.s2kparams = NULL; + } + + pa = NULL; + if (rep->kdc_rep.padata) { + int idx = 0; + pa = krb5_find_padata(rep->kdc_rep.padata->val, + rep->kdc_rep.padata->len, + KRB5_PADATA_PK_AS_REP, + &idx); + if (pa == NULL) { + idx = 0; + pa = krb5_find_padata(rep->kdc_rep.padata->val, + rep->kdc_rep.padata->len, + KRB5_PADATA_PK_AS_REP_19, + &idx); + } + } + if (pa && ctx->pk_init_ctx) { +#ifdef PKINIT + ret = _krb5_pk_rd_pa_reply(context, + ctx->pk_init_ctx, + etype, + ctx->pk_nonce, + pa, + key); +#else + krb5_set_error_string(context, "no support for PKINIT compiled in"); + ret = EINVAL; +#endif + } else if (ctx->password) + ret = pa_data_to_key_plain(context, creds->client, ctx, + paid.salt, paid.s2kparams, etype, key); + else { + krb5_set_error_string(context, "No usable pa data type"); + ret = EINVAL; + } + + free_paid(context, &paid); + return ret; +} + +static krb5_error_code +init_cred_loop(krb5_context context, + const krb5_get_init_creds_opt *init_cred_opts, + const krb5_prompter_fct prompter, + void *prompter_data, + krb5_get_init_creds_ctx *ctx, + krb5_creds *creds, + krb5_kdc_rep *ret_as_reply) +{ + krb5_error_code ret; + krb5_kdc_rep rep; + METHOD_DATA md; + krb5_data resp; + size_t len; + size_t size; + int send_to_kdc_flags = 0; + + memset(&md, 0, sizeof(md)); + memset(&rep, 0, sizeof(rep)); + + if (ret_as_reply) + memset(ret_as_reply, 0, sizeof(*ret_as_reply)); + + ret = init_creds_init_as_req(context, ctx->flags, creds, + ctx->addrs, ctx->etypes, &ctx->as_req); + if (ret) + return ret; + + /* Set a new nonce. */ + krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce)); + ctx->nonce &= 0xffffffff; + /* XXX these just needs to be the same when using Windows PK-INIT */ + ctx->pk_nonce = ctx->nonce; + + /* + * Increase counter when we want other pre-auth types then + * KRB5_PA_ENC_TIMESTAMP. + */ +#define MAX_PA_COUNTER 3 + + ctx->pa_counter = 0; + while (ctx->pa_counter < MAX_PA_COUNTER) { + krb5_data req; + + ctx->pa_counter++; + + if (ctx->as_req.padata) { + free_METHOD_DATA(ctx->as_req.padata); + free(ctx->as_req.padata); + ctx->as_req.padata = NULL; + } + + /* Set a new nonce. */ + ctx->as_req.req_body.nonce = ctx->nonce; + + /* fill_in_md_data */ + ret = process_pa_data_to_md(context, creds, &ctx->as_req, ctx, + &md, &ctx->as_req.padata, + prompter, prompter_data); + if (ret) + goto out; + ASN1_MALLOC_ENCODE(AS_REQ, req.data, req.length, + &ctx->as_req, &len, ret); + if (ret) + goto out; + if(len != req.length) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_sendto_kdc_flags (context, &req, + &creds->client->realm, &resp, + send_to_kdc_flags); + krb5_data_free(&req); + if (ret) + goto out; + + memset (&rep, 0, sizeof(rep)); + ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size); + if (ret == 0) { + krb5_data_free(&resp); + krb5_clear_error_string(context); + break; + } else { + /* let's try to parse it as a KRB-ERROR */ + KRB_ERROR error; + + ret = krb5_rd_error(context, &resp, &error); + if(ret && resp.data && ((char*)resp.data)[0] == 4) + ret = KRB5KRB_AP_ERR_V4_REPLY; + krb5_data_free(&resp); + if (ret) + goto out; + + ret = krb5_error_from_rd_error(context, &error, creds); + + /* + * If no preauth was set and KDC requires it, give it one + * more try. + */ + + if (ret == KRB5KDC_ERR_PREAUTH_REQUIRED) { + free_METHOD_DATA(&md); + memset(&md, 0, sizeof(md)); + + if (error.e_data) { + ret = decode_METHOD_DATA(error.e_data->data, + error.e_data->length, + &md, + NULL); + if (ret) + krb5_set_error_string(context, + "failed to decode METHOD DATA"); + } else { + /* XXX guess what the server want here add add md */ + } + krb5_free_error_contents(context, &error); + if (ret) + goto out; + } else if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG) { + if (send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG) { + if (ret_as_reply) + rep.error = error; + else + krb5_free_error_contents(context, &error); + goto out; + } + krb5_free_error_contents(context, &error); + send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; + } else { + if (ret_as_reply) + rep.error = error; + else + krb5_free_error_contents(context, &error); + goto out; + } + } + } + + { + krb5_keyblock *key = NULL; + + ret = process_pa_data_to_key(context, ctx, creds, + &ctx->as_req, &rep, &key); + if (ret) + goto out; + + ret = _krb5_extract_ticket(context, + &rep, + creds, + key, + NULL, + KRB5_KU_AS_REP_ENC_PART, + NULL, + ctx->nonce, + FALSE, + ctx->flags.b.request_anonymous, + NULL, + NULL); + krb5_free_keyblock(context, key); + } +out: + free_METHOD_DATA(&md); + memset(&md, 0, sizeof(md)); + + if (ret == 0 && ret_as_reply) + *ret_as_reply = rep; + else + krb5_free_kdc_rep (context, &rep); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds(krb5_context context, + krb5_creds *creds, + krb5_principal client, + krb5_prompter_fct prompter, + void *data, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *options) +{ + krb5_get_init_creds_ctx ctx; + krb5_kdc_rep kdc_reply; + krb5_error_code ret; + char buf[BUFSIZ]; + int done; + + memset(&kdc_reply, 0, sizeof(kdc_reply)); + + ret = get_init_creds_common(context, creds, client, start_time, + in_tkt_service, options, &ctx); + if (ret) + goto out; + + done = 0; + while(!done) { + memset(&kdc_reply, 0, sizeof(kdc_reply)); + + ret = init_cred_loop(context, + options, + prompter, + data, + &ctx, + &ctx.cred, + &kdc_reply); + + switch (ret) { + case 0 : + done = 1; + break; + case KRB5KDC_ERR_KEY_EXPIRED : + /* try to avoid recursion */ + + /* don't try to change password where then where none */ + if (prompter == NULL || ctx.password == NULL) + goto out; + + krb5_clear_error_string (context); + + if (ctx.in_tkt_service != NULL + && strcmp (ctx.in_tkt_service, "kadmin/changepw") == 0) + goto out; + + ret = change_password (context, + client, + ctx.password, + buf, + sizeof(buf), + prompter, + data, + options); + if (ret) + goto out; + ctx.password = buf; + break; + default: + goto out; + } + } + + if (prompter) + print_expire (context, + krb5_principal_get_realm (context, ctx.cred.client), + &kdc_reply, + prompter, + data); + + out: + memset (buf, 0, sizeof(buf)); + free_init_creds_ctx(context, &ctx); + krb5_free_kdc_rep (context, &kdc_reply); + if (ret == 0) + *creds = ctx.cred; + else + krb5_free_cred_contents (context, &ctx.cred); + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_password(krb5_context context, + krb5_creds *creds, + krb5_principal client, + const char *password, + krb5_prompter_fct prompter, + void *data, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *in_options) +{ + krb5_get_init_creds_opt *options; + char buf[BUFSIZ]; + krb5_error_code ret; + + if (in_options == NULL) + ret = krb5_get_init_creds_opt_alloc(context, &options); + else + ret = _krb5_get_init_creds_opt_copy(context, in_options, &options); + if (ret) + return ret; + + if (password == NULL && + options->private->password == NULL && + options->private->pk_init_ctx == NULL) + { + krb5_prompt prompt; + krb5_data password_data; + char *p, *q; + + krb5_unparse_name (context, client, &p); + asprintf (&q, "%s's Password: ", p); + free (p); + prompt.prompt = q; + password_data.data = buf; + password_data.length = sizeof(buf); + prompt.hidden = 1; + prompt.reply = &password_data; + prompt.type = KRB5_PROMPT_TYPE_PASSWORD; + + ret = (*prompter) (context, data, NULL, NULL, 1, &prompt); + free (q); + if (ret) { + memset (buf, 0, sizeof(buf)); + krb5_get_init_creds_opt_free(options); + ret = KRB5_LIBOS_PWDINTR; + krb5_clear_error_string (context); + return ret; + } + password = password_data.data; + } + + if (options->private->password == NULL) { + ret = krb5_get_init_creds_opt_set_pa_password(context, options, + password, NULL); + if (ret) { + krb5_get_init_creds_opt_free(options); + memset(buf, 0, sizeof(buf)); + return ret; + } + } + + ret = krb5_get_init_creds(context, creds, client, prompter, + data, start_time, in_tkt_service, options); + krb5_get_init_creds_opt_free(options); + memset(buf, 0, sizeof(buf)); + return ret; +} + +static krb5_error_code +init_creds_keyblock_key_proc (krb5_context context, + krb5_enctype type, + krb5_salt salt, + krb5_const_pointer keyseed, + krb5_keyblock **key) +{ + return krb5_copy_keyblock (context, keyseed, key); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_keyblock(krb5_context context, + krb5_creds *creds, + krb5_principal client, + krb5_keyblock *keyblock, + krb5_deltat start_time, + const char *in_tkt_service, + krb5_get_init_creds_opt *options) +{ + struct krb5_get_init_creds_ctx ctx; + krb5_error_code ret; + + ret = get_init_creds_common(context, creds, client, start_time, + in_tkt_service, options, &ctx); + if (ret) + goto out; + + ret = krb5_get_in_cred (context, + ctx.flags.i, + ctx.addrs, + ctx.etypes, + ctx.pre_auth_types, + NULL, + init_creds_keyblock_key_proc, + keyblock, + NULL, + NULL, + &ctx.cred, + NULL); + + if (ret == 0 && creds) + *creds = ctx.cred; + else + krb5_free_cred_contents (context, &ctx.cred); + + out: + free_init_creds_ctx(context, &ctx); + return ret; +} diff --git a/source4/heimdal/lib/krb5/k524_err.et b/source4/heimdal/lib/krb5/k524_err.et new file mode 100644 index 0000000000..2dc60f46ae --- /dev/null +++ b/source4/heimdal/lib/krb5/k524_err.et @@ -0,0 +1,20 @@ +# +# Error messages for the k524 functions +# +# This might look like a com_err file, but is not +# +id "$Id: k524_err.et,v 1.1 2001/06/20 02:44:11 joda Exp $" + +error_table k524 + +prefix KRB524 +error_code BADKEY, "wrong keytype in ticket" +error_code BADADDR, "incorrect network address" +error_code BADPRINC, "cannot convert V5 principal" #unused +error_code BADREALM, "V5 realm name longer than V4 maximum" #unused +error_code V4ERR, "kerberos V4 error server" +error_code ENCFULL, "encoding too large at server" +error_code DECEMPTY, "decoding out of data" #unused +error_code NOTRESP, "service not responding" #unused +end + diff --git a/source4/heimdal/lib/krb5/kcm.c b/source4/heimdal/lib/krb5/kcm.c new file mode 100644 index 0000000000..b7873f33d5 --- /dev/null +++ b/source4/heimdal/lib/krb5/kcm.c @@ -0,0 +1,1095 @@ +/* + * Copyright (c) 2005, 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. + */ + +#include "krb5_locl.h" + +#ifdef HAVE_KCM +/* + * Client library for Kerberos Credentials Manager (KCM) daemon + */ + +#ifdef HAVE_SYS_UN_H +#include +#endif + +#include "kcm.h" + +RCSID("$Id: kcm.c,v 1.7 2005/06/17 04:20:11 lha Exp $"); + +typedef struct krb5_kcmcache { + char *name; + struct sockaddr_un path; + char *door_path; +} krb5_kcmcache; + +#define KCMCACHE(X) ((krb5_kcmcache *)(X)->data.data) +#define CACHENAME(X) (KCMCACHE(X)->name) +#define KCMCURSOR(C) (*(u_int32_t *)(C)) + +static krb5_error_code +try_door(krb5_context context, const krb5_kcmcache *k, + krb5_data *request_data, + krb5_data *response_data) +{ +#ifdef HAVE_DOOR_CREATE + door_arg_t arg; + int fd; + int ret; + + memset(&arg, 0, sizeof(arg)); + + fd = open(k->door_path, O_RDWR); + if (fd < 0) + return KRB5_CC_IO; + + arg.data_ptr = request_data->data; + arg.data_size = request_data->length; + arg.desc_ptr = NULL; + arg.desc_num = 0; + arg.rbuf = NULL; + arg.rsize = 0; + + ret = door_call(fd, &arg); + close(fd); + if (ret != 0) + return KRB5_CC_IO; + + ret = krb5_data_copy(response_data, arg.rbuf, arg.rsize); + munmap(arg.rbuf, arg.rsize); + if (ret) + return ret; + + return 0; +#else + return KRB5_CC_IO; +#endif +} + +static krb5_error_code +try_unix_socket(krb5_context context, const krb5_kcmcache *k, + krb5_data *request_data, + krb5_data *response_data) +{ + krb5_error_code ret; + int fd; + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) + return KRB5_CC_IO; + + if (connect(fd, rk_UNCONST(&k->path), sizeof(k->path)) != 0) { + close(fd); + return KRB5_CC_IO; + } + + ret = _krb5_send_and_recv_tcp(fd, context->kdc_timeout, + request_data, response_data); + close(fd); + return ret; +} + +static krb5_error_code +kcm_send_request(krb5_context context, + krb5_kcmcache *k, + krb5_storage *request, + krb5_data *response_data) +{ + krb5_error_code ret; + krb5_data request_data; + int i; + + response_data->data = NULL; + response_data->length = 0; + + ret = krb5_storage_to_data(request, &request_data); + if (ret) { + krb5_clear_error_string(context); + return KRB5_CC_NOMEM; + } + + ret = KRB5_CC_IO; + + for (i = 0; i < context->max_retries; i++) { + ret = try_door(context, k, &request_data, response_data); + if (ret == 0 && response_data->length != 0) + break; + ret = try_unix_socket(context, k, &request_data, response_data); + if (ret == 0 && response_data->length != 0) + break; + } + + krb5_data_free(&request_data); + + if (ret) { + krb5_clear_error_string(context); + ret = KRB5_CC_IO; + } + + return ret; +} + +static krb5_error_code +kcm_storage_request(krb5_context context, + kcm_operation opcode, + krb5_storage **storage_p) +{ + krb5_storage *sp; + krb5_error_code ret; + + *storage_p = NULL; + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + + /* Send MAJOR | VERSION | OPCODE */ + ret = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MAJOR); + if (ret) + goto fail; + ret = krb5_store_int8(sp, KCM_PROTOCOL_VERSION_MINOR); + if (ret) + goto fail; + ret = krb5_store_int16(sp, opcode); + if (ret) + goto fail; + + *storage_p = sp; + fail: + if (ret) { + krb5_set_error_string(context, "Failed to encode request"); + krb5_storage_free(sp); + } + + return ret; +} + +static krb5_error_code +kcm_alloc(krb5_context context, const char *name, krb5_ccache *id) +{ + krb5_kcmcache *k; + const char *path; + + k = malloc(sizeof(*k)); + if (k == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + + if (name != NULL) { + k->name = strdup(name); + if (k->name == NULL) { + free(k); + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + } else + k->name = NULL; + + path = krb5_config_get_string_default(context, NULL, + _PATH_KCM_SOCKET, + "libdefaults", + "kcm_socket", + NULL); + + k->path.sun_family = AF_UNIX; + strlcpy(k->path.sun_path, path, sizeof(k->path.sun_path)); + + path = krb5_config_get_string_default(context, NULL, + _PATH_KCM_DOOR, + "libdefaults", + "kcm_door", + NULL); + k->door_path = strdup(path); + + (*id)->data.data = k; + (*id)->data.length = sizeof(*k); + + return 0; +} + +static krb5_error_code +kcm_call(krb5_context context, + krb5_kcmcache *k, + krb5_storage *request, + krb5_storage **response_p, + krb5_data *response_data_p) +{ + krb5_data response_data; + krb5_error_code ret, status; + krb5_storage *response; + + if (response_p != NULL) + *response_p = NULL; + + ret = kcm_send_request(context, k, request, &response_data); + if (ret) { + return ret; + } + + response = krb5_storage_from_data(&response_data); + if (response == NULL) { + krb5_data_free(&response_data); + return KRB5_CC_IO; + } + + ret = krb5_ret_int32(response, &status); + if (ret) { + krb5_storage_free(response); + krb5_data_free(&response_data); + return KRB5_CC_FORMAT; + } + + if (status) { + krb5_storage_free(response); + krb5_data_free(&response_data); + return status; + } + + if (response_p != NULL) { + *response_data_p = response_data; + *response_p = response; + + return 0; + } + + krb5_storage_free(response); + krb5_data_free(&response_data); + + return 0; +} + +static void +kcm_free(krb5_context context, krb5_ccache *id) +{ + krb5_kcmcache *k = KCMCACHE(*id); + + if (k != NULL) { + if (k->name != NULL) + free(k->name); + if (k->door_path) + free(k->door_path); + memset(k, 0, sizeof(*k)); + krb5_data_free(&(*id)->data); + } + + *id = NULL; +} + +static const char * +kcm_get_name(krb5_context context, + krb5_ccache id) +{ + return CACHENAME(id); +} + +static krb5_error_code +kcm_resolve(krb5_context context, krb5_ccache *id, const char *res) +{ + return kcm_alloc(context, res, id); +} + +/* + * Request: + * + * Response: + * NameZ + */ +static krb5_error_code +kcm_gen_new(krb5_context context, krb5_ccache *id) +{ + krb5_kcmcache *k; + krb5_error_code ret; + krb5_storage *request, *response; + krb5_data response_data; + + ret = kcm_alloc(context, NULL, id); + if (ret) + return ret; + + k = KCMCACHE(*id); + + ret = kcm_storage_request(context, KCM_OP_GEN_NEW, &request); + if (ret) { + kcm_free(context, id); + return ret; + } + + ret = kcm_call(context, k, request, &response, &response_data); + if (ret) { + krb5_storage_free(request); + kcm_free(context, id); + return ret; + } + + ret = krb5_ret_stringz(response, &k->name); + if (ret) + ret = KRB5_CC_IO; + + krb5_storage_free(request); + krb5_storage_free(response); + krb5_data_free(&response_data); + + if (ret) + kcm_free(context, id); + + return ret; +} + +/* + * Request: + * NameZ + * Principal + * + * Response: + * + */ +static krb5_error_code +kcm_initialize(krb5_context context, + krb5_ccache id, + krb5_principal primary_principal) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_INITIALIZE, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_principal(request, primary_principal); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + +static krb5_error_code +kcm_close(krb5_context context, + krb5_ccache id) +{ + kcm_free(context, &id); + return 0; +} + +/* + * Request: + * NameZ + * + * Response: + * + */ +static krb5_error_code +kcm_destroy(krb5_context context, + krb5_ccache id) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_DESTROY, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + +/* + * Request: + * NameZ + * Creds + * + * Response: + * + */ +static krb5_error_code +kcm_store_cred(krb5_context context, + krb5_ccache id, + krb5_creds *creds) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_STORE, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_creds(request, creds); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + +/* + * Request: + * NameZ + * WhichFields + * MatchCreds + * + * Response: + * Creds + * + */ +static krb5_error_code +kcm_retrieve(krb5_context context, + krb5_ccache id, + krb5_flags which, + const krb5_creds *mcred, + krb5_creds *creds) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request, *response; + krb5_data response_data; + + ret = kcm_storage_request(context, KCM_OP_RETRIEVE, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, which); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_creds_tag(request, rk_UNCONST(mcred)); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, &response, &response_data); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_ret_creds(response, creds); + if (ret) + ret = KRB5_CC_IO; + + krb5_storage_free(request); + krb5_storage_free(response); + krb5_data_free(&response_data); + + return ret; +} + +/* + * Request: + * NameZ + * + * Response: + * Principal + */ +static krb5_error_code +kcm_get_principal(krb5_context context, + krb5_ccache id, + krb5_principal *principal) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request, *response; + krb5_data response_data; + + ret = kcm_storage_request(context, KCM_OP_GET_PRINCIPAL, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, &response, &response_data); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_ret_principal(response, principal); + if (ret) + ret = KRB5_CC_IO; + + krb5_storage_free(request); + krb5_storage_free(response); + krb5_data_free(&response_data); + + return ret; +} + +/* + * Request: + * NameZ + * + * Response: + * Cursor + * + */ +static krb5_error_code +kcm_get_first (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request, *response; + krb5_data response_data; + u_int32_t tmp; + + ret = kcm_storage_request(context, KCM_OP_GET_FIRST, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, &response, &response_data); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_ret_int32(response, &tmp); + if (ret) + ret = KRB5_CC_IO; + + krb5_storage_free(request); + krb5_storage_free(response); + krb5_data_free(&response_data); + + if (ret) + return ret; + + *cursor = malloc(sizeof(tmp)); + if (*cursor == NULL) + return KRB5_CC_NOMEM; + + KCMCURSOR(*cursor) = tmp; + + return 0; +} + +/* + * Request: + * NameZ + * Cursor + * + * Response: + * Creds + */ +static krb5_error_code +kcm_get_next (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request, *response; + krb5_data response_data; + + ret = kcm_storage_request(context, KCM_OP_GET_NEXT, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, KCMCURSOR(*cursor)); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, &response, &response_data); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_ret_creds(response, creds); + if (ret) + ret = KRB5_CC_IO; + + krb5_storage_free(request); + krb5_storage_free(response); + krb5_data_free(&response_data); + + return ret; +} + +/* + * Request: + * NameZ + * Cursor + * + * Response: + * + */ +static krb5_error_code +kcm_end_get (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_END_GET, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, KCMCURSOR(*cursor)); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + if (ret) { + krb5_storage_free(request); + return ret; + } + + krb5_storage_free(request); + + KCMCURSOR(*cursor) = 0; + free(*cursor); + *cursor = NULL; + + return ret; +} + +/* + * Request: + * NameZ + * WhichFields + * MatchCreds + * + * Response: + * + */ +static krb5_error_code +kcm_remove_cred(krb5_context context, + krb5_ccache id, + krb5_flags which, + krb5_creds *cred) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_REMOVE_CRED, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, which); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_creds_tag(request, cred); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + +static krb5_error_code +kcm_set_flags(krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_SET_FLAGS, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, flags); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + +static krb5_error_code +kcm_get_version(krb5_context context, + krb5_ccache id) +{ + return 0; +} + +const krb5_cc_ops krb5_kcm_ops = { + "KCM", + kcm_get_name, + kcm_resolve, + kcm_gen_new, + kcm_initialize, + kcm_destroy, + kcm_close, + kcm_store_cred, + kcm_retrieve, + kcm_get_principal, + kcm_get_first, + kcm_get_next, + kcm_end_get, + kcm_remove_cred, + kcm_set_flags, + kcm_get_version +}; + +krb5_boolean +_krb5_kcm_is_running(krb5_context context) +{ + krb5_error_code ret; + krb5_ccache_data ccdata; + krb5_ccache id = &ccdata; + krb5_boolean running; + + ret = kcm_alloc(context, NULL, &id); + if (ret) + return 0; + + running = (_krb5_kcm_noop(context, id) == 0); + + kcm_free(context, &id); + + return running; +} + +/* + * Request: + * + * Response: + * + */ +krb5_error_code +_krb5_kcm_noop(krb5_context context, + krb5_ccache id) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_NOOP, &request); + if (ret) + return ret; + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + + +/* + * Request: + * NameZ + * Mode + * + * Response: + * + */ +krb5_error_code +_krb5_kcm_chmod(krb5_context context, + krb5_ccache id, + u_int16_t mode) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_CHMOD, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int16(request, mode); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + + +/* + * Request: + * NameZ + * UID + * GID + * + * Response: + * + */ +krb5_error_code +_krb5_kcm_chown(krb5_context context, + krb5_ccache id, + u_int32_t uid, + u_int32_t gid) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_CHOWN, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, uid); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, gid); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + + +/* + * Request: + * NameZ + * ServerPrincipalPresent + * ServerPrincipal OPTIONAL + * Key + * + * Repsonse: + * + */ +krb5_error_code +_krb5_kcm_get_initial_ticket(krb5_context context, + krb5_ccache id, + krb5_principal server, + krb5_keyblock *key) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_GET_INITIAL_TICKET, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int8(request, (server == NULL) ? 0 : 1); + if (ret) { + krb5_storage_free(request); + return ret; + } + + if (server != NULL) { + ret = krb5_store_principal(request, server); + if (ret) { + krb5_storage_free(request); + return ret; + } + } + + ret = krb5_store_keyblock(request, *key); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + + +/* + * Request: + * NameZ + * KDCFlags + * EncryptionType + * ServerPrincipal + * + * Repsonse: + * + */ +krb5_error_code +_krb5_kcm_get_ticket(krb5_context context, + krb5_ccache id, + krb5_kdc_flags flags, + krb5_enctype enctype, + krb5_principal server) +{ + krb5_error_code ret; + krb5_kcmcache *k = KCMCACHE(id); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_GET_TICKET, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, k->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, flags.i); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_int32(request, enctype); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_principal(request, server); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = kcm_call(context, k, request, NULL, NULL); + + krb5_storage_free(request); + return ret; +} + + +#endif /* HAVE_KCM */ diff --git a/source4/heimdal/lib/krb5/keyblock.c b/source4/heimdal/lib/krb5/keyblock.c new file mode 100644 index 0000000000..314d97978b --- /dev/null +++ b/source4/heimdal/lib/krb5/keyblock.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keyblock.c,v 1.17 2005/05/18 04:21:31 lha Exp $"); + +void KRB5_LIB_FUNCTION +krb5_keyblock_zero(krb5_keyblock *keyblock) +{ + keyblock->keytype = 0; + krb5_data_zero(&keyblock->keyvalue); +} + +void KRB5_LIB_FUNCTION +krb5_free_keyblock_contents(krb5_context context, + krb5_keyblock *keyblock) +{ + if(keyblock) { + if (keyblock->keyvalue.data != NULL) + memset(keyblock->keyvalue.data, 0, keyblock->keyvalue.length); + krb5_data_free (&keyblock->keyvalue); + keyblock->keytype = ENCTYPE_NULL; + } +} + +void KRB5_LIB_FUNCTION +krb5_free_keyblock(krb5_context context, + krb5_keyblock *keyblock) +{ + if(keyblock){ + krb5_free_keyblock_contents(context, keyblock); + free(keyblock); + } +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_keyblock_contents (krb5_context context, + const krb5_keyblock *inblock, + krb5_keyblock *to) +{ + return copy_EncryptionKey(inblock, to); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_keyblock (krb5_context context, + const krb5_keyblock *inblock, + krb5_keyblock **to) +{ + krb5_keyblock *k; + + k = malloc (sizeof(*k)); + if (k == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + *to = k; + return krb5_copy_keyblock_contents (context, inblock, k); +} + +krb5_enctype +krb5_keyblock_get_enctype(const krb5_keyblock *block) +{ + return block->keytype; +} + +/* + * Fill in `key' with key data of type `enctype' from `data' of length + * `size'. Key should be freed using krb5_free_keyblock_contents. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keyblock_init(krb5_context context, + krb5_enctype type, + const void *data, + size_t size, + krb5_keyblock *key) +{ + krb5_error_code ret; + size_t len; + + memset(key, 0, sizeof(*key)); + + ret = krb5_enctype_keysize(context, type, &len); + if (ret) + return ret; + + if (len != size) { + krb5_set_error_string(context, "Encryption key %d is %lu bytes " + "long, %lu was passed in", + type, (unsigned long)len, (unsigned long)size); + return KRB5_PROG_ETYPE_NOSUPP; + } + ret = krb5_data_copy(&key->keyvalue, data, len); + if(ret) { + krb5_set_error_string(context, "malloc failed: %lu", + (unsigned long)len); + return ret; + } + key->keytype = type; + + return 0; +} diff --git a/source4/heimdal/lib/krb5/keytab.c b/source4/heimdal/lib/krb5/keytab.c new file mode 100644 index 0000000000..a405664122 --- /dev/null +++ b/source4/heimdal/lib/krb5/keytab.c @@ -0,0 +1,491 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keytab.c,v 1.60 2005/05/19 14:04:45 lha Exp $"); + +/* + * Register a new keytab in `ops' + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_register(krb5_context context, + const krb5_kt_ops *ops) +{ + struct krb5_keytab_data *tmp; + + if (strlen(ops->prefix) > KRB5_KT_PREFIX_MAX_LEN - 1) { + krb5_set_error_string(context, "krb5_kt_register; prefix too long"); + return KRB5_KT_BADNAME; + } + + tmp = realloc(context->kt_types, + (context->num_kt_types + 1) * sizeof(*context->kt_types)); + if(tmp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(&tmp[context->num_kt_types], ops, + sizeof(tmp[context->num_kt_types])); + context->kt_types = tmp; + context->num_kt_types++; + return 0; +} + +/* + * Resolve the keytab name (of the form `type:residual') in `name' + * into a keytab in `id'. + * Return 0 or an error + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_resolve(krb5_context context, + const char *name, + krb5_keytab *id) +{ + krb5_keytab k; + int i; + const char *type, *residual; + size_t type_len; + krb5_error_code ret; + + residual = strchr(name, ':'); + if(residual == NULL) { + type = "FILE"; + type_len = strlen(type); + residual = name; + } else { + type = name; + type_len = residual - name; + residual++; + } + + for(i = 0; i < context->num_kt_types; i++) { + if(strncasecmp(type, context->kt_types[i].prefix, type_len) == 0) + break; + } + if(i == context->num_kt_types) { + krb5_set_error_string(context, "unknown keytab type %.*s", + (int)type_len, type); + return KRB5_KT_UNKNOWN_TYPE; + } + + k = malloc (sizeof(*k)); + if (k == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(k, &context->kt_types[i], sizeof(*k)); + k->data = NULL; + ret = (*k->resolve)(context, residual, k); + if(ret) { + free(k); + k = NULL; + } + *id = k; + return ret; +} + +/* + * copy the name of the default keytab into `name'. + * Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_default_name(krb5_context context, char *name, size_t namesize) +{ + if (strlcpy (name, context->default_keytab, namesize) >= namesize) { + krb5_clear_error_string (context); + return KRB5_CONFIG_NOTENUFSPACE; + } + return 0; +} + +/* + * copy the name of the default modify keytab into `name'. + * Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_default_modify_name(krb5_context context, char *name, size_t namesize) +{ + const char *kt = NULL; + if(context->default_keytab_modify == NULL) { + if(strncasecmp(context->default_keytab, "ANY:", 4) != 0) + kt = context->default_keytab; + else { + size_t len = strcspn(context->default_keytab + 4, ","); + if(len >= namesize) { + krb5_clear_error_string(context); + return KRB5_CONFIG_NOTENUFSPACE; + } + strlcpy(name, context->default_keytab + 4, namesize); + name[len] = '\0'; + return 0; + } + } else + kt = context->default_keytab_modify; + if (strlcpy (name, kt, namesize) >= namesize) { + krb5_clear_error_string (context); + return KRB5_CONFIG_NOTENUFSPACE; + } + return 0; +} + +/* + * Set `id' to the default keytab. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_default(krb5_context context, krb5_keytab *id) +{ + return krb5_kt_resolve (context, context->default_keytab, id); +} + +/* + * Read the key identified by `(principal, vno, enctype)' from the + * keytab in `keyprocarg' (the default if == NULL) into `*key'. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_read_service_key(krb5_context context, + krb5_pointer keyprocarg, + krb5_principal principal, + krb5_kvno vno, + krb5_enctype enctype, + krb5_keyblock **key) +{ + krb5_keytab keytab; + krb5_keytab_entry entry; + krb5_error_code ret; + + if (keyprocarg) + ret = krb5_kt_resolve (context, keyprocarg, &keytab); + else + ret = krb5_kt_default (context, &keytab); + + if (ret) + return ret; + + ret = krb5_kt_get_entry (context, keytab, principal, vno, enctype, &entry); + krb5_kt_close (context, keytab); + if (ret) + return ret; + ret = krb5_copy_keyblock (context, &entry.keyblock, key); + krb5_kt_free_entry(context, &entry); + return ret; +} + +/* + * Return the type of the `keytab' in the string `prefix of length + * `prefixsize'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_type(krb5_context context, + krb5_keytab keytab, + char *prefix, + size_t prefixsize) +{ + strlcpy(prefix, keytab->prefix, prefixsize); + return 0; +} + +/* + * Retrieve the name of the keytab `keytab' into `name', `namesize' + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_name(krb5_context context, + krb5_keytab keytab, + char *name, + size_t namesize) +{ + return (*keytab->get_name)(context, keytab, name, namesize); +} + +/* + * Finish using the keytab in `id'. All resources will be released. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_close(krb5_context context, + krb5_keytab id) +{ + krb5_error_code ret; + + ret = (*id->close)(context, id); + if(ret == 0) + free(id); + return ret; +} + +/* + * Compare `entry' against `principal, vno, enctype'. + * Any of `principal, vno, enctype' might be 0 which acts as a wildcard. + * Return TRUE if they compare the same, FALSE otherwise. + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_kt_compare(krb5_context context, + krb5_keytab_entry *entry, + krb5_const_principal principal, + krb5_kvno vno, + krb5_enctype enctype) +{ + if(principal != NULL && + !krb5_principal_compare(context, entry->principal, principal)) + return FALSE; + if(vno && vno != entry->vno) + return FALSE; + if(enctype && enctype != entry->keyblock.keytype) + return FALSE; + return TRUE; +} + +/* + * Retrieve the keytab entry for `principal, kvno, enctype' into `entry' + * from the keytab `id'. + * kvno == 0 is a wildcard and gives the keytab with the highest vno. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_entry(krb5_context context, + krb5_keytab id, + krb5_const_principal principal, + krb5_kvno kvno, + krb5_enctype enctype, + krb5_keytab_entry *entry) +{ + krb5_keytab_entry tmp; + krb5_error_code ret; + krb5_kt_cursor cursor; + + if(id->get) + return (*id->get)(context, id, principal, kvno, enctype, entry); + + ret = krb5_kt_start_seq_get (context, id, &cursor); + if (ret) + return KRB5_KT_NOTFOUND; /* XXX i.e. file not found */ + + entry->vno = 0; + while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) { + if (krb5_kt_compare(context, &tmp, principal, 0, enctype)) { + /* the file keytab might only store the lower 8 bits of + the kvno, so only compare those bits */ + if (kvno == tmp.vno + || (tmp.vno < 256 && kvno % 256 == tmp.vno)) { + krb5_kt_copy_entry_contents (context, &tmp, entry); + krb5_kt_free_entry (context, &tmp); + krb5_kt_end_seq_get(context, id, &cursor); + return 0; + } else if (kvno == 0 && tmp.vno > entry->vno) { + if (entry->vno) + krb5_kt_free_entry (context, entry); + krb5_kt_copy_entry_contents (context, &tmp, entry); + } + } + krb5_kt_free_entry(context, &tmp); + } + krb5_kt_end_seq_get (context, id, &cursor); + if (entry->vno) { + return 0; + } else { + char princ[256], kt_name[256], kvno_str[25]; + char *enctype_str = NULL; + + krb5_unparse_name_fixed (context, principal, princ, sizeof(princ)); + krb5_kt_get_name (context, id, kt_name, sizeof(kt_name)); + krb5_enctype_to_string(context, enctype, &enctype_str); + + if (kvno) + snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno); + else + kvno_str[0] = '\0'; + + krb5_set_error_string (context, + "failed to find %s%s in keytab %s (%s)", + princ, + kvno_str, + kt_name, + enctype_str ? enctype_str : "unknown enctype"); + free(enctype_str); + return KRB5_KT_NOTFOUND; + } +} + +/* + * Copy the contents of `in' into `out'. + * Return 0 or an error. */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_copy_entry_contents(krb5_context context, + const krb5_keytab_entry *in, + krb5_keytab_entry *out) +{ + krb5_error_code ret; + + memset(out, 0, sizeof(*out)); + out->vno = in->vno; + + ret = krb5_copy_principal (context, in->principal, &out->principal); + if (ret) + goto fail; + ret = krb5_copy_keyblock_contents (context, + &in->keyblock, + &out->keyblock); + if (ret) + goto fail; + out->timestamp = in->timestamp; + return 0; +fail: + krb5_kt_free_entry (context, out); + return ret; +} + +/* + * Free the contents of `entry'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_free_entry(krb5_context context, + krb5_keytab_entry *entry) +{ + krb5_free_principal (context, entry->principal); + krb5_free_keyblock_contents (context, &entry->keyblock); + memset(entry, 0, sizeof(*entry)); + return 0; +} + +/* + * Set `cursor' to point at the beginning of `id'. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_start_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *cursor) +{ + if(id->start_seq_get == NULL) { + krb5_set_error_string(context, + "start_seq_get is not supported in the %s " + " keytab", id->prefix); + return HEIM_ERR_OPNOTSUPP; + } + return (*id->start_seq_get)(context, id, cursor); +} + +/* + * Get the next entry from `id' pointed to by `cursor' and advance the + * `cursor'. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_next_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *cursor) +{ + if(id->next_entry == NULL) { + krb5_set_error_string(context, + "next_entry is not supported in the %s " + " keytab", id->prefix); + return HEIM_ERR_OPNOTSUPP; + } + return (*id->next_entry)(context, id, entry, cursor); +} + +/* + * Release all resources associated with `cursor'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_end_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *cursor) +{ + if(id->end_seq_get == NULL) { + krb5_set_error_string(context, + "end_seq_get is not supported in the %s " + " keytab", id->prefix); + return HEIM_ERR_OPNOTSUPP; + } + return (*id->end_seq_get)(context, id, cursor); +} + +/* + * Add the entry in `entry' to the keytab `id'. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_add_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + if(id->add == NULL) { + krb5_set_error_string(context, "Add is not supported in the %s keytab", + id->prefix); + return KRB5_KT_NOWRITE; + } + entry->timestamp = time(NULL); + return (*id->add)(context, id,entry); +} + +/* + * Remove the entry `entry' from the keytab `id'. + * Return 0 or an error. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_remove_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + if(id->remove == NULL) { + krb5_set_error_string(context, + "Remove is not supported in the %s keytab", + id->prefix); + return KRB5_KT_NOWRITE; + } + return (*id->remove)(context, id, entry); +} diff --git a/source4/heimdal/lib/krb5/keytab_any.c b/source4/heimdal/lib/krb5/keytab_any.c new file mode 100644 index 0000000000..667788c69d --- /dev/null +++ b/source4/heimdal/lib/krb5/keytab_any.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2001-2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keytab_any.c,v 1.7 2002/10/21 13:36:59 joda Exp $"); + +struct any_data { + krb5_keytab kt; + char *name; + struct any_data *next; +}; + +static void +free_list (krb5_context context, struct any_data *a) +{ + struct any_data *next; + + for (; a != NULL; a = next) { + next = a->next; + free (a->name); + if(a->kt) + krb5_kt_close(context, a->kt); + free (a); + } +} + +static krb5_error_code +any_resolve(krb5_context context, const char *name, krb5_keytab id) +{ + struct any_data *a, *a0 = NULL, *prev = NULL; + krb5_error_code ret; + char buf[256]; + + while (strsep_copy(&name, ",", buf, sizeof(buf)) != -1) { + a = malloc(sizeof(*a)); + if (a == NULL) { + ret = ENOMEM; + goto fail; + } + if (a0 == NULL) { + a0 = a; + a->name = strdup(buf); + if (a->name == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto fail; + } + } else + a->name = NULL; + if (prev != NULL) + prev->next = a; + a->next = NULL; + ret = krb5_kt_resolve (context, buf, &a->kt); + if (ret) + goto fail; + prev = a; + } + if (a0 == NULL) { + krb5_set_error_string(context, "empty ANY: keytab"); + return ENOENT; + } + id->data = a0; + return 0; + fail: + free_list (context, a0); + return ret; +} + +static krb5_error_code +any_get_name (krb5_context context, + krb5_keytab id, + char *name, + size_t namesize) +{ + struct any_data *a = id->data; + strlcpy(name, a->name, namesize); + return 0; +} + +static krb5_error_code +any_close (krb5_context context, + krb5_keytab id) +{ + struct any_data *a = id->data; + + free_list (context, a); + return 0; +} + +struct any_cursor_extra_data { + struct any_data *a; + krb5_kt_cursor cursor; +}; + +static krb5_error_code +any_start_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *c) +{ + struct any_data *a = id->data; + struct any_cursor_extra_data *ed; + krb5_error_code ret; + + c->data = malloc (sizeof(struct any_cursor_extra_data)); + if(c->data == NULL){ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ed = (struct any_cursor_extra_data *)c->data; + ed->a = a; + ret = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor); + if (ret) { + free (c->data); + c->data = NULL; + return ret; + } + return 0; +} + +static krb5_error_code +any_next_entry (krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *cursor) +{ + krb5_error_code ret, ret2; + struct any_cursor_extra_data *ed; + + ed = (struct any_cursor_extra_data *)cursor->data; + do { + ret = krb5_kt_next_entry(context, ed->a->kt, entry, &ed->cursor); + if (ret == 0) + return 0; + else if (ret == KRB5_KT_END) { + ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor); + if (ret2) + return ret2; + while ((ed->a = ed->a->next) != NULL) { + ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor); + if (ret2 == 0) + break; + } + if (ed->a == NULL) { + krb5_clear_error_string (context); + return KRB5_KT_END; + } + } else + return ret; + } while (ret == KRB5_KT_END); + return ret; +} + +static krb5_error_code +any_end_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *cursor) +{ + krb5_error_code ret = 0; + struct any_cursor_extra_data *ed; + + ed = (struct any_cursor_extra_data *)cursor->data; + if (ed->a != NULL) + ret = krb5_kt_end_seq_get(context, ed->a->kt, &ed->cursor); + free (ed); + cursor->data = NULL; + return ret; +} + +static krb5_error_code +any_add_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct any_data *a = id->data; + krb5_error_code ret; + while(a != NULL) { + ret = krb5_kt_add_entry(context, a->kt, entry); + if(ret != 0 && ret != KRB5_KT_NOWRITE) { + krb5_set_error_string(context, "failed to add entry to %s", + a->name); + return ret; + } + a = a->next; + } + return 0; +} + +static krb5_error_code +any_remove_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct any_data *a = id->data; + krb5_error_code ret; + int found = 0; + while(a != NULL) { + ret = krb5_kt_remove_entry(context, a->kt, entry); + if(ret == 0) + found++; + else { + if(ret != KRB5_KT_NOWRITE && ret != KRB5_KT_NOTFOUND) { + krb5_set_error_string(context, "failed to remove entry from %s", + a->name); + return ret; + } + } + a = a->next; + } + if(!found) + return KRB5_KT_NOTFOUND; + return 0; +} + +const krb5_kt_ops krb5_any_ops = { + "ANY", + any_resolve, + any_get_name, + any_close, + NULL, /* get */ + any_start_seq_get, + any_next_entry, + any_end_seq_get, + any_add_entry, + any_remove_entry +}; diff --git a/source4/heimdal/lib/krb5/keytab_file.c b/source4/heimdal/lib/krb5/keytab_file.c new file mode 100644 index 0000000000..dca09ff6f3 --- /dev/null +++ b/source4/heimdal/lib/krb5/keytab_file.c @@ -0,0 +1,678 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keytab_file.c,v 1.18 2005/05/31 21:50:43 lha Exp $"); + +#define KRB5_KT_VNO_1 1 +#define KRB5_KT_VNO_2 2 +#define KRB5_KT_VNO KRB5_KT_VNO_2 + +#define KRB5_KT_FL_JAVA 1 + + +/* file operations -------------------------------------------- */ + +struct fkt_data { + char *filename; + int flags; +}; + +static krb5_error_code +krb5_kt_ret_data(krb5_context context, + krb5_storage *sp, + krb5_data *data) +{ + int ret; + int16_t size; + ret = krb5_ret_int16(sp, &size); + if(ret) + return ret; + data->length = size; + data->data = malloc(size); + if (data->data == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_storage_read(sp, data->data, size); + if(ret != size) + return (ret < 0)? errno : KRB5_KT_END; + return 0; +} + +static krb5_error_code +krb5_kt_ret_string(krb5_context context, + krb5_storage *sp, + heim_general_string *data) +{ + int ret; + int16_t size; + ret = krb5_ret_int16(sp, &size); + if(ret) + return ret; + *data = malloc(size + 1); + if (*data == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_storage_read(sp, *data, size); + (*data)[size] = '\0'; + if(ret != size) + return (ret < 0)? errno : KRB5_KT_END; + return 0; +} + +static krb5_error_code +krb5_kt_store_data(krb5_context context, + krb5_storage *sp, + krb5_data data) +{ + int ret; + ret = krb5_store_int16(sp, data.length); + if(ret < 0) + return ret; + ret = krb5_storage_write(sp, data.data, data.length); + if(ret != data.length){ + if(ret < 0) + return errno; + return KRB5_KT_END; + } + return 0; +} + +static krb5_error_code +krb5_kt_store_string(krb5_storage *sp, + heim_general_string data) +{ + int ret; + size_t len = strlen(data); + ret = krb5_store_int16(sp, len); + if(ret < 0) + return ret; + ret = krb5_storage_write(sp, data, len); + if(ret != len){ + if(ret < 0) + return errno; + return KRB5_KT_END; + } + return 0; +} + +static krb5_error_code +krb5_kt_ret_keyblock(krb5_context context, krb5_storage *sp, krb5_keyblock *p) +{ + int ret; + int16_t tmp; + + ret = krb5_ret_int16(sp, &tmp); /* keytype + etype */ + if(ret) return ret; + p->keytype = tmp; + ret = krb5_kt_ret_data(context, sp, &p->keyvalue); + return ret; +} + +static krb5_error_code +krb5_kt_store_keyblock(krb5_context context, + krb5_storage *sp, + krb5_keyblock *p) +{ + int ret; + + ret = krb5_store_int16(sp, p->keytype); /* keytype + etype */ + if(ret) return ret; + ret = krb5_kt_store_data(context, sp, p->keyvalue); + return ret; +} + + +static krb5_error_code +krb5_kt_ret_principal(krb5_context context, + krb5_storage *sp, + krb5_principal *princ) +{ + int i; + int ret; + krb5_principal p; + int16_t tmp; + + ALLOC(p, 1); + if(p == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + + ret = krb5_ret_int16(sp, &tmp); + if(ret) + return ret; + if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) + tmp--; + p->name.name_string.len = tmp; + ret = krb5_kt_ret_string(context, sp, &p->realm); + if(ret) + return ret; + p->name.name_string.val = calloc(p->name.name_string.len, + sizeof(*p->name.name_string.val)); + if(p->name.name_string.val == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + for(i = 0; i < p->name.name_string.len; i++){ + ret = krb5_kt_ret_string(context, sp, p->name.name_string.val + i); + if(ret) + return ret; + } + if (krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) + p->name.name_type = KRB5_NT_UNKNOWN; + else { + int32_t tmp32; + ret = krb5_ret_int32(sp, &tmp32); + p->name.name_type = tmp32; + if (ret) + return ret; + } + *princ = p; + return 0; +} + +static krb5_error_code +krb5_kt_store_principal(krb5_context context, + krb5_storage *sp, + krb5_principal p) +{ + int i; + int ret; + + if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) + ret = krb5_store_int16(sp, p->name.name_string.len + 1); + else + ret = krb5_store_int16(sp, p->name.name_string.len); + if(ret) return ret; + ret = krb5_kt_store_string(sp, p->realm); + if(ret) return ret; + for(i = 0; i < p->name.name_string.len; i++){ + ret = krb5_kt_store_string(sp, p->name.name_string.val[i]); + if(ret) + return ret; + } + if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) { + ret = krb5_store_int32(sp, p->name.name_type); + if(ret) + return ret; + } + + return 0; +} + +static krb5_error_code +fkt_resolve(krb5_context context, const char *name, krb5_keytab id) +{ + struct fkt_data *d; + + d = malloc(sizeof(*d)); + if(d == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->filename = strdup(name); + if(d->filename == NULL) { + free(d); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->flags = 0; + id->data = d; + return 0; +} + +static krb5_error_code +fkt_resolve_java14(krb5_context context, const char *name, krb5_keytab id) +{ + krb5_error_code ret; + + ret = fkt_resolve(context, name, id); + if (ret == 0) { + struct fkt_data *d = id->data; + d->flags |= KRB5_KT_FL_JAVA; + } + return ret; +} + +static krb5_error_code +fkt_close(krb5_context context, krb5_keytab id) +{ + struct fkt_data *d = id->data; + free(d->filename); + free(d); + return 0; +} + +static krb5_error_code +fkt_get_name(krb5_context context, + krb5_keytab id, + char *name, + size_t namesize) +{ + /* This function is XXX */ + struct fkt_data *d = id->data; + strlcpy(name, d->filename, namesize); + return 0; +} + +static void +storage_set_flags(krb5_context context, krb5_storage *sp, int vno) +{ + int flags = 0; + switch(vno) { + case KRB5_KT_VNO_1: + flags |= KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS; + flags |= KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE; + flags |= KRB5_STORAGE_HOST_BYTEORDER; + break; + case KRB5_KT_VNO_2: + break; + default: + krb5_warnx(context, + "storage_set_flags called with bad vno (%d)", vno); + } + krb5_storage_set_flags(sp, flags); +} + +static krb5_error_code +fkt_start_seq_get_int(krb5_context context, + krb5_keytab id, + int flags, + int exclusive, + krb5_kt_cursor *c) +{ + int8_t pvno, tag; + krb5_error_code ret; + struct fkt_data *d = id->data; + + c->fd = open (d->filename, flags); + if (c->fd < 0) { + ret = errno; + krb5_set_error_string(context, "%s: %s", d->filename, + strerror(ret)); + return ret; + } + ret = _krb5_xlock(context, c->fd, exclusive, d->filename); + if (ret) { + close(c->fd); + return ret; + } + c->sp = krb5_storage_from_fd(c->fd); + krb5_storage_set_eof_code(c->sp, KRB5_KT_END); + ret = krb5_ret_int8(c->sp, &pvno); + if(ret) { + krb5_storage_free(c->sp); + _krb5_xunlock(context, c->fd); + close(c->fd); + krb5_clear_error_string(context); + return ret; + } + if(pvno != 5) { + krb5_storage_free(c->sp); + _krb5_xunlock(context, c->fd); + close(c->fd); + krb5_clear_error_string (context); + return KRB5_KEYTAB_BADVNO; + } + ret = krb5_ret_int8(c->sp, &tag); + if (ret) { + krb5_storage_free(c->sp); + _krb5_xunlock(context, c->fd); + close(c->fd); + krb5_clear_error_string(context); + return ret; + } + id->version = tag; + storage_set_flags(context, c->sp, id->version); + return 0; +} + +static krb5_error_code +fkt_start_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *c) +{ + return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY, 0, c); +} + +static krb5_error_code +fkt_next_entry_int(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *cursor, + off_t *start, + off_t *end) +{ + int32_t len; + int ret; + int8_t tmp8; + int32_t tmp32; + off_t pos, curpos; + + pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); +loop: + ret = krb5_ret_int32(cursor->sp, &len); + if (ret) + return ret; + if(len < 0) { + pos = krb5_storage_seek(cursor->sp, -len, SEEK_CUR); + goto loop; + } + ret = krb5_kt_ret_principal (context, cursor->sp, &entry->principal); + if (ret) + goto out; + ret = krb5_ret_int32(cursor->sp, &tmp32); + entry->timestamp = tmp32; + if (ret) + goto out; + ret = krb5_ret_int8(cursor->sp, &tmp8); + if (ret) + goto out; + entry->vno = tmp8; + ret = krb5_kt_ret_keyblock (context, cursor->sp, &entry->keyblock); + if (ret) + goto out; + /* there might be a 32 bit kvno here + * if it's zero, assume that the 8bit one was right, + * otherwise trust the new value */ + curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); + if(len + 4 + pos - curpos == 4) { + ret = krb5_ret_int32(cursor->sp, &tmp32); + if (ret == 0 && tmp32 != 0) { + entry->vno = tmp32; + } + } + if(start) *start = pos; + if(end) *end = *start + 4 + len; + out: + krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET); + return ret; +} + +static krb5_error_code +fkt_next_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *cursor) +{ + return fkt_next_entry_int(context, id, entry, cursor, NULL, NULL); +} + +static krb5_error_code +fkt_end_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *cursor) +{ + krb5_storage_free(cursor->sp); + _krb5_xunlock(context, cursor->fd); + close(cursor->fd); + return 0; +} + +static krb5_error_code +fkt_setup_keytab(krb5_context context, + krb5_keytab id, + krb5_storage *sp) +{ + krb5_error_code ret; + ret = krb5_store_int8(sp, 5); + if(ret) + return ret; + if(id->version == 0) + id->version = KRB5_KT_VNO; + return krb5_store_int8 (sp, id->version); +} + +static krb5_error_code +fkt_add_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + int ret; + int fd; + krb5_storage *sp; + struct fkt_data *d = id->data; + krb5_data keytab; + int32_t len; + + fd = open (d->filename, O_RDWR | O_BINARY); + if (fd < 0) { + fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600); + if (fd < 0) { + ret = errno; + krb5_set_error_string(context, "open(%s): %s", d->filename, + strerror(ret)); + return ret; + } + ret = _krb5_xlock(context, fd, 1, d->filename); + if (ret) { + close(fd); + return ret; + } + sp = krb5_storage_from_fd(fd); + krb5_storage_set_eof_code(sp, KRB5_KT_END); + ret = fkt_setup_keytab(context, id, sp); + if(ret) { + goto out; + } + storage_set_flags(context, sp, id->version); + } else { + int8_t pvno, tag; + ret = _krb5_xlock(context, fd, 1, d->filename); + if (ret) { + close(fd); + return ret; + } + sp = krb5_storage_from_fd(fd); + krb5_storage_set_eof_code(sp, KRB5_KT_END); + ret = krb5_ret_int8(sp, &pvno); + if(ret) { + /* we probably have a zero byte file, so try to set it up + properly */ + ret = fkt_setup_keytab(context, id, sp); + if(ret) { + krb5_set_error_string(context, "%s: keytab is corrupted: %s", + d->filename, strerror(ret)); + goto out; + } + storage_set_flags(context, sp, id->version); + } else { + if(pvno != 5) { + ret = KRB5_KEYTAB_BADVNO; + krb5_set_error_string(context, "%s: %s", + d->filename, strerror(ret)); + goto out; + } + ret = krb5_ret_int8 (sp, &tag); + if (ret) { + krb5_set_error_string(context, "%s: reading tag: %s", + d->filename, strerror(ret)); + goto out; + } + id->version = tag; + storage_set_flags(context, sp, id->version); + } + } + + { + krb5_storage *emem; + emem = krb5_storage_emem(); + if(emem == NULL) { + ret = ENOMEM; + krb5_set_error_string (context, "malloc: out of memory"); + goto out; + } + ret = krb5_kt_store_principal(context, emem, entry->principal); + if(ret) { + krb5_storage_free(emem); + goto out; + } + ret = krb5_store_int32 (emem, entry->timestamp); + if(ret) { + krb5_storage_free(emem); + goto out; + } + ret = krb5_store_int8 (emem, entry->vno % 256); + if(ret) { + krb5_storage_free(emem); + goto out; + } + ret = krb5_kt_store_keyblock (context, emem, &entry->keyblock); + if(ret) { + krb5_storage_free(emem); + goto out; + } + if ((d->flags & KRB5_KT_FL_JAVA) == 0) { + ret = krb5_store_int32 (emem, entry->vno); + if (ret) { + krb5_storage_free(emem); + goto out; + } + } + + ret = krb5_storage_to_data(emem, &keytab); + krb5_storage_free(emem); + if(ret) + goto out; + } + + while(1) { + ret = krb5_ret_int32(sp, &len); + if(ret == KRB5_KT_END) { + len = keytab.length; + break; + } + if(len < 0) { + len = -len; + if(len >= keytab.length) { + krb5_storage_seek(sp, -4, SEEK_CUR); + break; + } + } + krb5_storage_seek(sp, len, SEEK_CUR); + } + ret = krb5_store_int32(sp, len); + if(krb5_storage_write(sp, keytab.data, keytab.length) < 0) + ret = errno; + memset(keytab.data, 0, keytab.length); + krb5_data_free(&keytab); + out: + krb5_storage_free(sp); + _krb5_xunlock(context, fd); + close(fd); + return ret; +} + +static krb5_error_code +fkt_remove_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + krb5_keytab_entry e; + krb5_kt_cursor cursor; + off_t pos_start, pos_end; + int found = 0; + krb5_error_code ret; + + ret = fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY, 1, &cursor); + if(ret != 0) + goto out; /* return other error here? */ + while(fkt_next_entry_int(context, id, &e, &cursor, + &pos_start, &pos_end) == 0) { + if(krb5_kt_compare(context, &e, entry->principal, + entry->vno, entry->keyblock.keytype)) { + int32_t len; + unsigned char buf[128]; + found = 1; + krb5_storage_seek(cursor.sp, pos_start, SEEK_SET); + len = pos_end - pos_start - 4; + krb5_store_int32(cursor.sp, -len); + memset(buf, 0, sizeof(buf)); + while(len > 0) { + krb5_storage_write(cursor.sp, buf, min(len, sizeof(buf))); + len -= min(len, sizeof(buf)); + } + } + krb5_kt_free_entry(context, &e); + } + krb5_kt_end_seq_get(context, id, &cursor); + out: + if (!found) { + krb5_clear_error_string (context); + return KRB5_KT_NOTFOUND; + } + return 0; +} + +const krb5_kt_ops krb5_fkt_ops = { + "FILE", + fkt_resolve, + fkt_get_name, + fkt_close, + NULL, /* get */ + fkt_start_seq_get, + fkt_next_entry, + fkt_end_seq_get, + fkt_add_entry, + fkt_remove_entry +}; + +const krb5_kt_ops krb5_wrfkt_ops = { + "WRFILE", + fkt_resolve, + fkt_get_name, + fkt_close, + NULL, /* get */ + fkt_start_seq_get, + fkt_next_entry, + fkt_end_seq_get, + fkt_add_entry, + fkt_remove_entry +}; + +const krb5_kt_ops krb5_javakt_ops = { + "JAVA14", + fkt_resolve_java14, + fkt_get_name, + fkt_close, + NULL, /* get */ + fkt_start_seq_get, + fkt_next_entry, + fkt_end_seq_get, + fkt_add_entry, + fkt_remove_entry +}; diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c new file mode 100644 index 0000000000..b53fa36a03 --- /dev/null +++ b/source4/heimdal/lib/krb5/keytab_keyfile.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keytab_keyfile.c,v 1.16 2005/01/08 22:57:18 lha Exp $"); + +/* afs keyfile operations --------------------------------------- */ + +/* + * Minimum tools to handle the AFS KeyFile. + * + * Format of the KeyFile is: + * {[ ] * numkeys} + * + * It just adds to the end of the keyfile, deleting isn't implemented. + * Use your favorite text/hex editor to delete keys. + * + */ + +#define AFS_SERVERTHISCELL "/usr/afs/etc/ThisCell" +#define AFS_SERVERMAGICKRBCONF "/usr/afs/etc/krb.conf" + +struct akf_data { + int num_entries; + char *filename; + char *cell; + char *realm; +}; + +/* + * set `d->cell' and `d->realm' + */ + +static int +get_cell_and_realm (krb5_context context, + struct akf_data *d) +{ + FILE *f; + char buf[BUFSIZ], *cp; + int ret; + + f = fopen (AFS_SERVERTHISCELL, "r"); + if (f == NULL) { + ret = errno; + krb5_set_error_string (context, "open %s: %s", AFS_SERVERTHISCELL, + strerror(ret)); + return ret; + } + if (fgets (buf, sizeof(buf), f) == NULL) { + fclose (f); + krb5_set_error_string (context, "no cell in %s", AFS_SERVERTHISCELL); + return EINVAL; + } + buf[strcspn(buf, "\n")] = '\0'; + fclose(f); + + d->cell = strdup (buf); + if (d->cell == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + + f = fopen (AFS_SERVERMAGICKRBCONF, "r"); + if (f != NULL) { + if (fgets (buf, sizeof(buf), f) == NULL) { + fclose (f); + krb5_set_error_string (context, "no realm in %s", + AFS_SERVERMAGICKRBCONF); + return EINVAL; + } + buf[strcspn(buf, "\n")] = '\0'; + fclose(f); + } + /* uppercase */ + for (cp = buf; *cp != '\0'; cp++) + *cp = toupper((unsigned char)*cp); + + d->realm = strdup (buf); + if (d->realm == NULL) { + free (d->cell); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + +/* + * init and get filename + */ + +static krb5_error_code +akf_resolve(krb5_context context, const char *name, krb5_keytab id) +{ + int ret; + struct akf_data *d = malloc(sizeof (struct akf_data)); + + if (d == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + + d->num_entries = 0; + ret = get_cell_and_realm (context, d); + if (ret) { + free (d); + return ret; + } + d->filename = strdup (name); + if (d->filename == NULL) { + free (d->cell); + free (d->realm); + free (d); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + id->data = d; + + return 0; +} + +/* + * cleanup + */ + +static krb5_error_code +akf_close(krb5_context context, krb5_keytab id) +{ + struct akf_data *d = id->data; + + free (d->filename); + free (d->cell); + free (d); + return 0; +} + +/* + * Return filename + */ + +static krb5_error_code +akf_get_name(krb5_context context, + krb5_keytab id, + char *name, + size_t name_sz) +{ + struct akf_data *d = id->data; + + strlcpy (name, d->filename, name_sz); + return 0; +} + +/* + * Init + */ + +static krb5_error_code +akf_start_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *c) +{ + int32_t ret; + struct akf_data *d = id->data; + + c->fd = open (d->filename, O_RDONLY|O_BINARY, 0600); + if (c->fd < 0) { + ret = errno; + krb5_set_error_string(context, "open(%s): %s", d->filename, + strerror(ret)); + return ret; + } + + c->sp = krb5_storage_from_fd(c->fd); + ret = krb5_ret_int32(c->sp, &d->num_entries); + if(ret) { + krb5_storage_free(c->sp); + close(c->fd); + krb5_clear_error_string (context); + if(ret == KRB5_KT_END) + return KRB5_KT_NOTFOUND; + return ret; + } + + return 0; +} + +static krb5_error_code +akf_next_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *cursor) +{ + struct akf_data *d = id->data; + int32_t kvno; + off_t pos; + int ret; + + pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); + + if ((pos - 4) / (4 + 8) >= d->num_entries) + return KRB5_KT_END; + + ret = krb5_make_principal (context, &entry->principal, + d->realm, "afs", d->cell, NULL); + if (ret) + goto out; + + ret = krb5_ret_int32(cursor->sp, &kvno); + if (ret) { + krb5_free_principal (context, entry->principal); + goto out; + } + + entry->vno = kvno; + + entry->keyblock.keytype = ETYPE_DES_CBC_MD5; + entry->keyblock.keyvalue.length = 8; + entry->keyblock.keyvalue.data = malloc (8); + if (entry->keyblock.keyvalue.data == NULL) { + krb5_free_principal (context, entry->principal); + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + + ret = krb5_storage_read(cursor->sp, entry->keyblock.keyvalue.data, 8); + if(ret != 8) + ret = (ret < 0) ? errno : KRB5_KT_END; + else + ret = 0; + + entry->timestamp = time(NULL); + + out: + krb5_storage_seek(cursor->sp, pos + 4 + 8, SEEK_SET); + return ret; +} + +static krb5_error_code +akf_end_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *cursor) +{ + krb5_storage_free(cursor->sp); + close(cursor->fd); + return 0; +} + +static krb5_error_code +akf_add_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct akf_data *d = id->data; + int fd, created = 0; + krb5_error_code ret; + int32_t len; + krb5_storage *sp; + + + if (entry->keyblock.keyvalue.length != 8 + || entry->keyblock.keytype != ETYPE_DES_CBC_MD5) + return 0; + + fd = open (d->filename, O_RDWR | O_BINARY); + if (fd < 0) { + fd = open (d->filename, + O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600); + if (fd < 0) { + ret = errno; + krb5_set_error_string(context, "open(%s): %s", d->filename, + strerror(ret)); + return ret; + } + created = 1; + } + + sp = krb5_storage_from_fd(fd); + if(sp == NULL) { + close(fd); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + if (created) + len = 0; + else { + if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) { + ret = errno; + krb5_storage_free(sp); + close(fd); + krb5_set_error_string (context, "seek: %s", strerror(ret)); + return ret; + } + + ret = krb5_ret_int32(sp, &len); + if(ret) { + krb5_storage_free(sp); + close(fd); + return ret; + } + } + len++; + + if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) { + ret = errno; + krb5_storage_free(sp); + close(fd); + krb5_set_error_string (context, "seek: %s", strerror(ret)); + return ret; + } + + ret = krb5_store_int32(sp, len); + if(ret) { + krb5_storage_free(sp); + close(fd); + return ret; + } + + + if(krb5_storage_seek(sp, (len - 1) * (8 + 4), SEEK_CUR) < 0) { + ret = errno; + krb5_storage_free(sp); + close(fd); + krb5_set_error_string (context, "seek: %s", strerror(ret)); + return ret; + } + + ret = krb5_store_int32(sp, entry->vno); + if(ret) { + krb5_storage_free(sp); + close(fd); + return ret; + } + ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data, + entry->keyblock.keyvalue.length); + if(ret != entry->keyblock.keyvalue.length) { + krb5_storage_free(sp); + close(fd); + if(ret < 0) + return errno; + return ENOTTY; + } + krb5_storage_free(sp); + close (fd); + return 0; +} + +const krb5_kt_ops krb5_akf_ops = { + "AFSKEYFILE", + akf_resolve, + akf_get_name, + akf_close, + NULL, /* get */ + akf_start_seq_get, + akf_next_entry, + akf_end_seq_get, + akf_add_entry, + NULL /* remove */ +}; diff --git a/source4/heimdal/lib/krb5/keytab_krb4.c b/source4/heimdal/lib/krb5/keytab_krb4.c new file mode 100644 index 0000000000..1a83faca57 --- /dev/null +++ b/source4/heimdal/lib/krb5/keytab_krb4.c @@ -0,0 +1,443 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keytab_krb4.c,v 1.13 2005/05/19 04:13:18 lha Exp $"); + +struct krb4_kt_data { + char *filename; +}; + +static krb5_error_code +krb4_kt_resolve(krb5_context context, const char *name, krb5_keytab id) +{ + struct krb4_kt_data *d; + + d = malloc (sizeof(*d)); + if (d == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->filename = strdup (name); + if (d->filename == NULL) { + free(d); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + id->data = d; + return 0; +} + +static krb5_error_code +krb4_kt_get_name (krb5_context context, + krb5_keytab id, + char *name, + size_t name_sz) +{ + struct krb4_kt_data *d = id->data; + + strlcpy (name, d->filename, name_sz); + return 0; +} + +static krb5_error_code +krb4_kt_close (krb5_context context, + krb5_keytab id) +{ + struct krb4_kt_data *d = id->data; + + free (d->filename); + free (d); + return 0; +} + +struct krb4_cursor_extra_data { + krb5_keytab_entry entry; + int num; +}; + +static int +open_flock(const char *filename, int flags, int mode) +{ + int lock_mode; + int tries = 0; + int fd = open(filename, flags, mode); + if(fd < 0) + return fd; + if((flags & O_ACCMODE) == O_RDONLY) + lock_mode = LOCK_SH | LOCK_NB; + else + lock_mode = LOCK_EX | LOCK_NB; + while(flock(fd, lock_mode) < 0) { + if(++tries < 5) { + sleep(1); + } else { + close(fd); + return -1; + } + } + return fd; +} + + + +static krb5_error_code +krb4_kt_start_seq_get_int (krb5_context context, + krb5_keytab id, + int flags, + krb5_kt_cursor *c) +{ + struct krb4_kt_data *d = id->data; + struct krb4_cursor_extra_data *ed; + int ret; + + ed = malloc (sizeof(*ed)); + if (ed == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ed->entry.principal = NULL; + ed->num = -1; + c->data = ed; + c->fd = open_flock (d->filename, flags, 0); + if (c->fd < 0) { + ret = errno; + free (ed); + krb5_set_error_string(context, "open(%s): %s", d->filename, + strerror(ret)); + return ret; + } + c->sp = krb5_storage_from_fd(c->fd); + krb5_storage_set_eof_code(c->sp, KRB5_KT_END); + return 0; +} + +static krb5_error_code +krb4_kt_start_seq_get (krb5_context context, + krb5_keytab id, + krb5_kt_cursor *c) +{ + return krb4_kt_start_seq_get_int (context, id, O_BINARY | O_RDONLY, c); +} + +static krb5_error_code +read_v4_entry (krb5_context context, + struct krb4_kt_data *d, + krb5_kt_cursor *c, + struct krb4_cursor_extra_data *ed) +{ + unsigned char des_key[8]; + krb5_error_code ret; + char *service, *instance, *realm; + int8_t kvno; + + ret = krb5_ret_stringz(c->sp, &service); + if (ret) + return ret; + ret = krb5_ret_stringz(c->sp, &instance); + if (ret) { + free (service); + return ret; + } + ret = krb5_ret_stringz(c->sp, &realm); + if (ret) { + free (service); + free (instance); + return ret; + } + ret = krb5_425_conv_principal (context, service, instance, realm, + &ed->entry.principal); + free (service); + free (instance); + free (realm); + if (ret) + return ret; + ret = krb5_ret_int8(c->sp, &kvno); + if (ret) { + krb5_free_principal (context, ed->entry.principal); + return ret; + } + ret = krb5_storage_read(c->sp, des_key, sizeof(des_key)); + if (ret < 0) { + krb5_free_principal(context, ed->entry.principal); + return ret; + } + if (ret < 8) { + krb5_free_principal(context, ed->entry.principal); + return EINVAL; + } + ed->entry.vno = kvno; + ret = krb5_data_copy (&ed->entry.keyblock.keyvalue, + des_key, sizeof(des_key)); + if (ret) + return ret; + ed->entry.timestamp = time(NULL); + ed->num = 0; + return 0; +} + +static krb5_error_code +krb4_kt_next_entry (krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *c) +{ + krb5_error_code ret; + struct krb4_kt_data *d = id->data; + struct krb4_cursor_extra_data *ed = c->data; + const krb5_enctype keytypes[] = {ETYPE_DES_CBC_MD5, + ETYPE_DES_CBC_MD4, + ETYPE_DES_CBC_CRC}; + + if (ed->num == -1) { + ret = read_v4_entry (context, d, c, ed); + if (ret) + return ret; + } + ret = krb5_kt_copy_entry_contents (context, + &ed->entry, + entry); + if (ret) + return ret; + entry->keyblock.keytype = keytypes[ed->num]; + if (++ed->num == 3) { + krb5_kt_free_entry (context, &ed->entry); + ed->num = -1; + } + return 0; +} + +static krb5_error_code +krb4_kt_end_seq_get (krb5_context context, + krb5_keytab id, + krb5_kt_cursor *c) +{ + struct krb4_cursor_extra_data *ed = c->data; + + krb5_storage_free (c->sp); + if (ed->num != -1) + krb5_kt_free_entry (context, &ed->entry); + free (c->data); + close (c->fd); + return 0; +} + +static krb5_error_code +krb4_store_keytab_entry(krb5_context context, + krb5_keytab_entry *entry, + krb5_storage *sp) +{ + krb5_error_code ret; +#define ANAME_SZ 40 +#define INST_SZ 40 +#define REALM_SZ 40 + char service[ANAME_SZ]; + char instance[INST_SZ]; + char realm[REALM_SZ]; + ret = krb5_524_conv_principal (context, entry->principal, + service, instance, realm); + if (ret) + return ret; + if (entry->keyblock.keyvalue.length == 8 + && entry->keyblock.keytype == ETYPE_DES_CBC_MD5) { + ret = krb5_store_stringz(sp, service); + ret = krb5_store_stringz(sp, instance); + ret = krb5_store_stringz(sp, realm); + ret = krb5_store_int8(sp, entry->vno); + ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data, 8); + } + return 0; +} + +static krb5_error_code +krb4_kt_add_entry (krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct krb4_kt_data *d = id->data; + krb5_storage *sp; + krb5_error_code ret; + int fd; + + fd = open_flock (d->filename, O_WRONLY | O_APPEND | O_BINARY, 0); + if (fd < 0) { + fd = open_flock (d->filename, + O_WRONLY | O_APPEND | O_BINARY | O_CREAT, 0600); + if (fd < 0) { + ret = errno; + krb5_set_error_string(context, "open(%s): %s", d->filename, + strerror(ret)); + return ret; + } + } + sp = krb5_storage_from_fd(fd); + krb5_storage_set_eof_code(sp, KRB5_KT_END); + if(sp == NULL) { + close(fd); + return ENOMEM; + } + ret = krb4_store_keytab_entry(context, entry, sp); + krb5_storage_free(sp); + if(close (fd) < 0) + return errno; + return ret; +} + +static krb5_error_code +krb4_kt_remove_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct krb4_kt_data *d = id->data; + krb5_error_code ret; + krb5_keytab_entry e; + krb5_kt_cursor cursor; + krb5_storage *sp; + int remove_flag = 0; + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = krb5_kt_start_seq_get(context, id, &cursor); + if (ret) { + krb5_storage_free(sp); + return ret; + } + while(krb5_kt_next_entry(context, id, &e, &cursor) == 0) { + if(!krb5_kt_compare(context, &e, entry->principal, + entry->vno, entry->keyblock.keytype)) { + ret = krb4_store_keytab_entry(context, &e, sp); + if(ret) { + krb5_kt_free_entry(context, &e); + krb5_storage_free(sp); + return ret; + } + } else + remove_flag = 1; + krb5_kt_free_entry(context, &e); + } + krb5_kt_end_seq_get(context, id, &cursor); + if(remove_flag) { + int fd; + unsigned char buf[1024]; + ssize_t n; + krb5_data data; + struct stat st; + + krb5_storage_to_data(sp, &data); + krb5_storage_free(sp); + + fd = open_flock (d->filename, O_RDWR | O_BINARY, 0); + if(fd < 0) { + memset(data.data, 0, data.length); + krb5_data_free(&data); + if(errno == EACCES || errno == EROFS) + return KRB5_KT_NOWRITE; + return errno; + } + + if(write(fd, data.data, data.length) != data.length) { + memset(data.data, 0, data.length); + krb5_data_free(&data); + close(fd); + krb5_set_error_string(context, "failed writing to \"%s\"", d->filename); + return errno; + } + memset(data.data, 0, data.length); + if(fstat(fd, &st) < 0) { + krb5_data_free(&data); + close(fd); + krb5_set_error_string(context, "failed getting size of \"%s\"", d->filename); + return errno; + } + st.st_size -= data.length; + memset(buf, 0, sizeof(buf)); + while(st.st_size > 0) { + n = min(st.st_size, sizeof(buf)); + n = write(fd, buf, n); + if(n <= 0) { + krb5_data_free(&data); + close(fd); + krb5_set_error_string(context, "failed writing to \"%s\"", d->filename); + return errno; + + } + st.st_size -= n; + } + if(ftruncate(fd, data.length) < 0) { + krb5_data_free(&data); + close(fd); + krb5_set_error_string(context, "failed truncating \"%s\"", d->filename); + return errno; + } + krb5_data_free(&data); + if(close(fd) < 0) { + krb5_set_error_string(context, "error closing \"%s\"", d->filename); + return errno; + } + return 0; + } else { + krb5_storage_free(sp); + return KRB5_KT_NOTFOUND; + } +} + + +const krb5_kt_ops krb4_fkt_ops = { + "krb4", + krb4_kt_resolve, + krb4_kt_get_name, + krb4_kt_close, + NULL, /* get */ + krb4_kt_start_seq_get, + krb4_kt_next_entry, + krb4_kt_end_seq_get, + krb4_kt_add_entry, /* add_entry */ + krb4_kt_remove_entry /* remove_entry */ +}; + +const krb5_kt_ops krb5_srvtab_fkt_ops = { + "SRVTAB", + krb4_kt_resolve, + krb4_kt_get_name, + krb4_kt_close, + NULL, /* get */ + krb4_kt_start_seq_get, + krb4_kt_next_entry, + krb4_kt_end_seq_get, + krb4_kt_add_entry, /* add_entry */ + krb4_kt_remove_entry /* remove_entry */ +}; diff --git a/source4/heimdal/lib/krb5/keytab_memory.c b/source4/heimdal/lib/krb5/keytab_memory.c new file mode 100644 index 0000000000..3dca5154e3 --- /dev/null +++ b/source4/heimdal/lib/krb5/keytab_memory.c @@ -0,0 +1,229 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: keytab_memory.c,v 1.6 2005/05/18 04:44:40 lha Exp $"); + +/* memory operations -------------------------------------------- */ + +struct mkt_data { + krb5_keytab_entry *entries; + int num_entries; +}; + +static krb5_error_code +mkt_resolve(krb5_context context, const char *name, krb5_keytab id) +{ + struct mkt_data *d; + d = malloc(sizeof(*d)); + if(d == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->entries = NULL; + d->num_entries = 0; + id->data = d; + return 0; +} + +static krb5_error_code +mkt_close(krb5_context context, krb5_keytab id) +{ + struct mkt_data *d = id->data; + int i; + for(i = 0; i < d->num_entries; i++) + krb5_kt_free_entry(context, &d->entries[i]); + free(d->entries); + free(d); + return 0; +} + +static krb5_error_code +mkt_get_name(krb5_context context, + krb5_keytab id, + char *name, + size_t namesize) +{ + strlcpy(name, "", namesize); + return 0; +} + +static krb5_error_code +mkt_start_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *c) +{ + /* XXX */ + c->fd = 0; + return 0; +} + +static krb5_error_code +mkt_next_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry, + krb5_kt_cursor *c) +{ + struct mkt_data *d = id->data; + if(c->fd >= d->num_entries) + return KRB5_KT_END; + return krb5_kt_copy_entry_contents(context, &d->entries[c->fd++], entry); +} + +static krb5_error_code +mkt_end_seq_get(krb5_context context, + krb5_keytab id, + krb5_kt_cursor *cursor) +{ + return 0; +} + +static krb5_error_code +mkt_add_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct mkt_data *d = id->data; + krb5_keytab_entry *tmp; + tmp = realloc(d->entries, (d->num_entries + 1) * sizeof(*d->entries)); + if(tmp == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->entries = tmp; + return krb5_kt_copy_entry_contents(context, entry, + &d->entries[d->num_entries++]); +} + +static krb5_error_code +mkt_remove_entry(krb5_context context, + krb5_keytab id, + krb5_keytab_entry *entry) +{ + struct mkt_data *d = id->data; + krb5_keytab_entry *e, *end; + int found = 0; + + if (d->num_entries == 0) { + krb5_clear_error_string(context); + return KRB5_KT_NOTFOUND; + } + + /* do this backwards to minimize copying */ + for(end = d->entries + d->num_entries, e = end - 1; e >= d->entries; e--) { + if(krb5_kt_compare(context, e, entry->principal, + entry->vno, entry->keyblock.keytype)) { + krb5_kt_free_entry(context, e); + memmove(e, e + 1, (end - e - 1) * sizeof(*e)); + memset(end - 1, 0, sizeof(*end)); + d->num_entries--; + end--; + found = 1; + } + } + if (!found) { + krb5_clear_error_string (context); + return KRB5_KT_NOTFOUND; + } + e = realloc(d->entries, d->num_entries * sizeof(*d->entries)); + if(e != NULL) + d->entries = e; + return 0; +} + +const krb5_kt_ops krb5_mkt_ops = { + "MEMORY", + mkt_resolve, + mkt_get_name, + mkt_close, + NULL, /* get */ + mkt_start_seq_get, + mkt_next_entry, + mkt_end_seq_get, + mkt_add_entry, + mkt_remove_entry +}; + +static krb5_error_code +mktw_get_entry(krb5_context context, + krb5_keytab id, + krb5_const_principal principal, + krb5_kvno kvno, + krb5_enctype enctype, + krb5_keytab_entry *entry) +{ + krb5_keytab_entry tmp; + krb5_error_code ret; + krb5_kt_cursor cursor; + + ret = krb5_kt_start_seq_get (context, id, &cursor); + if (ret) + return KRB5_KT_NOTFOUND; /* XXX i.e. file not found */ + + entry->vno = 0; + while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) { + if (krb5_kt_compare(context, &tmp, NULL, 0, enctype)) { + if (kvno == tmp.vno) { + krb5_kt_copy_entry_contents (context, &tmp, entry); + krb5_kt_free_entry (context, &tmp); + krb5_kt_end_seq_get(context, id, &cursor); + return 0; + } else if (kvno == 0 && tmp.vno > entry->vno) { + if (entry->vno) + krb5_kt_free_entry (context, entry); + krb5_kt_copy_entry_contents (context, &tmp, entry); + } + } + krb5_kt_free_entry(context, &tmp); + } + krb5_kt_end_seq_get (context, id, &cursor); + if (entry->vno) { + return 0; + } else { + return KRB5_KT_NOTFOUND; + } +}; + +const krb5_kt_ops krb5_mktw_ops = { + "MEMORY_WILDCARD", + mkt_resolve, + mkt_get_name, + mkt_close, + mktw_get_entry, /* get */ + mkt_start_seq_get, + mkt_next_entry, + mkt_end_seq_get, + mkt_add_entry, + mkt_remove_entry +}; diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h new file mode 100644 index 0000000000..e59cab8ca7 --- /dev/null +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -0,0 +1,358 @@ +/* This is a generated file */ +#ifndef __krb5_private_h__ +#define __krb5_private_h__ + +#include + +#ifndef KRB5_LIB_FUNCTION +#if defined(_WIN32) +#define KRB5_LIB_FUNCTION _stdcall +#else +#define KRB5_LIB_FUNCTION +#endif +#endif + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_PKCS5_PBKDF2 ( + krb5_context /*context*/, + krb5_cksumtype /*cktype*/, + krb5_data /*password*/, + krb5_salt /*salt*/, + u_int32_t /*iter*/, + krb5_keytype /*type*/, + krb5_keyblock */*key*/); + +void KRB5_LIB_FUNCTION +_krb5_aes_cts_encrypt ( + const unsigned char */*in*/, + unsigned char */*out*/, + size_t /*len*/, + const void */*aes_key*/, + unsigned char */*ivec*/, + const int /*encryptp*/); + +void +_krb5_crc_init_table (void); + +u_int32_t +_krb5_crc_update ( + const char */*p*/, + size_t /*len*/, + u_int32_t /*res*/); + +krb5_error_code +_krb5_expand_default_cc_name ( + krb5_context /*context*/, + const char */*str*/, + char **/*res*/); + +int +_krb5_extract_ticket ( + krb5_context /*context*/, + krb5_kdc_rep */*rep*/, + krb5_creds */*creds*/, + krb5_keyblock */*key*/, + krb5_const_pointer /*keyseed*/, + krb5_key_usage /*key_usage*/, + krb5_addresses */*addrs*/, + unsigned /*nonce*/, + krb5_boolean /*allow_server_mismatch*/, + krb5_boolean /*ignore_cname*/, + krb5_decrypt_proc /*decrypt_proc*/, + krb5_const_pointer /*decryptarg*/); + +krb5_error_code +_krb5_get_default_principal_local ( + krb5_context /*context*/, + krb5_principal */*princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_get_host_realm_int ( + krb5_context /*context*/, + const char */*host*/, + krb5_boolean /*use_dns*/, + krb5_realm **/*realms*/); + +krb5_error_code +_krb5_get_init_creds_opt_copy ( + krb5_context /*context*/, + const krb5_get_init_creds_opt */*in*/, + krb5_get_init_creds_opt **/*out*/); + +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_free_pkinit (krb5_get_init_creds_opt */*opt*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +_krb5_get_int ( + void */*buffer*/, + unsigned long */*value*/, + size_t /*size*/); + +krb5_error_code +_krb5_get_krbtgt ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_realm /*realm*/, + krb5_creds **/*cred*/); + +krb5_error_code +_krb5_kcm_chmod ( + krb5_context /*context*/, + krb5_ccache /*id*/, + u_int16_t /*mode*/); + +krb5_error_code +_krb5_kcm_chown ( + krb5_context /*context*/, + krb5_ccache /*id*/, + u_int32_t /*uid*/, + u_int32_t /*gid*/); + +krb5_error_code +_krb5_kcm_get_initial_ticket ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_principal /*server*/, + krb5_keyblock */*key*/); + +krb5_error_code +_krb5_kcm_get_ticket ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_kdc_flags /*flags*/, + krb5_enctype /*enctype*/, + krb5_principal /*server*/); + +krb5_boolean +_krb5_kcm_is_running (krb5_context /*context*/); + +krb5_error_code +_krb5_kcm_noop ( + krb5_context /*context*/, + krb5_ccache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_cr_err_reply ( + krb5_context /*context*/, + const char */*name*/, + const char */*inst*/, + const char */*realm*/, + u_int32_t /*time_ws*/, + u_int32_t /*e*/, + const char */*e_string*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_create_auth_reply ( + krb5_context /*context*/, + const char */*pname*/, + const char */*pinst*/, + const char */*prealm*/, + int32_t /*time_ws*/, + int /*n*/, + u_int32_t /*x_date*/, + unsigned char /*kvno*/, + const krb5_data */*cipher*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_create_ciph ( + krb5_context /*context*/, + const krb5_keyblock */*session*/, + const char */*service*/, + const char */*instance*/, + const char */*realm*/, + u_int32_t /*life*/, + unsigned char /*kvno*/, + const krb5_data */*ticket*/, + u_int32_t /*kdc_time*/, + const krb5_keyblock */*key*/, + krb5_data */*enc_data*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_create_ticket ( + krb5_context /*context*/, + unsigned char /*flags*/, + const char */*pname*/, + const char */*pinstance*/, + const char */*prealm*/, + int32_t /*paddress*/, + const krb5_keyblock */*session*/, + int16_t /*life*/, + int32_t /*life_sec*/, + const char */*sname*/, + const char */*sinstance*/, + const krb5_keyblock */*key*/, + krb5_data */*enc_data*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_decomp_ticket ( + krb5_context /*context*/, + const krb5_data */*enc_ticket*/, + const krb5_keyblock */*key*/, + const char */*local_realm*/, + char **/*sname*/, + char **/*sinstance*/, + struct _krb5_krb_auth_data */*ad*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_dest_tkt ( + krb5_context /*context*/, + const char */*tkfile*/); + +void KRB5_LIB_FUNCTION +_krb5_krb_free_auth_data ( + krb5_context /*context*/, + struct _krb5_krb_auth_data */*ad*/); + +time_t KRB5_LIB_FUNCTION +_krb5_krb_life_to_time ( + int /*start*/, + int /*life_*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_rd_req ( + krb5_context /*context*/, + krb5_data */*authent*/, + const char */*service*/, + const char */*instance*/, + const char */*local_realm*/, + int32_t /*from_addr*/, + const krb5_keyblock */*key*/, + struct _krb5_krb_auth_data */*ad*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_tf_setup ( + krb5_context /*context*/, + struct credentials */*v4creds*/, + const char */*tkfile*/, + int /*append*/); + +int KRB5_LIB_FUNCTION +_krb5_krb_time_to_life ( + time_t /*start*/, + time_t /*end*/); + +krb5_error_code +_krb5_mk_req_internal ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_flags /*ap_req_options*/, + krb5_data */*in_data*/, + krb5_creds */*in_creds*/, + krb5_data */*outbuf*/, + krb5_key_usage /*checksum_usage*/, + krb5_key_usage /*encrypt_usage*/); + +void KRB5_LIB_FUNCTION +_krb5_n_fold ( + const void */*str*/, + size_t /*len*/, + void */*key*/, + size_t /*size*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_oid_to_enctype ( + krb5_context /*context*/, + const heim_oid */*oid*/, + krb5_enctype */*etype*/); + +void KRB5_LIB_FUNCTION +_krb5_pk_cert_free (struct krb5_pk_cert */*cert*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_create_sign ( + krb5_context /*context*/, + const heim_oid */*eContentType*/, + krb5_data */*eContent*/, + struct krb5_pk_identity */*id*/, + krb5_data */*sd_data*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_load_openssl_id ( + krb5_context /*context*/, + struct krb5_pk_identity **/*ret_id*/, + const char */*user_id*/, + const char */*x509_anchors*/, + krb5_prompter_fct /*prompter*/, + void */*prompter_data*/, + char */*password*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_mk_ContentInfo ( + krb5_context /*context*/, + const krb5_data */*buf*/, + const heim_oid */*oid*/, + struct ContentInfo */*content_info*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_mk_padata ( + krb5_context /*context*/, + void */*c*/, + const KDC_REQ_BODY */*req_body*/, + unsigned /*nonce*/, + METHOD_DATA */*md*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_rd_pa_reply ( + krb5_context /*context*/, + void */*c*/, + krb5_enctype /*etype*/, + unsigned /*nonce*/, + PA_DATA */*pa*/, + krb5_keyblock **/*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_verify_sign ( + krb5_context /*context*/, + const char */*data*/, + size_t /*length*/, + struct krb5_pk_identity */*id*/, + heim_oid */*contentType*/, + krb5_data */*content*/, + struct krb5_pk_cert **/*signer*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_principal2principalname ( + PrincipalName */*p*/, + const krb5_principal /*from*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_principalname2krb5_principal ( + krb5_principal */*principal*/, + const PrincipalName /*from*/, + const Realm /*realm*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +_krb5_put_int ( + void */*buffer*/, + unsigned long /*value*/, + size_t /*size*/); + +int +_krb5_send_and_recv_tcp ( + int /*fd*/, + time_t /*tmout*/, + const krb5_data */*req*/, + krb5_data */*rep*/); + +int +_krb5_xlock ( + krb5_context /*context*/, + int /*fd*/, + krb5_boolean /*exclusive*/, + const char */*filename*/); + +int +_krb5_xunlock ( + krb5_context /*context*/, + int /*fd*/); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_rd_rep_type(krb5_context context, + krb5_auth_context auth_context, + const krb5_data *inbuf, + krb5_ap_rep_enc_part **repl, + krb5_boolean dce_style_response); + +#endif /* __krb5_private_h__ */ diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h new file mode 100644 index 0000000000..cee8a02419 --- /dev/null +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -0,0 +1,3407 @@ +/* This is a generated file */ +#ifndef __krb5_protos_h__ +#define __krb5_protos_h__ + +#include + +#if !defined(__GNUC__) && !defined(__attribute__) +#define __attribute__(x) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef KRB5_LIB_FUNCTION +#if defined(_WIN32) +#define KRB5_LIB_FUNCTION _stdcall +#else +#define KRB5_LIB_FUNCTION +#endif +#endif + +krb5_error_code KRB5_LIB_FUNCTION +krb524_convert_creds_kdc ( + krb5_context /*context*/, + krb5_creds */*in_cred*/, + struct credentials */*v4creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb524_convert_creds_kdc_ccache ( + krb5_context /*context*/, + krb5_ccache /*ccache*/, + krb5_creds */*in_cred*/, + struct credentials */*v4creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_425_conv_principal ( + krb5_context /*context*/, + const char */*name*/, + const char */*instance*/, + const char */*realm*/, + krb5_principal */*princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_425_conv_principal_ext ( + krb5_context /*context*/, + const char */*name*/, + const char */*instance*/, + const char */*realm*/, + krb5_boolean (*/*func*/)(krb5_context, krb5_principal), + krb5_boolean /*resolve*/, + krb5_principal */*principal*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_425_conv_principal_ext2 ( + krb5_context /*context*/, + const char */*name*/, + const char */*instance*/, + const char */*realm*/, + krb5_boolean (*/*func*/)(krb5_context, void *, krb5_principal), + void */*funcctx*/, + krb5_boolean /*resolve*/, + krb5_principal */*princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_524_conv_principal ( + krb5_context /*context*/, + const krb5_principal /*principal*/, + char */*name*/, + char */*instance*/, + char */*realm*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_abort ( + krb5_context /*context*/, + krb5_error_code /*code*/, + const char */*fmt*/, + ...) + __attribute__ ((noreturn, format (printf, 3, 4))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_abortx ( + krb5_context /*context*/, + const char */*fmt*/, + ...) + __attribute__ ((noreturn, format (printf, 2, 3))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_acl_match_file ( + krb5_context /*context*/, + const char */*file*/, + const char */*format*/, + ...); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_acl_match_string ( + krb5_context /*context*/, + const char */*string*/, + const char */*format*/, + ...); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_add_et_list ( + krb5_context /*context*/, + void (*/*func*/)(struct et_list **)); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_add_extra_addresses ( + krb5_context /*context*/, + krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_add_ignore_addresses ( + krb5_context /*context*/, + krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_addlog_dest ( + krb5_context /*context*/, + krb5_log_facility */*f*/, + const char */*orig*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_addlog_func ( + krb5_context /*context*/, + krb5_log_facility */*fac*/, + int /*min*/, + int /*max*/, + krb5_log_log_func_t /*log_func*/, + krb5_log_close_func_t /*close_func*/, + void */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_addr2sockaddr ( + krb5_context /*context*/, + const krb5_address */*addr*/, + struct sockaddr */*sa*/, + krb5_socklen_t */*sa_size*/, + int /*port*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_address_compare ( + krb5_context /*context*/, + const krb5_address */*addr1*/, + const krb5_address */*addr2*/); + +int KRB5_LIB_FUNCTION +krb5_address_order ( + krb5_context /*context*/, + const krb5_address */*addr1*/, + const krb5_address */*addr2*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_address_prefixlen_boundary ( + krb5_context /*context*/, + const krb5_address */*inaddr*/, + unsigned long /*prefixlen*/, + krb5_address */*low*/, + krb5_address */*high*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_address_search ( + krb5_context /*context*/, + const krb5_address */*addr*/, + const krb5_addresses */*addrlist*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_aname_to_localname ( + krb5_context /*context*/, + krb5_const_principal /*aname*/, + size_t /*lnsize*/, + char */*lname*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_anyaddr ( + krb5_context /*context*/, + int /*af*/, + struct sockaddr */*sa*/, + krb5_socklen_t */*sa_size*/, + int /*port*/); + +void KRB5_LIB_FUNCTION +krb5_appdefault_boolean ( + krb5_context /*context*/, + const char */*appname*/, + krb5_const_realm /*realm*/, + const char */*option*/, + krb5_boolean /*def_val*/, + krb5_boolean */*ret_val*/); + +void KRB5_LIB_FUNCTION +krb5_appdefault_string ( + krb5_context /*context*/, + const char */*appname*/, + krb5_const_realm /*realm*/, + const char */*option*/, + const char */*def_val*/, + char **/*ret_val*/); + +void KRB5_LIB_FUNCTION +krb5_appdefault_time ( + krb5_context /*context*/, + const char */*appname*/, + krb5_const_realm /*realm*/, + const char */*option*/, + time_t /*def_val*/, + time_t */*ret_val*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_append_addresses ( + krb5_context /*context*/, + krb5_addresses */*dest*/, + const krb5_addresses */*source*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_addflags ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t /*addflags*/, + int32_t */*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_free ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_genaddrs ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int /*fd*/, + int /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_generatelocalsubkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getaddrs ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_address **/*local_addr*/, + krb5_address **/*remote_addr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getauthenticator ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_authenticator */*authenticator*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getcksumtype ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_cksumtype */*cksumtype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getflags ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t */*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock **/*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getkeytype ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keytype */*keytype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getlocalseqnumber ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t */*seqnumber*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getlocalsubkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock **/*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getrcache ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_rcache */*rcache*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_getremotesubkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock **/*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_init ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_removeflags ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t /*removeflags*/, + int32_t */*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setaddrs ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_address */*local_addr*/, + krb5_address */*remote_addr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setaddrs_from_fd ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + void */*p_fd*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setcksumtype ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_cksumtype /*cksumtype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setflags ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setkeytype ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keytype /*keytype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setlocalseqnumber ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t /*seqnumber*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setlocalsubkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setrcache ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_rcache /*rcache*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setremoteseqnumber ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t /*seqnumber*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setremotesubkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_con_setuserkey ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_auth_getremoteseqnumber ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + int32_t */*seqnumber*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_ap_req ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + krb5_creds */*cred*/, + krb5_flags /*ap_options*/, + krb5_data /*authenticator*/, + krb5_data */*retdata*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_authenticator ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_enctype /*enctype*/, + krb5_creds */*cred*/, + Checksum */*cksum*/, + Authenticator **/*auth_result*/, + krb5_data */*result*/, + krb5_key_usage /*usage*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal ( + krb5_context /*context*/, + krb5_principal */*principal*/, + int /*rlen*/, + krb5_const_realm /*realm*/, + ...); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal_ext ( + krb5_context /*context*/, + krb5_principal */*principal*/, + int /*rlen*/, + krb5_const_realm /*realm*/, + ...); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal_va ( + krb5_context /*context*/, + krb5_principal */*principal*/, + int /*rlen*/, + krb5_const_realm /*realm*/, + va_list /*ap*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal_va_ext ( + krb5_context /*context*/, + krb5_principal */*principal*/, + int /*rlen*/, + krb5_const_realm /*realm*/, + va_list /*ap*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_block_size ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + size_t */*blocksize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_checksum_length ( + krb5_context /*context*/, + krb5_cksumtype /*cksumtype*/, + size_t */*length*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_decrypt ( + krb5_context /*context*/, + const krb5_keyblock /*key*/, + krb5_keyusage /*usage*/, + const krb5_data */*ivec*/, + krb5_enc_data */*input*/, + krb5_data */*output*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_encrypt ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + krb5_keyusage /*usage*/, + const krb5_data */*ivec*/, + const krb5_data */*input*/, + krb5_enc_data */*output*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_encrypt_length ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + size_t /*inputlen*/, + size_t */*length*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_enctype_compare ( + krb5_context /*context*/, + krb5_enctype /*e1*/, + krb5_enctype /*e2*/, + krb5_boolean */*similar*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_get_checksum ( + krb5_context /*context*/, + const krb5_checksum */*cksum*/, + krb5_cksumtype */*type*/, + krb5_data **/*data*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_is_coll_proof_cksum (krb5_cksumtype /*ctype*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_is_keyed_cksum (krb5_cksumtype /*ctype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_make_checksum ( + krb5_context /*context*/, + krb5_cksumtype /*cksumtype*/, + const krb5_keyblock */*key*/, + krb5_keyusage /*usage*/, + const krb5_data */*input*/, + krb5_checksum */*cksum*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_make_random_key ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + krb5_keyblock */*random_key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_set_checksum ( + krb5_context /*context*/, + krb5_checksum */*cksum*/, + krb5_cksumtype /*type*/, + const krb5_data */*data*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_valid_cksumtype (krb5_cksumtype /*ctype*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_valid_enctype (krb5_enctype /*etype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_verify_checksum ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + krb5_keyusage /*usage*/, + const krb5_data */*data*/, + const krb5_checksum */*cksum*/, + krb5_boolean */*valid*/); + +void KRB5_LIB_FUNCTION +krb5_cc_clear_mcred (krb5_creds */*mcred*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_close ( + krb5_context /*context*/, + krb5_ccache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_copy_cache ( + krb5_context /*context*/, + const krb5_ccache /*from*/, + krb5_ccache /*to*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_copy_cache_match ( + krb5_context /*context*/, + const krb5_ccache /*from*/, + krb5_ccache /*to*/, + krb5_flags /*whichfields*/, + const krb5_creds * /*mcreds*/, + unsigned int */*matched*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_default ( + krb5_context /*context*/, + krb5_ccache */*id*/); + +const char* KRB5_LIB_FUNCTION +krb5_cc_default_name (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_destroy ( + krb5_context /*context*/, + krb5_ccache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_end_seq_get ( + krb5_context /*context*/, + const krb5_ccache /*id*/, + krb5_cc_cursor */*cursor*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_gen_new ( + krb5_context /*context*/, + const krb5_cc_ops */*ops*/, + krb5_ccache */*id*/); + +const char* KRB5_LIB_FUNCTION +krb5_cc_get_name ( + krb5_context /*context*/, + krb5_ccache /*id*/); + +const krb5_cc_ops * +krb5_cc_get_ops ( + krb5_context /*context*/, + krb5_ccache /*id*/); + +const krb5_cc_ops * +krb5_cc_get_prefix_ops ( + krb5_context /*context*/, + const char */*prefix*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_principal ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_principal */*principal*/); + +const char* KRB5_LIB_FUNCTION +krb5_cc_get_type ( + krb5_context /*context*/, + krb5_ccache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_version ( + krb5_context /*context*/, + const krb5_ccache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_initialize ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_principal /*primary_principal*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_new_unique ( + krb5_context /*context*/, + const char */*type*/, + const char */*hint*/, + krb5_ccache */*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_next_cred ( + krb5_context /*context*/, + const krb5_ccache /*id*/, + krb5_cc_cursor */*cursor*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_next_cred_match ( + krb5_context /*context*/, + const krb5_ccache /*id*/, + krb5_cc_cursor * /*cursor*/, + krb5_creds * /*creds*/, + krb5_flags /*whichfields*/, + const krb5_creds * /*mcreds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_register ( + krb5_context /*context*/, + const krb5_cc_ops */*ops*/, + krb5_boolean /*override*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_remove_cred ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_flags /*which*/, + krb5_creds */*cred*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_resolve ( + krb5_context /*context*/, + const char */*name*/, + krb5_ccache */*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_retrieve_cred ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_flags /*whichfields*/, + const krb5_creds */*mcreds*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_set_default_name ( + krb5_context /*context*/, + const char */*name*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_set_flags ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_flags /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_start_seq_get ( + krb5_context /*context*/, + const krb5_ccache /*id*/, + krb5_cc_cursor */*cursor*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_store_cred ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_change_password ( + krb5_context /*context*/, + krb5_creds */*creds*/, + char */*newpw*/, + int */*result_code*/, + krb5_data */*result_code_string*/, + krb5_data */*result_string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_check_transited ( + krb5_context /*context*/, + krb5_const_realm /*client_realm*/, + krb5_const_realm /*server_realm*/, + krb5_realm */*realms*/, + int /*num_realms*/, + int */*bad_realm*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_check_transited_realms ( + krb5_context /*context*/, + const char *const */*realms*/, + int /*num_realms*/, + int */*bad_realm*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_checksum_disable ( + krb5_context /*context*/, + krb5_cksumtype /*type*/); + +void KRB5_LIB_FUNCTION +krb5_checksum_free ( + krb5_context /*context*/, + krb5_checksum */*cksum*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_checksum_is_collision_proof ( + krb5_context /*context*/, + krb5_cksumtype /*type*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_checksum_is_keyed ( + krb5_context /*context*/, + krb5_cksumtype /*type*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_checksumsize ( + krb5_context /*context*/, + krb5_cksumtype /*type*/, + size_t */*size*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cksumtype_valid ( + krb5_context /*context*/, + krb5_cksumtype /*ctype*/); + +void KRB5_LIB_FUNCTION +krb5_clear_error_string (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_closelog ( + krb5_context /*context*/, + krb5_log_facility */*fac*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_compare_creds ( + krb5_context /*context*/, + krb5_flags /*whichfields*/, + const krb5_creds * /*mcreds*/, + const krb5_creds * /*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_file_free ( + krb5_context /*context*/, + krb5_config_section */*s*/); + +void KRB5_LIB_FUNCTION +krb5_config_free_strings (char **/*strings*/); + +const void * +krb5_config_get ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + int /*type*/, + ...); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_get_bool ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + ...); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_get_bool_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + krb5_boolean /*def_value*/, + ...); + +int KRB5_LIB_FUNCTION +krb5_config_get_int ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + ...); + +int KRB5_LIB_FUNCTION +krb5_config_get_int_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + int /*def_value*/, + ...); + +const krb5_config_binding * +krb5_config_get_list ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + ...); + +const void * +krb5_config_get_next ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + const krb5_config_binding **/*pointer*/, + int /*type*/, + ...); + +const char* KRB5_LIB_FUNCTION +krb5_config_get_string ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + ...); + +const char* KRB5_LIB_FUNCTION +krb5_config_get_string_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + const char */*def_value*/, + ...); + +char** +krb5_config_get_strings ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + ...); + +int KRB5_LIB_FUNCTION +krb5_config_get_time ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + ...); + +int KRB5_LIB_FUNCTION +krb5_config_get_time_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + int /*def_value*/, + ...); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_file ( + krb5_context /*context*/, + const char */*fname*/, + krb5_config_section **/*res*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_file_multi ( + krb5_context /*context*/, + const char */*fname*/, + krb5_config_section **/*res*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_config_parse_string_multi ( + krb5_context /*context*/, + const char */*string*/, + krb5_config_section **/*res*/); + +const void * +krb5_config_vget ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + int /*type*/, + va_list /*args*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_vget_bool ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + va_list /*args*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_config_vget_bool_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + krb5_boolean /*def_value*/, + va_list /*args*/); + +int KRB5_LIB_FUNCTION +krb5_config_vget_int ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + va_list /*args*/); + +int KRB5_LIB_FUNCTION +krb5_config_vget_int_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + int /*def_value*/, + va_list /*args*/); + +const krb5_config_binding * +krb5_config_vget_list ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + va_list /*args*/); + +const void * +krb5_config_vget_next ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + const krb5_config_binding **/*pointer*/, + int /*type*/, + va_list /*args*/); + +const char* KRB5_LIB_FUNCTION +krb5_config_vget_string ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + va_list /*args*/); + +const char* KRB5_LIB_FUNCTION +krb5_config_vget_string_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + const char */*def_value*/, + va_list /*args*/); + +char ** KRB5_LIB_FUNCTION +krb5_config_vget_strings ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + va_list /*args*/); + +int KRB5_LIB_FUNCTION +krb5_config_vget_time ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + va_list /*args*/); + +int KRB5_LIB_FUNCTION +krb5_config_vget_time_default ( + krb5_context /*context*/, + const krb5_config_section */*c*/, + int /*def_value*/, + va_list /*args*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_address ( + krb5_context /*context*/, + const krb5_address */*inaddr*/, + krb5_address */*outaddr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_addresses ( + krb5_context /*context*/, + const krb5_addresses */*inaddr*/, + krb5_addresses */*outaddr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_checksum ( + krb5_context /*context*/, + const krb5_checksum */*old*/, + krb5_checksum **/*new*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_creds ( + krb5_context /*context*/, + const krb5_creds */*incred*/, + krb5_creds **/*outcred*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_creds_contents ( + krb5_context /*context*/, + const krb5_creds */*incred*/, + krb5_creds */*c*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_data ( + krb5_context /*context*/, + const krb5_data */*indata*/, + krb5_data **/*outdata*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_host_realm ( + krb5_context /*context*/, + const krb5_realm */*from*/, + krb5_realm **/*to*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_keyblock ( + krb5_context /*context*/, + const krb5_keyblock */*inblock*/, + krb5_keyblock **/*to*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_keyblock_contents ( + krb5_context /*context*/, + const krb5_keyblock */*inblock*/, + krb5_keyblock */*to*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_principal ( + krb5_context /*context*/, + krb5_const_principal /*inprinc*/, + krb5_principal */*outprinc*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_ticket ( + krb5_context /*context*/, + const krb5_ticket */*from*/, + krb5_ticket **/*to*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_create_checksum ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + krb5_key_usage /*usage*/, + int /*type*/, + void */*data*/, + size_t /*len*/, + Checksum */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_destroy ( + krb5_context /*context*/, + krb5_crypto /*crypto*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_get_checksum_type ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + krb5_cksumtype */*type*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_get_params ( + krb5_context /*context*/, + const krb5_crypto /*crypto*/, + const krb5_data */*params*/, + krb5_data */*ivec*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getblocksize ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + size_t */*blocksize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getconfoundersize ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + size_t */*confoundersize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getenctype ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + krb5_enctype */*enctype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_getpadsize ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + size_t */*padsize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_init ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + krb5_enctype /*etype*/, + krb5_crypto */*crypto*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_set_params ( + krb5_context /*context*/, + const krb5_crypto /*crypto*/, + const krb5_data */*ivec*/, + krb5_data */*params*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_data_alloc ( + krb5_data */*p*/, + int /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_data_copy ( + krb5_data */*p*/, + const void */*data*/, + size_t /*len*/); + +void KRB5_LIB_FUNCTION +krb5_data_free (krb5_data */*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_data_realloc ( + krb5_data */*p*/, + int /*len*/); + +void KRB5_LIB_FUNCTION +krb5_data_zero (krb5_data */*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_Authenticator ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + Authenticator */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_ETYPE_INFO ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + ETYPE_INFO */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_ETYPE_INFO2 ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + ETYPE_INFO2 */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncAPRepPart ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + EncAPRepPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncASRepPart ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + EncASRepPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncKrbCredPart ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + EncKrbCredPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncTGSRepPart ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + EncTGSRepPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_EncTicketPart ( + krb5_context /*context*/, + const void */*data*/, + size_t /*length*/, + EncTicketPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_ap_req ( + krb5_context /*context*/, + const krb5_data */*inbuf*/, + krb5_ap_req */*ap_req*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + unsigned /*usage*/, + void */*data*/, + size_t /*len*/, + krb5_data */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_EncryptedData ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + unsigned /*usage*/, + const EncryptedData */*e*/, + krb5_data */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_ivec ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + unsigned /*usage*/, + void */*data*/, + size_t /*len*/, + krb5_data */*result*/, + void */*ivec*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_ticket ( + krb5_context /*context*/, + Ticket */*ticket*/, + krb5_keyblock */*key*/, + EncTicketPart */*out*/, + krb5_flags /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_derive_key ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + krb5_enctype /*etype*/, + const void */*constant*/, + size_t /*constant_len*/, + krb5_keyblock **/*derived_key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_domain_x500_decode ( + krb5_context /*context*/, + krb5_data /*tr*/, + char ***/*realms*/, + int */*num_realms*/, + const char */*client_realm*/, + const char */*server_realm*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_domain_x500_encode ( + char **/*realms*/, + int /*num_realms*/, + krb5_data */*encoding*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_eai_to_heim_errno ( + int /*eai_errno*/, + int /*system_error*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_Authenticator ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + Authenticator */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_ETYPE_INFO ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + ETYPE_INFO */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_ETYPE_INFO2 ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + ETYPE_INFO2 */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncAPRepPart ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + EncAPRepPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncASRepPart ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + EncASRepPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncKrbCredPart ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + EncKrbCredPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncTGSRepPart ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + EncTGSRepPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encode_EncTicketPart ( + krb5_context /*context*/, + void */*data*/, + size_t /*length*/, + EncTicketPart */*t*/, + size_t */*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + unsigned /*usage*/, + void */*data*/, + size_t /*len*/, + krb5_data */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt_EncryptedData ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + unsigned /*usage*/, + void */*data*/, + size_t /*len*/, + int /*kvno*/, + EncryptedData */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt_ivec ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + unsigned /*usage*/, + void */*data*/, + size_t /*len*/, + krb5_data */*result*/, + void */*ivec*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_disable ( + krb5_context /*context*/, + krb5_enctype /*enctype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_keysize ( + krb5_context /*context*/, + krb5_enctype /*type*/, + size_t */*keysize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_to_keytype ( + krb5_context /*context*/, + krb5_enctype /*etype*/, + krb5_keytype */*keytype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_to_oid ( + krb5_context /*context*/, + krb5_enctype /*etype*/, + heim_oid */*oid*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_to_string ( + krb5_context /*context*/, + krb5_enctype /*etype*/, + char **/*string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_valid ( + krb5_context /*context*/, + krb5_enctype /*etype*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_enctypes_compatible_keys ( + krb5_context /*context*/, + krb5_enctype /*etype1*/, + krb5_enctype /*etype2*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_err ( + krb5_context /*context*/, + int /*eval*/, + krb5_error_code /*code*/, + const char */*fmt*/, + ...) + __attribute__ ((noreturn, format (printf, 4, 5))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_error_from_rd_error ( + krb5_context /*context*/, + const krb5_error */*error*/, + const krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_errx ( + krb5_context /*context*/, + int /*eval*/, + const char */*fmt*/, + ...) + __attribute__ ((noreturn, format (printf, 3, 4))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_expand_hostname ( + krb5_context /*context*/, + const char */*orig_hostname*/, + char **/*new_hostname*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_expand_hostname_realms ( + krb5_context /*context*/, + const char */*orig_hostname*/, + char **/*new_hostname*/, + char ***/*realms*/); + +PA_DATA * +krb5_find_padata ( + PA_DATA */*val*/, + unsigned /*len*/, + int /*type*/, + int */*idx*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_format_time ( + krb5_context /*context*/, + time_t /*t*/, + char */*s*/, + size_t /*len*/, + krb5_boolean /*include_time*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_address ( + krb5_context /*context*/, + krb5_address */*address*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_addresses ( + krb5_context /*context*/, + krb5_addresses */*addresses*/); + +void KRB5_LIB_FUNCTION +krb5_free_ap_rep_enc_part ( + krb5_context /*context*/, + krb5_ap_rep_enc_part */*val*/); + +void KRB5_LIB_FUNCTION +krb5_free_authenticator ( + krb5_context /*context*/, + krb5_authenticator */*authenticator*/); + +void KRB5_LIB_FUNCTION +krb5_free_checksum ( + krb5_context /*context*/, + krb5_checksum */*cksum*/); + +void KRB5_LIB_FUNCTION +krb5_free_checksum_contents ( + krb5_context /*context*/, + krb5_checksum */*cksum*/); + +void KRB5_LIB_FUNCTION +krb5_free_config_files (char **/*filenames*/); + +void KRB5_LIB_FUNCTION +krb5_free_context (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_cred_contents ( + krb5_context /*context*/, + krb5_creds */*c*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_creds ( + krb5_context /*context*/, + krb5_creds */*c*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_creds_contents ( + krb5_context /*context*/, + krb5_creds */*c*/); + +void KRB5_LIB_FUNCTION +krb5_free_data ( + krb5_context /*context*/, + krb5_data */*p*/); + +void KRB5_LIB_FUNCTION +krb5_free_data_contents ( + krb5_context /*context*/, + krb5_data */*data*/); + +void KRB5_LIB_FUNCTION +krb5_free_error ( + krb5_context /*context*/, + krb5_error */*error*/); + +void KRB5_LIB_FUNCTION +krb5_free_error_contents ( + krb5_context /*context*/, + krb5_error */*error*/); + +void KRB5_LIB_FUNCTION +krb5_free_error_string ( + krb5_context /*context*/, + char */*str*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_host_realm ( + krb5_context /*context*/, + krb5_realm */*realmlist*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_kdc_rep ( + krb5_context /*context*/, + krb5_kdc_rep */*rep*/); + +void KRB5_LIB_FUNCTION +krb5_free_keyblock ( + krb5_context /*context*/, + krb5_keyblock */*keyblock*/); + +void KRB5_LIB_FUNCTION +krb5_free_keyblock_contents ( + krb5_context /*context*/, + krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_krbhst ( + krb5_context /*context*/, + char **/*hostlist*/); + +void KRB5_LIB_FUNCTION +krb5_free_principal ( + krb5_context /*context*/, + krb5_principal /*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_salt ( + krb5_context /*context*/, + krb5_salt /*salt*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_ticket ( + krb5_context /*context*/, + krb5_ticket */*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_fwd_tgt_creds ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const char */*hostname*/, + krb5_principal /*client*/, + krb5_principal /*server*/, + krb5_ccache /*ccache*/, + int /*forwardable*/, + krb5_data */*out_data*/); + +void KRB5_LIB_FUNCTION +krb5_generate_random_block ( + void */*buf*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_random_keyblock ( + krb5_context /*context*/, + krb5_enctype /*type*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_seq_number ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + u_int32_t */*seqno*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_subkey ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + krb5_keyblock **/*subkey*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_generate_subkey_extended ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + krb5_enctype /*etype*/, + krb5_keyblock **/*subkey*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_all_client_addrs ( + krb5_context /*context*/, + krb5_addresses */*res*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_all_server_addrs ( + krb5_context /*context*/, + krb5_addresses */*res*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_cred_from_kdc ( + krb5_context /*context*/, + krb5_ccache /*ccache*/, + krb5_creds */*in_creds*/, + krb5_creds **/*out_creds*/, + krb5_creds ***/*ret_tgts*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_cred_from_kdc_opt ( + krb5_context /*context*/, + krb5_ccache /*ccache*/, + krb5_creds */*in_creds*/, + krb5_creds **/*out_creds*/, + krb5_creds ***/*ret_tgts*/, + krb5_flags /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_credentials ( + krb5_context /*context*/, + krb5_flags /*options*/, + krb5_ccache /*ccache*/, + krb5_creds */*in_creds*/, + krb5_creds **/*out_creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_credentials_with_flags ( + krb5_context /*context*/, + krb5_flags /*options*/, + krb5_kdc_flags /*flags*/, + krb5_ccache /*ccache*/, + krb5_creds */*in_creds*/, + krb5_creds **/*out_creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_config_files (char ***/*pfilenames*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_in_tkt_etypes ( + krb5_context /*context*/, + krb5_enctype **/*etypes*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_principal ( + krb5_context /*context*/, + krb5_principal */*princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_realm ( + krb5_context /*context*/, + krb5_realm */*realm*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_default_realms ( + krb5_context /*context*/, + krb5_realm **/*realms*/); + +const char* KRB5_LIB_FUNCTION +krb5_get_err_text ( + krb5_context /*context*/, + krb5_error_code /*code*/); + +char * KRB5_LIB_FUNCTION +krb5_get_error_string (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_extra_addresses ( + krb5_context /*context*/, + krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_fcache_version ( + krb5_context /*context*/, + int */*version*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_forwarded_creds ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_ccache /*ccache*/, + krb5_flags /*flags*/, + const char */*hostname*/, + krb5_creds */*in_creds*/, + krb5_data */*out_data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_host_realm ( + krb5_context /*context*/, + const char */*host*/, + krb5_realm **/*realms*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_ignore_addresses ( + krb5_context /*context*/, + krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_cred ( + krb5_context /*context*/, + krb5_flags /*options*/, + const krb5_addresses */*addrs*/, + const krb5_enctype */*etypes*/, + const krb5_preauthtype */*ptypes*/, + const krb5_preauthdata */*preauth*/, + krb5_key_proc /*key_proc*/, + krb5_const_pointer /*keyseed*/, + krb5_decrypt_proc /*decrypt_proc*/, + krb5_const_pointer /*decryptarg*/, + krb5_creds */*creds*/, + krb5_kdc_rep */*ret_as_reply*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt ( + krb5_context /*context*/, + krb5_flags /*options*/, + const krb5_addresses */*addrs*/, + const krb5_enctype */*etypes*/, + const krb5_preauthtype */*ptypes*/, + krb5_key_proc /*key_proc*/, + krb5_const_pointer /*keyseed*/, + krb5_decrypt_proc /*decrypt_proc*/, + krb5_const_pointer /*decryptarg*/, + krb5_creds */*creds*/, + krb5_ccache /*ccache*/, + krb5_kdc_rep */*ret_as_reply*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt_with_keytab ( + krb5_context /*context*/, + krb5_flags /*options*/, + krb5_addresses */*addrs*/, + const krb5_enctype */*etypes*/, + const krb5_preauthtype */*pre_auth_types*/, + krb5_keytab /*keytab*/, + krb5_ccache /*ccache*/, + krb5_creds */*creds*/, + krb5_kdc_rep */*ret_as_reply*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt_with_password ( + krb5_context /*context*/, + krb5_flags /*options*/, + krb5_addresses */*addrs*/, + const krb5_enctype */*etypes*/, + const krb5_preauthtype */*pre_auth_types*/, + const char */*password*/, + krb5_ccache /*ccache*/, + krb5_creds */*creds*/, + krb5_kdc_rep */*ret_as_reply*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_in_tkt_with_skey ( + krb5_context /*context*/, + krb5_flags /*options*/, + krb5_addresses */*addrs*/, + const krb5_enctype */*etypes*/, + const krb5_preauthtype */*pre_auth_types*/, + const krb5_keyblock */*key*/, + krb5_ccache /*ccache*/, + krb5_creds */*creds*/, + krb5_kdc_rep */*ret_as_reply*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_principal /*client*/, + krb5_prompter_fct /*prompter*/, + void */*data*/, + krb5_deltat /*start_time*/, + const char */*in_tkt_service*/, + krb5_get_init_creds_opt */*options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_keyblock ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_principal /*client*/, + krb5_keyblock */*keyblock*/, + krb5_deltat /*start_time*/, + const char */*in_tkt_service*/, + krb5_get_init_creds_opt */*options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_keytab ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_principal /*client*/, + krb5_keytab /*keytab*/, + krb5_deltat /*start_time*/, + const char */*in_tkt_service*/, + krb5_get_init_creds_opt */*options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_alloc ( + krb5_context /*context*/, + krb5_get_init_creds_opt **/*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_free (krb5_get_init_creds_opt */*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_init (krb5_get_init_creds_opt */*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_address_list ( + krb5_get_init_creds_opt */*opt*/, + krb5_addresses */*addresses*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_anonymous ( + krb5_get_init_creds_opt */*opt*/, + int /*anonymous*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_default_flags ( + krb5_context /*context*/, + const char */*appname*/, + krb5_const_realm /*realm*/, + krb5_get_init_creds_opt */*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_etype_list ( + krb5_get_init_creds_opt */*opt*/, + krb5_enctype */*etype_list*/, + int /*etype_list_length*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_forwardable ( + krb5_get_init_creds_opt */*opt*/, + int /*forwardable*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_pa_password ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + const char */*password*/, + krb5_s2k_proc /*key_proc*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_pac_request ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + krb5_boolean /*req_pac*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_pkinit ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + krb5_principal /*principal*/, + const char */*user_id*/, + const char */*x509_anchors*/, + int /*flags*/, + krb5_prompter_fct /*prompter*/, + void */*prompter_data*/, + char */*password*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_preauth_list ( + krb5_get_init_creds_opt */*opt*/, + krb5_preauthtype */*preauth_list*/, + int /*preauth_list_length*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_proxiable ( + krb5_get_init_creds_opt */*opt*/, + int /*proxiable*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_renew_life ( + krb5_get_init_creds_opt */*opt*/, + krb5_deltat /*renew_life*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_salt ( + krb5_get_init_creds_opt */*opt*/, + krb5_data */*salt*/); + +void KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_tkt_life ( + krb5_get_init_creds_opt */*opt*/, + krb5_deltat /*tkt_life*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_password ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_principal /*client*/, + const char */*password*/, + krb5_prompter_fct /*prompter*/, + void */*data*/, + krb5_deltat /*start_time*/, + const char */*in_tkt_service*/, + krb5_get_init_creds_opt */*in_options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_kdc_cred ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_kdc_flags /*flags*/, + krb5_addresses */*addresses*/, + Ticket */*second_ticket*/, + krb5_creds */*in_creds*/, + krb5_creds **out_creds ); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krb524hst ( + krb5_context /*context*/, + const krb5_realm */*realm*/, + char ***/*hostlist*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krb_admin_hst ( + krb5_context /*context*/, + const krb5_realm */*realm*/, + char ***/*hostlist*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krb_changepw_hst ( + krb5_context /*context*/, + const krb5_realm */*realm*/, + char ***/*hostlist*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krbhst ( + krb5_context /*context*/, + const krb5_realm */*realm*/, + char ***/*hostlist*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_pw_salt ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + krb5_salt */*salt*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_server_rcache ( + krb5_context /*context*/, + const krb5_data */*piece*/, + krb5_rcache */*id*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_get_use_admin_kdc (krb5_context /*context*/); + +size_t +krb5_get_wrapped_length ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + size_t /*data_len*/); + +int KRB5_LIB_FUNCTION +krb5_getportbyname ( + krb5_context /*context*/, + const char */*service*/, + const char */*proto*/, + int /*default_port*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_h_addr2addr ( + krb5_context /*context*/, + int /*af*/, + const char */*haddr*/, + krb5_address */*addr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_h_addr2sockaddr ( + krb5_context /*context*/, + int /*af*/, + const char */*addr*/, + struct sockaddr */*sa*/, + krb5_socklen_t */*sa_size*/, + int /*port*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_h_errno_to_heim_errno (int /*eai_errno*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_have_error_string (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_hmac ( + krb5_context /*context*/, + krb5_cksumtype /*cktype*/, + const void */*data*/, + size_t /*len*/, + unsigned /*usage*/, + krb5_keyblock */*key*/, + Checksum */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_init_context (krb5_context */*context*/); + +void KRB5_LIB_FUNCTION +krb5_init_ets (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_init_etype ( + krb5_context /*context*/, + unsigned */*len*/, + krb5_enctype **/*val*/, + const krb5_enctype */*etypes*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_initlog ( + krb5_context /*context*/, + const char */*program*/, + krb5_log_facility **/*fac*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_is_thread_safe (void); + +krb5_enctype +krb5_keyblock_get_enctype (const krb5_keyblock */*block*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keyblock_init ( + krb5_context /*context*/, + krb5_enctype /*type*/, + const void */*data*/, + size_t /*size*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keyblock_key_proc ( + krb5_context /*context*/, + krb5_keytype /*type*/, + krb5_data */*salt*/, + krb5_const_pointer /*keyseed*/, + krb5_keyblock **/*key*/); + +void KRB5_LIB_FUNCTION +krb5_keyblock_zero (krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytab_key_proc ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + krb5_salt /*salt*/, + krb5_const_pointer /*keyseed*/, + krb5_keyblock **/*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctypes ( + krb5_context /*context*/, + krb5_keytype /*keytype*/, + unsigned */*len*/, + krb5_enctype **/*val*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctypes_default ( + krb5_context /*context*/, + krb5_keytype /*keytype*/, + unsigned */*len*/, + krb5_enctype **/*val*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_string ( + krb5_context /*context*/, + krb5_keytype /*keytype*/, + char **/*string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_format_string ( + krb5_context /*context*/, + const krb5_krbhst_info */*host*/, + char */*hostname*/, + size_t /*hostlen*/); + +void KRB5_LIB_FUNCTION +krb5_krbhst_free ( + krb5_context /*context*/, + krb5_krbhst_handle /*handle*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_get_addrinfo ( + krb5_context /*context*/, + krb5_krbhst_info */*host*/, + struct addrinfo **/*ai*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_init ( + krb5_context /*context*/, + const char */*realm*/, + unsigned int /*type*/, + krb5_krbhst_handle */*handle*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_init_flags ( + krb5_context /*context*/, + const char */*realm*/, + unsigned int /*type*/, + int /*flags*/, + krb5_krbhst_handle */*handle*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_next ( + krb5_context /*context*/, + krb5_krbhst_handle /*handle*/, + krb5_krbhst_info **/*host*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_next_as_string ( + krb5_context /*context*/, + krb5_krbhst_handle /*handle*/, + char */*hostname*/, + size_t /*hostlen*/); + +void KRB5_LIB_FUNCTION +krb5_krbhst_reset ( + krb5_context /*context*/, + krb5_krbhst_handle /*handle*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_add_entry ( + krb5_context /*context*/, + krb5_keytab /*id*/, + krb5_keytab_entry */*entry*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_close ( + krb5_context /*context*/, + krb5_keytab /*id*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_kt_compare ( + krb5_context /*context*/, + krb5_keytab_entry */*entry*/, + krb5_const_principal /*principal*/, + krb5_kvno /*vno*/, + krb5_enctype /*enctype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_copy_entry_contents ( + krb5_context /*context*/, + const krb5_keytab_entry */*in*/, + krb5_keytab_entry */*out*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_default ( + krb5_context /*context*/, + krb5_keytab */*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_default_modify_name ( + krb5_context /*context*/, + char */*name*/, + size_t /*namesize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_default_name ( + krb5_context /*context*/, + char */*name*/, + size_t /*namesize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_end_seq_get ( + krb5_context /*context*/, + krb5_keytab /*id*/, + krb5_kt_cursor */*cursor*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_free_entry ( + krb5_context /*context*/, + krb5_keytab_entry */*entry*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_entry ( + krb5_context /*context*/, + krb5_keytab /*id*/, + krb5_const_principal /*principal*/, + krb5_kvno /*kvno*/, + krb5_enctype /*enctype*/, + krb5_keytab_entry */*entry*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_name ( + krb5_context /*context*/, + krb5_keytab /*keytab*/, + char */*name*/, + size_t /*namesize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_type ( + krb5_context /*context*/, + krb5_keytab /*keytab*/, + char */*prefix*/, + size_t /*prefixsize*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_next_entry ( + krb5_context /*context*/, + krb5_keytab /*id*/, + krb5_keytab_entry */*entry*/, + krb5_kt_cursor */*cursor*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_read_service_key ( + krb5_context /*context*/, + krb5_pointer /*keyprocarg*/, + krb5_principal /*principal*/, + krb5_kvno /*vno*/, + krb5_enctype /*enctype*/, + krb5_keyblock **/*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_register ( + krb5_context /*context*/, + const krb5_kt_ops */*ops*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_remove_entry ( + krb5_context /*context*/, + krb5_keytab /*id*/, + krb5_keytab_entry */*entry*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_resolve ( + krb5_context /*context*/, + const char */*name*/, + krb5_keytab */*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_start_seq_get ( + krb5_context /*context*/, + krb5_keytab /*id*/, + krb5_kt_cursor */*cursor*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_kuserok ( + krb5_context /*context*/, + krb5_principal /*principal*/, + const char */*luser*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_log ( + krb5_context /*context*/, + krb5_log_facility */*fac*/, + int /*level*/, + const char */*fmt*/, + ...) + __attribute__((format (printf, 4, 5))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_log_msg ( + krb5_context /*context*/, + krb5_log_facility */*fac*/, + int /*level*/, + char **/*reply*/, + const char */*fmt*/, + ...) + __attribute__((format (printf, 5, 6))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_make_addrport ( + krb5_context /*context*/, + krb5_address **/*res*/, + const krb5_address */*addr*/, + int16_t /*port*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_make_principal ( + krb5_context /*context*/, + krb5_principal */*principal*/, + krb5_const_realm /*realm*/, + ...); + +size_t KRB5_LIB_FUNCTION +krb5_max_sockaddr_size (void); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_error ( + krb5_context /*context*/, + krb5_error_code /*error_code*/, + const char */*e_text*/, + const krb5_data */*e_data*/, + const krb5_principal /*client*/, + const krb5_principal /*server*/, + time_t */*client_time*/, + int */*client_usec*/, + krb5_data */*reply*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_priv ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const krb5_data */*userdata*/, + krb5_data */*outbuf*/, + krb5_replay_data */*outdata*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_rep ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_data */*outbuf*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_req ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_flags /*ap_req_options*/, + const char */*service*/, + const char */*hostname*/, + krb5_data */*in_data*/, + krb5_ccache /*ccache*/, + krb5_data */*outbuf*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_req_exact ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_flags /*ap_req_options*/, + const krb5_principal /*server*/, + krb5_data */*in_data*/, + krb5_ccache /*ccache*/, + krb5_data */*outbuf*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_req_extended ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_flags /*ap_req_options*/, + krb5_data */*in_data*/, + krb5_creds */*in_creds*/, + krb5_data */*outbuf*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_safe ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const krb5_data */*userdata*/, + krb5_data */*outbuf*/, + krb5_replay_data */*outdata*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_net_read ( + krb5_context /*context*/, + void */*p_fd*/, + void */*buf*/, + size_t /*len*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_net_write ( + krb5_context /*context*/, + void */*p_fd*/, + const void */*buf*/, + size_t /*len*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_net_write_block ( + krb5_context /*context*/, + void */*p_fd*/, + const void */*buf*/, + size_t /*len*/, + time_t /*timeout*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_openlog ( + krb5_context /*context*/, + const char */*program*/, + krb5_log_facility **/*fac*/); + +int KRB5_LIB_FUNCTION +krb5_padata_add ( + krb5_context /*context*/, + METHOD_DATA */*md*/, + int /*type*/, + void */*buf*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_address ( + krb5_context /*context*/, + const char */*string*/, + krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name ( + krb5_context /*context*/, + const char */*name*/, + krb5_principal */*principal*/); + +const char* KRB5_LIB_FUNCTION +krb5_passwd_result_to_string ( + krb5_context /*context*/, + int /*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_password_key_proc ( + krb5_context /*context*/, + krb5_enctype /*type*/, + krb5_salt /*salt*/, + krb5_const_pointer /*keyseed*/, + krb5_keyblock **/*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_prepend_config_files ( + const char */*filelist*/, + char **/*pq*/, + char ***/*ret_pp*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_prepend_config_files_default ( + const char */*filelist*/, + char ***/*pfilenames*/); + +krb5_realm* +krb5_princ_realm ( + krb5_context /*context*/, + krb5_principal /*principal*/); + +void KRB5_LIB_FUNCTION +krb5_princ_set_realm ( + krb5_context /*context*/, + krb5_principal /*principal*/, + krb5_realm */*realm*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_principal_compare ( + krb5_context /*context*/, + krb5_const_principal /*princ1*/, + krb5_const_principal /*princ2*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_principal_compare_any_realm ( + krb5_context /*context*/, + krb5_const_principal /*princ1*/, + krb5_const_principal /*princ2*/); + +const char* KRB5_LIB_FUNCTION +krb5_principal_get_comp_string ( + krb5_context /*context*/, + krb5_principal /*principal*/, + unsigned int /*component*/); + +const char* KRB5_LIB_FUNCTION +krb5_principal_get_realm ( + krb5_context /*context*/, + krb5_const_principal /*principal*/); + +int KRB5_LIB_FUNCTION +krb5_principal_get_type ( + krb5_context /*context*/, + krb5_principal /*principal*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_principal_match ( + krb5_context /*context*/, + krb5_const_principal /*princ*/, + krb5_const_principal /*pattern*/); + +void KRB5_LIB_FUNCTION +krb5_principal_set_type ( + krb5_context /*context*/, + krb5_principal /*principal*/, + int /*type*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_print_address ( + const krb5_address */*addr*/, + char */*str*/, + size_t /*len*/, + size_t */*ret_len*/); + +int KRB5_LIB_FUNCTION +krb5_program_setup ( + krb5_context */*context*/, + int /*argc*/, + char **/*argv*/, + struct getargs */*args*/, + int /*num_args*/, + void (*/*usage*/)(int, struct getargs*, int)); + +int KRB5_LIB_FUNCTION +krb5_prompter_posix ( + krb5_context /*context*/, + void */*data*/, + const char */*name*/, + const char */*banner*/, + int /*num_prompts*/, + krb5_prompt prompts[]); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_random_to_key ( + krb5_context /*context*/, + krb5_enctype /*type*/, + const void */*data*/, + size_t /*size*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_close ( + krb5_context /*context*/, + krb5_rcache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_default ( + krb5_context /*context*/, + krb5_rcache */*id*/); + +const char* KRB5_LIB_FUNCTION +krb5_rc_default_name (krb5_context /*context*/); + +const char* KRB5_LIB_FUNCTION +krb5_rc_default_type (krb5_context /*context*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_destroy ( + krb5_context /*context*/, + krb5_rcache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_expunge ( + krb5_context /*context*/, + krb5_rcache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_get_lifespan ( + krb5_context /*context*/, + krb5_rcache /*id*/, + krb5_deltat */*auth_lifespan*/); + +const char* KRB5_LIB_FUNCTION +krb5_rc_get_name ( + krb5_context /*context*/, + krb5_rcache /*id*/); + +const char* KRB5_LIB_FUNCTION +krb5_rc_get_type ( + krb5_context /*context*/, + krb5_rcache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_initialize ( + krb5_context /*context*/, + krb5_rcache /*id*/, + krb5_deltat /*auth_lifespan*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_recover ( + krb5_context /*context*/, + krb5_rcache /*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_resolve ( + krb5_context /*context*/, + krb5_rcache /*id*/, + const char */*name*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_resolve_full ( + krb5_context /*context*/, + krb5_rcache */*id*/, + const char */*string_name*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_resolve_type ( + krb5_context /*context*/, + krb5_rcache */*id*/, + const char */*type*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_store ( + krb5_context /*context*/, + krb5_rcache /*id*/, + krb5_donot_replay */*rep*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_cred ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_data */*in_data*/, + krb5_creds ***/*ret_creds*/, + krb5_replay_data */*outdata*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_cred2 ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + krb5_ccache /*ccache*/, + krb5_data */*in_data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_error ( + krb5_context /*context*/, + krb5_data */*msg*/, + KRB_ERROR */*result*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_priv ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const krb5_data */*inbuf*/, + krb5_data */*outbuf*/, + krb5_replay_data */*outdata*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_rep ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const krb5_data */*inbuf*/, + krb5_ap_rep_enc_part **/*repl*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_data */*inbuf*/, + krb5_const_principal /*server*/, + krb5_keytab /*keytab*/, + krb5_flags */*ap_req_options*/, + krb5_ticket **/*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_return_keyblock ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_data */*inbuf*/, + krb5_const_principal /*server*/, + krb5_keytab /*keytab*/, + krb5_flags */*ap_req_options*/, + krb5_ticket **/*ticket*/, + krb5_keyblock **/*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_with_keyblock ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + const krb5_data */*inbuf*/, + krb5_const_principal /*server*/, + krb5_keyblock */*keyblock*/, + krb5_flags */*ap_req_options*/, + krb5_ticket **/*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_safe ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const krb5_data */*inbuf*/, + krb5_data */*outbuf*/, + krb5_replay_data */*outdata*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_read_message ( + krb5_context /*context*/, + krb5_pointer /*p_fd*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_read_priv_message ( + krb5_context /*context*/, + krb5_auth_context /*ac*/, + krb5_pointer /*p_fd*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_read_safe_message ( + krb5_context /*context*/, + krb5_auth_context /*ac*/, + krb5_pointer /*p_fd*/, + krb5_data */*data*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_realm_compare ( + krb5_context /*context*/, + krb5_const_principal /*princ1*/, + krb5_const_principal /*princ2*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_recvauth ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + krb5_pointer /*p_fd*/, + const char */*appl_version*/, + krb5_principal /*server*/, + int32_t /*flags*/, + krb5_keytab /*keytab*/, + krb5_ticket **/*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_recvauth_match_version ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + krb5_pointer /*p_fd*/, + krb5_boolean (*/*match_appl_version*/)(const void *, const char*), + const void */*match_data*/, + krb5_principal /*server*/, + int32_t /*flags*/, + krb5_keytab /*keytab*/, + krb5_ticket **/*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_address ( + krb5_storage */*sp*/, + krb5_address */*adr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_addrs ( + krb5_storage */*sp*/, + krb5_addresses */*adr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_authdata ( + krb5_storage */*sp*/, + krb5_authdata */*auth*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_creds ( + krb5_storage */*sp*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_creds_tag ( + krb5_storage */*sp*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_data ( + krb5_storage */*sp*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_int16 ( + krb5_storage */*sp*/, + int16_t */*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_int32 ( + krb5_storage */*sp*/, + int32_t */*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_int8 ( + krb5_storage */*sp*/, + int8_t */*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_keyblock ( + krb5_storage */*sp*/, + krb5_keyblock */*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_principal ( + krb5_storage */*sp*/, + krb5_principal */*princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_string ( + krb5_storage */*sp*/, + char **/*string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_stringz ( + krb5_storage */*sp*/, + char **/*string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_times ( + krb5_storage */*sp*/, + krb5_times */*times*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_salttype_to_string ( + krb5_context /*context*/, + krb5_enctype /*etype*/, + krb5_salttype /*stype*/, + char **/*string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendauth ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + krb5_pointer /*p_fd*/, + const char */*appl_version*/, + krb5_principal /*client*/, + krb5_principal /*server*/, + krb5_flags /*ap_req_options*/, + krb5_data */*in_data*/, + krb5_creds */*in_creds*/, + krb5_ccache /*ccache*/, + krb5_error **/*ret_error*/, + krb5_ap_rep_enc_part **/*rep_result*/, + krb5_creds **/*out_creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto ( + krb5_context /*context*/, + const krb5_data */*send_data*/, + krb5_krbhst_handle /*handle*/, + krb5_data */*receive*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_kdc ( + krb5_context /*context*/, + const krb5_data */*send_data*/, + const krb5_realm */*realm*/, + krb5_data */*receive*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_kdc_flags ( + krb5_context /*context*/, + const krb5_data */*send_data*/, + const krb5_realm */*realm*/, + krb5_data */*receive*/, + int /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_config_files ( + krb5_context /*context*/, + char **/*filenames*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_default_in_tkt_etypes ( + krb5_context /*context*/, + const krb5_enctype */*etypes*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_default_realm ( + krb5_context /*context*/, + const char */*realm*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_error_string ( + krb5_context /*context*/, + const char */*fmt*/, + ...) + __attribute__((format (printf, 2, 3))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_extra_addresses ( + krb5_context /*context*/, + const krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_fcache_version ( + krb5_context /*context*/, + int /*version*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_ignore_addresses ( + krb5_context /*context*/, + const krb5_addresses */*addresses*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_password ( + krb5_context /*context*/, + krb5_creds */*creds*/, + char */*newpw*/, + krb5_principal /*targprinc*/, + int */*result_code*/, + krb5_data */*result_code_string*/, + krb5_data */*result_string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_password_using_ccache ( + krb5_context /*context*/, + krb5_ccache /*ccache*/, + char */*newpw*/, + krb5_principal /*targprinc*/, + int */*result_code*/, + krb5_data */*result_code_string*/, + krb5_data */*result_string*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_real_time ( + krb5_context /*context*/, + krb5_timestamp /*sec*/, + int32_t /*usec*/); + +void KRB5_LIB_FUNCTION +krb5_set_use_admin_kdc ( + krb5_context /*context*/, + krb5_boolean /*flag*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_warn_dest ( + krb5_context /*context*/, + krb5_log_facility */*fac*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sname_to_principal ( + krb5_context /*context*/, + const char */*hostname*/, + const char */*sname*/, + int32_t /*type*/, + krb5_principal */*ret_princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sock_to_principal ( + krb5_context /*context*/, + int /*sock*/, + const char */*sname*/, + int32_t /*type*/, + krb5_principal */*ret_princ*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sockaddr2address ( + krb5_context /*context*/, + const struct sockaddr */*sa*/, + krb5_address */*addr*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sockaddr2port ( + krb5_context /*context*/, + const struct sockaddr */*sa*/, + int16_t */*port*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_sockaddr_uninteresting (const struct sockaddr */*sa*/); + +void KRB5_LIB_FUNCTION +krb5_std_usage ( + int /*code*/, + struct getargs */*args*/, + int /*num_args*/); + +void KRB5_LIB_FUNCTION +krb5_storage_clear_flags ( + krb5_storage */*sp*/, + krb5_flags /*flags*/); + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_emem (void); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_storage_free (krb5_storage */*sp*/); + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_data (krb5_data */*data*/); + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_fd (int /*fd*/); + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_mem ( + void */*buf*/, + size_t /*len*/); + +krb5_flags KRB5_LIB_FUNCTION +krb5_storage_get_byteorder ( + krb5_storage */*sp*/, + krb5_flags /*byteorder*/); + +krb5_boolean KRB5_LIB_FUNCTION +krb5_storage_is_flags ( + krb5_storage */*sp*/, + krb5_flags /*flags*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_storage_read ( + krb5_storage */*sp*/, + void */*buf*/, + size_t /*len*/); + +off_t KRB5_LIB_FUNCTION +krb5_storage_seek ( + krb5_storage */*sp*/, + off_t /*offset*/, + int /*whence*/); + +void KRB5_LIB_FUNCTION +krb5_storage_set_byteorder ( + krb5_storage */*sp*/, + krb5_flags /*byteorder*/); + +void KRB5_LIB_FUNCTION +krb5_storage_set_eof_code ( + krb5_storage */*sp*/, + int /*code*/); + +void KRB5_LIB_FUNCTION +krb5_storage_set_flags ( + krb5_storage */*sp*/, + krb5_flags /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_storage_to_data ( + krb5_storage */*sp*/, + krb5_data */*data*/); + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_storage_write ( + krb5_storage */*sp*/, + const void */*buf*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_address ( + krb5_storage */*sp*/, + krb5_address /*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_addrs ( + krb5_storage */*sp*/, + krb5_addresses /*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_authdata ( + krb5_storage */*sp*/, + krb5_authdata /*auth*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_creds ( + krb5_storage */*sp*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_creds_tag ( + krb5_storage */*sp*/, + krb5_creds */*creds*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_data ( + krb5_storage */*sp*/, + krb5_data /*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_int16 ( + krb5_storage */*sp*/, + int16_t /*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_int32 ( + krb5_storage */*sp*/, + int32_t /*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_int8 ( + krb5_storage */*sp*/, + int8_t /*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_keyblock ( + krb5_storage */*sp*/, + krb5_keyblock /*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_principal ( + krb5_storage */*sp*/, + krb5_principal /*p*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_string ( + krb5_storage */*sp*/, + const char */*s*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_stringz ( + krb5_storage */*sp*/, + const char */*s*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_times ( + krb5_storage */*sp*/, + krb5_times /*times*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_deltat ( + const char */*string*/, + krb5_deltat */*deltat*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_enctype ( + krb5_context /*context*/, + const char */*string*/, + krb5_enctype */*etype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + const char */*password*/, + krb5_principal /*principal*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_data ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + krb5_data /*password*/, + krb5_principal /*principal*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_data_salt ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + krb5_data /*password*/, + krb5_salt /*salt*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_data_salt_opaque ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + krb5_data /*password*/, + krb5_salt /*salt*/, + krb5_data /*opaque*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_derived ( + krb5_context /*context*/, + const void */*str*/, + size_t /*len*/, + krb5_enctype /*etype*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_salt ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + const char */*password*/, + krb5_salt /*salt*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_key_salt_opaque ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + const char */*password*/, + krb5_salt /*salt*/, + krb5_data /*opaque*/, + krb5_keyblock */*key*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_keytype ( + krb5_context /*context*/, + const char */*string*/, + krb5_keytype */*keytype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_salttype ( + krb5_context /*context*/, + krb5_enctype /*etype*/, + const char */*string*/, + krb5_salttype */*salttype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ticket_get_authorization_data_type ( + krb5_context /*context*/, + krb5_ticket */*ticket*/, + int /*type*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ticket_get_client ( + krb5_context /*context*/, + const krb5_ticket */*ticket*/, + krb5_principal */*client*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ticket_get_server ( + krb5_context /*context*/, + const krb5_ticket */*ticket*/, + krb5_principal */*server*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_timeofday ( + krb5_context /*context*/, + krb5_timestamp */*timeret*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + char **/*name*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_fixed ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + char */*name*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_fixed_short ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + char */*name*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_short ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + char **/*name*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_us_timeofday ( + krb5_context /*context*/, + krb5_timestamp */*sec*/, + int32_t */*usec*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vabort ( + krb5_context /*context*/, + krb5_error_code /*code*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__ ((noreturn, format (printf, 3, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vabortx ( + krb5_context /*context*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__ ((noreturn, format (printf, 2, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_ap_req ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + krb5_ap_req */*ap_req*/, + krb5_const_principal /*server*/, + krb5_keyblock */*keyblock*/, + krb5_flags /*flags*/, + krb5_flags */*ap_req_options*/, + krb5_ticket **/*ticket*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_ap_req2 ( + krb5_context /*context*/, + krb5_auth_context */*auth_context*/, + krb5_ap_req */*ap_req*/, + krb5_const_principal /*server*/, + krb5_keyblock */*keyblock*/, + krb5_flags /*flags*/, + krb5_flags */*ap_req_options*/, + krb5_ticket **/*ticket*/, + krb5_key_usage /*usage*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_authenticator_checksum ( + krb5_context /*context*/, + krb5_auth_context /*ac*/, + void */*data*/, + size_t /*len*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_checksum ( + krb5_context /*context*/, + krb5_crypto /*crypto*/, + krb5_key_usage /*usage*/, + void */*data*/, + size_t /*len*/, + Checksum */*cksum*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_init_creds ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_principal /*ap_req_server*/, + krb5_keytab /*ap_req_keytab*/, + krb5_ccache */*ccache*/, + krb5_verify_init_creds_opt */*options*/); + +void KRB5_LIB_FUNCTION +krb5_verify_init_creds_opt_init (krb5_verify_init_creds_opt */*options*/); + +void KRB5_LIB_FUNCTION +krb5_verify_init_creds_opt_set_ap_req_nofail ( + krb5_verify_init_creds_opt */*options*/, + int /*ap_req_nofail*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_init (krb5_verify_opt */*opt*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_ccache ( + krb5_verify_opt */*opt*/, + krb5_ccache /*ccache*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_flags ( + krb5_verify_opt */*opt*/, + unsigned int /*flags*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_keytab ( + krb5_verify_opt */*opt*/, + krb5_keytab /*keytab*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_secure ( + krb5_verify_opt */*opt*/, + krb5_boolean /*secure*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_set_service ( + krb5_verify_opt */*opt*/, + const char */*service*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_user ( + krb5_context /*context*/, + krb5_principal /*principal*/, + krb5_ccache /*ccache*/, + const char */*password*/, + krb5_boolean /*secure*/, + const char */*service*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_user_lrealm ( + krb5_context /*context*/, + krb5_principal /*principal*/, + krb5_ccache /*ccache*/, + const char */*password*/, + krb5_boolean /*secure*/, + const char */*service*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_user_opt ( + krb5_context /*context*/, + krb5_principal /*principal*/, + const char */*password*/, + krb5_verify_opt */*opt*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verr ( + krb5_context /*context*/, + int /*eval*/, + krb5_error_code /*code*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__ ((noreturn, format (printf, 4, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verrx ( + krb5_context /*context*/, + int /*eval*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__ ((noreturn, format (printf, 3, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vlog ( + krb5_context /*context*/, + krb5_log_facility */*fac*/, + int /*level*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__((format (printf, 4, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vlog_msg ( + krb5_context /*context*/, + krb5_log_facility */*fac*/, + char **/*reply*/, + int /*level*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__((format (printf, 5, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vset_error_string ( + krb5_context /*context*/, + const char */*fmt*/, + va_list /*args*/) + __attribute__ ((format (printf, 2, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vwarn ( + krb5_context /*context*/, + krb5_error_code /*code*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__ ((format (printf, 3, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vwarnx ( + krb5_context /*context*/, + const char */*fmt*/, + va_list /*ap*/) + __attribute__ ((format (printf, 2, 0))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_warn ( + krb5_context /*context*/, + krb5_error_code /*code*/, + const char */*fmt*/, + ...) + __attribute__ ((format (printf, 3, 4))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_warnx ( + krb5_context /*context*/, + const char */*fmt*/, + ...) + __attribute__ ((format (printf, 2, 3))); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_write_message ( + krb5_context /*context*/, + krb5_pointer /*p_fd*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_write_priv_message ( + krb5_context /*context*/, + krb5_auth_context /*ac*/, + krb5_pointer /*p_fd*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_write_safe_message ( + krb5_context /*context*/, + krb5_auth_context /*ac*/, + krb5_pointer /*p_fd*/, + krb5_data */*data*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_xfree (void */*ptr*/); + +#ifdef __cplusplus +} +#endif + +#endif /* __krb5_protos_h__ */ diff --git a/source4/heimdal/lib/krb5/krb5-v4compat.h b/source4/heimdal/lib/krb5/krb5-v4compat.h new file mode 100644 index 0000000000..1d092dcbc9 --- /dev/null +++ b/source4/heimdal/lib/krb5/krb5-v4compat.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +/* $Id: krb5-v4compat.h,v 1.6 2005/04/23 19:38:16 lha Exp $ */ + +#ifndef __KRB5_V4COMPAT_H__ +#define __KRB5_V4COMPAT_H__ + +/* + * This file must only be included with v4 compat glue stuff in + * heimdal sources. + * + * It MUST NOT be installed. + */ + +#define KRB_PROT_VERSION 4 + +#define AUTH_MSG_KDC_REQUEST (1<<1) +#define AUTH_MSG_KDC_REPLY (2<<1) +#define AUTH_MSG_APPL_REQUEST (3<<1) +#define AUTH_MSG_APPL_REQUEST_MUTUAL (4<<1) +#define AUTH_MSG_ERR_REPLY (5<<1) +#define AUTH_MSG_PRIVATE (6<<1) +#define AUTH_MSG_SAFE (7<<1) +#define AUTH_MSG_APPL_ERR (8<<1) +#define AUTH_MSG_KDC_FORWARD (9<<1) +#define AUTH_MSG_KDC_RENEW (10<<1) +#define AUTH_MSG_DIE (63<<1) + +/* values for kerb error codes */ + +#define KERB_ERR_OK 0 +#define KERB_ERR_NAME_EXP 1 +#define KERB_ERR_SERVICE_EXP 2 +#define KERB_ERR_AUTH_EXP 3 +#define KERB_ERR_PKT_VER 4 +#define KERB_ERR_NAME_MAST_KEY_VER 5 +#define KERB_ERR_SERV_MAST_KEY_VER 6 +#define KERB_ERR_BYTE_ORDER 7 +#define KERB_ERR_PRINCIPAL_UNKNOWN 8 +#define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9 +#define KERB_ERR_NULL_KEY 10 +#define KERB_ERR_TIMEOUT 11 + + +/* Error codes returned from the KDC */ +#define KDC_OK 0 /* Request OK */ +#define KDC_NAME_EXP 1 /* Principal expired */ +#define KDC_SERVICE_EXP 2 /* Service expired */ +#define KDC_AUTH_EXP 3 /* Auth expired */ +#define KDC_PKT_VER 4 /* Protocol version unknown */ +#define KDC_P_MKEY_VER 5 /* Wrong master key version */ +#define KDC_S_MKEY_VER 6 /* Wrong master key version */ +#define KDC_BYTE_ORDER 7 /* Byte order unknown */ +#define KDC_PR_UNKNOWN 8 /* Principal unknown */ +#define KDC_PR_N_UNIQUE 9 /* Principal not unique */ +#define KDC_NULL_KEY 10 /* Principal has null key */ +#define KDC_GEN_ERR 20 /* Generic error from KDC */ + +/* General definitions */ +#define KSUCCESS 0 +#define KFAILURE 255 + +/* Values returned by rd_ap_req */ +#define RD_AP_OK 0 /* Request authentic */ +#define RD_AP_UNDEC 31 /* Can't decode authenticator */ +#define RD_AP_EXP 32 /* Ticket expired */ +#define RD_AP_NYV 33 /* Ticket not yet valid */ +#define RD_AP_REPEAT 34 /* Repeated request */ +#define RD_AP_NOT_US 35 /* The ticket isn't for us */ +#define RD_AP_INCON 36 /* Request is inconsistent */ +#define RD_AP_TIME 37 /* delta_t too big */ +#define RD_AP_BADD 38 /* Incorrect net address */ +#define RD_AP_VERSION 39 /* protocol version mismatch */ +#define RD_AP_MSG_TYPE 40 /* invalid msg type */ +#define RD_AP_MODIFIED 41 /* message stream modified */ +#define RD_AP_ORDER 42 /* message out of order */ +#define RD_AP_UNAUTHOR 43 /* unauthorized request */ + +/* */ + +#define MAX_KTXT_LEN 1250 + +#define ANAME_SZ 40 +#define REALM_SZ 40 +#define SNAME_SZ 40 +#define INST_SZ 40 + +struct ktext { + unsigned int length; /* Length of the text */ + unsigned char dat[MAX_KTXT_LEN]; /* The data itself */ + u_int32_t mbz; /* zero to catch runaway strings */ +}; + +struct credentials { + char service[ANAME_SZ]; /* Service name */ + char instance[INST_SZ]; /* Instance */ + char realm[REALM_SZ]; /* Auth domain */ + char session[8]; /* Session key */ + int lifetime; /* Lifetime */ + int kvno; /* Key version number */ + struct ktext ticket_st; /* The ticket itself */ + int32_t issue_date; /* The issue time */ + char pname[ANAME_SZ]; /* Principal's name */ + char pinst[INST_SZ]; /* Principal's instance */ +}; + +#define TKTLIFENUMFIXED 64 +#define TKTLIFEMINFIXED 0x80 +#define TKTLIFEMAXFIXED 0xBF +#define TKTLIFENOEXPIRE 0xFF +#define MAXTKTLIFETIME (30*24*3600) /* 30 days */ +#ifndef NEVERDATE +#define NEVERDATE ((time_t)0x7fffffffL) +#endif + +#define KERB_ERR_NULL_KEY 10 + +#define CLOCK_SKEW 5*60 + +#ifndef TKT_ROOT +#define TKT_ROOT "/tmp/tkt" +#endif + +struct _krb5_krb_auth_data { + int8_t k_flags; /* Flags from ticket */ + char *pname; /* Principal's name */ + char *pinst; /* His Instance */ + char *prealm; /* His Realm */ + u_int32_t checksum; /* Data checksum (opt) */ + krb5_keyblock session; /* Session Key */ + unsigned char life; /* Life of ticket */ + u_int32_t time_sec; /* Time ticket issued */ + u_int32_t address; /* Address in ticket */ +}; + +time_t _krb5_krb_life_to_time (int, int); +int _krb5_krb_time_to_life (time_t, time_t); +krb5_error_code _krb5_krb_tf_setup (krb5_context, struct credentials *, + const char *, int); +krb5_error_code _krb5_krb_dest_tkt(krb5_context, const char *); + +#define krb_time_to_life _krb5_krb_time_to_life +#define krb_life_to_time _krb5_krb_life_to_time + +#endif /* __KRB5_V4COMPAT_H__ */ diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h new file mode 100644 index 0000000000..890a500caa --- /dev/null +++ b/source4/heimdal/lib/krb5/krb5.h @@ -0,0 +1,754 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +/* $Id: krb5.h,v 1.236 2005/06/11 00:05:24 lha Exp $ */ + +#ifndef __KRB5_H__ +#define __KRB5_H__ + +#include +#include + +#include +#include +#include +#include + +#include + +/* name confusion with MIT */ +#ifndef KRB5KDC_ERR_KEY_EXP +#define KRB5KDC_ERR_KEY_EXP KRB5KDC_ERR_KEY_EXPIRED +#endif + +/* simple constants */ + +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif + +typedef int krb5_boolean; + +typedef int32_t krb5_error_code; + +typedef int krb5_kvno; + +typedef u_int32_t krb5_flags; + +typedef void *krb5_pointer; +typedef const void *krb5_const_pointer; + +struct krb5_crypto_data; +typedef struct krb5_crypto_data *krb5_crypto; + +typedef CKSUMTYPE krb5_cksumtype; + +typedef Checksum krb5_checksum; + +typedef ENCTYPE krb5_enctype; + +typedef heim_octet_string krb5_data; + +/* PKINIT related forward declarations */ +struct ContentInfo; +struct krb5_pk_identity; +struct krb5_pk_cert; + +/* krb5_enc_data is a mit compat structure */ +typedef struct krb5_enc_data { + krb5_enctype enctype; + krb5_kvno kvno; + krb5_data ciphertext; +} krb5_enc_data; + +/* alternative names */ +enum { + ENCTYPE_NULL = ETYPE_NULL, + ENCTYPE_DES_CBC_CRC = ETYPE_DES_CBC_CRC, + ENCTYPE_DES_CBC_MD4 = ETYPE_DES_CBC_MD4, + ENCTYPE_DES_CBC_MD5 = ETYPE_DES_CBC_MD5, + ENCTYPE_DES3_CBC_MD5 = ETYPE_DES3_CBC_MD5, + ENCTYPE_OLD_DES3_CBC_SHA1 = ETYPE_OLD_DES3_CBC_SHA1, + ENCTYPE_SIGN_DSA_GENERATE = ETYPE_SIGN_DSA_GENERATE, + ENCTYPE_ENCRYPT_RSA_PRIV = ETYPE_ENCRYPT_RSA_PRIV, + ENCTYPE_ENCRYPT_RSA_PUB = ETYPE_ENCRYPT_RSA_PUB, + ENCTYPE_DES3_CBC_SHA1 = ETYPE_DES3_CBC_SHA1, + ENCTYPE_AES128_CTS_HMAC_SHA1_96 = ETYPE_AES128_CTS_HMAC_SHA1_96, + ENCTYPE_AES256_CTS_HMAC_SHA1_96 = ETYPE_AES256_CTS_HMAC_SHA1_96, + ENCTYPE_ARCFOUR_HMAC = ETYPE_ARCFOUR_HMAC_MD5, + ENCTYPE_ARCFOUR_HMAC_MD5 = ETYPE_ARCFOUR_HMAC_MD5, + ENCTYPE_ARCFOUR_HMAC_MD5_56 = ETYPE_ARCFOUR_HMAC_MD5_56, + ENCTYPE_ENCTYPE_PK_CROSS = ETYPE_ENCTYPE_PK_CROSS, + ENCTYPE_DES_CBC_NONE = ETYPE_DES_CBC_NONE, + ENCTYPE_DES3_CBC_NONE = ETYPE_DES3_CBC_NONE, + ENCTYPE_DES_CFB64_NONE = ETYPE_DES_CFB64_NONE, + ENCTYPE_DES_PCBC_NONE = ETYPE_DES_PCBC_NONE +}; + +typedef PADATA_TYPE krb5_preauthtype; + +typedef enum krb5_key_usage { + KRB5_KU_PA_ENC_TIMESTAMP = 1, + /* AS-REQ PA-ENC-TIMESTAMP padata timestamp, encrypted with the + client key (section 5.4.1) */ + KRB5_KU_TICKET = 2, + /* AS-REP Ticket and TGS-REP Ticket (includes tgs session key or + application session key), encrypted with the service key + (section 5.4.2) */ + KRB5_KU_AS_REP_ENC_PART = 3, + /* AS-REP encrypted part (includes tgs session key or application + session key), encrypted with the client key (section 5.4.2) */ + KRB5_KU_TGS_REQ_AUTH_DAT_SESSION = 4, + /* TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with the tgs + session key (section 5.4.1) */ + KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY = 5, + /* TGS-REQ KDC-REQ-BODY AuthorizationData, encrypted with the tgs + authenticator subkey (section 5.4.1) */ + KRB5_KU_TGS_REQ_AUTH_CKSUM = 6, + /* TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator cksum, keyed + with the tgs session key (sections 5.3.2, 5.4.1) */ + KRB5_KU_TGS_REQ_AUTH = 7, + /* TGS-REQ PA-TGS-REQ padata AP-REQ Authenticator (includes tgs + authenticator subkey), encrypted with the tgs session key + (section 5.3.2) */ + KRB5_KU_TGS_REP_ENC_PART_SESSION = 8, + /* TGS-REP encrypted part (includes application session key), + encrypted with the tgs session key (section 5.4.2) */ + KRB5_KU_TGS_REP_ENC_PART_SUB_KEY = 9, + /* TGS-REP encrypted part (includes application session key), + encrypted with the tgs authenticator subkey (section 5.4.2) */ + KRB5_KU_AP_REQ_AUTH_CKSUM = 10, + /* AP-REQ Authenticator cksum, keyed with the application session + key (section 5.3.2) */ + KRB5_KU_AP_REQ_AUTH = 11, + /* AP-REQ Authenticator (includes application authenticator + subkey), encrypted with the application session key (section + 5.3.2) */ + KRB5_KU_AP_REQ_ENC_PART = 12, + /* AP-REP encrypted part (includes application session subkey), + encrypted with the application session key (section 5.5.2) */ + KRB5_KU_KRB_PRIV = 13, + /* KRB-PRIV encrypted part, encrypted with a key chosen by the + application (section 5.7.1) */ + KRB5_KU_KRB_CRED = 14, + /* KRB-CRED encrypted part, encrypted with a key chosen by the + application (section 5.8.1) */ + KRB5_KU_KRB_SAFE_CKSUM = 15, + /* KRB-SAFE cksum, keyed with a key chosen by the application + (section 5.6.1) */ + KRB5_KU_OTHER_ENCRYPTED = 16, + /* Data which is defined in some specification outside of + Kerberos to be encrypted using an RFC1510 encryption type. */ + KRB5_KU_OTHER_CKSUM = 17, + /* Data which is defined in some specification outside of + Kerberos to be checksummed using an RFC1510 checksum type. */ + KRB5_KU_KRB_ERROR = 18, + /* Krb-error checksum */ + KRB5_KU_AD_KDC_ISSUED = 19, + /* AD-KDCIssued checksum */ + KRB5_KU_MANDATORY_TICKET_EXTENSION = 20, + /* Checksum for Mandatory Ticket Extensions */ + KRB5_KU_AUTH_DATA_TICKET_EXTENSION = 21, + /* Checksum in Authorization Data in Ticket Extensions */ + KRB5_KU_USAGE_SEAL = 22, + /* seal in GSSAPI krb5 mechanism */ + KRB5_KU_USAGE_SIGN = 23, + /* sign in GSSAPI krb5 mechanism */ + KRB5_KU_USAGE_SEQ = 24, + /* SEQ in GSSAPI krb5 mechanism */ + KRB5_KU_USAGE_ACCEPTOR_SEAL = 22, + /* acceptor sign in GSSAPI CFX krb5 mechanism */ + KRB5_KU_USAGE_ACCEPTOR_SIGN = 23, + /* acceptor seal in GSSAPI CFX krb5 mechanism */ + KRB5_KU_USAGE_INITIATOR_SEAL = 24, + /* initiator sign in GSSAPI CFX krb5 mechanism */ + KRB5_KU_USAGE_INITIATOR_SIGN = 25, + /* initiator seal in GSSAPI CFX krb5 mechanism */ + KRB5_KU_PA_SERVER_REFERRAL_DATA = 22, + /* encrypted server referral data */ + KRB5_KU_SAM_CHECKSUM = 25, + /* Checksum for the SAM-CHECKSUM field */ + KRB5_KU_SAM_ENC_TRACK_ID = 26, + /* Encryption of the SAM-TRACK-ID field */ + KRB5_KU_PA_SERVER_REFERRAL = 26, + /* Keyusage for the server referral in a TGS req */ + KRB5_KU_SAM_ENC_NONCE_SAD = 27 + /* Encryption of the SAM-NONCE-OR-SAD field */ +} krb5_key_usage; + +typedef krb5_key_usage krb5_keyusage; + +typedef enum krb5_salttype { + KRB5_PW_SALT = KRB5_PADATA_PW_SALT, + KRB5_AFS3_SALT = KRB5_PADATA_AFS3_SALT +}krb5_salttype; + +typedef struct krb5_salt { + krb5_salttype salttype; + krb5_data saltvalue; +} krb5_salt; + +typedef ETYPE_INFO krb5_preauthinfo; + +typedef struct { + krb5_preauthtype type; + krb5_preauthinfo info; /* list of preauthinfo for this type */ +} krb5_preauthdata_entry; + +typedef struct krb5_preauthdata { + unsigned len; + krb5_preauthdata_entry *val; +}krb5_preauthdata; + +typedef enum krb5_address_type { + KRB5_ADDRESS_INET = 2, + KRB5_ADDRESS_INET6 = 24, + KRB5_ADDRESS_ADDRPORT = 256, + KRB5_ADDRESS_IPPORT = 257 +} krb5_address_type; + +enum { + AP_OPTS_USE_SESSION_KEY = 1, + AP_OPTS_MUTUAL_REQUIRED = 2, + AP_OPTS_USE_SUBKEY = 4 /* library internal */ +}; + +typedef HostAddress krb5_address; + +typedef HostAddresses krb5_addresses; + +typedef enum krb5_keytype { + KEYTYPE_NULL = 0, + KEYTYPE_DES = 1, + KEYTYPE_DES3 = 7, + KEYTYPE_AES128 = 17, + KEYTYPE_AES256 = 18, + KEYTYPE_ARCFOUR = 23, + KEYTYPE_ARCFOUR_56 = 24, + KEYTYPE_RC2 = -0x1005, + KEYTYPE_AES192 = -0x1006 +} krb5_keytype; + +typedef EncryptionKey krb5_keyblock; + +typedef AP_REQ krb5_ap_req; + +struct krb5_cc_ops; + +#define KRB5_DEFAULT_CCFILE_ROOT "/tmp/krb5cc_" + +#define KRB5_DEFAULT_CCROOT "FILE:" KRB5_DEFAULT_CCFILE_ROOT + +#define KRB5_ACCEPT_NULL_ADDRESSES(C) \ + krb5_config_get_bool_default((C), NULL, TRUE, \ + "libdefaults", "accept_null_addresses", \ + NULL) + +typedef void *krb5_cc_cursor; + +typedef struct krb5_ccache_data { + const struct krb5_cc_ops *ops; + krb5_data data; +}krb5_ccache_data; + +typedef struct krb5_ccache_data *krb5_ccache; + +typedef struct krb5_context_data *krb5_context; + +typedef Realm krb5_realm; +typedef const char *krb5_const_realm; /* stupid language */ + +#define krb5_realm_length(r) strlen(r) +#define krb5_realm_data(r) (r) + +typedef Principal krb5_principal_data; +typedef struct Principal *krb5_principal; +typedef const struct Principal *krb5_const_principal; + +typedef time_t krb5_deltat; +typedef time_t krb5_timestamp; + +typedef struct krb5_times { + krb5_timestamp authtime; + krb5_timestamp starttime; + krb5_timestamp endtime; + krb5_timestamp renew_till; +} krb5_times; + +typedef union { + TicketFlags b; + krb5_flags i; +} krb5_ticket_flags; + +/* options for krb5_get_in_tkt() */ +#define KDC_OPT_FORWARDABLE (1 << 1) +#define KDC_OPT_FORWARDED (1 << 2) +#define KDC_OPT_PROXIABLE (1 << 3) +#define KDC_OPT_PROXY (1 << 4) +#define KDC_OPT_ALLOW_POSTDATE (1 << 5) +#define KDC_OPT_POSTDATED (1 << 6) +#define KDC_OPT_RENEWABLE (1 << 8) +#define KDC_OPT_REQUEST_ANONYMOUS (1 << 14) +#define KDC_OPT_DISABLE_TRANSITED_CHECK (1 << 26) +#define KDC_OPT_RENEWABLE_OK (1 << 27) +#define KDC_OPT_ENC_TKT_IN_SKEY (1 << 28) +#define KDC_OPT_RENEW (1 << 30) +#define KDC_OPT_VALIDATE (1 << 31) + +typedef union { + KDCOptions b; + krb5_flags i; +} krb5_kdc_flags; + +/* flags for krb5_verify_ap_req */ + +#define KRB5_VERIFY_AP_REQ_IGNORE_INVALID (1 << 0) + +#define KRB5_GC_CACHED (1U << 0) +#define KRB5_GC_USER_USER (1U << 1) +#define KRB5_GC_EXPIRED_OK (1U << 2) + +/* constants for compare_creds (and cc_retrieve_cred) */ +#define KRB5_TC_DONT_MATCH_REALM (1U << 31) +#define KRB5_TC_MATCH_KEYTYPE (1U << 30) +#define KRB5_TC_MATCH_KTYPE KRB5_TC_MATCH_KEYTYPE /* MIT name */ +#define KRB5_TC_MATCH_SRV_NAMEONLY (1 << 29) +#define KRB5_TC_MATCH_FLAGS_EXACT (1 << 28) +#define KRB5_TC_MATCH_FLAGS (1 << 27) +#define KRB5_TC_MATCH_TIMES_EXACT (1 << 26) +#define KRB5_TC_MATCH_TIMES (1 << 25) +#define KRB5_TC_MATCH_AUTHDATA (1 << 24) +#define KRB5_TC_MATCH_2ND_TKT (1 << 23) +#define KRB5_TC_MATCH_IS_SKEY (1 << 22) + +typedef AuthorizationData krb5_authdata; + +typedef KRB_ERROR krb5_error; + +typedef struct krb5_creds { + krb5_principal client; + krb5_principal server; + krb5_keyblock session; + krb5_times times; + krb5_data ticket; + krb5_data second_ticket; + krb5_authdata authdata; + krb5_addresses addresses; + krb5_ticket_flags flags; +} krb5_creds; + +typedef struct krb5_cc_ops { + const char *prefix; + const char* (*get_name)(krb5_context, krb5_ccache); + krb5_error_code (*resolve)(krb5_context, krb5_ccache *, const char *); + krb5_error_code (*gen_new)(krb5_context, krb5_ccache *); + krb5_error_code (*init)(krb5_context, krb5_ccache, krb5_principal); + krb5_error_code (*destroy)(krb5_context, krb5_ccache); + krb5_error_code (*close)(krb5_context, krb5_ccache); + krb5_error_code (*store)(krb5_context, krb5_ccache, krb5_creds*); + krb5_error_code (*retrieve)(krb5_context, krb5_ccache, + krb5_flags, const krb5_creds*, krb5_creds *); + krb5_error_code (*get_princ)(krb5_context, krb5_ccache, krb5_principal*); + krb5_error_code (*get_first)(krb5_context, krb5_ccache, krb5_cc_cursor *); + krb5_error_code (*get_next)(krb5_context, krb5_ccache, + krb5_cc_cursor*, krb5_creds*); + krb5_error_code (*end_get)(krb5_context, krb5_ccache, krb5_cc_cursor*); + krb5_error_code (*remove_cred)(krb5_context, krb5_ccache, + krb5_flags, krb5_creds*); + krb5_error_code (*set_flags)(krb5_context, krb5_ccache, krb5_flags); + int (*get_version)(krb5_context, krb5_ccache); +} krb5_cc_ops; + +struct krb5_log_facility; + +struct krb5_config_binding { + enum { krb5_config_string, krb5_config_list } type; + char *name; + struct krb5_config_binding *next; + union { + char *string; + struct krb5_config_binding *list; + void *generic; + } u; +}; + +typedef struct krb5_config_binding krb5_config_binding; + +typedef krb5_config_binding krb5_config_section; + +typedef struct krb5_context_data { + krb5_enctype *etypes; + krb5_enctype *etypes_des; + char **default_realms; + time_t max_skew; + time_t kdc_timeout; + unsigned max_retries; + int32_t kdc_sec_offset; + int32_t kdc_usec_offset; + krb5_config_section *cf; + struct et_list *et_list; + struct krb5_log_facility *warn_dest; + krb5_cc_ops *cc_ops; + int num_cc_ops; + const char *http_proxy; + const char *time_fmt; + krb5_boolean log_utc; + const char *default_keytab; + const char *default_keytab_modify; + krb5_boolean use_admin_kdc; + krb5_addresses *extra_addresses; + krb5_boolean scan_interfaces; /* `ifconfig -a' */ + krb5_boolean srv_lookup; /* do SRV lookups */ + krb5_boolean srv_try_txt; /* try TXT records also */ + int32_t fcache_vno; /* create cache files w/ this + version */ + int num_kt_types; /* # of registered keytab types */ + struct krb5_keytab_data *kt_types; /* registered keytab types */ + const char *date_fmt; + char *error_string; + char error_buf[256]; + krb5_addresses *ignore_addresses; + char *default_cc_name; + int pkinit_flags; + void *mutex; /* protects error_string/error_buf */ + int large_msg_size; +} krb5_context_data; + +enum { + KRB5_PKINIT_WIN2K = 1, /* wire compatible with Windows 2k */ + KRB5_PKINIT_PACKET_CABLE = 2 /* use packet cable standard */ +}; + +typedef struct krb5_ticket { + EncTicketPart ticket; + krb5_principal client; + krb5_principal server; +} krb5_ticket; + +typedef Authenticator krb5_authenticator_data; + +typedef krb5_authenticator_data *krb5_authenticator; + +struct krb5_rcache_data; +typedef struct krb5_rcache_data *krb5_rcache; +typedef Authenticator krb5_donot_replay; + +#define KRB5_STORAGE_HOST_BYTEORDER 0x01 /* old */ +#define KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS 0x02 +#define KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE 0x04 +#define KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE 0x08 +#define KRB5_STORAGE_BYTEORDER_MASK 0x60 +#define KRB5_STORAGE_BYTEORDER_BE 0x00 /* default */ +#define KRB5_STORAGE_BYTEORDER_LE 0x20 +#define KRB5_STORAGE_BYTEORDER_HOST 0x40 +#define KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER 0x80 + +struct krb5_storage_data; +typedef struct krb5_storage_data krb5_storage; + +typedef struct krb5_keytab_entry { + krb5_principal principal; + krb5_kvno vno; + krb5_keyblock keyblock; + u_int32_t timestamp; +} krb5_keytab_entry; + +typedef struct krb5_kt_cursor { + int fd; + krb5_storage *sp; + void *data; +} krb5_kt_cursor; + +struct krb5_keytab_data; + +typedef struct krb5_keytab_data *krb5_keytab; + +#define KRB5_KT_PREFIX_MAX_LEN 30 + +struct krb5_keytab_data { + const char *prefix; + krb5_error_code (*resolve)(krb5_context, const char*, krb5_keytab); + krb5_error_code (*get_name)(krb5_context, krb5_keytab, char*, size_t); + krb5_error_code (*close)(krb5_context, krb5_keytab); + krb5_error_code (*get)(krb5_context, krb5_keytab, krb5_const_principal, + krb5_kvno, krb5_enctype, krb5_keytab_entry*); + krb5_error_code (*start_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*); + krb5_error_code (*next_entry)(krb5_context, krb5_keytab, + krb5_keytab_entry*, krb5_kt_cursor*); + krb5_error_code (*end_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*); + krb5_error_code (*add)(krb5_context, krb5_keytab, krb5_keytab_entry*); + krb5_error_code (*remove)(krb5_context, krb5_keytab, krb5_keytab_entry*); + void *data; + int32_t version; +}; + +typedef struct krb5_keytab_data krb5_kt_ops; + +struct krb5_keytab_key_proc_args { + krb5_keytab keytab; + krb5_principal principal; +}; + +typedef struct krb5_keytab_key_proc_args krb5_keytab_key_proc_args; + +typedef struct krb5_replay_data { + krb5_timestamp timestamp; + int32_t usec; + u_int32_t seq; +} krb5_replay_data; + +/* flags for krb5_auth_con_setflags */ +enum { + KRB5_AUTH_CONTEXT_DO_TIME = 1, + KRB5_AUTH_CONTEXT_RET_TIME = 2, + KRB5_AUTH_CONTEXT_DO_SEQUENCE = 4, + KRB5_AUTH_CONTEXT_RET_SEQUENCE = 8, + KRB5_AUTH_CONTEXT_PERMIT_ALL = 16, + KRB5_AUTH_CONTEXT_USE_SUBKEY = 32, + KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED = 64 +}; + +/* flags for krb5_auth_con_genaddrs */ +enum { + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_ADDR = 1, + KRB5_AUTH_CONTEXT_GENERATE_LOCAL_FULL_ADDR = 3, + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_ADDR = 4, + KRB5_AUTH_CONTEXT_GENERATE_REMOTE_FULL_ADDR = 12 +}; + +typedef struct krb5_auth_context_data { + unsigned int flags; + + krb5_address *local_address; + krb5_address *remote_address; + int16_t local_port; + int16_t remote_port; + krb5_keyblock *keyblock; + krb5_keyblock *local_subkey; + krb5_keyblock *remote_subkey; + + u_int32_t local_seqnumber; + u_int32_t remote_seqnumber; + + krb5_authenticator authenticator; + + krb5_pointer i_vector; + + krb5_rcache rcache; + + krb5_keytype keytype; /* ¿requested key type ? */ + krb5_cksumtype cksumtype; /* ¡requested checksum type! */ + +}krb5_auth_context_data, *krb5_auth_context; + +typedef struct { + KDC_REP kdc_rep; + EncKDCRepPart enc_part; + KRB_ERROR error; +} krb5_kdc_rep; + +extern const char *heimdal_version, *heimdal_long_version; + +typedef void (*krb5_log_log_func_t)(const char*, const char*, void*); +typedef void (*krb5_log_close_func_t)(void*); + +typedef struct krb5_log_facility { + char *program; + int len; + struct facility *val; +} krb5_log_facility; + +typedef EncAPRepPart krb5_ap_rep_enc_part; + +#define KRB5_RECVAUTH_IGNORE_VERSION 1 + +#define KRB5_SENDAUTH_VERSION "KRB5_SENDAUTH_V1.0" + +#define KRB5_TGS_NAME_SIZE (6) +#define KRB5_TGS_NAME ("krbtgt") + +/* variables */ + +extern const char *krb5_config_file; +extern const char *krb5_defkeyname; + +typedef enum { + KRB5_PROMPT_TYPE_PASSWORD = 0x1, + KRB5_PROMPT_TYPE_NEW_PASSWORD = 0x2, + KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN = 0x3, + KRB5_PROMPT_TYPE_PREAUTH = 0x4 +} krb5_prompt_type; + +typedef struct _krb5_prompt { + const char *prompt; + int hidden; + krb5_data *reply; + krb5_prompt_type type; +} krb5_prompt; + +typedef int (*krb5_prompter_fct)(krb5_context context, + void *data, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[]); +typedef krb5_error_code (*krb5_key_proc)(krb5_context context, + krb5_enctype type, + krb5_salt salt, + krb5_const_pointer keyseed, + krb5_keyblock **key); +typedef krb5_error_code (*krb5_decrypt_proc)(krb5_context context, + krb5_keyblock *key, + krb5_key_usage usage, + krb5_const_pointer decrypt_arg, + krb5_kdc_rep *dec_rep); +typedef krb5_error_code (*krb5_s2k_proc)(krb5_context context, + krb5_enctype type, + krb5_const_pointer keyseed, + krb5_salt salt, + krb5_data *s2kparms, + krb5_keyblock **key); + +struct _krb5_get_init_creds_opt_private; + +typedef struct _krb5_get_init_creds_opt { + krb5_flags flags; + krb5_deltat tkt_life; + krb5_deltat renew_life; + int forwardable; + int proxiable; + int anonymous; + krb5_enctype *etype_list; + int etype_list_length; + krb5_addresses *address_list; + /* XXX the next three should not be used, as they may be + removed later */ + krb5_preauthtype *preauth_list; + int preauth_list_length; + krb5_data *salt; + struct _krb5_get_init_creds_opt_private *private; +} krb5_get_init_creds_opt; + +#define KRB5_GET_INIT_CREDS_OPT_TKT_LIFE 0x0001 +#define KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE 0x0002 +#define KRB5_GET_INIT_CREDS_OPT_FORWARDABLE 0x0004 +#define KRB5_GET_INIT_CREDS_OPT_PROXIABLE 0x0008 +#define KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST 0x0010 +#define KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST 0x0020 +#define KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST 0x0040 +#define KRB5_GET_INIT_CREDS_OPT_SALT 0x0080 +#define KRB5_GET_INIT_CREDS_OPT_ANONYMOUS 0x0100 +#define KRB5_GET_INIT_CREDS_OPT_DISABLE_TRANSITED_CHECK 0x0200 + +typedef struct _krb5_verify_init_creds_opt { + krb5_flags flags; + int ap_req_nofail; +} krb5_verify_init_creds_opt; + +#define KRB5_VERIFY_INIT_CREDS_OPT_AP_REQ_NOFAIL 0x0001 + +typedef struct krb5_verify_opt { + unsigned int flags; + krb5_ccache ccache; + krb5_keytab keytab; + krb5_boolean secure; + const char *service; +} krb5_verify_opt; + +#define KRB5_VERIFY_LREALMS 1 +#define KRB5_VERIFY_NO_ADDRESSES 2 + +extern const krb5_cc_ops krb5_acc_ops; +extern const krb5_cc_ops krb5_fcc_ops; +extern const krb5_cc_ops krb5_mcc_ops; +extern const krb5_cc_ops krb5_kcm_ops; + +extern const krb5_kt_ops krb5_fkt_ops; +extern const krb5_kt_ops krb5_wrfkt_ops; +extern const krb5_kt_ops krb5_javakt_ops; +extern const krb5_kt_ops krb5_mkt_ops; +extern const krb5_kt_ops krb5_mktw_ops; +extern const krb5_kt_ops krb5_akf_ops; +extern const krb5_kt_ops krb4_fkt_ops; +extern const krb5_kt_ops krb5_srvtab_fkt_ops; +extern const krb5_kt_ops krb5_any_ops; + +#define KRB5_KPASSWD_VERS_CHANGEPW 1 +#define KRB5_KPASSWD_VERS_SETPW 0xff80 + +#define KRB5_KPASSWD_SUCCESS 0 +#define KRB5_KPASSWD_MALFORMED 1 +#define KRB5_KPASSWD_HARDERROR 2 +#define KRB5_KPASSWD_AUTHERROR 3 +#define KRB5_KPASSWD_SOFTERROR 4 +#define KRB5_KPASSWD_ACCESSDENIED 5 +#define KRB5_KPASSWD_BAD_VERSION 6 +#define KRB5_KPASSWD_INITIAL_FLAG_NEEDED 7 + +#define KPASSWD_PORT 464 + +/* types for the new krbhst interface */ +struct krb5_krbhst_data; +typedef struct krb5_krbhst_data *krb5_krbhst_handle; + +#define KRB5_KRBHST_KDC 1 +#define KRB5_KRBHST_ADMIN 2 +#define KRB5_KRBHST_CHANGEPW 3 +#define KRB5_KRBHST_KRB524 4 + +typedef struct krb5_krbhst_info { + enum { KRB5_KRBHST_UDP, + KRB5_KRBHST_TCP, + KRB5_KRBHST_HTTP } proto; + unsigned short port; + unsigned short def_port; + struct addrinfo *ai; + struct krb5_krbhst_info *next; + char hostname[1]; /* has to come last */ +} krb5_krbhst_info; + +/* flags for krb5_krbhst_init_flags (and krb5_send_to_kdc_flags) */ +enum { + KRB5_KRBHST_FLAGS_MASTER = 1, + KRB5_KRBHST_FLAGS_LARGE_MSG = 2 +}; + +struct credentials; /* this is to keep the compiler happy */ +struct getargs; +struct sockaddr; + +#include + +#endif /* __KRB5_H__ */ + diff --git a/source4/heimdal/lib/krb5/krb5_ccapi.h b/source4/heimdal/lib/krb5/krb5_ccapi.h new file mode 100644 index 0000000000..00c30d7791 --- /dev/null +++ b/source4/heimdal/lib/krb5/krb5_ccapi.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +/* $Id: krb5_ccapi.h,v 1.1 2004/09/11 04:00:42 lha Exp $ */ + +#ifndef KRB5_CCAPI_H +#define KRB5_CCAPI_H 1 + +#include + +enum { + cc_credentials_v5 = 2 +}; + +enum { + ccapi_version_3 = 3 +}; + +enum { + ccNoError = 0, + + ccIteratorEnd = 201, + ccErrBadParam, + ccErrNoMem, + ccErrInvalidContext, + ccErrInvalidCCache, + + ccErrInvalidString, /* 206 */ + ccErrInvalidCredentials, + ccErrInvalidCCacheIterator, + ccErrInvalidCredentialsIterator, + ccErrInvalidLock, + + ccErrBadName, /* 211 */ + ccErrBadCredentialsVersion, + ccErrBadAPIVersion, + ccErrContextLocked, + ccErrContextUnlocked, + + ccErrCCacheLocked, /* 216 */ + ccErrCCacheUnlocked, + ccErrBadLockType, + ccErrNeverDefault, + ccErrCredentialsNotFound, + + ccErrCCacheNotFound, /* 221 */ + ccErrContextNotFound, + ccErrServerUnavailable, + ccErrServerInsecure, + ccErrServerCantBecomeUID, + + ccErrTimeOffsetNotSet /* 226 */ +}; + +typedef int32_t cc_int32; +typedef u_int32_t cc_uint32; +typedef struct cc_context_t *cc_context_t; +typedef struct cc_ccache_t *cc_ccache_t; +typedef struct cc_ccache_iterator_t *cc_ccache_iterator_t; +typedef struct cc_credentials_v5_t cc_credentials_v5_t; +typedef struct cc_credentials_t *cc_credentials_t; +typedef struct cc_credentials_iterator_t *cc_credentials_iterator_t; +typedef struct cc_string_t *cc_string_t; +typedef time_t cc_time_t; + +typedef struct cc_data { + cc_uint32 type; + cc_uint32 length; + void *data; +} cc_data; + +struct cc_credentials_v5_t { + char *client; + char *server; + cc_data keyblock; + cc_time_t authtime; + cc_time_t starttime; + cc_time_t endtime; + cc_time_t renew_till; + cc_uint32 is_skey; + cc_uint32 ticket_flags; /* XXX ticket flags undefined */ + cc_data **addresses; + cc_data ticket; + cc_data second_ticket; + cc_data **authdata; +}; + + +typedef struct cc_string_functions { + cc_int32 (*release)(cc_string_t); +} cc_string_functions; + +struct cc_string_t { + const char *data; + const cc_string_functions *func; +}; + +typedef struct cc_credentials_union { + cc_int32 version; + union { + cc_credentials_v5_t* credentials_v5; + } credentials; +} cc_credentials_union; + +struct cc_credentials_functions { + cc_int32 (*release)(cc_credentials_t); + cc_int32 (*compare)(cc_credentials_t, cc_credentials_t, cc_uint32*); +}; + +struct cc_credentials_t { + const cc_credentials_union* data; + const struct cc_credentials_functions* func; +}; + +struct cc_credentials_iterator_functions { + cc_int32 (*release)(cc_credentials_iterator_t); + cc_int32 (*next)(cc_credentials_iterator_t, cc_credentials_t*); +}; + +struct cc_credentials_iterator_t { + const struct cc_credentials_iterator_functions *func; +}; + +struct cc_ccache_iterator_functions { + cc_int32 (*release) (cc_ccache_iterator_t); + cc_int32 (*next)(cc_ccache_iterator_t, cc_ccache_t*); +}; + +struct cc_ccache_iterator_t { + const struct cc_ccache_iterator_functions* func; +}; + +typedef struct cc_ccache_functions { + cc_int32 (*release)(cc_ccache_t); + cc_int32 (*destroy)(cc_ccache_t); + cc_int32 (*set_default)(cc_ccache_t); + cc_int32 (*get_credentials_version)(cc_ccache_t, cc_uint32*); + cc_int32 (*get_name)(cc_ccache_t ccache,cc_string_t*); + cc_int32 (*get_principal)(cc_ccache_t, cc_uint32, cc_string_t*); + cc_int32 (*set_principal)(cc_ccache_t, cc_uint32, const char*); + cc_int32 (*store_credentials)(cc_ccache_t, const cc_credentials_union*); + cc_int32 (*remove_credentials)(cc_ccache_t, cc_credentials_t); + cc_int32 (*new_credentials_iterator)(cc_ccache_t, + cc_credentials_iterator_t*); + cc_int32 (*move)(cc_ccache_t source, cc_ccache_t); + cc_int32 (*lock)(cc_ccache_t, cc_uint32, cc_uint32); + cc_int32 (*unlock)(cc_ccache_t); + cc_int32 (*get_last_default_time)(cc_ccache_t, cc_time_t*); + cc_int32 (*get_change_time)(cc_ccache_t ccache, cc_time_t*); + cc_int32 (*compare)(cc_ccache_t, cc_ccache_t, cc_uint32*); + cc_int32 (*get_kdc_time_offset)(cc_ccache_t, cc_int32, cc_time_t *); + cc_int32 (*set_kdc_time_offset)(cc_ccache_t, cc_int32, cc_time_t); + cc_int32 (*clear_kdc_time_offset)(cc_ccache_t, cc_int32); +} cc_ccache_functions; + +struct cc_ccache_t { + const cc_ccache_functions *func; +}; + +struct cc_context_functions { + cc_int32 (*release)(cc_context_t); + cc_int32 (*get_change_time)(cc_context_t, cc_time_t *); + cc_int32 (*get_default_ccache_name)(cc_context_t, cc_string_t*); + cc_int32 (*open_ccache)(cc_context_t, const char*, cc_ccache_t *); + cc_int32 (*open_default_ccache)(cc_context_t, cc_ccache_t*); + cc_int32 (*create_ccache)(cc_context_t,const char*, cc_uint32, + const char*, cc_ccache_t*); + cc_int32 (*create_default_ccache)(cc_context_t, cc_uint32, + const char*, cc_ccache_t*); + cc_int32 (*create_new_ccache)(cc_context_t, cc_uint32, + const char*, cc_ccache_t*); + cc_int32 (*new_ccache_iterator)(cc_context_t, cc_ccache_iterator_t*); + cc_int32 (*lock)(cc_context_t, cc_uint32, cc_uint32); + cc_int32 (*unlock)(cc_context_t); + cc_int32 (*compare)(cc_context_t, cc_context_t, cc_uint32*); +}; + +struct cc_context_t { + const struct cc_context_functions* func; +}; + +typedef cc_int32 +(*cc_initialize_func)(cc_context_t*, cc_int32, cc_int32 *, char const **); + +#endif /* KRB5_CCAPI_H */ diff --git a/source4/heimdal/lib/krb5/krb5_err.et b/source4/heimdal/lib/krb5/krb5_err.et new file mode 100644 index 0000000000..1257b074fb --- /dev/null +++ b/source4/heimdal/lib/krb5/krb5_err.et @@ -0,0 +1,258 @@ +# +# Error messages for the krb5 library +# +# This might look like a com_err file, but is not +# +id "$Id: krb5_err.et,v 1.12 2004/10/14 15:30:29 lha Exp $" + +error_table krb5 + +prefix KRB5KDC_ERR +error_code NONE, "No error" +error_code NAME_EXP, "Client's entry in database has expired" +error_code SERVICE_EXP, "Server's entry in database has expired" +error_code BAD_PVNO, "Requested protocol version not supported" +error_code C_OLD_MAST_KVNO, "Client's key is encrypted in an old master key" +error_code S_OLD_MAST_KVNO, "Server's key is encrypted in an old master key" +error_code C_PRINCIPAL_UNKNOWN, "Client not found in Kerberos database" +error_code S_PRINCIPAL_UNKNOWN, "Server not found in Kerberos database" +error_code PRINCIPAL_NOT_UNIQUE,"Principal has multiple entries in Kerberos database" +error_code NULL_KEY, "Client or server has a null key" +error_code CANNOT_POSTDATE, "Ticket is ineligible for postdating" +error_code NEVER_VALID, "Requested effective lifetime is negative or too short" +error_code POLICY, "KDC policy rejects request" +error_code BADOPTION, "KDC can't fulfill requested option" +error_code ETYPE_NOSUPP, "KDC has no support for encryption type" +error_code SUMTYPE_NOSUPP, "KDC has no support for checksum type" +error_code PADATA_TYPE_NOSUPP, "KDC has no support for padata type" +error_code TRTYPE_NOSUPP, "KDC has no support for transited type" +error_code CLIENT_REVOKED, "Clients credentials have been revoked" +error_code SERVICE_REVOKED, "Credentials for server have been revoked" +error_code TGT_REVOKED, "TGT has been revoked" +error_code CLIENT_NOTYET, "Client not yet valid - try again later" +error_code SERVICE_NOTYET, "Server not yet valid - try again later" +error_code KEY_EXPIRED, "Password has expired" +error_code PREAUTH_FAILED, "Preauthentication failed" +error_code PREAUTH_REQUIRED, "Additional pre-authentication required" +error_code SERVER_NOMATCH, "Requested server and ticket don't match" + +# 27-30 are reserved +index 31 +prefix KRB5KRB_AP +error_code ERR_BAD_INTEGRITY, "Decrypt integrity check failed" +error_code ERR_TKT_EXPIRED, "Ticket expired" +error_code ERR_TKT_NYV, "Ticket not yet valid" +error_code ERR_REPEAT, "Request is a replay" +error_code ERR_NOT_US, "The ticket isn't for us" +error_code ERR_BADMATCH, "Ticket/authenticator don't match" +error_code ERR_SKEW, "Clock skew too great" +error_code ERR_BADADDR, "Incorrect net address" +error_code ERR_BADVERSION, "Protocol version mismatch" +error_code ERR_MSG_TYPE, "Invalid message type" +error_code ERR_MODIFIED, "Message stream modified" +error_code ERR_BADORDER, "Message out of order" +error_code ERR_ILL_CR_TKT, "Invalid cross-realm ticket" +error_code ERR_BADKEYVER, "Key version is not available" +error_code ERR_NOKEY, "Service key not available" +error_code ERR_MUT_FAIL, "Mutual authentication failed" +error_code ERR_BADDIRECTION, "Incorrect message direction" +error_code ERR_METHOD, "Alternative authentication method required" +error_code ERR_BADSEQ, "Incorrect sequence number in message" +error_code ERR_INAPP_CKSUM, "Inappropriate type of checksum in message" +error_code PATH_NOT_ACCEPTED, "Policy rejects transited path" + +prefix KRB5KRB_ERR +error_code RESPONSE_TOO_BIG, "Response too big for UDP, retry with TCP" +# 53-59 are reserved +index 60 +error_code GENERIC, "Generic error (see e-text)" +error_code FIELD_TOOLONG, "Field is too long for this implementation" + +# pkinit +index 62 +prefix KRB5_KDC_ERR +error_code CLIENT_NOT_TRUSTED, "Client not trusted" +error_code KDC_NOT_TRUSTED, "KDC not trusted" +error_code INVALID_SIG, "Invalid signature" +error_code KEY_SIZE, "Key size too small/key too weak" +error_code CERTIFICATE_MISMATCH, "Certificate mismatch" + +prefix KRB5_AP_ERR +error_code USER_TO_USER_REQUIRED, "User to user required" + +index 70 +prefix KRB5_KDC_ERROR +error_code CANT_VERIFY_CERTIFICATE, "Cannot verify certificate" +error_code INVALID_CERTIFICATE, "Invalid certificate" +error_code REVOKED_CERTIFICATE, "Revoked certificate" +error_code REVOCATION_STATUS_UNKNOWN, "Revocation status unknown" +error_code REVOCATION_STATUS_UNAVAILABLE, "Revocation status unknown" +error_code CLIENT_NAME_MISMATCH, "Client name mismatch" +index 75 +error_code KDC_NAME_MISMATCH, "KDC name mismatch" + +# 76-79 are reserved + +index 80 +prefix KRB5_IAKERB +error_code ERR_KDC_NOT_FOUND, "IAKERB proxy could not find a KDC" +error_code ERR_KDC_NO_RESPONSE, "IAKERB proxy never reeived a response from a KDC" + +# 82-127 are reserved + +index 128 +prefix +error_code KRB5_ERR_RCSID, "$Id: krb5_err.et,v 1.12 2004/10/14 15:30:29 lha Exp $" + +error_code KRB5_LIBOS_BADLOCKFLAG, "Invalid flag for file lock mode" +error_code KRB5_LIBOS_CANTREADPWD, "Cannot read password" +error_code KRB5_LIBOS_BADPWDMATCH, "Password mismatch" +error_code KRB5_LIBOS_PWDINTR, "Password read interrupted" + +error_code KRB5_PARSE_ILLCHAR, "Invalid character in component name" +error_code KRB5_PARSE_MALFORMED, "Malformed representation of principal" + +error_code KRB5_CONFIG_CANTOPEN, "Can't open/find configuration file" +error_code KRB5_CONFIG_BADFORMAT, "Improper format of configuration file" +error_code KRB5_CONFIG_NOTENUFSPACE, "Insufficient space to return complete information" + +error_code KRB5_BADMSGTYPE, "Invalid message type specified for encoding" + +error_code KRB5_CC_BADNAME, "Credential cache name malformed" +error_code KRB5_CC_UNKNOWN_TYPE, "Unknown credential cache type" +error_code KRB5_CC_NOTFOUND, "Matching credential not found" +error_code KRB5_CC_END, "End of credential cache reached" + +error_code KRB5_NO_TKT_SUPPLIED, "Request did not supply a ticket" + +error_code KRB5KRB_AP_WRONG_PRINC, "Wrong principal in request" +error_code KRB5KRB_AP_ERR_TKT_INVALID, "Ticket has invalid flag set" + +error_code KRB5_PRINC_NOMATCH, "Requested principal and ticket don't match" +error_code KRB5_KDCREP_MODIFIED, "KDC reply did not match expectations" +error_code KRB5_KDCREP_SKEW, "Clock skew too great in KDC reply" +error_code KRB5_IN_TKT_REALM_MISMATCH, "Client/server realm mismatch in initial ticket request" + +error_code KRB5_PROG_ETYPE_NOSUPP, "Program lacks support for encryption type" +error_code KRB5_PROG_KEYTYPE_NOSUPP, "Program lacks support for key type" +error_code KRB5_WRONG_ETYPE, "Requested encryption type not used in message" +error_code KRB5_PROG_SUMTYPE_NOSUPP, "Program lacks support for checksum type" + +error_code KRB5_REALM_UNKNOWN, "Cannot find KDC for requested realm" +error_code KRB5_SERVICE_UNKNOWN, "Kerberos service unknown" +error_code KRB5_KDC_UNREACH, "Cannot contact any KDC for requested realm" +error_code KRB5_NO_LOCALNAME, "No local name found for principal name" + +error_code KRB5_MUTUAL_FAILED, "Mutual authentication failed" + +# some of these should be combined/supplanted by system codes + +error_code KRB5_RC_TYPE_EXISTS, "Replay cache type is already registered" +error_code KRB5_RC_MALLOC, "No more memory to allocate (in replay cache code)" +error_code KRB5_RC_TYPE_NOTFOUND, "Replay cache type is unknown" +error_code KRB5_RC_UNKNOWN, "Generic unknown RC error" +error_code KRB5_RC_REPLAY, "Message is a replay" +error_code KRB5_RC_IO, "Replay I/O operation failed XXX" +error_code KRB5_RC_NOIO, "Replay cache type does not support non-volatile storage" +error_code KRB5_RC_PARSE, "Replay cache name parse/format error" + +error_code KRB5_RC_IO_EOF, "End-of-file on replay cache I/O" +error_code KRB5_RC_IO_MALLOC, "No more memory to allocate (in replay cache I/O code)" +error_code KRB5_RC_IO_PERM, "Permission denied in replay cache code" +error_code KRB5_RC_IO_IO, "I/O error in replay cache i/o code" +error_code KRB5_RC_IO_UNKNOWN, "Generic unknown RC/IO error" +error_code KRB5_RC_IO_SPACE, "Insufficient system space to store replay information" + +error_code KRB5_TRANS_CANTOPEN, "Can't open/find realm translation file" +error_code KRB5_TRANS_BADFORMAT, "Improper format of realm translation file" + +error_code KRB5_LNAME_CANTOPEN, "Can't open/find lname translation database" +error_code KRB5_LNAME_NOTRANS, "No translation available for requested principal" +error_code KRB5_LNAME_BADFORMAT, "Improper format of translation database entry" + +error_code KRB5_CRYPTO_INTERNAL, "Cryptosystem internal error" + +error_code KRB5_KT_BADNAME, "Key table name malformed" +error_code KRB5_KT_UNKNOWN_TYPE, "Unknown Key table type" +error_code KRB5_KT_NOTFOUND, "Key table entry not found" +error_code KRB5_KT_END, "End of key table reached" +error_code KRB5_KT_NOWRITE, "Cannot write to specified key table" +error_code KRB5_KT_IOERR, "Error writing to key table" + +error_code KRB5_NO_TKT_IN_RLM, "Cannot find ticket for requested realm" +error_code KRB5DES_BAD_KEYPAR, "DES key has bad parity" +error_code KRB5DES_WEAK_KEY, "DES key is a weak key" + +error_code KRB5_BAD_ENCTYPE, "Bad encryption type" +error_code KRB5_BAD_KEYSIZE, "Key size is incompatible with encryption type" +error_code KRB5_BAD_MSIZE, "Message size is incompatible with encryption type" + +error_code KRB5_CC_TYPE_EXISTS, "Credentials cache type is already registered." +error_code KRB5_KT_TYPE_EXISTS, "Key table type is already registered." + +error_code KRB5_CC_IO, "Credentials cache I/O operation failed XXX" +error_code KRB5_FCC_PERM, "Credentials cache file permissions incorrect" +error_code KRB5_FCC_NOFILE, "No credentials cache file found" +error_code KRB5_FCC_INTERNAL, "Internal file credentials cache error" +error_code KRB5_CC_WRITE, "Error writing to credentials cache file" +error_code KRB5_CC_NOMEM, "No more memory to allocate (in credentials cache code)" +error_code KRB5_CC_FORMAT, "Bad format in credentials cache" +error_code KRB5_CC_NOT_KTYPE, "No credentials found with supported encryption types" + +# errors for dual tgt library calls +error_code KRB5_INVALID_FLAGS, "Invalid KDC option combination (library internal error)" +error_code KRB5_NO_2ND_TKT, "Request missing second ticket" + +error_code KRB5_NOCREDS_SUPPLIED, "No credentials supplied to library routine" + +# errors for sendauth (and recvauth) + +error_code KRB5_SENDAUTH_BADAUTHVERS, "Bad sendauth version was sent" +error_code KRB5_SENDAUTH_BADAPPLVERS, "Bad application version was sent (via sendauth)" +error_code KRB5_SENDAUTH_BADRESPONSE, "Bad response (during sendauth exchange)" +error_code KRB5_SENDAUTH_REJECTED, "Server rejected authentication (during sendauth exchange)" + +# errors for preauthentication + +error_code KRB5_PREAUTH_BAD_TYPE, "Unsupported preauthentication type" +error_code KRB5_PREAUTH_NO_KEY, "Required preauthentication key not supplied" +error_code KRB5_PREAUTH_FAILED, "Generic preauthentication failure" + +# version number errors + +error_code KRB5_RCACHE_BADVNO, "Unsupported replay cache format version number" +error_code KRB5_CCACHE_BADVNO, "Unsupported credentials cache format version number" +error_code KRB5_KEYTAB_BADVNO, "Unsupported key table format version number" + +# +# + +error_code KRB5_PROG_ATYPE_NOSUPP, "Program lacks support for address type" +error_code KRB5_RC_REQUIRED, "Message replay detection requires rcache parameter" +error_code KRB5_ERR_BAD_HOSTNAME, "Hostname cannot be canonicalized" +error_code KRB5_ERR_HOST_REALM_UNKNOWN, "Cannot determine realm for host" +error_code KRB5_SNAME_UNSUPP_NAMETYPE, "Conversion to service principal undefined for name type" + +error_code KRB5KRB_AP_ERR_V4_REPLY, "Initial Ticket response appears to be Version 4" +error_code KRB5_REALM_CANT_RESOLVE, "Cannot resolve KDC for requested realm" +error_code KRB5_TKT_NOT_FORWARDABLE, "Requesting ticket can't get forwardable tickets" +error_code KRB5_FWD_BAD_PRINCIPAL, "Bad principal name while trying to forward credentials" + +error_code KRB5_GET_IN_TKT_LOOP, "Looping detected inside krb5_get_in_tkt" +error_code KRB5_CONFIG_NODEFREALM, "Configuration file does not specify default realm" + +error_code KRB5_SAM_UNSUPPORTED, "Bad SAM flags in obtain_sam_padata" +error_code KRB5_SAM_INVALID_ETYPE, "Invalid encryption type in SAM challenge" +error_code KRB5_SAM_NO_CHECKSUM, "Missing checksum in SAM challenge" +error_code KRB5_SAM_BAD_CHECKSUM, "Bad checksum in SAM challenge" + +index 238 +error_code KRB5_OBSOLETE_FN, "Program called an obsolete, deleted function" + +index 245 +error_code KRB5_ERR_BAD_S2K_PARAMS, "Invalid key generation parameters from KDC" +error_code KRB5_ERR_NO_SERVICE, "Service not available" +error_code KRB5_CC_NOSUPP, "Credential cache function not supported" +error_code KRB5_DELTAT_BADFORMAT, "Invalid format of Kerberos lifetime or clock skew string" + +end diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h new file mode 100644 index 0000000000..a64ccc586e --- /dev/null +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +/* $Id: krb5_locl.h,v 1.81 2005/05/29 14:28:39 lha Exp $ */ + +#ifndef __KRB5_LOCL_H__ +#define __KRB5_LOCL_H__ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_MMAN_H +#include +#endif +#ifdef HAVE_UNISTD_H +#include +#endif +#ifdef HAVE_FCNTL_H +#include +#endif + +#if defined(HAVE_SYS_IOCTL_H) && SunOS != 40 +#include +#endif +#ifdef HAVE_PWD_H +#undef _POSIX_PTHREAD_SEMANTICS +/* This gets us the 5-arg getpwnam_r on Solaris 9. */ +#define _POSIX_PTHREAD_SEMANTICS +#include +#endif + +#ifdef HAVE_SYS_PARAM_H +#include +#endif +#include +#ifdef HAVE_SYS_TIME_H +#include +#endif +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#ifdef HAVE_NETINET_IN_H +#include +#endif +#ifdef HAVE_NETINET_IN6_H +#include +#endif +#ifdef HAVE_NETINET6_IN6_H +#include +#endif +#ifdef HAVE_NETDB_H +#include +#endif +#ifdef _AIX +struct ether_addr; +struct mbuf; +struct sockaddr_dl; +#endif +#ifdef HAVE_ARPA_INET_H +#include +#endif +#ifdef HAVE_ARPA_NAMESER_H +#include +#endif +#ifdef HAVE_SYS_UIO_H +#include +#endif +#ifdef HAVE_SYS_FILIO_H +#include +#endif +#ifdef HAVE_SYS_FILE_H +#include +#endif + +#ifdef HAVE_CRYPT_H +#undef des_encrypt +#define des_encrypt wingless_pigs_mostly_fail_to_fly +#include +#undef des_encrypt +#endif + +#ifdef HAVE_DOOR_CREATE +#include +#endif + +#include +#include +#include + +#include "crypto-headers.h" + + +#include + +/* XXX glue for pkinit */ +struct krb5_pk_identity; +struct krb5_pk_cert; +struct ContentInfo; +typedef struct krb5_pk_init_ctx_data *krb5_pk_init_ctx; + +/* v4 glue */ +struct _krb5_krb_auth_data; + +#include + +#include +#include +#include +#include + +#include "heim_threads.h" + +#define ALLOC(X, N) (X) = calloc((N), sizeof(*(X))) +#define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0) + +/* should this be public? */ +#define KEYTAB_DEFAULT "ANY:FILE:" SYSCONFDIR "/krb5.keytab,krb4:" SYSCONFDIR "/srvtab" +#define KEYTAB_DEFAULT_MODIFY "FILE:" SYSCONFDIR "/krb5.keytab" + +#ifndef O_BINARY +#define O_BINARY 0 +#endif + +#define KRB5_BUFSIZ 1024 + +typedef enum { + KRB5_PA_PAC_DONT_CARE = 0, + KRB5_PA_PAC_REQ_TRUE, + KRB5_PA_PAC_REQ_FALSE +} krb5_get_init_creds_req_pac; + +struct _krb5_get_init_creds_opt_private { + int refcount; + /* ENC_TIMESTAMP */ + const char *password; + krb5_s2k_proc key_proc; + /* PA_PAC_REQUEST */ + krb5_get_init_creds_req_pac req_pac; + /* PKINIT */ + krb5_pk_init_ctx pk_init_ctx; + int canonicalize; +}; + +#endif /* __KRB5_LOCL_H__ */ diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c new file mode 100644 index 0000000000..49eee08ca5 --- /dev/null +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -0,0 +1,861 @@ +/* + * Copyright (c) 2001 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +#include + +RCSID("$Id: krbhst.c,v 1.52 2005/06/17 04:23:26 lha Exp $"); + +static int +string_to_proto(const char *string) +{ + if(strcasecmp(string, "udp") == 0) + return KRB5_KRBHST_UDP; + else if(strcasecmp(string, "tcp") == 0) + return KRB5_KRBHST_TCP; + else if(strcasecmp(string, "http") == 0) + return KRB5_KRBHST_HTTP; + return -1; +} + +/* + * set `res' and `count' to the result of looking up SRV RR in DNS for + * `proto', `proto', `realm' using `dns_type'. + * if `port' != 0, force that port number + */ + +static krb5_error_code +srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count, + const char *realm, const char *dns_type, + const char *proto, const char *service, int port) +{ + char domain[1024]; + struct dns_reply *r; + struct resource_record *rr; + int num_srv; + int proto_num; + int def_port; + + *res = NULL; + *count = 0; + + proto_num = string_to_proto(proto); + if(proto_num < 0) { + krb5_set_error_string(context, "unknown protocol `%s'", proto); + return EINVAL; + } + + if(proto_num == KRB5_KRBHST_HTTP) + def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80)); + else if(port == 0) + def_port = ntohs(krb5_getportbyname (context, service, proto, 88)); + else + def_port = port; + + snprintf(domain, sizeof(domain), "_%s._%s.%s.", service, proto, realm); + + r = dns_lookup(domain, dns_type); + if(r == NULL) + return KRB5_KDC_UNREACH; + + for(num_srv = 0, rr = r->head; rr; rr = rr->next) + if(rr->type == T_SRV) + num_srv++; + + *res = malloc(num_srv * sizeof(**res)); + if(*res == NULL) { + dns_free_data(r); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + dns_srv_order(r); + + for(num_srv = 0, rr = r->head; rr; rr = rr->next) + if(rr->type == T_SRV) { + krb5_krbhst_info *hi; + size_t len = strlen(rr->u.srv->target); + + hi = calloc(1, sizeof(*hi) + len); + if(hi == NULL) { + dns_free_data(r); + while(--num_srv >= 0) + free((*res)[num_srv]); + free(*res); + *res = NULL; + return ENOMEM; + } + (*res)[num_srv++] = hi; + + hi->proto = proto_num; + + hi->def_port = def_port; + if (port != 0) + hi->port = port; + else + hi->port = rr->u.srv->port; + + strlcpy(hi->hostname, rr->u.srv->target, len + 1); + } + + *count = num_srv; + + dns_free_data(r); + return 0; +} + + +struct krb5_krbhst_data { + char *realm; + unsigned int flags; + int def_port; + int port; /* hardwired port number if != 0 */ +#define KD_CONFIG 1 +#define KD_SRV_UDP 2 +#define KD_SRV_TCP 4 +#define KD_SRV_HTTP 8 +#define KD_FALLBACK 16 +#define KD_CONFIG_EXISTS 32 +#define KD_LARGE_MSG 64 + krb5_error_code (*get_next)(krb5_context, struct krb5_krbhst_data *, + krb5_krbhst_info**); + + unsigned int fallback_count; + + struct krb5_krbhst_info *hosts, **index, **end; +}; + +static krb5_boolean +krbhst_empty(const struct krb5_krbhst_data *kd) +{ + return kd->index == &kd->hosts; +} + +/* + * Return the default protocol for the `kd' (either TCP or UDP) + */ + +static int +krbhst_get_default_proto(struct krb5_krbhst_data *kd) +{ + if (kd->flags & KD_LARGE_MSG) + return KRB5_KRBHST_TCP; + return KRB5_KRBHST_UDP; +} + + +/* + * parse `spec' into a krb5_krbhst_info, defaulting the port to `def_port' + * and forcing it to `port' if port != 0 + */ + +static struct krb5_krbhst_info* +parse_hostspec(krb5_context context, struct krb5_krbhst_data *kd, + const char *spec, int def_port, int port) +{ + const char *p = spec; + struct krb5_krbhst_info *hi; + + hi = calloc(1, sizeof(*hi) + strlen(spec)); + if(hi == NULL) + return NULL; + + hi->proto = krbhst_get_default_proto(kd); + + if(strncmp(p, "http://", 7) == 0){ + hi->proto = KRB5_KRBHST_HTTP; + p += 7; + } else if(strncmp(p, "http/", 5) == 0) { + hi->proto = KRB5_KRBHST_HTTP; + p += 5; + def_port = ntohs(krb5_getportbyname (context, "http", "tcp", 80)); + }else if(strncmp(p, "tcp/", 4) == 0){ + hi->proto = KRB5_KRBHST_TCP; + p += 4; + } else if(strncmp(p, "udp/", 4) == 0) { + p += 4; + } + + if(strsep_copy(&p, ":", hi->hostname, strlen(spec) + 1) < 0) { + free(hi); + return NULL; + } + /* get rid of trailing /, and convert to lower case */ + hi->hostname[strcspn(hi->hostname, "/")] = '\0'; + strlwr(hi->hostname); + + hi->port = hi->def_port = def_port; + if(p != NULL) { + char *end; + hi->port = strtol(p, &end, 0); + if(end == p) { + free(hi); + return NULL; + } + } + if (port) + hi->port = port; + return hi; +} + +static void +free_krbhst_info(krb5_krbhst_info *hi) +{ + if (hi->ai != NULL) + freeaddrinfo(hi->ai); + free(hi); +} + +static void +append_host_hostinfo(struct krb5_krbhst_data *kd, struct krb5_krbhst_info *host) +{ + struct krb5_krbhst_info *h; + + for(h = kd->hosts; h; h = h->next) + if(h->proto == host->proto && + h->port == host->port && + strcmp(h->hostname, host->hostname) == 0) { + free_krbhst_info(host); + return; + } + *kd->end = host; + kd->end = &host->next; +} + +static krb5_error_code +append_host_string(krb5_context context, struct krb5_krbhst_data *kd, + const char *host, int def_port, int port) +{ + struct krb5_krbhst_info *hi; + + hi = parse_hostspec(context, kd, host, def_port, port); + if(hi == NULL) + return ENOMEM; + + append_host_hostinfo(kd, hi); + return 0; +} + +/* + * return a readable representation of `host' in `hostname, hostlen' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_format_string(krb5_context context, const krb5_krbhst_info *host, + char *hostname, size_t hostlen) +{ + const char *proto = ""; + char portstr[7] = ""; + if(host->proto == KRB5_KRBHST_TCP) + proto = "tcp/"; + else if(host->proto == KRB5_KRBHST_HTTP) + proto = "http://"; + if(host->port != host->def_port) + snprintf(portstr, sizeof(portstr), ":%d", host->port); + snprintf(hostname, hostlen, "%s%s%s", proto, host->hostname, portstr); + return 0; +} + +/* + * create a getaddrinfo `hints' based on `proto' + */ + +static void +make_hints(struct addrinfo *hints, int proto) +{ + memset(hints, 0, sizeof(*hints)); + hints->ai_family = AF_UNSPEC; + switch(proto) { + case KRB5_KRBHST_UDP : + hints->ai_socktype = SOCK_DGRAM; + break; + case KRB5_KRBHST_HTTP : + case KRB5_KRBHST_TCP : + hints->ai_socktype = SOCK_STREAM; + break; + } +} + +/* + * return an `struct addrinfo *' in `ai' corresponding to the information + * in `host'. free:ing is handled by krb5_krbhst_free. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_get_addrinfo(krb5_context context, krb5_krbhst_info *host, + struct addrinfo **ai) +{ + struct addrinfo hints; + char portstr[NI_MAXSERV]; + int ret; + + if (host->ai == NULL) { + make_hints(&hints, host->proto); + snprintf (portstr, sizeof(portstr), "%d", host->port); + ret = getaddrinfo(host->hostname, portstr, &hints, &host->ai); + if (ret) + return krb5_eai_to_heim_errno(ret, errno); + } + *ai = host->ai; + return 0; +} + +static krb5_boolean +get_next(struct krb5_krbhst_data *kd, krb5_krbhst_info **host) +{ + struct krb5_krbhst_info *hi = *kd->index; + if(hi != NULL) { + *host = hi; + kd->index = &(*kd->index)->next; + return TRUE; + } + return FALSE; +} + +static void +srv_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, + const char *proto, const char *service) +{ + krb5_krbhst_info **res; + int count, i; + + if (srv_find_realm(context, &res, &count, kd->realm, "SRV", proto, service, + kd->port)) + return; + for(i = 0; i < count; i++) + append_host_hostinfo(kd, res[i]); + free(res); +} + +/* + * read the configuration for `conf_string', defaulting to kd->def_port and + * forcing it to `kd->port' if kd->port != 0 + */ + +static void +config_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, + const char *conf_string) +{ + int i; + + char **hostlist; + hostlist = krb5_config_get_strings(context, NULL, + "realms", kd->realm, conf_string, NULL); + + if(hostlist == NULL) + return; + kd->flags |= KD_CONFIG_EXISTS; + for(i = 0; hostlist && hostlist[i] != NULL; i++) + append_host_string(context, kd, hostlist[i], kd->def_port, kd->port); + + krb5_config_free_strings(hostlist); +} + +/* + * as a fallback, look for `serv_string.kd->realm' (typically + * kerberos.REALM, kerberos-1.REALM, ... + * `port' is the default port for the service, and `proto' the + * protocol + */ + +static krb5_error_code +fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, + const char *serv_string, int port, int proto) +{ + char *host; + int ret; + struct addrinfo *ai; + struct addrinfo hints; + char portstr[NI_MAXSERV]; + + if(kd->fallback_count == 0) + asprintf(&host, "%s.%s.", serv_string, kd->realm); + else + asprintf(&host, "%s-%d.%s.", + serv_string, kd->fallback_count, kd->realm); + + if (host == NULL) + return ENOMEM; + + make_hints(&hints, proto); + snprintf(portstr, sizeof(portstr), "%d", port); + ret = getaddrinfo(host, portstr, &hints, &ai); + if (ret) { + /* no more hosts, so we're done here */ + free(host); + kd->flags |= KD_FALLBACK; + } else { + struct krb5_krbhst_info *hi; + size_t hostlen = strlen(host); + + hi = calloc(1, sizeof(*hi) + hostlen); + if(hi == NULL) { + free(host); + return ENOMEM; + } + + hi->proto = proto; + hi->port = hi->def_port = port; + hi->ai = ai; + memmove(hi->hostname, host, hostlen - 1); + hi->hostname[hostlen - 1] = '\0'; + free(host); + append_host_hostinfo(kd, hi); + kd->fallback_count++; + } + return 0; +} + +static krb5_error_code +kdc_get_next(krb5_context context, + struct krb5_krbhst_data *kd, + krb5_krbhst_info **host) +{ + krb5_error_code ret; + + if((kd->flags & KD_CONFIG) == 0) { + config_get_hosts(context, kd, "kdc"); + kd->flags |= KD_CONFIG; + if(get_next(kd, host)) + return 0; + } + + if (kd->flags & KD_CONFIG_EXISTS) + return KRB5_KDC_UNREACH; /* XXX */ + + if(context->srv_lookup) { + if((kd->flags & KD_SRV_UDP) == 0 && (kd->flags & KD_LARGE_MSG) == 0) { + srv_get_hosts(context, kd, "udp", "kerberos"); + kd->flags |= KD_SRV_UDP; + if(get_next(kd, host)) + return 0; + } + + if((kd->flags & KD_SRV_TCP) == 0) { + srv_get_hosts(context, kd, "tcp", "kerberos"); + kd->flags |= KD_SRV_TCP; + if(get_next(kd, host)) + return 0; + } + if((kd->flags & KD_SRV_HTTP) == 0) { + srv_get_hosts(context, kd, "http", "kerberos"); + kd->flags |= KD_SRV_HTTP; + if(get_next(kd, host)) + return 0; + } + } + + while((kd->flags & KD_FALLBACK) == 0) { + ret = fallback_get_hosts(context, kd, "kerberos", + kd->def_port, + krbhst_get_default_proto(kd)); + if(ret) + return ret; + if(get_next(kd, host)) + return 0; + } + + return KRB5_KDC_UNREACH; /* XXX */ +} + +static krb5_error_code +admin_get_next(krb5_context context, + struct krb5_krbhst_data *kd, + krb5_krbhst_info **host) +{ + krb5_error_code ret; + + if((kd->flags & KD_CONFIG) == 0) { + config_get_hosts(context, kd, "admin_server"); + kd->flags |= KD_CONFIG; + if(get_next(kd, host)) + return 0; + } + + if (kd->flags & KD_CONFIG_EXISTS) + return KRB5_KDC_UNREACH; /* XXX */ + + if(context->srv_lookup) { + if((kd->flags & KD_SRV_TCP) == 0) { + srv_get_hosts(context, kd, "tcp", "kerberos-adm"); + kd->flags |= KD_SRV_TCP; + if(get_next(kd, host)) + return 0; + } + } + + if (krbhst_empty(kd) + && (kd->flags & KD_FALLBACK) == 0) { + ret = fallback_get_hosts(context, kd, "kerberos", + kd->def_port, + krbhst_get_default_proto(kd)); + if(ret) + return ret; + kd->flags |= KD_FALLBACK; + if(get_next(kd, host)) + return 0; + } + + return KRB5_KDC_UNREACH; /* XXX */ +} + +static krb5_error_code +kpasswd_get_next(krb5_context context, + struct krb5_krbhst_data *kd, + krb5_krbhst_info **host) +{ + krb5_error_code ret; + + if((kd->flags & KD_CONFIG) == 0) { + config_get_hosts(context, kd, "kpasswd_server"); + kd->flags |= KD_CONFIG; + if(get_next(kd, host)) + return 0; + } + + if (kd->flags & KD_CONFIG_EXISTS) + return KRB5_KDC_UNREACH; /* XXX */ + + if(context->srv_lookup) { + if((kd->flags & KD_SRV_UDP) == 0) { + srv_get_hosts(context, kd, "udp", "kpasswd"); + kd->flags |= KD_SRV_UDP; + if(get_next(kd, host)) + return 0; + } + if((kd->flags & KD_SRV_TCP) == 0) { + srv_get_hosts(context, kd, "tcp", "kpasswd"); + kd->flags |= KD_SRV_TCP; + if(get_next(kd, host)) + return 0; + } + } + + /* no matches -> try admin */ + + if (krbhst_empty(kd)) { + kd->flags = 0; + kd->port = kd->def_port; + kd->get_next = admin_get_next; + ret = (*kd->get_next)(context, kd, host); + if (ret == 0) + (*host)->proto = krbhst_get_default_proto(kd); + return ret; + } + + return KRB5_KDC_UNREACH; /* XXX */ +} + +static krb5_error_code +krb524_get_next(krb5_context context, + struct krb5_krbhst_data *kd, + krb5_krbhst_info **host) +{ + if((kd->flags & KD_CONFIG) == 0) { + config_get_hosts(context, kd, "krb524_server"); + if(get_next(kd, host)) + return 0; + kd->flags |= KD_CONFIG; + } + + if (kd->flags & KD_CONFIG_EXISTS) + return KRB5_KDC_UNREACH; /* XXX */ + + if(context->srv_lookup) { + if((kd->flags & KD_SRV_UDP) == 0) { + srv_get_hosts(context, kd, "udp", "krb524"); + kd->flags |= KD_SRV_UDP; + if(get_next(kd, host)) + return 0; + } + + if((kd->flags & KD_SRV_TCP) == 0) { + srv_get_hosts(context, kd, "tcp", "krb524"); + kd->flags |= KD_SRV_TCP; + if(get_next(kd, host)) + return 0; + } + } + + /* no matches -> try kdc */ + + if (krbhst_empty(kd)) { + kd->flags = 0; + kd->port = kd->def_port; + kd->get_next = kdc_get_next; + return (*kd->get_next)(context, kd, host); + } + + return KRB5_KDC_UNREACH; /* XXX */ +} + +static struct krb5_krbhst_data* +common_init(krb5_context context, + const char *realm, + int flags) +{ + struct krb5_krbhst_data *kd; + + if((kd = calloc(1, sizeof(*kd))) == NULL) + return NULL; + + if((kd->realm = strdup(realm)) == NULL) { + free(kd); + return NULL; + } + + if (flags & KRB5_KRBHST_FLAGS_LARGE_MSG) + kd->flags |= KD_LARGE_MSG; + kd->end = kd->index = &kd->hosts; + return kd; +} + +/* + * initialize `handle' to look for hosts of type `type' in realm `realm' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_init(krb5_context context, + const char *realm, + unsigned int type, + krb5_krbhst_handle *handle) +{ + return krb5_krbhst_init_flags(context, realm, type, 0, handle); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_init_flags(krb5_context context, + const char *realm, + unsigned int type, + int flags, + krb5_krbhst_handle *handle) +{ + struct krb5_krbhst_data *kd; + krb5_error_code (*next)(krb5_context, struct krb5_krbhst_data *, + krb5_krbhst_info **); + int def_port; + + switch(type) { + case KRB5_KRBHST_KDC: + next = kdc_get_next; + def_port = ntohs(krb5_getportbyname (context, "kerberos", "udp", 88)); + break; + case KRB5_KRBHST_ADMIN: + next = admin_get_next; + def_port = ntohs(krb5_getportbyname (context, "kerberos-adm", + "tcp", 749)); + break; + case KRB5_KRBHST_CHANGEPW: + next = kpasswd_get_next; + def_port = ntohs(krb5_getportbyname (context, "kpasswd", "udp", + KPASSWD_PORT)); + break; + case KRB5_KRBHST_KRB524: + next = krb524_get_next; + def_port = ntohs(krb5_getportbyname (context, "krb524", "udp", 4444)); + break; + default: + krb5_set_error_string(context, "unknown krbhst type (%u)", type); + return ENOTTY; + } + if((kd = common_init(context, realm, flags)) == NULL) + return ENOMEM; + kd->get_next = next; + kd->def_port = def_port; + *handle = kd; + return 0; +} + +/* + * return the next host information from `handle' in `host' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_next(krb5_context context, + krb5_krbhst_handle handle, + krb5_krbhst_info **host) +{ + if(get_next(handle, host)) + return 0; + + return (*handle->get_next)(context, handle, host); +} + +/* + * return the next host information from `handle' as a host name + * in `hostname' (or length `hostlen) + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_krbhst_next_as_string(krb5_context context, + krb5_krbhst_handle handle, + char *hostname, + size_t hostlen) +{ + krb5_error_code ret; + krb5_krbhst_info *host; + ret = krb5_krbhst_next(context, handle, &host); + if(ret) + return ret; + return krb5_krbhst_format_string(context, host, hostname, hostlen); +} + + +void KRB5_LIB_FUNCTION +krb5_krbhst_reset(krb5_context context, krb5_krbhst_handle handle) +{ + handle->index = &handle->hosts; +} + +void KRB5_LIB_FUNCTION +krb5_krbhst_free(krb5_context context, krb5_krbhst_handle handle) +{ + krb5_krbhst_info *h, *next; + + if (handle == NULL) + return; + + for (h = handle->hosts; h != NULL; h = next) { + next = h->next; + free_krbhst_info(h); + } + + free(handle->realm); + free(handle); +} + +/* backwards compatibility ahead */ + +static krb5_error_code +gethostlist(krb5_context context, const char *realm, + unsigned int type, char ***hostlist) +{ + krb5_error_code ret; + int nhost = 0; + krb5_krbhst_handle handle; + char host[MAXHOSTNAMELEN]; + krb5_krbhst_info *hostinfo; + + ret = krb5_krbhst_init(context, realm, type, &handle); + if (ret) + return ret; + + while(krb5_krbhst_next(context, handle, &hostinfo) == 0) + nhost++; + if(nhost == 0) + return KRB5_KDC_UNREACH; + *hostlist = calloc(nhost + 1, sizeof(**hostlist)); + if(*hostlist == NULL) { + krb5_krbhst_free(context, handle); + return ENOMEM; + } + + krb5_krbhst_reset(context, handle); + nhost = 0; + while(krb5_krbhst_next_as_string(context, handle, + host, sizeof(host)) == 0) { + if(((*hostlist)[nhost++] = strdup(host)) == NULL) { + krb5_free_krbhst(context, *hostlist); + krb5_krbhst_free(context, handle); + return ENOMEM; + } + } + (*hostlist)[nhost++] = NULL; + krb5_krbhst_free(context, handle); + return 0; +} + +/* + * return an malloced list of kadmin-hosts for `realm' in `hostlist' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krb_admin_hst (krb5_context context, + const krb5_realm *realm, + char ***hostlist) +{ + return gethostlist(context, *realm, KRB5_KRBHST_ADMIN, hostlist); +} + +/* + * return an malloced list of changepw-hosts for `realm' in `hostlist' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krb_changepw_hst (krb5_context context, + const krb5_realm *realm, + char ***hostlist) +{ + return gethostlist(context, *realm, KRB5_KRBHST_CHANGEPW, hostlist); +} + +/* + * return an malloced list of 524-hosts for `realm' in `hostlist' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krb524hst (krb5_context context, + const krb5_realm *realm, + char ***hostlist) +{ + return gethostlist(context, *realm, KRB5_KRBHST_KRB524, hostlist); +} + + +/* + * return an malloced list of KDC's for `realm' in `hostlist' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_krbhst (krb5_context context, + const krb5_realm *realm, + char ***hostlist) +{ + return gethostlist(context, *realm, KRB5_KRBHST_KDC, hostlist); +} + +/* + * free all the memory allocated in `hostlist' + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_krbhst (krb5_context context, + char **hostlist) +{ + char **p; + + for (p = hostlist; *p; ++p) + free (*p); + free (hostlist); + return 0; +} diff --git a/source4/heimdal/lib/krb5/log.c b/source4/heimdal/lib/krb5/log.c new file mode 100644 index 0000000000..4f6381c858 --- /dev/null +++ b/source4/heimdal/lib/krb5/log.c @@ -0,0 +1,467 @@ +/* + * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: log.c,v 1.36 2005/06/17 04:25:05 lha Exp $"); + +struct facility { + int min; + int max; + krb5_log_log_func_t log_func; + krb5_log_close_func_t close_func; + void *data; +}; + +static struct facility* +log_realloc(krb5_log_facility *f) +{ + struct facility *fp; + fp = realloc(f->val, (f->len + 1) * sizeof(*f->val)); + if(fp == NULL) + return NULL; + f->len++; + f->val = fp; + fp += f->len - 1; + return fp; +} + +struct s2i { + const char *s; + int val; +}; + +#define L(X) { #X, LOG_ ## X } + +static struct s2i syslogvals[] = { + L(EMERG), + L(ALERT), + L(CRIT), + L(ERR), + L(WARNING), + L(NOTICE), + L(INFO), + L(DEBUG), + + L(AUTH), +#ifdef LOG_AUTHPRIV + L(AUTHPRIV), +#endif +#ifdef LOG_CRON + L(CRON), +#endif + L(DAEMON), +#ifdef LOG_FTP + L(FTP), +#endif + L(KERN), + L(LPR), + L(MAIL), +#ifdef LOG_NEWS + L(NEWS), +#endif + L(SYSLOG), + L(USER), +#ifdef LOG_UUCP + L(UUCP), +#endif + L(LOCAL0), + L(LOCAL1), + L(LOCAL2), + L(LOCAL3), + L(LOCAL4), + L(LOCAL5), + L(LOCAL6), + L(LOCAL7), + { NULL, -1 } +}; + +static int +find_value(const char *s, struct s2i *table) +{ + while(table->s && strcasecmp(table->s, s)) + table++; + return table->val; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_initlog(krb5_context context, + const char *program, + krb5_log_facility **fac) +{ + krb5_log_facility *f = calloc(1, sizeof(*f)); + if(f == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + f->program = strdup(program); + if(f->program == NULL){ + free(f); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + *fac = f; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_addlog_func(krb5_context context, + krb5_log_facility *fac, + int min, + int max, + krb5_log_log_func_t log_func, + krb5_log_close_func_t close_func, + void *data) +{ + struct facility *fp = log_realloc(fac); + if(fp == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + fp->min = min; + fp->max = max; + fp->log_func = log_func; + fp->close_func = close_func; + fp->data = data; + return 0; +} + + +struct _heimdal_syslog_data{ + int priority; +}; + +static void +log_syslog(const char *timestr, + const char *msg, + void *data) + +{ + struct _heimdal_syslog_data *s = data; + syslog(s->priority, "%s", msg); +} + +static void +close_syslog(void *data) +{ + free(data); + closelog(); +} + +static krb5_error_code +open_syslog(krb5_context context, + krb5_log_facility *facility, int min, int max, + const char *sev, const char *fac) +{ + struct _heimdal_syslog_data *sd = malloc(sizeof(*sd)); + int i; + + if(sd == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + i = find_value(sev, syslogvals); + if(i == -1) + i = LOG_ERR; + sd->priority = i; + i = find_value(fac, syslogvals); + if(i == -1) + i = LOG_AUTH; + sd->priority |= i; + roken_openlog(facility->program, LOG_PID | LOG_NDELAY, i); + return krb5_addlog_func(context, facility, min, max, + log_syslog, close_syslog, sd); +} + +struct file_data{ + const char *filename; + const char *mode; + FILE *fd; + int keep_open; +}; + +static void +log_file(const char *timestr, + const char *msg, + void *data) +{ + struct file_data *f = data; + if(f->keep_open == 0) + f->fd = fopen(f->filename, f->mode); + if(f->fd == NULL) + return; + fprintf(f->fd, "%s %s\n", timestr, msg); + if(f->keep_open == 0) + fclose(f->fd); +} + +static void +close_file(void *data) +{ + struct file_data *f = data; + if(f->keep_open && f->filename) + fclose(f->fd); + free(data); +} + +static krb5_error_code +open_file(krb5_context context, krb5_log_facility *fac, int min, int max, + const char *filename, const char *mode, FILE *f, int keep_open) +{ + struct file_data *fd = malloc(sizeof(*fd)); + if(fd == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + fd->filename = filename; + fd->mode = mode; + fd->fd = f; + fd->keep_open = keep_open; + + return krb5_addlog_func(context, fac, min, max, log_file, close_file, fd); +} + + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) +{ + krb5_error_code ret = 0; + int min = 0, max = -1, n; + char c; + const char *p = orig; + + n = sscanf(p, "%d%c%d/", &min, &c, &max); + if(n == 2){ + if(c == '/') { + if(min < 0){ + max = -min; + min = 0; + }else{ + max = min; + } + } + } + if(n){ + p = strchr(p, '/'); + if(p == NULL) { + krb5_set_error_string (context, "failed to parse \"%s\"", orig); + return HEIM_ERR_LOG_PARSE; + } + p++; + } + if(strcmp(p, "STDERR") == 0){ + ret = open_file(context, f, min, max, NULL, NULL, stderr, 1); + }else if(strcmp(p, "CONSOLE") == 0){ + ret = open_file(context, f, min, max, "/dev/console", "w", NULL, 0); + }else if(strncmp(p, "FILE:", 4) == 0 && (p[4] == ':' || p[4] == '=')){ + char *fn; + FILE *file = NULL; + int keep_open = 0; + fn = strdup(p + 5); + if(fn == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + if(p[4] == '='){ + int i = open(fn, O_WRONLY | O_CREAT | + O_TRUNC | O_APPEND, 0666); + if(i < 0) { + ret = errno; + krb5_set_error_string (context, "open(%s): %s", fn, + strerror(ret)); + return ret; + } + file = fdopen(i, "a"); + if(file == NULL){ + ret = errno; + close(i); + krb5_set_error_string (context, "fdopen(%s): %s", fn, + strerror(ret)); + return ret; + } + keep_open = 1; + } + ret = open_file(context, f, min, max, fn, "a", file, keep_open); + }else if(strncmp(p, "DEVICE=", 6) == 0){ + ret = open_file(context, f, min, max, strdup(p + 7), "w", NULL, 0); + }else if(strncmp(p, "SYSLOG", 6) == 0 && (p[6] == '\0' || p[6] == ':')){ + char severity[128] = ""; + char facility[128] = ""; + p += 6; + if(*p != '\0') + p++; + if(strsep_copy(&p, ":", severity, sizeof(severity)) != -1) + strsep_copy(&p, ":", facility, sizeof(facility)); + if(*severity == '\0') + strlcpy(severity, "ERR", sizeof(severity)); + if(*facility == '\0') + strlcpy(facility, "AUTH", sizeof(facility)); + ret = open_syslog(context, f, min, max, severity, facility); + }else{ + krb5_set_error_string (context, "unknown log type: %s", p); + ret = HEIM_ERR_LOG_PARSE; /* XXX */ + } + return ret; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_openlog(krb5_context context, + const char *program, + krb5_log_facility **fac) +{ + krb5_error_code ret; + char **p, **q; + + ret = krb5_initlog(context, program, fac); + if(ret) + return ret; + + p = krb5_config_get_strings(context, NULL, "logging", program, NULL); + if(p == NULL) + p = krb5_config_get_strings(context, NULL, "logging", "default", NULL); + if(p){ + for(q = p; *q; q++) + ret = krb5_addlog_dest(context, *fac, *q); + krb5_config_free_strings(p); + }else + ret = krb5_addlog_dest(context, *fac, "SYSLOG"); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_closelog(krb5_context context, + krb5_log_facility *fac) +{ + int i; + for(i = 0; i < fac->len; i++) + (*fac->val[i].close_func)(fac->val[i].data); + free(fac->val); + free(fac->program); + fac->val = NULL; + fac->len = 0; + fac->program = NULL; + free(fac); + return 0; +} + +#undef __attribute__ +#define __attribute__(X) + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vlog_msg(krb5_context context, + krb5_log_facility *fac, + char **reply, + int level, + const char *fmt, + va_list ap) + __attribute__((format (printf, 5, 0))) +{ + + char *msg = NULL; + const char *actual = NULL; + char buf[64]; + time_t t = 0; + int i; + + for(i = 0; fac && i < fac->len; i++) + if(fac->val[i].min <= level && + (fac->val[i].max < 0 || fac->val[i].max >= level)) { + if(t == 0) { + t = time(NULL); + krb5_format_time(context, t, buf, sizeof(buf), TRUE); + } + if(actual == NULL) { + vasprintf(&msg, fmt, ap); + if(msg == NULL) + actual = fmt; + else + actual = msg; + } + (*fac->val[i].log_func)(buf, actual, fac->val[i].data); + } + if(reply == NULL) + free(msg); + else + *reply = msg; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vlog(krb5_context context, + krb5_log_facility *fac, + int level, + const char *fmt, + va_list ap) + __attribute__((format (printf, 4, 0))) +{ + return krb5_vlog_msg(context, fac, NULL, level, fmt, ap); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_log_msg(krb5_context context, + krb5_log_facility *fac, + int level, + char **reply, + const char *fmt, + ...) + __attribute__((format (printf, 5, 6))) +{ + va_list ap; + krb5_error_code ret; + + va_start(ap, fmt); + ret = krb5_vlog_msg(context, fac, reply, level, fmt, ap); + va_end(ap); + return ret; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_log(krb5_context context, + krb5_log_facility *fac, + int level, + const char *fmt, + ...) + __attribute__((format (printf, 4, 5))) +{ + va_list ap; + krb5_error_code ret; + + va_start(ap, fmt); + ret = krb5_vlog(context, fac, level, fmt, ap); + va_end(ap); + return ret; +} + diff --git a/source4/heimdal/lib/krb5/mcache.c b/source4/heimdal/lib/krb5/mcache.c new file mode 100644 index 0000000000..0a65d53849 --- /dev/null +++ b/source4/heimdal/lib/krb5/mcache.c @@ -0,0 +1,353 @@ +/* + * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: mcache.c,v 1.19 2004/04/25 19:25:35 joda Exp $"); + +typedef struct krb5_mcache { + char *name; + unsigned int refcnt; + int dead; + krb5_principal primary_principal; + struct link { + krb5_creds cred; + struct link *next; + } *creds; + struct krb5_mcache *next; +} krb5_mcache; + +static HEIMDAL_MUTEX mcc_mutex = HEIMDAL_MUTEX_INITIALIZER; +static struct krb5_mcache *mcc_head; + +#define MCACHE(X) ((krb5_mcache *)(X)->data.data) + +#define MISDEAD(X) ((X)->dead) + +#define MCC_CURSOR(C) ((struct link*)(C)) + +static const char* +mcc_get_name(krb5_context context, + krb5_ccache id) +{ + return MCACHE(id)->name; +} + +static krb5_mcache * +mcc_alloc(const char *name) +{ + krb5_mcache *m, *m_c; + + ALLOC(m, 1); + if(m == NULL) + return NULL; + if(name == NULL) + asprintf(&m->name, "%p", m); + else + m->name = strdup(name); + if(m->name == NULL) { + free(m); + return NULL; + } + /* check for dups first */ + HEIMDAL_MUTEX_lock(&mcc_mutex); + for (m_c = mcc_head; m_c != NULL; m_c = m_c->next) + if (strcmp(m->name, m_c->name) == 0) + break; + if (m_c) { + free(m->name); + free(m); + HEIMDAL_MUTEX_unlock(&mcc_mutex); + return NULL; + } + + m->dead = 0; + m->refcnt = 1; + m->primary_principal = NULL; + m->creds = NULL; + m->next = mcc_head; + mcc_head = m; + HEIMDAL_MUTEX_unlock(&mcc_mutex); + return m; +} + +static krb5_error_code +mcc_resolve(krb5_context context, krb5_ccache *id, const char *res) +{ + krb5_mcache *m; + + HEIMDAL_MUTEX_lock(&mcc_mutex); + for (m = mcc_head; m != NULL; m = m->next) + if (strcmp(m->name, res) == 0) + break; + HEIMDAL_MUTEX_unlock(&mcc_mutex); + + if (m != NULL) { + m->refcnt++; + (*id)->data.data = m; + (*id)->data.length = sizeof(*m); + return 0; + } + + m = mcc_alloc(res); + if (m == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + + (*id)->data.data = m; + (*id)->data.length = sizeof(*m); + + return 0; +} + + +static krb5_error_code +mcc_gen_new(krb5_context context, krb5_ccache *id) +{ + krb5_mcache *m; + + m = mcc_alloc(NULL); + + if (m == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + + (*id)->data.data = m; + (*id)->data.length = sizeof(*m); + + return 0; +} + +static krb5_error_code +mcc_initialize(krb5_context context, + krb5_ccache id, + krb5_principal primary_principal) +{ + krb5_mcache *m = MCACHE(id); + m->dead = 0; + return krb5_copy_principal (context, + primary_principal, + &m->primary_principal); +} + +static krb5_error_code +mcc_close(krb5_context context, + krb5_ccache id) +{ + krb5_mcache *m = MCACHE(id); + + if (--m->refcnt != 0) + return 0; + + if (MISDEAD(m)) { + free (m->name); + krb5_data_free(&id->data); + } + + return 0; +} + +static krb5_error_code +mcc_destroy(krb5_context context, + krb5_ccache id) +{ + krb5_mcache **n, *m = MCACHE(id); + struct link *l; + + if (m->refcnt == 0) + krb5_abortx(context, "mcc_destroy: refcnt already 0"); + + if (!MISDEAD(m)) { + /* if this is an active mcache, remove it from the linked + list, and free all data */ + HEIMDAL_MUTEX_lock(&mcc_mutex); + for(n = &mcc_head; n && *n; n = &(*n)->next) { + if(m == *n) { + *n = m->next; + break; + } + } + HEIMDAL_MUTEX_unlock(&mcc_mutex); + if (m->primary_principal != NULL) { + krb5_free_principal (context, m->primary_principal); + m->primary_principal = NULL; + } + m->dead = 1; + + l = m->creds; + while (l != NULL) { + struct link *old; + + krb5_free_cred_contents (context, &l->cred); + old = l; + l = l->next; + free (old); + } + m->creds = NULL; + } + return 0; +} + +static krb5_error_code +mcc_store_cred(krb5_context context, + krb5_ccache id, + krb5_creds *creds) +{ + krb5_mcache *m = MCACHE(id); + krb5_error_code ret; + struct link *l; + + if (MISDEAD(m)) + return ENOENT; + + l = malloc (sizeof(*l)); + if (l == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + l->next = m->creds; + m->creds = l; + memset (&l->cred, 0, sizeof(l->cred)); + ret = krb5_copy_creds_contents (context, creds, &l->cred); + if (ret) { + m->creds = l->next; + free (l); + return ret; + } + return 0; +} + +static krb5_error_code +mcc_get_principal(krb5_context context, + krb5_ccache id, + krb5_principal *principal) +{ + krb5_mcache *m = MCACHE(id); + + if (MISDEAD(m) || m->primary_principal == NULL) + return ENOENT; + return krb5_copy_principal (context, + m->primary_principal, + principal); +} + +static krb5_error_code +mcc_get_first (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + krb5_mcache *m = MCACHE(id); + + if (MISDEAD(m)) + return ENOENT; + + *cursor = m->creds; + return 0; +} + +static krb5_error_code +mcc_get_next (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor, + krb5_creds *creds) +{ + krb5_mcache *m = MCACHE(id); + struct link *l; + + if (MISDEAD(m)) + return ENOENT; + + l = *cursor; + if (l != NULL) { + *cursor = l->next; + return krb5_copy_creds_contents (context, + &l->cred, + creds); + } else + return KRB5_CC_END; +} + +static krb5_error_code +mcc_end_get (krb5_context context, + krb5_ccache id, + krb5_cc_cursor *cursor) +{ + return 0; +} + +static krb5_error_code +mcc_remove_cred(krb5_context context, + krb5_ccache id, + krb5_flags which, + krb5_creds *mcreds) +{ + krb5_mcache *m = MCACHE(id); + struct link **q, *p; + for(q = &m->creds, p = *q; p; p = *q) { + if(krb5_compare_creds(context, which, mcreds, &p->cred)) { + *q = p->next; + krb5_free_cred_contents(context, &p->cred); + free(p); + } else + q = &p->next; + } + return 0; +} + +static krb5_error_code +mcc_set_flags(krb5_context context, + krb5_ccache id, + krb5_flags flags) +{ + return 0; /* XXX */ +} + +const krb5_cc_ops krb5_mcc_ops = { + "MEMORY", + mcc_get_name, + mcc_resolve, + mcc_gen_new, + mcc_initialize, + mcc_destroy, + mcc_close, + mcc_store_cred, + NULL, /* mcc_retrieve */ + mcc_get_principal, + mcc_get_first, + mcc_get_next, + mcc_end_get, + mcc_remove_cred, + mcc_set_flags +}; diff --git a/source4/heimdal/lib/krb5/misc.c b/source4/heimdal/lib/krb5/misc.c new file mode 100644 index 0000000000..baf63f6d52 --- /dev/null +++ b/source4/heimdal/lib/krb5/misc.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: misc.c,v 1.5 1999/12/02 17:05:11 joda Exp $"); diff --git a/source4/heimdal/lib/krb5/mit_glue.c b/source4/heimdal/lib/krb5/mit_glue.c new file mode 100755 index 0000000000..b7f06c1582 --- /dev/null +++ b/source4/heimdal/lib/krb5/mit_glue.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +RCSID("$Id: mit_glue.c,v 1.7 2005/05/18 04:21:44 lha Exp $"); + +/* + * Glue for MIT API + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_make_checksum(krb5_context context, + krb5_cksumtype cksumtype, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *input, + krb5_checksum *cksum) +{ + krb5_error_code ret; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + + ret = krb5_create_checksum(context, crypto, usage, cksumtype, + input->data, input->length, cksum); + krb5_crypto_destroy(context, crypto); + + return ret ; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_verify_checksum(krb5_context context, const krb5_keyblock *key, + krb5_keyusage usage, const krb5_data *data, + const krb5_checksum *cksum, krb5_boolean *valid) +{ + krb5_error_code ret; + krb5_checksum data_cksum; + + *valid = 0; + + ret = krb5_c_make_checksum(context, cksum->cksumtype, + key, usage, data, &data_cksum); + if (ret) + return ret; + + if (data_cksum.cksumtype == cksum->cksumtype + && data_cksum.checksum.length == cksum->checksum.length + && memcmp(data_cksum.checksum.data, cksum->checksum.data, cksum->checksum.length) == 0) + *valid = 1; + + krb5_free_checksum_contents(context, &data_cksum); + + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_get_checksum(krb5_context context, const krb5_checksum *cksum, + krb5_cksumtype *type, krb5_data **data) +{ + krb5_error_code ret; + + if (type) + *type = cksum->cksumtype; + if (data) { + *data = malloc(sizeof(**data)); + if (*data == NULL) + return ENOMEM; + + ret = copy_octet_string(&cksum->checksum, *data); + if (ret) { + free(*data); + *data = NULL; + return ret; + } + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_set_checksum(krb5_context context, krb5_checksum *cksum, + krb5_cksumtype type, const krb5_data *data) +{ + cksum->cksumtype = type; + return copy_octet_string(data, &cksum->checksum); +} + +void KRB5_LIB_FUNCTION +krb5_free_checksum (krb5_context context, krb5_checksum *cksum) +{ + krb5_checksum_free(context, cksum); + free(cksum); +} + +void KRB5_LIB_FUNCTION +krb5_free_checksum_contents(krb5_context context, krb5_checksum *cksum) +{ + krb5_checksum_free(context, cksum); + memset(cksum, 0, sizeof(*cksum)); +} + +void KRB5_LIB_FUNCTION +krb5_checksum_free(krb5_context context, krb5_checksum *cksum) +{ + free_Checksum(cksum); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_valid_enctype (krb5_enctype etype) +{ + return krb5_enctype_valid(NULL, etype); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_valid_cksumtype(krb5_cksumtype ctype) +{ + return krb5_cksumtype_valid(NULL, ctype); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype) +{ + return krb5_checksum_is_collision_proof(NULL, ctype); +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_c_is_keyed_cksum(krb5_cksumtype ctype) +{ + return krb5_checksum_is_keyed(NULL, ctype); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_checksum (krb5_context context, + const krb5_checksum *old, + krb5_checksum **new) +{ + *new = malloc(sizeof(**new)); + if (*new == NULL) + return ENOMEM; + return copy_Checksum(old, *new); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_checksum_length (krb5_context context, krb5_cksumtype cksumtype, + size_t *length) +{ + return krb5_checksumsize(context, cksumtype, length); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_block_size(krb5_context context, + krb5_enctype enctype, + size_t *blocksize) +{ + krb5_error_code ret; + krb5_crypto crypto; + krb5_keyblock key; + + ret = krb5_generate_random_keyblock(context, enctype, &key); + if (ret) + return ret; + + ret = krb5_crypto_init(context, &key, 0, &crypto); + krb5_free_keyblock_contents(context, &key); + if (ret) + return ret; + ret = krb5_crypto_getblocksize(context, crypto, blocksize); + krb5_crypto_destroy(context, crypto); + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_decrypt(krb5_context context, + const krb5_keyblock key, + krb5_keyusage usage, + const krb5_data *ivec, + krb5_enc_data *input, + krb5_data *output) +{ + krb5_error_code ret; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, &key, input->enctype, &crypto); + if (ret) + return ret; + + if (ivec) { + size_t blocksize; + + ret = krb5_crypto_getblocksize(context, crypto, &blocksize); + if (ret) { + krb5_crypto_destroy(context, crypto); + return ret; + } + + if (blocksize > ivec->length) { + krb5_crypto_destroy(context, crypto); + return KRB5_BAD_MSIZE; + } + } + + ret = krb5_decrypt_ivec(context, crypto, usage, + input->ciphertext.data, input->ciphertext.length, + output, + ivec ? ivec->data : NULL); + + krb5_crypto_destroy(context, crypto); + + return ret ; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_encrypt(krb5_context context, + const krb5_keyblock *key, + krb5_keyusage usage, + const krb5_data *ivec, + const krb5_data *input, + krb5_enc_data *output) +{ + krb5_error_code ret; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + + if (ivec) { + size_t blocksize; + + ret = krb5_crypto_getblocksize(context, crypto, &blocksize); + if (ret) { + krb5_crypto_destroy(context, crypto); + return ret; + } + + if (blocksize > ivec->length) { + krb5_crypto_destroy(context, crypto); + return KRB5_BAD_MSIZE; + } + } + + ret = krb5_encrypt_ivec(context, crypto, usage, + input->data, input->length, + &output->ciphertext, + ivec ? ivec->data : NULL); + output->kvno = 0; + krb5_crypto_getenctype(context, crypto, &output->enctype); + + krb5_crypto_destroy(context, crypto); + + return ret ; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_encrypt_length(krb5_context context, + krb5_enctype enctype, + size_t inputlen, + size_t *length) +{ + krb5_error_code ret; + krb5_crypto crypto; + krb5_keyblock key; + + ret = krb5_generate_random_keyblock(context, enctype, &key); + if (ret) + return ret; + + ret = krb5_crypto_init(context, &key, 0, &crypto); + krb5_free_keyblock_contents(context, &key); + if (ret) + return ret; + + *length = krb5_get_wrapped_length(context, crypto, inputlen); + krb5_crypto_destroy(context, crypto); + + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_enctype_compare(krb5_context context, + krb5_enctype e1, + krb5_enctype e2, + krb5_boolean *similar) +{ + *similar = krb5_enctypes_compatible_keys(context, e1, e2); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_make_random_key(krb5_context context, + krb5_enctype enctype, + krb5_keyblock *random_key) +{ + return krb5_generate_random_keyblock(context, enctype, random_key); +} diff --git a/source4/heimdal/lib/krb5/mk_error.c b/source4/heimdal/lib/krb5/mk_error.c new file mode 100644 index 0000000000..7a8b1ba06b --- /dev/null +++ b/source4/heimdal/lib/krb5/mk_error.c @@ -0,0 +1,92 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: mk_error.c,v 1.22 2005/06/16 21:16:40 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_error(krb5_context context, + krb5_error_code error_code, + const char *e_text, + const krb5_data *e_data, + const krb5_principal client, + const krb5_principal server, + time_t *client_time, + int *client_usec, + krb5_data *reply) +{ + KRB_ERROR msg; + krb5_timestamp sec; + int32_t usec; + size_t len; + krb5_error_code ret = 0; + + krb5_us_timeofday (context, &sec, &usec); + + memset(&msg, 0, sizeof(msg)); + msg.pvno = 5; + msg.msg_type = krb_error; + msg.stime = sec; + msg.susec = usec; + msg.ctime = client_time; + msg.cusec = client_usec; + /* Make sure we only send `protocol' error codes */ + if(error_code < KRB5KDC_ERR_NONE || error_code >= KRB5_ERR_RCSID) { + if(e_text == NULL) + e_text = krb5_get_err_text(context, error_code); + error_code = KRB5KRB_ERR_GENERIC; + } + msg.error_code = error_code - KRB5KDC_ERR_NONE; + if (e_text) + msg.e_text = rk_UNCONST(&e_text); + if (e_data) + msg.e_data = rk_UNCONST(e_data); + if(server){ + msg.realm = server->realm; + msg.sname = server->name; + }else{ + msg.realm = ""; + } + if(client){ + msg.crealm = &client->realm; + msg.cname = &client->name; + } + + ASN1_MALLOC_ENCODE(KRB_ERROR, reply->data, reply->length, &msg, &len, ret); + if (ret) + return ret; + if(reply->length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + return 0; +} diff --git a/source4/heimdal/lib/krb5/mk_priv.c b/source4/heimdal/lib/krb5/mk_priv.c new file mode 100644 index 0000000000..56112eea8c --- /dev/null +++ b/source4/heimdal/lib/krb5/mk_priv.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: mk_priv.c,v 1.34 2004/05/25 21:33:32 lha Exp $"); + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_priv(krb5_context context, + krb5_auth_context auth_context, + const krb5_data *userdata, + krb5_data *outbuf, + krb5_replay_data *outdata) +{ + krb5_error_code ret; + KRB_PRIV s; + EncKrbPrivPart part; + u_char *buf = NULL; + size_t buf_size; + size_t len; + krb5_crypto crypto; + krb5_keyblock *key; + krb5_replay_data rdata; + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + outdata == NULL) + return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */ + + if (auth_context->local_subkey) + key = auth_context->local_subkey; + else if (auth_context->remote_subkey) + key = auth_context->remote_subkey; + else + key = auth_context->keyblock; + + memset(&rdata, 0, sizeof(rdata)); + + part.user_data = *userdata; + + krb5_us_timeofday (context, &rdata.timestamp, &rdata.usec); + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + part.timestamp = &rdata.timestamp; + part.usec = &rdata.usec; + } else { + part.timestamp = NULL; + part.usec = NULL; + } + + if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_TIME) { + outdata->timestamp = rdata.timestamp; + outdata->usec = rdata.usec; + } + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + rdata.seq = auth_context->local_seqnumber; + part.seq_number = &rdata.seq; + } else + part.seq_number = NULL; + + if (auth_context->flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) + outdata->seq = auth_context->local_seqnumber; + + part.s_address = auth_context->local_address; + part.r_address = auth_context->remote_address; + + krb5_data_zero (&s.enc_part.cipher); + + ASN1_MALLOC_ENCODE(EncKrbPrivPart, buf, buf_size, &part, &len, ret); + if (ret) + goto fail; + if (buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + s.pvno = 5; + s.msg_type = krb_priv; + s.enc_part.etype = key->keytype; + s.enc_part.kvno = NULL; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + free (buf); + return ret; + } + ret = krb5_encrypt (context, + crypto, + KRB5_KU_KRB_PRIV, + buf + buf_size - len, + len, + &s.enc_part.cipher); + krb5_crypto_destroy(context, crypto); + if (ret) { + free(buf); + return ret; + } + free(buf); + + + ASN1_MALLOC_ENCODE(KRB_PRIV, buf, buf_size, &s, &len, ret); + + if(ret) + goto fail; + krb5_data_free (&s.enc_part.cipher); + + ret = krb5_data_copy(outbuf, buf + buf_size - len, len); + if (ret) { + krb5_set_error_string (context, "malloc: out of memory"); + free(buf); + return ENOMEM; + } + free (buf); + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) + auth_context->local_seqnumber = + (auth_context->local_seqnumber + 1) & 0xFFFFFFFF; + return 0; + + fail: + free (buf); + krb5_data_free (&s.enc_part.cipher); + return ret; +} diff --git a/source4/heimdal/lib/krb5/mk_rep.c b/source4/heimdal/lib/krb5/mk_rep.c new file mode 100644 index 0000000000..90823f9478 --- /dev/null +++ b/source4/heimdal/lib/krb5/mk_rep.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: mk_rep.c,v 1.26 2004/05/25 21:33:51 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_rep(krb5_context context, + krb5_auth_context auth_context, + krb5_data *outbuf) +{ + krb5_error_code ret; + AP_REP ap; + EncAPRepPart body; + u_char *buf = NULL; + size_t buf_size; + size_t len; + krb5_crypto crypto; + + ap.pvno = 5; + ap.msg_type = krb_ap_rep; + + memset (&body, 0, sizeof(body)); + + body.ctime = auth_context->authenticator->ctime; + body.cusec = auth_context->authenticator->cusec; + if (auth_context->flags & KRB5_AUTH_CONTEXT_USE_SUBKEY) { + if (auth_context->local_subkey == NULL) { + ret = krb5_auth_con_generatelocalsubkey(context, + auth_context, + auth_context->keyblock); + if(ret) { + krb5_set_error_string (context, + "krb5_mk_rep: generating subkey"); + free_EncAPRepPart(&body); + return ret; + } + } + ret = krb5_copy_keyblock(context, auth_context->local_subkey, + &body.subkey); + if (ret) { + krb5_set_error_string (context, + "krb5_copy_keyblock: out of memory"); + free_EncAPRepPart(&body); + return ENOMEM; + } + } else + body.subkey = NULL; + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + if(auth_context->local_seqnumber == 0) + krb5_generate_seq_number (context, + auth_context->keyblock, + &auth_context->local_seqnumber); + ALLOC(body.seq_number, 1); + if (body.seq_number == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + free_EncAPRepPart(&body); + return ENOMEM; + } + *(body.seq_number) = auth_context->local_seqnumber; + } else + body.seq_number = NULL; + + ap.enc_part.etype = auth_context->keyblock->keytype; + ap.enc_part.kvno = NULL; + + ASN1_MALLOC_ENCODE(EncAPRepPart, buf, buf_size, &body, &len, ret); + free_EncAPRepPart (&body); + if(ret) + return ret; + if (buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + ret = krb5_crypto_init(context, auth_context->keyblock, + 0 /* ap.enc_part.etype */, &crypto); + if (ret) { + free (buf); + return ret; + } + ret = krb5_encrypt (context, + crypto, + KRB5_KU_AP_REQ_ENC_PART, + buf + buf_size - len, + len, + &ap.enc_part.cipher); + krb5_crypto_destroy(context, crypto); + free(buf); + if (ret) + return ret; + + ASN1_MALLOC_ENCODE(AP_REP, outbuf->data, outbuf->length, &ap, &len, ret); + if (ret == 0 && outbuf->length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + free_AP_REP (&ap); + return ret; +} diff --git a/source4/heimdal/lib/krb5/mk_req.c b/source4/heimdal/lib/krb5/mk_req.c new file mode 100644 index 0000000000..adc077e13f --- /dev/null +++ b/source4/heimdal/lib/krb5/mk_req.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: mk_req.c,v 1.26 2004/05/25 21:34:11 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_req_exact(krb5_context context, + krb5_auth_context *auth_context, + const krb5_flags ap_req_options, + const krb5_principal server, + krb5_data *in_data, + krb5_ccache ccache, + krb5_data *outbuf) +{ + krb5_error_code ret; + krb5_creds this_cred, *cred; + + memset(&this_cred, 0, sizeof(this_cred)); + + ret = krb5_cc_get_principal(context, ccache, &this_cred.client); + + if(ret) + return ret; + + ret = krb5_copy_principal (context, server, &this_cred.server); + if (ret) { + krb5_free_cred_contents (context, &this_cred); + return ret; + } + + this_cred.times.endtime = 0; + if (auth_context && *auth_context && (*auth_context)->keytype) + this_cred.session.keytype = (*auth_context)->keytype; + + ret = krb5_get_credentials (context, 0, ccache, &this_cred, &cred); + krb5_free_cred_contents(context, &this_cred); + if (ret) + return ret; + + ret = krb5_mk_req_extended (context, + auth_context, + ap_req_options, + in_data, + cred, + outbuf); + krb5_free_creds(context, cred); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_req(krb5_context context, + krb5_auth_context *auth_context, + const krb5_flags ap_req_options, + const char *service, + const char *hostname, + krb5_data *in_data, + krb5_ccache ccache, + krb5_data *outbuf) +{ + krb5_error_code ret; + char **realms; + char *real_hostname; + krb5_principal server; + + ret = krb5_expand_hostname_realms (context, hostname, + &real_hostname, &realms); + if (ret) + return ret; + + ret = krb5_build_principal (context, &server, + strlen(*realms), + *realms, + service, + real_hostname, + NULL); + free (real_hostname); + krb5_free_host_realm (context, realms); + if (ret) + return ret; + ret = krb5_mk_req_exact (context, auth_context, ap_req_options, + server, in_data, ccache, outbuf); + krb5_free_principal (context, server); + return ret; +} diff --git a/source4/heimdal/lib/krb5/mk_req_ext.c b/source4/heimdal/lib/krb5/mk_req_ext.c new file mode 100644 index 0000000000..ab83d912ea --- /dev/null +++ b/source4/heimdal/lib/krb5/mk_req_ext.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: mk_req_ext.c,v 1.30 2005/01/05 06:31:01 lukeh Exp $"); + +krb5_error_code +_krb5_mk_req_internal(krb5_context context, + krb5_auth_context *auth_context, + const krb5_flags ap_req_options, + krb5_data *in_data, + krb5_creds *in_creds, + krb5_data *outbuf, + krb5_key_usage checksum_usage, + krb5_key_usage encrypt_usage) +{ + krb5_error_code ret; + krb5_data authenticator; + Checksum c; + Checksum *c_opt; + krb5_auth_context ac; + + if(auth_context) { + if(*auth_context == NULL) + ret = krb5_auth_con_init(context, auth_context); + else + ret = 0; + ac = *auth_context; + } else + ret = krb5_auth_con_init(context, &ac); + if(ret) + return ret; + + if(ac->local_subkey == NULL && (ap_req_options & AP_OPTS_USE_SUBKEY)) { + ret = krb5_auth_con_generatelocalsubkey(context, ac, &in_creds->session); + if(ret) + return ret; + } + +#if 0 + { + /* This is somewhat bogus since we're possibly overwriting a + value specified by the user, but it's the easiest way to make + the code use a compatible enctype */ + Ticket ticket; + krb5_keytype ticket_keytype; + + ret = decode_Ticket(in_creds->ticket.data, + in_creds->ticket.length, + &ticket, + NULL); + krb5_enctype_to_keytype (context, + ticket.enc_part.etype, + &ticket_keytype); + + if (ticket_keytype == in_creds->session.keytype) + krb5_auth_setenctype(context, + ac, + ticket.enc_part.etype); + free_Ticket(&ticket); + } +#endif + + krb5_free_keyblock(context, ac->keyblock); + krb5_copy_keyblock(context, &in_creds->session, &ac->keyblock); + + /* it's unclear what type of checksum we can use. try the best one, except: + * a) if it's configured differently for the current realm, or + * b) if the session key is des-cbc-crc + */ + + if (in_data) { + if(ac->keyblock->keytype == ETYPE_DES_CBC_CRC) { + /* this is to make DCE secd (and older MIT kdcs?) happy */ + ret = krb5_create_checksum(context, + NULL, + 0, + CKSUMTYPE_RSA_MD4, + in_data->data, + in_data->length, + &c); + } else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5 || + ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56) { + /* this is to make MS kdc happy */ + ret = krb5_create_checksum(context, + NULL, + 0, + CKSUMTYPE_RSA_MD5, + in_data->data, + in_data->length, + &c); + } else { + krb5_crypto crypto; + + ret = krb5_crypto_init(context, ac->keyblock, 0, &crypto); + if (ret) + return ret; + ret = krb5_create_checksum(context, + crypto, + checksum_usage, + 0, + in_data->data, + in_data->length, + &c); + + krb5_crypto_destroy(context, crypto); + } + c_opt = &c; + } else { + c_opt = NULL; + } + + ret = krb5_build_authenticator (context, + ac, + ac->keyblock->keytype, + in_creds, + c_opt, + NULL, + &authenticator, + encrypt_usage); + if (c_opt) + free_Checksum (c_opt); + if (ret) + return ret; + + ret = krb5_build_ap_req (context, ac->keyblock->keytype, + in_creds, ap_req_options, authenticator, outbuf); + if(auth_context == NULL) + krb5_auth_con_free(context, ac); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_mk_req_extended(krb5_context context, + krb5_auth_context *auth_context, + const krb5_flags ap_req_options, + krb5_data *in_data, + krb5_creds *in_creds, + krb5_data *outbuf) +{ + return _krb5_mk_req_internal (context, + auth_context, + ap_req_options, + in_data, + in_creds, + outbuf, + KRB5_KU_AP_REQ_AUTH_CKSUM, + KRB5_KU_AP_REQ_AUTH); +} diff --git a/source4/heimdal/lib/krb5/n-fold.c b/source4/heimdal/lib/krb5/n-fold.c new file mode 100644 index 0000000000..691e95eb86 --- /dev/null +++ b/source4/heimdal/lib/krb5/n-fold.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 KTH 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 KTH AND ITS 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 KTH OR ITS 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. */ + +#include "krb5_locl.h" + +RCSID("$Id: n-fold.c,v 1.7 2004/05/25 21:35:31 lha Exp $"); + +static void +rr13(unsigned char *buf, size_t len) +{ + unsigned char *tmp; + int bytes = (len + 7) / 8; + int i; + if(len == 0) + return; + { + const int bits = 13 % len; + const int lbit = len % 8; + + tmp = malloc(bytes); + memcpy(tmp, buf, bytes); + if(lbit) { + /* pad final byte with inital bits */ + tmp[bytes - 1] &= 0xff << (8 - lbit); + for(i = lbit; i < 8; i += len) + tmp[bytes - 1] |= buf[0] >> i; + } + for(i = 0; i < bytes; i++) { + int bb; + int b1, s1, b2, s2; + /* calculate first bit position of this byte */ + bb = 8 * i - bits; + while(bb < 0) + bb += len; + /* byte offset and shift count */ + b1 = bb / 8; + s1 = bb % 8; + + if(bb + 8 > bytes * 8) + /* watch for wraparound */ + s2 = (len + 8 - s1) % 8; + else + s2 = 8 - s1; + b2 = (b1 + 1) % bytes; + buf[i] = (tmp[b1] << s1) | (tmp[b2] >> s2); + } + free(tmp); + } +} + +/* Add `b' to `a', both beeing one's complement numbers. */ +static void +add1(unsigned char *a, unsigned char *b, size_t len) +{ + int i; + int carry = 0; + for(i = len - 1; i >= 0; i--){ + int x = a[i] + b[i] + carry; + carry = x > 0xff; + a[i] = x & 0xff; + } + for(i = len - 1; carry && i >= 0; i--){ + int x = a[i] + carry; + carry = x > 0xff; + a[i] = x & 0xff; + } +} + +void KRB5_LIB_FUNCTION +_krb5_n_fold(const void *str, size_t len, void *key, size_t size) +{ + /* if len < size we need at most N * len bytes, ie < 2 * size; + if len > size we need at most 2 * len */ + size_t maxlen = 2 * max(size, len); + size_t l = 0; + unsigned char *tmp = malloc(maxlen); + unsigned char *buf = malloc(len); + + memcpy(buf, str, len); + memset(key, 0, size); + do { + memcpy(tmp + l, buf, len); + l += len; + rr13(buf, len * 8); + while(l >= size) { + add1(key, tmp, size); + l -= size; + if(l == 0) + break; + memmove(tmp, tmp + size, l); + } + } while(l != 0); + memset(buf, 0, len); + free(buf); + memset(tmp, 0, maxlen); + free(tmp); +} diff --git a/source4/heimdal/lib/krb5/padata.c b/source4/heimdal/lib/krb5/padata.c new file mode 100644 index 0000000000..d5c3f422a7 --- /dev/null +++ b/source4/heimdal/lib/krb5/padata.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: padata.c,v 1.5 2005/06/17 04:28:35 lha Exp $"); + +PA_DATA * +krb5_find_padata(PA_DATA *val, unsigned len, int type, int *idx) +{ + for(; *idx < len; (*idx)++) + if(val[*idx].padata_type == type) + return val + *idx; + return NULL; +} + +int KRB5_LIB_FUNCTION +krb5_padata_add(krb5_context context, METHOD_DATA *md, + int type, void *buf, size_t len) +{ + PA_DATA *pa; + + pa = realloc (md->val, (md->len + 1) * sizeof(*md->val)); + if (pa == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + md->val = pa; + + pa[md->len].padata_type = type; + pa[md->len].padata_value.length = len; + pa[md->len].padata_value.data = buf; + md->len++; + + return 0; +} diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c new file mode 100755 index 0000000000..84db4fe544 --- /dev/null +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -0,0 +1,2583 @@ +/* + * Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: pkinit.c,v 1.55 2005/05/19 18:49:05 lha Exp $"); + +#ifdef PKINIT + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_DIRENT_H +#include +#endif + +#include "heim_asn1.h" +#include "rfc2459_asn1.h" +#include "cms_asn1.h" +#include "pkinit_asn1.h" + +enum { + COMPAT_WIN2K = 1, + COMPAT_19 = 2, + COMPAT_25 = 3 +}; + + + +#define OPENSSL_ASN1_MALLOC_ENCODE(T, B, BL, S, R) \ +{ \ + unsigned char *p; \ + (BL) = i2d_##T((S), NULL); \ + if ((BL) <= 0) { \ + (R) = EINVAL; \ + } else { \ + (B) = malloc((BL)); \ + if ((B) == NULL) { \ + (R) = ENOMEM; \ + } else { \ + p = (B); \ + (R) = 0; \ + (BL) = i2d_##T((S), &p); \ + if ((BL) <= 0) { \ + free((B)); \ + (R) = ASN1_OVERRUN; \ + } \ + } \ + } \ +} + +/* ENGING_load_private_key requires a UI_METHOD and data + * if to be usable from PAM + */ + +struct krb5_ui_data { + krb5_context context; + krb5_prompter_fct prompter; + void * prompter_data; +}; + +struct krb5_pk_identity { + EVP_PKEY *private_key; + STACK_OF(X509) *cert; + STACK_OF(X509) *trusted_certs; + STACK_OF(X509_CRL) *crls; + ENGINE *engine; +}; + +struct krb5_pk_cert { + X509 *cert; +}; + +struct krb5_pk_init_ctx_data { + struct krb5_pk_identity *id; + DH *dh; +}; + + +void KRB5_LIB_FUNCTION +_krb5_pk_cert_free(struct krb5_pk_cert *cert) +{ + if (cert->cert) + X509_free(cert->cert); + free(cert); +} + +static krb5_error_code +BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer) +{ + integer->length = BN_num_bytes(bn); + integer->data = malloc(integer->length); + if (integer->data == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + BN_bn2bin(bn, integer->data); + integer->negative = bn->neg; + return 0; +} + +/* + * UI ex_data has the callback_data as passed to Engine. This is far + * from being complete, we will only process one prompt + */ + +static int +krb5_ui_method_read_string(UI *ui, UI_STRING *uis) +{ + char *buffer; + size_t length; + krb5_error_code ret; + krb5_prompt prompt; + krb5_data password_data; + struct krb5_ui_data *ui_data; + + ui_data = (struct krb5_ui_data *)UI_get_app_data(ui); + + switch (UI_get_string_type(uis)) { + case UIT_INFO: + case UIT_ERROR: + /* looks like the RedHat pam_prompter might handle + * INFO and ERROR, Will see what happens */ + case UIT_VERIFY: + case UIT_PROMPT: + length = UI_get_result_maxsize(uis); + buffer = malloc(length); + if (buffer == NULL) { + krb5_set_error_string(ui_data->context, "malloc: out of memory"); + return 0; + } + password_data.data = buffer; + password_data.length = length; + + prompt.prompt = UI_get0_output_string(uis); + prompt.hidden = !(UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO); + prompt.reply = &password_data; + prompt.type = KRB5_PROMPT_TYPE_PASSWORD; + + ret = (*ui_data->prompter)(ui_data->context, + ui_data->prompter_data, + NULL, NULL, 1, &prompt); + if (ret == 0) { + buffer[length - 1] = '\0'; + UI_set_result(ui, uis, password_data.data); + + /* + * RedHat pam_krb5 pam_prompter does a strdup but others + * may copy into buffer. XXX should we just leak the + * memory instead ? + */ + + if (buffer != password_data.data) + free(password_data.data); + memset (buffer, 0, length); + free(buffer); + return 1; + } + memset (buffer, 0, length); + free(buffer); + break; + case UIT_NONE: + case UIT_BOOLEAN: + /* XXX for now do not handle */ + break; + + } + return 0; +} + + +static krb5_error_code +set_digest_alg(DigestAlgorithmIdentifier *id, + const heim_oid *oid, + void *param, size_t length) +{ + krb5_error_code ret; + if (param) { + id->parameters = malloc(sizeof(*id->parameters)); + if (id->parameters == NULL) + return ENOMEM; + id->parameters->data = malloc(length); + if (id->parameters->data == NULL) { + free(id->parameters); + id->parameters = NULL; + return ENOMEM; + } + memcpy(id->parameters->data, param, length); + id->parameters->length = length; + } else + id->parameters = NULL; + ret = copy_oid(oid, &id->algorithm); + if (ret) { + if (id->parameters) { + free(id->parameters->data); + free(id->parameters); + id->parameters = NULL; + } + return ret; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_create_sign(krb5_context context, + const heim_oid *eContentType, + krb5_data *eContent, + struct krb5_pk_identity *id, + krb5_data *sd_data) +{ + SignerInfo *signer_info; + X509 *user_cert; + heim_integer *serial; + krb5_error_code ret; + krb5_data buf; + SignedData sd; + EVP_MD_CTX md; + int len, i; + size_t size; + + X509_NAME *issuer_name; + + memset(&sd, 0, sizeof(sd)); + + if (id == NULL) + return HEIM_PKINIT_NO_CERTIFICATE; + if (id->cert == NULL) + return HEIM_PKINIT_NO_CERTIFICATE; + if (id->private_key == NULL) + return HEIM_PKINIT_NO_PRIVATE_KEY; + + if (sk_X509_num(id->cert) == 0) + return HEIM_PKINIT_NO_CERTIFICATE; + + sd.version = 3; + + sd.digestAlgorithms.len = 0; + sd.digestAlgorithms.val = NULL; + copy_oid(eContentType, &sd.encapContentInfo.eContentType); + ALLOC(sd.encapContentInfo.eContent, 1); + if (sd.encapContentInfo.eContent == NULL) { + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + ret = krb5_data_copy(&buf, eContent->data, eContent->length); + if (ret) { + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + sd.encapContentInfo.eContent->data = buf.data; + sd.encapContentInfo.eContent->length = buf.length; + + ALLOC_SEQ(&sd.signerInfos, 1); + if (sd.signerInfos.val == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + + signer_info = &sd.signerInfos.val[0]; + + user_cert = sk_X509_value(id->cert, 0); + if (user_cert == NULL) { + krb5_set_error_string(context, "pkinit: no user certificate"); + ret = HEIM_PKINIT_NO_CERTIFICATE; + goto out; + } + + signer_info->version = 1; + + issuer_name = X509_get_issuer_name(user_cert); + + OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, + buf.data, + buf.length, + issuer_name, + ret); + if (ret) { + krb5_set_error_string(context, "pkinit: failed encoding name"); + goto out; + } + ret = decode_Name(buf.data, buf.length, + &signer_info->sid.u.issuerAndSerialNumber.issuer, + NULL); + free(buf.data); + if (ret) { + krb5_set_error_string(context, "pkinit: failed to parse Name"); + goto out; + } + signer_info->sid.element = choice_CMSIdentifier_issuerAndSerialNumber; + + serial = &signer_info->sid.u.issuerAndSerialNumber.serialNumber; + { + ASN1_INTEGER *isn = X509_get_serialNumber(user_cert); + BIGNUM *bn = ASN1_INTEGER_to_BN(isn, NULL); + if (bn == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "pkinit: failed allocating " + "serial number"); + goto out; + } + ret = BN_to_integer(context, bn, serial); + BN_free(bn); + if (ret) { + krb5_set_error_string(context, "pkinit: failed encoding " + "serial number"); + goto out; + } + } + + ret = set_digest_alg(&signer_info->digestAlgorithm, + oid_id_secsig_sha_1(), "\x05\x00", 2); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + goto out; + } + + signer_info->signedAttrs = NULL; + signer_info->unsignedAttrs = NULL; + + copy_oid(oid_id_pkcs1_rsaEncryption(), + &signer_info->signatureAlgorithm.algorithm); + signer_info->signatureAlgorithm.parameters = NULL; + + buf.data = malloc(EVP_PKEY_size(id->private_key)); + if (buf.data == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + + EVP_SignInit(&md, EVP_sha1()); + EVP_SignUpdate(&md, + sd.encapContentInfo.eContent->data, + sd.encapContentInfo.eContent->length); + ret = EVP_SignFinal(&md, buf.data, &len, id->private_key); + if (ret != 1) { + free(buf.data); + krb5_set_error_string(context, "PKINIT: failed to sign with " + "private key: %s", + ERR_error_string(ERR_get_error(), NULL)); + ret = EINVAL; + goto out; + } + + signer_info->signature.data = buf.data; + signer_info->signature.length = len; + + ALLOC_SEQ(&sd.digestAlgorithms, 1); + if (sd.digestAlgorithms.val == NULL) { + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + ret = set_digest_alg(&sd.digestAlgorithms.val[0], + oid_id_secsig_sha_1(), "\x05\x00", 2); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + goto out; + } + + ALLOC(sd.certificates, 1); + if (sd.certificates == NULL) { + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + + sd.certificates->data = NULL; + sd.certificates->length = 0; + + for (i = 0; i < sk_X509_num(id->cert); i++) { + void *data; + + OPENSSL_ASN1_MALLOC_ENCODE(X509, + buf.data, + buf.length, + sk_X509_value(id->cert, i), + ret); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + data = realloc(sd.certificates->data, + sd.certificates->length + buf.length); + if (data == NULL) { + free(buf.data); + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + memcpy(((char *)data) + sd.certificates->length, + buf.data, buf.length); + sd.certificates->length += buf.length; + sd.certificates->data = data; + free(buf.data); + } + + ASN1_MALLOC_ENCODE(SignedData, sd_data->data, sd_data->length, + &sd, &size, ret); + if (ret) { + krb5_set_error_string(context, "SignedData failed %d", ret); + goto out; + } + if (sd_data->length != size) + krb5_abortx(context, "internal ASN1 encoder error"); + + out: + free_SignedData(&sd); + + return ret; +} + +static krb5_error_code +build_auth_pack_win2k(krb5_context context, + unsigned nonce, + const KDC_REQ_BODY *body, + AuthPack_Win2k *a) +{ + krb5_error_code ret; + krb5_timestamp sec; + int32_t usec; + + /* fill in PKAuthenticator */ + ret = copy_PrincipalName(body->sname, &a->pkAuthenticator.kdcName); + if (ret) + return ret; + ret = copy_Realm(&body->realm, &a->pkAuthenticator.kdcRealm); + if (ret) + return ret; + + krb5_us_timeofday(context, &sec, &usec); + a->pkAuthenticator.ctime = sec; + a->pkAuthenticator.cusec = usec; + a->pkAuthenticator.nonce = nonce; + + return 0; +} + +static krb5_error_code +build_auth_pack_19(krb5_context context, + unsigned nonce, + const KDC_REQ_BODY *body, + AuthPack_19 *a) +{ + size_t buf_size, len; + krb5_cksumtype cksum; + krb5_error_code ret; + void *buf; + krb5_timestamp sec; + int32_t usec; + + krb5_clear_error_string(context); + + /* XXX some PACKETCABLE needs implemetations need md5 */ + cksum = CKSUMTYPE_RSA_MD5; + + krb5_us_timeofday(context, &sec, &usec); + a->pkAuthenticator.ctime = sec; + a->pkAuthenticator.nonce = nonce; + + ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret); + if (ret) + return ret; + if (buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_create_checksum(context, + NULL, + 0, + cksum, + buf, + len, + &a->pkAuthenticator.paChecksum); + free(buf); + + return ret; +} + +static krb5_error_code +build_auth_pack(krb5_context context, + unsigned nonce, + DH *dh, + const KDC_REQ_BODY *body, + AuthPack *a) +{ + size_t buf_size, len; + krb5_error_code ret; + void *buf; + krb5_timestamp sec; + int32_t usec; + Checksum checksum; + + krb5_clear_error_string(context); + + memset(&checksum, 0, sizeof(checksum)); + + krb5_us_timeofday(context, &sec, &usec); + a->pkAuthenticator.ctime = sec; + a->pkAuthenticator.nonce = nonce; + + ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret); + if (ret) + return ret; + if (buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_create_checksum(context, + NULL, + 0, + CKSUMTYPE_SHA1, + buf, + len, + &checksum); + free(buf); + if (ret == 0) { + ret = krb5_data_copy(&a->pkAuthenticator.paChecksum, + checksum.checksum.data, checksum.checksum.length); + free_Checksum(&checksum); + } + + if (ret == 0 && dh) { + DomainParameters dp; + heim_integer dh_pub_key; + krb5_data buf; + size_t size; + + ALLOC(a->clientPublicValue, 1); + if (a->clientPublicValue == NULL) + return ENOMEM; + ret = copy_oid(oid_id_dhpublicnumber(), + &a->clientPublicValue->algorithm.algorithm); + if (ret) + return ret; + + memset(&dp, 0, sizeof(dp)); + + ret = BN_to_integer(context, dh->p, &dp.p); + if (ret) { + free_DomainParameters(&dp); + return ret; + } + ret = BN_to_integer(context, dh->g, &dp.g); + if (ret) { + free_DomainParameters(&dp); + return ret; + } + ret = BN_to_integer(context, dh->q, &dp.q); + if (ret) { + free_DomainParameters(&dp); + return ret; + } + dp.j = NULL; + dp.validationParms = NULL; + + a->clientPublicValue->algorithm.parameters = + malloc(sizeof(*a->clientPublicValue->algorithm.parameters)); + if (a->clientPublicValue->algorithm.parameters == NULL) { + free_DomainParameters(&dp); + return ret; + } + + ASN1_MALLOC_ENCODE(DomainParameters, + a->clientPublicValue->algorithm.parameters->data, + a->clientPublicValue->algorithm.parameters->length, + &dp, &size, ret); + free_DomainParameters(&dp); + if (ret) + return ret; + if (size != a->clientPublicValue->algorithm.parameters->length) + krb5_abortx(context, "Internal ASN1 encoder error"); + + ret = BN_to_integer(context, dh->pub_key, &dh_pub_key); + if (ret) + return ret; + + buf.length = length_heim_integer(&dh_pub_key); + buf.data = malloc(buf.length); + if (buf.data == NULL) { + free_heim_integer(&dh_pub_key); + krb5_set_error_string(context, "malloc: out of memory"); + return ret; + } + ret = der_put_heim_integer((char *)buf.data + buf.length - 1, + buf.length, &dh_pub_key, &size); + free_heim_integer(&dh_pub_key); + if (ret) { + free(buf.data); + return ret; + } + if (size != buf.length) + krb5_abortx(context, "asn1 internal error"); + + a->clientPublicValue->subjectPublicKey.length = buf.length * 8; + a->clientPublicValue->subjectPublicKey.data = buf.data; + } + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_mk_ContentInfo(krb5_context context, + const krb5_data *buf, + const heim_oid *oid, + struct ContentInfo *content_info) +{ + krb5_error_code ret; + + ret = copy_oid(oid, &content_info->contentType); + if (ret) + return ret; + ALLOC(content_info->content, 1); + if (content_info->content == NULL) + return ENOMEM; + content_info->content->data = malloc(buf->length); + if (content_info->content->data == NULL) + return ENOMEM; + memcpy(content_info->content->data, buf->data, buf->length); + content_info->content->length = buf->length; + return 0; +} + +static krb5_error_code +pk_mk_padata(krb5_context context, + int compat, + krb5_pk_init_ctx ctx, + const KDC_REQ_BODY *req_body, + unsigned nonce, + METHOD_DATA *md) +{ + struct ContentInfo content_info; + krb5_error_code ret; + const heim_oid *oid; + PA_PK_AS_REQ req; + size_t size; + krb5_data buf, sd_buf; + int pa_type; + + krb5_data_zero(&buf); + krb5_data_zero(&sd_buf); + memset(&req, 0, sizeof(req)); + memset(&content_info, 0, sizeof(content_info)); + + if (compat == COMPAT_WIN2K) { + AuthPack_Win2k ap; + + memset(&ap, 0, sizeof(ap)); + + ret = build_auth_pack_win2k(context, nonce, req_body, &ap); + if (ret) { + free_AuthPack_Win2k(&ap); + goto out; + } + + ASN1_MALLOC_ENCODE(AuthPack_Win2k, buf.data, buf.length, + &ap, &size, ret); + free_AuthPack_Win2k(&ap); + if (ret) { + krb5_set_error_string(context, "AuthPack_Win2k: %d", ret); + goto out; + } + if (buf.length != size) + krb5_abortx(context, "internal ASN1 encoder error"); + + oid = oid_id_pkcs7_data(); + } else if (compat == COMPAT_19) { + AuthPack_19 ap; + + memset(&ap, 0, sizeof(ap)); + + ret = build_auth_pack_19(context, nonce, req_body, &ap); + if (ret) { + free_AuthPack_19(&ap); + goto out; + } + + ASN1_MALLOC_ENCODE(AuthPack_19, buf.data, buf.length, &ap, &size, ret); + free_AuthPack_19(&ap); + if (ret) { + krb5_set_error_string(context, "AuthPack_19: %d", ret); + goto out; + } + if (buf.length != size) + krb5_abortx(context, "internal ASN1 encoder error"); + + oid = oid_id_pkauthdata(); + } else if (compat == COMPAT_25) { + AuthPack ap; + + memset(&ap, 0, sizeof(ap)); + + ret = build_auth_pack(context, nonce, ctx->dh, req_body, &ap); + if (ret) { + free_AuthPack(&ap); + goto out; + } + + ASN1_MALLOC_ENCODE(AuthPack, buf.data, buf.length, &ap, &size, ret); + free_AuthPack(&ap); + if (ret) { + krb5_set_error_string(context, "AuthPack: %d", ret); + goto out; + } + if (buf.length != size) + krb5_abortx(context, "internal ASN1 encoder error"); + + oid = oid_id_pkauthdata(); + } else + krb5_abortx(context, "internal pkinit error"); + + ret = _krb5_pk_create_sign(context, + oid, + &buf, + ctx->id, + &sd_buf); + krb5_data_free(&buf); + if (ret) + goto out; + + ret = _krb5_pk_mk_ContentInfo(context, &sd_buf, oid_id_pkcs7_signedData(), + &content_info); + krb5_data_free(&sd_buf); + if (ret) + goto out; + + /* XXX tell the kdc what CAs the client is willing to accept */ + req.trustedCertifiers = NULL; + req.kdcPkId = NULL; + + if (compat == COMPAT_WIN2K) { + PA_PK_AS_REQ_Win2k winreq; + + pa_type = KRB5_PADATA_PK_AS_REQ_WIN; + + memset(&winreq, 0, sizeof(winreq)); + + ASN1_MALLOC_ENCODE(ContentInfo, + winreq.signed_auth_pack.data, + winreq.signed_auth_pack.length, + &content_info, + &size, + ret); + if (ret) + goto out; + if (winreq.signed_auth_pack.length != size) + krb5_abortx(context, "Internal ASN1 encoder error"); + + ASN1_MALLOC_ENCODE(PA_PK_AS_REQ_Win2k, buf.data, buf.length, + &winreq, &size, ret); + free_PA_PK_AS_REQ_Win2k(&winreq); + + } else if (compat == COMPAT_19) { + PA_PK_AS_REQ_19 req_19; + + pa_type = KRB5_PADATA_PK_AS_REQ_19; + + memset(&req_19, 0, sizeof(req_19)); + + ret = copy_ContentInfo(&content_info, &req_19.signedAuthPack); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + req_19.kdcCert = NULL; + req_19.trustedCertifiers = NULL; + req_19.encryptionCert = NULL; + + ASN1_MALLOC_ENCODE(PA_PK_AS_REQ_19, buf.data, buf.length, + &req_19, &size, ret); + + free_PA_PK_AS_REQ_19(&req_19); + + } else if (compat == COMPAT_25) { + + pa_type = KRB5_PADATA_PK_AS_REQ; + + ASN1_MALLOC_ENCODE(ContentInfo, + req.signedAuthPack.data, + req.signedAuthPack.length, + &content_info, + &size, + ret); + if (ret) + goto out; + if (req.signedAuthPack.length != size) + krb5_abortx(context, "Internal ASN1 encoder error"); + + ASN1_MALLOC_ENCODE(PA_PK_AS_REQ, buf.data, buf.length, + &req, &size, ret); + + } else + krb5_abortx(context, "internal pkinit error"); + if (ret) { + krb5_set_error_string(context, "PA-PK-AS-REQ %d", ret); + goto out; + } + if (buf.length != size) + krb5_abortx(context, "Internal ASN1 encoder error"); + + ret = krb5_padata_add(context, md, pa_type, buf.data, buf.length); + if (ret) + free(buf.data); + out: + free_ContentInfo(&content_info); + + return ret; +} + + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_mk_padata(krb5_context context, + void *c, + const KDC_REQ_BODY *req_body, + unsigned nonce, + METHOD_DATA *md) +{ + krb5_pk_init_ctx ctx = c; + krb5_error_code ret; + size_t size; + krb5_data buf; + const char *provisioning_server; + int win2k_compat; + + win2k_compat = krb5_config_get_bool_default(context, NULL, + FALSE, + "realms", + req_body->realm, + "win2k_pkinit", + NULL); + if (context->pkinit_flags & KRB5_PKINIT_WIN2K) + win2k_compat = 1; + + if (win2k_compat) { + ret = pk_mk_padata(context, COMPAT_WIN2K, ctx, req_body, nonce, md); + if (ret) + goto out; + } else { + ret = pk_mk_padata(context, COMPAT_19, ctx, req_body, nonce, md); + if (ret) + goto out; + + ret = pk_mk_padata(context, COMPAT_25, ctx, req_body, nonce, md); + if (ret) + goto out; + } + + provisioning_server = + krb5_config_get_string(context, NULL, + "realms", + req_body->realm, + "packet-cable-provisioning-server", + NULL); + + if (provisioning_server) { + /* PacketCable requires the PROV-SRV-LOCATION authenticator */ + const PROV_SRV_LOCATION prov_server = (char *)provisioning_server; + + ASN1_MALLOC_ENCODE(PROV_SRV_LOCATION, buf.data, buf.length, + &prov_server, &size, ret); + if (ret) + goto out; + if (buf.length != size) + krb5_abortx(context, "Internal ASN1 encoder error"); + + /* PacketCable uses -1 (application specific) as the auth data type */ + ret = krb5_padata_add(context, md, -1, buf.data, buf.length); + if (ret) + free(buf.data); + } + out: + return ret; +} + +static krb5_boolean +pk_peer_compare(krb5_context context, + const SignerIdentifier *peer1, + X509 *peer2) +{ + switch (peer1->element) { + case choice_CMSIdentifier_issuerAndSerialNumber: { + ASN1_INTEGER *i; + const heim_integer *serial; + X509_NAME *name; + unsigned char *p; + size_t len; + + i = X509_get_serialNumber(peer2); + serial = &peer1->u.issuerAndSerialNumber.serialNumber; + + if (i->length != serial->length || + memcmp(i->data, serial->data, i->length) != 0) + return FALSE; + + p = peer1->u.issuerAndSerialNumber.issuer._save.data; + len = peer1->u.issuerAndSerialNumber.issuer._save.length; + name = d2i_X509_NAME(NULL, &p, len); + if (name == NULL) + return FALSE; + + if (X509_NAME_cmp(name, X509_get_issuer_name(peer2)) != 0) { + X509_NAME_free(name); + return FALSE; + } + X509_NAME_free(name); + break; + } + case choice_CMSIdentifier_subjectKeyIdentifier: + return FALSE; + default: + return FALSE; + } + return TRUE; +} + +static krb5_error_code +pk_decrypt_key(krb5_context context, + heim_octet_string *encrypted_key, + EVP_PKEY *priv_key, + krb5_keyblock *key) +{ + int ret; + unsigned char *buf; + + buf = malloc(EVP_PKEY_size(priv_key)); + if (buf == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = EVP_PKEY_decrypt(buf, + encrypted_key->data, + encrypted_key->length, + priv_key); + if (ret <= 0) { + free(buf); + krb5_set_error_string(context, "Can't decrypt key: %s", + ERR_error_string(ERR_get_error(), NULL)); + return ENOMEM; + } + + key->keytype = 0; + key->keyvalue.length = ret; + key->keyvalue.data = malloc(ret); + if (key->keyvalue.data == NULL) { + free(buf); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(key->keyvalue.data, buf, ret); + free(buf); + return 0; +} + + +static krb5_error_code +pk_verify_chain_standard(krb5_context context, + struct krb5_pk_identity *id, + const SignerIdentifier *client, + STACK_OF(X509) *chain, + X509 **client_cert) +{ + X509_STORE *cert_store = NULL; + X509_STORE_CTX *store_ctx = NULL; + X509 *cert = NULL; + int i; + int ret; + + ret = KRB5_KDC_ERROR_CLIENT_NAME_MISMATCH; + for (i = 0; i < sk_X509_num(chain); i++) { + cert = sk_X509_value(chain, i); + if (pk_peer_compare(context, client, cert) == TRUE) { + ret = 0; + break; + } + } + if (ret) { + krb5_set_error_string(context, "PKINIT: verify chain failed " + "to find client in chain"); + return ret; + } + + cert_store = X509_STORE_new(); + if (cert_store == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "PKINIT: can't create X509 store: %s", + ERR_error_string(ERR_get_error(), NULL)); + } + + store_ctx = X509_STORE_CTX_new(); + if (store_ctx == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, + "PKINIT: can't create X509 store ctx: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto end; + } + + X509_STORE_CTX_init(store_ctx, cert_store, cert, chain); + X509_STORE_CTX_trusted_stack(store_ctx, id->trusted_certs); + X509_verify_cert(store_ctx); + /* the last checked certificate is in store_ctx->current_cert */ + krb5_clear_error_string(context); + switch(store_ctx->error) { + case X509_V_OK: + ret = 0; + break; + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: + ret = KRB5_KDC_ERROR_CANT_VERIFY_CERTIFICATE; + krb5_set_error_string(context, "PKINIT: failed to verify " + "certificate: %s ", + X509_verify_cert_error_string(store_ctx->error)); + break; + case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: + case X509_V_ERR_CERT_SIGNATURE_FAILURE: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + case X509_V_ERR_CERT_HAS_EXPIRED: + ret = KRB5_KDC_ERROR_INVALID_CERTIFICATE; + krb5_set_error_string(context, "PKINIT: invalid certificate: %s ", + X509_verify_cert_error_string(store_ctx->error)); + break; + case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: + case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: + case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: + case X509_V_ERR_CERT_CHAIN_TOO_LONG: + case X509_V_ERR_PATH_LENGTH_EXCEEDED: + case X509_V_ERR_INVALID_CA: + ret = KRB5_KDC_ERROR_INVALID_CERTIFICATE; + krb5_set_error_string(context, "PKINIT: unknown CA or can't " + "verify certificate: %s", + X509_verify_cert_error_string(store_ctx->error)); + break; + default: + ret = KRB5_KDC_ERROR_INVALID_CERTIFICATE; /* XXX */ + krb5_set_error_string(context, "PKINIT: failed to verify " + "certificate: %s (%ld) ", + X509_verify_cert_error_string(store_ctx->error), + (long)store_ctx->error); + break; + } + if (ret) + goto end; + + /* + * Since X509_verify_cert() doesn't do CRL checking at all, we have to + * perform own verification against CRLs + */ +#if 0 + ret = pk_verify_crl(context, store_ctx, id->crls); + if (ret) + goto end; +#endif + + if (client_cert && cert) + *client_cert = X509_dup(cert); + + end: + if (cert_store) + X509_STORE_free(cert_store); + if (store_ctx) + X509_STORE_CTX_free(store_ctx); + return ret; +} + +static int +cert_to_X509(krb5_context context, CertificateSetReal *set, + STACK_OF(X509_CRL) **certs) +{ + krb5_error_code ret; + int i; + + *certs = sk_X509_new_null(); + + ret = 0; + for (i = 0; i < set->len; i++) { + unsigned char *p; + X509 *cert; + + p = set->val[i].data; + cert = d2i_X509(NULL, &p, set->val[i].length); + if (cert == NULL) { + ret = ASN1_BAD_FORMAT; + break; + } + sk_X509_insert(*certs, cert, i); + } + if (ret) { + krb5_set_error_string(context, + "PKINIT: Failed to decode certificate chain"); + sk_X509_free(*certs); + *certs = NULL; + } + return ret; +} + +static krb5_error_code +any_to_CertificateSet(krb5_context context, heim_any *cert, + CertificateSetReal *set) +{ + size_t size, len, length; + heim_any *val; + int ret; + char *p; + + set->len = 0; + set->val = NULL; + + len = 0; + p = cert->data; + length = cert->length; + while (len < cert->length) { + val = realloc(set->val, (set->len + 1) * sizeof(set->val[0])); + if (val == NULL) { + ret = ENOMEM; + goto out; + } + set->val = val; + ret = decode_heim_any(p, length, &set->val[set->len], &size); + if (ret) + goto out; + set->len++; + + p += size; + len += size; + length -= size; + } + return 0; + out: + krb5_clear_error_string(context); + free_CertificateSetReal(set); + set->val = NULL; + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_verify_sign(krb5_context context, + const char *data, + size_t length, + struct krb5_pk_identity *id, + heim_oid *contentType, + krb5_data *content, + struct krb5_pk_cert **signer) +{ + STACK_OF(X509) *certificates; + SignerInfo *signer_info; + const EVP_MD *evp_type; + EVP_PKEY *public_key; + krb5_error_code ret; + CertificateSetReal set; + EVP_MD_CTX md; + X509 *cert; + SignedData sd; + size_t size; + + *signer = NULL; + krb5_data_zero(content); + contentType->length = 0; + contentType->components = NULL; + + memset(&sd, 0, sizeof(sd)); + + ret = decode_SignedData(data, length, &sd, &size); + if (ret) { + krb5_set_error_string(context, + "PKINIT: decoding failed SignedData: %d", + ret); + goto out; + } + + if (sd.encapContentInfo.eContent == NULL) { + krb5_set_error_string(context, + "PKINIT: signature missing encapContent"); + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto out; + } + + /* XXX Check CMS version */ + + if (sd.signerInfos.len < 1) { + krb5_set_error_string(context, + "PKINIT: signature information missing from " + "pkinit response"); + ret = KRB5_KDC_ERR_INVALID_SIG; + goto out; + } + + signer_info = &sd.signerInfos.val[0]; + + ret = any_to_CertificateSet(context, sd.certificates, &set); + if (ret) { + krb5_set_error_string(context, + "PKINIT: failed to decode CertificateSet"); + goto out; + } + + ret = cert_to_X509(context, &set, &certificates); + free_CertificateSetReal(&set); + if (ret) { + krb5_set_error_string(context, + "PKINIT: failed to decode Certificates"); + goto out; + } + + ret = pk_verify_chain_standard(context, id, + &signer_info->sid, + certificates, + &cert); + sk_X509_free(certificates); + if (ret) + goto out; + + if (signer_info->signature.length == 0) { + free_SignedData(&sd); + X509_free(cert); + krb5_set_error_string(context, "PKINIT: signature missing from" + "pkinit response"); + return KRB5_KDC_ERR_INVALID_SIG; + } + + public_key = X509_get_pubkey(cert); + + /* verify signature */ + if (heim_oid_cmp(&signer_info->digestAlgorithm.algorithm, + oid_id_pkcs1_sha1WithRSAEncryption()) == 0) + evp_type = EVP_sha1(); + else if (heim_oid_cmp(&signer_info->digestAlgorithm.algorithm, + oid_id_pkcs1_md5WithRSAEncryption()) == 0) + evp_type = EVP_md5(); + else if (heim_oid_cmp(&signer_info->digestAlgorithm.algorithm, + oid_id_secsig_sha_1()) == 0) + evp_type = EVP_sha1(); + else { + X509_free(cert); + krb5_set_error_string(context, "PKINIT: The requested digest " + "algorithm is not supported"); + ret = KRB5_KDC_ERR_INVALID_SIG; + goto out; + } + + EVP_VerifyInit(&md, evp_type); + EVP_VerifyUpdate(&md, + sd.encapContentInfo.eContent->data, + sd.encapContentInfo.eContent->length); + ret = EVP_VerifyFinal(&md, + signer_info->signature.data, + signer_info->signature.length, + public_key); + if (ret != 1) { + X509_free(cert); + krb5_set_error_string(context, "PKINIT: signature didn't verify: %s", + ERR_error_string(ERR_get_error(), NULL)); + ret = KRB5_KDC_ERR_INVALID_SIG; + goto out; + } + + ret = copy_oid(&sd.encapContentInfo.eContentType, contentType); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + + content->data = malloc(sd.encapContentInfo.eContent->length); + if (content->data == NULL) { + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + content->length = sd.encapContentInfo.eContent->length; + memcpy(content->data,sd.encapContentInfo.eContent->data,content->length); + + *signer = malloc(sizeof(**signer)); + if (*signer == NULL) { + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + (*signer)->cert = cert; + + out: + free_SignedData(&sd); + if (ret) { + free_oid(contentType); + krb5_data_free(content); + } + return ret; +} + +static krb5_error_code +get_reply_key(krb5_context context, + const krb5_data *content, + unsigned nonce, + krb5_keyblock **key) +{ + ReplyKeyPack_19 key_pack; + krb5_error_code ret; + size_t size; + + ret = decode_ReplyKeyPack_19(content->data, + content->length, + &key_pack, + &size); + if (ret) { + krb5_set_error_string(context, "PKINIT decoding reply key failed"); + free_ReplyKeyPack_19(&key_pack); + return ret; + } + + if (key_pack.nonce != nonce) { + krb5_set_error_string(context, "PKINIT enckey nonce is wrong"); + free_ReplyKeyPack_19(&key_pack); + return KRB5KRB_AP_ERR_MODIFIED; + } + + *key = malloc (sizeof (**key)); + if (*key == NULL) { + krb5_set_error_string(context, "PKINIT failed allocating reply key"); + free_ReplyKeyPack_19(&key_pack); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ret = copy_EncryptionKey(&key_pack.replyKey, *key); + free_ReplyKeyPack_19(&key_pack); + if (ret) { + krb5_set_error_string(context, "PKINIT failed copying reply key"); + free(*key); + } + + return ret; +} + +static krb5_error_code +pk_verify_host(krb5_context context, struct krb5_pk_cert *host) +{ + /* XXX */ + return 0; +} + +static krb5_error_code +pk_rd_pa_reply_enckey(krb5_context context, + int win2k_compat, + ContentInfo *rep, + krb5_pk_init_ctx ctx, + krb5_enctype etype, + unsigned nonce, + PA_DATA *pa, + krb5_keyblock **key) +{ + krb5_error_code ret; + EnvelopedData ed; + krb5_keyblock tmp_key; + krb5_crypto crypto; + krb5_data plain; + KeyTransRecipientInfo *ri; + int length; + size_t size; + X509 *user_cert; + char *p; + krb5_boolean bret; + krb5_data content; + heim_oid contentType = { 0, NULL }; + struct krb5_pk_cert *host = NULL; + heim_octet_string encryptedContent; + heim_octet_string *any; + krb5_data ivec; + krb5_data params; + + + memset(&tmp_key, 0, sizeof(tmp_key)); + memset(&ed, 0, sizeof(ed)); + krb5_data_zero(&plain); + krb5_data_zero(&content); + krb5_data_zero(&encryptedContent); + krb5_data_zero(&ivec); + + user_cert = sk_X509_value(ctx->id->cert, 0); + + if (heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) { + krb5_set_error_string(context, "PKINIT: Invalid content type"); + return EINVAL; + } + + if (rep->content == NULL) { + krb5_set_error_string(context, "PKINIT: No content in reply"); + return EINVAL; + } + + ret = decode_EnvelopedData(rep->content->data, + rep->content->length, + &ed, + &size); + if (ret) { + free_EnvelopedData(&ed); + return ret; + } + + if (ed.recipientInfos.len != 1) { + free_EnvelopedData(&ed); + krb5_set_error_string(context, "pkinit: Number of recipient infos " + "not one (%d)", + ed.recipientInfos.len); + return EINVAL; /* XXX */ + } + + ri = &ed.recipientInfos.val[0]; + + /* XXX make SignerIdentifier and RecipientIdentifier the same */ + bret = pk_peer_compare(context, (SignerIdentifier *)&ri->rid, user_cert); + if (bret == FALSE) { + ret = KRB5KRB_AP_ERR_BADMATCH; /* XXX */ + goto out; + } + + if (heim_oid_cmp(oid_id_pkcs1_rsaEncryption(), + &ri->keyEncryptionAlgorithm.algorithm)) { + krb5_set_error_string(context, "PKINIT: invalid content type"); + return EINVAL; + } + + ret = pk_decrypt_key(context, &ri->encryptedKey, + ctx->id->private_key, &tmp_key); + if (ret) + goto out; + + + /* verify content type */ + if (win2k_compat) { + if (heim_oid_cmp(&ed.encryptedContentInfo.contentType, oid_id_pkcs7_data())) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto out; + } + } else { + if (heim_oid_cmp(&ed.encryptedContentInfo.contentType, oid_id_pkcs7_signedData())) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto out; + } + } + + if (ed.encryptedContentInfo.encryptedContent == NULL) { + krb5_set_error_string(context, "PKINIT: OPTIONAL encryptedContent " + "field not filled in in KDC reply"); + ret = KRB5_BADMSGTYPE; + goto out; + } + + any = ed.encryptedContentInfo.encryptedContent; + ret = der_get_octet_string(any->data, any->length, + &encryptedContent, NULL); + if (ret) { + krb5_set_error_string(context, + "PKINIT: encryptedContent content invalid"); + goto out; + } + + if (ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters == NULL){ + krb5_set_error_string(context, + "PKINIT: encryptedContent parameter missing"); + ret = KRB5_BADMSGTYPE; + goto out; + } + + params.data = ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters->data; + params.length = ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters->length; + + ret = _krb5_oid_to_enctype(context, + &ed.encryptedContentInfo.contentEncryptionAlgorithm.algorithm, + &tmp_key.keytype); + if (ret) + goto out; + + ret = krb5_crypto_init(context, &tmp_key, 0, &crypto); + if (ret) + goto out; + + ret = krb5_crypto_get_params(context, crypto, ¶ms, &ivec); + if (ret) + goto out; + + ret = krb5_decrypt_ivec(context, crypto, + 0, + encryptedContent.data, + encryptedContent.length, + &plain, + ivec.data); + + p = plain.data; + length = plain.length; + + /* win2k uses ContentInfo */ + if (win2k_compat) { + ContentInfo ci; + size_t size; + + ret = decode_ContentInfo(p, length, &ci, &size); + if (ret) { + krb5_set_error_string(context, + "PKINIT: failed decoding ContentInfo: %d", + ret); + goto out; + } + + if (heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) { + ret = EINVAL; /* XXX */ + krb5_set_error_string(context, "PKINIT: Invalid content type"); + goto out; + } + p = ci.content->data; + length = ci.content->length; + } + + ret = _krb5_pk_verify_sign(context, + p, + length, + ctx->id, + &contentType, + &content, + &host); + if (ret) + goto out; + + /* make sure that it is the kdc's certificate */ + ret = pk_verify_host(context, host); + if (ret) { + krb5_set_error_string(context, "PKINIT: failed verify host: %d", ret); + goto out; + } + + if (win2k_compat) { + if (heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) { + krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto out; + } + } else { + if (heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) { + krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto out; + } + } + + ret = get_reply_key(context, &content, nonce, key); + if (ret) + goto out; + + /* XXX compare given etype with key->etype */ + + out: + if (host) + _krb5_pk_cert_free(host); + free_oid(&contentType); + free_octet_string(&encryptedContent); + krb5_data_free(&content); + krb5_free_keyblock_contents(context, &tmp_key); + krb5_data_free(&plain); + krb5_data_free(&ivec); + + return ret; +} + +static krb5_error_code +pk_rd_pa_reply_dh(krb5_context context, + ContentInfo *rep, + krb5_pk_init_ctx ctx, + krb5_enctype etype, + unsigned nonce, + PA_DATA *pa, + krb5_keyblock **key) +{ + unsigned char *p, *dh_gen_key = NULL; + ASN1_INTEGER *dh_pub_key = NULL; + struct krb5_pk_cert *host = NULL; + BIGNUM *kdc_dh_pubkey = NULL; + KDCDHKeyInfo kdc_dh_info; + heim_oid contentType = { 0, NULL }; + krb5_data content; + krb5_error_code ret; + int dh_gen_keylen; + size_t size; + + krb5_data_zero(&content); + memset(&kdc_dh_info, 0, sizeof(kdc_dh_info)); + + if (heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) { + krb5_set_error_string(context, "PKINIT: Invalid content type"); + return EINVAL; + } + + if (rep->content == NULL) { + krb5_set_error_string(context, "PKINIT: No content in reply"); + return EINVAL; + } + + ret = _krb5_pk_verify_sign(context, + rep->content->data, + rep->content->length, + ctx->id, + &contentType, + &content, + &host); + if (ret) + goto out; + + /* make sure that it is the kdc's certificate */ + ret = pk_verify_host(context, host); + if (ret) + goto out; + + if (heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; /* XXX */ + goto out; + } + + ret = decode_KDCDHKeyInfo(content.data, + content.length, + &kdc_dh_info, + &size); + + if (ret) + goto out; + + if (kdc_dh_info.nonce != nonce) { + krb5_set_error_string(context, "PKINIT: DH nonce is wrong"); + ret = KRB5KRB_AP_ERR_MODIFIED; + goto out; + } + + p = kdc_dh_info.subjectPublicKey.data; + size = (kdc_dh_info.subjectPublicKey.length + 7) / 8; + dh_pub_key = d2i_ASN1_INTEGER(NULL, &p, size); + if (dh_pub_key == NULL) { + krb5_set_error_string(context, + "PKINIT: Can't parse KDC's DH public key"); + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + + kdc_dh_pubkey = ASN1_INTEGER_to_BN(dh_pub_key, NULL); + if (kdc_dh_pubkey == NULL) { + krb5_set_error_string(context, + "PKINIT: Can't convert KDC's DH public key"); + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + + dh_gen_key = malloc(DH_size(ctx->dh)); + if (dh_gen_key == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + + dh_gen_keylen = DH_compute_key(dh_gen_key, kdc_dh_pubkey, ctx->dh); + if (dh_gen_keylen == -1) { + krb5_set_error_string(context, + "PKINIT: Can't compute Diffie-Hellman key (%s)", + ERR_error_string(ERR_get_error(), NULL)); + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + + *key = malloc (sizeof (**key)); + if (*key == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + + ret = krb5_random_to_key(context, etype, dh_gen_key, dh_gen_keylen, *key); + if (ret) { + krb5_set_error_string(context, + "PKINIT: can't create key from DH key"); + free(*key); + *key = NULL; + goto out; + } + + out: + if (kdc_dh_pubkey) + BN_free(kdc_dh_pubkey); + if (dh_gen_key) { + memset(dh_gen_key, 0, DH_size(ctx->dh)); + free(dh_gen_key); + } + if (dh_pub_key) + ASN1_INTEGER_free(dh_pub_key); + if (host) + _krb5_pk_cert_free(host); + if (content.data) + krb5_data_free(&content); + free_KDCDHKeyInfo(&kdc_dh_info); + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_rd_pa_reply(krb5_context context, + void *c, + krb5_enctype etype, + unsigned nonce, + PA_DATA *pa, + krb5_keyblock **key) +{ + krb5_pk_init_ctx ctx = c; + krb5_error_code ret; + ContentInfo ci; + size_t size; + + /* Check for PK-INIT -25 */ + if (pa->padata_type == KRB5_PADATA_PK_AS_REP) { + PA_PK_AS_REP rep; + + memset(&rep, 0, sizeof(rep)); + + ret = decode_PA_PK_AS_REP(pa->padata_value.data, + pa->padata_value.length, + &rep, + &size); + if (ret) + return ret; + + switch (rep.element) { + case choice_PA_PK_AS_REP_encKeyPack: + ret = decode_ContentInfo(rep.u.encKeyPack.data, + rep.u.encKeyPack.length, + &ci, + &size); + free_PA_PK_AS_REP(&rep); + if (ret) { + krb5_set_error_string(context, + "PKINIT: -25 decoding failed " + "ContentInfo: %d", ret); + break; + } + ret = pk_rd_pa_reply_enckey(context, 0, &ci, ctx, + etype, nonce, pa, key); + free_ContentInfo(&ci); + return ret; + default: + free_PA_PK_AS_REP(&rep); + krb5_set_error_string(context, "PKINIT: -25 reply " + "invalid content type"); + break; + } + } + + /* Check for PK-INIT -19 */ + { + PA_PK_AS_REP_19 rep19; + + memset(&rep19, 0, sizeof(rep19)); + + ret = decode_PA_PK_AS_REP_19(pa->padata_value.data, + pa->padata_value.length, + &rep19, + &size); + if (ret == 0) { + switch(rep19.element) { + case choice_PA_PK_AS_REP_19_dhSignedData: + ret = pk_rd_pa_reply_dh(context, &rep19.u.dhSignedData, ctx, + etype, nonce, pa, key); + break; + case choice_PA_PK_AS_REP_19_encKeyPack: + ret = pk_rd_pa_reply_enckey(context, 0, + &rep19.u.encKeyPack, ctx, + etype, nonce, pa, key); + break; + default: + krb5_set_error_string(context, "PKINIT: -19 reply invalid " + "content type"); + ret = EINVAL; + break; + } + free_PA_PK_AS_REP_19(&rep19); + if (ret == 0) + return 0; + } + } + + /* Check for Windows encoding of the AS-REP pa data */ + { + PA_PK_AS_REP_Win2k w2krep; + + memset(&w2krep, 0, sizeof(w2krep)); + + ret = decode_PA_PK_AS_REP_Win2k(pa->padata_value.data, + pa->padata_value.length, + &w2krep, + &size); + if (ret) { + krb5_set_error_string(context, "PKINIT: Failed decoding windows" + "pkinit reply %d", ret); + return ret; + } + + switch (w2krep.element) { + case choice_PA_PK_AS_REP_Win2k_encKeyPack: + ret = decode_ContentInfo(w2krep.u.encKeyPack.data, + w2krep.u.encKeyPack.length, + &ci, + &size); + free_PA_PK_AS_REP_Win2k(&w2krep); + if (ret) { + krb5_set_error_string(context, + "PKINIT: decoding failed " + "ContentInfo: %d", + ret); + return ret; + } + ret = pk_rd_pa_reply_enckey(context, 1, &ci, ctx, + etype, nonce, pa, key); + free_ContentInfo(&ci); + break; + default: + free_PA_PK_AS_REP_Win2k(&w2krep); + krb5_set_error_string(context, "PKINIT: win2k reply invalid " + "content type"); + ret = EINVAL; + break; + } + + } + + return ret; +} + +static int +ssl_pass_cb(char *buf, int size, int rwflag, void *u) +{ + krb5_error_code ret; + krb5_prompt prompt; + krb5_data password_data; + krb5_prompter_fct prompter = u; + + password_data.data = buf; + password_data.length = size; + prompt.prompt = "Enter your private key passphrase: "; + prompt.hidden = 1; + prompt.reply = &password_data; + prompt.type = KRB5_PROMPT_TYPE_PASSWORD; + + ret = (*prompter)(NULL, NULL, NULL, NULL, 1, &prompt); + if (ret) { + memset (buf, 0, size); + return 0; + } + return strlen(buf); +} + +static krb5_error_code +load_openssl_cert(krb5_context context, + const char *file, + STACK_OF(X509) **c) +{ + STACK_OF(X509) *certificate; + krb5_error_code ret; + FILE *f; + + f = fopen(file, "r"); + if (f == NULL) { + ret = errno; + krb5_set_error_string(context, "PKINIT: open failed %s: %s", + file, strerror(ret)); + return ret; + } + + certificate = sk_X509_new_null(); + while (1) { + /* see http://www.openssl.org/docs/crypto/pem.html section BUGS */ + X509 *cert; + cert = PEM_read_X509(f, NULL, NULL, NULL); + if (cert == NULL) { + if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE) { + /* End of file reached. no error */ + ERR_clear_error(); + break; + } + krb5_set_error_string(context, "PKINIT: Can't read certificate"); + fclose(f); + return HEIM_PKINIT_CERTIFICATE_INVALID; + } + sk_X509_insert(certificate, cert, sk_X509_num(certificate)); + } + fclose(f); + if (sk_X509_num(certificate) == 0) { + krb5_set_error_string(context, "PKINIT: No certificate found"); + return HEIM_PKINIT_NO_CERTIFICATE; + } + *c = certificate; + return 0; +} + +static krb5_error_code +load_openssl_file(krb5_context context, + char *password, + krb5_prompter_fct prompter, + void *prompter_data, + const char *user_id, + struct krb5_pk_identity *id) +{ + krb5_error_code ret; + STACK_OF(X509) *certificate = NULL; + char *cert_file = NULL, *key_file; + EVP_PKEY *private_key = NULL; + FILE *f; + + cert_file = strdup(user_id); + if (cert_file == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + key_file = strchr(cert_file, ','); + if (key_file == NULL) { + krb5_set_error_string(context, "PKINIT: key file missing"); + ret = HEIM_PKINIT_NO_PRIVATE_KEY; + goto out; + } + *key_file++ = '\0'; + + ret = load_openssl_cert(context, cert_file, &certificate); + if (ret) + goto out; + + /* load private key */ + f = fopen(key_file, "r"); + if (f == NULL) { + ret = errno; + krb5_set_error_string(context, "PKINIT: open %s: %s", + key_file, strerror(ret)); + goto out; + } + if (password == NULL || password[0] == '\0') { + if (prompter == NULL) + prompter = krb5_prompter_posix; + private_key = PEM_read_PrivateKey(f, NULL, ssl_pass_cb, prompter); + } else + private_key = PEM_read_PrivateKey(f, NULL, NULL, password); + fclose(f); + if (private_key == NULL) { + krb5_set_error_string(context, "PKINIT: Can't read private key"); + ret = HEIM_PKINIT_PRIVATE_KEY_INVALID; + goto out; + } + ret = X509_check_private_key(sk_X509_value(certificate, 0), private_key); + if (ret != 1) { + ret = HEIM_PKINIT_PRIVATE_KEY_INVALID; + krb5_set_error_string(context, + "PKINIT: The private key doesn't match " + "the public key certificate"); + goto out; + } + + id->private_key = private_key; + id->cert = certificate; + + return 0; + out: + if (cert_file) + free(cert_file); + if (certificate) + sk_X509_pop_free(certificate, X509_free); + if (private_key) + EVP_PKEY_free(private_key); + + return ret; +} + +static int +add_pair(krb5_context context, char *str, char ***cmds, int *num) +{ + char **c; + char *p; + int i; + + p = strchr(str, ':'); + if (p) { + *p = '\0'; + p++; + } + + /* filter out dup keys */ + for (i = 0; i < *num; i++) + if (strcmp((*cmds)[i * 2], str) == 0) + return 0; + + c = realloc(*cmds, sizeof(*c) * ((*num + 1) * 2)); + if (c == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + c[(*num * 2)] = str; + c[(*num * 2) + 1] = p; + *num += 1; + *cmds = c; + return 0; +} + +static krb5_error_code +eval_pairs(krb5_context context, ENGINE *e, const char *name, + const char *type, char **cmds, int num) +{ + int i; + + for (i = 0; i < num; i++) { + char *a1 = cmds[i * 2], *a2 = cmds[(i * 2) + 1]; + if(!ENGINE_ctrl_cmd_string(e, a1, a2, 0)) { + krb5_set_error_string(context, + "PKINIT: Failed %scommand (%s - %s:%s): %s", + type, name, a1, a2 ? a2 : "(NULL)", + ERR_error_string(ERR_get_error(), NULL)); + return HEIM_PKINIT_NO_PRIVATE_KEY; + } + } + return 0; +} + +struct engine_context { + char **pre_cmds; + char **post_cmds; + int num_pre; + int num_post; + char *engine_name; + char *cert_file; + char *key_id; +}; + +static krb5_error_code +parse_openssl_engine_conf(krb5_context context, + struct engine_context *ctx, + char *line) +{ + krb5_error_code ret; + char *last, *p, *q; + + for (p = strtok_r(line, ",", &last); + p != NULL; + p = strtok_r(NULL, ",", &last)) { + + q = strchr(p, '='); + if (q == NULL) { + krb5_set_error_string(context, + "PKINIT: openssl engine configuration " + "key %s missing = and thus value", p); + return HEIM_PKINIT_NO_PRIVATE_KEY; + } + *q = '\0'; + q++; + if (strcasecmp("PRE", p) == 0) { + ret = add_pair(context, q, &ctx->pre_cmds, &ctx->num_pre); + if (ret) + return ret; + } else if (strcasecmp("POST", p) == 0) { + ret = add_pair(context, q, &ctx->post_cmds, &ctx->num_post); + if (ret) + return ret; + } else if (strcasecmp("KEY", p) == 0) { + ctx->key_id = q; + } else if (strcasecmp("CERT", p) == 0) { + ctx->cert_file = q; + } else if (strcasecmp("ENGINE", p) == 0) { + ctx->engine_name = q; + } else { + krb5_set_error_string(context, + "PKINIT: openssl engine configuration " + "key %s is unknown", p); + return HEIM_PKINIT_NO_PRIVATE_KEY; + } + } + return 0; +} + + +static krb5_error_code +load_openssl_engine(krb5_context context, + char *password, + krb5_prompter_fct prompter, + void *prompter_data, + const char *string, + struct krb5_pk_identity *id) +{ + struct engine_context ctx; + krb5_error_code ret; + const char *f; + char *file_conf = NULL, *user_conf = NULL; + ENGINE *e = NULL; + + memset(&ctx, 0, sizeof(ctx)); + + ENGINE_load_builtin_engines(); + + user_conf = strdup(string); + if (user_conf == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ret = parse_openssl_engine_conf(context, &ctx, user_conf); + if (ret) + goto out; + + f = krb5_config_get_string_default(context, NULL, NULL, + "libdefaults", + "pkinit-openssl-engine", + NULL); + if (f) { + file_conf = strdup(f); + if (file_conf) { + ret = parse_openssl_engine_conf(context, &ctx, file_conf); + if (ret) + goto out; + } + } + + if (ctx.cert_file == NULL) { + krb5_set_error_string(context, + "PKINIT: openssl engine missing certificate"); + ret = HEIM_PKINIT_NO_CERTIFICATE; + goto out; + } + if (ctx.key_id == NULL) { + krb5_set_error_string(context, + "PKINIT: openssl engine missing key id"); + ret = HEIM_PKINIT_NO_PRIVATE_KEY; + goto out; + } + if (ctx.engine_name == NULL) { + krb5_set_error_string(context, + "PKINIT: openssl engine missing engine name"); + ret = HEIM_PKINIT_NO_PRIVATE_KEY; + goto out; + } + + e = ENGINE_by_id(ctx.engine_name); + if (e == NULL) { + krb5_set_error_string(context, + "PKINIT: failed getting openssl engine %s: %s", + ctx.engine_name, + ERR_error_string(ERR_get_error(), NULL)); + ret = HEIM_PKINIT_NO_PRIVATE_KEY; + goto out; + } + + ret = eval_pairs(context, e, ctx.engine_name, "pre", + ctx.pre_cmds, ctx.num_pre); + if (ret) + goto out; + + if(!ENGINE_init(e)) { + ret = HEIM_PKINIT_NO_PRIVATE_KEY; + krb5_set_error_string(context, + "PKINIT: openssl engine init %s failed: %s", + ctx.engine_name, + ERR_error_string(ERR_get_error(), NULL)); + ENGINE_free(e); + goto out; + } + + ret = eval_pairs(context, e, ctx.engine_name, "post", + ctx.post_cmds, ctx.num_post); + if (ret) + goto out; + + /* + * If the engine supports a LOAD_CERT_CTRL function, lets try + * it. OpenSC support this function. Eventially this should be + * a ENGINE_load_cert function if it failes, treat it like a + * non fatal error. + */ + { + struct { + const char * cert_id; + X509 * cert; + } parms; + + parms.cert_id = ctx.cert_file; + parms.cert = NULL; + ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1); + if (parms.cert) { + id->cert = sk_X509_new_null(); + sk_X509_insert(id->cert, parms.cert, 0); + } + } + + if (id->cert == NULL) { + ret = load_openssl_cert(context, ctx.cert_file, &id->cert); + if (ret) + goto out; + } + + { + UI_METHOD * krb5_ui_method = NULL; + struct krb5_ui_data ui_data; + + krb5_ui_method = UI_create_method("Krb5 ui method"); + if (krb5_ui_method == NULL) { + krb5_set_error_string(context, + "PKINIT: failed to setup prompter " + "function: %s", + ERR_error_string(ERR_get_error(), NULL)); + ret = HEIM_PKINIT_NO_PRIVATE_KEY; + goto out; + } + UI_method_set_reader(krb5_ui_method, krb5_ui_method_read_string); + + ui_data.context = context; + ui_data.prompter = prompter; + if (prompter == NULL) + ui_data.prompter = krb5_prompter_posix; + ui_data.prompter_data = prompter_data; + + id->private_key = ENGINE_load_private_key(e, + ctx.key_id, + krb5_ui_method, + (void*) &ui_data); + UI_destroy_method(krb5_ui_method); + } + + if (id->private_key == NULL) { + krb5_set_error_string(context, + "PKINIT: failed to load private key: %s", + ERR_error_string(ERR_get_error(), NULL)); + ret = HEIM_PKINIT_NO_PRIVATE_KEY; + goto out; + } + + ret = X509_check_private_key(sk_X509_value(id->cert, 0), id->private_key); + if (ret != 1) { + ret = HEIM_PKINIT_PRIVATE_KEY_INVALID; + krb5_set_error_string(context, + "PKINIT: The private key doesn't match " + "the public key certificate"); + goto out; + } + + if (user_conf) + free(user_conf); + if (file_conf) + free(file_conf); + + id->engine = e; + + return 0; + + out: + if (user_conf) + free(user_conf); + if (file_conf) + free(file_conf); + if (e) { + ENGINE_finish(e); /* make sure all shared libs are unloaded */ + ENGINE_free(e); + } + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_pk_load_openssl_id(krb5_context context, + struct krb5_pk_identity **ret_id, + const char *user_id, + const char *x509_anchors, + krb5_prompter_fct prompter, + void *prompter_data, + char *password) +{ + STACK_OF(X509) *trusted_certs = NULL; + struct krb5_pk_identity *id = NULL; + krb5_error_code ret; + struct dirent *file; + char *dirname = NULL; + DIR *dir; + FILE *f; + krb5_error_code (*load_pair)(krb5_context, + char *, + krb5_prompter_fct prompter, + void * prompter_data, + const char *, + struct krb5_pk_identity *) = NULL; + + + *ret_id = NULL; + + if (x509_anchors == NULL) { + krb5_set_error_string(context, "PKINIT: No root ca directory given"); + return HEIM_PKINIT_NO_VALID_CA; + } + + if (user_id == NULL) { + krb5_set_error_string(context, + "PKINIT: No user X509 source given given"); + return HEIM_PKINIT_NO_PRIVATE_KEY; + } + + /* + * + */ + + if (strncasecmp(user_id, "FILE:", 5) == 0) { + load_pair = load_openssl_file; + user_id += 5; + } else if (strncasecmp(user_id, "ENGINE:", 7) == 0) { + load_pair = load_openssl_engine; + user_id += 7; + } else { + krb5_set_error_string(context, "PKINIT: user identity not FILE"); + return HEIM_PKINIT_NO_CERTIFICATE; + } + if (strncasecmp(x509_anchors, "OPENSSL-ANCHOR-DIR:", 19) != 0) { + krb5_set_error_string(context, "PKINIT: anchor OPENSSL-ANCHOR-DIR"); + return HEIM_PKINIT_NO_VALID_CA; + } + x509_anchors += 19; + + id = malloc(sizeof(*id)); + if (id == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + memset(id, 0, sizeof(*id)); + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + + + ret = (*load_pair)(context, password, prompter, prompter_data, user_id, id); + if (ret) + goto out; + + /* load anchors */ + + dirname = strdup(x509_anchors); + if (dirname == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + goto out; + } + + { + size_t len; + len = strlen(dirname); + if (dirname[len - 1] == '/') + dirname[len - 1] = '\0'; + } + + /* read ca certificates */ + dir = opendir(dirname); + if (dir == NULL) { + ret = errno; + krb5_set_error_string(context, "PKINIT: open directory %s: %s", + dirname, strerror(ret)); + goto out; + } + + trusted_certs = sk_X509_new_null(); + while ((file = readdir(dir)) != NULL) { + X509 *cert; + char *filename; + + /* + * Assume the certificate filenames constist of hashed subject + * name followed by suffix ".0" + */ + + if (strlen(file->d_name) == 10 && strcmp(&file->d_name[8],".0") == 0) { + asprintf(&filename, "%s/%s", dirname, file->d_name); + if (filename == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "malloc: out or memory"); + goto out; + } + f = fopen(filename, "r"); + if (f == NULL) { + ret = errno; + krb5_set_error_string(context, "PKINIT: open %s: %s", + filename, strerror(ret)); + free(filename); + closedir(dir); + goto out; + } + cert = PEM_read_X509(f, NULL, NULL, NULL); + fclose(f); + if (cert != NULL) { + /* order of the certs is not important */ + sk_X509_push(trusted_certs, cert); + } + free(filename); + } + } + closedir(dir); + + if (sk_X509_num(trusted_certs) == 0) { + krb5_set_error_string(context, + "PKINIT: No CA certificate(s) found in %s", + dirname); + ret = HEIM_PKINIT_NO_VALID_CA; + goto out; + } + + id->trusted_certs = trusted_certs; + + *ret_id = id; + + return 0; + + out: + if (dirname) + free(dirname); + if (trusted_certs) + sk_X509_pop_free(trusted_certs, X509_free); + if (id) { + if (id->cert) + sk_X509_pop_free(id->cert, X509_free); + if (id->private_key) + EVP_PKEY_free(id->private_key); + free(id); + } + + return ret; +} + +#endif /* PKINIT */ + +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) +{ +#ifdef PKINIT + krb5_pk_init_ctx ctx; + + if (opt->private == NULL || opt->private->pk_init_ctx == NULL) + return; + ctx = opt->private->pk_init_ctx; + if (ctx->dh) + DH_free(ctx->dh); + ctx->dh = NULL; + if (ctx->id) { + if (ctx->id->cert) + sk_X509_pop_free(ctx->id->cert, X509_free); + if (ctx->id->trusted_certs) + sk_X509_pop_free(ctx->id->trusted_certs, X509_free); + if (ctx->id->private_key) + EVP_PKEY_free(ctx->id->private_key); + if (ctx->id->engine) { + ENGINE_finish(ctx->id->engine); /* unload shared libs etc */ + ENGINE_free(ctx->id->engine); + ctx->id->engine = NULL; + } + free(ctx->id); + ctx->id = NULL; + } + opt->private->pk_init_ctx = NULL; +#endif +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_pkinit(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_principal principal, + const char *user_id, + const char *x509_anchors, + int flags, + krb5_prompter_fct prompter, + void *prompter_data, + char *password) +{ +#ifdef PKINIT + krb5_error_code ret; + + if (opt->private == NULL) { + krb5_set_error_string(context, "PKINIT: on non extendable opt"); + return EINVAL; + } + + opt->private->pk_init_ctx = malloc(sizeof(*opt->private->pk_init_ctx)); + if (opt->private->pk_init_ctx == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + opt->private->pk_init_ctx->dh = NULL; + opt->private->pk_init_ctx->id = NULL; + ret = _krb5_pk_load_openssl_id(context, + &opt->private->pk_init_ctx->id, + user_id, + x509_anchors, + prompter, + prompter_data, + password); + if (ret) { + free(opt->private->pk_init_ctx); + opt->private->pk_init_ctx = NULL; + } + + /* XXX */ + if (ret == 0 && (flags & 1) && !(flags & 2)) { + DH *dh; + const char *P = + "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" + "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" + "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" + "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" + "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" + "FFFFFFFF" "FFFFFFFF"; + const char *G = "2"; + const char *Q = + "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68" + "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E" + "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122" + "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6" + "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F67329C0" + "FFFFFFFF" "FFFFFFFF"; + + dh = DH_new(); + if (dh == NULL) { + _krb5_get_init_creds_opt_free_pkinit(opt); + return ENOMEM; + } + opt->private->pk_init_ctx->dh = dh; + if (!BN_hex2bn(&dh->p, P)) { + _krb5_get_init_creds_opt_free_pkinit(opt); + return ENOMEM; + } + if (!BN_hex2bn(&dh->g, G)) { + _krb5_get_init_creds_opt_free_pkinit(opt); + return ENOMEM; + } + if (!BN_hex2bn(&dh->q, Q)) { + _krb5_get_init_creds_opt_free_pkinit(opt); + return ENOMEM; + } + /* XXX generate a new key for each request ? */ + if (DH_generate_key(dh) != 1) { + _krb5_get_init_creds_opt_free_pkinit(opt); + return ENOMEM; + } + } + return ret; +#else + krb5_set_error_string(context, "no support for PKINIT compiled in"); + return EINVAL; +#endif +} diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c new file mode 100644 index 0000000000..b7194b4c41 --- /dev/null +++ b/source4/heimdal/lib/krb5/principal.c @@ -0,0 +1,1125 @@ +/* + * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +#ifdef HAVE_RES_SEARCH +#define USE_RESOLVER +#endif +#ifdef HAVE_ARPA_NAMESER_H +#include +#endif +#include +#include "resolve.h" + +RCSID("$Id: principal.c,v 1.90 2005/06/30 01:38:15 lha Exp $"); + +#define princ_num_comp(P) ((P)->name.name_string.len) +#define princ_type(P) ((P)->name.name_type) +#define princ_comp(P) ((P)->name.name_string.val) +#define princ_ncomp(P, N) ((P)->name.name_string.val[(N)]) +#define princ_realm(P) ((P)->realm) + +void KRB5_LIB_FUNCTION +krb5_free_principal(krb5_context context, + krb5_principal p) +{ + if(p){ + free_Principal(p); + free(p); + } +} + +void KRB5_LIB_FUNCTION +krb5_principal_set_type(krb5_context context, + krb5_principal principal, + int type) +{ + princ_type(principal) = type; +} + +int KRB5_LIB_FUNCTION +krb5_principal_get_type(krb5_context context, + krb5_principal principal) +{ + return princ_type(principal); +} + +const char* KRB5_LIB_FUNCTION +krb5_principal_get_realm(krb5_context context, + krb5_const_principal principal) +{ + return princ_realm(principal); +} + +const char* KRB5_LIB_FUNCTION +krb5_principal_get_comp_string(krb5_context context, + krb5_principal principal, + unsigned int component) +{ + if(component >= princ_num_comp(principal)) + return NULL; + return princ_ncomp(principal, component); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name(krb5_context context, + const char *name, + krb5_principal *principal) +{ + krb5_error_code ret; + heim_general_string *comp; + heim_general_string realm; + int ncomp; + + const char *p; + char *q; + char *s; + char *start; + + int n; + char c; + int got_realm = 0; + + /* count number of component */ + ncomp = 1; + for(p = name; *p; p++){ + if(*p=='\\'){ + if(!p[1]) { + krb5_set_error_string (context, + "trailing \\ in principal name"); + return KRB5_PARSE_MALFORMED; + } + p++; + } else if(*p == '/') + ncomp++; + } + comp = calloc(ncomp, sizeof(*comp)); + if (comp == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + + n = 0; + p = start = q = s = strdup(name); + if (start == NULL) { + free (comp); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + while(*p){ + c = *p++; + if(c == '\\'){ + c = *p++; + if(c == 'n') + c = '\n'; + else if(c == 't') + c = '\t'; + else if(c == 'b') + c = '\b'; + else if(c == '0') + c = '\0'; + else if(c == '\0') { + krb5_set_error_string (context, + "trailing \\ in principal name"); + ret = KRB5_PARSE_MALFORMED; + goto exit; + } + }else if(c == '/' || c == '@'){ + if(got_realm){ + krb5_set_error_string (context, + "part after realm in principal name"); + ret = KRB5_PARSE_MALFORMED; + goto exit; + }else{ + comp[n] = malloc(q - start + 1); + if (comp[n] == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto exit; + } + memcpy(comp[n], start, q - start); + comp[n][q - start] = 0; + n++; + } + if(c == '@') + got_realm = 1; + start = q; + continue; + } + if(got_realm && (c == ':' || c == '/' || c == '\0')) { + krb5_set_error_string (context, + "part after realm in principal name"); + ret = KRB5_PARSE_MALFORMED; + goto exit; + } + *q++ = c; + } + if(got_realm){ + realm = malloc(q - start + 1); + if (realm == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto exit; + } + memcpy(realm, start, q - start); + realm[q - start] = 0; + }else{ + ret = krb5_get_default_realm (context, &realm); + if (ret) + goto exit; + + comp[n] = malloc(q - start + 1); + if (comp[n] == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto exit; + } + memcpy(comp[n], start, q - start); + comp[n][q - start] = 0; + n++; + } + *principal = malloc(sizeof(**principal)); + if (*principal == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto exit; + } + (*principal)->name.name_type = KRB5_NT_PRINCIPAL; + (*principal)->name.name_string.val = comp; + princ_num_comp(*principal) = n; + (*principal)->realm = realm; + free(s); + return 0; +exit: + while(n>0){ + free(comp[--n]); + } + free(comp); + free(s); + return ret; +} + +static const char quotable_chars[] = " \n\t\b\\/@"; +static const char replace_chars[] = " ntb\\/@"; + +#define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0); + +static size_t +quote_string(const char *s, char *out, size_t string_index, size_t len) +{ + const char *p, *q; + for(p = s; *p && string_index < len; p++){ + if((q = strchr(quotable_chars, *p))){ + add_char(out, string_index, len, '\\'); + add_char(out, string_index, len, replace_chars[q - quotable_chars]); + }else + add_char(out, string_index, len, *p); + } + if(string_index < len) + out[string_index] = '\0'; + return string_index; +} + + +static krb5_error_code +unparse_name_fixed(krb5_context context, + krb5_const_principal principal, + char *name, + size_t len, + krb5_boolean short_form) +{ + size_t idx = 0; + int i; + for(i = 0; i < princ_num_comp(principal); i++){ + if(i) + add_char(name, idx, len, '/'); + idx = quote_string(princ_ncomp(principal, i), name, idx, len); + if(idx == len) + return ERANGE; + } + /* add realm if different from default realm */ + if(short_form) { + krb5_realm r; + krb5_error_code ret; + ret = krb5_get_default_realm(context, &r); + if(ret) + return ret; + if(strcmp(princ_realm(principal), r) != 0) + short_form = 0; + free(r); + } + if(!short_form) { + add_char(name, idx, len, '@'); + idx = quote_string(princ_realm(principal), name, idx, len); + if(idx == len) + return ERANGE; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_fixed(krb5_context context, + krb5_const_principal principal, + char *name, + size_t len) +{ + return unparse_name_fixed(context, principal, name, len, FALSE); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_fixed_short(krb5_context context, + krb5_const_principal principal, + char *name, + size_t len) +{ + return unparse_name_fixed(context, principal, name, len, TRUE); +} + +static krb5_error_code +unparse_name(krb5_context context, + krb5_const_principal principal, + char **name, + krb5_boolean short_flag) +{ + size_t len = 0, plen; + int i; + krb5_error_code ret; + /* count length */ + plen = strlen(princ_realm(principal)); + if(strcspn(princ_realm(principal), quotable_chars) == plen) + len += plen; + else + len += 2*plen; + len++; + for(i = 0; i < princ_num_comp(principal); i++){ + plen = strlen(princ_ncomp(principal, i)); + if(strcspn(princ_ncomp(principal, i), quotable_chars) == plen) + len += plen; + else + len += 2*plen; + len++; + } + len++; + *name = malloc(len); + if(*name == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + ret = unparse_name_fixed(context, principal, *name, len, short_flag); + if(ret) { + free(*name); + *name = NULL; + } + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name(krb5_context context, + krb5_const_principal principal, + char **name) +{ + return unparse_name(context, principal, name, FALSE); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_short(krb5_context context, + krb5_const_principal principal, + char **name) +{ + return unparse_name(context, principal, name, TRUE); +} + +#if 0 /* not implemented */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_ext(krb5_context context, + krb5_const_principal principal, + char **name, + size_t *size) +{ + krb5_abortx(context, "unimplemented krb5_unparse_name_ext called"); +} + +#endif + +krb5_realm* +krb5_princ_realm(krb5_context context, + krb5_principal principal) +{ + return &princ_realm(principal); +} + + +void KRB5_LIB_FUNCTION +krb5_princ_set_realm(krb5_context context, + krb5_principal principal, + krb5_realm *realm) +{ + princ_realm(principal) = *realm; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal(krb5_context context, + krb5_principal *principal, + int rlen, + krb5_const_realm realm, + ...) +{ + krb5_error_code ret; + va_list ap; + va_start(ap, realm); + ret = krb5_build_principal_va(context, principal, rlen, realm, ap); + va_end(ap); + return ret; +} + +static krb5_error_code +append_component(krb5_context context, krb5_principal p, + const char *comp, + size_t comp_len) +{ + heim_general_string *tmp; + size_t len = princ_num_comp(p); + + tmp = realloc(princ_comp(p), (len + 1) * sizeof(*tmp)); + if(tmp == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + princ_comp(p) = tmp; + princ_ncomp(p, len) = malloc(comp_len + 1); + if (princ_ncomp(p, len) == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memcpy (princ_ncomp(p, len), comp, comp_len); + princ_ncomp(p, len)[comp_len] = '\0'; + princ_num_comp(p)++; + return 0; +} + +static void +va_ext_princ(krb5_context context, krb5_principal p, va_list ap) +{ + while(1){ + const char *s; + int len; + len = va_arg(ap, int); + if(len == 0) + break; + s = va_arg(ap, const char*); + append_component(context, p, s, len); + } +} + +static void +va_princ(krb5_context context, krb5_principal p, va_list ap) +{ + while(1){ + const char *s; + s = va_arg(ap, const char*); + if(s == NULL) + break; + append_component(context, p, s, strlen(s)); + } +} + + +static krb5_error_code +build_principal(krb5_context context, + krb5_principal *principal, + int rlen, + krb5_const_realm realm, + void (*func)(krb5_context, krb5_principal, va_list), + va_list ap) +{ + krb5_principal p; + + p = calloc(1, sizeof(*p)); + if (p == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + princ_type(p) = KRB5_NT_PRINCIPAL; + + princ_realm(p) = strdup(realm); + if(p->realm == NULL){ + free(p); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + + (*func)(context, p, ap); + *principal = p; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_make_principal(krb5_context context, + krb5_principal *principal, + krb5_const_realm realm, + ...) +{ + krb5_error_code ret; + krb5_realm r = NULL; + va_list ap; + if(realm == NULL) { + ret = krb5_get_default_realm(context, &r); + if(ret) + return ret; + realm = r; + } + va_start(ap, realm); + ret = krb5_build_principal_va(context, principal, strlen(realm), realm, ap); + va_end(ap); + if(r) + free(r); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal_va(krb5_context context, + krb5_principal *principal, + int rlen, + krb5_const_realm realm, + va_list ap) +{ + return build_principal(context, principal, rlen, realm, va_princ, ap); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal_va_ext(krb5_context context, + krb5_principal *principal, + int rlen, + krb5_const_realm realm, + va_list ap) +{ + return build_principal(context, principal, rlen, realm, va_ext_princ, ap); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_build_principal_ext(krb5_context context, + krb5_principal *principal, + int rlen, + krb5_const_realm realm, + ...) +{ + krb5_error_code ret; + va_list ap; + va_start(ap, realm); + ret = krb5_build_principal_va_ext(context, principal, rlen, realm, ap); + va_end(ap); + return ret; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_principal(krb5_context context, + krb5_const_principal inprinc, + krb5_principal *outprinc) +{ + krb5_principal p = malloc(sizeof(*p)); + if (p == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + if(copy_Principal(inprinc, p)) { + free(p); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + *outprinc = p; + return 0; +} + +/* + * return TRUE iff princ1 == princ2 (without considering the realm) + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_principal_compare_any_realm(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + int i; + if(princ_num_comp(princ1) != princ_num_comp(princ2)) + return FALSE; + for(i = 0; i < princ_num_comp(princ1); i++){ + if(strcmp(princ_ncomp(princ1, i), princ_ncomp(princ2, i)) != 0) + return FALSE; + } + return TRUE; +} + +/* + * return TRUE iff princ1 == princ2 + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_principal_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + if(!krb5_realm_compare(context, princ1, princ2)) + return FALSE; + return krb5_principal_compare_any_realm(context, princ1, princ2); +} + +/* + * return TRUE iff realm(princ1) == realm(princ2) + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_realm_compare(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ + return strcmp(princ_realm(princ1), princ_realm(princ2)) == 0; +} + +/* + * return TRUE iff princ matches pattern + */ + +krb5_boolean KRB5_LIB_FUNCTION +krb5_principal_match(krb5_context context, + krb5_const_principal princ, + krb5_const_principal pattern) +{ + int i; + if(princ_num_comp(princ) != princ_num_comp(pattern)) + return FALSE; + if(fnmatch(princ_realm(pattern), princ_realm(princ), 0) != 0) + return FALSE; + for(i = 0; i < princ_num_comp(princ); i++){ + if(fnmatch(princ_ncomp(pattern, i), princ_ncomp(princ, i), 0) != 0) + return FALSE; + } + return TRUE; +} + + +static struct v4_name_convert { + const char *from; + const char *to; +} default_v4_name_convert[] = { + { "ftp", "ftp" }, + { "hprop", "hprop" }, + { "pop", "pop" }, + { "imap", "imap" }, + { "rcmd", "host" }, + { "smtp", "smtp" }, + { NULL, NULL } +}; + +/* + * return the converted instance name of `name' in `realm'. + * look in the configuration file and then in the default set above. + * return NULL if no conversion is appropriate. + */ + +static const char* +get_name_conversion(krb5_context context, const char *realm, const char *name) +{ + struct v4_name_convert *q; + const char *p; + + p = krb5_config_get_string(context, NULL, "realms", realm, + "v4_name_convert", "host", name, NULL); + if(p == NULL) + p = krb5_config_get_string(context, NULL, "libdefaults", + "v4_name_convert", "host", name, NULL); + if(p) + return p; + + /* XXX should be possible to override default list */ + p = krb5_config_get_string(context, NULL, + "realms", + realm, + "v4_name_convert", + "plain", + name, + NULL); + if(p) + return NULL; + p = krb5_config_get_string(context, NULL, + "libdefaults", + "v4_name_convert", + "plain", + name, + NULL); + if(p) + return NULL; + for(q = default_v4_name_convert; q->from; q++) + if(strcmp(q->from, name) == 0) + return q->to; + return NULL; +} + +/* + * convert the v4 principal `name.instance@realm' to a v5 principal in `princ'. + * if `resolve', use DNS. + * if `func', use that function for validating the conversion + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_425_conv_principal_ext2(krb5_context context, + const char *name, + const char *instance, + const char *realm, + krb5_boolean (*func)(krb5_context, + void *, krb5_principal), + void *funcctx, + krb5_boolean resolve, + krb5_principal *princ) +{ + const char *p; + krb5_error_code ret; + krb5_principal pr; + char host[MAXHOSTNAMELEN]; + char local_hostname[MAXHOSTNAMELEN]; + + /* do the following: if the name is found in the + `v4_name_convert:host' part, is is assumed to be a `host' type + principal, and the instance is looked up in the + `v4_instance_convert' part. if not found there the name is + (optionally) looked up as a hostname, and if that doesn't yield + anything, the `default_domain' is appended to the instance + */ + + if(instance == NULL) + goto no_host; + if(instance[0] == 0){ + instance = NULL; + goto no_host; + } + p = get_name_conversion(context, realm, name); + if(p == NULL) + goto no_host; + name = p; + p = krb5_config_get_string(context, NULL, "realms", realm, + "v4_instance_convert", instance, NULL); + if(p){ + instance = p; + ret = krb5_make_principal(context, &pr, realm, name, instance, NULL); + if(func == NULL || (*func)(context, funcctx, pr)){ + *princ = pr; + return 0; + } + krb5_free_principal(context, pr); + *princ = NULL; + krb5_clear_error_string (context); + return HEIM_ERR_V4_PRINC_NO_CONV; + } + if(resolve){ + krb5_boolean passed = FALSE; + char *inst = NULL; +#ifdef USE_RESOLVER + struct dns_reply *r; + + r = dns_lookup(instance, "aaaa"); + if (r && r->head && r->head->type == T_AAAA) { + inst = strdup(r->head->domain); + dns_free_data(r); + passed = TRUE; + } else { + r = dns_lookup(instance, "a"); + if(r && r->head && r->head->type == T_A) { + inst = strdup(r->head->domain); + dns_free_data(r); + passed = TRUE; + } + } +#else + struct addrinfo hints, *ai; + int ret; + + memset (&hints, 0, sizeof(hints)); + hints.ai_flags = AI_CANONNAME; + ret = getaddrinfo(instance, NULL, &hints, &ai); + if (ret == 0) { + const struct addrinfo *a; + for (a = ai; a != NULL; a = a->ai_next) { + if (a->ai_canonname != NULL) { + inst = strdup (a->ai_canonname); + passed = TRUE; + break; + } + } + freeaddrinfo (ai); + } +#endif + if (passed) { + if (inst == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + strlwr(inst); + ret = krb5_make_principal(context, &pr, realm, name, inst, + NULL); + free (inst); + if(ret == 0) { + if(func == NULL || (*func)(context, funcctx, pr)){ + *princ = pr; + return 0; + } + krb5_free_principal(context, pr); + } + } + } + if(func != NULL) { + snprintf(host, sizeof(host), "%s.%s", instance, realm); + strlwr(host); + ret = krb5_make_principal(context, &pr, realm, name, host, NULL); + if((*func)(context, funcctx, pr)){ + *princ = pr; + return 0; + } + krb5_free_principal(context, pr); + } + + /* + * if the instance is the first component of the local hostname, + * the converted host should be the long hostname. + */ + + if (func == NULL && + gethostname (local_hostname, sizeof(local_hostname)) == 0 && + strncmp(instance, local_hostname, strlen(instance)) == 0 && + local_hostname[strlen(instance)] == '.') { + strlcpy(host, local_hostname, sizeof(host)); + goto local_host; + } + + { + char **domains, **d; + domains = krb5_config_get_strings(context, NULL, "realms", realm, + "v4_domains", NULL); + for(d = domains; d && *d; d++){ + snprintf(host, sizeof(host), "%s.%s", instance, *d); + ret = krb5_make_principal(context, &pr, realm, name, host, NULL); + if(func == NULL || (*func)(context, funcctx, pr)){ + *princ = pr; + krb5_config_free_strings(domains); + return 0; + } + krb5_free_principal(context, pr); + } + krb5_config_free_strings(domains); + } + + + p = krb5_config_get_string(context, NULL, "realms", realm, + "default_domain", NULL); + if(p == NULL){ + /* this should be an error, just faking a name is not good */ + krb5_clear_error_string (context); + return HEIM_ERR_V4_PRINC_NO_CONV; + } + + if (*p == '.') + ++p; + snprintf(host, sizeof(host), "%s.%s", instance, p); +local_host: + ret = krb5_make_principal(context, &pr, realm, name, host, NULL); + if(func == NULL || (*func)(context, funcctx, pr)){ + *princ = pr; + return 0; + } + krb5_free_principal(context, pr); + krb5_clear_error_string (context); + return HEIM_ERR_V4_PRINC_NO_CONV; +no_host: + p = krb5_config_get_string(context, NULL, + "realms", + realm, + "v4_name_convert", + "plain", + name, + NULL); + if(p == NULL) + p = krb5_config_get_string(context, NULL, + "libdefaults", + "v4_name_convert", + "plain", + name, + NULL); + if(p) + name = p; + + ret = krb5_make_principal(context, &pr, realm, name, instance, NULL); + if(func == NULL || (*func)(context, funcctx, pr)){ + *princ = pr; + return 0; + } + krb5_free_principal(context, pr); + krb5_clear_error_string (context); + return HEIM_ERR_V4_PRINC_NO_CONV; +} + +static krb5_boolean +convert_func(krb5_context conxtext, void *funcctx, krb5_principal principal) +{ + krb5_boolean (*func)(krb5_context, krb5_principal) = funcctx; + return (*func)(conxtext, principal); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_425_conv_principal_ext(krb5_context context, + const char *name, + const char *instance, + const char *realm, + krb5_boolean (*func)(krb5_context, krb5_principal), + krb5_boolean resolve, + krb5_principal *principal) +{ + return krb5_425_conv_principal_ext2(context, + name, + instance, + realm, + func ? convert_func : NULL, + func, + resolve, + principal); +} + + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_425_conv_principal(krb5_context context, + const char *name, + const char *instance, + const char *realm, + krb5_principal *princ) +{ + krb5_boolean resolve = krb5_config_get_bool(context, + NULL, + "libdefaults", + "v4_instance_resolve", + NULL); + + return krb5_425_conv_principal_ext(context, name, instance, realm, + NULL, resolve, princ); +} + + +static int +check_list(const krb5_config_binding *l, const char *name, const char **out) +{ + while(l){ + if (l->type != krb5_config_string) + continue; + if(strcmp(name, l->u.string) == 0) { + *out = l->name; + return 1; + } + l = l->next; + } + return 0; +} + +static int +name_convert(krb5_context context, const char *name, const char *realm, + const char **out) +{ + const krb5_config_binding *l; + l = krb5_config_get_list (context, + NULL, + "realms", + realm, + "v4_name_convert", + "host", + NULL); + if(l && check_list(l, name, out)) + return KRB5_NT_SRV_HST; + l = krb5_config_get_list (context, + NULL, + "libdefaults", + "v4_name_convert", + "host", + NULL); + if(l && check_list(l, name, out)) + return KRB5_NT_SRV_HST; + l = krb5_config_get_list (context, + NULL, + "realms", + realm, + "v4_name_convert", + "plain", + NULL); + if(l && check_list(l, name, out)) + return KRB5_NT_UNKNOWN; + l = krb5_config_get_list (context, + NULL, + "libdefaults", + "v4_name_convert", + "host", + NULL); + if(l && check_list(l, name, out)) + return KRB5_NT_UNKNOWN; + + /* didn't find it in config file, try built-in list */ + { + struct v4_name_convert *q; + for(q = default_v4_name_convert; q->from; q++) { + if(strcmp(name, q->to) == 0) { + *out = q->from; + return KRB5_NT_SRV_HST; + } + } + } + return -1; +} + +/* + * convert the v5 principal in `principal' into a v4 corresponding one + * in `name, instance, realm' + * this is limited interface since there's no length given for these + * three parameters. They have to be 40 bytes each (ANAME_SZ). + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_524_conv_principal(krb5_context context, + const krb5_principal principal, + char *name, + char *instance, + char *realm) +{ + const char *n, *i, *r; + char tmpinst[40]; + int type = princ_type(principal); + const int aname_sz = 40; + + r = principal->realm; + + switch(principal->name.name_string.len){ + case 1: + n = principal->name.name_string.val[0]; + i = ""; + break; + case 2: + n = principal->name.name_string.val[0]; + i = principal->name.name_string.val[1]; + break; + default: + krb5_set_error_string (context, + "cannot convert a %d component principal", + principal->name.name_string.len); + return KRB5_PARSE_MALFORMED; + } + + { + const char *tmp; + int t = name_convert(context, n, r, &tmp); + if(t >= 0) { + type = t; + n = tmp; + } + } + + if(type == KRB5_NT_SRV_HST){ + char *p; + + strlcpy (tmpinst, i, sizeof(tmpinst)); + p = strchr(tmpinst, '.'); + if(p) + *p = 0; + i = tmpinst; + } + + if (strlcpy (name, n, aname_sz) >= aname_sz) { + krb5_set_error_string (context, + "too long name component to convert"); + return KRB5_PARSE_MALFORMED; + } + if (strlcpy (instance, i, aname_sz) >= aname_sz) { + krb5_set_error_string (context, + "too long instance component to convert"); + return KRB5_PARSE_MALFORMED; + } + if (strlcpy (realm, r, aname_sz) >= aname_sz) { + krb5_set_error_string (context, + "too long realm component to convert"); + return KRB5_PARSE_MALFORMED; + } + return 0; +} + +/* + * Create a principal in `ret_princ' for the service `sname' running + * on host `hostname'. */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sname_to_principal (krb5_context context, + const char *hostname, + const char *sname, + int32_t type, + krb5_principal *ret_princ) +{ + krb5_error_code ret; + char localhost[MAXHOSTNAMELEN]; + char **realms, *host = NULL; + + if(type != KRB5_NT_SRV_HST && type != KRB5_NT_UNKNOWN) { + krb5_set_error_string (context, "unsupported name type %d", + type); + return KRB5_SNAME_UNSUPP_NAMETYPE; + } + if(hostname == NULL) { + gethostname(localhost, sizeof(localhost)); + hostname = localhost; + } + if(sname == NULL) + sname = "host"; + if(type == KRB5_NT_SRV_HST) { + ret = krb5_expand_hostname_realms (context, hostname, + &host, &realms); + if (ret) + return ret; + strlwr(host); + hostname = host; + } else { + ret = krb5_get_host_realm(context, hostname, &realms); + if(ret) + return ret; + } + + ret = krb5_make_principal(context, ret_princ, realms[0], sname, + hostname, NULL); + if(host) + free(host); + krb5_free_host_realm(context, realms); + return ret; +} diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c new file mode 100644 index 0000000000..9129eceeff --- /dev/null +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -0,0 +1,299 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: rd_cred.c,v 1.23 2005/06/17 04:31:48 lha Exp $"); + +static krb5_error_code +compare_addrs(krb5_context context, + krb5_address *a, + krb5_address *b, + const char *message) +{ + char a_str[64], b_str[64]; + size_t len; + + if(krb5_address_compare (context, a, b)) + return 0; + + krb5_print_address (a, a_str, sizeof(a_str), &len); + krb5_print_address (b, b_str, sizeof(b_str), &len); + krb5_set_error_string(context, "%s: %s != %s", message, b_str, a_str); + return KRB5KRB_AP_ERR_BADADDR; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_cred(krb5_context context, + krb5_auth_context auth_context, + krb5_data *in_data, + krb5_creds ***ret_creds, + krb5_replay_data *outdata) +{ + krb5_error_code ret; + size_t len; + KRB_CRED cred; + EncKrbCredPart enc_krb_cred_part; + krb5_data enc_krb_cred_part_data; + krb5_crypto crypto; + int i; + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + outdata == NULL) + return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */ + + *ret_creds = NULL; + + ret = decode_KRB_CRED(in_data->data, in_data->length, + &cred, &len); + if(ret) + return ret; + + if (cred.pvno != 5) { + ret = KRB5KRB_AP_ERR_BADVERSION; + krb5_clear_error_string (context); + goto out; + } + + if (cred.msg_type != krb_cred) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + krb5_clear_error_string (context); + goto out; + } + + if (cred.enc_part.etype == ETYPE_NULL) { + /* DK: MIT GSS-API Compatibility */ + enc_krb_cred_part_data.length = cred.enc_part.cipher.length; + enc_krb_cred_part_data.data = cred.enc_part.cipher.data; + } else { + if (auth_context->remote_subkey) + ret = krb5_crypto_init(context, auth_context->remote_subkey, + 0, &crypto); + else + ret = krb5_crypto_init(context, auth_context->keyblock, + 0, &crypto); + /* DK: MIT rsh */ + + if (ret) + goto out; + + ret = krb5_decrypt_EncryptedData(context, + crypto, + KRB5_KU_KRB_CRED, + &cred.enc_part, + &enc_krb_cred_part_data); + + krb5_crypto_destroy(context, crypto); + if (ret) + goto out; + } + + ret = krb5_decode_EncKrbCredPart (context, + enc_krb_cred_part_data.data, + enc_krb_cred_part_data.length, + &enc_krb_cred_part, + &len); + if (ret) + goto out; + + /* check sender address */ + + if (enc_krb_cred_part.s_address + && auth_context->remote_address + && auth_context->remote_port) { + krb5_address *a; + + ret = krb5_make_addrport (context, &a, + auth_context->remote_address, + auth_context->remote_port); + if (ret) + goto out; + + + ret = compare_addrs(context, a, enc_krb_cred_part.s_address, + "sender address is wrong in received creds"); + krb5_free_address(context, a); + free(a); + if(ret) + goto out; + } + + /* check receiver address */ + + if (enc_krb_cred_part.r_address + && auth_context->local_address) { + if(auth_context->local_port && + enc_krb_cred_part.r_address->addr_type == KRB5_ADDRESS_ADDRPORT) { + krb5_address *a; + ret = krb5_make_addrport (context, &a, + auth_context->local_address, + auth_context->local_port); + if (ret) + goto out; + + ret = compare_addrs(context, a, enc_krb_cred_part.r_address, + "receiver address is wrong in received creds"); + krb5_free_address(context, a); + free(a); + if(ret) + goto out; + } else { + ret = compare_addrs(context, auth_context->local_address, + enc_krb_cred_part.r_address, + "receiver address is wrong in received creds"); + if(ret) + goto out; + } + } + + /* check timestamp */ + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + krb5_timestamp sec; + + krb5_timeofday (context, &sec); + + if (enc_krb_cred_part.timestamp == NULL || + enc_krb_cred_part.usec == NULL || + abs(*enc_krb_cred_part.timestamp - sec) + > context->max_skew) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_SKEW; + goto out; + } + } + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) { + /* if these fields are not present in the cred-part, silently + return zero */ + memset(outdata, 0, sizeof(*outdata)); + if(enc_krb_cred_part.timestamp) + outdata->timestamp = *enc_krb_cred_part.timestamp; + if(enc_krb_cred_part.usec) + outdata->usec = *enc_krb_cred_part.usec; + if(enc_krb_cred_part.nonce) + outdata->seq = *enc_krb_cred_part.nonce; + } + + /* Convert to NULL terminated list of creds */ + + *ret_creds = calloc(enc_krb_cred_part.ticket_info.len + 1, + sizeof(**ret_creds)); + + if (*ret_creds == NULL) { + ret = ENOMEM; + krb5_set_error_string (context, "malloc: out of memory"); + goto out; + } + + for (i = 0; i < enc_krb_cred_part.ticket_info.len; ++i) { + KrbCredInfo *kci = &enc_krb_cred_part.ticket_info.val[i]; + krb5_creds *creds; + + creds = calloc(1, sizeof(*creds)); + if(creds == NULL) { + ret = ENOMEM; + krb5_set_error_string (context, "malloc: out of memory"); + goto out; + } + + ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, + &cred.tickets.val[i], &len, ret); + if (ret) + goto out; + if(creds->ticket.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + copy_EncryptionKey (&kci->key, &creds->session); + if (kci->prealm && kci->pname) + _krb5_principalname2krb5_principal (&creds->client, + *kci->pname, + *kci->prealm); + if (kci->flags) + creds->flags.b = *kci->flags; + if (kci->authtime) + creds->times.authtime = *kci->authtime; + if (kci->starttime) + creds->times.starttime = *kci->starttime; + if (kci->endtime) + creds->times.endtime = *kci->endtime; + if (kci->renew_till) + creds->times.renew_till = *kci->renew_till; + if (kci->srealm && kci->sname) + _krb5_principalname2krb5_principal (&creds->server, + *kci->sname, + *kci->srealm); + if (kci->caddr) + krb5_copy_addresses (context, + kci->caddr, + &creds->addresses); + + (*ret_creds)[i] = creds; + + } + (*ret_creds)[i] = NULL; + return 0; + + out: + free_KRB_CRED (&cred); + if(*ret_creds) { + for(i = 0; (*ret_creds)[i]; i++) + krb5_free_creds(context, (*ret_creds)[i]); + free(*ret_creds); + } + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_cred2 (krb5_context context, + krb5_auth_context auth_context, + krb5_ccache ccache, + krb5_data *in_data) +{ + krb5_error_code ret; + krb5_creds **creds; + int i; + + ret = krb5_rd_cred(context, auth_context, in_data, &creds, NULL); + if(ret) + return ret; + + /* Store the creds in the ccache */ + + for(i = 0; creds && creds[i]; i++) { + krb5_cc_store_cred(context, ccache, creds[i]); + krb5_free_creds(context, creds[i]); + } + free(creds); + return 0; +} diff --git a/source4/heimdal/lib/krb5/rd_error.c b/source4/heimdal/lib/krb5/rd_error.c new file mode 100644 index 0000000000..93e70c48bd --- /dev/null +++ b/source4/heimdal/lib/krb5/rd_error.c @@ -0,0 +1,121 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: rd_error.c,v 1.8 2005/05/18 04:21:57 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_error(krb5_context context, + krb5_data *msg, + KRB_ERROR *result) +{ + + size_t len; + krb5_error_code ret; + + ret = decode_KRB_ERROR(msg->data, msg->length, result, &len); + if(ret) + return ret; + result->error_code += KRB5KDC_ERR_NONE; + return 0; +} + +void KRB5_LIB_FUNCTION +krb5_free_error_contents (krb5_context context, + krb5_error *error) +{ + free_KRB_ERROR(error); + memset(error, 0, sizeof(*error)); +} + +void KRB5_LIB_FUNCTION +krb5_free_error (krb5_context context, + krb5_error *error) +{ + krb5_free_error_contents (context, error); + free (error); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_error_from_rd_error(krb5_context context, + const krb5_error *error, + const krb5_creds *creds) +{ + krb5_error_code ret; + + ret = error->error_code; + if (error->e_text != NULL) { + krb5_set_error_string(context, "%s", *error->e_text); + } else { + char clientname[256], servername[256]; + + if (creds != NULL) { + krb5_unparse_name_fixed(context, creds->client, + clientname, sizeof(clientname)); + krb5_unparse_name_fixed(context, creds->server, + servername, sizeof(servername)); + } + + switch (ret) { + case KRB5KDC_ERR_NAME_EXP : + krb5_set_error_string(context, "Client %s%s%s expired", + creds ? "(" : "", + creds ? clientname : "", + creds ? ")" : ""); + break; + case KRB5KDC_ERR_SERVICE_EXP : + krb5_set_error_string(context, "Server %s%s%s expired", + creds ? "(" : "", + creds ? servername : "", + creds ? ")" : ""); + break; + case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN : + krb5_set_error_string(context, "Client %s%s%s unknown", + creds ? "(" : "", + creds ? clientname : "", + creds ? ")" : ""); + break; + case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN : + krb5_set_error_string(context, "Server %s%s%s unknown", + creds ? "(" : "", + creds ? servername : "", + creds ? ")" : ""); + break; + default : + krb5_clear_error_string(context); + break; + } + } + return ret; +} diff --git a/source4/heimdal/lib/krb5/rd_priv.c b/source4/heimdal/lib/krb5/rd_priv.c new file mode 100644 index 0000000000..bafd23e995 --- /dev/null +++ b/source4/heimdal/lib/krb5/rd_priv.c @@ -0,0 +1,176 @@ +/* + * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: rd_priv.c,v 1.31 2004/05/25 21:39:13 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_priv(krb5_context context, + krb5_auth_context auth_context, + const krb5_data *inbuf, + krb5_data *outbuf, + krb5_replay_data *outdata) +{ + krb5_error_code ret; + KRB_PRIV priv; + EncKrbPrivPart part; + size_t len; + krb5_data plain; + krb5_keyblock *key; + krb5_crypto crypto; + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && + outdata == NULL) + return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */ + + memset(&priv, 0, sizeof(priv)); + ret = decode_KRB_PRIV (inbuf->data, inbuf->length, &priv, &len); + if (ret) + goto failure; + if (priv.pvno != 5) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BADVERSION; + goto failure; + } + if (priv.msg_type != krb_priv) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_MSG_TYPE; + goto failure; + } + + if (auth_context->remote_subkey) + key = auth_context->remote_subkey; + else if (auth_context->local_subkey) + key = auth_context->local_subkey; + else + key = auth_context->keyblock; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + goto failure; + ret = krb5_decrypt_EncryptedData(context, + crypto, + KRB5_KU_KRB_PRIV, + &priv.enc_part, + &plain); + krb5_crypto_destroy(context, crypto); + if (ret) + goto failure; + + ret = decode_EncKrbPrivPart (plain.data, plain.length, &part, &len); + krb5_data_free (&plain); + if (ret) + goto failure; + + /* check sender address */ + + if (part.s_address + && auth_context->remote_address + && !krb5_address_compare (context, + auth_context->remote_address, + part.s_address)) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BADADDR; + goto failure_part; + } + + /* check receiver address */ + + if (part.r_address + && auth_context->local_address + && !krb5_address_compare (context, + auth_context->local_address, + part.r_address)) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BADADDR; + goto failure_part; + } + + /* check timestamp */ + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + krb5_timestamp sec; + + krb5_timeofday (context, &sec); + if (part.timestamp == NULL || + part.usec == NULL || + abs(*part.timestamp - sec) > context->max_skew) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_SKEW; + goto failure_part; + } + } + + /* XXX - check replay cache */ + + /* check sequence number. since MIT krb5 cannot generate a sequence + number of zero but instead generates no sequence number, we accept that + */ + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { + if ((part.seq_number == NULL + && auth_context->remote_seqnumber != 0) + || (part.seq_number != NULL + && *part.seq_number != auth_context->remote_seqnumber)) { + krb5_clear_error_string (context); + ret = KRB5KRB_AP_ERR_BADORDER; + goto failure_part; + } + auth_context->remote_seqnumber++; + } + + ret = krb5_data_copy (outbuf, part.user_data.data, part.user_data.length); + if (ret) + goto failure_part; + + if ((auth_context->flags & + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) { + /* if these fields are not present in the priv-part, silently + return zero */ + memset(outdata, 0, sizeof(*outdata)); + if(part.timestamp) + outdata->timestamp = *part.timestamp; + if(part.usec) + outdata->usec = *part.usec; + if(part.seq_number) + outdata->seq = *part.seq_number; + } + + failure_part: + free_EncKrbPrivPart (&part); + + failure: + free_KRB_PRIV (&priv); + return ret; +} diff --git a/source4/heimdal/lib/krb5/rd_rep.c b/source4/heimdal/lib/krb5/rd_rep.c new file mode 100644 index 0000000000..a92eea5c04 --- /dev/null +++ b/source4/heimdal/lib/krb5/rd_rep.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: rd_rep.c,v 1.25 2005/06/17 07:49:33 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_rd_rep_type(krb5_context context, + krb5_auth_context auth_context, + const krb5_data *inbuf, + krb5_ap_rep_enc_part **repl, + krb5_boolean dce_style_response) +{ + krb5_error_code ret; + AP_REP ap_rep; + size_t len; + krb5_data data; + krb5_crypto crypto; + + krb5_data_zero (&data); + ret = 0; + + ret = decode_AP_REP(inbuf->data, inbuf->length, &ap_rep, &len); + if (ret) + return ret; + if (ap_rep.pvno != 5) { + ret = KRB5KRB_AP_ERR_BADVERSION; + krb5_clear_error_string (context); + goto out; + } + if (ap_rep.msg_type != krb_ap_rep) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + krb5_clear_error_string (context); + goto out; + } + + ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto); + if (ret) + goto out; + ret = krb5_decrypt_EncryptedData (context, + crypto, + KRB5_KU_AP_REQ_ENC_PART, + &ap_rep.enc_part, + &data); + krb5_crypto_destroy(context, crypto); + if (ret) + goto out; + + *repl = malloc(sizeof(**repl)); + if (*repl == NULL) { + ret = ENOMEM; + krb5_set_error_string (context, "malloc: out of memory"); + goto out; + } + ret = krb5_decode_EncAPRepPart(context, + data.data, + data.length, + *repl, + &len); + if (ret) + return ret; + + if (!dce_style_response) { + if ((*repl)->ctime != auth_context->authenticator->ctime || + (*repl)->cusec != auth_context->authenticator->cusec) { + ret = KRB5KRB_AP_ERR_MUT_FAIL; + krb5_set_error_string (context, "Mutual authentication failed: Timestamps mismatch"); + goto out; + } + } + if ((*repl)->seq_number) + krb5_auth_con_setremoteseqnumber(context, auth_context, + *((*repl)->seq_number)); + if ((*repl)->subkey) + krb5_auth_con_setremotesubkey(context, auth_context, (*repl)->subkey); + +out: + krb5_data_free (&data); + free_AP_REP (&ap_rep); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_rep(krb5_context context, + krb5_auth_context auth_context, + const krb5_data *inbuf, + krb5_ap_rep_enc_part **repl) +{ + return _krb5_rd_rep_type(context, + auth_context, + inbuf, + repl, + FALSE); +} + +void KRB5_LIB_FUNCTION +krb5_free_ap_rep_enc_part (krb5_context context, + krb5_ap_rep_enc_part *val) +{ + free_EncAPRepPart (val); + free (val); +} diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c new file mode 100644 index 0000000000..30ad08bd82 --- /dev/null +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -0,0 +1,649 @@ +/* + * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include + +RCSID("$Id: rd_req.c,v 1.57 2005/01/08 20:41:17 lha Exp $"); + +static krb5_error_code +decrypt_tkt_enc_part (krb5_context context, + krb5_keyblock *key, + EncryptedData *enc_part, + EncTicketPart *decr_part) +{ + krb5_error_code ret; + krb5_data plain; + size_t len; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + ret = krb5_decrypt_EncryptedData (context, + crypto, + KRB5_KU_TICKET, + enc_part, + &plain); + krb5_crypto_destroy(context, crypto); + if (ret) + return ret; + + ret = krb5_decode_EncTicketPart(context, plain.data, plain.length, + decr_part, &len); + krb5_data_free (&plain); + return ret; +} + +static krb5_error_code +decrypt_authenticator (krb5_context context, + EncryptionKey *key, + EncryptedData *enc_part, + Authenticator *authenticator, + krb5_key_usage usage) +{ + krb5_error_code ret; + krb5_data plain; + size_t len; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + ret = krb5_decrypt_EncryptedData (context, + crypto, + usage /* KRB5_KU_AP_REQ_AUTH */, + enc_part, + &plain); + /* for backwards compatibility, also try the old usage */ + if (ret && usage == KRB5_KU_TGS_REQ_AUTH) + ret = krb5_decrypt_EncryptedData (context, + crypto, + KRB5_KU_AP_REQ_AUTH, + enc_part, + &plain); + krb5_crypto_destroy(context, crypto); + if (ret) + return ret; + + ret = krb5_decode_Authenticator(context, plain.data, plain.length, + authenticator, &len); + krb5_data_free (&plain); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decode_ap_req(krb5_context context, + const krb5_data *inbuf, + krb5_ap_req *ap_req) +{ + krb5_error_code ret; + size_t len; + ret = decode_AP_REQ(inbuf->data, inbuf->length, ap_req, &len); + if (ret) + return ret; + if (ap_req->pvno != 5){ + free_AP_REQ(ap_req); + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_BADVERSION; + } + if (ap_req->msg_type != krb_ap_req){ + free_AP_REQ(ap_req); + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_MSG_TYPE; + } + if (ap_req->ticket.tkt_vno != 5){ + free_AP_REQ(ap_req); + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_BADVERSION; + } + return 0; +} + +static krb5_error_code +check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc) +{ + char **realms; + int num_realms; + krb5_error_code ret; + + if(enc->transited.tr_type != DOMAIN_X500_COMPRESS) + return KRB5KDC_ERR_TRTYPE_NOSUPP; + + if(enc->transited.contents.length == 0) + return 0; + + ret = krb5_domain_x500_decode(context, enc->transited.contents, + &realms, &num_realms, + enc->crealm, + ticket->realm); + if(ret) + return ret; + ret = krb5_check_transited(context, enc->crealm, + ticket->realm, + realms, num_realms, NULL); + free(realms); + return ret; +} + +static krb5_error_code +find_etypelist(krb5_context context, + krb5_auth_context auth_context, + EtypeList *etypes) +{ + krb5_error_code ret; + krb5_authdata *ad; + krb5_authdata adIfRelevant; + unsigned i; + + adIfRelevant.len = 0; + + etypes->len = 0; + etypes->val = NULL; + + ad = auth_context->authenticator->authorization_data; + if (ad == NULL) + return 0; + + for (i = 0; i < ad->len; i++) { + if (ad->val[i].ad_type == KRB5_AUTHDATA_IF_RELEVANT) { + ret = decode_AD_IF_RELEVANT(ad->val[i].ad_data.data, + ad->val[i].ad_data.length, + &adIfRelevant, + NULL); + if (ret) + return ret; + + if (adIfRelevant.len == 1 && + adIfRelevant.val[0].ad_type == + KRB5_AUTHDATA_GSS_API_ETYPE_NEGOTIATION) { + break; + } + free_AD_IF_RELEVANT(&adIfRelevant); + adIfRelevant.len = 0; + } + } + + if (adIfRelevant.len == 0) + return 0; + + ret = decode_EtypeList(adIfRelevant.val[0].ad_data.data, + adIfRelevant.val[0].ad_data.length, + etypes, + NULL); + + free_AD_IF_RELEVANT(&adIfRelevant); + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_ticket(krb5_context context, + Ticket *ticket, + krb5_keyblock *key, + EncTicketPart *out, + krb5_flags flags) +{ + EncTicketPart t; + krb5_error_code ret; + ret = decrypt_tkt_enc_part (context, key, &ticket->enc_part, &t); + if (ret) + return ret; + + { + krb5_timestamp now; + time_t start = t.authtime; + + krb5_timeofday (context, &now); + if(t.starttime) + start = *t.starttime; + if(start - now > context->max_skew + || (t.flags.invalid + && !(flags & KRB5_VERIFY_AP_REQ_IGNORE_INVALID))) { + free_EncTicketPart(&t); + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_TKT_NYV; + } + if(now - t.endtime > context->max_skew) { + free_EncTicketPart(&t); + krb5_clear_error_string (context); + return KRB5KRB_AP_ERR_TKT_EXPIRED; + } + + if(!t.flags.transited_policy_checked) { + ret = check_transited(context, ticket, &t); + if(ret) { + free_EncTicketPart(&t); + return ret; + } + } + } + + if(out) + *out = t; + else + free_EncTicketPart(&t); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_authenticator_checksum(krb5_context context, + krb5_auth_context ac, + void *data, + size_t len) +{ + krb5_error_code ret; + krb5_keyblock *key; + krb5_authenticator authenticator; + krb5_crypto crypto; + + ret = krb5_auth_con_getauthenticator (context, + ac, + &authenticator); + if(ret) + return ret; + if(authenticator->cksum == NULL) + return -17; + ret = krb5_auth_con_getkey(context, ac, &key); + if(ret) { + krb5_free_authenticator(context, &authenticator); + return ret; + } + ret = krb5_crypto_init(context, key, 0, &crypto); + if(ret) + goto out; + ret = krb5_verify_checksum (context, + crypto, + KRB5_KU_AP_REQ_AUTH_CKSUM, + data, + len, + authenticator->cksum); + krb5_crypto_destroy(context, crypto); +out: + krb5_free_authenticator(context, &authenticator); + krb5_free_keyblock(context, key); + return ret; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_ap_req(krb5_context context, + krb5_auth_context *auth_context, + krb5_ap_req *ap_req, + krb5_const_principal server, + krb5_keyblock *keyblock, + krb5_flags flags, + krb5_flags *ap_req_options, + krb5_ticket **ticket) +{ + return krb5_verify_ap_req2 (context, + auth_context, + ap_req, + server, + keyblock, + flags, + ap_req_options, + ticket, + KRB5_KU_AP_REQ_AUTH); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verify_ap_req2(krb5_context context, + krb5_auth_context *auth_context, + krb5_ap_req *ap_req, + krb5_const_principal server, + krb5_keyblock *keyblock, + krb5_flags flags, + krb5_flags *ap_req_options, + krb5_ticket **ticket, + krb5_key_usage usage) +{ + krb5_ticket *t; + krb5_auth_context ac; + krb5_error_code ret; + EtypeList etypes; + + if (auth_context && *auth_context) { + ac = *auth_context; + } else { + ret = krb5_auth_con_init (context, &ac); + if (ret) + return ret; + } + + t = malloc(sizeof(*t)); + if (t == NULL) { + ret = ENOMEM; + krb5_clear_error_string (context); + goto out; + } + memset(t, 0, sizeof(*t)); + + if (ap_req->ap_options.use_session_key && ac->keyblock){ + ret = krb5_decrypt_ticket(context, &ap_req->ticket, + ac->keyblock, + &t->ticket, + flags); + krb5_free_keyblock(context, ac->keyblock); + ac->keyblock = NULL; + }else + ret = krb5_decrypt_ticket(context, &ap_req->ticket, + keyblock, + &t->ticket, + flags); + + if(ret) + goto out; + + _krb5_principalname2krb5_principal(&t->server, ap_req->ticket.sname, + ap_req->ticket.realm); + _krb5_principalname2krb5_principal(&t->client, t->ticket.cname, + t->ticket.crealm); + + /* save key */ + + krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock); + + ret = decrypt_authenticator (context, + &t->ticket.key, + &ap_req->authenticator, + ac->authenticator, + usage); + if (ret) + goto out; + + { + krb5_principal p1, p2; + krb5_boolean res; + + _krb5_principalname2krb5_principal(&p1, + ac->authenticator->cname, + ac->authenticator->crealm); + _krb5_principalname2krb5_principal(&p2, + t->ticket.cname, + t->ticket.crealm); + res = krb5_principal_compare (context, p1, p2); + krb5_free_principal (context, p1); + krb5_free_principal (context, p2); + if (!res) { + ret = KRB5KRB_AP_ERR_BADMATCH; + krb5_clear_error_string (context); + goto out; + } + } + + /* check addresses */ + + if (t->ticket.caddr + && ac->remote_address + && !krb5_address_search (context, + ac->remote_address, + t->ticket.caddr)) { + ret = KRB5KRB_AP_ERR_BADADDR; + krb5_clear_error_string (context); + goto out; + } + + if (ac->authenticator->seq_number) + krb5_auth_con_setremoteseqnumber(context, ac, + *ac->authenticator->seq_number); + + /* XXX - Xor sequence numbers */ + + if (ac->authenticator->subkey) { + ret = krb5_auth_con_setremotesubkey(context, ac, + ac->authenticator->subkey); + if (ret) + goto out; + } + + ret = find_etypelist(context, ac, &etypes); + if (ret) + goto out; + + ac->keytype = ETYPE_NULL; + + if (etypes.val) { + int i; + + for (i = 0; i < etypes.len; i++) { + if (krb5_enctype_valid(context, etypes.val[i]) == 0) { + ac->keytype = etypes.val[i]; + break; + } + } + } + + if (ap_req_options) { + *ap_req_options = 0; + if (ac->keytype != ETYPE_NULL) + *ap_req_options |= AP_OPTS_USE_SUBKEY; + if (ap_req->ap_options.use_session_key) + *ap_req_options |= AP_OPTS_USE_SESSION_KEY; + if (ap_req->ap_options.mutual_required) + *ap_req_options |= AP_OPTS_MUTUAL_REQUIRED; + } + + if(ticket) + *ticket = t; + else + krb5_free_ticket (context, t); + if (auth_context) { + if (*auth_context == NULL) + *auth_context = ac; + } else + krb5_auth_con_free (context, ac); + free_EtypeList(&etypes); + return 0; + out: + if (t) + krb5_free_ticket (context, t); + if (auth_context == NULL || *auth_context == NULL) + krb5_auth_con_free (context, ac); + return ret; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_with_keyblock(krb5_context context, + krb5_auth_context *auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_keyblock *keyblock, + krb5_flags *ap_req_options, + krb5_ticket **ticket) +{ + krb5_error_code ret; + krb5_ap_req ap_req; + + if (*auth_context == NULL) { + ret = krb5_auth_con_init(context, auth_context); + if (ret) + return ret; + } + + ret = krb5_decode_ap_req(context, inbuf, &ap_req); + if(ret) + return ret; + + ret = krb5_verify_ap_req(context, + auth_context, + &ap_req, + server, + keyblock, + 0, + ap_req_options, + ticket); + + free_AP_REQ(&ap_req); + return ret; +} + +static krb5_error_code +get_key_from_keytab(krb5_context context, + krb5_auth_context *auth_context, + krb5_ap_req *ap_req, + krb5_const_principal server, + krb5_keytab keytab, + krb5_keyblock **out_key) +{ + krb5_keytab_entry entry; + krb5_error_code ret; + int kvno; + krb5_keytab real_keytab; + + if(keytab == NULL) + krb5_kt_default(context, &real_keytab); + else + real_keytab = keytab; + + if (ap_req->ticket.enc_part.kvno) + kvno = *ap_req->ticket.enc_part.kvno; + else + kvno = 0; + + ret = krb5_kt_get_entry (context, + real_keytab, + server, + kvno, + ap_req->ticket.enc_part.etype, + &entry); + if(ret) + goto out; + ret = krb5_copy_keyblock(context, &entry.keyblock, out_key); + krb5_kt_free_entry (context, &entry); +out: + if(keytab == NULL) + krb5_kt_close(context, real_keytab); + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_return_keyblock(krb5_context context, + krb5_auth_context *auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_keytab keytab, + krb5_flags *ap_req_options, + krb5_ticket **ticket, + krb5_keyblock **keyblock) +{ + krb5_error_code ret; + krb5_ap_req ap_req; + krb5_principal service = NULL; + + if (*auth_context == NULL) { + ret = krb5_auth_con_init(context, auth_context); + if (ret) + return ret; + } + + ret = krb5_decode_ap_req(context, inbuf, &ap_req); + if(ret) + return ret; + + if(server == NULL){ + _krb5_principalname2krb5_principal(&service, + ap_req.ticket.sname, + ap_req.ticket.realm); + server = service; + } + if (ap_req.ap_options.use_session_key && + (*auth_context)->keyblock == NULL) { + krb5_set_error_string(context, "krb5_rd_req: user to user auth " + "without session key given"); + ret = KRB5KRB_AP_ERR_NOKEY; + goto out; + } + + if((*auth_context)->keyblock == NULL){ + ret = get_key_from_keytab(context, + auth_context, + &ap_req, + server, + keytab, + keyblock); + if(ret) + goto out; + } else { + ret = krb5_copy_keyblock(context, + (*auth_context)->keyblock, + keyblock); + if (ret) + goto out; + } + + ret = krb5_verify_ap_req(context, + auth_context, + &ap_req, + server, + *keyblock, + 0, + ap_req_options, + ticket); + +out: + free_AP_REQ(&ap_req); + if(service) + krb5_free_principal(context, service); + if (ret) + krb5_free_keyblock(context, *keyblock); + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req(krb5_context context, + krb5_auth_context *auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_keytab keytab, + krb5_flags *ap_req_options, + krb5_ticket **ticket) +{ + krb5_error_code ret; + krb5_keyblock *keyblock; + + ret = krb5_rd_req_return_keyblock(context, + auth_context, + inbuf, + server, + keytab, + ap_req_options, + ticket, + &keyblock); + + krb5_free_keyblock(context, keyblock); + return ret; +} + diff --git a/source4/heimdal/lib/krb5/replay.c b/source4/heimdal/lib/krb5/replay.c new file mode 100644 index 0000000000..ec99f86c7c --- /dev/null +++ b/source4/heimdal/lib/krb5/replay.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 1997-2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +#include + +RCSID("$Id: replay.c,v 1.10 2004/05/25 21:41:15 lha Exp $"); + +struct krb5_rcache_data { + char *name; +}; + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_resolve(krb5_context context, + krb5_rcache id, + const char *name) +{ + id->name = strdup(name); + if(id->name == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return KRB5_RC_MALLOC; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_resolve_type(krb5_context context, + krb5_rcache *id, + const char *type) +{ + if(strcmp(type, "FILE")) { + krb5_set_error_string (context, "replay cache type %s not supported", + type); + return KRB5_RC_TYPE_NOTFOUND; + } + *id = calloc(1, sizeof(**id)); + if(*id == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return KRB5_RC_MALLOC; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_resolve_full(krb5_context context, + krb5_rcache *id, + const char *string_name) +{ + krb5_error_code ret; + if(strncmp(string_name, "FILE:", 5)) { + krb5_set_error_string (context, "replay cache type %s not supported", + string_name); + return KRB5_RC_TYPE_NOTFOUND; + } + ret = krb5_rc_resolve_type(context, id, "FILE"); + if(ret) + return ret; + ret = krb5_rc_resolve(context, *id, string_name + 5); + return ret; +} + +const char* KRB5_LIB_FUNCTION +krb5_rc_default_name(krb5_context context) +{ + return "FILE:/var/run/default_rcache"; +} + +const char* KRB5_LIB_FUNCTION +krb5_rc_default_type(krb5_context context) +{ + return "FILE"; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_default(krb5_context context, + krb5_rcache *id) +{ + return krb5_rc_resolve_full(context, id, krb5_rc_default_name(context)); +} + +struct rc_entry{ + time_t stamp; + unsigned char data[16]; +}; + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_initialize(krb5_context context, + krb5_rcache id, + krb5_deltat auth_lifespan) +{ + FILE *f = fopen(id->name, "w"); + struct rc_entry tmp; + int ret; + + if(f == NULL) { + ret = errno; + krb5_set_error_string (context, "open(%s): %s", id->name, + strerror(ret)); + return ret; + } + tmp.stamp = auth_lifespan; + fwrite(&tmp, 1, sizeof(tmp), f); + fclose(f); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_recover(krb5_context context, + krb5_rcache id) +{ + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_destroy(krb5_context context, + krb5_rcache id) +{ + int ret; + + if(remove(id->name) < 0) { + ret = errno; + krb5_set_error_string (context, "remove(%s): %s", id->name, + strerror(ret)); + return ret; + } + return krb5_rc_close(context, id); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_close(krb5_context context, + krb5_rcache id) +{ + free(id->name); + free(id); + return 0; +} + +static void +checksum_authenticator(Authenticator *auth, void *data) +{ + MD5_CTX md5; + int i; + + MD5_Init (&md5); + MD5_Update (&md5, auth->crealm, strlen(auth->crealm)); + for(i = 0; i < auth->cname.name_string.len; i++) + MD5_Update(&md5, auth->cname.name_string.val[i], + strlen(auth->cname.name_string.val[i])); + MD5_Update (&md5, &auth->ctime, sizeof(auth->ctime)); + MD5_Update (&md5, &auth->cusec, sizeof(auth->cusec)); + MD5_Final (data, &md5); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_store(krb5_context context, + krb5_rcache id, + krb5_donot_replay *rep) +{ + struct rc_entry ent, tmp; + time_t t; + FILE *f; + int ret; + + ent.stamp = time(NULL); + checksum_authenticator(rep, ent.data); + f = fopen(id->name, "r"); + if(f == NULL) { + ret = errno; + krb5_set_error_string (context, "open(%s): %s", id->name, + strerror(ret)); + return ret; + } + fread(&tmp, sizeof(ent), 1, f); + t = ent.stamp - tmp.stamp; + while(fread(&tmp, sizeof(ent), 1, f)){ + if(tmp.stamp < t) + continue; + if(memcmp(tmp.data, ent.data, sizeof(ent.data)) == 0){ + fclose(f); + krb5_clear_error_string (context); + return KRB5_RC_REPLAY; + } + } + if(ferror(f)){ + ret = errno; + fclose(f); + krb5_set_error_string (context, "%s: %s", id->name, strerror(ret)); + return ret; + } + fclose(f); + f = fopen(id->name, "a"); + if(f == NULL) { + krb5_set_error_string (context, "open(%s): %s", id->name, + strerror(errno)); + return KRB5_RC_IO_UNKNOWN; + } + fwrite(&ent, 1, sizeof(ent), f); + fclose(f); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_expunge(krb5_context context, + krb5_rcache id) +{ + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rc_get_lifespan(krb5_context context, + krb5_rcache id, + krb5_deltat *auth_lifespan) +{ + FILE *f = fopen(id->name, "r"); + int r; + struct rc_entry ent; + r = fread(&ent, sizeof(ent), 1, f); + fclose(f); + if(r){ + *auth_lifespan = ent.stamp; + return 0; + } + krb5_clear_error_string (context); + return KRB5_RC_IO_UNKNOWN; +} + +const char* KRB5_LIB_FUNCTION +krb5_rc_get_name(krb5_context context, + krb5_rcache id) +{ + return id->name; +} + +const char* KRB5_LIB_FUNCTION +krb5_rc_get_type(krb5_context context, + krb5_rcache id) +{ + return "FILE"; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_server_rcache(krb5_context context, + const krb5_data *piece, + krb5_rcache *id) +{ + krb5_rcache rcache; + krb5_error_code ret; + + char *tmp = malloc(4 * piece->length + 1); + char *name; + + if(tmp == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + strvisx(tmp, piece->data, piece->length, VIS_WHITE | VIS_OCTAL); +#ifdef HAVE_GETEUID + asprintf(&name, "FILE:rc_%s_%u", tmp, (unsigned)geteuid()); +#else + asprintf(&name, "FILE:rc_%s", tmp); +#endif + free(tmp); + if(name == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + + ret = krb5_rc_resolve_full(context, &rcache, name); + free(name); + if(ret) + return ret; + *id = rcache; + return ret; +} diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c new file mode 100644 index 0000000000..d55f8dc692 --- /dev/null +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -0,0 +1,416 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: send_to_kdc.c,v 1.56 2005/06/17 04:33:11 lha Exp $"); + +/* + * send the data in `req' on the socket `fd' (which is datagram iff udp) + * waiting `tmout' for a reply and returning the reply in `rep'. + * iff limit read up to this many bytes + * returns 0 and data in `rep' if succesful, otherwise -1 + */ + +static int +recv_loop (int fd, + time_t tmout, + int udp, + size_t limit, + krb5_data *rep) +{ + fd_set fdset; + struct timeval timeout; + int ret; + int nbytes; + + if (fd >= FD_SETSIZE) { + return -1; + } + + krb5_data_zero(rep); + do { + FD_ZERO(&fdset); + FD_SET(fd, &fdset); + timeout.tv_sec = tmout; + timeout.tv_usec = 0; + ret = select (fd + 1, &fdset, NULL, NULL, &timeout); + if (ret < 0) { + if (errno == EINTR) + continue; + return -1; + } else if (ret == 0) { + return 0; + } else { + void *tmp; + + if (ioctl (fd, FIONREAD, &nbytes) < 0) { + krb5_data_free (rep); + return -1; + } + if(nbytes == 0) + return 0; + + if (limit) + nbytes = min(nbytes, limit - rep->length); + + tmp = realloc (rep->data, rep->length + nbytes); + if (tmp == NULL) { + krb5_data_free (rep); + return -1; + } + rep->data = tmp; + ret = recv (fd, (char*)tmp + rep->length, nbytes, 0); + if (ret < 0) { + krb5_data_free (rep); + return -1; + } + rep->length += ret; + } + } while(!udp && (limit == 0 || rep->length < limit)); + return 0; +} + +/* + * Send kerberos requests and receive a reply on a udp or any other kind + * of a datagram socket. See `recv_loop'. + */ + +static int +send_and_recv_udp(int fd, + time_t tmout, + const krb5_data *req, + krb5_data *rep) +{ + if (send (fd, req->data, req->length, 0) < 0) + return -1; + + return recv_loop(fd, tmout, 1, 0, rep); +} + +/* + * `send_and_recv' for a TCP (or any other stream) socket. + * Since there are no record limits on a stream socket the protocol here + * is to prepend the request with 4 bytes of its length and the reply + * is similarly encoded. + */ + +static int +send_and_recv_tcp(int fd, + time_t tmout, + const krb5_data *req, + krb5_data *rep) +{ + unsigned char len[4]; + unsigned long rep_len; + krb5_data len_data; + + _krb5_put_int(len, req->length, 4); + if(net_write(fd, len, sizeof(len)) < 0) + return -1; + if(net_write(fd, req->data, req->length) < 0) + return -1; + if (recv_loop (fd, tmout, 0, 4, &len_data) < 0) + return -1; + if (len_data.length != 4) { + krb5_data_free (&len_data); + return -1; + } + _krb5_get_int(len_data.data, &rep_len, 4); + krb5_data_free (&len_data); + if (recv_loop (fd, tmout, 0, rep_len, rep) < 0) + return -1; + if(rep->length != rep_len) { + krb5_data_free (rep); + return -1; + } + return 0; +} + +int +_krb5_send_and_recv_tcp(int fd, + time_t tmout, + const krb5_data *req, + krb5_data *rep) +{ + return send_and_recv_tcp(fd, tmout, req, rep); +} + +/* + * `send_and_recv' tailored for the HTTP protocol. + */ + +static int +send_and_recv_http(int fd, + time_t tmout, + const char *prefix, + const krb5_data *req, + krb5_data *rep) +{ + char *request; + char *str; + int ret; + int len = base64_encode(req->data, req->length, &str); + + if(len < 0) + return -1; + asprintf(&request, "GET %s%s HTTP/1.0\r\n\r\n", prefix, str); + free(str); + if (request == NULL) + return -1; + ret = net_write (fd, request, strlen(request)); + free (request); + if (ret < 0) + return ret; + ret = recv_loop(fd, tmout, 0, 0, rep); + if(ret) + return ret; + { + unsigned long rep_len; + char *s, *p; + + s = realloc(rep->data, rep->length + 1); + if (s == NULL) { + krb5_data_free (rep); + return -1; + } + s[rep->length] = 0; + p = strstr(s, "\r\n\r\n"); + if(p == NULL) { + free(s); + return -1; + } + p += 4; + rep->data = s; + rep->length -= p - s; + if(rep->length < 4) { /* remove length */ + free(s); + return -1; + } + rep->length -= 4; + _krb5_get_int(p, &rep_len, 4); + if (rep_len != rep->length) { + free(s); + return -1; + } + memmove(rep->data, p + 4, rep->length); + } + return 0; +} + +static int +init_port(const char *s, int fallback) +{ + if (s) { + int tmp; + + sscanf (s, "%d", &tmp); + return htons(tmp); + } else + return fallback; +} + +/* + * Return 0 if succesful, otherwise 1 + */ + +static int +send_via_proxy (krb5_context context, + const krb5_krbhst_info *hi, + const krb5_data *send_data, + krb5_data *receive) +{ + char *proxy2 = strdup(context->http_proxy); + char *proxy = proxy2; + char *prefix; + char *colon; + struct addrinfo hints; + struct addrinfo *ai, *a; + int ret; + int s = -1; + char portstr[NI_MAXSERV]; + + if (proxy == NULL) + return ENOMEM; + if (strncmp (proxy, "http://", 7) == 0) + proxy += 7; + + colon = strchr(proxy, ':'); + if(colon != NULL) + *colon++ = '\0'; + memset (&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + snprintf (portstr, sizeof(portstr), "%d", + ntohs(init_port (colon, htons(80)))); + ret = getaddrinfo (proxy, portstr, &hints, &ai); + free (proxy2); + if (ret) + return krb5_eai_to_heim_errno(ret, errno); + + for (a = ai; a != NULL; a = a->ai_next) { + s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); + if (s < 0) + continue; + if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { + close (s); + continue; + } + break; + } + if (a == NULL) { + freeaddrinfo (ai); + return 1; + } + freeaddrinfo (ai); + + asprintf(&prefix, "http://%s/", hi->hostname); + if(prefix == NULL) { + close(s); + return 1; + } + ret = send_and_recv_http(s, context->kdc_timeout, + prefix, send_data, receive); + close (s); + free(prefix); + if(ret == 0 && receive->length != 0) + return 0; + return 1; +} + +/* + * Send the data `send' to one host from `handle` and get back the reply + * in `receive'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto (krb5_context context, + const krb5_data *send_data, + krb5_krbhst_handle handle, + krb5_data *receive) +{ + krb5_error_code ret = 0; + int fd; + int i; + + for (i = 0; i < context->max_retries; ++i) { + krb5_krbhst_info *hi; + + while (krb5_krbhst_next(context, handle, &hi) == 0) { + struct addrinfo *ai, *a; + + if(hi->proto == KRB5_KRBHST_HTTP && context->http_proxy) { + if (send_via_proxy (context, hi, send_data, receive)) + continue; + else + goto out; + } + + ret = krb5_krbhst_get_addrinfo(context, hi, &ai); + if (ret) + continue; + + for (a = ai; a != NULL; a = a->ai_next) { + fd = socket (a->ai_family, a->ai_socktype, a->ai_protocol); + if (fd < 0) + continue; + if (connect (fd, a->ai_addr, a->ai_addrlen) < 0) { + close (fd); + continue; + } + switch (hi->proto) { + case KRB5_KRBHST_HTTP : + ret = send_and_recv_http(fd, context->kdc_timeout, + "", send_data, receive); + break; + case KRB5_KRBHST_TCP : + ret = send_and_recv_tcp (fd, context->kdc_timeout, + send_data, receive); + break; + case KRB5_KRBHST_UDP : + ret = send_and_recv_udp (fd, context->kdc_timeout, + send_data, receive); + break; + } + close (fd); + if(ret == 0 && receive->length != 0) + goto out; + } + } + krb5_krbhst_reset(context, handle); + } + krb5_clear_error_string (context); + ret = KRB5_KDC_UNREACH; +out: + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_kdc(krb5_context context, + const krb5_data *send_data, + const krb5_realm *realm, + krb5_data *receive) +{ + return krb5_sendto_kdc_flags(context, send_data, realm, receive, 0); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_kdc_flags(krb5_context context, + const krb5_data *send_data, + const krb5_realm *realm, + krb5_data *receive, + int flags) +{ + krb5_error_code ret; + krb5_krbhst_handle handle; + int type; + + if ((flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc) + type = KRB5_KRBHST_ADMIN; + else + type = KRB5_KRBHST_KDC; + + if (send_data->length > context->large_msg_size) + flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; + + ret = krb5_krbhst_init_flags(context, *realm, type, flags, &handle); + if (ret) + return ret; + + ret = krb5_sendto(context, send_data, handle, receive); + krb5_krbhst_free(context, handle); + if (ret == KRB5_KDC_UNREACH) + krb5_set_error_string(context, + "unable to reach any KDC in realm %s", *realm); + return ret; +} diff --git a/source4/heimdal/lib/krb5/set_default_realm.c b/source4/heimdal/lib/krb5/set_default_realm.c new file mode 100644 index 0000000000..965883309c --- /dev/null +++ b/source4/heimdal/lib/krb5/set_default_realm.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: set_default_realm.c,v 1.14 2004/05/25 21:42:26 lha Exp $"); + +/* + * Convert the simple string `s' into a NULL-terminated and freshly allocated + * list in `list'. Return an error code. + */ + +static krb5_error_code +string_to_list (krb5_context context, const char *s, krb5_realm **list) +{ + + *list = malloc (2 * sizeof(**list)); + if (*list == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + (*list)[0] = strdup (s); + if ((*list)[0] == NULL) { + free (*list); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + (*list)[1] = NULL; + return 0; +} + +/* + * Set the knowledge of the default realm(s) in `context'. + * If realm != NULL, that's the new default realm. + * Otherwise, the realm(s) are figured out from configuration or DNS. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_default_realm(krb5_context context, + const char *realm) +{ + krb5_error_code ret = 0; + krb5_realm *realms = NULL; + + if (realm == NULL) { + realms = krb5_config_get_strings (context, NULL, + "libdefaults", + "default_realm", + NULL); + if (realms == NULL) + ret = krb5_get_host_realm(context, NULL, &realms); + } else { + ret = string_to_list (context, realm, &realms); + } + if (ret) + return ret; + krb5_free_host_realm (context, context->default_realms); + context->default_realms = realms; + return 0; +} diff --git a/source4/heimdal/lib/krb5/store-int.h b/source4/heimdal/lib/krb5/store-int.h new file mode 100644 index 0000000000..42e695a11b --- /dev/null +++ b/source4/heimdal/lib/krb5/store-int.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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 __store_int_h__ +#define __store_int_h__ + +struct krb5_storage_data { + void *data; + ssize_t (*fetch)(struct krb5_storage_data*, void*, size_t); + ssize_t (*store)(struct krb5_storage_data*, const void*, size_t); + off_t (*seek)(struct krb5_storage_data*, off_t, int); + void (*free)(struct krb5_storage_data*); + krb5_flags flags; + int eof_code; +}; + +#endif /* __store_int_h__ */ diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c new file mode 100644 index 0000000000..42667765fb --- /dev/null +++ b/source4/heimdal/lib/krb5/store.c @@ -0,0 +1,888 @@ +/* + * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +#include "store-int.h" + +RCSID("$Id: store.c,v 1.50 2005/06/17 04:36:33 lha Exp $"); + +#define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) +#define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) +#define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE) +#define BYTEORDER_IS_HOST(SP) (BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_HOST) || \ + krb5_storage_is_flags((SP), KRB5_STORAGE_HOST_BYTEORDER)) + +void KRB5_LIB_FUNCTION +krb5_storage_set_flags(krb5_storage *sp, krb5_flags flags) +{ + sp->flags |= flags; +} + +void KRB5_LIB_FUNCTION +krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags) +{ + sp->flags &= ~flags; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags) +{ + return (sp->flags & flags) == flags; +} + +void KRB5_LIB_FUNCTION +krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder) +{ + sp->flags &= ~KRB5_STORAGE_BYTEORDER_MASK; + sp->flags |= byteorder; +} + +krb5_flags KRB5_LIB_FUNCTION +krb5_storage_get_byteorder(krb5_storage *sp, krb5_flags byteorder) +{ + return sp->flags & KRB5_STORAGE_BYTEORDER_MASK; +} + +off_t KRB5_LIB_FUNCTION +krb5_storage_seek(krb5_storage *sp, off_t offset, int whence) +{ + return (*sp->seek)(sp, offset, whence); +} + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_storage_read(krb5_storage *sp, void *buf, size_t len) +{ + return sp->fetch(sp, buf, len); +} + +krb5_ssize_t KRB5_LIB_FUNCTION +krb5_storage_write(krb5_storage *sp, const void *buf, size_t len) +{ + return sp->store(sp, buf, len); +} + +void KRB5_LIB_FUNCTION +krb5_storage_set_eof_code(krb5_storage *sp, int code) +{ + sp->eof_code = code; +} + +krb5_ssize_t KRB5_LIB_FUNCTION +_krb5_put_int(void *buffer, unsigned long value, size_t size) +{ + unsigned char *p = buffer; + int i; + for (i = size - 1; i >= 0; i--) { + p[i] = value & 0xff; + value >>= 8; + } + return size; +} + +krb5_ssize_t KRB5_LIB_FUNCTION +_krb5_get_int(void *buffer, unsigned long *value, size_t size) +{ + unsigned char *p = buffer; + unsigned long v = 0; + int i; + for (i = 0; i < size; i++) + v = (v << 8) + p[i]; + *value = v; + return size; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_storage_free(krb5_storage *sp) +{ + if(sp->free) + (*sp->free)(sp); + free(sp->data); + free(sp); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_storage_to_data(krb5_storage *sp, krb5_data *data) +{ + off_t pos; + size_t size; + krb5_error_code ret; + + pos = sp->seek(sp, 0, SEEK_CUR); + size = (size_t)sp->seek(sp, 0, SEEK_END); + ret = krb5_data_alloc (data, size); + if (ret) { + sp->seek(sp, pos, SEEK_SET); + return ret; + } + if (size) { + sp->seek(sp, 0, SEEK_SET); + sp->fetch(sp, data->data, data->length); + sp->seek(sp, pos, SEEK_SET); + } + return 0; +} + +static krb5_error_code +krb5_store_int(krb5_storage *sp, + int32_t value, + size_t len) +{ + int ret; + unsigned char v[16]; + + if(len > sizeof(v)) + return EINVAL; + _krb5_put_int(v, value, len); + ret = sp->store(sp, v, len); + if (ret != len) + return (ret<0)?errno:sp->eof_code; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_int32(krb5_storage *sp, + int32_t value) +{ + if(BYTEORDER_IS_HOST(sp)) + value = htonl(value); + else if(BYTEORDER_IS_LE(sp)) + value = bswap32(value); + return krb5_store_int(sp, value, 4); +} + +static krb5_error_code +krb5_ret_int(krb5_storage *sp, + int32_t *value, + size_t len) +{ + int ret; + unsigned char v[4]; + unsigned long w; + ret = sp->fetch(sp, v, len); + if(ret != len) + return (ret<0)?errno:sp->eof_code; + _krb5_get_int(v, &w, len); + *value = w; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_int32(krb5_storage *sp, + int32_t *value) +{ + krb5_error_code ret = krb5_ret_int(sp, value, 4); + if(ret) + return ret; + if(BYTEORDER_IS_HOST(sp)) + *value = htonl(*value); + else if(BYTEORDER_IS_LE(sp)) + *value = bswap32(*value); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_int16(krb5_storage *sp, + int16_t value) +{ + if(BYTEORDER_IS_HOST(sp)) + value = htons(value); + else if(BYTEORDER_IS_LE(sp)) + value = bswap16(value); + return krb5_store_int(sp, value, 2); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_int16(krb5_storage *sp, + int16_t *value) +{ + int32_t v; + int ret; + ret = krb5_ret_int(sp, &v, 2); + if(ret) + return ret; + *value = v; + if(BYTEORDER_IS_HOST(sp)) + *value = htons(*value); + else if(BYTEORDER_IS_LE(sp)) + *value = bswap16(*value); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_int8(krb5_storage *sp, + int8_t value) +{ + int ret; + + ret = sp->store(sp, &value, sizeof(value)); + if (ret != sizeof(value)) + return (ret<0)?errno:sp->eof_code; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_int8(krb5_storage *sp, + int8_t *value) +{ + int ret; + + ret = sp->fetch(sp, value, sizeof(*value)); + if (ret != sizeof(*value)) + return (ret<0)?errno:sp->eof_code; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_data(krb5_storage *sp, + krb5_data data) +{ + int ret; + ret = krb5_store_int32(sp, data.length); + if(ret < 0) + return ret; + ret = sp->store(sp, data.data, data.length); + if(ret != data.length){ + if(ret < 0) + return errno; + return sp->eof_code; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_data(krb5_storage *sp, + krb5_data *data) +{ + int ret; + int32_t size; + + ret = krb5_ret_int32(sp, &size); + if(ret) + return ret; + ret = krb5_data_alloc (data, size); + if (ret) + return ret; + if (size) { + ret = sp->fetch(sp, data->data, size); + if(ret != size) + return (ret < 0)? errno : sp->eof_code; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_string(krb5_storage *sp, const char *s) +{ + krb5_data data; + data.length = strlen(s); + data.data = rk_UNCONST(s); + return krb5_store_data(sp, data); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_string(krb5_storage *sp, + char **string) +{ + int ret; + krb5_data data; + ret = krb5_ret_data(sp, &data); + if(ret) + return ret; + *string = realloc(data.data, data.length + 1); + if(*string == NULL){ + free(data.data); + return ENOMEM; + } + (*string)[data.length] = 0; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_stringz(krb5_storage *sp, const char *s) +{ + size_t len = strlen(s) + 1; + ssize_t ret; + + ret = sp->store(sp, s, len); + if(ret != len) { + if(ret < 0) + return ret; + else + return sp->eof_code; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_stringz(krb5_storage *sp, + char **string) +{ + char c; + char *s = NULL; + size_t len = 0; + ssize_t ret; + + while((ret = sp->fetch(sp, &c, 1)) == 1){ + char *tmp; + + len++; + tmp = realloc (s, len); + if (tmp == NULL) { + free (s); + return ENOMEM; + } + s = tmp; + s[len - 1] = c; + if(c == 0) + break; + } + if(ret != 1){ + free(s); + if(ret == 0) + return sp->eof_code; + return ret; + } + *string = s; + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_principal(krb5_storage *sp, + krb5_principal p) +{ + int i; + int ret; + + if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) { + ret = krb5_store_int32(sp, p->name.name_type); + if(ret) return ret; + } + if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) + ret = krb5_store_int32(sp, p->name.name_string.len + 1); + else + ret = krb5_store_int32(sp, p->name.name_string.len); + + if(ret) return ret; + ret = krb5_store_string(sp, p->realm); + if(ret) return ret; + for(i = 0; i < p->name.name_string.len; i++){ + ret = krb5_store_string(sp, p->name.name_string.val[i]); + if(ret) return ret; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_principal(krb5_storage *sp, + krb5_principal *princ) +{ + int i; + int ret; + krb5_principal p; + int32_t type; + int32_t ncomp; + + p = calloc(1, sizeof(*p)); + if(p == NULL) + return ENOMEM; + + if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) + type = KRB5_NT_UNKNOWN; + else if((ret = krb5_ret_int32(sp, &type))){ + free(p); + return ret; + } + if((ret = krb5_ret_int32(sp, &ncomp))){ + free(p); + return ret; + } + if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) + ncomp--; + p->name.name_type = type; + p->name.name_string.len = ncomp; + ret = krb5_ret_string(sp, &p->realm); + if(ret) return ret; + p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val)); + if(p->name.name_string.val == NULL){ + free(p->realm); + return ENOMEM; + } + for(i = 0; i < ncomp; i++){ + ret = krb5_ret_string(sp, &p->name.name_string.val[i]); + if(ret) return ret; /* XXX */ + } + *princ = p; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p) +{ + int ret; + ret = krb5_store_int16(sp, p.keytype); + if(ret) return ret; + + if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ + /* this should really be enctype, but it is the same as + keytype nowadays */ + ret = krb5_store_int16(sp, p.keytype); + if(ret) return ret; + } + + ret = krb5_store_data(sp, p.keyvalue); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p) +{ + int ret; + int16_t tmp; + + ret = krb5_ret_int16(sp, &tmp); + if(ret) return ret; + p->keytype = tmp; + + if(krb5_storage_is_flags(sp, KRB5_STORAGE_KEYBLOCK_KEYTYPE_TWICE)){ + ret = krb5_ret_int16(sp, &tmp); + if(ret) return ret; + } + + ret = krb5_ret_data(sp, &p->keyvalue); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_times(krb5_storage *sp, krb5_times times) +{ + int ret; + ret = krb5_store_int32(sp, times.authtime); + if(ret) return ret; + ret = krb5_store_int32(sp, times.starttime); + if(ret) return ret; + ret = krb5_store_int32(sp, times.endtime); + if(ret) return ret; + ret = krb5_store_int32(sp, times.renew_till); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_times(krb5_storage *sp, krb5_times *times) +{ + int ret; + int32_t tmp; + ret = krb5_ret_int32(sp, &tmp); + times->authtime = tmp; + if(ret) return ret; + ret = krb5_ret_int32(sp, &tmp); + times->starttime = tmp; + if(ret) return ret; + ret = krb5_ret_int32(sp, &tmp); + times->endtime = tmp; + if(ret) return ret; + ret = krb5_ret_int32(sp, &tmp); + times->renew_till = tmp; + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_address(krb5_storage *sp, krb5_address p) +{ + int ret; + ret = krb5_store_int16(sp, p.addr_type); + if(ret) return ret; + ret = krb5_store_data(sp, p.address); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_address(krb5_storage *sp, krb5_address *adr) +{ + int16_t t; + int ret; + ret = krb5_ret_int16(sp, &t); + if(ret) return ret; + adr->addr_type = t; + ret = krb5_ret_data(sp, &adr->address); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_addrs(krb5_storage *sp, krb5_addresses p) +{ + int i; + int ret; + ret = krb5_store_int32(sp, p.len); + if(ret) return ret; + for(i = 0; ilen = tmp; + ALLOC(adr->val, adr->len); + if (adr->val == NULL && adr->len != 0) + return ENOMEM; + for(i = 0; i < adr->len; i++){ + ret = krb5_ret_address(sp, &adr->val[i]); + if(ret) break; + } + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_authdata(krb5_storage *sp, krb5_authdata auth) +{ + krb5_error_code ret; + int i; + ret = krb5_store_int32(sp, auth.len); + if(ret) return ret; + for(i = 0; i < auth.len; i++){ + ret = krb5_store_int16(sp, auth.val[i].ad_type); + if(ret) break; + ret = krb5_store_data(sp, auth.val[i].ad_data); + if(ret) break; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_authdata(krb5_storage *sp, krb5_authdata *auth) +{ + krb5_error_code ret; + int32_t tmp; + int16_t tmp2; + int i; + ret = krb5_ret_int32(sp, &tmp); + if(ret) return ret; + ALLOC_SEQ(auth, tmp); + if (auth->val == NULL && tmp != 0) + return ENOMEM; + for(i = 0; i < tmp; i++){ + ret = krb5_ret_int16(sp, &tmp2); + if(ret) break; + auth->val[i].ad_type = tmp2; + ret = krb5_ret_data(sp, &auth->val[i].ad_data); + if(ret) break; + } + return ret; +} + +static int32_t +bitswap32(int32_t b) +{ + int32_t r = 0; + int i; + for (i = 0; i < 32; i++) { + r = r << 1 | (b & 1); + b = b >> 1; + } + return r; +} + + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_creds(krb5_storage *sp, krb5_creds *creds) +{ + int ret; + + ret = krb5_store_principal(sp, creds->client); + if(ret) + return ret; + ret = krb5_store_principal(sp, creds->server); + if(ret) + return ret; + ret = krb5_store_keyblock(sp, creds->session); + if(ret) + return ret; + ret = krb5_store_times(sp, creds->times); + if(ret) + return ret; + ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ + if(ret) + return ret; + + if(krb5_storage_is_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER)) + ret = krb5_store_int32(sp, creds->flags.i); + else + ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); + if(ret) + return ret; + + ret = krb5_store_addrs(sp, creds->addresses); + if(ret) + return ret; + ret = krb5_store_authdata(sp, creds->authdata); + if(ret) + return ret; + ret = krb5_store_data(sp, creds->ticket); + if(ret) + return ret; + ret = krb5_store_data(sp, creds->second_ticket); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_creds(krb5_storage *sp, krb5_creds *creds) +{ + krb5_error_code ret; + int8_t dummy8; + int32_t dummy32; + + memset(creds, 0, sizeof(*creds)); + ret = krb5_ret_principal (sp, &creds->client); + if(ret) goto cleanup; + ret = krb5_ret_principal (sp, &creds->server); + if(ret) goto cleanup; + ret = krb5_ret_keyblock (sp, &creds->session); + if(ret) goto cleanup; + ret = krb5_ret_times (sp, &creds->times); + if(ret) goto cleanup; + ret = krb5_ret_int8 (sp, &dummy8); + if(ret) goto cleanup; + ret = krb5_ret_int32 (sp, &dummy32); + if(ret) goto cleanup; + /* + * Runtime detect the what is the higher bits of the bitfield. If + * any of the higher bits are set in the input data, its either a + * new ticket flag (and this code need to be removed), or its a + * MIT cache (or new Heimdal cache), lets change it to our current + * format. + */ + { + u_int32_t mask = 0xffff0000; + creds->flags.i = 0; + creds->flags.b.anonymous = 1; + if (creds->flags.i & mask) + mask = ~mask; + if (dummy32 & mask) + dummy32 = bitswap32(dummy32); + } + creds->flags.i = dummy32; + ret = krb5_ret_addrs (sp, &creds->addresses); + if(ret) goto cleanup; + ret = krb5_ret_authdata (sp, &creds->authdata); + if(ret) goto cleanup; + ret = krb5_ret_data (sp, &creds->ticket); + if(ret) goto cleanup; + ret = krb5_ret_data (sp, &creds->second_ticket); +cleanup: + if(ret) { +#if 0 + krb5_free_cred_contents(context, creds); /* XXX */ +#endif + } + return ret; +} + +#define SC_CLIENT_PRINCIPAL 0x0001 +#define SC_SERVER_PRINCIPAL 0x0002 +#define SC_SESSION_KEY 0x0004 +#define SC_TICKET 0x0008 +#define SC_SECOND_TICKET 0x0010 +#define SC_AUTHDATA 0x0020 +#define SC_ADDRESSES 0x0040 + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds) +{ + int ret; + int32_t header = 0; + + if (creds->client) + header |= SC_CLIENT_PRINCIPAL; + if (creds->server) + header |= SC_SERVER_PRINCIPAL; + if (creds->session.keyvalue.data) + header |= SC_SESSION_KEY; + if (creds->ticket.data) + header |= SC_TICKET; + if (creds->second_ticket.length) + header |= SC_SECOND_TICKET; + if (creds->authdata.len) + header |= SC_AUTHDATA; + if (creds->addresses.len) + header |= SC_ADDRESSES; + + ret = krb5_store_int32(sp, header); + + if (creds->client) { + ret = krb5_store_principal(sp, creds->client); + if(ret) + return ret; + } + + if (creds->server) { + ret = krb5_store_principal(sp, creds->server); + if(ret) + return ret; + } + + if (creds->session.keyvalue.data) { + ret = krb5_store_keyblock(sp, creds->session); + if(ret) + return ret; + } + + ret = krb5_store_times(sp, creds->times); + if(ret) + return ret; + ret = krb5_store_int8(sp, creds->second_ticket.length != 0); /* is_skey */ + if(ret) + return ret; + + ret = krb5_store_int32(sp, bitswap32(TicketFlags2int(creds->flags.b))); + if(ret) + return ret; + + if (creds->addresses.len) { + ret = krb5_store_addrs(sp, creds->addresses); + if(ret) + return ret; + } + + if (creds->authdata.len) { + ret = krb5_store_authdata(sp, creds->authdata); + if(ret) + return ret; + } + + if (creds->ticket.data) { + ret = krb5_store_data(sp, creds->ticket); + if(ret) + return ret; + } + + if (creds->second_ticket.data) { + ret = krb5_store_data(sp, creds->second_ticket); + if (ret) + return ret; + } + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_creds_tag(krb5_storage *sp, + krb5_creds *creds) +{ + krb5_error_code ret; + int8_t dummy8; + int32_t dummy32, header; + + memset(creds, 0, sizeof(*creds)); + + ret = krb5_ret_int32 (sp, &header); + if (ret) goto cleanup; + + if (header & SC_CLIENT_PRINCIPAL) { + ret = krb5_ret_principal (sp, &creds->client); + if(ret) goto cleanup; + } + if (header & SC_SERVER_PRINCIPAL) { + ret = krb5_ret_principal (sp, &creds->server); + if(ret) goto cleanup; + } + if (header & SC_SESSION_KEY) { + ret = krb5_ret_keyblock (sp, &creds->session); + if(ret) goto cleanup; + } + ret = krb5_ret_times (sp, &creds->times); + if(ret) goto cleanup; + ret = krb5_ret_int8 (sp, &dummy8); + if(ret) goto cleanup; + ret = krb5_ret_int32 (sp, &dummy32); + if(ret) goto cleanup; + /* + * Runtime detect the what is the higher bits of the bitfield. If + * any of the higher bits are set in the input data, its either a + * new ticket flag (and this code need to be removed), or its a + * MIT cache (or new Heimdal cache), lets change it to our current + * format. + */ + { + u_int32_t mask = 0xffff0000; + creds->flags.i = 0; + creds->flags.b.anonymous = 1; + if (creds->flags.i & mask) + mask = ~mask; + if (dummy32 & mask) + dummy32 = bitswap32(dummy32); + } + creds->flags.i = dummy32; + if (header & SC_ADDRESSES) { + ret = krb5_ret_addrs (sp, &creds->addresses); + if(ret) goto cleanup; + } + if (header & SC_AUTHDATA) { + ret = krb5_ret_authdata (sp, &creds->authdata); + if(ret) goto cleanup; + } + if (header & SC_TICKET) { + ret = krb5_ret_data (sp, &creds->ticket); + if(ret) goto cleanup; + } + if (header & SC_SECOND_TICKET) { + ret = krb5_ret_data (sp, &creds->second_ticket); + if(ret) goto cleanup; + } + +cleanup: + if(ret) { +#if 0 + krb5_free_cred_contents(context, creds); /* XXX */ +#endif + } + return ret; +} diff --git a/source4/heimdal/lib/krb5/store_emem.c b/source4/heimdal/lib/krb5/store_emem.c new file mode 100644 index 0000000000..b9f93728de --- /dev/null +++ b/source4/heimdal/lib/krb5/store_emem.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +#include "store-int.h" + +RCSID("$Id: store_emem.c,v 1.14 2004/05/25 21:43:29 lha Exp $"); + +typedef struct emem_storage{ + unsigned char *base; + size_t size; + size_t len; + unsigned char *ptr; +}emem_storage; + +static ssize_t +emem_fetch(krb5_storage *sp, void *data, size_t size) +{ + emem_storage *s = (emem_storage*)sp->data; + if(s->base + s->len - s->ptr < size) + size = s->base + s->len - s->ptr; + memmove(data, s->ptr, size); + sp->seek(sp, size, SEEK_CUR); + return size; +} + +static ssize_t +emem_store(krb5_storage *sp, const void *data, size_t size) +{ + emem_storage *s = (emem_storage*)sp->data; + if(size > s->base + s->size - s->ptr){ + void *base; + size_t sz, off; + off = s->ptr - s->base; + sz = off + size; + if (sz < 4096) + sz *= 2; + base = realloc(s->base, sz); + if(base == NULL) + return 0; + s->size = sz; + s->base = base; + s->ptr = (unsigned char*)base + off; + } + memmove(s->ptr, data, size); + sp->seek(sp, size, SEEK_CUR); + return size; +} + +static off_t +emem_seek(krb5_storage *sp, off_t offset, int whence) +{ + emem_storage *s = (emem_storage*)sp->data; + switch(whence){ + case SEEK_SET: + if(offset > s->size) + offset = s->size; + if(offset < 0) + offset = 0; + s->ptr = s->base + offset; + if(offset > s->len) + s->len = offset; + break; + case SEEK_CUR: + sp->seek(sp,s->ptr - s->base + offset, SEEK_SET); + break; + case SEEK_END: + sp->seek(sp, s->len + offset, SEEK_SET); + break; + default: + errno = EINVAL; + return -1; + } + return s->ptr - s->base; +} + +static void +emem_free(krb5_storage *sp) +{ + emem_storage *s = sp->data; + memset(s->base, 0, s->len); + free(s->base); +} + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_emem(void) +{ + krb5_storage *sp = malloc(sizeof(krb5_storage)); + emem_storage *s = malloc(sizeof(*s)); + sp->data = s; + sp->flags = 0; + sp->eof_code = HEIM_ERR_EOF; + s->size = 1024; + s->base = malloc(s->size); + s->len = 0; + s->ptr = s->base; + sp->fetch = emem_fetch; + sp->store = emem_store; + sp->seek = emem_seek; + sp->free = emem_free; + return sp; +} diff --git a/source4/heimdal/lib/krb5/store_fd.c b/source4/heimdal/lib/krb5/store_fd.c new file mode 100644 index 0000000000..46043a6761 --- /dev/null +++ b/source4/heimdal/lib/krb5/store_fd.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +#include "store-int.h" + +RCSID("$Id: store_fd.c,v 1.12 2004/05/25 21:43:57 lha Exp $"); + +typedef struct fd_storage { + int fd; +} fd_storage; + +#define FD(S) (((fd_storage*)(S)->data)->fd) + +static ssize_t +fd_fetch(krb5_storage * sp, void *data, size_t size) +{ + return net_read(FD(sp), data, size); +} + +static ssize_t +fd_store(krb5_storage * sp, const void *data, size_t size) +{ + return net_write(FD(sp), data, size); +} + +static off_t +fd_seek(krb5_storage * sp, off_t offset, int whence) +{ + return lseek(FD(sp), offset, whence); +} + +static void +fd_free(krb5_storage * sp) +{ + close(FD(sp)); +} + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_fd(int fd) +{ + krb5_storage *sp; + + fd = dup(fd); + if (fd < 0) + return NULL; + sp = malloc(sizeof(krb5_storage)); + + if (sp == NULL) + return NULL; + + sp->data = malloc(sizeof(fd_storage)); + if (sp->data == NULL) { + free(sp); + return NULL; + } + sp->flags = 0; + sp->eof_code = HEIM_ERR_EOF; + FD(sp) = fd; + sp->fetch = fd_fetch; + sp->store = fd_store; + sp->seek = fd_seek; + sp->free = fd_free; + return sp; +} diff --git a/source4/heimdal/lib/krb5/store_mem.c b/source4/heimdal/lib/krb5/store_mem.c new file mode 100644 index 0000000000..decf74adce --- /dev/null +++ b/source4/heimdal/lib/krb5/store_mem.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1997 - 2000, 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +#include "store-int.h" + +RCSID("$Id: store_mem.c,v 1.12 2004/05/25 21:44:17 lha Exp $"); + +typedef struct mem_storage{ + unsigned char *base; + size_t size; + unsigned char *ptr; +}mem_storage; + +static ssize_t +mem_fetch(krb5_storage *sp, void *data, size_t size) +{ + mem_storage *s = (mem_storage*)sp->data; + if(size > s->base + s->size - s->ptr) + size = s->base + s->size - s->ptr; + memmove(data, s->ptr, size); + sp->seek(sp, size, SEEK_CUR); + return size; +} + +static ssize_t +mem_store(krb5_storage *sp, const void *data, size_t size) +{ + mem_storage *s = (mem_storage*)sp->data; + if(size > s->base + s->size - s->ptr) + size = s->base + s->size - s->ptr; + memmove(s->ptr, data, size); + sp->seek(sp, size, SEEK_CUR); + return size; +} + +static off_t +mem_seek(krb5_storage *sp, off_t offset, int whence) +{ + mem_storage *s = (mem_storage*)sp->data; + switch(whence){ + case SEEK_SET: + if(offset > s->size) + offset = s->size; + if(offset < 0) + offset = 0; + s->ptr = s->base + offset; + break; + case SEEK_CUR: + return sp->seek(sp, s->ptr - s->base + offset, SEEK_SET); + case SEEK_END: + return sp->seek(sp, s->size + offset, SEEK_SET); + default: + errno = EINVAL; + return -1; + } + return s->ptr - s->base; +} + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_mem(void *buf, size_t len) +{ + krb5_storage *sp = malloc(sizeof(krb5_storage)); + mem_storage *s; + if(sp == NULL) + return NULL; + s = malloc(sizeof(*s)); + if(s == NULL) { + free(sp); + return NULL; + } + sp->data = s; + sp->flags = 0; + sp->eof_code = HEIM_ERR_EOF; + s->base = buf; + s->size = len; + s->ptr = buf; + sp->fetch = mem_fetch; + sp->store = mem_store; + sp->seek = mem_seek; + sp->free = NULL; + return sp; +} + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_data(krb5_data *data) +{ + return krb5_storage_from_mem(data->data, data->length); +} diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c new file mode 100644 index 0000000000..734cd4d4ca --- /dev/null +++ b/source4/heimdal/lib/krb5/ticket.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: ticket.c,v 1.12 2004/05/25 21:44:47 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_free_ticket(krb5_context context, + krb5_ticket *ticket) +{ + free_EncTicketPart(&ticket->ticket); + krb5_free_principal(context, ticket->client); + krb5_free_principal(context, ticket->server); + free(ticket); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_copy_ticket(krb5_context context, + const krb5_ticket *from, + krb5_ticket **to) +{ + krb5_error_code ret; + krb5_ticket *tmp; + + *to = NULL; + tmp = malloc(sizeof(*tmp)); + if(tmp == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){ + free(tmp); + return ret; + } + ret = krb5_copy_principal(context, from->client, &tmp->client); + if(ret){ + free_EncTicketPart(&tmp->ticket); + free(tmp); + return ret; + } + ret = krb5_copy_principal(context, from->server, &tmp->server); + if(ret){ + krb5_free_principal(context, tmp->client); + free_EncTicketPart(&tmp->ticket); + free(tmp); + return ret; + } + *to = tmp; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ticket_get_client(krb5_context context, + const krb5_ticket *ticket, + krb5_principal *client) +{ + return krb5_copy_principal(context, ticket->client, client); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ticket_get_server(krb5_context context, + const krb5_ticket *ticket, + krb5_principal *server) +{ + return krb5_copy_principal(context, ticket->server, server); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ticket_get_authorization_data_type(krb5_context context, + krb5_ticket *ticket, + int type, + krb5_data *data) +{ + AuthorizationData *ad; + int i; + + data->length = 0; + data->data = NULL; + + ad = ticket->ticket.authorization_data; + if (ad == NULL) { + krb5_set_error_string(context, "Ticket have not authorization data"); + return ENOENT; /* XXX */ + } + + for (i = 0; i < ad->len; i++) { + if (ad->val[i].ad_type == type) + return copy_octet_string(&ad->val[i].ad_data, data); + } + krb5_set_error_string(context, "Ticket have not authorization " + "data of type %d", type); + return ENOENT; /* XXX */ +} diff --git a/source4/heimdal/lib/krb5/time.c b/source4/heimdal/lib/krb5/time.c new file mode 100644 index 0000000000..4a120ab771 --- /dev/null +++ b/source4/heimdal/lib/krb5/time.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: time.c,v 1.13 2004/10/13 17:57:11 lha Exp $"); + +/* + * Set the absolute time that the caller knows the kdc has so the + * kerberos library can calculate the relative diffrence beteen the + * KDC time and local system time. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_real_time (krb5_context context, + krb5_timestamp sec, + int32_t usec) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + context->kdc_sec_offset = sec - tv.tv_sec; + context->kdc_usec_offset = usec - tv.tv_usec; + + if (context->kdc_usec_offset < 0) { + context->kdc_sec_offset--; + context->kdc_usec_offset += 1000000; + } + return 0; +} + +/* + * return ``corrected'' time in `timeret'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_timeofday (krb5_context context, + krb5_timestamp *timeret) +{ + *timeret = time(NULL) + context->kdc_sec_offset; + return 0; +} + +/* + * like gettimeofday but with time correction to the KDC + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_us_timeofday (krb5_context context, + krb5_timestamp *sec, + int32_t *usec) +{ + struct timeval tv; + + gettimeofday (&tv, NULL); + + *sec = tv.tv_sec + context->kdc_sec_offset; + *usec = tv.tv_usec; /* XXX */ + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_format_time(krb5_context context, time_t t, + char *s, size_t len, krb5_boolean include_time) +{ + struct tm *tm; + if(context->log_utc) + tm = gmtime (&t); + else + tm = localtime(&t); + if(tm == NULL || + strftime(s, len, include_time ? context->time_fmt : context->date_fmt, tm) == 0) + snprintf(s, len, "%ld", (long)t); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_deltat(const char *string, krb5_deltat *deltat) +{ + if((*deltat = parse_time(string, "s")) == -1) + return KRB5_DELTAT_BADFORMAT; + return 0; +} diff --git a/source4/heimdal/lib/krb5/transited.c b/source4/heimdal/lib/krb5/transited.c new file mode 100644 index 0000000000..9e24db0da0 --- /dev/null +++ b/source4/heimdal/lib/krb5/transited.c @@ -0,0 +1,481 @@ +/* + * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: transited.c,v 1.16 2005/06/17 04:53:35 lha Exp $"); + +/* this is an attempt at one of the most horrible `compression' + schemes that has ever been invented; it's so amazingly brain-dead + that words can not describe it, and all this just to save a few + silly bytes */ + +struct tr_realm { + char *realm; + unsigned leading_space:1; + unsigned leading_slash:1; + unsigned trailing_dot:1; + struct tr_realm *next; +}; + +static void +free_realms(struct tr_realm *r) +{ + struct tr_realm *p; + while(r){ + p = r; + r = r->next; + free(p->realm); + free(p); + } +} + +static int +make_path(krb5_context context, struct tr_realm *r, + const char *from, const char *to) +{ + const char *p; + struct tr_realm *path = r->next; + struct tr_realm *tmp; + + if(strlen(from) < strlen(to)){ + const char *str; + str = from; + from = to; + to = str; + } + + if(strcmp(from + strlen(from) - strlen(to), to) == 0){ + p = from; + while(1){ + p = strchr(p, '.'); + if(p == NULL) { + krb5_clear_error_string (context); + return KRB5KDC_ERR_POLICY; + } + p++; + if(strcmp(p, to) == 0) + break; + tmp = calloc(1, sizeof(*tmp)); + tmp->next = path; + path = tmp; + path->realm = strdup(p); + if(path->realm == NULL){ + r->next = path; /* XXX */ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM;; + } + } + }else if(strncmp(from, to, strlen(to)) == 0){ + p = from + strlen(from); + while(1){ + while(p >= from && *p != '/') p--; + if(p == from) + return KRB5KDC_ERR_POLICY; + if(strncmp(to, from, p - from) == 0) + break; + tmp = calloc(1, sizeof(*tmp)); + tmp->next = path; + path = tmp; + path->realm = malloc(p - from + 1); + if(path->realm == NULL){ + r->next = path; /* XXX */ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(path->realm, from, p - from); + path->realm[p - from] = '\0'; + p--; + } + } else { + krb5_clear_error_string (context); + return KRB5KDC_ERR_POLICY; + } + r->next = path; + + return 0; +} + +static int +make_paths(krb5_context context, + struct tr_realm *realms, const char *client_realm, + const char *server_realm) +{ + struct tr_realm *r; + int ret; + const char *prev_realm = client_realm; + const char *next_realm = NULL; + for(r = realms; r; r = r->next){ + /* it *might* be that you can have more than one empty + component in a row, at least that's how I interpret the + "," exception in 1510 */ + if(r->realm[0] == '\0'){ + while(r->next && r->next->realm[0] == '\0') + r = r->next; + if(r->next) + next_realm = r->next->realm; + else + next_realm = server_realm; + ret = make_path(context, r, prev_realm, next_realm); + if(ret){ + free_realms(realms); + return ret; + } + } + prev_realm = r->realm; + } + return 0; +} + +static int +expand_realms(krb5_context context, + struct tr_realm *realms, const char *client_realm) +{ + struct tr_realm *r; + const char *prev_realm = NULL; + for(r = realms; r; r = r->next){ + if(r->trailing_dot){ + char *tmp; + size_t len = strlen(r->realm) + strlen(prev_realm) + 1; + + if(prev_realm == NULL) + prev_realm = client_realm; + tmp = realloc(r->realm, len); + if(tmp == NULL){ + free_realms(realms); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + r->realm = tmp; + strlcat(r->realm, prev_realm, len); + }else if(r->leading_slash && !r->leading_space && prev_realm){ + /* yet another exception: if you use x500-names, the + leading realm doesn't have to be "quoted" with a space */ + char *tmp; + size_t len = strlen(r->realm) + strlen(prev_realm) + 1; + + tmp = malloc(len); + if(tmp == NULL){ + free_realms(realms); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + strlcpy(tmp, prev_realm, len); + strlcat(tmp, r->realm, len); + free(r->realm); + r->realm = tmp; + } + prev_realm = r->realm; + } + return 0; +} + +static struct tr_realm * +make_realm(char *realm) +{ + struct tr_realm *r; + char *p, *q; + int quote = 0; + r = calloc(1, sizeof(*r)); + if(r == NULL){ + free(realm); + return NULL; + } + r->realm = realm; + for(p = q = r->realm; *p; p++){ + if(p == r->realm && *p == ' '){ + r->leading_space = 1; + continue; + } + if(q == r->realm && *p == '/') + r->leading_slash = 1; + if(quote){ + *q++ = *p; + quote = 0; + continue; + } + if(*p == '\\'){ + quote = 1; + continue; + } + if(p[0] == '.' && p[1] == '\0') + r->trailing_dot = 1; + *q++ = *p; + } + *q = '\0'; + return r; +} + +static struct tr_realm* +append_realm(struct tr_realm *head, struct tr_realm *r) +{ + struct tr_realm *p; + if(head == NULL){ + r->next = NULL; + return r; + } + p = head; + while(p->next) p = p->next; + p->next = r; + return head; +} + +static int +decode_realms(krb5_context context, + const char *tr, int length, struct tr_realm **realms) +{ + struct tr_realm *r = NULL; + + char *tmp; + int quote = 0; + const char *start = tr; + int i; + + for(i = 0; i < length; i++){ + if(quote){ + quote = 0; + continue; + } + if(tr[i] == '\\'){ + quote = 1; + continue; + } + if(tr[i] == ','){ + tmp = malloc(tr + i - start + 1); + memcpy(tmp, start, tr + i - start); + tmp[tr + i - start] = '\0'; + r = make_realm(tmp); + if(r == NULL){ + free_realms(*realms); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + *realms = append_realm(*realms, r); + start = tr + i + 1; + } + } + tmp = malloc(tr + i - start + 1); + memcpy(tmp, start, tr + i - start); + tmp[tr + i - start] = '\0'; + r = make_realm(tmp); + if(r == NULL){ + free_realms(*realms); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + *realms = append_realm(*realms, r); + + return 0; +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_domain_x500_decode(krb5_context context, + krb5_data tr, char ***realms, int *num_realms, + const char *client_realm, const char *server_realm) +{ + struct tr_realm *r = NULL; + struct tr_realm *p, **q; + int ret; + + if(tr.length == 0) { + *realms = NULL; + *num_realms = 0; + return 0; + } + + /* split string in components */ + ret = decode_realms(context, tr.data, tr.length, &r); + if(ret) + return ret; + + /* apply prefix rule */ + ret = expand_realms(context, r, client_realm); + if(ret) + return ret; + + ret = make_paths(context, r, client_realm, server_realm); + if(ret) + return ret; + + /* remove empty components and count realms */ + q = &r; + *num_realms = 0; + for(p = r; p; ){ + if(p->realm[0] == '\0'){ + free(p->realm); + *q = p->next; + free(p); + p = *q; + }else{ + q = &p->next; + p = p->next; + (*num_realms)++; + } + } + if (*num_realms < 0 || *num_realms + 1 > UINT_MAX/sizeof(**realms)) + return ERANGE; + + { + char **R; + R = malloc((*num_realms + 1) * sizeof(*R)); + if (R == NULL) + return ENOMEM; + *realms = R; + while(r){ + *R++ = r->realm; + p = r->next; + free(r); + r = p; + } + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_domain_x500_encode(char **realms, int num_realms, krb5_data *encoding) +{ + char *s = NULL; + int len = 0; + int i; + krb5_data_zero(encoding); + if (num_realms == 0) + return 0; + for(i = 0; i < num_realms; i++){ + len += strlen(realms[i]); + if(realms[i][0] == '/') + len++; + } + len += num_realms - 1; + s = malloc(len + 1); + if (s == NULL) + return ENOMEM; + *s = '\0'; + for(i = 0; i < num_realms; i++){ + if(i && i < num_realms - 1) + strlcat(s, ",", len + 1); + if(realms[i][0] == '/') + strlcat(s, " ", len + 1); + strlcat(s, realms[i], len + 1); + } + encoding->data = s; + encoding->length = strlen(s); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_check_transited(krb5_context context, + krb5_const_realm client_realm, + krb5_const_realm server_realm, + krb5_realm *realms, + int num_realms, + int *bad_realm) +{ + char **tr_realms; + char **p; + int i; + + if(num_realms == 0) + return 0; + + tr_realms = krb5_config_get_strings(context, NULL, + "capaths", + client_realm, + server_realm, + NULL); + for(i = 0; i < num_realms; i++) { + for(p = tr_realms; p && *p; p++) { + if(strcmp(*p, realms[i]) == 0) + break; + } + if(p == NULL || *p == NULL) { + krb5_config_free_strings(tr_realms); + krb5_set_error_string (context, "no transit through realm %s", + realms[i]); + if(bad_realm) + *bad_realm = i; + return KRB5KRB_AP_ERR_ILL_CR_TKT; + } + } + krb5_config_free_strings(tr_realms); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_check_transited_realms(krb5_context context, + const char *const *realms, + int num_realms, + int *bad_realm) +{ + int i; + int ret = 0; + char **bad_realms = krb5_config_get_strings(context, NULL, + "libdefaults", + "transited_realms_reject", + NULL); + if(bad_realms == NULL) + return 0; + + for(i = 0; i < num_realms; i++) { + char **p; + for(p = bad_realms; *p; p++) + if(strcmp(*p, realms[i]) == 0) { + krb5_set_error_string (context, "no transit through realm %s", + *p); + ret = KRB5KRB_AP_ERR_ILL_CR_TKT; + if(bad_realm) + *bad_realm = i; + break; + } + } + krb5_config_free_strings(bad_realms); + return ret; +} + +#if 0 +int +main(int argc, char **argv) +{ + krb5_data x; + char **r; + int num, i; + x.data = argv[1]; + x.length = strlen(x.data); + if(domain_expand(x, &r, &num, argv[2], argv[3])) + exit(1); + for(i = 0; i < num; i++) + printf("%s\n", r[i]); + return 0; +} +#endif + diff --git a/source4/heimdal/lib/krb5/v4_glue.c b/source4/heimdal/lib/krb5/v4_glue.c new file mode 100644 index 0000000000..c66b06c09f --- /dev/null +++ b/source4/heimdal/lib/krb5/v4_glue.c @@ -0,0 +1,922 @@ +/* + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +RCSID("$Id: v4_glue.c,v 1.2 2005/04/24 13:44:02 lha Exp $"); + +#include "krb5-v4compat.h" + +/* + * + */ + +#define RCHECK(r,func,label) \ + do { (r) = func ; if (r) goto label; } while(0); + + +/* include this here, to avoid dependencies on libkrb */ + +static const int _tkt_lifetimes[TKTLIFENUMFIXED] = { + 38400, 41055, 43894, 46929, 50174, 53643, 57352, 61318, + 65558, 70091, 74937, 80119, 85658, 91581, 97914, 104684, + 111922, 119661, 127935, 136781, 146239, 156350, 167161, 178720, + 191077, 204289, 218415, 233517, 249664, 266926, 285383, 305116, + 326213, 348769, 372885, 398668, 426234, 455705, 487215, 520904, + 556921, 595430, 636601, 680618, 727680, 777995, 831789, 889303, + 950794, 1016537, 1086825, 1161973, 1242318, 1328218, 1420057, 1518247, + 1623226, 1735464, 1855462, 1983758, 2120925, 2267576, 2424367, 2592000 +}; + +int KRB5_LIB_FUNCTION +_krb5_krb_time_to_life(time_t start, time_t end) +{ + int i; + time_t life = end - start; + + if (life > MAXTKTLIFETIME || life <= 0) + return 0; +#if 0 + if (krb_no_long_lifetimes) + return (life + 5*60 - 1)/(5*60); +#endif + + if (end >= NEVERDATE) + return TKTLIFENOEXPIRE; + if (life < _tkt_lifetimes[0]) + return (life + 5*60 - 1)/(5*60); + for (i=0; i TKTLIFEMAXFIXED) + return start + MAXTKTLIFETIME; + return start + _tkt_lifetimes[life - TKTLIFEMINFIXED]; +} + +/* + * Get the name of the krb4 credentials cache, will use `tkfile' as + * the name if that is passed in. `cc' must be free()ed by caller, + */ + +static krb5_error_code +get_krb4_cc_name(const char *tkfile, char **cc) +{ + + *cc = NULL; + if(tkfile == NULL) { + char *path; + if(!issuid()) { + path = getenv("KRBTKFILE"); + if (path) + *cc = strdup(path); + } + if(*cc == NULL) + if (asprintf(cc, "%s%u", TKT_ROOT, (unsigned)getuid()) < 0) + return errno; + } else { + *cc = strdup(tkfile); + if (*cc == NULL) + return ENOMEM; + } + return 0; +} + +/* + * Write a Kerberos 4 ticket file + */ + +#define KRB5_TF_LCK_RETRY_COUNT 50 +#define KRB5_TF_LCK_RETRY 1 + +static krb5_error_code +write_v4_cc(krb5_context context, const char *tkfile, + krb5_storage *sp, int append) +{ + krb5_error_code ret; + struct stat sb; + krb5_data data; + char *path; + int fd, i; + + ret = get_krb4_cc_name(tkfile, &path); + if (ret) { + krb5_set_error_string(context, + "krb5_krb_tf_setup: failed getting " + "the krb4 credentials cache name"); + return ret; + } + + fd = open(path, O_WRONLY|O_CREAT, 0600); + if (fd < 0) { + free(path); + krb5_set_error_string(context, + "krb5_krb_tf_setup: error opening file %s", + path); + return errno; + } + + if (fstat(fd, &sb) != 0 || !S_ISREG(sb.st_mode)) { + free(path); + close(fd); + krb5_set_error_string(context, + "krb5_krb_tf_setup: tktfile %s is not a file", + path); + return KRB5_FCC_PERM; + } + + for (i = 0; i < KRB5_TF_LCK_RETRY_COUNT; i++) { + if (flock(fd, LOCK_EX | LOCK_NB) < 0) { + sleep(KRB5_TF_LCK_RETRY); + } else + break; + } + if (i == KRB5_TF_LCK_RETRY_COUNT) { + free(path); + close(fd); + krb5_set_error_string(context, + "krb5_krb_tf_setup: failed to lock %s", + path); + return KRB5_FCC_PERM; + } + + if (!append) { + ret = ftruncate(fd, 0); + if (ret < 0) { + flock(fd, LOCK_UN); + free(path); + close(fd); + krb5_set_error_string(context, + "krb5_krb_tf_setup: failed to truncate %s", + path); + return KRB5_FCC_PERM; + } + } + ret = lseek(fd, 0L, SEEK_END); + if (ret < 0) { + ret = errno; + flock(fd, LOCK_UN); + free(path); + close(fd); + return ret; + } + + krb5_storage_to_data(sp, &data); + + ret = write(fd, data.data, data.length); + if (ret != data.length) + ret = KRB5_CC_IO; + + krb5_free_data_contents(context, &data); + + flock(fd, LOCK_UN); + free(path); + close(fd); + + return 0; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_tf_setup(krb5_context context, + struct credentials *v4creds, + const char *tkfile, + int append) +{ + krb5_error_code ret; + krb5_storage *sp; + + sp = krb5_storage_emem(); + if (sp == NULL) + return ENOMEM; + + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_HOST); + krb5_storage_set_eof_code(sp, KRB5_CC_IO); + + krb5_clear_error_string(context); + + if (!append) { + RCHECK(ret, krb5_store_stringz(sp, v4creds->pname), error); + RCHECK(ret, krb5_store_stringz(sp, v4creds->pinst), error); + } + + /* cred */ + RCHECK(ret, krb5_store_stringz(sp, v4creds->service), error); + RCHECK(ret, krb5_store_stringz(sp, v4creds->instance), error); + RCHECK(ret, krb5_store_stringz(sp, v4creds->realm), error); + ret = krb5_storage_write(sp, v4creds->session, 8); + if (ret != 8) { + ret = KRB5_CC_IO; + goto error; + } + RCHECK(ret, krb5_store_int32(sp, v4creds->lifetime), error); + RCHECK(ret, krb5_store_int32(sp, v4creds->kvno), error); + RCHECK(ret, krb5_store_int32(sp, v4creds->ticket_st.length), error); + + ret = krb5_storage_write(sp, v4creds->ticket_st.dat, + v4creds->ticket_st.length); + if (ret != v4creds->ticket_st.length) { + ret = KRB5_CC_IO; + goto error; + } + RCHECK(ret, krb5_store_int32(sp, v4creds->issue_date), error); + + ret = write_v4_cc(context, tkfile, sp, append); + + error: + krb5_storage_free(sp); + + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_dest_tkt(krb5_context context, const char *tkfile) +{ + krb5_error_code ret; + char *path; + + ret = get_krb4_cc_name(tkfile, &path); + if (ret) { + krb5_set_error_string(context, + "krb5_krb_tf_setup: failed getting " + "the krb4 credentials cache name"); + return ret; + } + + if (unlink(path) < 0) { + ret = errno; + krb5_set_error_string(context, + "krb5_krb_dest_tkt failed removing the cache " + "with error %s", strerror(ret)); + } + free(path); + + return ret; +} + +/* + * + */ + +static krb5_error_code +decrypt_etext(krb5_context context, const krb5_keyblock *key, + const krb5_data *cdata, krb5_data *data) +{ + krb5_error_code ret; + krb5_crypto crypto; + + ret = krb5_crypto_init(context, key, ETYPE_DES_PCBC_NONE, &crypto); + if (ret) + return ret; + + ret = krb5_decrypt(context, crypto, 0, cdata->data, cdata->length, data); + krb5_crypto_destroy(context, crypto); + + return ret; +} + + +/* + * + */ + +static const char eightzeros[8] = "\x00\x00\x00\x00\x00\x00\x00\x00"; + +static krb5_error_code +storage_to_etext(krb5_context context, + krb5_storage *sp, + const krb5_keyblock *key, + krb5_data *enc_data) +{ + krb5_error_code ret; + krb5_crypto crypto; + krb5_ssize_t size; + krb5_data data; + + /* multiple of eight bytes */ + + size = krb5_storage_seek(sp, 0, SEEK_END); + if (size < 0) + return EINVAL; + size = 8 - (size & 7); + + ret = krb5_storage_write(sp, eightzeros, size); + if (ret != size) + return EINVAL; + + ret = krb5_storage_to_data(sp, &data); + if (ret) + return ret; + + ret = krb5_crypto_init(context, key, ETYPE_DES_PCBC_NONE, &crypto); + if (ret) { + krb5_data_free(&data); + return ret; + } + + ret = krb5_encrypt(context, crypto, 0, data.data, data.length, enc_data); + + krb5_data_free(&data); + krb5_crypto_destroy(context, crypto); + + return ret; +} + +/* + * + */ + +static krb5_error_code +put_nir(krb5_storage *sp, const char *name, + const char *instance, const char *realm) +{ + krb5_error_code ret; + + RCHECK(ret, krb5_store_stringz(sp, name), error); + RCHECK(ret, krb5_store_stringz(sp, instance), error); + if (realm) { + RCHECK(ret, krb5_store_stringz(sp, realm), error); + } + error: + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_create_ticket(krb5_context context, + unsigned char flags, + const char *pname, + const char *pinstance, + const char *prealm, + int32_t paddress, + const krb5_keyblock *session, + int16_t life, + int32_t life_sec, + const char *sname, + const char *sinstance, + const krb5_keyblock *key, + krb5_data *enc_data) +{ + krb5_error_code ret; + krb5_storage *sp; + + krb5_data_zero(enc_data); + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + RCHECK(ret, krb5_store_int8(sp, flags), error); + RCHECK(ret, put_nir(sp, pname, pinstance, prealm), error); + RCHECK(ret, krb5_store_int32(sp, ntohl(paddress)), error); + + /* session key */ + ret = krb5_storage_write(sp, + session->keyvalue.data, + session->keyvalue.length); + if (ret != session->keyvalue.length) { + ret = EINVAL; + goto error; + } + + RCHECK(ret, krb5_store_int8(sp, life), error); + RCHECK(ret, krb5_store_int32(sp, life_sec), error); + RCHECK(ret, put_nir(sp, sname, sinstance, NULL), error); + + ret = storage_to_etext(context, sp, key, enc_data); + + error: + krb5_storage_free(sp); + if (ret) + krb5_set_error_string(context, "Failed to encode kerberos 4 ticket"); + + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_create_ciph(krb5_context context, + const krb5_keyblock *session, + const char *service, + const char *instance, + const char *realm, + u_int32_t life, + unsigned char kvno, + const krb5_data *ticket, + u_int32_t kdc_time, + const krb5_keyblock *key, + krb5_data *enc_data) +{ + krb5_error_code ret; + krb5_storage *sp; + + krb5_data_zero(enc_data); + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + /* session key */ + ret = krb5_storage_write(sp, + session->keyvalue.data, + session->keyvalue.length); + if (ret != session->keyvalue.length) { + ret = EINVAL; + goto error; + } + + RCHECK(ret, put_nir(sp, service, instance, realm), error); + RCHECK(ret, krb5_store_int8(sp, life), error); + RCHECK(ret, krb5_store_int8(sp, kvno), error); + RCHECK(ret, krb5_store_int8(sp, ticket->length), error); + ret = krb5_storage_write(sp, ticket->data, ticket->length); + if (ret != ticket->length) { + ret = EINVAL; + goto error; + } + RCHECK(ret, krb5_store_int32(sp, kdc_time), error); + + ret = storage_to_etext(context, sp, key, enc_data); + + error: + krb5_storage_free(sp); + if (ret) + krb5_set_error_string(context, "Failed to encode kerberos 4 ticket"); + + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_create_auth_reply(krb5_context context, + const char *pname, + const char *pinst, + const char *prealm, + int32_t time_ws, + int n, + u_int32_t x_date, + unsigned char kvno, + const krb5_data *cipher, + krb5_data *data) +{ + krb5_error_code ret; + krb5_storage *sp; + + krb5_data_zero(data); + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + RCHECK(ret, krb5_store_int8(sp, KRB_PROT_VERSION), error); + RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_KDC_REPLY), error); + RCHECK(ret, put_nir(sp, pname, pinst, prealm), error); + RCHECK(ret, krb5_store_int32(sp, time_ws), error); + RCHECK(ret, krb5_store_int8(sp, n), error); + RCHECK(ret, krb5_store_int32(sp, x_date), error); + RCHECK(ret, krb5_store_int8(sp, kvno), error); + RCHECK(ret, krb5_store_int16(sp, cipher->length), error); + ret = krb5_storage_write(sp, cipher->data, cipher->length); + if (ret != cipher->length) { + ret = EINVAL; + goto error; + } + + ret = krb5_storage_to_data(sp, data); + + error: + krb5_storage_free(sp); + if (ret) + krb5_set_error_string(context, "Failed to encode kerberos 4 ticket"); + + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_cr_err_reply(krb5_context context, + const char *name, + const char *inst, + const char *realm, + u_int32_t time_ws, + u_int32_t e, + const char *e_string, + krb5_data *data) +{ + krb5_error_code ret; + krb5_storage *sp; + + krb5_data_zero(data); + + if (name == NULL) name = ""; + if (inst == NULL) inst = ""; + if (realm == NULL) realm = ""; + if (e_string == NULL) e_string = ""; + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + RCHECK(ret, krb5_store_int8(sp, KRB_PROT_VERSION), error); + RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_ERR_REPLY), error); + RCHECK(ret, put_nir(sp, name, inst, realm), error); + RCHECK(ret, krb5_store_int32(sp, time_ws), error); + RCHECK(ret, krb5_store_int32(sp, e), error); + RCHECK(ret, krb5_store_stringz(sp, e_string), error); + + ret = krb5_storage_to_data(sp, data); + + error: + krb5_storage_free(sp); + if (ret) + krb5_set_error_string(context, "Failed to encode kerberos 4 error"); + + return 0; +} + +static krb5_error_code +get_v4_stringz(krb5_storage *sp, char **str, size_t max_len) +{ + krb5_error_code ret; + + ret = krb5_ret_stringz(sp, str); + if (ret) + return ret; + if (strlen(*str) > max_len) { + free(*str); + *str = NULL; + return EINVAL; + } + return 0; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_decomp_ticket(krb5_context context, + const krb5_data *enc_ticket, + const krb5_keyblock *key, + const char *local_realm, + char **sname, + char **sinstance, + struct _krb5_krb_auth_data *ad) +{ + krb5_error_code ret; + krb5_ssize_t size; + krb5_storage *sp = NULL; + krb5_data ticket; + unsigned char des_key[8]; + + memset(ad, 0, sizeof(*ad)); + krb5_data_zero(&ticket); + + *sname = NULL; + *sinstance = NULL; + + RCHECK(ret, decrypt_etext(context, key, enc_ticket, &ticket), error); + + sp = krb5_storage_from_data(&ticket); + if (sp == NULL) { + krb5_data_free(&ticket); + krb5_set_error_string(context, "alloc: out of memory"); + return ENOMEM; + } + + krb5_storage_set_eof_code(sp, EINVAL); /* XXX */ + + RCHECK(ret, krb5_ret_int8(sp, &ad->k_flags), error); + RCHECK(ret, get_v4_stringz(sp, &ad->pname, ANAME_SZ), error); + RCHECK(ret, get_v4_stringz(sp, &ad->pinst, INST_SZ), error); + RCHECK(ret, get_v4_stringz(sp, &ad->prealm, REALM_SZ), error); + RCHECK(ret, krb5_ret_int32(sp, &ad->address), error); + + size = krb5_storage_read(sp, des_key, sizeof(des_key)); + if (size != sizeof(des_key)) { + ret = EINVAL; /* XXX */ + goto error; + } + + RCHECK(ret, krb5_ret_int8(sp, &ad->life), error); + + if (ad->k_flags & 1) + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); + else + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + RCHECK(ret, krb5_ret_int32(sp, &ad->time_sec), error); + + RCHECK(ret, get_v4_stringz(sp, sname, ANAME_SZ), error); + RCHECK(ret, get_v4_stringz(sp, sinstance, INST_SZ), error); + + ret = krb5_keyblock_init(context, ETYPE_DES_PCBC_NONE, + des_key, sizeof(des_key), &ad->session); + if (ret) + goto error; + + if (strlen(ad->prealm) == 0) { + free(ad->prealm); + ad->prealm = strdup(local_realm); + if (ad->prealm == NULL) { + ret = ENOMEM; + goto error; + } + } + + error: + memset(des_key, 0, sizeof(des_key)); + if (sp) + krb5_storage_free(sp); + krb5_data_free(&ticket); + if (ret) { + if (*sname) { + free(*sname); + *sname = NULL; + } + if (*sinstance) { + free(*sinstance); + *sinstance = NULL; + } + _krb5_krb_free_auth_data(context, ad); + krb5_set_error_string(context, "Failed to decode v4 ticket"); + } + return ret; +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_krb_rd_req(krb5_context context, + krb5_data *authent, + const char *service, + const char *instance, + const char *local_realm, + int32_t from_addr, + const krb5_keyblock *key, + struct _krb5_krb_auth_data *ad) +{ + krb5_error_code ret; + krb5_storage *sp; + krb5_data ticket, eaut, aut; + krb5_ssize_t size; + int little_endian; + int8_t pvno; + int8_t type; + int8_t s_kvno; + u_int8_t ticket_length; + u_int8_t eaut_length; + u_int8_t time_5ms; + char *realm = NULL; + char *sname = NULL; + char *sinstance = NULL; + char *r_realm = NULL; + char *r_name = NULL; + char *r_instance = NULL; + + u_int32_t r_time_sec; /* Coarse time from authenticator */ + unsigned long delta_t; /* Time in authenticator - local time */ + long tkt_age; /* Age of ticket */ + + struct timeval tv; + + krb5_data_zero(&ticket); + krb5_data_zero(&eaut); + krb5_data_zero(&aut); + + sp = krb5_storage_from_data(authent); + if (sp == NULL) { + krb5_set_error_string(context, "alloc: out of memory"); + return ENOMEM; + } + + krb5_storage_set_eof_code(sp, EINVAL); /* XXX */ + + ret = krb5_ret_int8(sp, &pvno); + if (ret) + goto error; + + if (pvno != KRB_PROT_VERSION) { + ret = EINVAL; /* XXX */ + goto error; + } + + ret = krb5_ret_int8(sp, &type); + if (ret) + goto error; + + little_endian = type & 1; + type &= ~1; + + if(type != AUTH_MSG_APPL_REQUEST && type != AUTH_MSG_APPL_REQUEST_MUTUAL) { + ret = EINVAL; /* RD_AP_MSG_TYPE */ + goto error; + } + + RCHECK(ret, krb5_ret_int8(sp, &s_kvno), error); + RCHECK(ret, get_v4_stringz(sp, &realm, REALM_SZ), error); + RCHECK(ret, krb5_ret_int8(sp, &ticket_length), error); + RCHECK(ret, krb5_ret_int8(sp, &eaut_length), error); + RCHECK(ret, krb5_data_alloc(&ticket, ticket_length), error); + + size = krb5_storage_read(sp, ticket.data, ticket.length); + if (size != ticket.length) { + ret = EINVAL; + goto error; + } + + /* Decrypt and take apart ticket */ + ret = _krb5_krb_decomp_ticket(context, &ticket, key, local_realm, + &sname, &sinstance, ad); + if (ret) + goto error; + + RCHECK(ret, krb5_data_alloc(&eaut, eaut_length), error); + + size = krb5_storage_read(sp, eaut.data, eaut.length); + if (size != eaut.length) { + ret = EINVAL; + goto error; + } + + krb5_storage_free(sp); + sp = NULL; + + ret = decrypt_etext(context, &ad->session, &eaut, &aut); + if (ret) + goto error; + + sp = krb5_storage_from_data(&aut); + if (sp == NULL) { + krb5_set_error_string(context, "alloc: out of memory"); + ret = ENOMEM; + goto error; + } + + if (little_endian) + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); + else + krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); + + RCHECK(ret, get_v4_stringz(sp, &r_name, ANAME_SZ), error); + RCHECK(ret, get_v4_stringz(sp, &r_instance, INST_SZ), error); + RCHECK(ret, get_v4_stringz(sp, &r_realm, REALM_SZ), error); + + RCHECK(ret, krb5_ret_int32(sp, &ad->checksum), error); + RCHECK(ret, krb5_ret_int8(sp, &time_5ms), error); + RCHECK(ret, krb5_ret_int32(sp, &r_time_sec), error); + + if (strcmp(ad->pname, r_name) != 0 || + strcmp(ad->pinst, r_instance) != 0 || + strcmp(ad->prealm, r_realm) != 0) { + ret = EINVAL; /* RD_AP_INCON */ + goto error; + } + + if (from_addr && from_addr == ad->address) { + ret = EINVAL; /* RD_AP_BADD */ + goto error; + } + + gettimeofday(&tv, NULL); + delta_t = abs((int)(tv.tv_sec - r_time_sec)); + if (delta_t > CLOCK_SKEW) { + ret = EINVAL; /* RD_AP_TIME */ + goto error; + } + + /* Now check for expiration of ticket */ + + tkt_age = tv.tv_sec - ad->time_sec; + + if ((tkt_age < 0) && (-tkt_age > CLOCK_SKEW)) { + ret = EINVAL; /* RD_AP_NYV */ + goto error; + } + + if (tv.tv_sec > _krb5_krb_life_to_time(ad->time_sec, ad->life)) { + ret = EINVAL; /* RD_AP_EXP */ + goto error; + } + + ret = 0; + error: + krb5_data_free(&ticket); + krb5_data_free(&eaut); + krb5_data_free(&aut); + if (realm) + free(realm); + if (sname) + free(sname); + if (sinstance) + free(sinstance); + if (r_name) + free(r_name); + if (r_instance) + free(r_instance); + if (r_realm) + free(r_realm); + if (sp) + krb5_storage_free(sp); + + if (ret) + krb5_clear_error_string(context); + + return ret; +} + +/* + * + */ + +void KRB5_LIB_FUNCTION +_krb5_krb_free_auth_data(krb5_context context, struct _krb5_krb_auth_data *ad) +{ + if (ad->pname) + free(ad->pname); + if (ad->pinst) + free(ad->pinst); + if (ad->prealm) + free(ad->prealm); + krb5_free_keyblock_contents(context, &ad->session); + memset(ad, 0, sizeof(*ad)); +} diff --git a/source4/heimdal/lib/krb5/version.c b/source4/heimdal/lib/krb5/version.c new file mode 100644 index 0000000000..5f0fd6680b --- /dev/null +++ b/source4/heimdal/lib/krb5/version.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: version.c,v 1.3 1999/12/02 17:05:13 joda Exp $"); + +/* this is just to get a version stamp in the library file */ + +#define heimdal_version __heimdal_version +#define heimdal_long_version __heimdal_long_version +#include "version.h" + diff --git a/source4/heimdal/lib/krb5/warn.c b/source4/heimdal/lib/krb5/warn.c new file mode 100644 index 0000000000..f9825914ee --- /dev/null +++ b/source4/heimdal/lib/krb5/warn.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +#include + +RCSID("$Id: warn.c,v 1.15 2004/05/25 21:46:26 lha Exp $"); + +static krb5_error_code _warnerr(krb5_context context, int do_errtext, + krb5_error_code code, int level, const char *fmt, va_list ap) + __attribute__((__format__(__printf__, 5, 0))); + +static krb5_error_code +_warnerr(krb5_context context, int do_errtext, + krb5_error_code code, int level, const char *fmt, va_list ap) +{ + char xfmt[7] = ""; + const char *args[2], **arg; + char *msg = NULL; + char *err_str = NULL; + + args[0] = args[1] = NULL; + arg = args; + if(fmt){ + strlcat(xfmt, "%s", sizeof(xfmt)); + if(do_errtext) + strlcat(xfmt, ": ", sizeof(xfmt)); + vasprintf(&msg, fmt, ap); + if(msg == NULL) + return ENOMEM; + *arg++ = msg; + } + if(context && do_errtext){ + const char *err_msg; + + strlcat(xfmt, "%s", sizeof(xfmt)); + + err_str = krb5_get_error_string(context); + if (err_str != NULL) { + *arg++ = err_str; + } else { + err_msg = krb5_get_err_text(context, code); + if (err_msg) + *arg++ = err_msg; + else + *arg++ = ""; + } + } + + if(context && context->warn_dest) + krb5_log(context, context->warn_dest, level, xfmt, args[0], args[1]); + else + warnx(xfmt, args[0], args[1]); + free(msg); + free(err_str); + return 0; +} + +#define FUNC(ETEXT, CODE, LEVEL) \ + krb5_error_code ret; \ + va_list ap; \ + va_start(ap, fmt); \ + ret = _warnerr(context, ETEXT, CODE, LEVEL, fmt, ap); \ + va_end(ap); + +#undef __attribute__ +#define __attribute__(X) + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vwarn(krb5_context context, krb5_error_code code, + const char *fmt, va_list ap) + __attribute__ ((format (printf, 3, 0))) +{ + return _warnerr(context, 1, code, 1, fmt, ap); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_warn(krb5_context context, krb5_error_code code, const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))) +{ + FUNC(1, code, 1); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vwarnx(krb5_context context, const char *fmt, va_list ap) + __attribute__ ((format (printf, 2, 0))) +{ + return _warnerr(context, 0, 0, 1, fmt, ap); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_warnx(krb5_context context, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))) +{ + FUNC(0, 0, 1); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verr(krb5_context context, int eval, krb5_error_code code, + const char *fmt, va_list ap) + __attribute__ ((noreturn, format (printf, 4, 0))) +{ + _warnerr(context, 1, code, 0, fmt, ap); + exit(eval); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_err(krb5_context context, int eval, krb5_error_code code, + const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 4, 5))) +{ + FUNC(1, code, 0); + exit(eval); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_verrx(krb5_context context, int eval, const char *fmt, va_list ap) + __attribute__ ((noreturn, format (printf, 3, 0))) +{ + _warnerr(context, 0, 0, 0, fmt, ap); + exit(eval); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_errx(krb5_context context, int eval, const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 3, 4))) +{ + FUNC(0, 0, 0); + exit(eval); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vabort(krb5_context context, krb5_error_code code, + const char *fmt, va_list ap) + __attribute__ ((noreturn, format (printf, 3, 0))) +{ + _warnerr(context, 1, code, 0, fmt, ap); + abort(); +} + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_abort(krb5_context context, krb5_error_code code, const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 3, 4))) +{ + FUNC(1, code, 0); + abort(); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vabortx(krb5_context context, const char *fmt, va_list ap) + __attribute__ ((noreturn, format (printf, 2, 0))) +{ + _warnerr(context, 0, 0, 0, fmt, ap); + abort(); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_abortx(krb5_context context, const char *fmt, ...) + __attribute__ ((noreturn, format (printf, 2, 3))) +{ + FUNC(0, 0, 0); + abort(); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_warn_dest(krb5_context context, krb5_log_facility *fac) +{ + context->warn_dest = fac; + return 0; +} -- cgit From 8c018ff786952424a2f1c612046eb91d2e42f648 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Jul 2005 03:52:31 +0000 Subject: r8310: replace the heimdal networking interface scanning code with glue code that uses the Samba interfaces list. This makes heimdal obey the 'interfaces=' smb.conf option, and should also fix the portability problems with the heimdal code (This used to be commit ba621d1c554e135f449a144019b84719a086e04f) --- source4/heimdal/lib/krb5/get_addrs.c | 291 ----------------------------------- 1 file changed, 291 deletions(-) delete mode 100644 source4/heimdal/lib/krb5/get_addrs.c (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/get_addrs.c b/source4/heimdal/lib/krb5/get_addrs.c deleted file mode 100644 index 034516d7d4..0000000000 --- a/source4/heimdal/lib/krb5/get_addrs.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. - */ - -#include "krb5_locl.h" - -RCSID("$Id: get_addrs.c,v 1.46 2004/05/25 21:26:05 lha Exp $"); - -#ifdef __osf__ -/* hate */ -struct rtentry; -struct mbuf; -#endif -#ifdef HAVE_NET_IF_H -#include -#endif -#include - -static krb5_error_code -gethostname_fallback (krb5_context context, krb5_addresses *res) -{ - krb5_error_code ret; - char hostname[MAXHOSTNAMELEN]; - struct hostent *hostent; - - if (gethostname (hostname, sizeof(hostname))) { - ret = errno; - krb5_set_error_string (context, "gethostname: %s", strerror(ret)); - return ret; - } - hostent = roken_gethostbyname (hostname); - if (hostent == NULL) { - ret = errno; - krb5_set_error_string (context, "gethostbyname %s: %s", - hostname, strerror(ret)); - return ret; - } - res->len = 1; - res->val = malloc (sizeof(*res->val)); - if (res->val == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - res->val[0].addr_type = hostent->h_addrtype; - res->val[0].address.data = NULL; - res->val[0].address.length = 0; - ret = krb5_data_copy (&res->val[0].address, - hostent->h_addr, - hostent->h_length); - if (ret) { - free (res->val); - return ret; - } - return 0; -} - -enum { - LOOP = 1, /* do include loopback interfaces */ - LOOP_IF_NONE = 2, /* include loopback if no other if's */ - EXTRA_ADDRESSES = 4, /* include extra addresses */ - SCAN_INTERFACES = 8 /* scan interfaces for addresses */ -}; - -/* - * Try to figure out the addresses of all configured interfaces with a - * lot of magic ioctls. - */ - -static krb5_error_code -find_all_addresses (krb5_context context, krb5_addresses *res, int flags) -{ - struct sockaddr sa_zero; - struct ifaddrs *ifa0, *ifa; - krb5_error_code ret = ENXIO; - int num, idx; - krb5_addresses ignore_addresses; - - res->val = NULL; - - if (getifaddrs(&ifa0) == -1) { - ret = errno; - krb5_set_error_string(context, "getifaddrs: %s", strerror(ret)); - return (ret); - } - - memset(&sa_zero, 0, sizeof(sa_zero)); - - /* First, count all the ifaddrs. */ - for (ifa = ifa0, num = 0; ifa != NULL; ifa = ifa->ifa_next, num++) - /* nothing */; - - if (num == 0) { - freeifaddrs(ifa0); - krb5_set_error_string(context, "no addresses found"); - return (ENXIO); - } - - if (flags & EXTRA_ADDRESSES) { - /* we'll remove the addresses we don't care about */ - ret = krb5_get_ignore_addresses(context, &ignore_addresses); - if(ret) - return ret; - } - - /* Allocate storage for them. */ - res->val = calloc(num, sizeof(*res->val)); - if (res->val == NULL) { - krb5_free_addresses(context, &ignore_addresses); - freeifaddrs(ifa0); - krb5_set_error_string (context, "malloc: out of memory"); - return (ENOMEM); - } - - /* Now traverse the list. */ - for (ifa = ifa0, idx = 0; ifa != NULL; ifa = ifa->ifa_next) { - if ((ifa->ifa_flags & IFF_UP) == 0) - continue; - if (ifa->ifa_addr == NULL) - continue; - if (memcmp(ifa->ifa_addr, &sa_zero, sizeof(sa_zero)) == 0) - continue; - if (krb5_sockaddr_uninteresting(ifa->ifa_addr)) - continue; - if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) { - /* We'll deal with the LOOP_IF_NONE case later. */ - if ((flags & LOOP) == 0) - continue; - } - - ret = krb5_sockaddr2address(context, ifa->ifa_addr, &res->val[idx]); - if (ret) { - /* - * The most likely error here is going to be "Program - * lacks support for address type". This is no big - * deal -- just continue, and we'll listen on the - * addresses who's type we *do* support. - */ - continue; - } - /* possibly skip this address? */ - if((flags & EXTRA_ADDRESSES) && - krb5_address_search(context, &res->val[idx], &ignore_addresses)) { - krb5_free_address(context, &res->val[idx]); - flags &= ~LOOP_IF_NONE; /* we actually found an address, - so don't add any loop-back - addresses */ - continue; - } - - idx++; - } - - /* - * If no addresses were found, and LOOP_IF_NONE is set, then find - * the loopback addresses and add them to our list. - */ - if ((flags & LOOP_IF_NONE) != 0 && idx == 0) { - for (ifa = ifa0; ifa != NULL; ifa = ifa->ifa_next) { - if ((ifa->ifa_flags & IFF_UP) == 0) - continue; - if (ifa->ifa_addr == NULL) - continue; - if (memcmp(ifa->ifa_addr, &sa_zero, sizeof(sa_zero)) == 0) - continue; - if (krb5_sockaddr_uninteresting(ifa->ifa_addr)) - continue; - - if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) { - ret = krb5_sockaddr2address(context, - ifa->ifa_addr, &res->val[idx]); - if (ret) { - /* - * See comment above. - */ - continue; - } - if((flags & EXTRA_ADDRESSES) && - krb5_address_search(context, &res->val[idx], - &ignore_addresses)) { - krb5_free_address(context, &res->val[idx]); - continue; - } - idx++; - } - } - } - - if (flags & EXTRA_ADDRESSES) - krb5_free_addresses(context, &ignore_addresses); - freeifaddrs(ifa0); - if (ret) - free(res->val); - else - res->len = idx; /* Now a count. */ - return (ret); -} - -static krb5_error_code -get_addrs_int (krb5_context context, krb5_addresses *res, int flags) -{ - krb5_error_code ret = -1; - - if (flags & SCAN_INTERFACES) { - ret = find_all_addresses (context, res, flags); - if(ret || res->len == 0) - ret = gethostname_fallback (context, res); - } else { - res->len = 0; - res->val = NULL; - ret = 0; - } - - if(ret == 0 && (flags & EXTRA_ADDRESSES)) { - krb5_addresses a; - /* append user specified addresses */ - ret = krb5_get_extra_addresses(context, &a); - if(ret) { - krb5_free_addresses(context, res); - return ret; - } - ret = krb5_append_addresses(context, res, &a); - if(ret) { - krb5_free_addresses(context, res); - return ret; - } - krb5_free_addresses(context, &a); - } - if(res->len == 0) { - free(res->val); - res->val = NULL; - } - return ret; -} - -/* - * Try to get all addresses, but return the one corresponding to - * `hostname' if we fail. - * - * Only include loopback address if there are no other. - */ - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_all_client_addrs (krb5_context context, krb5_addresses *res) -{ - int flags = LOOP_IF_NONE | EXTRA_ADDRESSES; - - if (context->scan_interfaces) - flags |= SCAN_INTERFACES; - - return get_addrs_int (context, res, flags); -} - -/* - * Try to get all local addresses that a server should listen to. - * If that fails, we return the address corresponding to `hostname'. - */ - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_all_server_addrs (krb5_context context, krb5_addresses *res) -{ - return get_addrs_int (context, res, LOOP | SCAN_INTERFACES); -} -- cgit From c0e8144c5d1e402b36ebe04b843eba62e7ab9958 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 9 Aug 2005 03:04:47 +0000 Subject: r9221: Try to merge Heimdal across from lorikeet-heimdal to samba4. This is my first attempt at this, so there may be a few rough edges. Andrew Bartlett (This used to be commit 9a1d2f2fec67930975da856a2d365345cec46216) --- source4/heimdal/lib/krb5/crypto.c | 88 +++++++++-- source4/heimdal/lib/krb5/get_cred.c | 6 +- source4/heimdal/lib/krb5/keytab.c | 14 +- source4/heimdal/lib/krb5/keytab_file.c | 10 +- source4/heimdal/lib/krb5/krb5-private.h | 15 +- source4/heimdal/lib/krb5/krb5-protos.h | 6 +- source4/heimdal/lib/krb5/krb5.h | 52 +++---- source4/heimdal/lib/krb5/pkinit.c | 188 +++++++++++++----------- source4/heimdal/lib/krb5/principal.c | 18 +-- source4/heimdal/lib/krb5/rd_cred.c | 9 +- source4/heimdal/lib/krb5/test_crypto_wrapping.c | 163 ++++++++++++++++++++ source4/heimdal/lib/krb5/test_pkinit_dh2key.c | 110 ++++++++++++++ 12 files changed, 518 insertions(+), 161 deletions(-) create mode 100644 source4/heimdal/lib/krb5/test_crypto_wrapping.c create mode 100644 source4/heimdal/lib/krb5/test_pkinit_dh2key.c (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 2b1ac3a5c4..c8fa556696 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.123 2005/06/29 22:20:33 lha Exp $"); +RCSID("$Id: crypto.c,v 1.128 2005/07/20 07:22:43 lha Exp $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -2124,7 +2124,8 @@ verify_checksum(krb5_context context, return KRB5_PROG_SUMTYPE_NOSUPP; } if(ct->checksumsize != cksum->checksum.length) { - krb5_clear_error_string (context); + krb5_set_error_string (context, "checksum length was %d, but should be %d for checksum type %s", + cksum->checksum.length, ct->checksumsize, ct->name); return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */ } keyed_checksum = (ct->flags & F_KEYED) != 0; @@ -2145,8 +2146,11 @@ verify_checksum(krb5_context context, (*ct->checksum)(context, dkey, data, len, usage, &c); - if(c.checksum.length != cksum->checksum.length || - memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) { + if(c.checksum.length != cksum->checksum.length) { + krb5_set_error_string (context, "(INTERNAL ERROR) our checksum length was %d, but should be %d for checksum type %s", + c.checksum.length, ct->checksumsize, ct->name); + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } else if (memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) { krb5_clear_error_string (context); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; } else { @@ -3246,7 +3250,7 @@ static krb5_error_code encrypt_internal_derived(krb5_context context, krb5_crypto crypto, unsigned usage, - void *data, + const void *data, size_t len, krb5_data *result, void *ivec) @@ -3315,7 +3319,7 @@ encrypt_internal_derived(krb5_context context, static krb5_error_code encrypt_internal(krb5_context context, krb5_crypto crypto, - void *data, + const void *data, size_t len, krb5_data *result, void *ivec) @@ -3395,7 +3399,7 @@ static krb5_error_code encrypt_internal_special(krb5_context context, krb5_crypto crypto, int usage, - void *data, + const void *data, size_t len, krb5_data *result, void *ivec) @@ -3624,7 +3628,7 @@ krb5_error_code KRB5_LIB_FUNCTION krb5_encrypt_ivec(krb5_context context, krb5_crypto crypto, unsigned usage, - void *data, + const void *data, size_t len, krb5_data *result, void *ivec) @@ -3643,7 +3647,7 @@ krb5_error_code KRB5_LIB_FUNCTION krb5_encrypt(krb5_context context, krb5_crypto crypto, unsigned usage, - void *data, + const void *data, size_t len, krb5_data *result) { @@ -4228,14 +4232,9 @@ wrapped_length (krb5_context context, { struct encryption_type *et = crypto->et; size_t padsize = et->padsize; - size_t checksumsize; + size_t checksumsize = CHECKSUMSIZE(et->checksum); size_t res; - if (et->keyed_checksum) - checksumsize = et->keyed_checksum->checksumsize; - else - checksumsize = et->checksum->checksumsize; - res = et->confoundersize + checksumsize + data_len; res = (res + padsize - 1) / padsize * padsize; return res; @@ -4306,6 +4305,65 @@ krb5_random_to_key(krb5_context context, return 0; } +krb5_error_code +_krb5_pk_octetstring2key(krb5_context context, + krb5_enctype type, + const void *dhdata, + size_t dhsize, + const heim_octet_string *c_n, + const heim_octet_string *k_n, + krb5_keyblock *key) +{ + struct encryption_type *et = _find_enctype(type); + krb5_error_code ret; + size_t keylen, offset; + void *keydata; + unsigned char counter; + unsigned char shaoutput[20]; + + if(et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + type); + return KRB5_PROG_ETYPE_NOSUPP; + } + keylen = (et->keytype->bits + 7) / 8; + + keydata = malloc(keylen); + if (keydata == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + counter = 0; + offset = 0; + do { + SHA_CTX m; + + SHA1_Init(&m); + SHA1_Update(&m, &counter, 1); + SHA1_Update(&m, dhdata, dhsize); + if (c_n) + SHA1_Update(&m, c_n->data, c_n->length); + if (k_n) + SHA1_Update(&m, k_n->data, k_n->length); + SHA1_Final(shaoutput, &m); + + memcpy((unsigned char *)keydata + offset, + shaoutput, + min(keylen - offset, sizeof(shaoutput))); + + offset += sizeof(shaoutput); + counter++; + } while(offset < keylen); + memset(shaoutput, 0, sizeof(shaoutput)); + + ret = krb5_random_to_key(context, type, keydata, keylen, key); + memset(keydata, 0, sizeof(keylen)); + free(keydata); + return ret; +} + + #ifdef CRYPTO_DEBUG static krb5_error_code diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 63fb55608c..7043b8ae51 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_cred.c,v 1.107 2005/06/16 22:57:14 lha Exp $"); +RCSID("$Id: get_cred.c,v 1.108 2005/07/13 07:38:02 lha Exp $"); /* * Take the `body' and encode it into `padata' using the credentials @@ -837,10 +837,6 @@ krb5_get_credentials_with_flags(krb5_context context, if (in_creds->session.keytype) options |= KRB5_TC_MATCH_KEYTYPE; - ret = krb5_cc_retrieve_cred(context, - ccache, - options, - in_creds, res_creds); /* * If we got a credential, check if credential is expired before * returning it. diff --git a/source4/heimdal/lib/krb5/keytab.c b/source4/heimdal/lib/krb5/keytab.c index a405664122..23f6685049 100644 --- a/source4/heimdal/lib/krb5/keytab.c +++ b/source4/heimdal/lib/krb5/keytab.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab.c,v 1.60 2005/05/19 14:04:45 lha Exp $"); +RCSID("$Id: keytab.c,v 1.62 2005/07/06 01:14:42 lha Exp $"); /* * Register a new keytab in `ops' @@ -240,8 +240,8 @@ krb5_kt_get_name(krb5_context context, } /* - * Finish using the keytab in `id'. All resources will be released. - * Return 0 or an error. + * Finish using the keytab in `id'. All resources will be released, + * even on errors. Return 0 or an error. */ krb5_error_code KRB5_LIB_FUNCTION @@ -251,8 +251,8 @@ krb5_kt_close(krb5_context context, krb5_error_code ret; ret = (*id->close)(context, id); - if(ret == 0) - free(id); + memset(id, 0, sizeof(*id)); + free(id); return ret; } @@ -302,8 +302,10 @@ krb5_kt_get_entry(krb5_context context, return (*id->get)(context, id, principal, kvno, enctype, entry); ret = krb5_kt_start_seq_get (context, id, &cursor); - if (ret) + if (ret) { + krb5_clear_error_string(context); return KRB5_KT_NOTFOUND; /* XXX i.e. file not found */ + } entry->vno = 0; while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) { diff --git a/source4/heimdal/lib/krb5/keytab_file.c b/source4/heimdal/lib/krb5/keytab_file.c index dca09ff6f3..6ff2680ed1 100644 --- a/source4/heimdal/lib/krb5/keytab_file.c +++ b/source4/heimdal/lib/krb5/keytab_file.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_file.c,v 1.18 2005/05/31 21:50:43 lha Exp $"); +RCSID("$Id: keytab_file.c,v 1.20 2005/07/13 06:08:07 lha Exp $"); #define KRB5_KT_VNO_1 1 #define KRB5_KT_VNO_2 2 @@ -332,6 +332,12 @@ fkt_start_seq_get_int(krb5_context context, return ret; } c->sp = krb5_storage_from_fd(c->fd); + if (c->sp == NULL) { + _krb5_xunlock(context, c->fd); + close(c->fd); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } krb5_storage_set_eof_code(c->sp, KRB5_KT_END); ret = krb5_ret_int8(c->sp, &pvno); if(ret) { diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index e59cab8ca7..b877de8cf2 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -329,6 +329,14 @@ _krb5_put_int ( unsigned long /*value*/, size_t /*size*/); +krb5_error_code KRB5_LIB_FUNCTION +_krb5_rd_rep_type ( + krb5_context /*context*/, + krb5_auth_context /*auth_context*/, + const krb5_data */*inbuf*/, + krb5_ap_rep_enc_part **/*repl*/, + krb5_boolean /*dce_style_response*/); + int _krb5_send_and_recv_tcp ( int /*fd*/, @@ -348,11 +356,4 @@ _krb5_xunlock ( krb5_context /*context*/, int /*fd*/); -krb5_error_code KRB5_LIB_FUNCTION -_krb5_rd_rep_type(krb5_context context, - krb5_auth_context auth_context, - const krb5_data *inbuf, - krb5_ap_rep_enc_part **repl, - krb5_boolean dce_style_response); - #endif /* __krb5_private_h__ */ diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index cee8a02419..f306bf949f 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -1305,7 +1305,7 @@ krb5_encrypt ( krb5_context /*context*/, krb5_crypto /*crypto*/, unsigned /*usage*/, - void */*data*/, + const void */*data*/, size_t /*len*/, krb5_data */*result*/); @@ -1324,7 +1324,7 @@ krb5_encrypt_ivec ( krb5_context /*context*/, krb5_crypto /*crypto*/, unsigned /*usage*/, - void */*data*/, + const void */*data*/, size_t /*len*/, krb5_data */*result*/, void */*ivec*/); @@ -2424,7 +2424,7 @@ krb5_principal_get_comp_string ( const char* KRB5_LIB_FUNCTION krb5_principal_get_realm ( krb5_context /*context*/, - krb5_const_principal /*principal*/); + krb5_principal /*principal*/); int KRB5_LIB_FUNCTION krb5_principal_get_type ( diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 890a500caa..5789bff205 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h,v 1.236 2005/06/11 00:05:24 lha Exp $ */ +/* $Id: krb5.h,v 1.237 2005/07/09 14:47:21 lha Exp $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -567,8 +567,8 @@ typedef struct krb5_auth_context_data { krb5_rcache rcache; - krb5_keytype keytype; /* ¿requested key type ? */ - krb5_cksumtype cksumtype; /* ¡requested checksum type! */ + krb5_keytype keytype; /* ¿requested key type ? */ + krb5_cksumtype cksumtype; /* ¡requested checksum type! */ }krb5_auth_context_data, *krb5_auth_context; @@ -617,28 +617,28 @@ typedef struct _krb5_prompt { krb5_prompt_type type; } krb5_prompt; -typedef int (*krb5_prompter_fct)(krb5_context context, - void *data, - const char *name, - const char *banner, - int num_prompts, - krb5_prompt prompts[]); -typedef krb5_error_code (*krb5_key_proc)(krb5_context context, - krb5_enctype type, - krb5_salt salt, - krb5_const_pointer keyseed, - krb5_keyblock **key); -typedef krb5_error_code (*krb5_decrypt_proc)(krb5_context context, - krb5_keyblock *key, - krb5_key_usage usage, - krb5_const_pointer decrypt_arg, - krb5_kdc_rep *dec_rep); -typedef krb5_error_code (*krb5_s2k_proc)(krb5_context context, - krb5_enctype type, - krb5_const_pointer keyseed, - krb5_salt salt, - krb5_data *s2kparms, - krb5_keyblock **key); +typedef int (*krb5_prompter_fct)(krb5_context /*context*/, + void * /*data*/, + const char * /*name*/, + const char * /*banner*/, + int /*num_prompts*/, + krb5_prompt /*prompts*/[]); +typedef krb5_error_code (*krb5_key_proc)(krb5_context /*context*/, + krb5_enctype /*type*/, + krb5_salt /*salt*/, + krb5_const_pointer /*keyseed*/, + krb5_keyblock ** /*key*/); +typedef krb5_error_code (*krb5_decrypt_proc)(krb5_context /*context*/, + krb5_keyblock * /*key*/, + krb5_key_usage /*usage*/, + krb5_const_pointer /*decrypt_arg*/, + krb5_kdc_rep * /*dec_rep*/); +typedef krb5_error_code (*krb5_s2k_proc)(krb5_context /*context*/, + krb5_enctype /*type*/, + krb5_const_pointer /*keyseed*/, + krb5_salt /*salt*/, + krb5_data * /*s2kparms*/, + krb5_keyblock ** /*key*/); struct _krb5_get_init_creds_opt_private; diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 84db4fe544..35a751c291 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.55 2005/05/19 18:49:05 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.58 2005/07/23 10:42:01 lha Exp $"); #ifdef PKINIT @@ -407,34 +407,25 @@ _krb5_pk_create_sign(krb5_context context, goto out; } - sd.certificates->data = NULL; - sd.certificates->length = 0; + i = sk_X509_num(id->cert); + sd.certificates->val = malloc(sizeof(sd.certificates->val[0]) * i); + if (sd.certificates->val == NULL) { + krb5_clear_error_string(context); + ret = ENOMEM; + goto out; + } + sd.certificates->len = i; for (i = 0; i < sk_X509_num(id->cert); i++) { - void *data; - OPENSSL_ASN1_MALLOC_ENCODE(X509, - buf.data, - buf.length, + sd.certificates->val[i].data, + sd.certificates->val[i].length, sk_X509_value(id->cert, i), ret); if (ret) { krb5_clear_error_string(context); goto out; } - data = realloc(sd.certificates->data, - sd.certificates->length + buf.length); - if (data == NULL) { - free(buf.data); - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; - } - memcpy(((char *)data) + sd.certificates->length, - buf.data, buf.length); - sd.certificates->length += buf.length; - sd.certificates->data = data; - free(buf.data); } ASN1_MALLOC_ENCODE(SignedData, sd_data->data, sd_data->length, @@ -563,7 +554,7 @@ build_auth_pack(krb5_context context, if (ret == 0 && dh) { DomainParameters dp; heim_integer dh_pub_key; - krb5_data buf; + krb5_data dhbuf; size_t size; ALLOC(a->clientPublicValue, 1); @@ -615,25 +606,25 @@ build_auth_pack(krb5_context context, if (ret) return ret; - buf.length = length_heim_integer(&dh_pub_key); - buf.data = malloc(buf.length); - if (buf.data == NULL) { + dhbuf.length = length_heim_integer(&dh_pub_key); + dhbuf.data = malloc(dhbuf.length); + if (dhbuf.data == NULL) { free_heim_integer(&dh_pub_key); krb5_set_error_string(context, "malloc: out of memory"); return ret; } - ret = der_put_heim_integer((char *)buf.data + buf.length - 1, - buf.length, &dh_pub_key, &size); + ret = der_put_heim_integer((char *)dhbuf.data + dhbuf.length - 1, + dhbuf.length, &dh_pub_key, &size); free_heim_integer(&dh_pub_key); if (ret) { - free(buf.data); + free(dhbuf.data); return ret; } - if (size != buf.length) + if (size != dhbuf.length) krb5_abortx(context, "asn1 internal error"); - a->clientPublicValue->subjectPublicKey.length = buf.length * 8; - a->clientPublicValue->subjectPublicKey.data = buf.data; + a->clientPublicValue->subjectPublicKey.length = dhbuf.length * 8; + a->clientPublicValue->subjectPublicKey.data = dhbuf.data; } return ret; @@ -894,7 +885,7 @@ _krb5_pk_mk_padata(krb5_context context, if (provisioning_server) { /* PacketCable requires the PROV-SRV-LOCATION authenticator */ - const PROV_SRV_LOCATION prov_server = (char *)provisioning_server; + const PROV_SRV_LOCATION prov_server = rk_UNCONST(provisioning_server); ASN1_MALLOC_ENCODE(PROV_SRV_LOCATION, buf.data, buf.length, &prov_server, &size, ret); @@ -1104,7 +1095,7 @@ pk_verify_chain_standard(krb5_context context, } static int -cert_to_X509(krb5_context context, CertificateSetReal *set, +cert_to_X509(krb5_context context, CertificateSet *set, STACK_OF(X509_CRL) **certs) { krb5_error_code ret; @@ -1112,6 +1103,9 @@ cert_to_X509(krb5_context context, CertificateSetReal *set, *certs = sk_X509_new_null(); + if (set == NULL) + return 0; + ret = 0; for (i = 0; i < set->len; i++) { unsigned char *p; @@ -1134,45 +1128,6 @@ cert_to_X509(krb5_context context, CertificateSetReal *set, return ret; } -static krb5_error_code -any_to_CertificateSet(krb5_context context, heim_any *cert, - CertificateSetReal *set) -{ - size_t size, len, length; - heim_any *val; - int ret; - char *p; - - set->len = 0; - set->val = NULL; - - len = 0; - p = cert->data; - length = cert->length; - while (len < cert->length) { - val = realloc(set->val, (set->len + 1) * sizeof(set->val[0])); - if (val == NULL) { - ret = ENOMEM; - goto out; - } - set->val = val; - ret = decode_heim_any(p, length, &set->val[set->len], &size); - if (ret) - goto out; - set->len++; - - p += size; - len += size; - length -= size; - } - return 0; - out: - krb5_clear_error_string(context); - free_CertificateSetReal(set); - set->val = NULL; - return ret; -} - krb5_error_code KRB5_LIB_FUNCTION _krb5_pk_verify_sign(krb5_context context, const char *data, @@ -1187,7 +1142,6 @@ _krb5_pk_verify_sign(krb5_context context, const EVP_MD *evp_type; EVP_PKEY *public_key; krb5_error_code ret; - CertificateSetReal set; EVP_MD_CTX md; X509 *cert; SignedData sd; @@ -1227,15 +1181,14 @@ _krb5_pk_verify_sign(krb5_context context, signer_info = &sd.signerInfos.val[0]; - ret = any_to_CertificateSet(context, sd.certificates, &set); - if (ret) { - krb5_set_error_string(context, - "PKINIT: failed to decode CertificateSet"); - goto out; - } + { + CertificateSet set; + set.val = sd.certificates->val; + set.len = sd.certificates->len; - ret = cert_to_X509(context, &set, &certificates); - free_CertificateSetReal(&set); + ret = cert_to_X509(context, &set, &certificates); + free_CertificateSet(&set); + } if (ret) { krb5_set_error_string(context, "PKINIT: failed to decode Certificates"); @@ -1530,7 +1483,6 @@ pk_rd_pa_reply_enckey(krb5_context context, /* win2k uses ContentInfo */ if (win2k_compat) { ContentInfo ci; - size_t size; ret = decode_ContentInfo(p, length, &ci, &size); if (ret) { @@ -1604,6 +1556,8 @@ pk_rd_pa_reply_dh(krb5_context context, ContentInfo *rep, krb5_pk_init_ctx ctx, krb5_enctype etype, + const DHNonce *c_n, + const DHNonce *k_n, unsigned nonce, PA_DATA *pa, krb5_keyblock **key) @@ -1666,6 +1620,30 @@ pk_rd_pa_reply_dh(krb5_context context, goto out; } + if (kdc_dh_info.dhKeyExpiration) { + if (k_n == NULL) { + krb5_set_error_string(context, "pkinit; got key expiration " + "without server nonce"); + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + if (c_n == NULL) { + krb5_set_error_string(context, "pkinit; got DH reuse but no " + "client nonce"); + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + } else { + if (k_n) { + krb5_set_error_string(context, "pkinit; got server nonce " + "without key expiration"); + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + c_n = NULL; + } + + p = kdc_dh_info.subjectPublicKey.data; size = (kdc_dh_info.subjectPublicKey.length + 7) / 8; dh_pub_key = d2i_ASN1_INTEGER(NULL, &p, size); @@ -1684,14 +1662,21 @@ pk_rd_pa_reply_dh(krb5_context context, goto out; } - dh_gen_key = malloc(DH_size(ctx->dh)); + dh_gen_keylen = DH_size(ctx->dh); + size = BN_num_bytes(ctx->dh->p); + if (size < dh_gen_keylen) + size = dh_gen_keylen; + + dh_gen_key = malloc(size); if (dh_gen_key == NULL) { krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; goto out; } + memset(dh_gen_key, 0, size - dh_gen_keylen); - dh_gen_keylen = DH_compute_key(dh_gen_key, kdc_dh_pubkey, ctx->dh); + dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen), + kdc_dh_pubkey, ctx->dh); if (dh_gen_keylen == -1) { krb5_set_error_string(context, "PKINIT: Can't compute Diffie-Hellman key (%s)", @@ -1707,7 +1692,11 @@ pk_rd_pa_reply_dh(krb5_context context, goto out; } - ret = krb5_random_to_key(context, etype, dh_gen_key, dh_gen_keylen, *key); + ret = _krb5_pk_octetstring2key(context, + etype, + dh_gen_key, dh_gen_keylen, + c_n, k_n, + *key); if (ret) { krb5_set_error_string(context, "PKINIT: can't create key from DH key"); @@ -1761,6 +1750,25 @@ _krb5_pk_rd_pa_reply(krb5_context context, return ret; switch (rep.element) { + case choice_PA_PK_AS_REP_dhInfo: + ret = decode_ContentInfo(rep.u.dhInfo.dhSignedData.data, + rep.u.dhInfo.dhSignedData.length, + &ci, + &size); + if (ret) { + krb5_set_error_string(context, + "PKINIT: -25 decoding failed DH " + "ContentInfo: %d", ret); + + free_PA_PK_AS_REP(&rep); + break; + } + ret = pk_rd_pa_reply_dh(context, &ci, ctx, + etype, NULL, NULL, nonce, pa, key); + free_ContentInfo(&ci); + free_PA_PK_AS_REP(&rep); + + break; case choice_PA_PK_AS_REP_encKeyPack: ret = decode_ContentInfo(rep.u.encKeyPack.data, rep.u.encKeyPack.length, @@ -1799,7 +1807,8 @@ _krb5_pk_rd_pa_reply(krb5_context context, switch(rep19.element) { case choice_PA_PK_AS_REP_19_dhSignedData: ret = pk_rd_pa_reply_dh(context, &rep19.u.dhSignedData, ctx, - etype, nonce, pa, key); + etype, NULL, NULL, + nonce, pa, key); break; case choice_PA_PK_AS_REP_19_encKeyPack: ret = pk_rd_pa_reply_enckey(context, 0, @@ -2314,8 +2323,8 @@ _krb5_pk_load_openssl_id(krb5_context context, FILE *f; krb5_error_code (*load_pair)(krb5_context, char *, - krb5_prompter_fct prompter, - void * prompter_data, + krb5_prompter_fct, + void *, const char *, struct krb5_pk_identity *) = NULL; @@ -2553,24 +2562,29 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, dh = DH_new(); if (dh == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); _krb5_get_init_creds_opt_free_pkinit(opt); return ENOMEM; } opt->private->pk_init_ctx->dh = dh; if (!BN_hex2bn(&dh->p, P)) { + krb5_set_error_string(context, "malloc: out of memory"); _krb5_get_init_creds_opt_free_pkinit(opt); return ENOMEM; } if (!BN_hex2bn(&dh->g, G)) { + krb5_set_error_string(context, "malloc: out of memory"); _krb5_get_init_creds_opt_free_pkinit(opt); return ENOMEM; } if (!BN_hex2bn(&dh->q, Q)) { + krb5_set_error_string(context, "malloc: out of memory"); _krb5_get_init_creds_opt_free_pkinit(opt); return ENOMEM; } /* XXX generate a new key for each request ? */ if (DH_generate_key(dh) != 1) { + krb5_set_error_string(context, "malloc: out of memory"); _krb5_get_init_creds_opt_free_pkinit(opt); return ENOMEM; } diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index b7194b4c41..b510478f65 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -76,7 +76,7 @@ krb5_principal_get_type(krb5_context context, const char* KRB5_LIB_FUNCTION krb5_principal_get_realm(krb5_context context, - krb5_const_principal principal) + krb5_principal principal) { return princ_realm(principal); } @@ -235,19 +235,19 @@ static const char replace_chars[] = " ntb\\/@"; #define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0); static size_t -quote_string(const char *s, char *out, size_t string_index, size_t len) +quote_string(const char *s, char *out, size_t idx, size_t len) { const char *p, *q; - for(p = s; *p && string_index < len; p++){ + for(p = s; *p && idx < len; p++){ if((q = strchr(quotable_chars, *p))){ - add_char(out, string_index, len, '\\'); - add_char(out, string_index, len, replace_chars[q - quotable_chars]); + add_char(out, idx, len, '\\'); + add_char(out, idx, len, replace_chars[q - quotable_chars]); }else - add_char(out, string_index, len, *p); + add_char(out, idx, len, *p); } - if(string_index < len) - out[string_index] = '\0'; - return string_index; + if(idx < len) + out[idx] = '\0'; + return idx; } diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c index 9129eceeff..2571591e9d 100644 --- a/source4/heimdal/lib/krb5/rd_cred.c +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_cred.c,v 1.23 2005/06/17 04:31:48 lha Exp $"); +RCSID("$Id: rd_cred.c,v 1.24 2005/07/13 08:22:50 lha Exp $"); static krb5_error_code compare_addrs(krb5_context context, @@ -68,6 +68,8 @@ krb5_rd_cred(krb5_context context, krb5_crypto crypto; int i; + memset(&enc_krb_cred_part, 0, sizeof(enc_krb_cred_part)); + if ((auth_context->flags & (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && outdata == NULL) @@ -262,9 +264,14 @@ krb5_rd_cred(krb5_context context, } (*ret_creds)[i] = NULL; + + free_KRB_CRED (&cred); + free_EncKrbCredPart(&enc_krb_cred_part); + return 0; out: + free_EncKrbCredPart(&enc_krb_cred_part); free_KRB_CRED (&cred); if(*ret_creds) { for(i = 0; (*ret_creds)[i]; i++) diff --git a/source4/heimdal/lib/krb5/test_crypto_wrapping.c b/source4/heimdal/lib/krb5/test_crypto_wrapping.c new file mode 100644 index 0000000000..37d9bbacb7 --- /dev/null +++ b/source4/heimdal/lib/krb5/test_crypto_wrapping.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 KTH 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 KTH AND ITS 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 KTH OR ITS 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. */ + +#include "krb5_locl.h" +#include +#include + +RCSID("$Id: test_crypto_wrapping.c,v 1.2 2005/07/09 01:31:43 lha Exp $"); + +static void +test_wrapping(krb5_context context, + size_t min_size, + size_t max_size, + size_t step, + krb5_enctype etype) +{ + krb5_error_code ret; + krb5_keyblock key; + krb5_crypto crypto; + krb5_data data; + char *etype_name; + void *buf; + size_t size; + + ret = krb5_generate_random_keyblock(context, etype, &key); + if (ret) + krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); + + ret = krb5_enctype_to_string(context, etype, &etype_name); + if (ret) + krb5_err(context, 1, ret, "krb5_enctype_to_string"); + + buf = malloc(max_size); + if (buf == NULL) + krb5_errx(context, 1, "out of memory"); + memset(buf, 0, max_size); + + ret = krb5_crypto_init(context, &key, 0, &crypto); + if (ret) + krb5_err(context, 1, ret, "krb5_crypto_init"); + + for (size = min_size; size < max_size; size += step) { + size_t wrapped_size; + + ret = krb5_encrypt(context, crypto, 0, buf, size, &data); + if (ret) + krb5_err(context, 1, ret, "encrypt size %d using %s", + size, etype_name); + + wrapped_size = krb5_get_wrapped_length(context, crypto, size); + + if (wrapped_size != data.length) + krb5_errx(context, 1, "calculated wrapped length %lu != " + "real wrapped length %lu for data length %lu using " + "enctype %s", + (unsigned long)wrapped_size, + (unsigned long)data.length, + (unsigned long)size, + etype_name); + krb5_data_free(&data); + } + + free(buf); + krb5_crypto_destroy(context, crypto); + krb5_free_keyblock_contents(context, &key); +} + + + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + int i, optidx = 0; + + krb5_enctype enctypes[] = { + ETYPE_DES_CBC_CRC, + ETYPE_DES_CBC_MD4, + ETYPE_DES_CBC_MD5, + ETYPE_DES3_CBC_SHA1, + ETYPE_ARCFOUR_HMAC_MD5, + ETYPE_AES128_CTS_HMAC_SHA1_96, + ETYPE_AES256_CTS_HMAC_SHA1_96 + }; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + for (i = 0; i < sizeof(enctypes)/sizeof(enctypes[0]); i++) { + test_wrapping(context, 0, 1024, 1, enctypes[i]); + test_wrapping(context, 1024, 1024 * 100, 1024, enctypes[i]); + } + krb5_free_context(context); + + return 0; +} diff --git a/source4/heimdal/lib/krb5/test_pkinit_dh2key.c b/source4/heimdal/lib/krb5/test_pkinit_dh2key.c new file mode 100644 index 0000000000..a40c218e12 --- /dev/null +++ b/source4/heimdal/lib/krb5/test_pkinit_dh2key.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2005 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 KTH 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 KTH AND ITS 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 KTH OR ITS 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. */ + +#include "krb5_locl.h" +#include +#include + +RCSID("$Id: test_pkinit_dh2key.c,v 1.1 2005/07/20 16:27:58 lha Exp $"); + +static void +test_dh2key(krb5_context context, + const heim_octet_string *K, + const heim_octet_string *c_n, + const heim_octet_string *k_n, + krb5_enctype etype) +{ + return; +} + + + +static int version_flag = 0; +static int help_flag = 0; + +static struct getargs args[] = { + {"version", 0, arg_flag, &version_flag, + "print version", NULL }, + {"help", 0, arg_flag, &help_flag, + NULL, NULL } +}; + +static void +usage (int ret) +{ + arg_printusage (args, + sizeof(args)/sizeof(*args), + NULL, + ""); + exit (ret); +} + +int +main(int argc, char **argv) +{ + krb5_context context; + krb5_error_code ret; + int i, optidx = 0; + + krb5_enctype enctypes[] = { + ETYPE_AES128_CTS_HMAC_SHA1_96, + ETYPE_AES256_CTS_HMAC_SHA1_96 + }; + + setprogname(argv[0]); + + if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) + usage(1); + + if (help_flag) + usage (0); + + if(version_flag){ + print_version(NULL); + exit(0); + } + + argc -= optidx; + argv += optidx; + + ret = krb5_init_context(&context); + if (ret) + errx (1, "krb5_init_context failed: %d", ret); + + for (i = 0; i < sizeof(enctypes)/sizeof(enctypes[0]); i++) { + test_dh2key(context, NULL, NULL, NULL, enctypes[i]); + } + + krb5_free_context(context); + + return 0; +} -- cgit From 55f5453bc81d9a3a4fe67ff0a6ba528d8d0f7984 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 20 Aug 2005 06:00:50 +0000 Subject: r9413: Bring Samba4 back up to date with lorikeet-heimdal. Delete test_crypto_wrapping.c, previously included but unbuilt. Andrew Bartlett (This used to be commit d5fb30fb0cef330e0947969f0c9afc1f58fc4c7d) --- source4/heimdal/lib/krb5/crypto.c | 10 +- source4/heimdal/lib/krb5/fcache.c | 2 +- source4/heimdal/lib/krb5/init_creds_pw.c | 19 ++- source4/heimdal/lib/krb5/krb5-private.h | 10 ++ source4/heimdal/lib/krb5/krb5-protos.h | 8 ++ source4/heimdal/lib/krb5/pkinit.c | 115 ++++++++++++++--- source4/heimdal/lib/krb5/test_crypto_wrapping.c | 163 ------------------------ source4/heimdal/lib/krb5/test_pkinit_dh2key.c | 110 ---------------- 8 files changed, 128 insertions(+), 309 deletions(-) delete mode 100644 source4/heimdal/lib/krb5/test_crypto_wrapping.c delete mode 100644 source4/heimdal/lib/krb5/test_pkinit_dh2key.c (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index c8fa556696..1c3e8d2a10 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -2124,8 +2124,7 @@ verify_checksum(krb5_context context, return KRB5_PROG_SUMTYPE_NOSUPP; } if(ct->checksumsize != cksum->checksum.length) { - krb5_set_error_string (context, "checksum length was %d, but should be %d for checksum type %s", - cksum->checksum.length, ct->checksumsize, ct->name); + krb5_clear_error_string (context); return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */ } keyed_checksum = (ct->flags & F_KEYED) != 0; @@ -2146,11 +2145,8 @@ verify_checksum(krb5_context context, (*ct->checksum)(context, dkey, data, len, usage, &c); - if(c.checksum.length != cksum->checksum.length) { - krb5_set_error_string (context, "(INTERNAL ERROR) our checksum length was %d, but should be %d for checksum type %s", - c.checksum.length, ct->checksumsize, ct->name); - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; - } else if (memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) { + if(c.checksum.length != cksum->checksum.length || + memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) { krb5_clear_error_string (context); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; } else { diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c index 03848abb9a..f8ebe837b7 100644 --- a/source4/heimdal/lib/krb5/fcache.c +++ b/source4/heimdal/lib/krb5/fcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: fcache.c,v 1.49 2005/06/16 20:25:20 lha Exp $"); +RCSID("$Id: fcache.c,v 1.51 2005/08/12 13:31:19 lha Exp $"); typedef struct krb5_fcache{ char *filename; diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 8b3975f418..8fd5c4611f 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c,v 1.87 2005/06/17 04:15:20 lha Exp $"); +RCSID("$Id: init_creds_pw.c,v 1.88 2005/08/13 08:25:32 lha Exp $"); typedef struct krb5_get_init_creds_ctx { krb5_kdc_flags flags; @@ -45,6 +45,7 @@ typedef struct krb5_get_init_creds_ctx { unsigned nonce; unsigned pk_nonce; + krb5_data req_buffer; AS_REQ as_req; int pa_counter; @@ -1158,6 +1159,7 @@ process_pa_data_to_key(krb5_context context, ctx->pk_init_ctx, etype, ctx->pk_nonce, + &ctx->req_buffer, pa, key); #else @@ -1218,7 +1220,6 @@ init_cred_loop(krb5_context context, ctx->pa_counter = 0; while (ctx->pa_counter < MAX_PA_COUNTER) { - krb5_data req; ctx->pa_counter++; @@ -1237,17 +1238,20 @@ init_cred_loop(krb5_context context, prompter, prompter_data); if (ret) goto out; - ASN1_MALLOC_ENCODE(AS_REQ, req.data, req.length, + + krb5_data_free(&ctx->req_buffer); + + ASN1_MALLOC_ENCODE(AS_REQ, + ctx->req_buffer.data, ctx->req_buffer.length, &ctx->as_req, &len, ret); if (ret) goto out; - if(len != req.length) + if(len != ctx->req_buffer.length) krb5_abortx(context, "internal error in ASN.1 encoder"); - ret = krb5_sendto_kdc_flags (context, &req, + ret = krb5_sendto_kdc_flags (context, &ctx->req_buffer, &creds->client->realm, &resp, send_to_kdc_flags); - krb5_data_free(&req); if (ret) goto out; @@ -1336,6 +1340,7 @@ init_cred_loop(krb5_context context, krb5_free_keyblock(context, key); } out: + krb5_data_free(&ctx->req_buffer); free_METHOD_DATA(&md); memset(&md, 0, sizeof(md)); diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index b877de8cf2..e70527845b 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -293,6 +293,16 @@ _krb5_pk_mk_padata ( unsigned /*nonce*/, METHOD_DATA */*md*/); +krb5_error_code +_krb5_pk_octetstring2key ( + krb5_context /*context*/, + krb5_enctype /*type*/, + const void */*dhdata*/, + size_t /*dhsize*/, + const heim_octet_string */*c_n*/, + const heim_octet_string */*k_n*/, + krb5_keyblock */*key*/); + krb5_error_code KRB5_LIB_FUNCTION _krb5_pk_rd_pa_reply ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index f306bf949f..2750c8b5d2 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -3251,6 +3251,14 @@ krb5_verify_init_creds_opt_set_ap_req_nofail ( krb5_verify_init_creds_opt */*options*/, int /*ap_req_nofail*/); +int KRB5_LIB_FUNCTION +krb5_verify_opt_alloc ( + krb5_context /*context*/, + krb5_verify_opt **/*opt*/); + +void KRB5_LIB_FUNCTION +krb5_verify_opt_free (krb5_verify_opt */*opt*/); + void KRB5_LIB_FUNCTION krb5_verify_opt_init (krb5_verify_opt */*opt*/); diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 35a751c291..69f72d7b88 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.58 2005/07/23 10:42:01 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.59 2005/08/12 08:53:00 lha Exp $"); #ifdef PKINIT @@ -58,7 +58,7 @@ RCSID("$Id: pkinit.c,v 1.58 2005/07/23 10:42:01 lha Exp $"); enum { COMPAT_WIN2K = 1, COMPAT_19 = 2, - COMPAT_25 = 3 + COMPAT_27 = 3 }; @@ -716,7 +716,7 @@ pk_mk_padata(krb5_context context, krb5_abortx(context, "internal ASN1 encoder error"); oid = oid_id_pkauthdata(); - } else if (compat == COMPAT_25) { + } else if (compat == COMPAT_27) { AuthPack ap; memset(&ap, 0, sizeof(ap)); @@ -802,7 +802,7 @@ pk_mk_padata(krb5_context context, free_PA_PK_AS_REQ_19(&req_19); - } else if (compat == COMPAT_25) { + } else if (compat == COMPAT_27) { pa_type = KRB5_PADATA_PK_AS_REQ; @@ -871,7 +871,7 @@ _krb5_pk_mk_padata(krb5_context context, if (ret) goto out; - ret = pk_mk_padata(context, COMPAT_25, ctx, req_body, nonce, md); + ret = pk_mk_padata(context, COMPAT_27, ctx, req_body, nonce, md); if (ret) goto out; } @@ -1280,10 +1280,10 @@ _krb5_pk_verify_sign(krb5_context context, } static krb5_error_code -get_reply_key(krb5_context context, - const krb5_data *content, - unsigned nonce, - krb5_keyblock **key) +get_reply_key_19(krb5_context context, + const krb5_data *content, + unsigned nonce, + krb5_keyblock **key) { ReplyKeyPack_19 key_pack; krb5_error_code ret; @@ -1323,6 +1323,69 @@ get_reply_key(krb5_context context, return ret; } +static krb5_error_code +get_reply_key(krb5_context context, + const krb5_data *content, + const krb5_data *req_buffer, + krb5_keyblock **key) +{ + ReplyKeyPack key_pack; + krb5_error_code ret; + size_t size; + + ret = decode_ReplyKeyPack(content->data, + content->length, + &key_pack, + &size); + if (ret) { + krb5_set_error_string(context, "PKINIT decoding reply key failed"); + free_ReplyKeyPack(&key_pack); + return ret; + } + + { + krb5_crypto crypto; + + /* + * XXX Verify kp.replyKey is a allowed enctype in the + * configuration file + */ + + ret = krb5_crypto_init(context, &key_pack.replyKey, 0, &crypto); + if (ret) { + free_ReplyKeyPack(&key_pack); + return ret; + } + + ret = krb5_verify_checksum(context, crypto, 6, + req_buffer->data, req_buffer->length, + &key_pack.asChecksum); + krb5_crypto_destroy(context, crypto); + if (ret) { + free_ReplyKeyPack(&key_pack); + return ret; + } + } + + *key = malloc (sizeof (**key)); + if (*key == NULL) { + krb5_set_error_string(context, "PKINIT failed allocating reply key"); + free_ReplyKeyPack(&key_pack); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ret = copy_EncryptionKey(&key_pack.replyKey, *key); + free_ReplyKeyPack(&key_pack); + if (ret) { + krb5_set_error_string(context, "PKINIT failed copying reply key"); + free(*key); + } + + return ret; +} + + static krb5_error_code pk_verify_host(krb5_context context, struct krb5_pk_cert *host) { @@ -1332,11 +1395,12 @@ pk_verify_host(krb5_context context, struct krb5_pk_cert *host) static krb5_error_code pk_rd_pa_reply_enckey(krb5_context context, - int win2k_compat, + int type, ContentInfo *rep, krb5_pk_init_ctx ctx, krb5_enctype etype, unsigned nonce, + const krb5_data *req_buffer, PA_DATA *pa, krb5_keyblock **key) { @@ -1418,7 +1482,7 @@ pk_rd_pa_reply_enckey(krb5_context context, /* verify content type */ - if (win2k_compat) { + if (type == COMPAT_WIN2K) { if (heim_oid_cmp(&ed.encryptedContentInfo.contentType, oid_id_pkcs7_data())) { ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; @@ -1481,7 +1545,7 @@ pk_rd_pa_reply_enckey(krb5_context context, length = plain.length; /* win2k uses ContentInfo */ - if (win2k_compat) { + if (type == COMPAT_WIN2K) { ContentInfo ci; ret = decode_ContentInfo(p, length, &ci, &size); @@ -1518,7 +1582,7 @@ pk_rd_pa_reply_enckey(krb5_context context, goto out; } - if (win2k_compat) { + if (type == COMPAT_WIN2K) { if (heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) { krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; @@ -1532,7 +1596,15 @@ pk_rd_pa_reply_enckey(krb5_context context, } } - ret = get_reply_key(context, &content, nonce, key); + switch(type) { + case COMPAT_WIN2K: + case COMPAT_19: + ret = get_reply_key_19(context, &content, nonce, key); + break; + case COMPAT_27: + ret = get_reply_key(context, &content, req_buffer, key); + break; + } if (ret) goto out; @@ -1728,6 +1800,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, void *c, krb5_enctype etype, unsigned nonce, + const krb5_data *req_buffer, PA_DATA *pa, krb5_keyblock **key) { @@ -1736,7 +1809,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, ContentInfo ci; size_t size; - /* Check for PK-INIT -25 */ + /* Check for PK-INIT -27 */ if (pa->padata_type == KRB5_PADATA_PK_AS_REP) { PA_PK_AS_REP rep; @@ -1781,8 +1854,8 @@ _krb5_pk_rd_pa_reply(krb5_context context, "ContentInfo: %d", ret); break; } - ret = pk_rd_pa_reply_enckey(context, 0, &ci, ctx, - etype, nonce, pa, key); + ret = pk_rd_pa_reply_enckey(context, COMPAT_27, &ci, ctx, + etype, nonce, req_buffer, pa, key); free_ContentInfo(&ci); return ret; default: @@ -1811,9 +1884,9 @@ _krb5_pk_rd_pa_reply(krb5_context context, nonce, pa, key); break; case choice_PA_PK_AS_REP_19_encKeyPack: - ret = pk_rd_pa_reply_enckey(context, 0, + ret = pk_rd_pa_reply_enckey(context, COMPAT_19, &rep19.u.encKeyPack, ctx, - etype, nonce, pa, key); + etype, nonce, NULL, pa, key); break; default: krb5_set_error_string(context, "PKINIT: -19 reply invalid " @@ -1857,8 +1930,8 @@ _krb5_pk_rd_pa_reply(krb5_context context, ret); return ret; } - ret = pk_rd_pa_reply_enckey(context, 1, &ci, ctx, - etype, nonce, pa, key); + ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, ctx, + etype, nonce, NULL, pa, key); free_ContentInfo(&ci); break; default: diff --git a/source4/heimdal/lib/krb5/test_crypto_wrapping.c b/source4/heimdal/lib/krb5/test_crypto_wrapping.c deleted file mode 100644 index 37d9bbacb7..0000000000 --- a/source4/heimdal/lib/krb5/test_crypto_wrapping.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (c) 2005 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * 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 KTH 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 KTH AND ITS 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 KTH OR ITS 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. */ - -#include "krb5_locl.h" -#include -#include - -RCSID("$Id: test_crypto_wrapping.c,v 1.2 2005/07/09 01:31:43 lha Exp $"); - -static void -test_wrapping(krb5_context context, - size_t min_size, - size_t max_size, - size_t step, - krb5_enctype etype) -{ - krb5_error_code ret; - krb5_keyblock key; - krb5_crypto crypto; - krb5_data data; - char *etype_name; - void *buf; - size_t size; - - ret = krb5_generate_random_keyblock(context, etype, &key); - if (ret) - krb5_err(context, 1, ret, "krb5_generate_random_keyblock"); - - ret = krb5_enctype_to_string(context, etype, &etype_name); - if (ret) - krb5_err(context, 1, ret, "krb5_enctype_to_string"); - - buf = malloc(max_size); - if (buf == NULL) - krb5_errx(context, 1, "out of memory"); - memset(buf, 0, max_size); - - ret = krb5_crypto_init(context, &key, 0, &crypto); - if (ret) - krb5_err(context, 1, ret, "krb5_crypto_init"); - - for (size = min_size; size < max_size; size += step) { - size_t wrapped_size; - - ret = krb5_encrypt(context, crypto, 0, buf, size, &data); - if (ret) - krb5_err(context, 1, ret, "encrypt size %d using %s", - size, etype_name); - - wrapped_size = krb5_get_wrapped_length(context, crypto, size); - - if (wrapped_size != data.length) - krb5_errx(context, 1, "calculated wrapped length %lu != " - "real wrapped length %lu for data length %lu using " - "enctype %s", - (unsigned long)wrapped_size, - (unsigned long)data.length, - (unsigned long)size, - etype_name); - krb5_data_free(&data); - } - - free(buf); - krb5_crypto_destroy(context, crypto); - krb5_free_keyblock_contents(context, &key); -} - - - -static int version_flag = 0; -static int help_flag = 0; - -static struct getargs args[] = { - {"version", 0, arg_flag, &version_flag, - "print version", NULL }, - {"help", 0, arg_flag, &help_flag, - NULL, NULL } -}; - -static void -usage (int ret) -{ - arg_printusage (args, - sizeof(args)/sizeof(*args), - NULL, - ""); - exit (ret); -} - -int -main(int argc, char **argv) -{ - krb5_context context; - krb5_error_code ret; - int i, optidx = 0; - - krb5_enctype enctypes[] = { - ETYPE_DES_CBC_CRC, - ETYPE_DES_CBC_MD4, - ETYPE_DES_CBC_MD5, - ETYPE_DES3_CBC_SHA1, - ETYPE_ARCFOUR_HMAC_MD5, - ETYPE_AES128_CTS_HMAC_SHA1_96, - ETYPE_AES256_CTS_HMAC_SHA1_96 - }; - - setprogname(argv[0]); - - if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) - usage(1); - - if (help_flag) - usage (0); - - if(version_flag){ - print_version(NULL); - exit(0); - } - - argc -= optidx; - argv += optidx; - - ret = krb5_init_context(&context); - if (ret) - errx (1, "krb5_init_context failed: %d", ret); - - for (i = 0; i < sizeof(enctypes)/sizeof(enctypes[0]); i++) { - test_wrapping(context, 0, 1024, 1, enctypes[i]); - test_wrapping(context, 1024, 1024 * 100, 1024, enctypes[i]); - } - krb5_free_context(context); - - return 0; -} diff --git a/source4/heimdal/lib/krb5/test_pkinit_dh2key.c b/source4/heimdal/lib/krb5/test_pkinit_dh2key.c deleted file mode 100644 index a40c218e12..0000000000 --- a/source4/heimdal/lib/krb5/test_pkinit_dh2key.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2005 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * 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 KTH 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 KTH AND ITS 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 KTH OR ITS 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. */ - -#include "krb5_locl.h" -#include -#include - -RCSID("$Id: test_pkinit_dh2key.c,v 1.1 2005/07/20 16:27:58 lha Exp $"); - -static void -test_dh2key(krb5_context context, - const heim_octet_string *K, - const heim_octet_string *c_n, - const heim_octet_string *k_n, - krb5_enctype etype) -{ - return; -} - - - -static int version_flag = 0; -static int help_flag = 0; - -static struct getargs args[] = { - {"version", 0, arg_flag, &version_flag, - "print version", NULL }, - {"help", 0, arg_flag, &help_flag, - NULL, NULL } -}; - -static void -usage (int ret) -{ - arg_printusage (args, - sizeof(args)/sizeof(*args), - NULL, - ""); - exit (ret); -} - -int -main(int argc, char **argv) -{ - krb5_context context; - krb5_error_code ret; - int i, optidx = 0; - - krb5_enctype enctypes[] = { - ETYPE_AES128_CTS_HMAC_SHA1_96, - ETYPE_AES256_CTS_HMAC_SHA1_96 - }; - - setprogname(argv[0]); - - if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx)) - usage(1); - - if (help_flag) - usage (0); - - if(version_flag){ - print_version(NULL); - exit(0); - } - - argc -= optidx; - argv += optidx; - - ret = krb5_init_context(&context); - if (ret) - errx (1, "krb5_init_context failed: %d", ret); - - for (i = 0; i < sizeof(enctypes)/sizeof(enctypes[0]); i++) { - test_dh2key(context, NULL, NULL, NULL, enctypes[i]); - } - - krb5_free_context(context); - - return 0; -} -- cgit From 08730652fbf1c9f6d53378b1b094a2c5ddf2cf62 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 27 Aug 2005 11:49:06 +0000 Subject: r9680: Update Heimdal to current lorikeet-heimdal (which was itself updated to Heimdal CVS as of 2005-08-27). Andrew Bartlett (This used to be commit 913924a4997f5e14c503f87510cbd8e4bfd965a9) --- source4/heimdal/lib/krb5/get_host_realm.c | 27 +++++++++----- source4/heimdal/lib/krb5/krb5-private.h | 1 + source4/heimdal/lib/krb5/krb5-protos.h | 23 +++++++++--- source4/heimdal/lib/krb5/principal.c | 59 ++++++++++++++++++++++--------- 4 files changed, 81 insertions(+), 29 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/get_host_realm.c b/source4/heimdal/lib/krb5/get_host_realm.c index d9c5bd5dc1..feb01f0036 100644 --- a/source4/heimdal/lib/krb5/get_host_realm.c +++ b/source4/heimdal/lib/krb5/get_host_realm.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: get_host_realm.c,v 1.34 2005/04/19 18:52:51 lha Exp $"); +RCSID("$Id: get_host_realm.c,v 1.35 2005/08/23 08:14:02 lha Exp $"); /* To automagically find the correct realm of a host (without * [domain_realm] in krb5.conf) add a text record for your domain with @@ -94,30 +94,41 @@ dns_find_realm(krb5_context context, const char *domain, krb5_realm **realms) { - static char *default_labels[] = { "_kerberos", NULL }; + static const char *default_labels[] = { "_kerberos", NULL }; char dom[MAXHOSTNAMELEN]; struct dns_reply *r; - char **labels; + const char **labels; + char **config_labels; int i, ret; - labels = krb5_config_get_strings(context, NULL, "libdefaults", - "dns_lookup_realm_labels", NULL); - if(labels == NULL) + config_labels = krb5_config_get_strings(context, NULL, "libdefaults", + "dns_lookup_realm_labels", NULL); + if(config_labels != NULL) + labels = (const char **)config_labels; + else labels = default_labels; if(*domain == '.') domain++; for (i = 0; labels[i] != NULL; i++) { ret = snprintf(dom, sizeof(dom), "%s.%s.", labels[i], domain); - if(ret < 0 || ret >= sizeof(dom)) + if(ret < 0 || ret >= sizeof(dom)) { + if (config_labels) + krb5_config_free_strings(config_labels); return -1; + } r = dns_lookup(dom, "TXT"); if(r != NULL) { ret = copy_txt_to_realms (r->head, realms); dns_free_data(r); - if(ret == 0) + if(ret == 0) { + if (config_labels) + krb5_config_free_strings(config_labels); return 0; + } } } + if (config_labels) + krb5_config_free_strings(config_labels); return -1; } diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index e70527845b..8e2ebcf43e 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -309,6 +309,7 @@ _krb5_pk_rd_pa_reply ( void */*c*/, krb5_enctype /*etype*/, unsigned /*nonce*/, + const krb5_data */*req_buffer*/, PA_DATA */*pa*/, krb5_keyblock **/*key*/); diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 2750c8b5d2..711c5ead6e 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -20,6 +20,15 @@ extern "C" { #endif #endif +void +initialize_heim_error_table_r (struct et_list **/*list*/); + +void +initialize_k524_error_table_r (struct et_list **/*list*/); + +void +initialize_krb5_error_table_r (struct et_list **/*list*/); + krb5_error_code KRB5_LIB_FUNCTION krb524_convert_creds_kdc ( krb5_context /*context*/, @@ -2392,7 +2401,7 @@ krb5_prepend_config_files_default ( const char */*filelist*/, char ***/*pfilenames*/); -krb5_realm* +krb5_realm* KRB5_LIB_FUNCTION krb5_princ_realm ( krb5_context /*context*/, krb5_principal /*principal*/); @@ -2418,18 +2427,18 @@ krb5_principal_compare_any_realm ( const char* KRB5_LIB_FUNCTION krb5_principal_get_comp_string ( krb5_context /*context*/, - krb5_principal /*principal*/, + krb5_const_principal /*principal*/, unsigned int /*component*/); const char* KRB5_LIB_FUNCTION krb5_principal_get_realm ( krb5_context /*context*/, - krb5_principal /*principal*/); + krb5_const_principal /*principal*/); int KRB5_LIB_FUNCTION krb5_principal_get_type ( krb5_context /*context*/, - krb5_principal /*principal*/); + krb5_const_principal /*principal*/); krb5_boolean KRB5_LIB_FUNCTION krb5_principal_match ( @@ -3154,6 +3163,12 @@ krb5_unparse_name ( krb5_const_principal /*principal*/, char **/*name*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_always_short ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + char **/*name*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_unparse_name_fixed ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index b510478f65..74db080ab7 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -41,7 +41,7 @@ #include #include "resolve.h" -RCSID("$Id: principal.c,v 1.90 2005/06/30 01:38:15 lha Exp $"); +RCSID("$Id: principal.c,v 1.91 2005/08/23 08:34:40 lha Exp $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -69,21 +69,21 @@ krb5_principal_set_type(krb5_context context, int KRB5_LIB_FUNCTION krb5_principal_get_type(krb5_context context, - krb5_principal principal) + krb5_const_principal principal) { return princ_type(principal); } const char* KRB5_LIB_FUNCTION krb5_principal_get_realm(krb5_context context, - krb5_principal principal) + krb5_const_principal principal) { return princ_realm(principal); } const char* KRB5_LIB_FUNCTION krb5_principal_get_comp_string(krb5_context context, - krb5_principal principal, + krb5_const_principal principal, unsigned int component) { if(component >= princ_num_comp(principal)) @@ -268,16 +268,6 @@ unparse_name_fixed(krb5_context context, return ERANGE; } /* add realm if different from default realm */ - if(short_form) { - krb5_realm r; - krb5_error_code ret; - ret = krb5_get_default_realm(context, &r); - if(ret) - return ret; - if(strcmp(princ_realm(principal), r) != 0) - short_form = 0; - free(r); - } if(!short_form) { add_char(name, idx, len, '@'); idx = quote_string(princ_realm(principal), name, idx, len); @@ -296,13 +286,31 @@ krb5_unparse_name_fixed(krb5_context context, return unparse_name_fixed(context, principal, name, len, FALSE); } +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_norealm_fixed(krb5_context context, + krb5_const_principal principal, + char *name, + size_t len) +{ + return unparse_name_fixed(context, principal, name, len, TRUE); +} + krb5_error_code KRB5_LIB_FUNCTION krb5_unparse_name_fixed_short(krb5_context context, krb5_const_principal principal, char *name, size_t len) { - return unparse_name_fixed(context, principal, name, len, TRUE); + krb5_realm r; + krb5_error_code ret; + krb5_boolean short_form = TRUE; + ret = krb5_get_default_realm(context, &r); + if(ret) + return ret; + if(strcmp(princ_realm(principal), r) != 0) + short_form = 0; + free(r); + return unparse_name_fixed(context, principal, name, len, short_form); } static krb5_error_code @@ -355,6 +363,23 @@ krb5_error_code KRB5_LIB_FUNCTION krb5_unparse_name_short(krb5_context context, krb5_const_principal principal, char **name) +{ + krb5_realm r; + krb5_error_code ret; + krb5_boolean short_form = TRUE; + ret = krb5_get_default_realm(context, &r); + if(ret) + return ret; + if(strcmp(princ_realm(principal), r) != 0) + short_form = 0; + free(r); + return unparse_name(context, principal, name, short_form); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_norealm(krb5_context context, + krb5_const_principal principal, + char **name) { return unparse_name(context, principal, name, TRUE); } @@ -372,7 +397,7 @@ krb5_unparse_name_ext(krb5_context context, #endif -krb5_realm* +krb5_realm* KRB5_LIB_FUNCTION krb5_princ_realm(krb5_context context, krb5_principal principal) { @@ -380,6 +405,7 @@ krb5_princ_realm(krb5_context context, } + void KRB5_LIB_FUNCTION krb5_princ_set_realm(krb5_context context, krb5_principal principal, @@ -764,7 +790,6 @@ krb5_425_conv_principal_ext2(krb5_context context, } #else struct addrinfo hints, *ai; - int ret; memset (&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; -- cgit From 3c265c79867e55a8118c2fa3c545a451e2b5e7e9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 27 Aug 2005 22:48:39 +0000 Subject: r9696: Update prototypes for new name of short parsing function. Andrew Bartlett (This used to be commit cc35cd5ee2abbd6be01dc1ea66eca0bd48a6f636) --- source4/heimdal/lib/krb5/krb5-protos.h | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 711c5ead6e..71d42b43b8 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -3164,20 +3164,27 @@ krb5_unparse_name ( char **/*name*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_always_short ( +krb5_unparse_name_fixed ( krb5_context /*context*/, krb5_const_principal /*principal*/, - char **/*name*/); + char */*name*/, + size_t /*len*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_fixed ( +krb5_unparse_name_fixed_short ( krb5_context /*context*/, krb5_const_principal /*principal*/, char */*name*/, size_t /*len*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_fixed_short ( +krb5_unparse_name_norealm ( + krb5_context /*context*/, + krb5_const_principal /*principal*/, + char **/*name*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_unparse_name_norealm_fixed ( krb5_context /*context*/, krb5_const_principal /*principal*/, char */*name*/, -- cgit From ad14812b8f036fb47b4817d5ee391416dd9bf567 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 1 Sep 2005 23:31:51 +0000 Subject: r9931: Make use of new 'norealm' parsing functions rather than strchr(p '@'). Merge these norealm functions from lorikeet-heimdal. Andrew Bartlett (This used to be commit 6aef275efd7f434f65824eb3dd129c8e5efd8731) --- source4/heimdal/lib/krb5/krb5-protos.h | 13 +++++++ source4/heimdal/lib/krb5/principal.c | 71 ++++++++++++++++++++++++---------- 2 files changed, 64 insertions(+), 20 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 71d42b43b8..cc619314a3 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -2377,6 +2377,12 @@ krb5_parse_name ( const char */*name*/, krb5_principal */*principal*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name_norealm ( + krb5_context /*context*/, + const char */*name*/, + krb5_principal */*principal*/); + const char* KRB5_LIB_FUNCTION krb5_passwd_result_to_string ( krb5_context /*context*/, @@ -3430,6 +3436,13 @@ krb5_write_safe_message ( krb5_error_code KRB5_LIB_FUNCTION krb5_xfree (void */*ptr*/); +krb5_error_code +parse_name ( + krb5_context /*context*/, + const char */*name*/, + krb5_boolean /*short_form*/, + krb5_principal */*principal*/); + #ifdef __cplusplus } #endif diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index 74db080ab7..8540636403 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -91,10 +91,11 @@ krb5_principal_get_comp_string(krb5_context context, return princ_ncomp(principal, component); } -krb5_error_code KRB5_LIB_FUNCTION -krb5_parse_name(krb5_context context, - const char *name, - krb5_principal *principal) +krb5_error_code +parse_name(krb5_context context, + const char *name, + krb5_boolean short_form, + krb5_principal *principal) { krb5_error_code ret; heim_general_string *comp; @@ -184,19 +185,29 @@ krb5_parse_name(krb5_context context, } *q++ = c; } - if(got_realm){ - realm = malloc(q - start + 1); - if (realm == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); - ret = ENOMEM; + if (got_realm) { + if (short_form) { + krb5_set_error_string (context, "realm found in 'short' principal expected to be without one!"); + ret = KRB5_PARSE_MALFORMED; goto exit; + } else { + realm = malloc(q - start + 1); + if (realm == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto exit; + } + memcpy(realm, start, q - start); + realm[q - start] = 0; } - memcpy(realm, start, q - start); - realm[q - start] = 0; }else{ - ret = krb5_get_default_realm (context, &realm); - if (ret) - goto exit; + if (short_form) { + ret = krb5_get_default_realm (context, &realm); + if (ret) + goto exit; + } else { + realm = NULL; + } comp[n] = malloc(q - start + 1); if (comp[n] == NULL) { @@ -229,6 +240,21 @@ exit: return ret; } +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name(krb5_context context, + const char *name, + krb5_principal *principal) +{ + return parse_name(context, name, FALSE, principal); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name_norealm(krb5_context context, + const char *name, + krb5_principal *principal) +{ + return parse_name(context, name, TRUE, principal); +} static const char quotable_chars[] = " \n\t\b\\/@"; static const char replace_chars[] = " ntb\\/@"; @@ -323,12 +349,17 @@ unparse_name(krb5_context context, int i; krb5_error_code ret; /* count length */ - plen = strlen(princ_realm(principal)); - if(strcspn(princ_realm(principal), quotable_chars) == plen) - len += plen; - else - len += 2*plen; - len++; + if (!short_flag) { + plen = strlen(princ_realm(principal)); + if(strcspn(princ_realm(principal), quotable_chars) == plen) + len += plen; + else + len += 2*plen; + len++; + } else { + len = 0; + } + for(i = 0; i < princ_num_comp(principal); i++){ plen = strlen(princ_ncomp(principal, i)); if(strcspn(princ_ncomp(principal, i), quotable_chars) == plen) -- cgit From 6b14ffe2713efe2e16a988d920d2dbd7c088601d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 5 Sep 2005 10:53:14 +0000 Subject: r10035: This patch removes the need for the special case hack 'MEMORY_WILDCARD' keytab type. (part of this checking is in effect a merge from lorikeet-heimdal, where I removed this) This is achieved by correctly using the GSSAPI gsskrb5_acquire_cred() function, as this allows us to specify the target principal, regardless of which alias the client may use. This patch also tries to simplify some principal handling and fixes some error cases. Posted to samba-technical, reviewed by metze, and looked over by lha on IRC. Andrew Bartlett (This used to be commit 506a7b67aee949b102d8bf0d6ee9cd12def10d00) --- source4/heimdal/lib/krb5/context.c | 1 - source4/heimdal/lib/krb5/keytab_memory.c | 53 -------------------------------- source4/heimdal/lib/krb5/krb5.h | 1 - 3 files changed, 55 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index 62fb92d666..4d6eae2b24 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -231,7 +231,6 @@ krb5_init_context(krb5_context *context) krb5_kt_register (p, &krb5_wrfkt_ops); krb5_kt_register (p, &krb5_javakt_ops); krb5_kt_register (p, &krb5_mkt_ops); - krb5_kt_register (p, &krb5_mktw_ops); krb5_kt_register (p, &krb5_akf_ops); krb5_kt_register (p, &krb4_fkt_ops); krb5_kt_register (p, &krb5_srvtab_fkt_ops); diff --git a/source4/heimdal/lib/krb5/keytab_memory.c b/source4/heimdal/lib/krb5/keytab_memory.c index 3dca5154e3..1d866fa11e 100644 --- a/source4/heimdal/lib/krb5/keytab_memory.c +++ b/source4/heimdal/lib/krb5/keytab_memory.c @@ -174,56 +174,3 @@ const krb5_kt_ops krb5_mkt_ops = { mkt_add_entry, mkt_remove_entry }; - -static krb5_error_code -mktw_get_entry(krb5_context context, - krb5_keytab id, - krb5_const_principal principal, - krb5_kvno kvno, - krb5_enctype enctype, - krb5_keytab_entry *entry) -{ - krb5_keytab_entry tmp; - krb5_error_code ret; - krb5_kt_cursor cursor; - - ret = krb5_kt_start_seq_get (context, id, &cursor); - if (ret) - return KRB5_KT_NOTFOUND; /* XXX i.e. file not found */ - - entry->vno = 0; - while (krb5_kt_next_entry(context, id, &tmp, &cursor) == 0) { - if (krb5_kt_compare(context, &tmp, NULL, 0, enctype)) { - if (kvno == tmp.vno) { - krb5_kt_copy_entry_contents (context, &tmp, entry); - krb5_kt_free_entry (context, &tmp); - krb5_kt_end_seq_get(context, id, &cursor); - return 0; - } else if (kvno == 0 && tmp.vno > entry->vno) { - if (entry->vno) - krb5_kt_free_entry (context, entry); - krb5_kt_copy_entry_contents (context, &tmp, entry); - } - } - krb5_kt_free_entry(context, &tmp); - } - krb5_kt_end_seq_get (context, id, &cursor); - if (entry->vno) { - return 0; - } else { - return KRB5_KT_NOTFOUND; - } -}; - -const krb5_kt_ops krb5_mktw_ops = { - "MEMORY_WILDCARD", - mkt_resolve, - mkt_get_name, - mkt_close, - mktw_get_entry, /* get */ - mkt_start_seq_get, - mkt_next_entry, - mkt_end_seq_get, - mkt_add_entry, - mkt_remove_entry -}; diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 5789bff205..c47c4450f1 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -698,7 +698,6 @@ extern const krb5_kt_ops krb5_fkt_ops; extern const krb5_kt_ops krb5_wrfkt_ops; extern const krb5_kt_ops krb5_javakt_ops; extern const krb5_kt_ops krb5_mkt_ops; -extern const krb5_kt_ops krb5_mktw_ops; extern const krb5_kt_ops krb5_akf_ops; extern const krb5_kt_ops krb4_fkt_ops; extern const krb5_kt_ops krb5_srvtab_fkt_ops; -- cgit From 1f2f470889d63a2a81ee3f2d8bdff782ac8d0e28 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 7 Sep 2005 21:52:50 +0000 Subject: r10066: This is the second in my patches to work on Samba4's kerberos support, with an aim to make the code simpiler and more correct. Gone is the old (since the very early Samba 3.0 krb5 days) 'iterate over all keytypes)' code in gensec_krb5, we now follow the approach used in gensec_gssapi, and use a keytab. I have also done a lot of work in the GSSAPI code, to try and reduce the diff between us and upstream heimdal. It was becoming hard to track patches in this code, and I also want this patch (the DCE_STYLE support) to be in a 'manageable' state for when lha considers it for merging. (metze assures me it still has memory leak problems, but I've started to address some of that). This patch also includes a simple update of other code to current heimdal, as well as changes we need for better PAC verification. On the PAC side of things we now match windows member servers by checking the name and authtime on an incoming PAC. Not generating these right was the cause of the PAC pain, and so now both the main code and torture test validate this behaviour. One thing doesn't work with this patch: - the sealing of RPC pipes with kerberos, Samba -> Samba seems broken. I'm pretty sure this is related to AES, and the need to break apart the gss_wrap interface. Andrew Bartlett (This used to be commit a3aba57c00a9c5318f4706db55d03f64e8bea60c) --- source4/heimdal/lib/krb5/krb5-protos.h | 13 ++- source4/heimdal/lib/krb5/rd_rep.c | 146 +++++++++++++++------------------ source4/heimdal/lib/krb5/rd_req.c | 20 +++-- 3 files changed, 86 insertions(+), 93 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index cc619314a3..97f286b83e 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -2377,6 +2377,12 @@ krb5_parse_name ( const char */*name*/, krb5_principal */*principal*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name_mustrealm ( + krb5_context /*context*/, + const char */*name*/, + krb5_principal */*principal*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_parse_name_norealm ( krb5_context /*context*/, @@ -3436,13 +3442,6 @@ krb5_write_safe_message ( krb5_error_code KRB5_LIB_FUNCTION krb5_xfree (void */*ptr*/); -krb5_error_code -parse_name ( - krb5_context /*context*/, - const char */*name*/, - krb5_boolean /*short_form*/, - krb5_principal */*principal*/); - #ifdef __cplusplus } #endif diff --git a/source4/heimdal/lib/krb5/rd_rep.c b/source4/heimdal/lib/krb5/rd_rep.c index a92eea5c04..53138d9f45 100644 --- a/source4/heimdal/lib/krb5/rd_rep.c +++ b/source4/heimdal/lib/krb5/rd_rep.c @@ -36,94 +36,80 @@ RCSID("$Id: rd_rep.c,v 1.25 2005/06/17 07:49:33 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION -_krb5_rd_rep_type(krb5_context context, - krb5_auth_context auth_context, - const krb5_data *inbuf, - krb5_ap_rep_enc_part **repl, - krb5_boolean dce_style_response) +krb5_rd_rep(krb5_context context, + krb5_auth_context auth_context, + const krb5_data *inbuf, + krb5_ap_rep_enc_part **repl) { - krb5_error_code ret; - AP_REP ap_rep; - size_t len; - krb5_data data; - krb5_crypto crypto; + krb5_error_code ret; + AP_REP ap_rep; + size_t len; + krb5_data data; + krb5_crypto crypto; - krb5_data_zero (&data); - ret = 0; + krb5_data_zero (&data); + ret = 0; - ret = decode_AP_REP(inbuf->data, inbuf->length, &ap_rep, &len); - if (ret) - return ret; - if (ap_rep.pvno != 5) { - ret = KRB5KRB_AP_ERR_BADVERSION; - krb5_clear_error_string (context); - goto out; - } - if (ap_rep.msg_type != krb_ap_rep) { - ret = KRB5KRB_AP_ERR_MSG_TYPE; - krb5_clear_error_string (context); - goto out; - } + ret = decode_AP_REP(inbuf->data, inbuf->length, &ap_rep, &len); + if (ret) + return ret; + if (ap_rep.pvno != 5) { + ret = KRB5KRB_AP_ERR_BADVERSION; + krb5_clear_error_string (context); + goto out; + } + if (ap_rep.msg_type != krb_ap_rep) { + ret = KRB5KRB_AP_ERR_MSG_TYPE; + krb5_clear_error_string (context); + goto out; + } - ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto); - if (ret) - goto out; - ret = krb5_decrypt_EncryptedData (context, - crypto, - KRB5_KU_AP_REQ_ENC_PART, - &ap_rep.enc_part, - &data); - krb5_crypto_destroy(context, crypto); - if (ret) - goto out; + ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto); + if (ret) + goto out; + ret = krb5_decrypt_EncryptedData (context, + crypto, + KRB5_KU_AP_REQ_ENC_PART, + &ap_rep.enc_part, + &data); + krb5_crypto_destroy(context, crypto); + if (ret) + goto out; - *repl = malloc(sizeof(**repl)); - if (*repl == NULL) { - ret = ENOMEM; - krb5_set_error_string (context, "malloc: out of memory"); - goto out; - } - ret = krb5_decode_EncAPRepPart(context, - data.data, - data.length, - *repl, - &len); - if (ret) - return ret; - - if (!dce_style_response) { - if ((*repl)->ctime != auth_context->authenticator->ctime || - (*repl)->cusec != auth_context->authenticator->cusec) { - ret = KRB5KRB_AP_ERR_MUT_FAIL; - krb5_set_error_string (context, "Mutual authentication failed: Timestamps mismatch"); - goto out; - } - } - if ((*repl)->seq_number) - krb5_auth_con_setremoteseqnumber(context, auth_context, - *((*repl)->seq_number)); - if ((*repl)->subkey) - krb5_auth_con_setremotesubkey(context, auth_context, (*repl)->subkey); + *repl = malloc(sizeof(**repl)); + if (*repl == NULL) { + ret = ENOMEM; + krb5_set_error_string (context, "malloc: out of memory"); + goto out; + } + ret = krb5_decode_EncAPRepPart(context, + data.data, + data.length, + *repl, + &len); + if (ret) + return ret; + + if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { + if ((*repl)->ctime != auth_context->authenticator->ctime || + (*repl)->cusec != auth_context->authenticator->cusec) { + ret = KRB5KRB_AP_ERR_MUT_FAIL; + krb5_clear_error_string (context); + goto out; + } + } + if ((*repl)->seq_number) + krb5_auth_con_setremoteseqnumber(context, auth_context, + *((*repl)->seq_number)); + if ((*repl)->subkey) + krb5_auth_con_setremotesubkey(context, auth_context, (*repl)->subkey); -out: - krb5_data_free (&data); - free_AP_REP (&ap_rep); - return ret; + out: + krb5_data_free (&data); + free_AP_REP (&ap_rep); + return ret; } -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_rep(krb5_context context, - krb5_auth_context auth_context, - const krb5_data *inbuf, - krb5_ap_rep_enc_part **repl) -{ - return _krb5_rd_rep_type(context, - auth_context, - inbuf, - repl, - FALSE); -} - void KRB5_LIB_FUNCTION krb5_free_ap_rep_enc_part (krb5_context context, krb5_ap_rep_enc_part *val) diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 30ad08bd82..66172c10fb 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_req.c,v 1.57 2005/01/08 20:41:17 lha Exp $"); +RCSID("$Id: rd_req.c,v 1.58 2005/08/27 05:48:57 lha Exp $"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, @@ -136,6 +136,10 @@ check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc) int num_realms; krb5_error_code ret; + /* Windows w2k and w2k3 uses this */ + if(enc->transited.tr_type == 0 && enc->transited.contents.length == 0) + return 0; + if(enc->transited.tr_type != DOMAIN_X500_COMPRESS) return KRB5KDC_ERR_TRTYPE_NOSUPP; @@ -561,6 +565,7 @@ krb5_rd_req_return_keyblock(krb5_context context, krb5_error_code ret; krb5_ap_req ap_req; krb5_principal service = NULL; + krb5_keyblock *local_keyblock; if (*auth_context == NULL) { ret = krb5_auth_con_init(context, auth_context); @@ -592,13 +597,13 @@ krb5_rd_req_return_keyblock(krb5_context context, &ap_req, server, keytab, - keyblock); + &local_keyblock); if(ret) goto out; } else { ret = krb5_copy_keyblock(context, (*auth_context)->keyblock, - keyblock); + &local_keyblock); if (ret) goto out; } @@ -607,17 +612,20 @@ krb5_rd_req_return_keyblock(krb5_context context, auth_context, &ap_req, server, - *keyblock, + local_keyblock, 0, ap_req_options, ticket); + if (ret) { + krb5_free_keyblock(context, local_keyblock); + } else { + *keyblock = local_keyblock; + } out: free_AP_REQ(&ap_req); if(service) krb5_free_principal(context, service); - if (ret) - krb5_free_keyblock(context, *keyblock); return ret; } -- cgit From cfdcc32f8480e538246ca1771e58e9a4835f22b6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 10 Sep 2005 22:25:13 +0000 Subject: r10149: Update Samba4 to current lorikeet-heimdal. Andrew Bartlett (This used to be commit b9695d5e7cc052a952d8d60bc1ab08e00f4827e8) --- source4/heimdal/lib/krb5/principal.c | 32 ++++++++++++++++++------ source4/heimdal/lib/krb5/rd_req.c | 47 +++++++++++++++++------------------- 2 files changed, 47 insertions(+), 32 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index 8540636403..ae5c8c1de8 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -91,10 +91,16 @@ krb5_principal_get_comp_string(krb5_context context, return princ_ncomp(principal, component); } -krb5_error_code +enum realm_presence { + MAY, + MUSTNOT, + MUST +}; + +static krb5_error_code parse_name(krb5_context context, const char *name, - krb5_boolean short_form, + enum realm_presence realm_presence, krb5_principal *principal) { krb5_error_code ret; @@ -186,7 +192,7 @@ parse_name(krb5_context context, *q++ = c; } if (got_realm) { - if (short_form) { + if (realm_presence == MUSTNOT) { krb5_set_error_string (context, "realm found in 'short' principal expected to be without one!"); ret = KRB5_PARSE_MALFORMED; goto exit; @@ -201,12 +207,16 @@ parse_name(krb5_context context, realm[q - start] = 0; } }else{ - if (short_form) { + if (realm_presence == MAY) { ret = krb5_get_default_realm (context, &realm); if (ret) goto exit; - } else { + } else if (realm_presence == MUSTNOT) { realm = NULL; + } else if (realm_presence == MUST) { + krb5_set_error_string (context, "realm NOT found in principal expected to be with one!"); + ret = KRB5_PARSE_MALFORMED; + goto exit; } comp[n] = malloc(q - start + 1); @@ -245,7 +255,7 @@ krb5_parse_name(krb5_context context, const char *name, krb5_principal *principal) { - return parse_name(context, name, FALSE, principal); + return parse_name(context, name, MAY, principal); } krb5_error_code KRB5_LIB_FUNCTION @@ -253,7 +263,15 @@ krb5_parse_name_norealm(krb5_context context, const char *name, krb5_principal *principal) { - return parse_name(context, name, TRUE, principal); + return parse_name(context, name, MUSTNOT, principal); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name_mustrealm(krb5_context context, + const char *name, + krb5_principal *principal) +{ + return parse_name(context, name, MUST, principal); } static const char quotable_chars[] = " \n\t\b\\/@"; static const char replace_chars[] = " ntb\\/@"; diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 66172c10fb..582b71db03 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -560,12 +560,15 @@ krb5_rd_req_return_keyblock(krb5_context context, krb5_keytab keytab, krb5_flags *ap_req_options, krb5_ticket **ticket, - krb5_keyblock **keyblock) + krb5_keyblock **return_keyblock) { krb5_error_code ret; krb5_ap_req ap_req; + krb5_keyblock *keyblock = NULL; krb5_principal service = NULL; - krb5_keyblock *local_keyblock; + + if (return_keyblock) + *return_keyblock = NULL; if (*auth_context == NULL) { ret = krb5_auth_con_init(context, auth_context); @@ -597,13 +600,13 @@ krb5_rd_req_return_keyblock(krb5_context context, &ap_req, server, keytab, - &local_keyblock); + &keyblock); if(ret) goto out; } else { ret = krb5_copy_keyblock(context, (*auth_context)->keyblock, - &local_keyblock); + &keyblock); if (ret) goto out; } @@ -612,21 +615,20 @@ krb5_rd_req_return_keyblock(krb5_context context, auth_context, &ap_req, server, - local_keyblock, + keyblock, 0, ap_req_options, ticket); - if (ret) { - krb5_free_keyblock(context, local_keyblock); - } else { - *keyblock = local_keyblock; - } + + if (ret == 0 && return_keyblock) + *return_keyblock = keyblock; + else + krb5_free_keyblock(context, keyblock); out: free_AP_REQ(&ap_req); if(service) krb5_free_principal(context, service); - return ret; } @@ -639,19 +641,14 @@ krb5_rd_req(krb5_context context, krb5_flags *ap_req_options, krb5_ticket **ticket) { - krb5_error_code ret; - krb5_keyblock *keyblock; - - ret = krb5_rd_req_return_keyblock(context, - auth_context, - inbuf, - server, - keytab, - ap_req_options, - ticket, - &keyblock); - - krb5_free_keyblock(context, keyblock); - return ret; + return krb5_rd_req_return_keyblock(context, + auth_context, + inbuf, + server, + keytab, + ap_req_options, + ticket, + NULL); + } -- cgit From f9263dd1023499479d64be1eb1b5b04c15ca3ce6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 20 Sep 2005 07:03:47 +0000 Subject: r10337: This grubby little hack is the implementation of a concept discussed on the kerberos mailing lists a couple of weeks ago: Don't use DNS at all for expanding short names into long names. Using the 'override krb5_init_context' code already in the tree, this removes the DNS lag on a kerberos session setup/connection. Andrew Bartlett (This used to be commit de3ceab3d064a286e8662a2b9b62b212f0454156) --- source4/heimdal/lib/krb5/context.c | 1 + source4/heimdal/lib/krb5/expand_hostname.c | 9 +++++++++ source4/heimdal/lib/krb5/krb5.h | 1 + 3 files changed, 11 insertions(+) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index 4d6eae2b24..3140f1b08f 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -182,6 +182,7 @@ init_context_from_config_file(krb5_context context) INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc"); INIT_FIELD(context, int, large_msg_size, 6000, "large_message_size"); context->default_cc_name = NULL; + INIT_FIELD(context, bool, fdns, TRUE, "fdns"); return 0; } diff --git a/source4/heimdal/lib/krb5/expand_hostname.c b/source4/heimdal/lib/krb5/expand_hostname.c index 8488119552..f03bf15807 100644 --- a/source4/heimdal/lib/krb5/expand_hostname.c +++ b/source4/heimdal/lib/krb5/expand_hostname.c @@ -65,6 +65,10 @@ krb5_expand_hostname (krb5_context context, memset (&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; + if (!context->fdns) { + return copy_hostname (context, orig_hostname, new_hostname); + } + error = getaddrinfo (orig_hostname, NULL, &hints, &ai); if (error) return copy_hostname (context, orig_hostname, new_hostname); @@ -124,6 +128,11 @@ krb5_expand_hostname_realms (krb5_context context, int error; krb5_error_code ret = 0; + if (!context->fdns) { + return vanilla_hostname (context, orig_hostname, new_hostname, + realms); + } + memset (&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index c47c4450f1..90b239cf0d 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -443,6 +443,7 @@ typedef struct krb5_context_data { int pkinit_flags; void *mutex; /* protects error_string/error_buf */ int large_msg_size; + krb5_boolean fdns; /* Lookup hostnames to find full name, or send as-is */ } krb5_context_data; enum { -- cgit From 42f2519b507bcb70157039a390529bf4b5df4d9c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 21 Sep 2005 10:17:56 +0000 Subject: r10382: In the absence of client support for the full KDC-side canonicalisation code, I've hacked Heimdal to use the default realm if no other realm can be determined for a given host. Andrew Bartlett (This used to be commit 0f0b0021b7728ce75ca0060003a3d08264ead810) --- source4/heimdal/lib/krb5/get_host_realm.c | 33 +++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/get_host_realm.c b/source4/heimdal/lib/krb5/get_host_realm.c index feb01f0036..78684f20a9 100644 --- a/source4/heimdal/lib/krb5/get_host_realm.c +++ b/source4/heimdal/lib/krb5/get_host_realm.c @@ -187,15 +187,18 @@ _krb5_get_host_realm_int (krb5_context context, return 0; } } - p = strchr(host, '.'); - if(p != NULL) { - p++; - *realms = malloc(2 * sizeof(krb5_realm)); - if (*realms == NULL) { + + *realms = malloc(2 * sizeof(krb5_realm)); + if (*realms == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; - } + } + + (*realms)[1] = NULL; + p = strchr(host, '.'); + if(p != NULL) { + p++; (*realms)[0] = strdup(p); if((*realms)[0] == NULL) { free(*realms); @@ -203,11 +206,21 @@ _krb5_get_host_realm_int (krb5_context context, return ENOMEM; } strupr((*realms)[0]); - (*realms)[1] = NULL; - return 0; + } else { + krb5_error_code ret; + ret = krb5_get_default_realm(context, &(*realms)[0]); + if(ret) { + free(*realms); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + if((*realms)[0] == NULL) { + free(*realms); + krb5_set_error_string(context, "unable to find realm of host %s", host); + return KRB5_ERR_HOST_REALM_UNKNOWN; + } } - krb5_set_error_string(context, "unable to find realm of host %s", host); - return KRB5_ERR_HOST_REALM_UNKNOWN; + return 0; } /* -- cgit From c44efdaa2242f50d75dd5b800e372dd5586c6deb Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 21 Sep 2005 12:24:41 +0000 Subject: r10386: Merge current lorikeet-heimdal into Samba4. Andrew Bartlett (This used to be commit 4d2a9a9bc497eae269c24cbf156b43b8588e2f73) --- source4/heimdal/lib/krb5/changepw.c | 20 ++--- source4/heimdal/lib/krb5/crypto.c | 136 +++++++++++++++++--------------- source4/heimdal/lib/krb5/kcm.c | 9 ++- source4/heimdal/lib/krb5/krb5-private.h | 8 -- source4/heimdal/lib/krb5/krb5-protos.h | 17 +--- source4/heimdal/lib/krb5/pkinit.c | 15 ++-- 6 files changed, 101 insertions(+), 104 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/changepw.c b/source4/heimdal/lib/krb5/changepw.c index e6ef1d9d9b..c3cd6d4db9 100644 --- a/source4/heimdal/lib/krb5/changepw.c +++ b/source4/heimdal/lib/krb5/changepw.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: changepw.c,v 1.53 2005/05/25 05:30:42 lha Exp $"); +RCSID("$Id: changepw.c,v 1.54 2005/09/08 11:38:01 lha Exp $"); static void str2data (krb5_data *d, @@ -67,7 +67,7 @@ chgpw_send_request (krb5_context context, krb5_principal targprinc, int is_stream, int sock, - char *passwd, + const char *passwd, const char *host) { krb5_error_code ret; @@ -98,7 +98,7 @@ chgpw_send_request (krb5_context context, if (ret) return ret; - passwd_data.data = passwd; + passwd_data.data = rk_UNCONST(passwd); passwd_data.length = strlen(passwd); krb5_data_zero (&krb_priv_data); @@ -160,7 +160,7 @@ setpw_send_request (krb5_context context, krb5_principal targprinc, int is_stream, int sock, - char *passwd, + const char *passwd, const char *host) { krb5_error_code ret; @@ -186,7 +186,7 @@ setpw_send_request (krb5_context context, return ret; chpw.newpasswd.length = strlen(passwd); - chpw.newpasswd.data = passwd; + chpw.newpasswd.data = rk_UNCONST(passwd); if (targprinc) { chpw.targname = &targprinc->name; chpw.targrealm = &targprinc->realm; @@ -456,7 +456,7 @@ typedef krb5_error_code (*kpwd_send_request) (krb5_context, krb5_principal, int, int, - char *, + const char *, const char *); typedef krb5_error_code (*kpwd_process_reply) (krb5_context, krb5_auth_context, @@ -509,7 +509,7 @@ static krb5_error_code change_password_loop (krb5_context context, krb5_creds *creds, krb5_principal targprinc, - char *newpw, + const char *newpw, int *result_code, krb5_data *result_code_string, krb5_data *result_string, @@ -663,7 +663,7 @@ change_password_loop (krb5_context context, krb5_error_code KRB5_LIB_FUNCTION krb5_change_password (krb5_context context, krb5_creds *creds, - char *newpw, + const char *newpw, int *result_code, krb5_data *result_code_string, krb5_data *result_string) @@ -689,7 +689,7 @@ krb5_change_password (krb5_context context, krb5_error_code KRB5_LIB_FUNCTION krb5_set_password(krb5_context context, krb5_creds *creds, - char *newpw, + const char *newpw, krb5_principal targprinc, int *result_code, krb5_data *result_code_string, @@ -732,7 +732,7 @@ krb5_set_password(krb5_context context, krb5_error_code KRB5_LIB_FUNCTION krb5_set_password_using_ccache(krb5_context context, krb5_ccache ccache, - char *newpw, + const char *newpw, krb5_principal targprinc, int *result_code, krb5_data *result_code_string, diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 1c3e8d2a10..2e23306c96 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.128 2005/07/20 07:22:43 lha Exp $"); +RCSID("$Id: crypto.c,v 1.129 2005/09/19 22:13:54 lha Exp $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -188,68 +188,6 @@ krb5_DES_schedule(krb5_context context, DES_set_key(key->key->keyvalue.data, key->schedule->data); } -static void -DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key) -{ - DES_key_schedule schedule; - int i; - int reverse = 0; - unsigned char *p; - - unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, - 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; - memset(key, 0, 8); - - p = (unsigned char*)key; - for (i = 0; i < length; i++) { - unsigned char tmp = data[i]; - if (!reverse) - *p++ ^= (tmp << 1); - else - *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4]; - if((i % 8) == 7) - reverse = !reverse; - } - DES_set_odd_parity(key); - if(DES_is_weak_key(key)) - (*key)[7] ^= 0xF0; - DES_set_key(key, &schedule); - DES_cbc_cksum((void*)data, key, length, &schedule, key); - memset(&schedule, 0, sizeof(schedule)); - DES_set_odd_parity(key); - if(DES_is_weak_key(key)) - (*key)[7] ^= 0xF0; -} - -static krb5_error_code -krb5_DES_string_to_key(krb5_context context, - krb5_enctype enctype, - krb5_data password, - krb5_salt salt, - krb5_data opaque, - krb5_keyblock *key) -{ - unsigned char *s; - size_t len; - DES_cblock tmp; - - len = password.length + salt.saltvalue.length; - s = malloc(len); - if(len > 0 && s == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - memcpy(s, password.data, password.length); - memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); - DES_string_to_key_int(s, len, &tmp); - key->keytype = enctype; - krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); - memset(&tmp, 0, sizeof(tmp)); - memset(s, 0, len); - free(s); - return 0; -} - #ifdef ENABLE_AFS_STRING_TO_KEY /* This defines the Andrew string_to_key function. It accepts a password @@ -349,6 +287,78 @@ DES_AFS3_string_to_key(krb5_context context, } #endif /* ENABLE_AFS_STRING_TO_KEY */ +static void +DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key) +{ + DES_key_schedule schedule; + int i; + int reverse = 0; + unsigned char *p; + + unsigned char swap[] = { 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, + 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf }; + memset(key, 0, 8); + + p = (unsigned char*)key; + for (i = 0; i < length; i++) { + unsigned char tmp = data[i]; + if (!reverse) + *p++ ^= (tmp << 1); + else + *--p ^= (swap[tmp & 0xf] << 4) | swap[(tmp & 0xf0) >> 4]; + if((i % 8) == 7) + reverse = !reverse; + } + DES_set_odd_parity(key); + if(DES_is_weak_key(key)) + (*key)[7] ^= 0xF0; + DES_set_key(key, &schedule); + DES_cbc_cksum((void*)data, key, length, &schedule, key); + memset(&schedule, 0, sizeof(schedule)); + DES_set_odd_parity(key); + if(DES_is_weak_key(key)) + (*key)[7] ^= 0xF0; +} + +static krb5_error_code +krb5_DES_string_to_key(krb5_context context, + krb5_enctype enctype, + krb5_data password, + krb5_salt salt, + krb5_data opaque, + krb5_keyblock *key) +{ + unsigned char *s; + size_t len; + DES_cblock tmp; + +#ifdef ENABLE_AFS_STRING_TO_KEY + if (opaque.length == 1) { + unsigned long v; + _krb5_get_int(opaque.data, &v, 1); + if (v == 1) + return DES_AFS3_string_to_key(context, enctype, password, + salt, opaque, key); + } +#endif + + len = password.length + salt.saltvalue.length; + s = malloc(len); + if(len > 0 && s == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + memcpy(s, password.data, password.length); + memcpy(s + password.length, salt.saltvalue.data, salt.saltvalue.length); + DES_string_to_key_int(s, len, &tmp); + key->keytype = enctype; + krb5_data_copy(&key->keyvalue, tmp, sizeof(tmp)); + memset(&tmp, 0, sizeof(tmp)); + memset(s, 0, len); + free(s); + return 0; +} + static void krb5_DES_random_to_key(krb5_context context, krb5_keyblock *key, diff --git a/source4/heimdal/lib/krb5/kcm.c b/source4/heimdal/lib/krb5/kcm.c index b7873f33d5..f4372422ac 100644 --- a/source4/heimdal/lib/krb5/kcm.c +++ b/source4/heimdal/lib/krb5/kcm.c @@ -43,7 +43,7 @@ #include "kcm.h" -RCSID("$Id: kcm.c,v 1.7 2005/06/17 04:20:11 lha Exp $"); +RCSID("$Id: kcm.c,v 1.8 2005/09/19 20:23:05 lha Exp $"); typedef struct krb5_kcmcache { char *name; @@ -246,7 +246,8 @@ kcm_call(krb5_context context, krb5_data *response_data_p) { krb5_data response_data; - krb5_error_code ret, status; + krb5_error_code ret; + int32_t status; krb5_storage *response; if (response_p != NULL) @@ -605,7 +606,7 @@ kcm_get_first (krb5_context context, krb5_kcmcache *k = KCMCACHE(id); krb5_storage *request, *response; krb5_data response_data; - u_int32_t tmp; + int32_t tmp; ret = kcm_storage_request(context, KCM_OP_GET_FIRST, &request); if (ret) @@ -624,7 +625,7 @@ kcm_get_first (krb5_context context, } ret = krb5_ret_int32(response, &tmp); - if (ret) + if (ret || tmp < 0) ret = KRB5_CC_IO; krb5_storage_free(request); diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 8e2ebcf43e..ef47bd1e26 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -340,14 +340,6 @@ _krb5_put_int ( unsigned long /*value*/, size_t /*size*/); -krb5_error_code KRB5_LIB_FUNCTION -_krb5_rd_rep_type ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - const krb5_data */*inbuf*/, - krb5_ap_rep_enc_part **/*repl*/, - krb5_boolean /*dce_style_response*/); - int _krb5_send_and_recv_tcp ( int /*fd*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 97f286b83e..8db553e6e3 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -20,15 +20,6 @@ extern "C" { #endif #endif -void -initialize_heim_error_table_r (struct et_list **/*list*/); - -void -initialize_k524_error_table_r (struct et_list **/*list*/); - -void -initialize_krb5_error_table_r (struct et_list **/*list*/); - krb5_error_code KRB5_LIB_FUNCTION krb524_convert_creds_kdc ( krb5_context /*context*/, @@ -706,7 +697,7 @@ krb5_error_code KRB5_LIB_FUNCTION krb5_change_password ( krb5_context /*context*/, krb5_creds */*creds*/, - char */*newpw*/, + const char */*newpw*/, int */*result_code*/, krb5_data */*result_code_string*/, krb5_data */*result_string*/); @@ -2629,7 +2620,7 @@ krb5_rd_req_return_keyblock ( krb5_keytab /*keytab*/, krb5_flags */*ap_req_options*/, krb5_ticket **/*ticket*/, - krb5_keyblock **/*keyblock*/); + krb5_keyblock **/*return_keyblock*/); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_req_with_keyblock ( @@ -2854,7 +2845,7 @@ krb5_error_code KRB5_LIB_FUNCTION krb5_set_password ( krb5_context /*context*/, krb5_creds */*creds*/, - char */*newpw*/, + const char */*newpw*/, krb5_principal /*targprinc*/, int */*result_code*/, krb5_data */*result_code_string*/, @@ -2864,7 +2855,7 @@ krb5_error_code KRB5_LIB_FUNCTION krb5_set_password_using_ccache ( krb5_context /*context*/, krb5_ccache /*ccache*/, - char */*newpw*/, + const char */*newpw*/, krb5_principal /*targprinc*/, int */*result_code*/, krb5_data */*result_code_string*/, diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 69f72d7b88..7ac1436f6e 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.59 2005/08/12 08:53:00 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.62 2005/09/20 23:21:36 lha Exp $"); #ifdef PKINIT @@ -867,10 +867,11 @@ _krb5_pk_mk_padata(krb5_context context, if (ret) goto out; } else { +#if 0 ret = pk_mk_padata(context, COMPAT_19, ctx, req_body, nonce, md); if (ret) goto out; - +#endif ret = pk_mk_padata(context, COMPAT_27, ctx, req_body, nonce, md); if (ret) goto out; @@ -1143,7 +1144,7 @@ _krb5_pk_verify_sign(krb5_context context, EVP_PKEY *public_key; krb5_error_code ret; EVP_MD_CTX md; - X509 *cert; + X509 *cert = NULL; SignedData sd; size_t size; @@ -1187,7 +1188,6 @@ _krb5_pk_verify_sign(krb5_context context, set.len = sd.certificates->len; ret = cert_to_X509(context, &set, &certificates); - free_CertificateSet(&set); } if (ret) { krb5_set_error_string(context, @@ -1860,10 +1860,13 @@ _krb5_pk_rd_pa_reply(krb5_context context, return ret; default: free_PA_PK_AS_REP(&rep); - krb5_set_error_string(context, "PKINIT: -25 reply " + krb5_set_error_string(context, "PKINIT: -27 reply " "invalid content type"); + ret = EINVAL; break; } + if (ret == 0) + return ret; } /* Check for PK-INIT -19 */ @@ -1911,7 +1914,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, &w2krep, &size); if (ret) { - krb5_set_error_string(context, "PKINIT: Failed decoding windows" + krb5_set_error_string(context, "PKINIT: Failed decoding windows " "pkinit reply %d", ret); return ret; } -- cgit From 3b7f8ddd9a7c0d372a0585790913ac95c9eb3324 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 21 Sep 2005 22:55:39 +0000 Subject: r10398: Don't do DNS lookups on short names (no .). Andrew Bartlett (This used to be commit 77aca9619d24a8e118f53bcd1a1e54b8437812a8) --- source4/heimdal/lib/krb5/krbhst.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index 49eee08ca5..98e9cb3f09 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -634,6 +634,11 @@ common_init(krb5_context context, return NULL; } + /* For 'realms' without a . do not even think of going to DNS */ + if (!strchr(realm, '.')) { + kd->flags |= KD_CONFIG_EXISTS; + } + if (flags & KRB5_KRBHST_FLAGS_LARGE_MSG) kd->flags |= KD_LARGE_MSG; kd->end = kd->index = &kd->hosts; -- cgit From 8407a1a8665e188d9dc6774ce1535802e4e3cb29 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 28 Sep 2005 01:09:10 +0000 Subject: r10561: This patch takes over KDC socket routines in Heimdal, and directs them at the Samba4 socket layer. The intention here is to ensure that other events may be processed while heimdal is waiting on the KDC. The interface is designed to be sufficiently flexible, so that the plugin may choose how to time communication with the KDC (ie multiple outstanding requests, looking for a functional KDC). I've hacked the socket layer out of cldap.c to handle this very specific case of one udp packet and reply. Likewise I also handle TCP, stolen from the winbind code. This same plugin system might also be useful for a self-contained testing mode in Heimdal, in conjunction with libkdc. I would suggest using socket-wrapper instead however. Andrew Bartlett (This used to be commit 3b09f9e8f9f6f645cd03073ef833c8d0fb0d84e2) --- source4/heimdal/lib/krb5/context.c | 1 + source4/heimdal/lib/krb5/krb5-protos.h | 5 ++++ source4/heimdal/lib/krb5/krb5.h | 8 +++++ source4/heimdal/lib/krb5/send_to_kdc.c | 55 +++++++++++++++++++++++++++++----- 4 files changed, 61 insertions(+), 8 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index 3140f1b08f..594665235b 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -263,6 +263,7 @@ krb5_free_context(krb5_context context) krb5_closelog(context, context->warn_dest); krb5_set_extra_addresses(context, NULL); krb5_set_ignore_addresses(context, NULL); + free(context->send_and_recv); if (context->mutex != NULL) { HEIMDAL_MUTEX_destroy(context->mutex); free(context->mutex); diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 8db553e6e3..681ac4189b 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -3432,6 +3432,11 @@ krb5_write_safe_message ( krb5_error_code KRB5_LIB_FUNCTION krb5_xfree (void */*ptr*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_send_recv_func(krb5_context context, + krb5_send_and_recv_func_t func, + krb5_send_and_recv_close_func_t close_fn, + void *data); #ifdef __cplusplus } diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 90b239cf0d..800683ef0c 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -444,6 +444,7 @@ typedef struct krb5_context_data { void *mutex; /* protects error_string/error_buf */ int large_msg_size; krb5_boolean fdns; /* Lookup hostnames to find full name, or send as-is */ + struct send_and_recv *send_and_recv; /* Alternate functions for KDC communication */ } krb5_context_data; enum { @@ -744,6 +745,13 @@ enum { KRB5_KRBHST_FLAGS_LARGE_MSG = 2 }; +typedef int (*krb5_send_and_recv_func_t)(krb5_context, + void *, + krb5_krbhst_info *, + const krb5_data *, + krb5_data *); +typedef void (*krb5_send_and_recv_close_func_t)(krb5_context, void*); + struct credentials; /* this is to keep the compiler happy */ struct getargs; struct sockaddr; diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index d55f8dc692..7bb4adabbd 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -35,6 +35,30 @@ RCSID("$Id: send_to_kdc.c,v 1.56 2005/06/17 04:33:11 lha Exp $"); +struct send_and_recv { + krb5_send_and_recv_func_t func; + krb5_send_and_recv_close_func_t close; + void *data; +}; + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_send_recv_func(krb5_context context, + krb5_send_and_recv_func_t func, + krb5_send_and_recv_close_func_t close_fn, + void *data) +{ + free(context->send_and_recv); + context->send_and_recv = malloc(sizeof(*context->send_and_recv)); + if (!context->send_and_recv) { + return ENOMEM; + } + context->send_and_recv->func = func; + context->send_and_recv->close = close_fn; + context->send_and_recv->data = data; + return 0; +} + + /* * send the data in `req' on the socket `fd' (which is datagram iff udp) * waiting `tmout' for a reply and returning the reply in `rep'. @@ -329,11 +353,27 @@ krb5_sendto (krb5_context context, while (krb5_krbhst_next(context, handle, &hi) == 0) { struct addrinfo *ai, *a; + if (context->send_and_recv) { + ret = context->send_and_recv->func(context, + context->send_and_recv->data, + hi, send_data, receive); + if (ret) { + continue; + } else if (receive->length != 0) { + return 0; + } else { + continue; + } + } + if(hi->proto == KRB5_KRBHST_HTTP && context->http_proxy) { - if (send_via_proxy (context, hi, send_data, receive)) + if (send_via_proxy (context, hi, send_data, receive)) { + /* Try again, with next host */ continue; - else - goto out; + } else { + /* Success */ + return 0; + } } ret = krb5_krbhst_get_addrinfo(context, hi, &ai); @@ -363,16 +403,15 @@ krb5_sendto (krb5_context context, break; } close (fd); - if(ret == 0 && receive->length != 0) - goto out; + if(ret == 0 && receive->length != 0) { + return 0; + } } } krb5_krbhst_reset(context, handle); } krb5_clear_error_string (context); - ret = KRB5_KDC_UNREACH; -out: - return ret; + return KRB5_KDC_UNREACH; } krb5_error_code KRB5_LIB_FUNCTION -- cgit From 5a30cd8097f043fc7466e72f6d63305883392a46 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 14 Oct 2005 05:29:44 +0000 Subject: r10983: Another case were we want to avoid DNS for unqualified names. Andrew Bartlett (This used to be commit 1d7094b8dfd53dfda55db7ce30f47f74864093bf) --- source4/heimdal/lib/krb5/get_host_realm.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/get_host_realm.c b/source4/heimdal/lib/krb5/get_host_realm.c index 78684f20a9..33a3438b12 100644 --- a/source4/heimdal/lib/krb5/get_host_realm.c +++ b/source4/heimdal/lib/krb5/get_host_realm.c @@ -233,6 +233,7 @@ krb5_get_host_realm(krb5_context context, krb5_realm **realms) { char hostname[MAXHOSTNAMELEN]; + krb5_boolean use_dns; if (host == NULL) { if (gethostname (hostname, sizeof(hostname))) @@ -240,5 +241,11 @@ krb5_get_host_realm(krb5_context context, host = hostname; } - return _krb5_get_host_realm_int (context, host, 1, realms); + if (strchr(host, '.') == NULL) { + use_dns = FALSE; + } else { + use_dns = TRUE; + } + + return _krb5_get_host_realm_int (context, host, use_dns, realms); } -- cgit From 4019064c5d866015a0d78b32dd051ec1dacf8ebf Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 25 Oct 2005 13:43:37 +0000 Subject: r11294: Update Heimdal in Samba4 to lorikeet-heimdal (which is in turn updated to CVS of 2005-10-24). Andrew Bartlett (This used to be commit 939d4f340feaad15d0a6a5da79feba2b2558f174) --- source4/heimdal/lib/krb5/acache.c | 110 ++++- source4/heimdal/lib/krb5/cache.c | 215 +++++++- source4/heimdal/lib/krb5/init_creds.c | 36 +- source4/heimdal/lib/krb5/init_creds_pw.c | 32 +- source4/heimdal/lib/krb5/keytab_keyfile.c | 75 ++- source4/heimdal/lib/krb5/krb5-private.h | 42 +- source4/heimdal/lib/krb5/krb5-protos.h | 36 +- source4/heimdal/lib/krb5/krb5.h | 9 +- source4/heimdal/lib/krb5/krb5_locl.h | 5 +- source4/heimdal/lib/krb5/krbhst.c | 33 +- source4/heimdal/lib/krb5/mcache.c | 89 +++- source4/heimdal/lib/krb5/pkinit.c | 789 ++++++++++++++++++------------ source4/heimdal/lib/krb5/rd_cred.c | 53 +- 13 files changed, 1079 insertions(+), 445 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c index 75f5315c71..7cf2c65d89 100644 --- a/source4/heimdal/lib/krb5/acache.c +++ b/source4/heimdal/lib/krb5/acache.c @@ -37,7 +37,7 @@ #include #endif -RCSID("$Id: acache.c,v 1.11 2005/06/16 19:32:44 lha Exp $"); +RCSID("$Id: acache.c,v 1.14 2005/10/03 08:44:18 lha Exp $"); /* XXX should we fetch these for each open ? */ static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; @@ -67,7 +67,7 @@ static const struct { { ccErrContextNotFound, KRB5_CC_NOTFOUND }, { ccIteratorEnd, KRB5_CC_END }, { ccErrNoMem, KRB5_CC_NOMEM }, - { ccErrServerUnavailable, KRB5_CC_BADNAME }, + { ccErrServerUnavailable, KRB5_CC_NOSUPP }, { ccNoError, 0 } }; @@ -110,7 +110,7 @@ init_ccapi(krb5_context context) if (cc_handle == NULL) { HEIMDAL_MUTEX_unlock(&acc_mutex); krb5_set_error_string(context, "Failed to load %s", lib); - return ccErrServerUnavailable; + return KRB5_CC_NOSUPP; } init_func = dlsym(cc_handle, "cc_initialize"); @@ -119,14 +119,14 @@ init_ccapi(krb5_context context) krb5_set_error_string(context, "Failed to find cc_initialize" "in %s: %s", lib, dlerror()); dlclose(cc_handle); - return ccErrServerUnavailable; + return KRB5_CC_NOSUPP; } return 0; #else HEIMDAL_MUTEX_unlock(&acc_mutex); krb5_set_error_string(context, "no support for shared object"); - return ccErrServerUnavailable; + return KRB5_CC_NOSUPP; #endif } @@ -633,8 +633,10 @@ acc_get_first (krb5_context context, int32_t error; error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter); - if (error) + if (error) { + krb5_clear_error_string(context); return ENOENT; + } *cursor = iter; return 0; } @@ -761,6 +763,97 @@ acc_get_version(krb5_context context, return 0; } +struct cache_iter { + cc_context_t context; + cc_ccache_iterator_t iter; +}; + +static krb5_error_code +acc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) +{ + struct cache_iter *iter; + krb5_error_code ret; + cc_int32 error; + + ret = init_ccapi(context); + if (ret) + return ret; + + iter = calloc(1, sizeof(*iter)); + if (iter == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + error = (*init_func)(&iter->context, ccapi_version_3, NULL, NULL); + if (error) { + free(iter); + return translate_cc_error(context, error); + } + + error = (*iter->context->func->new_ccache_iterator)(iter->context, + &iter->iter); + if (error) { + free(iter); + krb5_clear_error_string(context); + return ENOENT; + } + *cursor = iter; + return 0; +} + +static krb5_error_code +acc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) +{ + struct cache_iter *iter = cursor; + cc_ccache_t cache; + krb5_acc *a; + krb5_error_code ret; + int32_t error; + + error = (*iter->iter->func->next)(iter->iter, &cache); + if (error) + return translate_cc_error(context, error); + + ret = _krb5_cc_allocate(context, &krb5_acc_ops, id); + if (ret) { + (*cache->func->release)(cache); + return ret; + } + + ret = acc_alloc(context, id); + if (ret) { + (*cache->func->release)(cache); + free(*id); + return ret; + } + + a = ACACHE(*id); + a->ccache = cache; + + a->cache_name = get_cc_name(a->ccache); + if (a->cache_name == NULL) { + acc_close(context, *id); + *id = NULL; + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + +static krb5_error_code +acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) +{ + struct cache_iter *iter = cursor; + + (*iter->iter->func->release)(iter->iter); + iter->iter = NULL; + (*iter->context->func->release)(iter->context); + iter->context = NULL; + free(iter); + return 0; +} + const krb5_cc_ops krb5_acc_ops = { "API", acc_get_name, @@ -777,5 +870,8 @@ const krb5_cc_ops krb5_acc_ops = { acc_end_get, acc_remove_cred, acc_set_flags, - acc_get_version + acc_get_version, + acc_get_cache_first, + acc_get_cache_next, + acc_end_cache_get }; diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index f293a96ed9..ec956409a7 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c,v 1.71 2005/06/16 20:19:57 lha Exp $"); +RCSID("$Id: cache.c,v 1.73 2005/10/19 17:30:40 lha Exp $"); /* * Add a new ccache type with operations `ops', overwriting any @@ -76,6 +76,29 @@ krb5_cc_register(krb5_context context, return 0; } +/* + * Allocate the memory for a `id' and the that function table to + * `ops'. Returns 0 or and error code. + */ + +krb5_error_code +_krb5_cc_allocate(krb5_context context, + const krb5_cc_ops *ops, + krb5_ccache *id) +{ + krb5_ccache p; + + p = malloc (sizeof(*p)); + if(p == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return KRB5_CC_NOMEM; + } + p->ops = ops; + *id = p; + + return 0; +} + /* * Allocate memory for a new ccache in `id' with operations `ops' * and name `residual'. @@ -89,18 +112,13 @@ allocate_ccache (krb5_context context, krb5_ccache *id) { krb5_error_code ret; - krb5_ccache p; - p = malloc(sizeof(*p)); - if(p == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return KRB5_CC_NOMEM; - } - p->ops = ops; - *id = p; - ret = p->ops->resolve(context, id, residual); + ret = _krb5_cc_allocate(context, ops, id); + if (ret) + return ret; + ret = (*id)->ops->resolve(context, id, residual); if(ret) - free(p); + free(*id); return ret; } @@ -145,16 +163,12 @@ krb5_cc_gen_new(krb5_context context, const krb5_cc_ops *ops, krb5_ccache *id) { - krb5_ccache p; + krb5_error_code ret; - p = malloc (sizeof(*p)); - if (p == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return KRB5_CC_NOMEM; - } - p->ops = ops; - *id = p; - return p->ops->gen_new(context, id); + ret = _krb5_cc_allocate(context, ops, id); + if (ret) + return ret; + return (*id)->ops->gen_new(context, id); } /* @@ -641,17 +655,172 @@ krb5_cc_clear_mcred(krb5_creds *mcred) /* * Get the cc ops that is registered in `context' to handle the - * `prefix'. Returns NULL if ops not found. + * `prefix'. `prefix' can be a complete credential cache name or a + * prefix, the function will only use part up to the first colon (:) + * if there is one. Returns NULL if ops not found. */ const krb5_cc_ops * krb5_cc_get_prefix_ops(krb5_context context, const char *prefix) { + char *p, *p1; int i; + + p = strdup(prefix); + if (p == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return NULL; + } + p1 = strchr(p, ':'); + if (p1) + *p1 = '\0'; for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) { - if(strcmp(context->cc_ops[i].prefix, prefix) == 0) + if(strcmp(context->cc_ops[i].prefix, p) == 0) { + free(p); return &context->cc_ops[i]; + } } + free(p); return NULL; } + +struct krb5_cc_cache_cursor_data { + const krb5_cc_ops *ops; + krb5_cc_cursor cursor; +}; + +/* + * Start iterating over all caches of `type'. If `type' is NULL, the + * default type is * used. `cursor' is initialized to the beginning. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_get_first (krb5_context context, + const char *type, + krb5_cc_cache_cursor *cursor) +{ + const krb5_cc_ops *ops; + krb5_error_code ret; + + if (type == NULL) + type = krb5_cc_default_name(context); + + ops = krb5_cc_get_prefix_ops(context, type); + if (ops == NULL) { + krb5_set_error_string(context, "Unknown type \"%s\" when iterating " + "trying to iterate the credential caches", type); + return KRB5_CC_UNKNOWN_TYPE; + } + + if (ops->get_cache_first == NULL) { + krb5_set_error_string(context, "Credential cache type %s doesn't support " + "iterations over caches", ops->prefix); + return KRB5_CC_NOSUPP; + } + + *cursor = calloc(1, sizeof(**cursor)); + if (*cursor == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + (*cursor)->ops = ops; + + ret = ops->get_cache_first(context, &(*cursor)->cursor); + if (ret) { + free(*cursor); + *cursor = NULL; + } + return ret; +} + +/* + * Retrieve the next cache pointed to by (`cursor') in `id' + * and advance `cursor'. + * Return 0 or an error code. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_next (krb5_context context, + krb5_cc_cache_cursor cursor, + krb5_ccache *id) +{ + return cursor->ops->get_cache_next(context, cursor->cursor, id); +} + +/* + * Destroy the cursor `cursor'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_end_seq_get (krb5_context context, + krb5_cc_cache_cursor cursor) +{ + krb5_error_code ret; + ret = cursor->ops->end_cache_get(context, cursor->cursor); + cursor->ops = NULL; + free(cursor); + return ret; +} + +/* + * Search for a matching credential cache of type `type' that have the + * `principal' as the default principal. If NULL is used for `type', + * the default type is used. On success, `id' needs to be freed with + * krb5_cc_close or krb5_cc_destroy. On failure, error code is + * returned and `id' is set to NULL. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_match (krb5_context context, + krb5_principal client, + const char *type, + krb5_ccache *id) +{ + krb5_cc_cache_cursor cursor; + krb5_error_code ret; + krb5_ccache cache = NULL; + + *id = NULL; + + ret = krb5_cc_cache_get_first (context, type, &cursor); + if (ret) + return ret; + + while ((ret = krb5_cc_cache_next (context, cursor, &cache)) == 0) { + krb5_principal principal; + + ret = krb5_cc_get_principal(context, cache, &principal); + if (ret == 0) { + krb5_boolean match; + + match = krb5_principal_compare(context, principal, client); + krb5_free_principal(context, principal); + if (match) + break; + } + + krb5_cc_close(context, cache); + cache = NULL; + } + + krb5_cc_cache_end_seq_get(context, cursor); + + if (cache == NULL) { + char *str; + + krb5_unparse_name(context, client, &str); + + krb5_set_error_string(context, "Principal %s not found in a " + "credential cache", str ? str : ""); + if (str) + free(str); + return KRB5_CC_NOTFOUND; + } + *id = cache; + + return 0; +} + diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index 95c980d92c..51b8ebc392 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,14 +33,14 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c,v 1.20 2004/11/09 18:50:43 lha Exp $"); +RCSID("$Id: init_creds.c,v 1.21 2005/10/12 12:45:27 lha Exp $"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) { memset (opt, 0, sizeof(*opt)); opt->flags = 0; - opt->private = NULL; + opt->opt_private = NULL; } krb5_error_code KRB5_LIB_FUNCTION @@ -56,13 +56,13 @@ krb5_get_init_creds_opt_alloc(krb5_context context, return ENOMEM; } krb5_get_init_creds_opt_init(o); - o->private = calloc(1, sizeof(*o->private)); - if (o->private == NULL) { + o->opt_private = calloc(1, sizeof(*o->opt_private)); + if (o->opt_private == NULL) { krb5_set_error_string(context, "out of memory"); free(o); return ENOMEM; } - o->private->refcount = 1; + o->opt_private->refcount = 1; *opt = o; return 0; } @@ -82,16 +82,16 @@ _krb5_get_init_creds_opt_copy(krb5_context context, } if (in) *opt = *in; - if(opt->private == NULL) { - opt->private = calloc(1, sizeof(*opt->private)); - if (opt->private == NULL) { + if(opt->opt_private == NULL) { + opt->opt_private = calloc(1, sizeof(*opt->opt_private)); + if (opt->opt_private == NULL) { krb5_set_error_string(context, "out of memory"); free(opt); return ENOMEM; } - opt->private->refcount = 1; + opt->opt_private->refcount = 1; } else - opt->private->refcount++; + opt->opt_private->refcount++; *out = opt; return 0; } @@ -99,13 +99,13 @@ _krb5_get_init_creds_opt_copy(krb5_context context, void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt) { - if (opt->private == NULL) + if (opt->opt_private == NULL) return; - if (opt->private->refcount < 1) /* abort ? */ + if (opt->opt_private->refcount < 1) /* abort ? */ return; - if (--opt->private->refcount == 0) { + if (--opt->opt_private->refcount == 0) { _krb5_get_init_creds_opt_free_pkinit(opt); - free(opt->private); + free(opt->opt_private); } memset(opt, 0, sizeof(*opt)); free(opt); @@ -293,7 +293,7 @@ require_ext_opt(krb5_context context, krb5_get_init_creds_opt *opt, const char *type) { - if (opt->private == NULL) { + if (opt->opt_private == NULL) { krb5_set_error_string(context, "%s on non extendable opt", type); return EINVAL; } @@ -310,8 +310,8 @@ krb5_get_init_creds_opt_set_pa_password(krb5_context context, ret = require_ext_opt(context, opt, "init_creds_opt_set_pa_password"); if (ret) return ret; - opt->private->password = password; - opt->private->key_proc = key_proc; + opt->opt_private->password = password; + opt->opt_private->key_proc = key_proc; return 0; } @@ -324,7 +324,7 @@ krb5_get_init_creds_opt_set_pac_request(krb5_context context, ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req"); if (ret) return ret; - opt->private->req_pac = req_pac ? + opt->opt_private->req_pac = req_pac ? KRB5_PA_PAC_REQ_TRUE : KRB5_PA_PAC_REQ_FALSE; return 0; diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 8fd5c4611f..3c694624bf 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c,v 1.88 2005/08/13 08:25:32 lha Exp $"); +RCSID("$Id: init_creds_pw.c,v 1.90 2005/10/12 12:45:11 lha Exp $"); typedef struct krb5_get_init_creds_ctx { krb5_kdc_flags flags; @@ -275,11 +275,11 @@ get_init_creds_common(krb5_context context, options = &default_opt; } - if (options->private) { - ctx->password = options->private->password; - ctx->key_proc = options->private->key_proc; - ctx->req_pac = options->private->req_pac; - ctx->pk_init_ctx = options->private->pk_init_ctx; + if (options->opt_private) { + ctx->password = options->opt_private->password; + ctx->key_proc = options->opt_private->key_proc; + ctx->req_pac = options->opt_private->req_pac; + ctx->pk_init_ctx = options->opt_private->pk_init_ctx; } else ctx->req_pac = KRB5_PA_PAC_DONT_CARE; @@ -1014,10 +1014,10 @@ pa_data_to_md_pkinit(krb5_context context, return 0; #ifdef PKINIT return _krb5_pk_mk_padata(context, - ctx->pk_init_ctx, - &a->req_body, - ctx->pk_nonce, - md); + ctx->pk_init_ctx, + &a->req_body, + ctx->pk_nonce, + md); #else krb5_set_error_string(context, "no support for PKINIT compiled in"); return EINVAL; @@ -1114,6 +1114,7 @@ process_pa_data_to_key(krb5_context context, krb5_creds *creds, AS_REQ *a, krb5_kdc_rep *rep, + const krb5_krbhst_info *hi, krb5_keyblock **key) { struct pa_info_data paid, *ppaid = NULL; @@ -1158,6 +1159,7 @@ process_pa_data_to_key(krb5_context context, ret = _krb5_pk_rd_pa_reply(context, ctx->pk_init_ctx, etype, + hi, ctx->pk_nonce, &ctx->req_buffer, pa, @@ -1194,6 +1196,8 @@ init_cred_loop(krb5_context context, size_t len; size_t size; int send_to_kdc_flags = 0; + krb5_krbhst_info *hi = NULL; + memset(&md, 0, sizeof(md)); memset(&rep, 0, sizeof(rep)); @@ -1321,7 +1325,7 @@ init_cred_loop(krb5_context context, krb5_keyblock *key = NULL; ret = process_pa_data_to_key(context, ctx, creds, - &ctx->as_req, &rep, &key); + &ctx->as_req, &rep, hi, &key); if (ret) goto out; @@ -1462,8 +1466,8 @@ krb5_get_init_creds_password(krb5_context context, return ret; if (password == NULL && - options->private->password == NULL && - options->private->pk_init_ctx == NULL) + options->opt_private->password == NULL && + options->opt_private->pk_init_ctx == NULL) { krb5_prompt prompt; krb5_data password_data; @@ -1491,7 +1495,7 @@ krb5_get_init_creds_password(krb5_context context, password = password_data.data; } - if (options->private->password == NULL) { + if (options->opt_private->password == NULL) { ret = krb5_get_init_creds_opt_set_pa_password(context, options, password, NULL); if (ret) { diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c index b53fa36a03..5c94291e72 100644 --- a/source4/heimdal/lib/krb5/keytab_keyfile.c +++ b/source4/heimdal/lib/krb5/keytab_keyfile.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2002, 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_keyfile.c,v 1.16 2005/01/08 22:57:18 lha Exp $"); +RCSID("$Id: keytab_keyfile.c,v 1.17 2005/09/30 11:20:53 lha Exp $"); /* afs keyfile operations --------------------------------------- */ @@ -288,9 +288,16 @@ akf_add_entry(krb5_context context, krb5_storage *sp; - if (entry->keyblock.keyvalue.length != 8 - || entry->keyblock.keytype != ETYPE_DES_CBC_MD5) + if (entry->keyblock.keyvalue.length != 8) return 0; + switch(entry->keyblock.keytype) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + break; + default: + return 0; + } fd = open (d->filename, O_RDWR | O_BINARY); if (fd < 0) { @@ -329,50 +336,72 @@ akf_add_entry(krb5_context context, return ret; } } + + /* + * Make sure we don't add the entry twice, assumes the DES + * encryption types are all the same key. + */ + if (len > 0) { + int32_t kvno; + int i; + + for (i = 0; i < len; i++) { + ret = krb5_ret_int32(sp, &kvno); + if (ret) { + krb5_set_error_string (context, "Failed got get kvno "); + goto out; + } + if(krb5_storage_seek(sp, 8, SEEK_CUR) < 0) { + krb5_set_error_string (context, "seek: %s", strerror(ret)); + goto out; + } + if (kvno == entry->vno) { + ret = 0; + goto out; + } + } + } + len++; if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) { ret = errno; - krb5_storage_free(sp); - close(fd); krb5_set_error_string (context, "seek: %s", strerror(ret)); - return ret; + goto out; } ret = krb5_store_int32(sp, len); if(ret) { - krb5_storage_free(sp); - close(fd); + krb5_set_error_string(context, "keytab keyfile failed new length"); return ret; } - if(krb5_storage_seek(sp, (len - 1) * (8 + 4), SEEK_CUR) < 0) { ret = errno; - krb5_storage_free(sp); - close(fd); - krb5_set_error_string (context, "seek: %s", strerror(ret)); - return ret; + krb5_set_error_string (context, "seek to end: %s", strerror(ret)); + goto out; } ret = krb5_store_int32(sp, entry->vno); if(ret) { - krb5_storage_free(sp); - close(fd); - return ret; + krb5_set_error_string(context, "keytab keyfile failed store kvno"); + goto out; } ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data, entry->keyblock.keyvalue.length); if(ret != entry->keyblock.keyvalue.length) { - krb5_storage_free(sp); - close(fd); - if(ret < 0) - return errno; - return ENOTTY; + if (ret < 0) + ret = errno; + else + ret = ENOTTY; + krb5_set_error_string(context, "keytab keyfile failed to add key"); + goto out; } + ret = 0; +out: krb5_storage_free(sp); close (fd); - return 0; + return ret; } const krb5_kt_ops krb5_akf_ops = { diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index ef47bd1e26..07d9329337 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -31,6 +31,12 @@ _krb5_aes_cts_encrypt ( unsigned char */*ivec*/, const int /*encryptp*/); +krb5_error_code +_krb5_cc_allocate ( + krb5_context /*context*/, + const krb5_cc_ops */*ops*/, + krb5_ccache */*id*/); + void _krb5_crc_init_table (void); @@ -40,6 +46,16 @@ _krb5_crc_update ( size_t /*len*/, u_int32_t /*res*/); +krb5_error_code +_krb5_dh_group_ok ( + krb5_context /*context*/, + unsigned long /*bits*/, + heim_integer */*p*/, + heim_integer */*g*/, + heim_integer */*q*/, + struct krb5_dh_moduli **/*moduli*/, + char **/*name*/); + krb5_error_code _krb5_expand_default_cc_name ( krb5_context /*context*/, @@ -61,6 +77,9 @@ _krb5_extract_ticket ( krb5_decrypt_proc /*decrypt_proc*/, krb5_const_pointer /*decryptarg*/); +void +_krb5_free_krbhst_info (krb5_krbhst_info */*hi*/); + krb5_error_code _krb5_get_default_principal_local ( krb5_context /*context*/, @@ -233,6 +252,12 @@ _krb5_krb_time_to_life ( time_t /*start*/, time_t /*end*/); +krb5_error_code +_krb5_krbhost_info_move ( + krb5_context /*context*/, + krb5_krbhst_info */*from*/, + krb5_krbhst_info **/*to*/); + krb5_error_code _krb5_mk_req_internal ( krb5_context /*context*/, @@ -257,6 +282,20 @@ _krb5_oid_to_enctype ( const heim_oid */*oid*/, krb5_enctype */*etype*/); +krb5_error_code +_krb5_parse_moduli ( + krb5_context /*context*/, + const char */*file*/, + struct krb5_dh_moduli ***/*moduli*/); + +krb5_error_code +_krb5_parse_moduli_line ( + krb5_context /*context*/, + const char */*file*/, + int /*lineno*/, + char */*p*/, + struct krb5_dh_moduli **/*m*/); + void KRB5_LIB_FUNCTION _krb5_pk_cert_free (struct krb5_pk_cert */*cert*/); @@ -308,6 +347,7 @@ _krb5_pk_rd_pa_reply ( krb5_context /*context*/, void */*c*/, krb5_enctype /*etype*/, + const krb5_krbhst_info */*hi*/, unsigned /*nonce*/, const krb5_data */*req_buffer*/, PA_DATA */*pa*/, @@ -316,7 +356,7 @@ _krb5_pk_rd_pa_reply ( krb5_error_code KRB5_LIB_FUNCTION _krb5_pk_verify_sign ( krb5_context /*context*/, - const char */*data*/, + const void */*data*/, size_t /*length*/, struct krb5_pk_identity */*id*/, heim_oid */*contentType*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 681ac4189b..a46f8b8f8f 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -535,6 +535,30 @@ krb5_c_verify_checksum ( const krb5_checksum */*cksum*/, krb5_boolean */*valid*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_end_seq_get ( + krb5_context /*context*/, + krb5_cc_cache_cursor /*cursor*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_get_first ( + krb5_context /*context*/, + const char */*type*/, + krb5_cc_cache_cursor */*cursor*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_match ( + krb5_context /*context*/, + krb5_principal /*client*/, + const char */*type*/, + krb5_ccache */*id*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_cache_next ( + krb5_context /*context*/, + krb5_cc_cache_cursor /*cursor*/, + krb5_ccache */*id*/); + void KRB5_LIB_FUNCTION krb5_cc_clear_mcred (krb5_creds */*mcred*/); @@ -2867,6 +2891,13 @@ krb5_set_real_time ( krb5_timestamp /*sec*/, int32_t /*usec*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_send_recv_func ( + krb5_context /*context*/, + krb5_send_and_recv_func_t /*func*/, + krb5_send_and_recv_close_func_t /*close_fn*/, + void */*data*/); + void KRB5_LIB_FUNCTION krb5_set_use_admin_kdc ( krb5_context /*context*/, @@ -3432,11 +3463,6 @@ krb5_write_safe_message ( krb5_error_code KRB5_LIB_FUNCTION krb5_xfree (void */*ptr*/); -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_send_recv_func(krb5_context context, - krb5_send_and_recv_func_t func, - krb5_send_and_recv_close_func_t close_fn, - void *data); #ifdef __cplusplus } diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 800683ef0c..ef595d4d20 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h,v 1.237 2005/07/09 14:47:21 lha Exp $ */ +/* $Id: krb5.h,v 1.239 2005/10/12 12:39:28 lha Exp $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -368,6 +368,8 @@ typedef struct krb5_creds { krb5_ticket_flags flags; } krb5_creds; +typedef struct krb5_cc_cache_cursor_data *krb5_cc_cache_cursor; + typedef struct krb5_cc_ops { const char *prefix; const char* (*get_name)(krb5_context, krb5_ccache); @@ -388,6 +390,9 @@ typedef struct krb5_cc_ops { krb5_flags, krb5_creds*); krb5_error_code (*set_flags)(krb5_context, krb5_ccache, krb5_flags); int (*get_version)(krb5_context, krb5_ccache); + krb5_error_code (*get_cache_first)(krb5_context, krb5_cc_cursor *); + krb5_error_code (*get_cache_next)(krb5_context, krb5_cc_cursor, krb5_ccache *); + krb5_error_code (*end_cache_get)(krb5_context, krb5_cc_cursor); } krb5_cc_ops; struct krb5_log_facility; @@ -659,7 +664,7 @@ typedef struct _krb5_get_init_creds_opt { krb5_preauthtype *preauth_list; int preauth_list_length; krb5_data *salt; - struct _krb5_get_init_creds_opt_private *private; + struct _krb5_get_init_creds_opt_private *opt_private; } krb5_get_init_creds_opt; #define KRB5_GET_INIT_CREDS_OPT_TKT_LIFE 0x0001 diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index a64ccc586e..4a02677239 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_locl.h,v 1.81 2005/05/29 14:28:39 lha Exp $ */ +/* $Id: krb5_locl.h,v 1.83 2005/10/07 12:08:02 lha Exp $ */ #ifndef __KRB5_LOCL_H__ #define __KRB5_LOCL_H__ @@ -141,6 +141,7 @@ struct krb5_pk_identity; struct krb5_pk_cert; struct ContentInfo; typedef struct krb5_pk_init_ctx_data *krb5_pk_init_ctx; +struct krb5_dh_moduli; /* v4 glue */ struct _krb5_krb_auth_data; @@ -161,6 +162,8 @@ struct _krb5_krb_auth_data; #define KEYTAB_DEFAULT "ANY:FILE:" SYSCONFDIR "/krb5.keytab,krb4:" SYSCONFDIR "/srvtab" #define KEYTAB_DEFAULT_MODIFY "FILE:" SYSCONFDIR "/krb5.keytab" +#define MODULI_FILE SYSCONFDIR "/krb5.moduli" + #ifndef O_BINARY #define O_BINARY 0 #endif diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index 98e9cb3f09..ef9f5dbd60 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: krbhst.c,v 1.52 2005/06/17 04:23:26 lha Exp $"); +RCSID("$Id: krbhst.c,v 1.53 2005/10/08 15:40:50 lha Exp $"); static int string_to_proto(const char *string) @@ -228,14 +228,37 @@ parse_hostspec(krb5_context context, struct krb5_krbhst_data *kd, return hi; } -static void -free_krbhst_info(krb5_krbhst_info *hi) +void +_krb5_free_krbhst_info(krb5_krbhst_info *hi) { if (hi->ai != NULL) freeaddrinfo(hi->ai); free(hi); } +krb5_error_code +_krb5_krbhost_info_move(krb5_context context, + krb5_krbhst_info *from, + krb5_krbhst_info **to) +{ + /* trailing NUL is included in structure */ + *to = calloc(1, sizeof(**to) + strlen(from->hostname)); + if(*to == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + (*to)->proto = from->proto; + (*to)->port = from->port; + (*to)->def_port = from->def_port; + (*to)->ai = from->ai; + from->ai = NULL; + (*to)->next = NULL; + strcpy((*to)->hostname, from->hostname); + return 0; +} + + static void append_host_hostinfo(struct krb5_krbhst_data *kd, struct krb5_krbhst_info *host) { @@ -245,7 +268,7 @@ append_host_hostinfo(struct krb5_krbhst_data *kd, struct krb5_krbhst_info *host) if(h->proto == host->proto && h->port == host->port && strcmp(h->hostname, host->hostname) == 0) { - free_krbhst_info(host); + _krb5_free_krbhst_info(host); return; } *kd->end = host; @@ -752,7 +775,7 @@ krb5_krbhst_free(krb5_context context, krb5_krbhst_handle handle) for (h = handle->hosts; h != NULL; h = next) { next = h->next; - free_krbhst_info(h); + _krb5_free_krbhst_info(h); } free(handle->realm); diff --git a/source4/heimdal/lib/krb5/mcache.c b/source4/heimdal/lib/krb5/mcache.c index 0a65d53849..9588d936d5 100644 --- a/source4/heimdal/lib/krb5/mcache.c +++ b/source4/heimdal/lib/krb5/mcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: mcache.c,v 1.19 2004/04/25 19:25:35 joda Exp $"); +RCSID("$Id: mcache.c,v 1.20 2005/09/30 11:16:04 lha Exp $"); typedef struct krb5_mcache { char *name; @@ -162,20 +162,25 @@ mcc_initialize(krb5_context context, &m->primary_principal); } -static krb5_error_code -mcc_close(krb5_context context, - krb5_ccache id) +static int +mcc_close_internal(krb5_mcache *m) { - krb5_mcache *m = MCACHE(id); - if (--m->refcnt != 0) return 0; if (MISDEAD(m)) { free (m->name); - krb5_data_free(&id->data); + return 1; } + return 0; +} +static krb5_error_code +mcc_close(krb5_context context, + krb5_ccache id) +{ + if (mcc_close_internal(MCACHE(id))) + krb5_data_free(&id->data); return 0; } @@ -334,6 +339,70 @@ mcc_set_flags(krb5_context context, return 0; /* XXX */ } +struct mcache_iter { + krb5_mcache *cache; +}; + +static krb5_error_code +mcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) +{ + struct mcache_iter *iter; + + iter = calloc(1, sizeof(*iter)); + if (iter == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + HEIMDAL_MUTEX_lock(&mcc_mutex); + iter->cache = mcc_head; + if (iter->cache) + iter->cache->refcnt++; + HEIMDAL_MUTEX_unlock(&mcc_mutex); + + *cursor = iter; + return 0; +} + +static krb5_error_code +mcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) +{ + struct mcache_iter *iter = cursor; + krb5_error_code ret; + krb5_mcache *m; + + if (iter->cache == NULL) + return KRB5_CC_END; + + HEIMDAL_MUTEX_lock(&mcc_mutex); + m = iter->cache; + if (m->next) + m->next->refcnt++; + iter->cache = m->next; + HEIMDAL_MUTEX_unlock(&mcc_mutex); + + ret = _krb5_cc_allocate(context, &krb5_mcc_ops, id); + if (ret) + return ret; + + (*id)->data.data = m; + (*id)->data.length = sizeof(*m); + + return 0; +} + +static krb5_error_code +mcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) +{ + struct mcache_iter *iter = cursor; + + if (iter->cache) + mcc_close_internal(iter->cache); + iter->cache = NULL; + free(iter); + return 0; +} + const krb5_cc_ops krb5_mcc_ops = { "MEMORY", mcc_get_name, @@ -349,5 +418,9 @@ const krb5_cc_ops krb5_mcc_ops = { mcc_get_next, mcc_end_get, mcc_remove_cred, - mcc_set_flags + mcc_set_flags, + NULL, + mcc_get_cache_first, + mcc_get_cache_next, + mcc_end_cache_get }; diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 7ac1436f6e..0c5dfc44e9 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.62 2005/09/20 23:21:36 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.75 2005/10/21 17:18:38 lha Exp $"); #ifdef PKINIT @@ -57,12 +57,9 @@ RCSID("$Id: pkinit.c,v 1.62 2005/09/20 23:21:36 lha Exp $"); enum { COMPAT_WIN2K = 1, - COMPAT_19 = 2, - COMPAT_27 = 3 + COMPAT_IETF = 2 }; - - #define OPENSSL_ASN1_MALLOC_ENCODE(T, B, BL, S, R) \ { \ unsigned char *p; \ @@ -107,12 +104,22 @@ struct krb5_pk_cert { X509 *cert; }; +struct krb5_dh_moduli { + char *name; + unsigned long bits; + heim_integer p; + heim_integer g; + heim_integer q; +}; + struct krb5_pk_init_ctx_data { struct krb5_pk_identity *id; DH *dh; + krb5_data *clientDHNonce; + struct krb5_dh_moduli **m; + int require_binding; }; - void KRB5_LIB_FUNCTION _krb5_pk_cert_free(struct krb5_pk_cert *cert) { @@ -135,6 +142,20 @@ BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer) return 0; } +static BIGNUM * +integer_to_BN(krb5_context context, const char *field, const heim_integer *f) +{ + BIGNUM *bn; + + bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL); + if (bn == NULL) { + krb5_set_error_string(context, "PKINIT: parsing BN failed %s", field); + return NULL; + } + bn->neg = f->negative; + return bn; +} + /* * UI ex_data has the callback_data as passed to Engine. This is far * from being complete, we will only process one prompt @@ -251,7 +272,8 @@ _krb5_pk_create_sign(krb5_context context, krb5_data buf; SignedData sd; EVP_MD_CTX md; - int len, i; + int i; + unsigned len; size_t size; X509_NAME *issuer_name; @@ -443,75 +465,10 @@ _krb5_pk_create_sign(krb5_context context, return ret; } -static krb5_error_code -build_auth_pack_win2k(krb5_context context, - unsigned nonce, - const KDC_REQ_BODY *body, - AuthPack_Win2k *a) -{ - krb5_error_code ret; - krb5_timestamp sec; - int32_t usec; - - /* fill in PKAuthenticator */ - ret = copy_PrincipalName(body->sname, &a->pkAuthenticator.kdcName); - if (ret) - return ret; - ret = copy_Realm(&body->realm, &a->pkAuthenticator.kdcRealm); - if (ret) - return ret; - - krb5_us_timeofday(context, &sec, &usec); - a->pkAuthenticator.ctime = sec; - a->pkAuthenticator.cusec = usec; - a->pkAuthenticator.nonce = nonce; - - return 0; -} - -static krb5_error_code -build_auth_pack_19(krb5_context context, - unsigned nonce, - const KDC_REQ_BODY *body, - AuthPack_19 *a) -{ - size_t buf_size, len; - krb5_cksumtype cksum; - krb5_error_code ret; - void *buf; - krb5_timestamp sec; - int32_t usec; - - krb5_clear_error_string(context); - - /* XXX some PACKETCABLE needs implemetations need md5 */ - cksum = CKSUMTYPE_RSA_MD5; - - krb5_us_timeofday(context, &sec, &usec); - a->pkAuthenticator.ctime = sec; - a->pkAuthenticator.nonce = nonce; - - ASN1_MALLOC_ENCODE(KDC_REQ_BODY, buf, buf_size, body, &len, ret); - if (ret) - return ret; - if (buf_size != len) - krb5_abortx(context, "internal error in ASN.1 encoder"); - - ret = krb5_create_checksum(context, - NULL, - 0, - cksum, - buf, - len, - &a->pkAuthenticator.paChecksum); - free(buf); - - return ret; -} - static krb5_error_code build_auth_pack(krb5_context context, unsigned nonce, + krb5_pk_init_ctx ctx, DH *dh, const KDC_REQ_BODY *body, AuthPack *a) @@ -545,18 +502,39 @@ build_auth_pack(krb5_context context, len, &checksum); free(buf); - if (ret == 0) { - ret = krb5_data_copy(&a->pkAuthenticator.paChecksum, - checksum.checksum.data, checksum.checksum.length); - free_Checksum(&checksum); - } + if (ret) + return ret; - if (ret == 0 && dh) { + ret = krb5_data_copy(&a->pkAuthenticator.paChecksum, + checksum.checksum.data, checksum.checksum.length); + free_Checksum(&checksum); + if (ret) + return ret; + + if (dh) { DomainParameters dp; heim_integer dh_pub_key; krb5_data dhbuf; size_t size; + if (1 /* support_cached_dh */) { + ALLOC(a->clientDHNonce, 1); + if (a->clientDHNonce == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + ret = krb5_data_alloc(a->clientDHNonce, 40); + if (a->clientDHNonce == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + memset(a->clientDHNonce->data, 0, a->clientDHNonce->length); + ret = krb5_copy_data(context, a->clientDHNonce, + &ctx->clientDHNonce); + if (ret) + return ret; + } + ALLOC(a->clientPublicValue, 1); if (a->clientPublicValue == NULL) return ENOMEM; @@ -606,20 +584,11 @@ build_auth_pack(krb5_context context, if (ret) return ret; - dhbuf.length = length_heim_integer(&dh_pub_key); - dhbuf.data = malloc(dhbuf.length); - if (dhbuf.data == NULL) { - free_heim_integer(&dh_pub_key); - krb5_set_error_string(context, "malloc: out of memory"); - return ret; - } - ret = der_put_heim_integer((char *)dhbuf.data + dhbuf.length - 1, - dhbuf.length, &dh_pub_key, &size); + ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length, + &dh_pub_key, &size, ret); free_heim_integer(&dh_pub_key); - if (ret) { - free(dhbuf.data); + if (ret) return ret; - } if (size != dhbuf.length) krb5_abortx(context, "asn1 internal error"); @@ -663,27 +632,40 @@ pk_mk_padata(krb5_context context, struct ContentInfo content_info; krb5_error_code ret; const heim_oid *oid; - PA_PK_AS_REQ req; size_t size; krb5_data buf, sd_buf; int pa_type; krb5_data_zero(&buf); krb5_data_zero(&sd_buf); - memset(&req, 0, sizeof(req)); memset(&content_info, 0, sizeof(content_info)); if (compat == COMPAT_WIN2K) { AuthPack_Win2k ap; + krb5_timestamp sec; + int32_t usec; memset(&ap, 0, sizeof(ap)); - ret = build_auth_pack_win2k(context, nonce, req_body, &ap); + /* fill in PKAuthenticator */ + ret = copy_PrincipalName(req_body->sname, &ap.pkAuthenticator.kdcName); + if (ret) { + free_AuthPack_Win2k(&ap); + krb5_clear_error_string(context); + goto out; + } + ret = copy_Realm(&req_body->realm, &ap.pkAuthenticator.kdcRealm); if (ret) { free_AuthPack_Win2k(&ap); + krb5_clear_error_string(context); goto out; } + krb5_us_timeofday(context, &sec, &usec); + ap.pkAuthenticator.ctime = sec; + ap.pkAuthenticator.cusec = usec; + ap.pkAuthenticator.nonce = nonce; + ASN1_MALLOC_ENCODE(AuthPack_Win2k, buf.data, buf.length, &ap, &size, ret); free_AuthPack_Win2k(&ap); @@ -695,33 +677,12 @@ pk_mk_padata(krb5_context context, krb5_abortx(context, "internal ASN1 encoder error"); oid = oid_id_pkcs7_data(); - } else if (compat == COMPAT_19) { - AuthPack_19 ap; - - memset(&ap, 0, sizeof(ap)); - - ret = build_auth_pack_19(context, nonce, req_body, &ap); - if (ret) { - free_AuthPack_19(&ap); - goto out; - } - - ASN1_MALLOC_ENCODE(AuthPack_19, buf.data, buf.length, &ap, &size, ret); - free_AuthPack_19(&ap); - if (ret) { - krb5_set_error_string(context, "AuthPack_19: %d", ret); - goto out; - } - if (buf.length != size) - krb5_abortx(context, "internal ASN1 encoder error"); - - oid = oid_id_pkauthdata(); - } else if (compat == COMPAT_27) { + } else if (compat == COMPAT_IETF) { AuthPack ap; memset(&ap, 0, sizeof(ap)); - ret = build_auth_pack(context, nonce, ctx->dh, req_body, &ap); + ret = build_auth_pack(context, nonce, ctx, ctx->dh, req_body, &ap); if (ret) { free_AuthPack(&ap); goto out; @@ -755,9 +716,12 @@ pk_mk_padata(krb5_context context, if (ret) goto out; - /* XXX tell the kdc what CAs the client is willing to accept */ - req.trustedCertifiers = NULL; - req.kdcPkId = NULL; + ASN1_MALLOC_ENCODE(ContentInfo, buf.data, buf.length, + &content_info, &size, ret); + if (ret) + goto out; + if (buf.length != size) + krb5_abortx(context, "Internal ASN1 encoder error"); if (compat == COMPAT_WIN2K) { PA_PK_AS_REQ_Win2k winreq; @@ -766,60 +730,29 @@ pk_mk_padata(krb5_context context, memset(&winreq, 0, sizeof(winreq)); - ASN1_MALLOC_ENCODE(ContentInfo, - winreq.signed_auth_pack.data, - winreq.signed_auth_pack.length, - &content_info, - &size, - ret); - if (ret) - goto out; - if (winreq.signed_auth_pack.length != size) - krb5_abortx(context, "Internal ASN1 encoder error"); + winreq.signed_auth_pack = buf; ASN1_MALLOC_ENCODE(PA_PK_AS_REQ_Win2k, buf.data, buf.length, &winreq, &size, ret); free_PA_PK_AS_REQ_Win2k(&winreq); - } else if (compat == COMPAT_19) { - PA_PK_AS_REQ_19 req_19; - - pa_type = KRB5_PADATA_PK_AS_REQ_19; - - memset(&req_19, 0, sizeof(req_19)); - - ret = copy_ContentInfo(&content_info, &req_19.signedAuthPack); - if (ret) { - krb5_clear_error_string(context); - goto out; - } - req_19.kdcCert = NULL; - req_19.trustedCertifiers = NULL; - req_19.encryptionCert = NULL; - - ASN1_MALLOC_ENCODE(PA_PK_AS_REQ_19, buf.data, buf.length, - &req_19, &size, ret); - - free_PA_PK_AS_REQ_19(&req_19); - - } else if (compat == COMPAT_27) { + } else if (compat == COMPAT_IETF) { + PA_PK_AS_REQ req; pa_type = KRB5_PADATA_PK_AS_REQ; - ASN1_MALLOC_ENCODE(ContentInfo, - req.signedAuthPack.data, - req.signedAuthPack.length, - &content_info, - &size, - ret); - if (ret) - goto out; - if (req.signedAuthPack.length != size) - krb5_abortx(context, "Internal ASN1 encoder error"); + memset(&req, 0, sizeof(req)); + req.signedAuthPack = buf; + + /* XXX tell the kdc what CAs the client is willing to accept */ + req.trustedCertifiers = NULL; + req.kdcPkId = NULL; ASN1_MALLOC_ENCODE(PA_PK_AS_REQ, buf.data, buf.length, &req, &size, ret); + free_PA_PK_AS_REQ(&req); + } else krb5_abortx(context, "internal pkinit error"); if (ret) { @@ -832,7 +765,11 @@ pk_mk_padata(krb5_context context, ret = krb5_padata_add(context, md, pa_type, buf.data, buf.length); if (ret) free(buf.data); - out: + + if (ret == 0 && compat == COMPAT_WIN2K) + krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0); + +out: free_ContentInfo(&content_info); return ret; @@ -847,11 +784,7 @@ _krb5_pk_mk_padata(krb5_context context, METHOD_DATA *md) { krb5_pk_init_ctx ctx = c; - krb5_error_code ret; - size_t size; - krb5_data buf; - const char *provisioning_server; - int win2k_compat; + int win2k_compat, type; win2k_compat = krb5_config_get_bool_default(context, NULL, FALSE, @@ -863,45 +796,18 @@ _krb5_pk_mk_padata(krb5_context context, win2k_compat = 1; if (win2k_compat) { - ret = pk_mk_padata(context, COMPAT_WIN2K, ctx, req_body, nonce, md); - if (ret) - goto out; - } else { -#if 0 - ret = pk_mk_padata(context, COMPAT_19, ctx, req_body, nonce, md); - if (ret) - goto out; -#endif - ret = pk_mk_padata(context, COMPAT_27, ctx, req_body, nonce, md); - if (ret) - goto out; - } - - provisioning_server = - krb5_config_get_string(context, NULL, - "realms", - req_body->realm, - "packet-cable-provisioning-server", - NULL); - - if (provisioning_server) { - /* PacketCable requires the PROV-SRV-LOCATION authenticator */ - const PROV_SRV_LOCATION prov_server = rk_UNCONST(provisioning_server); - - ASN1_MALLOC_ENCODE(PROV_SRV_LOCATION, buf.data, buf.length, - &prov_server, &size, ret); - if (ret) - goto out; - if (buf.length != size) - krb5_abortx(context, "Internal ASN1 encoder error"); + ctx->require_binding = + krb5_config_get_bool_default(context, NULL, + FALSE, + "realms", + req_body->realm, + "win2k_pkinit_require_binding", + NULL); + type = COMPAT_WIN2K; + } else + type = COMPAT_IETF; - /* PacketCable uses -1 (application specific) as the auth data type */ - ret = krb5_padata_add(context, md, -1, buf.data, buf.length); - if (ret) - free(buf.data); - } - out: - return ret; + return pk_mk_padata(context, type, ctx, req_body, nonce, md); } static krb5_boolean @@ -997,7 +903,7 @@ pk_verify_chain_standard(krb5_context context, int i; int ret; - ret = KRB5_KDC_ERROR_CLIENT_NAME_MISMATCH; + ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; for (i = 0; i < sk_X509_num(chain); i++) { cert = sk_X509_value(chain, i); if (pk_peer_compare(context, client, cert) == TRUE) { @@ -1037,7 +943,7 @@ pk_verify_chain_standard(krb5_context context, ret = 0; break; case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - ret = KRB5_KDC_ERROR_CANT_VERIFY_CERTIFICATE; + ret = KRB5_KDC_ERR_CANT_VERIFY_CERTIFICATE; krb5_set_error_string(context, "PKINIT: failed to verify " "certificate: %s ", X509_verify_cert_error_string(store_ctx->error)); @@ -1048,7 +954,7 @@ pk_verify_chain_standard(krb5_context context, case X509_V_ERR_CERT_NOT_YET_VALID: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: case X509_V_ERR_CERT_HAS_EXPIRED: - ret = KRB5_KDC_ERROR_INVALID_CERTIFICATE; + ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; krb5_set_error_string(context, "PKINIT: invalid certificate: %s ", X509_verify_cert_error_string(store_ctx->error)); break; @@ -1058,13 +964,13 @@ pk_verify_chain_standard(krb5_context context, case X509_V_ERR_CERT_CHAIN_TOO_LONG: case X509_V_ERR_PATH_LENGTH_EXCEEDED: case X509_V_ERR_INVALID_CA: - ret = KRB5_KDC_ERROR_INVALID_CERTIFICATE; + ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; krb5_set_error_string(context, "PKINIT: unknown CA or can't " "verify certificate: %s", X509_verify_cert_error_string(store_ctx->error)); break; default: - ret = KRB5_KDC_ERROR_INVALID_CERTIFICATE; /* XXX */ + ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; /* XXX */ krb5_set_error_string(context, "PKINIT: failed to verify " "certificate: %s (%ld) ", X509_verify_cert_error_string(store_ctx->error), @@ -1131,7 +1037,7 @@ cert_to_X509(krb5_context context, CertificateSet *set, krb5_error_code KRB5_LIB_FUNCTION _krb5_pk_verify_sign(krb5_context context, - const char *data, + const void *data, size_t length, struct krb5_pk_identity *id, heim_oid *contentType, @@ -1280,41 +1186,41 @@ _krb5_pk_verify_sign(krb5_context context, } static krb5_error_code -get_reply_key_19(krb5_context context, - const krb5_data *content, - unsigned nonce, - krb5_keyblock **key) +get_reply_key_win(krb5_context context, + const krb5_data *content, + unsigned nonce, + krb5_keyblock **key) { - ReplyKeyPack_19 key_pack; + ReplyKeyPack_Win2k key_pack; krb5_error_code ret; size_t size; - ret = decode_ReplyKeyPack_19(content->data, - content->length, - &key_pack, - &size); + ret = decode_ReplyKeyPack_Win2k(content->data, + content->length, + &key_pack, + &size); if (ret) { krb5_set_error_string(context, "PKINIT decoding reply key failed"); - free_ReplyKeyPack_19(&key_pack); + free_ReplyKeyPack_Win2k(&key_pack); return ret; } if (key_pack.nonce != nonce) { krb5_set_error_string(context, "PKINIT enckey nonce is wrong"); - free_ReplyKeyPack_19(&key_pack); + free_ReplyKeyPack_Win2k(&key_pack); return KRB5KRB_AP_ERR_MODIFIED; } *key = malloc (sizeof (**key)); if (*key == NULL) { krb5_set_error_string(context, "PKINIT failed allocating reply key"); - free_ReplyKeyPack_19(&key_pack); + free_ReplyKeyPack_Win2k(&key_pack); krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } ret = copy_EncryptionKey(&key_pack.replyKey, *key); - free_ReplyKeyPack_19(&key_pack); + free_ReplyKeyPack_Win2k(&key_pack); if (ret) { krb5_set_error_string(context, "PKINIT failed copying reply key"); free(*key); @@ -1399,6 +1305,7 @@ pk_rd_pa_reply_enckey(krb5_context context, ContentInfo *rep, krb5_pk_init_ctx ctx, krb5_enctype etype, + const krb5_krbhst_info *hi, unsigned nonce, const krb5_data *req_buffer, PA_DATA *pa, @@ -1413,7 +1320,7 @@ pk_rd_pa_reply_enckey(krb5_context context, int length; size_t size; X509 *user_cert; - char *p; + void *p; krb5_boolean bret; krb5_data content; heim_oid contentType = { 0, NULL }; @@ -1481,13 +1388,13 @@ pk_rd_pa_reply_enckey(krb5_context context, goto out; - /* verify content type */ - if (type == COMPAT_WIN2K) { - if (heim_oid_cmp(&ed.encryptedContentInfo.contentType, oid_id_pkcs7_data())) { - ret = KRB5KRB_AP_ERR_MSG_TYPE; - goto out; - } - } else { + /* + * Try to verify content type. We can't do this for W2K case + * because W2K/W2K3 sends id-pkcs7-data, but Windows Vista sends + * id-pkcs7-signedData to all versions, even W2K clients. + */ + + if (type != COMPAT_WIN2K) { if (heim_oid_cmp(&ed.encryptedContentInfo.contentType, oid_id_pkcs7_signedData())) { ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; @@ -1563,7 +1470,7 @@ pk_rd_pa_reply_enckey(krb5_context context, } p = ci.content->data; length = ci.content->length; - } + } ret = _krb5_pk_verify_sign(context, p, @@ -1582,6 +1489,7 @@ pk_rd_pa_reply_enckey(krb5_context context, goto out; } +#if 0 if (type == COMPAT_WIN2K) { if (heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) { krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); @@ -1595,13 +1503,15 @@ pk_rd_pa_reply_enckey(krb5_context context, goto out; } } +#endif switch(type) { case COMPAT_WIN2K: - case COMPAT_19: - ret = get_reply_key_19(context, &content, nonce, key); + ret = get_reply_key(context, &content, req_buffer, key); + if (ret != 0 && ctx->require_binding == 0) + ret = get_reply_key_win(context, &content, nonce, key); break; - case COMPAT_27: + case COMPAT_IETF: ret = get_reply_key(context, &content, req_buffer, key); break; } @@ -1628,6 +1538,7 @@ pk_rd_pa_reply_dh(krb5_context context, ContentInfo *rep, krb5_pk_init_ctx ctx, krb5_enctype etype, + const krb5_krbhst_info *hi, const DHNonce *c_n, const DHNonce *k_n, unsigned nonce, @@ -1674,7 +1585,8 @@ pk_rd_pa_reply_dh(krb5_context context, goto out; if (heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) { - ret = KRB5KRB_AP_ERR_MSG_TYPE; /* XXX */ + krb5_set_error_string(context, "pkinit - dh reply contains wrong oid"); + ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; } @@ -1799,6 +1711,7 @@ krb5_error_code KRB5_LIB_FUNCTION _krb5_pk_rd_pa_reply(krb5_context context, void *c, krb5_enctype etype, + const krb5_krbhst_info *hi, unsigned nonce, const krb5_data *req_buffer, PA_DATA *pa, @@ -1836,8 +1749,10 @@ _krb5_pk_rd_pa_reply(krb5_context context, free_PA_PK_AS_REP(&rep); break; } - ret = pk_rd_pa_reply_dh(context, &ci, ctx, - etype, NULL, NULL, nonce, pa, key); + ret = pk_rd_pa_reply_dh(context, &ci, ctx, etype, hi, + ctx->clientDHNonce, + rep.u.dhInfo.serverDHNonce, + nonce, pa, key); free_ContentInfo(&ci); free_PA_PK_AS_REP(&rep); @@ -1854,8 +1769,8 @@ _krb5_pk_rd_pa_reply(krb5_context context, "ContentInfo: %d", ret); break; } - ret = pk_rd_pa_reply_enckey(context, COMPAT_27, &ci, ctx, - etype, nonce, req_buffer, pa, key); + ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &ci, ctx, + etype, hi, nonce, req_buffer, pa, key); free_ContentInfo(&ci); return ret; default: @@ -1869,40 +1784,6 @@ _krb5_pk_rd_pa_reply(krb5_context context, return ret; } - /* Check for PK-INIT -19 */ - { - PA_PK_AS_REP_19 rep19; - - memset(&rep19, 0, sizeof(rep19)); - - ret = decode_PA_PK_AS_REP_19(pa->padata_value.data, - pa->padata_value.length, - &rep19, - &size); - if (ret == 0) { - switch(rep19.element) { - case choice_PA_PK_AS_REP_19_dhSignedData: - ret = pk_rd_pa_reply_dh(context, &rep19.u.dhSignedData, ctx, - etype, NULL, NULL, - nonce, pa, key); - break; - case choice_PA_PK_AS_REP_19_encKeyPack: - ret = pk_rd_pa_reply_enckey(context, COMPAT_19, - &rep19.u.encKeyPack, ctx, - etype, nonce, NULL, pa, key); - break; - default: - krb5_set_error_string(context, "PKINIT: -19 reply invalid " - "content type"); - ret = EINVAL; - break; - } - free_PA_PK_AS_REP_19(&rep19); - if (ret == 0) - return 0; - } - } - /* Check for Windows encoding of the AS-REP pa data */ { PA_PK_AS_REP_Win2k w2krep; @@ -1918,6 +1799,8 @@ _krb5_pk_rd_pa_reply(krb5_context context, "pkinit reply %d", ret); return ret; } + + krb5_clear_error_string(context); switch (w2krep.element) { case choice_PA_PK_AS_REP_Win2k_encKeyPack: @@ -1934,7 +1817,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, return ret; } ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, ctx, - etype, nonce, NULL, pa, key); + etype, hi, nonce, NULL, pa, key); free_ContentInfo(&ci); break; default: @@ -2546,6 +2429,264 @@ _krb5_pk_load_openssl_id(krb5_context context, return ret; } +static int +parse_integer(krb5_context context, char **p, const char *file, int lineno, + const char *name, heim_integer *integer) +{ + int ret; + char *p1; + p1 = strsep(p, " \t"); + if (p1 == NULL) { + krb5_set_error_string(context, "moduli file %s missing %s on line %d", + file, name, lineno); + return EINVAL; + } + ret = der_parse_hex_heim_integer(p1, integer); + if (ret) { + krb5_set_error_string(context, "moduli file %s failed parsing %s " + "on line %d", + file, name, lineno); + return ret; + } + + return 0; +} + +krb5_error_code +_krb5_parse_moduli_line(krb5_context context, + const char *file, + int lineno, + char *p, + struct krb5_dh_moduli **m) +{ + struct krb5_dh_moduli *m1; + char *p1; + int ret; + + *m = NULL; + + m1 = calloc(1, sizeof(*m1)); + if (m1 == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + + while (isspace((unsigned char)*p)) + p++; + if (*p == '#') + return 0; + ret = EINVAL; + + p1 = strsep(&p, " \t"); + if (p1 == NULL) { + krb5_set_error_string(context, "moduli file %s missing name " + "on line %d", file, lineno); + goto out; + } + m1->name = strdup(p1); + if (p1 == NULL) { + krb5_set_error_string(context, "malloc - out of memeory"); + ret = ENOMEM; + goto out; + } + + p1 = strsep(&p, " \t"); + if (p1 == NULL) { + krb5_set_error_string(context, "moduli file %s missing bits on line %d", + file, lineno); + goto out; + } + + m1->bits = atoi(p1); + if (m1->bits == 0) { + krb5_set_error_string(context, "moduli file %s have un-parsable " + "bits on line %d", file, lineno); + goto out; + } + + ret = parse_integer(context, &p, file, lineno, "p", &m1->p); + if (ret) + goto out; + ret = parse_integer(context, &p, file, lineno, "g", &m1->g); + if (ret) + goto out; + ret = parse_integer(context, &p, file, lineno, "q", &m1->q); + if (ret) + goto out; + + *m = m1; + + return 0; +out: + free(m1->name); + free_heim_integer(&m1->p); + free_heim_integer(&m1->g); + free_heim_integer(&m1->q); + free(m1); + return ret; +} + +static void +_krb5_free_moduli(struct krb5_dh_moduli **moduli) +{ + int i; + for (i = 0; moduli[i] != NULL; i++) { + free(moduli[i]->name); + free_heim_integer(&moduli[i]->p); + free_heim_integer(&moduli[i]->g); + free_heim_integer(&moduli[i]->q); + free(moduli[i]); + } + free(moduli); +} + +static const char *default_moduli = + /* bits */ + "RFC2412-MODP-group2 " + "1024 " + /* p */ + "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" + "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" + "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" + "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" + "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" + "FFFFFFFF" "FFFFFFFF " + /* g */ + "02 " + /* q */ + "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68" + "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E" + "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122" + "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6" + "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F67329C0" + "FFFFFFFF" "FFFFFFFF"; + + +krb5_error_code +_krb5_parse_moduli(krb5_context context, const char *file, + struct krb5_dh_moduli ***moduli) +{ + /* comment bits P G Q */ + krb5_error_code ret; + struct krb5_dh_moduli **m = NULL, **m2; + char buf[4096]; + FILE *f; + int lineno = 0, n = 0; + + *moduli = NULL; + + m = calloc(1, sizeof(m[0]) * 2); + if (m == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + strlcpy(buf, default_moduli, sizeof(buf)); + ret = _krb5_parse_moduli_line(context, "builtin", 1, buf, &m[0]); + if (ret) { + _krb5_free_moduli(m); + return ret; + } + n = 1; + + if (file == NULL) { + *moduli = m; + return 0; + } + + f = fopen(file, "r"); + if (f == NULL) { + *moduli = m; + return 0; + } + + while(fgets(buf, sizeof(buf), f) != NULL) { + struct krb5_dh_moduli *element; + + buf[strcspn(buf, "\n")] = '\0'; + lineno++; + + m2 = realloc(m, (n + 2) * sizeof(m[0])); + if (m2 == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + _krb5_free_moduli(m); + return ENOMEM; + } + m = m2; + + m[n] = NULL; + + ret = _krb5_parse_moduli_line(context, file, lineno, buf, &element); + if (ret) { + _krb5_free_moduli(m); + return ret; + } + if (element == NULL) + continue; + + m[n] = element; + m[n + 1] = NULL; + n++; + } + *moduli = m; + return 0; +} + +krb5_error_code +_krb5_dh_group_ok(krb5_context context, unsigned long bits, + heim_integer *p, heim_integer *g, heim_integer *q, + struct krb5_dh_moduli **moduli, + char **name) +{ + int i; + + if (name) + *name = NULL; + + for (i = 0; moduli[i] != NULL; i++) { + if (heim_integer_cmp(&moduli[i]->g, g) == 0 && + heim_integer_cmp(&moduli[i]->p, p) == 0 && + heim_integer_cmp(&moduli[i]->q, q) == 0) + { + if (bits && bits > moduli[i]->bits) { + krb5_set_error_string(context, "PKINIT: DH group parameter %s " + "no accepted, not enough bits generated", + moduli[i]->name); + return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + } + if (name) + *name = strdup(moduli[i]->name); + return 0; + } + } + krb5_set_error_string(context, "PKINIT: DH group parameter no ok"); + return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; +} + +static krb5_error_code +select_dh_group(krb5_context context, DH *dh, unsigned long bits, + struct krb5_dh_moduli **moduli) +{ + const struct krb5_dh_moduli *m; + + m = moduli[1]; /* XXX */ + if (m == NULL) + m = moduli[0]; /* XXX */ + + dh->p = integer_to_BN(context, "p", &m->p); + if (dh->p == NULL) + return ENOMEM; + dh->g = integer_to_BN(context, "g", &m->g); + if (dh->g == NULL) + return ENOMEM; + dh->q = integer_to_BN(context, "q", &m->q); + if (dh->q == NULL) + return ENOMEM; + + return 0; +} + + #endif /* PKINIT */ void KRB5_LIB_FUNCTION @@ -2554,9 +2695,9 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) #ifdef PKINIT krb5_pk_init_ctx ctx; - if (opt->private == NULL || opt->private->pk_init_ctx == NULL) + if (opt->opt_private == NULL || opt->opt_private->pk_init_ctx == NULL) return; - ctx = opt->private->pk_init_ctx; + ctx = opt->opt_private->pk_init_ctx; if (ctx->dh) DH_free(ctx->dh); ctx->dh = NULL; @@ -2572,10 +2713,16 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) ENGINE_free(ctx->id->engine); ctx->id->engine = NULL; } + if (ctx->clientDHNonce) { + krb5_free_data(NULL, ctx->clientDHNonce); + ctx->clientDHNonce = NULL; + } + if (ctx->m) + _krb5_free_moduli(ctx->m); free(ctx->id); ctx->id = NULL; } - opt->private->pk_init_ctx = NULL; + opt->opt_private->pk_init_ctx = NULL; #endif } @@ -2593,79 +2740,73 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, #ifdef PKINIT krb5_error_code ret; - if (opt->private == NULL) { + if (opt->opt_private == NULL) { krb5_set_error_string(context, "PKINIT: on non extendable opt"); return EINVAL; } - opt->private->pk_init_ctx = malloc(sizeof(*opt->private->pk_init_ctx)); - if (opt->private->pk_init_ctx == NULL) { + opt->opt_private->pk_init_ctx = + calloc(1, sizeof(*opt->opt_private->pk_init_ctx)); + if (opt->opt_private->pk_init_ctx == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - opt->private->pk_init_ctx->dh = NULL; - opt->private->pk_init_ctx->id = NULL; + opt->opt_private->pk_init_ctx->dh = NULL; + opt->opt_private->pk_init_ctx->id = NULL; + opt->opt_private->pk_init_ctx->clientDHNonce = NULL; + opt->opt_private->pk_init_ctx->require_binding = 0; + ret = _krb5_pk_load_openssl_id(context, - &opt->private->pk_init_ctx->id, + &opt->opt_private->pk_init_ctx->id, user_id, x509_anchors, prompter, prompter_data, password); if (ret) { - free(opt->private->pk_init_ctx); - opt->private->pk_init_ctx = NULL; + free(opt->opt_private->pk_init_ctx); + opt->opt_private->pk_init_ctx = NULL; + return ret; } - /* XXX */ - if (ret == 0 && (flags & 1) && !(flags & 2)) { - DH *dh; - const char *P = - "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" - "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" - "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" - "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" - "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE65381" - "FFFFFFFF" "FFFFFFFF"; - const char *G = "2"; - const char *Q = - "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68" - "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E" - "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122" - "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6" - "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F67329C0" - "FFFFFFFF" "FFFFFFFF"; - - dh = DH_new(); - if (dh == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - _krb5_get_init_creds_opt_free_pkinit(opt); - return ENOMEM; - } - opt->private->pk_init_ctx->dh = dh; - if (!BN_hex2bn(&dh->p, P)) { - krb5_set_error_string(context, "malloc: out of memory"); + if ((flags & 2) == 0) { + const char *moduli_file; + + moduli_file = krb5_config_get_string_default(context, NULL, + MODULI_FILE, + "libdefaults", + "moduli", + NULL); + + ret = _krb5_parse_moduli(context, moduli_file, + &opt->opt_private->pk_init_ctx->m); + if (ret) { _krb5_get_init_creds_opt_free_pkinit(opt); - return ENOMEM; + return ret; } - if (!BN_hex2bn(&dh->g, G)) { + + opt->opt_private->pk_init_ctx->dh = DH_new(); + if (opt->opt_private->pk_init_ctx->dh == NULL) { krb5_set_error_string(context, "malloc: out of memory"); _krb5_get_init_creds_opt_free_pkinit(opt); return ENOMEM; } - if (!BN_hex2bn(&dh->q, Q)) { - krb5_set_error_string(context, "malloc: out of memory"); + + ret = select_dh_group(context, opt->opt_private->pk_init_ctx->dh, 0, + opt->opt_private->pk_init_ctx->m); + if (ret) { _krb5_get_init_creds_opt_free_pkinit(opt); - return ENOMEM; + return ret; } - /* XXX generate a new key for each request ? */ - if (DH_generate_key(dh) != 1) { + + if (DH_generate_key(opt->opt_private->pk_init_ctx->dh) != 1) { krb5_set_error_string(context, "malloc: out of memory"); _krb5_get_init_creds_opt_free_pkinit(opt); return ENOMEM; } } - return ret; + + return 0; #else krb5_set_error_string(context, "no support for PKINIT compiled in"); return EINVAL; diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c index 2571591e9d..ddd5866aeb 100644 --- a/source4/heimdal/lib/krb5/rd_cred.c +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_cred.c,v 1.24 2005/07/13 08:22:50 lha Exp $"); +RCSID("$Id: rd_cred.c,v 1.25 2005/09/23 03:37:57 lha Exp $"); static krb5_error_code compare_addrs(krb5_context context, @@ -99,24 +99,49 @@ krb5_rd_cred(krb5_context context, enc_krb_cred_part_data.length = cred.enc_part.cipher.length; enc_krb_cred_part_data.data = cred.enc_part.cipher.data; } else { - if (auth_context->remote_subkey) + /* Try both subkey and session key. + * + * RFC2140 claims we should use the session key, but Heimdal + * before 0.8 used the remote subkey if it was send in the + * auth_context. + */ + + if (auth_context->remote_subkey) { ret = krb5_crypto_init(context, auth_context->remote_subkey, 0, &crypto); - else + if (ret) + goto out; + + ret = krb5_decrypt_EncryptedData(context, + crypto, + KRB5_KU_KRB_CRED, + &cred.enc_part, + &enc_krb_cred_part_data); + + krb5_crypto_destroy(context, crypto); + } + + /* + * If there was not subkey, or we failed using subkey, + * retry using the session key + */ + if (auth_context->remote_subkey == NULL || ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) + { + ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto); - /* DK: MIT rsh */ - if (ret) - goto out; - - ret = krb5_decrypt_EncryptedData(context, - crypto, - KRB5_KU_KRB_CRED, - &cred.enc_part, - &enc_krb_cred_part_data); - - krb5_crypto_destroy(context, crypto); + if (ret) + goto out; + + ret = krb5_decrypt_EncryptedData(context, + crypto, + KRB5_KU_KRB_CRED, + &cred.enc_part, + &enc_krb_cred_part_data); + + krb5_crypto_destroy(context, crypto); + } if (ret) goto out; } -- cgit From 14a3abd5591a7c310bdd2638e5c06833dc2c8f92 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 26 Oct 2005 23:41:01 +0000 Subject: r11314: Use a patch from lha to have the kerberos libs extract the PAC, rather than doing ASN.1 parsing in Samba. Also use the API function for getting a client from a ticket, rather than just digging in the structure. Andrew Bartlett (This used to be commit 25d5ea6d724bd2b64a6086ae6e2e1c5148b8ca4a) --- source4/heimdal/lib/krb5/ticket.c | 158 +++++++++++++++++++++++++++++++++++--- 1 file changed, 148 insertions(+), 10 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c index 734cd4d4ca..8f4f8fb152 100644 --- a/source4/heimdal/lib/krb5/ticket.c +++ b/source4/heimdal/lib/krb5/ticket.c @@ -97,6 +97,141 @@ krb5_ticket_get_server(krb5_context context, return krb5_copy_principal(context, ticket->server, server); } +static int +find_type_in_ad(krb5_context context, + int type, + krb5_data *data, + int *found, + int failp, + krb5_keyblock *sessionkey, + const AuthorizationData *ad, + int level) +{ + krb5_error_code ret = ENOENT; + int i; + + if (level > 9) { + krb5_set_error_string(context, "Authorization data nested deeper " + "then %d levels, stop searching", level); + ret = ENOENT; /* XXX */ + goto out; + } + + /* + * Only copy out the element the first time we get to it, we need + * to run over the whole authorization data fields to check if + * there are any container clases we need to care about. + */ + for (i = 0; i < ad->len; i++) { + if (!*found && ad->val[i].ad_type == type) { + ret = copy_octet_string(&ad->val[i].ad_data, data); + if (ret) { + krb5_set_error_string(context, "malloc - out of memory"); + goto out; + } + *found = 1; + continue; + } + switch (ad->val[i].ad_type) { + case KRB5_AUTHDATA_IF_RELEVANT: { + AuthorizationData child; + ret = decode_AuthorizationData(ad->val[i].ad_data.data, + ad->val[i].ad_data.length, + &child, + NULL); + if (ret) { + krb5_set_error_string(context, "Failed to decode " + "IF_RELEVANT with %d", ret); + goto out; + } + ret = find_type_in_ad(context, type, data, found, 0, sessionkey, + &child, level + 1); + free_AuthorizationData(&child); + if (ret) + goto out; + break; + } + case KRB5_AUTHDATA_KDC_ISSUED: { + AD_KDCIssued child; + + ret = decode_AD_KDCIssued(ad->val[i].ad_data.data, + ad->val[i].ad_data.length, + &child, + NULL); + if (ret) { + krb5_set_error_string(context, "Failed to decode " + "AD_KDCIssued with %d", ret); + goto out; + } + if (failp) { + krb5_boolean valid; + krb5_data buf; + size_t len; + + ASN1_MALLOC_ENCODE(AuthorizationData, buf.data, buf.length, + &child.elements, &len, ret); + if (ret) { + free_AD_KDCIssued(&child); + krb5_clear_error_string(context); + goto out; + } + if(buf.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + + ret = krb5_c_verify_checksum(context, sessionkey, 19, &buf, + &child.ad_checksum, &valid); + krb5_data_free(&buf); + if (ret) { + free_AD_KDCIssued(&child); + goto out; + } + if (!valid) { + krb5_clear_error_string(context); + ret = ENOENT; + free_AD_KDCIssued(&child); + goto out; + } + } + ret = find_type_in_ad(context, type, data, found, failp, sessionkey, + &child.elements, level + 1); + free_AD_KDCIssued(&child); + if (ret) + goto out; + break; + } + case KRB5_AUTHDATA_AND_OR: + if (!failp) + break; + krb5_set_error_string(context, "Authorization data contains " + "AND-OR element that is unknown to the " + "application"); + ret = ENOENT; /* XXX */ + goto out; + default: + if (!failp) + break; + krb5_set_error_string(context, "Authorization data contains " + "unknown type (%d) ", ad->val[i].ad_type); + ret = ENOENT; /* XXX */ + goto out; + } + } +out: + if (ret) { + if (*found) { + krb5_data_free(data); + *found = 0; + } + } + return ret; +} + +/* + * Extract the authorization data type of `type' from the + * 'ticket'. Store the field in `data'. This function is to use for + * kerberos applications + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_ticket_get_authorization_data_type(krb5_context context, krb5_ticket *ticket, @@ -104,22 +239,25 @@ krb5_ticket_get_authorization_data_type(krb5_context context, krb5_data *data) { AuthorizationData *ad; - int i; + krb5_error_code ret; + int found = 0; - data->length = 0; - data->data = NULL; + krb5_data_zero(data); ad = ticket->ticket.authorization_data; - if (ad == NULL) { + if (ticket->ticket.authorization_data == NULL) { krb5_set_error_string(context, "Ticket have not authorization data"); return ENOENT; /* XXX */ } - for (i = 0; i < ad->len; i++) { - if (ad->val[i].ad_type == type) - return copy_octet_string(&ad->val[i].ad_data, data); - } - krb5_set_error_string(context, "Ticket have not authorization " + ret = find_type_in_ad(context, type, data, &found, 1, &ticket->ticket.key, + ticket->ticket.authorization_data, 0); + if (ret) + return ret; + if (!found) { + krb5_set_error_string(context, "Ticket have not authorization " "data of type %d", type); - return ENOENT; /* XXX */ + return ENOENT; /* XXX */ + } + return 0; } -- cgit From 3b2a6997b43dcfe37adf67c84e564a4fbff5b108 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 2 Nov 2005 00:31:22 +0000 Subject: r11452: Update Heimdal to current lorikeet, including removing the ccache side of the gsskrb5_acquire_cred hack. Add support for delegated credentials into the auth and credentials subsystem, and specifically into gensec_gssapi. Add the CIFS NTVFS handler as a consumer of delegated credentials, when no user/domain/password is specified. Andrew Bartlett (This used to be commit 55b89899adb692d90e63873ccdf80b9f94a6b448) --- source4/heimdal/lib/krb5/ticket.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c index 8f4f8fb152..7dae26acf2 100644 --- a/source4/heimdal/lib/krb5/ticket.c +++ b/source4/heimdal/lib/krb5/ticket.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: ticket.c,v 1.12 2004/05/25 21:44:47 lha Exp $"); +RCSID("$Id: ticket.c,v 1.14 2005/10/27 13:21:42 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_free_ticket(krb5_context context, @@ -151,6 +151,7 @@ find_type_in_ad(krb5_context context, goto out; break; } +#if 0 /* XXX test */ case KRB5_AUTHDATA_KDC_ISSUED: { AD_KDCIssued child; @@ -199,6 +200,7 @@ find_type_in_ad(krb5_context context, goto out; break; } +#endif case KRB5_AUTHDATA_AND_OR: if (!failp) break; @@ -229,7 +231,7 @@ out: /* * Extract the authorization data type of `type' from the * 'ticket'. Store the field in `data'. This function is to use for - * kerberos applications + * kerberos applications. */ krb5_error_code KRB5_LIB_FUNCTION -- cgit From 3b213ca9a3e44266647ac4ceb88d3acd2fb4a295 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 2 Nov 2005 04:11:36 +0000 Subject: r11469: Fix typo, and use the correct (RFC4120) session key for delegating credentials. This means we now delegate to windows correctly. Andrew Bartlett (This used to be commit d6928a3bf86f1ab89f29eac538ceb701c6669913) --- source4/heimdal/lib/krb5/get_for_creds.c | 22 ++++++++++++---------- source4/heimdal/lib/krb5/rd_cred.c | 2 +- 2 files changed, 13 insertions(+), 11 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index ea0bc4ad9e..adb6000cd6 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -378,16 +378,18 @@ krb5_get_forwarded_creds (krb5_context context, cred.enc_part.cipher.data = buf; cred.enc_part.cipher.length = buf_size; } else { - krb5_keyblock *key; - - if (auth_context->local_subkey) - key = auth_context->local_subkey; - else if (auth_context->remote_subkey) - key = auth_context->remote_subkey; - else - key = auth_context->keyblock; - - ret = krb5_crypto_init(context, key, 0, &crypto); + /* + * RFC4120 claims we should use the session key, but Heimdal + * before 0.8 used the remote subkey if it was send in the + * auth_context. + * + * Lorikeet-Heimdal is interested in windows compatiblity + * more than Heimdal compatability, so we must choose the + * session key, and break forwarding credentials to older + * Heimdal servers. + */ + + ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto); if (ret) { free(buf); free_KRB_CRED(&cred); diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c index ddd5866aeb..07f142267c 100644 --- a/source4/heimdal/lib/krb5/rd_cred.c +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -101,7 +101,7 @@ krb5_rd_cred(krb5_context context, } else { /* Try both subkey and session key. * - * RFC2140 claims we should use the session key, but Heimdal + * RFC4120 claims we should use the session key, but Heimdal * before 0.8 used the remote subkey if it was send in the * auth_context. */ -- cgit From 512f5ae8817eb378d5d3bdf6ba08c50c8dc3bf8c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 6 Nov 2005 01:46:12 +0000 Subject: r11529: Disable DNS lookups for forwarded credentials, unless really, really wanted. There is nothing that suggests that the host we forward credentials to will not have other interfaces, unassoicated with their service name. Likewise, the name may be a netbios, not DNS name. This should avoid some nasty DNS lookups. Andrew Bartlett (This used to be commit da0ff19856a8f41eb64787990d47d2961824711d) --- source4/heimdal/lib/krb5/get_for_creds.c | 75 +++++++++++++++++--------------- 1 file changed, 41 insertions(+), 34 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index adb6000cd6..7bc8942f66 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -162,7 +162,8 @@ krb5_get_forwarded_creds (krb5_context context, { krb5_error_code ret; krb5_creds *out_creds; - krb5_addresses addrs, *paddrs; + krb5_addresses *paddrs = NULL; + krb5_addresses addrs; KRB_CRED cred; KrbCredInfo *krb_cred_info; EncKrbCredPart enc_krb_cred_part; @@ -171,50 +172,56 @@ krb5_get_forwarded_creds (krb5_context context, size_t buf_size; krb5_kdc_flags kdc_flags; krb5_crypto crypto; - struct addrinfo *ai; int save_errno; krb5_creds *ticket; char *realm; + krb5_boolean noaddr_ever; + + addrs.len = 0; + addrs.val = NULL; if (in_creds->client && in_creds->client->realm) realm = in_creds->client->realm; else realm = in_creds->server->realm; - addrs.len = 0; - addrs.val = NULL; - paddrs = &addrs; - - /* - * If tickets are address-less, forward address-less tickets. - */ - - ret = _krb5_get_krbtgt (context, - ccache, - realm, - &ticket); - if(ret == 0) { - if (ticket->addresses.len == 0) - paddrs = NULL; - krb5_free_creds (context, ticket); + krb5_appdefault_boolean(context, NULL, realm, "no-addresses-ever", + TRUE, &noaddr_ever); + if (!noaddr_ever) { + struct addrinfo *ai; + paddrs = &addrs; + + /* + * If tickets are address-less, forward address-less tickets. + */ + + ret = _krb5_get_krbtgt (context, + ccache, + realm, + &ticket); + if(ret == 0) { + if (ticket->addresses.len == 0) + paddrs = NULL; + krb5_free_creds (context, ticket); + } + + if (paddrs != NULL) { + + ret = getaddrinfo (hostname, NULL, NULL, &ai); + if (ret) { + save_errno = errno; + krb5_set_error_string(context, "resolving %s: %s", + hostname, gai_strerror(ret)); + return krb5_eai_to_heim_errno(ret, save_errno); + } + + ret = add_addrs (context, &addrs, ai); + freeaddrinfo (ai); + if (ret) + return ret; + } } - - if (paddrs != NULL) { - ret = getaddrinfo (hostname, NULL, NULL, &ai); - if (ret) { - save_errno = errno; - krb5_set_error_string(context, "resolving %s: %s", - hostname, gai_strerror(ret)); - return krb5_eai_to_heim_errno(ret, save_errno); - } - - ret = add_addrs (context, &addrs, ai); - freeaddrinfo (ai); - if (ret) - return ret; - } - kdc_flags.b = int2KDCOptions(flags); ret = krb5_get_kdc_cred (context, -- cgit From f7ca7308490c5bb41c6e42e7fe52f6b2586d3d5d Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 7 Nov 2005 02:25:37 +0000 Subject: r11542: Add the netbios name type. We will need it when we start to handle allowedWorkstations on Krb5. Andrew Bartlett (This used to be commit dbf73a82fc7d1f82e2ad45e545cefdd9a5b24215) --- source4/heimdal/lib/krb5/krb5.h | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index ef595d4d20..fe9a0e5e7a 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -233,6 +233,7 @@ typedef struct krb5_preauthdata { typedef enum krb5_address_type { KRB5_ADDRESS_INET = 2, + KRB5_ADDRESS_NETBIOS = 20, KRB5_ADDRESS_INET6 = 24, KRB5_ADDRESS_ADDRPORT = 256, KRB5_ADDRESS_IPPORT = 257 -- cgit From 918c7634c21deb0aa89388bb3d9e147bfc8576c8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 7 Nov 2005 02:29:37 +0000 Subject: r11543: A major upgrade to our KDC and PAC handling. We now put the PAC in the AS-REP, so that the client has it in the TGT. We then validate it (and re-sign it) on a TGS-REQ, ie when the client wants a ticket. This should also allow us to interop with windows KDCs. If we get an invalid PAC at the TGS stage, we just drop it. I'm slowly trying to move the application logic out of hdb-ldb.c, and back in with the rest of Samba's auth system, for consistancy. This continues that trend. Andrew Bartlett (This used to be commit 36973b1eef7db5983cce76ba241e54d5f925c69c) --- source4/heimdal/lib/krb5/krb5-private.h | 8 ++++++++ source4/heimdal/lib/krb5/mk_req.c | 2 ++ source4/heimdal/lib/krb5/ticket.c | 27 +++++++++++++++++++-------- 3 files changed, 29 insertions(+), 8 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 07d9329337..2645c29fe7 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -399,4 +399,12 @@ _krb5_xunlock ( krb5_context /*context*/, int /*fd*/); +int +_krb5_find_type_in_ad(krb5_context context, + int type, + krb5_data *data, + int *found, + krb5_keyblock *sessionkey, + const AuthorizationData *ad); + #endif /* __krb5_private_h__ */ diff --git a/source4/heimdal/lib/krb5/mk_req.c b/source4/heimdal/lib/krb5/mk_req.c index adc077e13f..44e5d9c222 100644 --- a/source4/heimdal/lib/krb5/mk_req.c +++ b/source4/heimdal/lib/krb5/mk_req.c @@ -64,7 +64,9 @@ krb5_mk_req_exact(krb5_context context, if (auth_context && *auth_context && (*auth_context)->keytype) this_cred.session.keytype = (*auth_context)->keytype; + /* This is the network contact with the KDC */ ret = krb5_get_credentials (context, 0, ccache, &this_cred, &cred); + krb5_free_cred_contents(context, &this_cred); if (ret) return ret; diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c index 7dae26acf2..b3efeb39d3 100644 --- a/source4/heimdal/lib/krb5/ticket.c +++ b/source4/heimdal/lib/krb5/ticket.c @@ -101,8 +101,8 @@ static int find_type_in_ad(krb5_context context, int type, krb5_data *data, - int *found, - int failp, + krb5_boolean *found, + krb5_boolean failp, krb5_keyblock *sessionkey, const AuthorizationData *ad, int level) @@ -129,7 +129,7 @@ find_type_in_ad(krb5_context context, krb5_set_error_string(context, "malloc - out of memory"); goto out; } - *found = 1; + *found = TRUE; continue; } switch (ad->val[i].ad_type) { @@ -228,6 +228,19 @@ out: return ret; } +int +_krb5_find_type_in_ad(krb5_context context, + int type, + krb5_data *data, + krb5_boolean *found, + krb5_keyblock *sessionkey, + const AuthorizationData *ad) +{ + krb5_data_zero(data); + return find_type_in_ad(context, type, data, found, TRUE, sessionkey, ad, 0); +} + + /* * Extract the authorization data type of `type' from the * 'ticket'. Store the field in `data'. This function is to use for @@ -242,9 +255,7 @@ krb5_ticket_get_authorization_data_type(krb5_context context, { AuthorizationData *ad; krb5_error_code ret; - int found = 0; - - krb5_data_zero(data); + krb5_boolean found = 0; ad = ticket->ticket.authorization_data; if (ticket->ticket.authorization_data == NULL) { @@ -252,8 +263,8 @@ krb5_ticket_get_authorization_data_type(krb5_context context, return ENOENT; /* XXX */ } - ret = find_type_in_ad(context, type, data, &found, 1, &ticket->ticket.key, - ticket->ticket.authorization_data, 0); + ret = _krb5_find_type_in_ad(context, type, data, &found, &ticket->ticket.key, + ticket->ticket.authorization_data); if (ret) return ret; if (!found) { -- cgit From 9c6b7f2d62e134a4bc15efc04e05be25e4a53dc7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 1 Dec 2005 05:20:39 +0000 Subject: r11995: A big kerberos-related update. This merges Samba4 up to current lorikeet-heimdal, which includes a replacement for some Samba-specific hacks. In particular, the credentials system now supplies GSS client and server credentials. These are imported into GSS with gss_krb5_import_creds(). Unfortunetly this can't take an MEMORY keytab, so we now create a FILE based keytab as provision and join time. Because the keytab is now created in advance, we don't spend .4s at negprot doing sha1 s2k calls. Also, because the keytab is read in real time, any change in the server key will be correctly picked up by the the krb5 code. To mark entries in the secrets which should be exported to a keytab, there is a new kerberosSecret objectClass. The new routine cli_credentials_update_all_keytabs() searches for these, and updates the keytabs. This is called in the provision.js via the ejs wrapper credentials_update_all_keytabs(). We can now (in theory) use a system-provided /etc/krb5.keytab, if krb5Keytab: FILE:/etc/krb5.keytab is added to the secrets.ldb record. By default the attribute privateKeytab: secrets.keytab is set, pointing to allow the whole private directory to be moved without breaking the internal links. (This used to be commit 6b75573df49c6210e1b9d71e108a9490976bd41d) --- source4/heimdal/lib/krb5/cache.c | 37 +++++++++++++++++++++++++++++++- source4/heimdal/lib/krb5/get_for_creds.c | 22 ++++++++----------- source4/heimdal/lib/krb5/keytab.c | 36 ++++++++++++++++++++++++++++++- source4/heimdal/lib/krb5/krb5-private.h | 17 ++++++++------- source4/heimdal/lib/krb5/krb5-protos.h | 12 +++++++++++ source4/heimdal/lib/krb5/rd_cred.c | 2 +- 6 files changed, 102 insertions(+), 24 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index ec956409a7..25dc2cb8c0 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c,v 1.73 2005/10/19 17:30:40 lha Exp $"); +RCSID("$Id: cache.c,v 1.74 2005/11/01 09:36:41 lha Exp $"); /* * Add a new ccache type with operations `ops', overwriting any @@ -222,6 +222,41 @@ krb5_cc_get_type(krb5_context context, return id->ops->prefix; } +/* + * Return the complete resolvable name the ccache `id' in `str´. + * `str` should be freed with free(3). + * Returns 0 or an error (and then *str is set to NULL). + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_full_name(krb5_context context, + krb5_ccache id, + char **str) +{ + const char *type, *name; + + *str = NULL; + + type = krb5_cc_get_type(context, id); + if (type == NULL) { + krb5_set_error_string(context, "cache have no name of type"); + return KRB5_CC_UNKNOWN_TYPE; + } + + name = krb5_cc_get_name(context, id); + if (name == NULL) { + krb5_set_error_string(context, "cache of type %s have no name", type); + return KRB5_CC_BADNAME; + } + + if (asprintf(str, "%s:%s", type, name) == -1) { + krb5_set_error_string(context, "malloc - out of memory"); + *str = NULL; + return ENOMEM; + } + return 0; +} + /* * Return krb5_cc_ops of a the ccache `id'. */ diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index 7bc8942f66..be5c1db47d 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_for_creds.c,v 1.45 2005/06/15 02:44:36 lha Exp $"); +RCSID("$Id: get_for_creds.c,v 1.46 2005/11/28 20:43:02 lha Exp $"); static krb5_error_code add_addrs(krb5_context context, @@ -385,17 +385,13 @@ krb5_get_forwarded_creds (krb5_context context, cred.enc_part.cipher.data = buf; cred.enc_part.cipher.length = buf_size; } else { - /* - * RFC4120 claims we should use the session key, but Heimdal - * before 0.8 used the remote subkey if it was send in the - * auth_context. - * - * Lorikeet-Heimdal is interested in windows compatiblity - * more than Heimdal compatability, so we must choose the - * session key, and break forwarding credentials to older - * Heimdal servers. - */ - + /* + * Here older versions then 0.7.2 of Heimdal used the local or + * remote subkey. That is wrong, the session key should be + * used. Heimdal 0.7.2 and newer have code to try both in the + * receiving end. + */ + ret = krb5_crypto_init(context, auth_context->keyblock, 0, &crypto); if (ret) { free(buf); diff --git a/source4/heimdal/lib/krb5/keytab.c b/source4/heimdal/lib/krb5/keytab.c index 23f6685049..43fc21c1d1 100644 --- a/source4/heimdal/lib/krb5/keytab.c +++ b/source4/heimdal/lib/krb5/keytab.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab.c,v 1.62 2005/07/06 01:14:42 lha Exp $"); +RCSID("$Id: keytab.c,v 1.63 2005/11/25 21:46:40 lha Exp $"); /* * Register a new keytab in `ops' @@ -239,6 +239,40 @@ krb5_kt_get_name(krb5_context context, return (*keytab->get_name)(context, keytab, name, namesize); } +/* + * Retrieve the full name of the keytab `keytab' and store the name in + * `str'. `str' needs to be freed by the caller using free(3). + * Returns 0 or an error. On error, *str is set to NULL. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_full_name(krb5_context context, + krb5_keytab keytab, + char **str) +{ + char type[KRB5_KT_PREFIX_MAX_LEN]; + char name[MAXPATHLEN]; + krb5_error_code ret; + + *str = NULL; + + ret = krb5_kt_get_type(context, keytab, type, sizeof(type)); + if (ret) + return ret; + + ret = krb5_kt_get_name(context, keytab, name, sizeof(name)); + if (ret) + return ret; + + if (asprintf(str, "%s:%s", type, name) == -1) { + krb5_set_error_string(context, "malloc - out of memory"); + *str = NULL; + return ENOMEM; + } + + return 0; +} + /* * Finish using the keytab in `id'. All resources will be released, * even on errors. Return 0 or an error. diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 2645c29fe7..3602c89ec6 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -77,6 +77,15 @@ _krb5_extract_ticket ( krb5_decrypt_proc /*decrypt_proc*/, krb5_const_pointer /*decryptarg*/); +int +_krb5_find_type_in_ad ( + krb5_context /*context*/, + int /*type*/, + krb5_data */*data*/, + krb5_boolean */*found*/, + krb5_keyblock */*sessionkey*/, + const AuthorizationData */*ad*/); + void _krb5_free_krbhst_info (krb5_krbhst_info */*hi*/); @@ -399,12 +408,4 @@ _krb5_xunlock ( krb5_context /*context*/, int /*fd*/); -int -_krb5_find_type_in_ad(krb5_context context, - int type, - krb5_data *data, - int *found, - krb5_keyblock *sessionkey, - const AuthorizationData *ad); - #endif /* __krb5_private_h__ */ diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index a46f8b8f8f..33e35ca60e 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -607,6 +607,12 @@ krb5_cc_gen_new ( const krb5_cc_ops */*ops*/, krb5_ccache */*id*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_full_name ( + krb5_context /*context*/, + krb5_ccache /*id*/, + char **/*str*/); + const char* KRB5_LIB_FUNCTION krb5_cc_get_name ( krb5_context /*context*/, @@ -2185,6 +2191,12 @@ krb5_kt_get_entry ( krb5_enctype /*enctype*/, krb5_keytab_entry */*entry*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_kt_get_full_name ( + krb5_context /*context*/, + krb5_keytab /*keytab*/, + char **/*str*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_kt_get_name ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c index 07f142267c..d62adadf26 100644 --- a/source4/heimdal/lib/krb5/rd_cred.c +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_cred.c,v 1.25 2005/09/23 03:37:57 lha Exp $"); +RCSID("$Id: rd_cred.c,v 1.26 2005/11/02 08:36:42 lha Exp $"); static krb5_error_code compare_addrs(krb5_context context, -- cgit From 6913dddf644525f4bdadfb740b5bff41abe030b2 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 1 Dec 2005 22:18:34 +0000 Subject: r12000: Update to current lorikeet-heimdal, including in particular support for referencing an existing in-MEMORY keytab (required for the new way we push that to GSSAPI). Andrew Bartlett (This used to be commit 2426581dfb9f5f0f9367f846c01dfd3c30fea954) --- source4/heimdal/lib/krb5/cache.c | 5 ++- source4/heimdal/lib/krb5/keytab_memory.c | 66 ++++++++++++++++++++++++++++++-- source4/heimdal/lib/krb5/krb5-protos.h | 18 +++++++++ source4/heimdal/lib/krb5/krb5.h | 2 +- source4/heimdal/lib/krb5/rd_req.c | 23 +++++++++-- 5 files changed, 105 insertions(+), 9 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index 25dc2cb8c0..0c821cb11d 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c,v 1.74 2005/11/01 09:36:41 lha Exp $"); +RCSID("$Id: cache.c,v 1.76 2005/11/29 09:10:47 lha Exp $"); /* * Add a new ccache type with operations `ops', overwriting any @@ -701,6 +701,9 @@ krb5_cc_get_prefix_ops(krb5_context context, const char *prefix) char *p, *p1; int i; + if (prefix[0] == '/') + return &krb5_fcc_ops; + p = strdup(prefix); if (p == NULL) { krb5_set_error_string(context, "malloc - out of memory"); diff --git a/source4/heimdal/lib/krb5/keytab_memory.c b/source4/heimdal/lib/krb5/keytab_memory.c index 1d866fa11e..afa8f433ac 100644 --- a/source4/heimdal/lib/krb5/keytab_memory.c +++ b/source4/heimdal/lib/krb5/keytab_memory.c @@ -33,26 +33,64 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_memory.c,v 1.6 2005/05/18 04:44:40 lha Exp $"); +RCSID("$Id: keytab_memory.c,v 1.7 2005/12/01 12:40:22 lha Exp $"); /* memory operations -------------------------------------------- */ struct mkt_data { krb5_keytab_entry *entries; int num_entries; + char *name; + int refcount; + struct mkt_data *next; }; +/* this mutex protects mkt_head, ->refcount, and ->next + * content is not protected (name is static and need no protection) + */ +static HEIMDAL_MUTEX mkt_mutex = HEIMDAL_MUTEX_INITIALIZER; +static struct mkt_data *mkt_head; + + static krb5_error_code mkt_resolve(krb5_context context, const char *name, krb5_keytab id) { struct mkt_data *d; - d = malloc(sizeof(*d)); + + HEIMDAL_MUTEX_lock(&mkt_mutex); + + for (d = mkt_head; d != NULL; d = d->next) + if (strcmp(d->name, name) == 0) + break; + if (d) { + if (d->refcount < 1) + krb5_abortx(context, "Double close on memory keytab, " + "refcount < 1 %d", d->refcount); + d->refcount++; + id->data = d; + HEIMDAL_MUTEX_unlock(&mkt_mutex); + return 0; + } + + d = calloc(1, sizeof(*d)); if(d == NULL) { + HEIMDAL_MUTEX_unlock(&mkt_mutex); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } + d->name = strdup(name); + if (d->name == NULL) { + HEIMDAL_MUTEX_unlock(&mkt_mutex); + free(d); krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } d->entries = NULL; d->num_entries = 0; + d->refcount = 1; + d->next = mkt_head; + mkt_head = d; + HEIMDAL_MUTEX_unlock(&mkt_mutex); id->data = d; return 0; } @@ -60,8 +98,27 @@ mkt_resolve(krb5_context context, const char *name, krb5_keytab id) static krb5_error_code mkt_close(krb5_context context, krb5_keytab id) { - struct mkt_data *d = id->data; + struct mkt_data *d = id->data, **dp; int i; + + HEIMDAL_MUTEX_lock(&mkt_mutex); + if (d->refcount < 1) + krb5_abortx(context, + "krb5 internal error, memory keytab refcount < 1 on close"); + + if (--d->refcount > 0) { + HEIMDAL_MUTEX_unlock(&mkt_mutex); + return 0; + } + for (dp = &mkt_head; *dp != NULL; dp = &(*dp)->next) { + if (*dp == d) { + *dp = d->next; + break; + } + } + HEIMDAL_MUTEX_unlock(&mkt_mutex); + + free(d->name); for(i = 0; i < d->num_entries; i++) krb5_kt_free_entry(context, &d->entries[i]); free(d->entries); @@ -75,7 +132,8 @@ mkt_get_name(krb5_context context, char *name, size_t namesize) { - strlcpy(name, "", namesize); + struct mkt_data *d = id->data; + strlcpy(name, d->name, namesize); return 0; } diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 33e35ca60e..301b8853e4 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -20,6 +20,24 @@ extern "C" { #endif #endif +void +initialize_heim_error_table (void); + +void +initialize_heim_error_table_r (struct et_list **/*list*/); + +void +initialize_k524_error_table (void); + +void +initialize_k524_error_table_r (struct et_list **/*list*/); + +void +initialize_krb5_error_table (void); + +void +initialize_krb5_error_table_r (struct et_list **/*list*/); + krb5_error_code KRB5_LIB_FUNCTION krb524_convert_creds_kdc ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index fe9a0e5e7a..adee4708e6 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h,v 1.239 2005/10/12 12:39:28 lha Exp $ */ +/* $Id: krb5.h,v 1.240 2005/11/30 15:20:32 lha Exp $ */ #ifndef __KRB5_H__ #define __KRB5_H__ diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 582b71db03..313c14f6e6 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2001, 2003 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_req.c,v 1.58 2005/08/27 05:48:57 lha Exp $"); +RCSID("$Id: rd_req.c,v 1.61 2005/11/29 18:22:51 lha Exp $"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, @@ -136,7 +136,11 @@ check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc) int num_realms; krb5_error_code ret; - /* Windows w2k and w2k3 uses this */ + /* + * Windows 2000 and 2003 uses this inside their TGT so its normaly + * not seen by others, however, samba4 joined with a Windows AD as + * a Domain Controller gets exposed to this. + */ if(enc->transited.tr_type == 0 && enc->transited.contents.length == 0) return 0; @@ -417,6 +421,19 @@ krb5_verify_ap_req2(krb5_context context, goto out; } + /* check timestamp in authenticator */ + { + krb5_timestamp now; + + krb5_timeofday (context, &now); + + if (abs(ac->authenticator->ctime - now) > context->max_skew) { + ret = KRB5KRB_AP_ERR_SKEW; + krb5_clear_error_string (context); + goto out; + } + } + if (ac->authenticator->seq_number) krb5_auth_con_setremoteseqnumber(context, ac, *ac->authenticator->seq_number); -- cgit From 9afdb938cd5e3c86d72d7ef8c5a8fced13291c9c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 3 Dec 2005 00:47:51 +0000 Subject: r12037: Fix malloc corruption caused by double-free(), where realloc(ptr, 0) is equivilant to free(). This is the issue tridge was seeing in the MEMORY: keytab code. Andrew Bartlett (This used to be commit d5a2de8ef06a08274d25ab005f2a68ec32e226f0) --- source4/heimdal/lib/krb5/keytab_memory.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/keytab_memory.c b/source4/heimdal/lib/krb5/keytab_memory.c index afa8f433ac..1039847de9 100644 --- a/source4/heimdal/lib/krb5/keytab_memory.c +++ b/source4/heimdal/lib/krb5/keytab_memory.c @@ -214,9 +214,15 @@ mkt_remove_entry(krb5_context context, krb5_clear_error_string (context); return KRB5_KT_NOTFOUND; } - e = realloc(d->entries, d->num_entries * sizeof(*d->entries)); - if(e != NULL) - d->entries = e; + if (d->num_entries == 0) { + free(d->entries); + d->entries = NULL; + } else { + e = realloc(d->entries, d->num_entries * sizeof(*d->entries)); + if(e != NULL) + d->entries = e; + } + return 0; } -- cgit From fbf106f6701c580f5839da575996de34fc953e1f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 15 Dec 2005 20:38:24 +0000 Subject: r12269: Update to current lorikeet-heimdal. This changed the way the hdb interface worked, so hdb-ldb.c and the glue have been updated. Andrew Bartlett (This used to be commit 8fd5224c6b5c17c3a2c04c7366b7e367012db77e) --- source4/heimdal/lib/krb5/cache.c | 14 ++++++-------- source4/heimdal/lib/krb5/changepw.c | 11 ++++++++--- source4/heimdal/lib/krb5/crypto.c | 13 +++++++------ source4/heimdal/lib/krb5/keytab_memory.c | 14 ++++---------- source4/heimdal/lib/krb5/krb5-protos.h | 9 --------- source4/heimdal/lib/krb5/krb5_locl.h | 10 +++++++++- source4/heimdal/lib/krb5/principal.c | 2 +- source4/heimdal/lib/krb5/set_default_realm.c | 15 +++++++++++++-- 8 files changed, 48 insertions(+), 40 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index 0c821cb11d..efb2ad1374 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c,v 1.76 2005/11/29 09:10:47 lha Exp $"); +RCSID("$Id: cache.c,v 1.77 2005/12/13 15:42:36 lha Exp $"); /* * Add a new ccache type with operations `ops', overwriting any @@ -358,14 +358,12 @@ krb5_cc_set_default_name(krb5_context context, const char *name) if (e == NULL) { e = krb5_config_get_string(context, NULL, "libdefaults", "default_cc_name", NULL); - if (e) { - ret = _krb5_expand_default_cc_name(context, e, &p); - if (ret) - return ret; - } + if (e == NULL) + e = KRB5_DEFAULT_CCNAME; + ret = _krb5_expand_default_cc_name(context, e, &p); + if (ret) + return ret; } - if (e == NULL) - asprintf(&p,"FILE:/tmp/krb5cc_%u", (unsigned)getuid()); } else p = strdup(name); diff --git a/source4/heimdal/lib/krb5/changepw.c b/source4/heimdal/lib/krb5/changepw.c index c3cd6d4db9..7907e1ad9c 100644 --- a/source4/heimdal/lib/krb5/changepw.c +++ b/source4/heimdal/lib/krb5/changepw.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: changepw.c,v 1.54 2005/09/08 11:38:01 lha Exp $"); +RCSID("$Id: changepw.c,v 1.55 2005/12/12 12:48:57 lha Exp $"); static void str2data (krb5_data *d, @@ -522,7 +522,12 @@ change_password_loop (krb5_context context, int sock; int i; int done = 0; - krb5_realm realm = creds->client->realm; + krb5_realm realm; + + if (targprinc) + realm = targprinc->realm; + else + realm = creds->client->realm; ret = krb5_auth_con_init (context, &auth_context); if (ret) @@ -712,7 +717,7 @@ krb5_set_password(krb5_context context, for (i = 0; procs[i].name != NULL; i++) { *result_code = 0; - ret = change_password_loop(context, creds, targprinc, newpw, + ret = change_password_loop(context, creds, principal, newpw, result_code, result_code_string, result_string, &procs[i]); diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 2e23306c96..de40b059b8 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.129 2005/09/19 22:13:54 lha Exp $"); +RCSID("$Id: crypto.c,v 1.130 2005/12/02 14:47:44 lha Exp $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -3942,6 +3942,8 @@ krb5_derive_key(krb5_context context, struct encryption_type *et; struct key_data d; + *derived_key = NULL; + et = _find_enctype (etype); if (et == NULL) { krb5_set_error_string(context, "encryption type %d not supported", @@ -3949,16 +3951,15 @@ krb5_derive_key(krb5_context context, return KRB5_PROG_ETYPE_NOSUPP; } - ret = krb5_copy_keyblock(context, key, derived_key); + ret = krb5_copy_keyblock(context, key, &d.key); if (ret) return ret; - d.key = *derived_key; d.schedule = NULL; ret = derive_key(context, et, &d, constant, constant_len); - if (ret) - return ret; - ret = krb5_copy_keyblock(context, d.key, derived_key); + if (ret == 0) + ret = krb5_copy_keyblock(context, d.key, derived_key); + free_key_data(context, &d); return ret; } diff --git a/source4/heimdal/lib/krb5/keytab_memory.c b/source4/heimdal/lib/krb5/keytab_memory.c index 1039847de9..fa54ff43ce 100644 --- a/source4/heimdal/lib/krb5/keytab_memory.c +++ b/source4/heimdal/lib/krb5/keytab_memory.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_memory.c,v 1.7 2005/12/01 12:40:22 lha Exp $"); +RCSID("$Id: keytab_memory.c,v 1.8 2005/12/05 18:39:46 lha Exp $"); /* memory operations -------------------------------------------- */ @@ -214,15 +214,9 @@ mkt_remove_entry(krb5_context context, krb5_clear_error_string (context); return KRB5_KT_NOTFOUND; } - if (d->num_entries == 0) { - free(d->entries); - d->entries = NULL; - } else { - e = realloc(d->entries, d->num_entries * sizeof(*d->entries)); - if(e != NULL) - d->entries = e; - } - + e = realloc(d->entries, d->num_entries * sizeof(*d->entries)); + if(e != NULL || d->num_entries == 0) + d->entries = e; return 0; } diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 301b8853e4..c08d8058a4 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -20,21 +20,12 @@ extern "C" { #endif #endif -void -initialize_heim_error_table (void); - void initialize_heim_error_table_r (struct et_list **/*list*/); -void -initialize_k524_error_table (void); - void initialize_k524_error_table_r (struct et_list **/*list*/); -void -initialize_krb5_error_table (void); - void initialize_krb5_error_table_r (struct et_list **/*list*/); diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 4a02677239..60d72c8f80 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_locl.h,v 1.83 2005/10/07 12:08:02 lha Exp $ */ +/* $Id: krb5_locl.h,v 1.84 2005/12/13 15:40:50 lha Exp $ */ #ifndef __KRB5_LOCL_H__ #define __KRB5_LOCL_H__ @@ -170,6 +170,14 @@ struct _krb5_krb_auth_data; #define KRB5_BUFSIZ 1024 +#ifndef KRB5_DEFAULT_CCNAME +#ifdef __APPLE__ +#define KRB5_DEFAULT_CCNAME "API:" +#else +#define KRB5_DEFAULT_CCNAME "FILE:/tmp/krb5cc_%{uid}" +#endif +#endif + typedef enum { KRB5_PA_PAC_DONT_CARE = 0, KRB5_PA_PAC_REQ_TRUE, diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index ae5c8c1de8..6cc49945cc 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -41,7 +41,7 @@ #include #include "resolve.h" -RCSID("$Id: principal.c,v 1.91 2005/08/23 08:34:40 lha Exp $"); +RCSID("$Id: principal.c,v 1.92 2005/12/11 17:48:13 lha Exp $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) diff --git a/source4/heimdal/lib/krb5/set_default_realm.c b/source4/heimdal/lib/krb5/set_default_realm.c index 965883309c..fd57b6fe67 100644 --- a/source4/heimdal/lib/krb5/set_default_realm.c +++ b/source4/heimdal/lib/krb5/set_default_realm.c @@ -77,8 +77,19 @@ krb5_set_default_realm(krb5_context context, "libdefaults", "default_realm", NULL); - if (realms == NULL) - ret = krb5_get_host_realm(context, NULL, &realms); + if (realms == NULL) { + char hostname[MAXHOSTNAMELEN]; + if (gethostname (hostname, sizeof(hostname))) { + return errno; + } + + if (strchr(hostname, '.') == NULL) { + /* There is no way we can get this mapping, as we can't do DNS */ + return KRB5_CONFIG_NODEFREALM; + } + ret = krb5_get_host_realm(context, hostname, + &realms); + } } else { ret = string_to_list (context, realm, &realms); } -- cgit From 63d718e243fd03e6ea24c47e7442975ec088a5b5 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 3 Jan 2006 17:27:33 +0000 Subject: r12696: Reduce the size of include/structs.h (This used to be commit 63917616016133c623fc6ff59454bc313ee7dd8f) --- source4/heimdal/lib/krb5/krb5-private.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 3602c89ec6..c308287a36 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -12,6 +12,9 @@ #endif #endif +struct krb5_dh_moduli; +struct _krb5_krb_auth_data; + krb5_error_code KRB5_LIB_FUNCTION _krb5_PKCS5_PBKDF2 ( krb5_context /*context*/, -- cgit From 28d78c40ade22c4b5d445dbe23f18ca210e41f8c Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 24 Jan 2006 05:31:08 +0000 Subject: r13107: Follow the lead of Heimdal's kpasswdd and use the HDB (hdb-ldb in our case) as the keytab. This avoids issues in replicated setups, as we will replicate the kpasswd key correctly (including from windows, which is why I care at the moment). Andrew Bartlett (This used to be commit 849500d1aa658817052423051b1f5d0b7a1db8e0) --- source4/heimdal/lib/krb5/krb5.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index adee4708e6..9814817600 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -451,6 +451,9 @@ typedef struct krb5_context_data { int large_msg_size; krb5_boolean fdns; /* Lookup hostnames to find full name, or send as-is */ struct send_and_recv *send_and_recv; /* Alternate functions for KDC communication */ + void *mem_ctx; /* Some parts of Samba4 need a valid + memory context (under the event + context) to use */ } krb5_context_data; enum { -- cgit From b7afac2b834674e20f303c3a03b4ac7bb283695e Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 11 Mar 2006 04:03:12 +0000 Subject: r14198: Update Samba4 to current lorikeet-heimdal. Andrew Bartlett (This used to be commit 97a0a0e2fa6784e5fc5278f7a15b385ddcb6a3b3) --- source4/heimdal/lib/krb5/crypto.c | 146 ++++++------------------------- source4/heimdal/lib/krb5/error_string.c | 25 +++++- source4/heimdal/lib/krb5/get_cred.c | 5 +- source4/heimdal/lib/krb5/get_for_creds.c | 25 ++---- source4/heimdal/lib/krb5/init_creds.c | 5 +- source4/heimdal/lib/krb5/krb5-private.h | 16 +--- source4/heimdal/lib/krb5/krb5-protos.h | 14 ++- source4/heimdal/lib/krb5/krb5_err.et | 37 ++++---- source4/heimdal/lib/krb5/krb5_locl.h | 28 +++--- source4/heimdal/lib/krb5/mk_priv.c | 8 +- source4/heimdal/lib/krb5/pkinit.c | 109 +++++++++++------------ 11 files changed, 168 insertions(+), 250 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index de40b059b8..3cfc780eb4 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.130 2005/12/02 14:47:44 lha Exp $"); +RCSID("$Id: crypto.c,v 1.132 2006/02/28 14:52:57 lha Exp $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -591,114 +591,6 @@ ARCFOUR_string_to_key(krb5_context context, * AES */ -/* iter is really 1 based, so iter == 0 will be 1 iteration */ - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_PKCS5_PBKDF2(krb5_context context, krb5_cksumtype cktype, - krb5_data password, krb5_salt salt, u_int32_t iter, - krb5_keytype type, krb5_keyblock *key) -{ - struct checksum_type *c = _find_checksum(cktype); - struct key_type *kt; - size_t datalen, leftofkey; - krb5_error_code ret; - u_int32_t keypart; - struct key_data ksign; - krb5_keyblock kb; - Checksum result; - char *data, *tmpcksum; - int i, j; - char *p; - - if (c == NULL) { - krb5_set_error_string(context, "checksum %d not supported", cktype); - return KRB5_PROG_KEYTYPE_NOSUPP; - } - - kt = _find_keytype(type); - if (kt == NULL) { - krb5_set_error_string(context, "key type %d not supported", type); - return KRB5_PROG_KEYTYPE_NOSUPP; - } - - key->keytype = type; - ret = krb5_data_alloc (&key->keyvalue, kt->bits / 8); - if (ret) { - krb5_set_error_string(context, "malloc: out of memory"); - return ret; - } - - ret = krb5_data_alloc (&result.checksum, c->checksumsize); - if (ret) { - krb5_set_error_string(context, "malloc: out of memory"); - krb5_data_free (&key->keyvalue); - return ret; - } - - tmpcksum = malloc(c->checksumsize); - if (tmpcksum == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - krb5_data_free (&key->keyvalue); - krb5_data_free (&result.checksum); - return ENOMEM; - } - - datalen = salt.saltvalue.length + 4; - data = malloc(datalen); - if (data == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - free(tmpcksum); - krb5_data_free (&key->keyvalue); - krb5_data_free (&result.checksum); - return ENOMEM; - } - - kb.keyvalue = password; - ksign.key = &kb; - - memcpy(data, salt.saltvalue.data, salt.saltvalue.length); - - keypart = 1; - leftofkey = key->keyvalue.length; - p = key->keyvalue.data; - - while (leftofkey) { - int len; - - if (leftofkey > c->checksumsize) - len = c->checksumsize; - else - len = leftofkey; - - _krb5_put_int(data + datalen - 4, keypart, 4); - - ret = hmac(context, c, data, datalen, 0, &ksign, &result); - if (ret) - krb5_abortx(context, "hmac failed"); - memcpy(p, result.checksum.data, len); - memcpy(tmpcksum, result.checksum.data, result.checksum.length); - for (i = 0; i < iter; i++) { - ret = hmac(context, c, tmpcksum, result.checksum.length, - 0, &ksign, &result); - if (ret) - krb5_abortx(context, "hmac failed"); - memcpy(tmpcksum, result.checksum.data, result.checksum.length); - for (j = 0; j < len; j++) - p[j] ^= tmpcksum[j]; - } - - p += len; - leftofkey -= len; - keypart++; - } - - free(data); - free(tmpcksum); - krb5_data_free (&result.checksum); - - return 0; -} - int _krb5_AES_string_to_default_iterator = 4096; static krb5_error_code @@ -715,33 +607,44 @@ AES_string_to_key(krb5_context context, struct key_data kd; if (opaque.length == 0) - iter = _krb5_AES_string_to_default_iterator - 1; + iter = _krb5_AES_string_to_default_iterator; else if (opaque.length == 4) { unsigned long v; _krb5_get_int(opaque.data, &v, 4); - iter = ((u_int32_t)v) - 1; + iter = ((u_int32_t)v); } else return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */ - et = _find_enctype(enctype); if (et == NULL) return KRB5_PROG_KEYTYPE_NOSUPP; - ret = _krb5_PKCS5_PBKDF2(context, CKSUMTYPE_SHA1, password, salt, - iter, enctype, key); - if (ret) + key->keytype = enctype; + ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); + if (ret) { + krb5_set_error_string(context, "Failed to allocate pkcs5 key"); return ret; - + } ret = krb5_copy_keyblock(context, key, &kd.key); + if (ret) { + krb5_free_keyblock(context, key); + return ret; + } + + ret = PKCS5_PBKDF2_HMAC_SHA1(password.data, password.length, + salt.saltvalue.data, salt.saltvalue.length, + iter, + et->keytype->size, kd.key->keyvalue.data); kd.schedule = NULL; + if (ret != 1) { + krb5_set_error_string(context, "Error calculating s2k"); + return KRB5_PROG_KEYTYPE_NOSUPP; + } ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos")); - krb5_free_keyblock_contents(context, key); - if (ret == 0) { + if (ret == 0) ret = krb5_copy_keyblock_contents(context, kd.key, key); - free_key_data(context, &kd); - } + free_key_data(context, &kd); return ret; } @@ -3789,7 +3692,8 @@ krb5_generate_random_block(void *buf, size_t len) rng_initialized = 1; } HEIMDAL_MUTEX_unlock(&crypto_mutex); - RAND_bytes(buf, len); + if (RAND_bytes(buf, len) != 1) + krb5_abortx(NULL, "Failed to generate random block"); } #else diff --git a/source4/heimdal/lib/krb5/error_string.c b/source4/heimdal/lib/krb5/error_string.c index 649bdd20fd..b672fe74f9 100644 --- a/source4/heimdal/lib/krb5/error_string.c +++ b/source4/heimdal/lib/krb5/error_string.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001 Kungliga Tekniska Högskolan + * Copyright (c) 2001, 2003, 2005 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: error_string.c,v 1.3 2004/05/25 21:23:55 lha Exp $"); +RCSID("$Id: error_string.c,v 1.7 2006/02/16 07:49:23 lha Exp $"); #undef __attribute__ #define __attribute__(X) @@ -107,3 +107,24 @@ krb5_have_error_string(krb5_context context) HEIMDAL_MUTEX_unlock(context->mutex); return str != NULL; } + +char * KRB5_LIB_FUNCTION +krb5_get_error_message(krb5_context context, krb5_error_code code) +{ + const char *cstr; + char *str; + + str = krb5_get_error_string(context); + if (str) + return str; + + cstr = krb5_get_err_text(context, code); + if (cstr) + return strdup(cstr); + + if (asprintf(&str, "", code) == -1) + return NULL; + + return str; +} + diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 7043b8ae51..1fa3f9143e 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_cred.c,v 1.108 2005/07/13 07:38:02 lha Exp $"); +RCSID("$Id: get_cred.c,v 1.109 2006/02/03 11:41:02 lha Exp $"); /* * Take the `body' and encode it into `padata' using the credentials @@ -772,7 +772,8 @@ get_cred_from_kdc_flags(krb5_context context, krb5_boolean noaddr; krb5_appdefault_boolean(context, NULL, tgt->server->realm, - "no-addresses", FALSE, &noaddr); + "no-addresses", KRB5_ADDRESSLESS_DEFAULT, + &noaddr); if (noaddr) ret = get_cred_kdc (context, ccache, flags, NULL, in_creds, tgt, *out_creds); diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index be5c1db47d..aa7c62befc 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_for_creds.c,v 1.46 2005/11/28 20:43:02 lha Exp $"); +RCSID("$Id: get_for_creds.c,v 1.47 2006/02/03 11:37:29 lha Exp $"); static krb5_error_code add_addrs(krb5_context context, @@ -284,21 +284,14 @@ krb5_get_forwarded_creds (krb5_context context, enc_krb_cred_part.usec = NULL; } - if (auth_context->local_address && auth_context->local_port) { - krb5_boolean noaddr; - krb5_const_realm srealm; - - srealm = krb5_principal_get_realm(context, out_creds->server); - krb5_appdefault_boolean(context, NULL, srealm, "no-addresses", - paddrs == NULL, &noaddr); - if (!noaddr) { - ret = krb5_make_addrport (context, - &enc_krb_cred_part.s_address, - auth_context->local_address, - auth_context->local_port); - if (ret) - goto out4; - } + if (auth_context->local_address && auth_context->local_port && paddrs) { + + ret = krb5_make_addrport (context, + &enc_krb_cred_part.s_address, + auth_context->local_address, + auth_context->local_port); + if (ret) + goto out4; } if (auth_context->remote_address) { diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index 51b8ebc392..316c2f02eb 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c,v 1.21 2005/10/12 12:45:27 lha Exp $"); +RCSID("$Id: init_creds.c,v 1.22 2006/02/03 11:42:31 lha Exp $"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) @@ -191,7 +191,8 @@ krb5_get_init_creds_opt_set_default_flags(krb5_context context, if(t != 0) krb5_get_init_creds_opt_set_renew_life(opt, t); - krb5_appdefault_boolean(context, appname, realm, "no-addresses", FALSE, &b); + krb5_appdefault_boolean(context, appname, realm, "no-addresses", + KRB5_ADDRESSLESS_DEFAULT, &b); if (b) krb5_get_init_creds_opt_set_address_list (opt, &no_addrs); diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index c308287a36..8d9b3c62ac 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -12,19 +12,6 @@ #endif #endif -struct krb5_dh_moduli; -struct _krb5_krb_auth_data; - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_PKCS5_PBKDF2 ( - krb5_context /*context*/, - krb5_cksumtype /*cktype*/, - krb5_data /*password*/, - krb5_salt /*salt*/, - u_int32_t /*iter*/, - krb5_keytype /*type*/, - krb5_keyblock */*key*/); - void KRB5_LIB_FUNCTION _krb5_aes_cts_encrypt ( const unsigned char */*in*/, @@ -92,6 +79,9 @@ _krb5_find_type_in_ad ( void _krb5_free_krbhst_info (krb5_krbhst_info */*hi*/); +void +_krb5_free_moduli (struct krb5_dh_moduli **/*moduli*/); + krb5_error_code _krb5_get_default_principal_local ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index c08d8058a4..d7e74621ef 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -20,15 +20,6 @@ extern "C" { #endif #endif -void -initialize_heim_error_table_r (struct et_list **/*list*/); - -void -initialize_k524_error_table_r (struct et_list **/*list*/); - -void -initialize_krb5_error_table_r (struct et_list **/*list*/); - krb5_error_code KRB5_LIB_FUNCTION krb524_convert_creds_kdc ( krb5_context /*context*/, @@ -1688,6 +1679,11 @@ krb5_get_err_text ( krb5_context /*context*/, krb5_error_code /*code*/); +char * KRB5_LIB_FUNCTION +krb5_get_error_message ( + krb5_context /*context*/, + krb5_error_code /*code*/); + char * KRB5_LIB_FUNCTION krb5_get_error_string (krb5_context /*context*/); diff --git a/source4/heimdal/lib/krb5/krb5_err.et b/source4/heimdal/lib/krb5/krb5_err.et index 1257b074fb..e7bada1808 100644 --- a/source4/heimdal/lib/krb5/krb5_err.et +++ b/source4/heimdal/lib/krb5/krb5_err.et @@ -3,7 +3,7 @@ # # This might look like a com_err file, but is not # -id "$Id: krb5_err.et,v 1.12 2004/10/14 15:30:29 lha Exp $" +id "$Id: krb5_err.et,v 1.14 2006/02/13 11:28:22 lha Exp $" error_table krb5 @@ -74,35 +74,36 @@ prefix KRB5_KDC_ERR error_code CLIENT_NOT_TRUSTED, "Client not trusted" error_code KDC_NOT_TRUSTED, "KDC not trusted" error_code INVALID_SIG, "Invalid signature" -error_code KEY_SIZE, "Key size too small/key too weak" -error_code CERTIFICATE_MISMATCH, "Certificate mismatch" +error_code DH_KEY_PARAMETERS_NOT_ACCEPTED, "DH parameters not accepted" +index 69 prefix KRB5_AP_ERR error_code USER_TO_USER_REQUIRED, "User to user required" index 70 -prefix KRB5_KDC_ERROR +prefix KRB5_KDC_ERR error_code CANT_VERIFY_CERTIFICATE, "Cannot verify certificate" -error_code INVALID_CERTIFICATE, "Invalid certificate" -error_code REVOKED_CERTIFICATE, "Revoked certificate" +error_code INVALID_CERTIFICATE, "Certificate invalid" +error_code REVOKED_CERTIFICATE, "Certificate revoked" error_code REVOCATION_STATUS_UNKNOWN, "Revocation status unknown" -error_code REVOCATION_STATUS_UNAVAILABLE, "Revocation status unknown" -error_code CLIENT_NAME_MISMATCH, "Client name mismatch" -index 75 -error_code KDC_NAME_MISMATCH, "KDC name mismatch" - -# 76-79 are reserved - -index 80 -prefix KRB5_IAKERB -error_code ERR_KDC_NOT_FOUND, "IAKERB proxy could not find a KDC" -error_code ERR_KDC_NO_RESPONSE, "IAKERB proxy never reeived a response from a KDC" +error_code CLIENT_NAME_MISMATCH, "Revocation status unknown" +error_code INCONSISTENT_KEY_PURPOSE, "Inconsistent key purpose" +error_code DIGEST_IN_CERT_NOT_ACCEPTED, "Digest in certificate not accepted" +error_code PA_CHECKSUM_MUST_BE_INCLUDED, "paChecksum must be included" +error_code DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED, "Digest in signedData not accepted" +error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not supported" + +## these are never used +#index 80 +#prefix KRB5_IAKERB +#error_code ERR_KDC_NOT_FOUND, "IAKERB proxy could not find a KDC" +#error_code ERR_KDC_NO_RESPONSE, "IAKERB proxy never reeived a response from a KDC" # 82-127 are reserved index 128 prefix -error_code KRB5_ERR_RCSID, "$Id: krb5_err.et,v 1.12 2004/10/14 15:30:29 lha Exp $" +error_code KRB5_ERR_RCSID, "$Id: krb5_err.et,v 1.14 2006/02/13 11:28:22 lha Exp $" error_code KRB5_LIBOS_BADLOCKFLAG, "Invalid flag for file lock mode" error_code KRB5_LIBOS_CANTREADPWD, "Cannot read password" diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 60d72c8f80..92dd3271f5 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_locl.h,v 1.84 2005/12/13 15:40:50 lha Exp $ */ +/* $Id: krb5_locl.h,v 1.87 2006/02/09 11:36:27 lha Exp $ */ #ifndef __KRB5_LOCL_H__ #define __KRB5_LOCL_H__ @@ -170,14 +170,6 @@ struct _krb5_krb_auth_data; #define KRB5_BUFSIZ 1024 -#ifndef KRB5_DEFAULT_CCNAME -#ifdef __APPLE__ -#define KRB5_DEFAULT_CCNAME "API:" -#else -#define KRB5_DEFAULT_CCNAME "FILE:/tmp/krb5cc_%{uid}" -#endif -#endif - typedef enum { KRB5_PA_PAC_DONT_CARE = 0, KRB5_PA_PAC_REQ_TRUE, @@ -196,4 +188,20 @@ struct _krb5_get_init_creds_opt_private { int canonicalize; }; +/* + * Configurable options + */ + +#ifndef KRB5_DEFAULT_CCNAME +#ifdef __APPLE__ +#define KRB5_DEFAULT_CCNAME "API:" +#else +#define KRB5_DEFAULT_CCNAME "FILE:/tmp/krb5cc_%{uid}" +#endif +#endif + +#ifndef KRB5_ADDRESSLESS_DEFAULT +#define KRB5_ADDRESSLESS_DEFAULT FALSE +#endif + #endif /* __KRB5_LOCL_H__ */ diff --git a/source4/heimdal/lib/krb5/mk_priv.c b/source4/heimdal/lib/krb5/mk_priv.c index 56112eea8c..b5a1aadfea 100644 --- a/source4/heimdal/lib/krb5/mk_priv.c +++ b/source4/heimdal/lib/krb5/mk_priv.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_priv.c,v 1.34 2004/05/25 21:33:32 lha Exp $"); +RCSID("$Id: mk_priv.c,v 1.35 2006/02/01 12:39:26 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION @@ -129,9 +129,11 @@ krb5_mk_priv(krb5_context context, ASN1_MALLOC_ENCODE(KRB_PRIV, buf, buf_size, &s, &len, ret); - - if(ret) + if (ret) goto fail; + if (buf_size != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + krb5_data_free (&s.enc_part.cipher); ret = krb5_data_copy(outbuf, buf + buf_size - len, len); diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 0c5dfc44e9..1247bb22ca 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,15 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.75 2005/10/21 17:18:38 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.77 2006/02/14 10:08:29 lha Exp $"); + +struct krb5_dh_moduli { + char *name; + unsigned long bits; + heim_integer p; + heim_integer g; + heim_integer q; +}; #ifdef PKINIT @@ -104,14 +112,6 @@ struct krb5_pk_cert { X509 *cert; }; -struct krb5_dh_moduli { - char *name; - unsigned long bits; - heim_integer p; - heim_integer g; - heim_integer q; -}; - struct krb5_pk_init_ctx_data { struct krb5_pk_identity *id; DH *dh; @@ -505,7 +505,13 @@ build_auth_pack(krb5_context context, if (ret) return ret; - ret = krb5_data_copy(&a->pkAuthenticator.paChecksum, + ALLOC(a->pkAuthenticator.paChecksum, 1); + if (a->pkAuthenticator.paChecksum == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + ret = krb5_data_copy(a->pkAuthenticator.paChecksum, checksum.checksum.data, checksum.checksum.length); free_Checksum(&checksum); if (ret) @@ -984,11 +990,9 @@ pk_verify_chain_standard(krb5_context context, * Since X509_verify_cert() doesn't do CRL checking at all, we have to * perform own verification against CRLs */ -#if 0 - ret = pk_verify_crl(context, store_ctx, id->crls); - if (ret) - goto end; -#endif + /* + * XXX add crl checking + */ if (client_cert && cert) *client_cert = X509_dup(cert); @@ -2429,6 +2433,31 @@ _krb5_pk_load_openssl_id(krb5_context context, return ret; } +static krb5_error_code +select_dh_group(krb5_context context, DH *dh, unsigned long bits, + struct krb5_dh_moduli **moduli) +{ + const struct krb5_dh_moduli *m; + + m = moduli[1]; /* XXX */ + if (m == NULL) + m = moduli[0]; /* XXX */ + + dh->p = integer_to_BN(context, "p", &m->p); + if (dh->p == NULL) + return ENOMEM; + dh->g = integer_to_BN(context, "g", &m->g); + if (dh->g == NULL) + return ENOMEM; + dh->q = integer_to_BN(context, "q", &m->q); + if (dh->q == NULL) + return ENOMEM; + + return 0; +} + +#endif /* PKINIT */ + static int parse_integer(krb5_context context, char **p, const char *file, int lineno, const char *name, heim_integer *integer) @@ -2526,7 +2555,7 @@ out: return ret; } -static void +void _krb5_free_moduli(struct krb5_dh_moduli **moduli) { int i; @@ -2541,8 +2570,9 @@ _krb5_free_moduli(struct krb5_dh_moduli **moduli) } static const char *default_moduli = - /* bits */ + /* name */ "RFC2412-MODP-group2 " + /* bits */ "1024 " /* p */ "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" @@ -2566,7 +2596,7 @@ krb5_error_code _krb5_parse_moduli(krb5_context context, const char *file, struct krb5_dh_moduli ***moduli) { - /* comment bits P G Q */ + /* name bits P G Q */ krb5_error_code ret; struct krb5_dh_moduli **m = NULL, **m2; char buf[4096]; @@ -2589,10 +2619,8 @@ _krb5_parse_moduli(krb5_context context, const char *file, } n = 1; - if (file == NULL) { - *moduli = m; - return 0; - } + if (file == NULL) + file = MODULI_FILE; f = fopen(file, "r"); if (f == NULL) { @@ -2646,7 +2674,7 @@ _krb5_dh_group_ok(krb5_context context, unsigned long bits, for (i = 0; moduli[i] != NULL; i++) { if (heim_integer_cmp(&moduli[i]->g, g) == 0 && heim_integer_cmp(&moduli[i]->p, p) == 0 && - heim_integer_cmp(&moduli[i]->q, q) == 0) + (q == NULL || heim_integer_cmp(&moduli[i]->q, q) == 0)) { if (bits && bits > moduli[i]->bits) { krb5_set_error_string(context, "PKINIT: DH group parameter %s " @@ -2663,32 +2691,6 @@ _krb5_dh_group_ok(krb5_context context, unsigned long bits, return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; } -static krb5_error_code -select_dh_group(krb5_context context, DH *dh, unsigned long bits, - struct krb5_dh_moduli **moduli) -{ - const struct krb5_dh_moduli *m; - - m = moduli[1]; /* XXX */ - if (m == NULL) - m = moduli[0]; /* XXX */ - - dh->p = integer_to_BN(context, "p", &m->p); - if (dh->p == NULL) - return ENOMEM; - dh->g = integer_to_BN(context, "g", &m->g); - if (dh->g == NULL) - return ENOMEM; - dh->q = integer_to_BN(context, "q", &m->q); - if (dh->q == NULL) - return ENOMEM; - - return 0; -} - - -#endif /* PKINIT */ - void KRB5_LIB_FUNCTION _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) { @@ -2772,11 +2774,10 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, if ((flags & 2) == 0) { const char *moduli_file; - moduli_file = krb5_config_get_string_default(context, NULL, - MODULI_FILE, - "libdefaults", - "moduli", - NULL); + moduli_file = krb5_config_get_string(context, NULL, + "libdefaults", + "moduli", + NULL); ret = _krb5_parse_moduli(context, moduli_file, &opt->opt_private->pk_init_ctx->m); -- cgit From 864d9b531dc2fba94f5ea839b087e28d402c643a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Mar 2006 10:16:59 +0000 Subject: r14635: - Remove lex.c from SVN (it is built anyway, and having it in SVN confuses things) - Update Samba4 from lorikeet-heimdal - Remove generated symlink on make clean Andrew Bartlett (This used to be commit a5c2b4cc92e807d18cb8df99bebf004fa4252e1e) --- source4/heimdal/lib/krb5/addr_families.c | 11 +- source4/heimdal/lib/krb5/crypto.c | 8 +- source4/heimdal/lib/krb5/get_for_creds.c | 4 +- source4/heimdal/lib/krb5/mk_req_ext.c | 195 ++++++++++++++----------------- source4/heimdal/lib/krb5/rd_priv.c | 7 +- source4/heimdal/lib/krb5/send_to_kdc.c | 4 +- 6 files changed, 112 insertions(+), 117 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c index ccc97f412d..cf460ba725 100644 --- a/source4/heimdal/lib/krb5/addr_families.c +++ b/source4/heimdal/lib/krb5/addr_families.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: addr_families.c,v 1.49 2005/06/16 20:16:12 lha Exp $"); +RCSID("$Id: addr_families.c,v 1.50 2006/03/17 22:12:13 lha Exp $"); struct addr_operations { int af; @@ -930,11 +930,18 @@ krb5_parse_address(krb5_context context, int error; int save_errno; + addresses->len = 0; + addresses->val = NULL; + for(i = 0; i < num_addrs; i++) { if(at[i].parse_addr) { krb5_address addr; if((*at[i].parse_addr)(context, string, &addr) == 0) { ALLOC_SEQ(addresses, 1); + if (addresses->val == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } addresses->val[0] = addr; return 0; } @@ -1047,6 +1054,8 @@ krb5_free_addresses(krb5_context context, for(i = 0; i < addresses->len; i++) krb5_free_address(context, &addresses->val[i]); free(addresses->val); + addresses->len = 0; + addresses->val = NULL; return 0; } diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 3cfc780eb4..039484c650 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.132 2006/02/28 14:52:57 lha Exp $"); +RCSID("$Id: crypto.c,v 1.133 2006/03/07 19:34:55 lha Exp $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -3414,7 +3414,7 @@ decrypt_internal_derived(krb5_context context, l = len - et->confoundersize; memmove(p, p + et->confoundersize, l); result->data = realloc(p, l); - if(result->data == NULL) { + if(result->data == NULL && l != 0) { free(p); krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; @@ -3479,7 +3479,7 @@ decrypt_internal(krb5_context context, l = len - et->confoundersize - checksum_sz; memmove(p, p + et->confoundersize + checksum_sz, l); result->data = realloc(p, l); - if(result->data == NULL) { + if(result->data == NULL && l != 0) { free(p); krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; @@ -3523,7 +3523,7 @@ decrypt_internal_special(krb5_context context, memmove (p, p + cksum_sz + et->confoundersize, sz); result->data = realloc(p, sz); - if(result->data == NULL) { + if(result->data == NULL && sz != 0) { free(p); krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index aa7c62befc..dafe668b5d 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_for_creds.c,v 1.47 2006/02/03 11:37:29 lha Exp $"); +RCSID("$Id: get_for_creds.c,v 1.48 2006/03/07 19:38:09 lha Exp $"); static krb5_error_code add_addrs(krb5_context context, @@ -50,7 +50,7 @@ add_addrs(krb5_context context, ++n; tmp = realloc(addr->val, (addr->len + n) * sizeof(*addr->val)); - if (tmp == NULL) { + if (tmp == NULL && (addr->len + n) != 0) { krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; goto fail; diff --git a/source4/heimdal/lib/krb5/mk_req_ext.c b/source4/heimdal/lib/krb5/mk_req_ext.c index ab83d912ea..18b0e3552f 100644 --- a/source4/heimdal/lib/krb5/mk_req_ext.c +++ b/source4/heimdal/lib/krb5/mk_req_ext.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_req_ext.c,v 1.30 2005/01/05 06:31:01 lukeh Exp $"); +RCSID("$Id: mk_req_ext.c,v 1.32 2006/03/19 20:33:13 lha Exp $"); krb5_error_code _krb5_mk_req_internal(krb5_context context, @@ -45,120 +45,103 @@ _krb5_mk_req_internal(krb5_context context, krb5_key_usage checksum_usage, krb5_key_usage encrypt_usage) { - krb5_error_code ret; - krb5_data authenticator; - Checksum c; - Checksum *c_opt; - krb5_auth_context ac; + krb5_error_code ret; + krb5_data authenticator; + Checksum c; + Checksum *c_opt; + krb5_auth_context ac; - if(auth_context) { - if(*auth_context == NULL) - ret = krb5_auth_con_init(context, auth_context); - else - ret = 0; - ac = *auth_context; - } else - ret = krb5_auth_con_init(context, &ac); - if(ret) - return ret; + if(auth_context) { + if(*auth_context == NULL) + ret = krb5_auth_con_init(context, auth_context); + else + ret = 0; + ac = *auth_context; + } else + ret = krb5_auth_con_init(context, &ac); + if(ret) + return ret; - if(ac->local_subkey == NULL && (ap_req_options & AP_OPTS_USE_SUBKEY)) { - ret = krb5_auth_con_generatelocalsubkey(context, ac, &in_creds->session); - if(ret) - return ret; - } + if(ac->local_subkey == NULL && (ap_req_options & AP_OPTS_USE_SUBKEY)) { + ret = krb5_auth_con_generatelocalsubkey(context, + ac, + &in_creds->session); + if(ret) + goto out; + } -#if 0 - { - /* This is somewhat bogus since we're possibly overwriting a - value specified by the user, but it's the easiest way to make - the code use a compatible enctype */ - Ticket ticket; - krb5_keytype ticket_keytype; + krb5_free_keyblock(context, ac->keyblock); + ret = krb5_copy_keyblock(context, &in_creds->session, &ac->keyblock); + if (ret) + goto out; + + /* it's unclear what type of checksum we can use. try the best one, except: + * a) if it's configured differently for the current realm, or + * b) if the session key is des-cbc-crc + */ - ret = decode_Ticket(in_creds->ticket.data, - in_creds->ticket.length, - &ticket, - NULL); - krb5_enctype_to_keytype (context, - ticket.enc_part.etype, - &ticket_keytype); + if (in_data) { + if(ac->keyblock->keytype == ETYPE_DES_CBC_CRC) { + /* this is to make DCE secd (and older MIT kdcs?) happy */ + ret = krb5_create_checksum(context, + NULL, + 0, + CKSUMTYPE_RSA_MD4, + in_data->data, + in_data->length, + &c); + } else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5 || + ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56) { + /* this is to make MS kdc happy */ + ret = krb5_create_checksum(context, + NULL, + 0, + CKSUMTYPE_RSA_MD5, + in_data->data, + in_data->length, + &c); + } else { + krb5_crypto crypto; - if (ticket_keytype == in_creds->session.keytype) - krb5_auth_setenctype(context, - ac, - ticket.enc_part.etype); - free_Ticket(&ticket); - } -#endif + ret = krb5_crypto_init(context, ac->keyblock, 0, &crypto); + if (ret) + goto out; + ret = krb5_create_checksum(context, + crypto, + checksum_usage, + 0, + in_data->data, + in_data->length, + &c); + krb5_crypto_destroy(context, crypto); + } + c_opt = &c; + } else { + c_opt = NULL; + } - krb5_free_keyblock(context, ac->keyblock); - krb5_copy_keyblock(context, &in_creds->session, &ac->keyblock); + if (ret) + goto out; - /* it's unclear what type of checksum we can use. try the best one, except: - * a) if it's configured differently for the current realm, or - * b) if the session key is des-cbc-crc - */ - - if (in_data) { - if(ac->keyblock->keytype == ETYPE_DES_CBC_CRC) { - /* this is to make DCE secd (and older MIT kdcs?) happy */ - ret = krb5_create_checksum(context, - NULL, - 0, - CKSUMTYPE_RSA_MD4, - in_data->data, - in_data->length, - &c); - } else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5 || - ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56) { - /* this is to make MS kdc happy */ - ret = krb5_create_checksum(context, - NULL, - 0, - CKSUMTYPE_RSA_MD5, - in_data->data, - in_data->length, - &c); - } else { - krb5_crypto crypto; + ret = krb5_build_authenticator (context, + ac, + ac->keyblock->keytype, + in_creds, + c_opt, + NULL, + &authenticator, + encrypt_usage); + if (c_opt) + free_Checksum (c_opt); + if (ret) + goto out; - ret = krb5_crypto_init(context, ac->keyblock, 0, &crypto); - if (ret) - return ret; - ret = krb5_create_checksum(context, - crypto, - checksum_usage, - 0, - in_data->data, - in_data->length, - &c); - - krb5_crypto_destroy(context, crypto); - } - c_opt = &c; - } else { - c_opt = NULL; - } - - ret = krb5_build_authenticator (context, - ac, - ac->keyblock->keytype, - in_creds, - c_opt, - NULL, - &authenticator, - encrypt_usage); - if (c_opt) - free_Checksum (c_opt); - if (ret) + ret = krb5_build_ap_req (context, ac->keyblock->keytype, + in_creds, ap_req_options, authenticator, outbuf); +out: + if(auth_context == NULL) + krb5_auth_con_free(context, ac); return ret; - - ret = krb5_build_ap_req (context, ac->keyblock->keytype, - in_creds, ap_req_options, authenticator, outbuf); - if(auth_context == NULL) - krb5_auth_con_free(context, ac); - return ret; } krb5_error_code KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/rd_priv.c b/source4/heimdal/lib/krb5/rd_priv.c index bafd23e995..bf82ad556e 100644 --- a/source4/heimdal/lib/krb5/rd_priv.c +++ b/source4/heimdal/lib/krb5/rd_priv.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_priv.c,v 1.31 2004/05/25 21:39:13 lha Exp $"); +RCSID("$Id: rd_priv.c,v 1.32 2006/03/18 22:15:57 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_priv(krb5_context context, @@ -50,6 +50,9 @@ krb5_rd_priv(krb5_context context, krb5_keyblock *key; krb5_crypto crypto; + if (outdata) + krb5_data_zero(outdata); + if ((auth_context->flags & (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && outdata == NULL) @@ -158,7 +161,7 @@ krb5_rd_priv(krb5_context context, (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) { /* if these fields are not present in the priv-part, silently return zero */ - memset(outdata, 0, sizeof(*outdata)); + krb5_data_zero(outdata); if(part.timestamp) outdata->timestamp = *part.timestamp; if(part.usec) diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index 7bb4adabbd..d3d21aea3f 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: send_to_kdc.c,v 1.56 2005/06/17 04:33:11 lha Exp $"); +RCSID("$Id: send_to_kdc.c,v 1.57 2006/03/07 19:39:59 lha Exp $"); struct send_and_recv { krb5_send_and_recv_func_t func; @@ -102,7 +102,7 @@ recv_loop (int fd, krb5_data_free (rep); return -1; } - if(nbytes == 0) + if(nbytes <= 0) return 0; if (limit) -- cgit From c33f6b2c370379dfd010600adc59e7439f1318f7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 24 Apr 2006 09:36:24 +0000 Subject: r15192: Update Samba4 to use current lorikeet-heimdal. Andrew Bartlett (This used to be commit f0e538126c5cb29ca14ad0d8281eaa0a715ed94f) --- source4/heimdal/lib/krb5/acache.c | 64 +- source4/heimdal/lib/krb5/addr_families.c | 3 +- source4/heimdal/lib/krb5/build_auth.c | 11 +- source4/heimdal/lib/krb5/cache.c | 5 +- source4/heimdal/lib/krb5/config_file.c | 4 +- source4/heimdal/lib/krb5/crypto.c | 6 +- source4/heimdal/lib/krb5/data.c | 3 +- source4/heimdal/lib/krb5/fcache.c | 7 +- source4/heimdal/lib/krb5/get_for_creds.c | 7 +- source4/heimdal/lib/krb5/init_creds.c | 4 +- source4/heimdal/lib/krb5/init_creds_pw.c | 29 +- source4/heimdal/lib/krb5/keytab_any.c | 33 +- source4/heimdal/lib/krb5/keytab_file.c | 40 +- source4/heimdal/lib/krb5/keytab_keyfile.c | 3 +- source4/heimdal/lib/krb5/keytab_krb4.c | 13 +- source4/heimdal/lib/krb5/krb5-private.h | 14 +- source4/heimdal/lib/krb5/krb5-protos.h | 2 + source4/heimdal/lib/krb5/krb5_ccapi.h | 21 +- source4/heimdal/lib/krb5/krbhst.c | 7 +- source4/heimdal/lib/krb5/log.c | 8 +- source4/heimdal/lib/krb5/pkinit.c | 1732 ++++++----------------------- source4/heimdal/lib/krb5/principal.c | 22 +- source4/heimdal/lib/krb5/rd_cred.c | 7 +- source4/heimdal/lib/krb5/rd_priv.c | 8 +- source4/heimdal/lib/krb5/rd_req.c | 25 +- source4/heimdal/lib/krb5/replay.c | 10 +- source4/heimdal/lib/krb5/send_to_kdc.c | 5 +- source4/heimdal/lib/krb5/store.c | 23 +- source4/heimdal/lib/krb5/transited.c | 11 +- source4/heimdal/lib/krb5/v4_glue.c | 19 +- 30 files changed, 594 insertions(+), 1552 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c index 7cf2c65d89..b38104fc2d 100644 --- a/source4/heimdal/lib/krb5/acache.c +++ b/source4/heimdal/lib/krb5/acache.c @@ -37,7 +37,7 @@ #include #endif -RCSID("$Id: acache.c,v 1.14 2005/10/03 08:44:18 lha Exp $"); +RCSID("$Id: acache.c,v 1.15 2006/03/27 04:22:23 lha Exp $"); /* XXX should we fetch these for each open ? */ static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; @@ -218,7 +218,36 @@ make_cred_from_ccred(krb5_context context, } } - cred->flags.b = int2TicketFlags(incred->ticket_flags); /* XXX */ + cred->flags.i = 0; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDABLE) + cred->flags.b.forwardable = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_FORWARDED) + cred->flags.b.forwarded = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXIABLE) + cred->flags.b.proxiable = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PROXY) + cred->flags.b.proxy = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_MAY_POSTDATE) + cred->flags.b.may_postdate = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_POSTDATED) + cred->flags.b.postdated = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INVALID) + cred->flags.b.invalid = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_RENEWABLE) + cred->flags.b.renewable = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_INITIAL) + cred->flags.b.initial = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_PRE_AUTH) + cred->flags.b.pre_authent = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_HW_AUTH) + cred->flags.b.hw_authent = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED) + cred->flags.b.transited_policy_checked = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE) + cred->flags.b.ok_as_delegate = 1; + if (incred->ticket_flags & KRB5_CCAPI_TKT_FLG_ANONYMOUS) + cred->flags.b.anonymous = 1; + return 0; nomem: @@ -310,7 +339,36 @@ make_ccred_from_cred(krb5_context context, } cred->addresses[i] = NULL; - cred->ticket_flags = TicketFlags2int(incred->flags.b); /* XXX */ + cred->ticket_flags = 0; + if (incred->flags.b.forwardable) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDABLE; + if (incred->flags.b.forwarded) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_FORWARDED; + if (incred->flags.b.proxiable) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXIABLE; + if (incred->flags.b.proxy) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PROXY; + if (incred->flags.b.may_postdate) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_MAY_POSTDATE; + if (incred->flags.b.postdated) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_POSTDATED; + if (incred->flags.b.invalid) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INVALID; + if (incred->flags.b.renewable) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_RENEWABLE; + if (incred->flags.b.initial) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_INITIAL; + if (incred->flags.b.pre_authent) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_PRE_AUTH; + if (incred->flags.b.hw_authent) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_HW_AUTH; + if (incred->flags.b.transited_policy_checked) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED; + if (incred->flags.b.ok_as_delegate) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE; + if (incred->flags.b.anonymous) + cred->ticket_flags |= KRB5_CCAPI_TKT_FLG_ANONYMOUS; + return 0; fail: diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c index cf460ba725..ebdbcfed46 100644 --- a/source4/heimdal/lib/krb5/addr_families.c +++ b/source4/heimdal/lib/krb5/addr_families.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: addr_families.c,v 1.50 2006/03/17 22:12:13 lha Exp $"); +RCSID("$Id: addr_families.c,v 1.51 2006/04/02 02:17:31 lha Exp $"); struct addr_operations { int af; @@ -1136,6 +1136,7 @@ krb5_make_addrport (krb5_context context, if (ret) { krb5_set_error_string(context, "malloc: out of memory"); free (*res); + *res = NULL; return ret; } p = (*res)->address.data; diff --git a/source4/heimdal/lib/krb5/build_auth.c b/source4/heimdal/lib/krb5/build_auth.c index 1c38721b02..9eff09bb0a 100644 --- a/source4/heimdal/lib/krb5/build_auth.c +++ b/source4/heimdal/lib/krb5/build_auth.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: build_auth.c,v 1.42 2005/01/05 02:34:53 lukeh Exp $"); +RCSID("$Id: build_auth.c,v 1.43 2006/04/10 08:53:21 lha Exp $"); static krb5_error_code make_etypelist(krb5_context context, @@ -116,13 +116,12 @@ krb5_build_authenticator (krb5_context context, krb5_error_code ret; krb5_crypto crypto; - auth = malloc(sizeof(*auth)); + auth = calloc(1, sizeof(*auth)); if (auth == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - memset (auth, 0, sizeof(*auth)); auth->authenticator_vno = 5; copy_Realm(&cred->client->realm, &auth->crealm); copy_PrincipalName(&cred->client->name, &auth->cname); @@ -161,10 +160,8 @@ krb5_build_authenticator (krb5_context context, /* XXX - Copy more to auth_context? */ - if (auth_context) { - auth_context->authenticator->ctime = auth->ctime; - auth_context->authenticator->cusec = auth->cusec; - } + auth_context->authenticator->ctime = auth->ctime; + auth_context->authenticator->cusec = auth->cusec; ASN1_MALLOC_ENCODE(Authenticator, buf, buf_size, auth, &len, ret); if (ret) diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index efb2ad1374..b21d42d653 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c,v 1.77 2005/12/13 15:42:36 lha Exp $"); +RCSID("$Id: cache.c,v 1.79 2006/04/02 00:54:48 lha Exp $"); /* * Add a new ccache type with operations `ops', overwriting any @@ -316,7 +316,7 @@ _krb5_expand_default_cc_name(krb5_context context, const char *str, char **res) } if (append == NULL) { free(*res); - res = NULL; + *res = NULL; krb5_set_error_string(context, "malloc - out of memory"); return ENOMEM; } @@ -324,6 +324,7 @@ _krb5_expand_default_cc_name(krb5_context context, const char *str, char **res) tlen = strlen(append); tmp = realloc(*res, len + tlen + 1); if (tmp == NULL) { + free(append); free(*res); *res = NULL; krb5_set_error_string(context, "malloc - out of memory"); diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c index 86e286c638..66051303ed 100644 --- a/source4/heimdal/lib/krb5/config_file.c +++ b/source4/heimdal/lib/krb5/config_file.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: config_file.c,v 1.53 2005/06/16 20:22:53 lha Exp $"); +RCSID("$Id: config_file.c,v 1.54 2006/04/02 00:59:19 lha Exp $"); #ifndef HAVE_NETINFO @@ -574,7 +574,7 @@ krb5_config_vget_strings(krb5_context context, } if(nstr){ char **tmp = realloc(strings, (nstr + 1) * sizeof(*strings)); - if(strings == NULL) + if(tmp == NULL) goto cleanup; strings = tmp; strings[nstr] = NULL; diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 039484c650..3a90995283 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.133 2006/03/07 19:34:55 lha Exp $"); +RCSID("$Id: crypto.c,v 1.134 2006/04/10 08:58:53 lha Exp $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -4096,7 +4096,7 @@ krb5_string_to_key_derived(krb5_context context, struct encryption_type *et = _find_enctype(etype); krb5_error_code ret; struct key_data kd; - size_t keylen = et->keytype->bits / 8; + size_t keylen; u_char *tmp; if(et == NULL) { @@ -4104,6 +4104,8 @@ krb5_string_to_key_derived(krb5_context context, etype); return KRB5_PROG_ETYPE_NOSUPP; } + keylen = et->keytype->bits / 8; + ALLOC(kd.key, 1); if(kd.key == NULL) { krb5_set_error_string (context, "malloc: out of memory"); diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c index 9cf1410e70..3192c4c64f 100644 --- a/source4/heimdal/lib/krb5/data.c +++ b/source4/heimdal/lib/krb5/data.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: data.c,v 1.19 2004/05/25 21:22:23 lha Exp $"); +RCSID("$Id: data.c,v 1.20 2006/04/02 01:06:07 lha Exp $"); void KRB5_LIB_FUNCTION krb5_data_zero(krb5_data *p) @@ -114,6 +114,7 @@ krb5_copy_data(krb5_context context, if(ret) { krb5_clear_error_string (context); free(*outdata); + *outdata = NULL; } return ret; } diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c index f8ebe837b7..79b809d2a2 100644 --- a/source4/heimdal/lib/krb5/fcache.c +++ b/source4/heimdal/lib/krb5/fcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: fcache.c,v 1.51 2005/08/12 13:31:19 lha Exp $"); +RCSID("$Id: fcache.c,v 1.52 2006/04/02 01:04:37 lha Exp $"); typedef struct krb5_fcache{ char *filename; @@ -269,10 +269,11 @@ fcc_gen_new(krb5_context context, krb5_ccache *id) } fd = mkstemp(file); if(fd < 0) { + int ret = errno; + krb5_set_error_string(context, "mkstemp %s", file); free(f); free(file); - krb5_set_error_string(context, "mkstemp %s", file); - return errno; + return ret; } close(fd); f->filename = file; diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index dafe668b5d..661d05663b 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_for_creds.c,v 1.48 2006/03/07 19:38:09 lha Exp $"); +RCSID("$Id: get_for_creds.c,v 1.49 2006/04/10 09:28:15 lha Exp $"); static krb5_error_code add_addrs(krb5_context context, @@ -180,10 +180,7 @@ krb5_get_forwarded_creds (krb5_context context, addrs.len = 0; addrs.val = NULL; - if (in_creds->client && in_creds->client->realm) - realm = in_creds->client->realm; - else - realm = in_creds->server->realm; + realm = in_creds->client->realm; krb5_appdefault_boolean(context, NULL, realm, "no-addresses-ever", TRUE, &noaddr_ever); diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index 316c2f02eb..88de280a00 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c,v 1.22 2006/02/03 11:42:31 lha Exp $"); +RCSID("$Id: init_creds.c,v 1.23 2006/04/02 01:08:30 lha Exp $"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) @@ -75,7 +75,7 @@ _krb5_get_init_creds_opt_copy(krb5_context context, krb5_get_init_creds_opt *opt; *out = NULL; - opt = malloc(sizeof(*opt)); + opt = calloc(1, sizeof(*opt)); if (opt == NULL) { krb5_set_error_string(context, "out of memory"); return ENOMEM; diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 3c694624bf..489a88a31b 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c,v 1.90 2005/10/12 12:45:11 lha Exp $"); +RCSID("$Id: init_creds_pw.c,v 1.92 2006/04/02 01:20:15 lha Exp $"); typedef struct krb5_get_init_creds_ctx { krb5_kdc_flags flags; @@ -79,8 +79,10 @@ default_s2k_func(krb5_context context, krb5_enctype type, return ENOMEM; ret = krb5_string_to_key_data_salt_opaque(context, type, password, salt, opaque, *key); - if (ret) + if (ret) { free(*key); + *key = NULL; + } return ret; } @@ -545,23 +547,14 @@ init_creds_init_as_req (krb5_context context, krb5_set_error_string(context, "malloc: out of memory"); goto fail; } - if (creds->client) { - ret = _krb5_principal2principalname (a->req_body.cname, creds->client); - if (ret) - goto fail; - ret = copy_Realm(&creds->client->realm, &a->req_body.realm); - if (ret) - goto fail; - } else { - krb5_realm realm; - a->req_body.cname = NULL; - ret = krb5_get_default_realm(context, &realm); - if (ret) - goto fail; - ret = copy_Realm(&realm, &a->req_body.realm); - free(realm); - } + ret = _krb5_principal2principalname (a->req_body.cname, creds->client); + if (ret) + goto fail; + ret = copy_Realm(&creds->client->realm, &a->req_body.realm); + if (ret) + goto fail; + ret = _krb5_principal2principalname (a->req_body.sname, creds->server); if (ret) goto fail; diff --git a/source4/heimdal/lib/krb5/keytab_any.c b/source4/heimdal/lib/krb5/keytab_any.c index 667788c69d..d5130aaad8 100644 --- a/source4/heimdal/lib/krb5/keytab_any.c +++ b/source4/heimdal/lib/krb5/keytab_any.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_any.c,v 1.7 2002/10/21 13:36:59 joda Exp $"); +RCSID("$Id: keytab_any.c,v 1.8 2006/04/10 09:20:13 lha Exp $"); struct any_data { krb5_keytab kt; @@ -162,23 +162,22 @@ any_next_entry (krb5_context context, ret = krb5_kt_next_entry(context, ed->a->kt, entry, &ed->cursor); if (ret == 0) return 0; - else if (ret == KRB5_KT_END) { - ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor); - if (ret2) - return ret2; - while ((ed->a = ed->a->next) != NULL) { - ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor); - if (ret2 == 0) - break; - } - if (ed->a == NULL) { - krb5_clear_error_string (context); - return KRB5_KT_END; - } - } else + else if (ret != KRB5_KT_END) return ret; - } while (ret == KRB5_KT_END); - return ret; + + ret2 = krb5_kt_end_seq_get (context, ed->a->kt, &ed->cursor); + if (ret2) + return ret2; + while ((ed->a = ed->a->next) != NULL) { + ret2 = krb5_kt_start_seq_get(context, ed->a->kt, &ed->cursor); + if (ret2 == 0) + break; + } + if (ed->a == NULL) { + krb5_clear_error_string (context); + return KRB5_KT_END; + } + } while (1); } static krb5_error_code diff --git a/source4/heimdal/lib/krb5/keytab_file.c b/source4/heimdal/lib/krb5/keytab_file.c index 6ff2680ed1..f9a76e634a 100644 --- a/source4/heimdal/lib/krb5/keytab_file.c +++ b/source4/heimdal/lib/krb5/keytab_file.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_file.c,v 1.20 2005/07/13 06:08:07 lha Exp $"); +RCSID("$Id: keytab_file.c,v 1.22 2006/04/07 21:57:31 lha Exp $"); #define KRB5_KT_VNO_1 1 #define KRB5_KT_VNO_2 2 @@ -164,7 +164,7 @@ krb5_kt_ret_principal(krb5_context context, int i; int ret; krb5_principal p; - int16_t tmp; + int16_t len; ALLOC(p, 1); if(p == NULL) { @@ -172,25 +172,34 @@ krb5_kt_ret_principal(krb5_context context, return ENOMEM; } - ret = krb5_ret_int16(sp, &tmp); - if(ret) - return ret; + ret = krb5_ret_int16(sp, &len); + if(ret) { + krb5_set_error_string(context, + "Failed decoding length of keytab principal"); + goto out; + } if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) - tmp--; - p->name.name_string.len = tmp; + len--; + if (len < 0) { + krb5_set_error_string(context, + "Keytab principal contains invalid length"); + ret = KRB5_KT_END; + goto out; + } ret = krb5_kt_ret_string(context, sp, &p->realm); if(ret) - return ret; - p->name.name_string.val = calloc(p->name.name_string.len, - sizeof(*p->name.name_string.val)); + goto out; + p->name.name_string.val = calloc(len, sizeof(*p->name.name_string.val)); if(p->name.name_string.val == NULL) { krb5_set_error_string (context, "malloc: out of memory"); - return ENOMEM; + ret = ENOMEM; + goto out; } + p->name.name_string.len = len; for(i = 0; i < p->name.name_string.len; i++){ ret = krb5_kt_ret_string(context, sp, p->name.name_string.val + i); if(ret) - return ret; + goto out; } if (krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) p->name.name_type = KRB5_NT_UNKNOWN; @@ -199,10 +208,13 @@ krb5_kt_ret_principal(krb5_context context, ret = krb5_ret_int32(sp, &tmp32); p->name.name_type = tmp32; if (ret) - return ret; + goto out; } *princ = p; return 0; +out: + krb5_free_principal(context, p); + return ret; } static krb5_error_code @@ -423,7 +435,7 @@ loop: } } if(start) *start = pos; - if(end) *end = *start + 4 + len; + if(end) *end = pos + 4 + len; out: krb5_storage_seek(cursor->sp, pos + 4 + len, SEEK_SET); return ret; diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c index 5c94291e72..32fb48a8a2 100644 --- a/source4/heimdal/lib/krb5/keytab_keyfile.c +++ b/source4/heimdal/lib/krb5/keytab_keyfile.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_keyfile.c,v 1.17 2005/09/30 11:20:53 lha Exp $"); +RCSID("$Id: keytab_keyfile.c,v 1.18 2006/04/02 01:24:52 lha Exp $"); /* afs keyfile operations --------------------------------------- */ @@ -94,6 +94,7 @@ get_cell_and_realm (krb5_context context, f = fopen (AFS_SERVERMAGICKRBCONF, "r"); if (f != NULL) { if (fgets (buf, sizeof(buf), f) == NULL) { + free (d->cell); fclose (f); krb5_set_error_string (context, "no realm in %s", AFS_SERVERMAGICKRBCONF); diff --git a/source4/heimdal/lib/krb5/keytab_krb4.c b/source4/heimdal/lib/krb5/keytab_krb4.c index 1a83faca57..19e7f106bf 100644 --- a/source4/heimdal/lib/krb5/keytab_krb4.c +++ b/source4/heimdal/lib/krb5/keytab_krb4.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_krb4.c,v 1.13 2005/05/19 04:13:18 lha Exp $"); +RCSID("$Id: keytab_krb4.c,v 1.15 2006/04/10 17:10:53 lha Exp $"); struct krb4_kt_data { char *filename; @@ -139,6 +139,11 @@ krb4_kt_start_seq_get_int (krb5_context context, return ret; } c->sp = krb5_storage_from_fd(c->fd); + if(c->sp == NULL) { + close(c->fd); + free(ed); + return ENOMEM; + } krb5_storage_set_eof_code(c->sp, KRB5_KT_END); return 0; } @@ -302,11 +307,11 @@ krb4_kt_add_entry (krb5_context context, } } sp = krb5_storage_from_fd(fd); - krb5_storage_set_eof_code(sp, KRB5_KT_END); if(sp == NULL) { close(fd); return ENOMEM; } + krb5_storage_set_eof_code(sp, KRB5_KT_END); ret = krb4_store_keytab_entry(context, entry, sp); krb5_storage_free(sp); if(close (fd) < 0) @@ -316,8 +321,8 @@ krb4_kt_add_entry (krb5_context context, static krb5_error_code krb4_kt_remove_entry(krb5_context context, - krb5_keytab id, - krb5_keytab_entry *entry) + krb5_keytab id, + krb5_keytab_entry *entry) { struct krb4_kt_data *d = id->data; krb5_error_code ret; diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 8d9b3c62ac..00126d60ed 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -302,19 +302,13 @@ void KRB5_LIB_FUNCTION _krb5_pk_cert_free (struct krb5_pk_cert */*cert*/); krb5_error_code KRB5_LIB_FUNCTION -_krb5_pk_create_sign ( - krb5_context /*context*/, - const heim_oid */*eContentType*/, - krb5_data */*eContent*/, - struct krb5_pk_identity */*id*/, - krb5_data */*sd_data*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_pk_load_openssl_id ( +_krb5_pk_load_id ( krb5_context /*context*/, struct krb5_pk_identity **/*ret_id*/, const char */*user_id*/, - const char */*x509_anchors*/, + const char */*anchor_id*/, + char * const */*chain*/, + char * const */*revoke*/, krb5_prompter_fct /*prompter*/, void */*prompter_data*/, char */*password*/); diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index d7e74621ef..56f43f6c3d 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -1874,6 +1874,8 @@ krb5_get_init_creds_opt_set_pkinit ( krb5_principal /*principal*/, const char */*user_id*/, const char */*x509_anchors*/, + char * const * /*chain*/, + char * const * /*revoke*/, int /*flags*/, krb5_prompter_fct /*prompter*/, void */*prompter_data*/, diff --git a/source4/heimdal/lib/krb5/krb5_ccapi.h b/source4/heimdal/lib/krb5/krb5_ccapi.h index 00c30d7791..29b2ddbecc 100644 --- a/source4/heimdal/lib/krb5/krb5_ccapi.h +++ b/source4/heimdal/lib/krb5/krb5_ccapi.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_ccapi.h,v 1.1 2004/09/11 04:00:42 lha Exp $ */ +/* $Id: krb5_ccapi.h,v 1.2 2006/03/27 04:21:06 lha Exp $ */ #ifndef KRB5_CCAPI_H #define KRB5_CCAPI_H 1 @@ -43,7 +43,8 @@ enum { }; enum { - ccapi_version_3 = 3 + ccapi_version_3 = 3, + ccapi_version_4 = 4 }; enum { @@ -108,7 +109,21 @@ struct cc_credentials_v5_t { cc_time_t endtime; cc_time_t renew_till; cc_uint32 is_skey; - cc_uint32 ticket_flags; /* XXX ticket flags undefined */ + cc_uint32 ticket_flags; +#define KRB5_CCAPI_TKT_FLG_FORWARDABLE 0x40000000 +#define KRB5_CCAPI_TKT_FLG_FORWARDED 0x20000000 +#define KRB5_CCAPI_TKT_FLG_PROXIABLE 0x10000000 +#define KRB5_CCAPI_TKT_FLG_PROXY 0x08000000 +#define KRB5_CCAPI_TKT_FLG_MAY_POSTDATE 0x04000000 +#define KRB5_CCAPI_TKT_FLG_POSTDATED 0x02000000 +#define KRB5_CCAPI_TKT_FLG_INVALID 0x01000000 +#define KRB5_CCAPI_TKT_FLG_RENEWABLE 0x00800000 +#define KRB5_CCAPI_TKT_FLG_INITIAL 0x00400000 +#define KRB5_CCAPI_TKT_FLG_PRE_AUTH 0x00200000 +#define KRB5_CCAPI_TKT_FLG_HW_AUTH 0x00100000 +#define KRB5_CCAPI_TKT_FLG_TRANSIT_POLICY_CHECKED 0x00080000 +#define KRB5_CCAPI_TKT_FLG_OK_AS_DELEGATE 0x00040000 +#define KRB5_CCAPI_TKT_FLG_ANONYMOUS 0x00020000 cc_data **addresses; cc_data ticket; cc_data second_ticket; diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index ef9f5dbd60..221bd706f4 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: krbhst.c,v 1.53 2005/10/08 15:40:50 lha Exp $"); +RCSID("$Id: krbhst.c,v 1.55 2006/04/02 10:32:20 lha Exp $"); static int string_to_proto(const char *string) @@ -241,8 +241,9 @@ _krb5_krbhost_info_move(krb5_context context, krb5_krbhst_info *from, krb5_krbhst_info **to) { + size_t hostnamelen = strlen(from->hostname); /* trailing NUL is included in structure */ - *to = calloc(1, sizeof(**to) + strlen(from->hostname)); + *to = calloc(1, sizeof(**to) + hostnamelen); if(*to == NULL) { krb5_set_error_string(context, "malloc - out of memory"); return ENOMEM; @@ -254,7 +255,7 @@ _krb5_krbhost_info_move(krb5_context context, (*to)->ai = from->ai; from->ai = NULL; (*to)->next = NULL; - strcpy((*to)->hostname, from->hostname); + memcpy((*to)->hostname, from->hostname, hostnamelen + 1); return 0; } diff --git a/source4/heimdal/lib/krb5/log.c b/source4/heimdal/lib/krb5/log.c index 4f6381c858..7e478bf1e0 100644 --- a/source4/heimdal/lib/krb5/log.c +++ b/source4/heimdal/lib/krb5/log.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: log.c,v 1.36 2005/06/17 04:25:05 lha Exp $"); +RCSID("$Id: log.c,v 1.38 2006/04/10 09:41:26 lha Exp $"); struct facility { int min; @@ -284,7 +284,7 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) ret = open_file(context, f, min, max, NULL, NULL, stderr, 1); }else if(strcmp(p, "CONSOLE") == 0){ ret = open_file(context, f, min, max, "/dev/console", "w", NULL, 0); - }else if(strncmp(p, "FILE:", 4) == 0 && (p[4] == ':' || p[4] == '=')){ + }else if(strncmp(p, "FILE", 4) == 0 && (p[4] == ':' || p[4] == '=')){ char *fn; FILE *file = NULL; int keep_open = 0; @@ -300,6 +300,7 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) ret = errno; krb5_set_error_string (context, "open(%s): %s", fn, strerror(ret)); + free(fn); return ret; } file = fdopen(i, "a"); @@ -308,12 +309,13 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) close(i); krb5_set_error_string (context, "fdopen(%s): %s", fn, strerror(ret)); + free(fn); return ret; } keep_open = 1; } ret = open_file(context, f, min, max, fn, "a", file, keep_open); - }else if(strncmp(p, "DEVICE=", 6) == 0){ + }else if(strncmp(p, "DEVICE", 6) == 0 && (p[6] == ':' || p[6] == '=')){ ret = open_file(context, f, min, max, strdup(p + 7), "w", NULL, 0); }else if(strncmp(p, "SYSLOG", 6) == 0 && (p[6] == '\0' || p[6] == ':')){ char severity[128] = ""; diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 1247bb22ca..fa4fb4699e 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.77 2006/02/14 10:08:29 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.88 2006/04/23 21:30:17 lha Exp $"); struct krb5_dh_moduli { char *name; @@ -45,71 +45,35 @@ struct krb5_dh_moduli { #ifdef PKINIT -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_DIRENT_H -#include -#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#include -#include "heim_asn1.h" -#include "rfc2459_asn1.h" -#include "cms_asn1.h" -#include "pkinit_asn1.h" +#include enum { COMPAT_WIN2K = 1, COMPAT_IETF = 2 }; -#define OPENSSL_ASN1_MALLOC_ENCODE(T, B, BL, S, R) \ -{ \ - unsigned char *p; \ - (BL) = i2d_##T((S), NULL); \ - if ((BL) <= 0) { \ - (R) = EINVAL; \ - } else { \ - (B) = malloc((BL)); \ - if ((B) == NULL) { \ - (R) = ENOMEM; \ - } else { \ - p = (B); \ - (R) = 0; \ - (BL) = i2d_##T((S), &p); \ - if ((BL) <= 0) { \ - free((B)); \ - (R) = ASN1_OVERRUN; \ - } \ - } \ - } \ -} - -/* ENGING_load_private_key requires a UI_METHOD and data - * if to be usable from PAM - */ - -struct krb5_ui_data { - krb5_context context; - krb5_prompter_fct prompter; - void * prompter_data; -}; - struct krb5_pk_identity { - EVP_PKEY *private_key; - STACK_OF(X509) *cert; - STACK_OF(X509) *trusted_certs; - STACK_OF(X509_CRL) *crls; - ENGINE *engine; + hx509_context hx509ctx; + hx509_verify_ctx verify_ctx; + hx509_certs certs; + hx509_certs anchors; + hx509_certs certpool; + hx509_revoke_ctx revoke; }; struct krb5_pk_cert { - X509 *cert; + hx509_cert cert; }; struct krb5_pk_init_ctx_data { @@ -118,13 +82,16 @@ struct krb5_pk_init_ctx_data { krb5_data *clientDHNonce; struct krb5_dh_moduli **m; int require_binding; + int require_eku; + int require_krbtgt_otherName; }; void KRB5_LIB_FUNCTION _krb5_pk_cert_free(struct krb5_pk_cert *cert) { - if (cert->cert) - X509_free(cert->cert); + if (cert->cert) { + hx509_cert_free(cert->cert); + } free(cert); } @@ -138,7 +105,7 @@ BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer) return ENOMEM; } BN_bn2bin(bn, integer->data); - integer->negative = bn->neg; + integer->negative = BN_is_negative(bn); return 0; } @@ -152,315 +119,44 @@ integer_to_BN(krb5_context context, const char *field, const heim_integer *f) krb5_set_error_string(context, "PKINIT: parsing BN failed %s", field); return NULL; } - bn->neg = f->negative; + BN_set_negative(bn, f->negative); return bn; } -/* - * UI ex_data has the callback_data as passed to Engine. This is far - * from being complete, we will only process one prompt - */ - -static int -krb5_ui_method_read_string(UI *ui, UI_STRING *uis) -{ - char *buffer; - size_t length; - krb5_error_code ret; - krb5_prompt prompt; - krb5_data password_data; - struct krb5_ui_data *ui_data; - - ui_data = (struct krb5_ui_data *)UI_get_app_data(ui); - - switch (UI_get_string_type(uis)) { - case UIT_INFO: - case UIT_ERROR: - /* looks like the RedHat pam_prompter might handle - * INFO and ERROR, Will see what happens */ - case UIT_VERIFY: - case UIT_PROMPT: - length = UI_get_result_maxsize(uis); - buffer = malloc(length); - if (buffer == NULL) { - krb5_set_error_string(ui_data->context, "malloc: out of memory"); - return 0; - } - password_data.data = buffer; - password_data.length = length; - - prompt.prompt = UI_get0_output_string(uis); - prompt.hidden = !(UI_get_input_flags(uis) & UI_INPUT_FLAG_ECHO); - prompt.reply = &password_data; - prompt.type = KRB5_PROMPT_TYPE_PASSWORD; - - ret = (*ui_data->prompter)(ui_data->context, - ui_data->prompter_data, - NULL, NULL, 1, &prompt); - if (ret == 0) { - buffer[length - 1] = '\0'; - UI_set_result(ui, uis, password_data.data); - - /* - * RedHat pam_krb5 pam_prompter does a strdup but others - * may copy into buffer. XXX should we just leak the - * memory instead ? - */ - - if (buffer != password_data.data) - free(password_data.data); - memset (buffer, 0, length); - free(buffer); - return 1; - } - memset (buffer, 0, length); - free(buffer); - break; - case UIT_NONE: - case UIT_BOOLEAN: - /* XXX for now do not handle */ - break; - - } - return 0; -} - static krb5_error_code -set_digest_alg(DigestAlgorithmIdentifier *id, - const heim_oid *oid, - void *param, size_t length) -{ - krb5_error_code ret; - if (param) { - id->parameters = malloc(sizeof(*id->parameters)); - if (id->parameters == NULL) - return ENOMEM; - id->parameters->data = malloc(length); - if (id->parameters->data == NULL) { - free(id->parameters); - id->parameters = NULL; - return ENOMEM; - } - memcpy(id->parameters->data, param, length); - id->parameters->length = length; - } else - id->parameters = NULL; - ret = copy_oid(oid, &id->algorithm); - if (ret) { - if (id->parameters) { - free(id->parameters->data); - free(id->parameters); - id->parameters = NULL; - } - return ret; - } - return 0; -} - -krb5_error_code KRB5_LIB_FUNCTION _krb5_pk_create_sign(krb5_context context, const heim_oid *eContentType, krb5_data *eContent, struct krb5_pk_identity *id, krb5_data *sd_data) { - SignerInfo *signer_info; - X509 *user_cert; - heim_integer *serial; - krb5_error_code ret; - krb5_data buf; - SignedData sd; - EVP_MD_CTX md; - int i; - unsigned len; - size_t size; - - X509_NAME *issuer_name; - - memset(&sd, 0, sizeof(sd)); - - if (id == NULL) - return HEIM_PKINIT_NO_CERTIFICATE; - if (id->cert == NULL) - return HEIM_PKINIT_NO_CERTIFICATE; - if (id->private_key == NULL) - return HEIM_PKINIT_NO_PRIVATE_KEY; - - if (sk_X509_num(id->cert) == 0) - return HEIM_PKINIT_NO_CERTIFICATE; - - sd.version = 3; - - sd.digestAlgorithms.len = 0; - sd.digestAlgorithms.val = NULL; - copy_oid(eContentType, &sd.encapContentInfo.eContentType); - ALLOC(sd.encapContentInfo.eContent, 1); - if (sd.encapContentInfo.eContent == NULL) { - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; - } - - ret = krb5_data_copy(&buf, eContent->data, eContent->length); - if (ret) { - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; - } - - sd.encapContentInfo.eContent->data = buf.data; - sd.encapContentInfo.eContent->length = buf.length; - - ALLOC_SEQ(&sd.signerInfos, 1); - if (sd.signerInfos.val == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - ret = ENOMEM; - goto out; - } - - signer_info = &sd.signerInfos.val[0]; - - user_cert = sk_X509_value(id->cert, 0); - if (user_cert == NULL) { - krb5_set_error_string(context, "pkinit: no user certificate"); - ret = HEIM_PKINIT_NO_CERTIFICATE; - goto out; - } - - signer_info->version = 1; - - issuer_name = X509_get_issuer_name(user_cert); - - OPENSSL_ASN1_MALLOC_ENCODE(X509_NAME, - buf.data, - buf.length, - issuer_name, - ret); - if (ret) { - krb5_set_error_string(context, "pkinit: failed encoding name"); - goto out; - } - ret = decode_Name(buf.data, buf.length, - &signer_info->sid.u.issuerAndSerialNumber.issuer, - NULL); - free(buf.data); - if (ret) { - krb5_set_error_string(context, "pkinit: failed to parse Name"); - goto out; - } - signer_info->sid.element = choice_CMSIdentifier_issuerAndSerialNumber; - - serial = &signer_info->sid.u.issuerAndSerialNumber.serialNumber; - { - ASN1_INTEGER *isn = X509_get_serialNumber(user_cert); - BIGNUM *bn = ASN1_INTEGER_to_BN(isn, NULL); - if (bn == NULL) { - ret = ENOMEM; - krb5_set_error_string(context, "pkinit: failed allocating " - "serial number"); - goto out; - } - ret = BN_to_integer(context, bn, serial); - BN_free(bn); - if (ret) { - krb5_set_error_string(context, "pkinit: failed encoding " - "serial number"); - goto out; - } - } - - ret = set_digest_alg(&signer_info->digestAlgorithm, - oid_id_secsig_sha_1(), "\x05\x00", 2); - if (ret) { - krb5_set_error_string(context, "malloc: out of memory"); - goto out; - } - - signer_info->signedAttrs = NULL; - signer_info->unsignedAttrs = NULL; - - copy_oid(oid_id_pkcs1_rsaEncryption(), - &signer_info->signatureAlgorithm.algorithm); - signer_info->signatureAlgorithm.parameters = NULL; - - buf.data = malloc(EVP_PKEY_size(id->private_key)); - if (buf.data == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - ret = ENOMEM; - goto out; - } - - EVP_SignInit(&md, EVP_sha1()); - EVP_SignUpdate(&md, - sd.encapContentInfo.eContent->data, - sd.encapContentInfo.eContent->length); - ret = EVP_SignFinal(&md, buf.data, &len, id->private_key); - if (ret != 1) { - free(buf.data); - krb5_set_error_string(context, "PKINIT: failed to sign with " - "private key: %s", - ERR_error_string(ERR_get_error(), NULL)); - ret = EINVAL; - goto out; - } - - signer_info->signature.data = buf.data; - signer_info->signature.length = len; - - ALLOC_SEQ(&sd.digestAlgorithms, 1); - if (sd.digestAlgorithms.val == NULL) { - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; - } - - ret = set_digest_alg(&sd.digestAlgorithms.val[0], - oid_id_secsig_sha_1(), "\x05\x00", 2); - if (ret) { - krb5_set_error_string(context, "malloc: out of memory"); - goto out; - } + hx509_cert cert; + hx509_query *q; + int ret; - ALLOC(sd.certificates, 1); - if (sd.certificates == NULL) { - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; - } + ret = hx509_query_alloc(id->hx509ctx, &q); + if (ret) + return ret; - i = sk_X509_num(id->cert); - sd.certificates->val = malloc(sizeof(sd.certificates->val[0]) * i); - if (sd.certificates->val == NULL) { - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; - } - sd.certificates->len = i; - - for (i = 0; i < sk_X509_num(id->cert); i++) { - OPENSSL_ASN1_MALLOC_ENCODE(X509, - sd.certificates->val[i].data, - sd.certificates->val[i].length, - sk_X509_value(id->cert, i), - ret); - if (ret) { - krb5_clear_error_string(context); - goto out; - } - } + hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); + hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); - ASN1_MALLOC_ENCODE(SignedData, sd_data->data, sd_data->length, - &sd, &size, ret); - if (ret) { - krb5_set_error_string(context, "SignedData failed %d", ret); - goto out; - } - if (sd_data->length != size) - krb5_abortx(context, "internal ASN1 encoder error"); + ret = hx509_certs_find(id->hx509ctx, id->certs, q, &cert); + hx509_query_free(id->hx509ctx, q); + if (ret) + return ret; - out: - free_SignedData(&sd); + ret = hx509_cms_create_signed_1(id->hx509ctx, + eContentType, + eContent->data, + eContent->length, + NULL, + cert, + NULL, + NULL, + sd_data); + hx509_cert_free(cert); return ret; } @@ -813,230 +509,23 @@ _krb5_pk_mk_padata(krb5_context context, } else type = COMPAT_IETF; - return pk_mk_padata(context, type, ctx, req_body, nonce, md); -} + ctx->require_eku = + krb5_config_get_bool_default(context, NULL, + TRUE, + "realms", + req_body->realm, + "pkinit_require_eku", + NULL); + ctx->require_krbtgt_otherName = + krb5_config_get_bool_default(context, NULL, + TRUE, + "realms", + req_body->realm, + "pkinit_require_krbtgt_otherName", + NULL); -static krb5_boolean -pk_peer_compare(krb5_context context, - const SignerIdentifier *peer1, - X509 *peer2) -{ - switch (peer1->element) { - case choice_CMSIdentifier_issuerAndSerialNumber: { - ASN1_INTEGER *i; - const heim_integer *serial; - X509_NAME *name; - unsigned char *p; - size_t len; - - i = X509_get_serialNumber(peer2); - serial = &peer1->u.issuerAndSerialNumber.serialNumber; - - if (i->length != serial->length || - memcmp(i->data, serial->data, i->length) != 0) - return FALSE; - - p = peer1->u.issuerAndSerialNumber.issuer._save.data; - len = peer1->u.issuerAndSerialNumber.issuer._save.length; - name = d2i_X509_NAME(NULL, &p, len); - if (name == NULL) - return FALSE; - - if (X509_NAME_cmp(name, X509_get_issuer_name(peer2)) != 0) { - X509_NAME_free(name); - return FALSE; - } - X509_NAME_free(name); - break; - } - case choice_CMSIdentifier_subjectKeyIdentifier: - return FALSE; - default: - return FALSE; - } - return TRUE; -} - -static krb5_error_code -pk_decrypt_key(krb5_context context, - heim_octet_string *encrypted_key, - EVP_PKEY *priv_key, - krb5_keyblock *key) -{ - int ret; - unsigned char *buf; - buf = malloc(EVP_PKEY_size(priv_key)); - if (buf == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - ret = EVP_PKEY_decrypt(buf, - encrypted_key->data, - encrypted_key->length, - priv_key); - if (ret <= 0) { - free(buf); - krb5_set_error_string(context, "Can't decrypt key: %s", - ERR_error_string(ERR_get_error(), NULL)); - return ENOMEM; - } - - key->keytype = 0; - key->keyvalue.length = ret; - key->keyvalue.data = malloc(ret); - if (key->keyvalue.data == NULL) { - free(buf); - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - memcpy(key->keyvalue.data, buf, ret); - free(buf); - return 0; -} - - -static krb5_error_code -pk_verify_chain_standard(krb5_context context, - struct krb5_pk_identity *id, - const SignerIdentifier *client, - STACK_OF(X509) *chain, - X509 **client_cert) -{ - X509_STORE *cert_store = NULL; - X509_STORE_CTX *store_ctx = NULL; - X509 *cert = NULL; - int i; - int ret; - - ret = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH; - for (i = 0; i < sk_X509_num(chain); i++) { - cert = sk_X509_value(chain, i); - if (pk_peer_compare(context, client, cert) == TRUE) { - ret = 0; - break; - } - } - if (ret) { - krb5_set_error_string(context, "PKINIT: verify chain failed " - "to find client in chain"); - return ret; - } - - cert_store = X509_STORE_new(); - if (cert_store == NULL) { - ret = ENOMEM; - krb5_set_error_string(context, "PKINIT: can't create X509 store: %s", - ERR_error_string(ERR_get_error(), NULL)); - } - - store_ctx = X509_STORE_CTX_new(); - if (store_ctx == NULL) { - ret = ENOMEM; - krb5_set_error_string(context, - "PKINIT: can't create X509 store ctx: %s", - ERR_error_string(ERR_get_error(), NULL)); - goto end; - } - - X509_STORE_CTX_init(store_ctx, cert_store, cert, chain); - X509_STORE_CTX_trusted_stack(store_ctx, id->trusted_certs); - X509_verify_cert(store_ctx); - /* the last checked certificate is in store_ctx->current_cert */ - krb5_clear_error_string(context); - switch(store_ctx->error) { - case X509_V_OK: - ret = 0; - break; - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY: - ret = KRB5_KDC_ERR_CANT_VERIFY_CERTIFICATE; - krb5_set_error_string(context, "PKINIT: failed to verify " - "certificate: %s ", - X509_verify_cert_error_string(store_ctx->error)); - break; - case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY: - case X509_V_ERR_CERT_SIGNATURE_FAILURE: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - case X509_V_ERR_CERT_HAS_EXPIRED: - ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; - krb5_set_error_string(context, "PKINIT: invalid certificate: %s ", - X509_verify_cert_error_string(store_ctx->error)); - break; - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: - case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE: - case X509_V_ERR_CERT_CHAIN_TOO_LONG: - case X509_V_ERR_PATH_LENGTH_EXCEEDED: - case X509_V_ERR_INVALID_CA: - ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; - krb5_set_error_string(context, "PKINIT: unknown CA or can't " - "verify certificate: %s", - X509_verify_cert_error_string(store_ctx->error)); - break; - default: - ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; /* XXX */ - krb5_set_error_string(context, "PKINIT: failed to verify " - "certificate: %s (%ld) ", - X509_verify_cert_error_string(store_ctx->error), - (long)store_ctx->error); - break; - } - if (ret) - goto end; - - /* - * Since X509_verify_cert() doesn't do CRL checking at all, we have to - * perform own verification against CRLs - */ - /* - * XXX add crl checking - */ - - if (client_cert && cert) - *client_cert = X509_dup(cert); - - end: - if (cert_store) - X509_STORE_free(cert_store); - if (store_ctx) - X509_STORE_CTX_free(store_ctx); - return ret; -} - -static int -cert_to_X509(krb5_context context, CertificateSet *set, - STACK_OF(X509_CRL) **certs) -{ - krb5_error_code ret; - int i; - - *certs = sk_X509_new_null(); - - if (set == NULL) - return 0; - - ret = 0; - for (i = 0; i < set->len; i++) { - unsigned char *p; - X509 *cert; - - p = set->val[i].data; - cert = d2i_X509(NULL, &p, set->val[i].length); - if (cert == NULL) { - ret = ASN1_BAD_FORMAT; - break; - } - sk_X509_insert(*certs, cert, i); - } - if (ret) { - krb5_set_error_string(context, - "PKINIT: Failed to decode certificate chain"); - sk_X509_free(*certs); - *certs = NULL; - } - return ret; + return pk_mk_padata(context, type, ctx, req_body, nonce, md); } krb5_error_code KRB5_LIB_FUNCTION @@ -1048,144 +537,67 @@ _krb5_pk_verify_sign(krb5_context context, krb5_data *content, struct krb5_pk_cert **signer) { - STACK_OF(X509) *certificates; - SignerInfo *signer_info; - const EVP_MD *evp_type; - EVP_PKEY *public_key; - krb5_error_code ret; - EVP_MD_CTX md; - X509 *cert = NULL; - SignedData sd; - size_t size; - - *signer = NULL; - krb5_data_zero(content); - contentType->length = 0; - contentType->components = NULL; - - memset(&sd, 0, sizeof(sd)); - - ret = decode_SignedData(data, length, &sd, &size); - if (ret) { - krb5_set_error_string(context, - "PKINIT: decoding failed SignedData: %d", - ret); - goto out; - } - - if (sd.encapContentInfo.eContent == NULL) { - krb5_set_error_string(context, - "PKINIT: signature missing encapContent"); - ret = KRB5KRB_AP_ERR_MSG_TYPE; - goto out; - } - - /* XXX Check CMS version */ - - if (sd.signerInfos.len < 1) { - krb5_set_error_string(context, - "PKINIT: signature information missing from " - "pkinit response"); - ret = KRB5_KDC_ERR_INVALID_SIG; - goto out; - } - - signer_info = &sd.signerInfos.val[0]; - - { - CertificateSet set; - set.val = sd.certificates->val; - set.len = sd.certificates->len; + hx509_certs signer_certs; + int ret; - ret = cert_to_X509(context, &set, &certificates); - } - if (ret) { - krb5_set_error_string(context, - "PKINIT: failed to decode Certificates"); - goto out; - } + *signer = NULL; - ret = pk_verify_chain_standard(context, id, - &signer_info->sid, - certificates, - &cert); - sk_X509_free(certificates); + ret = hx509_cms_verify_signed(id->hx509ctx, + id->verify_ctx, + data, + length, + id->certpool, + contentType, + content, + &signer_certs); if (ret) - goto out; - - if (signer_info->signature.length == 0) { - free_SignedData(&sd); - X509_free(cert); - krb5_set_error_string(context, "PKINIT: signature missing from" - "pkinit response"); - return KRB5_KDC_ERR_INVALID_SIG; - } - - public_key = X509_get_pubkey(cert); - - /* verify signature */ - if (heim_oid_cmp(&signer_info->digestAlgorithm.algorithm, - oid_id_pkcs1_sha1WithRSAEncryption()) == 0) - evp_type = EVP_sha1(); - else if (heim_oid_cmp(&signer_info->digestAlgorithm.algorithm, - oid_id_pkcs1_md5WithRSAEncryption()) == 0) - evp_type = EVP_md5(); - else if (heim_oid_cmp(&signer_info->digestAlgorithm.algorithm, - oid_id_secsig_sha_1()) == 0) - evp_type = EVP_sha1(); - else { - X509_free(cert); - krb5_set_error_string(context, "PKINIT: The requested digest " - "algorithm is not supported"); - ret = KRB5_KDC_ERR_INVALID_SIG; - goto out; - } - - EVP_VerifyInit(&md, evp_type); - EVP_VerifyUpdate(&md, - sd.encapContentInfo.eContent->data, - sd.encapContentInfo.eContent->length); - ret = EVP_VerifyFinal(&md, - signer_info->signature.data, - signer_info->signature.length, - public_key); - if (ret != 1) { - X509_free(cert); - krb5_set_error_string(context, "PKINIT: signature didn't verify: %s", - ERR_error_string(ERR_get_error(), NULL)); - ret = KRB5_KDC_ERR_INVALID_SIG; - goto out; - } - - ret = copy_oid(&sd.encapContentInfo.eContentType, contentType); - if (ret) { - krb5_clear_error_string(context); - goto out; - } + return ret; - content->data = malloc(sd.encapContentInfo.eContent->length); - if (content->data == NULL) { + *signer = calloc(1, sizeof(**signer)); + if (*signer == NULL) { krb5_clear_error_string(context); ret = ENOMEM; goto out; } - content->length = sd.encapContentInfo.eContent->length; - memcpy(content->data,sd.encapContentInfo.eContent->data,content->length); + + /* XXX */ + { + hx509_cursor cursor; - *signer = malloc(sizeof(**signer)); - if (*signer == NULL) { - krb5_clear_error_string(context); - ret = ENOMEM; - goto out; + ret = hx509_certs_start_seq(id->hx509ctx, + signer_certs, + &cursor); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + ret = hx509_certs_next_cert(id->hx509ctx, + signer_certs, + cursor, + &(*signer)->cert); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + ret = hx509_certs_end_seq(id->hx509ctx, + signer_certs, + cursor); + if (ret) { + krb5_clear_error_string(context); + goto out; + } } - (*signer)->cert = cert; - out: - free_SignedData(&sd); +out: + hx509_certs_free(&signer_certs); if (ret) { - free_oid(contentType); - krb5_data_free(content); + if (*signer) { + hx509_cert_free((*signer)->cert); + free(*signer); + *signer = NULL; + } } + return ret; } @@ -1297,10 +709,60 @@ get_reply_key(krb5_context context, static krb5_error_code -pk_verify_host(krb5_context context, struct krb5_pk_cert *host) +pk_verify_host(krb5_context context, + struct krb5_pk_init_ctx_data *ctx, + struct krb5_pk_cert *host) { - /* XXX */ - return 0; + krb5_error_code ret = 0; + + if (ctx->require_eku) { + ret = hx509_cert_check_eku(ctx->id->hx509ctx, host->cert, + oid_id_pkkdcekuoid(), 0); + if (ret) { + krb5_clear_error_string(context); + return ret; + } + } + if (ctx->require_krbtgt_otherName) { + hx509_octet_string_list list; + krb5_error_code ret; + int i; + + ret = hx509_cert_find_subjectAltName_otherName(host->cert, + oid_id_pkinit_san(), + &list); + if (ret) { + krb5_clear_error_string(context); + return ret; + } + + for (i = 0; i < list.len; i++) { + KRB5PrincipalName r; + ret = decode_KRB5PrincipalName(list.val[i].data, + list.val[i].length, + &r, + NULL); + if (ret) { + krb5_clear_error_string(context); + break; + } + +#if 0 + if (r.principalName.name.len != 2) { + krb5_clear_error_string(context); + ret = EINVAL; + } +#endif + /* XXX verify realm */ + + free_KRB5PrincipalName(&r); + if (ret) + break; + } + hx509_free_octet_string_list(&list); + } + + return ret; } static krb5_error_code @@ -1316,33 +778,12 @@ pk_rd_pa_reply_enckey(krb5_context context, krb5_keyblock **key) { krb5_error_code ret; - EnvelopedData ed; - krb5_keyblock tmp_key; - krb5_crypto crypto; - krb5_data plain; - KeyTransRecipientInfo *ri; - int length; + struct krb5_pk_cert *host = NULL; size_t size; - X509 *user_cert; + int length; void *p; - krb5_boolean bret; krb5_data content; heim_oid contentType = { 0, NULL }; - struct krb5_pk_cert *host = NULL; - heim_octet_string encryptedContent; - heim_octet_string *any; - krb5_data ivec; - krb5_data params; - - - memset(&tmp_key, 0, sizeof(tmp_key)); - memset(&ed, 0, sizeof(ed)); - krb5_data_zero(&plain); - krb5_data_zero(&content); - krb5_data_zero(&encryptedContent); - krb5_data_zero(&ivec); - - user_cert = sk_X509_value(ctx->id->cert, 0); if (heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) { krb5_set_error_string(context, "PKINIT: Invalid content type"); @@ -1354,106 +795,17 @@ pk_rd_pa_reply_enckey(krb5_context context, return EINVAL; } - ret = decode_EnvelopedData(rep->content->data, + ret = hx509_cms_unenvelope(ctx->id->hx509ctx, + ctx->id->certs, + rep->content->data, rep->content->length, - &ed, - &size); - if (ret) { - free_EnvelopedData(&ed); - return ret; - } - - if (ed.recipientInfos.len != 1) { - free_EnvelopedData(&ed); - krb5_set_error_string(context, "pkinit: Number of recipient infos " - "not one (%d)", - ed.recipientInfos.len); - return EINVAL; /* XXX */ - } - - ri = &ed.recipientInfos.val[0]; - - /* XXX make SignerIdentifier and RecipientIdentifier the same */ - bret = pk_peer_compare(context, (SignerIdentifier *)&ri->rid, user_cert); - if (bret == FALSE) { - ret = KRB5KRB_AP_ERR_BADMATCH; /* XXX */ - goto out; - } - - if (heim_oid_cmp(oid_id_pkcs1_rsaEncryption(), - &ri->keyEncryptionAlgorithm.algorithm)) { - krb5_set_error_string(context, "PKINIT: invalid content type"); - return EINVAL; - } - - ret = pk_decrypt_key(context, &ri->encryptedKey, - ctx->id->private_key, &tmp_key); - if (ret) - goto out; - - - /* - * Try to verify content type. We can't do this for W2K case - * because W2K/W2K3 sends id-pkcs7-data, but Windows Vista sends - * id-pkcs7-signedData to all versions, even W2K clients. - */ - - if (type != COMPAT_WIN2K) { - if (heim_oid_cmp(&ed.encryptedContentInfo.contentType, oid_id_pkcs7_signedData())) { - ret = KRB5KRB_AP_ERR_MSG_TYPE; - goto out; - } - } - - if (ed.encryptedContentInfo.encryptedContent == NULL) { - krb5_set_error_string(context, "PKINIT: OPTIONAL encryptedContent " - "field not filled in in KDC reply"); - ret = KRB5_BADMSGTYPE; - goto out; - } - - any = ed.encryptedContentInfo.encryptedContent; - ret = der_get_octet_string(any->data, any->length, - &encryptedContent, NULL); - if (ret) { - krb5_set_error_string(context, - "PKINIT: encryptedContent content invalid"); - goto out; - } - - if (ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters == NULL){ - krb5_set_error_string(context, - "PKINIT: encryptedContent parameter missing"); - ret = KRB5_BADMSGTYPE; - goto out; - } - - params.data = ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters->data; - params.length = ed.encryptedContentInfo.contentEncryptionAlgorithm.parameters->length; - - ret = _krb5_oid_to_enctype(context, - &ed.encryptedContentInfo.contentEncryptionAlgorithm.algorithm, - &tmp_key.keytype); - if (ret) - goto out; - - ret = krb5_crypto_init(context, &tmp_key, 0, &crypto); - if (ret) - goto out; - - ret = krb5_crypto_get_params(context, crypto, ¶ms, &ivec); + &contentType, + &content); if (ret) - goto out; - - ret = krb5_decrypt_ivec(context, crypto, - 0, - encryptedContent.data, - encryptedContent.length, - &plain, - ivec.data); + return ret; - p = plain.data; - length = plain.length; + p = content.data; + length = content.length; /* win2k uses ContentInfo */ if (type == COMPAT_WIN2K) { @@ -1472,6 +824,13 @@ pk_rd_pa_reply_enckey(krb5_context context, krb5_set_error_string(context, "PKINIT: Invalid content type"); goto out; } + if (ci.content == NULL) { + ret = EINVAL; /* XXX */ + krb5_set_error_string(context, "PKINIT: Invalid content type"); + goto out; + } + krb5_data_free(&content); + content = *ci.content; p = ci.content->data; length = ci.content->length; } @@ -1487,7 +846,7 @@ pk_rd_pa_reply_enckey(krb5_context context, goto out; /* make sure that it is the kdc's certificate */ - ret = pk_verify_host(context, host); + ret = pk_verify_host(context, ctx, host); if (ret) { krb5_set_error_string(context, "PKINIT: failed verify host: %d", ret); goto out; @@ -1528,11 +887,7 @@ pk_rd_pa_reply_enckey(krb5_context context, if (host) _krb5_pk_cert_free(host); free_oid(&contentType); - free_octet_string(&encryptedContent); krb5_data_free(&content); - krb5_free_keyblock_contents(context, &tmp_key); - krb5_data_free(&plain); - krb5_data_free(&ivec); return ret; } @@ -1550,7 +905,6 @@ pk_rd_pa_reply_dh(krb5_context context, krb5_keyblock **key) { unsigned char *p, *dh_gen_key = NULL; - ASN1_INTEGER *dh_pub_key = NULL; struct krb5_pk_cert *host = NULL; BIGNUM *kdc_dh_pubkey = NULL; KDCDHKeyInfo kdc_dh_info; @@ -1584,7 +938,7 @@ pk_rd_pa_reply_dh(krb5_context context, goto out; /* make sure that it is the kdc's certificate */ - ret = pk_verify_host(context, host); + ret = pk_verify_host(context, ctx, host); if (ret) goto out; @@ -1623,7 +977,7 @@ pk_rd_pa_reply_dh(krb5_context context, } } else { if (k_n) { - krb5_set_error_string(context, "pkinit; got server nonce " + krb5_set_error_string(context, "pkinit: got server nonce " "without key expiration"); ret = KRB5KRB_ERR_GENERIC; goto out; @@ -1634,22 +988,24 @@ pk_rd_pa_reply_dh(krb5_context context, p = kdc_dh_info.subjectPublicKey.data; size = (kdc_dh_info.subjectPublicKey.length + 7) / 8; - dh_pub_key = d2i_ASN1_INTEGER(NULL, &p, size); - if (dh_pub_key == NULL) { - krb5_set_error_string(context, - "PKINIT: Can't parse KDC's DH public key"); - ret = KRB5KRB_ERR_GENERIC; - goto out; - } - kdc_dh_pubkey = ASN1_INTEGER_to_BN(dh_pub_key, NULL); - if (kdc_dh_pubkey == NULL) { - krb5_set_error_string(context, - "PKINIT: Can't convert KDC's DH public key"); - ret = KRB5KRB_ERR_GENERIC; - goto out; - } + { + DHPublicKey k; + ret = decode_DHPublicKey(p, size, &k, NULL); + if (ret) { + krb5_set_error_string(context, "pkinit: can't decode " + "without key expiration"); + goto out; + } + kdc_dh_pubkey = integer_to_BN(context, "DHPublicKey", &k); + free_DHPublicKey(&k); + if (kdc_dh_pubkey == NULL) { + ret = KRB5KRB_ERR_GENERIC; + goto out; + } + } + dh_gen_keylen = DH_size(ctx->dh); size = BN_num_bytes(ctx->dh->p); if (size < dh_gen_keylen) @@ -1667,8 +1023,7 @@ pk_rd_pa_reply_dh(krb5_context context, kdc_dh_pubkey, ctx->dh); if (dh_gen_keylen == -1) { krb5_set_error_string(context, - "PKINIT: Can't compute Diffie-Hellman key (%s)", - ERR_error_string(ERR_get_error(), NULL)); + "PKINIT: Can't compute Diffie-Hellman key"); ret = KRB5KRB_ERR_GENERIC; goto out; } @@ -1700,8 +1055,6 @@ pk_rd_pa_reply_dh(krb5_context context, memset(dh_gen_key, 0, DH_size(ctx->dh)); free(dh_gen_key); } - if (dh_pub_key) - ASN1_INTEGER_free(dh_pub_key); if (host) _krb5_pk_cert_free(host); if (content.data) @@ -1726,7 +1079,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, ContentInfo ci; size_t size; - /* Check for PK-INIT -27 */ + /* Check for IETF PK-INIT first */ if (pa->padata_type == KRB5_PADATA_PK_AS_REP) { PA_PK_AS_REP rep; @@ -1747,7 +1100,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, &size); if (ret) { krb5_set_error_string(context, - "PKINIT: -25 decoding failed DH " + "PKINIT: decoding failed DH " "ContentInfo: %d", ret); free_PA_PK_AS_REP(&rep); @@ -1821,7 +1174,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, return ret; } ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, ctx, - etype, hi, nonce, NULL, pa, key); + etype, hi, nonce, req_buffer, pa, key); free_ContentInfo(&ci); break; default: @@ -1837,598 +1190,158 @@ _krb5_pk_rd_pa_reply(krb5_context context, return ret; } -static int -ssl_pass_cb(char *buf, int size, int rwflag, void *u) +struct prompter { + krb5_context context; + krb5_prompter_fct prompter; + void *prompter_data; +}; + +static int +hx_pass_prompter(void *data, const hx509_prompt *prompter) { krb5_error_code ret; krb5_prompt prompt; krb5_data password_data; - krb5_prompter_fct prompter = u; + struct prompter *p = data; - password_data.data = buf; - password_data.length = size; + password_data.data = prompter->reply->data; + password_data.length = prompter->reply->length; prompt.prompt = "Enter your private key passphrase: "; prompt.hidden = 1; prompt.reply = &password_data; - prompt.type = KRB5_PROMPT_TYPE_PASSWORD; + if (prompter->hidden) + prompt.type = KRB5_PROMPT_TYPE_PASSWORD; + else + prompt.type = KRB5_PROMPT_TYPE_PREAUTH; /* XXX */ - ret = (*prompter)(NULL, NULL, NULL, NULL, 1, &prompt); + ret = (*p->prompter)(p->context, p->prompter_data, NULL, NULL, 1, &prompt); if (ret) { - memset (buf, 0, size); + memset (prompter->reply->data, 0, prompter->reply->length); return 0; } - return strlen(buf); -} - -static krb5_error_code -load_openssl_cert(krb5_context context, - const char *file, - STACK_OF(X509) **c) -{ - STACK_OF(X509) *certificate; - krb5_error_code ret; - FILE *f; - - f = fopen(file, "r"); - if (f == NULL) { - ret = errno; - krb5_set_error_string(context, "PKINIT: open failed %s: %s", - file, strerror(ret)); - return ret; - } - - certificate = sk_X509_new_null(); - while (1) { - /* see http://www.openssl.org/docs/crypto/pem.html section BUGS */ - X509 *cert; - cert = PEM_read_X509(f, NULL, NULL, NULL); - if (cert == NULL) { - if (ERR_GET_REASON(ERR_peek_error()) == PEM_R_NO_START_LINE) { - /* End of file reached. no error */ - ERR_clear_error(); - break; - } - krb5_set_error_string(context, "PKINIT: Can't read certificate"); - fclose(f); - return HEIM_PKINIT_CERTIFICATE_INVALID; - } - sk_X509_insert(certificate, cert, sk_X509_num(certificate)); - } - fclose(f); - if (sk_X509_num(certificate) == 0) { - krb5_set_error_string(context, "PKINIT: No certificate found"); - return HEIM_PKINIT_NO_CERTIFICATE; - } - *c = certificate; - return 0; -} - -static krb5_error_code -load_openssl_file(krb5_context context, - char *password, - krb5_prompter_fct prompter, - void *prompter_data, - const char *user_id, - struct krb5_pk_identity *id) -{ - krb5_error_code ret; - STACK_OF(X509) *certificate = NULL; - char *cert_file = NULL, *key_file; - EVP_PKEY *private_key = NULL; - FILE *f; - - cert_file = strdup(user_id); - if (cert_file == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - key_file = strchr(cert_file, ','); - if (key_file == NULL) { - krb5_set_error_string(context, "PKINIT: key file missing"); - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - goto out; - } - *key_file++ = '\0'; - - ret = load_openssl_cert(context, cert_file, &certificate); - if (ret) - goto out; - - /* load private key */ - f = fopen(key_file, "r"); - if (f == NULL) { - ret = errno; - krb5_set_error_string(context, "PKINIT: open %s: %s", - key_file, strerror(ret)); - goto out; - } - if (password == NULL || password[0] == '\0') { - if (prompter == NULL) - prompter = krb5_prompter_posix; - private_key = PEM_read_PrivateKey(f, NULL, ssl_pass_cb, prompter); - } else - private_key = PEM_read_PrivateKey(f, NULL, NULL, password); - fclose(f); - if (private_key == NULL) { - krb5_set_error_string(context, "PKINIT: Can't read private key"); - ret = HEIM_PKINIT_PRIVATE_KEY_INVALID; - goto out; - } - ret = X509_check_private_key(sk_X509_value(certificate, 0), private_key); - if (ret != 1) { - ret = HEIM_PKINIT_PRIVATE_KEY_INVALID; - krb5_set_error_string(context, - "PKINIT: The private key doesn't match " - "the public key certificate"); - goto out; - } - - id->private_key = private_key; - id->cert = certificate; - - return 0; - out: - if (cert_file) - free(cert_file); - if (certificate) - sk_X509_pop_free(certificate, X509_free); - if (private_key) - EVP_PKEY_free(private_key); - - return ret; -} - -static int -add_pair(krb5_context context, char *str, char ***cmds, int *num) -{ - char **c; - char *p; - int i; - - p = strchr(str, ':'); - if (p) { - *p = '\0'; - p++; - } - - /* filter out dup keys */ - for (i = 0; i < *num; i++) - if (strcmp((*cmds)[i * 2], str) == 0) - return 0; - - c = realloc(*cmds, sizeof(*c) * ((*num + 1) * 2)); - if (c == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - - c[(*num * 2)] = str; - c[(*num * 2) + 1] = p; - *num += 1; - *cmds = c; - return 0; -} - -static krb5_error_code -eval_pairs(krb5_context context, ENGINE *e, const char *name, - const char *type, char **cmds, int num) -{ - int i; - - for (i = 0; i < num; i++) { - char *a1 = cmds[i * 2], *a2 = cmds[(i * 2) + 1]; - if(!ENGINE_ctrl_cmd_string(e, a1, a2, 0)) { - krb5_set_error_string(context, - "PKINIT: Failed %scommand (%s - %s:%s): %s", - type, name, a1, a2 ? a2 : "(NULL)", - ERR_error_string(ERR_get_error(), NULL)); - return HEIM_PKINIT_NO_PRIVATE_KEY; - } - } - return 0; -} - -struct engine_context { - char **pre_cmds; - char **post_cmds; - int num_pre; - int num_post; - char *engine_name; - char *cert_file; - char *key_id; -}; - -static krb5_error_code -parse_openssl_engine_conf(krb5_context context, - struct engine_context *ctx, - char *line) -{ - krb5_error_code ret; - char *last, *p, *q; - - for (p = strtok_r(line, ",", &last); - p != NULL; - p = strtok_r(NULL, ",", &last)) { - - q = strchr(p, '='); - if (q == NULL) { - krb5_set_error_string(context, - "PKINIT: openssl engine configuration " - "key %s missing = and thus value", p); - return HEIM_PKINIT_NO_PRIVATE_KEY; - } - *q = '\0'; - q++; - if (strcasecmp("PRE", p) == 0) { - ret = add_pair(context, q, &ctx->pre_cmds, &ctx->num_pre); - if (ret) - return ret; - } else if (strcasecmp("POST", p) == 0) { - ret = add_pair(context, q, &ctx->post_cmds, &ctx->num_post); - if (ret) - return ret; - } else if (strcasecmp("KEY", p) == 0) { - ctx->key_id = q; - } else if (strcasecmp("CERT", p) == 0) { - ctx->cert_file = q; - } else if (strcasecmp("ENGINE", p) == 0) { - ctx->engine_name = q; - } else { - krb5_set_error_string(context, - "PKINIT: openssl engine configuration " - "key %s is unknown", p); - return HEIM_PKINIT_NO_PRIVATE_KEY; - } - } - return 0; -} - - -static krb5_error_code -load_openssl_engine(krb5_context context, - char *password, - krb5_prompter_fct prompter, - void *prompter_data, - const char *string, - struct krb5_pk_identity *id) -{ - struct engine_context ctx; - krb5_error_code ret; - const char *f; - char *file_conf = NULL, *user_conf = NULL; - ENGINE *e = NULL; - - memset(&ctx, 0, sizeof(ctx)); - - ENGINE_load_builtin_engines(); - - user_conf = strdup(string); - if (user_conf == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - - ret = parse_openssl_engine_conf(context, &ctx, user_conf); - if (ret) - goto out; - - f = krb5_config_get_string_default(context, NULL, NULL, - "libdefaults", - "pkinit-openssl-engine", - NULL); - if (f) { - file_conf = strdup(f); - if (file_conf) { - ret = parse_openssl_engine_conf(context, &ctx, file_conf); - if (ret) - goto out; - } - } - - if (ctx.cert_file == NULL) { - krb5_set_error_string(context, - "PKINIT: openssl engine missing certificate"); - ret = HEIM_PKINIT_NO_CERTIFICATE; - goto out; - } - if (ctx.key_id == NULL) { - krb5_set_error_string(context, - "PKINIT: openssl engine missing key id"); - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - goto out; - } - if (ctx.engine_name == NULL) { - krb5_set_error_string(context, - "PKINIT: openssl engine missing engine name"); - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - goto out; - } - - e = ENGINE_by_id(ctx.engine_name); - if (e == NULL) { - krb5_set_error_string(context, - "PKINIT: failed getting openssl engine %s: %s", - ctx.engine_name, - ERR_error_string(ERR_get_error(), NULL)); - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - goto out; - } - - ret = eval_pairs(context, e, ctx.engine_name, "pre", - ctx.pre_cmds, ctx.num_pre); - if (ret) - goto out; - - if(!ENGINE_init(e)) { - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - krb5_set_error_string(context, - "PKINIT: openssl engine init %s failed: %s", - ctx.engine_name, - ERR_error_string(ERR_get_error(), NULL)); - ENGINE_free(e); - goto out; - } - - ret = eval_pairs(context, e, ctx.engine_name, "post", - ctx.post_cmds, ctx.num_post); - if (ret) - goto out; - - /* - * If the engine supports a LOAD_CERT_CTRL function, lets try - * it. OpenSC support this function. Eventially this should be - * a ENGINE_load_cert function if it failes, treat it like a - * non fatal error. - */ - { - struct { - const char * cert_id; - X509 * cert; - } parms; - - parms.cert_id = ctx.cert_file; - parms.cert = NULL; - ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1); - if (parms.cert) { - id->cert = sk_X509_new_null(); - sk_X509_insert(id->cert, parms.cert, 0); - } - } - - if (id->cert == NULL) { - ret = load_openssl_cert(context, ctx.cert_file, &id->cert); - if (ret) - goto out; - } - - { - UI_METHOD * krb5_ui_method = NULL; - struct krb5_ui_data ui_data; - - krb5_ui_method = UI_create_method("Krb5 ui method"); - if (krb5_ui_method == NULL) { - krb5_set_error_string(context, - "PKINIT: failed to setup prompter " - "function: %s", - ERR_error_string(ERR_get_error(), NULL)); - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - goto out; - } - UI_method_set_reader(krb5_ui_method, krb5_ui_method_read_string); - - ui_data.context = context; - ui_data.prompter = prompter; - if (prompter == NULL) - ui_data.prompter = krb5_prompter_posix; - ui_data.prompter_data = prompter_data; - - id->private_key = ENGINE_load_private_key(e, - ctx.key_id, - krb5_ui_method, - (void*) &ui_data); - UI_destroy_method(krb5_ui_method); - } - - if (id->private_key == NULL) { - krb5_set_error_string(context, - "PKINIT: failed to load private key: %s", - ERR_error_string(ERR_get_error(), NULL)); - ret = HEIM_PKINIT_NO_PRIVATE_KEY; - goto out; - } - - ret = X509_check_private_key(sk_X509_value(id->cert, 0), id->private_key); - if (ret != 1) { - ret = HEIM_PKINIT_PRIVATE_KEY_INVALID; - krb5_set_error_string(context, - "PKINIT: The private key doesn't match " - "the public key certificate"); - goto out; - } - - if (user_conf) - free(user_conf); - if (file_conf) - free(file_conf); - - id->engine = e; - - return 0; - - out: - if (user_conf) - free(user_conf); - if (file_conf) - free(file_conf); - if (e) { - ENGINE_finish(e); /* make sure all shared libs are unloaded */ - ENGINE_free(e); - } - - return ret; + return strlen(prompter->reply->data); } krb5_error_code KRB5_LIB_FUNCTION -_krb5_pk_load_openssl_id(krb5_context context, - struct krb5_pk_identity **ret_id, - const char *user_id, - const char *x509_anchors, - krb5_prompter_fct prompter, - void *prompter_data, - char *password) +_krb5_pk_load_id(krb5_context context, + struct krb5_pk_identity **ret_id, + const char *user_id, + const char *anchor_id, + char * const *chain, + char * const *revoke, + krb5_prompter_fct prompter, + void *prompter_data, + char *password) { - STACK_OF(X509) *trusted_certs = NULL; struct krb5_pk_identity *id = NULL; - krb5_error_code ret; - struct dirent *file; - char *dirname = NULL; - DIR *dir; - FILE *f; - krb5_error_code (*load_pair)(krb5_context, - char *, - krb5_prompter_fct, - void *, - const char *, - struct krb5_pk_identity *) = NULL; - + hx509_lock lock = NULL; + struct prompter p; + int ret; *ret_id = NULL; - if (x509_anchors == NULL) { - krb5_set_error_string(context, "PKINIT: No root ca directory given"); + if (anchor_id == NULL) { + krb5_set_error_string(context, "PKINIT: No anchor given"); return HEIM_PKINIT_NO_VALID_CA; } if (user_id == NULL) { krb5_set_error_string(context, - "PKINIT: No user X509 source given given"); + "PKINIT: No user certificate given"); return HEIM_PKINIT_NO_PRIVATE_KEY; } - /* - * - */ - - if (strncasecmp(user_id, "FILE:", 5) == 0) { - load_pair = load_openssl_file; - user_id += 5; - } else if (strncasecmp(user_id, "ENGINE:", 7) == 0) { - load_pair = load_openssl_engine; - user_id += 7; - } else { - krb5_set_error_string(context, "PKINIT: user identity not FILE"); - return HEIM_PKINIT_NO_CERTIFICATE; - } - if (strncasecmp(x509_anchors, "OPENSSL-ANCHOR-DIR:", 19) != 0) { - krb5_set_error_string(context, "PKINIT: anchor OPENSSL-ANCHOR-DIR"); - return HEIM_PKINIT_NO_VALID_CA; - } - x509_anchors += 19; + /* load cert */ - id = malloc(sizeof(*id)); + id = calloc(1, sizeof(*id)); if (id == NULL) { krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; goto out; } - memset(id, 0, sizeof(*id)); - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - - - ret = (*load_pair)(context, password, prompter, prompter_data, user_id, id); + ret = hx509_context_init(&id->hx509ctx); if (ret) goto out; - /* load anchors */ + ret = hx509_lock_init(id->hx509ctx, &lock); + if (password) + hx509_lock_add_password(lock, password); - dirname = strdup(x509_anchors); - if (dirname == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - ret = ENOMEM; - goto out; - } + if (prompter) { + p.context = context; + p.prompter = prompter; + p.prompter_data = prompter_data; - { - size_t len; - len = strlen(dirname); - if (dirname[len - 1] == '/') - dirname[len - 1] = '\0'; + ret = hx509_lock_set_prompter(lock, hx_pass_prompter, &p); + if (ret) + goto out; } - /* read ca certificates */ - dir = opendir(dirname); - if (dir == NULL) { - ret = errno; - krb5_set_error_string(context, "PKINIT: open directory %s: %s", - dirname, strerror(ret)); + ret = hx509_certs_init(id->hx509ctx, user_id, 0, NULL, &id->certs); + if (ret) goto out; - } - trusted_certs = sk_X509_new_null(); - while ((file = readdir(dir)) != NULL) { - X509 *cert; - char *filename; + ret = hx509_certs_init(id->hx509ctx, anchor_id, 0, NULL, &id->anchors); + if (ret) + goto out; - /* - * Assume the certificate filenames constist of hashed subject - * name followed by suffix ".0" - */ + ret = hx509_certs_init(id->hx509ctx, "MEMORY:pkinit-cert-chain", + 0, NULL, &id->certpool); + if (ret) + goto out; - if (strlen(file->d_name) == 10 && strcmp(&file->d_name[8],".0") == 0) { - asprintf(&filename, "%s/%s", dirname, file->d_name); - if (filename == NULL) { - ret = ENOMEM; - krb5_set_error_string(context, "malloc: out or memory"); - goto out; - } - f = fopen(filename, "r"); - if (f == NULL) { - ret = errno; - krb5_set_error_string(context, "PKINIT: open %s: %s", - filename, strerror(ret)); - free(filename); - closedir(dir); - goto out; - } - cert = PEM_read_X509(f, NULL, NULL, NULL); - fclose(f); - if (cert != NULL) { - /* order of the certs is not important */ - sk_X509_push(trusted_certs, cert); - } - free(filename); + while (chain && *chain) { + ret = hx509_certs_append(id->hx509ctx, id->certpool, NULL, *chain); + if (ret) { + krb5_set_error_string(context, + "pkinit failed to load chain %s", + *chain); + goto out; } + chain++; } - closedir(dir); - if (sk_X509_num(trusted_certs) == 0) { - krb5_set_error_string(context, - "PKINIT: No CA certificate(s) found in %s", - dirname); - ret = HEIM_PKINIT_NO_VALID_CA; - goto out; - } + if (revoke) { + ret = hx509_revoke_init(id->hx509ctx, &id->revoke); + if (ret) { + krb5_set_error_string(context, "revoke failed to init"); + goto out; + } - id->trusted_certs = trusted_certs; + while (*revoke) { + ret = hx509_revoke_add_crl(id->hx509ctx, id->revoke, *revoke); + if (ret) { + krb5_set_error_string(context, + "pkinit failed to load revoke %s", + *revoke); + goto out; + } + revoke++; + } + } else + hx509_context_set_missing_revoke(id->hx509ctx, 1); - *ret_id = id; + ret = hx509_verify_init_ctx(id->hx509ctx, &id->verify_ctx); + if (ret) + goto out; - return 0; + hx509_verify_attach_anchors(id->verify_ctx, id->anchors); + hx509_verify_attach_revoke(id->verify_ctx, id->revoke); - out: - if (dirname) - free(dirname); - if (trusted_certs) - sk_X509_pop_free(trusted_certs, X509_free); - if (id) { - if (id->cert) - sk_X509_pop_free(id->cert, X509_free); - if (id->private_key) - EVP_PKEY_free(id->private_key); +out: + if (ret) { + hx509_verify_destroy_ctx(id->verify_ctx); + hx509_certs_free(&id->certs); + hx509_certs_free(&id->anchors); + hx509_certs_free(&id->certpool); + hx509_revoke_free(&id->revoke); + hx509_context_free(&id->hx509ctx); free(id); - } + } else + *ret_id = id; + + hx509_lock_free(lock); return ret; } @@ -2704,17 +1617,12 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) DH_free(ctx->dh); ctx->dh = NULL; if (ctx->id) { - if (ctx->id->cert) - sk_X509_pop_free(ctx->id->cert, X509_free); - if (ctx->id->trusted_certs) - sk_X509_pop_free(ctx->id->trusted_certs, X509_free); - if (ctx->id->private_key) - EVP_PKEY_free(ctx->id->private_key); - if (ctx->id->engine) { - ENGINE_finish(ctx->id->engine); /* unload shared libs etc */ - ENGINE_free(ctx->id->engine); - ctx->id->engine = NULL; - } + hx509_verify_destroy_ctx(ctx->id->verify_ctx); + hx509_certs_free(&ctx->id->certs); + hx509_certs_free(&ctx->id->anchors); + hx509_certs_free(&ctx->id->certpool); + hx509_context_free(&ctx->id->hx509ctx); + if (ctx->clientDHNonce) { krb5_free_data(NULL, ctx->clientDHNonce); ctx->clientDHNonce = NULL; @@ -2734,6 +1642,8 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, krb5_principal principal, const char *user_id, const char *x509_anchors, + char * const * chain, + char * const * revoke, int flags, krb5_prompter_fct prompter, void *prompter_data, @@ -2757,14 +1667,18 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, opt->opt_private->pk_init_ctx->id = NULL; opt->opt_private->pk_init_ctx->clientDHNonce = NULL; opt->opt_private->pk_init_ctx->require_binding = 0; - - ret = _krb5_pk_load_openssl_id(context, - &opt->opt_private->pk_init_ctx->id, - user_id, - x509_anchors, - prompter, - prompter_data, - password); + opt->opt_private->pk_init_ctx->require_eku = 1; + opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1; + + ret = _krb5_pk_load_id(context, + &opt->opt_private->pk_init_ctx->id, + user_id, + x509_anchors, + chain, + revoke, + prompter, + prompter_data, + password); if (ret) { free(opt->opt_private->pk_init_ctx); opt->opt_private->pk_init_ctx = NULL; diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index 6cc49945cc..34086b1fbe 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -41,7 +41,7 @@ #include #include "resolve.h" -RCSID("$Id: principal.c,v 1.92 2005/12/11 17:48:13 lha Exp $"); +RCSID("$Id: principal.c,v 1.94 2006/04/10 10:10:01 lha Exp $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -105,7 +105,7 @@ parse_name(krb5_context context, { krb5_error_code ret; heim_general_string *comp; - heim_general_string realm; + heim_general_string realm = NULL; int ncomp; const char *p; @@ -246,6 +246,7 @@ exit: free(comp[--n]); } free(comp); + free(realm); free(s); return ret; } @@ -825,16 +826,21 @@ krb5_425_conv_principal_ext2(krb5_context context, struct dns_reply *r; r = dns_lookup(instance, "aaaa"); - if (r && r->head && r->head->type == T_AAAA) { - inst = strdup(r->head->domain); + if (r) { + if (r->head && r->head->type == T_AAAA) { + inst = strdup(r->head->domain); + dns_free_data(r); + passed = TRUE; + } dns_free_data(r); - passed = TRUE; } else { r = dns_lookup(instance, "a"); - if(r && r->head && r->head->type == T_A) { - inst = strdup(r->head->domain); + if (r) { + if(r->head && r->head->type == T_A) { + inst = strdup(r->head->domain); + passed = TRUE; + } dns_free_data(r); - passed = TRUE; } } #else diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c index d62adadf26..520b3a1418 100644 --- a/source4/heimdal/lib/krb5/rd_cred.c +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_cred.c,v 1.26 2005/11/02 08:36:42 lha Exp $"); +RCSID("$Id: rd_cred.c,v 1.28 2006/04/02 02:27:33 lha Exp $"); static krb5_error_code compare_addrs(krb5_context context, @@ -257,8 +257,10 @@ krb5_rd_cred(krb5_context context, ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, &cred.tickets.val[i], &len, ret); - if (ret) + if (ret) { + free(creds); goto out; + } if(creds->ticket.length != len) krb5_abortx(context, "internal error in ASN.1 encoder"); copy_EncryptionKey (&kci->key, &creds->session); @@ -302,6 +304,7 @@ krb5_rd_cred(krb5_context context, for(i = 0; (*ret_creds)[i]; i++) krb5_free_creds(context, (*ret_creds)[i]); free(*ret_creds); + *ret_creds = NULL; } return ret; } diff --git a/source4/heimdal/lib/krb5/rd_priv.c b/source4/heimdal/lib/krb5/rd_priv.c index bf82ad556e..c52ac175fd 100644 --- a/source4/heimdal/lib/krb5/rd_priv.c +++ b/source4/heimdal/lib/krb5/rd_priv.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_priv.c,v 1.32 2006/03/18 22:15:57 lha Exp $"); +RCSID("$Id: rd_priv.c,v 1.33 2006/04/12 16:18:10 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_priv(krb5_context context, @@ -50,8 +50,8 @@ krb5_rd_priv(krb5_context context, krb5_keyblock *key; krb5_crypto crypto; - if (outdata) - krb5_data_zero(outdata); + if (outbuf) + krb5_data_zero(outbuf); if ((auth_context->flags & (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && @@ -161,7 +161,7 @@ krb5_rd_priv(krb5_context context, (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) { /* if these fields are not present in the priv-part, silently return zero */ - krb5_data_zero(outdata); + memset(outdata, 0, sizeof(*outdata)); if(part.timestamp) outdata->timestamp = *part.timestamp; if(part.usec) diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 313c14f6e6..0d4635b964 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_req.c,v 1.61 2005/11/29 18:22:51 lha Exp $"); +RCSID("$Id: rd_req.c,v 1.63 2006/04/10 10:14:44 lha Exp $"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, @@ -279,8 +279,10 @@ krb5_verify_authenticator_checksum(krb5_context context, &authenticator); if(ret) return ret; - if(authenticator->cksum == NULL) + if(authenticator->cksum == NULL) { + krb5_free_authenticator(context, &authenticator); return -17; + } ret = krb5_auth_con_getkey(context, ac, &key); if(ret) { krb5_free_authenticator(context, &authenticator); @@ -340,6 +342,9 @@ krb5_verify_ap_req2(krb5_context context, krb5_error_code ret; EtypeList etypes; + if (ticket) + *ticket = NULL; + if (auth_context && *auth_context) { ac = *auth_context; } else { @@ -348,13 +353,12 @@ krb5_verify_ap_req2(krb5_context context, return ret; } - t = malloc(sizeof(*t)); + t = calloc(1, sizeof(*t)); if (t == NULL) { ret = ENOMEM; krb5_clear_error_string (context); goto out; } - memset(t, 0, sizeof(*t)); if (ap_req->ap_options.use_session_key && ac->keyblock){ ret = krb5_decrypt_ticket(context, &ap_req->ticket, @@ -372,14 +376,17 @@ krb5_verify_ap_req2(krb5_context context, if(ret) goto out; - _krb5_principalname2krb5_principal(&t->server, ap_req->ticket.sname, - ap_req->ticket.realm); - _krb5_principalname2krb5_principal(&t->client, t->ticket.cname, - t->ticket.crealm); + ret = _krb5_principalname2krb5_principal(&t->server, ap_req->ticket.sname, + ap_req->ticket.realm); + if (ret) goto out; + ret = _krb5_principalname2krb5_principal(&t->client, t->ticket.cname, + t->ticket.crealm); + if (ret) goto out; /* save key */ - krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock); + ret = krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock); + if (ret) goto out; ret = decrypt_authenticator (context, &t->ticket.key, diff --git a/source4/heimdal/lib/krb5/replay.c b/source4/heimdal/lib/krb5/replay.c index ec99f86c7c..b89f150159 100644 --- a/source4/heimdal/lib/krb5/replay.c +++ b/source4/heimdal/lib/krb5/replay.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: replay.c,v 1.10 2004/05/25 21:41:15 lha Exp $"); +RCSID("$Id: replay.c,v 1.12 2006/04/10 17:13:49 lha Exp $"); struct krb5_rcache_data { char *name; @@ -58,6 +58,7 @@ krb5_rc_resolve_type(krb5_context context, krb5_rcache *id, const char *type) { + *id = NULL; if(strcmp(type, "FILE")) { krb5_set_error_string (context, "replay cache type %s not supported", type); @@ -77,6 +78,9 @@ krb5_rc_resolve_full(krb5_context context, const char *string_name) { krb5_error_code ret; + + *id = NULL; + if(strncmp(string_name, "FILE:", 5)) { krb5_set_error_string (context, "replay cache type %s not supported", string_name); @@ -86,6 +90,10 @@ krb5_rc_resolve_full(krb5_context context, if(ret) return ret; ret = krb5_rc_resolve(context, *id, string_name + 5); + if (ret) { + krb5_rc_close(context, *id); + *id = NULL; + } return ret; } diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index d3d21aea3f..0bcafa70a1 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: send_to_kdc.c,v 1.57 2006/03/07 19:39:59 lha Exp $"); +RCSID("$Id: send_to_kdc.c,v 1.58 2006/04/02 02:32:03 lha Exp $"); struct send_and_recv { krb5_send_and_recv_func_t func; @@ -231,6 +231,7 @@ send_and_recv_http(int fd, s[rep->length] = 0; p = strstr(s, "\r\n\r\n"); if(p == NULL) { + krb5_data_zero(rep); free(s); return -1; } @@ -238,12 +239,14 @@ send_and_recv_http(int fd, rep->data = s; rep->length -= p - s; if(rep->length < 4) { /* remove length */ + krb5_data_zero(rep); free(s); return -1; } rep->length -= 4; _krb5_get_int(p, &rep_len, 4); if (rep_len != rep->length) { + krb5_data_zero(rep); free(s); return -1; } diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c index 42667765fb..4a567bb379 100644 --- a/source4/heimdal/lib/krb5/store.c +++ b/source4/heimdal/lib/krb5/store.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store.c,v 1.50 2005/06/17 04:36:33 lha Exp $"); +RCSID("$Id: store.c,v 1.51 2006/04/07 22:23:20 lha Exp $"); #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) @@ -420,7 +420,7 @@ krb5_ret_principal(krb5_storage *sp, if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) type = KRB5_NT_UNKNOWN; - else if((ret = krb5_ret_int32(sp, &type))){ + else if((ret = krb5_ret_int32(sp, &type))){ free(p); return ret; } @@ -430,18 +430,31 @@ krb5_ret_principal(krb5_storage *sp, } if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) ncomp--; + if (ncomp < 0) { + free(p); + return EINVAL; + } p->name.name_type = type; p->name.name_string.len = ncomp; ret = krb5_ret_string(sp, &p->realm); - if(ret) return ret; + if(ret) { + free(p); + return ret; + } p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val)); - if(p->name.name_string.val == NULL){ + if(p->name.name_string.val == NULL && ncomp != 0){ free(p->realm); return ENOMEM; } for(i = 0; i < ncomp; i++){ ret = krb5_ret_string(sp, &p->name.name_string.val[i]); - if(ret) return ret; /* XXX */ + if(ret) { + while (i >= 0) + free(p->name.name_string.val[i--]); + free(p->realm); + free(p); + return ret; + } } *princ = p; return 0; diff --git a/source4/heimdal/lib/krb5/transited.c b/source4/heimdal/lib/krb5/transited.c index 9e24db0da0..7f18b30c88 100644 --- a/source4/heimdal/lib/krb5/transited.c +++ b/source4/heimdal/lib/krb5/transited.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: transited.c,v 1.16 2005/06/17 04:53:35 lha Exp $"); +RCSID("$Id: transited.c,v 1.18 2006/04/10 10:26:35 lha Exp $"); /* this is an attempt at one of the most horrible `compression' schemes that has ever been invented; it's so amazingly brain-dead @@ -100,8 +100,10 @@ make_path(krb5_context context, struct tr_realm *r, p = from + strlen(from); while(1){ while(p >= from && *p != '/') p--; - if(p == from) + if(p == from) { + r->next = path; /* XXX */ return KRB5KDC_ERR_POLICY; + } if(strncmp(to, from, p - from) == 0) break; tmp = calloc(1, sizeof(*tmp)); @@ -166,10 +168,13 @@ expand_realms(krb5_context context, for(r = realms; r; r = r->next){ if(r->trailing_dot){ char *tmp; - size_t len = strlen(r->realm) + strlen(prev_realm) + 1; + size_t len; if(prev_realm == NULL) prev_realm = client_realm; + + len = strlen(r->realm) + strlen(prev_realm) + 1; + tmp = realloc(r->realm, len); if(tmp == NULL){ free_realms(realms); diff --git a/source4/heimdal/lib/krb5/v4_glue.c b/source4/heimdal/lib/krb5/v4_glue.c index c66b06c09f..dd294c8943 100644 --- a/source4/heimdal/lib/krb5/v4_glue.c +++ b/source4/heimdal/lib/krb5/v4_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: v4_glue.c,v 1.2 2005/04/24 13:44:02 lha Exp $"); +RCSID("$Id: v4_glue.c,v 1.3 2006/04/02 01:39:54 lha Exp $"); #include "krb5-v4compat.h" @@ -155,19 +155,20 @@ write_v4_cc(krb5_context context, const char *tkfile, fd = open(path, O_WRONLY|O_CREAT, 0600); if (fd < 0) { - free(path); + ret = errno; krb5_set_error_string(context, "krb5_krb_tf_setup: error opening file %s", path); - return errno; + free(path); + return ret; } if (fstat(fd, &sb) != 0 || !S_ISREG(sb.st_mode)) { - free(path); - close(fd); krb5_set_error_string(context, "krb5_krb_tf_setup: tktfile %s is not a file", path); + free(path); + close(fd); return KRB5_FCC_PERM; } @@ -178,11 +179,11 @@ write_v4_cc(krb5_context context, const char *tkfile, break; } if (i == KRB5_TF_LCK_RETRY_COUNT) { - free(path); - close(fd); krb5_set_error_string(context, "krb5_krb_tf_setup: failed to lock %s", path); + free(path); + close(fd); return KRB5_FCC_PERM; } @@ -190,11 +191,11 @@ write_v4_cc(krb5_context context, const char *tkfile, ret = ftruncate(fd, 0); if (ret < 0) { flock(fd, LOCK_UN); - free(path); - close(fd); krb5_set_error_string(context, "krb5_krb_tf_setup: failed to truncate %s", path); + free(path); + close(fd); return KRB5_FCC_PERM; } } -- cgit From 835926c87921a0f4186a9331b6e31b2e6f1c0d90 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 7 May 2006 04:51:30 +0000 Subject: r15481: Update heimdal/ to match current lorikeet-heimdal. This includes many useful upstream changes, many of which should reduce warnings in our compile. It also includes a change to the HDB interface, which removes the need for Samba4/lorikeet-heimdal to deviate from upstream for hdb_fetch(). The new flags replace the old entry type enum. (This required the rework in hdb-ldb.c included in this commit) Andrew Bartlett (This used to be commit ef5604b87744c89e66e4d845f45b23563754ec05) --- source4/heimdal/lib/krb5/addr_families.c | 6 +- source4/heimdal/lib/krb5/changepw.c | 4 +- source4/heimdal/lib/krb5/crc.c | 6 +- source4/heimdal/lib/krb5/crypto.c | 12 +- source4/heimdal/lib/krb5/generate_seq_number.c | 6 +- source4/heimdal/lib/krb5/init_creds_pw.c | 3 +- source4/heimdal/lib/krb5/kcm.c | 10 +- source4/heimdal/lib/krb5/keytab_file.c | 4 +- source4/heimdal/lib/krb5/keytab_keyfile.c | 7 +- source4/heimdal/lib/krb5/krb5-private.h | 26 ++-- source4/heimdal/lib/krb5/krb5-protos.h | 34 ++++- source4/heimdal/lib/krb5/krb5-v4compat.h | 10 +- source4/heimdal/lib/krb5/krb5.h | 12 +- source4/heimdal/lib/krb5/krb5_ccapi.h | 4 +- source4/heimdal/lib/krb5/krb5_locl.h | 2 +- source4/heimdal/lib/krb5/log.c | 6 +- source4/heimdal/lib/krb5/pkinit.c | 193 ++++++++++++++++++++++--- source4/heimdal/lib/krb5/principal.c | 3 +- source4/heimdal/lib/krb5/store.c | 79 +++++++++- source4/heimdal/lib/krb5/v4_glue.c | 38 ++--- 20 files changed, 358 insertions(+), 107 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c index ebdbcfed46..895b01f9d8 100644 --- a/source4/heimdal/lib/krb5/addr_families.c +++ b/source4/heimdal/lib/krb5/addr_families.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: addr_families.c,v 1.51 2006/04/02 02:17:31 lha Exp $"); +RCSID("$Id: addr_families.c,v 1.52 2006/05/05 09:26:22 lha Exp $"); struct addr_operations { int af; @@ -199,7 +199,7 @@ ipv4_mask_boundary(krb5_context context, const krb5_address *inaddr, unsigned long len, krb5_address *low, krb5_address *high) { unsigned long ia; - u_int32_t l, h, m = 0xffffffff; + uint32_t l, h, m = 0xffffffff; if (len > 32) { krb5_set_error_string(context, "IPv4 prefix too large (%ld)", len); @@ -391,7 +391,7 @@ ipv6_mask_boundary(krb5_context context, const krb5_address *inaddr, unsigned long len, krb5_address *low, krb5_address *high) { struct in6_addr addr, laddr, haddr; - u_int32_t m; + uint32_t m; int i, sub_len; if (len > 128) { diff --git a/source4/heimdal/lib/krb5/changepw.c b/source4/heimdal/lib/krb5/changepw.c index 7907e1ad9c..ba584a04a4 100644 --- a/source4/heimdal/lib/krb5/changepw.c +++ b/source4/heimdal/lib/krb5/changepw.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: changepw.c,v 1.55 2005/12/12 12:48:57 lha Exp $"); +RCSID("$Id: changepw.c,v 1.56 2006/05/05 09:26:47 lha Exp $"); static void str2data (krb5_data *d, @@ -271,7 +271,7 @@ process_reply (krb5_context context, krb5_error_code ret; u_char reply[1024 * 3]; ssize_t len; - u_int16_t pkt_len, pkt_ver; + uint16_t pkt_len, pkt_ver; krb5_data ap_rep_data; int save_errno; diff --git a/source4/heimdal/lib/krb5/crc.c b/source4/heimdal/lib/krb5/crc.c index c7cedd8c9e..4cfed75154 100644 --- a/source4/heimdal/lib/krb5/crc.c +++ b/source4/heimdal/lib/krb5/crc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: crc.c,v 1.9 2000/08/03 01:45:14 assar Exp $"); +RCSID("$Id: crc.c,v 1.10 2006/05/05 09:27:09 lha Exp $"); static u_long table[256]; @@ -62,8 +62,8 @@ _krb5_crc_init_table(void) flag = 1; } -u_int32_t -_krb5_crc_update (const char *p, size_t len, u_int32_t res) +uint32_t +_krb5_crc_update (const char *p, size_t len, uint32_t res) { while (len--) res = table[(res ^ *p++) & 0xFF] ^ (res >> 8); diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 3a90995283..2e8160518b 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.134 2006/04/10 08:58:53 lha Exp $"); +RCSID("$Id: crypto.c,v 1.135 2006/05/05 09:27:24 lha Exp $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -602,7 +602,7 @@ AES_string_to_key(krb5_context context, krb5_keyblock *key) { krb5_error_code ret; - u_int32_t iter; + uint32_t iter; struct encryption_type *et; struct key_data kd; @@ -611,7 +611,7 @@ AES_string_to_key(krb5_context context, else if (opaque.length == 4) { unsigned long v; _krb5_get_int(opaque.data, &v, 4); - iter = ((u_int32_t)v); + iter = ((uint32_t)v); } else return KRB5_PROG_KEYTYPE_NOSUPP; /* XXX */ @@ -1296,7 +1296,7 @@ CRC32_checksum(krb5_context context, unsigned usage, Checksum *C) { - u_int32_t crc; + uint32_t crc; unsigned char *r = C->checksum.data; _krb5_crc_init_table (); crc = _krb5_crc_update (data, len, 0); @@ -4282,7 +4282,7 @@ _krb5_pk_octetstring2key(krb5_context context, static krb5_error_code krb5_get_keyid(krb5_context context, krb5_keyblock *key, - u_int32_t *keyid) + uint32_t *keyid) { MD5_CTX md5; unsigned char tmp[16]; @@ -4300,7 +4300,7 @@ krb5_crypto_debug(krb5_context context, size_t len, krb5_keyblock *key) { - u_int32_t keyid; + uint32_t keyid; char *kt; krb5_get_keyid(context, key, &keyid); krb5_enctype_to_string(context, key->keytype, &kt); diff --git a/source4/heimdal/lib/krb5/generate_seq_number.c b/source4/heimdal/lib/krb5/generate_seq_number.c index f9e9cded5f..7f79e29858 100644 --- a/source4/heimdal/lib/krb5/generate_seq_number.c +++ b/source4/heimdal/lib/krb5/generate_seq_number.c @@ -33,16 +33,16 @@ #include -RCSID("$Id: generate_seq_number.c,v 1.9 2004/05/25 21:25:22 lha Exp $"); +RCSID("$Id: generate_seq_number.c,v 1.10 2006/05/05 09:28:06 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_generate_seq_number(krb5_context context, const krb5_keyblock *key, - u_int32_t *seqno) + uint32_t *seqno) { krb5_error_code ret; krb5_keyblock *subkey; - u_int32_t q; + uint32_t q; u_char *p; int i; diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 489a88a31b..70b6c3e4c3 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c,v 1.92 2006/04/02 01:20:15 lha Exp $"); +RCSID("$Id: init_creds_pw.c,v 1.94 2006/04/24 08:49:08 lha Exp $"); typedef struct krb5_get_init_creds_ctx { krb5_kdc_flags flags; @@ -1150,6 +1150,7 @@ process_pa_data_to_key(krb5_context context, if (pa && ctx->pk_init_ctx) { #ifdef PKINIT ret = _krb5_pk_rd_pa_reply(context, + a->req_body.realm, ctx->pk_init_ctx, etype, hi, diff --git a/source4/heimdal/lib/krb5/kcm.c b/source4/heimdal/lib/krb5/kcm.c index f4372422ac..8f2d9f7f86 100644 --- a/source4/heimdal/lib/krb5/kcm.c +++ b/source4/heimdal/lib/krb5/kcm.c @@ -43,7 +43,7 @@ #include "kcm.h" -RCSID("$Id: kcm.c,v 1.8 2005/09/19 20:23:05 lha Exp $"); +RCSID("$Id: kcm.c,v 1.9 2006/05/05 09:28:48 lha Exp $"); typedef struct krb5_kcmcache { char *name; @@ -53,7 +53,7 @@ typedef struct krb5_kcmcache { #define KCMCACHE(X) ((krb5_kcmcache *)(X)->data.data) #define CACHENAME(X) (KCMCACHE(X)->name) -#define KCMCURSOR(C) (*(u_int32_t *)(C)) +#define KCMCURSOR(C) (*(uint32_t *)(C)) static krb5_error_code try_door(krb5_context context, const krb5_kcmcache *k, @@ -903,7 +903,7 @@ _krb5_kcm_noop(krb5_context context, krb5_error_code _krb5_kcm_chmod(krb5_context context, krb5_ccache id, - u_int16_t mode) + uint16_t mode) { krb5_error_code ret; krb5_kcmcache *k = KCMCACHE(id); @@ -944,8 +944,8 @@ _krb5_kcm_chmod(krb5_context context, krb5_error_code _krb5_kcm_chown(krb5_context context, krb5_ccache id, - u_int32_t uid, - u_int32_t gid) + uint32_t uid, + uint32_t gid) { krb5_error_code ret; krb5_kcmcache *k = KCMCACHE(id); diff --git a/source4/heimdal/lib/krb5/keytab_file.c b/source4/heimdal/lib/krb5/keytab_file.c index f9a76e634a..1b06387339 100644 --- a/source4/heimdal/lib/krb5/keytab_file.c +++ b/source4/heimdal/lib/krb5/keytab_file.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_file.c,v 1.22 2006/04/07 21:57:31 lha Exp $"); +RCSID("$Id: keytab_file.c,v 1.23 2006/05/05 12:36:57 lha Exp $"); #define KRB5_KT_VNO_1 1 #define KRB5_KT_VNO_2 2 @@ -428,7 +428,7 @@ loop: * if it's zero, assume that the 8bit one was right, * otherwise trust the new value */ curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR); - if(len + 4 + pos - curpos == 4) { + if(len + 4 + pos - curpos >= 4) { ret = krb5_ret_int32(cursor->sp, &tmp32); if (ret == 0 && tmp32 != 0) { entry->vno = tmp32; diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c index 32fb48a8a2..d7f8a720e1 100644 --- a/source4/heimdal/lib/krb5/keytab_keyfile.c +++ b/source4/heimdal/lib/krb5/keytab_keyfile.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_keyfile.c,v 1.18 2006/04/02 01:24:52 lha Exp $"); +RCSID("$Id: keytab_keyfile.c,v 1.19 2006/04/24 15:06:57 lha Exp $"); /* afs keyfile operations --------------------------------------- */ @@ -63,8 +63,7 @@ struct akf_data { */ static int -get_cell_and_realm (krb5_context context, - struct akf_data *d) +get_cell_and_realm (krb5_context context, struct akf_data *d) { FILE *f; char buf[BUFSIZ], *cp; @@ -95,6 +94,7 @@ get_cell_and_realm (krb5_context context, if (f != NULL) { if (fgets (buf, sizeof(buf), f) == NULL) { free (d->cell); + d->cell = NULL; fclose (f); krb5_set_error_string (context, "no realm in %s", AFS_SERVERMAGICKRBCONF); @@ -110,6 +110,7 @@ get_cell_and_realm (krb5_context context, d->realm = strdup (buf); if (d->realm == NULL) { free (d->cell); + d->cell = NULL; krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 00126d60ed..17b282f1d8 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -30,11 +30,11 @@ _krb5_cc_allocate ( void _krb5_crc_init_table (void); -u_int32_t +uint32_t _krb5_crc_update ( const char */*p*/, size_t /*len*/, - u_int32_t /*res*/); + uint32_t /*res*/); krb5_error_code _krb5_dh_group_ok ( @@ -120,14 +120,14 @@ krb5_error_code _krb5_kcm_chmod ( krb5_context /*context*/, krb5_ccache /*id*/, - u_int16_t /*mode*/); + uint16_t /*mode*/); krb5_error_code _krb5_kcm_chown ( krb5_context /*context*/, krb5_ccache /*id*/, - u_int32_t /*uid*/, - u_int32_t /*gid*/); + uint32_t /*uid*/, + uint32_t /*gid*/); krb5_error_code _krb5_kcm_get_initial_ticket ( @@ -158,8 +158,8 @@ _krb5_krb_cr_err_reply ( const char */*name*/, const char */*inst*/, const char */*realm*/, - u_int32_t /*time_ws*/, - u_int32_t /*e*/, + uint32_t /*time_ws*/, + uint32_t /*e*/, const char */*e_string*/, krb5_data */*data*/); @@ -171,7 +171,7 @@ _krb5_krb_create_auth_reply ( const char */*prealm*/, int32_t /*time_ws*/, int /*n*/, - u_int32_t /*x_date*/, + uint32_t /*x_date*/, unsigned char /*kvno*/, const krb5_data */*cipher*/, krb5_data */*data*/); @@ -183,10 +183,10 @@ _krb5_krb_create_ciph ( const char */*service*/, const char */*instance*/, const char */*realm*/, - u_int32_t /*life*/, + uint32_t /*life*/, unsigned char /*kvno*/, const krb5_data */*ticket*/, - u_int32_t /*kdc_time*/, + uint32_t /*kdc_time*/, const krb5_keyblock */*key*/, krb5_data */*enc_data*/); @@ -298,6 +298,11 @@ _krb5_parse_moduli_line ( char */*p*/, struct krb5_dh_moduli **/*m*/); +void KRB5_LIB_FUNCTION +_krb5_pk_allow_proxy_certificate ( + struct krb5_pk_identity */*id*/, + int /*boolean*/); + void KRB5_LIB_FUNCTION _krb5_pk_cert_free (struct krb5_pk_cert */*cert*/); @@ -341,6 +346,7 @@ _krb5_pk_octetstring2key ( krb5_error_code KRB5_LIB_FUNCTION _krb5_pk_rd_pa_reply ( krb5_context /*context*/, + const char */*realm*/, void */*c*/, krb5_enctype /*etype*/, const krb5_krbhst_info */*hi*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 56f43f6c3d..37293ff982 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -1592,7 +1592,7 @@ krb5_error_code KRB5_LIB_FUNCTION krb5_generate_seq_number ( krb5_context /*context*/, const krb5_keyblock */*key*/, - u_int32_t */*seqno*/); + uint32_t */*seqno*/); krb5_error_code KRB5_LIB_FUNCTION krb5_generate_subkey ( @@ -2802,6 +2802,21 @@ krb5_ret_times ( krb5_storage */*sp*/, krb5_times */*times*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_uint16 ( + krb5_storage */*sp*/, + uint16_t */*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_uint32 ( + krb5_storage */*sp*/, + uint32_t */*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_uint8 ( + krb5_storage */*sp*/, + uint8_t */*value*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_salttype_to_string ( krb5_context /*context*/, @@ -3087,7 +3102,7 @@ krb5_store_keyblock ( krb5_error_code KRB5_LIB_FUNCTION krb5_store_principal ( krb5_storage */*sp*/, - krb5_principal /*p*/); + krb5_const_principal /*p*/); krb5_error_code KRB5_LIB_FUNCTION krb5_store_string ( @@ -3104,6 +3119,21 @@ krb5_store_times ( krb5_storage */*sp*/, krb5_times /*times*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_uint16 ( + krb5_storage */*sp*/, + uint16_t /*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_uint32 ( + krb5_storage */*sp*/, + uint32_t /*value*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_uint8 ( + krb5_storage */*sp*/, + uint8_t /*value*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_string_to_deltat ( const char */*string*/, diff --git a/source4/heimdal/lib/krb5/krb5-v4compat.h b/source4/heimdal/lib/krb5/krb5-v4compat.h index 1d092dcbc9..3e14c5a38f 100644 --- a/source4/heimdal/lib/krb5/krb5-v4compat.h +++ b/source4/heimdal/lib/krb5/krb5-v4compat.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5-v4compat.h,v 1.6 2005/04/23 19:38:16 lha Exp $ */ +/* $Id: krb5-v4compat.h,v 1.7 2006/05/05 09:29:07 lha Exp $ */ #ifndef __KRB5_V4COMPAT_H__ #define __KRB5_V4COMPAT_H__ @@ -119,7 +119,7 @@ struct ktext { unsigned int length; /* Length of the text */ unsigned char dat[MAX_KTXT_LEN]; /* The data itself */ - u_int32_t mbz; /* zero to catch runaway strings */ + uint32_t mbz; /* zero to catch runaway strings */ }; struct credentials { @@ -157,11 +157,11 @@ struct _krb5_krb_auth_data { char *pname; /* Principal's name */ char *pinst; /* His Instance */ char *prealm; /* His Realm */ - u_int32_t checksum; /* Data checksum (opt) */ + uint32_t checksum; /* Data checksum (opt) */ krb5_keyblock session; /* Session Key */ unsigned char life; /* Life of ticket */ - u_int32_t time_sec; /* Time ticket issued */ - u_int32_t address; /* Address in ticket */ + uint32_t time_sec; /* Time ticket issued */ + uint32_t address; /* Address in ticket */ }; time_t _krb5_krb_life_to_time (int, int); diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 9814817600..32fdd6d383 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h,v 1.240 2005/11/30 15:20:32 lha Exp $ */ +/* $Id: krb5.h,v 1.241 2006/05/05 09:29:36 lha Exp $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -64,7 +64,7 @@ typedef int32_t krb5_error_code; typedef int krb5_kvno; -typedef u_int32_t krb5_flags; +typedef uint32_t krb5_flags; typedef void *krb5_pointer; typedef const void *krb5_const_pointer; @@ -492,7 +492,7 @@ typedef struct krb5_keytab_entry { krb5_principal principal; krb5_kvno vno; krb5_keyblock keyblock; - u_int32_t timestamp; + uint32_t timestamp; } krb5_keytab_entry; typedef struct krb5_kt_cursor { @@ -536,7 +536,7 @@ typedef struct krb5_keytab_key_proc_args krb5_keytab_key_proc_args; typedef struct krb5_replay_data { krb5_timestamp timestamp; int32_t usec; - u_int32_t seq; + uint32_t seq; } krb5_replay_data; /* flags for krb5_auth_con_setflags */ @@ -569,8 +569,8 @@ typedef struct krb5_auth_context_data { krb5_keyblock *local_subkey; krb5_keyblock *remote_subkey; - u_int32_t local_seqnumber; - u_int32_t remote_seqnumber; + uint32_t local_seqnumber; + uint32_t remote_seqnumber; krb5_authenticator authenticator; diff --git a/source4/heimdal/lib/krb5/krb5_ccapi.h b/source4/heimdal/lib/krb5/krb5_ccapi.h index 29b2ddbecc..d59b589304 100644 --- a/source4/heimdal/lib/krb5/krb5_ccapi.h +++ b/source4/heimdal/lib/krb5/krb5_ccapi.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_ccapi.h,v 1.2 2006/03/27 04:21:06 lha Exp $ */ +/* $Id: krb5_ccapi.h,v 1.3 2006/05/05 09:29:59 lha Exp $ */ #ifndef KRB5_CCAPI_H #define KRB5_CCAPI_H 1 @@ -84,7 +84,7 @@ enum { }; typedef int32_t cc_int32; -typedef u_int32_t cc_uint32; +typedef uint32_t cc_uint32; typedef struct cc_context_t *cc_context_t; typedef struct cc_ccache_t *cc_ccache_t; typedef struct cc_ccache_iterator_t *cc_ccache_iterator_t; diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 92dd3271f5..4dcac40c7a 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * diff --git a/source4/heimdal/lib/krb5/log.c b/source4/heimdal/lib/krb5/log.c index 7e478bf1e0..e6fcb6bbb9 100644 --- a/source4/heimdal/lib/krb5/log.c +++ b/source4/heimdal/lib/krb5/log.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: log.c,v 1.38 2006/04/10 09:41:26 lha Exp $"); +RCSID("$Id: log.c,v 1.39 2006/04/24 15:09:27 lha Exp $"); struct facility { int min; @@ -221,8 +221,10 @@ log_file(const char *timestr, if(f->fd == NULL) return; fprintf(f->fd, "%s %s\n", timestr, msg); - if(f->keep_open == 0) + if(f->keep_open == 0) { fclose(f->fd); + f->fd = NULL; + } } static void diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index fa4fb4699e..7e91946095 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.88 2006/04/23 21:30:17 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.98 2006/05/06 13:24:54 lha Exp $"); struct krb5_dh_moduli { char *name; @@ -84,6 +84,7 @@ struct krb5_pk_init_ctx_data { int require_binding; int require_eku; int require_krbtgt_otherName; + int require_hostname_match; }; void KRB5_LIB_FUNCTION @@ -161,6 +162,109 @@ _krb5_pk_create_sign(krb5_context context, return ret; } +static int +cert2epi(hx509_context context, void *ctx, hx509_cert c) +{ + ExternalPrincipalIdentifiers *ids = ctx; + ExternalPrincipalIdentifier id; + hx509_name subject = NULL; + void *p; + int ret; + + memset(&id, 0, sizeof(id)); + + ret = hx509_cert_get_subject(c, &subject); + if (ret) + return ret; + + if (hx509_name_is_null_p(subject) != 0) { + + id.subjectName = calloc(1, sizeof(*id.subjectName)); + if (id.subjectName == NULL) { + hx509_name_free(&subject); + free_ExternalPrincipalIdentifier(&id); + return ENOMEM; + } + + ret = hx509_name_to_der_name(subject, &id.subjectName->data, + &id.subjectName->length); + if (ret) { + hx509_name_free(&subject); + free_ExternalPrincipalIdentifier(&id); + return ret; + } + } + hx509_name_free(&subject); + + + id.issuerAndSerialNumber = calloc(1, sizeof(*id.issuerAndSerialNumber)); + if (id.issuerAndSerialNumber == NULL) { + free_ExternalPrincipalIdentifier(&id); + return ENOMEM; + } + + { + IssuerAndSerialNumber iasn; + hx509_name issuer; + size_t size; + + memset(&iasn, 0, sizeof(iasn)); + + ret = hx509_cert_get_issuer(c, &issuer); + if (ret) { + free_ExternalPrincipalIdentifier(&id); + return ret; + } + + ret = hx509_name_to_Name(issuer, &iasn.issuer); + hx509_name_free(&issuer); + if (ret) { + free_ExternalPrincipalIdentifier(&id); + return ret; + } + + ret = hx509_cert_get_serialnumber(c, &iasn.serialNumber); + if (ret) { + free_IssuerAndSerialNumber(&iasn); + free_ExternalPrincipalIdentifier(&id); + return ret; + } + + ASN1_MALLOC_ENCODE(IssuerAndSerialNumber, + id.issuerAndSerialNumber->data, + id.issuerAndSerialNumber->length, + &iasn, &size, ret); + free_IssuerAndSerialNumber(&iasn); + if (ret) + return ret; + if (id.issuerAndSerialNumber->length != size) + abort(); + } + + id.subjectKeyIdentifier = NULL; + + p = realloc(ids->val, sizeof(ids->val[0]) * (ids->len + 1)); + if (p == NULL) { + free_ExternalPrincipalIdentifier(&id); + return ENOMEM; + } + + ids->val = p; + ids->val[ids->len] = id; + ids->len++; + + return 0; +} + +static krb5_error_code +build_edi(krb5_context context, + hx509_context hx509ctx, + hx509_certs certs, + ExternalPrincipalIdentifiers *ids) +{ + return hx509_certs_iter(hx509ctx, certs, cert2epi, ids); +} + static krb5_error_code build_auth_pack(krb5_context context, unsigned nonce, @@ -446,8 +550,19 @@ pk_mk_padata(krb5_context context, memset(&req, 0, sizeof(req)); req.signedAuthPack = buf; - /* XXX tell the kdc what CAs the client is willing to accept */ - req.trustedCertifiers = NULL; + req.trustedCertifiers = calloc(1, sizeof(*req.trustedCertifiers)); + if (req.trustedCertifiers == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + free_PA_PK_AS_REQ(&req); + goto out; + } + ret = build_edi(context, ctx->id->hx509ctx, + ctx->id->anchors, req.trustedCertifiers); + if (ret) { + krb5_set_error_string(context, "pk-init: failed to build trustedCertifiers"); + free_PA_PK_AS_REQ(&req); + goto out; + } req.kdcPkId = NULL; ASN1_MALLOC_ENCODE(PA_PK_AS_REQ, buf.data, buf.length, @@ -524,6 +639,13 @@ _krb5_pk_mk_padata(krb5_context context, "pkinit_require_krbtgt_otherName", NULL); + ctx->require_hostname_match = + krb5_config_get_bool_default(context, NULL, + FALSE, + "realms", + req_body->realm, + "pkinit_require_hostname_match", + NULL); return pk_mk_padata(context, type, ctx, req_body, nonce, md); } @@ -710,6 +832,8 @@ get_reply_key(krb5_context context, static krb5_error_code pk_verify_host(krb5_context context, + const char *realm, + const krb5_krbhst_info *hi, struct krb5_pk_init_ctx_data *ctx, struct krb5_pk_cert *host) { @@ -719,13 +843,12 @@ pk_verify_host(krb5_context context, ret = hx509_cert_check_eku(ctx->id->hx509ctx, host->cert, oid_id_pkkdcekuoid(), 0); if (ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "No PK-INIT KDC EKU in kdc certificate"); return ret; } } if (ctx->require_krbtgt_otherName) { hx509_octet_string_list list; - krb5_error_code ret; int i; ret = hx509_cert_find_subjectAltName_otherName(host->cert, @@ -738,6 +861,7 @@ pk_verify_host(krb5_context context, for (i = 0; i < list.len; i++) { KRB5PrincipalName r; + ret = decode_KRB5PrincipalName(list.val[i].data, list.val[i].length, &r, @@ -747,13 +871,15 @@ pk_verify_host(krb5_context context, break; } -#if 0 - if (r.principalName.name.len != 2) { - krb5_clear_error_string(context); + if (r.principalName.name_string.len != 2 || + strcmp(r.principalName.name_string.val[0], KRB5_TGS_NAME) != 0 || + strcmp(r.principalName.name_string.val[1], realm) != 0 || + strcmp(r.realm, realm) != 0) + { + krb5_set_error_string(context, "KDC have wrong realm name in " + "the certificate"); ret = EINVAL; } -#endif - /* XXX verify realm */ free_KRB5PrincipalName(&r); if (ret) @@ -761,14 +887,26 @@ pk_verify_host(krb5_context context, } hx509_free_octet_string_list(&list); } + if (ret) + return ret; + + if (hi) { + ret = hx509_verify_hostname(ctx->id->hx509ctx, host->cert, + ctx->require_hostname_match, + hi->hostname, + hi->ai->ai_addr, hi->ai->ai_addrlen); + if (ret) + krb5_set_error_string(context, "Address mismatch in the KDC certificate"); + } return ret; } static krb5_error_code pk_rd_pa_reply_enckey(krb5_context context, int type, - ContentInfo *rep, + const ContentInfo *rep, + const char *realm, krb5_pk_init_ctx ctx, krb5_enctype etype, const krb5_krbhst_info *hi, @@ -846,7 +984,7 @@ pk_rd_pa_reply_enckey(krb5_context context, goto out; /* make sure that it is the kdc's certificate */ - ret = pk_verify_host(context, ctx, host); + ret = pk_verify_host(context, realm, hi, ctx, host); if (ret) { krb5_set_error_string(context, "PKINIT: failed verify host: %d", ret); goto out; @@ -894,7 +1032,8 @@ pk_rd_pa_reply_enckey(krb5_context context, static krb5_error_code pk_rd_pa_reply_dh(krb5_context context, - ContentInfo *rep, + const ContentInfo *rep, + const char *realm, krb5_pk_init_ctx ctx, krb5_enctype etype, const krb5_krbhst_info *hi, @@ -938,7 +1077,7 @@ pk_rd_pa_reply_dh(krb5_context context, goto out; /* make sure that it is the kdc's certificate */ - ret = pk_verify_host(context, ctx, host); + ret = pk_verify_host(context, realm, hi, ctx, host); if (ret) goto out; @@ -1066,6 +1205,7 @@ pk_rd_pa_reply_dh(krb5_context context, krb5_error_code KRB5_LIB_FUNCTION _krb5_pk_rd_pa_reply(krb5_context context, + const char *realm, void *c, krb5_enctype etype, const krb5_krbhst_info *hi, @@ -1106,7 +1246,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, free_PA_PK_AS_REP(&rep); break; } - ret = pk_rd_pa_reply_dh(context, &ci, ctx, etype, hi, + ret = pk_rd_pa_reply_dh(context, &ci, realm, ctx, etype, hi, ctx->clientDHNonce, rep.u.dhInfo.serverDHNonce, nonce, pa, key); @@ -1126,7 +1266,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, "ContentInfo: %d", ret); break; } - ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &ci, ctx, + ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &ci, realm, ctx, etype, hi, nonce, req_buffer, pa, key); free_ContentInfo(&ci); return ret; @@ -1173,7 +1313,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, ret); return ret; } - ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, ctx, + ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, realm, ctx, etype, hi, nonce, req_buffer, pa, key); free_ContentInfo(&ci); break; @@ -1204,8 +1344,8 @@ hx_pass_prompter(void *data, const hx509_prompt *prompter) krb5_data password_data; struct prompter *p = data; - password_data.data = prompter->reply->data; - password_data.length = prompter->reply->length; + password_data.data = prompter->reply.data; + password_data.length = prompter->reply.length; prompt.prompt = "Enter your private key passphrase: "; prompt.hidden = 1; prompt.reply = &password_data; @@ -1216,12 +1356,21 @@ hx_pass_prompter(void *data, const hx509_prompt *prompter) ret = (*p->prompter)(p->context, p->prompter_data, NULL, NULL, 1, &prompt); if (ret) { - memset (prompter->reply->data, 0, prompter->reply->length); + memset (prompter->reply.data, 0, prompter->reply.length); return 0; } - return strlen(prompter->reply->data); + return strlen(prompter->reply.data); +} + + +void KRB5_LIB_FUNCTION +_krb5_pk_allow_proxy_certificate(struct krb5_pk_identity *id, + int boolean) +{ + hx509_verify_set_proxy_certificate(id->verify_ctx, boolean); } + krb5_error_code KRB5_LIB_FUNCTION _krb5_pk_load_id(krb5_context context, struct krb5_pk_identity **ret_id, @@ -1715,7 +1864,7 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, } if (DH_generate_key(opt->opt_private->pk_init_ctx->dh) != 1) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_string(context, "pkinit: failed to generate DH key"); _krb5_get_init_creds_opt_free_pkinit(opt); return ENOMEM; } diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index 34086b1fbe..f6e3847cce 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -41,7 +41,7 @@ #include #include "resolve.h" -RCSID("$Id: principal.c,v 1.94 2006/04/10 10:10:01 lha Exp $"); +RCSID("$Id: principal.c,v 1.95 2006/04/24 15:16:14 lha Exp $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -829,7 +829,6 @@ krb5_425_conv_principal_ext2(krb5_context context, if (r) { if (r->head && r->head->type == T_AAAA) { inst = strdup(r->head->domain); - dns_free_data(r); passed = TRUE; } dns_free_data(r); diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c index 4a567bb379..a6f4a011a1 100644 --- a/source4/heimdal/lib/krb5/store.c +++ b/source4/heimdal/lib/krb5/store.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store.c,v 1.51 2006/04/07 22:23:20 lha Exp $"); +RCSID("$Id: store.c,v 1.58 2006/05/05 07:15:18 lha Exp $"); #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) @@ -181,6 +181,13 @@ krb5_store_int32(krb5_storage *sp, return krb5_store_int(sp, value, 4); } +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_uint32(krb5_storage *sp, + uint32_t value) +{ + return krb5_store_int32(sp, (int32_t)value); +} + static krb5_error_code krb5_ret_int(krb5_storage *sp, int32_t *value, @@ -211,6 +218,20 @@ krb5_ret_int32(krb5_storage *sp, return 0; } +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_uint32(krb5_storage *sp, + uint32_t *value) +{ + krb5_error_code ret; + int32_t v; + + ret = krb5_ret_int32(sp, &v); + if (ret == 0) + *value = (uint32_t)v; + + return ret; +} + krb5_error_code KRB5_LIB_FUNCTION krb5_store_int16(krb5_storage *sp, int16_t value) @@ -222,6 +243,13 @@ krb5_store_int16(krb5_storage *sp, return krb5_store_int(sp, value, 2); } +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_uint16(krb5_storage *sp, + uint16_t value) +{ + return krb5_store_int16(sp, (int16_t)value); +} + krb5_error_code KRB5_LIB_FUNCTION krb5_ret_int16(krb5_storage *sp, int16_t *value) @@ -239,6 +267,20 @@ krb5_ret_int16(krb5_storage *sp, return 0; } +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_uint16(krb5_storage *sp, + uint16_t *value) +{ + krb5_error_code ret; + int16_t v; + + ret = krb5_ret_int16(sp, &v); + if (ret == 0) + *value = (uint16_t)v; + + return ret; +} + krb5_error_code KRB5_LIB_FUNCTION krb5_store_int8(krb5_storage *sp, int8_t value) @@ -251,6 +293,13 @@ krb5_store_int8(krb5_storage *sp, return 0; } +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_uint8(krb5_storage *sp, + uint8_t value) +{ + return krb5_store_int8(sp, (int8_t)value); +} + krb5_error_code KRB5_LIB_FUNCTION krb5_ret_int8(krb5_storage *sp, int8_t *value) @@ -263,6 +312,20 @@ krb5_ret_int8(krb5_storage *sp, return 0; } +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_uint8(krb5_storage *sp, + uint8_t *value) +{ + krb5_error_code ret; + int8_t v; + + ret = krb5_ret_int8(sp, &v); + if (ret == 0) + *value = (uint8_t)v; + + return ret; +} + krb5_error_code KRB5_LIB_FUNCTION krb5_store_data(krb5_storage *sp, krb5_data data) @@ -380,19 +443,19 @@ krb5_ret_stringz(krb5_storage *sp, krb5_error_code KRB5_LIB_FUNCTION krb5_store_principal(krb5_storage *sp, - krb5_principal p) + krb5_const_principal p) { int i; int ret; if(!krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_NO_NAME_TYPE)) { - ret = krb5_store_int32(sp, p->name.name_type); - if(ret) return ret; + ret = krb5_store_int32(sp, p->name.name_type); + if(ret) return ret; } if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) ret = krb5_store_int32(sp, p->name.name_string.len + 1); else - ret = krb5_store_int32(sp, p->name.name_string.len); + ret = krb5_store_int32(sp, p->name.name_string.len); if(ret) return ret; ret = krb5_store_string(sp, p->realm); @@ -710,7 +773,7 @@ krb5_ret_creds(krb5_storage *sp, krb5_creds *creds) * format. */ { - u_int32_t mask = 0xffff0000; + uint32_t mask = 0xffff0000; creds->flags.i = 0; creds->flags.b.anonymous = 1; if (creds->flags.i & mask) @@ -865,7 +928,7 @@ krb5_ret_creds_tag(krb5_storage *sp, * format. */ { - u_int32_t mask = 0xffff0000; + uint32_t mask = 0xffff0000; creds->flags.i = 0; creds->flags.b.anonymous = 1; if (creds->flags.i & mask) diff --git a/source4/heimdal/lib/krb5/v4_glue.c b/source4/heimdal/lib/krb5/v4_glue.c index dd294c8943..b1e12674dc 100644 --- a/source4/heimdal/lib/krb5/v4_glue.c +++ b/source4/heimdal/lib/krb5/v4_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: v4_glue.c,v 1.3 2006/04/02 01:39:54 lha Exp $"); +RCSID("$Id: v4_glue.c,v 1.5 2006/05/05 09:31:00 lha Exp $"); #include "krb5-v4compat.h" @@ -463,10 +463,10 @@ _krb5_krb_create_ciph(krb5_context context, const char *service, const char *instance, const char *realm, - u_int32_t life, + uint32_t life, unsigned char kvno, const krb5_data *ticket, - u_int32_t kdc_time, + uint32_t kdc_time, const krb5_keyblock *key, krb5_data *enc_data) { @@ -523,7 +523,7 @@ _krb5_krb_create_auth_reply(krb5_context context, const char *prealm, int32_t time_ws, int n, - u_int32_t x_date, + uint32_t x_date, unsigned char kvno, const krb5_data *cipher, krb5_data *data) @@ -573,8 +573,8 @@ _krb5_krb_cr_err_reply(krb5_context context, const char *name, const char *inst, const char *realm, - u_int32_t time_ws, - u_int32_t e, + uint32_t time_ws, + uint32_t e, const char *e_string, krb5_data *data) { @@ -668,7 +668,7 @@ _krb5_krb_decomp_ticket(krb5_context context, RCHECK(ret, get_v4_stringz(sp, &ad->pname, ANAME_SZ), error); RCHECK(ret, get_v4_stringz(sp, &ad->pinst, INST_SZ), error); RCHECK(ret, get_v4_stringz(sp, &ad->prealm, REALM_SZ), error); - RCHECK(ret, krb5_ret_int32(sp, &ad->address), error); + RCHECK(ret, krb5_ret_uint32(sp, &ad->address), error); size = krb5_storage_read(sp, des_key, sizeof(des_key)); if (size != sizeof(des_key)) { @@ -676,14 +676,14 @@ _krb5_krb_decomp_ticket(krb5_context context, goto error; } - RCHECK(ret, krb5_ret_int8(sp, &ad->life), error); + RCHECK(ret, krb5_ret_uint8(sp, &ad->life), error); if (ad->k_flags & 1) krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); else krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); - RCHECK(ret, krb5_ret_int32(sp, &ad->time_sec), error); + RCHECK(ret, krb5_ret_uint32(sp, &ad->time_sec), error); RCHECK(ret, get_v4_stringz(sp, sname, ANAME_SZ), error); RCHECK(ret, get_v4_stringz(sp, sinstance, INST_SZ), error); @@ -744,9 +744,9 @@ _krb5_krb_rd_req(krb5_context context, int8_t pvno; int8_t type; int8_t s_kvno; - u_int8_t ticket_length; - u_int8_t eaut_length; - u_int8_t time_5ms; + uint8_t ticket_length; + uint8_t eaut_length; + uint8_t time_5ms; char *realm = NULL; char *sname = NULL; char *sinstance = NULL; @@ -754,7 +754,7 @@ _krb5_krb_rd_req(krb5_context context, char *r_name = NULL; char *r_instance = NULL; - u_int32_t r_time_sec; /* Coarse time from authenticator */ + uint32_t r_time_sec; /* Coarse time from authenticator */ unsigned long delta_t; /* Time in authenticator - local time */ long tkt_age; /* Age of ticket */ @@ -795,8 +795,8 @@ _krb5_krb_rd_req(krb5_context context, RCHECK(ret, krb5_ret_int8(sp, &s_kvno), error); RCHECK(ret, get_v4_stringz(sp, &realm, REALM_SZ), error); - RCHECK(ret, krb5_ret_int8(sp, &ticket_length), error); - RCHECK(ret, krb5_ret_int8(sp, &eaut_length), error); + RCHECK(ret, krb5_ret_uint8(sp, &ticket_length), error); + RCHECK(ret, krb5_ret_uint8(sp, &eaut_length), error); RCHECK(ret, krb5_data_alloc(&ticket, ticket_length), error); size = krb5_storage_read(sp, ticket.data, ticket.length); @@ -842,9 +842,9 @@ _krb5_krb_rd_req(krb5_context context, RCHECK(ret, get_v4_stringz(sp, &r_instance, INST_SZ), error); RCHECK(ret, get_v4_stringz(sp, &r_realm, REALM_SZ), error); - RCHECK(ret, krb5_ret_int32(sp, &ad->checksum), error); - RCHECK(ret, krb5_ret_int8(sp, &time_5ms), error); - RCHECK(ret, krb5_ret_int32(sp, &r_time_sec), error); + RCHECK(ret, krb5_ret_uint32(sp, &ad->checksum), error); + RCHECK(ret, krb5_ret_uint8(sp, &time_5ms), error); + RCHECK(ret, krb5_ret_uint32(sp, &r_time_sec), error); if (strcmp(ad->pname, r_name) != 0 || strcmp(ad->pinst, r_instance) != 0 || @@ -853,7 +853,7 @@ _krb5_krb_rd_req(krb5_context context, goto error; } - if (from_addr && from_addr == ad->address) { + if (from_addr && from_addr != ad->address) { ret = EINVAL; /* RD_AP_BADD */ goto error; } -- cgit From 1ec7132b3058fb9d20ac188ea1840db2b068bea1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sun, 7 May 2006 09:28:49 +0000 Subject: r15484: Make accept_security_context() more compatible with how Samba3 (and similarly built clients) behave. This is better than just ignoring the checksum, if it isn't the GSSAPI checksum. (Samba4 clients in Samba3 mode use more than just the MD5 checksum, and will use a signed AES checksum if available. Actual samba3 may well do the same in future, against a suitable KDC). Also a change for easier debugging of checksum issues. Andrew Bartlett (This used to be commit 120374f5f9e9af0653a26e0308e4bfdabbcaa3f3) --- source4/heimdal/lib/krb5/crypto.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 2e8160518b..1a37ec538b 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -2042,7 +2042,8 @@ verify_checksum(krb5_context context, } keyed_checksum = (ct->flags & F_KEYED) != 0; if(keyed_checksum && crypto == NULL) { - krb5_clear_error_string (context); + krb5_set_error_string (context, "checksum type %s is keyed, and requires a crypto context", + ct->name); return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ } if(keyed_checksum) -- cgit From bfff6b0e640b3b3456ec1d9d26da0bd80a08585f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 8 May 2006 23:30:40 +0000 Subject: r15515: Syncronsise with current lorikeet-heimdal. Andrew Bartlett (This used to be commit 0132312124260f74001546a34ff96db89d72b7f6) --- source4/heimdal/lib/krb5/crypto.c | 154 ++------------------------------------ source4/heimdal/lib/krb5/pkinit.c | 32 ++------ 2 files changed, 13 insertions(+), 173 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 1a37ec538b..876cbb5192 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.135 2006/05/05 09:27:24 lha Exp $"); +RCSID("$Id: crypto.c,v 1.138 2006/05/08 13:47:24 lha Exp $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -70,7 +70,6 @@ struct krb5_crypto_data { #define F_PSEUDO 16 /* not a real protocol type */ #define F_SPECIAL 32 /* backwards */ #define F_DISABLED 64 /* enctype/checksum disabled */ -#define F_PADCMS 128 /* padding done like in CMS */ struct salt_type { krb5_salttype type; @@ -1957,7 +1956,9 @@ create_checksum (krb5_context context, } keyed_checksum = (ct->flags & F_KEYED) != 0; if(keyed_checksum && crypto == NULL) { - krb5_clear_error_string (context); + krb5_set_error_string (context, "Checksum type %s is keyed " + "but no crypto context (key) was passed in", + ct->name); return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ } if(keyed_checksum) { @@ -2042,7 +2043,8 @@ verify_checksum(krb5_context context, } keyed_checksum = (ct->flags & F_KEYED) != 0; if(keyed_checksum && crypto == NULL) { - krb5_set_error_string (context, "checksum type %s is keyed, and requires a crypto context", + krb5_set_error_string (context, "Checksum type %s is keyed " + "but no crypto context (key) was passed in", ct->name); return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ } @@ -2391,55 +2393,6 @@ AES_CTS_encrypt(krb5_context context, return 0; } -static krb5_error_code -AES_CBC_encrypt(krb5_context context, - struct key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ivec) -{ - struct krb5_aes_schedule *aeskey = key->schedule->data; - char local_ivec[AES_BLOCK_SIZE]; - AES_KEY *k; - - if (encryptp) - k = &aeskey->ekey; - else - k = &aeskey->dkey; - - if(ivec == NULL) { - ivec = &local_ivec; - memset(local_ivec, 0, sizeof(local_ivec)); - } - AES_cbc_encrypt(data, data, len, k, ivec, encryptp); - return 0; -} - -/* - * RC2 - */ - -static krb5_error_code -RC2_CBC_encrypt(krb5_context context, - struct key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ivec) -{ - unsigned char local_ivec[8]; - RC2_KEY *s = key->schedule->data; - if(ivec == NULL) { - ivec = &local_ivec; - memset(local_ivec, 0, sizeof(local_ivec)); - } - RC2_cbc_encrypt(data, data, len, s, ivec, encryptp); - return 0; -} - /* * section 6 of draft-brezak-win2k-krb-rc4-hmac-03 * @@ -2764,51 +2717,6 @@ static struct encryption_type enctype_aes256_cts_hmac_sha1 = { F_DERIVED, AES_CTS_encrypt, }; -static unsigned aes_128_cbc_num[] = { 2, 16, 840, 1, 101, 3, 4, 1, 2 }; -static heim_oid aes_128_cbc_oid = kcrypto_oid_enc(aes_128_cbc_num); -static struct encryption_type enctype_aes128_cbc_none = { - ETYPE_AES128_CBC_NONE, - "aes128-cbc-none", - &aes_128_cbc_oid, - 16, - 16, - 16, - &keytype_aes128, - &checksum_none, - NULL, - F_PSEUDO|F_PADCMS, - AES_CBC_encrypt, -}; -static unsigned aes_192_cbc_num[] = { 2, 16, 840, 1, 101, 3, 4, 1, 22 }; -static heim_oid aes_192_cbc_oid = kcrypto_oid_enc(aes_192_cbc_num); -static struct encryption_type enctype_aes192_cbc_none = { - ETYPE_AES192_CBC_NONE, - "aes192-cbc-none", - &aes_192_cbc_oid, - 16, - 16, - 16, - &keytype_aes192, - &checksum_none, - NULL, - F_PSEUDO|F_PADCMS, - AES_CBC_encrypt, -}; -static unsigned aes_256_cbc_num[] = { 2, 16, 840, 1, 101, 3, 4, 1, 42 }; -static heim_oid aes_256_cbc_oid = kcrypto_oid_enc(aes_256_cbc_num); -static struct encryption_type enctype_aes256_cbc_none = { - ETYPE_AES256_CBC_NONE, - "aes256-cbc-none", - &aes_256_cbc_oid, - 16, - 16, - 16, - &keytype_aes256, - &checksum_none, - NULL, - F_PSEUDO|F_PADCMS, - AES_CBC_encrypt, -}; static struct encryption_type enctype_des_cbc_none = { ETYPE_DES_CBC_NONE, "des-cbc-none", @@ -2848,21 +2756,6 @@ static struct encryption_type enctype_des_pcbc_none = { F_PSEUDO, DES_PCBC_encrypt_key_ivec, }; -static unsigned des_ede3_cbc_num[] = { 1, 2, 840, 113549, 3, 7 }; -static heim_oid des_ede3_cbc_oid = kcrypto_oid_enc(des_ede3_cbc_num); -static struct encryption_type enctype_des3_cbc_none_cms = { - ETYPE_DES3_CBC_NONE_CMS, - "des3-cbc-none-cms", - &des_ede3_cbc_oid, - 8, - 8, - 0, - &keytype_des3_derived, - &checksum_none, - NULL, - F_PSEUDO|F_PADCMS, - DES3_CBC_encrypt, -}; static struct encryption_type enctype_des3_cbc_none = { ETYPE_DES3_CBC_NONE, "des3-cbc-none", @@ -2876,21 +2769,6 @@ static struct encryption_type enctype_des3_cbc_none = { F_PSEUDO, DES3_CBC_encrypt, }; -static unsigned rc2CBC_num[] = { 1, 2, 840, 113549, 3, 2 }; -static heim_oid rc2CBC_oid = kcrypto_oid_enc(rc2CBC_num); -static struct encryption_type enctype_rc2_cbc_none = { - ETYPE_RC2_CBC_NONE, - "rc2-cbc-none", - &rc2CBC_oid, - 8, - 8, - 0, - &keytype_rc2, - &checksum_none, - NULL, - F_PSEUDO|F_PADCMS, - RC2_CBC_encrypt, -}; static struct encryption_type *etypes[] = { &enctype_null, @@ -2903,15 +2781,10 @@ static struct encryption_type *etypes[] = { &enctype_old_des3_cbc_sha1, &enctype_aes128_cts_hmac_sha1, &enctype_aes256_cts_hmac_sha1, - &enctype_aes128_cbc_none, - &enctype_aes192_cbc_none, - &enctype_aes256_cbc_none, &enctype_des_cbc_none, &enctype_des_cfb64_none, &enctype_des_pcbc_none, - &enctype_des3_cbc_none, - &enctype_des3_cbc_none_cms, - &enctype_rc2_cbc_none + &enctype_des3_cbc_none }; static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]); @@ -3234,7 +3107,7 @@ encrypt_internal(krb5_context context, krb5_data *result, void *ivec) { - size_t sz, block_sz, checksum_sz, padsize = 0; + size_t sz, block_sz, checksum_sz; Checksum cksum; unsigned char *p, *q; krb5_error_code ret; @@ -3244,11 +3117,6 @@ encrypt_internal(krb5_context context, sz = et->confoundersize + checksum_sz + len; block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ - if ((et->flags & F_PADCMS) && et->padsize != 1) { - padsize = et->padsize - (sz % et->padsize); - if (padsize == et->padsize) - block_sz += et->padsize; - } p = calloc(1, block_sz); if(p == NULL) { krb5_set_error_string(context, "malloc: out of memory"); @@ -3281,12 +3149,6 @@ encrypt_internal(krb5_context context, ret = _key_schedule(context, &crypto->key, crypto->params); if(ret) goto fail; - if (et->flags & F_PADCMS) { - int i; - q = p + len + checksum_sz + et->confoundersize; - for (i = 0; i < padsize; i++) - q[i] = padsize; - } #ifdef CRYPTO_DEBUG krb5_crypto_debug(context, 1, block_sz, crypto->key.key); #endif diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 7e91946095..00f7b4ebd9 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.98 2006/05/06 13:24:54 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.99 2006/05/07 12:32:38 lha Exp $"); struct krb5_dh_moduli { char *name; @@ -682,32 +682,10 @@ _krb5_pk_verify_sign(krb5_context context, goto out; } - /* XXX */ - { - hx509_cursor cursor; - - ret = hx509_certs_start_seq(id->hx509ctx, - signer_certs, - &cursor); - if (ret) { - krb5_clear_error_string(context); - goto out; - } - ret = hx509_certs_next_cert(id->hx509ctx, - signer_certs, - cursor, - &(*signer)->cert); - if (ret) { - krb5_clear_error_string(context); - goto out; - } - ret = hx509_certs_end_seq(id->hx509ctx, - signer_certs, - cursor); - if (ret) { - krb5_clear_error_string(context); - goto out; - } + ret = hx509_get_one_cert(id->hx509ctx, signer_certs, &(*signer)->cert); + if (ret) { + krb5_clear_error_string(context); + goto out; } out: -- cgit From e3a6c6be79326578a1e9c7cb8547234eab62235f Mon Sep 17 00:00:00 2001 From: Gerald Carter Date: Thu, 8 Jun 2006 15:20:05 +0000 Subject: r16100: Patch from Michael Wood : s/then/than/ for correct grammar (This used to be commit 26a2fa97e4c819e630bc9b50e11c8d5328c7b8c8) --- source4/heimdal/lib/krb5/crypto.c | 2 +- source4/heimdal/lib/krb5/get_for_creds.c | 2 +- source4/heimdal/lib/krb5/heim_threads.h | 2 +- source4/heimdal/lib/krb5/init_creds_pw.c | 4 ++-- source4/heimdal/lib/krb5/ticket.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 876cbb5192..a3c58051f9 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -2299,7 +2299,7 @@ _krb5_aes_cts_encrypt(const unsigned char *in, unsigned char *out, /* * In the framework of kerberos, the length can never be shorter - * then at least one blocksize. + * than at least one blocksize. */ if (encryptp) { diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index 661d05663b..f042cdb573 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -376,7 +376,7 @@ krb5_get_forwarded_creds (krb5_context context, cred.enc_part.cipher.length = buf_size; } else { /* - * Here older versions then 0.7.2 of Heimdal used the local or + * Here older versions than 0.7.2 of Heimdal used the local or * remote subkey. That is wrong, the session key should be * used. Heimdal 0.7.2 and newer have code to try both in the * receiving end. diff --git a/source4/heimdal/lib/krb5/heim_threads.h b/source4/heimdal/lib/krb5/heim_threads.h index 3ebe66beee..41f0f83306 100755 --- a/source4/heimdal/lib/krb5/heim_threads.h +++ b/source4/heimdal/lib/krb5/heim_threads.h @@ -53,7 +53,7 @@ /* * NetBSD have a thread lib that we can use that part of libc that * works regardless if application are linked to pthreads or not. - * NetBSD newer then 2.99.11 just use pthread.h, and the same thing + * NetBSD newer than 2.99.11 just use pthread.h, and the same thing * will happen. */ #include diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 70b6c3e4c3..c05386ec23 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -1211,7 +1211,7 @@ init_cred_loop(krb5_context context, ctx->pk_nonce = ctx->nonce; /* - * Increase counter when we want other pre-auth types then + * Increase counter when we want other pre-auth types than * KRB5_PA_ENC_TIMESTAMP. */ #define MAX_PA_COUNTER 3 @@ -1391,7 +1391,7 @@ krb5_get_init_creds(krb5_context context, case KRB5KDC_ERR_KEY_EXPIRED : /* try to avoid recursion */ - /* don't try to change password where then where none */ + /* don't try to change password where there where none */ if (prompter == NULL || ctx.password == NULL) goto out; diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c index b3efeb39d3..99cb778722 100644 --- a/source4/heimdal/lib/krb5/ticket.c +++ b/source4/heimdal/lib/krb5/ticket.c @@ -112,7 +112,7 @@ find_type_in_ad(krb5_context context, if (level > 9) { krb5_set_error_string(context, "Authorization data nested deeper " - "then %d levels, stop searching", level); + "than %d levels, stop searching", level); ret = ENOENT; /* XXX */ goto out; } -- cgit From 83558e822b9b1ea64ae89b77b2d815d19211d996 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 22 Sep 2006 18:39:49 +0000 Subject: r18826: Allow 'enterprise' principal names to log in. These principals do not need to be in the same realm as the rest of the ticket, the full principal name is in the first componet of the ASN.1. Samba4's backend will handle getting this to the 'right' place. Andrew Bartlett (This used to be commit 90b01b8af21609e2e5c8b6bd8cab8bd393844acf) --- source4/heimdal/lib/krb5/asn1_glue.c | 20 +++++++++++++++----- source4/heimdal/lib/krb5/get_in_tkt.c | 6 ++++-- source4/heimdal/lib/krb5/krb5-private.h | 1 + source4/heimdal/lib/krb5/rd_cred.c | 5 +++-- source4/heimdal/lib/krb5/rd_req.c | 12 +++++++----- 5 files changed, 30 insertions(+), 14 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/asn1_glue.c b/source4/heimdal/lib/krb5/asn1_glue.c index 01b5d3ee44..8f7b886e80 100644 --- a/source4/heimdal/lib/krb5/asn1_glue.c +++ b/source4/heimdal/lib/krb5/asn1_glue.c @@ -47,13 +47,23 @@ _krb5_principal2principalname (PrincipalName *p, } krb5_error_code KRB5_LIB_FUNCTION -_krb5_principalname2krb5_principal (krb5_principal *principal, +_krb5_principalname2krb5_principal (krb5_context context, + krb5_principal *principal, const PrincipalName from, const Realm realm) { - krb5_principal p = malloc(sizeof(*p)); - copy_PrincipalName(&from, &p->name); - p->realm = strdup(realm); - *principal = p; + if (from.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { + if (from.name_string.len != 1) { + return KRB5_PARSE_MALFORMED; + } + return krb5_parse_name(context, + from.name_string.val[0], + principal); + } else { + krb5_principal p = malloc(sizeof(*p)); + copy_PrincipalName(&from, &p->name); + p->realm = strdup(realm); + *principal = p; + } return 0; } diff --git a/source4/heimdal/lib/krb5/get_in_tkt.c b/source4/heimdal/lib/krb5/get_in_tkt.c index 24d6c29f52..5c488d1ddc 100644 --- a/source4/heimdal/lib/krb5/get_in_tkt.c +++ b/source4/heimdal/lib/krb5/get_in_tkt.c @@ -137,7 +137,8 @@ _krb5_extract_ticket(krb5_context context, time_t tmp_time; krb5_timestamp sec_now; - ret = _krb5_principalname2krb5_principal (&tmp_principal, + ret = _krb5_principalname2krb5_principal (context, + &tmp_principal, rep->kdc_rep.cname, rep->kdc_rep.crealm); if (ret) @@ -170,7 +171,8 @@ _krb5_extract_ticket(krb5_context context, /* compare server */ - ret = _krb5_principalname2krb5_principal (&tmp_principal, + ret = _krb5_principalname2krb5_principal (context, + &tmp_principal, rep->kdc_rep.ticket.sname, rep->kdc_rep.ticket.realm); if (ret) diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 17b282f1d8..9ba288e22b 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -372,6 +372,7 @@ _krb5_principal2principalname ( krb5_error_code KRB5_LIB_FUNCTION _krb5_principalname2krb5_principal ( + krb5_context /* context */, krb5_principal */*principal*/, const PrincipalName /*from*/, const Realm /*realm*/); diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c index 520b3a1418..01b5188bae 100644 --- a/source4/heimdal/lib/krb5/rd_cred.c +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -265,7 +265,7 @@ krb5_rd_cred(krb5_context context, krb5_abortx(context, "internal error in ASN.1 encoder"); copy_EncryptionKey (&kci->key, &creds->session); if (kci->prealm && kci->pname) - _krb5_principalname2krb5_principal (&creds->client, + _krb5_principalname2krb5_principal (context, &creds->client, *kci->pname, *kci->prealm); if (kci->flags) @@ -279,7 +279,8 @@ krb5_rd_cred(krb5_context context, if (kci->renew_till) creds->times.renew_till = *kci->renew_till; if (kci->srealm && kci->sname) - _krb5_principalname2krb5_principal (&creds->server, + _krb5_principalname2krb5_principal (context, + &creds->server, *kci->sname, *kci->srealm); if (kci->caddr) diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 0d4635b964..c0bb710a59 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -376,10 +376,12 @@ krb5_verify_ap_req2(krb5_context context, if(ret) goto out; - ret = _krb5_principalname2krb5_principal(&t->server, ap_req->ticket.sname, + ret = _krb5_principalname2krb5_principal(context, + &t->server, ap_req->ticket.sname, ap_req->ticket.realm); if (ret) goto out; - ret = _krb5_principalname2krb5_principal(&t->client, t->ticket.cname, + ret = _krb5_principalname2krb5_principal(context, + &t->client, t->ticket.cname, t->ticket.crealm); if (ret) goto out; @@ -400,10 +402,10 @@ krb5_verify_ap_req2(krb5_context context, krb5_principal p1, p2; krb5_boolean res; - _krb5_principalname2krb5_principal(&p1, + _krb5_principalname2krb5_principal(context, &p1, ac->authenticator->cname, ac->authenticator->crealm); - _krb5_principalname2krb5_principal(&p2, + _krb5_principalname2krb5_principal(context, &p2, t->ticket.cname, t->ticket.crealm); res = krb5_principal_compare (context, p1, p2); @@ -605,7 +607,7 @@ krb5_rd_req_return_keyblock(krb5_context context, return ret; if(server == NULL){ - _krb5_principalname2krb5_principal(&service, + _krb5_principalname2krb5_principal(context, &service, ap_req.ticket.sname, ap_req.ticket.realm); server = service; -- cgit From 3c1e780ec7e16dc6667402bbc65708bf9a5c062f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 7 Nov 2006 06:59:56 +0000 Subject: r19604: This is a massive commit, and I appologise in advance for it's size. This merges Samba4 with lorikeet-heimdal, which itself has been tracking Heimdal CVS for the past couple of weeks. This is such a big change because Heimdal reorganised it's internal structures, with the mechglue merge, and because many of our 'wishes' have been granted: we now have DCE_STYLE GSSAPI, send_to_kdc hooks and many other features merged into the mainline code. We have adapted to upstream's choice of API in these cases. In gensec_gssapi and gensec_krb5, we either expect a valid PAC, or NO PAC. This matches windows behavour. We also have an option to require the PAC to be present (which allows us to automate the testing of this code). This also includes a restructure of how the kerberos dependencies are handled, due to the fallout of the merge. Andrew Bartlett (This used to be commit 4826f1735197c2a471d771495e6d4c1051b4c471) --- source4/heimdal/lib/krb5/acache.c | 4 +- source4/heimdal/lib/krb5/addr_families.c | 3 +- source4/heimdal/lib/krb5/asn1_glue.c | 2 +- source4/heimdal/lib/krb5/cache.c | 28 +-- source4/heimdal/lib/krb5/context.c | 61 ++++- source4/heimdal/lib/krb5/crypto.c | 278 +++------------------ source4/heimdal/lib/krb5/data.c | 4 +- source4/heimdal/lib/krb5/expand_hostname.c | 12 +- source4/heimdal/lib/krb5/get_cred.c | 346 +++++++++++++++++++++++++-- source4/heimdal/lib/krb5/get_for_creds.c | 2 +- source4/heimdal/lib/krb5/get_host_realm.c | 74 +++--- source4/heimdal/lib/krb5/get_in_tkt.c | 21 +- source4/heimdal/lib/krb5/heim_err.c | 162 +++++++++++++ source4/heimdal/lib/krb5/heim_threads.h | 2 +- source4/heimdal/lib/krb5/init_creds.c | 91 ++++++- source4/heimdal/lib/krb5/init_creds_pw.c | 80 ++++--- source4/heimdal/lib/krb5/k524_err.c | 30 +++ source4/heimdal/lib/krb5/krb5-private.h | 29 ++- source4/heimdal/lib/krb5/krb5-protos.h | 306 +++++++++++++++++++---- source4/heimdal/lib/krb5/krb5.h | 102 ++++---- source4/heimdal/lib/krb5/krb5_err.c | 271 +++++++++++++++++++++ source4/heimdal/lib/krb5/krb5_locl.h | 66 ++++- source4/heimdal/lib/krb5/krbhst.c | 14 +- source4/heimdal/lib/krb5/misc.c | 51 +++- source4/heimdal/lib/krb5/mit_glue.c | 6 +- source4/heimdal/lib/krb5/pkinit.c | 157 +++++++----- source4/heimdal/lib/krb5/principal.c | 187 +++++++-------- source4/heimdal/lib/krb5/rd_cred.c | 5 +- source4/heimdal/lib/krb5/rd_rep.c | 13 +- source4/heimdal/lib/krb5/rd_req.c | 23 +- source4/heimdal/lib/krb5/send_to_kdc.c | 91 +++---- source4/heimdal/lib/krb5/set_default_realm.c | 15 +- source4/heimdal/lib/krb5/store.c | 72 +++++- source4/heimdal/lib/krb5/store_fd.c | 9 +- source4/heimdal/lib/krb5/ticket.c | 12 +- 35 files changed, 1888 insertions(+), 741 deletions(-) create mode 100644 source4/heimdal/lib/krb5/heim_err.c create mode 100644 source4/heimdal/lib/krb5/k524_err.c create mode 100644 source4/heimdal/lib/krb5/krb5_err.c (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c index b38104fc2d..004926bc89 100644 --- a/source4/heimdal/lib/krb5/acache.c +++ b/source4/heimdal/lib/krb5/acache.c @@ -37,7 +37,7 @@ #include #endif -RCSID("$Id: acache.c,v 1.15 2006/03/27 04:22:23 lha Exp $"); +RCSID("$Id: acache.c,v 1.16 2006/10/19 11:41:38 lha Exp $"); /* XXX should we fetch these for each open ? */ static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; @@ -113,7 +113,7 @@ init_ccapi(krb5_context context) return KRB5_CC_NOSUPP; } - init_func = dlsym(cc_handle, "cc_initialize"); + init_func = (cc_initialize_func)dlsym(cc_handle, "cc_initialize"); HEIMDAL_MUTEX_unlock(&acc_mutex); if (init_func == NULL) { krb5_set_error_string(context, "Failed to find cc_initialize" diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c index 895b01f9d8..f68be423b0 100644 --- a/source4/heimdal/lib/krb5/addr_families.c +++ b/source4/heimdal/lib/krb5/addr_families.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: addr_families.c,v 1.52 2006/05/05 09:26:22 lha Exp $"); +RCSID("$Id: addr_families.c,v 1.53 2006/10/22 06:54:00 lha Exp $"); struct addr_operations { int af; @@ -551,6 +551,7 @@ arange_free (krb5_context context, krb5_address *addr) a = addr->address.data; krb5_free_address(context, &a->low); krb5_free_address(context, &a->high); + krb5_data_free(&addr->address); return 0; } diff --git a/source4/heimdal/lib/krb5/asn1_glue.c b/source4/heimdal/lib/krb5/asn1_glue.c index 8f7b886e80..b07e058550 100644 --- a/source4/heimdal/lib/krb5/asn1_glue.c +++ b/source4/heimdal/lib/krb5/asn1_glue.c @@ -37,7 +37,7 @@ #include "krb5_locl.h" -RCSID("$Id: asn1_glue.c,v 1.9 2004/12/29 18:54:15 lha Exp $"); +RCSID("$Id: asn1_glue.c,v 1.10 2006/10/06 17:02:48 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION _krb5_principal2principalname (PrincipalName *p, diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index b21d42d653..a96870a7de 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c,v 1.79 2006/04/02 00:54:48 lha Exp $"); +RCSID("$Id: cache.c,v 1.82 2006/09/12 17:35:33 lha Exp $"); /* * Add a new ccache type with operations `ops', overwriting any @@ -188,7 +188,7 @@ krb5_cc_new_unique(krb5_context context, const char *type, const krb5_cc_ops *ops; if (type == NULL) - type = "FILE"; + type = KRB5_DEFAULT_CCNAME; ops = krb5_cc_get_prefix_ops(context, type); if (ops == NULL) { @@ -423,7 +423,7 @@ krb5_cc_initialize(krb5_context context, krb5_ccache id, krb5_principal primary_principal) { - return id->ops->init(context, id, primary_principal); + return (*id->ops->init)(context, id, primary_principal); } @@ -438,7 +438,7 @@ krb5_cc_destroy(krb5_context context, { krb5_error_code ret; - ret = id->ops->destroy(context, id); + ret = (*id->ops->destroy)(context, id); krb5_cc_close (context, id); return ret; } @@ -453,7 +453,7 @@ krb5_cc_close(krb5_context context, krb5_ccache id) { krb5_error_code ret; - ret = id->ops->close(context, id); + ret = (*id->ops->close)(context, id); free(id); return ret; } @@ -468,7 +468,7 @@ krb5_cc_store_cred(krb5_context context, krb5_ccache id, krb5_creds *creds) { - return id->ops->store(context, id, creds); + return (*id->ops->store)(context, id, creds); } /* @@ -488,8 +488,8 @@ krb5_cc_retrieve_cred(krb5_context context, krb5_cc_cursor cursor; if (id->ops->retrieve != NULL) { - return id->ops->retrieve(context, id, whichfields, - mcreds, creds); + return (*id->ops->retrieve)(context, id, whichfields, + mcreds, creds); } krb5_cc_start_seq_get(context, id, &cursor); @@ -514,7 +514,7 @@ krb5_cc_get_principal(krb5_context context, krb5_ccache id, krb5_principal *principal) { - return id->ops->get_princ(context, id, principal); + return (*id->ops->get_princ)(context, id, principal); } /* @@ -528,7 +528,7 @@ krb5_cc_start_seq_get (krb5_context context, const krb5_ccache id, krb5_cc_cursor *cursor) { - return id->ops->get_first(context, id, cursor); + return (*id->ops->get_first)(context, id, cursor); } /* @@ -543,7 +543,7 @@ krb5_cc_next_cred (krb5_context context, krb5_cc_cursor *cursor, krb5_creds *creds) { - return id->ops->get_next(context, id, cursor, creds); + return (*id->ops->get_next)(context, id, cursor, creds); } /* like krb5_cc_next_cred, but allow for selective retrieval */ @@ -576,7 +576,7 @@ krb5_cc_end_seq_get (krb5_context context, const krb5_ccache id, krb5_cc_cursor *cursor) { - return id->ops->end_get(context, id, cursor); + return (*id->ops->end_get)(context, id, cursor); } /* @@ -607,7 +607,7 @@ krb5_cc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags) { - return id->ops->set_flags(context, id, flags); + return (*id->ops->set_flags)(context, id, flags); } /* @@ -672,7 +672,7 @@ krb5_cc_get_version(krb5_context context, const krb5_ccache id) { if(id->ops->get_version) - return id->ops->get_version(context, id); + return (*id->ops->get_version)(context, id); else return 0; } diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index 594665235b..f7b3ffbf9e 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: context.c,v 1.102 2005/05/18 04:20:50 lha Exp $"); +RCSID("$Id: context.c,v 1.108 2006/10/20 22:26:10 lha Exp $"); #define INIT_FIELD(C, T, E, D, F) \ (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ @@ -181,8 +181,8 @@ init_context_from_config_file(krb5_context context) INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup"); INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc"); INIT_FIELD(context, int, large_msg_size, 6000, "large_message_size"); + INIT_FIELD(context, bool, dns_canonicalize_hostname, TRUE, "dns_canonize_hostname"); context->default_cc_name = NULL; - INIT_FIELD(context, bool, fdns, TRUE, "fdns"); return 0; } @@ -263,7 +263,7 @@ krb5_free_context(krb5_context context) krb5_closelog(context, context->warn_dest); krb5_set_extra_addresses(context, NULL); krb5_set_ignore_addresses(context, NULL); - free(context->send_and_recv); + krb5_set_send_to_kdc_func(context, NULL, NULL); if (context->mutex != NULL) { HEIMDAL_MUTEX_destroy(context->mutex); free(context->mutex); @@ -424,13 +424,17 @@ krb5_free_config_files(char **filenames) } /* - * set `etype' to a malloced list of the default enctypes + * Returns the list of Kerberos encryption types sorted in order of + * most preferred to least preferred encryption type. The array ends + * with ETYPE_NULL. Note that some encryption types might be + * disabled, so you need to check with krb5_enctype_valid() before + * using the encryption type. */ -static krb5_error_code -default_etypes(krb5_context context, krb5_enctype **etype) +const krb5_enctype * KRB5_LIB_FUNCTION +krb5_kerberos_enctypes(krb5_context context) { - krb5_enctype p[] = { + static const krb5_enctype p[] = { ETYPE_AES256_CTS_HMAC_SHA1_96, ETYPE_AES128_CTS_HMAC_SHA1_96, ETYPE_DES3_CBC_SHA1, @@ -438,12 +442,26 @@ default_etypes(krb5_context context, krb5_enctype **etype) ETYPE_ARCFOUR_HMAC_MD5, ETYPE_DES_CBC_MD5, ETYPE_DES_CBC_MD4, - ETYPE_DES_CBC_CRC + ETYPE_DES_CBC_CRC, + ETYPE_NULL }; + return p; +} + +/* + * set `etype' to a malloced list of the default enctypes + */ + +static krb5_error_code +default_etypes(krb5_context context, krb5_enctype **etype) +{ + const krb5_enctype *p; krb5_enctype *e = NULL, *ep; int i, n = 0; - for (i = 0; i < sizeof(p)/sizeof(p[0]); i++) { + p = krb5_kerberos_enctypes(context); + + for (i = 0; p[i] != ETYPE_NULL; i++) { if (krb5_enctype_valid(context, p[i]) != 0) continue; ep = realloc(e, (n + 2) * sizeof(*e)); @@ -537,6 +555,9 @@ krb5_init_ets(krb5_context context) krb5_add_et_list(context, initialize_asn1_error_table_r); krb5_add_et_list(context, initialize_heim_error_table_r); krb5_add_et_list(context, initialize_k524_error_table_r); +#ifdef PKINIT + krb5_add_et_list(context, initialize_hx_error_table_r); +#endif } } @@ -662,3 +683,25 @@ krb5_is_thread_safe(void) return FALSE; #endif } + +void KRB5_LIB_FUNCTION +krb5_set_dns_canonicalize_hostname (krb5_context context, krb5_boolean flag) +{ + context->dns_canonicalize_hostname = flag; +} + +krb5_boolean KRB5_LIB_FUNCTION +krb5_get_dns_canonize_hostname (krb5_context context) +{ + return context->dns_canonicalize_hostname; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec) +{ + if (sec) + *sec = context->kdc_sec_offset; + if (usec) + *usec = context->kdc_usec_offset; + return 0; +} diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index a3c58051f9..9f6ef6b82b 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.138 2006/05/08 13:47:24 lha Exp $"); +RCSID("$Id: crypto.c,v 1.145 2006/10/22 07:32:40 lha Exp $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -55,7 +55,6 @@ struct krb5_crypto_data { struct key_data key; int num_key_usage; struct key_usage *key_usage; - void *params; }; #define kcrypto_oid_enc(n) { sizeof(n)/sizeof(n[0]), n } @@ -89,13 +88,9 @@ struct key_type { krb5_enctype best_etype; #endif void (*random_key)(krb5_context, krb5_keyblock*); - void (*schedule)(krb5_context, struct key_data *, const void *); + void (*schedule)(krb5_context, struct key_data *); struct salt_type *string_to_key; void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t); - krb5_error_code (*get_params)(krb5_context, const krb5_data *, - void **, krb5_data *); - krb5_error_code (*set_params)(krb5_context, const void *, - const krb5_data *, krb5_data *); }; struct checksum_type { @@ -181,8 +176,7 @@ krb5_DES_random_key(krb5_context context, static void krb5_DES_schedule(krb5_context context, - struct key_data *key, - const void *params) + struct key_data *key) { DES_set_key(key->key->keyvalue.data, key->schedule->data); } @@ -392,8 +386,7 @@ DES3_random_key(krb5_context context, static void DES3_schedule(krb5_context context, - struct key_data *key, - const void *params) + struct key_data *key) { DES_cblock *k = key->key->keyvalue.data; DES_key_schedule *s = key->schedule->data; @@ -546,8 +539,7 @@ DES3_random_to_key(krb5_context context, static void ARCFOUR_schedule(krb5_context context, - struct key_data *kd, - const void *params) + struct key_data *kd) { RC4_set_key (kd->schedule->data, kd->key->keyvalue.length, kd->key->keyvalue.data); @@ -618,15 +610,16 @@ AES_string_to_key(krb5_context context, if (et == NULL) return KRB5_PROG_KEYTYPE_NOSUPP; - key->keytype = enctype; - ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); - if (ret) { - krb5_set_error_string(context, "Failed to allocate pkcs5 key"); - return ret; + kd.schedule = NULL; + ALLOC(kd.key, 1); + if(kd.key == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; } - ret = krb5_copy_keyblock(context, key, &kd.key); + kd.key->keytype = enctype; + ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); if (ret) { - krb5_free_keyblock(context, key); + krb5_set_error_string(context, "Failed to allocate pkcs5 key"); return ret; } @@ -634,8 +627,8 @@ AES_string_to_key(krb5_context context, salt.saltvalue.data, salt.saltvalue.length, iter, et->keytype->size, kd.key->keyvalue.data); - kd.schedule = NULL; if (ret != 1) { + free_key_data(context, &kd); krb5_set_error_string(context, "Error calculating s2k"); return KRB5_PROG_KEYTYPE_NOSUPP; } @@ -655,8 +648,7 @@ struct krb5_aes_schedule { static void AES_schedule(krb5_context context, - struct key_data *kd, - const void *params) + struct key_data *kd) { struct krb5_aes_schedule *key = kd->schedule->data; int bits = kd->key->keyvalue.length * 8; @@ -666,115 +658,6 @@ AES_schedule(krb5_context context, AES_set_decrypt_key(kd->key->keyvalue.data, bits, &key->dkey); } -/* - * RC2 - */ - -struct _RC2_params { - int maximum_effective_key; -}; - -static krb5_error_code -rc2_get_params(krb5_context context, - const krb5_data *data, - void **params, - krb5_data *ivec) -{ - RC2CBCParameter rc2params; - struct _RC2_params *p; - krb5_error_code ret; - size_t size; - - ret = decode_RC2CBCParameter(data->data, data->length, &rc2params, &size); - if (ret) { - krb5_set_error_string(context, "Can't decode RC2 parameters"); - return ret; - } - p = malloc(sizeof(*p)); - if (p == NULL) { - free_RC2CBCParameter(&rc2params); - krb5_set_error_string(context, "malloc - out of memory"); - return ENOMEM; - } - /* XXX */ - switch(rc2params.rc2ParameterVersion) { - case 160: - p->maximum_effective_key = 40; - break; - case 120: - p->maximum_effective_key = 64; - break; - case 58: - p->maximum_effective_key = 128; - break; - - } - if (ivec) - ret = copy_octet_string(&rc2params.iv, ivec); - free_RC2CBCParameter(&rc2params); - *params = p; - - return ret; -} - -static krb5_error_code -rc2_set_params(krb5_context context, - const void *params, - const krb5_data *ivec, - krb5_data *data) -{ - RC2CBCParameter rc2params; - const struct _RC2_params *p = params; - int maximum_effective_key = 128; - krb5_error_code ret; - size_t size; - - memset(&rc2params, 0, sizeof(rc2params)); - - if (p) - maximum_effective_key = p->maximum_effective_key; - - /* XXX */ - switch(maximum_effective_key) { - case 40: - rc2params.rc2ParameterVersion = 160; - break; - case 64: - rc2params.rc2ParameterVersion = 120; - break; - case 128: - rc2params.rc2ParameterVersion = 58; - break; - } - ret = copy_octet_string(ivec, &rc2params.iv); - if (ret) - return ret; - - ASN1_MALLOC_ENCODE(RC2CBCParameter, data->data, data->length, - &rc2params, &size, ret); - if (ret == 0 && size != data->length) - krb5_abortx(context, "Internal asn1 encoder failure"); - free_RC2CBCParameter(&rc2params); - - return ret; -} - -static void -rc2_schedule(krb5_context context, - struct key_data *kd, - const void *params) -{ - const struct _RC2_params *p = params; - int maximum_effective_key = 128; - if (p) - maximum_effective_key = p->maximum_effective_key; - RC2_set_key (kd->schedule->data, - kd->key->keyvalue.length, - kd->key->keyvalue.data, - maximum_effective_key); -} - - /* * */ @@ -898,18 +781,6 @@ static struct key_type keytype_aes128 = { AES_salt }; -static struct key_type keytype_aes192 = { - KEYTYPE_AES192, - "aes-192", - 192, - 24, - 24, - sizeof(struct krb5_aes_schedule), - NULL, - AES_schedule, - AES_salt -}; - static struct key_type keytype_aes256 = { KEYTYPE_AES256, "aes-256", @@ -934,30 +805,13 @@ static struct key_type keytype_arcfour = { arcfour_salt }; -static struct key_type keytype_rc2 = { - KEYTYPE_RC2, - "rc2", - 128, - 16, - 1, - sizeof(RC2_KEY), - NULL, - rc2_schedule, - NULL, /* XXX salt */ - NULL, - rc2_get_params, - rc2_set_params -}; - static struct key_type *keytypes[] = { &keytype_null, &keytype_des, &keytype_des3_derived, &keytype_des3, &keytype_aes128, - &keytype_aes192, &keytype_aes256, - &keytype_rc2, &keytype_arcfour }; @@ -1247,8 +1101,7 @@ krb5_generate_random_keyblock(krb5_context context, static krb5_error_code _key_schedule(krb5_context context, - struct key_data *key, - const void *params) + struct key_data *key) { krb5_error_code ret; struct encryption_type *et = _find_enctype(key->key->keytype); @@ -1269,7 +1122,7 @@ _key_schedule(krb5_context context, key->schedule = NULL; return ret; } - (*kt->schedule)(context, key, params); + (*kt->schedule)(context, key); return 0; } @@ -1933,7 +1786,7 @@ get_checksum_key(krb5_context context, *key = &crypto->key; } if(ret == 0) - ret = _key_schedule(context, *key, crypto->params); + ret = _key_schedule(context, *key); return ret; } @@ -2290,16 +2143,15 @@ DES_PCBC_encrypt_key_ivec(krb5_context context, void KRB5_LIB_FUNCTION _krb5_aes_cts_encrypt(const unsigned char *in, unsigned char *out, - size_t len, const void *aes_key, + size_t len, const AES_KEY *key, unsigned char *ivec, const int encryptp) { unsigned char tmp[AES_BLOCK_SIZE]; - const AES_KEY *key = aes_key; /* XXX remove this when we always have AES */ int i; /* * In the framework of kerberos, the length can never be shorter - * than at least one blocksize. + * then at least one blocksize. */ if (encryptp) { @@ -2838,7 +2690,7 @@ krb5_string_to_enctype(krb5_context context, } krb5_error_code KRB5_LIB_FUNCTION -krb5_enctype_to_oid(krb5_context context, +_krb5_enctype_to_oid(krb5_context context, krb5_enctype etype, heim_oid *oid) { @@ -2853,7 +2705,7 @@ krb5_enctype_to_oid(krb5_context context, return KRB5_PROG_ETYPE_NOSUPP; } krb5_clear_error_string(context); - return copy_oid(et->oid, oid); + return der_copy_oid(et->oid, oid); } krb5_error_code KRB5_LIB_FUNCTION @@ -2863,7 +2715,7 @@ _krb5_oid_to_enctype(krb5_context context, { int i; for(i = 0; i < num_etypes; i++) { - if(etypes[i]->oid && heim_oid_cmp(etypes[i]->oid, oid) == 0) { + if(etypes[i]->oid && der_heim_oid_cmp(etypes[i]->oid, oid) == 0) { *etype = etypes[i]->type; return 0; } @@ -3080,7 +2932,7 @@ encrypt_internal_derived(krb5_context context, ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); if(ret) goto fail; - ret = _key_schedule(context, dkey, crypto->params); + ret = _key_schedule(context, dkey); if(ret) goto fail; #ifdef CRYPTO_DEBUG @@ -3146,7 +2998,7 @@ encrypt_internal(krb5_context context, goto fail; memcpy(p + et->confoundersize, cksum.checksum.data, cksum.checksum.length); free_Checksum(&cksum); - ret = _key_schedule(context, &crypto->key, crypto->params); + ret = _key_schedule(context, &crypto->key); if(ret) goto fail; #ifdef CRYPTO_DEBUG @@ -3246,7 +3098,7 @@ decrypt_internal_derived(krb5_context context, free(p); return ret; } - ret = _key_schedule(context, dkey, crypto->params); + ret = _key_schedule(context, dkey); if(ret) { free(p); return ret; @@ -3313,7 +3165,7 @@ decrypt_internal(krb5_context context, } memcpy(p, data, len); - ret = _key_schedule(context, &crypto->key, crypto->params); + ret = _key_schedule(context, &crypto->key); if(ret) { free(p); return ret; @@ -3613,11 +3465,9 @@ derive_key(krb5_context context, unsigned char *k; unsigned int nblocks = 0, i; krb5_error_code ret = 0; - struct key_type *kt = et->keytype; - /* since RC2 is only the weird crypto alg with parameter and this - * function not defined with work with RC2, this is ok */ - ret = _key_schedule(context, key, NULL); + + ret = _key_schedule(context, key); if(ret) return ret; if(et->blocksize * 8 < kt->bits || @@ -3795,7 +3645,6 @@ krb5_crypto_init(krb5_context context, (*crypto)->key.schedule = NULL; (*crypto)->num_key_usage = 0; (*crypto)->key_usage = NULL; - (*crypto)->params = NULL; return 0; } @@ -3825,79 +3674,10 @@ krb5_crypto_destroy(krb5_context context, free_key_usage(context, &crypto->key_usage[i]); free(crypto->key_usage); free_key_data(context, &crypto->key); - free(crypto->params); free (crypto); return 0; } -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_get_params(krb5_context context, - const krb5_crypto crypto, - const krb5_data *params, - krb5_data *ivec) -{ - krb5_error_code (*gp)(krb5_context, const krb5_data *,void **,krb5_data *); - krb5_error_code ret; - - gp = crypto->et->keytype->get_params; - if (gp) { - if (crypto->params) { - krb5_set_error_string(context, - "krb5_crypto_get_params called " - "more than once"); - return KRB5_PROG_ETYPE_NOSUPP; - } - ret = (*gp)(context, params, &crypto->params, ivec); - } else { - size_t size; - if (ivec == NULL) - return 0; - ret = decode_CBCParameter(params->data, params->length, ivec, &size); - } - if (ret) - return ret; - if (ivec->length < crypto->et->blocksize) { - krb5_data_free(ivec); - krb5_set_error_string(context, "%s IV of wrong size", - crypto->et->name); - return ASN1_PARSE_ERROR; - } - return 0; -} - -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_set_params(krb5_context context, - const krb5_crypto crypto, - const krb5_data *ivec, - krb5_data *params) -{ - krb5_error_code (*sp)(krb5_context, const void *, - const krb5_data *, krb5_data *); - krb5_error_code ret; - - sp = crypto->et->keytype->set_params; - if (sp == NULL) { - size_t size; - if (ivec == NULL) - return 0; - ASN1_MALLOC_ENCODE(CBCParameter, params->data, params->length, - ivec, &size, ret); - if (ret) - return ret; - if (size != params->length) - krb5_abortx(context, "Internal asn1 encoder failure"); - return 0; - } - if (crypto->params) { - krb5_set_error_string(context, - "krb5_crypto_set_params called " - "more than once"); - return KRB5_PROG_ETYPE_NOSUPP; - } - return (*sp)(context, crypto->params, ivec, params); -} - - krb5_error_code KRB5_LIB_FUNCTION krb5_crypto_getblocksize(krb5_context context, krb5_crypto crypto, diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c index 3192c4c64f..f0c6d00abe 100644 --- a/source4/heimdal/lib/krb5/data.c +++ b/source4/heimdal/lib/krb5/data.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: data.c,v 1.20 2006/04/02 01:06:07 lha Exp $"); +RCSID("$Id: data.c,v 1.21 2006/10/14 09:45:41 lha Exp $"); void KRB5_LIB_FUNCTION krb5_data_zero(krb5_data *p) @@ -110,7 +110,7 @@ krb5_copy_data(krb5_context context, krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - ret = copy_octet_string(indata, *outdata); + ret = der_copy_octet_string(indata, *outdata); if(ret) { krb5_clear_error_string (context); free(*outdata); diff --git a/source4/heimdal/lib/krb5/expand_hostname.c b/source4/heimdal/lib/krb5/expand_hostname.c index f03bf15807..4d0692bcfa 100644 --- a/source4/heimdal/lib/krb5/expand_hostname.c +++ b/source4/heimdal/lib/krb5/expand_hostname.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: expand_hostname.c,v 1.12 2004/05/25 21:24:14 lha Exp $"); +RCSID("$Id: expand_hostname.c,v 1.13 2006/10/17 09:16:32 lha Exp $"); static krb5_error_code copy_hostname(krb5_context context, @@ -62,13 +62,12 @@ krb5_expand_hostname (krb5_context context, struct addrinfo *ai, *a, hints; int error; + if (!context->dns_canonicalize_hostname) + return copy_hostname (context, orig_hostname, new_hostname); + memset (&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; - if (!context->fdns) { - return copy_hostname (context, orig_hostname, new_hostname); - } - error = getaddrinfo (orig_hostname, NULL, &hints, &ai); if (error) return copy_hostname (context, orig_hostname, new_hostname); @@ -128,10 +127,9 @@ krb5_expand_hostname_realms (krb5_context context, int error; krb5_error_code ret = 0; - if (!context->fdns) { + if (!context->dns_canonicalize_hostname) return vanilla_hostname (context, orig_hostname, new_hostname, realms); - } memset (&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 1fa3f9143e..b404c30f6e 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_cred.c,v 1.109 2006/02/03 11:41:02 lha Exp $"); +RCSID("$Id: get_cred.c,v 1.112 2006/06/06 21:22:54 lha Exp $"); /* * Take the `body' and encode it into `padata' using the credentials @@ -142,6 +142,7 @@ init_tgs_req (krb5_context context, krb5_creds *in_creds, krb5_creds *krbtgt, unsigned nonce, + const METHOD_DATA *padata, krb5_keyblock **subkey, TGS_REQ *t, krb5_key_usage usage) @@ -220,12 +221,22 @@ init_tgs_req (krb5_context context, krb5_set_error_string(context, "malloc: out of memory"); goto fail; } - ALLOC_SEQ(t->padata, 1); + ALLOC_SEQ(t->padata, 1 + padata->len); if (t->padata->val == NULL) { ret = ENOMEM; krb5_set_error_string(context, "malloc: out of memory"); goto fail; } + { + int i; + for (i = 0; i < padata->len; i++) { + ret = copy_PA_DATA(&padata->val[i], &t->padata->val[i + 1]); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + goto fail; + } + } + } { krb5_auth_context ac; @@ -268,7 +279,7 @@ init_tgs_req (krb5_context context, ret = make_pa_tgs_req(context, ac, &t->req_body, - t->padata->val, + &t->padata->val[0], krbtgt, usage); if(ret) { @@ -383,8 +394,10 @@ get_cred_kdc_usage(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, krb5_addresses *addresses, - krb5_creds *in_creds, + krb5_creds *in_creds, krb5_creds *krbtgt, + krb5_principal impersonate_principal, + Ticket *second_ticket, krb5_creds *out_creds, krb5_key_usage usage) { @@ -397,36 +410,91 @@ get_cred_kdc_usage(krb5_context context, unsigned nonce; krb5_keyblock *subkey = NULL; size_t len; - Ticket second_ticket; + Ticket second_ticket_data; int send_to_kdc_flags = 0; + METHOD_DATA padata; krb5_data_zero(&resp); krb5_data_zero(&enc); + padata.val = NULL; + padata.len = 0; krb5_generate_random_block(&nonce, sizeof(nonce)); nonce &= 0xffffffff; - if(flags.b.enc_tkt_in_skey){ + if(flags.b.enc_tkt_in_skey && second_ticket == NULL){ ret = decode_Ticket(in_creds->second_ticket.data, in_creds->second_ticket.length, - &second_ticket, &len); + &second_ticket_data, &len); if(ret) return ret; + second_ticket = &second_ticket_data; + } + + + if (impersonate_principal) { + krb5_crypto crypto; + PA_S4U2Self self; + krb5_data data; + void *buf; + size_t size; + + self.name = impersonate_principal->name; + self.realm = impersonate_principal->realm; + self.auth = estrdup("Kerberos"); + + ret = _krb5_s4u2self_to_checksumdata(context, &self, &data); + if (ret) { + free(self.auth); + goto out; + } + + ret = krb5_crypto_init(context, &krbtgt->session, 0, &crypto); + if (ret) { + free(self.auth); + krb5_data_free(&data); + goto out; + } + + ret = krb5_create_checksum(context, + crypto, + KRB5_KU_TGS_IMPERSONATE, + 0, + data.data, + data.length, + &self.cksum); + krb5_crypto_destroy(context, crypto); + krb5_data_free(&data); + if (ret) { + free(self.auth); + goto out; + } + + ASN1_MALLOC_ENCODE(PA_S4U2Self, buf, len, &self, &size, ret); + free(self.auth); + free_Checksum(&self.cksum); + if (ret) + goto out; + if (len != size) + krb5_abortx(context, "internal asn1 error"); + + ret = krb5_padata_add(context, &padata, KRB5_PADATA_S4U2SELF, buf, len); + if (ret) + goto out; } ret = init_tgs_req (context, id, addresses, flags, - flags.b.enc_tkt_in_skey ? &second_ticket : NULL, + second_ticket, in_creds, krbtgt, nonce, + &padata, &subkey, &req, usage); - if(flags.b.enc_tkt_in_skey) - free_Ticket(&second_ticket); if (ret) goto out; @@ -475,7 +543,7 @@ again: &krbtgt->addresses, nonce, TRUE, - flags.b.request_anonymous, + TRUE /* flags.b.request_anonymous */, decrypt_tkt_with_subkey, subkey); krb5_free_kdc_rep(context, &rep); @@ -497,6 +565,9 @@ again: } out: + if (second_ticket == &second_ticket_data) + free_Ticket(&second_ticket_data); + free_METHOD_DATA(&padata); krb5_data_free(&resp); krb5_data_free(&enc); if(subkey){ @@ -514,16 +585,20 @@ get_cred_kdc(krb5_context context, krb5_addresses *addresses, krb5_creds *in_creds, krb5_creds *krbtgt, + krb5_principal impersonate_principal, + Ticket *second_ticket, krb5_creds *out_creds) { krb5_error_code ret; ret = get_cred_kdc_usage(context, id, flags, addresses, in_creds, - krbtgt, out_creds, KRB5_KU_TGS_REQ_AUTH); + krbtgt, impersonate_principal, second_ticket, + out_creds, KRB5_KU_TGS_REQ_AUTH); if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { krb5_clear_error_string (context); ret = get_cred_kdc_usage(context, id, flags, addresses, in_creds, - krbtgt, out_creds, KRB5_KU_AP_REQ_AUTH); + krbtgt, impersonate_principal, second_ticket, + out_creds, KRB5_KU_AP_REQ_AUTH); } return ret; } @@ -533,6 +608,7 @@ get_cred_kdc(krb5_context context, static krb5_error_code get_cred_kdc_la(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, krb5_creds *in_creds, krb5_creds *krbtgt, + krb5_principal impersonate_principal, Ticket *second_ticket, krb5_creds *out_creds) { krb5_error_code ret; @@ -543,7 +619,8 @@ get_cred_kdc_la(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, if(addresses.len == 0) addrs = NULL; ret = get_cred_kdc(context, id, flags, addrs, - in_creds, krbtgt, out_creds); + in_creds, krbtgt, impersonate_principal, second_ticket, + out_creds); krb5_free_addresses(context, &addresses); return ret; } @@ -575,7 +652,7 @@ krb5_get_kdc_cred(krb5_context context, return ret; } ret = get_cred_kdc(context, id, flags, addresses, - in_creds, krbtgt, *out_creds); + in_creds, krbtgt, NULL, NULL, *out_creds); krb5_free_creds (context, krbtgt); if(ret) free(*out_creds); @@ -607,7 +684,17 @@ find_cred(krb5_context context, } tgts++; } - krb5_clear_error_string(context); + { + char *str; + ret = krb5_unparse_name(context, server, &str); + if(ret == 0) { + krb5_set_error_string(context, "Matching credential " + "(%s) not found", str); + free(str); + } else { + krb5_clear_error_string(context); + } + } return KRB5_CC_NOTFOUND; } @@ -650,6 +737,8 @@ get_cred_from_kdc_flags(krb5_context context, krb5_kdc_flags flags, krb5_ccache ccache, krb5_creds *in_creds, + krb5_principal impersonate_principal, + Ticket *second_ticket, krb5_creds **out_creds, krb5_creds ***ret_tgts) { @@ -707,10 +796,16 @@ get_cred_from_kdc_flags(krb5_context context, if (noaddr) ret = get_cred_kdc(context, ccache, flags, NULL, - in_creds, &tgts, *out_creds); + in_creds, &tgts, + impersonate_principal, + second_ticket, + *out_creds); else ret = get_cred_kdc_la(context, ccache, flags, - in_creds, &tgts, *out_creds); + in_creds, &tgts, + impersonate_principal, + second_ticket, + *out_creds); if (ret) { free (*out_creds); *out_creds = NULL; @@ -731,7 +826,7 @@ get_cred_from_kdc_flags(krb5_context context, heim_general_string tgt_inst; ret = get_cred_from_kdc_flags(context, flags, ccache, &tmp_creds, - &tgt, ret_tgts); + NULL, NULL, &tgt, ret_tgts); if(ret) { krb5_free_principal(context, tmp_creds.server); krb5_free_principal(context, tmp_creds.client); @@ -776,10 +871,12 @@ get_cred_from_kdc_flags(krb5_context context, &noaddr); if (noaddr) ret = get_cred_kdc (context, ccache, flags, NULL, - in_creds, tgt, *out_creds); + in_creds, tgt, NULL, NULL, + *out_creds); else ret = get_cred_kdc_la(context, ccache, flags, - in_creds, tgt, *out_creds); + in_creds, tgt, NULL, NULL, + *out_creds); if (ret) { free (*out_creds); *out_creds = NULL; @@ -800,7 +897,8 @@ krb5_get_cred_from_kdc_opt(krb5_context context, krb5_kdc_flags f; f.i = flags; return get_cred_from_kdc_flags(context, f, ccache, - in_creds, out_creds, ret_tgts); + in_creds, NULL, NULL, + out_creds, ret_tgts); } krb5_error_code KRB5_LIB_FUNCTION @@ -879,15 +977,18 @@ krb5_get_credentials_with_flags(krb5_context context, } if(options & KRB5_GC_USER_USER) flags.b.enc_tkt_in_skey = 1; + if (flags.b.enc_tkt_in_skey) + options |= KRB5_GC_NO_STORE; + tgts = NULL; ret = get_cred_from_kdc_flags(context, flags, ccache, - in_creds, out_creds, &tgts); + in_creds, NULL, NULL, out_creds, &tgts); for(i = 0; tgts && tgts[i]; i++) { krb5_cc_store_cred(context, ccache, tgts[i]); krb5_free_creds(context, tgts[i]); } free(tgts); - if(ret == 0 && flags.b.enc_tkt_in_skey == 0) + if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) krb5_cc_store_cred(context, ccache, *out_creds); return ret; } @@ -904,3 +1005,200 @@ krb5_get_credentials(krb5_context context, return krb5_get_credentials_with_flags(context, options, flags, ccache, in_creds, out_creds); } + +struct krb5_get_creds_opt_data { + krb5_principal self; + krb5_flags options; + krb5_enctype enctype; + Ticket *ticket; +}; + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_alloc(krb5_context context, krb5_get_creds_opt *opt) +{ + *opt = calloc(1, sizeof(**opt)); + if (*opt == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_free(krb5_context context, krb5_get_creds_opt opt) +{ + if (opt->self) + krb5_free_principal(context, opt->self); + memset(opt, 0, sizeof(*opt)); + free(opt); +} + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_options(krb5_context context, + krb5_get_creds_opt opt, + krb5_flags options) +{ + opt->options = options; +} + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_add_options(krb5_context context, + krb5_get_creds_opt opt, + krb5_flags options) +{ + opt->options |= options; +} + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_enctype(krb5_context context, + krb5_get_creds_opt opt, + krb5_enctype enctype) +{ + opt->enctype = enctype; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_impersonate(krb5_context context, + krb5_get_creds_opt opt, + krb5_const_principal self) +{ + if (opt->self) + krb5_free_principal(context, opt->self); + return krb5_copy_principal(context, self, &opt->self); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_ticket(krb5_context context, + krb5_get_creds_opt opt, + const Ticket *ticket) +{ + if (opt->ticket) { + free_Ticket(opt->ticket); + free(opt->ticket); + opt->ticket = NULL; + } + if (ticket) { + krb5_error_code ret; + + opt->ticket = malloc(sizeof(*ticket)); + if (opt->ticket == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = copy_Ticket(ticket, opt->ticket); + if (ret) { + free(opt->ticket); + opt->ticket = NULL; + krb5_set_error_string(context, "malloc: out of memory"); + return ret; + } + } + return 0; +} + + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds(krb5_context context, + krb5_get_creds_opt opt, + krb5_ccache ccache, + krb5_const_principal inprinc, + krb5_creds **out_creds) +{ + krb5_kdc_flags flags; + krb5_flags options; + krb5_creds in_creds; + krb5_error_code ret; + krb5_creds **tgts; + krb5_creds *res_creds; + int i; + + memset(&in_creds, 0, sizeof(in_creds)); + in_creds.server = rk_UNCONST(inprinc); + + ret = krb5_cc_get_principal(context, ccache, &in_creds.client); + if (ret) + return ret; + + options = opt->options; + flags.i = 0; + + *out_creds = NULL; + res_creds = calloc(1, sizeof(*res_creds)); + if (res_creds == NULL) { + krb5_free_principal(context, in_creds.client); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + + if (opt->enctype) { + in_creds.session.keytype = opt->enctype; + options |= KRB5_TC_MATCH_KEYTYPE; + } + + /* + * If we got a credential, check if credential is expired before + * returning it. + */ + ret = krb5_cc_retrieve_cred(context, + ccache, + opt->enctype ? KRB5_TC_MATCH_KEYTYPE : 0, + &in_creds, res_creds); + /* + * If we got a credential, check if credential is expired before + * returning it, but only if KRB5_GC_EXPIRED_OK is not set. + */ + if (ret == 0) { + krb5_timestamp timeret; + + /* If expired ok, don't bother checking */ + if(options & KRB5_GC_EXPIRED_OK) { + *out_creds = res_creds; + krb5_free_principal(context, in_creds.client); + return 0; + } + + krb5_timeofday(context, &timeret); + if(res_creds->times.endtime > timeret) { + *out_creds = res_creds; + krb5_free_principal(context, in_creds.client); + return 0; + } + if(options & KRB5_GC_CACHED) + krb5_cc_remove_cred(context, ccache, 0, res_creds); + + } else if(ret != KRB5_CC_END) { + free(res_creds); + krb5_free_principal(context, in_creds.client); + return ret; + } + free(res_creds); + if(options & KRB5_GC_CACHED) { + krb5_clear_error_string (context); + krb5_free_principal(context, in_creds.client); + return KRB5_CC_NOTFOUND; + } + if(options & KRB5_GC_USER_USER) { + flags.b.enc_tkt_in_skey = 1; + options |= KRB5_GC_NO_STORE; + } + if (options & KRB5_GC_FORWARDABLE) + flags.b.forwardable = 1; + if (options & KRB5_GC_NO_TRANSIT_CHECK) + flags.b.disable_transited_check = 1; + + tgts = NULL; + ret = get_cred_from_kdc_flags(context, flags, ccache, + &in_creds, opt->self, opt->ticket, + out_creds, &tgts); + krb5_free_principal(context, in_creds.client); + for(i = 0; tgts && tgts[i]; i++) { + krb5_cc_store_cred(context, ccache, tgts[i]); + krb5_free_creds(context, tgts[i]); + } + free(tgts); + if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0) + krb5_cc_store_cred(context, ccache, *out_creds); + return ret; +} diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index f042cdb573..661d05663b 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -376,7 +376,7 @@ krb5_get_forwarded_creds (krb5_context context, cred.enc_part.cipher.length = buf_size; } else { /* - * Here older versions than 0.7.2 of Heimdal used the local or + * Here older versions then 0.7.2 of Heimdal used the local or * remote subkey. That is wrong, the session key should be * used. Heimdal 0.7.2 and newer have code to try both in the * receiving end. diff --git a/source4/heimdal/lib/krb5/get_host_realm.c b/source4/heimdal/lib/krb5/get_host_realm.c index 33a3438b12..ffc646d98b 100644 --- a/source4/heimdal/lib/krb5/get_host_realm.c +++ b/source4/heimdal/lib/krb5/get_host_realm.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: get_host_realm.c,v 1.35 2005/08/23 08:14:02 lha Exp $"); +RCSID("$Id: get_host_realm.c,v 1.37 2006/10/17 19:28:36 lha Exp $"); /* To automagically find the correct realm of a host (without * [domain_realm] in krb5.conf) add a text record for your domain with @@ -187,65 +187,71 @@ _krb5_get_host_realm_int (krb5_context context, return 0; } } - - *realms = malloc(2 * sizeof(krb5_realm)); - if (*realms == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - - (*realms)[1] = NULL; - p = strchr(host, '.'); if(p != NULL) { p++; - (*realms)[0] = strdup(p); - if((*realms)[0] == NULL) { - free(*realms); + *realms = malloc(2 * sizeof(krb5_realm)); + if (*realms == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - strupr((*realms)[0]); - } else { - krb5_error_code ret; - ret = krb5_get_default_realm(context, &(*realms)[0]); - if(ret) { + + (*realms)[0] = strdup(p); + if((*realms)[0] == NULL) { free(*realms); krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - if((*realms)[0] == NULL) { - free(*realms); - krb5_set_error_string(context, "unable to find realm of host %s", host); - return KRB5_ERR_HOST_REALM_UNKNOWN; - } + strupr((*realms)[0]); + (*realms)[1] = NULL; + return 0; } - return 0; + krb5_set_error_string(context, "unable to find realm of host %s", host); + return KRB5_ERR_HOST_REALM_UNKNOWN; } /* - * Return the realm(s) of `host' as a NULL-terminated list in `realms'. + * Return the realm(s) of `host' as a NULL-terminated list in + * `realms'. Free `realms' with krb5_free_host_realm(). */ krb5_error_code KRB5_LIB_FUNCTION krb5_get_host_realm(krb5_context context, - const char *host, + const char *targethost, krb5_realm **realms) { + const char *host = targethost; char hostname[MAXHOSTNAMELEN]; - krb5_boolean use_dns; + krb5_error_code ret; + int use_dns; if (host == NULL) { - if (gethostname (hostname, sizeof(hostname))) + if (gethostname (hostname, sizeof(hostname))) { + *realms = NULL; return errno; + } host = hostname; } - if (strchr(host, '.') == NULL) { - use_dns = FALSE; - } else { - use_dns = TRUE; - } + /* + * If our local hostname is without components, don't even try to dns. + */ + + use_dns = (strchr(host, '.') != NULL); - return _krb5_get_host_realm_int (context, host, use_dns, realms); + ret = _krb5_get_host_realm_int (context, host, use_dns, realms); + if (ret && targethost != NULL) { + /* + * If there was no realm mapping for the host (and we wasn't + * looking for ourself), guess at the local realm, maybe our + * KDC knows better then we do and we get a referral back. + */ + ret = krb5_get_default_realms(context, realms); + if (ret) { + krb5_set_error_string(context, "Unable to find realm of host %s", + host); + return KRB5_ERR_HOST_REALM_UNKNOWN; + } + } + return ret; } diff --git a/source4/heimdal/lib/krb5/get_in_tkt.c b/source4/heimdal/lib/krb5/get_in_tkt.c index 5c488d1ddc..ebc96f2279 100644 --- a/source4/heimdal/lib/krb5/get_in_tkt.c +++ b/source4/heimdal/lib/krb5/get_in_tkt.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_in_tkt.c,v 1.116 2005/06/15 02:53:20 lha Exp $"); +RCSID("$Id: get_in_tkt.c,v 1.119 2006/10/06 17:05:08 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_init_etype (krb5_context context, @@ -137,7 +137,7 @@ _krb5_extract_ticket(krb5_context context, time_t tmp_time; krb5_timestamp sec_now; - ret = _krb5_principalname2krb5_principal (context, + ret = _krb5_principalname2krb5_principal (context, &tmp_principal, rep->kdc_rep.cname, rep->kdc_rep.crealm); @@ -171,7 +171,7 @@ _krb5_extract_ticket(krb5_context context, /* compare server */ - ret = _krb5_principalname2krb5_principal (context, + ret = _krb5_principalname2krb5_principal (context, &tmp_principal, rep->kdc_rep.ticket.sname, rep->kdc_rep.ticket.realm); @@ -411,7 +411,7 @@ add_padata(krb5_context context, static krb5_error_code init_as_req (krb5_context context, - krb5_kdc_flags opts, + KDCOptions opts, krb5_creds *creds, const krb5_addresses *addrs, const krb5_enctype *etypes, @@ -429,7 +429,7 @@ init_as_req (krb5_context context, a->pvno = 5; a->msg_type = krb_as_req; - a->req_body.kdc_options = opts.b; + a->req_body.kdc_options = opts; a->req_body.cname = malloc(sizeof(*a->req_body.cname)); if (a->req_body.cname == NULL) { ret = ENOMEM; @@ -649,14 +649,14 @@ krb5_get_in_cred(krb5_context context, krb5_salt salt; krb5_keyblock *key; size_t size; - krb5_kdc_flags opts; + KDCOptions opts; PA_DATA *pa; krb5_enctype etype; krb5_preauthdata *my_preauth = NULL; unsigned nonce; int done; - opts.i = options; + opts = int2KDCOptions(options); krb5_generate_random_block (&nonce, sizeof(nonce)); nonce &= 0xffffffff; @@ -771,7 +771,7 @@ krb5_get_in_cred(krb5_context context, NULL, nonce, FALSE, - opts.b.request_anonymous, + opts.request_anonymous, decrypt_proc, decryptarg); memset (key->keyvalue.data, 0, key->keyvalue.length); @@ -801,12 +801,9 @@ krb5_get_in_tkt(krb5_context context, krb5_kdc_rep *ret_as_reply) { krb5_error_code ret; - krb5_kdc_flags opts; - opts.i = 0; - opts.b = int2KDCOptions(options); ret = krb5_get_in_cred (context, - opts.i, + options, addrs, etypes, ptypes, diff --git a/source4/heimdal/lib/krb5/heim_err.c b/source4/heimdal/lib/krb5/heim_err.c new file mode 100644 index 0000000000..f72a265ba9 --- /dev/null +++ b/source4/heimdal/lib/krb5/heim_err.c @@ -0,0 +1,162 @@ +/* Generated from heim_err.et */ +/* $Id: heim_err.et,v 1.13 2004/02/13 16:23:40 lha Exp $ */ + +#include +#include +#include "heim_err.h" + +static const char *heim_error_strings[] = { + /* 000 */ "Error parsing log destination", + /* 001 */ "Failed to convert v4 principal", + /* 002 */ "Salt type is not supported by enctype", + /* 003 */ "Host not found", + /* 004 */ "Operation not supported", + /* 005 */ "End of file", + /* 006 */ "Failed to get the master key", + /* 007 */ "Unacceptable service used", + /* 008 */ "Reserved heim error (8)", + /* 009 */ "Reserved heim error (9)", + /* 010 */ "Reserved heim error (10)", + /* 011 */ "Reserved heim error (11)", + /* 012 */ "Reserved heim error (12)", + /* 013 */ "Reserved heim error (13)", + /* 014 */ "Reserved heim error (14)", + /* 015 */ "Reserved heim error (15)", + /* 016 */ "Reserved heim error (16)", + /* 017 */ "Reserved heim error (17)", + /* 018 */ "Reserved heim error (18)", + /* 019 */ "Reserved heim error (19)", + /* 020 */ "Reserved heim error (20)", + /* 021 */ "Reserved heim error (21)", + /* 022 */ "Reserved heim error (22)", + /* 023 */ "Reserved heim error (23)", + /* 024 */ "Reserved heim error (24)", + /* 025 */ "Reserved heim error (25)", + /* 026 */ "Reserved heim error (26)", + /* 027 */ "Reserved heim error (27)", + /* 028 */ "Reserved heim error (28)", + /* 029 */ "Reserved heim error (29)", + /* 030 */ "Reserved heim error (30)", + /* 031 */ "Reserved heim error (31)", + /* 032 */ "Reserved heim error (32)", + /* 033 */ "Reserved heim error (33)", + /* 034 */ "Reserved heim error (34)", + /* 035 */ "Reserved heim error (35)", + /* 036 */ "Reserved heim error (36)", + /* 037 */ "Reserved heim error (37)", + /* 038 */ "Reserved heim error (38)", + /* 039 */ "Reserved heim error (39)", + /* 040 */ "Reserved heim error (40)", + /* 041 */ "Reserved heim error (41)", + /* 042 */ "Reserved heim error (42)", + /* 043 */ "Reserved heim error (43)", + /* 044 */ "Reserved heim error (44)", + /* 045 */ "Reserved heim error (45)", + /* 046 */ "Reserved heim error (46)", + /* 047 */ "Reserved heim error (47)", + /* 048 */ "Reserved heim error (48)", + /* 049 */ "Reserved heim error (49)", + /* 050 */ "Reserved heim error (50)", + /* 051 */ "Reserved heim error (51)", + /* 052 */ "Reserved heim error (52)", + /* 053 */ "Reserved heim error (53)", + /* 054 */ "Reserved heim error (54)", + /* 055 */ "Reserved heim error (55)", + /* 056 */ "Reserved heim error (56)", + /* 057 */ "Reserved heim error (57)", + /* 058 */ "Reserved heim error (58)", + /* 059 */ "Reserved heim error (59)", + /* 060 */ "Reserved heim error (60)", + /* 061 */ "Reserved heim error (61)", + /* 062 */ "Reserved heim error (62)", + /* 063 */ "Reserved heim error (63)", + /* 064 */ "Certificate missing", + /* 065 */ "Private key missing", + /* 066 */ "No valid certificate authority", + /* 067 */ "Certificate invalid", + /* 068 */ "Private key invalid", + /* 069 */ "Reserved heim error (69)", + /* 070 */ "Reserved heim error (70)", + /* 071 */ "Reserved heim error (71)", + /* 072 */ "Reserved heim error (72)", + /* 073 */ "Reserved heim error (73)", + /* 074 */ "Reserved heim error (74)", + /* 075 */ "Reserved heim error (75)", + /* 076 */ "Reserved heim error (76)", + /* 077 */ "Reserved heim error (77)", + /* 078 */ "Reserved heim error (78)", + /* 079 */ "Reserved heim error (79)", + /* 080 */ "Reserved heim error (80)", + /* 081 */ "Reserved heim error (81)", + /* 082 */ "Reserved heim error (82)", + /* 083 */ "Reserved heim error (83)", + /* 084 */ "Reserved heim error (84)", + /* 085 */ "Reserved heim error (85)", + /* 086 */ "Reserved heim error (86)", + /* 087 */ "Reserved heim error (87)", + /* 088 */ "Reserved heim error (88)", + /* 089 */ "Reserved heim error (89)", + /* 090 */ "Reserved heim error (90)", + /* 091 */ "Reserved heim error (91)", + /* 092 */ "Reserved heim error (92)", + /* 093 */ "Reserved heim error (93)", + /* 094 */ "Reserved heim error (94)", + /* 095 */ "Reserved heim error (95)", + /* 096 */ "Reserved heim error (96)", + /* 097 */ "Reserved heim error (97)", + /* 098 */ "Reserved heim error (98)", + /* 099 */ "Reserved heim error (99)", + /* 100 */ "Reserved heim error (100)", + /* 101 */ "Reserved heim error (101)", + /* 102 */ "Reserved heim error (102)", + /* 103 */ "Reserved heim error (103)", + /* 104 */ "Reserved heim error (104)", + /* 105 */ "Reserved heim error (105)", + /* 106 */ "Reserved heim error (106)", + /* 107 */ "Reserved heim error (107)", + /* 108 */ "Reserved heim error (108)", + /* 109 */ "Reserved heim error (109)", + /* 110 */ "Reserved heim error (110)", + /* 111 */ "Reserved heim error (111)", + /* 112 */ "Reserved heim error (112)", + /* 113 */ "Reserved heim error (113)", + /* 114 */ "Reserved heim error (114)", + /* 115 */ "Reserved heim error (115)", + /* 116 */ "Reserved heim error (116)", + /* 117 */ "Reserved heim error (117)", + /* 118 */ "Reserved heim error (118)", + /* 119 */ "Reserved heim error (119)", + /* 120 */ "Reserved heim error (120)", + /* 121 */ "Reserved heim error (121)", + /* 122 */ "Reserved heim error (122)", + /* 123 */ "Reserved heim error (123)", + /* 124 */ "Reserved heim error (124)", + /* 125 */ "Reserved heim error (125)", + /* 126 */ "Reserved heim error (126)", + /* 127 */ "Reserved heim error (127)", + /* 128 */ "unknown error from getaddrinfo", + /* 129 */ "address family for nodename not supported", + /* 130 */ "temporary failure in name resolution", + /* 131 */ "invalid value for ai_flags", + /* 132 */ "non-recoverable failure in name resolution", + /* 133 */ "ai_family not supported", + /* 134 */ "memory allocation failure", + /* 135 */ "no address associated with nodename", + /* 136 */ "nodename nor servname provided, or not known", + /* 137 */ "servname not supported for ai_socktype", + /* 138 */ "ai_socktype not supported", + /* 139 */ "system error returned in errno", + NULL +}; + +#define num_errors 140 + +void initialize_heim_error_table_r(struct et_list **list) +{ + initialize_error_table_r(list, heim_error_strings, num_errors, ERROR_TABLE_BASE_heim); +} + +void initialize_heim_error_table(void) +{ + init_error_table(heim_error_strings, ERROR_TABLE_BASE_heim, num_errors); +} diff --git a/source4/heimdal/lib/krb5/heim_threads.h b/source4/heimdal/lib/krb5/heim_threads.h index 41f0f83306..3ebe66beee 100755 --- a/source4/heimdal/lib/krb5/heim_threads.h +++ b/source4/heimdal/lib/krb5/heim_threads.h @@ -53,7 +53,7 @@ /* * NetBSD have a thread lib that we can use that part of libc that * works regardless if application are linked to pthreads or not. - * NetBSD newer than 2.99.11 just use pthread.h, and the same thing + * NetBSD newer then 2.99.11 just use pthread.h, and the same thing * will happen. */ #include diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index 88de280a00..6dacb316d8 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c,v 1.23 2006/04/02 01:08:30 lha Exp $"); +RCSID("$Id: init_creds.c,v 1.28 2006/09/04 14:28:54 lha Exp $"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) @@ -96,6 +96,39 @@ _krb5_get_init_creds_opt_copy(krb5_context context, return 0; } +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_free_krb5_error(krb5_get_init_creds_opt *opt) +{ + if (opt->opt_private == NULL || opt->opt_private->error == NULL) + return; + free_KRB_ERROR(opt->opt_private->error); + free(opt->opt_private->error); + opt->opt_private->error = NULL; +} + +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_set_krb5_error(krb5_context context, + krb5_get_init_creds_opt *opt, + const KRB_ERROR *error) +{ + krb5_error_code ret; + + if (opt->opt_private == NULL) + return; + + _krb5_get_init_creds_opt_free_krb5_error(opt); + + opt->opt_private->error = malloc(sizeof(*opt->opt_private->error)); + if (opt->opt_private->error == NULL) + return; + ret = copy_KRB_ERROR(error, opt->opt_private->error); + if (ret) { + free(opt->opt_private->error); + opt->opt_private->error = NULL; + } +} + + void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt) { @@ -104,6 +137,7 @@ krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt) if (opt->opt_private->refcount < 1) /* abort ? */ return; if (--opt->opt_private->refcount == 0) { + _krb5_get_init_creds_opt_free_krb5_error(opt); _krb5_get_init_creds_opt_free_pkinit(opt); free(opt->opt_private); } @@ -160,8 +194,6 @@ get_config_bool (krb5_context context, * [realms] or [libdefaults] for some of the values. */ -static krb5_addresses no_addrs = {0, NULL}; - void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_set_default_flags(krb5_context context, const char *appname, @@ -192,9 +224,9 @@ krb5_get_init_creds_opt_set_default_flags(krb5_context context, krb5_get_init_creds_opt_set_renew_life(opt, t); krb5_appdefault_boolean(context, appname, realm, "no-addresses", - KRB5_ADDRESSLESS_DEFAULT, &b); + FALSE, &b); if (b) - krb5_get_init_creds_opt_set_address_list (opt, &no_addrs); + krb5_get_init_creds_opt_set_addressless (context, opt, TRUE); #if 0 krb5_appdefault_boolean(context, appname, realm, "anonymous", FALSE, &b); @@ -326,7 +358,52 @@ krb5_get_init_creds_opt_set_pac_request(krb5_context context, if (ret) return ret; opt->opt_private->req_pac = req_pac ? - KRB5_PA_PAC_REQ_TRUE : - KRB5_PA_PAC_REQ_FALSE; + KRB5_INIT_CREDS_TRISTATE_TRUE : + KRB5_INIT_CREDS_TRISTATE_FALSE; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_get_error(krb5_context context, + krb5_get_init_creds_opt *opt, + KRB_ERROR **error) +{ + krb5_error_code ret; + + *error = NULL; + + ret = require_ext_opt(context, opt, "init_creds_opt_get_error"); + if (ret) + return ret; + + if (opt->opt_private->error == NULL) + return 0; + + *error = malloc(sizeof(**error)); + if (*error == NULL) { + krb5_set_error_string(context, "malloc - out memory"); + return ENOMEM; + } + + ret = copy_KRB_ERROR(*error, opt->opt_private->error); + if (ret) + krb5_clear_error_string(context); + + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_addressless(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_boolean addressless) +{ + krb5_error_code ret; + ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req"); + if (ret) + return ret; + if (addressless) + opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_TRUE; + else + opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_FALSE; return 0; } diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index c05386ec23..d43ae0ae6f 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,10 +33,10 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c,v 1.94 2006/04/24 08:49:08 lha Exp $"); +RCSID("$Id: init_creds_pw.c,v 1.101 2006/10/02 12:00:59 lha Exp $"); typedef struct krb5_get_init_creds_ctx { - krb5_kdc_flags flags; + KDCOptions flags; krb5_creds cred; krb5_addresses *addrs; krb5_enctype *etypes; @@ -52,7 +52,7 @@ typedef struct krb5_get_init_creds_ctx { const char *password; krb5_s2k_proc key_proc; - krb5_get_init_creds_req_pac req_pac; + krb5_get_init_creds_tristate req_pac; krb5_pk_init_ctx pk_init_ctx; } krb5_get_init_creds_ctx; @@ -256,9 +256,10 @@ print_expire (krb5_context context, } } +static krb5_addresses no_addrs = { 0, NULL }; + static krb5_error_code get_init_creds_common(krb5_context context, - krb5_creds *creds, krb5_principal client, krb5_deltat start_time, const char *in_tkt_service, @@ -275,6 +276,8 @@ get_init_creds_common(krb5_context context, if (options == NULL) { krb5_get_init_creds_opt_init (&default_opt); options = &default_opt; + } else { + _krb5_get_init_creds_opt_free_krb5_error(options); } if (options->opt_private) { @@ -283,13 +286,12 @@ get_init_creds_common(krb5_context context, ctx->req_pac = options->opt_private->req_pac; ctx->pk_init_ctx = options->opt_private->pk_init_ctx; } else - ctx->req_pac = KRB5_PA_PAC_DONT_CARE; + ctx->req_pac = KRB5_INIT_CREDS_TRISTATE_UNSET; if (ctx->key_proc == NULL) ctx->key_proc = default_s2k_func; ctx->pre_auth_types = NULL; - ctx->flags.i = 0; ctx->addrs = NULL; ctx->etypes = NULL; ctx->pre_auth_types = NULL; @@ -300,20 +302,35 @@ get_init_creds_common(krb5_context context, if (ret) return ret; - ctx->flags.i = 0; - if (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE) - ctx->flags.b.forwardable = options->forwardable; + ctx->flags.forwardable = options->forwardable; if (options->flags & KRB5_GET_INIT_CREDS_OPT_PROXIABLE) - ctx->flags.b.proxiable = options->proxiable; + ctx->flags.proxiable = options->proxiable; if (start_time) - ctx->flags.b.postdated = 1; + ctx->flags.postdated = 1; if (ctx->cred.times.renew_till) - ctx->flags.b.renewable = 1; - if (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST) + ctx->flags.renewable = 1; + if (options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST) { ctx->addrs = options->address_list; + } else if (options->opt_private) { + switch (options->opt_private->addressless) { + case KRB5_INIT_CREDS_TRISTATE_UNSET: +#if KRB5_ADDRESSLESS_DEFAULT == TRUE + ctx->addrs = &no_addrs; +#else + ctx->addrs = NULL; +#endif + break; + case KRB5_INIT_CREDS_TRISTATE_FALSE: + ctx->addrs = NULL; + break; + case KRB5_INIT_CREDS_TRISTATE_TRUE: + ctx->addrs = &no_addrs; + break; + } + } if (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST) { etypes = malloc((options->etype_list_length + 1) * sizeof(krb5_enctype)); @@ -341,7 +358,7 @@ get_init_creds_common(krb5_context context, if (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT) ; /* XXX */ if (options->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS) - ctx->flags.b.request_anonymous = options->anonymous; + ctx->flags.request_anonymous = options->anonymous; return 0; } @@ -478,7 +495,7 @@ krb5_get_init_creds_keytab(krb5_context context, krb5_error_code ret; krb5_keytab_key_proc_args *a; - ret = get_init_creds_common(context, creds, client, start_time, + ret = get_init_creds_common(context, client, start_time, in_tkt_service, options, &ctx); if (ret) goto out; @@ -493,7 +510,7 @@ krb5_get_init_creds_keytab(krb5_context context, a->keytab = keytab; ret = krb5_get_in_cred (context, - ctx.flags.i, + KDCOptions2int(ctx.flags), ctx.addrs, ctx.etypes, ctx.pre_auth_types, @@ -522,7 +539,7 @@ krb5_get_init_creds_keytab(krb5_context context, static krb5_error_code init_creds_init_as_req (krb5_context context, - krb5_kdc_flags opts, + KDCOptions opts, const krb5_creds *creds, const krb5_addresses *addrs, const krb5_enctype *etypes, @@ -534,7 +551,7 @@ init_creds_init_as_req (krb5_context context, a->pvno = 5; a->msg_type = krb_as_req; - a->req_body.kdc_options = opts.b; + a->req_body.kdc_options = opts; a->req_body.cname = malloc(sizeof(*a->req_body.cname)); if (a->req_body.cname == NULL) { ret = ENOMEM; @@ -1028,12 +1045,12 @@ pa_data_add_pac_request(krb5_context context, void *buf; switch (ctx->req_pac) { - case KRB5_PA_PAC_DONT_CARE: + case KRB5_INIT_CREDS_TRISTATE_UNSET: return 0; /* don't bother */ - case KRB5_PA_PAC_REQ_TRUE: + case KRB5_INIT_CREDS_TRISTATE_TRUE: req.include_pac = 1; break; - case KRB5_PA_PAC_REQ_FALSE: + case KRB5_INIT_CREDS_TRISTATE_FALSE: req.include_pac = 0; } @@ -1176,7 +1193,7 @@ process_pa_data_to_key(krb5_context context, static krb5_error_code init_cred_loop(krb5_context context, - const krb5_get_init_creds_opt *init_cred_opts, + krb5_get_init_creds_opt *init_cred_opts, const krb5_prompter_fct prompter, void *prompter_data, krb5_get_init_creds_ctx *ctx, @@ -1196,6 +1213,8 @@ init_cred_loop(krb5_context context, memset(&md, 0, sizeof(md)); memset(&rep, 0, sizeof(rep)); + _krb5_get_init_creds_opt_free_krb5_error(init_cred_opts); + if (ret_as_reply) memset(ret_as_reply, 0, sizeof(*ret_as_reply)); @@ -1211,7 +1230,7 @@ init_cred_loop(krb5_context context, ctx->pk_nonce = ctx->nonce; /* - * Increase counter when we want other pre-auth types than + * Increase counter when we want other pre-auth types then * KRB5_PA_ENC_TIMESTAMP. */ #define MAX_PA_COUNTER 3 @@ -1306,6 +1325,9 @@ init_cred_loop(krb5_context context, krb5_free_error_contents(context, &error); send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; } else { + _krb5_get_init_creds_opt_set_krb5_error(context, + init_cred_opts, + &error); if (ret_as_reply) rep.error = error; else @@ -1332,7 +1354,7 @@ init_cred_loop(krb5_context context, NULL, ctx->nonce, FALSE, - ctx->flags.b.request_anonymous, + ctx->flags.request_anonymous, NULL, NULL); krb5_free_keyblock(context, key); @@ -1344,7 +1366,7 @@ out: if (ret == 0 && ret_as_reply) *ret_as_reply = rep; - else + else krb5_free_kdc_rep (context, &rep); return ret; } @@ -1367,7 +1389,7 @@ krb5_get_init_creds(krb5_context context, memset(&kdc_reply, 0, sizeof(kdc_reply)); - ret = get_init_creds_common(context, creds, client, start_time, + ret = get_init_creds_common(context, client, start_time, in_tkt_service, options, &ctx); if (ret) goto out; @@ -1391,7 +1413,7 @@ krb5_get_init_creds(krb5_context context, case KRB5KDC_ERR_KEY_EXPIRED : /* try to avoid recursion */ - /* don't try to change password where there where none */ + /* don't try to change password where then where none */ if (prompter == NULL || ctx.password == NULL) goto out; @@ -1528,13 +1550,13 @@ krb5_get_init_creds_keyblock(krb5_context context, struct krb5_get_init_creds_ctx ctx; krb5_error_code ret; - ret = get_init_creds_common(context, creds, client, start_time, + ret = get_init_creds_common(context, client, start_time, in_tkt_service, options, &ctx); if (ret) goto out; ret = krb5_get_in_cred (context, - ctx.flags.i, + KDCOptions2int(ctx.flags), ctx.addrs, ctx.etypes, ctx.pre_auth_types, diff --git a/source4/heimdal/lib/krb5/k524_err.c b/source4/heimdal/lib/krb5/k524_err.c new file mode 100644 index 0000000000..266d3ee577 --- /dev/null +++ b/source4/heimdal/lib/krb5/k524_err.c @@ -0,0 +1,30 @@ +/* Generated from k524_err.et */ +/* $Id: k524_err.et,v 1.1 2001/06/20 02:44:11 joda Exp $ */ + +#include +#include +#include "k524_err.h" + +static const char *k524_error_strings[] = { + /* 000 */ "wrong keytype in ticket", + /* 001 */ "incorrect network address", + /* 002 */ "cannot convert V5 principal", + /* 003 */ "V5 realm name longer than V4 maximum", + /* 004 */ "kerberos V4 error server", + /* 005 */ "encoding too large at server", + /* 006 */ "decoding out of data", + /* 007 */ "service not responding", + NULL +}; + +#define num_errors 8 + +void initialize_k524_error_table_r(struct et_list **list) +{ + initialize_error_table_r(list, k524_error_strings, num_errors, ERROR_TABLE_BASE_k524); +} + +void initialize_k524_error_table(void) +{ + init_error_table(k524_error_strings, ERROR_TABLE_BASE_k524, num_errors); +} diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 9ba288e22b..968b6079b7 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -17,7 +17,7 @@ _krb5_aes_cts_encrypt ( const unsigned char */*in*/, unsigned char */*out*/, size_t /*len*/, - const void */*aes_key*/, + const AES_KEY */*key*/, unsigned char */*ivec*/, const int /*encryptp*/); @@ -46,6 +46,12 @@ _krb5_dh_group_ok ( struct krb5_dh_moduli **/*moduli*/, char **/*name*/); +krb5_error_code KRB5_LIB_FUNCTION +_krb5_enctype_to_oid ( + krb5_context /*context*/, + krb5_enctype /*etype*/, + heim_oid */*oid*/); + krb5_error_code _krb5_expand_default_cc_name ( krb5_context /*context*/, @@ -100,9 +106,18 @@ _krb5_get_init_creds_opt_copy ( const krb5_get_init_creds_opt */*in*/, krb5_get_init_creds_opt **/*out*/); +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_free_krb5_error (krb5_get_init_creds_opt */*opt*/); + void KRB5_LIB_FUNCTION _krb5_get_init_creds_opt_free_pkinit (krb5_get_init_creds_opt */*opt*/); +void KRB5_LIB_FUNCTION +_krb5_get_init_creds_opt_set_krb5_error ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + const KRB_ERROR */*error*/); + krb5_ssize_t KRB5_LIB_FUNCTION _krb5_get_int ( void */*buffer*/, @@ -312,8 +327,8 @@ _krb5_pk_load_id ( struct krb5_pk_identity **/*ret_id*/, const char */*user_id*/, const char */*anchor_id*/, - char * const */*chain*/, - char * const */*revoke*/, + char * const */*chain_list*/, + char * const */*revoke_list*/, krb5_prompter_fct /*prompter*/, void */*prompter_data*/, char */*password*/); @@ -372,7 +387,7 @@ _krb5_principal2principalname ( krb5_error_code KRB5_LIB_FUNCTION _krb5_principalname2krb5_principal ( - krb5_context /* context */, + krb5_context /*context*/, krb5_principal */*principal*/, const PrincipalName /*from*/, const Realm /*realm*/); @@ -383,6 +398,12 @@ _krb5_put_int ( unsigned long /*value*/, size_t /*size*/); +krb5_error_code KRB5_LIB_FUNCTION +_krb5_s4u2self_to_checksumdata ( + krb5_context /*context*/, + const PA_S4U2Self */*self*/, + krb5_data */*data*/); + int _krb5_send_and_recv_tcp ( int /*fd*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 37293ff982..2010e25f5a 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -1065,13 +1065,6 @@ krb5_crypto_get_checksum_type ( krb5_crypto /*crypto*/, krb5_cksumtype */*type*/); -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_get_params ( - krb5_context /*context*/, - const krb5_crypto /*crypto*/, - const krb5_data */*params*/, - krb5_data */*ivec*/); - krb5_error_code KRB5_LIB_FUNCTION krb5_crypto_getblocksize ( krb5_context /*context*/, @@ -1103,13 +1096,6 @@ krb5_crypto_init ( krb5_enctype /*etype*/, krb5_crypto */*crypto*/); -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_set_params ( - krb5_context /*context*/, - const krb5_crypto /*crypto*/, - const krb5_data */*ivec*/, - krb5_data */*params*/); - krb5_error_code KRB5_LIB_FUNCTION krb5_data_alloc ( krb5_data */*p*/, @@ -1246,6 +1232,169 @@ krb5_derive_key ( size_t /*constant_len*/, krb5_keyblock **/*derived_key*/); +krb5_error_code +krb5_digest_alloc ( + krb5_context /*context*/, + krb5_digest */*digest*/); + +void +krb5_digest_free (krb5_digest /*digest*/); + +krb5_error_code +krb5_digest_get_a1_hash ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_data */*data*/); + +krb5_error_code +krb5_digest_get_client_binding ( + krb5_context /*context*/, + krb5_digest /*digest*/, + char **/*type*/, + char **/*binding*/); + +const char * +krb5_digest_get_identifier ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +const char * +krb5_digest_get_opaque ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +const char * +krb5_digest_get_responseData ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +const char * +krb5_digest_get_rsp ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +const char * +krb5_digest_get_server_nonce ( + krb5_context /*context*/, + krb5_digest /*digest*/); + +krb5_error_code +krb5_digest_get_tickets ( + krb5_context /*context*/, + krb5_digest /*digest*/, + Ticket **/*tickets*/); + +krb5_error_code +krb5_digest_init_request ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/); + +krb5_error_code +krb5_digest_request ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/); + +krb5_error_code +krb5_digest_set_authentication_user ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_principal /*authentication_user*/); + +krb5_error_code +krb5_digest_set_authid ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*authid*/); + +krb5_error_code +krb5_digest_set_client_nonce ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*nonce*/); + +krb5_error_code +krb5_digest_set_digest ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*dgst*/); + +krb5_error_code +krb5_digest_set_hostname ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*hostname*/); + +krb5_error_code +krb5_digest_set_identifier ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*id*/); + +krb5_error_code +krb5_digest_set_method ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*method*/); + +krb5_error_code +krb5_digest_set_nonceCount ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*nonce_count*/); + +krb5_error_code +krb5_digest_set_opaque ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*opaque*/); + +krb5_error_code +krb5_digest_set_qop ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*qop*/); + +krb5_error_code +krb5_digest_set_realm ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*realm*/); + +krb5_error_code +krb5_digest_set_server_cb ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*type*/, + const char */*binding*/); + +krb5_error_code +krb5_digest_set_server_nonce ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*nonce*/); + +krb5_error_code +krb5_digest_set_type ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*type*/); + +krb5_error_code +krb5_digest_set_uri ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*uri*/); + +krb5_error_code +krb5_digest_set_username ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*username*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_domain_x500_decode ( krb5_context /*context*/, @@ -1376,12 +1525,6 @@ krb5_enctype_to_keytype ( krb5_enctype /*etype*/, krb5_keytype */*keytype*/); -krb5_error_code KRB5_LIB_FUNCTION -krb5_enctype_to_oid ( - krb5_context /*context*/, - krb5_enctype /*etype*/, - heim_oid */*oid*/); - krb5_error_code KRB5_LIB_FUNCTION krb5_enctype_to_string ( krb5_context /*context*/, @@ -1651,6 +1794,54 @@ krb5_get_credentials_with_flags ( krb5_creds */*in_creds*/, krb5_creds **/*out_creds*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_ccache /*ccache*/, + krb5_const_principal /*inprinc*/, + krb5_creds **/*out_creds*/); + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_add_options ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_flags /*options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_alloc ( + krb5_context /*context*/, + krb5_get_creds_opt */*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_free ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/); + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_enctype ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_enctype /*enctype*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_impersonate ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_const_principal /*self*/); + +void KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_options ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + krb5_flags /*options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_creds_opt_set_ticket ( + krb5_context /*context*/, + krb5_get_creds_opt /*opt*/, + const Ticket */*ticket*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_get_default_config_files (char ***/*pfilenames*/); @@ -1674,6 +1865,9 @@ krb5_get_default_realms ( krb5_context /*context*/, krb5_realm **/*realms*/); +krb5_boolean KRB5_LIB_FUNCTION +krb5_get_dns_canonize_hostname (krb5_context /*context*/); + const char* KRB5_LIB_FUNCTION krb5_get_err_text ( krb5_context /*context*/, @@ -1710,7 +1904,7 @@ krb5_get_forwarded_creds ( krb5_error_code KRB5_LIB_FUNCTION krb5_get_host_realm ( krb5_context /*context*/, - const char */*host*/, + const char */*targethost*/, krb5_realm **/*realms*/); krb5_error_code KRB5_LIB_FUNCTION @@ -1823,6 +2017,12 @@ krb5_get_init_creds_opt_alloc ( void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_free (krb5_get_init_creds_opt */*opt*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_get_error ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + KRB_ERROR **/*error*/); + void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init (krb5_get_init_creds_opt */*opt*/); @@ -1831,6 +2031,12 @@ krb5_get_init_creds_opt_set_address_list ( krb5_get_init_creds_opt */*opt*/, krb5_addresses */*addresses*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_addressless ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + krb5_boolean /*addressless*/); + void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_set_anonymous ( krb5_get_init_creds_opt */*opt*/, @@ -1874,8 +2080,8 @@ krb5_get_init_creds_opt_set_pkinit ( krb5_principal /*principal*/, const char */*user_id*/, const char */*x509_anchors*/, - char * const * /*chain*/, - char * const * /*revoke*/, + char * const * /*pool*/, + char * const * /*pki_revoke*/, int /*flags*/, krb5_prompter_fct /*prompter*/, void */*prompter_data*/, @@ -1929,6 +2135,12 @@ krb5_get_kdc_cred ( krb5_creds */*in_creds*/, krb5_creds **out_creds ); +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_kdc_sec_offset ( + krb5_context /*context*/, + int32_t */*sec*/, + int32_t */*usec*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_get_krb524hst ( krb5_context /*context*/, @@ -2035,6 +2247,9 @@ krb5_initlog ( krb5_boolean KRB5_LIB_FUNCTION krb5_is_thread_safe (void); +const krb5_enctype * KRB5_LIB_FUNCTION +krb5_kerberos_enctypes (krb5_context /*context*/); + krb5_enctype krb5_keyblock_get_enctype (const krb5_keyblock */*block*/); @@ -2412,15 +2627,10 @@ krb5_parse_name ( krb5_principal */*principal*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_parse_name_mustrealm ( - krb5_context /*context*/, - const char */*name*/, - krb5_principal */*principal*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_parse_name_norealm ( +krb5_parse_name_flags ( krb5_context /*context*/, const char */*name*/, + int /*flags*/, krb5_principal */*principal*/); const char* KRB5_LIB_FUNCTION @@ -2447,7 +2657,7 @@ krb5_prepend_config_files_default ( const char */*filelist*/, char ***/*pfilenames*/); -krb5_realm* KRB5_LIB_FUNCTION +krb5_realm * KRB5_LIB_FUNCTION krb5_princ_realm ( krb5_context /*context*/, krb5_principal /*principal*/); @@ -2792,6 +3002,11 @@ krb5_ret_string ( krb5_storage */*sp*/, char **/*string*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_stringnl ( + krb5_storage */*sp*/, + char **/*string*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_ret_stringz ( krb5_storage */*sp*/, @@ -2877,6 +3092,11 @@ krb5_set_default_realm ( krb5_context /*context*/, const char */*realm*/); +void KRB5_LIB_FUNCTION +krb5_set_dns_canonicalize_hostname ( + krb5_context /*context*/, + krb5_boolean /*flag*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_set_error_string ( krb5_context /*context*/, @@ -2926,10 +3146,9 @@ krb5_set_real_time ( int32_t /*usec*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_set_send_recv_func ( +krb5_set_send_to_kdc_func ( krb5_context /*context*/, - krb5_send_and_recv_func_t /*func*/, - krb5_send_and_recv_close_func_t /*close_fn*/, + krb5_send_to_kdc_func /*func*/, void */*data*/); void KRB5_LIB_FUNCTION @@ -3109,6 +3328,11 @@ krb5_store_string ( krb5_storage */*sp*/, const char */*s*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_stringnl ( + krb5_storage */*sp*/, + const char */*s*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_store_stringz ( krb5_storage */*sp*/, @@ -3254,24 +3478,26 @@ krb5_unparse_name_fixed ( size_t /*len*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_fixed_short ( +krb5_unparse_name_fixed_flags ( krb5_context /*context*/, krb5_const_principal /*principal*/, + int /*flags*/, char */*name*/, size_t /*len*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_norealm ( +krb5_unparse_name_fixed_short ( krb5_context /*context*/, krb5_const_principal /*principal*/, - char **/*name*/); + char */*name*/, + size_t /*len*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_norealm_fixed ( +krb5_unparse_name_flags ( krb5_context /*context*/, krb5_const_principal /*principal*/, - char */*name*/, - size_t /*len*/); + int /*flags*/, + char **/*name*/); krb5_error_code KRB5_LIB_FUNCTION krb5_unparse_name_short ( diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 32fdd6d383..4b5058094b 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h,v 1.241 2006/05/05 09:29:36 lha Exp $ */ +/* $Id: krb5.h,v 1.253 2006/10/20 18:12:06 lha Exp $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -72,6 +72,12 @@ typedef const void *krb5_const_pointer; struct krb5_crypto_data; typedef struct krb5_crypto_data *krb5_crypto; +struct krb5_get_creds_opt_data; +typedef struct krb5_get_creds_opt_data *krb5_get_creds_opt; + +struct krb5_digest; +typedef struct krb5_digest *krb5_digest; + typedef CKSUMTYPE krb5_cksumtype; typedef Checksum krb5_checksum; @@ -203,8 +209,16 @@ typedef enum krb5_key_usage { /* Encryption of the SAM-TRACK-ID field */ KRB5_KU_PA_SERVER_REFERRAL = 26, /* Keyusage for the server referral in a TGS req */ - KRB5_KU_SAM_ENC_NONCE_SAD = 27 + KRB5_KU_SAM_ENC_NONCE_SAD = 27, /* Encryption of the SAM-NONCE-OR-SAD field */ + KRB5_KU_TGS_IMPERSONATE = -17, + /* Checksum type used in the impersonate field */ + KRB5_KU_DIGEST_ENCRYPT = -18, + /* Encryption key usage used in the digest encryption field */ + KRB5_KU_DIGEST_OPAQUE = -19, + /* Checksum key usage used in the digest opaque field */ + KRB5_KU_KRB5SIGNEDPATH = -21 + /* Checksum key usage on KRB5SignedPath */ } krb5_key_usage; typedef krb5_key_usage krb5_keyusage; @@ -256,9 +270,7 @@ typedef enum krb5_keytype { KEYTYPE_AES128 = 17, KEYTYPE_AES256 = 18, KEYTYPE_ARCFOUR = 23, - KEYTYPE_ARCFOUR_56 = 24, - KEYTYPE_RC2 = -0x1005, - KEYTYPE_AES192 = -0x1006 + KEYTYPE_ARCFOUR_56 = 24 } krb5_keytype; typedef EncryptionKey krb5_keyblock; @@ -339,6 +351,9 @@ typedef union { #define KRB5_GC_CACHED (1U << 0) #define KRB5_GC_USER_USER (1U << 1) #define KRB5_GC_EXPIRED_OK (1U << 2) +#define KRB5_GC_NO_STORE (1U << 3) +#define KRB5_GC_FORWARDABLE (1U << 4) +#define KRB5_GC_NO_TRANSIT_CHECK (1U << 5) /* constants for compare_creds (and cc_retrieve_cred) */ #define KRB5_TC_DONT_MATCH_REALM (1U << 31) @@ -413,49 +428,6 @@ typedef struct krb5_config_binding krb5_config_binding; typedef krb5_config_binding krb5_config_section; -typedef struct krb5_context_data { - krb5_enctype *etypes; - krb5_enctype *etypes_des; - char **default_realms; - time_t max_skew; - time_t kdc_timeout; - unsigned max_retries; - int32_t kdc_sec_offset; - int32_t kdc_usec_offset; - krb5_config_section *cf; - struct et_list *et_list; - struct krb5_log_facility *warn_dest; - krb5_cc_ops *cc_ops; - int num_cc_ops; - const char *http_proxy; - const char *time_fmt; - krb5_boolean log_utc; - const char *default_keytab; - const char *default_keytab_modify; - krb5_boolean use_admin_kdc; - krb5_addresses *extra_addresses; - krb5_boolean scan_interfaces; /* `ifconfig -a' */ - krb5_boolean srv_lookup; /* do SRV lookups */ - krb5_boolean srv_try_txt; /* try TXT records also */ - int32_t fcache_vno; /* create cache files w/ this - version */ - int num_kt_types; /* # of registered keytab types */ - struct krb5_keytab_data *kt_types; /* registered keytab types */ - const char *date_fmt; - char *error_string; - char error_buf[256]; - krb5_addresses *ignore_addresses; - char *default_cc_name; - int pkinit_flags; - void *mutex; /* protects error_string/error_buf */ - int large_msg_size; - krb5_boolean fdns; /* Lookup hostnames to find full name, or send as-is */ - struct send_and_recv *send_and_recv; /* Alternate functions for KDC communication */ - void *mem_ctx; /* Some parts of Samba4 need a valid - memory context (under the event - context) to use */ -} krb5_context_data; - enum { KRB5_PKINIT_WIN2K = 1, /* wire compatible with Windows 2k */ KRB5_PKINIT_PACKET_CABLE = 2 /* use packet cable standard */ @@ -578,8 +550,8 @@ typedef struct krb5_auth_context_data { krb5_rcache rcache; - krb5_keytype keytype; /* ¿requested key type ? */ - krb5_cksumtype cksumtype; /* ¡requested checksum type! */ + krb5_keytype keytype; /* ¿requested key type ? */ + krb5_cksumtype cksumtype; /* ¡requested checksum type! */ }krb5_auth_context_data, *krb5_auth_context; @@ -609,6 +581,8 @@ typedef EncAPRepPart krb5_ap_rep_enc_part; #define KRB5_TGS_NAME_SIZE (6) #define KRB5_TGS_NAME ("krbtgt") +#define KRB5_DIGEST_NAME ("digest") + /* variables */ extern const char *krb5_config_file; @@ -618,7 +592,8 @@ typedef enum { KRB5_PROMPT_TYPE_PASSWORD = 0x1, KRB5_PROMPT_TYPE_NEW_PASSWORD = 0x2, KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN = 0x3, - KRB5_PROMPT_TYPE_PREAUTH = 0x4 + KRB5_PROMPT_TYPE_PREAUTH = 0x4, + KRB5_PROMPT_TYPE_INFO = 0x5 } krb5_prompt_type; typedef struct _krb5_prompt { @@ -754,12 +729,23 @@ enum { KRB5_KRBHST_FLAGS_LARGE_MSG = 2 }; -typedef int (*krb5_send_and_recv_func_t)(krb5_context, - void *, - krb5_krbhst_info *, - const krb5_data *, - krb5_data *); -typedef void (*krb5_send_and_recv_close_func_t)(krb5_context, void*); +typedef krb5_error_code (*krb5_send_to_kdc_func)(krb5_context, + void *, + krb5_krbhst_info *, + const krb5_data *, + krb5_data *); + +/* flags for krb5_parse_name_flags */ +enum { + KRB5_PRINCIPAL_PARSE_NO_REALM = 1, + KRB5_PRINCIPAL_PARSE_MUST_REALM = 2 +}; + +/* flags for krb5_unparse_name_flags */ +enum { + KRB5_PRINCIPAL_UNPARSE_SHORT = 1, + KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2 +}; struct credentials; /* this is to keep the compiler happy */ struct getargs; diff --git a/source4/heimdal/lib/krb5/krb5_err.c b/source4/heimdal/lib/krb5/krb5_err.c new file mode 100644 index 0000000000..9185f729d5 --- /dev/null +++ b/source4/heimdal/lib/krb5/krb5_err.c @@ -0,0 +1,271 @@ +/* Generated from krb5_err.et */ +/* $Id: krb5_err.et,v 1.14 2006/02/13 11:28:22 lha Exp $ */ + +#include +#include +#include "krb5_err.h" + +static const char *krb5_error_strings[] = { + /* 000 */ "No error", + /* 001 */ "Client's entry in database has expired", + /* 002 */ "Server's entry in database has expired", + /* 003 */ "Requested protocol version not supported", + /* 004 */ "Client's key is encrypted in an old master key", + /* 005 */ "Server's key is encrypted in an old master key", + /* 006 */ "Client not found in Kerberos database", + /* 007 */ "Server not found in Kerberos database", + /* 008 */ "Principal has multiple entries in Kerberos database", + /* 009 */ "Client or server has a null key", + /* 010 */ "Ticket is ineligible for postdating", + /* 011 */ "Requested effective lifetime is negative or too short", + /* 012 */ "KDC policy rejects request", + /* 013 */ "KDC can't fulfill requested option", + /* 014 */ "KDC has no support for encryption type", + /* 015 */ "KDC has no support for checksum type", + /* 016 */ "KDC has no support for padata type", + /* 017 */ "KDC has no support for transited type", + /* 018 */ "Clients credentials have been revoked", + /* 019 */ "Credentials for server have been revoked", + /* 020 */ "TGT has been revoked", + /* 021 */ "Client not yet valid - try again later", + /* 022 */ "Server not yet valid - try again later", + /* 023 */ "Password has expired", + /* 024 */ "Preauthentication failed", + /* 025 */ "Additional pre-authentication required", + /* 026 */ "Requested server and ticket don't match", + /* 027 */ "Reserved krb5 error (27)", + /* 028 */ "Reserved krb5 error (28)", + /* 029 */ "Reserved krb5 error (29)", + /* 030 */ "Reserved krb5 error (30)", + /* 031 */ "Decrypt integrity check failed", + /* 032 */ "Ticket expired", + /* 033 */ "Ticket not yet valid", + /* 034 */ "Request is a replay", + /* 035 */ "The ticket isn't for us", + /* 036 */ "Ticket/authenticator don't match", + /* 037 */ "Clock skew too great", + /* 038 */ "Incorrect net address", + /* 039 */ "Protocol version mismatch", + /* 040 */ "Invalid message type", + /* 041 */ "Message stream modified", + /* 042 */ "Message out of order", + /* 043 */ "Invalid cross-realm ticket", + /* 044 */ "Key version is not available", + /* 045 */ "Service key not available", + /* 046 */ "Mutual authentication failed", + /* 047 */ "Incorrect message direction", + /* 048 */ "Alternative authentication method required", + /* 049 */ "Incorrect sequence number in message", + /* 050 */ "Inappropriate type of checksum in message", + /* 051 */ "Policy rejects transited path", + /* 052 */ "Response too big for UDP, retry with TCP", + /* 053 */ "Reserved krb5 error (53)", + /* 054 */ "Reserved krb5 error (54)", + /* 055 */ "Reserved krb5 error (55)", + /* 056 */ "Reserved krb5 error (56)", + /* 057 */ "Reserved krb5 error (57)", + /* 058 */ "Reserved krb5 error (58)", + /* 059 */ "Reserved krb5 error (59)", + /* 060 */ "Generic error (see e-text)", + /* 061 */ "Field is too long for this implementation", + /* 062 */ "Client not trusted", + /* 063 */ "KDC not trusted", + /* 064 */ "Invalid signature", + /* 065 */ "DH parameters not accepted", + /* 066 */ "Reserved krb5 error (66)", + /* 067 */ "Reserved krb5 error (67)", + /* 068 */ "Reserved krb5 error (68)", + /* 069 */ "User to user required", + /* 070 */ "Cannot verify certificate", + /* 071 */ "Certificate invalid", + /* 072 */ "Certificate revoked", + /* 073 */ "Revocation status unknown", + /* 074 */ "Revocation status unknown", + /* 075 */ "Inconsistent key purpose", + /* 076 */ "Digest in certificate not accepted", + /* 077 */ "paChecksum must be included", + /* 078 */ "Digest in signedData not accepted", + /* 079 */ "Public key encryption not supported", + /* 080 */ "Reserved krb5 error (80)", + /* 081 */ "Reserved krb5 error (81)", + /* 082 */ "Reserved krb5 error (82)", + /* 083 */ "Reserved krb5 error (83)", + /* 084 */ "Reserved krb5 error (84)", + /* 085 */ "Reserved krb5 error (85)", + /* 086 */ "Reserved krb5 error (86)", + /* 087 */ "Reserved krb5 error (87)", + /* 088 */ "Reserved krb5 error (88)", + /* 089 */ "Reserved krb5 error (89)", + /* 090 */ "Reserved krb5 error (90)", + /* 091 */ "Reserved krb5 error (91)", + /* 092 */ "Reserved krb5 error (92)", + /* 093 */ "Reserved krb5 error (93)", + /* 094 */ "Reserved krb5 error (94)", + /* 095 */ "Reserved krb5 error (95)", + /* 096 */ "Reserved krb5 error (96)", + /* 097 */ "Reserved krb5 error (97)", + /* 098 */ "Reserved krb5 error (98)", + /* 099 */ "Reserved krb5 error (99)", + /* 100 */ "Reserved krb5 error (100)", + /* 101 */ "Reserved krb5 error (101)", + /* 102 */ "Reserved krb5 error (102)", + /* 103 */ "Reserved krb5 error (103)", + /* 104 */ "Reserved krb5 error (104)", + /* 105 */ "Reserved krb5 error (105)", + /* 106 */ "Reserved krb5 error (106)", + /* 107 */ "Reserved krb5 error (107)", + /* 108 */ "Reserved krb5 error (108)", + /* 109 */ "Reserved krb5 error (109)", + /* 110 */ "Reserved krb5 error (110)", + /* 111 */ "Reserved krb5 error (111)", + /* 112 */ "Reserved krb5 error (112)", + /* 113 */ "Reserved krb5 error (113)", + /* 114 */ "Reserved krb5 error (114)", + /* 115 */ "Reserved krb5 error (115)", + /* 116 */ "Reserved krb5 error (116)", + /* 117 */ "Reserved krb5 error (117)", + /* 118 */ "Reserved krb5 error (118)", + /* 119 */ "Reserved krb5 error (119)", + /* 120 */ "Reserved krb5 error (120)", + /* 121 */ "Reserved krb5 error (121)", + /* 122 */ "Reserved krb5 error (122)", + /* 123 */ "Reserved krb5 error (123)", + /* 124 */ "Reserved krb5 error (124)", + /* 125 */ "Reserved krb5 error (125)", + /* 126 */ "Reserved krb5 error (126)", + /* 127 */ "Reserved krb5 error (127)", + /* 128 */ "$Id: krb5_err.et,v 1.14 2006/02/13 11:28:22 lha Exp $", + /* 129 */ "Invalid flag for file lock mode", + /* 130 */ "Cannot read password", + /* 131 */ "Password mismatch", + /* 132 */ "Password read interrupted", + /* 133 */ "Invalid character in component name", + /* 134 */ "Malformed representation of principal", + /* 135 */ "Can't open/find configuration file", + /* 136 */ "Improper format of configuration file", + /* 137 */ "Insufficient space to return complete information", + /* 138 */ "Invalid message type specified for encoding", + /* 139 */ "Credential cache name malformed", + /* 140 */ "Unknown credential cache type", + /* 141 */ "Matching credential not found", + /* 142 */ "End of credential cache reached", + /* 143 */ "Request did not supply a ticket", + /* 144 */ "Wrong principal in request", + /* 145 */ "Ticket has invalid flag set", + /* 146 */ "Requested principal and ticket don't match", + /* 147 */ "KDC reply did not match expectations", + /* 148 */ "Clock skew too great in KDC reply", + /* 149 */ "Client/server realm mismatch in initial ticket request", + /* 150 */ "Program lacks support for encryption type", + /* 151 */ "Program lacks support for key type", + /* 152 */ "Requested encryption type not used in message", + /* 153 */ "Program lacks support for checksum type", + /* 154 */ "Cannot find KDC for requested realm", + /* 155 */ "Kerberos service unknown", + /* 156 */ "Cannot contact any KDC for requested realm", + /* 157 */ "No local name found for principal name", + /* 158 */ "Mutual authentication failed", + /* 159 */ "Replay cache type is already registered", + /* 160 */ "No more memory to allocate (in replay cache code)", + /* 161 */ "Replay cache type is unknown", + /* 162 */ "Generic unknown RC error", + /* 163 */ "Message is a replay", + /* 164 */ "Replay I/O operation failed XXX", + /* 165 */ "Replay cache type does not support non-volatile storage", + /* 166 */ "Replay cache name parse/format error", + /* 167 */ "End-of-file on replay cache I/O", + /* 168 */ "No more memory to allocate (in replay cache I/O code)", + /* 169 */ "Permission denied in replay cache code", + /* 170 */ "I/O error in replay cache i/o code", + /* 171 */ "Generic unknown RC/IO error", + /* 172 */ "Insufficient system space to store replay information", + /* 173 */ "Can't open/find realm translation file", + /* 174 */ "Improper format of realm translation file", + /* 175 */ "Can't open/find lname translation database", + /* 176 */ "No translation available for requested principal", + /* 177 */ "Improper format of translation database entry", + /* 178 */ "Cryptosystem internal error", + /* 179 */ "Key table name malformed", + /* 180 */ "Unknown Key table type", + /* 181 */ "Key table entry not found", + /* 182 */ "End of key table reached", + /* 183 */ "Cannot write to specified key table", + /* 184 */ "Error writing to key table", + /* 185 */ "Cannot find ticket for requested realm", + /* 186 */ "DES key has bad parity", + /* 187 */ "DES key is a weak key", + /* 188 */ "Bad encryption type", + /* 189 */ "Key size is incompatible with encryption type", + /* 190 */ "Message size is incompatible with encryption type", + /* 191 */ "Credentials cache type is already registered.", + /* 192 */ "Key table type is already registered.", + /* 193 */ "Credentials cache I/O operation failed XXX", + /* 194 */ "Credentials cache file permissions incorrect", + /* 195 */ "No credentials cache file found", + /* 196 */ "Internal file credentials cache error", + /* 197 */ "Error writing to credentials cache file", + /* 198 */ "No more memory to allocate (in credentials cache code)", + /* 199 */ "Bad format in credentials cache", + /* 200 */ "No credentials found with supported encryption types", + /* 201 */ "Invalid KDC option combination (library internal error)", + /* 202 */ "Request missing second ticket", + /* 203 */ "No credentials supplied to library routine", + /* 204 */ "Bad sendauth version was sent", + /* 205 */ "Bad application version was sent (via sendauth)", + /* 206 */ "Bad response (during sendauth exchange)", + /* 207 */ "Server rejected authentication (during sendauth exchange)", + /* 208 */ "Unsupported preauthentication type", + /* 209 */ "Required preauthentication key not supplied", + /* 210 */ "Generic preauthentication failure", + /* 211 */ "Unsupported replay cache format version number", + /* 212 */ "Unsupported credentials cache format version number", + /* 213 */ "Unsupported key table format version number", + /* 214 */ "Program lacks support for address type", + /* 215 */ "Message replay detection requires rcache parameter", + /* 216 */ "Hostname cannot be canonicalized", + /* 217 */ "Cannot determine realm for host", + /* 218 */ "Conversion to service principal undefined for name type", + /* 219 */ "Initial Ticket response appears to be Version 4", + /* 220 */ "Cannot resolve KDC for requested realm", + /* 221 */ "Requesting ticket can't get forwardable tickets", + /* 222 */ "Bad principal name while trying to forward credentials", + /* 223 */ "Looping detected inside krb5_get_in_tkt", + /* 224 */ "Configuration file does not specify default realm", + /* 225 */ "Bad SAM flags in obtain_sam_padata", + /* 226 */ "Invalid encryption type in SAM challenge", + /* 227 */ "Missing checksum in SAM challenge", + /* 228 */ "Bad checksum in SAM challenge", + /* 229 */ "Reserved krb5 error (229)", + /* 230 */ "Reserved krb5 error (230)", + /* 231 */ "Reserved krb5 error (231)", + /* 232 */ "Reserved krb5 error (232)", + /* 233 */ "Reserved krb5 error (233)", + /* 234 */ "Reserved krb5 error (234)", + /* 235 */ "Reserved krb5 error (235)", + /* 236 */ "Reserved krb5 error (236)", + /* 237 */ "Reserved krb5 error (237)", + /* 238 */ "Program called an obsolete, deleted function", + /* 239 */ "Reserved krb5 error (239)", + /* 240 */ "Reserved krb5 error (240)", + /* 241 */ "Reserved krb5 error (241)", + /* 242 */ "Reserved krb5 error (242)", + /* 243 */ "Reserved krb5 error (243)", + /* 244 */ "Reserved krb5 error (244)", + /* 245 */ "Invalid key generation parameters from KDC", + /* 246 */ "Service not available", + /* 247 */ "Credential cache function not supported", + /* 248 */ "Invalid format of Kerberos lifetime or clock skew string", + NULL +}; + +#define num_errors 249 + +void initialize_krb5_error_table_r(struct et_list **list) +{ + initialize_error_table_r(list, krb5_error_strings, num_errors, ERROR_TABLE_BASE_krb5); +} + +void initialize_krb5_error_table(void) +{ + init_error_table(krb5_error_strings, ERROR_TABLE_BASE_krb5, num_errors); +} diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 4dcac40c7a..89b3c6ad40 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_locl.h,v 1.87 2006/02/09 11:36:27 lha Exp $ */ +/* $Id: krb5_locl.h,v 1.93 2006/10/20 18:13:31 lha Exp $ */ #ifndef __KRB5_LOCL_H__ #define __KRB5_LOCL_H__ @@ -136,6 +136,8 @@ struct sockaddr_dl; #include +struct send_to_kdc; + /* XXX glue for pkinit */ struct krb5_pk_identity; struct krb5_pk_cert; @@ -151,6 +153,9 @@ struct _krb5_krb_auth_data; #include #include #include +#ifdef PKINIT +#include +#endif #include #include "heim_threads.h" @@ -171,10 +176,10 @@ struct _krb5_krb_auth_data; #define KRB5_BUFSIZ 1024 typedef enum { - KRB5_PA_PAC_DONT_CARE = 0, - KRB5_PA_PAC_REQ_TRUE, - KRB5_PA_PAC_REQ_FALSE -} krb5_get_init_creds_req_pac; + KRB5_INIT_CREDS_TRISTATE_UNSET = 0, + KRB5_INIT_CREDS_TRISTATE_TRUE, + KRB5_INIT_CREDS_TRISTATE_FALSE +} krb5_get_init_creds_tristate; struct _krb5_get_init_creds_opt_private { int refcount; @@ -182,12 +187,57 @@ struct _krb5_get_init_creds_opt_private { const char *password; krb5_s2k_proc key_proc; /* PA_PAC_REQUEST */ - krb5_get_init_creds_req_pac req_pac; + krb5_get_init_creds_tristate req_pac; /* PKINIT */ krb5_pk_init_ctx pk_init_ctx; int canonicalize; + KRB_ERROR *error; + krb5_get_init_creds_tristate addressless; }; +typedef struct krb5_context_data { + krb5_enctype *etypes; + krb5_enctype *etypes_des; + char **default_realms; + time_t max_skew; + time_t kdc_timeout; + unsigned max_retries; + int32_t kdc_sec_offset; + int32_t kdc_usec_offset; + krb5_config_section *cf; + struct et_list *et_list; + struct krb5_log_facility *warn_dest; + krb5_cc_ops *cc_ops; + int num_cc_ops; + const char *http_proxy; + const char *time_fmt; + krb5_boolean log_utc; + const char *default_keytab; + const char *default_keytab_modify; + krb5_boolean use_admin_kdc; + krb5_addresses *extra_addresses; + krb5_boolean scan_interfaces; /* `ifconfig -a' */ + krb5_boolean srv_lookup; /* do SRV lookups */ + krb5_boolean srv_try_txt; /* try TXT records also */ + int32_t fcache_vno; /* create cache files w/ this + version */ + int num_kt_types; /* # of registered keytab types */ + struct krb5_keytab_data *kt_types; /* registered keytab types */ + const char *date_fmt; + char *error_string; + char error_buf[256]; + krb5_addresses *ignore_addresses; + char *default_cc_name; + int pkinit_flags; + void *mutex; /* protects error_string/error_buf */ + int large_msg_size; + int dns_canonicalize_hostname; + struct send_to_kdc *send_to_kdc; + void *mem_ctx; /* Some parts of Samba4 need a valid + memory context (under the event + context) to use */ +} krb5_context_data; + /* * Configurable options */ @@ -201,7 +251,7 @@ struct _krb5_get_init_creds_opt_private { #endif #ifndef KRB5_ADDRESSLESS_DEFAULT -#define KRB5_ADDRESSLESS_DEFAULT FALSE +#define KRB5_ADDRESSLESS_DEFAULT TRUE #endif #endif /* __KRB5_LOCL_H__ */ diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index 221bd706f4..e7b2579229 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: krbhst.c,v 1.55 2006/04/02 10:32:20 lha Exp $"); +RCSID("$Id: krbhst.c,v 1.57 2006/10/06 17:11:02 lha Exp $"); static int string_to_proto(const char *string) @@ -422,6 +422,15 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, struct addrinfo hints; char portstr[NI_MAXSERV]; + /* + * Don't try forever in case the DNS server keep returning us + * entries (like wildcard entries or the .nu TLD) + */ + if(kd->fallback_count >= 5) { + kd->flags |= KD_FALLBACK; + return 0; + } + if(kd->fallback_count == 0) asprintf(&host, "%s.%s.", serv_string, kd->realm); else @@ -659,9 +668,8 @@ common_init(krb5_context context, } /* For 'realms' without a . do not even think of going to DNS */ - if (!strchr(realm, '.')) { + if (!strchr(realm, '.')) kd->flags |= KD_CONFIG_EXISTS; - } if (flags & KRB5_KRBHST_FLAGS_LARGE_MSG) kd->flags |= KD_LARGE_MSG; diff --git a/source4/heimdal/lib/krb5/misc.c b/source4/heimdal/lib/krb5/misc.c index baf63f6d52..f04f8d9996 100644 --- a/source4/heimdal/lib/krb5/misc.c +++ b/source4/heimdal/lib/krb5/misc.c @@ -33,4 +33,53 @@ #include "krb5_locl.h" -RCSID("$Id: misc.c,v 1.5 1999/12/02 17:05:11 joda Exp $"); +RCSID("$Id: misc.c,v 1.6 2006/06/06 14:57:47 lha Exp $"); + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_s4u2self_to_checksumdata(krb5_context context, + const PA_S4U2Self *self, + krb5_data *data) +{ + krb5_error_code ret; + krb5_ssize_t ssize; + krb5_storage *sp; + size_t size; + int i; + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + ret = krb5_store_int32(sp, self->name.name_type); + if (ret) + goto out; + for (i = 0; i < self->name.name_string.len; i++) { + size = strlen(self->name.name_string.val[i]); + ssize = krb5_storage_write(sp, self->name.name_string.val[i], size); + if (ssize != size) { + ret = ENOMEM; + goto out; + } + } + size = strlen(self->realm); + ssize = krb5_storage_write(sp, self->realm, size); + if (ssize != size) { + ret = ENOMEM; + goto out; + } + size = strlen(self->auth); + ssize = krb5_storage_write(sp, self->auth, size); + if (ssize != size) { + ret = ENOMEM; + goto out; + } + + ret = krb5_storage_to_data(sp, data); + krb5_storage_free(sp); + return ret; + +out: + krb5_clear_error_string(context); + return ret; +} diff --git a/source4/heimdal/lib/krb5/mit_glue.c b/source4/heimdal/lib/krb5/mit_glue.c index b7f06c1582..b9075b3079 100755 --- a/source4/heimdal/lib/krb5/mit_glue.c +++ b/source4/heimdal/lib/krb5/mit_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: mit_glue.c,v 1.7 2005/05/18 04:21:44 lha Exp $"); +RCSID("$Id: mit_glue.c,v 1.8 2006/10/14 09:51:02 lha Exp $"); /* * Glue for MIT API @@ -98,7 +98,7 @@ krb5_c_get_checksum(krb5_context context, const krb5_checksum *cksum, if (*data == NULL) return ENOMEM; - ret = copy_octet_string(&cksum->checksum, *data); + ret = der_copy_octet_string(&cksum->checksum, *data); if (ret) { free(*data); *data = NULL; @@ -113,7 +113,7 @@ krb5_c_set_checksum(krb5_context context, krb5_checksum *cksum, krb5_cksumtype type, const krb5_data *data) { cksum->cksumtype = type; - return copy_octet_string(data, &cksum->checksum); + return der_copy_octet_string(data, &cksum->checksum); } void KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 00f7b4ebd9..f519b5ad08 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.99 2006/05/07 12:32:38 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.110 2006/10/14 09:52:50 lha Exp $"); struct krb5_dh_moduli { char *name; @@ -69,7 +69,7 @@ struct krb5_pk_identity { hx509_certs certs; hx509_certs anchors; hx509_certs certpool; - hx509_revoke_ctx revoke; + hx509_revoke_ctx revokectx; }; struct krb5_pk_cert { @@ -344,8 +344,8 @@ build_auth_pack(krb5_context context, ALLOC(a->clientPublicValue, 1); if (a->clientPublicValue == NULL) return ENOMEM; - ret = copy_oid(oid_id_dhpublicnumber(), - &a->clientPublicValue->algorithm.algorithm); + ret = der_copy_oid(oid_id_dhpublicnumber(), + &a->clientPublicValue->algorithm.algorithm); if (ret) return ret; @@ -392,7 +392,7 @@ build_auth_pack(krb5_context context, ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length, &dh_pub_key, &size, ret); - free_heim_integer(&dh_pub_key); + der_free_heim_integer(&dh_pub_key); if (ret) return ret; if (size != dhbuf.length) @@ -413,7 +413,7 @@ _krb5_pk_mk_ContentInfo(krb5_context context, { krb5_error_code ret; - ret = copy_oid(oid, &content_info->contentType); + ret = der_copy_oid(oid, &content_info->contentType); if (ret) return ret; ALLOC(content_info->content, 1); @@ -672,8 +672,16 @@ _krb5_pk_verify_sign(krb5_context context, contentType, content, &signer_certs); - if (ret) + if (ret) { + char *s = hx509_get_error_string(id->hx509ctx, ret); + if (s) { + krb5_set_error_string(context, + "CMS verify signed failed with %s", s); + free(s); + } else + krb5_clear_error_string(context); return ret; + } *signer = calloc(1, sizeof(**signer)); if (*signer == NULL) { @@ -833,7 +841,9 @@ pk_verify_host(krb5_context context, oid_id_pkinit_san(), &list); if (ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Failed to find the PK-INIT " + "subjectAltName in the KDC certificate"); + return ret; } @@ -845,7 +855,9 @@ pk_verify_host(krb5_context context, &r, NULL); if (ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Failed to decode the PK-INIT " + "subjectAltName in the KDC certificate"); + break; } @@ -856,7 +868,7 @@ pk_verify_host(krb5_context context, { krb5_set_error_string(context, "KDC have wrong realm name in " "the certificate"); - ret = EINVAL; + ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; } free_KRB5PrincipalName(&r); @@ -875,7 +887,8 @@ pk_verify_host(krb5_context context, hi->ai->ai_addr, hi->ai->ai_addrlen); if (ret) - krb5_set_error_string(context, "Address mismatch in the KDC certificate"); + krb5_set_error_string(context, "Address mismatch in " + "the KDC certificate"); } return ret; } @@ -901,7 +914,7 @@ pk_rd_pa_reply_enckey(krb5_context context, krb5_data content; heim_oid contentType = { 0, NULL }; - if (heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) { + if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) { krb5_set_error_string(context, "PKINIT: Invalid content type"); return EINVAL; } @@ -913,8 +926,10 @@ pk_rd_pa_reply_enckey(krb5_context context, ret = hx509_cms_unenvelope(ctx->id->hx509ctx, ctx->id->certs, + HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT, rep->content->data, rep->content->length, + NULL, &contentType, &content); if (ret) @@ -935,7 +950,7 @@ pk_rd_pa_reply_enckey(krb5_context context, goto out; } - if (heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) { + if (der_heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) { ret = EINVAL; /* XXX */ krb5_set_error_string(context, "PKINIT: Invalid content type"); goto out; @@ -964,19 +979,18 @@ pk_rd_pa_reply_enckey(krb5_context context, /* make sure that it is the kdc's certificate */ ret = pk_verify_host(context, realm, hi, ctx, host); if (ret) { - krb5_set_error_string(context, "PKINIT: failed verify host: %d", ret); goto out; } #if 0 if (type == COMPAT_WIN2K) { - if (heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) { + if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) { krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; } } else { - if (heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) { + if (der_heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) { krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; @@ -1002,7 +1016,7 @@ pk_rd_pa_reply_enckey(krb5_context context, out: if (host) _krb5_pk_cert_free(host); - free_oid(&contentType); + der_free_oid(&contentType); krb5_data_free(&content); return ret; @@ -1034,7 +1048,7 @@ pk_rd_pa_reply_dh(krb5_context context, krb5_data_zero(&content); memset(&kdc_dh_info, 0, sizeof(kdc_dh_info)); - if (heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) { + if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) { krb5_set_error_string(context, "PKINIT: Invalid content type"); return EINVAL; } @@ -1059,7 +1073,7 @@ pk_rd_pa_reply_dh(krb5_context context, if (ret) goto out; - if (heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) { + if (der_heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) { krb5_set_error_string(context, "pkinit - dh reply contains wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; goto out; @@ -1324,20 +1338,28 @@ hx_pass_prompter(void *data, const hx509_prompt *prompter) password_data.data = prompter->reply.data; password_data.length = prompter->reply.length; - prompt.prompt = "Enter your private key passphrase: "; - prompt.hidden = 1; + + prompt.prompt = prompter->prompt; + prompt.hidden = hx509_prompt_hidden(prompter->type); prompt.reply = &password_data; - if (prompter->hidden) + + switch (prompter->type) { + case HX509_PROMPT_TYPE_INFO: + prompt.type = KRB5_PROMPT_TYPE_INFO; + break; + case HX509_PROMPT_TYPE_PASSWORD: + case HX509_PROMPT_TYPE_QUESTION: + default: prompt.type = KRB5_PROMPT_TYPE_PASSWORD; - else - prompt.type = KRB5_PROMPT_TYPE_PREAUTH; /* XXX */ + break; + } ret = (*p->prompter)(p->context, p->prompter_data, NULL, NULL, 1, &prompt); if (ret) { memset (prompter->reply.data, 0, prompter->reply.length); - return 0; + return 1; } - return strlen(prompter->reply.data); + return 0; } @@ -1354,8 +1376,8 @@ _krb5_pk_load_id(krb5_context context, struct krb5_pk_identity **ret_id, const char *user_id, const char *anchor_id, - char * const *chain, - char * const *revoke, + char * const *chain_list, + char * const *revoke_list, krb5_prompter_fct prompter, void *prompter_data, char *password) @@ -1392,7 +1414,7 @@ _krb5_pk_load_id(krb5_context context, goto out; ret = hx509_lock_init(id->hx509ctx, &lock); - if (password) + if (password && password[0]) hx509_lock_add_password(lock, password); if (prompter) { @@ -1405,7 +1427,7 @@ _krb5_pk_load_id(krb5_context context, goto out; } - ret = hx509_certs_init(id->hx509ctx, user_id, 0, NULL, &id->certs); + ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs); if (ret) goto out; @@ -1418,33 +1440,36 @@ _krb5_pk_load_id(krb5_context context, if (ret) goto out; - while (chain && *chain) { - ret = hx509_certs_append(id->hx509ctx, id->certpool, NULL, *chain); + while (chain_list && *chain_list) { + ret = hx509_certs_append(id->hx509ctx, id->certpool, + NULL, *chain_list); if (ret) { krb5_set_error_string(context, "pkinit failed to load chain %s", - *chain); + *chain_list); goto out; } - chain++; + chain_list++; } - if (revoke) { - ret = hx509_revoke_init(id->hx509ctx, &id->revoke); + if (revoke_list) { + ret = hx509_revoke_init(id->hx509ctx, &id->revokectx); if (ret) { krb5_set_error_string(context, "revoke failed to init"); goto out; } - while (*revoke) { - ret = hx509_revoke_add_crl(id->hx509ctx, id->revoke, *revoke); + while (*revoke_list) { + ret = hx509_revoke_add_crl(id->hx509ctx, + id->revokectx, + *revoke_list); if (ret) { krb5_set_error_string(context, "pkinit failed to load revoke %s", - *revoke); + *revoke_list); goto out; } - revoke++; + revoke_list++; } } else hx509_context_set_missing_revoke(id->hx509ctx, 1); @@ -1454,7 +1479,7 @@ _krb5_pk_load_id(krb5_context context, goto out; hx509_verify_attach_anchors(id->verify_ctx, id->anchors); - hx509_verify_attach_revoke(id->verify_ctx, id->revoke); + hx509_verify_attach_revoke(id->verify_ctx, id->revokectx); out: if (ret) { @@ -1462,7 +1487,7 @@ out: hx509_certs_free(&id->certs); hx509_certs_free(&id->anchors); hx509_certs_free(&id->certpool); - hx509_revoke_free(&id->revoke); + hx509_revoke_free(&id->revokectx); hx509_context_free(&id->hx509ctx); free(id); } else @@ -1588,9 +1613,9 @@ _krb5_parse_moduli_line(krb5_context context, return 0; out: free(m1->name); - free_heim_integer(&m1->p); - free_heim_integer(&m1->g); - free_heim_integer(&m1->q); + der_free_heim_integer(&m1->p); + der_free_heim_integer(&m1->g); + der_free_heim_integer(&m1->q); free(m1); return ret; } @@ -1601,9 +1626,9 @@ _krb5_free_moduli(struct krb5_dh_moduli **moduli) int i; for (i = 0; moduli[i] != NULL; i++) { free(moduli[i]->name); - free_heim_integer(&moduli[i]->p); - free_heim_integer(&moduli[i]->g); - free_heim_integer(&moduli[i]->q); + der_free_heim_integer(&moduli[i]->p); + der_free_heim_integer(&moduli[i]->g); + der_free_heim_integer(&moduli[i]->q); free(moduli[i]); } free(moduli); @@ -1712,9 +1737,9 @@ _krb5_dh_group_ok(krb5_context context, unsigned long bits, *name = NULL; for (i = 0; moduli[i] != NULL; i++) { - if (heim_integer_cmp(&moduli[i]->g, g) == 0 && - heim_integer_cmp(&moduli[i]->p, p) == 0 && - (q == NULL || heim_integer_cmp(&moduli[i]->q, q) == 0)) + if (der_heim_integer_cmp(&moduli[i]->g, g) == 0 && + der_heim_integer_cmp(&moduli[i]->p, p) == 0 && + (q == NULL || der_heim_integer_cmp(&moduli[i]->q, q) == 0)) { if (bits && bits > moduli[i]->bits) { krb5_set_error_string(context, "PKINIT: DH group parameter %s " @@ -1769,8 +1794,8 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, krb5_principal principal, const char *user_id, const char *x509_anchors, - char * const * chain, - char * const * revoke, + char * const * pool, + char * const * pki_revoke, int flags, krb5_prompter_fct prompter, void *prompter_data, @@ -1778,6 +1803,7 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, { #ifdef PKINIT krb5_error_code ret; + char *anchors = NULL; if (opt->opt_private == NULL) { krb5_set_error_string(context, "PKINIT: on non extendable opt"); @@ -1797,12 +1823,33 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, opt->opt_private->pk_init_ctx->require_eku = 1; opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1; + + /* XXX implement krb5_appdefault_strings */ + if (pool == NULL) + pool = krb5_config_get_strings(context, NULL, + "appdefaults", + "pkinit-pool", + NULL); + + if (pki_revoke == NULL) + pki_revoke = krb5_config_get_strings(context, NULL, + "appdefaults", + "pkinit-revoke", + NULL); + + if (x509_anchors == NULL) { + krb5_appdefault_string(context, "kinit", + krb5_principal_get_realm(context, principal), + "pkinit-anchors", NULL, &anchors); + x509_anchors = anchors; + } + ret = _krb5_pk_load_id(context, &opt->opt_private->pk_init_ctx->id, user_id, x509_anchors, - chain, - revoke, + pool, + pki_revoke, prompter, prompter_data, password); diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index f6e3847cce..4d13e7db11 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -41,7 +41,7 @@ #include #include "resolve.h" -RCSID("$Id: principal.c,v 1.95 2006/04/24 15:16:14 lha Exp $"); +RCSID("$Id: principal.c,v 1.99 2006/10/18 06:53:22 lha Exp $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -91,17 +91,11 @@ krb5_principal_get_comp_string(krb5_context context, return princ_ncomp(principal, component); } -enum realm_presence { - MAY, - MUSTNOT, - MUST -}; - -static krb5_error_code -parse_name(krb5_context context, - const char *name, - enum realm_presence realm_presence, - krb5_principal *principal) +krb5_error_code KRB5_LIB_FUNCTION +krb5_parse_name_flags(krb5_context context, + const char *name, + int flags, + krb5_principal *principal) { krb5_error_code ret; heim_general_string *comp; @@ -117,6 +111,17 @@ parse_name(krb5_context context, char c; int got_realm = 0; + *principal = NULL; + +#define RFLAGS (KRB5_PRINCIPAL_PARSE_NO_REALM|KRB5_PRINCIPAL_PARSE_MUST_REALM) + + if ((flags & RFLAGS) == RFLAGS) { + krb5_set_error_string(context, "Can't require both realm and " + "no realm at the same time"); + return KRB5_ERR_NO_SERVICE; + } +#undef RFLAGS + /* count number of component */ ncomp = 1; for(p = name; *p; p++){ @@ -191,32 +196,33 @@ parse_name(krb5_context context, } *q++ = c; } - if (got_realm) { - if (realm_presence == MUSTNOT) { - krb5_set_error_string (context, "realm found in 'short' principal expected to be without one!"); + if(got_realm){ + if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { + krb5_set_error_string (context, "realm found in 'short' principal " + "expected to be without one"); ret = KRB5_PARSE_MALFORMED; goto exit; - } else { - realm = malloc(q - start + 1); - if (realm == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); - ret = ENOMEM; - goto exit; - } - memcpy(realm, start, q - start); - realm[q - start] = 0; } + realm = malloc(q - start + 1); + if (realm == NULL) { + krb5_set_error_string (context, "malloc: out of memory"); + ret = ENOMEM; + goto exit; + } + memcpy(realm, start, q - start); + realm[q - start] = 0; }else{ - if (realm_presence == MAY) { - ret = krb5_get_default_realm (context, &realm); - if (ret) - goto exit; - } else if (realm_presence == MUSTNOT) { - realm = NULL; - } else if (realm_presence == MUST) { - krb5_set_error_string (context, "realm NOT found in principal expected to be with one!"); + if (flags & KRB5_PRINCIPAL_PARSE_MUST_REALM) { + krb5_set_error_string (context, "realm NOT found in principal " + "expected to be with one"); ret = KRB5_PARSE_MALFORMED; goto exit; + } else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { + realm = NULL; + } else { + ret = krb5_get_default_realm (context, &realm); + if (ret) + goto exit; } comp[n] = malloc(q - start + 1); @@ -256,24 +262,9 @@ krb5_parse_name(krb5_context context, const char *name, krb5_principal *principal) { - return parse_name(context, name, MAY, principal); + return krb5_parse_name_flags(context, name, 0, principal); } -krb5_error_code KRB5_LIB_FUNCTION -krb5_parse_name_norealm(krb5_context context, - const char *name, - krb5_principal *principal) -{ - return parse_name(context, name, MUSTNOT, principal); -} - -krb5_error_code KRB5_LIB_FUNCTION -krb5_parse_name_mustrealm(krb5_context context, - const char *name, - krb5_principal *principal) -{ - return parse_name(context, name, MUST, principal); -} static const char quotable_chars[] = " \n\t\b\\/@"; static const char replace_chars[] = " ntb\\/@"; @@ -301,23 +292,47 @@ unparse_name_fixed(krb5_context context, krb5_const_principal principal, char *name, size_t len, - krb5_boolean short_form) + int flags) { size_t idx = 0; int i; + int short_form = (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) != 0; + int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0; + + if (!no_realm && princ_realm(principal) == NULL) { + krb5_set_error_string(context, "Realm missing from principal, " + "can't unparse"); + return ERANGE; + } + for(i = 0; i < princ_num_comp(principal); i++){ if(i) add_char(name, idx, len, '/'); idx = quote_string(princ_ncomp(principal, i), name, idx, len); - if(idx == len) + if(idx == len) { + krb5_set_error_string(context, "Out of space printing principal"); return ERANGE; + } } /* add realm if different from default realm */ - if(!short_form) { + if(short_form && !no_realm) { + krb5_realm r; + krb5_error_code ret; + ret = krb5_get_default_realm(context, &r); + if(ret) + return ret; + if(strcmp(princ_realm(principal), r) != 0) + short_form = 0; + free(r); + } + if(!short_form && !no_realm) { add_char(name, idx, len, '@'); idx = quote_string(princ_realm(principal), name, idx, len); - if(idx == len) + if(idx == len) { + krb5_set_error_string(context, + "Out of space printing realm of principal"); return ERANGE; + } } return 0; } @@ -328,57 +343,48 @@ krb5_unparse_name_fixed(krb5_context context, char *name, size_t len) { - return unparse_name_fixed(context, principal, name, len, FALSE); + return unparse_name_fixed(context, principal, name, len, 0); } krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_norealm_fixed(krb5_context context, - krb5_const_principal principal, - char *name, - size_t len) +krb5_unparse_name_fixed_short(krb5_context context, + krb5_const_principal principal, + char *name, + size_t len) { - return unparse_name_fixed(context, principal, name, len, TRUE); + return unparse_name_fixed(context, principal, name, len, + KRB5_PRINCIPAL_UNPARSE_SHORT); } krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_fixed_short(krb5_context context, +krb5_unparse_name_fixed_flags(krb5_context context, krb5_const_principal principal, + int flags, char *name, size_t len) { - krb5_realm r; - krb5_error_code ret; - krb5_boolean short_form = TRUE; - ret = krb5_get_default_realm(context, &r); - if(ret) - return ret; - if(strcmp(princ_realm(principal), r) != 0) - short_form = 0; - free(r); - return unparse_name_fixed(context, principal, name, len, short_form); + return unparse_name_fixed(context, principal, name, len, flags); } static krb5_error_code unparse_name(krb5_context context, krb5_const_principal principal, char **name, - krb5_boolean short_flag) + int flags) { size_t len = 0, plen; int i; krb5_error_code ret; /* count length */ - if (!short_flag) { + if (princ_realm(principal)) { plen = strlen(princ_realm(principal)); + if(strcspn(princ_realm(principal), quotable_chars) == plen) len += plen; else len += 2*plen; - len++; - } else { - len = 0; + len++; /* '@' */ } - for(i = 0; i < princ_num_comp(principal); i++){ plen = strlen(princ_ncomp(principal, i)); if(strcspn(princ_ncomp(principal, i), quotable_chars) == plen) @@ -387,13 +393,13 @@ unparse_name(krb5_context context, len += 2*plen; len++; } - len++; + len++; /* '\0' */ *name = malloc(len); if(*name == NULL) { krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } - ret = unparse_name_fixed(context, principal, *name, len, short_flag); + ret = unparse_name_fixed(context, principal, *name, len, flags); if(ret) { free(*name); *name = NULL; @@ -406,32 +412,24 @@ krb5_unparse_name(krb5_context context, krb5_const_principal principal, char **name) { - return unparse_name(context, principal, name, FALSE); + return unparse_name(context, principal, name, 0); } krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_short(krb5_context context, +krb5_unparse_name_flags(krb5_context context, krb5_const_principal principal, + int flags, char **name) { - krb5_realm r; - krb5_error_code ret; - krb5_boolean short_form = TRUE; - ret = krb5_get_default_realm(context, &r); - if(ret) - return ret; - if(strcmp(princ_realm(principal), r) != 0) - short_form = 0; - free(r); - return unparse_name(context, principal, name, short_form); + return unparse_name(context, principal, name, flags); } krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_norealm(krb5_context context, - krb5_const_principal principal, - char **name) +krb5_unparse_name_short(krb5_context context, + krb5_const_principal principal, + char **name) { - return unparse_name(context, principal, name, TRUE); + return unparse_name(context, principal, name, KRB5_PRINCIPAL_UNPARSE_SHORT); } #if 0 /* not implemented */ @@ -447,7 +445,7 @@ krb5_unparse_name_ext(krb5_context context, #endif -krb5_realm* KRB5_LIB_FUNCTION +krb5_realm * KRB5_LIB_FUNCTION krb5_princ_realm(krb5_context context, krb5_principal principal) { @@ -455,7 +453,6 @@ krb5_princ_realm(krb5_context context, } - void KRB5_LIB_FUNCTION krb5_princ_set_realm(krb5_context context, krb5_principal principal, diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c index 01b5188bae..46a36c9aac 100644 --- a/source4/heimdal/lib/krb5/rd_cred.c +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_cred.c,v 1.28 2006/04/02 02:27:33 lha Exp $"); +RCSID("$Id: rd_cred.c,v 1.29 2006/10/06 17:04:47 lha Exp $"); static krb5_error_code compare_addrs(krb5_context context, @@ -265,7 +265,8 @@ krb5_rd_cred(krb5_context context, krb5_abortx(context, "internal error in ASN.1 encoder"); copy_EncryptionKey (&kci->key, &creds->session); if (kci->prealm && kci->pname) - _krb5_principalname2krb5_principal (context, &creds->client, + _krb5_principalname2krb5_principal (context, + &creds->client, *kci->pname, *kci->prealm); if (kci->flags) diff --git a/source4/heimdal/lib/krb5/rd_rep.c b/source4/heimdal/lib/krb5/rd_rep.c index 53138d9f45..6b7f27c3cf 100644 --- a/source4/heimdal/lib/krb5/rd_rep.c +++ b/source4/heimdal/lib/krb5/rd_rep.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_rep.c,v 1.25 2005/06/17 07:49:33 lha Exp $"); +RCSID("$Id: rd_rep.c,v 1.26 2006/08/21 09:19:22 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_rep(krb5_context context, @@ -92,7 +92,10 @@ krb5_rd_rep(krb5_context context, if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) { if ((*repl)->ctime != auth_context->authenticator->ctime || - (*repl)->cusec != auth_context->authenticator->cusec) { + (*repl)->cusec != auth_context->authenticator->cusec) + { + krb5_free_ap_rep_enc_part(context, *repl); + *repl = NULL; ret = KRB5KRB_AP_ERR_MUT_FAIL; krb5_clear_error_string (context); goto out; @@ -114,6 +117,8 @@ void KRB5_LIB_FUNCTION krb5_free_ap_rep_enc_part (krb5_context context, krb5_ap_rep_enc_part *val) { - free_EncAPRepPart (val); - free (val); + if (val) { + free_EncAPRepPart (val); + free (val); + } } diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index c0bb710a59..c424a73a34 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001, 2003 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2001, 2003 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_req.c,v 1.63 2006/04/10 10:14:44 lha Exp $"); +RCSID("$Id: rd_req.c,v 1.66 2006/10/06 17:04:29 lha Exp $"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, @@ -376,12 +376,14 @@ krb5_verify_ap_req2(krb5_context context, if(ret) goto out; - ret = _krb5_principalname2krb5_principal(context, - &t->server, ap_req->ticket.sname, + ret = _krb5_principalname2krb5_principal(context, + &t->server, + ap_req->ticket.sname, ap_req->ticket.realm); if (ret) goto out; - ret = _krb5_principalname2krb5_principal(context, - &t->client, t->ticket.cname, + ret = _krb5_principalname2krb5_principal(context, + &t->client, + t->ticket.cname, t->ticket.crealm); if (ret) goto out; @@ -402,10 +404,12 @@ krb5_verify_ap_req2(krb5_context context, krb5_principal p1, p2; krb5_boolean res; - _krb5_principalname2krb5_principal(context, &p1, + _krb5_principalname2krb5_principal(context, + &p1, ac->authenticator->cname, ac->authenticator->crealm); - _krb5_principalname2krb5_principal(context, &p2, + _krb5_principalname2krb5_principal(context, + &p2, t->ticket.cname, t->ticket.crealm); res = krb5_principal_compare (context, p1, p2); @@ -607,7 +611,8 @@ krb5_rd_req_return_keyblock(krb5_context context, return ret; if(server == NULL){ - _krb5_principalname2krb5_principal(context, &service, + _krb5_principalname2krb5_principal(context, + &service, ap_req.ticket.sname, ap_req.ticket.realm); server = service; diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index 0bcafa70a1..11c07c9e8f 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -33,32 +33,13 @@ #include "krb5_locl.h" -RCSID("$Id: send_to_kdc.c,v 1.58 2006/04/02 02:32:03 lha Exp $"); +RCSID("$Id: send_to_kdc.c,v 1.60 2006/10/20 18:42:01 lha Exp $"); -struct send_and_recv { - krb5_send_and_recv_func_t func; - krb5_send_and_recv_close_func_t close; - void *data; +struct send_to_kdc { + krb5_send_to_kdc_func func; + void *data; }; -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_send_recv_func(krb5_context context, - krb5_send_and_recv_func_t func, - krb5_send_and_recv_close_func_t close_fn, - void *data) -{ - free(context->send_and_recv); - context->send_and_recv = malloc(sizeof(*context->send_and_recv)); - if (!context->send_and_recv) { - return ENOMEM; - } - context->send_and_recv->func = func; - context->send_and_recv->close = close_fn; - context->send_and_recv->data = data; - return 0; -} - - /* * send the data in `req' on the socket `fd' (which is datagram iff udp) * waiting `tmout' for a reply and returning the reply in `rep'. @@ -346,7 +327,7 @@ krb5_sendto (krb5_context context, krb5_krbhst_handle handle, krb5_data *receive) { - krb5_error_code ret = 0; + krb5_error_code ret; int fd; int i; @@ -356,27 +337,22 @@ krb5_sendto (krb5_context context, while (krb5_krbhst_next(context, handle, &hi) == 0) { struct addrinfo *ai, *a; - if (context->send_and_recv) { - ret = context->send_and_recv->func(context, - context->send_and_recv->data, - hi, send_data, receive); - if (ret) { - continue; - } else if (receive->length != 0) { - return 0; - } else { - continue; - } + if (context->send_to_kdc) { + struct send_to_kdc *s = context->send_to_kdc; + + ret = (*s->func)(context, s->data, + hi, send_data, receive); + if (ret == 0 && receive->length != 0) + goto out; + continue; } if(hi->proto == KRB5_KRBHST_HTTP && context->http_proxy) { - if (send_via_proxy (context, hi, send_data, receive)) { - /* Try again, with next host */ - continue; - } else { - /* Success */ - return 0; + if (send_via_proxy (context, hi, send_data, receive) == 0) { + ret = 0; + goto out; } + continue; } ret = krb5_krbhst_get_addrinfo(context, hi, &ai); @@ -406,15 +382,16 @@ krb5_sendto (krb5_context context, break; } close (fd); - if(ret == 0 && receive->length != 0) { - return 0; - } + if(ret == 0 && receive->length != 0) + goto out; } } krb5_krbhst_reset(context, handle); } krb5_clear_error_string (context); - return KRB5_KDC_UNREACH; + ret = KRB5_KDC_UNREACH; +out: + return ret; } krb5_error_code KRB5_LIB_FUNCTION @@ -456,3 +433,27 @@ krb5_sendto_kdc_flags(krb5_context context, "unable to reach any KDC in realm %s", *realm); return ret; } + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_send_to_kdc_func(krb5_context context, + krb5_send_to_kdc_func func, + void *data) +{ + free(context->send_to_kdc); + if (func == NULL) { + context->send_to_kdc = NULL; + return 0; + } + + context->send_to_kdc = malloc(sizeof(*context->send_to_kdc)); + if (context->send_to_kdc == NULL) { + krb5_set_error_string(context, "Out of memory"); + return ENOMEM; + } + + context->send_to_kdc->func = func; + context->send_to_kdc->data = data; + return 0; +} + + diff --git a/source4/heimdal/lib/krb5/set_default_realm.c b/source4/heimdal/lib/krb5/set_default_realm.c index fd57b6fe67..965883309c 100644 --- a/source4/heimdal/lib/krb5/set_default_realm.c +++ b/source4/heimdal/lib/krb5/set_default_realm.c @@ -77,19 +77,8 @@ krb5_set_default_realm(krb5_context context, "libdefaults", "default_realm", NULL); - if (realms == NULL) { - char hostname[MAXHOSTNAMELEN]; - if (gethostname (hostname, sizeof(hostname))) { - return errno; - } - - if (strchr(hostname, '.') == NULL) { - /* There is no way we can get this mapping, as we can't do DNS */ - return KRB5_CONFIG_NODEFREALM; - } - ret = krb5_get_host_realm(context, hostname, - &realms); - } + if (realms == NULL) + ret = krb5_get_host_realm(context, NULL, &realms); } else { ret = string_to_list (context, realm, &realms); } diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c index a6f4a011a1..e75f28ca5f 100644 --- a/source4/heimdal/lib/krb5/store.c +++ b/source4/heimdal/lib/krb5/store.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store.c,v 1.58 2006/05/05 07:15:18 lha Exp $"); +RCSID("$Id: store.c,v 1.59 2006/08/18 08:39:13 lha Exp $"); #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) @@ -440,6 +440,76 @@ krb5_ret_stringz(krb5_storage *sp, return 0; } +krb5_error_code KRB5_LIB_FUNCTION +krb5_store_stringnl(krb5_storage *sp, const char *s) +{ + size_t len = strlen(s); + ssize_t ret; + + ret = sp->store(sp, s, len); + if(ret != len) { + if(ret < 0) + return ret; + else + return sp->eof_code; + } + ret = sp->store(sp, "\n", 1); + if(ret != 1) { + if(ret < 0) + return ret; + else + return sp->eof_code; + } + + return 0; + +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_ret_stringnl(krb5_storage *sp, + char **string) +{ + int expect_nl = 0; + char c; + char *s = NULL; + size_t len = 0; + ssize_t ret; + + while((ret = sp->fetch(sp, &c, 1)) == 1){ + char *tmp; + + if (c == '\r') { + expect_nl = 1; + continue; + } + if (expect_nl && c != '\n') { + free(s); + return KRB5_BADMSGTYPE; + } + + len++; + tmp = realloc (s, len); + if (tmp == NULL) { + free (s); + return ENOMEM; + } + s = tmp; + if(c == '\n') { + s[len - 1] = '\0'; + break; + } + s[len - 1] = c; + } + if(ret != 1){ + free(s); + if(ret == 0) + return sp->eof_code; + return ret; + } + *string = s; + return 0; +} + krb5_error_code KRB5_LIB_FUNCTION krb5_store_principal(krb5_storage *sp, diff --git a/source4/heimdal/lib/krb5/store_fd.c b/source4/heimdal/lib/krb5/store_fd.c index 46043a6761..835d3478e2 100644 --- a/source4/heimdal/lib/krb5/store_fd.c +++ b/source4/heimdal/lib/krb5/store_fd.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store_fd.c,v 1.12 2004/05/25 21:43:57 lha Exp $"); +RCSID("$Id: store_fd.c,v 1.13 2006/06/30 21:23:19 lha Exp $"); typedef struct fd_storage { int fd; @@ -74,13 +74,16 @@ krb5_storage_from_fd(int fd) fd = dup(fd); if (fd < 0) return NULL; - sp = malloc(sizeof(krb5_storage)); - if (sp == NULL) + sp = malloc(sizeof(krb5_storage)); + if (sp == NULL) { + close(fd); return NULL; + } sp->data = malloc(sizeof(fd_storage)); if (sp->data == NULL) { + close(fd); free(sp); return NULL; } diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c index 99cb778722..fdc2a1b3a5 100644 --- a/source4/heimdal/lib/krb5/ticket.c +++ b/source4/heimdal/lib/krb5/ticket.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: ticket.c,v 1.14 2005/10/27 13:21:42 lha Exp $"); +RCSID("$Id: ticket.c,v 1.15 2006/10/14 09:53:19 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_free_ticket(krb5_context context, @@ -107,12 +107,16 @@ find_type_in_ad(krb5_context context, const AuthorizationData *ad, int level) { - krb5_error_code ret = ENOENT; + /* It is not an error if nothing in here, that is reported by *found */ + /* Setting a default error causes found to be set to FALSE, on + * recursion to an second embedded authz data even if the first + * element contains the required type */ + krb5_error_code ret = 0; int i; if (level > 9) { krb5_set_error_string(context, "Authorization data nested deeper " - "than %d levels, stop searching", level); + "then %d levels, stop searching", level); ret = ENOENT; /* XXX */ goto out; } @@ -124,7 +128,7 @@ find_type_in_ad(krb5_context context, */ for (i = 0; i < ad->len; i++) { if (!*found && ad->val[i].ad_type == type) { - ret = copy_octet_string(&ad->val[i].ad_data, data); + ret = der_copy_octet_string(&ad->val[i].ad_data, data); if (ret) { krb5_set_error_string(context, "malloc - out of memory"); goto out; -- cgit From 601f0e63166d1cbae59bbfd397f2daac4d0de285 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 7 Nov 2006 10:40:50 +0000 Subject: r19606: Remove generated files Andrew Bartlett (This used to be commit 7b7e1fe15358d9ed1893305fbf8a1010293ed772) --- source4/heimdal/lib/krb5/heim_err.c | 162 --------------------- source4/heimdal/lib/krb5/k524_err.c | 30 ---- source4/heimdal/lib/krb5/krb5_err.c | 271 ------------------------------------ 3 files changed, 463 deletions(-) delete mode 100644 source4/heimdal/lib/krb5/heim_err.c delete mode 100644 source4/heimdal/lib/krb5/k524_err.c delete mode 100644 source4/heimdal/lib/krb5/krb5_err.c (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/heim_err.c b/source4/heimdal/lib/krb5/heim_err.c deleted file mode 100644 index f72a265ba9..0000000000 --- a/source4/heimdal/lib/krb5/heim_err.c +++ /dev/null @@ -1,162 +0,0 @@ -/* Generated from heim_err.et */ -/* $Id: heim_err.et,v 1.13 2004/02/13 16:23:40 lha Exp $ */ - -#include -#include -#include "heim_err.h" - -static const char *heim_error_strings[] = { - /* 000 */ "Error parsing log destination", - /* 001 */ "Failed to convert v4 principal", - /* 002 */ "Salt type is not supported by enctype", - /* 003 */ "Host not found", - /* 004 */ "Operation not supported", - /* 005 */ "End of file", - /* 006 */ "Failed to get the master key", - /* 007 */ "Unacceptable service used", - /* 008 */ "Reserved heim error (8)", - /* 009 */ "Reserved heim error (9)", - /* 010 */ "Reserved heim error (10)", - /* 011 */ "Reserved heim error (11)", - /* 012 */ "Reserved heim error (12)", - /* 013 */ "Reserved heim error (13)", - /* 014 */ "Reserved heim error (14)", - /* 015 */ "Reserved heim error (15)", - /* 016 */ "Reserved heim error (16)", - /* 017 */ "Reserved heim error (17)", - /* 018 */ "Reserved heim error (18)", - /* 019 */ "Reserved heim error (19)", - /* 020 */ "Reserved heim error (20)", - /* 021 */ "Reserved heim error (21)", - /* 022 */ "Reserved heim error (22)", - /* 023 */ "Reserved heim error (23)", - /* 024 */ "Reserved heim error (24)", - /* 025 */ "Reserved heim error (25)", - /* 026 */ "Reserved heim error (26)", - /* 027 */ "Reserved heim error (27)", - /* 028 */ "Reserved heim error (28)", - /* 029 */ "Reserved heim error (29)", - /* 030 */ "Reserved heim error (30)", - /* 031 */ "Reserved heim error (31)", - /* 032 */ "Reserved heim error (32)", - /* 033 */ "Reserved heim error (33)", - /* 034 */ "Reserved heim error (34)", - /* 035 */ "Reserved heim error (35)", - /* 036 */ "Reserved heim error (36)", - /* 037 */ "Reserved heim error (37)", - /* 038 */ "Reserved heim error (38)", - /* 039 */ "Reserved heim error (39)", - /* 040 */ "Reserved heim error (40)", - /* 041 */ "Reserved heim error (41)", - /* 042 */ "Reserved heim error (42)", - /* 043 */ "Reserved heim error (43)", - /* 044 */ "Reserved heim error (44)", - /* 045 */ "Reserved heim error (45)", - /* 046 */ "Reserved heim error (46)", - /* 047 */ "Reserved heim error (47)", - /* 048 */ "Reserved heim error (48)", - /* 049 */ "Reserved heim error (49)", - /* 050 */ "Reserved heim error (50)", - /* 051 */ "Reserved heim error (51)", - /* 052 */ "Reserved heim error (52)", - /* 053 */ "Reserved heim error (53)", - /* 054 */ "Reserved heim error (54)", - /* 055 */ "Reserved heim error (55)", - /* 056 */ "Reserved heim error (56)", - /* 057 */ "Reserved heim error (57)", - /* 058 */ "Reserved heim error (58)", - /* 059 */ "Reserved heim error (59)", - /* 060 */ "Reserved heim error (60)", - /* 061 */ "Reserved heim error (61)", - /* 062 */ "Reserved heim error (62)", - /* 063 */ "Reserved heim error (63)", - /* 064 */ "Certificate missing", - /* 065 */ "Private key missing", - /* 066 */ "No valid certificate authority", - /* 067 */ "Certificate invalid", - /* 068 */ "Private key invalid", - /* 069 */ "Reserved heim error (69)", - /* 070 */ "Reserved heim error (70)", - /* 071 */ "Reserved heim error (71)", - /* 072 */ "Reserved heim error (72)", - /* 073 */ "Reserved heim error (73)", - /* 074 */ "Reserved heim error (74)", - /* 075 */ "Reserved heim error (75)", - /* 076 */ "Reserved heim error (76)", - /* 077 */ "Reserved heim error (77)", - /* 078 */ "Reserved heim error (78)", - /* 079 */ "Reserved heim error (79)", - /* 080 */ "Reserved heim error (80)", - /* 081 */ "Reserved heim error (81)", - /* 082 */ "Reserved heim error (82)", - /* 083 */ "Reserved heim error (83)", - /* 084 */ "Reserved heim error (84)", - /* 085 */ "Reserved heim error (85)", - /* 086 */ "Reserved heim error (86)", - /* 087 */ "Reserved heim error (87)", - /* 088 */ "Reserved heim error (88)", - /* 089 */ "Reserved heim error (89)", - /* 090 */ "Reserved heim error (90)", - /* 091 */ "Reserved heim error (91)", - /* 092 */ "Reserved heim error (92)", - /* 093 */ "Reserved heim error (93)", - /* 094 */ "Reserved heim error (94)", - /* 095 */ "Reserved heim error (95)", - /* 096 */ "Reserved heim error (96)", - /* 097 */ "Reserved heim error (97)", - /* 098 */ "Reserved heim error (98)", - /* 099 */ "Reserved heim error (99)", - /* 100 */ "Reserved heim error (100)", - /* 101 */ "Reserved heim error (101)", - /* 102 */ "Reserved heim error (102)", - /* 103 */ "Reserved heim error (103)", - /* 104 */ "Reserved heim error (104)", - /* 105 */ "Reserved heim error (105)", - /* 106 */ "Reserved heim error (106)", - /* 107 */ "Reserved heim error (107)", - /* 108 */ "Reserved heim error (108)", - /* 109 */ "Reserved heim error (109)", - /* 110 */ "Reserved heim error (110)", - /* 111 */ "Reserved heim error (111)", - /* 112 */ "Reserved heim error (112)", - /* 113 */ "Reserved heim error (113)", - /* 114 */ "Reserved heim error (114)", - /* 115 */ "Reserved heim error (115)", - /* 116 */ "Reserved heim error (116)", - /* 117 */ "Reserved heim error (117)", - /* 118 */ "Reserved heim error (118)", - /* 119 */ "Reserved heim error (119)", - /* 120 */ "Reserved heim error (120)", - /* 121 */ "Reserved heim error (121)", - /* 122 */ "Reserved heim error (122)", - /* 123 */ "Reserved heim error (123)", - /* 124 */ "Reserved heim error (124)", - /* 125 */ "Reserved heim error (125)", - /* 126 */ "Reserved heim error (126)", - /* 127 */ "Reserved heim error (127)", - /* 128 */ "unknown error from getaddrinfo", - /* 129 */ "address family for nodename not supported", - /* 130 */ "temporary failure in name resolution", - /* 131 */ "invalid value for ai_flags", - /* 132 */ "non-recoverable failure in name resolution", - /* 133 */ "ai_family not supported", - /* 134 */ "memory allocation failure", - /* 135 */ "no address associated with nodename", - /* 136 */ "nodename nor servname provided, or not known", - /* 137 */ "servname not supported for ai_socktype", - /* 138 */ "ai_socktype not supported", - /* 139 */ "system error returned in errno", - NULL -}; - -#define num_errors 140 - -void initialize_heim_error_table_r(struct et_list **list) -{ - initialize_error_table_r(list, heim_error_strings, num_errors, ERROR_TABLE_BASE_heim); -} - -void initialize_heim_error_table(void) -{ - init_error_table(heim_error_strings, ERROR_TABLE_BASE_heim, num_errors); -} diff --git a/source4/heimdal/lib/krb5/k524_err.c b/source4/heimdal/lib/krb5/k524_err.c deleted file mode 100644 index 266d3ee577..0000000000 --- a/source4/heimdal/lib/krb5/k524_err.c +++ /dev/null @@ -1,30 +0,0 @@ -/* Generated from k524_err.et */ -/* $Id: k524_err.et,v 1.1 2001/06/20 02:44:11 joda Exp $ */ - -#include -#include -#include "k524_err.h" - -static const char *k524_error_strings[] = { - /* 000 */ "wrong keytype in ticket", - /* 001 */ "incorrect network address", - /* 002 */ "cannot convert V5 principal", - /* 003 */ "V5 realm name longer than V4 maximum", - /* 004 */ "kerberos V4 error server", - /* 005 */ "encoding too large at server", - /* 006 */ "decoding out of data", - /* 007 */ "service not responding", - NULL -}; - -#define num_errors 8 - -void initialize_k524_error_table_r(struct et_list **list) -{ - initialize_error_table_r(list, k524_error_strings, num_errors, ERROR_TABLE_BASE_k524); -} - -void initialize_k524_error_table(void) -{ - init_error_table(k524_error_strings, ERROR_TABLE_BASE_k524, num_errors); -} diff --git a/source4/heimdal/lib/krb5/krb5_err.c b/source4/heimdal/lib/krb5/krb5_err.c deleted file mode 100644 index 9185f729d5..0000000000 --- a/source4/heimdal/lib/krb5/krb5_err.c +++ /dev/null @@ -1,271 +0,0 @@ -/* Generated from krb5_err.et */ -/* $Id: krb5_err.et,v 1.14 2006/02/13 11:28:22 lha Exp $ */ - -#include -#include -#include "krb5_err.h" - -static const char *krb5_error_strings[] = { - /* 000 */ "No error", - /* 001 */ "Client's entry in database has expired", - /* 002 */ "Server's entry in database has expired", - /* 003 */ "Requested protocol version not supported", - /* 004 */ "Client's key is encrypted in an old master key", - /* 005 */ "Server's key is encrypted in an old master key", - /* 006 */ "Client not found in Kerberos database", - /* 007 */ "Server not found in Kerberos database", - /* 008 */ "Principal has multiple entries in Kerberos database", - /* 009 */ "Client or server has a null key", - /* 010 */ "Ticket is ineligible for postdating", - /* 011 */ "Requested effective lifetime is negative or too short", - /* 012 */ "KDC policy rejects request", - /* 013 */ "KDC can't fulfill requested option", - /* 014 */ "KDC has no support for encryption type", - /* 015 */ "KDC has no support for checksum type", - /* 016 */ "KDC has no support for padata type", - /* 017 */ "KDC has no support for transited type", - /* 018 */ "Clients credentials have been revoked", - /* 019 */ "Credentials for server have been revoked", - /* 020 */ "TGT has been revoked", - /* 021 */ "Client not yet valid - try again later", - /* 022 */ "Server not yet valid - try again later", - /* 023 */ "Password has expired", - /* 024 */ "Preauthentication failed", - /* 025 */ "Additional pre-authentication required", - /* 026 */ "Requested server and ticket don't match", - /* 027 */ "Reserved krb5 error (27)", - /* 028 */ "Reserved krb5 error (28)", - /* 029 */ "Reserved krb5 error (29)", - /* 030 */ "Reserved krb5 error (30)", - /* 031 */ "Decrypt integrity check failed", - /* 032 */ "Ticket expired", - /* 033 */ "Ticket not yet valid", - /* 034 */ "Request is a replay", - /* 035 */ "The ticket isn't for us", - /* 036 */ "Ticket/authenticator don't match", - /* 037 */ "Clock skew too great", - /* 038 */ "Incorrect net address", - /* 039 */ "Protocol version mismatch", - /* 040 */ "Invalid message type", - /* 041 */ "Message stream modified", - /* 042 */ "Message out of order", - /* 043 */ "Invalid cross-realm ticket", - /* 044 */ "Key version is not available", - /* 045 */ "Service key not available", - /* 046 */ "Mutual authentication failed", - /* 047 */ "Incorrect message direction", - /* 048 */ "Alternative authentication method required", - /* 049 */ "Incorrect sequence number in message", - /* 050 */ "Inappropriate type of checksum in message", - /* 051 */ "Policy rejects transited path", - /* 052 */ "Response too big for UDP, retry with TCP", - /* 053 */ "Reserved krb5 error (53)", - /* 054 */ "Reserved krb5 error (54)", - /* 055 */ "Reserved krb5 error (55)", - /* 056 */ "Reserved krb5 error (56)", - /* 057 */ "Reserved krb5 error (57)", - /* 058 */ "Reserved krb5 error (58)", - /* 059 */ "Reserved krb5 error (59)", - /* 060 */ "Generic error (see e-text)", - /* 061 */ "Field is too long for this implementation", - /* 062 */ "Client not trusted", - /* 063 */ "KDC not trusted", - /* 064 */ "Invalid signature", - /* 065 */ "DH parameters not accepted", - /* 066 */ "Reserved krb5 error (66)", - /* 067 */ "Reserved krb5 error (67)", - /* 068 */ "Reserved krb5 error (68)", - /* 069 */ "User to user required", - /* 070 */ "Cannot verify certificate", - /* 071 */ "Certificate invalid", - /* 072 */ "Certificate revoked", - /* 073 */ "Revocation status unknown", - /* 074 */ "Revocation status unknown", - /* 075 */ "Inconsistent key purpose", - /* 076 */ "Digest in certificate not accepted", - /* 077 */ "paChecksum must be included", - /* 078 */ "Digest in signedData not accepted", - /* 079 */ "Public key encryption not supported", - /* 080 */ "Reserved krb5 error (80)", - /* 081 */ "Reserved krb5 error (81)", - /* 082 */ "Reserved krb5 error (82)", - /* 083 */ "Reserved krb5 error (83)", - /* 084 */ "Reserved krb5 error (84)", - /* 085 */ "Reserved krb5 error (85)", - /* 086 */ "Reserved krb5 error (86)", - /* 087 */ "Reserved krb5 error (87)", - /* 088 */ "Reserved krb5 error (88)", - /* 089 */ "Reserved krb5 error (89)", - /* 090 */ "Reserved krb5 error (90)", - /* 091 */ "Reserved krb5 error (91)", - /* 092 */ "Reserved krb5 error (92)", - /* 093 */ "Reserved krb5 error (93)", - /* 094 */ "Reserved krb5 error (94)", - /* 095 */ "Reserved krb5 error (95)", - /* 096 */ "Reserved krb5 error (96)", - /* 097 */ "Reserved krb5 error (97)", - /* 098 */ "Reserved krb5 error (98)", - /* 099 */ "Reserved krb5 error (99)", - /* 100 */ "Reserved krb5 error (100)", - /* 101 */ "Reserved krb5 error (101)", - /* 102 */ "Reserved krb5 error (102)", - /* 103 */ "Reserved krb5 error (103)", - /* 104 */ "Reserved krb5 error (104)", - /* 105 */ "Reserved krb5 error (105)", - /* 106 */ "Reserved krb5 error (106)", - /* 107 */ "Reserved krb5 error (107)", - /* 108 */ "Reserved krb5 error (108)", - /* 109 */ "Reserved krb5 error (109)", - /* 110 */ "Reserved krb5 error (110)", - /* 111 */ "Reserved krb5 error (111)", - /* 112 */ "Reserved krb5 error (112)", - /* 113 */ "Reserved krb5 error (113)", - /* 114 */ "Reserved krb5 error (114)", - /* 115 */ "Reserved krb5 error (115)", - /* 116 */ "Reserved krb5 error (116)", - /* 117 */ "Reserved krb5 error (117)", - /* 118 */ "Reserved krb5 error (118)", - /* 119 */ "Reserved krb5 error (119)", - /* 120 */ "Reserved krb5 error (120)", - /* 121 */ "Reserved krb5 error (121)", - /* 122 */ "Reserved krb5 error (122)", - /* 123 */ "Reserved krb5 error (123)", - /* 124 */ "Reserved krb5 error (124)", - /* 125 */ "Reserved krb5 error (125)", - /* 126 */ "Reserved krb5 error (126)", - /* 127 */ "Reserved krb5 error (127)", - /* 128 */ "$Id: krb5_err.et,v 1.14 2006/02/13 11:28:22 lha Exp $", - /* 129 */ "Invalid flag for file lock mode", - /* 130 */ "Cannot read password", - /* 131 */ "Password mismatch", - /* 132 */ "Password read interrupted", - /* 133 */ "Invalid character in component name", - /* 134 */ "Malformed representation of principal", - /* 135 */ "Can't open/find configuration file", - /* 136 */ "Improper format of configuration file", - /* 137 */ "Insufficient space to return complete information", - /* 138 */ "Invalid message type specified for encoding", - /* 139 */ "Credential cache name malformed", - /* 140 */ "Unknown credential cache type", - /* 141 */ "Matching credential not found", - /* 142 */ "End of credential cache reached", - /* 143 */ "Request did not supply a ticket", - /* 144 */ "Wrong principal in request", - /* 145 */ "Ticket has invalid flag set", - /* 146 */ "Requested principal and ticket don't match", - /* 147 */ "KDC reply did not match expectations", - /* 148 */ "Clock skew too great in KDC reply", - /* 149 */ "Client/server realm mismatch in initial ticket request", - /* 150 */ "Program lacks support for encryption type", - /* 151 */ "Program lacks support for key type", - /* 152 */ "Requested encryption type not used in message", - /* 153 */ "Program lacks support for checksum type", - /* 154 */ "Cannot find KDC for requested realm", - /* 155 */ "Kerberos service unknown", - /* 156 */ "Cannot contact any KDC for requested realm", - /* 157 */ "No local name found for principal name", - /* 158 */ "Mutual authentication failed", - /* 159 */ "Replay cache type is already registered", - /* 160 */ "No more memory to allocate (in replay cache code)", - /* 161 */ "Replay cache type is unknown", - /* 162 */ "Generic unknown RC error", - /* 163 */ "Message is a replay", - /* 164 */ "Replay I/O operation failed XXX", - /* 165 */ "Replay cache type does not support non-volatile storage", - /* 166 */ "Replay cache name parse/format error", - /* 167 */ "End-of-file on replay cache I/O", - /* 168 */ "No more memory to allocate (in replay cache I/O code)", - /* 169 */ "Permission denied in replay cache code", - /* 170 */ "I/O error in replay cache i/o code", - /* 171 */ "Generic unknown RC/IO error", - /* 172 */ "Insufficient system space to store replay information", - /* 173 */ "Can't open/find realm translation file", - /* 174 */ "Improper format of realm translation file", - /* 175 */ "Can't open/find lname translation database", - /* 176 */ "No translation available for requested principal", - /* 177 */ "Improper format of translation database entry", - /* 178 */ "Cryptosystem internal error", - /* 179 */ "Key table name malformed", - /* 180 */ "Unknown Key table type", - /* 181 */ "Key table entry not found", - /* 182 */ "End of key table reached", - /* 183 */ "Cannot write to specified key table", - /* 184 */ "Error writing to key table", - /* 185 */ "Cannot find ticket for requested realm", - /* 186 */ "DES key has bad parity", - /* 187 */ "DES key is a weak key", - /* 188 */ "Bad encryption type", - /* 189 */ "Key size is incompatible with encryption type", - /* 190 */ "Message size is incompatible with encryption type", - /* 191 */ "Credentials cache type is already registered.", - /* 192 */ "Key table type is already registered.", - /* 193 */ "Credentials cache I/O operation failed XXX", - /* 194 */ "Credentials cache file permissions incorrect", - /* 195 */ "No credentials cache file found", - /* 196 */ "Internal file credentials cache error", - /* 197 */ "Error writing to credentials cache file", - /* 198 */ "No more memory to allocate (in credentials cache code)", - /* 199 */ "Bad format in credentials cache", - /* 200 */ "No credentials found with supported encryption types", - /* 201 */ "Invalid KDC option combination (library internal error)", - /* 202 */ "Request missing second ticket", - /* 203 */ "No credentials supplied to library routine", - /* 204 */ "Bad sendauth version was sent", - /* 205 */ "Bad application version was sent (via sendauth)", - /* 206 */ "Bad response (during sendauth exchange)", - /* 207 */ "Server rejected authentication (during sendauth exchange)", - /* 208 */ "Unsupported preauthentication type", - /* 209 */ "Required preauthentication key not supplied", - /* 210 */ "Generic preauthentication failure", - /* 211 */ "Unsupported replay cache format version number", - /* 212 */ "Unsupported credentials cache format version number", - /* 213 */ "Unsupported key table format version number", - /* 214 */ "Program lacks support for address type", - /* 215 */ "Message replay detection requires rcache parameter", - /* 216 */ "Hostname cannot be canonicalized", - /* 217 */ "Cannot determine realm for host", - /* 218 */ "Conversion to service principal undefined for name type", - /* 219 */ "Initial Ticket response appears to be Version 4", - /* 220 */ "Cannot resolve KDC for requested realm", - /* 221 */ "Requesting ticket can't get forwardable tickets", - /* 222 */ "Bad principal name while trying to forward credentials", - /* 223 */ "Looping detected inside krb5_get_in_tkt", - /* 224 */ "Configuration file does not specify default realm", - /* 225 */ "Bad SAM flags in obtain_sam_padata", - /* 226 */ "Invalid encryption type in SAM challenge", - /* 227 */ "Missing checksum in SAM challenge", - /* 228 */ "Bad checksum in SAM challenge", - /* 229 */ "Reserved krb5 error (229)", - /* 230 */ "Reserved krb5 error (230)", - /* 231 */ "Reserved krb5 error (231)", - /* 232 */ "Reserved krb5 error (232)", - /* 233 */ "Reserved krb5 error (233)", - /* 234 */ "Reserved krb5 error (234)", - /* 235 */ "Reserved krb5 error (235)", - /* 236 */ "Reserved krb5 error (236)", - /* 237 */ "Reserved krb5 error (237)", - /* 238 */ "Program called an obsolete, deleted function", - /* 239 */ "Reserved krb5 error (239)", - /* 240 */ "Reserved krb5 error (240)", - /* 241 */ "Reserved krb5 error (241)", - /* 242 */ "Reserved krb5 error (242)", - /* 243 */ "Reserved krb5 error (243)", - /* 244 */ "Reserved krb5 error (244)", - /* 245 */ "Invalid key generation parameters from KDC", - /* 246 */ "Service not available", - /* 247 */ "Credential cache function not supported", - /* 248 */ "Invalid format of Kerberos lifetime or clock skew string", - NULL -}; - -#define num_errors 249 - -void initialize_krb5_error_table_r(struct et_list **list) -{ - initialize_error_table_r(list, krb5_error_strings, num_errors, ERROR_TABLE_BASE_krb5); -} - -void initialize_krb5_error_table(void) -{ - init_error_table(krb5_error_strings, ERROR_TABLE_BASE_krb5, num_errors); -} -- cgit From f722b0743811a4a5caf5288fa901cc8f683b9ffd Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 8 Nov 2006 01:48:35 +0000 Subject: r19633: Merge to lorikeet-heimdal, removing krb5_rd_req_return_keyblock in favour of a more tasteful replacement. Remove kerberos_verify.c, as we don't need that code any more. Replace with code for using the new krb5_rd_req_ctx() borrowed from Heimdal's accecpt_sec_context.c Andrew Bartlett (This used to be commit 13c9df1d4f0517468c80040d3756310d4dcbdd50) --- source4/heimdal/lib/krb5/context.c | 18 +- source4/heimdal/lib/krb5/expand_hostname.c | 2 +- source4/heimdal/lib/krb5/krb5-private.h | 5 + source4/heimdal/lib/krb5/krb5-protos.h | 63 ++++++- source4/heimdal/lib/krb5/krb5.h | 5 +- source4/heimdal/lib/krb5/rd_req.c | 294 ++++++++++++++++++++++------- 6 files changed, 304 insertions(+), 83 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index f7b3ffbf9e..a25bb80786 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: context.c,v 1.108 2006/10/20 22:26:10 lha Exp $"); +RCSID("$Id: context.c,v 1.110 2006/11/04 03:27:47 lha Exp $"); #define INIT_FIELD(C, T, E, D, F) \ (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ @@ -181,7 +181,7 @@ init_context_from_config_file(krb5_context context) INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup"); INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc"); INIT_FIELD(context, int, large_msg_size, 6000, "large_message_size"); - INIT_FIELD(context, bool, dns_canonicalize_hostname, TRUE, "dns_canonize_hostname"); + INIT_FIELD(context, bool, dns_canonicalize_hostname, TRUE, "dns_canonicalize_hostname"); context->default_cc_name = NULL; return 0; } @@ -691,7 +691,7 @@ krb5_set_dns_canonicalize_hostname (krb5_context context, krb5_boolean flag) } krb5_boolean KRB5_LIB_FUNCTION -krb5_get_dns_canonize_hostname (krb5_context context) +krb5_get_dns_canonicalize_hostname (krb5_context context) { return context->dns_canonicalize_hostname; } @@ -705,3 +705,15 @@ krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec) *usec = context->kdc_usec_offset; return 0; } + +time_t KRB5_LIB_FUNCTION +krb5_get_time_wrap (krb5_context context) +{ + return context->max_skew; +} + +void KRB5_LIB_FUNCTION +krb5_set_time_wrap (krb5_context context, time_t t) +{ + context->max_skew = t; +} diff --git a/source4/heimdal/lib/krb5/expand_hostname.c b/source4/heimdal/lib/krb5/expand_hostname.c index 4d0692bcfa..46e784f561 100644 --- a/source4/heimdal/lib/krb5/expand_hostname.c +++ b/source4/heimdal/lib/krb5/expand_hostname.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: expand_hostname.c,v 1.13 2006/10/17 09:16:32 lha Exp $"); +RCSID("$Id: expand_hostname.c,v 1.14 2006/11/04 03:34:57 lha Exp $"); static krb5_error_code copy_hostname(krb5_context context, diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 968b6079b7..0bf184a530 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -398,6 +398,11 @@ _krb5_put_int ( unsigned long /*value*/, size_t /*size*/); +krb5_error_code KRB5_LIB_FUNCTION +_krb5_rd_req_out_ctx_alloc ( + krb5_context /*context*/, + krb5_rd_req_out_ctx */*ctx*/); + krb5_error_code KRB5_LIB_FUNCTION _krb5_s4u2self_to_checksumdata ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 2010e25f5a..104f10bdf2 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -1866,7 +1866,7 @@ krb5_get_default_realms ( krb5_realm **/*realms*/); krb5_boolean KRB5_LIB_FUNCTION -krb5_get_dns_canonize_hostname (krb5_context /*context*/); +krb5_get_dns_canonicalize_hostname (krb5_context /*context*/); const char* KRB5_LIB_FUNCTION krb5_get_err_text ( @@ -2177,6 +2177,9 @@ krb5_get_server_rcache ( const krb5_data */*piece*/, krb5_rcache */*id*/); +time_t KRB5_LIB_FUNCTION +krb5_get_time_wrap (krb5_context /*context*/); + krb5_boolean KRB5_LIB_FUNCTION krb5_get_use_admin_kdc (krb5_context /*context*/); @@ -2865,15 +2868,58 @@ krb5_rd_req ( krb5_ticket **/*ticket*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req_return_keyblock ( +krb5_rd_req_ctx ( krb5_context /*context*/, krb5_auth_context */*auth_context*/, const krb5_data */*inbuf*/, krb5_const_principal /*server*/, - krb5_keytab /*keytab*/, - krb5_flags */*ap_req_options*/, - krb5_ticket **/*ticket*/, - krb5_keyblock **/*return_keyblock*/); + krb5_rd_req_in_ctx /*inctx*/, + krb5_rd_req_out_ctx */*outctx*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_ctx_alloc ( + krb5_context /*context*/, + krb5_rd_req_in_ctx */*ctx*/); + +void KRB5_LIB_FUNCTION +krb5_rd_req_in_ctx_free ( + krb5_context /*context*/, + krb5_rd_req_in_ctx /*ctx*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_set_keyblock ( + krb5_context /*context*/, + krb5_rd_req_in_ctx /*in*/, + krb5_keyblock */*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_set_keytab ( + krb5_context /*context*/, + krb5_rd_req_in_ctx /*in*/, + krb5_keytab /*keytab*/); + +void KRB5_LIB_FUNCTION +krb5_rd_req_out_ctx_free ( + krb5_context /*context*/, + krb5_rd_req_out_ctx /*ctx*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_out_get_ap_req_options ( + krb5_context /*context*/, + krb5_rd_req_out_ctx /*out*/, + krb5_flags */*ap_req_options*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_out_get_keyblock ( + krb5_context /*context*/, + krb5_rd_req_out_ctx /*out*/, + krb5_keyblock **/*keyblock*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_out_get_ticket ( + krb5_context /*context*/, + krb5_rd_req_out_ctx /*out*/, + krb5_ticket **/*ticket*/); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_req_with_keyblock ( @@ -3151,6 +3197,11 @@ krb5_set_send_to_kdc_func ( krb5_send_to_kdc_func /*func*/, void */*data*/); +void KRB5_LIB_FUNCTION +krb5_set_time_wrap ( + krb5_context /*context*/, + time_t /*t*/); + void KRB5_LIB_FUNCTION krb5_set_use_admin_kdc ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 4b5058094b..f5c8b069de 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h,v 1.253 2006/10/20 18:12:06 lha Exp $ */ +/* $Id: krb5.h,v 1.254 2006/11/07 00:17:42 lha Exp $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -78,6 +78,9 @@ typedef struct krb5_get_creds_opt_data *krb5_get_creds_opt; struct krb5_digest; typedef struct krb5_digest *krb5_digest; +typedef struct krb5_rd_req_in_ctx *krb5_rd_req_in_ctx; +typedef struct krb5_rd_req_out_ctx *krb5_rd_req_out_ctx; + typedef CKSUMTYPE krb5_cksumtype; typedef Checksum krb5_checksum; diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index c424a73a34..3352334f65 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001, 2003 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2001, 2003 - 2005 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_req.c,v 1.66 2006/10/06 17:04:29 lha Exp $"); +RCSID("$Id: rd_req.c,v 1.68 2006/11/07 17:11:31 lha Exp $"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, @@ -506,6 +506,151 @@ krb5_verify_ap_req2(krb5_context context, return ret; } +/* + * + */ + +struct krb5_rd_req_in_ctx { + krb5_keytab keytab; + krb5_keyblock *keyblock; +}; + +struct krb5_rd_req_out_ctx { + krb5_keyblock *keyblock; + krb5_flags ap_req_options; + krb5_ticket *ticket; +}; + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_ctx_alloc(krb5_context context, krb5_rd_req_in_ctx *ctx) +{ + *ctx = calloc(1, sizeof(**ctx)); + if (*ctx == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_set_keytab(krb5_context context, + krb5_rd_req_in_ctx in, + krb5_keytab keytab) +{ + in->keytab = keytab; /* XXX should make copy */ + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_set_keyblock(krb5_context context, + krb5_rd_req_in_ctx in, + krb5_keyblock *keyblock) +{ + in->keyblock = keyblock; /* XXX should make copy */ + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_out_get_ap_req_options(krb5_context context, + krb5_rd_req_out_ctx out, + krb5_flags *ap_req_options) +{ + *ap_req_options = out->ap_req_options; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_out_get_ticket(krb5_context context, + krb5_rd_req_out_ctx out, + krb5_ticket **ticket) +{ + return krb5_copy_ticket(context, out->ticket, ticket); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_out_get_keyblock(krb5_context context, + krb5_rd_req_out_ctx out, + krb5_keyblock **keyblock) +{ + return krb5_copy_keyblock(context, out->keyblock, keyblock); +} + +void KRB5_LIB_FUNCTION +krb5_rd_req_in_ctx_free(krb5_context context, krb5_rd_req_in_ctx ctx) +{ + free(ctx); +} + +krb5_error_code KRB5_LIB_FUNCTION +_krb5_rd_req_out_ctx_alloc(krb5_context context, krb5_rd_req_out_ctx *ctx) +{ + *ctx = calloc(1, sizeof(**ctx)); + if (*ctx == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +void KRB5_LIB_FUNCTION +krb5_rd_req_out_ctx_free(krb5_context context, krb5_rd_req_out_ctx ctx) +{ + krb5_free_keyblock(context, ctx->keyblock); + free(ctx); +} + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req(krb5_context context, + krb5_auth_context *auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_keytab keytab, + krb5_flags *ap_req_options, + krb5_ticket **ticket) +{ + krb5_error_code ret; + krb5_rd_req_in_ctx in; + krb5_rd_req_out_ctx out; + + ret = krb5_rd_req_in_ctx_alloc(context, &in); + if (ret) + return ret; + + ret = krb5_rd_req_in_set_keytab(context, in, keytab); + if (ret) { + krb5_rd_req_in_ctx_free(context, in); + return ret; + } + + ret = krb5_rd_req_ctx(context, auth_context, inbuf, server, in, &out); + krb5_rd_req_in_ctx_free(context, in); + if (ret) + return ret; + + if (ap_req_options) + *ap_req_options = out->ap_req_options; + if (ticket) { + ret = krb5_copy_ticket(context, out->ticket, ticket); + if (ret) + goto out; + } + +out: + krb5_rd_req_out_ctx_free(context, out); + return ret; +} + +/* + * + */ krb5_error_code KRB5_LIB_FUNCTION krb5_rd_req_with_keyblock(krb5_context context, @@ -517,31 +662,41 @@ krb5_rd_req_with_keyblock(krb5_context context, krb5_ticket **ticket) { krb5_error_code ret; - krb5_ap_req ap_req; + krb5_rd_req_in_ctx in; + krb5_rd_req_out_ctx out; - if (*auth_context == NULL) { - ret = krb5_auth_con_init(context, auth_context); - if (ret) - return ret; + ret = krb5_rd_req_in_ctx_alloc(context, &in); + if (ret) + return ret; + + ret = krb5_rd_req_in_set_keyblock(context, in, keyblock); + if (ret) { + krb5_rd_req_in_ctx_free(context, in); + return ret; } - ret = krb5_decode_ap_req(context, inbuf, &ap_req); - if(ret) + ret = krb5_rd_req_ctx(context, auth_context, inbuf, server, in, &out); + krb5_rd_req_in_ctx_free(context, in); + if (ret) return ret; - ret = krb5_verify_ap_req(context, - auth_context, - &ap_req, - server, - keyblock, - 0, - ap_req_options, - ticket); + if (ap_req_options) + *ap_req_options = out->ap_req_options; + if (ticket) { + ret = krb5_copy_ticket(context, out->ticket, ticket); + if (ret) + goto out; + } - free_AP_REQ(&ap_req); +out: + krb5_rd_req_out_ctx_free(context, out); return ret; } +/* + * + */ + static krb5_error_code get_key_from_keytab(krb5_context context, krb5_auth_context *auth_context, @@ -582,39 +737,44 @@ out: return ret; } +/* + * + */ + krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req_return_keyblock(krb5_context context, - krb5_auth_context *auth_context, - const krb5_data *inbuf, - krb5_const_principal server, - krb5_keytab keytab, - krb5_flags *ap_req_options, - krb5_ticket **ticket, - krb5_keyblock **return_keyblock) +krb5_rd_req_ctx(krb5_context context, + krb5_auth_context *auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_rd_req_in_ctx inctx, + krb5_rd_req_out_ctx *outctx) { krb5_error_code ret; krb5_ap_req ap_req; - krb5_keyblock *keyblock = NULL; krb5_principal service = NULL; + krb5_rd_req_out_ctx o = NULL; - if (return_keyblock) - *return_keyblock = NULL; + ret = _krb5_rd_req_out_ctx_alloc(context, &o); + if (ret) + goto out; if (*auth_context == NULL) { ret = krb5_auth_con_init(context, auth_context); if (ret) - return ret; + goto out; } ret = krb5_decode_ap_req(context, inbuf, &ap_req); if(ret) - return ret; + goto out; if(server == NULL){ - _krb5_principalname2krb5_principal(context, - &service, - ap_req.ticket.sname, - ap_req.ticket.realm); + ret = _krb5_principalname2krb5_principal(context, + &service, + ap_req.ticket.sname, + ap_req.ticket.realm); + if (ret) + goto out; server = service; } if (ap_req.ap_options.use_session_key && @@ -625,61 +785,51 @@ krb5_rd_req_return_keyblock(krb5_context context, goto out; } - if((*auth_context)->keyblock == NULL){ + if((*auth_context)->keyblock){ + ret = krb5_copy_keyblock(context, + (*auth_context)->keyblock, + &o->keyblock); + if (ret) + goto out; + } else if(inctx->keyblock){ + ret = krb5_copy_keyblock(context, + inctx->keyblock, + &o->keyblock); + if (ret) + goto out; + } else { + krb5_keytab keytab = NULL; + + if (inctx && inctx->keytab) + keytab = inctx->keytab; + ret = get_key_from_keytab(context, auth_context, &ap_req, server, keytab, - &keyblock); + &o->keyblock); if(ret) goto out; - } else { - ret = krb5_copy_keyblock(context, - (*auth_context)->keyblock, - &keyblock); - if (ret) - goto out; } ret = krb5_verify_ap_req(context, auth_context, &ap_req, server, - keyblock, + o->keyblock, 0, - ap_req_options, - ticket); - - if (ret == 0 && return_keyblock) - *return_keyblock = keyblock; - else - krb5_free_keyblock(context, keyblock); + &o->ap_req_options, + &o->ticket); out: + if (ret || outctx == NULL) { + krb5_rd_req_out_ctx_free(context, o); + } else + *outctx = o; + free_AP_REQ(&ap_req); if(service) krb5_free_principal(context, service); return ret; } - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req(krb5_context context, - krb5_auth_context *auth_context, - const krb5_data *inbuf, - krb5_const_principal server, - krb5_keytab keytab, - krb5_flags *ap_req_options, - krb5_ticket **ticket) -{ - return krb5_rd_req_return_keyblock(context, - auth_context, - inbuf, - server, - keytab, - ap_req_options, - ticket, - NULL); - -} - -- cgit From ed77e4e57beee0c9c8b0c4c75626c41ebfc5b0c4 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 9 Nov 2006 00:33:43 +0000 Subject: r19644: Merge up to current lorikeet-heimdal, incling adding gsskrb5_set_default_realm(), which should fix mimir's issues. Andrew Bartlett (This used to be commit 8117e76d2adee163925a29df872015ff5021a1d3) --- source4/heimdal/lib/krb5/context.c | 6 +-- source4/heimdal/lib/krb5/get_for_creds.c | 88 +++++++++++++++++--------------- source4/heimdal/lib/krb5/mk_req.c | 2 - source4/heimdal/lib/krb5/store_mem.c | 33 +++++++++++- 4 files changed, 81 insertions(+), 48 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index a25bb80786..f3b0fad347 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: context.c,v 1.110 2006/11/04 03:27:47 lha Exp $"); +RCSID("$Id: context.c,v 1.111 2006/11/08 02:55:46 lha Exp $"); #define INIT_FIELD(C, T, E, D, F) \ (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ @@ -707,13 +707,13 @@ krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec) } time_t KRB5_LIB_FUNCTION -krb5_get_time_wrap (krb5_context context) +krb5_get_max_time_skew (krb5_context context) { return context->max_skew; } void KRB5_LIB_FUNCTION -krb5_set_time_wrap (krb5_context context, time_t t) +krb5_set_max_time_skew (krb5_context context, time_t t) { context->max_skew = t; } diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index 661d05663b..6eebf1fa80 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -162,8 +162,7 @@ krb5_get_forwarded_creds (krb5_context context, { krb5_error_code ret; krb5_creds *out_creds; - krb5_addresses *paddrs = NULL; - krb5_addresses addrs; + krb5_addresses addrs, *paddrs; KRB_CRED cred; KrbCredInfo *krb_cred_info; EncKrbCredPart enc_krb_cred_part; @@ -172,53 +171,58 @@ krb5_get_forwarded_creds (krb5_context context, size_t buf_size; krb5_kdc_flags kdc_flags; krb5_crypto crypto; + struct addrinfo *ai; int save_errno; krb5_creds *ticket; char *realm; - krb5_boolean noaddr_ever; - - addrs.len = 0; - addrs.val = NULL; realm = in_creds->client->realm; - krb5_appdefault_boolean(context, NULL, realm, "no-addresses-ever", - TRUE, &noaddr_ever); - if (!noaddr_ever) { - struct addrinfo *ai; - paddrs = &addrs; - - /* - * If tickets are address-less, forward address-less tickets. - */ - - ret = _krb5_get_krbtgt (context, - ccache, - realm, - &ticket); - if(ret == 0) { - if (ticket->addresses.len == 0) - paddrs = NULL; - krb5_free_creds (context, ticket); - } - - if (paddrs != NULL) { - - ret = getaddrinfo (hostname, NULL, NULL, &ai); - if (ret) { - save_errno = errno; - krb5_set_error_string(context, "resolving %s: %s", - hostname, gai_strerror(ret)); - return krb5_eai_to_heim_errno(ret, save_errno); - } - - ret = add_addrs (context, &addrs, ai); - freeaddrinfo (ai); - if (ret) - return ret; - } + addrs.len = 0; + addrs.val = NULL; + paddrs = &addrs; + + { + krb5_boolean noaddr; + krb5_appdefault_boolean(context, NULL, realm, + "no-addresses", KRB5_ADDRESSLESS_DEFAULT, + &noaddr); + if (noaddr) + paddrs = NULL; } + + /* + * If tickets are address-less, forward address-less tickets. + */ + + if (paddrs) { + ret = _krb5_get_krbtgt (context, + ccache, + realm, + &ticket); + if(ret == 0) { + if (ticket->addresses.len == 0) + paddrs = NULL; + krb5_free_creds (context, ticket); + } + } + + if (paddrs != NULL) { + ret = getaddrinfo (hostname, NULL, NULL, &ai); + if (ret) { + save_errno = errno; + krb5_set_error_string(context, "resolving %s: %s", + hostname, gai_strerror(ret)); + return krb5_eai_to_heim_errno(ret, save_errno); + } + + ret = add_addrs (context, &addrs, ai); + freeaddrinfo (ai); + if (ret) + return ret; + } + kdc_flags.b = int2KDCOptions(flags); ret = krb5_get_kdc_cred (context, diff --git a/source4/heimdal/lib/krb5/mk_req.c b/source4/heimdal/lib/krb5/mk_req.c index 44e5d9c222..adc077e13f 100644 --- a/source4/heimdal/lib/krb5/mk_req.c +++ b/source4/heimdal/lib/krb5/mk_req.c @@ -64,9 +64,7 @@ krb5_mk_req_exact(krb5_context context, if (auth_context && *auth_context && (*auth_context)->keytype) this_cred.session.keytype = (*auth_context)->keytype; - /* This is the network contact with the KDC */ ret = krb5_get_credentials (context, 0, ccache, &this_cred, &cred); - krb5_free_cred_contents(context, &this_cred); if (ret) return ret; diff --git a/source4/heimdal/lib/krb5/store_mem.c b/source4/heimdal/lib/krb5/store_mem.c index decf74adce..d2b6d18252 100644 --- a/source4/heimdal/lib/krb5/store_mem.c +++ b/source4/heimdal/lib/krb5/store_mem.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store_mem.c,v 1.12 2004/05/25 21:44:17 lha Exp $"); +RCSID("$Id: store_mem.c,v 1.13 2006/11/07 23:02:53 lha Exp $"); typedef struct mem_storage{ unsigned char *base; @@ -64,6 +64,12 @@ mem_store(krb5_storage *sp, const void *data, size_t size) return size; } +static ssize_t +mem_no_store(krb5_storage *sp, const void *data, size_t size) +{ + return -1; +} + static off_t mem_seek(krb5_storage *sp, off_t offset, int whence) { @@ -117,3 +123,28 @@ krb5_storage_from_data(krb5_data *data) { return krb5_storage_from_mem(data->data, data->length); } + +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_readonly_mem(const void *buf, size_t len) +{ + krb5_storage *sp = malloc(sizeof(krb5_storage)); + mem_storage *s; + if(sp == NULL) + return NULL; + s = malloc(sizeof(*s)); + if(s == NULL) { + free(sp); + return NULL; + } + sp->data = s; + sp->flags = 0; + sp->eof_code = HEIM_ERR_EOF; + s->base = rk_UNCONST(buf); + s->size = len; + s->ptr = rk_UNCONST(buf); + sp->fetch = mem_fetch; + sp->store = mem_no_store; + sp->seek = mem_seek; + sp->free = NULL; + return sp; +} -- cgit From d822b963f9c178f3f2278be717ac97fbcb8de01c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 11 Nov 2006 14:00:24 +0000 Subject: r19663: merge changes from lorikeet heimdal: support for netbios domain based realms metze (This used to be commit dcec6eebf1b474ae3055449efebf491b1106a458) --- source4/heimdal/lib/krb5/get_in_tkt.c | 74 ++++++++++++++++++++++++----------- 1 file changed, 52 insertions(+), 22 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/get_in_tkt.c b/source4/heimdal/lib/krb5/get_in_tkt.c index ebc96f2279..e140011413 100644 --- a/source4/heimdal/lib/krb5/get_in_tkt.c +++ b/source4/heimdal/lib/krb5/get_in_tkt.c @@ -131,12 +131,21 @@ _krb5_extract_ticket(krb5_context context, krb5_const_pointer decryptarg) { krb5_error_code ret; - krb5_principal tmp_principal; + krb5_principal tmp_principal, srv_principal = NULL; int tmp; size_t len; time_t tmp_time; krb5_timestamp sec_now; +/* + * HACK: + * this is really a ugly hack, to support using the Netbios Domain Name + * as realm against windows KDC's, they always return the full realm + * based on the DNS Name. + */ +allow_server_mismatch = 1; +ignore_cname = 1; + ret = _krb5_principalname2krb5_principal (context, &tmp_principal, rep->kdc_rep.cname, @@ -168,44 +177,63 @@ _krb5_extract_ticket(krb5_context context, krb5_abortx(context, "internal error in ASN.1 encoder"); creds->second_ticket.length = 0; creds->second_ticket.data = NULL; + + /* decrypt */ + + if (decrypt_proc == NULL) + decrypt_proc = decrypt_tkt; + + ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep); + if (ret) + goto out; + +#if 0 + /* XXX should this decode be here, or in the decrypt_proc? */ + ret = krb5_decode_keyblock(context, &rep->enc_part.key, 1); + if(ret) + goto out; +#endif /* compare server */ ret = _krb5_principalname2krb5_principal (context, - &tmp_principal, + &srv_principal, rep->kdc_rep.ticket.sname, rep->kdc_rep.ticket.realm); if (ret) goto out; + + ret = _krb5_principalname2krb5_principal (context, + &tmp_principal, + rep->enc_part.sname, + rep->enc_part.srealm); + if (ret) + goto out; + + /* + * see if the service principal matches in the ticket + * and in the enc_part + */ + tmp = krb5_principal_compare (context, tmp_principal, srv_principal); + krb5_free_principal (context, tmp_principal); + if (!tmp) { + ret = KRB5KRB_AP_ERR_MODIFIED; + krb5_clear_error_string (context); + goto out; + } + if(allow_server_mismatch){ krb5_free_principal(context, creds->server); - creds->server = tmp_principal; - tmp_principal = NULL; + creds->server = srv_principal; + srv_principal = NULL; }else{ - tmp = krb5_principal_compare (context, tmp_principal, creds->server); - krb5_free_principal (context, tmp_principal); + tmp = krb5_principal_compare (context, srv_principal, creds->server); if (!tmp) { ret = KRB5KRB_AP_ERR_MODIFIED; krb5_clear_error_string (context); goto out; } } - - /* decrypt */ - - if (decrypt_proc == NULL) - decrypt_proc = decrypt_tkt; - - ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep); - if (ret) - goto out; - -#if 0 - /* XXX should this decode be here, or in the decrypt_proc? */ - ret = krb5_decode_keyblock(context, &rep->enc_part.key, 1); - if(ret) - goto out; -#endif /* compare nonces */ @@ -301,6 +329,8 @@ _krb5_extract_ticket(krb5_context context, out: memset (rep->enc_part.key.keyvalue.data, 0, rep->enc_part.key.keyvalue.length); + if (srv_principal) + krb5_free_principal (context, srv_principal); return ret; } -- cgit From 5a6288f45891be30bd8e22978f61faf487214de6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 13 Nov 2006 03:19:59 +0000 Subject: r19681: Update to current lorikeet-heimdal. I'm looking at using the realm lookup plugin, the new PAC validation code as well as Heimdal's SPNEGO implementation. Andrew Bartlett (This used to be commit 05421f45ed7811697ea491e26c9d991a7faa1a64) --- source4/heimdal/lib/krb5/krb5-private.h | 54 +++++++ source4/heimdal/lib/krb5/krb5-protos.h | 27 +++- source4/heimdal/lib/krb5/krb5.h | 4 +- source4/heimdal/lib/krb5/krb5_locl.h | 6 + source4/heimdal/lib/krb5/krbhst.c | 97 ++++++++++++- source4/heimdal/lib/krb5/locate_plugin.h | 64 ++++++++ source4/heimdal/lib/krb5/mit_glue.c | 10 +- source4/heimdal/lib/krb5/plugin.c | 242 +++++++++++++++++++++++++++++++ 8 files changed, 491 insertions(+), 13 deletions(-) create mode 100644 source4/heimdal/lib/krb5/locate_plugin.h create mode 100644 source4/heimdal/lib/krb5/plugin.c (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 0bf184a530..ba2f75ad22 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -299,6 +299,37 @@ _krb5_oid_to_enctype ( const heim_oid */*oid*/, krb5_enctype */*etype*/); +void +_krb5_pac_free ( + krb5_context /*context*/, + struct krb5_pac */*pac*/); + +krb5_error_code +_krb5_pac_parse ( + krb5_context /*context*/, + const void */*ptr*/, + size_t /*len*/, + struct krb5_pac **/*pac*/); + +krb5_error_code +_krb5_pac_sign ( + krb5_context /*context*/, + struct krb5_pac */*p*/, + time_t /*authtime*/, + krb5_principal /*principal*/, + krb5_keyblock */*server_key*/, + krb5_keyblock */*priv_key*/, + krb5_data */*data*/); + +krb5_error_code +_krb5_pac_verify ( + krb5_context /*context*/, + struct krb5_pac */*pac*/, + time_t /*authtime*/, + krb5_principal /*principal*/, + krb5_keyblock */*server*/, + krb5_keyblock */*privsvr*/); + krb5_error_code _krb5_parse_moduli ( krb5_context /*context*/, @@ -380,6 +411,29 @@ _krb5_pk_verify_sign ( krb5_data */*content*/, struct krb5_pk_cert **/*signer*/); +krb5_error_code +_krb5_plugin_find ( + krb5_context /*context*/, + enum plugin_type /*type*/, + const char */*name*/, + struct krb5_plugin **/*list*/); + +void +_krb5_plugin_free (struct krb5_plugin */*list*/); + +struct krb5_plugin * +_krb5_plugin_get_next (struct krb5_plugin */*p*/); + +void * +_krb5_plugin_get_symbol (struct krb5_plugin */*p*/); + +krb5_error_code +_krb5_plugin_register ( + krb5_context /*context*/, + enum plugin_type /*type*/, + const char */*name*/, + void */*symbol*/); + krb5_error_code KRB5_LIB_FUNCTION _krb5_principal2principalname ( PrincipalName */*p*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 104f10bdf2..8b61e8d7d2 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -498,6 +498,12 @@ krb5_c_is_coll_proof_cksum (krb5_cksumtype /*ctype*/); krb5_boolean KRB5_LIB_FUNCTION krb5_c_is_keyed_cksum (krb5_cksumtype /*ctype*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_keylength ( + krb5_context /*context*/, + krb5_enctype /*enctype*/, + size_t */*len*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_c_make_checksum ( krb5_context /*context*/, @@ -2165,6 +2171,9 @@ krb5_get_krbhst ( const krb5_realm */*realm*/, char ***/*hostlist*/); +time_t KRB5_LIB_FUNCTION +krb5_get_max_time_skew (krb5_context /*context*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_get_pw_salt ( krb5_context /*context*/, @@ -2177,9 +2186,6 @@ krb5_get_server_rcache ( const krb5_data */*piece*/, krb5_rcache */*id*/); -time_t KRB5_LIB_FUNCTION -krb5_get_time_wrap (krb5_context /*context*/); - krb5_boolean KRB5_LIB_FUNCTION krb5_get_use_admin_kdc (krb5_context /*context*/); @@ -3165,6 +3171,11 @@ krb5_set_ignore_addresses ( krb5_context /*context*/, const krb5_addresses */*addresses*/); +void KRB5_LIB_FUNCTION +krb5_set_max_time_skew ( + krb5_context /*context*/, + time_t /*t*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_set_password ( krb5_context /*context*/, @@ -3197,11 +3208,6 @@ krb5_set_send_to_kdc_func ( krb5_send_to_kdc_func /*func*/, void */*data*/); -void KRB5_LIB_FUNCTION -krb5_set_time_wrap ( - krb5_context /*context*/, - time_t /*t*/); - void KRB5_LIB_FUNCTION krb5_set_use_admin_kdc ( krb5_context /*context*/, @@ -3271,6 +3277,11 @@ krb5_storage_from_mem ( void */*buf*/, size_t /*len*/); +krb5_storage * KRB5_LIB_FUNCTION +krb5_storage_from_readonly_mem ( + const void */*buf*/, + size_t /*len*/); + krb5_flags KRB5_LIB_FUNCTION krb5_storage_get_byteorder ( krb5_storage */*sp*/, diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index f5c8b069de..1b26e8b3e7 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h,v 1.254 2006/11/07 00:17:42 lha Exp $ */ +/* $Id: krb5.h,v 1.255 2006/11/12 08:33:07 lha Exp $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -78,6 +78,8 @@ typedef struct krb5_get_creds_opt_data *krb5_get_creds_opt; struct krb5_digest; typedef struct krb5_digest *krb5_digest; +struct krb5_pac; + typedef struct krb5_rd_req_in_ctx *krb5_rd_req_in_ctx; typedef struct krb5_rd_req_out_ctx *krb5_rd_req_out_ctx; diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 89b3c6ad40..3fb5461b3c 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -148,6 +148,12 @@ struct krb5_dh_moduli; /* v4 glue */ struct _krb5_krb_auth_data; +struct krb5_plugin; +enum plugin_type { + PLUGIN_TYPE_DATA = 1, + PLUGIN_TYPE_FUNC +}; + #include #include diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index e7b2579229..f395f0d0c3 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -33,8 +33,9 @@ #include "krb5_locl.h" #include +#include "locate_plugin.h" -RCSID("$Id: krbhst.c,v 1.57 2006/10/06 17:11:02 lha Exp $"); +RCSID("$Id: krbhst.c,v 1.58 2006/11/12 20:05:20 lha Exp $"); static int string_to_proto(const char *string) @@ -147,6 +148,7 @@ struct krb5_krbhst_data { #define KD_FALLBACK 16 #define KD_CONFIG_EXISTS 32 #define KD_LARGE_MSG 64 +#define KD_PLUGIN 128 krb5_error_code (*get_next)(krb5_context, struct krb5_krbhst_data *, krb5_krbhst_info**); @@ -460,8 +462,8 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, hi->proto = proto; hi->port = hi->def_port = port; hi->ai = ai; - memmove(hi->hostname, host, hostlen - 1); - hi->hostname[hostlen - 1] = '\0'; + memmove(hi->hostname, host, hostlen); + hi->hostname[hostlen] = '\0'; free(host); append_host_hostinfo(kd, hi); kd->fallback_count++; @@ -469,6 +471,88 @@ fallback_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, return 0; } +/* + * Fetch hosts from plugin + */ + +static krb5_error_code +add_locate(void *ctx, int type, struct sockaddr *addr) +{ + struct krb5_krbhst_info *hi; + struct krb5_krbhst_data *kd = ctx; + char host[NI_MAXHOST], port[NI_MAXSERV]; + struct addrinfo hints, *ai; + socklen_t socklen; + size_t hostlen; + int ret; + + socklen = socket_sockaddr_size(addr); + + ret = getnameinfo(addr, socklen, host, sizeof(host), port, sizeof(port), + NI_NUMERICHOST|NI_NUMERICSERV); + if (ret != 0) + return 0; + + memset(&hints, 0, sizeof(hints)); + ret = getaddrinfo(host, port, &hints, &ai); + if (ret) + return 0; + + hostlen = strlen(host); + + hi = calloc(1, sizeof(*hi) + hostlen); + if(hi == NULL) { + free(host); + return ENOMEM; + } + + hi->proto = krbhst_get_default_proto(kd); + hi->port = hi->def_port = socket_get_port(addr); + hi->ai = ai; + memmove(hi->hostname, host, hostlen); + hi->hostname[hostlen] = '\0'; + append_host_hostinfo(kd, hi); + + return 0; +} + +static void +plugin_get_hosts(krb5_context context, + struct krb5_krbhst_data *kd, + enum locate_service_type type) +{ + struct krb5_plugin *list, *e; + krb5_error_code ret; + + ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, "resolve", &list); + if(ret != 0 || list == NULL) + return; + + kd->flags |= KD_CONFIG_EXISTS; + + for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) { + krb5plugin_service_locate_ftable *service; + void *ctx; + + service = _krb5_plugin_get_symbol(e); + if (service->minor_version != 0) + continue; + + (*service->init)(context, &ctx); + ret = (*service->lookup)(ctx, type, kd->realm, 0, 0, add_locate, kd); + (*service->fini)(ctx); + if (ret) { + krb5_set_error_string(context, "Plugin failed to lookup"); + break; + } + } + _krb5_plugin_free(list); +} + +/* + * + */ + static krb5_error_code kdc_get_next(krb5_context context, struct krb5_krbhst_data *kd, @@ -476,6 +560,13 @@ kdc_get_next(krb5_context context, { krb5_error_code ret; + if ((kd->flags & KD_PLUGIN) == 0) { + plugin_get_hosts(context, kd, locate_service_kdc); + kd->flags |= KD_PLUGIN; + if(get_next(kd, host)) + return 0; + } + if((kd->flags & KD_CONFIG) == 0) { config_get_hosts(context, kd, "kdc"); kd->flags |= KD_CONFIG; diff --git a/source4/heimdal/lib/krb5/locate_plugin.h b/source4/heimdal/lib/krb5/locate_plugin.h new file mode 100644 index 0000000000..ec06d362cf --- /dev/null +++ b/source4/heimdal/lib/krb5/locate_plugin.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +/* $Id: locate_plugin.h,v 1.1 2006/11/12 19:00:03 lha Exp $ */ + +#ifndef HEIMDAL_KRB5_LOCATE_PLUGIN_H +#define HEIMDAL_KRB5_LOCATE_PLUGIN_H 1 + +#include + +enum locate_service_type { + locate_service_kdc = 1, + locate_service_master_kdc, + locate_service_kadmin, + locate_service_krb524, + locate_service_kpasswd +}; + +typedef krb5_error_code +(*krb5plugin_service_locate_lookup) (void *, enum locate_service_type, + const char *, int, int, + int (*)(void *,int,struct sockaddr *), + void *); + + +typedef struct krb5plugin_service_locate_ftable { + int minor_version; + krb5_error_code (*init)(krb5_context, void **); + void (*fini)(void *); + krb5plugin_service_locate_lookup lookup; +} krb5plugin_service_locate_ftable; + +#endif /* HEIMDAL_KRB5_LOCATE_PLUGIN_H */ + diff --git a/source4/heimdal/lib/krb5/mit_glue.c b/source4/heimdal/lib/krb5/mit_glue.c index b9075b3079..493c4cd845 100755 --- a/source4/heimdal/lib/krb5/mit_glue.c +++ b/source4/heimdal/lib/krb5/mit_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: mit_glue.c,v 1.8 2006/10/14 09:51:02 lha Exp $"); +RCSID("$Id: mit_glue.c,v 1.9 2006/11/09 21:24:16 lha Exp $"); /* * Glue for MIT API @@ -325,3 +325,11 @@ krb5_c_make_random_key(krb5_context context, { return krb5_generate_random_keyblock(context, enctype, random_key); } + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_keylength(krb5_context context, + krb5_enctype enctype, + size_t *len) +{ + return krb5_enctype_keysize(context, enctype, len); +} diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c new file mode 100644 index 0000000000..294807faab --- /dev/null +++ b/source4/heimdal/lib/krb5/plugin.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2006 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +RCSID("$Id: plugin.c,v 1.2 2006/11/12 21:39:43 lha Exp $"); +#ifdef HAVE_DLFCN_H +#include +#endif +#include + +struct krb5_plugin { + void *symbol; + void *dsohandle; + struct krb5_plugin *next; +}; + +struct plugin { + enum plugin_type type; + void *name; + void *symbol; + struct plugin *next; +}; + +static HEIMDAL_MUTEX plugin_mutex = HEIMDAL_MUTEX_INITIALIZER; +static struct plugin *registered = NULL; + +static const char *plugin_dir = LIBDIR "/plugin/krb5"; + +/* + * + */ + +void * +_krb5_plugin_get_symbol(struct krb5_plugin *p) +{ + return p->symbol; +} + +struct krb5_plugin * +_krb5_plugin_get_next(struct krb5_plugin *p) +{ + return p->next; +} + +/* + * + */ + +static krb5_error_code +loadlib(krb5_context context, + enum plugin_type type, + const char *name, + const char *lib, + struct krb5_plugin **e) +{ + *e = calloc(1, sizeof(**e)); + if (*e == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + + (*e)->dsohandle = dlopen(lib, 0); + if ((*e)->dsohandle == NULL) { + free(*e); + krb5_set_error_string(context, "Failed to load %s: %s", + lib, dlerror()); + return ENOMEM; + } + + /* dlsym doesn't care about the type */ + (*e)->symbol = dlsym((*e)->dsohandle, name); + if ((*e)->symbol == NULL) { + dlclose((*e)->dsohandle); + free(*e); + krb5_clear_error_string(context); + return ENOMEM; + } + + return 0; +} + +krb5_error_code +_krb5_plugin_register(krb5_context context, + enum plugin_type type, + const char *name, + void *symbol) +{ + struct plugin *e; + + e = calloc(1, sizeof(*e)); + if (e == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + e->type = type; + e->name = strdup(name); + if (e->name == NULL) { + free(e); + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + e->symbol = symbol; + + HEIMDAL_MUTEX_lock(&plugin_mutex); + e->next = registered; + registered = e; + HEIMDAL_MUTEX_unlock(&plugin_mutex); + + return 0; +} + +krb5_error_code +_krb5_plugin_find(krb5_context context, + enum plugin_type type, + const char *name, + struct krb5_plugin **list) +{ + struct krb5_plugin *e; + struct plugin *p; + krb5_error_code ret; + char *sysdirs[2] = { NULL, NULL }; + char **dirs = NULL, **di; + struct dirent *entry; + char *path; + DIR *d = NULL; + + *list = NULL; + + HEIMDAL_MUTEX_lock(&plugin_mutex); + + for (p = registered; p != NULL; p = p->next) { + if (p->type != type || strcmp(p->name, name) != 0) + continue; + + e = calloc(1, sizeof(*e)); + if (e == NULL) { + HEIMDAL_MUTEX_unlock(&plugin_mutex); + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + e->symbol = p->symbol; + e->dsohandle = NULL; + e->next = *list; + *list = e; + } + HEIMDAL_MUTEX_unlock(&plugin_mutex); + + dirs = krb5_config_get_strings(context, NULL, "libdefaults", + "plugin_dir", NULL); + if (dirs == NULL) { + sysdirs[0] = rk_UNCONST(plugin_dir); + dirs = sysdirs; + } + + for (di = dirs; *di != NULL; di++) { + + d = opendir(*di); + if (d == NULL) + continue; + + while ((entry = readdir(d)) != NULL) { + asprintf(&path, "%s/%s", *di, entry->d_name); + if (path == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + ret = loadlib(context, type, name, path, &e); + free(path); + if (ret) + continue; + + e->next = *list; + *list = e; + } + closedir(d); + } + if (dirs != sysdirs) + krb5_config_free_strings(dirs); + + if (*list == NULL) { + krb5_set_error_string(context, "Did not find a plugin for %s", name); + return ENOENT; + } + + return 0; + +out: + if (dirs && dirs != sysdirs) + krb5_config_free_strings(dirs); + if (d) + closedir(d); + _krb5_plugin_free(*list); + *list = NULL; + + return ret; +} + +void +_krb5_plugin_free(struct krb5_plugin *list) +{ + struct krb5_plugin *next; + while (list) { + next = list->next; + if (list->dsohandle) + dlclose(list->dsohandle); + free(list); + list = next; + } +} + -- cgit From f7242f643763ccb6e10801af4ce53d0873e2d3e1 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 10 Jan 2007 01:57:32 +0000 Subject: r20640: Commit part 2/2 Update Heimdal to match current lorikeet-heimdal. This includes integrated PAC hooks, so Samba doesn't have to handle this any more. This also brings in the PKINIT code, hence so many new files. Andrew Bartlett (This used to be commit 351f7040f7bb73b9a60b22b564686f7c2f98a729) --- source4/heimdal/lib/krb5/acache.c | 9 +- source4/heimdal/lib/krb5/config_file.c | 8 +- source4/heimdal/lib/krb5/context.c | 4 +- source4/heimdal/lib/krb5/crypto.c | 17 +- source4/heimdal/lib/krb5/fcache.c | 63 +- source4/heimdal/lib/krb5/get_cred.c | 4 +- source4/heimdal/lib/krb5/init_creds.c | 7 +- source4/heimdal/lib/krb5/init_creds_pw.c | 36 +- source4/heimdal/lib/krb5/krb5-private.h | 34 +- source4/heimdal/lib/krb5/krb5-protos.h | 189 +++++- source4/heimdal/lib/krb5/krb5.h | 9 +- source4/heimdal/lib/krb5/krb5_locl.h | 14 +- source4/heimdal/lib/krb5/krbhst.c | 27 +- source4/heimdal/lib/krb5/log.c | 4 +- source4/heimdal/lib/krb5/mit_glue.c | 17 +- source4/heimdal/lib/krb5/mk_req_ext.c | 6 +- source4/heimdal/lib/krb5/pac.c | 1034 ++++++++++++++++++++++++++++++ source4/heimdal/lib/krb5/pkinit.c | 220 +++++-- source4/heimdal/lib/krb5/plugin.c | 10 +- source4/heimdal/lib/krb5/principal.c | 4 +- source4/heimdal/lib/krb5/rd_req.c | 43 +- source4/heimdal/lib/krb5/store.c | 3 +- source4/heimdal/lib/krb5/ticket.c | 38 +- source4/heimdal/lib/krb5/warn.c | 8 +- 24 files changed, 1637 insertions(+), 171 deletions(-) create mode 100644 source4/heimdal/lib/krb5/pac.c (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c index 004926bc89..d20c24699b 100644 --- a/source4/heimdal/lib/krb5/acache.c +++ b/source4/heimdal/lib/krb5/acache.c @@ -37,7 +37,7 @@ #include #endif -RCSID("$Id: acache.c,v 1.16 2006/10/19 11:41:38 lha Exp $"); +RCSID("$Id: acache.c,v 1.17 2007/01/08 15:31:01 lha Exp $"); /* XXX should we fetch these for each open ? */ static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; @@ -106,7 +106,12 @@ init_ccapi(krb5_context context) } #ifdef HAVE_DLOPEN - cc_handle = dlopen(lib, 0); + +#ifndef RTLD_LAZY +#define RTLD_LAZY 0 +#endif + + cc_handle = dlopen(lib, RTLD_LAZY); if (cc_handle == NULL) { HEIMDAL_MUTEX_unlock(&acc_mutex); krb5_set_error_string(context, "Failed to load %s", lib); diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c index 66051303ed..bbd9cf4c78 100644 --- a/source4/heimdal/lib/krb5/config_file.c +++ b/source4/heimdal/lib/krb5/config_file.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: config_file.c,v 1.54 2006/04/02 00:59:19 lha Exp $"); +RCSID("$Id: config_file.c,v 1.55 2006/12/04 23:35:54 lha Exp $"); #ifndef HAVE_NETINFO @@ -158,8 +158,7 @@ parse_list(struct fileptr *f, unsigned *lineno, krb5_config_binding **parent, char *p; ++*lineno; - if (buf[strlen(buf) - 1] == '\n') - buf[strlen(buf) - 1] = '\0'; + buf[strcspn(buf, "\r\n")] = '\0'; p = buf; while(isspace((unsigned char)*p)) ++p; @@ -255,8 +254,7 @@ krb5_config_parse_debug (struct fileptr *f, char *p; ++*lineno; - if(buf[strlen(buf) - 1] == '\n') - buf[strlen(buf) - 1] = '\0'; + buf[strcspn(buf, "\r\n")] = '\0'; p = buf; while(isspace((unsigned char)*p)) ++p; diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index f3b0fad347..d0317da375 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: context.c,v 1.111 2006/11/08 02:55:46 lha Exp $"); +RCSID("$Id: context.c,v 1.112 2006/11/24 14:24:33 lha Exp $"); #define INIT_FIELD(C, T, E, D, F) \ (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ @@ -180,7 +180,7 @@ init_context_from_config_file(krb5_context context) /* prefer dns_lookup_kdc over srv_lookup. */ INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup"); INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc"); - INIT_FIELD(context, int, large_msg_size, 6000, "large_message_size"); + INIT_FIELD(context, int, large_msg_size, 1400, "large_message_size"); INIT_FIELD(context, bool, dns_canonicalize_hostname, TRUE, "dns_canonicalize_hostname"); context->default_cc_name = NULL; return 0; diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 9f6ef6b82b..6d4a81baa8 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.145 2006/10/22 07:32:40 lha Exp $"); +RCSID("$Id: crypto.c,v 1.146 2006/11/17 21:58:47 lha Exp $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -1075,6 +1075,21 @@ krb5_enctype_keysize(krb5_context context, return 0; } +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_keybits(krb5_context context, + krb5_enctype type, + size_t *keybits) +{ + struct encryption_type *et = _find_enctype(type); + if(et == NULL) { + krb5_set_error_string(context, "encryption type %d not supported", + type); + return KRB5_PROG_ETYPE_NOSUPP; + } + *keybits = et->keytype->bits; + return 0; +} + krb5_error_code KRB5_LIB_FUNCTION krb5_generate_random_keyblock(krb5_context context, krb5_enctype type, diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c index 79b809d2a2..7441509e38 100644 --- a/source4/heimdal/lib/krb5/fcache.c +++ b/source4/heimdal/lib/krb5/fcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: fcache.c,v 1.52 2006/04/02 01:04:37 lha Exp $"); +RCSID("$Id: fcache.c,v 1.54 2006/12/15 21:35:52 lha Exp $"); typedef struct krb5_fcache{ char *filename; @@ -699,6 +699,62 @@ fcc_get_version(krb5_context context, return FCACHE(id)->version; } +struct fcache_iter { + int first; +}; + +static krb5_error_code +fcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) +{ + struct fcache_iter *iter; + + iter = calloc(1, sizeof(*iter)); + if (iter == NULL) { + krb5_set_error_string(context, "malloc - out of memory"); + return ENOMEM; + } + iter->first = 1; + *cursor = iter; + return 0; +} + +static krb5_error_code +fcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) +{ + struct fcache_iter *iter = cursor; + krb5_error_code ret; + const char *fn; + char *expandedfn = NULL; + + if (!iter->first) { + krb5_clear_error_string(context); + return KRB5_CC_END; + } + iter->first = 0; + + fn = krb5_cc_default_name(context); + if (strncasecmp(fn, "FILE:", 5) != 0) { + ret = _krb5_expand_default_cc_name(context, + KRB5_DEFAULT_CCNAME_FILE, + &expandedfn); + if (ret) + return ret; + } + ret = krb5_cc_resolve(context, fn, id); + if (expandedfn) + free(expandedfn); + + return ret; +} + +static krb5_error_code +fcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) +{ + struct fcache_iter *iter = cursor; + free(iter); + return 0; +} + const krb5_cc_ops krb5_fcc_ops = { "FILE", fcc_get_name, @@ -715,5 +771,8 @@ const krb5_cc_ops krb5_fcc_ops = { fcc_end_get, fcc_remove_cred, fcc_set_flags, - fcc_get_version + fcc_get_version, + fcc_get_cache_first, + fcc_get_cache_next, + fcc_end_cache_get }; diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index b404c30f6e..663b5e7f1b 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_cred.c,v 1.112 2006/06/06 21:22:54 lha Exp $"); +RCSID("$Id: get_cred.c,v 1.113 2006/11/21 05:14:01 lha Exp $"); /* * Take the `body' and encode it into `padata' using the credentials @@ -458,7 +458,7 @@ get_cred_kdc_usage(krb5_context context, ret = krb5_create_checksum(context, crypto, - KRB5_KU_TGS_IMPERSONATE, + KRB5_KU_OTHER_CKSUM, 0, data.data, data.length, diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index 6dacb316d8..a331524a7e 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c,v 1.28 2006/09/04 14:28:54 lha Exp $"); +RCSID("$Id: init_creds.c,v 1.30 2006/11/23 16:27:36 lha Exp $"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) @@ -130,9 +130,10 @@ _krb5_get_init_creds_opt_set_krb5_error(krb5_context context, void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt) +krb5_get_init_creds_opt_free(krb5_context context, + krb5_get_init_creds_opt *opt) { - if (opt->opt_private == NULL) + if (opt == NULL || opt->opt_private == NULL) return; if (opt->opt_private->refcount < 1) /* abort ? */ return; diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index d43ae0ae6f..f6f6eac7d5 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c,v 1.101 2006/10/02 12:00:59 lha Exp $"); +RCSID("$Id: init_creds_pw.c,v 1.105 2007/01/09 10:44:59 lha Exp $"); typedef struct krb5_get_init_creds_ctx { KDCOptions flags; @@ -656,7 +656,7 @@ free_paid(krb5_context context, struct pa_info_data *ppaid) { krb5_free_salt(context, ppaid->salt); if (ppaid->s2kparams) - krb5_data_free(ppaid->s2kparams); + krb5_free_data(context, ppaid->s2kparams); } @@ -729,8 +729,8 @@ pa_etype_info2(krb5_context context, if (e.val[i].salt == NULL) krb5_free_salt(context, salt); if (ret == 0) { - free_ETYPE_INFO2(&e); - return paid; + free_ETYPE_INFO2(&e); + return paid; } } } @@ -1092,23 +1092,31 @@ process_pa_data_to_md(krb5_context context, (*out_md)->len = 0; (*out_md)->val = NULL; - if (in_md->len != 0) { - struct pa_info_data paid, *ppaid; + /* + * Make sure we don't sent both ENC-TS and PK-INIT pa data, no + * need to expose our password protecting our PKCS12 key. + */ - memset(&paid, 0, sizeof(paid)); + if (ctx->pk_init_ctx) { + + ret = pa_data_to_md_pkinit(context, a, creds->client, ctx, *out_md); + if (ret) + return ret; + } else if (in_md->len != 0) { + struct pa_info_data paid, *ppaid; + + memset(&paid, 0, sizeof(paid)); + paid.etype = ENCTYPE_NULL; ppaid = process_pa_info(context, creds->client, a, &paid, in_md); - + pa_data_to_md_ts_enc(context, a, creds->client, ctx, ppaid, *out_md); if (ppaid) free_paid(context, ppaid); } pa_data_add_pac_request(context, ctx, *out_md); - ret = pa_data_to_md_pkinit(context, a, creds->client, ctx, *out_md); - if (ret) - return ret; if ((*out_md)->len == 0) { free(*out_md); @@ -1503,7 +1511,7 @@ krb5_get_init_creds_password(krb5_context context, free (q); if (ret) { memset (buf, 0, sizeof(buf)); - krb5_get_init_creds_opt_free(options); + krb5_get_init_creds_opt_free(context, options); ret = KRB5_LIBOS_PWDINTR; krb5_clear_error_string (context); return ret; @@ -1515,7 +1523,7 @@ krb5_get_init_creds_password(krb5_context context, ret = krb5_get_init_creds_opt_set_pa_password(context, options, password, NULL); if (ret) { - krb5_get_init_creds_opt_free(options); + krb5_get_init_creds_opt_free(context, options); memset(buf, 0, sizeof(buf)); return ret; } @@ -1523,7 +1531,7 @@ krb5_get_init_creds_password(krb5_context context, ret = krb5_get_init_creds(context, creds, client, prompter, data, start_time, in_tkt_service, options); - krb5_get_init_creds_opt_free(options); + krb5_get_init_creds_opt_free(context, options); memset(buf, 0, sizeof(buf)); return ret; } diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index ba2f75ad22..c3e5732753 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -73,15 +73,6 @@ _krb5_extract_ticket ( krb5_decrypt_proc /*decrypt_proc*/, krb5_const_pointer /*decryptarg*/); -int -_krb5_find_type_in_ad ( - krb5_context /*context*/, - int /*type*/, - krb5_data */*data*/, - krb5_boolean */*found*/, - krb5_keyblock */*sessionkey*/, - const AuthorizationData */*ad*/); - void _krb5_free_krbhst_info (krb5_krbhst_info */*hi*/); @@ -299,37 +290,16 @@ _krb5_oid_to_enctype ( const heim_oid */*oid*/, krb5_enctype */*etype*/); -void -_krb5_pac_free ( - krb5_context /*context*/, - struct krb5_pac */*pac*/); - -krb5_error_code -_krb5_pac_parse ( - krb5_context /*context*/, - const void */*ptr*/, - size_t /*len*/, - struct krb5_pac **/*pac*/); - krb5_error_code _krb5_pac_sign ( krb5_context /*context*/, struct krb5_pac */*p*/, time_t /*authtime*/, krb5_principal /*principal*/, - krb5_keyblock */*server_key*/, - krb5_keyblock */*priv_key*/, + const krb5_keyblock */*server_key*/, + const krb5_keyblock */*priv_key*/, krb5_data */*data*/); -krb5_error_code -_krb5_pac_verify ( - krb5_context /*context*/, - struct krb5_pac */*pac*/, - time_t /*authtime*/, - krb5_principal /*principal*/, - krb5_keyblock */*server*/, - krb5_keyblock */*privsvr*/); - krb5_error_code _krb5_parse_moduli ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 8b61e8d7d2..9dfe487b0a 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -499,10 +499,11 @@ krb5_boolean KRB5_LIB_FUNCTION krb5_c_is_keyed_cksum (krb5_cksumtype /*ctype*/); krb5_error_code KRB5_LIB_FUNCTION -krb5_c_keylength ( +krb5_c_keylengths ( krb5_context /*context*/, krb5_enctype /*enctype*/, - size_t */*len*/); + size_t */*ilen*/, + size_t */*keylen*/); krb5_error_code KRB5_LIB_FUNCTION krb5_c_make_checksum ( @@ -1519,6 +1520,12 @@ krb5_enctype_disable ( krb5_context /*context*/, krb5_enctype /*enctype*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_keybits ( + krb5_context /*context*/, + krb5_enctype /*type*/, + size_t */*keybits*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_enctype_keysize ( krb5_context /*context*/, @@ -2021,7 +2028,9 @@ krb5_get_init_creds_opt_alloc ( krb5_get_init_creds_opt **/*opt*/); void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_free (krb5_get_init_creds_opt */*opt*/); +krb5_get_init_creds_opt_free ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/); krb5_error_code KRB5_LIB_FUNCTION krb5_get_init_creds_opt_get_error ( @@ -2189,6 +2198,9 @@ krb5_get_server_rcache ( krb5_boolean KRB5_LIB_FUNCTION krb5_get_use_admin_kdc (krb5_context /*context*/); +krb5_log_facility * KRB5_LIB_FUNCTION +krb5_get_warn_dest (krb5_context /*context*/); + size_t krb5_get_wrapped_length ( krb5_context /*context*/, @@ -2609,12 +2621,172 @@ krb5_net_write_block ( size_t /*len*/, time_t /*timeout*/); +krb5_error_code +krb5_ntlm_alloc ( + krb5_context /*context*/, + krb5_ntlm */*ntlm*/); + +krb5_error_code +krb5_ntlm_free ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/); + +krb5_error_code +krb5_ntlm_init_get_challange ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_data */*challange*/); + +krb5_error_code +krb5_ntlm_init_get_flags ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + uint32_t */*flags*/); + +krb5_error_code +krb5_ntlm_init_get_opaque ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_data */*opaque*/); + +krb5_error_code +krb5_ntlm_init_get_targetinfo ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_data */*data*/); + +krb5_error_code +krb5_ntlm_init_get_targetname ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + char **/*name*/); + +krb5_error_code +krb5_ntlm_init_request ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/, + uint32_t /*flags*/, + const char */*hostname*/, + const char */*domainname*/); + +krb5_error_code +krb5_ntlm_rep_get_sessionkey ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_data */*data*/); + +krb5_boolean +krb5_ntlm_rep_get_status ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/); + +krb5_error_code +krb5_ntlm_req_set_flags ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + uint32_t /*flags*/); + +krb5_error_code +krb5_ntlm_req_set_lm ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + void */*hash*/, + size_t /*len*/); + +krb5_error_code +krb5_ntlm_req_set_ntlm ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + void */*hash*/, + size_t /*len*/); + +krb5_error_code +krb5_ntlm_req_set_opaque ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_data */*opaque*/); + +krb5_error_code +krb5_ntlm_req_set_session ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + void */*sessionkey*/, + size_t /*length*/); + +krb5_error_code +krb5_ntlm_req_set_targetname ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + const char */*targetname*/); + +krb5_error_code +krb5_ntlm_req_set_username ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + const char */*username*/); + +krb5_error_code +krb5_ntlm_request ( + krb5_context /*context*/, + krb5_ntlm /*ntlm*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_openlog ( krb5_context /*context*/, const char */*program*/, krb5_log_facility **/*fac*/); +krb5_error_code +krb5_pac_add_buffer ( + krb5_context /*context*/, + struct krb5_pac */*p*/, + uint32_t /*type*/, + const krb5_data */*data*/); + +void +krb5_pac_free ( + krb5_context /*context*/, + struct krb5_pac */*pac*/); + +krb5_error_code +krb5_pac_get_buffer ( + krb5_context /*context*/, + struct krb5_pac */*p*/, + uint32_t /*type*/, + krb5_data */*data*/); + +krb5_error_code +krb5_pac_get_types ( + krb5_context /*context*/, + struct krb5_pac */*p*/, + size_t */*len*/, + uint32_t **/*types*/); + +krb5_error_code +krb5_pac_init ( + krb5_context /*context*/, + struct krb5_pac **/*pac*/); + +krb5_error_code +krb5_pac_parse ( + krb5_context /*context*/, + const void */*ptr*/, + size_t /*len*/, + struct krb5_pac **/*pac*/); + +krb5_error_code +krb5_pac_verify ( + krb5_context /*context*/, + const struct krb5_pac */*pac*/, + time_t /*authtime*/, + krb5_const_principal /*principal*/, + const krb5_keyblock */*server*/, + const krb5_keyblock */*privsvr*/); + int KRB5_LIB_FUNCTION krb5_padata_add ( krb5_context /*context*/, @@ -2904,6 +3076,12 @@ krb5_rd_req_in_set_keytab ( krb5_rd_req_in_ctx /*in*/, krb5_keytab /*keytab*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_set_pac_check ( + krb5_context /*context*/, + krb5_rd_req_in_ctx /*in*/, + krb5_boolean /*flag*/); + void KRB5_LIB_FUNCTION krb5_rd_req_out_ctx_free ( krb5_context /*context*/, @@ -3515,6 +3693,11 @@ krb5_ticket_get_client ( const krb5_ticket */*ticket*/, krb5_principal */*client*/); +time_t KRB5_LIB_FUNCTION +krb5_ticket_get_endtime ( + krb5_context /*context*/, + const krb5_ticket */*ticket*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_ticket_get_server ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 1b26e8b3e7..55a83fb533 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h,v 1.255 2006/11/12 08:33:07 lha Exp $ */ +/* $Id: krb5.h,v 1.259 2007/01/03 18:51:52 lha Exp $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -77,8 +77,10 @@ typedef struct krb5_get_creds_opt_data *krb5_get_creds_opt; struct krb5_digest; typedef struct krb5_digest *krb5_digest; +struct krb5_ntlm; +typedef struct krb5_ntlm *krb5_ntlm; -struct krb5_pac; +typedef struct krb5_pac *krb5_pac; typedef struct krb5_rd_req_in_ctx *krb5_rd_req_in_ctx; typedef struct krb5_rd_req_out_ctx *krb5_rd_req_out_ctx; @@ -216,8 +218,6 @@ typedef enum krb5_key_usage { /* Keyusage for the server referral in a TGS req */ KRB5_KU_SAM_ENC_NONCE_SAD = 27, /* Encryption of the SAM-NONCE-OR-SAD field */ - KRB5_KU_TGS_IMPERSONATE = -17, - /* Checksum type used in the impersonate field */ KRB5_KU_DIGEST_ENCRYPT = -18, /* Encryption key usage used in the digest encryption field */ KRB5_KU_DIGEST_OPAQUE = -19, @@ -716,6 +716,7 @@ typedef struct krb5_krbhst_data *krb5_krbhst_handle; #define KRB5_KRBHST_ADMIN 2 #define KRB5_KRBHST_CHANGEPW 3 #define KRB5_KRBHST_KRB524 4 +#define KRB5_KRBHST_KCA 5 typedef struct krb5_krbhst_info { enum { KRB5_KRBHST_UDP, diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 3fb5461b3c..35d046c8d9 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_locl.h,v 1.93 2006/10/20 18:13:31 lha Exp $ */ +/* $Id: krb5_locl.h,v 1.97 2006/12/15 16:46:51 lha Exp $ */ #ifndef __KRB5_LOCL_H__ #define __KRB5_LOCL_H__ @@ -239,20 +239,20 @@ typedef struct krb5_context_data { int large_msg_size; int dns_canonicalize_hostname; struct send_to_kdc *send_to_kdc; - void *mem_ctx; /* Some parts of Samba4 need a valid - memory context (under the event - context) to use */ } krb5_context_data; +#define KRB5_DEFAULT_CCNAME_FILE "FILE:/tmp/krb5cc_%{uid}" +#define KRB5_DEFAULT_CCNAME_API "API:" + /* * Configurable options */ #ifndef KRB5_DEFAULT_CCNAME #ifdef __APPLE__ -#define KRB5_DEFAULT_CCNAME "API:" +#define KRB5_DEFAULT_CCNAME KRB5_DEFAULT_CCNAME_API #else -#define KRB5_DEFAULT_CCNAME "FILE:/tmp/krb5cc_%{uid}" +#define KRB5_DEFAULT_CCNAME KRB5_DEFAULT_CCNAME_FILE #endif #endif diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index f395f0d0c3..3e281e5c63 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -35,7 +35,7 @@ #include #include "locate_plugin.h" -RCSID("$Id: krbhst.c,v 1.58 2006/11/12 20:05:20 lha Exp $"); +RCSID("$Id: krbhst.c,v 1.61 2006/11/30 17:23:08 lha Exp $"); static int string_to_proto(const char *string) @@ -493,7 +493,7 @@ add_locate(void *ctx, int type, struct sockaddr *addr) if (ret != 0) return 0; - memset(&hints, 0, sizeof(hints)); + make_hints(&hints, krbhst_get_default_proto(kd)); ret = getaddrinfo(host, port, &hints, &ai); if (ret) return 0; @@ -521,7 +521,7 @@ plugin_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, enum locate_service_type type) { - struct krb5_plugin *list, *e; + struct krb5_plugin *list = NULL, *e; krb5_error_code ret; ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, "resolve", &list); @@ -619,6 +619,13 @@ admin_get_next(krb5_context context, { krb5_error_code ret; + if ((kd->flags & KD_PLUGIN) == 0) { + plugin_get_hosts(context, kd, locate_service_kadmin); + kd->flags |= KD_PLUGIN; + if(get_next(kd, host)) + return 0; + } + if((kd->flags & KD_CONFIG) == 0) { config_get_hosts(context, kd, "admin_server"); kd->flags |= KD_CONFIG; @@ -660,6 +667,13 @@ kpasswd_get_next(krb5_context context, { krb5_error_code ret; + if ((kd->flags & KD_PLUGIN) == 0) { + plugin_get_hosts(context, kd, locate_service_kpasswd); + kd->flags |= KD_PLUGIN; + if(get_next(kd, host)) + return 0; + } + if((kd->flags & KD_CONFIG) == 0) { config_get_hosts(context, kd, "kpasswd_server"); kd->flags |= KD_CONFIG; @@ -705,6 +719,13 @@ krb524_get_next(krb5_context context, struct krb5_krbhst_data *kd, krb5_krbhst_info **host) { + if ((kd->flags & KD_PLUGIN) == 0) { + plugin_get_hosts(context, kd, locate_service_krb524); + kd->flags |= KD_PLUGIN; + if(get_next(kd, host)) + return 0; + } + if((kd->flags & KD_CONFIG) == 0) { config_get_hosts(context, kd, "krb524_server"); if(get_next(kd, host)) diff --git a/source4/heimdal/lib/krb5/log.c b/source4/heimdal/lib/krb5/log.c index e6fcb6bbb9..9523ca848c 100644 --- a/source4/heimdal/lib/krb5/log.c +++ b/source4/heimdal/lib/krb5/log.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: log.c,v 1.39 2006/04/24 15:09:27 lha Exp $"); +RCSID("$Id: log.c,v 1.40 2006/11/21 08:08:46 lha Exp $"); struct facility { int min; diff --git a/source4/heimdal/lib/krb5/mit_glue.c b/source4/heimdal/lib/krb5/mit_glue.c index 493c4cd845..c4d3ff5390 100755 --- a/source4/heimdal/lib/krb5/mit_glue.c +++ b/source4/heimdal/lib/krb5/mit_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: mit_glue.c,v 1.9 2006/11/09 21:24:16 lha Exp $"); +RCSID("$Id: mit_glue.c,v 1.12 2006/11/17 22:17:46 lha Exp $"); /* * Glue for MIT API @@ -327,9 +327,16 @@ krb5_c_make_random_key(krb5_context context, } krb5_error_code KRB5_LIB_FUNCTION -krb5_c_keylength(krb5_context context, - krb5_enctype enctype, - size_t *len) +krb5_c_keylengths(krb5_context context, + krb5_enctype enctype, + size_t *ilen, + size_t *keylen) { - return krb5_enctype_keysize(context, enctype, len); + krb5_error_code ret; + + ret = krb5_enctype_keybits(context, enctype, ilen); + if (ret) + return ret; + *ilen = (*ilen + 7) / 8; + return krb5_enctype_keysize(context, enctype, keylen); } diff --git a/source4/heimdal/lib/krb5/mk_req_ext.c b/source4/heimdal/lib/krb5/mk_req_ext.c index 18b0e3552f..8646c4ebea 100644 --- a/source4/heimdal/lib/krb5/mk_req_ext.c +++ b/source4/heimdal/lib/krb5/mk_req_ext.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_req_ext.c,v 1.32 2006/03/19 20:33:13 lha Exp $"); +RCSID("$Id: mk_req_ext.c,v 1.33 2006/12/27 12:07:22 lha Exp $"); krb5_error_code _krb5_mk_req_internal(krb5_context context, @@ -91,7 +91,9 @@ _krb5_mk_req_internal(krb5_context context, in_data->length, &c); } else if(ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5 || - ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56) { + ac->keyblock->keytype == ETYPE_ARCFOUR_HMAC_MD5_56 || + ac->keyblock->keytype == ETYPE_DES_CBC_MD4 || + ac->keyblock->keytype == ETYPE_DES_CBC_MD5) { /* this is to make MS kdc happy */ ret = krb5_create_checksum(context, NULL, diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c new file mode 100644 index 0000000000..5bc7235459 --- /dev/null +++ b/source4/heimdal/lib/krb5/pac.c @@ -0,0 +1,1034 @@ +/* + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: pac.c,v 1.13 2007/01/09 11:22:56 lha Exp $"); + +struct PAC_INFO_BUFFER { + uint32_t type; + uint32_t buffersize; + uint32_t offset_hi; + uint32_t offset_lo; +}; + +struct PACTYPE { + uint32_t numbuffers; + uint32_t version; + struct PAC_INFO_BUFFER buffers[1]; +}; + +struct krb5_pac { + struct PACTYPE *pac; + krb5_data data; + struct PAC_INFO_BUFFER *server_checksum; + struct PAC_INFO_BUFFER *privsvr_checksum; + struct PAC_INFO_BUFFER *logon_name; +}; + +#define PAC_ALIGNMENT 8 + +#define PACTYPE_SIZE 8 +#define PAC_INFO_BUFFER_SIZE 16 + +#define PAC_SERVER_CHECKSUM 6 +#define PAC_PRIVSVR_CHECKSUM 7 +#define PAC_LOGON_NAME 10 + +#define CHECK(r,f,l) \ + do { \ + if (((r) = f ) != 0) { \ + krb5_clear_error_string(context); \ + goto l; \ + } \ + } while(0) + +static const char zeros[PAC_ALIGNMENT] = { 0 }; + +/* + * + */ + +krb5_error_code +krb5_pac_parse(krb5_context context, const void *ptr, size_t len, + struct krb5_pac **pac) +{ + krb5_error_code ret; + struct krb5_pac *p; + krb5_storage *sp = NULL; + uint32_t i, tmp, tmp2, header_end; + + p = calloc(1, sizeof(*p)); + if (p == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "out of memory"); + goto out; + } + + sp = krb5_storage_from_readonly_mem(ptr, len); + if (sp == NULL) { + ret = ENOMEM; + krb5_set_error_string(context, "out of memory"); + goto out; + } + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + + CHECK(ret, krb5_ret_uint32(sp, &tmp), out); + CHECK(ret, krb5_ret_uint32(sp, &tmp2), out); + if (tmp < 1) { + krb5_set_error_string(context, "PAC have too few buffer"); + ret = EINVAL; /* Too few buffers */ + goto out; + } + if (tmp2 != 0) { + krb5_set_error_string(context, "PAC have wrong version"); + ret = EINVAL; /* Wrong version */ + goto out; + } + + p->pac = calloc(1, + sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (tmp - 1))); + if (p->pac == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + + p->pac->numbuffers = tmp; + p->pac->version = tmp2; + + header_end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers); + if (header_end > len) { + ret = EINVAL; + goto out; + } + + for (i = 0; i < p->pac->numbuffers; i++) { + CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].type), out); + CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].buffersize), out); + CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].offset_lo), out); + CHECK(ret, krb5_ret_uint32(sp, &p->pac->buffers[i].offset_hi), out); + + /* consistency checks */ + if (p->pac->buffers[i].offset_lo & (PAC_ALIGNMENT - 1)) { + krb5_set_error_string(context, "PAC out of allignment"); + ret = EINVAL; + goto out; + } + if (p->pac->buffers[i].offset_hi) { + krb5_set_error_string(context, "PAC high offset set"); + ret = EINVAL; + goto out; + } + if (p->pac->buffers[i].offset_lo > len) { + krb5_set_error_string(context, "PAC offset off end"); + ret = EINVAL; + goto out; + } + if (p->pac->buffers[i].offset_lo < header_end) { + krb5_set_error_string(context, "PAC offset inside header: %d %d", + p->pac->buffers[i].offset_lo, header_end); + ret = EINVAL; + goto out; + } + if (p->pac->buffers[i].buffersize > len - p->pac->buffers[i].offset_lo){ + krb5_set_error_string(context, "PAC length off end"); + ret = EINVAL; + goto out; + } + + /* let save pointer to data we need later */ + if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) { + if (p->server_checksum) { + krb5_set_error_string(context, "PAC have two server checksums"); + ret = EINVAL; + goto out; + } + p->server_checksum = &p->pac->buffers[i]; + } else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) { + if (p->privsvr_checksum) { + krb5_set_error_string(context, "PAC have two KDC checksums"); + ret = EINVAL; + goto out; + } + p->privsvr_checksum = &p->pac->buffers[i]; + } else if (p->pac->buffers[i].type == PAC_LOGON_NAME) { + if (p->logon_name) { + krb5_set_error_string(context, "PAC have two logon names"); + ret = EINVAL; + goto out; + } + p->logon_name = &p->pac->buffers[i]; + } + } + + ret = krb5_data_copy(&p->data, ptr, len); + if (ret) + goto out; + + krb5_storage_free(sp); + + *pac = p; + return 0; + +out: + if (sp) + krb5_storage_free(sp); + if (p) { + if (p->pac) + free(p->pac); + free(p); + } + *pac = NULL; + + return ret; +} + +krb5_error_code +krb5_pac_init(krb5_context context, struct krb5_pac **pac) +{ + krb5_error_code ret; + struct krb5_pac *p; + + p = calloc(1, sizeof(*p)); + if (p == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + + p->pac = calloc(1, sizeof(*p->pac)); + if (p->pac == NULL) { + free(p); + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + + ret = krb5_data_alloc(&p->data, PACTYPE_SIZE); + if (ret) { + free (p->pac); + free(p); + krb5_set_error_string(context, "out of memory"); + return ret; + } + + + *pac = p; + return 0; +} + +krb5_error_code +krb5_pac_add_buffer(krb5_context context, struct krb5_pac *p, + uint32_t type, const krb5_data *data) +{ + krb5_error_code ret; + void *ptr; + size_t len, offset, header_end; + uint32_t i; + + len = p->pac->numbuffers + 1; + if (len < p->pac->numbuffers) + return EINVAL; + + ptr = realloc(p->pac, + sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * len)); + if (ptr == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + p->pac = ptr; + + for (i = 0; i < len; i++) + p->pac->buffers[i].offset_lo += PAC_INFO_BUFFER_SIZE; + + offset = p->data.length + PAC_INFO_BUFFER_SIZE; + + p->pac->buffers[len - 1].type = type; + p->pac->buffers[len - 1].buffersize = data->length; + p->pac->buffers[len - 1].offset_lo = offset; + p->pac->buffers[len - 1].offset_hi = 0; + + len = p->data.length + data->length + PAC_INFO_BUFFER_SIZE; + if (len < p->data.length) { + krb5_set_error_string(context, "integer overrun"); + return EINVAL; + } + + /* align to PAC_ALIGNMENT */ + len = ((len + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT) * PAC_ALIGNMENT; + + ret = krb5_data_realloc(&p->data, len); + if (ret) { + krb5_set_error_string(context, "out of memory"); + return ret; + } + + /* make place for PAC INFO BUFFER header */ + header_end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers); + memmove((unsigned char *)p->data.data + header_end, + (unsigned char *)p->data.data + header_end + PAC_INFO_BUFFER_SIZE, + PAC_INFO_BUFFER_SIZE); + + /* + * + */ + + memcpy((unsigned char *)p->data.data + offset, + data->data, data->length); + memset((unsigned char *)p->data.data + offset + data->length, + 0, p->data.length - offset - data->length); + + p->pac->numbuffers += 1; + + return 0; +} + +krb5_error_code +krb5_pac_get_buffer(krb5_context context, struct krb5_pac *p, + uint32_t type, krb5_data *data) +{ + krb5_error_code ret; + uint32_t i; + + /* + * Hide the checksums from external consumers + */ + + if (type == PAC_PRIVSVR_CHECKSUM || type == PAC_SERVER_CHECKSUM) { + ret = krb5_data_alloc(data, 16); + if (ret) { + krb5_set_error_string(context, "out of memory"); + return ret; + } + memset(data->data, 0, data->length); + return 0; + } + + for (i = 0; i < p->pac->numbuffers; i++) { + size_t len = p->pac->buffers[i].buffersize; + size_t offset = p->pac->buffers[i].offset_lo; + + if (p->pac->buffers[i].type != type) + continue; + + ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len); + if (ret) { + krb5_set_error_string(context, "Out of memory"); + return ret; + } + return 0; + } + krb5_set_error_string(context, "No PAC buffer of type %lu was found", + (unsigned long)type); + return ENOENT; +} + +/* + * + */ + +krb5_error_code +krb5_pac_get_types(krb5_context context, + struct krb5_pac *p, + size_t *len, + uint32_t **types) +{ + size_t i; + + *types = calloc(p->pac->numbuffers, sizeof(*types)); + if (*types == NULL) { + *len = 0; + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + for (i = 0; i < p->pac->numbuffers; i++) + (*types)[i] = p->pac->buffers[i].type; + *len = p->pac->numbuffers; + + return 0; +} + +/* + * + */ + +void +krb5_pac_free(krb5_context context, struct krb5_pac *pac) +{ + krb5_data_free(&pac->data); + free(pac->pac); + free(pac); +} + +/* + * + */ + +static krb5_error_code +verify_checksum(krb5_context context, + const struct PAC_INFO_BUFFER *sig, + const krb5_data *data, + void *ptr, size_t len, + const krb5_keyblock *key) +{ + krb5_crypto crypto = NULL; + krb5_storage *sp = NULL; + uint32_t type; + krb5_error_code ret; + Checksum cksum; + + sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo, + sig->buffersize); + if (sp == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + + CHECK(ret, krb5_ret_uint32(sp, &type), out); + cksum.cksumtype = type; + cksum.checksum.length = + sig->buffersize - krb5_storage_seek(sp, 0, SEEK_CUR); + cksum.checksum.data = malloc(cksum.checksum.length); + if (cksum.checksum.data == NULL) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + ret = krb5_storage_read(sp, cksum.checksum.data, cksum.checksum.length); + if (ret != cksum.checksum.length) { + krb5_set_error_string(context, "PAC checksum missing checksum"); + ret = EINVAL; + goto out; + } + + if (!krb5_checksum_is_keyed(context, cksum.cksumtype)) { + krb5_set_error_string (context, "Checksum type %d not keyed", + cksum.cksumtype); + ret = EINVAL; + goto out; + } + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + goto out; + + ret = krb5_verify_checksum(context, crypto, KRB5_KU_OTHER_CKSUM, + ptr, len, &cksum); + krb5_crypto_destroy(context, crypto); + krb5_storage_free(sp); + + return ret; + +out: + if (sp) + krb5_storage_free(sp); + if (crypto) + krb5_crypto_destroy(context, crypto); + return ret; +} + +static krb5_error_code +create_checksum(krb5_context context, + const krb5_keyblock *key, + void *data, size_t datalen, + void *sig, size_t siglen) +{ + krb5_crypto crypto = NULL; + krb5_error_code ret; + Checksum cksum; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + + ret = krb5_create_checksum(context, crypto, KRB5_KU_OTHER_CKSUM, 0, + data, datalen, &cksum); + krb5_crypto_destroy(context, crypto); + if (ret) + return ret; + + if (cksum.checksum.length != siglen) { + krb5_set_error_string(context, "pac checksum wrong length"); + free_Checksum(&cksum); + return EINVAL; + } + + memcpy(sig, cksum.checksum.data, siglen); + free_Checksum(&cksum); + + return 0; +} + + +/* + * + */ + +#define NTTIME_EPOCH 0x019DB1DED53E8000LL + +static uint64_t +unix2nttime(time_t unix_time) +{ + long long wt; + wt = unix_time * (uint64_t)10000000 + (uint64_t)NTTIME_EPOCH; + return wt; +} + +static krb5_error_code +verify_logonname(krb5_context context, + const struct PAC_INFO_BUFFER *logon_name, + const krb5_data *data, + time_t authtime, + krb5_const_principal principal) +{ + krb5_error_code ret; + krb5_principal p2; + uint32_t time1, time2; + krb5_storage *sp; + uint16_t len; + char *s; + + sp = krb5_storage_from_readonly_mem((const char *)data->data + logon_name->offset_lo, + logon_name->buffersize); + if (sp == NULL) { + krb5_set_error_string(context, "Out of memory"); + return ENOMEM; + } + + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + + CHECK(ret, krb5_ret_uint32(sp, &time1), out); + CHECK(ret, krb5_ret_uint32(sp, &time2), out); + + { + uint64_t t1, t2; + t1 = unix2nttime(authtime); + t2 = ((uint64_t)time2 << 32) | time1; + if (t1 != t2) { + krb5_storage_free(sp); + krb5_set_error_string(context, "PAC timestamp mismatch"); + return EINVAL; + } + } + CHECK(ret, krb5_ret_uint16(sp, &len), out); + if (len == 0) { + krb5_storage_free(sp); + krb5_set_error_string(context, "PAC logon name length missing"); + return EINVAL; + } + + s = malloc(len); + if (s == NULL) { + krb5_storage_free(sp); + krb5_set_error_string(context, "Out of memory"); + return ENOMEM; + } + ret = krb5_storage_read(sp, s, len); + if (ret != len) { + krb5_storage_free(sp); + krb5_set_error_string(context, "Failed to read pac logon name"); + return EINVAL; + } + krb5_storage_free(sp); +#if 1 /* cheat for now */ + { + size_t i; + + if (len & 1) { + krb5_set_error_string(context, "PAC logon name malformed"); + return EINVAL; + } + + for (i = 0; i < len / 2; i++) { + if (s[(i * 2) + 1]) { + krb5_set_error_string(context, "PAC logon name not ASCII"); + return EINVAL; + } + s[i] = s[i * 2]; + } + s[i] = '\0'; + } +#else + { + uint16_t *ucs2; + ssize_t ucs2len; + size_t u8len; + + ucs2 = malloc(sizeof(ucs2[0]) * len / 2); + if (ucs2) + abort(); + ucs2len = wind_ucs2read(s, len / 2, ucs2); + free(s); + if (len < 0) + return -1; + ret = wind_ucs2toutf8(ucs2, ucs2len, NULL, &u8len); + if (ret < 0) + abort(); + s = malloc(u8len + 1); + if (s == NULL) + abort(); + wind_ucs2toutf8(ucs2, ucs2len, s, &u8len); + free(ucs2); + } +#endif + ret = krb5_parse_name_flags(context, s, KRB5_PRINCIPAL_PARSE_NO_REALM, &p2); + free(s); + if (ret) + return ret; + + if (krb5_principal_compare_any_realm(context, principal, p2) != TRUE) { + krb5_set_error_string(context, "PAC logon name mismatch"); + ret = EINVAL; + } + krb5_free_principal(context, p2); + return ret; +out: + return ret; +} + +/* + * + */ + +static krb5_error_code +build_logon_name(krb5_context context, + time_t authtime, + krb5_const_principal principal, + krb5_data *logon) +{ + krb5_error_code ret; + krb5_storage *sp; + uint64_t t; + char *s, *s2; + size_t i, len; + + t = unix2nttime(authtime); + + krb5_data_zero(logon); + + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + + CHECK(ret, krb5_store_uint32(sp, t & 0xffffffff), out); + CHECK(ret, krb5_store_uint32(sp, t >> 32), out); + + ret = krb5_unparse_name_flags(context, principal, + KRB5_PRINCIPAL_UNPARSE_NO_REALM, &s); + if (ret) + goto out; + + len = strlen(s); + + CHECK(ret, krb5_store_uint16(sp, len * 2), out); + +#if 1 /* cheat for now */ + s2 = malloc(len * 2); + if (s2 == NULL) { + ret = ENOMEM; + free(s); + goto out; + } + for (i = 0; i < len; i++) { + s2[i * 2] = s[i]; + s2[i * 2 + 1] = 0; + } + free(s); +#else + /* write libwind code here */ +#endif + + ret = krb5_storage_write(sp, s2, len * 2); + free(s2); + if (ret != len * 2) { + ret = ENOMEM; + goto out; + } + ret = krb5_storage_to_data(sp, logon); + if (ret) + goto out; + krb5_storage_free(sp); + + return 0; +out: + krb5_storage_free(sp); + return ret; +} + + +/* + * + */ + +krb5_error_code +krb5_pac_verify(krb5_context context, + const struct krb5_pac *pac, + time_t authtime, + krb5_const_principal principal, + const krb5_keyblock *server, + const krb5_keyblock *privsvr) +{ + krb5_error_code ret; + + if (pac->server_checksum == NULL) { + krb5_set_error_string(context, "PAC missing server checksum"); + return EINVAL; + } + if (pac->privsvr_checksum == NULL) { + krb5_set_error_string(context, "PAC missing kdc checksum"); + return EINVAL; + } + if (pac->logon_name == NULL) { + krb5_set_error_string(context, "PAC missing logon name"); + return EINVAL; + } + + ret = verify_logonname(context, + pac->logon_name, + &pac->data, + authtime, + principal); + if (ret) + return ret; + + /* + * in the service case, clean out data option of the privsvr and + * server checksum before checking the checksum. + */ + { + krb5_data *copy; + + ret = krb5_copy_data(context, &pac->data, ©); + if (ret) + return ret; + + if (pac->server_checksum->buffersize < 4) + return EINVAL; + if (pac->privsvr_checksum->buffersize < 4) + return EINVAL; + + memset((char *)copy->data + pac->server_checksum->offset_lo + 4, + 0, + pac->server_checksum->buffersize - 4); + + memset((char *)copy->data + pac->privsvr_checksum->offset_lo + 4, + 0, + pac->privsvr_checksum->buffersize - 4); + + ret = verify_checksum(context, + pac->server_checksum, + &pac->data, + copy->data, + copy->length, + server); + krb5_free_data(context, copy); + if (ret) + return ret; + } + if (privsvr) { + ret = verify_checksum(context, + pac->privsvr_checksum, + &pac->data, + (char *)pac->data.data + + pac->server_checksum->offset_lo + 4, + pac->server_checksum->buffersize - 4, + privsvr); + if (ret) + return ret; + } + + return 0; +} + +/* + * + */ + +static krb5_error_code +fill_zeros(krb5_context context, krb5_storage *sp, size_t len) +{ + ssize_t sret; + size_t l; + + while (len) { + l = len; + if (l > sizeof(zeros)) + l = sizeof(zeros); + sret = krb5_storage_write(sp, zeros, l); + if (sret <= 0) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + len -= sret; + } + return 0; +} + +static krb5_error_code +pac_checksum(krb5_context context, + const krb5_keyblock *key, + uint32_t *cksumtype, + size_t *cksumsize) +{ + krb5_cksumtype cktype; + krb5_error_code ret; + krb5_crypto crypto = NULL; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + + ret = krb5_crypto_get_checksum_type(context, crypto, &cktype); + ret = krb5_crypto_destroy(context, crypto); + if (ret) + return ret; + + if (krb5_checksum_is_keyed(context, cktype) == FALSE) { + krb5_set_error_string(context, "PAC checksum type is not keyed"); + return EINVAL; + } + + ret = krb5_checksumsize(context, cktype, cksumsize); + if (ret) + return ret; + + *cksumtype = (uint32_t)cktype; + + return 0; +} + +krb5_error_code +_krb5_pac_sign(krb5_context context, + struct krb5_pac *p, + time_t authtime, + krb5_principal principal, + const krb5_keyblock *server_key, + const krb5_keyblock *priv_key, + krb5_data *data) +{ + krb5_error_code ret; + krb5_storage *sp = NULL, *spdata = NULL; + uint32_t end; + size_t server_size, priv_size; + uint32_t server_offset = 0, priv_offset = 0; + uint32_t server_cksumtype = 0, priv_cksumtype = 0; + int i, num = 0; + krb5_data logon, d; + + krb5_data_zero(&logon); + + if (p->server_checksum == NULL) + num++; + if (p->privsvr_checksum == NULL) + num++; + if (p->logon_name == NULL) + num++; + + if (num) { + void *ptr; + + ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (p->pac->numbuffers + num - 1))); + if (ptr == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + p->pac = ptr; + + if (p->server_checksum == NULL) { + p->server_checksum = &p->pac->buffers[p->pac->numbuffers++]; + memset(p->server_checksum, 0, sizeof(*p->server_checksum)); + p->server_checksum->type = PAC_SERVER_CHECKSUM; + } + if (p->privsvr_checksum == NULL) { + p->privsvr_checksum = &p->pac->buffers[p->pac->numbuffers++]; + memset(p->privsvr_checksum, 0, sizeof(*p->privsvr_checksum)); + p->privsvr_checksum->type = PAC_PRIVSVR_CHECKSUM; + } + if (p->logon_name == NULL) { + p->logon_name = &p->pac->buffers[p->pac->numbuffers++]; + memset(p->logon_name, 0, sizeof(*p->logon_name)); + p->logon_name->type = PAC_LOGON_NAME; + } + } + + /* Calculate LOGON NAME */ + ret = build_logon_name(context, authtime, principal, &logon); + if (ret) + goto out; + + /* Set lengths for checksum */ + + ret = pac_checksum(context, server_key, &server_cksumtype, &server_size); + if (ret) + goto out; + ret = pac_checksum(context, priv_key, &priv_cksumtype, &priv_size); + if (ret) + goto out; + + /* Encode PAC */ + sp = krb5_storage_emem(); + if (sp == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); + + spdata = krb5_storage_emem(); + if (spdata == NULL) { + krb5_storage_free(sp); + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + krb5_storage_set_flags(spdata, KRB5_STORAGE_BYTEORDER_LE); + + CHECK(ret, krb5_store_uint32(sp, p->pac->numbuffers), out); + CHECK(ret, krb5_store_uint32(sp, p->pac->version), out); + + end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers); + + for (i = 0; i < p->pac->numbuffers; i++) { + uint32_t len; + size_t sret; + void *ptr = NULL; + + /* store data */ + + if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) { + len = server_size + 4; + server_offset = end + 4; + CHECK(ret, krb5_store_uint32(spdata, server_cksumtype), out); + CHECK(ret, fill_zeros(context, spdata, server_size), out); + } else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) { + len = priv_size + 4; + priv_offset = end + 4; + CHECK(ret, krb5_store_uint32(spdata, priv_cksumtype), out); + CHECK(ret, fill_zeros(context, spdata, priv_size), out); + } else if (p->pac->buffers[i].type == PAC_LOGON_NAME) { + len = krb5_storage_write(spdata, logon.data, logon.length); + if (logon.length != len) { + ret = EINVAL; + goto out; + } + } else { + len = p->pac->buffers[i].buffersize; + ptr = (char *)p->data.data + p->pac->buffers[i].offset_lo; + + sret = krb5_storage_write(spdata, ptr, len); + if (sret != len) { + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + /* XXX if not aligned, fill_zeros */ + } + + /* write header */ + CHECK(ret, krb5_store_uint32(sp, p->pac->buffers[i].type), out); + CHECK(ret, krb5_store_uint32(sp, len), out); + CHECK(ret, krb5_store_uint32(sp, end), out); + CHECK(ret, krb5_store_uint32(sp, 0), out); + + /* advance data endpointer and align */ + { + int32_t e; + + end += len; + e = ((end + PAC_ALIGNMENT - 1) / PAC_ALIGNMENT) * PAC_ALIGNMENT; + if (end != e) { + CHECK(ret, fill_zeros(context, spdata, e - end), out); + } + end = e; + } + + } + + /* assert (server_offset != 0 && priv_offset != 0); */ + + /* export PAC */ + ret = krb5_storage_to_data(spdata, &d); + if (ret) { + krb5_set_error_string(context, "out of memory"); + goto out; + } + ret = krb5_storage_write(sp, d.data, d.length); + if (ret != d.length) { + krb5_data_free(&d); + krb5_set_error_string(context, "out of memory"); + ret = ENOMEM; + goto out; + } + krb5_data_free(&d); + + ret = krb5_storage_to_data(sp, &d); + if (ret) { + krb5_set_error_string(context, "out of memory"); + goto out; + } + + /* sign */ + + ret = create_checksum(context, server_key, + d.data, d.length, + (char *)d.data + server_offset, server_size); + if (ret) { + krb5_data_free(&d); + goto out; + } + + ret = create_checksum(context, priv_key, + (char *)d.data + server_offset, server_size, + (char *)d.data + priv_offset, priv_size); + if (ret) { + krb5_data_free(&d); + goto out; + } + + /* done */ + *data = d; + + krb5_data_free(&logon); + krb5_storage_free(sp); + krb5_storage_free(spdata); + + return 0; +out: + krb5_data_free(&logon); + if (sp) + krb5_storage_free(sp); + if (spdata) + krb5_storage_free(spdata); + return ret; +} diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index f519b5ad08..4f8ed8fe07 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.110 2006/10/14 09:52:50 lha Exp $"); +RCSID("$Id: pkinit.c,v 1.120 2006/12/08 02:48:09 lha Exp $"); struct krb5_dh_moduli { char *name; @@ -81,12 +81,26 @@ struct krb5_pk_init_ctx_data { DH *dh; krb5_data *clientDHNonce; struct krb5_dh_moduli **m; + hx509_peer_info peer; + int type; int require_binding; int require_eku; int require_krbtgt_otherName; int require_hostname_match; }; +static void +_krb5_pk_copy_error(krb5_context context, + hx509_context hx509ctx, + int hxret, + const char *fmt, + ...) + __attribute__ ((format (printf, 4, 5))); + +/* + * + */ + void KRB5_LIB_FUNCTION _krb5_pk_cert_free(struct krb5_pk_cert *cert) { @@ -130,6 +144,7 @@ _krb5_pk_create_sign(krb5_context context, const heim_oid *eContentType, krb5_data *eContent, struct krb5_pk_identity *id, + hx509_peer_info peer, krb5_data *sd_data) { hx509_cert cert; @@ -137,16 +152,22 @@ _krb5_pk_create_sign(krb5_context context, int ret; ret = hx509_query_alloc(id->hx509ctx, &q); - if (ret) + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Allocate query to find signing certificate"); return ret; + } hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); ret = hx509_certs_find(id->hx509ctx, id->certs, q, &cert); hx509_query_free(id->hx509ctx, q); - if (ret) + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Find certificate to signed CMS data"); return ret; + } ret = hx509_cms_create_signed_1(id->hx509ctx, eContentType, @@ -154,9 +175,12 @@ _krb5_pk_create_sign(krb5_context context, eContent->length, NULL, cert, + peer, NULL, - NULL, + id->certs, sd_data); + if (ret) + _krb5_pk_copy_error(context, id->hx509ctx, ret, "create CMS signedData"); hx509_cert_free(cert); return ret; @@ -402,6 +426,19 @@ build_auth_pack(krb5_context context, a->clientPublicValue->subjectPublicKey.data = dhbuf.data; } + { + a->supportedCMSTypes = calloc(1, sizeof(*a->supportedCMSTypes)); + if (a->supportedCMSTypes == NULL) + return ENOMEM; + + ret = hx509_crypto_available(ctx->id->hx509ctx, HX509_SELECT_ALL, NULL, + &a->supportedCMSTypes->val, + &a->supportedCMSTypes->len); + if (ret) + return ret; + } + + return ret; } @@ -429,7 +466,6 @@ _krb5_pk_mk_ContentInfo(krb5_context context, static krb5_error_code pk_mk_padata(krb5_context context, - int compat, krb5_pk_init_ctx ctx, const KDC_REQ_BODY *req_body, unsigned nonce, @@ -446,7 +482,7 @@ pk_mk_padata(krb5_context context, krb5_data_zero(&sd_buf); memset(&content_info, 0, sizeof(content_info)); - if (compat == COMPAT_WIN2K) { + if (ctx->type == COMPAT_WIN2K) { AuthPack_Win2k ap; krb5_timestamp sec; int32_t usec; @@ -483,7 +519,7 @@ pk_mk_padata(krb5_context context, krb5_abortx(context, "internal ASN1 encoder error"); oid = oid_id_pkcs7_data(); - } else if (compat == COMPAT_IETF) { + } else if (ctx->type == COMPAT_IETF) { AuthPack ap; memset(&ap, 0, sizeof(ap)); @@ -510,7 +546,8 @@ pk_mk_padata(krb5_context context, ret = _krb5_pk_create_sign(context, oid, &buf, - ctx->id, + ctx->id, + ctx->peer, &sd_buf); krb5_data_free(&buf); if (ret) @@ -529,7 +566,7 @@ pk_mk_padata(krb5_context context, if (buf.length != size) krb5_abortx(context, "Internal ASN1 encoder error"); - if (compat == COMPAT_WIN2K) { + if (ctx->type == COMPAT_WIN2K) { PA_PK_AS_REQ_Win2k winreq; pa_type = KRB5_PADATA_PK_AS_REQ_WIN; @@ -542,7 +579,7 @@ pk_mk_padata(krb5_context context, &winreq, &size, ret); free_PA_PK_AS_REQ_Win2k(&winreq); - } else if (compat == COMPAT_IETF) { + } else if (ctx->type == COMPAT_IETF) { PA_PK_AS_REQ req; pa_type = KRB5_PADATA_PK_AS_REQ; @@ -583,7 +620,7 @@ pk_mk_padata(krb5_context context, if (ret) free(buf.data); - if (ret == 0 && compat == COMPAT_WIN2K) + if (ret == 0 && ctx->type == COMPAT_WIN2K) krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0); out: @@ -601,13 +638,13 @@ _krb5_pk_mk_padata(krb5_context context, METHOD_DATA *md) { krb5_pk_init_ctx ctx = c; - int win2k_compat, type; + int win2k_compat; win2k_compat = krb5_config_get_bool_default(context, NULL, FALSE, "realms", req_body->realm, - "win2k_pkinit", + "pkinit_win2k", NULL); if (context->pkinit_flags & KRB5_PKINIT_WIN2K) win2k_compat = 1; @@ -618,11 +655,11 @@ _krb5_pk_mk_padata(krb5_context context, FALSE, "realms", req_body->realm, - "win2k_pkinit_require_binding", + "pkinit_win2k_require_binding", NULL); - type = COMPAT_WIN2K; + ctx->type = COMPAT_WIN2K; } else - type = COMPAT_IETF; + ctx->type = COMPAT_IETF; ctx->require_eku = krb5_config_get_bool_default(context, NULL, @@ -647,7 +684,7 @@ _krb5_pk_mk_padata(krb5_context context, "pkinit_require_hostname_match", NULL); - return pk_mk_padata(context, type, ctx, req_body, nonce, md); + return pk_mk_padata(context, ctx, req_body, nonce, md); } krb5_error_code KRB5_LIB_FUNCTION @@ -673,13 +710,8 @@ _krb5_pk_verify_sign(krb5_context context, content, &signer_certs); if (ret) { - char *s = hx509_get_error_string(id->hx509ctx, ret); - if (s) { - krb5_set_error_string(context, - "CMS verify signed failed with %s", s); - free(s); - } else - krb5_clear_error_string(context); + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "CMS verify signed failed"); return ret; } @@ -692,7 +724,8 @@ _krb5_pk_verify_sign(krb5_context context, ret = hx509_get_one_cert(id->hx509ctx, signer_certs, &(*signer)->cert); if (ret) { - krb5_clear_error_string(context); + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed to get on of the signer certs"); goto out; } @@ -932,8 +965,11 @@ pk_rd_pa_reply_enckey(krb5_context context, NULL, &contentType, &content); - if (ret) + if (ret) { + _krb5_pk_copy_error(context, ctx->id->hx509ctx, ret, + "Failed to unenvelope CMS data in PK-INIT reply"); return ret; + } p = content.data; length = content.length; @@ -1212,8 +1248,13 @@ _krb5_pk_rd_pa_reply(krb5_context context, size_t size; /* Check for IETF PK-INIT first */ - if (pa->padata_type == KRB5_PADATA_PK_AS_REP) { + if (ctx->type == COMPAT_IETF) { PA_PK_AS_REP rep; + + if (pa->padata_type != KRB5_PADATA_PK_AS_REP) { + krb5_set_error_string(context, "PKINIT: wrong padata recv"); + return EINVAL; + } memset(&rep, 0, sizeof(rep)); @@ -1269,14 +1310,19 @@ _krb5_pk_rd_pa_reply(krb5_context context, ret = EINVAL; break; } - if (ret == 0) - return ret; - } - /* Check for Windows encoding of the AS-REP pa data */ - { + } else if (ctx->type == COMPAT_WIN2K) { PA_PK_AS_REP_Win2k w2krep; + /* Check for Windows encoding of the AS-REP pa data */ + +#if 0 /* should this be ? */ + if (pa->padata_type != KRB5_PADATA_PK_AS_REP) { + krb5_set_error_string(context, "PKINIT: wrong padata recv"); + return EINVAL; + } +#endif + memset(&w2krep, 0, sizeof(w2krep)); ret = decode_PA_PK_AS_REP_Win2k(pa->padata_value.data, @@ -1317,6 +1363,9 @@ _krb5_pk_rd_pa_reply(krb5_context context, break; } + } else { + krb5_set_error_string(context, "PKINIT: unknown reply type"); + ret = EINVAL; } return ret; @@ -1428,25 +1477,34 @@ _krb5_pk_load_id(krb5_context context, } ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs); - if (ret) + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed to init cert certs"); goto out; + } ret = hx509_certs_init(id->hx509ctx, anchor_id, 0, NULL, &id->anchors); - if (ret) + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed to init anchors"); goto out; + } ret = hx509_certs_init(id->hx509ctx, "MEMORY:pkinit-cert-chain", 0, NULL, &id->certpool); - if (ret) + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed to init chain"); goto out; + } while (chain_list && *chain_list) { ret = hx509_certs_append(id->hx509ctx, id->certpool, NULL, *chain_list); if (ret) { - krb5_set_error_string(context, - "pkinit failed to load chain %s", - *chain_list); + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed to laod chain %s", + *chain_list); goto out; } chain_list++; @@ -1455,7 +1513,8 @@ _krb5_pk_load_id(krb5_context context, if (revoke_list) { ret = hx509_revoke_init(id->hx509ctx, &id->revokectx); if (ret) { - krb5_set_error_string(context, "revoke failed to init"); + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed init revoke list"); goto out; } @@ -1464,9 +1523,8 @@ _krb5_pk_load_id(krb5_context context, id->revokectx, *revoke_list); if (ret) { - krb5_set_error_string(context, - "pkinit failed to load revoke %s", - *revoke_list); + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed load revoke list"); goto out; } revoke_list++; @@ -1475,8 +1533,11 @@ _krb5_pk_load_id(krb5_context context, hx509_context_set_missing_revoke(id->hx509ctx, 1); ret = hx509_verify_init_ctx(id->hx509ctx, &id->verify_ctx); - if (ret) + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed init verify context"); goto out; + } hx509_verify_attach_anchors(id->verify_ctx, id->anchors); hx509_verify_attach_revoke(id->verify_ctx, id->revokectx); @@ -1504,9 +1565,25 @@ select_dh_group(krb5_context context, DH *dh, unsigned long bits, { const struct krb5_dh_moduli *m; - m = moduli[1]; /* XXX */ - if (m == NULL) - m = moduli[0]; /* XXX */ + if (bits == 0) { + m = moduli[1]; /* XXX */ + if (m == NULL) + m = moduli[0]; /* XXX */ + } else { + int i; + for (i = 0; moduli[i] != NULL; i++) { + if (bits < moduli[i]->bits) + break; + } + if (moduli[i] == NULL) { + krb5_set_error_string(context, + "Did not find a DH group parameter " + "matching requirement of %lu bits", + bits); + return EINVAL; + } + m = moduli[i]; + } dh->p = integer_to_BN(context, "p", &m->p); if (dh->p == NULL) @@ -1822,25 +1899,25 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, opt->opt_private->pk_init_ctx->require_binding = 0; opt->opt_private->pk_init_ctx->require_eku = 1; opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1; - + opt->opt_private->pk_init_ctx->peer = NULL; /* XXX implement krb5_appdefault_strings */ if (pool == NULL) pool = krb5_config_get_strings(context, NULL, "appdefaults", - "pkinit-pool", + "pkinit_pool", NULL); if (pki_revoke == NULL) pki_revoke = krb5_config_get_strings(context, NULL, "appdefaults", - "pkinit-revoke", + "pkinit_revoke", NULL); if (x509_anchors == NULL) { krb5_appdefault_string(context, "kinit", krb5_principal_get_realm(context, principal), - "pkinit-anchors", NULL, &anchors); + "pkinit_anchors", NULL, &anchors); x509_anchors = anchors; } @@ -1861,12 +1938,19 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, if ((flags & 2) == 0) { const char *moduli_file; + unsigned long dh_min_bits; moduli_file = krb5_config_get_string(context, NULL, "libdefaults", "moduli", NULL); + dh_min_bits = + krb5_config_get_int_default(context, NULL, 0, + "libdefaults", + "pkinit_dh_min_bits", + NULL); + ret = _krb5_parse_moduli(context, moduli_file, &opt->opt_private->pk_init_ctx->m); if (ret) { @@ -1881,7 +1965,8 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, return ENOMEM; } - ret = select_dh_group(context, opt->opt_private->pk_init_ctx->dh, 0, + ret = select_dh_group(context, opt->opt_private->pk_init_ctx->dh, + dh_min_bits, opt->opt_private->pk_init_ctx->m); if (ret) { _krb5_get_init_creds_opt_free_pkinit(opt); @@ -1901,3 +1986,36 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, return EINVAL; #endif } + +/* + * + */ + +static void +_krb5_pk_copy_error(krb5_context context, + hx509_context hx509ctx, + int hxret, + const char *fmt, + ...) +{ + va_list va; + char *s, *f; + + va_start(va, fmt); + vasprintf(&f, fmt, va); + va_end(va); + if (f == NULL) { + krb5_clear_error_string(context); + return; + } + + s = hx509_get_error_string(hx509ctx, hxret); + if (s == NULL) { + krb5_clear_error_string(context); + free(f); + return; + } + krb5_set_error_string(context, "%s: %s", f, s); + free(s); + free(f); +} diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c index 294807faab..ce7171dbf0 100644 --- a/source4/heimdal/lib/krb5/plugin.c +++ b/source4/heimdal/lib/krb5/plugin.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 Kungliga Tekniska Högskolan + * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: plugin.c,v 1.2 2006/11/12 21:39:43 lha Exp $"); +RCSID("$Id: plugin.c,v 1.4 2007/01/09 17:46:01 lha Exp $"); #ifdef HAVE_DLFCN_H #include #endif @@ -89,7 +89,11 @@ loadlib(krb5_context context, return ENOMEM; } - (*e)->dsohandle = dlopen(lib, 0); +#ifndef RTLD_LAZY +#define RTLD_LAZY 0 +#endif + + (*e)->dsohandle = dlopen(lib, RTLD_LAZY); if ((*e)->dsohandle == NULL) { free(*e); krb5_set_error_string(context, "Failed to load %s: %s", diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index 4d13e7db11..57fcf63dcf 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -41,7 +41,7 @@ #include #include "resolve.h" -RCSID("$Id: principal.c,v 1.99 2006/10/18 06:53:22 lha Exp $"); +RCSID("$Id: principal.c,v 1.100 2006/12/17 22:53:39 lha Exp $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 3352334f65..b7dea2a327 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_req.c,v 1.68 2006/11/07 17:11:31 lha Exp $"); +RCSID("$Id: rd_req.c,v 1.70 2007/01/04 11:27:20 lha Exp $"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, @@ -513,6 +513,7 @@ krb5_verify_ap_req2(krb5_context context, struct krb5_rd_req_in_ctx { krb5_keytab keytab; krb5_keyblock *keyblock; + krb5_boolean no_pac_check; }; struct krb5_rd_req_out_ctx { @@ -545,6 +546,16 @@ krb5_rd_req_in_set_keytab(krb5_context context, return 0; } +krb5_error_code KRB5_LIB_FUNCTION +krb5_rd_req_in_set_pac_check(krb5_context context, + krb5_rd_req_in_ctx in, + krb5_boolean flag) +{ + in->no_pac_check = !flag; + return 0; +} + + krb5_error_code KRB5_LIB_FUNCTION krb5_rd_req_in_set_keyblock(krb5_context context, krb5_rd_req_in_ctx in, @@ -822,6 +833,36 @@ krb5_rd_req_ctx(krb5_context context, &o->ap_req_options, &o->ticket); + if (ret) + goto out; + + /* If there is a PAC, verify its server signature */ + if (inctx->no_pac_check == FALSE) { + krb5_pac pac; + krb5_data data; + + ret = krb5_ticket_get_authorization_data_type(context, + o->ticket, + KRB5_AUTHDATA_WIN2K_PAC, + &data); + if (ret == 0) { + ret = krb5_pac_parse(context, data.data, data.length, &pac); + krb5_data_free(&data); + if (ret) + goto out; + + ret = krb5_pac_verify(context, + pac, + o->ticket->ticket.authtime, + o->ticket->client, + o->keyblock, + NULL); + krb5_pac_free(context, pac); + if (ret) + goto out; + } + ret = 0; + } out: if (ret || outctx == NULL) { krb5_rd_req_out_ctx_free(context, o); diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c index e75f28ca5f..5422c540b9 100644 --- a/source4/heimdal/lib/krb5/store.c +++ b/source4/heimdal/lib/krb5/store.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store.c,v 1.59 2006/08/18 08:39:13 lha Exp $"); +RCSID("$Id: store.c,v 1.60 2006/12/17 22:49:37 lha Exp $"); #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) @@ -577,6 +577,7 @@ krb5_ret_principal(krb5_storage *sp, p->name.name_string.val = calloc(ncomp, sizeof(*p->name.name_string.val)); if(p->name.name_string.val == NULL && ncomp != 0){ free(p->realm); + free(p); return ENOMEM; } for(i = 0; i < ncomp; i++){ diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c index fdc2a1b3a5..81372c158e 100644 --- a/source4/heimdal/lib/krb5/ticket.c +++ b/source4/heimdal/lib/krb5/ticket.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: ticket.c,v 1.15 2006/10/14 09:53:19 lha Exp $"); +RCSID("$Id: ticket.c,v 1.18 2006/12/28 20:49:18 lha Exp $"); krb5_error_code KRB5_LIB_FUNCTION krb5_free_ticket(krb5_context context, @@ -97,6 +97,13 @@ krb5_ticket_get_server(krb5_context context, return krb5_copy_principal(context, ticket->server, server); } +time_t KRB5_LIB_FUNCTION +krb5_ticket_get_endtime(krb5_context context, + const krb5_ticket *ticket) +{ + return ticket->ticket.endtime; +} + static int find_type_in_ad(krb5_context context, int type, @@ -107,10 +114,6 @@ find_type_in_ad(krb5_context context, const AuthorizationData *ad, int level) { - /* It is not an error if nothing in here, that is reported by *found */ - /* Setting a default error causes found to be set to FALSE, on - * recursion to an second embedded authz data even if the first - * element contains the required type */ krb5_error_code ret = 0; int i; @@ -148,8 +151,8 @@ find_type_in_ad(krb5_context context, "IF_RELEVANT with %d", ret); goto out; } - ret = find_type_in_ad(context, type, data, found, 0, sessionkey, - &child, level + 1); + ret = find_type_in_ad(context, type, data, found, FALSE, + sessionkey, &child, level + 1); free_AuthorizationData(&child); if (ret) goto out; @@ -232,19 +235,6 @@ out: return ret; } -int -_krb5_find_type_in_ad(krb5_context context, - int type, - krb5_data *data, - krb5_boolean *found, - krb5_keyblock *sessionkey, - const AuthorizationData *ad) -{ - krb5_data_zero(data); - return find_type_in_ad(context, type, data, found, TRUE, sessionkey, ad, 0); -} - - /* * Extract the authorization data type of `type' from the * 'ticket'. Store the field in `data'. This function is to use for @@ -259,7 +249,9 @@ krb5_ticket_get_authorization_data_type(krb5_context context, { AuthorizationData *ad; krb5_error_code ret; - krb5_boolean found = 0; + krb5_boolean found = FALSE; + + krb5_data_zero(data); ad = ticket->ticket.authorization_data; if (ticket->ticket.authorization_data == NULL) { @@ -267,8 +259,8 @@ krb5_ticket_get_authorization_data_type(krb5_context context, return ENOENT; /* XXX */ } - ret = _krb5_find_type_in_ad(context, type, data, &found, &ticket->ticket.key, - ticket->ticket.authorization_data); + ret = find_type_in_ad(context, type, data, &found, TRUE, + &ticket->ticket.key, ad, 0); if (ret) return ret; if (!found) { diff --git a/source4/heimdal/lib/krb5/warn.c b/source4/heimdal/lib/krb5/warn.c index f9825914ee..4252865301 100644 --- a/source4/heimdal/lib/krb5/warn.c +++ b/source4/heimdal/lib/krb5/warn.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: warn.c,v 1.15 2004/05/25 21:46:26 lha Exp $"); +RCSID("$Id: warn.c,v 1.16 2006/11/21 08:06:40 lha Exp $"); static krb5_error_code _warnerr(krb5_context context, int do_errtext, krb5_error_code code, int level, const char *fmt, va_list ap) @@ -203,3 +203,9 @@ krb5_set_warn_dest(krb5_context context, krb5_log_facility *fac) context->warn_dest = fac; return 0; } + +krb5_log_facility * KRB5_LIB_FUNCTION +krb5_get_warn_dest(krb5_context context) +{ + return context->warn_dest; +} -- cgit From 837f283f813a98a321d193a3d5c9ce8c8ea72a0a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 18 Feb 2007 23:49:29 +0000 Subject: r21438: create the PAC element in the same order as w2k3, maybe there's some broken code in windows which relies on this... love: can you merge this to heimdal? metze (This used to be commit b64abf9113a939308dc9e92ff7ddaad7be6ab551) --- source4/heimdal/lib/krb5/pac.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 5bc7235459..283759c98b 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -850,12 +850,12 @@ _krb5_pac_sign(krb5_context context, krb5_data_zero(&logon); + if (p->logon_name == NULL) + num++; if (p->server_checksum == NULL) num++; if (p->privsvr_checksum == NULL) num++; - if (p->logon_name == NULL) - num++; if (num) { void *ptr; @@ -867,6 +867,11 @@ _krb5_pac_sign(krb5_context context, } p->pac = ptr; + if (p->logon_name == NULL) { + p->logon_name = &p->pac->buffers[p->pac->numbuffers++]; + memset(p->logon_name, 0, sizeof(*p->logon_name)); + p->logon_name->type = PAC_LOGON_NAME; + } if (p->server_checksum == NULL) { p->server_checksum = &p->pac->buffers[p->pac->numbuffers++]; memset(p->server_checksum, 0, sizeof(*p->server_checksum)); @@ -877,11 +882,6 @@ _krb5_pac_sign(krb5_context context, memset(p->privsvr_checksum, 0, sizeof(*p->privsvr_checksum)); p->privsvr_checksum->type = PAC_PRIVSVR_CHECKSUM; } - if (p->logon_name == NULL) { - p->logon_name = &p->pac->buffers[p->pac->numbuffers++]; - memset(p->logon_name, 0, sizeof(*p->logon_name)); - p->logon_name->type = PAC_LOGON_NAME; - } } /* Calculate LOGON NAME */ -- cgit From cc275f011ea8ca17d270de6946eb54015a4f7055 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 12 Apr 2007 11:23:58 +0000 Subject: r22191: Add a samba4kinit binary to the build, so I can test using an existing ccache, as well as PKINIT. Andrew Bartlett (This used to be commit 440b8d9e4b09d5e8c943504ade85c17f752fe705) --- source4/heimdal/lib/krb5/convert_creds.c | 179 ++++++++++++++++++++++++++++++ source4/heimdal/lib/krb5/prompter_posix.c | 74 ++++++++++++ 2 files changed, 253 insertions(+) create mode 100644 source4/heimdal/lib/krb5/convert_creds.c create mode 100644 source4/heimdal/lib/krb5/prompter_posix.c (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/convert_creds.c b/source4/heimdal/lib/krb5/convert_creds.c new file mode 100644 index 0000000000..bff56a2602 --- /dev/null +++ b/source4/heimdal/lib/krb5/convert_creds.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" +RCSID("$Id: convert_creds.c,v 1.32 2005/04/23 19:40:57 lha Exp $"); + +#include "krb5-v4compat.h" + +static krb5_error_code +check_ticket_flags(TicketFlags f) +{ + return 0; /* maybe add some more tests here? */ +} + +/* Convert the v5 credentials in `in_cred' to v4-dito in `v4creds'. + * This is done by sending them to the 524 function in the KDC. If + * `in_cred' doesn't contain a DES session key, then a new one is + * gotten from the KDC and stored in the cred cache `ccache'. + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb524_convert_creds_kdc(krb5_context context, + krb5_creds *in_cred, + struct credentials *v4creds) +{ + krb5_error_code ret; + krb5_data reply; + krb5_storage *sp; + int32_t tmp; + krb5_data ticket; + char realm[REALM_SZ]; + krb5_creds *v5_creds = in_cred; + + ret = check_ticket_flags(v5_creds->flags.b); + if(ret) + goto out2; + + { + krb5_krbhst_handle handle; + + ret = krb5_krbhst_init(context, + krb5_principal_get_realm(context, + v5_creds->server), + KRB5_KRBHST_KRB524, + &handle); + if (ret) + goto out2; + + ret = krb5_sendto (context, + &v5_creds->ticket, + handle, + &reply); + krb5_krbhst_free(context, handle); + if (ret) + goto out2; + } + sp = krb5_storage_from_mem(reply.data, reply.length); + if(sp == NULL) { + ret = ENOMEM; + krb5_set_error_string (context, "malloc: out of memory"); + goto out2; + } + krb5_ret_int32(sp, &tmp); + ret = tmp; + if(ret == 0) { + memset(v4creds, 0, sizeof(*v4creds)); + ret = krb5_ret_int32(sp, &tmp); + if(ret) + goto out; + v4creds->kvno = tmp; + ret = krb5_ret_data(sp, &ticket); + if(ret) + goto out; + v4creds->ticket_st.length = ticket.length; + memcpy(v4creds->ticket_st.dat, ticket.data, ticket.length); + krb5_data_free(&ticket); + ret = krb5_524_conv_principal(context, + v5_creds->server, + v4creds->service, + v4creds->instance, + v4creds->realm); + if(ret) + goto out; + v4creds->issue_date = v5_creds->times.starttime; + v4creds->lifetime = _krb5_krb_time_to_life(v4creds->issue_date, + v5_creds->times.endtime); + ret = krb5_524_conv_principal(context, v5_creds->client, + v4creds->pname, + v4creds->pinst, + realm); + if(ret) + goto out; + memcpy(v4creds->session, v5_creds->session.keyvalue.data, 8); + } else { + krb5_set_error_string(context, "converting credentials: %s", + krb5_get_err_text(context, ret)); + } +out: + krb5_storage_free(sp); + krb5_data_free(&reply); +out2: + if (v5_creds != in_cred) + krb5_free_creds (context, v5_creds); + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb524_convert_creds_kdc_ccache(krb5_context context, + krb5_ccache ccache, + krb5_creds *in_cred, + struct credentials *v4creds) +{ + krb5_error_code ret; + krb5_creds *v5_creds = in_cred; + krb5_keytype keytype; + + keytype = v5_creds->session.keytype; + + if (keytype != ENCTYPE_DES_CBC_CRC) { + /* MIT krb524d doesn't like nothing but des-cbc-crc tickets, + so go get one */ + krb5_creds template; + + memset (&template, 0, sizeof(template)); + template.session.keytype = ENCTYPE_DES_CBC_CRC; + ret = krb5_copy_principal (context, in_cred->client, &template.client); + if (ret) { + krb5_free_cred_contents (context, &template); + return ret; + } + ret = krb5_copy_principal (context, in_cred->server, &template.server); + if (ret) { + krb5_free_cred_contents (context, &template); + return ret; + } + + ret = krb5_get_credentials (context, 0, ccache, + &template, &v5_creds); + krb5_free_cred_contents (context, &template); + if (ret) + return ret; + } + + ret = krb524_convert_creds_kdc(context, v5_creds, v4creds); + + if (v5_creds != in_cred) + krb5_free_creds (context, v5_creds); + return ret; +} diff --git a/source4/heimdal/lib/krb5/prompter_posix.c b/source4/heimdal/lib/krb5/prompter_posix.c new file mode 100644 index 0000000000..3ea512c9a7 --- /dev/null +++ b/source4/heimdal/lib/krb5/prompter_posix.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +#include "krb5_locl.h" + +RCSID("$Id: prompter_posix.c,v 1.10 2004/05/25 21:38:14 lha Exp $"); + +int KRB5_LIB_FUNCTION +krb5_prompter_posix (krb5_context context, + void *data, + const char *name, + const char *banner, + int num_prompts, + krb5_prompt prompts[]) +{ + int i; + + if (name) + fprintf (stderr, "%s\n", name); + if (banner) + fprintf (stderr, "%s\n", banner); + if (name || banner) + fflush(stderr); + for (i = 0; i < num_prompts; ++i) { + if (prompts[i].hidden) { + if(UI_UTIL_read_pw_string(prompts[i].reply->data, + prompts[i].reply->length, + prompts[i].prompt, + 0)) + return 1; + } else { + char *s = prompts[i].reply->data; + + fputs (prompts[i].prompt, stdout); + fflush (stdout); + if(fgets(prompts[i].reply->data, + prompts[i].reply->length, + stdin) == NULL) + return 1; + s[strcspn(s, "\n")] = '\0'; + } + } + return 0; +} -- cgit From 91adebe749beb0dc23cacaea316cb2b724776aad Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 13 Jun 2007 05:44:24 +0000 Subject: r23456: Update Samba4 to current lorikeet-heimdal. Andrew Bartlett (This used to be commit ae0f81ab235c72cceb120bcdeb051a483cf3cc4f) --- source4/heimdal/lib/krb5/acache.c | 2 +- source4/heimdal/lib/krb5/add_et_list.c | 2 +- source4/heimdal/lib/krb5/addr_families.c | 2 +- source4/heimdal/lib/krb5/appdefault.c | 2 +- source4/heimdal/lib/krb5/asn1_glue.c | 21 +- source4/heimdal/lib/krb5/auth_context.c | 2 +- source4/heimdal/lib/krb5/build_ap_req.c | 2 +- source4/heimdal/lib/krb5/build_auth.c | 2 +- source4/heimdal/lib/krb5/cache.c | 5 +- source4/heimdal/lib/krb5/changepw.c | 2 +- source4/heimdal/lib/krb5/codec.c | 2 +- source4/heimdal/lib/krb5/config_file.c | 2 +- source4/heimdal/lib/krb5/config_file_netinfo.c | 2 +- source4/heimdal/lib/krb5/constants.c | 2 +- source4/heimdal/lib/krb5/context.c | 2 +- source4/heimdal/lib/krb5/convert_creds.c | 2 +- source4/heimdal/lib/krb5/copy_host_realm.c | 2 +- source4/heimdal/lib/krb5/crc.c | 2 +- source4/heimdal/lib/krb5/creds.c | 2 +- source4/heimdal/lib/krb5/crypto.c | 225 +++++++++++++++++----- source4/heimdal/lib/krb5/data.c | 10 +- source4/heimdal/lib/krb5/eai_to_heim_errno.c | 2 +- source4/heimdal/lib/krb5/error_string.c | 2 +- source4/heimdal/lib/krb5/expand_hostname.c | 2 +- source4/heimdal/lib/krb5/fcache.c | 2 +- source4/heimdal/lib/krb5/free.c | 2 +- source4/heimdal/lib/krb5/free_host_realm.c | 2 +- source4/heimdal/lib/krb5/generate_seq_number.c | 2 +- source4/heimdal/lib/krb5/generate_subkey.c | 2 +- source4/heimdal/lib/krb5/get_cred.c | 40 ++-- source4/heimdal/lib/krb5/get_default_principal.c | 2 +- source4/heimdal/lib/krb5/get_default_realm.c | 2 +- source4/heimdal/lib/krb5/get_for_creds.c | 2 +- source4/heimdal/lib/krb5/get_host_realm.c | 2 +- source4/heimdal/lib/krb5/get_in_tkt.c | 113 +++++------ source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c | 2 +- source4/heimdal/lib/krb5/get_port.c | 2 +- source4/heimdal/lib/krb5/heim_err.et | 2 +- source4/heimdal/lib/krb5/heim_threads.h | 2 +- source4/heimdal/lib/krb5/init_creds.c | 37 +++- source4/heimdal/lib/krb5/init_creds_pw.c | 75 +++++++- source4/heimdal/lib/krb5/k524_err.et | 2 +- source4/heimdal/lib/krb5/kcm.c | 2 +- source4/heimdal/lib/krb5/keyblock.c | 2 +- source4/heimdal/lib/krb5/keytab.c | 11 +- source4/heimdal/lib/krb5/keytab_any.c | 2 +- source4/heimdal/lib/krb5/keytab_file.c | 2 +- source4/heimdal/lib/krb5/keytab_keyfile.c | 6 +- source4/heimdal/lib/krb5/keytab_krb4.c | 2 +- source4/heimdal/lib/krb5/keytab_memory.c | 2 +- source4/heimdal/lib/krb5/krb5-private.h | 11 +- source4/heimdal/lib/krb5/krb5-protos.h | 76 ++++++-- source4/heimdal/lib/krb5/krb5-v4compat.h | 2 +- source4/heimdal/lib/krb5/krb5.h | 11 +- source4/heimdal/lib/krb5/krb5_ccapi.h | 2 +- source4/heimdal/lib/krb5/krb5_err.et | 11 +- source4/heimdal/lib/krb5/krb5_locl.h | 10 +- source4/heimdal/lib/krb5/krbhst.c | 2 +- source4/heimdal/lib/krb5/locate_plugin.h | 2 +- source4/heimdal/lib/krb5/log.c | 2 +- source4/heimdal/lib/krb5/mcache.c | 4 +- source4/heimdal/lib/krb5/misc.c | 2 +- source4/heimdal/lib/krb5/mit_glue.c | 29 ++- source4/heimdal/lib/krb5/mk_error.c | 2 +- source4/heimdal/lib/krb5/mk_priv.c | 2 +- source4/heimdal/lib/krb5/mk_rep.c | 2 +- source4/heimdal/lib/krb5/mk_req.c | 2 +- source4/heimdal/lib/krb5/mk_req_ext.c | 2 +- source4/heimdal/lib/krb5/n-fold.c | 2 +- source4/heimdal/lib/krb5/pac.c | 47 +++-- source4/heimdal/lib/krb5/padata.c | 2 +- source4/heimdal/lib/krb5/pkinit.c | 60 ++++-- source4/heimdal/lib/krb5/plugin.c | 2 +- source4/heimdal/lib/krb5/principal.c | 42 ++-- source4/heimdal/lib/krb5/prompter_posix.c | 2 +- source4/heimdal/lib/krb5/rd_cred.c | 10 +- source4/heimdal/lib/krb5/rd_error.c | 6 +- source4/heimdal/lib/krb5/rd_priv.c | 2 +- source4/heimdal/lib/krb5/rd_rep.c | 2 +- source4/heimdal/lib/krb5/rd_req.c | 6 +- source4/heimdal/lib/krb5/replay.c | 2 +- source4/heimdal/lib/krb5/send_to_kdc.c | 4 +- source4/heimdal/lib/krb5/set_default_realm.c | 2 +- source4/heimdal/lib/krb5/store.c | 6 +- source4/heimdal/lib/krb5/store_emem.c | 2 +- source4/heimdal/lib/krb5/store_fd.c | 2 +- source4/heimdal/lib/krb5/store_mem.c | 4 +- source4/heimdal/lib/krb5/ticket.c | 2 +- source4/heimdal/lib/krb5/time.c | 2 +- source4/heimdal/lib/krb5/transited.c | 2 +- source4/heimdal/lib/krb5/v4_glue.c | 2 +- source4/heimdal/lib/krb5/version.c | 2 +- source4/heimdal/lib/krb5/warn.c | 2 +- 93 files changed, 683 insertions(+), 331 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c index d20c24699b..999ce7f120 100644 --- a/source4/heimdal/lib/krb5/acache.c +++ b/source4/heimdal/lib/krb5/acache.c @@ -37,7 +37,7 @@ #include #endif -RCSID("$Id: acache.c,v 1.17 2007/01/08 15:31:01 lha Exp $"); +RCSID("$Id: acache.c 19764 2007-01-08 15:31:01Z lha $"); /* XXX should we fetch these for each open ? */ static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; diff --git a/source4/heimdal/lib/krb5/add_et_list.c b/source4/heimdal/lib/krb5/add_et_list.c index 3b9773bebb..a6005c6859 100644 --- a/source4/heimdal/lib/krb5/add_et_list.c +++ b/source4/heimdal/lib/krb5/add_et_list.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: add_et_list.c,v 1.3 2004/04/13 14:33:45 lha Exp $"); +RCSID("$Id: add_et_list.c 13713 2004-04-13 14:33:45Z lha $"); /* * Add a specified list of error messages to the et list in context. diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c index f68be423b0..8c31843058 100644 --- a/source4/heimdal/lib/krb5/addr_families.c +++ b/source4/heimdal/lib/krb5/addr_families.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: addr_families.c,v 1.53 2006/10/22 06:54:00 lha Exp $"); +RCSID("$Id: addr_families.c 18805 2006-10-22 06:54:00Z lha $"); struct addr_operations { int af; diff --git a/source4/heimdal/lib/krb5/appdefault.c b/source4/heimdal/lib/krb5/appdefault.c index 03fa933b6f..b0bb171f4a 100644 --- a/source4/heimdal/lib/krb5/appdefault.c +++ b/source4/heimdal/lib/krb5/appdefault.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: appdefault.c,v 1.10 2005/01/05 05:40:59 lukeh Exp $"); +RCSID("$Id: appdefault.c 14465 2005-01-05 05:40:59Z lukeh $"); void KRB5_LIB_FUNCTION krb5_appdefault_boolean(krb5_context context, const char *appname, diff --git a/source4/heimdal/lib/krb5/asn1_glue.c b/source4/heimdal/lib/krb5/asn1_glue.c index b07e058550..6b7d40d453 100644 --- a/source4/heimdal/lib/krb5/asn1_glue.c +++ b/source4/heimdal/lib/krb5/asn1_glue.c @@ -37,7 +37,7 @@ #include "krb5_locl.h" -RCSID("$Id: asn1_glue.c,v 1.10 2006/10/06 17:02:48 lha Exp $"); +RCSID("$Id: asn1_glue.c 18269 2006-10-06 17:02:48Z lha $"); krb5_error_code KRB5_LIB_FUNCTION _krb5_principal2principalname (PrincipalName *p, @@ -47,23 +47,14 @@ _krb5_principal2principalname (PrincipalName *p, } krb5_error_code KRB5_LIB_FUNCTION -_krb5_principalname2krb5_principal (krb5_context context, +_krb5_principalname2krb5_principal (krb5_context context, krb5_principal *principal, const PrincipalName from, const Realm realm) { - if (from.name_type == KRB5_NT_ENTERPRISE_PRINCIPAL) { - if (from.name_string.len != 1) { - return KRB5_PARSE_MALFORMED; - } - return krb5_parse_name(context, - from.name_string.val[0], - principal); - } else { - krb5_principal p = malloc(sizeof(*p)); - copy_PrincipalName(&from, &p->name); - p->realm = strdup(realm); - *principal = p; - } + krb5_principal p = malloc(sizeof(*p)); + copy_PrincipalName(&from, &p->name); + p->realm = strdup(realm); + *principal = p; return 0; } diff --git a/source4/heimdal/lib/krb5/auth_context.c b/source4/heimdal/lib/krb5/auth_context.c index b8ce65d9a5..5e08f15ad4 100644 --- a/source4/heimdal/lib/krb5/auth_context.c +++ b/source4/heimdal/lib/krb5/auth_context.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: auth_context.c,v 1.62 2005/01/05 02:34:08 lukeh Exp $"); +RCSID("$Id: auth_context.c 14452 2005-01-05 02:34:08Z lukeh $"); krb5_error_code KRB5_LIB_FUNCTION krb5_auth_con_init(krb5_context context, diff --git a/source4/heimdal/lib/krb5/build_ap_req.c b/source4/heimdal/lib/krb5/build_ap_req.c index e11744cc3a..b1968fe817 100644 --- a/source4/heimdal/lib/krb5/build_ap_req.c +++ b/source4/heimdal/lib/krb5/build_ap_req.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: build_ap_req.c,v 1.20 2004/05/25 21:18:17 lha Exp $"); +RCSID("$Id: build_ap_req.c 13863 2004-05-25 21:46:46Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_build_ap_req (krb5_context context, diff --git a/source4/heimdal/lib/krb5/build_auth.c b/source4/heimdal/lib/krb5/build_auth.c index 9eff09bb0a..f8739c044d 100644 --- a/source4/heimdal/lib/krb5/build_auth.c +++ b/source4/heimdal/lib/krb5/build_auth.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: build_auth.c,v 1.43 2006/04/10 08:53:21 lha Exp $"); +RCSID("$Id: build_auth.c 17033 2006-04-10 08:53:21Z lha $"); static krb5_error_code make_etypelist(krb5_context context, diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index a96870a7de..5be3935f2b 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c,v 1.82 2006/09/12 17:35:33 lha Exp $"); +RCSID("$Id: cache.c 20503 2007-04-21 22:03:56Z lha $"); /* * Add a new ccache type with operations `ops', overwriting any @@ -473,7 +473,8 @@ krb5_cc_store_cred(krb5_context context, /* * Retrieve the credential identified by `mcreds' (and `whichfields') - * from `id' in `creds'. + * from `id' in `creds'. 'creds' must be free by the caller using + * krb5_free_cred_contents. * Return 0 or an error code. */ diff --git a/source4/heimdal/lib/krb5/changepw.c b/source4/heimdal/lib/krb5/changepw.c index ba584a04a4..3ceb6df89c 100644 --- a/source4/heimdal/lib/krb5/changepw.c +++ b/source4/heimdal/lib/krb5/changepw.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: changepw.c,v 1.56 2006/05/05 09:26:47 lha Exp $"); +RCSID("$Id: changepw.c 17442 2006-05-05 09:31:15Z lha $"); static void str2data (krb5_data *d, diff --git a/source4/heimdal/lib/krb5/codec.c b/source4/heimdal/lib/krb5/codec.c index 080e8a6511..0d36b4b442 100644 --- a/source4/heimdal/lib/krb5/codec.c +++ b/source4/heimdal/lib/krb5/codec.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: codec.c,v 1.9 2004/05/25 21:19:37 lha Exp $"); +RCSID("$Id: codec.c 13863 2004-05-25 21:46:46Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_decode_EncTicketPart (krb5_context context, diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c index bbd9cf4c78..ac5eba39dc 100644 --- a/source4/heimdal/lib/krb5/config_file.c +++ b/source4/heimdal/lib/krb5/config_file.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: config_file.c,v 1.55 2006/12/04 23:35:54 lha Exp $"); +RCSID("$Id: config_file.c 19213 2006-12-04 23:36:36Z lha $"); #ifndef HAVE_NETINFO diff --git a/source4/heimdal/lib/krb5/config_file_netinfo.c b/source4/heimdal/lib/krb5/config_file_netinfo.c index 6e72509ab6..1e01e7c5ff 100644 --- a/source4/heimdal/lib/krb5/config_file_netinfo.c +++ b/source4/heimdal/lib/krb5/config_file_netinfo.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: config_file_netinfo.c,v 1.4 2004/05/25 21:20:18 lha Exp $"); +RCSID("$Id: config_file_netinfo.c 13863 2004-05-25 21:46:46Z lha $"); /* * Netinfo implementation from Luke Howard diff --git a/source4/heimdal/lib/krb5/constants.c b/source4/heimdal/lib/krb5/constants.c index 89ebc34a1a..5188a1d3a8 100644 --- a/source4/heimdal/lib/krb5/constants.c +++ b/source4/heimdal/lib/krb5/constants.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: constants.c,v 1.8 2004/09/23 07:57:37 joda Exp $"); +RCSID("$Id: constants.c 14253 2004-09-23 07:57:37Z joda $"); const char *krb5_config_file = #ifdef __APPLE__ diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index d0317da375..b54e293a60 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: context.c,v 1.112 2006/11/24 14:24:33 lha Exp $"); +RCSID("$Id: context.c 19107 2006-11-24 14:24:33Z lha $"); #define INIT_FIELD(C, T, E, D, F) \ (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ diff --git a/source4/heimdal/lib/krb5/convert_creds.c b/source4/heimdal/lib/krb5/convert_creds.c index bff56a2602..1d1b4d7070 100644 --- a/source4/heimdal/lib/krb5/convert_creds.c +++ b/source4/heimdal/lib/krb5/convert_creds.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: convert_creds.c,v 1.32 2005/04/23 19:40:57 lha Exp $"); +RCSID("$Id: convert_creds.c 14897 2005-04-23 19:40:57Z lha $"); #include "krb5-v4compat.h" diff --git a/source4/heimdal/lib/krb5/copy_host_realm.c b/source4/heimdal/lib/krb5/copy_host_realm.c index eb77fba024..4e668c2a14 100644 --- a/source4/heimdal/lib/krb5/copy_host_realm.c +++ b/source4/heimdal/lib/krb5/copy_host_realm.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: copy_host_realm.c,v 1.5 2004/05/25 21:21:17 lha Exp $"); +RCSID("$Id: copy_host_realm.c 13863 2004-05-25 21:46:46Z lha $"); /* * Copy the list of realms from `from' to `to'. diff --git a/source4/heimdal/lib/krb5/crc.c b/source4/heimdal/lib/krb5/crc.c index 4cfed75154..072c29d689 100644 --- a/source4/heimdal/lib/krb5/crc.c +++ b/source4/heimdal/lib/krb5/crc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: crc.c,v 1.10 2006/05/05 09:27:09 lha Exp $"); +RCSID("$Id: crc.c 17442 2006-05-05 09:31:15Z lha $"); static u_long table[256]; diff --git a/source4/heimdal/lib/krb5/creds.c b/source4/heimdal/lib/krb5/creds.c index 2afd0725f1..d4d83162f1 100644 --- a/source4/heimdal/lib/krb5/creds.c +++ b/source4/heimdal/lib/krb5/creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: creds.c,v 1.20 2005/05/18 04:21:04 lha Exp $"); +RCSID("$Id: creds.c 15167 2005-05-18 04:21:57Z lha $"); /* keep this for compatibility with older code */ krb5_error_code KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 6d4a81baa8..93f3e44ba1 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c,v 1.146 2006/11/17 21:58:47 lha Exp $"); +RCSID("$Id: crypto.c 20981 2007-06-07 20:05:50Z lha $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -57,8 +57,6 @@ struct krb5_crypto_data { struct key_usage *key_usage; }; -#define kcrypto_oid_enc(n) { sizeof(n)/sizeof(n[0]), n } - #define CRYPTO_ETYPE(C) ((C)->et->type) /* bits for `flags' below */ @@ -82,7 +80,6 @@ struct key_type { const char *name; size_t bits; size_t size; - size_t minsize; size_t schedule_size; #if 0 krb5_enctype best_etype; @@ -128,6 +125,9 @@ struct encryption_type { krb5_boolean encryptp, int usage, void *ivec); + size_t prf_length; + krb5_error_code (*prf)(krb5_context, + krb5_crypto, const krb5_data *, krb5_data *); }; #define ENCRYPTION_USAGE(U) (((U) << 8) | 0xAA) @@ -724,7 +724,6 @@ static struct key_type keytype_null = { 0, 0, 0, - 0, NULL, NULL, NULL @@ -735,7 +734,6 @@ static struct key_type keytype_des = { "des", 56, sizeof(DES_cblock), - sizeof(DES_cblock), sizeof(DES_key_schedule), krb5_DES_random_key, krb5_DES_schedule, @@ -748,7 +746,6 @@ static struct key_type keytype_des3 = { "des3", 168, 3 * sizeof(DES_cblock), - 3 * sizeof(DES_cblock), 3 * sizeof(DES_key_schedule), DES3_random_key, DES3_schedule, @@ -761,7 +758,6 @@ static struct key_type keytype_des3_derived = { "des3", 168, 3 * sizeof(DES_cblock), - 3 * sizeof(DES_cblock), 3 * sizeof(DES_key_schedule), DES3_random_key, DES3_schedule, @@ -774,7 +770,6 @@ static struct key_type keytype_aes128 = { "aes-128", 128, 16, - 16, sizeof(struct krb5_aes_schedule), NULL, AES_schedule, @@ -786,7 +781,6 @@ static struct key_type keytype_aes256 = { "aes-256", 256, 32, - 32, sizeof(struct krb5_aes_schedule), NULL, AES_schedule, @@ -798,7 +792,6 @@ static struct key_type keytype_arcfour = { "arcfour", 128, 16, - 16, sizeof(RC4_KEY), NULL, ARCFOUR_schedule, @@ -2450,6 +2443,58 @@ ARCFOUR_encrypt(krb5_context context, } +/* + * + */ + +static krb5_error_code +AES_PRF(krb5_context context, + krb5_crypto crypto, + const krb5_data *in, + krb5_data *out) +{ + struct checksum_type *ct = crypto->et->checksum; + krb5_error_code ret; + Checksum result; + krb5_keyblock *derived; + + result.cksumtype = ct->type; + ret = krb5_data_alloc(&result.checksum, ct->checksumsize); + if (ret) { + krb5_set_error_string(context, "out memory"); + return ret; + } + + (*ct->checksum)(context, NULL, in->data, in->length, 0, &result); + + if (result.checksum.length < crypto->et->blocksize) + krb5_abortx(context, "internal prf error"); + + derived = NULL; + ret = krb5_derive_key(context, crypto->key.key, + crypto->et->type, "prf", 3, &derived); + if (ret) + krb5_abortx(context, "krb5_derive_key"); + + ret = krb5_data_alloc(out, crypto->et->blocksize); + if (ret) + krb5_abortx(context, "malloc failed"); + + { + AES_KEY key; + + AES_set_encrypt_key(derived->keyvalue.data, + crypto->et->keytype->bits, &key); + AES_encrypt(result.checksum.data, out->data, &key); + memset(&key, 0, sizeof(key)); + } + + krb5_data_free(&result.checksum); + krb5_free_keyblock(context, derived); + + return ret; +} + /* * these should currently be in reverse preference order. * (only relevant for !F_PSEUDO) */ @@ -2466,6 +2511,8 @@ static struct encryption_type enctype_null = { NULL, F_DISABLED, NULL_encrypt, + 0, + NULL }; static struct encryption_type enctype_des_cbc_crc = { ETYPE_DES_CBC_CRC, @@ -2479,6 +2526,8 @@ static struct encryption_type enctype_des_cbc_crc = { NULL, 0, DES_CBC_encrypt_key_ivec, + 0, + NULL }; static struct encryption_type enctype_des_cbc_md4 = { ETYPE_DES_CBC_MD4, @@ -2492,6 +2541,8 @@ static struct encryption_type enctype_des_cbc_md4 = { &checksum_rsa_md4_des, 0, DES_CBC_encrypt_null_ivec, + 0, + NULL }; static struct encryption_type enctype_des_cbc_md5 = { ETYPE_DES_CBC_MD5, @@ -2505,6 +2556,8 @@ static struct encryption_type enctype_des_cbc_md5 = { &checksum_rsa_md5_des, 0, DES_CBC_encrypt_null_ivec, + 0, + NULL }; static struct encryption_type enctype_arcfour_hmac_md5 = { ETYPE_ARCFOUR_HMAC_MD5, @@ -2517,7 +2570,9 @@ static struct encryption_type enctype_arcfour_hmac_md5 = { &checksum_hmac_md5, NULL, F_SPECIAL, - ARCFOUR_encrypt + ARCFOUR_encrypt, + 0, + NULL }; static struct encryption_type enctype_des3_cbc_md5 = { ETYPE_DES3_CBC_MD5, @@ -2531,6 +2586,8 @@ static struct encryption_type enctype_des3_cbc_md5 = { &checksum_rsa_md5_des3, 0, DES3_CBC_encrypt, + 0, + NULL }; static struct encryption_type enctype_des3_cbc_sha1 = { ETYPE_DES3_CBC_SHA1, @@ -2544,6 +2601,8 @@ static struct encryption_type enctype_des3_cbc_sha1 = { &checksum_hmac_sha1_des3, F_DERIVED, DES3_CBC_encrypt, + 0, + NULL }; static struct encryption_type enctype_old_des3_cbc_sha1 = { ETYPE_OLD_DES3_CBC_SHA1, @@ -2557,6 +2616,8 @@ static struct encryption_type enctype_old_des3_cbc_sha1 = { &checksum_hmac_sha1_des3, 0, DES3_CBC_encrypt, + 0, + NULL }; static struct encryption_type enctype_aes128_cts_hmac_sha1 = { ETYPE_AES128_CTS_HMAC_SHA1_96, @@ -2570,6 +2631,8 @@ static struct encryption_type enctype_aes128_cts_hmac_sha1 = { &checksum_hmac_sha1_aes128, F_DERIVED, AES_CTS_encrypt, + 16, + AES_PRF }; static struct encryption_type enctype_aes256_cts_hmac_sha1 = { ETYPE_AES256_CTS_HMAC_SHA1_96, @@ -2583,6 +2646,8 @@ static struct encryption_type enctype_aes256_cts_hmac_sha1 = { &checksum_hmac_sha1_aes256, F_DERIVED, AES_CTS_encrypt, + 16, + AES_PRF }; static struct encryption_type enctype_des_cbc_none = { ETYPE_DES_CBC_NONE, @@ -2596,6 +2661,8 @@ static struct encryption_type enctype_des_cbc_none = { NULL, F_PSEUDO, DES_CBC_encrypt_null_ivec, + 0, + NULL }; static struct encryption_type enctype_des_cfb64_none = { ETYPE_DES_CFB64_NONE, @@ -2609,6 +2676,8 @@ static struct encryption_type enctype_des_cfb64_none = { NULL, F_PSEUDO, DES_CFB64_encrypt_null_ivec, + 0, + NULL }; static struct encryption_type enctype_des_pcbc_none = { ETYPE_DES_PCBC_NONE, @@ -2622,6 +2691,8 @@ static struct encryption_type enctype_des_pcbc_none = { NULL, F_PSEUDO, DES_PCBC_encrypt_key_ivec, + 0, + NULL }; static struct encryption_type enctype_des3_cbc_none = { ETYPE_DES3_CBC_NONE, @@ -2635,6 +2706,8 @@ static struct encryption_type enctype_des3_cbc_none = { NULL, F_PSEUDO, DES3_CBC_encrypt, + 0, + NULL }; static struct encryption_type *etypes[] = { @@ -3090,8 +3163,8 @@ decrypt_internal_derived(krb5_context context, checksum_sz = CHECKSUMSIZE(et->keyed_checksum); if (len < checksum_sz) { - krb5_clear_error_string (context); - return EINVAL; /* XXX - better error code? */ + krb5_set_error_string(context, "Encrypted data shorter then checksum"); + return KRB5_BAD_MSIZE; } if (((len - checksum_sz) % et->padsize) != 0) { @@ -3357,11 +3430,8 @@ krb5_decrypt_EncryptedData(krb5_context context, * * ************************************************************/ -#ifdef HAVE_OPENSSL -#include +#define ENTROPY_NEEDED 128 -/* From openssl/crypto/rand/rand_lcl.h */ -#define ENTROPY_NEEDED 20 static int seed_something(void) { @@ -3417,7 +3487,8 @@ krb5_generate_random_block(void *buf, size_t len) HEIMDAL_MUTEX_lock(&crypto_mutex); if (!rng_initialized) { if (seed_something()) - krb5_abortx(NULL, "Fatal: could not seed the random number generator"); + krb5_abortx(NULL, "Fatal: could not seed the " + "random number generator"); rng_initialized = 1; } @@ -3426,38 +3497,6 @@ krb5_generate_random_block(void *buf, size_t len) krb5_abortx(NULL, "Failed to generate random block"); } -#else - -void KRB5_LIB_FUNCTION -krb5_generate_random_block(void *buf, size_t len) -{ - DES_cblock key, out; - static DES_cblock counter; - static DES_key_schedule schedule; - int i; - static int initialized = 0; - - HEIMDAL_MUTEX_lock(&crypto_mutex); - if(!initialized) { - DES_new_random_key(&key); - DES_set_key(&key, &schedule); - memset(&key, 0, sizeof(key)); - DES_new_random_key(&counter); - initialized = 1; - } - HEIMDAL_MUTEX_unlock(&crypto_mutex); - while(len > 0) { - DES_ecb_encrypt(&counter, &out, &schedule, DES_ENCRYPT); - for(i = 7; i >=0; i--) - if(counter[i]++) - break; - memcpy(buf, out, min(len, sizeof(out))); - len -= min(len, sizeof(out)); - buf = (char*)buf + sizeof(out); - } -} -#endif - static void DES3_postproc(krb5_context context, unsigned char *k, size_t len, struct key_data *key) @@ -3645,7 +3684,7 @@ krb5_crypto_init(krb5_context context, etype); return KRB5_PROG_ETYPE_NOSUPP; } - if((*crypto)->et->keytype->minsize > key->keyvalue.length) { + if((*crypto)->et->keytype->size != key->keyvalue.length) { free(*crypto); *crypto = NULL; krb5_set_error_string (context, "encryption key has bad length"); @@ -3844,6 +3883,50 @@ krb5_get_wrapped_length (krb5_context context, return wrapped_length (context, crypto, data_len); } +/* + * Return the size of an encrypted packet of length `data_len' + */ + +static size_t +crypto_overhead (krb5_context context, + krb5_crypto crypto) +{ + struct encryption_type *et = crypto->et; + size_t res; + + res = CHECKSUMSIZE(et->checksum); + res += et->confoundersize; + if (et->padsize > 1) + res += et->padsize; + return res; +} + +static size_t +crypto_overhead_dervied (krb5_context context, + krb5_crypto crypto) +{ + struct encryption_type *et = crypto->et; + size_t res; + + if (et->keyed_checksum) + res = CHECKSUMSIZE(et->keyed_checksum); + else + res = CHECKSUMSIZE(et->checksum); + res += et->confoundersize; + if (et->padsize > 1) + res += et->padsize; + return res; +} + +size_t +krb5_crypto_overhead (krb5_context context, krb5_crypto crypto) +{ + if (derived_crypto (context, crypto)) + return crypto_overhead_dervied (context, crypto); + else + return crypto_overhead (context, crypto); +} + krb5_error_code KRB5_LIB_FUNCTION krb5_random_to_key(krb5_context context, krb5_enctype type, @@ -3934,6 +4017,44 @@ _krb5_pk_octetstring2key(krb5_context context, return ret; } +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_prf_length(krb5_context context, + krb5_enctype type, + size_t *length) +{ + struct encryption_type *et = _find_enctype(type); + + if(et == NULL || et->prf_length == 0) { + krb5_set_error_string(context, "encryption type %d not supported", + type); + return KRB5_PROG_ETYPE_NOSUPP; + } + + *length = et->prf_length; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_prf(krb5_context context, + const krb5_crypto crypto, + const krb5_data *input, + krb5_data *output) +{ + struct encryption_type *et = crypto->et; + + krb5_data_zero(output); + + if(et->prf == NULL) { + krb5_set_error_string(context, "kerberos prf for %s not supported", + et->name); + return KRB5_PROG_ETYPE_NOSUPP; + } + + return (*et->prf)(context, crypto, input, output); +} + + + #ifdef CRYPTO_DEBUG diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c index f0c6d00abe..2ece85bdb3 100644 --- a/source4/heimdal/lib/krb5/data.c +++ b/source4/heimdal/lib/krb5/data.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: data.c,v 1.21 2006/10/14 09:45:41 lha Exp $"); +RCSID("$Id: data.c 20039 2007-01-23 20:34:01Z lha $"); void KRB5_LIB_FUNCTION krb5_data_zero(krb5_data *p) @@ -118,3 +118,11 @@ krb5_copy_data(krb5_context context, } return ret; } + +int KRB5_LIB_FUNCTION +krb5_data_cmp(const krb5_data *data1, const krb5_data *data2) +{ + if (data1->length != data2->length) + return data1->length - data2->length; + return memcmp(data1->data, data2->data, data1->length); +} diff --git a/source4/heimdal/lib/krb5/eai_to_heim_errno.c b/source4/heimdal/lib/krb5/eai_to_heim_errno.c index f0d1f51033..c6b5cfb18b 100644 --- a/source4/heimdal/lib/krb5/eai_to_heim_errno.c +++ b/source4/heimdal/lib/krb5/eai_to_heim_errno.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: eai_to_heim_errno.c,v 1.5 2004/05/25 21:23:35 lha Exp $"); +RCSID("$Id: eai_to_heim_errno.c 13863 2004-05-25 21:46:46Z lha $"); /* * convert the getaddrinfo error code in `eai_errno' into a diff --git a/source4/heimdal/lib/krb5/error_string.c b/source4/heimdal/lib/krb5/error_string.c index b672fe74f9..1ba6494487 100644 --- a/source4/heimdal/lib/krb5/error_string.c +++ b/source4/heimdal/lib/krb5/error_string.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: error_string.c,v 1.7 2006/02/16 07:49:23 lha Exp $"); +RCSID("$Id: error_string.c 16746 2006-02-16 07:49:23Z lha $"); #undef __attribute__ #define __attribute__(X) diff --git a/source4/heimdal/lib/krb5/expand_hostname.c b/source4/heimdal/lib/krb5/expand_hostname.c index 46e784f561..b2b410269e 100644 --- a/source4/heimdal/lib/krb5/expand_hostname.c +++ b/source4/heimdal/lib/krb5/expand_hostname.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: expand_hostname.c,v 1.14 2006/11/04 03:34:57 lha Exp $"); +RCSID("$Id: expand_hostname.c 18906 2006-11-04 03:34:57Z lha $"); static krb5_error_code copy_hostname(krb5_context context, diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c index 7441509e38..864efa8d7d 100644 --- a/source4/heimdal/lib/krb5/fcache.c +++ b/source4/heimdal/lib/krb5/fcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: fcache.c,v 1.54 2006/12/15 21:35:52 lha Exp $"); +RCSID("$Id: fcache.c 19379 2006-12-15 21:35:52Z lha $"); typedef struct krb5_fcache{ char *filename; diff --git a/source4/heimdal/lib/krb5/free.c b/source4/heimdal/lib/krb5/free.c index 84aa6f8c2c..1b0bd05412 100644 --- a/source4/heimdal/lib/krb5/free.c +++ b/source4/heimdal/lib/krb5/free.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: free.c,v 1.8 2005/05/18 10:06:16 lha Exp $"); +RCSID("$Id: free.c 15175 2005-05-18 10:06:16Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *rep) diff --git a/source4/heimdal/lib/krb5/free_host_realm.c b/source4/heimdal/lib/krb5/free_host_realm.c index 27afcdbb23..6b13ce7d0e 100644 --- a/source4/heimdal/lib/krb5/free_host_realm.c +++ b/source4/heimdal/lib/krb5/free_host_realm.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: free_host_realm.c,v 1.5 2004/05/25 21:25:02 lha Exp $"); +RCSID("$Id: free_host_realm.c 13863 2004-05-25 21:46:46Z lha $"); /* * Free all memory allocated by `realmlist' diff --git a/source4/heimdal/lib/krb5/generate_seq_number.c b/source4/heimdal/lib/krb5/generate_seq_number.c index 7f79e29858..8a04f048c8 100644 --- a/source4/heimdal/lib/krb5/generate_seq_number.c +++ b/source4/heimdal/lib/krb5/generate_seq_number.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: generate_seq_number.c,v 1.10 2006/05/05 09:28:06 lha Exp $"); +RCSID("$Id: generate_seq_number.c 17442 2006-05-05 09:31:15Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_generate_seq_number(krb5_context context, diff --git a/source4/heimdal/lib/krb5/generate_subkey.c b/source4/heimdal/lib/krb5/generate_subkey.c index df4828d097..fb99cbbf3f 100644 --- a/source4/heimdal/lib/krb5/generate_subkey.c +++ b/source4/heimdal/lib/krb5/generate_subkey.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: generate_subkey.c,v 1.11 2005/01/05 02:39:21 lukeh Exp $"); +RCSID("$Id: generate_subkey.c 14455 2005-01-05 02:39:21Z lukeh $"); krb5_error_code KRB5_LIB_FUNCTION krb5_generate_subkey(krb5_context context, diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 663b5e7f1b..761224b82c 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_cred.c,v 1.113 2006/11/21 05:14:01 lha Exp $"); +RCSID("$Id: get_cred.c 21004 2007-06-08 01:53:10Z lha $"); /* * Take the `body' and encode it into `padata' using the credentials @@ -542,8 +542,8 @@ again: KRB5_KU_TGS_REP_ENC_PART_SESSION, &krbtgt->addresses, nonce, - TRUE, - TRUE /* flags.b.request_anonymous */, + EXTRACT_TICKET_ALLOW_CNAME_MISMATCH| + EXTRACT_TICKET_ALLOW_SERVER_MISMATCH, decrypt_tkt_with_subkey, subkey); krb5_free_kdc_rep(context, &rep); @@ -659,6 +659,20 @@ krb5_get_kdc_cred(krb5_context context, return ret; } +static void +not_found(krb5_context context, krb5_const_principal p) +{ + krb5_error_code ret; + char *str; + + ret = krb5_unparse_name(context, p, &str); + if(ret) { + krb5_clear_error_string(context); + return; + } + krb5_set_error_string(context, "Matching credential (%s) not found", str); + free(str); +} static krb5_error_code find_cred(krb5_context context, @@ -684,17 +698,7 @@ find_cred(krb5_context context, } tgts++; } - { - char *str; - ret = krb5_unparse_name(context, server, &str); - if(ret == 0) { - krb5_set_error_string(context, "Matching credential " - "(%s) not found", str); - free(str); - } else { - krb5_clear_error_string(context); - } - } + not_found(context, server); return KRB5_CC_NOTFOUND; } @@ -818,7 +822,7 @@ get_cred_from_kdc_flags(krb5_context context, } } if(krb5_realm_compare(context, in_creds->client, in_creds->server)) { - krb5_clear_error_string (context); + not_found(context, in_creds->server); return KRB5_CC_NOTFOUND; } /* XXX this can loop forever */ @@ -972,7 +976,7 @@ krb5_get_credentials_with_flags(krb5_context context, } free(res_creds); if(options & KRB5_GC_CACHED) { - krb5_clear_error_string (context); + not_found(context, in_creds->server); return KRB5_CC_NOTFOUND; } if(options & KRB5_GC_USER_USER) @@ -1175,7 +1179,7 @@ krb5_get_creds(krb5_context context, } free(res_creds); if(options & KRB5_GC_CACHED) { - krb5_clear_error_string (context); + not_found(context, in_creds.server); krb5_free_principal(context, in_creds.client); return KRB5_CC_NOTFOUND; } diff --git a/source4/heimdal/lib/krb5/get_default_principal.c b/source4/heimdal/lib/krb5/get_default_principal.c index 03e8f0a823..83fb2b0fa9 100644 --- a/source4/heimdal/lib/krb5/get_default_principal.c +++ b/source4/heimdal/lib/krb5/get_default_principal.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_default_principal.c,v 1.10 2005/04/20 20:53:29 lha Exp $"); +RCSID("$Id: get_default_principal.c 14870 2005-04-20 20:53:29Z lha $"); /* * Try to find out what's a reasonable default principal. diff --git a/source4/heimdal/lib/krb5/get_default_realm.c b/source4/heimdal/lib/krb5/get_default_realm.c index bb72daf373..09c8577b26 100644 --- a/source4/heimdal/lib/krb5/get_default_realm.c +++ b/source4/heimdal/lib/krb5/get_default_realm.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_default_realm.c,v 1.13 2004/05/25 21:27:17 lha Exp $"); +RCSID("$Id: get_default_realm.c 13863 2004-05-25 21:46:46Z lha $"); /* * Return a NULL-terminated list of default realms in `realms'. diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index 6eebf1fa80..1bb98737d1 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_for_creds.c,v 1.49 2006/04/10 09:28:15 lha Exp $"); +RCSID("$Id: get_for_creds.c 17036 2006-04-10 09:28:15Z lha $"); static krb5_error_code add_addrs(krb5_context context, diff --git a/source4/heimdal/lib/krb5/get_host_realm.c b/source4/heimdal/lib/krb5/get_host_realm.c index ffc646d98b..d709e4b38d 100644 --- a/source4/heimdal/lib/krb5/get_host_realm.c +++ b/source4/heimdal/lib/krb5/get_host_realm.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: get_host_realm.c,v 1.37 2006/10/17 19:28:36 lha Exp $"); +RCSID("$Id: get_host_realm.c 18541 2006-10-17 19:28:36Z lha $"); /* To automagically find the correct realm of a host (without * [domain_realm] in krb5.conf) add a text record for your domain with diff --git a/source4/heimdal/lib/krb5/get_in_tkt.c b/source4/heimdal/lib/krb5/get_in_tkt.c index e140011413..ec106bb7ec 100644 --- a/source4/heimdal/lib/krb5/get_in_tkt.c +++ b/source4/heimdal/lib/krb5/get_in_tkt.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_in_tkt.c,v 1.119 2006/10/06 17:05:08 lha Exp $"); +RCSID("$Id: get_in_tkt.c 20226 2007-02-16 03:31:50Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_init_etype (krb5_context context, @@ -125,13 +125,12 @@ _krb5_extract_ticket(krb5_context context, krb5_key_usage key_usage, krb5_addresses *addrs, unsigned nonce, - krb5_boolean allow_server_mismatch, - krb5_boolean ignore_cname, + unsigned flags, krb5_decrypt_proc decrypt_proc, krb5_const_pointer decryptarg) { krb5_error_code ret; - krb5_principal tmp_principal, srv_principal = NULL; + krb5_principal tmp_principal; int tmp; size_t len; time_t tmp_time; @@ -143,8 +142,8 @@ _krb5_extract_ticket(krb5_context context, * as realm against windows KDC's, they always return the full realm * based on the DNS Name. */ -allow_server_mismatch = 1; -ignore_cname = 1; +flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; +flags |=EXTRACT_TICKET_ALLOW_CNAME_MISMATCH ; ret = _krb5_principalname2krb5_principal (context, &tmp_principal, @@ -155,7 +154,7 @@ ignore_cname = 1; /* compare client */ - if (!ignore_cname) { + if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0){ tmp = krb5_principal_compare (context, tmp_principal, creds->client); if (!tmp) { krb5_free_principal (context, tmp_principal); @@ -177,60 +176,49 @@ ignore_cname = 1; krb5_abortx(context, "internal error in ASN.1 encoder"); creds->second_ticket.length = 0; creds->second_ticket.data = NULL; - - /* decrypt */ - - if (decrypt_proc == NULL) - decrypt_proc = decrypt_tkt; - - ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep); - if (ret) - goto out; - -#if 0 - /* XXX should this decode be here, or in the decrypt_proc? */ - ret = krb5_decode_keyblock(context, &rep->enc_part.key, 1); - if(ret) - goto out; -#endif /* compare server */ ret = _krb5_principalname2krb5_principal (context, - &srv_principal, + &tmp_principal, rep->kdc_rep.ticket.sname, rep->kdc_rep.ticket.realm); if (ret) goto out; + if(flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH){ + krb5_free_principal(context, creds->server); + creds->server = tmp_principal; + tmp_principal = NULL; + } else { + tmp = krb5_principal_compare (context, tmp_principal, + creds->server); + krb5_free_principal (context, tmp_principal); + if (!tmp) { + ret = KRB5KRB_AP_ERR_MODIFIED; + krb5_clear_error_string (context); + goto out; + } + } + + /* decrypt */ - ret = _krb5_principalname2krb5_principal (context, - &tmp_principal, - rep->enc_part.sname, - rep->enc_part.srealm); + if (decrypt_proc == NULL) + decrypt_proc = decrypt_tkt; + + ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep); if (ret) goto out; - /* - * see if the service principal matches in the ticket - * and in the enc_part - */ - tmp = krb5_principal_compare (context, tmp_principal, srv_principal); - krb5_free_principal (context, tmp_principal); - if (!tmp) { - ret = KRB5KRB_AP_ERR_MODIFIED; - krb5_clear_error_string (context); - goto out; - } + /* verify names */ + if(flags & EXTRACT_TICKET_MATCH_REALM){ + const char *srealm = krb5_principal_get_realm(context, creds->server); + const char *crealm = krb5_principal_get_realm(context, creds->client); - if(allow_server_mismatch){ - krb5_free_principal(context, creds->server); - creds->server = srv_principal; - srv_principal = NULL; - }else{ - tmp = krb5_principal_compare (context, srv_principal, creds->server); - if (!tmp) { + if (strcmp(rep->enc_part.srealm, srealm) != 0 || + strcmp(rep->enc_part.srealm, crealm) != 0) + { ret = KRB5KRB_AP_ERR_MODIFIED; - krb5_clear_error_string (context); + krb5_clear_error_string(context); goto out; } } @@ -329,8 +317,6 @@ ignore_cname = 1; out: memset (rep->enc_part.key.keyvalue.data, 0, rep->enc_part.key.keyvalue.length); - if (srv_principal) - krb5_free_principal (context, srv_principal); return ret; } @@ -792,18 +778,23 @@ krb5_get_in_cred(krb5_context context, if (ret) goto out; - ret = _krb5_extract_ticket(context, - &rep, - creds, - key, - keyseed, - KRB5_KU_AS_REP_ENC_PART, - NULL, - nonce, - FALSE, - opts.request_anonymous, - decrypt_proc, - decryptarg); + { + unsigned flags = 0; + if (opts.request_anonymous) + flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; + + ret = _krb5_extract_ticket(context, + &rep, + creds, + key, + keyseed, + KRB5_KU_AS_REP_ENC_PART, + NULL, + nonce, + flags, + decrypt_proc, + decryptarg); + } memset (key->keyvalue.data, 0, key->keyvalue.length); krb5_free_keyblock_contents (context, key); free (key); diff --git a/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c b/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c index 69da6c5ea7..52f95c4bc4 100644 --- a/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c +++ b/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_in_tkt_with_keytab.c,v 1.9 2005/06/17 04:56:44 lha Exp $"); +RCSID("$Id: get_in_tkt_with_keytab.c 15477 2005-06-17 04:56:44Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_keytab_key_proc (krb5_context context, diff --git a/source4/heimdal/lib/krb5/get_port.c b/source4/heimdal/lib/krb5/get_port.c index ba76466e06..85587ea766 100644 --- a/source4/heimdal/lib/krb5/get_port.c +++ b/source4/heimdal/lib/krb5/get_port.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_port.c,v 1.9 2004/05/25 21:29:59 lha Exp $"); +RCSID("$Id: get_port.c 13863 2004-05-25 21:46:46Z lha $"); int KRB5_LIB_FUNCTION krb5_getportbyname (krb5_context context, diff --git a/source4/heimdal/lib/krb5/heim_err.et b/source4/heimdal/lib/krb5/heim_err.et index 3c4f06edb1..1b8ab49bc1 100644 --- a/source4/heimdal/lib/krb5/heim_err.et +++ b/source4/heimdal/lib/krb5/heim_err.et @@ -3,7 +3,7 @@ # # This might look like a com_err file, but is not # -id "$Id: heim_err.et,v 1.13 2004/02/13 16:23:40 lha Exp $" +id "$Id: heim_err.et 13352 2004-02-13 16:23:40Z lha $" error_table heim diff --git a/source4/heimdal/lib/krb5/heim_threads.h b/source4/heimdal/lib/krb5/heim_threads.h index 3ebe66beee..3c27d13d81 100755 --- a/source4/heimdal/lib/krb5/heim_threads.h +++ b/source4/heimdal/lib/krb5/heim_threads.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: heim_threads.h,v 1.11 2004/12/18 16:03:38 lha Exp $ */ +/* $Id: heim_threads.h 14409 2004-12-18 16:03:38Z lha $ */ /* * Provide wrapper macros for thread synchronization primitives so we diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index a331524a7e..5bdf23d97f 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c,v 1.30 2006/11/23 16:27:36 lha Exp $"); +RCSID("$Id: init_creds.c 20541 2007-04-23 12:19:14Z lha $"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) @@ -386,7 +386,7 @@ krb5_get_init_creds_opt_get_error(krb5_context context, return ENOMEM; } - ret = copy_KRB_ERROR(*error, opt->opt_private->error); + ret = copy_KRB_ERROR(opt->opt_private->error, *error); if (ret) krb5_clear_error_string(context); @@ -408,3 +408,36 @@ krb5_get_init_creds_opt_set_addressless(krb5_context context, opt->opt_private->addressless = KRB5_INIT_CREDS_TRISTATE_FALSE; return 0; } + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_canonicalize(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_boolean req) +{ + krb5_error_code ret; + ret = require_ext_opt(context, opt, "init_creds_opt_set_canonicalize"); + if (ret) + return ret; + if (req) + opt->opt_private->flags |= KRB5_INIT_CREDS_CANONICALIZE; + else + opt->opt_private->flags &= ~KRB5_INIT_CREDS_CANONICALIZE; + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_win2k(krb5_context context, + krb5_get_init_creds_opt *opt, + krb5_boolean req) +{ + krb5_error_code ret; + ret = require_ext_opt(context, opt, "init_creds_opt_set_win2k"); + if (ret) + return ret; + if (req) + opt->opt_private->flags |= KRB5_INIT_CREDS_NO_C_CANON_CHECK; + else + opt->opt_private->flags &= ~KRB5_INIT_CREDS_NO_C_CANON_CHECK; + return 0; +} + diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index f6f6eac7d5..a58435a9ea 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c,v 1.105 2007/01/09 10:44:59 lha Exp $"); +RCSID("$Id: init_creds_pw.c 20262 2007-02-18 00:33:01Z lha $"); typedef struct krb5_get_init_creds_ctx { KDCOptions flags; @@ -55,6 +55,7 @@ typedef struct krb5_get_init_creds_ctx { krb5_get_init_creds_tristate req_pac; krb5_pk_init_ctx pk_init_ctx; + int ic_flags; } krb5_get_init_creds_ctx; static krb5_error_code @@ -285,12 +286,16 @@ get_init_creds_common(krb5_context context, ctx->key_proc = options->opt_private->key_proc; ctx->req_pac = options->opt_private->req_pac; ctx->pk_init_ctx = options->opt_private->pk_init_ctx; + ctx->ic_flags = options->opt_private->flags; } else ctx->req_pac = KRB5_INIT_CREDS_TRISTATE_UNSET; if (ctx->key_proc == NULL) ctx->key_proc = default_s2k_func; + if (ctx->ic_flags & KRB5_INIT_CREDS_CANONICALIZE) + ctx->flags.canonicalize = 1; + ctx->pre_auth_types = NULL; ctx->addrs = NULL; ctx->etypes = NULL; @@ -834,6 +839,8 @@ static PA_DATA * find_pa_data(const METHOD_DATA *md, int type) { int i; + if (md == NULL) + return NULL; for (i = 0; i < md->len; i++) if (md->val[i].padata_type == type) return &md->val[i]; @@ -1347,6 +1354,15 @@ init_cred_loop(krb5_context context, { krb5_keyblock *key = NULL; + unsigned flags = 0; + + if (ctx->flags.request_anonymous) + flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; + if (ctx->flags.canonicalize) { + flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH; + flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; + flags |= EXTRACT_TICKET_MATCH_REALM; + } ret = process_pa_data_to_key(context, ctx, creds, &ctx->as_req, &rep, hi, &key); @@ -1361,12 +1377,65 @@ init_cred_loop(krb5_context context, KRB5_KU_AS_REP_ENC_PART, NULL, ctx->nonce, - FALSE, - ctx->flags.request_anonymous, + flags, NULL, NULL); krb5_free_keyblock(context, key); } + /* + * Verify referral data + */ + if ((ctx->ic_flags & KRB5_INIT_CREDS_CANONICALIZE) && + (ctx->ic_flags & KRB5_INIT_CREDS_NO_C_CANON_CHECK) == 0) + { + PA_ClientCanonicalized canon; + krb5_crypto crypto; + krb5_data data; + PA_DATA *pa; + size_t len; + + pa = find_pa_data(rep.kdc_rep.padata, KRB5_PADATA_CLIENT_CANONICALIZED); + if (pa == NULL) { + ret = EINVAL; + krb5_set_error_string(context, "Client canonicalizion not signed"); + goto out; + } + + ret = decode_PA_ClientCanonicalized(pa->padata_value.data, + pa->padata_value.length, + &canon, &len); + if (ret) { + krb5_set_error_string(context, "Failed to decode " + "PA_ClientCanonicalized"); + goto out; + } + + ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length, + &canon.names, &len, ret); + if (ret) + goto out; + if (data.length != len) + krb5_abortx(context, "internal asn.1 error"); + + ret = krb5_crypto_init(context, &creds->session, 0, &crypto); + if (ret) { + free(data.data); + free_PA_ClientCanonicalized(&canon); + goto out; + } + + ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES, + data.data, data.length, + &canon.canon_checksum); + krb5_crypto_destroy(context, crypto); + free(data.data); + free_PA_ClientCanonicalized(&canon); + if (ret) { + krb5_set_error_string(context, "Failed to verify " + "client canonicalized data"); + goto out; + } + } out: krb5_data_free(&ctx->req_buffer); free_METHOD_DATA(&md); diff --git a/source4/heimdal/lib/krb5/k524_err.et b/source4/heimdal/lib/krb5/k524_err.et index 2dc60f46ae..0ca25f74d4 100644 --- a/source4/heimdal/lib/krb5/k524_err.et +++ b/source4/heimdal/lib/krb5/k524_err.et @@ -3,7 +3,7 @@ # # This might look like a com_err file, but is not # -id "$Id: k524_err.et,v 1.1 2001/06/20 02:44:11 joda Exp $" +id "$Id: k524_err.et 10141 2001-06-20 02:45:58Z joda $" error_table k524 diff --git a/source4/heimdal/lib/krb5/kcm.c b/source4/heimdal/lib/krb5/kcm.c index 8f2d9f7f86..c945a9ce13 100644 --- a/source4/heimdal/lib/krb5/kcm.c +++ b/source4/heimdal/lib/krb5/kcm.c @@ -43,7 +43,7 @@ #include "kcm.h" -RCSID("$Id: kcm.c,v 1.9 2006/05/05 09:28:48 lha Exp $"); +RCSID("$Id: kcm.c 17442 2006-05-05 09:31:15Z lha $"); typedef struct krb5_kcmcache { char *name; diff --git a/source4/heimdal/lib/krb5/keyblock.c b/source4/heimdal/lib/krb5/keyblock.c index 314d97978b..ff4f972e57 100644 --- a/source4/heimdal/lib/krb5/keyblock.c +++ b/source4/heimdal/lib/krb5/keyblock.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keyblock.c,v 1.17 2005/05/18 04:21:31 lha Exp $"); +RCSID("$Id: keyblock.c 15167 2005-05-18 04:21:57Z lha $"); void KRB5_LIB_FUNCTION krb5_keyblock_zero(krb5_keyblock *keyblock) diff --git a/source4/heimdal/lib/krb5/keytab.c b/source4/heimdal/lib/krb5/keytab.c index 43fc21c1d1..f6c7858c12 100644 --- a/source4/heimdal/lib/krb5/keytab.c +++ b/source4/heimdal/lib/krb5/keytab.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab.c,v 1.63 2005/11/25 21:46:40 lha Exp $"); +RCSID("$Id: keytab.c 20211 2007-02-09 07:11:03Z lha $"); /* * Register a new keytab in `ops' @@ -364,11 +364,11 @@ krb5_kt_get_entry(krb5_context context, if (entry->vno) { return 0; } else { - char princ[256], kt_name[256], kvno_str[25]; + char princ[256], kvno_str[25], *kt_name; char *enctype_str = NULL; krb5_unparse_name_fixed (context, principal, princ, sizeof(princ)); - krb5_kt_get_name (context, id, kt_name, sizeof(kt_name)); + krb5_kt_get_full_name (context, id, &kt_name); krb5_enctype_to_string(context, enctype, &enctype_str); if (kvno) @@ -377,11 +377,12 @@ krb5_kt_get_entry(krb5_context context, kvno_str[0] = '\0'; krb5_set_error_string (context, - "failed to find %s%s in keytab %s (%s)", + "Failed to find %s%s in keytab %s (%s)", princ, kvno_str, - kt_name, + kt_name ? kt_name : "unknown keytab", enctype_str ? enctype_str : "unknown enctype"); + free(kt_name); free(enctype_str); return KRB5_KT_NOTFOUND; } diff --git a/source4/heimdal/lib/krb5/keytab_any.c b/source4/heimdal/lib/krb5/keytab_any.c index d5130aaad8..54272d4845 100644 --- a/source4/heimdal/lib/krb5/keytab_any.c +++ b/source4/heimdal/lib/krb5/keytab_any.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_any.c,v 1.8 2006/04/10 09:20:13 lha Exp $"); +RCSID("$Id: keytab_any.c 17035 2006-04-10 09:20:13Z lha $"); struct any_data { krb5_keytab kt; diff --git a/source4/heimdal/lib/krb5/keytab_file.c b/source4/heimdal/lib/krb5/keytab_file.c index 1b06387339..4ada3a463e 100644 --- a/source4/heimdal/lib/krb5/keytab_file.c +++ b/source4/heimdal/lib/krb5/keytab_file.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_file.c,v 1.23 2006/05/05 12:36:57 lha Exp $"); +RCSID("$Id: keytab_file.c 17457 2006-05-05 12:36:57Z lha $"); #define KRB5_KT_VNO_1 1 #define KRB5_KT_VNO_2 2 diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c index d7f8a720e1..77455ba5f7 100644 --- a/source4/heimdal/lib/krb5/keytab_keyfile.c +++ b/source4/heimdal/lib/krb5/keytab_keyfile.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2002, 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_keyfile.c,v 1.19 2006/04/24 15:06:57 lha Exp $"); +RCSID("$Id: keytab_keyfile.c 20695 2007-05-30 14:09:09Z lha $"); /* afs keyfile operations --------------------------------------- */ @@ -350,7 +350,7 @@ akf_add_entry(krb5_context context, for (i = 0; i < len; i++) { ret = krb5_ret_int32(sp, &kvno); if (ret) { - krb5_set_error_string (context, "Failed got get kvno "); + krb5_set_error_string (context, "Failed to get kvno "); goto out; } if(krb5_storage_seek(sp, 8, SEEK_CUR) < 0) { diff --git a/source4/heimdal/lib/krb5/keytab_krb4.c b/source4/heimdal/lib/krb5/keytab_krb4.c index 19e7f106bf..907836c144 100644 --- a/source4/heimdal/lib/krb5/keytab_krb4.c +++ b/source4/heimdal/lib/krb5/keytab_krb4.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_krb4.c,v 1.15 2006/04/10 17:10:53 lha Exp $"); +RCSID("$Id: keytab_krb4.c 17046 2006-04-10 17:10:53Z lha $"); struct krb4_kt_data { char *filename; diff --git a/source4/heimdal/lib/krb5/keytab_memory.c b/source4/heimdal/lib/krb5/keytab_memory.c index fa54ff43ce..0ad8720c3f 100644 --- a/source4/heimdal/lib/krb5/keytab_memory.c +++ b/source4/heimdal/lib/krb5/keytab_memory.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_memory.c,v 1.8 2005/12/05 18:39:46 lha Exp $"); +RCSID("$Id: keytab_memory.c 16352 2005-12-05 18:39:46Z lha $"); /* memory operations -------------------------------------------- */ diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index c3e5732753..be718f6714 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -4,14 +4,6 @@ #include -#ifndef KRB5_LIB_FUNCTION -#if defined(_WIN32) -#define KRB5_LIB_FUNCTION _stdcall -#else -#define KRB5_LIB_FUNCTION -#endif -#endif - void KRB5_LIB_FUNCTION _krb5_aes_cts_encrypt ( const unsigned char */*in*/, @@ -68,8 +60,7 @@ _krb5_extract_ticket ( krb5_key_usage /*key_usage*/, krb5_addresses */*addrs*/, unsigned /*nonce*/, - krb5_boolean /*allow_server_mismatch*/, - krb5_boolean /*ignore_cname*/, + unsigned /*flags*/, krb5_decrypt_proc /*decrypt_proc*/, krb5_const_pointer /*decryptarg*/); diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 9dfe487b0a..e852bffeb1 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -520,6 +520,19 @@ krb5_c_make_random_key ( krb5_enctype /*enctype*/, krb5_keyblock */*random_key*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_prf ( + krb5_context /*context*/, + const krb5_keyblock */*key*/, + const krb5_data */*input*/, + krb5_data */*output*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_prf_length ( + krb5_context /*context*/, + krb5_enctype /*type*/, + size_t */*length*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_c_set_checksum ( krb5_context /*context*/, @@ -1103,11 +1116,34 @@ krb5_crypto_init ( krb5_enctype /*etype*/, krb5_crypto */*crypto*/); +size_t +krb5_crypto_overhead ( + krb5_context /*context*/, + krb5_crypto /*crypto*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_prf ( + krb5_context /*context*/, + const krb5_crypto /*crypto*/, + const krb5_data */*input*/, + krb5_data */*output*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_crypto_prf_length ( + krb5_context /*context*/, + krb5_enctype /*type*/, + size_t */*length*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_data_alloc ( krb5_data */*p*/, int /*len*/); +int KRB5_LIB_FUNCTION +krb5_data_cmp ( + const krb5_data */*data1*/, + const krb5_data */*data2*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_data_copy ( krb5_data */*p*/, @@ -1247,12 +1283,6 @@ krb5_digest_alloc ( void krb5_digest_free (krb5_digest /*digest*/); -krb5_error_code -krb5_digest_get_a1_hash ( - krb5_context /*context*/, - krb5_digest /*digest*/, - krb5_data */*data*/); - krb5_error_code krb5_digest_get_client_binding ( krb5_context /*context*/, @@ -1270,11 +1300,6 @@ krb5_digest_get_opaque ( krb5_context /*context*/, krb5_digest /*digest*/); -const char * -krb5_digest_get_responseData ( - krb5_context /*context*/, - krb5_digest /*digest*/); - const char * krb5_digest_get_rsp ( krb5_context /*context*/, @@ -1285,6 +1310,12 @@ krb5_digest_get_server_nonce ( krb5_context /*context*/, krb5_digest /*digest*/); +krb5_error_code +krb5_digest_get_session_key ( + krb5_context /*context*/, + krb5_digest /*digest*/, + krb5_data */*data*/); + krb5_error_code krb5_digest_get_tickets ( krb5_context /*context*/, @@ -1298,6 +1329,11 @@ krb5_digest_init_request ( krb5_realm /*realm*/, krb5_ccache /*ccache*/); +krb5_boolean +krb5_digest_rep_get_status ( + krb5_context /*context*/, + krb5_digest /*digest*/); + krb5_error_code krb5_digest_request ( krb5_context /*context*/, @@ -1371,6 +1407,12 @@ krb5_digest_set_realm ( krb5_digest /*digest*/, const char */*realm*/); +int +krb5_digest_set_responseData ( + krb5_context /*context*/, + krb5_digest /*digest*/, + const char */*response*/); + krb5_error_code krb5_digest_set_server_cb ( krb5_context /*context*/, @@ -2057,6 +2099,12 @@ krb5_get_init_creds_opt_set_anonymous ( krb5_get_init_creds_opt */*opt*/, int /*anonymous*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_canonicalize ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + krb5_boolean /*req*/); + void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_set_default_flags ( krb5_context /*context*/, @@ -2128,6 +2176,12 @@ krb5_get_init_creds_opt_set_tkt_life ( krb5_get_init_creds_opt */*opt*/, krb5_deltat /*tkt_life*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_init_creds_opt_set_win2k ( + krb5_context /*context*/, + krb5_get_init_creds_opt */*opt*/, + krb5_boolean /*req*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_get_init_creds_password ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5-v4compat.h b/source4/heimdal/lib/krb5/krb5-v4compat.h index 3e14c5a38f..2ea534cfe3 100644 --- a/source4/heimdal/lib/krb5/krb5-v4compat.h +++ b/source4/heimdal/lib/krb5/krb5-v4compat.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5-v4compat.h,v 1.7 2006/05/05 09:29:07 lha Exp $ */ +/* $Id: krb5-v4compat.h 17442 2006-05-05 09:31:15Z lha $ */ #ifndef __KRB5_V4COMPAT_H__ #define __KRB5_V4COMPAT_H__ diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 55a83fb533..eefda81ca9 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h,v 1.259 2007/01/03 18:51:52 lha Exp $ */ +/* $Id: krb5.h 20245 2007-02-17 00:09:57Z lha $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -222,8 +222,10 @@ typedef enum krb5_key_usage { /* Encryption key usage used in the digest encryption field */ KRB5_KU_DIGEST_OPAQUE = -19, /* Checksum key usage used in the digest opaque field */ - KRB5_KU_KRB5SIGNEDPATH = -21 + KRB5_KU_KRB5SIGNEDPATH = -21, /* Checksum key usage on KRB5SignedPath */ + KRB5_KU_CANONICALIZED_NAMES = -23 + /* Checksum key usage on PA-CANONICALIZED */ } krb5_key_usage; typedef krb5_key_usage krb5_keyusage; @@ -744,7 +746,8 @@ typedef krb5_error_code (*krb5_send_to_kdc_func)(krb5_context, /* flags for krb5_parse_name_flags */ enum { KRB5_PRINCIPAL_PARSE_NO_REALM = 1, - KRB5_PRINCIPAL_PARSE_MUST_REALM = 2 + KRB5_PRINCIPAL_PARSE_MUST_REALM = 2, + KRB5_PRINCIPAL_PARSE_ENTERPRISE = 4 }; /* flags for krb5_unparse_name_flags */ diff --git a/source4/heimdal/lib/krb5/krb5_ccapi.h b/source4/heimdal/lib/krb5/krb5_ccapi.h index d59b589304..b53d77ef18 100644 --- a/source4/heimdal/lib/krb5/krb5_ccapi.h +++ b/source4/heimdal/lib/krb5/krb5_ccapi.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_ccapi.h,v 1.3 2006/05/05 09:29:59 lha Exp $ */ +/* $Id: krb5_ccapi.h 17442 2006-05-05 09:31:15Z lha $ */ #ifndef KRB5_CCAPI_H #define KRB5_CCAPI_H 1 diff --git a/source4/heimdal/lib/krb5/krb5_err.et b/source4/heimdal/lib/krb5/krb5_err.et index e7bada1808..785c258ee0 100644 --- a/source4/heimdal/lib/krb5/krb5_err.et +++ b/source4/heimdal/lib/krb5/krb5_err.et @@ -3,7 +3,7 @@ # # This might look like a com_err file, but is not # -id "$Id: krb5_err.et,v 1.14 2006/02/13 11:28:22 lha Exp $" +id "$Id: krb5_err.et 20760 2007-06-01 03:24:49Z lha $" error_table krb5 @@ -76,6 +76,10 @@ error_code KDC_NOT_TRUSTED, "KDC not trusted" error_code INVALID_SIG, "Invalid signature" error_code DH_KEY_PARAMETERS_NOT_ACCEPTED, "DH parameters not accepted" +index 68 +prefix KRB5_KDC_ERR +error_code WRONG_REALM, "Wrong realm" + index 69 prefix KRB5_AP_ERR error_code USER_TO_USER_REQUIRED, "User to user required" @@ -86,7 +90,8 @@ error_code CANT_VERIFY_CERTIFICATE, "Cannot verify certificate" error_code INVALID_CERTIFICATE, "Certificate invalid" error_code REVOKED_CERTIFICATE, "Certificate revoked" error_code REVOCATION_STATUS_UNKNOWN, "Revocation status unknown" -error_code CLIENT_NAME_MISMATCH, "Revocation status unknown" +error_code REVOCATION_STATUS_UNAVAILABLE, "Revocation status unavaible" +error_code CLIENT_NAME_MISMATCH, "Client name mismatch in certificate" error_code INCONSISTENT_KEY_PURPOSE, "Inconsistent key purpose" error_code DIGEST_IN_CERT_NOT_ACCEPTED, "Digest in certificate not accepted" error_code PA_CHECKSUM_MUST_BE_INCLUDED, "paChecksum must be included" @@ -103,7 +108,7 @@ error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not suppo index 128 prefix -error_code KRB5_ERR_RCSID, "$Id: krb5_err.et,v 1.14 2006/02/13 11:28:22 lha Exp $" +error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 20760 2007-06-01 03:24:49Z lha $" error_code KRB5_LIBOS_BADLOCKFLAG, "Invalid flag for file lock mode" error_code KRB5_LIBOS_CANTREADPWD, "Cannot read password" diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 35d046c8d9..87169fc430 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_locl.h,v 1.97 2006/12/15 16:46:51 lha Exp $ */ +/* $Id: krb5_locl.h 20261 2007-02-18 00:32:22Z lha $ */ #ifndef __KRB5_LOCL_H__ #define __KRB5_LOCL_H__ @@ -196,9 +196,11 @@ struct _krb5_get_init_creds_opt_private { krb5_get_init_creds_tristate req_pac; /* PKINIT */ krb5_pk_init_ctx pk_init_ctx; - int canonicalize; KRB_ERROR *error; krb5_get_init_creds_tristate addressless; + int flags; +#define KRB5_INIT_CREDS_CANONICALIZE 1 +#define KRB5_INIT_CREDS_NO_C_CANON_CHECK 2 }; typedef struct krb5_context_data { @@ -244,6 +246,10 @@ typedef struct krb5_context_data { #define KRB5_DEFAULT_CCNAME_FILE "FILE:/tmp/krb5cc_%{uid}" #define KRB5_DEFAULT_CCNAME_API "API:" +#define EXTRACT_TICKET_ALLOW_CNAME_MISMATCH 1 +#define EXTRACT_TICKET_ALLOW_SERVER_MISMATCH 2 +#define EXTRACT_TICKET_MATCH_REALM 4 + /* * Configurable options */ diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index 3e281e5c63..51bf934bfd 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -35,7 +35,7 @@ #include #include "locate_plugin.h" -RCSID("$Id: krbhst.c,v 1.61 2006/11/30 17:23:08 lha Exp $"); +RCSID("$Id: krbhst.c 19198 2006-11-30 17:23:08Z lha $"); static int string_to_proto(const char *string) diff --git a/source4/heimdal/lib/krb5/locate_plugin.h b/source4/heimdal/lib/krb5/locate_plugin.h index ec06d362cf..251712c894 100644 --- a/source4/heimdal/lib/krb5/locate_plugin.h +++ b/source4/heimdal/lib/krb5/locate_plugin.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: locate_plugin.h,v 1.1 2006/11/12 19:00:03 lha Exp $ */ +/* $Id: locate_plugin.h 18998 2006-11-12 19:00:03Z lha $ */ #ifndef HEIMDAL_KRB5_LOCATE_PLUGIN_H #define HEIMDAL_KRB5_LOCATE_PLUGIN_H 1 diff --git a/source4/heimdal/lib/krb5/log.c b/source4/heimdal/lib/krb5/log.c index 9523ca848c..c04f50fd9a 100644 --- a/source4/heimdal/lib/krb5/log.c +++ b/source4/heimdal/lib/krb5/log.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: log.c,v 1.40 2006/11/21 08:08:46 lha Exp $"); +RCSID("$Id: log.c 19088 2006-11-21 08:08:46Z lha $"); struct facility { int min; diff --git a/source4/heimdal/lib/krb5/mcache.c b/source4/heimdal/lib/krb5/mcache.c index 9588d936d5..ff9261a7db 100644 --- a/source4/heimdal/lib/krb5/mcache.c +++ b/source4/heimdal/lib/krb5/mcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: mcache.c,v 1.20 2005/09/30 11:16:04 lha Exp $"); +RCSID("$Id: mcache.c 19834 2007-01-11 09:26:21Z lha $"); typedef struct krb5_mcache { char *name; @@ -54,8 +54,6 @@ static struct krb5_mcache *mcc_head; #define MISDEAD(X) ((X)->dead) -#define MCC_CURSOR(C) ((struct link*)(C)) - static const char* mcc_get_name(krb5_context context, krb5_ccache id) diff --git a/source4/heimdal/lib/krb5/misc.c b/source4/heimdal/lib/krb5/misc.c index f04f8d9996..0d410b57d2 100644 --- a/source4/heimdal/lib/krb5/misc.c +++ b/source4/heimdal/lib/krb5/misc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: misc.c,v 1.6 2006/06/06 14:57:47 lha Exp $"); +RCSID("$Id: misc.c 17616 2006-06-06 14:57:47Z lha $"); krb5_error_code KRB5_LIB_FUNCTION _krb5_s4u2self_to_checksumdata(krb5_context context, diff --git a/source4/heimdal/lib/krb5/mit_glue.c b/source4/heimdal/lib/krb5/mit_glue.c index c4d3ff5390..7440d54762 100755 --- a/source4/heimdal/lib/krb5/mit_glue.c +++ b/source4/heimdal/lib/krb5/mit_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: mit_glue.c,v 1.12 2006/11/17 22:17:46 lha Exp $"); +RCSID("$Id: mit_glue.c 20042 2007-01-23 20:37:43Z lha $"); /* * Glue for MIT API @@ -340,3 +340,30 @@ krb5_c_keylengths(krb5_context context, *ilen = (*ilen + 7) / 8; return krb5_enctype_keysize(context, enctype, keylen); } + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_prf_length(krb5_context context, + krb5_enctype type, + size_t *length) +{ + return krb5_crypto_prf_length(context, type, length); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_c_prf(krb5_context context, + const krb5_keyblock *key, + const krb5_data *input, + krb5_data *output) +{ + krb5_crypto crypto; + krb5_error_code ret; + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) + return ret; + + ret = krb5_crypto_prf(context, crypto, input, output); + krb5_crypto_destroy(context, crypto); + + return ret; +} diff --git a/source4/heimdal/lib/krb5/mk_error.c b/source4/heimdal/lib/krb5/mk_error.c index 7a8b1ba06b..7046649934 100644 --- a/source4/heimdal/lib/krb5/mk_error.c +++ b/source4/heimdal/lib/krb5/mk_error.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: mk_error.c,v 1.22 2005/06/16 21:16:40 lha Exp $"); +RCSID("$Id: mk_error.c 15457 2005-06-16 21:16:40Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_mk_error(krb5_context context, diff --git a/source4/heimdal/lib/krb5/mk_priv.c b/source4/heimdal/lib/krb5/mk_priv.c index b5a1aadfea..87e429af8c 100644 --- a/source4/heimdal/lib/krb5/mk_priv.c +++ b/source4/heimdal/lib/krb5/mk_priv.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_priv.c,v 1.35 2006/02/01 12:39:26 lha Exp $"); +RCSID("$Id: mk_priv.c 16680 2006-02-01 12:39:26Z lha $"); krb5_error_code KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/mk_rep.c b/source4/heimdal/lib/krb5/mk_rep.c index 90823f9478..570a837201 100644 --- a/source4/heimdal/lib/krb5/mk_rep.c +++ b/source4/heimdal/lib/krb5/mk_rep.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_rep.c,v 1.26 2004/05/25 21:33:51 lha Exp $"); +RCSID("$Id: mk_rep.c 13863 2004-05-25 21:46:46Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_mk_rep(krb5_context context, diff --git a/source4/heimdal/lib/krb5/mk_req.c b/source4/heimdal/lib/krb5/mk_req.c index adc077e13f..5f64f01e95 100644 --- a/source4/heimdal/lib/krb5/mk_req.c +++ b/source4/heimdal/lib/krb5/mk_req.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_req.c,v 1.26 2004/05/25 21:34:11 lha Exp $"); +RCSID("$Id: mk_req.c 13863 2004-05-25 21:46:46Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_mk_req_exact(krb5_context context, diff --git a/source4/heimdal/lib/krb5/mk_req_ext.c b/source4/heimdal/lib/krb5/mk_req_ext.c index 8646c4ebea..b6d55c8815 100644 --- a/source4/heimdal/lib/krb5/mk_req_ext.c +++ b/source4/heimdal/lib/krb5/mk_req_ext.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_req_ext.c,v 1.33 2006/12/27 12:07:22 lha Exp $"); +RCSID("$Id: mk_req_ext.c 19511 2006-12-27 12:07:22Z lha $"); krb5_error_code _krb5_mk_req_internal(krb5_context context, diff --git a/source4/heimdal/lib/krb5/n-fold.c b/source4/heimdal/lib/krb5/n-fold.c index 691e95eb86..1474a76b77 100644 --- a/source4/heimdal/lib/krb5/n-fold.c +++ b/source4/heimdal/lib/krb5/n-fold.c @@ -32,7 +32,7 @@ #include "krb5_locl.h" -RCSID("$Id: n-fold.c,v 1.7 2004/05/25 21:35:31 lha Exp $"); +RCSID("$Id: n-fold.c 13863 2004-05-25 21:46:46Z lha $"); static void rr13(unsigned char *buf, size_t len) diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 283759c98b..55d4f5ff56 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pac.c,v 1.13 2007/01/09 11:22:56 lha Exp $"); +RCSID("$Id: pac.c 20845 2007-06-03 14:31:16Z lha $"); struct PAC_INFO_BUFFER { uint32_t type; @@ -56,14 +56,15 @@ struct krb5_pac { struct PAC_INFO_BUFFER *logon_name; }; -#define PAC_ALIGNMENT 8 +#define PAC_ALIGNMENT 8 -#define PACTYPE_SIZE 8 -#define PAC_INFO_BUFFER_SIZE 16 +#define PACTYPE_SIZE 8 +#define PAC_INFO_BUFFER_SIZE 16 -#define PAC_SERVER_CHECKSUM 6 -#define PAC_PRIVSVR_CHECKSUM 7 -#define PAC_LOGON_NAME 10 +#define PAC_SERVER_CHECKSUM 6 +#define PAC_PRIVSVR_CHECKSUM 7 +#define PAC_LOGON_NAME 10 +#define PAC_CONSTRAINED_DELEGATION 11 #define CHECK(r,f,l) \ do { \ @@ -252,12 +253,10 @@ krb5_pac_add_buffer(krb5_context context, struct krb5_pac *p, { krb5_error_code ret; void *ptr; - size_t len, offset, header_end; + size_t len, offset, header_end, old_end; uint32_t i; - len = p->pac->numbuffers + 1; - if (len < p->pac->numbuffers) - return EINVAL; + len = p->pac->numbuffers; ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * len)); @@ -272,11 +271,12 @@ krb5_pac_add_buffer(krb5_context context, struct krb5_pac *p, offset = p->data.length + PAC_INFO_BUFFER_SIZE; - p->pac->buffers[len - 1].type = type; - p->pac->buffers[len - 1].buffersize = data->length; - p->pac->buffers[len - 1].offset_lo = offset; - p->pac->buffers[len - 1].offset_hi = 0; + p->pac->buffers[len].type = type; + p->pac->buffers[len].buffersize = data->length; + p->pac->buffers[len].offset_lo = offset; + p->pac->buffers[len].offset_hi = 0; + old_end = p->data.length; len = p->data.length + data->length + PAC_INFO_BUFFER_SIZE; if (len < p->data.length) { krb5_set_error_string(context, "integer overrun"); @@ -292,14 +292,17 @@ krb5_pac_add_buffer(krb5_context context, struct krb5_pac *p, return ret; } - /* make place for PAC INFO BUFFER header */ + /* + * make place for new PAC INFO BUFFER header + */ header_end = PACTYPE_SIZE + (PAC_INFO_BUFFER_SIZE * p->pac->numbuffers); - memmove((unsigned char *)p->data.data + header_end, - (unsigned char *)p->data.data + header_end + PAC_INFO_BUFFER_SIZE, - PAC_INFO_BUFFER_SIZE); + memmove((unsigned char *)p->data.data + header_end + PAC_INFO_BUFFER_SIZE, + (unsigned char *)p->data.data + header_end , + old_end - header_end); + memset((unsigned char *)p->data.data + header_end, 0, PAC_INFO_BUFFER_SIZE); /* - * + * copy in new data part */ memcpy((unsigned char *)p->data.data + offset, @@ -444,12 +447,15 @@ verify_checksum(krb5_context context, ret = krb5_verify_checksum(context, crypto, KRB5_KU_OTHER_CKSUM, ptr, len, &cksum); + free(cksum.checksum.data); krb5_crypto_destroy(context, crypto); krb5_storage_free(sp); return ret; out: + if (cksum.checksum.data) + free(cksum.checksum.data); if (sp) krb5_storage_free(sp); if (crypto) @@ -890,7 +896,6 @@ _krb5_pac_sign(krb5_context context, goto out; /* Set lengths for checksum */ - ret = pac_checksum(context, server_key, &server_cksumtype, &server_size); if (ret) goto out; diff --git a/source4/heimdal/lib/krb5/padata.c b/source4/heimdal/lib/krb5/padata.c index d5c3f422a7..b2b70f52e7 100644 --- a/source4/heimdal/lib/krb5/padata.c +++ b/source4/heimdal/lib/krb5/padata.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: padata.c,v 1.5 2005/06/17 04:28:35 lha Exp $"); +RCSID("$Id: padata.c 15469 2005-06-17 04:28:35Z lha $"); PA_DATA * krb5_find_padata(PA_DATA *val, unsigned len, int type, int *idx) diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 4f8ed8fe07..dd82842084 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c,v 1.120 2006/12/08 02:48:09 lha Exp $"); +RCSID("$Id: pkinit.c 21004 2007-06-08 01:53:10Z lha $"); struct krb5_dh_moduli { char *name; @@ -83,10 +83,11 @@ struct krb5_pk_init_ctx_data { struct krb5_dh_moduli **m; hx509_peer_info peer; int type; - int require_binding; - int require_eku; - int require_krbtgt_otherName; - int require_hostname_match; + unsigned int require_binding:1; + unsigned int require_eku:1; + unsigned int require_krbtgt_otherName:1; + unsigned int require_hostname_match:1; + unsigned int trustedCertifiers:1; }; static void @@ -170,6 +171,7 @@ _krb5_pk_create_sign(krb5_context context, } ret = hx509_cms_create_signed_1(id->hx509ctx, + 0, eContentType, eContent->data, eContent->length, @@ -438,7 +440,6 @@ build_auth_pack(krb5_context context, return ret; } - return ret; } @@ -587,18 +588,21 @@ pk_mk_padata(krb5_context context, memset(&req, 0, sizeof(req)); req.signedAuthPack = buf; - req.trustedCertifiers = calloc(1, sizeof(*req.trustedCertifiers)); - if (req.trustedCertifiers == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - free_PA_PK_AS_REQ(&req); - goto out; - } - ret = build_edi(context, ctx->id->hx509ctx, - ctx->id->anchors, req.trustedCertifiers); - if (ret) { - krb5_set_error_string(context, "pk-init: failed to build trustedCertifiers"); - free_PA_PK_AS_REQ(&req); - goto out; + if (ctx->trustedCertifiers) { + + req.trustedCertifiers = calloc(1, sizeof(*req.trustedCertifiers)); + if (req.trustedCertifiers == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + free_PA_PK_AS_REQ(&req); + goto out; + } + ret = build_edi(context, ctx->id->hx509ctx, + ctx->id->anchors, req.trustedCertifiers); + if (ret) { + krb5_set_error_string(context, "pk-init: failed to build trustedCertifiers"); + free_PA_PK_AS_REQ(&req); + goto out; + } } req.kdcPkId = NULL; @@ -684,6 +688,14 @@ _krb5_pk_mk_padata(krb5_context context, "pkinit_require_hostname_match", NULL); + ctx->trustedCertifiers = + krb5_config_get_bool_default(context, NULL, + TRUE, + "realms", + req_body->realm, + "pkinit_trustedCertifiers", + NULL); + return pk_mk_padata(context, ctx, req_body, nonce, md); } @@ -705,6 +717,7 @@ _krb5_pk_verify_sign(krb5_context context, id->verify_ctx, data, length, + NULL, id->certpool, contentType, content, @@ -1120,8 +1133,11 @@ pk_rd_pa_reply_dh(krb5_context context, &kdc_dh_info, &size); - if (ret) + if (ret) { + krb5_set_error_string(context, "pkinit - " + "failed to decode KDC DH Key Info"); goto out; + } if (kdc_dh_info.nonce != nonce) { krb5_set_error_string(context, "PKINIT: DH nonce is wrong"); @@ -1226,6 +1242,7 @@ pk_rd_pa_reply_dh(krb5_context context, _krb5_pk_cert_free(host); if (content.data) krb5_data_free(&content); + der_free_oid(&contentType); free_KDCDHKeyInfo(&kdc_dh_info); return ret; @@ -1262,8 +1279,10 @@ _krb5_pk_rd_pa_reply(krb5_context context, pa->padata_value.length, &rep, &size); - if (ret) + if (ret) { + krb5_set_error_string(context, "Failed to decode pkinit AS rep"); return ret; + } switch (rep.element) { case choice_PA_PK_AS_REP_dhInfo: @@ -1861,6 +1880,7 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) free(ctx->id); ctx->id = NULL; } + free(opt->opt_private->pk_init_ctx); opt->opt_private->pk_init_ctx = NULL; #endif } diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c index ce7171dbf0..f19464bf3c 100644 --- a/source4/heimdal/lib/krb5/plugin.c +++ b/source4/heimdal/lib/krb5/plugin.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: plugin.c,v 1.4 2007/01/09 17:46:01 lha Exp $"); +RCSID("$Id: plugin.c 19789 2007-01-09 17:46:01Z lha $"); #ifdef HAVE_DLFCN_H #include #endif diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index 57fcf63dcf..ef3f5412db 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -41,7 +41,7 @@ #include #include "resolve.h" -RCSID("$Id: principal.c,v 1.100 2006/12/17 22:53:39 lha Exp $"); +RCSID("$Id: principal.c 20223 2007-02-15 04:17:04Z lha $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -110,6 +110,8 @@ krb5_parse_name_flags(krb5_context context, int n; char c; int got_realm = 0; + int first_at = 1; + int enterprise = (flags & KRB5_PRINCIPAL_PARSE_ENTERPRISE); *principal = NULL; @@ -122,18 +124,24 @@ krb5_parse_name_flags(krb5_context context, } #undef RFLAGS - /* count number of component */ + /* count number of component, + * enterprise names only have one component + */ ncomp = 1; - for(p = name; *p; p++){ - if(*p=='\\'){ - if(!p[1]) { - krb5_set_error_string (context, - "trailing \\ in principal name"); - return KRB5_PARSE_MALFORMED; - } - p++; - } else if(*p == '/') - ncomp++; + if (!enterprise) { + for(p = name; *p; p++){ + if(*p=='\\'){ + if(!p[1]) { + krb5_set_error_string (context, + "trailing \\ in principal name"); + return KRB5_PARSE_MALFORMED; + } + p++; + } else if(*p == '/') + ncomp++; + else if(*p == '@') + break; + } } comp = calloc(ncomp, sizeof(*comp)); if (comp == NULL) { @@ -166,7 +174,10 @@ krb5_parse_name_flags(krb5_context context, ret = KRB5_PARSE_MALFORMED; goto exit; } - }else if(c == '/' || c == '@'){ + }else if(enterprise && first_at) { + if (c == '@') + first_at = 0; + }else if((c == '/' && !enterprise) || c == '@'){ if(got_realm){ krb5_set_error_string (context, "part after realm in principal name"); @@ -241,7 +252,10 @@ krb5_parse_name_flags(krb5_context context, ret = ENOMEM; goto exit; } - (*principal)->name.name_type = KRB5_NT_PRINCIPAL; + if (enterprise) + (*principal)->name.name_type = KRB5_NT_ENTERPRISE_PRINCIPAL; + else + (*principal)->name.name_type = KRB5_NT_PRINCIPAL; (*principal)->name.name_string.val = comp; princ_num_comp(*principal) = n; (*principal)->realm = realm; diff --git a/source4/heimdal/lib/krb5/prompter_posix.c b/source4/heimdal/lib/krb5/prompter_posix.c index 3ea512c9a7..e0f407fb24 100644 --- a/source4/heimdal/lib/krb5/prompter_posix.c +++ b/source4/heimdal/lib/krb5/prompter_posix.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: prompter_posix.c,v 1.10 2004/05/25 21:38:14 lha Exp $"); +RCSID("$Id: prompter_posix.c 13863 2004-05-25 21:46:46Z lha $"); int KRB5_LIB_FUNCTION krb5_prompter_posix (krb5_context context, diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c index 46a36c9aac..c3f732201f 100644 --- a/source4/heimdal/lib/krb5/rd_cred.c +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_cred.c,v 1.29 2006/10/06 17:04:47 lha Exp $"); +RCSID("$Id: rd_cred.c 20304 2007-04-11 11:15:05Z lha $"); static krb5_error_code compare_addrs(krb5_context context, @@ -79,8 +79,10 @@ krb5_rd_cred(krb5_context context, ret = decode_KRB_CRED(in_data->data, in_data->length, &cred, &len); - if(ret) + if(ret) { + krb5_clear_error_string(context); return ret; + } if (cred.pvno != 5) { ret = KRB5KRB_AP_ERR_BADVERSION; @@ -151,6 +153,8 @@ krb5_rd_cred(krb5_context context, enc_krb_cred_part_data.length, &enc_krb_cred_part, &len); + if (enc_krb_cred_part_data.data != cred.enc_part.cipher.data) + krb5_data_free(&enc_krb_cred_part_data); if (ret) goto out; diff --git a/source4/heimdal/lib/krb5/rd_error.c b/source4/heimdal/lib/krb5/rd_error.c index 93e70c48bd..89615ee8ac 100644 --- a/source4/heimdal/lib/krb5/rd_error.c +++ b/source4/heimdal/lib/krb5/rd_error.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: rd_error.c,v 1.8 2005/05/18 04:21:57 lha Exp $"); +RCSID("$Id: rd_error.c 20304 2007-04-11 11:15:05Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_error(krb5_context context, @@ -45,8 +45,10 @@ krb5_rd_error(krb5_context context, krb5_error_code ret; ret = decode_KRB_ERROR(msg->data, msg->length, result, &len); - if(ret) + if(ret) { + krb5_clear_error_string(context); return ret; + } result->error_code += KRB5KDC_ERR_NONE; return 0; } diff --git a/source4/heimdal/lib/krb5/rd_priv.c b/source4/heimdal/lib/krb5/rd_priv.c index c52ac175fd..d3920dd941 100644 --- a/source4/heimdal/lib/krb5/rd_priv.c +++ b/source4/heimdal/lib/krb5/rd_priv.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_priv.c,v 1.33 2006/04/12 16:18:10 lha Exp $"); +RCSID("$Id: rd_priv.c 17056 2006-04-12 16:18:10Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_priv(krb5_context context, diff --git a/source4/heimdal/lib/krb5/rd_rep.c b/source4/heimdal/lib/krb5/rd_rep.c index 6b7f27c3cf..8c9b7bb441 100644 --- a/source4/heimdal/lib/krb5/rd_rep.c +++ b/source4/heimdal/lib/krb5/rd_rep.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_rep.c,v 1.26 2006/08/21 09:19:22 lha Exp $"); +RCSID("$Id: rd_rep.c 17890 2006-08-21 09:19:22Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_rep(krb5_context context, diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index b7dea2a327..001b47f094 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001, 2003 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_req.c,v 1.70 2007/01/04 11:27:20 lha Exp $"); +RCSID("$Id: rd_req.c 21004 2007-06-08 01:53:10Z lha $"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, @@ -208,6 +208,8 @@ find_etypelist(krb5_context context, adIfRelevant.val[0].ad_data.length, etypes, NULL); + if (ret) + krb5_clear_error_string(context); free_AD_IF_RELEVANT(&adIfRelevant); diff --git a/source4/heimdal/lib/krb5/replay.c b/source4/heimdal/lib/krb5/replay.c index b89f150159..12894d96a9 100644 --- a/source4/heimdal/lib/krb5/replay.c +++ b/source4/heimdal/lib/krb5/replay.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: replay.c,v 1.12 2006/04/10 17:13:49 lha Exp $"); +RCSID("$Id: replay.c 17047 2006-04-10 17:13:49Z lha $"); struct krb5_rcache_data { char *name; diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index 11c07c9e8f..6c70244327 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: send_to_kdc.c,v 1.60 2006/10/20 18:42:01 lha Exp $"); +RCSID("$Id: send_to_kdc.c 19973 2007-01-17 17:19:52Z lha $"); struct send_to_kdc { krb5_send_to_kdc_func func; @@ -331,6 +331,8 @@ krb5_sendto (krb5_context context, int fd; int i; + krb5_data_zero(receive); + for (i = 0; i < context->max_retries; ++i) { krb5_krbhst_info *hi; diff --git a/source4/heimdal/lib/krb5/set_default_realm.c b/source4/heimdal/lib/krb5/set_default_realm.c index 965883309c..98040bc2e9 100644 --- a/source4/heimdal/lib/krb5/set_default_realm.c +++ b/source4/heimdal/lib/krb5/set_default_realm.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: set_default_realm.c,v 1.14 2004/05/25 21:42:26 lha Exp $"); +RCSID("$Id: set_default_realm.c 13863 2004-05-25 21:46:46Z lha $"); /* * Convert the simple string `s' into a NULL-terminated and freshly allocated diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c index 5422c540b9..4abcf44a43 100644 --- a/source4/heimdal/lib/krb5/store.c +++ b/source4/heimdal/lib/krb5/store.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store.c,v 1.60 2006/12/17 22:49:37 lha Exp $"); +RCSID("$Id: store.c 20529 2007-04-22 14:28:19Z lha $"); #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) @@ -891,7 +891,7 @@ krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds) header |= SC_CLIENT_PRINCIPAL; if (creds->server) header |= SC_SERVER_PRINCIPAL; - if (creds->session.keyvalue.data) + if (creds->session.keytype != ETYPE_NULL) header |= SC_SESSION_KEY; if (creds->ticket.data) header |= SC_TICKET; @@ -916,7 +916,7 @@ krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds) return ret; } - if (creds->session.keyvalue.data) { + if (creds->session.keytype != ETYPE_NULL) { ret = krb5_store_keyblock(sp, creds->session); if(ret) return ret; diff --git a/source4/heimdal/lib/krb5/store_emem.c b/source4/heimdal/lib/krb5/store_emem.c index b9f93728de..07acdd1a00 100644 --- a/source4/heimdal/lib/krb5/store_emem.c +++ b/source4/heimdal/lib/krb5/store_emem.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store_emem.c,v 1.14 2004/05/25 21:43:29 lha Exp $"); +RCSID("$Id: store_emem.c 13863 2004-05-25 21:46:46Z lha $"); typedef struct emem_storage{ unsigned char *base; diff --git a/source4/heimdal/lib/krb5/store_fd.c b/source4/heimdal/lib/krb5/store_fd.c index 835d3478e2..15f86fcac3 100644 --- a/source4/heimdal/lib/krb5/store_fd.c +++ b/source4/heimdal/lib/krb5/store_fd.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store_fd.c,v 1.13 2006/06/30 21:23:19 lha Exp $"); +RCSID("$Id: store_fd.c 17779 2006-06-30 21:23:19Z lha $"); typedef struct fd_storage { int fd; diff --git a/source4/heimdal/lib/krb5/store_mem.c b/source4/heimdal/lib/krb5/store_mem.c index d2b6d18252..e6e62b5a62 100644 --- a/source4/heimdal/lib/krb5/store_mem.c +++ b/source4/heimdal/lib/krb5/store_mem.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store_mem.c,v 1.13 2006/11/07 23:02:53 lha Exp $"); +RCSID("$Id: store_mem.c 20307 2007-04-11 11:16:28Z lha $"); typedef struct mem_storage{ unsigned char *base; @@ -121,7 +121,7 @@ krb5_storage_from_mem(void *buf, size_t len) krb5_storage * KRB5_LIB_FUNCTION krb5_storage_from_data(krb5_data *data) { - return krb5_storage_from_mem(data->data, data->length); + return krb5_storage_from_mem(data->data, data->length); } krb5_storage * KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c index 81372c158e..7eb4d32fad 100644 --- a/source4/heimdal/lib/krb5/ticket.c +++ b/source4/heimdal/lib/krb5/ticket.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: ticket.c,v 1.18 2006/12/28 20:49:18 lha Exp $"); +RCSID("$Id: ticket.c 19544 2006-12-28 20:49:18Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_free_ticket(krb5_context context, diff --git a/source4/heimdal/lib/krb5/time.c b/source4/heimdal/lib/krb5/time.c index 4a120ab771..4cd992d48f 100644 --- a/source4/heimdal/lib/krb5/time.c +++ b/source4/heimdal/lib/krb5/time.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: time.c,v 1.13 2004/10/13 17:57:11 lha Exp $"); +RCSID("$Id: time.c 14308 2004-10-13 17:57:11Z lha $"); /* * Set the absolute time that the caller knows the kdc has so the diff --git a/source4/heimdal/lib/krb5/transited.c b/source4/heimdal/lib/krb5/transited.c index 7f18b30c88..7f5498f592 100644 --- a/source4/heimdal/lib/krb5/transited.c +++ b/source4/heimdal/lib/krb5/transited.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: transited.c,v 1.18 2006/04/10 10:26:35 lha Exp $"); +RCSID("$Id: transited.c 17043 2006-04-10 10:26:35Z lha $"); /* this is an attempt at one of the most horrible `compression' schemes that has ever been invented; it's so amazingly brain-dead diff --git a/source4/heimdal/lib/krb5/v4_glue.c b/source4/heimdal/lib/krb5/v4_glue.c index b1e12674dc..d42fbec3a5 100644 --- a/source4/heimdal/lib/krb5/v4_glue.c +++ b/source4/heimdal/lib/krb5/v4_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: v4_glue.c,v 1.5 2006/05/05 09:31:00 lha Exp $"); +RCSID("$Id: v4_glue.c 17442 2006-05-05 09:31:15Z lha $"); #include "krb5-v4compat.h" diff --git a/source4/heimdal/lib/krb5/version.c b/source4/heimdal/lib/krb5/version.c index 5f0fd6680b..f7ccff5bc8 100644 --- a/source4/heimdal/lib/krb5/version.c +++ b/source4/heimdal/lib/krb5/version.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: version.c,v 1.3 1999/12/02 17:05:13 joda Exp $"); +RCSID("$Id: version.c 7464 1999-12-02 17:05:13Z joda $"); /* this is just to get a version stamp in the library file */ diff --git a/source4/heimdal/lib/krb5/warn.c b/source4/heimdal/lib/krb5/warn.c index 4252865301..85f143b8b4 100644 --- a/source4/heimdal/lib/krb5/warn.c +++ b/source4/heimdal/lib/krb5/warn.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: warn.c,v 1.16 2006/11/21 08:06:40 lha Exp $"); +RCSID("$Id: warn.c 19086 2006-11-21 08:06:40Z lha $"); static krb5_error_code _warnerr(krb5_context context, int do_errtext, krb5_error_code code, int level, const char *fmt, va_list ap) -- cgit From ec0035c9b8e0690f3bc21f3de089c39eae660916 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Tue, 3 Jul 2007 08:00:08 +0000 Subject: r23678: Update to current lorikeet-heimdal (-r 767), which should fix the panics on hosts without /dev/random. Andrew Bartlett (This used to be commit 14a4ddb131993fec72316f7e8e371638749e6f1f) --- source4/heimdal/lib/krb5/crypto.c | 7 +- source4/heimdal/lib/krb5/get_cred.c | 89 ++++++++++++-- source4/heimdal/lib/krb5/init_creds_pw.c | 28 ++--- source4/heimdal/lib/krb5/krb5-private.h | 8 ++ source4/heimdal/lib/krb5/krb5-protos.h | 53 +++++++- source4/heimdal/lib/krb5/krb5.h | 14 ++- source4/heimdal/lib/krb5/krb5_err.et | 8 +- source4/heimdal/lib/krb5/krbhst.c | 6 +- source4/heimdal/lib/krb5/misc.c | 3 +- source4/heimdal/lib/krb5/pac.c | 4 +- source4/heimdal/lib/krb5/pkinit.c | 203 +++++++++++++++---------------- source4/heimdal/lib/krb5/plugin.c | 3 +- source4/heimdal/lib/krb5/principal.c | 49 +++++++- source4/heimdal/lib/krb5/rd_error.c | 4 +- source4/heimdal/lib/krb5/send_to_kdc.c | 177 ++++++++++++++++++++++++--- 15 files changed, 481 insertions(+), 175 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 93f3e44ba1..12f75d0bcd 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c 20981 2007-06-07 20:05:50Z lha $"); +RCSID("$Id: crypto.c 21130 2007-06-18 20:45:21Z lha $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -3162,8 +3162,9 @@ decrypt_internal_derived(krb5_context context, unsigned long l; checksum_sz = CHECKSUMSIZE(et->keyed_checksum); - if (len < checksum_sz) { - krb5_set_error_string(context, "Encrypted data shorter then checksum"); + if (len < checksum_sz + et->confoundersize) { + krb5_set_error_string(context, "Encrypted data shorter then " + "checksum + confunder"); return KRB5_BAD_MSIZE; } diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 761224b82c..8a0af23e40 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_cred.c 21004 2007-06-08 01:53:10Z lha $"); +RCSID("$Id: get_cred.c 21327 2007-06-26 10:54:15Z lha $"); /* * Take the `body' and encode it into `padata' using the credentials @@ -411,7 +411,6 @@ get_cred_kdc_usage(krb5_context context, krb5_keyblock *subkey = NULL; size_t len; Ticket second_ticket_data; - int send_to_kdc_flags = 0; METHOD_DATA padata; krb5_data_zero(&resp); @@ -511,11 +510,18 @@ get_cred_kdc_usage(krb5_context context, /* * Send and receive */ -again: - ret = krb5_sendto_kdc_flags (context, &enc, - &krbtgt->server->name.name_string.val[1], - &resp, - send_to_kdc_flags); + { + krb5_sendto_ctx stctx; + ret = krb5_sendto_ctx_alloc(context, &stctx); + if (ret) + return ret; + krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL); + + ret = krb5_sendto_context (context, stctx, &enc, + krbtgt->server->name.name_string.val[1], + &resp); + krb5_sendto_ctx_free(context, stctx); + } if(ret) goto out; @@ -550,12 +556,6 @@ again: } else if(krb5_rd_error(context, &resp, &error) == 0) { ret = krb5_error_from_rd_error(context, &error, in_creds); krb5_free_error_contents(context, &error); - - if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG && !(send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG)) { - send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; - krb5_data_free(&resp); - goto again; - } } else if(resp.data && ((char*)resp.data)[0] == 4) { ret = KRB5KRB_AP_ERR_V4_REPLY; krb5_clear_error_string(context); @@ -1191,6 +1191,10 @@ krb5_get_creds(krb5_context context, flags.b.forwardable = 1; if (options & KRB5_GC_NO_TRANSIT_CHECK) flags.b.disable_transited_check = 1; + if (options & KRB5_GC_CONSTRAINED_DELEGATION) { + flags.b.request_anonymous = 1; /* XXX ARGH confusion */ + flags.b.constrained_delegation = 1; + } tgts = NULL; ret = get_cred_from_kdc_flags(context, flags, ccache, @@ -1206,3 +1210,62 @@ krb5_get_creds(krb5_context context, krb5_cc_store_cred(context, ccache, *out_creds); return ret; } + +/* + * + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_renewed_creds(krb5_context context, + krb5_creds *creds, + krb5_const_principal client, + krb5_ccache ccache, + const char *in_tkt_service) +{ + krb5_error_code ret; + krb5_kdc_flags flags; + krb5_creds in, *template; + + memset(&in, 0, sizeof(in)); + + ret = krb5_copy_principal(context, client, &in.client); + if (ret) + return ret; + + if (in_tkt_service) { + ret = krb5_parse_name(context, in_tkt_service, &in.server); + if (ret) { + krb5_free_principal(context, in.client); + return ret; + } + } else { + const char *realm = krb5_principal_get_realm(context, client); + + ret = krb5_make_principal(context, &in.server, realm, KRB5_TGS_NAME, + realm, NULL); + if (ret) { + krb5_free_principal(context, in.client); + return ret; + } + } + + flags.i = 0; + flags.b.renewable = flags.b.renew = 1; + + /* + * Get template from old credential cache for the same entry, if + * this failes, no worries. + */ + ret = krb5_get_credentials(context, KRB5_GC_CACHED, ccache, &in, &template); + if (ret == 0) { + flags.b.forwardable = template->flags.b.forwardable; + flags.b.proxiable = template->flags.b.proxiable; + krb5_free_creds (context, template); + } + + ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &in, &creds); + krb5_free_principal(context, in.client); + krb5_free_principal(context, in.server); + + return ret; +} diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index a58435a9ea..1676da3bd6 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c 20262 2007-02-18 00:33:01Z lha $"); +RCSID("$Id: init_creds_pw.c 21061 2007-06-12 17:56:30Z lha $"); typedef struct krb5_get_init_creds_ctx { KDCOptions flags; @@ -1221,8 +1221,8 @@ init_cred_loop(krb5_context context, krb5_data resp; size_t len; size_t size; - int send_to_kdc_flags = 0; krb5_krbhst_info *hi = NULL; + krb5_sendto_ctx stctx = NULL; memset(&md, 0, sizeof(md)); @@ -1238,6 +1238,11 @@ init_cred_loop(krb5_context context, if (ret) return ret; + ret = krb5_sendto_ctx_alloc(context, &stctx); + if (ret) + goto out; + krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL); + /* Set a new nonce. */ krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce)); ctx->nonce &= 0xffffffff; @@ -1281,10 +1286,9 @@ init_cred_loop(krb5_context context, if(len != ctx->req_buffer.length) krb5_abortx(context, "internal error in ASN.1 encoder"); - ret = krb5_sendto_kdc_flags (context, &ctx->req_buffer, - &creds->client->realm, &resp, - send_to_kdc_flags); - if (ret) + ret = krb5_sendto_context (context, stctx, &ctx->req_buffer, + creds->client->realm, &resp); + if (ret) goto out; memset (&rep, 0, sizeof(rep)); @@ -1329,16 +1333,6 @@ init_cred_loop(krb5_context context, krb5_free_error_contents(context, &error); if (ret) goto out; - } else if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG) { - if (send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG) { - if (ret_as_reply) - rep.error = error; - else - krb5_free_error_contents(context, &error); - goto out; - } - krb5_free_error_contents(context, &error); - send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; } else { _krb5_get_init_creds_opt_set_krb5_error(context, init_cred_opts, @@ -1437,6 +1431,8 @@ init_cred_loop(krb5_context context, } } out: + if (stctx) + krb5_sendto_ctx_free(context, stctx); krb5_data_free(&ctx->req_buffer); free_METHOD_DATA(&md); memset(&md, 0, sizeof(md)); diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index be718f6714..a551c42ecd 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -149,6 +149,14 @@ _krb5_kcm_noop ( krb5_context /*context*/, krb5_ccache /*id*/); +krb5_error_code +_krb5_kdc_retry ( + krb5_context /*context*/, + krb5_sendto_ctx /*ctx*/, + void */*data*/, + const krb5_data */*reply*/, + int */*action*/); + krb5_error_code KRB5_LIB_FUNCTION _krb5_krb_cr_err_reply ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index e852bffeb1..058496434e 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -2243,6 +2243,14 @@ krb5_get_pw_salt ( krb5_const_principal /*principal*/, krb5_salt */*salt*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_renewed_creds ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_const_principal /*client*/, + krb5_ccache /*ccache*/, + const char */*in_tkt_service*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_get_server_rcache ( krb5_context /*context*/, @@ -2868,6 +2876,12 @@ krb5_parse_name_flags ( int /*flags*/, krb5_principal */*principal*/); +krb5_error_code +krb5_parse_nametype ( + krb5_context /*context*/, + const char */*str*/, + int32_t */*nametype*/); + const char* KRB5_LIB_FUNCTION krb5_passwd_result_to_string ( krb5_context /*context*/, @@ -3071,7 +3085,7 @@ krb5_rd_cred2 ( krb5_error_code KRB5_LIB_FUNCTION krb5_rd_error ( krb5_context /*context*/, - krb5_data */*msg*/, + const krb5_data */*msg*/, KRB_ERROR */*result*/); krb5_error_code KRB5_LIB_FUNCTION @@ -3346,6 +3360,43 @@ krb5_sendto ( krb5_krbhst_handle /*handle*/, krb5_data */*receive*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_context ( + krb5_context /*context*/, + krb5_sendto_ctx /*ctx*/, + const krb5_data */*send_data*/, + const krb5_realm /*realm*/, + krb5_data */*receive*/); + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_add_flags ( + krb5_sendto_ctx /*ctx*/, + int /*flags*/); + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_ctx_alloc ( + krb5_context /*context*/, + krb5_sendto_ctx */*ctx*/); + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_free ( + krb5_context /*context*/, + krb5_sendto_ctx /*ctx*/); + +int KRB5_LIB_FUNCTION +krb5_sendto_ctx_get_flags (krb5_sendto_ctx /*ctx*/); + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_set_func ( + krb5_sendto_ctx /*ctx*/, + krb5_sendto_ctx_func /*func*/, + void */*data*/); + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_set_type ( + krb5_sendto_ctx /*ctx*/, + int /*type*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_sendto_kdc ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index eefda81ca9..345fe70764 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h 20245 2007-02-17 00:09:57Z lha $ */ +/* $Id: krb5.h 21252 2007-06-21 04:18:28Z lha $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -361,6 +361,7 @@ typedef union { #define KRB5_GC_NO_STORE (1U << 3) #define KRB5_GC_FORWARDABLE (1U << 4) #define KRB5_GC_NO_TRANSIT_CHECK (1U << 5) +#define KRB5_GC_CONSTRAINED_DELEGATION (1U << 6) /* constants for compare_creds (and cc_retrieve_cred) */ #define KRB5_TC_DONT_MATCH_REALM (1U << 31) @@ -753,9 +754,18 @@ enum { /* flags for krb5_unparse_name_flags */ enum { KRB5_PRINCIPAL_UNPARSE_SHORT = 1, - KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2 + KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2, + KRB5_PRINCIPAL_UNPARSE_DISPLAY = 4 }; +typedef struct krb5_sendto_ctx *krb5_sendto_ctx; + +#define KRB5_SENDTO_DONE 0 +#define KRB5_SENDTO_RESTART 1 +#define KRB5_SENDTO_CONTINUE 2 + +typedef krb5_error_code (*krb5_sendto_ctx_func)(krb5_context, krb5_sendto_ctx, void *, const krb5_data *, int *); + struct credentials; /* this is to keep the compiler happy */ struct getargs; struct sockaddr; diff --git a/source4/heimdal/lib/krb5/krb5_err.et b/source4/heimdal/lib/krb5/krb5_err.et index 785c258ee0..6714401e45 100644 --- a/source4/heimdal/lib/krb5/krb5_err.et +++ b/source4/heimdal/lib/krb5/krb5_err.et @@ -3,7 +3,7 @@ # # This might look like a com_err file, but is not # -id "$Id: krb5_err.et 20760 2007-06-01 03:24:49Z lha $" +id "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $" error_table krb5 @@ -35,8 +35,10 @@ error_code KEY_EXPIRED, "Password has expired" error_code PREAUTH_FAILED, "Preauthentication failed" error_code PREAUTH_REQUIRED, "Additional pre-authentication required" error_code SERVER_NOMATCH, "Requested server and ticket don't match" +error_code KDC_ERR_MUST_USE_USER2USER, "Server principal valid for user2user only" +error_code PATH_NOT_ACCEPTED, "KDC Policy rejects transited path" +error_code SVC_UNAVAILABLE, "A service is not available" -# 27-30 are reserved index 31 prefix KRB5KRB_AP error_code ERR_BAD_INTEGRITY, "Decrypt integrity check failed" @@ -108,7 +110,7 @@ error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not suppo index 128 prefix -error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 20760 2007-06-01 03:24:49Z lha $" +error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $" error_code KRB5_LIBOS_BADLOCKFLAG, "Invalid flag for file lock mode" error_code KRB5_LIBOS_CANTREADPWD, "Cannot read password" diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index 51bf934bfd..69b52dd808 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -35,7 +35,7 @@ #include #include "locate_plugin.h" -RCSID("$Id: krbhst.c 19198 2006-11-30 17:23:08Z lha $"); +RCSID("$Id: krbhst.c 21131 2007-06-18 20:48:09Z lha $"); static int string_to_proto(const char *string) @@ -501,10 +501,8 @@ add_locate(void *ctx, int type, struct sockaddr *addr) hostlen = strlen(host); hi = calloc(1, sizeof(*hi) + hostlen); - if(hi == NULL) { - free(host); + if(hi == NULL) return ENOMEM; - } hi->proto = krbhst_get_default_proto(kd); hi->port = hi->def_port = socket_get_port(addr); diff --git a/source4/heimdal/lib/krb5/misc.c b/source4/heimdal/lib/krb5/misc.c index 0d410b57d2..8050bdb9b4 100644 --- a/source4/heimdal/lib/krb5/misc.c +++ b/source4/heimdal/lib/krb5/misc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: misc.c 17616 2006-06-06 14:57:47Z lha $"); +RCSID("$Id: misc.c 21174 2007-06-19 10:10:58Z lha $"); krb5_error_code KRB5_LIB_FUNCTION _krb5_s4u2self_to_checksumdata(krb5_context context, @@ -51,6 +51,7 @@ _krb5_s4u2self_to_checksumdata(krb5_context context, krb5_clear_error_string(context); return ENOMEM; } + krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); ret = krb5_store_int32(sp, self->name.name_type); if (ret) goto out; diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 55d4f5ff56..f7a5e83ea3 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pac.c 20845 2007-06-03 14:31:16Z lha $"); +RCSID("$Id: pac.c 21149 2007-06-18 21:50:22Z lha $"); struct PAC_INFO_BUFFER { uint32_t type; @@ -409,6 +409,8 @@ verify_checksum(krb5_context context, krb5_error_code ret; Checksum cksum; + memset(&cksum, 0, sizeof(cksum)); + sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo, sig->buffersize); if (sp == NULL) { diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index dd82842084..105cab554d 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan + * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c 21004 2007-06-08 01:53:10Z lha $"); +RCSID("$Id: pkinit.c 21321 2007-06-26 05:21:56Z lha $"); struct krb5_dh_moduli { char *name; @@ -554,18 +554,13 @@ pk_mk_padata(krb5_context context, if (ret) goto out; - ret = _krb5_pk_mk_ContentInfo(context, &sd_buf, oid_id_pkcs7_signedData(), - &content_info); + ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &sd_buf, &buf); krb5_data_free(&sd_buf); - if (ret) - goto out; - - ASN1_MALLOC_ENCODE(ContentInfo, buf.data, buf.length, - &content_info, &size, ret); - if (ret) + if (ret) { + krb5_set_error_string(context, + "ContentInfo wrapping of signedData failed"); goto out; - if (buf.length != size) - krb5_abortx(context, "Internal ASN1 encoder error"); + } if (ctx->type == COMPAT_WIN2K) { PA_PK_AS_REQ_Win2k winreq; @@ -794,6 +789,7 @@ get_reply_key_win(krb5_context context, if (ret) { krb5_set_error_string(context, "PKINIT failed copying reply key"); free(*key); + *key = NULL; } return ret; @@ -856,6 +852,7 @@ get_reply_key(krb5_context context, if (ret) { krb5_set_error_string(context, "PKINIT failed copying reply key"); free(*key); + *key = NULL; } return ret; @@ -929,6 +926,7 @@ pk_verify_host(krb5_context context, if (hi) { ret = hx509_verify_hostname(ctx->id->hx509ctx, host->cert, ctx->require_hostname_match, + HX509_HN_HOSTNAME, hi->hostname, hi->ai->ai_addr, hi->ai->ai_addrlen); @@ -942,7 +940,8 @@ pk_verify_host(krb5_context context, static krb5_error_code pk_rd_pa_reply_enckey(krb5_context context, int type, - const ContentInfo *rep, + const heim_octet_string *indata, + const heim_oid *dataType, const char *realm, krb5_pk_init_ctx ctx, krb5_enctype etype, @@ -954,27 +953,19 @@ pk_rd_pa_reply_enckey(krb5_context context, { krb5_error_code ret; struct krb5_pk_cert *host = NULL; - size_t size; - int length; - void *p; krb5_data content; heim_oid contentType = { 0, NULL }; - if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) { + if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), dataType)) { krb5_set_error_string(context, "PKINIT: Invalid content type"); return EINVAL; } - if (rep->content == NULL) { - krb5_set_error_string(context, "PKINIT: No content in reply"); - return EINVAL; - } - ret = hx509_cms_unenvelope(ctx->id->hx509ctx, ctx->id->certs, HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT, - rep->content->data, - rep->content->length, + indata->data, + indata->length, NULL, &contentType, &content); @@ -983,41 +974,52 @@ pk_rd_pa_reply_enckey(krb5_context context, "Failed to unenvelope CMS data in PK-INIT reply"); return ret; } + der_free_oid(&contentType); + +#if 0 /* windows LH with interesting CMS packets, leaks memory */ + { + size_t ph = 1 + der_length_len (length); + unsigned char *ptr = malloc(length + ph); + size_t l; - p = content.data; - length = content.length; + memcpy(ptr + ph, p, length); + + ret = der_put_length_and_tag (ptr + ph - 1, ph, length, + ASN1_C_UNIV, CONS, UT_Sequence, &l); + if (ret) + return ret; + ptr += ph - l; + length += l; + p = ptr; + } +#endif /* win2k uses ContentInfo */ if (type == COMPAT_WIN2K) { - ContentInfo ci; + heim_oid type; + heim_octet_string out; - ret = decode_ContentInfo(p, length, &ci, &size); - if (ret) { - krb5_set_error_string(context, - "PKINIT: failed decoding ContentInfo: %d", - ret); - goto out; - } - - if (der_heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) { + ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL); + if (der_heim_oid_cmp(&type, oid_id_pkcs7_signedData())) { ret = EINVAL; /* XXX */ krb5_set_error_string(context, "PKINIT: Invalid content type"); + der_free_oid(&type); + der_free_octet_string(&out); goto out; } - if (ci.content == NULL) { - ret = EINVAL; /* XXX */ - krb5_set_error_string(context, "PKINIT: Invalid content type"); + der_free_oid(&type); + krb5_data_free(&content); + ret = krb5_data_copy(&content, out.data, out.length); + der_free_octet_string(&out); + if (ret) { + krb5_set_error_string(context, "PKINIT: out of memory"); goto out; } - krb5_data_free(&content); - content = *ci.content; - p = ci.content->data; - length = ci.content->length; } ret = _krb5_pk_verify_sign(context, - p, - length, + content.data, + content.length, ctx->id, &contentType, &content, @@ -1073,7 +1075,8 @@ pk_rd_pa_reply_enckey(krb5_context context, static krb5_error_code pk_rd_pa_reply_dh(krb5_context context, - const ContentInfo *rep, + const heim_octet_string *indata, + const heim_oid *dataType, const char *realm, krb5_pk_init_ctx ctx, krb5_enctype etype, @@ -1097,19 +1100,14 @@ pk_rd_pa_reply_dh(krb5_context context, krb5_data_zero(&content); memset(&kdc_dh_info, 0, sizeof(kdc_dh_info)); - if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) { + if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), dataType)) { krb5_set_error_string(context, "PKINIT: Invalid content type"); return EINVAL; } - if (rep->content == NULL) { - krb5_set_error_string(context, "PKINIT: No content in reply"); - return EINVAL; - } - ret = _krb5_pk_verify_sign(context, - rep->content->data, - rep->content->length, + indata->data, + indata->length, ctx->id, &contentType, &content, @@ -1261,20 +1259,19 @@ _krb5_pk_rd_pa_reply(krb5_context context, { krb5_pk_init_ctx ctx = c; krb5_error_code ret; - ContentInfo ci; size_t size; /* Check for IETF PK-INIT first */ if (ctx->type == COMPAT_IETF) { PA_PK_AS_REP rep; + heim_octet_string os, data; + heim_oid oid; if (pa->padata_type != KRB5_PADATA_PK_AS_REP) { krb5_set_error_string(context, "PKINIT: wrong padata recv"); return EINVAL; } - memset(&rep, 0, sizeof(rep)); - ret = decode_PA_PK_AS_REP(pa->padata_value.data, pa->padata_value.length, &rep, @@ -1286,49 +1283,42 @@ _krb5_pk_rd_pa_reply(krb5_context context, switch (rep.element) { case choice_PA_PK_AS_REP_dhInfo: - ret = decode_ContentInfo(rep.u.dhInfo.dhSignedData.data, - rep.u.dhInfo.dhSignedData.length, - &ci, - &size); - if (ret) { - krb5_set_error_string(context, - "PKINIT: decoding failed DH " - "ContentInfo: %d", ret); - - free_PA_PK_AS_REP(&rep); - break; - } - ret = pk_rd_pa_reply_dh(context, &ci, realm, ctx, etype, hi, - ctx->clientDHNonce, - rep.u.dhInfo.serverDHNonce, - nonce, pa, key); - free_ContentInfo(&ci); - free_PA_PK_AS_REP(&rep); - + os = rep.u.dhInfo.dhSignedData; break; case choice_PA_PK_AS_REP_encKeyPack: - ret = decode_ContentInfo(rep.u.encKeyPack.data, - rep.u.encKeyPack.length, - &ci, - &size); - free_PA_PK_AS_REP(&rep); - if (ret) { - krb5_set_error_string(context, - "PKINIT: -25 decoding failed " - "ContentInfo: %d", ret); - break; - } - ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &ci, realm, ctx, - etype, hi, nonce, req_buffer, pa, key); - free_ContentInfo(&ci); - return ret; + os = rep.u.encKeyPack; + break; default: free_PA_PK_AS_REP(&rep); krb5_set_error_string(context, "PKINIT: -27 reply " "invalid content type"); - ret = EINVAL; + return EINVAL; + } + + ret = hx509_cms_unwrap_ContentInfo(&os, &oid, &data, NULL); + if (ret) { + free_PA_PK_AS_REP(&rep); + krb5_set_error_string(context, "PKINIT: failed to unwrap CI"); + return ret; + } + + switch (rep.element) { + case choice_PA_PK_AS_REP_dhInfo: + ret = pk_rd_pa_reply_dh(context, &data, &oid, realm, ctx, etype, hi, + ctx->clientDHNonce, + rep.u.dhInfo.serverDHNonce, + nonce, pa, key); break; + case choice_PA_PK_AS_REP_encKeyPack: + ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &data, &oid, realm, + ctx, etype, hi, nonce, req_buffer, pa, key); + break; + default: + krb5_abortx(context, "pk-init as-rep case not possible to happen"); } + der_free_octet_string(&data); + der_free_oid(&oid); + free_PA_PK_AS_REP(&rep); } else if (ctx->type == COMPAT_WIN2K) { PA_PK_AS_REP_Win2k w2krep; @@ -1357,23 +1347,25 @@ _krb5_pk_rd_pa_reply(krb5_context context, krb5_clear_error_string(context); switch (w2krep.element) { - case choice_PA_PK_AS_REP_Win2k_encKeyPack: - ret = decode_ContentInfo(w2krep.u.encKeyPack.data, - w2krep.u.encKeyPack.length, - &ci, - &size); + case choice_PA_PK_AS_REP_Win2k_encKeyPack: { + heim_octet_string data; + heim_oid oid; + + ret = hx509_cms_unwrap_ContentInfo(&w2krep.u.encKeyPack, + &oid, &data, NULL); free_PA_PK_AS_REP_Win2k(&w2krep); if (ret) { - krb5_set_error_string(context, - "PKINIT: decoding failed " - "ContentInfo: %d", - ret); + krb5_set_error_string(context, "PKINIT: failed to unwrap CI"); return ret; } - ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, realm, ctx, - etype, hi, nonce, req_buffer, pa, key); - free_ContentInfo(&ci); + + ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &data, &oid, realm, + ctx, etype, hi, nonce, req_buffer, pa, key); + der_free_octet_string(&data); + der_free_oid(&oid); + break; + } default: free_PA_PK_AS_REP_Win2k(&w2krep); krb5_set_error_string(context, "PKINIT: win2k reply invalid " @@ -1473,8 +1465,7 @@ _krb5_pk_load_id(krb5_context context, id = calloc(1, sizeof(*id)); if (id == NULL) { krb5_set_error_string(context, "malloc: out of memory"); - ret = ENOMEM; - goto out; + return ENOMEM; } ret = hx509_context_init(&id->hx509ctx); diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c index f19464bf3c..68317a12c0 100644 --- a/source4/heimdal/lib/krb5/plugin.c +++ b/source4/heimdal/lib/krb5/plugin.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: plugin.c 19789 2007-01-09 17:46:01Z lha $"); +RCSID("$Id: plugin.c 21134 2007-06-18 21:02:23Z lha $"); #ifdef HAVE_DLFCN_H #include #endif @@ -96,6 +96,7 @@ loadlib(krb5_context context, (*e)->dsohandle = dlopen(lib, RTLD_LAZY); if ((*e)->dsohandle == NULL) { free(*e); + *e = NULL; krb5_set_error_string(context, "Failed to load %s: %s", lib, dlerror()); return ENOMEM; diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index ef3f5412db..c1a29d266b 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -41,7 +41,7 @@ #include #include "resolve.h" -RCSID("$Id: principal.c 20223 2007-02-15 04:17:04Z lha $"); +RCSID("$Id: principal.c 21285 2007-06-25 12:30:55Z lha $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -281,15 +281,19 @@ krb5_parse_name(krb5_context context, static const char quotable_chars[] = " \n\t\b\\/@"; static const char replace_chars[] = " ntb\\/@"; +static const char nq_chars[] = " \\/@"; #define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0); static size_t -quote_string(const char *s, char *out, size_t idx, size_t len) +quote_string(const char *s, char *out, size_t idx, size_t len, int display) { const char *p, *q; for(p = s; *p && idx < len; p++){ - if((q = strchr(quotable_chars, *p))){ + q = strchr(quotable_chars, *p); + if (q && display) { + add_char(out, idx, len, replace_chars[q - quotable_chars]); + } else if (q) { add_char(out, idx, len, '\\'); add_char(out, idx, len, replace_chars[q - quotable_chars]); }else @@ -312,6 +316,7 @@ unparse_name_fixed(krb5_context context, int i; int short_form = (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) != 0; int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0; + int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0; if (!no_realm && princ_realm(principal) == NULL) { krb5_set_error_string(context, "Realm missing from principal, " @@ -322,7 +327,7 @@ unparse_name_fixed(krb5_context context, for(i = 0; i < princ_num_comp(principal); i++){ if(i) add_char(name, idx, len, '/'); - idx = quote_string(princ_ncomp(principal, i), name, idx, len); + idx = quote_string(princ_ncomp(principal, i), name, idx, len, display); if(idx == len) { krb5_set_error_string(context, "Out of space printing principal"); return ERANGE; @@ -341,7 +346,7 @@ unparse_name_fixed(krb5_context context, } if(!short_form && !no_realm) { add_char(name, idx, len, '@'); - idx = quote_string(princ_realm(principal), name, idx, len); + idx = quote_string(princ_realm(principal), name, idx, len, display); if(idx == len) { krb5_set_error_string(context, "Out of space printing realm of principal"); @@ -1213,3 +1218,37 @@ krb5_sname_to_principal (krb5_context context, krb5_free_host_realm(context, realms); return ret; } + +static const struct { + const char *type; + int32_t value; +} nametypes[] = { + { "UNKNOWN", KRB5_NT_UNKNOWN }, + { "PRINCIPAL", KRB5_NT_PRINCIPAL }, + { "SRV_INST", KRB5_NT_SRV_INST }, + { "SRV_HST", KRB5_NT_SRV_HST }, + { "SRV_XHST", KRB5_NT_SRV_XHST }, + { "UID", KRB5_NT_UID }, + { "X500_PRINCIPAL", KRB5_NT_X500_PRINCIPAL }, + { "SMTP_NAME", KRB5_NT_SMTP_NAME }, + { "ENTERPRISE_PRINCIPAL", KRB5_NT_ENTERPRISE_PRINCIPAL }, + { "ENT_PRINCIPAL_AND_ID", KRB5_NT_ENT_PRINCIPAL_AND_ID }, + { "MS_PRINCIPAL", KRB5_NT_MS_PRINCIPAL }, + { "MS_PRINCIPAL_AND_ID", KRB5_NT_MS_PRINCIPAL_AND_ID }, + { NULL } +}; + +krb5_error_code +krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype) +{ + size_t i; + + for(i = 0; nametypes[i].type; i++) { + if (strcasecmp(nametypes[i].type, str) == 0) { + *nametype = nametypes[i].value; + return 0; + } + } + krb5_set_error_string(context, "Failed to find name type %s", str); + return KRB5_PARSE_MALFORMED; +} diff --git a/source4/heimdal/lib/krb5/rd_error.c b/source4/heimdal/lib/krb5/rd_error.c index 89615ee8ac..e7646467af 100644 --- a/source4/heimdal/lib/krb5/rd_error.c +++ b/source4/heimdal/lib/krb5/rd_error.c @@ -33,11 +33,11 @@ #include "krb5_locl.h" -RCSID("$Id: rd_error.c 20304 2007-04-11 11:15:05Z lha $"); +RCSID("$Id: rd_error.c 21057 2007-06-12 17:22:31Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_error(krb5_context context, - krb5_data *msg, + const krb5_data *msg, KRB_ERROR *result) { diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index 6c70244327..c1a4df2b01 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: send_to_kdc.c 19973 2007-01-17 17:19:52Z lha $"); +RCSID("$Id: send_to_kdc.c 21062 2007-06-12 17:58:57Z lha $"); struct send_to_kdc { krb5_send_to_kdc_func func; @@ -413,26 +413,16 @@ krb5_sendto_kdc_flags(krb5_context context, int flags) { krb5_error_code ret; - krb5_krbhst_handle handle; - int type; - - if ((flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc) - type = KRB5_KRBHST_ADMIN; - else - type = KRB5_KRBHST_KDC; + krb5_sendto_ctx ctx; - if (send_data->length > context->large_msg_size) - flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; - - ret = krb5_krbhst_init_flags(context, *realm, type, flags, &handle); + ret = krb5_sendto_ctx_alloc(context, &ctx); if (ret) return ret; + krb5_sendto_ctx_add_flags(ctx, flags); + krb5_sendto_ctx_set_func(ctx, _krb5_kdc_retry, NULL); - ret = krb5_sendto(context, send_data, handle, receive); - krb5_krbhst_free(context, handle); - if (ret == KRB5_KDC_UNREACH) - krb5_set_error_string(context, - "unable to reach any KDC in realm %s", *realm); + ret = krb5_sendto_context(context, ctx, send_data, *realm, receive); + krb5_sendto_ctx_free(context, ctx); return ret; } @@ -458,4 +448,157 @@ krb5_set_send_to_kdc_func(krb5_context context, return 0; } +struct krb5_sendto_ctx { + int flags; + int type; + krb5_sendto_ctx_func func; + void *data; +}; +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_ctx_alloc(krb5_context context, krb5_sendto_ctx *ctx) +{ + *ctx = calloc(1, sizeof(**ctx)); + if (*ctx == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_add_flags(krb5_sendto_ctx ctx, int flags) +{ + ctx->flags |= flags; +} + +int KRB5_LIB_FUNCTION +krb5_sendto_ctx_get_flags(krb5_sendto_ctx ctx) +{ + return ctx->flags; +} + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_set_type(krb5_sendto_ctx ctx, int type) +{ + ctx->type = type; +} + + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_set_func(krb5_sendto_ctx ctx, + krb5_sendto_ctx_func func, + void *data) +{ + ctx->func = func; + ctx->data = data; +} + +void KRB5_LIB_FUNCTION +krb5_sendto_ctx_free(krb5_context context, krb5_sendto_ctx ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + free(ctx); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_sendto_context(krb5_context context, + krb5_sendto_ctx ctx, + const krb5_data *send_data, + const krb5_realm realm, + krb5_data *receive) +{ + krb5_error_code ret; + krb5_krbhst_handle handle = NULL; + int type, freectx = 0; + int action; + + krb5_data_zero(receive); + + if (ctx == NULL) { + freectx = 1; + ret = krb5_sendto_ctx_alloc(context, &ctx); + if (ret) + return ret; + } + + type = ctx->type; + if (type == 0) { + if ((ctx->flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc) + type = KRB5_KRBHST_ADMIN; + else + type = KRB5_KRBHST_KDC; + } + + if (send_data->length > context->large_msg_size) + ctx->flags |= KRB5_KRBHST_FLAGS_LARGE_MSG; + + /* loop until we get back a appropriate response */ + + do { + action = KRB5_SENDTO_DONE; + + krb5_data_free(receive); + + if (handle == NULL) { + ret = krb5_krbhst_init_flags(context, realm, type, + ctx->flags, &handle); + if (ret) { + if (freectx) + krb5_sendto_ctx_free(context, ctx); + return ret; + } + } + + ret = krb5_sendto(context, send_data, handle, receive); + if (ret) + break; + if (ctx->func) { + ret = (*ctx->func)(context, ctx, ctx->data, receive, &action); + if (ret) + break; + } + if (action != KRB5_SENDTO_CONTINUE) { + krb5_krbhst_free(context, handle); + handle = NULL; + } + } while (action != KRB5_SENDTO_DONE); + if (handle) + krb5_krbhst_free(context, handle); + if (ret == KRB5_KDC_UNREACH) + krb5_set_error_string(context, + "unable to reach any KDC in realm %s", realm); + if (ret) + krb5_data_free(receive); + if (freectx) + krb5_sendto_ctx_free(context, ctx); + return ret; +} + +krb5_error_code +_krb5_kdc_retry(krb5_context context, krb5_sendto_ctx ctx, void *data, + const krb5_data *reply, int *action) +{ + krb5_error_code ret; + KRB_ERROR error; + + if(krb5_rd_error(context, reply, &error)) + return 0; + + ret = krb5_error_from_rd_error(context, &error, NULL); + krb5_free_error_contents(context, &error); + + switch(ret) { + case KRB5KRB_ERR_RESPONSE_TOO_BIG: { + if (krb5_sendto_ctx_get_flags(ctx) & KRB5_KRBHST_FLAGS_LARGE_MSG) + break; + krb5_sendto_ctx_add_flags(ctx, KRB5_KRBHST_FLAGS_LARGE_MSG); + *action = KRB5_SENDTO_RESTART; + break; + } + case KRB5KDC_ERR_SVC_UNAVAILABLE: + *action = KRB5_SENDTO_CONTINUE; + break; + } + return 0; +} -- cgit From b39330c4873d4c3923a577e89690fc0e43b0c61a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 22 Aug 2007 06:46:34 +0000 Subject: r24614: Merge with current lorikeet-heimdal. This brings us one step closer to an alpha release. Andrew Bartlett (This used to be commit 30e02747d511630659c59eafec8d28f58605943b) --- source4/heimdal/lib/krb5/cache.c | 39 +++++++++++++++++-- source4/heimdal/lib/krb5/changepw.c | 6 ++- source4/heimdal/lib/krb5/get_cred.c | 12 ++++-- source4/heimdal/lib/krb5/init_creds.c | 7 ++-- source4/heimdal/lib/krb5/init_creds_pw.c | 4 +- source4/heimdal/lib/krb5/krb5-private.h | 4 +- source4/heimdal/lib/krb5/krb5-protos.h | 8 ---- source4/heimdal/lib/krb5/krb5-v4compat.h | 50 ++----------------------- source4/heimdal/lib/krb5/krb5.h | 13 ++++--- source4/heimdal/lib/krb5/krb5_locl.h | 10 +---- source4/heimdal/lib/krb5/krb_err.et | 63 +++++++++++++++++++++++++++++++ source4/heimdal/lib/krb5/krbhst.c | 6 ++- source4/heimdal/lib/krb5/pkinit.c | 52 ++++++++++++++++++++++---- source4/heimdal/lib/krb5/plugin.c | 16 +++++--- source4/heimdal/lib/krb5/rd_priv.c | 16 +++++--- source4/heimdal/lib/krb5/v4_glue.c | 64 ++++++++++++++++++++------------ 16 files changed, 242 insertions(+), 128 deletions(-) create mode 100644 source4/heimdal/lib/krb5/krb_err.et (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index 5be3935f2b..59aae40d28 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c 20503 2007-04-21 22:03:56Z lha $"); +RCSID("$Id: cache.c 21498 2007-07-11 09:41:43Z lha $"); /* * Add a new ccache type with operations `ops', overwriting any @@ -338,6 +338,35 @@ _krb5_expand_default_cc_name(krb5_context context, const char *str, char **res) return 0; } +/* + * Return non-zero if envirnoment that will determine default krb5cc + * name has changed. + */ + +static int +environment_changed(krb5_context context) +{ + const char *e; + + if(issuid()) + return 0; + + e = getenv("KRB5CCNAME"); + if (e == NULL) { + if (context->default_cc_name_env) { + free(context->default_cc_name_env); + context->default_cc_name_env = NULL; + return 1; + } + } else { + if (context->default_cc_name_env == NULL) + return 1; + if (strcmp(e, context->default_cc_name_env) != 0) + return 1; + } + return 0; +} + /* * Set the default cc name for `context' to `name'. */ @@ -353,8 +382,12 @@ krb5_cc_set_default_name(krb5_context context, const char *name) if(!issuid()) { e = getenv("KRB5CCNAME"); - if (e) + if (e) { p = strdup(e); + if (context->default_cc_name_env) + free(context->default_cc_name_env); + context->default_cc_name_env = strdup(e); + } } if (e == NULL) { e = krb5_config_get_string(context, NULL, "libdefaults", @@ -389,7 +422,7 @@ krb5_cc_set_default_name(krb5_context context, const char *name) const char* KRB5_LIB_FUNCTION krb5_cc_default_name(krb5_context context) { - if (context->default_cc_name == NULL) + if (context->default_cc_name == NULL || environment_changed(context)) krb5_cc_set_default_name(context, NULL); return context->default_cc_name; diff --git a/source4/heimdal/lib/krb5/changepw.c b/source4/heimdal/lib/krb5/changepw.c index 3ceb6df89c..703cf43eb6 100644 --- a/source4/heimdal/lib/krb5/changepw.c +++ b/source4/heimdal/lib/krb5/changepw.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: changepw.c 17442 2006-05-05 09:31:15Z lha $"); +RCSID("$Id: changepw.c 21505 2007-07-12 12:28:38Z lha $"); static void str2data (krb5_data *d, @@ -46,10 +46,12 @@ str2data (krb5_data *d, ...) { va_list args; + char *str; va_start(args, fmt); - d->length = vasprintf ((char **)&d->data, fmt, args); + d->length = vasprintf (&str, fmt, args); va_end(args); + d->data = str; } /* diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 8a0af23e40..7c3f128ae5 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_cred.c 21327 2007-06-26 10:54:15Z lha $"); +RCSID("$Id: get_cred.c 21669 2007-07-22 11:29:13Z lha $"); /* * Take the `body' and encode it into `padata' using the credentials @@ -1224,9 +1224,10 @@ krb5_get_renewed_creds(krb5_context context, { krb5_error_code ret; krb5_kdc_flags flags; - krb5_creds in, *template; + krb5_creds in, *template, *out = NULL; memset(&in, 0, sizeof(in)); + memset(creds, 0, sizeof(*creds)); ret = krb5_copy_principal(context, client, &in.client); if (ret) @@ -1263,9 +1264,14 @@ krb5_get_renewed_creds(krb5_context context, krb5_free_creds (context, template); } - ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &in, &creds); + ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &in, &out); krb5_free_principal(context, in.client); krb5_free_principal(context, in.server); + if (ret) + return ret; + + ret = krb5_copy_creds_contents(context, out, creds); + krb5_free_creds(context, out); return ret; } diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index 5bdf23d97f..bd250cef2b 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c 20541 2007-04-23 12:19:14Z lha $"); +RCSID("$Id: init_creds.c 21712 2007-07-27 14:23:41Z lha $"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) @@ -225,9 +225,8 @@ krb5_get_init_creds_opt_set_default_flags(krb5_context context, krb5_get_init_creds_opt_set_renew_life(opt, t); krb5_appdefault_boolean(context, appname, realm, "no-addresses", - FALSE, &b); - if (b) - krb5_get_init_creds_opt_set_addressless (context, opt, TRUE); + KRB5_ADDRESSLESS_DEFAULT, &b); + krb5_get_init_creds_opt_set_addressless (context, opt, b); #if 0 krb5_appdefault_boolean(context, appname, realm, "anonymous", FALSE, &b); diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 1676da3bd6..0043b5ef3c 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c 21061 2007-06-12 17:56:30Z lha $"); +RCSID("$Id: init_creds_pw.c 21428 2007-07-10 12:31:58Z lha $"); typedef struct krb5_get_init_creds_ctx { KDCOptions flags; diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index a551c42ecd..9a84dde61a 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -383,7 +383,7 @@ _krb5_pk_verify_sign ( krb5_error_code _krb5_plugin_find ( krb5_context /*context*/, - enum plugin_type /*type*/, + enum krb5_plugin_type /*type*/, const char */*name*/, struct krb5_plugin **/*list*/); @@ -399,7 +399,7 @@ _krb5_plugin_get_symbol (struct krb5_plugin */*p*/); krb5_error_code _krb5_plugin_register ( krb5_context /*context*/, - enum plugin_type /*type*/, + enum krb5_plugin_type /*type*/, const char */*name*/, void */*symbol*/); diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 058496434e..740b394be8 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -2243,14 +2243,6 @@ krb5_get_pw_salt ( krb5_const_principal /*principal*/, krb5_salt */*salt*/); -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_renewed_creds ( - krb5_context /*context*/, - krb5_creds */*creds*/, - krb5_const_principal /*client*/, - krb5_ccache /*ccache*/, - const char */*in_tkt_service*/); - krb5_error_code KRB5_LIB_FUNCTION krb5_get_server_rcache ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5-v4compat.h b/source4/heimdal/lib/krb5/krb5-v4compat.h index 2ea534cfe3..dfd7e94460 100644 --- a/source4/heimdal/lib/krb5/krb5-v4compat.h +++ b/source4/heimdal/lib/krb5/krb5-v4compat.h @@ -31,11 +31,13 @@ * SUCH DAMAGE. */ -/* $Id: krb5-v4compat.h 17442 2006-05-05 09:31:15Z lha $ */ +/* $Id: krb5-v4compat.h 21575 2007-07-16 07:44:54Z lha $ */ #ifndef __KRB5_V4COMPAT_H__ #define __KRB5_V4COMPAT_H__ +#include "krb_err.h" + /* * This file must only be included with v4 compat glue stuff in * heimdal sources. @@ -57,56 +59,10 @@ #define AUTH_MSG_KDC_RENEW (10<<1) #define AUTH_MSG_DIE (63<<1) -/* values for kerb error codes */ - -#define KERB_ERR_OK 0 -#define KERB_ERR_NAME_EXP 1 -#define KERB_ERR_SERVICE_EXP 2 -#define KERB_ERR_AUTH_EXP 3 -#define KERB_ERR_PKT_VER 4 -#define KERB_ERR_NAME_MAST_KEY_VER 5 -#define KERB_ERR_SERV_MAST_KEY_VER 6 -#define KERB_ERR_BYTE_ORDER 7 -#define KERB_ERR_PRINCIPAL_UNKNOWN 8 -#define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9 -#define KERB_ERR_NULL_KEY 10 -#define KERB_ERR_TIMEOUT 11 - - -/* Error codes returned from the KDC */ -#define KDC_OK 0 /* Request OK */ -#define KDC_NAME_EXP 1 /* Principal expired */ -#define KDC_SERVICE_EXP 2 /* Service expired */ -#define KDC_AUTH_EXP 3 /* Auth expired */ -#define KDC_PKT_VER 4 /* Protocol version unknown */ -#define KDC_P_MKEY_VER 5 /* Wrong master key version */ -#define KDC_S_MKEY_VER 6 /* Wrong master key version */ -#define KDC_BYTE_ORDER 7 /* Byte order unknown */ -#define KDC_PR_UNKNOWN 8 /* Principal unknown */ -#define KDC_PR_N_UNIQUE 9 /* Principal not unique */ -#define KDC_NULL_KEY 10 /* Principal has null key */ -#define KDC_GEN_ERR 20 /* Generic error from KDC */ - /* General definitions */ #define KSUCCESS 0 #define KFAILURE 255 -/* Values returned by rd_ap_req */ -#define RD_AP_OK 0 /* Request authentic */ -#define RD_AP_UNDEC 31 /* Can't decode authenticator */ -#define RD_AP_EXP 32 /* Ticket expired */ -#define RD_AP_NYV 33 /* Ticket not yet valid */ -#define RD_AP_REPEAT 34 /* Repeated request */ -#define RD_AP_NOT_US 35 /* The ticket isn't for us */ -#define RD_AP_INCON 36 /* Request is inconsistent */ -#define RD_AP_TIME 37 /* delta_t too big */ -#define RD_AP_BADD 38 /* Incorrect net address */ -#define RD_AP_VERSION 39 /* protocol version mismatch */ -#define RD_AP_MSG_TYPE 40 /* invalid msg type */ -#define RD_AP_MODIFIED 41 /* message stream modified */ -#define RD_AP_ORDER 42 /* message out of order */ -#define RD_AP_UNAUTHOR 43 /* unauthorized request */ - /* */ #define MAX_KTXT_LEN 1250 diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 345fe70764..4f9a63bf05 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h 21252 2007-06-21 04:18:28Z lha $ */ +/* $Id: krb5.h 21551 2007-07-15 09:03:39Z lha $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -436,11 +436,6 @@ typedef struct krb5_config_binding krb5_config_binding; typedef krb5_config_binding krb5_config_section; -enum { - KRB5_PKINIT_WIN2K = 1, /* wire compatible with Windows 2k */ - KRB5_PKINIT_PACKET_CABLE = 2 /* use packet cable standard */ -}; - typedef struct krb5_ticket { EncTicketPart ticket; krb5_principal client; @@ -766,6 +761,12 @@ typedef struct krb5_sendto_ctx *krb5_sendto_ctx; typedef krb5_error_code (*krb5_sendto_ctx_func)(krb5_context, krb5_sendto_ctx, void *, const krb5_data *, int *); +struct krb5_plugin; +enum krb5_plugin_type { + PLUGIN_TYPE_DATA = 1, + PLUGIN_TYPE_FUNC +}; + struct credentials; /* this is to keep the compiler happy */ struct getargs; struct sockaddr; diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 87169fc430..b41e6e1182 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_locl.h 20261 2007-02-18 00:32:22Z lha $ */ +/* $Id: krb5_locl.h 21552 2007-07-15 09:04:00Z lha $ */ #ifndef __KRB5_LOCL_H__ #define __KRB5_LOCL_H__ @@ -148,12 +148,6 @@ struct krb5_dh_moduli; /* v4 glue */ struct _krb5_krb_auth_data; -struct krb5_plugin; -enum plugin_type { - PLUGIN_TYPE_DATA = 1, - PLUGIN_TYPE_FUNC -}; - #include #include @@ -236,7 +230,7 @@ typedef struct krb5_context_data { char error_buf[256]; krb5_addresses *ignore_addresses; char *default_cc_name; - int pkinit_flags; + char *default_cc_name_env; void *mutex; /* protects error_string/error_buf */ int large_msg_size; int dns_canonicalize_hostname; diff --git a/source4/heimdal/lib/krb5/krb_err.et b/source4/heimdal/lib/krb5/krb_err.et new file mode 100644 index 0000000000..f7dbb6ce7a --- /dev/null +++ b/source4/heimdal/lib/krb5/krb_err.et @@ -0,0 +1,63 @@ +# +# Error messages for the krb4 library +# +# This might look like a com_err file, but is not +# +id "$Id: krb_err.et,v 1.7 1998/03/29 14:19:52 bg Exp $" + +error_table krb + +prefix KRB4ET +ec KSUCCESS, "Kerberos 4 successful" +ec KDC_NAME_EXP, "Kerberos 4 principal expired" +ec KDC_SERVICE_EXP, "Kerberos 4 service expired" +ec KDC_AUTH_EXP, "Kerberos 4 auth expired" +ec KDC_PKT_VER, "Incorrect Kerberos 4 master key version" +ec KDC_P_MKEY_VER, "Incorrect Kerberos 4 master key version" +ec KDC_S_MKEY_VER, "Incorrect Kerberos 4 master key version" +ec KDC_BYTE_ORDER, "Kerberos 4 byte order unknown" +ec KDC_PR_UNKNOWN, "Kerberos 4 principal unknown" +ec KDC_PR_N_UNIQUE, "Kerberos 4 principal not unique" +ec KDC_NULL_KEY, "Kerberos 4 principal has null key" +index 20 +ec KDC_GEN_ERR, "Generic error from KDC (Kerberos 4)" +ec GC_TKFIL, "Can't read Kerberos 4 ticket file" +ec GC_NOTKT, "Can't find Kerberos 4 ticket or TGT" +index 26 +ec MK_AP_TGTEXP, "Kerberos 4 TGT Expired" +index 31 +ec RD_AP_UNDEC, "Kerberos 4: Can't decode authenticator" +ec RD_AP_EXP, "Kerberos 4 ticket expired" +ec RD_AP_NYV, "Kerberos 4 ticket not yet valid" +ec RD_AP_REPEAT, "Kerberos 4: Repeated request" +ec RD_AP_NOT_US, "The Kerberos 4 ticket isn't for us" +ec RD_AP_INCON, "Kerberos 4 request inconsistent" +ec RD_AP_TIME, "Kerberos 4: delta_t too big" +ec RD_AP_BADD, "Kerberos 4: incorrect net address" +ec RD_AP_VERSION, "Kerberos protocol not version 4" +ec RD_AP_MSG_TYPE, "Kerberos 4: invalid msg type" +ec RD_AP_MODIFIED, "Kerberos 4: message stream modified" +ec RD_AP_ORDER, "Kerberos 4: message out of order" +ec RD_AP_UNAUTHOR, "Kerberos 4: unauthorized request" +index 51 +ec GT_PW_NULL, "Kerberos 4: current PW is null" +ec GT_PW_BADPW, "Kerberos 4: Incorrect current password" +ec GT_PW_PROT, "Kerberos 4 protocol error" +ec GT_PW_KDCERR, "Error returned by KDC (Kerberos 4)" +ec GT_PW_NULLTKT, "Null Kerberos 4 ticket returned by KDC" +ec SKDC_RETRY, "Kerberos 4: Retry count exceeded" +ec SKDC_CANT, "Kerberos 4: Can't send request" +index 61 +ec INTK_W_NOTALL, "Kerberos 4: not all tickets returned" +ec INTK_BADPW, "Kerberos 4: incorrect password" +ec INTK_PROT, "Kerberos 4: Protocol Error" +index 70 +ec INTK_ERR, "Other error in Kerberos 4" +ec AD_NOTGT, "Don't have Kerberos 4 ticket-granting ticket" +index 76 +ec NO_TKT_FIL, "No Kerberos 4 ticket file found" +ec TKT_FIL_ACC, "Couldn't access Kerberos 4 ticket file" +ec TKT_FIL_LCK, "Couldn't lock Kerberos 4 ticket file" +ec TKT_FIL_FMT, "Bad Kerberos 4 ticket file format" +ec TKT_FIL_INI, "Kerberos 4: tf_init not called first" +ec KNAME_FMT, "Bad Kerberos 4 name format" diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index 69b52dd808..094fd4f9c6 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -35,7 +35,7 @@ #include #include "locate_plugin.h" -RCSID("$Id: krbhst.c 21131 2007-06-18 20:48:09Z lha $"); +RCSID("$Id: krbhst.c 21457 2007-07-10 12:53:25Z lha $"); static int string_to_proto(const char *string) @@ -919,8 +919,10 @@ gethostlist(krb5_context context, const char *realm, while(krb5_krbhst_next(context, handle, &hostinfo) == 0) nhost++; - if(nhost == 0) + if(nhost == 0) { + krb5_set_error_string(context, "No KDC found for realm %s", realm); return KRB5_KDC_UNREACH; + } *hostlist = calloc(nhost + 1, sizeof(**hostlist)); if(*hostlist == NULL) { krb5_krbhst_free(context, handle); diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 105cab554d..c8587770f4 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c 21321 2007-06-26 05:21:56Z lha $"); +RCSID("$Id: pkinit.c 21684 2007-07-23 23:09:10Z lha $"); struct krb5_dh_moduli { char *name; @@ -645,8 +645,6 @@ _krb5_pk_mk_padata(krb5_context context, req_body->realm, "pkinit_win2k", NULL); - if (context->pkinit_flags & KRB5_PKINIT_WIN2K) - win2k_compat = 1; if (win2k_compat) { ctx->require_binding = @@ -1721,7 +1719,7 @@ _krb5_free_moduli(struct krb5_dh_moduli **moduli) free(moduli); } -static const char *default_moduli = +static const char *default_moduli_RFC2412_MODP_group2 = /* name */ "RFC2412-MODP-group2 " /* bits */ @@ -1743,6 +1741,37 @@ static const char *default_moduli = "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F67329C0" "FFFFFFFF" "FFFFFFFF"; +static const char *default_moduli_rfc3526_MODP_group14 = + /* name */ + "rfc3526-MODP-group14 " + /* bits */ + "1760 " + /* p */ + "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" "C4C6628B" "80DC1CD1" + "29024E08" "8A67CC74" "020BBEA6" "3B139B22" "514A0879" "8E3404DD" + "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" "4FE1356D" "6D51C245" + "E485B576" "625E7EC6" "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" + "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" "49286651" "ECE45B3D" + "C2007CB8" "A163BF05" "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" + "83655D23" "DCA3AD96" "1C62F356" "208552BB" "9ED52907" "7096966D" + "670C354E" "4ABC9804" "F1746C08" "CA18217C" "32905E46" "2E36CE3B" + "E39E772C" "180E8603" "9B2783A2" "EC07A28F" "B5C55DF0" "6F4C52C9" + "DE2BCBF6" "95581718" "3995497C" "EA956AE5" "15D22618" "98FA0510" + "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF " + /* g */ + "02 " + /* q */ + "7FFFFFFF" "FFFFFFFF" "E487ED51" "10B4611A" "62633145" "C06E0E68" + "94812704" "4533E63A" "0105DF53" "1D89CD91" "28A5043C" "C71A026E" + "F7CA8CD9" "E69D218D" "98158536" "F92F8A1B" "A7F09AB6" "B6A8E122" + "F242DABB" "312F3F63" "7A262174" "D31BF6B5" "85FFAE5B" "7A035BF6" + "F71C35FD" "AD44CFD2" "D74F9208" "BE258FF3" "24943328" "F6722D9E" + "E1003E5C" "50B1DF82" "CC6D241B" "0E2AE9CD" "348B1FD4" "7E9267AF" + "C1B2AE91" "EE51D6CB" "0E3179AB" "1042A95D" "CF6A9483" "B84B4B36" + "B3861AA7" "255E4C02" "78BA3604" "650C10BE" "19482F23" "171B671D" + "F1CF3B96" "0C074301" "CD93C1D1" "7603D147" "DAE2AEF8" "37A62964" + "EF15E5FB" "4AAC0B8C" "1CCAA4BE" "754AB572" "8AE9130C" "4C7D0288" + "0AB9472D" "45565534" "7FFFFFFF" "FFFFFFFF"; krb5_error_code _krb5_parse_moduli(krb5_context context, const char *file, @@ -1757,19 +1786,28 @@ _krb5_parse_moduli(krb5_context context, const char *file, *moduli = NULL; - m = calloc(1, sizeof(m[0]) * 2); + m = calloc(1, sizeof(m[0]) * 3); if (m == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - strlcpy(buf, default_moduli, sizeof(buf)); + strlcpy(buf, default_moduli_rfc3526_MODP_group14, sizeof(buf)); ret = _krb5_parse_moduli_line(context, "builtin", 1, buf, &m[0]); if (ret) { _krb5_free_moduli(m); return ret; } - n = 1; + n++; + + strlcpy(buf, default_moduli_RFC2412_MODP_group2, sizeof(buf)); + ret = _krb5_parse_moduli_line(context, "builtin", 1, buf, &m[1]); + if (ret) { + _krb5_free_moduli(m); + return ret; + } + n++; + if (file == NULL) file = MODULI_FILE; diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c index 68317a12c0..43fa3f5b45 100644 --- a/source4/heimdal/lib/krb5/plugin.c +++ b/source4/heimdal/lib/krb5/plugin.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: plugin.c 21134 2007-06-18 21:02:23Z lha $"); +RCSID("$Id: plugin.c 21702 2007-07-26 19:13:53Z lha $"); #ifdef HAVE_DLFCN_H #include #endif @@ -45,7 +45,7 @@ struct krb5_plugin { }; struct plugin { - enum plugin_type type; + enum krb5_plugin_type type; void *name; void *symbol; struct plugin *next; @@ -76,9 +76,11 @@ _krb5_plugin_get_next(struct krb5_plugin *p) * */ +#ifdef HAVE_DLOPEN + static krb5_error_code loadlib(krb5_context context, - enum plugin_type type, + enum krb5_plugin_type type, const char *name, const char *lib, struct krb5_plugin **e) @@ -113,10 +115,11 @@ loadlib(krb5_context context, return 0; } +#endif /* HAVE_DLOPEN */ krb5_error_code _krb5_plugin_register(krb5_context context, - enum plugin_type type, + enum krb5_plugin_type type, const char *name, void *symbol) { @@ -146,7 +149,7 @@ _krb5_plugin_register(krb5_context context, krb5_error_code _krb5_plugin_find(krb5_context context, - enum plugin_type type, + enum krb5_plugin_type type, const char *name, struct krb5_plugin **list) { @@ -181,6 +184,8 @@ _krb5_plugin_find(krb5_context context, } HEIMDAL_MUTEX_unlock(&plugin_mutex); +#ifdef HAVE_DLOPEN + dirs = krb5_config_get_strings(context, NULL, "libdefaults", "plugin_dir", NULL); if (dirs == NULL) { @@ -213,6 +218,7 @@ _krb5_plugin_find(krb5_context context, } if (dirs != sysdirs) krb5_config_free_strings(dirs); +#endif /* HAVE_DLOPEN */ if (*list == NULL) { krb5_set_error_string(context, "Did not find a plugin for %s", name); diff --git a/source4/heimdal/lib/krb5/rd_priv.c b/source4/heimdal/lib/krb5/rd_priv.c index d3920dd941..47b5df85b2 100644 --- a/source4/heimdal/lib/krb5/rd_priv.c +++ b/source4/heimdal/lib/krb5/rd_priv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2003 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_priv.c 17056 2006-04-12 16:18:10Z lha $"); +RCSID("$Id: rd_priv.c 21770 2007-08-01 04:04:33Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_priv(krb5_context context, @@ -55,13 +55,17 @@ krb5_rd_priv(krb5_context context, if ((auth_context->flags & (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && - outdata == NULL) + outdata == NULL) { + krb5_clear_error_string (context); return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */ + } memset(&priv, 0, sizeof(priv)); ret = decode_KRB_PRIV (inbuf->data, inbuf->length, &priv, &len); - if (ret) + if (ret) { + krb5_clear_error_string (context); goto failure; + } if (priv.pvno != 5) { krb5_clear_error_string (context); ret = KRB5KRB_AP_ERR_BADVERSION; @@ -94,8 +98,10 @@ krb5_rd_priv(krb5_context context, ret = decode_EncKrbPrivPart (plain.data, plain.length, &part, &len); krb5_data_free (&plain); - if (ret) + if (ret) { + krb5_clear_error_string (context); goto failure; + } /* check sender address */ diff --git a/source4/heimdal/lib/krb5/v4_glue.c b/source4/heimdal/lib/krb5/v4_glue.c index d42fbec3a5..3f99df6391 100644 --- a/source4/heimdal/lib/krb5/v4_glue.c +++ b/source4/heimdal/lib/krb5/v4_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: v4_glue.c 17442 2006-05-05 09:31:15Z lha $"); +RCSID("$Id: v4_glue.c 21572 2007-07-16 05:13:08Z lha $"); #include "krb5-v4compat.h" @@ -351,12 +351,12 @@ storage_to_etext(krb5_context context, size = krb5_storage_seek(sp, 0, SEEK_END); if (size < 0) - return EINVAL; + return KRB4ET_RD_AP_UNDEC; size = 8 - (size & 7); ret = krb5_storage_write(sp, eightzeros, size); if (ret != size) - return EINVAL; + return KRB4ET_RD_AP_UNDEC; ret = krb5_storage_to_data(sp, &data); if (ret) @@ -435,7 +435,7 @@ _krb5_krb_create_ticket(krb5_context context, session->keyvalue.data, session->keyvalue.length); if (ret != session->keyvalue.length) { - ret = EINVAL; + ret = KRB4ET_INTK_PROT; goto error; } @@ -487,7 +487,7 @@ _krb5_krb_create_ciph(krb5_context context, session->keyvalue.data, session->keyvalue.length); if (ret != session->keyvalue.length) { - ret = EINVAL; + ret = KRB4ET_INTK_PROT; goto error; } @@ -497,7 +497,7 @@ _krb5_krb_create_ciph(krb5_context context, RCHECK(ret, krb5_store_int8(sp, ticket->length), error); ret = krb5_storage_write(sp, ticket->data, ticket->length); if (ret != ticket->length) { - ret = EINVAL; + ret = KRB4ET_INTK_PROT; goto error; } RCHECK(ret, krb5_store_int32(sp, kdc_time), error); @@ -550,7 +550,7 @@ _krb5_krb_create_auth_reply(krb5_context context, RCHECK(ret, krb5_store_int16(sp, cipher->length), error); ret = krb5_storage_write(sp, cipher->data, cipher->length); if (ret != cipher->length) { - ret = EINVAL; + ret = KRB4ET_INTK_PROT; goto error; } @@ -599,6 +599,9 @@ _krb5_krb_cr_err_reply(krb5_context context, RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_ERR_REPLY), error); RCHECK(ret, put_nir(sp, name, inst, realm), error); RCHECK(ret, krb5_store_int32(sp, time_ws), error); + /* If its a Kerberos 4 error-code, remove the et BASE */ + if (e >= ERROR_TABLE_BASE_krb && e <= ERROR_TABLE_BASE_krb + 255) + e -= ERROR_TABLE_BASE_krb; RCHECK(ret, krb5_store_int32(sp, e), error); RCHECK(ret, krb5_store_stringz(sp, e_string), error); @@ -623,7 +626,7 @@ get_v4_stringz(krb5_storage *sp, char **str, size_t max_len) if (strlen(*str) > max_len) { free(*str); *str = NULL; - return EINVAL; + return KRB4ET_INTK_PROT; } return 0; } @@ -662,7 +665,7 @@ _krb5_krb_decomp_ticket(krb5_context context, return ENOMEM; } - krb5_storage_set_eof_code(sp, EINVAL); /* XXX */ + krb5_storage_set_eof_code(sp, KRB4ET_INTK_PROT); RCHECK(ret, krb5_ret_int8(sp, &ad->k_flags), error); RCHECK(ret, get_v4_stringz(sp, &ad->pname, ANAME_SZ), error); @@ -672,7 +675,7 @@ _krb5_krb_decomp_ticket(krb5_context context, size = krb5_storage_read(sp, des_key, sizeof(des_key)); if (size != sizeof(des_key)) { - ret = EINVAL; /* XXX */ + ret = KRB4ET_INTK_PROT; goto error; } @@ -770,26 +773,32 @@ _krb5_krb_rd_req(krb5_context context, return ENOMEM; } - krb5_storage_set_eof_code(sp, EINVAL); /* XXX */ + krb5_storage_set_eof_code(sp, KRB4ET_INTK_PROT); ret = krb5_ret_int8(sp, &pvno); - if (ret) + if (ret) { + krb5_set_error_string(context, "Failed reading v4 pvno"); goto error; + } if (pvno != KRB_PROT_VERSION) { - ret = EINVAL; /* XXX */ + ret = KRB4ET_RD_AP_VERSION; + krb5_set_error_string(context, "Failed v4 pvno not 4"); goto error; } ret = krb5_ret_int8(sp, &type); - if (ret) + if (ret) { + krb5_set_error_string(context, "Failed readin v4 type"); goto error; + } little_endian = type & 1; type &= ~1; if(type != AUTH_MSG_APPL_REQUEST && type != AUTH_MSG_APPL_REQUEST_MUTUAL) { - ret = EINVAL; /* RD_AP_MSG_TYPE */ + ret = KRB4ET_RD_AP_MSG_TYPE; + krb5_set_error_string(context, "Not a valid v4 request type"); goto error; } @@ -801,7 +810,8 @@ _krb5_krb_rd_req(krb5_context context, size = krb5_storage_read(sp, ticket.data, ticket.length); if (size != ticket.length) { - ret = EINVAL; + ret = KRB4ET_INTK_PROT; + krb5_set_error_string(context, "Failed reading v4 ticket"); goto error; } @@ -815,7 +825,8 @@ _krb5_krb_rd_req(krb5_context context, size = krb5_storage_read(sp, eaut.data, eaut.length); if (size != eaut.length) { - ret = EINVAL; + ret = KRB4ET_INTK_PROT; + krb5_set_error_string(context, "Failed reading v4 authenticator"); goto error; } @@ -828,8 +839,8 @@ _krb5_krb_rd_req(krb5_context context, sp = krb5_storage_from_data(&aut); if (sp == NULL) { - krb5_set_error_string(context, "alloc: out of memory"); ret = ENOMEM; + krb5_set_error_string(context, "alloc: out of memory"); goto error; } @@ -849,19 +860,22 @@ _krb5_krb_rd_req(krb5_context context, if (strcmp(ad->pname, r_name) != 0 || strcmp(ad->pinst, r_instance) != 0 || strcmp(ad->prealm, r_realm) != 0) { - ret = EINVAL; /* RD_AP_INCON */ + krb5_set_error_string(context, "v4 principal mismatch"); + ret = KRB4ET_RD_AP_INCON; goto error; } - if (from_addr && from_addr != ad->address) { - ret = EINVAL; /* RD_AP_BADD */ + if (from_addr && ad->address && from_addr != ad->address) { + krb5_set_error_string(context, "v4 bad address in ticket"); + ret = KRB4ET_RD_AP_BADD; goto error; } gettimeofday(&tv, NULL); delta_t = abs((int)(tv.tv_sec - r_time_sec)); if (delta_t > CLOCK_SKEW) { - ret = EINVAL; /* RD_AP_TIME */ + ret = KRB4ET_RD_AP_TIME; + krb5_set_error_string(context, "v4 clock skew"); goto error; } @@ -870,12 +884,14 @@ _krb5_krb_rd_req(krb5_context context, tkt_age = tv.tv_sec - ad->time_sec; if ((tkt_age < 0) && (-tkt_age > CLOCK_SKEW)) { - ret = EINVAL; /* RD_AP_NYV */ + ret = KRB4ET_RD_AP_NYV; + krb5_set_error_string(context, "v4 clock skew for expiration"); goto error; } if (tv.tv_sec > _krb5_krb_life_to_time(ad->time_sec, ad->life)) { - ret = EINVAL; /* RD_AP_EXP */ + ret = KRB4ET_RD_AP_EXP; + krb5_set_error_string(context, "v4 ticket expired"); goto error; } -- cgit From 9e6b0c28712ee77ce878809c8576826a3ba08d95 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 19 Mar 2008 10:17:42 +1100 Subject: Merge lorikeet-heimdal -r 787 into Samba4 tree. Andrew Bartlett (This used to be commit d88b530522d3cef67c24422bd5182fb875d87ee2) --- source4/heimdal/lib/krb5/acache.c | 270 +++++++++++++--------- source4/heimdal/lib/krb5/add_et_list.c | 12 +- source4/heimdal/lib/krb5/addr_families.c | 282 +++++++++++++++++++++- source4/heimdal/lib/krb5/asn1_glue.c | 6 +- source4/heimdal/lib/krb5/auth_context.c | 8 +- source4/heimdal/lib/krb5/cache.c | 330 ++++++++++++++++++++------ source4/heimdal/lib/krb5/context.c | 334 ++++++++++++++++++++++++++- source4/heimdal/lib/krb5/convert_creds.c | 31 ++- source4/heimdal/lib/krb5/copy_host_realm.c | 13 +- source4/heimdal/lib/krb5/creds.c | 84 +++++-- source4/heimdal/lib/krb5/crypto.c | 63 +++-- source4/heimdal/lib/krb5/data.c | 100 +++++++- source4/heimdal/lib/krb5/eai_to_heim_errno.c | 26 ++- source4/heimdal/lib/krb5/error_string.c | 33 ++- source4/heimdal/lib/krb5/expand_hostname.c | 6 +- source4/heimdal/lib/krb5/fcache.c | 131 +++++++++-- source4/heimdal/lib/krb5/get_cred.c | 10 +- source4/heimdal/lib/krb5/get_for_creds.c | 94 +++++--- source4/heimdal/lib/krb5/get_in_tkt.c | 2 +- source4/heimdal/lib/krb5/init_creds.c | 2 +- source4/heimdal/lib/krb5/init_creds_pw.c | 12 +- source4/heimdal/lib/krb5/kcm.c | 30 ++- source4/heimdal/lib/krb5/keytab.c | 7 +- source4/heimdal/lib/krb5/keytab_file.c | 6 +- source4/heimdal/lib/krb5/keytab_keyfile.c | 6 +- source4/heimdal/lib/krb5/keytab_krb4.c | 28 ++- source4/heimdal/lib/krb5/krb5-private.h | 11 +- source4/heimdal/lib/krb5/krb5-protos.h | 50 +++- source4/heimdal/lib/krb5/krb5.h | 21 +- source4/heimdal/lib/krb5/krb5_ccapi.h | 8 +- source4/heimdal/lib/krb5/krb5_locl.h | 14 +- source4/heimdal/lib/krb5/mcache.c | 57 ++++- source4/heimdal/lib/krb5/n-fold.c | 23 +- source4/heimdal/lib/krb5/pac.c | 92 ++++---- source4/heimdal/lib/krb5/pkinit.c | 90 +++++--- source4/heimdal/lib/krb5/plugin.c | 23 +- source4/heimdal/lib/krb5/principal.c | 37 ++- source4/heimdal/lib/krb5/rd_priv.c | 2 +- source4/heimdal/lib/krb5/rd_req.c | 44 ++-- source4/heimdal/lib/krb5/send_to_kdc.c | 4 +- source4/heimdal/lib/krb5/store.c | 10 +- source4/heimdal/lib/krb5/store_emem.c | 21 +- source4/heimdal/lib/krb5/transited.c | 19 +- source4/heimdal/lib/krb5/v4_glue.c | 4 +- 44 files changed, 1969 insertions(+), 487 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c index 999ce7f120..775239cf6d 100644 --- a/source4/heimdal/lib/krb5/acache.c +++ b/source4/heimdal/lib/krb5/acache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -37,7 +37,7 @@ #include #endif -RCSID("$Id: acache.c 19764 2007-01-08 15:31:01Z lha $"); +RCSID("$Id: acache.c 22669 2008-03-09 23:39:25Z lha $"); /* XXX should we fetch these for each open ? */ static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; @@ -188,11 +188,10 @@ make_cred_from_ccred(krb5_context context, ; if (i) { - cred->authdata.val = malloc(sizeof(cred->authdata.val[0]) * i); + cred->authdata.val = calloc(i, sizeof(cred->authdata.val[0])); if (cred->authdata.val == NULL) goto nomem; cred->authdata.len = i; - memset(cred->authdata.val, 0, sizeof(cred->authdata.val[0]) * i); for (i = 0; i < cred->authdata.len; i++) { cred->authdata.val[i].ad_type = incred->authdata[i]->type; ret = krb5_data_copy(&cred->authdata.val[i].ad_data, @@ -207,11 +206,10 @@ make_cred_from_ccred(krb5_context context, ; if (i) { - cred->addresses.val = malloc(sizeof(cred->addresses.val[0]) * i); + cred->addresses.val = calloc(i, sizeof(cred->addresses.val[0])); if (cred->addresses.val == NULL) goto nomem; cred->addresses.len = i; - memset(cred->addresses.val, 0, sizeof(cred->addresses.val[0]) * i); for (i = 0; i < cred->addresses.len; i++) { cred->addresses.val[i].addr_type = incred->addresses[i]->type; @@ -260,7 +258,7 @@ nomem: krb5_set_error_string(context, "malloc - out of memory"); fail: - krb5_free_creds_contents(context, cred); + krb5_free_cred_contents(context, cred); return ret; } @@ -331,6 +329,10 @@ make_ccred_from_cred(krb5_context context, for (i = 0; i < incred->addresses.len; i++) { cc_data *addr; addr = malloc(sizeof(*addr)); + if (addr == NULL) { + ret = ENOMEM; + goto fail; + } addr->type = incred->addresses.val[i].addr_type; addr->length = incred->addresses.val[i].address.length; addr->data = malloc(addr->length); @@ -383,20 +385,21 @@ fail: return ret; } -static char * -get_cc_name(cc_ccache_t cache) +static cc_int32 +get_cc_name(krb5_acc *a) { cc_string_t name; cc_int32 error; - char *str; - error = (*cache->func->get_name)(cache, &name); + error = (*a->ccache->func->get_name)(a->ccache, &name); if (error) - return NULL; + return error; - str = strdup(name->data); + a->cache_name = strdup(name->data); (*name->func->release)(name); - return str; + if (a->cache_name == NULL) + return ccErrNoMem; + return ccNoError; } @@ -405,17 +408,36 @@ acc_get_name(krb5_context context, krb5_ccache id) { krb5_acc *a = ACACHE(id); - static char n[255]; - char *name; + int32_t error; - name = get_cc_name(a->ccache); - if (name == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return NULL; - } - strlcpy(n, name, sizeof(n)); - free(name); - return n; + if (a->cache_name == NULL) { + krb5_error_code ret; + krb5_principal principal; + char *name; + + ret = _krb5_get_default_principal_local(context, &principal); + if (ret) + return NULL; + + ret = krb5_unparse_name(context, principal, &name); + krb5_free_principal(context, principal); + if (ret) + return NULL; + + error = (*a->context->func->create_new_ccache)(a->context, + cc_credentials_v5, + name, + &a->ccache); + krb5_xfree(name); + if (error) + return NULL; + + error = get_cc_name(a); + if (error) + return NULL; + } + + return a->cache_name; } static krb5_error_code @@ -448,23 +470,6 @@ acc_alloc(krb5_context context, krb5_ccache *id) return 0; } -static krb5_error_code -get_default_principal(krb5_context context, char **p) -{ - krb5_error_code ret; - krb5_principal principal; - - *p = NULL; - - ret = _krb5_get_default_principal_local(context, &principal); - if (ret) - return ret; - - ret = krb5_unparse_name(context, principal, p); - krb5_free_principal(context, principal); - return ret; -} - static krb5_error_code acc_resolve(krb5_context context, krb5_ccache *id, const char *res) { @@ -478,38 +483,22 @@ acc_resolve(krb5_context context, krb5_ccache *id, const char *res) a = ACACHE(*id); - if (res == NULL || res[0] == '\0') { - error = (*a->context->func->open_default_ccache)(a->context, - &a->ccache); - if (error == ccErrCCacheNotFound) { - char *p; - - ret = get_default_principal(context, &p); - if (ret == 0) { - error = (*a->context->func->create_default_ccache)(a->context, - cc_credentials_v5, - p, - &a->ccache); - free(p); - } + error = (*a->context->func->open_ccache)(a->context, res, &a->ccache); + if (error == ccNoError) { + error = get_cc_name(a); + if (error != ccNoError) { + acc_close(context, *id); + *id = NULL; + return translate_cc_error(context, error); } - if (error == 0) - a->cache_name = get_cc_name(a->ccache); + } else if (error == ccErrCCacheNotFound) { + a->ccache = NULL; + a->cache_name = NULL; + error = 0; } else { - error = (*a->context->func->open_ccache)(a->context, res, &a->ccache); - if (error == 0) - a->cache_name = strdup(res); - } - if (error != 0) { *id = NULL; return translate_cc_error(context, error); } - if (a->cache_name == NULL) { - acc_close(context, *id); - *id = NULL; - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } return 0; } @@ -518,35 +507,17 @@ static krb5_error_code acc_gen_new(krb5_context context, krb5_ccache *id) { krb5_error_code ret; - cc_int32 error; krb5_acc *a; - char *p; - - ret = get_default_principal(context, &p); ret = acc_alloc(context, id); - if (ret) { - free(p); + if (ret) return ret; - } a = ACACHE(*id); - error = (*a->context->func->create_new_ccache)(a->context, - cc_credentials_v5, - p, &a->ccache); - free(p); - if (error) { - *id = NULL; - return translate_cc_error(context, error); - } - a->cache_name = get_cc_name(a->ccache); - if (a->cache_name == NULL) { - acc_close(context, *id); - *id = NULL; - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } + a->ccache = NULL; + a->cache_name = NULL; + return 0; } @@ -555,9 +526,7 @@ acc_initialize(krb5_context context, krb5_ccache id, krb5_principal primary_principal) { - cc_credentials_iterator_t iter; krb5_acc *a = ACACHE(id); - cc_credentials_t ccred; krb5_error_code ret; int32_t error; char *name; @@ -566,12 +535,17 @@ acc_initialize(krb5_context context, if (ret) return ret; - if (a->ccache == NULL) { + if (a->cache_name == NULL) { error = (*a->context->func->create_new_ccache)(a->context, cc_credentials_v5, name, &a->ccache); - } else { + free(name); + if (error == ccNoError) + error = get_cc_name(a); + } else { + cc_credentials_iterator_t iter; + cc_credentials_t ccred; error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter); if (error) { @@ -593,8 +567,6 @@ acc_initialize(krb5_context context, name); } - free(name); - return translate_cc_error(context, error); } @@ -629,6 +601,10 @@ acc_destroy(krb5_context context, error = (*a->ccache->func->destroy)(a->ccache); a->ccache = NULL; } + if (a->context) { + error = (a->context->func->release)(a->context); + a->context = NULL; + } return translate_cc_error(context, error); } @@ -643,6 +619,11 @@ acc_store_cred(krb5_context context, krb5_error_code ret; cc_int32 error; + if (a->ccache == NULL) { + krb5_set_error_string(context, "No API credential found"); + return KRB5_CC_NOTFOUND; + } + cred.version = cc_credentials_v5; cred.credentials.credentials_v5 = &v5cred; @@ -671,8 +652,10 @@ acc_get_principal(krb5_context context, int32_t error; cc_string_t name; - if (a->ccache == NULL) - return ENOENT; + if (a->ccache == NULL) { + krb5_set_error_string(context, "No API credential found"); + return KRB5_CC_NOTFOUND; + } error = (*a->ccache->func->get_principal)(a->ccache, cc_credentials_v5, @@ -695,6 +678,11 @@ acc_get_first (krb5_context context, krb5_acc *a = ACACHE(id); int32_t error; + if (a->ccache == NULL) { + krb5_set_error_string(context, "No API credential found"); + return KRB5_CC_NOTFOUND; + } + error = (*a->ccache->func->new_credentials_iterator)(a->ccache, &iter); if (error) { krb5_clear_error_string(context); @@ -755,6 +743,11 @@ acc_remove_cred(krb5_context context, cc_int32 error; char *client, *server; + if (a->ccache == NULL) { + krb5_set_error_string(context, "No API credential found"); + return KRB5_CC_NOTFOUND; + } + if (cred->client) { ret = krb5_unparse_name(context, cred->client, &client); if (ret) @@ -894,12 +887,11 @@ acc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id) a = ACACHE(*id); a->ccache = cache; - a->cache_name = get_cc_name(a->ccache); - if (a->cache_name == NULL) { + error = get_cc_name(a); + if (error) { acc_close(context, *id); *id = NULL; - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; + return translate_cc_error(context, error); } return 0; } @@ -917,6 +909,76 @@ acc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) return 0; } +static krb5_error_code +acc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_acc *afrom = ACACHE(from); + krb5_acc *ato = ACACHE(to); + int32_t error; + + if (ato->ccache == NULL) { + cc_string_t name; + + error = (*afrom->ccache->func->get_principal)(afrom->ccache, + cc_credentials_v5, + &name); + if (error) + return translate_cc_error(context, error); + + error = (*ato->context->func->create_new_ccache)(ato->context, + cc_credentials_v5, + name->data, + &ato->ccache); + (*name->func->release)(name); + if (error) + return translate_cc_error(context, error); + } + + + error = (*ato->ccache->func->move)(afrom->ccache, ato->ccache); + return translate_cc_error(context, error); +} + +static krb5_error_code +acc_default_name(krb5_context context, char **str) +{ + krb5_error_code ret; + cc_context_t cc; + cc_string_t name; + int32_t error; + + ret = init_ccapi(context); + if (ret) + return ret; + + error = (*init_func)(&cc, ccapi_version_3, NULL, NULL); + if (error) + return translate_cc_error(context, error); + + error = (*cc->func->get_default_ccache_name)(cc, &name); + if (error) { + (*cc->func->release)(cc); + return translate_cc_error(context, error); + } + + asprintf(str, "API:%s", name->data); + (*name->func->release)(name); + (*cc->func->release)(cc); + + if (*str == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + + +/** + * Variable containing the API based credential cache implemention. + * + * @ingroup krb5_ccache + */ + const krb5_cc_ops krb5_acc_ops = { "API", acc_get_name, @@ -936,5 +998,7 @@ const krb5_cc_ops krb5_acc_ops = { acc_get_version, acc_get_cache_first, acc_get_cache_next, - acc_end_cache_get + acc_end_cache_get, + acc_move, + acc_default_name }; diff --git a/source4/heimdal/lib/krb5/add_et_list.c b/source4/heimdal/lib/krb5/add_et_list.c index a6005c6859..5455d8ac99 100644 --- a/source4/heimdal/lib/krb5/add_et_list.c +++ b/source4/heimdal/lib/krb5/add_et_list.c @@ -33,12 +33,20 @@ #include "krb5_locl.h" -RCSID("$Id: add_et_list.c 13713 2004-04-13 14:33:45Z lha $"); +RCSID("$Id: add_et_list.c 22603 2008-02-21 18:44:57Z lha $"); -/* +/** * Add a specified list of error messages to the et list in context. * Call func (probably a comerr-generated function) with a pointer to * the current et_list. + * + * @param context A kerberos context. + * @param func The generated com_err et function. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 */ krb5_error_code KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c index 8c31843058..f364f5974d 100644 --- a/source4/heimdal/lib/krb5/addr_families.c +++ b/source4/heimdal/lib/krb5/addr_families.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: addr_families.c 18805 2006-10-22 06:54:00Z lha $"); +RCSID("$Id: addr_families.c 22039 2007-11-10 11:47:35Z lha $"); struct addr_operations { int af; @@ -767,6 +767,19 @@ find_atype(int atype) return NULL; } +/** + * krb5_sockaddr2address stores a address a "struct sockaddr" sa in + * the krb5_address addr. + * + * @param context a Keberos context + * @param sa a struct sockaddr to extract the address from + * @param addr an Kerberos 5 address to store the address in. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_sockaddr2address (krb5_context context, const struct sockaddr *sa, krb5_address *addr) @@ -780,6 +793,20 @@ krb5_sockaddr2address (krb5_context context, return (*a->sockaddr2addr)(sa, addr); } +/** + * krb5_sockaddr2port extracts a port (if possible) from a "struct + * sockaddr. + * + * @param context a Keberos context + * @param sa a struct sockaddr to extract the port from + * @param port a pointer to an int16_t store the port in. + * + * @return Return an error code or 0. Will return + * KRB5_PROG_ATYPE_NOSUPP in case address type is not supported. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_sockaddr2port (krb5_context context, const struct sockaddr *sa, int16_t *port) @@ -793,6 +820,27 @@ krb5_sockaddr2port (krb5_context context, return (*a->sockaddr2port)(sa, port); } +/** + * krb5_addr2sockaddr sets the "struct sockaddr sockaddr" from addr + * and port. The argument sa_size should initially contain the size of + * the sa and after the call, it will contain the actual length of the + * address. In case of the sa is too small to fit the whole address, + * the up to *sa_size will be stored, and then *sa_size will be set to + * the required length. + * + * @param context a Keberos context + * @param addr the address to copy the from + * @param sa the struct sockaddr that will be filled in + * @param sa_size pointer to length of sa, and after the call, it will + * contain the actual length of the address. + * @param port set port in sa. + * + * @return Return an error code or 0. Will return + * KRB5_PROG_ATYPE_NOSUPP in case address type is not supported. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_addr2sockaddr (krb5_context context, const krb5_address *addr, @@ -808,7 +856,8 @@ krb5_addr2sockaddr (krb5_context context, return KRB5_PROG_ATYPE_NOSUPP; } if (a->addr2sockaddr == NULL) { - krb5_set_error_string (context, "Can't convert address type %d to sockaddr", + krb5_set_error_string (context, + "Can't convert address type %d to sockaddr", addr->addr_type); return KRB5_PROG_ATYPE_NOSUPP; } @@ -816,6 +865,15 @@ krb5_addr2sockaddr (krb5_context context, return 0; } +/** + * krb5_max_sockaddr_size returns the max size of the .Li struct + * sockaddr that the Kerberos library will return. + * + * @return Return an size_t of the maximum struct sockaddr. + * + * @ingroup krb5_address + */ + size_t KRB5_LIB_FUNCTION krb5_max_sockaddr_size (void) { @@ -828,6 +886,18 @@ krb5_max_sockaddr_size (void) return max_sockaddr_size; } +/** + * krb5_sockaddr_uninteresting returns TRUE for all .Fa sa that the + * kerberos library thinks are uninteresting. One example are link + * local addresses. + * + * @param sa pointer to struct sockaddr that might be interesting. + * + * @return Return a non zero for uninteresting addresses. + * + * @ingroup krb5_address + */ + krb5_boolean KRB5_LIB_FUNCTION krb5_sockaddr_uninteresting(const struct sockaddr *sa) { @@ -837,6 +907,25 @@ krb5_sockaddr_uninteresting(const struct sockaddr *sa) return (*a->uninteresting)(sa); } +/** + * krb5_h_addr2sockaddr initializes a "struct sockaddr sa" from af and + * the "struct hostent" (see gethostbyname(3) ) h_addr_list + * component. The argument sa_size should initially contain the size + * of the sa, and after the call, it will contain the actual length of + * the address. + * + * @param context a Keberos context + * @param af addresses + * @param addr address + * @param sa returned struct sockaddr + * @param sa_size size of sa + * @param port port to set in sa. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_h_addr2sockaddr (krb5_context context, int af, @@ -853,6 +942,20 @@ krb5_h_addr2sockaddr (krb5_context context, return 0; } +/** + * krb5_h_addr2addr works like krb5_h_addr2sockaddr with the exception + * that it operates on a krb5_address instead of a struct sockaddr. + * + * @param context a Keberos context + * @param af address family + * @param haddr host address from struct hostent. + * @param addr returned krb5_address. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_h_addr2addr (krb5_context context, int af, @@ -866,6 +969,23 @@ krb5_h_addr2addr (krb5_context context, return (*a->h_addr2addr)(haddr, addr); } +/** + * krb5_anyaddr fills in a "struct sockaddr sa" that can be used to + * bind(2) to. The argument sa_size should initially contain the size + * of the sa, and after the call, it will contain the actual length + * of the address. + * + * @param context a Keberos context + * @param af address family + * @param sa sockaddr + * @param sa_size lenght of sa. + * @param port for to fill into sa. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_anyaddr (krb5_context context, int af, @@ -884,6 +1004,22 @@ krb5_anyaddr (krb5_context context, return 0; } +/** + * krb5_print_address prints the address in addr to the string string + * that have the length len. If ret_len is not NULL, it will be filled + * with the length of the string if size were unlimited (not including + * the final NUL) . + * + * @param addr address to be printed + * @param str pointer string to print the address into + * @param len length that will fit into area pointed to by "str". + * @param ret_len return length the str. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_print_address (const krb5_address *addr, char *str, size_t len, size_t *ret_len) @@ -921,6 +1057,19 @@ krb5_print_address (const krb5_address *addr, return 0; } +/** + * krb5_parse_address returns the resolved hostname in string to the + * krb5_addresses addresses . + * + * @param context a Keberos context + * @param string + * @param addresses + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_parse_address(krb5_context context, const char *string, @@ -980,6 +1129,21 @@ krb5_parse_address(krb5_context context, return 0; } +/** + * krb5_address_order compares the addresses addr1 and addr2 so that + * it can be used for sorting addresses. If the addresses are the same + * address krb5_address_order will return 0. Behavies like memcmp(2). + * + * @param context a Keberos context + * @param addr1 krb5_address to compare + * @param addr2 krb5_address to compare + * + * @return < 0 if address addr1 in "less" then addr2. 0 if addr1 and + * addr2 is the same address, > 0 if addr2 is "less" then addr1. + * + * @ingroup krb5_address + */ + int KRB5_LIB_FUNCTION krb5_address_order(krb5_context context, const krb5_address *addr1, @@ -1014,6 +1178,19 @@ krb5_address_order(krb5_context context, addr1->address.length); } +/** + * krb5_address_compare compares the addresses addr1 and addr2. + * Returns TRUE if the two addresses are the same. + * + * @param context a Keberos context + * @param addr1 address to compare + * @param addr2 address to compare + * + * @return Return an TRUE is the address are the same FALSE if not + * + * @ingroup krb5_address + */ + krb5_boolean KRB5_LIB_FUNCTION krb5_address_compare(krb5_context context, const krb5_address *addr1, @@ -1022,6 +1199,19 @@ krb5_address_compare(krb5_context context, return krb5_address_order (context, addr1, addr2) == 0; } +/** + * krb5_address_search checks if the address addr is a member of the + * address set list addrlist . + * + * @param context a Keberos context. + * @param addr address to search for. + * @param addrlist list of addresses to look in for addr. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_boolean KRB5_LIB_FUNCTION krb5_address_search(krb5_context context, const krb5_address *addr, @@ -1035,6 +1225,18 @@ krb5_address_search(krb5_context context, return FALSE; } +/** + * krb5_free_address frees the data stored in the address that is + * alloced with any of the krb5_address functions. + * + * @param context a Keberos context + * @param address addresss to be freed. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_free_address(krb5_context context, krb5_address *address) @@ -1047,6 +1249,18 @@ krb5_free_address(krb5_context context, return 0; } +/** + * krb5_free_addresses frees the data stored in the address that is + * alloced with any of the krb5_address functions. + * + * @param context a Keberos context + * @param addresses addressses to be freed. + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_free_addresses(krb5_context context, krb5_addresses *addresses) @@ -1060,6 +1274,19 @@ krb5_free_addresses(krb5_context context, return 0; } +/** + * krb5_copy_address copies the content of address + * inaddr to outaddr. + * + * @param context a Keberos context + * @param inaddr pointer to source address + * @param outaddr pointer to destination address + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_copy_address(krb5_context context, const krb5_address *inaddr, @@ -1071,6 +1298,19 @@ krb5_copy_address(krb5_context context, return copy_HostAddress(inaddr, outaddr); } +/** + * krb5_copy_addresses copies the content of addresses + * inaddr to outaddr. + * + * @param context a Keberos context + * @param inaddr pointer to source addresses + * @param outaddr pointer to destination addresses + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_copy_addresses(krb5_context context, const krb5_addresses *inaddr, @@ -1085,6 +1325,19 @@ krb5_copy_addresses(krb5_context context, return 0; } +/** + * krb5_append_addresses adds the set of addresses in source to + * dest. While copying the addresses, duplicates are also sorted out. + * + * @param context a Keberos context + * @param dest destination of copy operation + * @param source adresses that are going to be added to dest + * + * @return Return an error code or 0. + * + * @ingroup krb5_address + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_append_addresses(krb5_context context, krb5_addresses *dest, @@ -1115,8 +1368,17 @@ krb5_append_addresses(krb5_context context, return 0; } -/* +/** * Create an address of type KRB5_ADDRESS_ADDRPORT from (addr, port) + * + * @param context a Keberos context + * @param res built address from addr/port + * @param addr address to use + * @param port port to use + * + * @return Return an error code or 0. + * + * @ingroup krb5_address */ krb5_error_code KRB5_LIB_FUNCTION @@ -1170,9 +1432,19 @@ krb5_make_addrport (krb5_context context, return 0; } -/* +/** * Calculate the boundary addresses of `inaddr'/`prefixlen' and store * them in `low' and `high'. + * + * @param context a Keberos context + * @param inaddr address in prefixlen that the bondery searched + * @param prefixlen width of boundery + * @param low lowest address + * @param high highest address + * + * @return Return an error code or 0. + * + * @ingroup krb5_address */ krb5_error_code KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/asn1_glue.c b/source4/heimdal/lib/krb5/asn1_glue.c index 6b7d40d453..b3f775b4be 100644 --- a/source4/heimdal/lib/krb5/asn1_glue.c +++ b/source4/heimdal/lib/krb5/asn1_glue.c @@ -37,7 +37,7 @@ #include "krb5_locl.h" -RCSID("$Id: asn1_glue.c 18269 2006-10-06 17:02:48Z lha $"); +RCSID("$Id: asn1_glue.c 21745 2007-07-31 16:11:25Z lha $"); krb5_error_code KRB5_LIB_FUNCTION _krb5_principal2principalname (PrincipalName *p, @@ -53,8 +53,12 @@ _krb5_principalname2krb5_principal (krb5_context context, const Realm realm) { krb5_principal p = malloc(sizeof(*p)); + if (p == NULL) + return ENOMEM; copy_PrincipalName(&from, &p->name); p->realm = strdup(realm); + if (p->realm == NULL) + return ENOMEM; *principal = p; return 0; } diff --git a/source4/heimdal/lib/krb5/auth_context.c b/source4/heimdal/lib/krb5/auth_context.c index 5e08f15ad4..323f17a245 100644 --- a/source4/heimdal/lib/krb5/auth_context.c +++ b/source4/heimdal/lib/krb5/auth_context.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: auth_context.c 14452 2005-01-05 02:34:08Z lukeh $"); +RCSID("$Id: auth_context.c 21745 2007-07-31 16:11:25Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_auth_con_init(krb5_context context, @@ -141,14 +141,16 @@ krb5_auth_con_setaddrs(krb5_context context, if (auth_context->local_address) krb5_free_address (context, auth_context->local_address); else - auth_context->local_address = malloc(sizeof(krb5_address)); + if ((auth_context->local_address = malloc(sizeof(krb5_address))) == NULL) + return ENOMEM; krb5_copy_address(context, local_addr, auth_context->local_address); } if (remote_addr) { if (auth_context->remote_address) krb5_free_address (context, auth_context->remote_address); else - auth_context->remote_address = malloc(sizeof(krb5_address)); + if ((auth_context->remote_address = malloc(sizeof(krb5_address))) == NULL) + return ENOMEM; krb5_copy_address(context, remote_addr, auth_context->remote_address); } return 0; diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index 59aae40d28..5db6d2b2cf 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,12 +33,20 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c 21498 2007-07-11 09:41:43Z lha $"); +RCSID("$Id: cache.c 22127 2007-12-04 00:54:37Z lha $"); -/* +/** * Add a new ccache type with operations `ops', overwriting any * existing one if `override'. - * Return an error code or 0. + * + * @param context a Keberos context + * @param ops type of plugin symbol + * @param override flag to select if the registration is to overide + * an existing ops with the same name. + * + * @return Return an error code or 0. + * + * @ingroup krb5_ccache */ krb5_error_code KRB5_LIB_FUNCTION @@ -101,8 +109,7 @@ _krb5_cc_allocate(krb5_context context, /* * Allocate memory for a new ccache in `id' with operations `ops' - * and name `residual'. - * Return 0 or an error code. + * and name `residual'. Return 0 or an error code. */ static krb5_error_code @@ -122,12 +129,21 @@ allocate_ccache (krb5_context context, return ret; } -/* +/** * Find and allocate a ccache in `id' from the specification in `residual'. * If the ccache name doesn't contain any colon, interpret it as a file name. - * Return 0 or an error code. + * + * @param context a Keberos context. + * @param name string name of a credential cache. + * @param id return pointer to a found credential cache. + * + * @return Return 0 or an error code. In case of an error, id is set + * to NULL. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_resolve(krb5_context context, const char *name, @@ -135,6 +151,8 @@ krb5_cc_resolve(krb5_context context, { int i; + *id = NULL; + for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) { size_t prefix_len = strlen(context->cc_ops[i].prefix); @@ -153,57 +171,64 @@ krb5_cc_resolve(krb5_context context, } } -/* +/** * Generate a new ccache of type `ops' in `id'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_gen_new(krb5_context context, const krb5_cc_ops *ops, krb5_ccache *id) { - krb5_error_code ret; - - ret = _krb5_cc_allocate(context, ops, id); - if (ret) - return ret; - return (*id)->ops->gen_new(context, id); + return krb5_cc_new_unique(context, ops->prefix, NULL, id); } -/* +/** * Generates a new unique ccache of `type` in `id'. If `type' is NULL, * the library chooses the default credential cache type. The supplied * `hint' (that can be NULL) is a string that the credential cache * type can use to base the name of the credential on, this is to make - * its easier for the user to differentiate the credentials. + * it easier for the user to differentiate the credentials. + * + * @return Returns 0 or an error code. * - * Returns 0 or an error code. + * @ingroup krb5_ccache */ krb5_error_code KRB5_LIB_FUNCTION krb5_cc_new_unique(krb5_context context, const char *type, const char *hint, krb5_ccache *id) { - const krb5_cc_ops *ops; - - if (type == NULL) - type = KRB5_DEFAULT_CCNAME; + const krb5_cc_ops *ops = KRB5_DEFAULT_CCTYPE; + krb5_error_code ret; - ops = krb5_cc_get_prefix_ops(context, type); - if (ops == NULL) { - krb5_set_error_string(context, "Credential cache type %s is unknown", - type); - return KRB5_CC_UNKNOWN_TYPE; + if (type) { + ops = krb5_cc_get_prefix_ops(context, type); + if (ops == NULL) { + krb5_set_error_string(context, + "Credential cache type %s is unknown", type); + return KRB5_CC_UNKNOWN_TYPE; + } } - return krb5_cc_gen_new(context, ops, id); + ret = _krb5_cc_allocate(context, ops, id); + if (ret) + return ret; + return (*id)->ops->gen_new(context, id); } -/* +/** * Return the name of the ccache `id' + * + * @ingroup krb5_ccache */ + const char* KRB5_LIB_FUNCTION krb5_cc_get_name(krb5_context context, krb5_ccache id) @@ -211,10 +236,13 @@ krb5_cc_get_name(krb5_context context, return id->ops->get_name(context, id); } -/* +/** * Return the type of the ccache `id'. + * + * @ingroup krb5_ccache */ + const char* KRB5_LIB_FUNCTION krb5_cc_get_type(krb5_context context, krb5_ccache id) @@ -222,12 +250,15 @@ krb5_cc_get_type(krb5_context context, return id->ops->prefix; } -/* +/** * Return the complete resolvable name the ccache `id' in `str´. * `str` should be freed with free(3). * Returns 0 or an error (and then *str is set to NULL). + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_get_full_name(krb5_context context, krb5_ccache id, @@ -257,10 +288,13 @@ krb5_cc_get_full_name(krb5_context context, return 0; } -/* +/** * Return krb5_cc_ops of a the ccache `id'. + * + * @ingroup krb5_ccache */ + const krb5_cc_ops * krb5_cc_get_ops(krb5_context context, krb5_ccache id) { @@ -348,6 +382,10 @@ environment_changed(krb5_context context) { const char *e; + /* if the cc name was set, don't change it */ + if (context->default_cc_name_set) + return 0; + if(issuid()) return 0; @@ -367,10 +405,13 @@ environment_changed(krb5_context context) return 0; } -/* +/** * Set the default cc name for `context' to `name'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_set_default_name(krb5_context context, const char *name) { @@ -392,14 +433,23 @@ krb5_cc_set_default_name(krb5_context context, const char *name) if (e == NULL) { e = krb5_config_get_string(context, NULL, "libdefaults", "default_cc_name", NULL); - if (e == NULL) - e = KRB5_DEFAULT_CCNAME; - ret = _krb5_expand_default_cc_name(context, e, &p); - if (ret) - return ret; + if (e) { + ret = _krb5_expand_default_cc_name(context, e, &p); + if (ret) + return ret; + } + if (e == NULL) { + const krb5_cc_ops *ops = KRB5_DEFAULT_CCTYPE; + ret = (*ops->default_name)(context, &p); + if (ret) + return ret; + } } - } else + context->default_cc_name_set = 0; + } else { p = strdup(name); + context->default_cc_name_set = 1; + } if (p == NULL) { krb5_set_error_string(context, "malloc - out of memory"); @@ -414,11 +464,16 @@ krb5_cc_set_default_name(krb5_context context, const char *name) return ret; } -/* +/** * Return a pointer to a context static string containing the default * ccache name. + * + * @return String to the default credential cache name. + * + * @ingroup krb5_ccache */ + const char* KRB5_LIB_FUNCTION krb5_cc_default_name(krb5_context context) { @@ -428,11 +483,15 @@ krb5_cc_default_name(krb5_context context) return context->default_cc_name; } -/* +/** * Open the default ccache in `id'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_default(krb5_context context, krb5_ccache *id) @@ -446,11 +505,15 @@ krb5_cc_default(krb5_context context, return krb5_cc_resolve(context, p, id); } -/* +/** * Create a new ccache in `id' for `primary_principal'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_initialize(krb5_context context, krb5_ccache id, @@ -460,11 +523,15 @@ krb5_cc_initialize(krb5_context context, } -/* +/** * Remove the ccache `id'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_destroy(krb5_context context, krb5_ccache id) @@ -476,11 +543,15 @@ krb5_cc_destroy(krb5_context context, return ret; } -/* +/** * Stop using the ccache `id' and free the related resources. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_close(krb5_context context, krb5_ccache id) @@ -491,11 +562,15 @@ krb5_cc_close(krb5_context context, return ret; } -/* +/** * Store `creds' in the ccache `id'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_store_cred(krb5_context context, krb5_ccache id, @@ -504,13 +579,17 @@ krb5_cc_store_cred(krb5_context context, return (*id->ops->store)(context, id, creds); } -/* +/** * Retrieve the credential identified by `mcreds' (and `whichfields') * from `id' in `creds'. 'creds' must be free by the caller using * krb5_free_cred_contents. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_retrieve_cred(krb5_context context, krb5_ccache id, @@ -526,7 +605,9 @@ krb5_cc_retrieve_cred(krb5_context context, mcreds, creds); } - krb5_cc_start_seq_get(context, id, &cursor); + ret = krb5_cc_start_seq_get(context, id, &cursor); + if (ret) + return ret; while((ret = krb5_cc_next_cred(context, id, &cursor, creds)) == 0){ if(krb5_compare_creds(context, whichfields, mcreds, creds)){ ret = 0; @@ -538,11 +619,15 @@ krb5_cc_retrieve_cred(krb5_context context, return ret; } -/* +/** * Return the principal of `id' in `principal'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_get_principal(krb5_context context, krb5_ccache id, @@ -551,12 +636,16 @@ krb5_cc_get_principal(krb5_context context, return (*id->ops->get_princ)(context, id, principal); } -/* +/** * Start iterating over `id', `cursor' is initialized to the * beginning. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_start_seq_get (krb5_context context, const krb5_ccache id, @@ -565,12 +654,16 @@ krb5_cc_start_seq_get (krb5_context context, return (*id->ops->get_first)(context, id, cursor); } -/* +/** * Retrieve the next cred pointed to by (`id', `cursor') in `creds' * and advance `cursor'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_next_cred (krb5_context context, const krb5_ccache id, @@ -580,7 +673,12 @@ krb5_cc_next_cred (krb5_context context, return (*id->ops->get_next)(context, id, cursor, creds); } -/* like krb5_cc_next_cred, but allow for selective retrieval */ +/** + * Like krb5_cc_next_cred, but allow for selective retrieval + * + * @ingroup krb5_ccache + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_next_cred_match(krb5_context context, @@ -601,10 +699,13 @@ krb5_cc_next_cred_match(krb5_context context, } } -/* +/** * Destroy the cursor `cursor'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_end_seq_get (krb5_context context, const krb5_ccache id, @@ -613,10 +714,13 @@ krb5_cc_end_seq_get (krb5_context context, return (*id->ops->end_get)(context, id, cursor); } -/* +/** * Remove the credential identified by `cred', `which' from `id'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_remove_cred(krb5_context context, krb5_ccache id, @@ -632,10 +736,13 @@ krb5_cc_remove_cred(krb5_context context, return (*id->ops->remove_cred)(context, id, which, cred); } -/* +/** * Set the flags of `id' to `flags'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_set_flags(krb5_context context, krb5_ccache id, @@ -644,10 +751,13 @@ krb5_cc_set_flags(krb5_context context, return (*id->ops->set_flags)(context, id, flags); } -/* +/** * Copy the contents of `from' to `to'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_copy_cache_match(krb5_context context, const krb5_ccache from, @@ -689,6 +799,13 @@ krb5_cc_copy_cache_match(krb5_context context, return ret; } +/** + * Just like krb5_cc_copy_cache_match, but copy everything. + * + * @ingroup krb5_ccache + */ + + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_copy_cache(krb5_context context, const krb5_ccache from, @@ -697,10 +814,13 @@ krb5_cc_copy_cache(krb5_context context, return krb5_cc_copy_cache_match(context, from, to, 0, NULL, NULL); } -/* +/** * Return the version of `id'. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_get_version(krb5_context context, const krb5_ccache id) @@ -711,23 +831,30 @@ krb5_cc_get_version(krb5_context context, return 0; } -/* +/** * Clear `mcreds' so it can be used with krb5_cc_retrieve_cred + * + * @ingroup krb5_ccache */ + void KRB5_LIB_FUNCTION krb5_cc_clear_mcred(krb5_creds *mcred) { memset(mcred, 0, sizeof(*mcred)); } -/* +/** * Get the cc ops that is registered in `context' to handle the * `prefix'. `prefix' can be a complete credential cache name or a * prefix, the function will only use part up to the first colon (:) - * if there is one. Returns NULL if ops not found. + * if there is one. + * Returns NULL if ops not found. + * + * @ingroup krb5_ccache */ + const krb5_cc_ops * krb5_cc_get_prefix_ops(krb5_context context, const char *prefix) { @@ -761,12 +888,16 @@ struct krb5_cc_cache_cursor_data { krb5_cc_cursor cursor; }; -/* +/** * Start iterating over all caches of `type'. If `type' is NULL, the * default type is * used. `cursor' is initialized to the beginning. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_cache_get_first (krb5_context context, const char *type, @@ -807,12 +938,16 @@ krb5_cc_cache_get_first (krb5_context context, return ret; } -/* +/** * Retrieve the next cache pointed to by (`cursor') in `id' * and advance `cursor'. - * Return 0 or an error code. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_cache_next (krb5_context context, krb5_cc_cache_cursor cursor, @@ -821,10 +956,15 @@ krb5_cc_cache_next (krb5_context context, return cursor->ops->get_cache_next(context, cursor->cursor, id); } -/* +/** * Destroy the cursor `cursor'. + * + * @return Return 0 or an error code. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_cache_end_seq_get (krb5_context context, krb5_cc_cache_cursor cursor) @@ -836,14 +976,18 @@ krb5_cc_cache_end_seq_get (krb5_context context, return ret; } -/* +/** * Search for a matching credential cache of type `type' that have the * `principal' as the default principal. If NULL is used for `type', * the default type is used. On success, `id' needs to be freed with - * krb5_cc_close or krb5_cc_destroy. On failure, error code is - * returned and `id' is set to NULL. + * krb5_cc_close or krb5_cc_destroy. + * + * @return On failure, error code is returned and `id' is set to NULL. + * + * @ingroup krb5_ccache */ + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_cache_match (krb5_context context, krb5_principal client, @@ -895,3 +1039,35 @@ krb5_cc_cache_match (krb5_context context, return 0; } +/** + * Move the content from one credential cache to another. The + * operation is an atomic switch. + * + * @param context a Keberos context + * @param from the credential cache to move the content from + * @param to the credential cache to move the content to + + * @return On sucess, from is freed. On failure, error code is + * returned and from and to are both still allocated. + * + * @ingroup krb5_ccache + */ + +krb5_error_code +krb5_cc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_error_code ret; + + if (strcmp(from->ops->prefix, to->ops->prefix) != 0) { + krb5_set_error_string(context, "Moving credentials between diffrent " + "types not yet supported"); + return KRB5_CC_NOSUPP; + } + + ret = (*to->ops->move)(context, from, to); + if (ret == 0) { + memset(from, 0, sizeof(*from)); + free(from); + } + return ret; +} diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index b54e293a60..256783310e 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -34,12 +34,19 @@ #include "krb5_locl.h" #include -RCSID("$Id: context.c 19107 2006-11-24 14:24:33Z lha $"); +RCSID("$Id: context.c 22293 2007-12-14 05:25:59Z lha $"); #define INIT_FIELD(C, T, E, D, F) \ (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ "libdefaults", F, NULL) +#define INIT_FLAG(C, O, V, D, F) \ + do { \ + if (krb5_config_get_bool_default((C), NULL, (D),"libdefaults", F, NULL)) { \ + (C)->O |= V; \ + } \ + } while(0) + /* * Set the list of etypes `ret_etypes' from the configuration variable * `name' @@ -181,11 +188,28 @@ init_context_from_config_file(krb5_context context) INIT_FIELD(context, bool, srv_lookup, TRUE, "srv_lookup"); INIT_FIELD(context, bool, srv_lookup, context->srv_lookup, "dns_lookup_kdc"); INIT_FIELD(context, int, large_msg_size, 1400, "large_message_size"); - INIT_FIELD(context, bool, dns_canonicalize_hostname, TRUE, "dns_canonicalize_hostname"); + INIT_FLAG(context, flags, KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME, TRUE, "dns_canonicalize_hostname"); + INIT_FLAG(context, flags, KRB5_CTX_F_CHECK_PAC, TRUE, "check_pac"); context->default_cc_name = NULL; + context->default_cc_name_set = 0; return 0; } +/** + * Initializes the context structure and reads the configuration file + * /etc/krb5.conf. The structure should be freed by calling + * krb5_free_context() when it is no longer being used. + * + * @param context pointer to returned context + * + * @return Returns 0 to indicate success. Otherwise an errno code is + * returned. Failure means either that something bad happened during + * initialization (typically ENOMEM) or that Kerberos should not be + * used ENXIO. + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_init_context(krb5_context *context) { @@ -246,11 +270,21 @@ out: return ret; } +/** + * Frees the krb5_context allocated by krb5_init_context(). + * + * @param context context to be freed. + * + * @ingroup krb5 +*/ + void KRB5_LIB_FUNCTION krb5_free_context(krb5_context context) { if (context->default_cc_name) free(context->default_cc_name); + if (context->default_cc_name_env) + free(context->default_cc_name_env); free(context->etypes); free(context->etypes_des); krb5_free_host_realm (context, context->default_realms); @@ -272,6 +306,18 @@ krb5_free_context(krb5_context context) free(context); } +/** + * Reinit the context from a new set of filenames. + * + * @param context context to add configuration too. + * @param filenames array of filenames, end of list is indicated with a NULL filename. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_set_config_files(krb5_context context, char **filenames) { @@ -324,7 +370,7 @@ add_file(char ***pfilenames, int *len, char *file) } /* - * `pq' isn't free, its up the the caller + * `pq' isn't free, it's up the the caller */ krb5_error_code KRB5_LIB_FUNCTION @@ -380,6 +426,18 @@ krb5_prepend_config_files(const char *filelist, char **pq, char ***ret_pp) return 0; } +/** + * Prepend the filename to the global configuration list. + * + * @param filelist a filename to add to the default list of filename + * @param pfilenames return array of filenames, should be freed with krb5_free_config_files(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_prepend_config_files_default(const char *filelist, char ***pfilenames) { @@ -399,6 +457,17 @@ krb5_prepend_config_files_default(const char *filelist, char ***pfilenames) return 0; } +/** + * Get the global configuration list. + * + * @param pfilenames return array of filenames, should be freed with krb5_free_config_files(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_get_default_config_files(char ***pfilenames) { @@ -414,6 +483,17 @@ krb5_get_default_config_files(char ***pfilenames) return krb5_prepend_config_files(files, NULL, pfilenames); } +/** + * Free a list of configuration files. + * + * @param filenames list to be freed. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_free_config_files(char **filenames) { @@ -423,12 +503,17 @@ krb5_free_config_files(char **filenames) free(filenames); } -/* +/** * Returns the list of Kerberos encryption types sorted in order of - * most preferred to least preferred encryption type. The array ends - * with ETYPE_NULL. Note that some encryption types might be - * disabled, so you need to check with krb5_enctype_valid() before - * using the encryption type. + * most preferred to least preferred encryption type. Note that some + * encryption types might be disabled, so you need to check with + * krb5_enctype_valid() before using the encryption type. + * + * @return list of enctypes, terminated with ETYPE_NULL. Its a static + * array completed into the Kerberos library so the content doesn't + * need to be freed. + * + * @ingroup krb5 */ const krb5_enctype * KRB5_LIB_FUNCTION @@ -479,6 +564,19 @@ default_etypes(krb5_context context, krb5_enctype **etype) return 0; } +/** + * Set the default encryption types that will be use in communcation + * with the KDC, clients and servers. + * + * @param context Kerberos 5 context. + * @param etypes Encryption types, array terminated with ETYPE_NULL (0). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_set_default_in_tkt_etypes(krb5_context context, const krb5_enctype *etypes) @@ -507,6 +605,19 @@ krb5_set_default_in_tkt_etypes(krb5_context context, return 0; } +/** + * Get the default encryption types that will be use in communcation + * with the KDC, clients and servers. + * + * @param context Kerberos 5 context. + * @param etypes Encryption types, array terminated with + * ETYPE_NULL(0), caller should free array with krb5_xfree(): + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ krb5_error_code KRB5_LIB_FUNCTION krb5_get_default_in_tkt_etypes(krb5_context context, @@ -534,6 +645,18 @@ krb5_get_default_in_tkt_etypes(krb5_context context, return 0; } +/** + * Return the error string for the error code. The caller must not + * free the string. + * + * @param context Kerberos 5 context. + * @param code Kerberos error code. + * + * @return the error message matching code + * + * @ingroup krb5 + */ + const char* KRB5_LIB_FUNCTION krb5_get_err_text(krb5_context context, krb5_error_code code) { @@ -547,6 +670,14 @@ krb5_get_err_text(krb5_context context, krb5_error_code code) return p; } +/** + * Init the built-in ets in the Kerberos library. + * + * @param context kerberos context to add the ets too + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_init_ets(krb5_context context) { @@ -561,18 +692,50 @@ krb5_init_ets(krb5_context context) } } +/** + * Make the kerberos library default to the admin KDC. + * + * @param context Kerberos 5 context. + * @param flag boolean flag to select if the use the admin KDC or not. + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_set_use_admin_kdc (krb5_context context, krb5_boolean flag) { context->use_admin_kdc = flag; } +/** + * Make the kerberos library default to the admin KDC. + * + * @param context Kerberos 5 context. + * + * @return boolean flag to telling the context will use admin KDC as the default KDC. + * + * @ingroup krb5 + */ + krb5_boolean KRB5_LIB_FUNCTION krb5_get_use_admin_kdc (krb5_context context) { return context->use_admin_kdc; } +/** + * Add extra address to the address list that the library will add to + * the client's address list when communicating with the KDC. + * + * @param context Kerberos 5 context. + * @param addresses addreses to add + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses) { @@ -584,6 +747,19 @@ krb5_add_extra_addresses(krb5_context context, krb5_addresses *addresses) return krb5_set_extra_addresses(context, addresses); } +/** + * Set extra address to the address list that the library will add to + * the client's address list when communicating with the KDC. + * + * @param context Kerberos 5 context. + * @param addresses addreses to set + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses) { @@ -607,6 +783,19 @@ krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses) return krb5_copy_addresses(context, addresses, context->extra_addresses); } +/** + * Get extra address to the address list that the library will add to + * the client's address list when communicating with the KDC. + * + * @param context Kerberos 5 context. + * @param addresses addreses to set + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses) { @@ -617,6 +806,19 @@ krb5_get_extra_addresses(krb5_context context, krb5_addresses *addresses) return krb5_copy_addresses(context,context->extra_addresses, addresses); } +/** + * Add extra addresses to ignore when fetching addresses from the + * underlaying operating system. + * + * @param context Kerberos 5 context. + * @param addresses addreses to ignore + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_add_ignore_addresses(krb5_context context, krb5_addresses *addresses) { @@ -628,6 +830,19 @@ krb5_add_ignore_addresses(krb5_context context, krb5_addresses *addresses) return krb5_set_ignore_addresses(context, addresses); } +/** + * Set extra addresses to ignore when fetching addresses from the + * underlaying operating system. + * + * @param context Kerberos 5 context. + * @param addresses addreses to ignore + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses) { @@ -650,6 +865,19 @@ krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses) return krb5_copy_addresses(context, addresses, context->ignore_addresses); } +/** + * Get extra addresses to ignore when fetching addresses from the + * underlaying operating system. + * + * @param context Kerberos 5 context. + * @param addresses list addreses ignored + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_get_ignore_addresses(krb5_context context, krb5_addresses *addresses) { @@ -660,6 +888,18 @@ krb5_get_ignore_addresses(krb5_context context, krb5_addresses *addresses) return krb5_copy_addresses(context, context->ignore_addresses, addresses); } +/** + * Set version of fcache that the library should use. + * + * @param context Kerberos 5 context. + * @param version version number. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_set_fcache_version(krb5_context context, int version) { @@ -667,6 +907,18 @@ krb5_set_fcache_version(krb5_context context, int version) return 0; } +/** + * Get version of fcache that the library should use. + * + * @param context Kerberos 5 context. + * @param version version number. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_get_fcache_version(krb5_context context, int *version) { @@ -674,6 +926,15 @@ krb5_get_fcache_version(krb5_context context, int *version) return 0; } +/** + * Runtime check if the Kerberos library was complied with thread support. + * + * @return TRUE if the library was compiled with thread support, FALSE if not. + * + * @ingroup krb5 + */ + + krb5_boolean KRB5_LIB_FUNCTION krb5_is_thread_safe(void) { @@ -684,18 +945,52 @@ krb5_is_thread_safe(void) #endif } +/** + * Set if the library should use DNS to canonicalize hostnames. + * + * @param context Kerberos 5 context. + * @param flag if its dns canonicalizion is used or not. + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_set_dns_canonicalize_hostname (krb5_context context, krb5_boolean flag) { - context->dns_canonicalize_hostname = flag; + if (flag) + context->flags |= KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME; + else + context->flags &= ~KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME; } +/** + * Get if the library uses DNS to canonicalize hostnames. + * + * @param context Kerberos 5 context. + * + * @return return non zero if the library uses DNS to canonicalize hostnames. + * + * @ingroup krb5 + */ + krb5_boolean KRB5_LIB_FUNCTION krb5_get_dns_canonicalize_hostname (krb5_context context) { - return context->dns_canonicalize_hostname; + return (context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) ? 1 : 0; } +/** + * Get current offset in time to the KDC. + * + * @param context Kerberos 5 context. + * @param sec seconds part of offset. + * @param usec micro seconds part of offset. + * + * @return return non zero if the library uses DNS to canonicalize hostnames. + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec) { @@ -706,12 +1001,31 @@ krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec) return 0; } +/** + * Get max time skew allowed. + * + * @param context Kerberos 5 context. + * + * @return timeskew in seconds. + * + * @ingroup krb5 + */ + time_t KRB5_LIB_FUNCTION krb5_get_max_time_skew (krb5_context context) { return context->max_skew; } +/** + * Set max time skew allowed. + * + * @param context Kerberos 5 context. + * @param t timeskew in seconds. + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_set_max_time_skew (krb5_context context, time_t t) { diff --git a/source4/heimdal/lib/krb5/convert_creds.c b/source4/heimdal/lib/krb5/convert_creds.c index 1d1b4d7070..b2af0187ea 100644 --- a/source4/heimdal/lib/krb5/convert_creds.c +++ b/source4/heimdal/lib/krb5/convert_creds.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: convert_creds.c 14897 2005-04-23 19:40:57Z lha $"); +RCSID("$Id: convert_creds.c 22050 2007-11-11 11:20:46Z lha $"); #include "krb5-v4compat.h" @@ -42,10 +42,20 @@ check_ticket_flags(TicketFlags f) return 0; /* maybe add some more tests here? */ } -/* Convert the v5 credentials in `in_cred' to v4-dito in `v4creds'. - * This is done by sending them to the 524 function in the KDC. If +/** + * Convert the v5 credentials in in_cred to v4-dito in v4creds. This + * is done by sending them to the 524 function in the KDC. If * `in_cred' doesn't contain a DES session key, then a new one is * gotten from the KDC and stored in the cred cache `ccache'. + * + * @param context Kerberos 5 context. + * @param in_cred the credential to convert + * @param v4creds the converted credential + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5_v4compat */ krb5_error_code KRB5_LIB_FUNCTION @@ -134,6 +144,21 @@ out2: return ret; } +/** + * Convert the v5 credentials in in_cred to v4-dito in v4creds, + * check the credential cache ccache before checking with the KDC. + * + * @param context Kerberos 5 context. + * @param ccache credential cache used to check for des-ticket. + * @param in_cred the credential to convert + * @param v4creds the converted credential + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5_v4compat + */ + krb5_error_code KRB5_LIB_FUNCTION krb524_convert_creds_kdc_ccache(krb5_context context, krb5_ccache ccache, diff --git a/source4/heimdal/lib/krb5/copy_host_realm.c b/source4/heimdal/lib/krb5/copy_host_realm.c index 4e668c2a14..8c4f39b4ac 100644 --- a/source4/heimdal/lib/krb5/copy_host_realm.c +++ b/source4/heimdal/lib/krb5/copy_host_realm.c @@ -33,10 +33,19 @@ #include "krb5_locl.h" -RCSID("$Id: copy_host_realm.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id: copy_host_realm.c 22057 2007-11-11 15:13:13Z lha $"); -/* +/** * Copy the list of realms from `from' to `to'. + * + * @param context Kerberos 5 context. + * @param from list of realms to copy from. + * @param to list of realms to copy to, free list of krb5_free_host_realm(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 */ krb5_error_code KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/creds.c b/source4/heimdal/lib/krb5/creds.c index d4d83162f1..17ef46dfa3 100644 --- a/source4/heimdal/lib/krb5/creds.c +++ b/source4/heimdal/lib/krb5/creds.c @@ -33,15 +33,30 @@ #include "krb5_locl.h" -RCSID("$Id: creds.c 15167 2005-05-18 04:21:57Z lha $"); +RCSID("$Id: creds.c 22062 2007-11-11 15:41:50Z lha $"); + +#undef __attribute__ +#define __attribute__(X) /* keep this for compatibility with older code */ -krb5_error_code KRB5_LIB_FUNCTION +krb5_error_code KRB5_LIB_FUNCTION __attribute__((deprecated)) krb5_free_creds_contents (krb5_context context, krb5_creds *c) { return krb5_free_cred_contents (context, c); } +/** + * Free content of krb5_creds. + * + * @param context Kerberos 5 context. + * @param c krb5_creds to free. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_free_cred_contents (krb5_context context, krb5_creds *c) { @@ -58,6 +73,19 @@ krb5_free_cred_contents (krb5_context context, krb5_creds *c) return 0; } +/** + * Copy content of krb5_creds. + * + * @param context Kerberos 5 context. + * @param incred source credential + * @param c destination credential, free with krb5_free_cred_contents(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_copy_creds_contents (krb5_context context, const krb5_creds *incred, @@ -102,6 +130,19 @@ fail: return ret; } +/** + * Copy krb5_creds. + * + * @param context Kerberos 5 context. + * @param incred source credential + * @param outcred destination credential, free with krb5_free_creds(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_copy_creds (krb5_context context, const krb5_creds *incred, @@ -119,6 +160,18 @@ krb5_copy_creds (krb5_context context, return krb5_copy_creds_contents (context, incred, c); } +/** + * Free krb5_creds. + * + * @param context Kerberos 5 context. + * @param c krb5_creds to free. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_free_creds (krb5_context context, krb5_creds *c) { @@ -127,15 +180,7 @@ krb5_free_creds (krb5_context context, krb5_creds *c) return 0; } -/* XXX these do not belong here */ -static krb5_boolean -krb5_data_equal(const krb5_data *a, const krb5_data *b) -{ - if(a->length != b->length) - return FALSE; - return memcmp(a->data, b->data, a->length) == 0; -} - +/* XXX this do not belong here */ static krb5_boolean krb5_times_equal(const krb5_times *a, const krb5_times *b) { @@ -145,9 +190,18 @@ krb5_times_equal(const krb5_times *a, const krb5_times *b) a->renew_till == b->renew_till; } -/* +/** * Return TRUE if `mcreds' and `creds' are equal (`whichfields' * determines what equal means). + * + * @param context Kerberos 5 context. + * @param whichfields which fields to compare. + * @param mcreds cred to compare with. + * @param creds cred to compare with. + * + * @return return TRUE if mcred and creds are equal, FALSE if not. + * + * @ingroup krb5 */ krb5_boolean KRB5_LIB_FUNCTION @@ -201,11 +255,11 @@ krb5_compare_creds(krb5_context context, krb5_flags whichfields, for(i = 0; match && i < mcreds->authdata.len; i++) match = (mcreds->authdata.val[i].ad_type == creds->authdata.val[i].ad_type) && - krb5_data_equal(&mcreds->authdata.val[i].ad_data, - &creds->authdata.val[i].ad_data); + (krb5_data_cmp(&mcreds->authdata.val[i].ad_data, + &creds->authdata.val[i].ad_data) == 0); } if (match && (whichfields & KRB5_TC_MATCH_2ND_TKT)) - match = krb5_data_equal(&mcreds->second_ticket, &creds->second_ticket); + match = (krb5_data_cmp(&mcreds->second_ticket, &creds->second_ticket) == 0); if (match && (whichfields & KRB5_TC_MATCH_IS_SKEY)) match = ((mcreds->second_ticket.length == 0) == diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 12f75d0bcd..2e63490946 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c 21130 2007-06-18 20:45:21Z lha $"); +RCSID("$Id: crypto.c 22200 2007-12-07 13:48:01Z lha $"); #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -184,7 +184,7 @@ krb5_DES_schedule(krb5_context context, #ifdef ENABLE_AFS_STRING_TO_KEY /* This defines the Andrew string_to_key function. It accepts a password - * string as input and converts its via a one-way encryption algorithm to a DES + * string as input and converts it via a one-way encryption algorithm to a DES * encryption key. It is compatible with the original Andrew authentication * service password database. */ @@ -425,6 +425,7 @@ DES3_string_to_key(krb5_context context, size_t len; unsigned char tmp[24]; DES_cblock keys[3]; + krb5_error_code ret; len = password.length + salt.saltvalue.length; str = malloc(len); @@ -439,7 +440,13 @@ DES3_string_to_key(krb5_context context, DES_key_schedule s[3]; int i; - _krb5_n_fold(str, len, tmp, 24); + ret = _krb5_n_fold(str, len, tmp, 24); + if (ret) { + memset(str, 0, len); + free(str); + krb5_set_error_string(context, "out of memory"); + return ret; + } for(i = 0; i < 3; i++){ memcpy(keys + i, tmp + i * 8, sizeof(keys[i])); @@ -557,12 +564,14 @@ ARCFOUR_string_to_key(krb5_context context, size_t len; int i; MD4_CTX m; + krb5_error_code ret; len = 2 * password.length; s = malloc (len); if (len != 0 && s == NULL) { krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; + ret = ENOMEM; + goto out; } for (p = s, i = 0; i < password.length; ++i) { *p++ = ((char *)password.data)[i]; @@ -571,11 +580,17 @@ ARCFOUR_string_to_key(krb5_context context, MD4_Init (&m); MD4_Update (&m, s, len); key->keytype = enctype; - krb5_data_alloc (&key->keyvalue, 16); + ret = krb5_data_alloc (&key->keyvalue, 16); + if (ret) { + krb5_set_error_string(context, "malloc: out of memory"); + goto out; + } MD4_Final (key->keyvalue.data, &m); memset (s, 0, len); + ret = 0; +out: free (s); - return 0; + return ret; } /* @@ -1829,7 +1844,9 @@ create_checksum (krb5_context context, } else dkey = NULL; result->cksumtype = ct->type; - krb5_data_alloc(&result->checksum, ct->checksumsize); + ret = krb5_data_alloc(&result->checksum, ct->checksumsize); + if (ret) + return (ret); (*ct->checksum)(context, dkey, data, len, usage, result); return 0; } @@ -2751,6 +2768,7 @@ krb5_enctype_to_string(krb5_context context, if(e == NULL) { krb5_set_error_string (context, "encryption type %d not supported", etype); + *string = NULL; return KRB5_PROG_ETYPE_NOSUPP; } *string = strdup(e->name); @@ -3525,15 +3543,19 @@ derive_key(krb5_context context, ret = _key_schedule(context, key); if(ret) return ret; - if(et->blocksize * 8 < kt->bits || - len != et->blocksize) { + if(et->blocksize * 8 < kt->bits || len != et->blocksize) { nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8); k = malloc(nblocks * et->blocksize); if(k == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - _krb5_n_fold(constant, len, k, et->blocksize); + ret = _krb5_n_fold(constant, len, k, et->blocksize); + if (ret) { + free(k); + krb5_set_error_string(context, "out of memory"); + return ret; + } for(i = 0; i < nblocks; i++) { if(i > 0) memcpy(k + i * et->blocksize, @@ -3559,7 +3581,12 @@ derive_key(krb5_context context, krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } - _krb5_n_fold(c, len, k, res_len); + ret = _krb5_n_fold(c, len, k, res_len); + if (ret) { + free(k); + krb5_set_error_string(context, "out of memory"); + return ret; + } free(c); } @@ -3821,7 +3848,12 @@ krb5_string_to_key_derived(krb5_context context, krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } - _krb5_n_fold(str, len, tmp, keylen); + ret = _krb5_n_fold(str, len, tmp, keylen); + if (ret) { + free(tmp); + krb5_set_error_string(context, "out of memory"); + return ret; + } kd.schedule = NULL; DES3_postproc (context, tmp, keylen, &kd); /* XXX */ memset(tmp, 0, keylen); @@ -4122,7 +4154,7 @@ main() d = _new_derived_key(crypto, usage); if(d == NULL) - return ENOMEM; + krb5_errx(context, 1, "_new_derived_key failed"); krb5_copy_keyblock(context, crypto->key.key, &d->key); _krb5_put_int(constant, usage, 4); derive_key(context, crypto->et, d, constant, sizeof(constant)); @@ -4148,11 +4180,10 @@ main() "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */ key.keyvalue.length = 4; - d = calloc(1, sizeof(*d)); - + d = ecalloc(1, sizeof(*d)); d->key = &key; res.checksum.length = 20; - res.checksum.data = malloc(res.checksum.length); + res.checksum.data = emalloc(res.checksum.length); SP_HMAC_SHA1_checksum(context, d, data, 28, &res); return 0; diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c index 2ece85bdb3..eda1a8b259 100644 --- a/source4/heimdal/lib/krb5/data.c +++ b/source4/heimdal/lib/krb5/data.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,15 @@ #include "krb5_locl.h" -RCSID("$Id: data.c 20039 2007-01-23 20:34:01Z lha $"); +RCSID("$Id: data.c 22064 2007-11-11 16:28:14Z lha $"); + +/** + * Reset the (potentially uninitalized) krb5_data structure. + * + * @param p krb5_data to reset. + * + * @ingroup krb5 + */ void KRB5_LIB_FUNCTION krb5_data_zero(krb5_data *p) @@ -42,6 +50,15 @@ krb5_data_zero(krb5_data *p) p->data = NULL; } +/** + * Free the content of krb5_data structure, its ok to free a zeroed + * structure. When done, the structure will be zeroed. + * + * @param p krb5_data to free. + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_data_free(krb5_data *p) { @@ -50,12 +67,30 @@ krb5_data_free(krb5_data *p) krb5_data_zero(p); } +/** + * Same as krb5_data_free(). + * + * @param context Kerberos 5 context. + * @param data krb5_data to free. + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_free_data_contents(krb5_context context, krb5_data *data) { krb5_data_free(data); } +/** + * Free krb5_data (and its content). + * + * @param context Kerberos 5 context. + * @param p krb5_data to free. + * + * @ingroup krb5 + */ + void KRB5_LIB_FUNCTION krb5_free_data(krb5_context context, krb5_data *p) @@ -64,6 +99,18 @@ krb5_free_data(krb5_context context, free(p); } +/** + * Allocate data of and krb5_data. + * + * @param p krb5_data to free. + * @param len size to allocate. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned. + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_data_alloc(krb5_data *p, int len) { @@ -74,6 +121,18 @@ krb5_data_alloc(krb5_data *p, int len) return 0; } +/** + * Grow (or shrink) the content of krb5_data to a new size. + * + * @param p krb5_data to free. + * @param len new size. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned. + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_data_realloc(krb5_data *p, int len) { @@ -86,6 +145,19 @@ krb5_data_realloc(krb5_data *p, int len) return 0; } +/** + * Copy the data of len into the krb5_data. + * + * @param p krb5_data to copy into. + * @param data data to copy.. + * @param len new size. + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned. + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_data_copy(krb5_data *p, const void *data, size_t len) { @@ -99,6 +171,19 @@ krb5_data_copy(krb5_data *p, const void *data, size_t len) return 0; } +/** + * Copy the data into a newly allocated krb5_data. + * + * @param context Kerberos 5 context. + * @param indata the krb5_data data to copy + * @param outdata new krb5_date to copy too. Free with krb5_free_data(). + * + * @return Returns 0 to indicate success. Otherwise an kerberos et + * error code is returned. + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_copy_data(krb5_context context, const krb5_data *indata, @@ -119,6 +204,17 @@ krb5_copy_data(krb5_context context, return ret; } +/** + * Compare to data. + * + * @param data1 krb5_data to compare + * @param data2 krb5_data to compare + * + * @return return the same way as memcmp(), useful when sorting. + * + * @ingroup krb5 + */ + int KRB5_LIB_FUNCTION krb5_data_cmp(const krb5_data *data1, const krb5_data *data2) { diff --git a/source4/heimdal/lib/krb5/eai_to_heim_errno.c b/source4/heimdal/lib/krb5/eai_to_heim_errno.c index c6b5cfb18b..19315cea86 100644 --- a/source4/heimdal/lib/krb5/eai_to_heim_errno.c +++ b/source4/heimdal/lib/krb5/eai_to_heim_errno.c @@ -33,12 +33,17 @@ #include -RCSID("$Id: eai_to_heim_errno.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id: eai_to_heim_errno.c 22065 2007-11-11 16:41:06Z lha $"); -/* - * convert the getaddrinfo error code in `eai_errno' into a - * krb5_error_code. `system_error' should have the value of the errno - * after the failed call. +/** + * Convert the getaddrinfo() error code to a Kerberos et error code. + * + * @param eai_errno contains the error code from getaddrinfo(). + * @param system_error should have the value of errno after the failed getaddrinfo(). + * + * @return Kerberos error code representing the EAI errors. + * + * @ingroup krb5_error */ krb5_error_code KRB5_LIB_FUNCTION @@ -78,6 +83,17 @@ krb5_eai_to_heim_errno(int eai_errno, int system_error) } } +/** + * Convert the gethostname() error code (h_error) to a Kerberos et + * error code. + * + * @param eai_errno contains the error code from gethostname(). + * + * @return Kerberos error code representing the gethostname errors. + * + * @ingroup krb5_error + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_h_errno_to_heim_errno(int eai_errno) { diff --git a/source4/heimdal/lib/krb5/error_string.c b/source4/heimdal/lib/krb5/error_string.c index 1ba6494487..ff6e98a3dc 100644 --- a/source4/heimdal/lib/krb5/error_string.c +++ b/source4/heimdal/lib/krb5/error_string.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: error_string.c 16746 2006-02-16 07:49:23Z lha $"); +RCSID("$Id: error_string.c 22142 2007-12-04 16:56:02Z lha $"); #undef __attribute__ #define __attribute__(X) @@ -86,14 +86,26 @@ krb5_vset_error_string(krb5_context context, const char *fmt, va_list args) return 0; } +/** + * Return the error message in context. On error or no error string, + * the function returns NULL. + * + * @param context Kerberos 5 context + * + * @return an error string, needs to be freed with + * krb5_free_error_string(). The functions return NULL on error. + * + * @ingroup krb5_error + */ + char * KRB5_LIB_FUNCTION krb5_get_error_string(krb5_context context) { - char *ret; + char *ret = NULL; HEIMDAL_MUTEX_lock(context->mutex); - ret = context->error_string; - context->error_string = NULL; + if (context->error_string) + ret = strdup(context->error_string); HEIMDAL_MUTEX_unlock(context->mutex); return ret; } @@ -108,6 +120,19 @@ krb5_have_error_string(krb5_context context) return str != NULL; } +/** + * Return the error message for `code' in context. On error the + * function returns NULL. + * + * @param context Kerberos 5 context + * @param code Error code related to the error + * + * @return an error string, needs to be freed with + * krb5_free_error_string(). The functions return NULL on error. + * + * @ingroup krb5_error + */ + char * KRB5_LIB_FUNCTION krb5_get_error_message(krb5_context context, krb5_error_code code) { diff --git a/source4/heimdal/lib/krb5/expand_hostname.c b/source4/heimdal/lib/krb5/expand_hostname.c index b2b410269e..28e39afb42 100644 --- a/source4/heimdal/lib/krb5/expand_hostname.c +++ b/source4/heimdal/lib/krb5/expand_hostname.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: expand_hostname.c 18906 2006-11-04 03:34:57Z lha $"); +RCSID("$Id: expand_hostname.c 22229 2007-12-08 21:40:59Z lha $"); static krb5_error_code copy_hostname(krb5_context context, @@ -62,7 +62,7 @@ krb5_expand_hostname (krb5_context context, struct addrinfo *ai, *a, hints; int error; - if (!context->dns_canonicalize_hostname) + if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0) return copy_hostname (context, orig_hostname, new_hostname); memset (&hints, 0, sizeof(hints)); @@ -127,7 +127,7 @@ krb5_expand_hostname_realms (krb5_context context, int error; krb5_error_code ret = 0; - if (!context->dns_canonicalize_hostname) + if ((context->flags & KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME) == 0) return vanilla_hostname (context, orig_hostname, new_hostname, realms); diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c index 864efa8d7d..484df059ab 100644 --- a/source4/heimdal/lib/krb5/fcache.c +++ b/source4/heimdal/lib/krb5/fcache.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2004 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: fcache.c 19379 2006-12-15 21:35:52Z lha $"); +RCSID("$Id: fcache.c 22517 2008-01-24 11:45:51Z lha $"); typedef struct krb5_fcache{ char *filename; @@ -108,7 +108,7 @@ int _krb5_xunlock(krb5_context context, int fd) { int ret; -#ifdef HAVE_FCNTL_LOCK +#ifdef HAVE_FCNTL struct flock l; l.l_start = 0; l.l_len = 0; @@ -463,9 +463,13 @@ init_fcc (krb5_context context, krb5_storage_set_eof_code(sp, KRB5_CC_END); ret = krb5_ret_int8(sp, &pvno); if(ret != 0) { - if(ret == KRB5_CC_END) - ret = ENOENT; /* empty file */ - krb5_clear_error_string(context); + if(ret == KRB5_CC_END) { + krb5_set_error_string(context, "Empty credential cache file: %s", + FILENAME(id)); + ret = ENOENT; + } else + krb5_set_error_string(context, "Error reading pvno in " + "cache file: %s", FILENAME(id)); goto out; } if(pvno != 5) { @@ -476,7 +480,8 @@ init_fcc (krb5_context context, } ret = krb5_ret_int8(sp, &tag); /* should not be host byte order */ if(ret != 0) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading tag in " + "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; goto out; } @@ -489,7 +494,8 @@ init_fcc (krb5_context context, ret = krb5_ret_int16 (sp, &length); if(ret) { ret = KRB5_CC_FORMAT; - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading tag length in " + "cache file: %s", FILENAME(id)); goto out; } while(length > 0) { @@ -499,13 +505,15 @@ init_fcc (krb5_context context, ret = krb5_ret_int16 (sp, &dtag); if(ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading dtag in " + "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; goto out; } ret = krb5_ret_int16 (sp, &data_len); if(ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading dlength in " + "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; goto out; } @@ -513,13 +521,15 @@ init_fcc (krb5_context context, case FCC_TAG_DELTATIME : ret = krb5_ret_int32 (sp, &context->kdc_sec_offset); if(ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading kdc_sec in " + "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; goto out; } ret = krb5_ret_int32 (sp, &context->kdc_usec_offset); if(ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading kdc_usec in " + "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; goto out; } @@ -528,7 +538,9 @@ init_fcc (krb5_context context, for (i = 0; i < data_len; ++i) { ret = krb5_ret_int8 (sp, &dummy); if(ret) { - krb5_clear_error_string(context); + krb5_set_error_string(context, "Error reading unknown " + "tag in cache file: %s", + FILENAME(id)); ret = KRB5_CC_FORMAT; goto out; } @@ -755,6 +767,95 @@ fcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) return 0; } +static krb5_error_code +fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_error_code ret = 0; + + ret = rename(FILENAME(from), FILENAME(to)); + if (ret && errno != EXDEV) { + ret = errno; + krb5_set_error_string(context, + "Rename of file from %s to %s failed: %s", + FILENAME(from), FILENAME(to), + strerror(ret)); + return ret; + } else if (ret && errno == EXDEV) { + /* make a copy and delete the orignal */ + krb5_ssize_t sz1, sz2; + int fd1, fd2; + char buf[BUFSIZ]; + + ret = fcc_open(context, from, &fd1, O_RDONLY | O_BINARY, 0); + if(ret) + return ret; + + unlink(FILENAME(to)); + + ret = fcc_open(context, to, &fd2, + O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600); + if(ret) + goto out1; + + while((sz1 = read(fd1, buf, sizeof(buf))) > 0) { + sz2 = write(fd2, buf, sz1); + if (sz1 != sz2) { + ret = EIO; + krb5_set_error_string(context, + "Failed to write data from one file " + "credential cache to the other"); + goto out2; + } + } + if (sz1 < 0) { + ret = EIO; + krb5_set_error_string(context, + "Failed to read data from one file " + "credential cache to the other"); + goto out2; + } + erase_file(FILENAME(from)); + + out2: + fcc_unlock(context, fd2); + close(fd2); + + out1: + fcc_unlock(context, fd1); + close(fd1); + + if (ret) { + erase_file(FILENAME(to)); + return ret; + } + } + + /* make sure ->version is uptodate */ + { + krb5_storage *sp; + int fd; + ret = init_fcc (context, to, &sp, &fd); + krb5_storage_free(sp); + fcc_unlock(context, fd); + close(fd); + } + return ret; +} + +static krb5_error_code +fcc_default_name(krb5_context context, char **str) +{ + return _krb5_expand_default_cc_name(context, + KRB5_DEFAULT_CCNAME_FILE, + str); +} + +/** + * Variable containing the FILE based credential cache implemention. + * + * @ingroup krb5_ccache + */ + const krb5_cc_ops krb5_fcc_ops = { "FILE", fcc_get_name, @@ -774,5 +875,7 @@ const krb5_cc_ops krb5_fcc_ops = { fcc_get_version, fcc_get_cache_first, fcc_get_cache_next, - fcc_end_cache_get + fcc_end_cache_get, + fcc_move, + fcc_default_name }; diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 7c3f128ae5..fc78945c63 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_cred.c 21669 2007-07-22 11:29:13Z lha $"); +RCSID("$Id: get_cred.c 22530 2008-01-27 11:48:16Z lha $"); /* * Take the `body' and encode it into `padata' using the credentials @@ -761,14 +761,6 @@ get_cred_from_kdc_flags(krb5_context context, try_realm = krb5_config_get_string(context, NULL, "capaths", client_realm, server_realm, NULL); - -#if 1 - /* XXX remove in future release */ - if(try_realm == NULL) - try_realm = krb5_config_get_string(context, NULL, "libdefaults", - "capath", server_realm, NULL); -#endif - if (try_realm == NULL) try_realm = client_realm; diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index 1bb98737d1..cb8b7c8641 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_for_creds.c 17036 2006-04-10 09:28:15Z lha $"); +RCSID("$Id: get_for_creds.c 22504 2008-01-21 15:49:58Z lha $"); static krb5_error_code add_addrs(krb5_context context, @@ -83,11 +83,23 @@ fail: return ret; } -/* - * Forward credentials for `client' to host `hostname`, - * making them forwardable if `forwardable', and returning the - * blob of data to sent in `out_data'. - * If hostname == NULL, pick it from `server' +/** + * Forward credentials for client to host hostname , making them + * forwardable if forwardable, and returning the blob of data to sent + * in out_data. If hostname == NULL, pick it from server. + * + * @param context A kerberos 5 context. + * @param auth_context the auth context with the key to encrypt the out_data. + * @param hostname the host to forward the tickets too. + * @param client the client to delegate from. + * @param server the server to delegate the credential too. + * @param ccache credential cache to use. + * @param forwardable make the forwarded ticket forwabledable. + * @param out_data the resulting credential. + * + * @return Return an error code or 0. + * + * @ingroup krb5_credential */ krb5_error_code KRB5_LIB_FUNCTION @@ -147,8 +159,31 @@ krb5_fwd_tgt_creds (krb5_context context, return ret; } -/* +/** + * Gets tickets forwarded to hostname. If the tickets that are + * forwarded are address-less, the forwarded tickets will also be + * address-less. + * + * If the ticket have any address, hostname will be used for figure + * out the address to forward the ticket too. This since this might + * use DNS, its insecure and also doesn't represent configured all + * addresses of the host. For example, the host might have two + * adresses, one IPv4 and one IPv6 address where the later is not + * published in DNS. This IPv6 address might be used communications + * and thus the resulting ticket useless. * + * @param context A kerberos 5 context. + * @param auth_context the auth context with the key to encrypt the out_data. + * @param ccache credential cache to use + * @param flags the flags to control the resulting ticket flags + * @param hostname the host to forward the tickets too. + * @param in_creds the in client and server ticket names. The client + * and server components forwarded to the remote host. + * @param out_data the resulting credential. + * + * @return Return an error code or 0. + * + * @ingroup krb5_credential */ krb5_error_code KRB5_LIB_FUNCTION @@ -174,39 +209,31 @@ krb5_get_forwarded_creds (krb5_context context, struct addrinfo *ai; int save_errno; krb5_creds *ticket; - char *realm; - - realm = in_creds->client->realm; + paddrs = NULL; addrs.len = 0; addrs.val = NULL; - paddrs = &addrs; - { + ret = krb5_get_credentials(context, 0, ccache, in_creds, &ticket); + if(ret == 0) { + if (ticket->addresses.len) + paddrs = &addrs; + krb5_free_creds (context, ticket); + } else { krb5_boolean noaddr; - krb5_appdefault_boolean(context, NULL, realm, + krb5_appdefault_boolean(context, NULL, + krb5_principal_get_realm(context, + in_creds->client), "no-addresses", KRB5_ADDRESSLESS_DEFAULT, &noaddr); - if (noaddr) - paddrs = NULL; + if (!noaddr) + paddrs = &addrs; } /* - * If tickets are address-less, forward address-less tickets. + * If tickets have addresses, get the address of the remote host. */ - if (paddrs) { - ret = _krb5_get_krbtgt (context, - ccache, - realm, - &ticket); - if(ret == 0) { - if (ticket->addresses.len == 0) - paddrs = NULL; - krb5_free_creds (context, ticket); - } - } - if (paddrs != NULL) { ret = getaddrinfo (hostname, NULL, NULL, &ai); @@ -233,9 +260,8 @@ krb5_get_forwarded_creds (krb5_context context, in_creds, &out_creds); krb5_free_addresses (context, &addrs); - if (ret) { + if (ret) return ret; - } memset (&cred, 0, sizeof(cred)); cred.pvno = 5; @@ -373,6 +399,14 @@ krb5_get_forwarded_creds (krb5_context context, if(buf_size != len) krb5_abortx(context, "internal error in ASN.1 encoder"); + /** + * Some older of the MIT gssapi library used clear-text tickets + * (warped inside AP-REQ encryption), use the krb5_auth_context + * flag KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED to support those + * tickets. The session key is used otherwise to encrypt the + * forwarded ticket. + */ + if (auth_context->flags & KRB5_AUTH_CONTEXT_CLEAR_FORWARDED_CRED) { cred.enc_part.etype = ENCTYPE_NULL; cred.enc_part.kvno = NULL; diff --git a/source4/heimdal/lib/krb5/get_in_tkt.c b/source4/heimdal/lib/krb5/get_in_tkt.c index ec106bb7ec..a9ed3857d0 100644 --- a/source4/heimdal/lib/krb5/get_in_tkt.c +++ b/source4/heimdal/lib/krb5/get_in_tkt.c @@ -145,7 +145,7 @@ _krb5_extract_ticket(krb5_context context, flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; flags |=EXTRACT_TICKET_ALLOW_CNAME_MISMATCH ; - ret = _krb5_principalname2krb5_principal (context, + ret = _krb5_principalname2krb5_principal (context, &tmp_principal, rep->kdc_rep.cname, rep->kdc_rep.crealm); diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index bd250cef2b..a59c903bd9 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c 21712 2007-07-27 14:23:41Z lha $"); +RCSID("$Id: init_creds.c 21711 2007-07-27 14:22:02Z lha $"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 0043b5ef3c..441adff8fd 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c 21428 2007-07-10 12:31:58Z lha $"); +RCSID("$Id: init_creds_pw.c 21931 2007-08-27 14:11:55Z lha $"); typedef struct krb5_get_init_creds_ctx { KDCOptions flags; @@ -1547,9 +1547,15 @@ krb5_get_init_creds_password(krb5_context context, char buf[BUFSIZ]; krb5_error_code ret; - if (in_options == NULL) + if (in_options == NULL) { + const char *realm = krb5_principal_get_realm(context, client); ret = krb5_get_init_creds_opt_alloc(context, &options); - else + if (ret == 0) + krb5_get_init_creds_opt_set_default_flags(context, + NULL, + realm, + options); + } else ret = _krb5_get_init_creds_opt_copy(context, in_options, &options); if (ret) return ret; diff --git a/source4/heimdal/lib/krb5/kcm.c b/source4/heimdal/lib/krb5/kcm.c index c945a9ce13..8afaa6ea80 100644 --- a/source4/heimdal/lib/krb5/kcm.c +++ b/source4/heimdal/lib/krb5/kcm.c @@ -43,7 +43,7 @@ #include "kcm.h" -RCSID("$Id: kcm.c 17442 2006-05-05 09:31:15Z lha $"); +RCSID("$Id: kcm.c 22108 2007-12-03 17:23:53Z lha $"); typedef struct krb5_kcmcache { char *name; @@ -829,6 +829,27 @@ kcm_get_version(krb5_context context, return 0; } +static krb5_error_code +kcm_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_set_error_string(context, "kcm_move not implemented"); + return EINVAL; +} + +static krb5_error_code +kcm_default_name(krb5_context context, char **str) +{ + return _krb5_expand_default_cc_name(context, + KRB5_DEFAULT_CCNAME_KCM, + str); +} + +/** + * Variable containing the KCM based credential cache implemention. + * + * @ingroup krb5_ccache + */ + const krb5_cc_ops krb5_kcm_ops = { "KCM", kcm_get_name, @@ -845,7 +866,12 @@ const krb5_cc_ops krb5_kcm_ops = { kcm_end_get, kcm_remove_cred, kcm_set_flags, - kcm_get_version + kcm_get_version, + NULL, + NULL, + NULL, + kcm_move, + kcm_default_name }; krb5_boolean diff --git a/source4/heimdal/lib/krb5/keytab.c b/source4/heimdal/lib/krb5/keytab.c index f6c7858c12..79a3f20e79 100644 --- a/source4/heimdal/lib/krb5/keytab.c +++ b/source4/heimdal/lib/krb5/keytab.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab.c 20211 2007-02-09 07:11:03Z lha $"); +RCSID("$Id: keytab.c 22532 2008-01-27 11:59:18Z lha $"); /* * Register a new keytab in `ops' @@ -337,8 +337,9 @@ krb5_kt_get_entry(krb5_context context, ret = krb5_kt_start_seq_get (context, id, &cursor); if (ret) { - krb5_clear_error_string(context); - return KRB5_KT_NOTFOUND; /* XXX i.e. file not found */ + /* This is needed for krb5_verify_init_creds, but keep error + * string from previous error for the human. */ + return KRB5_KT_NOTFOUND; } entry->vno = 0; diff --git a/source4/heimdal/lib/krb5/keytab_file.c b/source4/heimdal/lib/krb5/keytab_file.c index 4ada3a463e..be195d96c2 100644 --- a/source4/heimdal/lib/krb5/keytab_file.c +++ b/source4/heimdal/lib/krb5/keytab_file.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_file.c 17457 2006-05-05 12:36:57Z lha $"); +RCSID("$Id: keytab_file.c 22532 2008-01-27 11:59:18Z lha $"); #define KRB5_KT_VNO_1 1 #define KRB5_KT_VNO_2 2 @@ -334,8 +334,8 @@ fkt_start_seq_get_int(krb5_context context, c->fd = open (d->filename, flags); if (c->fd < 0) { ret = errno; - krb5_set_error_string(context, "%s: %s", d->filename, - strerror(ret)); + krb5_set_error_string(context, "keytab %s open failed: %s", + d->filename, strerror(ret)); return ret; } ret = _krb5_xlock(context, c->fd, exclusive, d->filename); diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c index 77455ba5f7..aa612add09 100644 --- a/source4/heimdal/lib/krb5/keytab_keyfile.c +++ b/source4/heimdal/lib/krb5/keytab_keyfile.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_keyfile.c 20695 2007-05-30 14:09:09Z lha $"); +RCSID("$Id: keytab_keyfile.c 22532 2008-01-27 11:59:18Z lha $"); /* afs keyfile operations --------------------------------------- */ @@ -197,8 +197,8 @@ akf_start_seq_get(krb5_context context, c->fd = open (d->filename, O_RDONLY|O_BINARY, 0600); if (c->fd < 0) { ret = errno; - krb5_set_error_string(context, "open(%s): %s", d->filename, - strerror(ret)); + krb5_set_error_string(context, "keytab afs keyfil open %s failed: %s", + d->filename, strerror(ret)); return ret; } diff --git a/source4/heimdal/lib/krb5/keytab_krb4.c b/source4/heimdal/lib/krb5/keytab_krb4.c index 907836c144..32bb00141a 100644 --- a/source4/heimdal/lib/krb5/keytab_krb4.c +++ b/source4/heimdal/lib/krb5/keytab_krb4.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_krb4.c 17046 2006-04-10 17:10:53Z lha $"); +RCSID("$Id: keytab_krb4.c 22532 2008-01-27 11:59:18Z lha $"); struct krb4_kt_data { char *filename; @@ -134,14 +134,15 @@ krb4_kt_start_seq_get_int (krb5_context context, if (c->fd < 0) { ret = errno; free (ed); - krb5_set_error_string(context, "open(%s): %s", d->filename, - strerror(ret)); + krb5_set_error_string(context, "keytab krb5 open %s failed: %s", + d->filename, strerror(ret)); return ret; } c->sp = krb5_storage_from_fd(c->fd); if(c->sp == NULL) { close(c->fd); free(ed); + krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_eof_code(c->sp, KRB5_KT_END); @@ -369,8 +370,11 @@ krb4_kt_remove_entry(krb5_context context, if(fd < 0) { memset(data.data, 0, data.length); krb5_data_free(&data); - if(errno == EACCES || errno == EROFS) + if(errno == EACCES || errno == EROFS) { + krb5_set_error_string(context, "failed to open %s for writing", + d->filename); return KRB5_KT_NOWRITE; + } return errno; } @@ -378,14 +382,16 @@ krb4_kt_remove_entry(krb5_context context, memset(data.data, 0, data.length); krb5_data_free(&data); close(fd); - krb5_set_error_string(context, "failed writing to \"%s\"", d->filename); + krb5_set_error_string(context, "failed writing to file %s", + d->filename); return errno; } memset(data.data, 0, data.length); if(fstat(fd, &st) < 0) { krb5_data_free(&data); close(fd); - krb5_set_error_string(context, "failed getting size of \"%s\"", d->filename); + krb5_set_error_string(context, "failed getting size of file %s", + d->filename); return errno; } st.st_size -= data.length; @@ -396,7 +402,8 @@ krb4_kt_remove_entry(krb5_context context, if(n <= 0) { krb5_data_free(&data); close(fd); - krb5_set_error_string(context, "failed writing to \"%s\"", d->filename); + krb5_set_error_string(context, "failed writing to file %s", + d->filename); return errno; } @@ -405,17 +412,20 @@ krb4_kt_remove_entry(krb5_context context, if(ftruncate(fd, data.length) < 0) { krb5_data_free(&data); close(fd); - krb5_set_error_string(context, "failed truncating \"%s\"", d->filename); + krb5_set_error_string(context, "failed truncating file %s", + d->filename); return errno; } krb5_data_free(&data); if(close(fd) < 0) { - krb5_set_error_string(context, "error closing \"%s\"", d->filename); + krb5_set_error_string(context, "error closing %s", + d->filename); return errno; } return 0; } else { krb5_storage_free(sp); + krb5_set_error_string(context, "Keytab entry not found"); return KRB5_KT_NOTFOUND; } } diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 9a84dde61a..7e04446fe0 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -276,7 +276,7 @@ _krb5_mk_req_internal ( krb5_key_usage /*checksum_usage*/, krb5_key_usage /*encrypt_usage*/); -void KRB5_LIB_FUNCTION +krb5_error_code KRB5_LIB_FUNCTION _krb5_n_fold ( const void */*str*/, size_t /*len*/, @@ -292,7 +292,7 @@ _krb5_oid_to_enctype ( krb5_error_code _krb5_pac_sign ( krb5_context /*context*/, - struct krb5_pac */*p*/, + krb5_pac /*p*/, time_t /*authtime*/, krb5_principal /*principal*/, const krb5_keyblock */*server_key*/, @@ -396,13 +396,6 @@ _krb5_plugin_get_next (struct krb5_plugin */*p*/); void * _krb5_plugin_get_symbol (struct krb5_plugin */*p*/); -krb5_error_code -_krb5_plugin_register ( - krb5_context /*context*/, - enum krb5_plugin_type /*type*/, - const char */*name*/, - void */*symbol*/); - krb5_error_code KRB5_LIB_FUNCTION _krb5_principal2principalname ( PrincipalName */*p*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 740b394be8..647d8886b7 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -670,6 +670,12 @@ krb5_cc_initialize ( krb5_ccache /*id*/, krb5_principal /*primary_principal*/); +krb5_error_code +krb5_cc_move ( + krb5_context /*context*/, + krb5_ccache /*from*/, + krb5_ccache /*to*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_new_unique ( krb5_context /*context*/, @@ -1329,6 +1335,13 @@ krb5_digest_init_request ( krb5_realm /*realm*/, krb5_ccache /*ccache*/); +krb5_error_code +krb5_digest_probe ( + krb5_context /*context*/, + krb5_realm /*realm*/, + krb5_ccache /*ccache*/, + unsigned */*flags*/); + krb5_boolean krb5_digest_rep_get_status ( krb5_context /*context*/, @@ -1606,6 +1619,9 @@ krb5_err ( ...) __attribute__ ((noreturn, format (printf, 4, 5))); +krb5_error_code KRB5_LIB_FUNCTION + __attribute__((deprecated)) krb5_free_creds_contents (krb5_context context, krb5_creds *c); + krb5_error_code KRB5_LIB_FUNCTION krb5_error_from_rd_error ( krb5_context /*context*/, @@ -1694,11 +1710,6 @@ krb5_free_creds ( krb5_context /*context*/, krb5_creds */*c*/); -krb5_error_code KRB5_LIB_FUNCTION -krb5_free_creds_contents ( - krb5_context /*context*/, - krb5_creds */*c*/); - void KRB5_LIB_FUNCTION krb5_free_data ( krb5_context /*context*/, @@ -2243,6 +2254,14 @@ krb5_get_pw_salt ( krb5_const_principal /*principal*/, krb5_salt */*salt*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_get_renewed_creds ( + krb5_context /*context*/, + krb5_creds */*creds*/, + krb5_const_principal /*client*/, + krb5_ccache /*ccache*/, + const char */*in_tkt_service*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_get_server_rcache ( krb5_context /*context*/, @@ -2797,45 +2816,45 @@ krb5_openlog ( krb5_error_code krb5_pac_add_buffer ( krb5_context /*context*/, - struct krb5_pac */*p*/, + krb5_pac /*p*/, uint32_t /*type*/, const krb5_data */*data*/); void krb5_pac_free ( krb5_context /*context*/, - struct krb5_pac */*pac*/); + krb5_pac /*pac*/); krb5_error_code krb5_pac_get_buffer ( krb5_context /*context*/, - struct krb5_pac */*p*/, + krb5_pac /*p*/, uint32_t /*type*/, krb5_data */*data*/); krb5_error_code krb5_pac_get_types ( krb5_context /*context*/, - struct krb5_pac */*p*/, + krb5_pac /*p*/, size_t */*len*/, uint32_t **/*types*/); krb5_error_code krb5_pac_init ( krb5_context /*context*/, - struct krb5_pac **/*pac*/); + krb5_pac */*pac*/); krb5_error_code krb5_pac_parse ( krb5_context /*context*/, const void */*ptr*/, size_t /*len*/, - struct krb5_pac **/*pac*/); + krb5_pac */*pac*/); krb5_error_code krb5_pac_verify ( krb5_context /*context*/, - const struct krb5_pac */*pac*/, + const krb5_pac /*pac*/, time_t /*authtime*/, krb5_const_principal /*principal*/, const krb5_keyblock */*server*/, @@ -2887,6 +2906,13 @@ krb5_password_key_proc ( krb5_const_pointer /*keyseed*/, krb5_keyblock **/*key*/); +krb5_error_code +krb5_plugin_register ( + krb5_context /*context*/, + enum krb5_plugin_type /*type*/, + const char */*name*/, + void */*symbol*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_prepend_config_files ( const char */*filelist*/, diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 4f9a63bf05..571eb6192a 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h 21551 2007-07-15 09:03:39Z lha $ */ +/* $Id: krb5.h 22100 2007-12-03 17:15:00Z lha $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -75,15 +75,16 @@ typedef struct krb5_crypto_data *krb5_crypto; struct krb5_get_creds_opt_data; typedef struct krb5_get_creds_opt_data *krb5_get_creds_opt; -struct krb5_digest; -typedef struct krb5_digest *krb5_digest; -struct krb5_ntlm; -typedef struct krb5_ntlm *krb5_ntlm; +struct krb5_digest_data; +typedef struct krb5_digest_data *krb5_digest; +struct krb5_ntlm_data; +typedef struct krb5_ntlm_data *krb5_ntlm; -typedef struct krb5_pac *krb5_pac; +struct krb5_pac_data; +typedef struct krb5_pac_data *krb5_pac; -typedef struct krb5_rd_req_in_ctx *krb5_rd_req_in_ctx; -typedef struct krb5_rd_req_out_ctx *krb5_rd_req_out_ctx; +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; typedef CKSUMTYPE krb5_cksumtype; @@ -417,6 +418,8 @@ typedef struct krb5_cc_ops { krb5_error_code (*get_cache_first)(krb5_context, krb5_cc_cursor *); krb5_error_code (*get_cache_next)(krb5_context, krb5_cc_cursor, krb5_ccache *); krb5_error_code (*end_cache_get)(krb5_context, krb5_cc_cursor); + krb5_error_code (*move)(krb5_context, krb5_ccache, krb5_ccache); + krb5_error_code (*default_name)(krb5_context, char **); } krb5_cc_ops; struct krb5_log_facility; @@ -753,7 +756,7 @@ enum { KRB5_PRINCIPAL_UNPARSE_DISPLAY = 4 }; -typedef struct krb5_sendto_ctx *krb5_sendto_ctx; +typedef struct krb5_sendto_ctx_data *krb5_sendto_ctx; #define KRB5_SENDTO_DONE 0 #define KRB5_SENDTO_RESTART 1 diff --git a/source4/heimdal/lib/krb5/krb5_ccapi.h b/source4/heimdal/lib/krb5/krb5_ccapi.h index b53d77ef18..59a38425c2 100644 --- a/source4/heimdal/lib/krb5/krb5_ccapi.h +++ b/source4/heimdal/lib/krb5/krb5_ccapi.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_ccapi.h 17442 2006-05-05 09:31:15Z lha $ */ +/* $Id: krb5_ccapi.h 22090 2007-12-02 23:23:43Z lha $ */ #ifndef KRB5_CCAPI_H #define KRB5_CCAPI_H 1 @@ -180,18 +180,18 @@ typedef struct cc_ccache_functions { cc_int32 (*destroy)(cc_ccache_t); cc_int32 (*set_default)(cc_ccache_t); cc_int32 (*get_credentials_version)(cc_ccache_t, cc_uint32*); - cc_int32 (*get_name)(cc_ccache_t ccache,cc_string_t*); + cc_int32 (*get_name)(cc_ccache_t, cc_string_t*); cc_int32 (*get_principal)(cc_ccache_t, cc_uint32, cc_string_t*); cc_int32 (*set_principal)(cc_ccache_t, cc_uint32, const char*); cc_int32 (*store_credentials)(cc_ccache_t, const cc_credentials_union*); cc_int32 (*remove_credentials)(cc_ccache_t, cc_credentials_t); cc_int32 (*new_credentials_iterator)(cc_ccache_t, cc_credentials_iterator_t*); - cc_int32 (*move)(cc_ccache_t source, cc_ccache_t); + cc_int32 (*move)(cc_ccache_t, cc_ccache_t); cc_int32 (*lock)(cc_ccache_t, cc_uint32, cc_uint32); cc_int32 (*unlock)(cc_ccache_t); cc_int32 (*get_last_default_time)(cc_ccache_t, cc_time_t*); - cc_int32 (*get_change_time)(cc_ccache_t ccache, cc_time_t*); + cc_int32 (*get_change_time)(cc_ccache_t, cc_time_t*); cc_int32 (*compare)(cc_ccache_t, cc_ccache_t, cc_uint32*); cc_int32 (*get_kdc_time_offset)(cc_ccache_t, cc_int32, cc_time_t *); cc_int32 (*set_kdc_time_offset)(cc_ccache_t, cc_int32, cc_time_t); diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index b41e6e1182..8b7c41cc80 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_locl.h 21552 2007-07-15 09:04:00Z lha $ */ +/* $Id: krb5_locl.h 22226 2007-12-08 21:31:53Z lha $ */ #ifndef __KRB5_LOCL_H__ #define __KRB5_LOCL_H__ @@ -231,14 +231,18 @@ typedef struct krb5_context_data { krb5_addresses *ignore_addresses; char *default_cc_name; char *default_cc_name_env; + int default_cc_name_set; void *mutex; /* protects error_string/error_buf */ int large_msg_size; - int dns_canonicalize_hostname; + int flags; +#define KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME 1 +#define KRB5_CTX_F_CHECK_PAC 2 struct send_to_kdc *send_to_kdc; } krb5_context_data; #define KRB5_DEFAULT_CCNAME_FILE "FILE:/tmp/krb5cc_%{uid}" #define KRB5_DEFAULT_CCNAME_API "API:" +#define KRB5_DEFAULT_CCNAME_KCM "KCM:%{uid}" #define EXTRACT_TICKET_ALLOW_CNAME_MISMATCH 1 #define EXTRACT_TICKET_ALLOW_SERVER_MISMATCH 2 @@ -248,11 +252,11 @@ typedef struct krb5_context_data { * Configurable options */ -#ifndef KRB5_DEFAULT_CCNAME +#ifndef KRB5_DEFAULT_CCTYPE #ifdef __APPLE__ -#define KRB5_DEFAULT_CCNAME KRB5_DEFAULT_CCNAME_API +#define KRB5_DEFAULT_CCTYPE (&krb5_acc_ops) #else -#define KRB5_DEFAULT_CCNAME KRB5_DEFAULT_CCNAME_FILE +#define KRB5_DEFAULT_CCTYPE (&krb5_fcc_ops) #endif #endif diff --git a/source4/heimdal/lib/krb5/mcache.c b/source4/heimdal/lib/krb5/mcache.c index ff9261a7db..01bcb09d3b 100644 --- a/source4/heimdal/lib/krb5/mcache.c +++ b/source4/heimdal/lib/krb5/mcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: mcache.c 19834 2007-01-11 09:26:21Z lha $"); +RCSID("$Id: mcache.c 22107 2007-12-03 17:22:51Z lha $"); typedef struct krb5_mcache { char *name; @@ -401,6 +401,57 @@ mcc_end_cache_get(krb5_context context, krb5_cc_cursor cursor) return 0; } +static krb5_error_code +mcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) +{ + krb5_mcache *mfrom = MCACHE(from), *mto = MCACHE(to); + struct link *creds; + krb5_principal principal; + krb5_mcache **n; + + HEIMDAL_MUTEX_lock(&mcc_mutex); + + /* drop the from cache from the linked list to avoid lookups */ + for(n = &mcc_head; n && *n; n = &(*n)->next) { + if(mfrom == *n) { + *n = mfrom->next; + break; + } + } + + /* swap creds */ + creds = mto->creds; + mto->creds = mfrom->creds; + mfrom->creds = creds; + /* swap principal */ + principal = mto->primary_principal; + mto->primary_principal = mfrom->primary_principal; + mfrom->primary_principal = principal; + + HEIMDAL_MUTEX_unlock(&mcc_mutex); + mcc_destroy(context, from); + + return 0; +} + +static krb5_error_code +mcc_default_name(krb5_context context, char **str) +{ + *str = strdup("MEMORY:"); + if (*str == NULL) { + krb5_set_error_string(context, "out of memory"); + return ENOMEM; + } + return 0; +} + + +/** + * Variable containing the MEMORY based credential cache implemention. + * + * @ingroup krb5_ccache + */ + const krb5_cc_ops krb5_mcc_ops = { "MEMORY", mcc_get_name, @@ -420,5 +471,7 @@ const krb5_cc_ops krb5_mcc_ops = { NULL, mcc_get_cache_first, mcc_get_cache_next, - mcc_end_cache_get + mcc_end_cache_get, + mcc_move, + mcc_default_name }; diff --git a/source4/heimdal/lib/krb5/n-fold.c b/source4/heimdal/lib/krb5/n-fold.c index 1474a76b77..53528cfd1f 100644 --- a/source4/heimdal/lib/krb5/n-fold.c +++ b/source4/heimdal/lib/krb5/n-fold.c @@ -32,21 +32,23 @@ #include "krb5_locl.h" -RCSID("$Id: n-fold.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id: n-fold.c 22190 2007-12-06 16:24:22Z lha $"); -static void +static krb5_error_code rr13(unsigned char *buf, size_t len) { unsigned char *tmp; int bytes = (len + 7) / 8; int i; if(len == 0) - return; + return 0; { const int bits = 13 % len; const int lbit = len % 8; tmp = malloc(bytes); + if (tmp == NULL) + return ENOMEM; memcpy(tmp, buf, bytes); if(lbit) { /* pad final byte with inital bits */ @@ -75,9 +77,10 @@ rr13(unsigned char *buf, size_t len) } free(tmp); } + return 0; } -/* Add `b' to `a', both beeing one's complement numbers. */ +/* Add `b' to `a', both being one's complement numbers. */ static void add1(unsigned char *a, unsigned char *b, size_t len) { @@ -95,22 +98,28 @@ add1(unsigned char *a, unsigned char *b, size_t len) } } -void KRB5_LIB_FUNCTION +krb5_error_code KRB5_LIB_FUNCTION _krb5_n_fold(const void *str, size_t len, void *key, size_t size) { /* if len < size we need at most N * len bytes, ie < 2 * size; if len > size we need at most 2 * len */ + krb5_error_code ret = 0; size_t maxlen = 2 * max(size, len); size_t l = 0; unsigned char *tmp = malloc(maxlen); unsigned char *buf = malloc(len); + if (tmp == NULL || buf == NULL) + return ENOMEM; + memcpy(buf, str, len); memset(key, 0, size); do { memcpy(tmp + l, buf, len); l += len; - rr13(buf, len * 8); + ret = rr13(buf, len * 8); + if (ret) + goto out; while(l >= size) { add1(key, tmp, size); l -= size; @@ -119,8 +128,10 @@ _krb5_n_fold(const void *str, size_t len, void *key, size_t size) memmove(tmp, tmp + size, l); } } while(l != 0); +out: memset(buf, 0, len); free(buf); memset(tmp, 0, maxlen); free(tmp); + return ret; } diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index f7a5e83ea3..0b44ca1da3 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -32,8 +32,9 @@ */ #include "krb5_locl.h" +#include -RCSID("$Id: pac.c 21149 2007-06-18 21:50:22Z lha $"); +RCSID("$Id: pac.c 22562 2008-02-03 17:38:35Z lha $"); struct PAC_INFO_BUFFER { uint32_t type; @@ -48,7 +49,7 @@ struct PACTYPE { struct PAC_INFO_BUFFER buffers[1]; }; -struct krb5_pac { +struct krb5_pac_data { struct PACTYPE *pac; krb5_data data; struct PAC_INFO_BUFFER *server_checksum; @@ -82,10 +83,10 @@ static const char zeros[PAC_ALIGNMENT] = { 0 }; krb5_error_code krb5_pac_parse(krb5_context context, const void *ptr, size_t len, - struct krb5_pac **pac) + krb5_pac *pac) { krb5_error_code ret; - struct krb5_pac *p; + krb5_pac p; krb5_storage *sp = NULL; uint32_t i, tmp, tmp2, header_end; @@ -216,10 +217,10 @@ out: } krb5_error_code -krb5_pac_init(krb5_context context, struct krb5_pac **pac) +krb5_pac_init(krb5_context context, krb5_pac *pac) { krb5_error_code ret; - struct krb5_pac *p; + krb5_pac p; p = calloc(1, sizeof(*p)); if (p == NULL) { @@ -248,7 +249,7 @@ krb5_pac_init(krb5_context context, struct krb5_pac **pac) } krb5_error_code -krb5_pac_add_buffer(krb5_context context, struct krb5_pac *p, +krb5_pac_add_buffer(krb5_context context, krb5_pac p, uint32_t type, const krb5_data *data) { krb5_error_code ret; @@ -316,7 +317,7 @@ krb5_pac_add_buffer(krb5_context context, struct krb5_pac *p, } krb5_error_code -krb5_pac_get_buffer(krb5_context context, struct krb5_pac *p, +krb5_pac_get_buffer(krb5_context context, krb5_pac p, uint32_t type, krb5_data *data) { krb5_error_code ret; @@ -361,7 +362,7 @@ krb5_pac_get_buffer(krb5_context context, struct krb5_pac *p, krb5_error_code krb5_pac_get_types(krb5_context context, - struct krb5_pac *p, + krb5_pac p, size_t *len, uint32_t **types) { @@ -385,7 +386,7 @@ krb5_pac_get_types(krb5_context context, */ void -krb5_pac_free(krb5_context context, struct krb5_pac *pac) +krb5_pac_free(krb5_context context, krb5_pac pac) { krb5_data_free(&pac->data); free(pac->pac); @@ -564,51 +565,48 @@ verify_logonname(krb5_context context, ret = krb5_storage_read(sp, s, len); if (ret != len) { krb5_storage_free(sp); - krb5_set_error_string(context, "Failed to read pac logon name"); + krb5_set_error_string(context, "Failed to read PAC logon name"); return EINVAL; } krb5_storage_free(sp); -#if 1 /* cheat for now */ - { - size_t i; - - if (len & 1) { - krb5_set_error_string(context, "PAC logon name malformed"); - return EINVAL; - } - - for (i = 0; i < len / 2; i++) { - if (s[(i * 2) + 1]) { - krb5_set_error_string(context, "PAC logon name not ASCII"); - return EINVAL; - } - s[i] = s[i * 2]; - } - s[i] = '\0'; - } -#else { + size_t ucs2len = len / 2; uint16_t *ucs2; - ssize_t ucs2len; size_t u8len; + unsigned int flags = WIND_RW_LE; - ucs2 = malloc(sizeof(ucs2[0]) * len / 2); - if (ucs2) - abort(); - ucs2len = wind_ucs2read(s, len / 2, ucs2); + ucs2 = malloc(sizeof(ucs2[0]) * ucs2len); + if (ucs2 == NULL) { + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = wind_ucs2read(s, len, &flags, ucs2, &ucs2len); free(s); - if (len < 0) - return -1; - ret = wind_ucs2toutf8(ucs2, ucs2len, NULL, &u8len); - if (ret < 0) - abort(); - s = malloc(u8len + 1); - if (s == NULL) - abort(); - wind_ucs2toutf8(ucs2, ucs2len, s, &u8len); + if (ret) { + free(ucs2); + krb5_set_error_string(context, "Failed to convert string to UCS-2"); + return ret; + } + ret = wind_ucs2utf8_length(ucs2, ucs2len, &u8len); + if (ret) { + free(ucs2); + krb5_set_error_string(context, "Failed to count length of UCS-2 string"); + return ret; + } + u8len += 1; /* Add space for NUL */ + s = malloc(u8len); + if (s == NULL) { + free(ucs2); + krb5_set_error_string(context, "malloc: out of memory"); + return ENOMEM; + } + ret = wind_ucs2utf8(ucs2, ucs2len, s, &u8len); free(ucs2); + if (ret) { + krb5_set_error_string(context, "Failed to convert to UTF-8"); + return ret; + } } -#endif ret = krb5_parse_name_flags(context, s, KRB5_PRINCIPAL_PARSE_NO_REALM, &p2); free(s); if (ret) @@ -703,7 +701,7 @@ out: krb5_error_code krb5_pac_verify(krb5_context context, - const struct krb5_pac *pac, + const krb5_pac pac, time_t authtime, krb5_const_principal principal, const krb5_keyblock *server, @@ -840,7 +838,7 @@ pac_checksum(krb5_context context, krb5_error_code _krb5_pac_sign(krb5_context context, - struct krb5_pac *p, + krb5_pac p, time_t authtime, krb5_principal principal, const krb5_keyblock *server_key, diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index c8587770f4..4a585bff07 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c 21684 2007-07-23 23:09:10Z lha $"); +RCSID("$Id: pkinit.c 22673 2008-03-10 15:00:05Z lha $"); struct krb5_dh_moduli { char *name; @@ -139,17 +139,59 @@ integer_to_BN(krb5_context context, const char *field, const heim_integer *f) return bn; } +struct certfind { + const char *type; + const heim_oid *oid; +}; + +/* + * Try searchin the key by to use by first looking for for PK-INIT + * EKU, then the Microsoft smart card EKU and last, no special EKU at all. + */ static krb5_error_code -_krb5_pk_create_sign(krb5_context context, - const heim_oid *eContentType, - krb5_data *eContent, - struct krb5_pk_identity *id, - hx509_peer_info peer, - krb5_data *sd_data) +find_cert(krb5_context context, struct krb5_pk_identity *id, + hx509_query *q, hx509_cert *cert) { - hx509_cert cert; - hx509_query *q; + struct certfind cf[3] = { + { "PKINIT EKU" }, + { "MS EKU" }, + { "no" } + }; + int i, ret; + + cf[0].oid = oid_id_pkekuoid(); + cf[1].oid = oid_id_pkinit_ms_eku(); + cf[2].oid = NULL; + + for (i = 0; i < sizeof(cf)/sizeof(cf[0]); i++) { + ret = hx509_query_match_eku(q, cf[i].oid); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed setting %s OID", cf[i].type); + return ret; + } + + ret = hx509_certs_find(id->hx509ctx, id->certs, q, cert); + if (ret == 0) + break; + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Failed cert for finding %s OID", cf[i].type); + } + return ret; +} + + +static krb5_error_code +create_signature(krb5_context context, + const heim_oid *eContentType, + krb5_data *eContent, + struct krb5_pk_identity *id, + hx509_peer_info peer, + krb5_data *sd_data) +{ + hx509_cert cert = NULL; + hx509_query *q = NULL; int ret; ret = hx509_query_alloc(id->hx509ctx, &q); @@ -162,13 +204,10 @@ _krb5_pk_create_sign(krb5_context context, hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY); hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE); - ret = hx509_certs_find(id->hx509ctx, id->certs, q, &cert); + ret = find_cert(context, id, q, &cert); hx509_query_free(id->hx509ctx, q); - if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Find certificate to signed CMS data"); + if (ret) return ret; - } ret = hx509_cms_create_signed_1(id->hx509ctx, 0, @@ -181,11 +220,14 @@ _krb5_pk_create_sign(krb5_context context, NULL, id->certs, sd_data); - if (ret) - _krb5_pk_copy_error(context, id->hx509ctx, ret, "create CMS signedData"); hx509_cert_free(cert); + if (ret) { + _krb5_pk_copy_error(context, id->hx509ctx, ret, + "Create CMS signedData"); + return ret; + } - return ret; + return 0; } static int @@ -212,8 +254,7 @@ cert2epi(hx509_context context, void *ctx, hx509_cert c) return ENOMEM; } - ret = hx509_name_to_der_name(subject, &id.subjectName->data, - &id.subjectName->length); + ret = hx509_name_binary(subject, id.subjectName); if (ret) { hx509_name_free(&subject); free_ExternalPrincipalIdentifier(&id); @@ -544,12 +585,8 @@ pk_mk_padata(krb5_context context, } else krb5_abortx(context, "internal pkinit error"); - ret = _krb5_pk_create_sign(context, - oid, - &buf, - ctx->id, - ctx->peer, - &sd_buf); + ret = create_signature(context, oid, &buf, ctx->id, + ctx->peer, &sd_buf); krb5_data_free(&buf); if (ret) goto out; @@ -878,7 +915,8 @@ pk_verify_host(krb5_context context, hx509_octet_string_list list; int i; - ret = hx509_cert_find_subjectAltName_otherName(host->cert, + ret = hx509_cert_find_subjectAltName_otherName(ctx->id->hx509ctx, + host->cert, oid_id_pkinit_san(), &list); if (ret) { diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c index 43fa3f5b45..bae28496aa 100644 --- a/source4/heimdal/lib/krb5/plugin.c +++ b/source4/heimdal/lib/krb5/plugin.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: plugin.c 21702 2007-07-26 19:13:53Z lha $"); +RCSID("$Id: plugin.c 22033 2007-11-10 10:39:47Z lha $"); #ifdef HAVE_DLFCN_H #include #endif @@ -117,11 +117,23 @@ loadlib(krb5_context context, } #endif /* HAVE_DLOPEN */ +/** + * Register a plugin symbol name of specific type. + * @param context a Keberos context + * @param type type of plugin symbol + * @param name name of plugin symbol + * @param symbol a pointer to the named symbol + * @return In case of error a non zero error com_err error is returned + * and the Kerberos error string is set. + * + * @ingroup krb5_support + */ + krb5_error_code -_krb5_plugin_register(krb5_context context, - enum krb5_plugin_type type, - const char *name, - void *symbol) +krb5_plugin_register(krb5_context context, + enum krb5_plugin_type type, + const char *name, + void *symbol) { struct plugin *e; @@ -250,4 +262,3 @@ _krb5_plugin_free(struct krb5_plugin *list) list = next; } } - diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index c1a29d266b..cdad477115 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan + * Copyright (c) 1997-2007 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -31,6 +31,22 @@ * SUCH DAMAGE. */ +/** + * @page page_principal The principal handing functions. + * + * A Kerberos principal is a email address looking string that + * contains to parts separeted by a @. The later part is the kerbero + * realm the principal belongs to and the former is a list of 0 or + * more components. For example + * @verbatim +lha@SU.SE +host/hummel.it.su.se@SU.SE +host/admin@H5L.ORG +@endverbatim + * + * See the library functions here: @ref krb5_principal + */ + #include "krb5_locl.h" #ifdef HAVE_RES_SEARCH #define USE_RESOLVER @@ -41,7 +57,7 @@ #include #include "resolve.h" -RCSID("$Id: principal.c 21285 2007-06-25 12:30:55Z lha $"); +RCSID("$Id: principal.c 22549 2008-01-29 09:37:25Z lha $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -49,6 +65,21 @@ RCSID("$Id: principal.c 21285 2007-06-25 12:30:55Z lha $"); #define princ_ncomp(P, N) ((P)->name.name_string.val[(N)]) #define princ_realm(P) ((P)->realm) +/** + * Frees a Kerberos principal allocated by the library with + * krb5_parse_name(), krb5_make_principal() or any other related + * principal functions. + * + * @param context A Kerberos context. + * @param p a principal to free. + * + * @return An krb5 error code, see krb5_get_error_message(). + * + * @ingroup krb5_principal + */ + + + void KRB5_LIB_FUNCTION krb5_free_principal(krb5_context context, krb5_principal p) @@ -804,7 +835,7 @@ krb5_425_conv_principal_ext2(krb5_context context, char local_hostname[MAXHOSTNAMELEN]; /* do the following: if the name is found in the - `v4_name_convert:host' part, is is assumed to be a `host' type + `v4_name_convert:host' part, is assumed to be a `host' type principal, and the instance is looked up in the `v4_instance_convert' part. if not found there the name is (optionally) looked up as a hostname, and if that doesn't yield diff --git a/source4/heimdal/lib/krb5/rd_priv.c b/source4/heimdal/lib/krb5/rd_priv.c index 47b5df85b2..ed7a2ccc52 100644 --- a/source4/heimdal/lib/krb5/rd_priv.c +++ b/source4/heimdal/lib/krb5/rd_priv.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_priv.c 21770 2007-08-01 04:04:33Z lha $"); +RCSID("$Id: rd_priv.c 21751 2007-07-31 20:42:20Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_priv(krb5_context context, diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 001b47f094..0f33b97164 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_req.c 21004 2007-06-08 01:53:10Z lha $"); +RCSID("$Id: rd_req.c 22235 2007-12-08 21:52:07Z lha $"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, @@ -137,7 +137,7 @@ check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc) krb5_error_code ret; /* - * Windows 2000 and 2003 uses this inside their TGT so its normaly + * Windows 2000 and 2003 uses this inside their TGT so it's normaly * not seen by others, however, samba4 joined with a Windows AD as * a Domain Controller gets exposed to this. */ @@ -512,13 +512,13 @@ krb5_verify_ap_req2(krb5_context context, * */ -struct krb5_rd_req_in_ctx { +struct krb5_rd_req_in_ctx_data { krb5_keytab keytab; krb5_keyblock *keyblock; - krb5_boolean no_pac_check; + krb5_boolean check_pac; }; -struct krb5_rd_req_out_ctx { +struct krb5_rd_req_out_ctx_data { krb5_keyblock *keyblock; krb5_flags ap_req_options; krb5_ticket *ticket; @@ -536,6 +536,7 @@ krb5_rd_req_in_ctx_alloc(krb5_context context, krb5_rd_req_in_ctx *ctx) krb5_set_error_string(context, "out of memory"); return ENOMEM; } + (*ctx)->check_pac = (context->flags & KRB5_CTX_F_CHECK_PAC) ? 1 : 0; return 0; } @@ -548,12 +549,24 @@ krb5_rd_req_in_set_keytab(krb5_context context, return 0; } +/** + * Set if krb5_rq_red() is going to check the Windows PAC or not + * + * @param context Keberos 5 context. + * @param in krb5_rd_req_in_ctx to check the option on. + * @param flag flag to select if to check the pac (TRUE) or not (FALSE). + * + * @return Kerberos 5 error code, see krb5_get_error_message(). + * + * @ingroup krb5 + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_rd_req_in_set_pac_check(krb5_context context, krb5_rd_req_in_ctx in, krb5_boolean flag) { - in->no_pac_check = !flag; + in->check_pac = flag; return 0; } @@ -826,20 +839,21 @@ krb5_rd_req_ctx(krb5_context context, goto out; } - ret = krb5_verify_ap_req(context, - auth_context, - &ap_req, - server, - o->keyblock, - 0, - &o->ap_req_options, - &o->ticket); + ret = krb5_verify_ap_req2(context, + auth_context, + &ap_req, + server, + o->keyblock, + 0, + &o->ap_req_options, + &o->ticket, + KRB5_KU_AP_REQ_AUTH); if (ret) goto out; /* If there is a PAC, verify its server signature */ - if (inctx->no_pac_check == FALSE) { + if (inctx->check_pac) { krb5_pac pac; krb5_data data; diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index c1a4df2b01..2582a615c0 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: send_to_kdc.c 21062 2007-06-12 17:58:57Z lha $"); +RCSID("$Id: send_to_kdc.c 21934 2007-08-27 14:21:04Z lha $"); struct send_to_kdc { krb5_send_to_kdc_func func; @@ -448,7 +448,7 @@ krb5_set_send_to_kdc_func(krb5_context context, return 0; } -struct krb5_sendto_ctx { +struct krb5_sendto_ctx_data { int flags; int type; krb5_sendto_ctx_func func; diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c index 4abcf44a43..c9cbbb5cef 100644 --- a/source4/heimdal/lib/krb5/store.c +++ b/source4/heimdal/lib/krb5/store.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store.c 20529 2007-04-22 14:28:19Z lha $"); +RCSID("$Id: store.c 22071 2007-11-14 20:04:50Z lha $"); #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) @@ -838,8 +838,8 @@ krb5_ret_creds(krb5_storage *sp, krb5_creds *creds) if(ret) goto cleanup; /* * Runtime detect the what is the higher bits of the bitfield. If - * any of the higher bits are set in the input data, its either a - * new ticket flag (and this code need to be removed), or its a + * any of the higher bits are set in the input data, it's either a + * new ticket flag (and this code need to be removed), or it's a * MIT cache (or new Heimdal cache), lets change it to our current * format. */ @@ -993,8 +993,8 @@ krb5_ret_creds_tag(krb5_storage *sp, if(ret) goto cleanup; /* * Runtime detect the what is the higher bits of the bitfield. If - * any of the higher bits are set in the input data, its either a - * new ticket flag (and this code need to be removed), or its a + * any of the higher bits are set in the input data, it's either a + * new ticket flag (and this code need to be removed), or it's a * MIT cache (or new Heimdal cache), lets change it to our current * format. */ diff --git a/source4/heimdal/lib/krb5/store_emem.c b/source4/heimdal/lib/krb5/store_emem.c index 07acdd1a00..c38c1b53c3 100644 --- a/source4/heimdal/lib/krb5/store_emem.c +++ b/source4/heimdal/lib/krb5/store_emem.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store_emem.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id: store_emem.c 22574 2008-02-05 20:31:55Z lha $"); typedef struct emem_storage{ unsigned char *base; @@ -115,13 +115,28 @@ emem_free(krb5_storage *sp) krb5_storage * KRB5_LIB_FUNCTION krb5_storage_emem(void) { - krb5_storage *sp = malloc(sizeof(krb5_storage)); - emem_storage *s = malloc(sizeof(*s)); + krb5_storage *sp; + emem_storage *s; + + sp = malloc(sizeof(krb5_storage)); + if (sp == NULL) + return NULL; + + s = malloc(sizeof(*s)); + if (s == NULL) { + free(sp); + return NULL; + } sp->data = s; sp->flags = 0; sp->eof_code = HEIM_ERR_EOF; s->size = 1024; s->base = malloc(s->size); + if (s->base == NULL) { + free(sp); + free(s); + return NULL; + } s->len = 0; s->ptr = s->base; sp->fetch = emem_fetch; diff --git a/source4/heimdal/lib/krb5/transited.c b/source4/heimdal/lib/krb5/transited.c index 7f5498f592..9b67ecc04f 100644 --- a/source4/heimdal/lib/krb5/transited.c +++ b/source4/heimdal/lib/krb5/transited.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: transited.c 17043 2006-04-10 10:26:35Z lha $"); +RCSID("$Id: transited.c 21745 2007-07-31 16:11:25Z lha $"); /* this is an attempt at one of the most horrible `compression' schemes that has ever been invented; it's so amazingly brain-dead @@ -87,6 +87,10 @@ make_path(krb5_context context, struct tr_realm *r, if(strcmp(p, to) == 0) break; tmp = calloc(1, sizeof(*tmp)); + if(tmp == NULL){ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } tmp->next = path; path = tmp; path->realm = strdup(p); @@ -107,6 +111,10 @@ make_path(krb5_context context, struct tr_realm *r, if(strncmp(to, from, p - from) == 0) break; tmp = calloc(1, sizeof(*tmp)); + if(tmp == NULL){ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } tmp->next = path; path = tmp; path->realm = malloc(p - from + 1); @@ -277,6 +285,10 @@ decode_realms(krb5_context context, } if(tr[i] == ','){ tmp = malloc(tr + i - start + 1); + if(tmp == NULL){ + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } memcpy(tmp, start, tr + i - start); tmp[tr + i - start] = '\0'; r = make_realm(tmp); @@ -290,6 +302,11 @@ decode_realms(krb5_context context, } } tmp = malloc(tr + i - start + 1); + if(tmp == NULL){ + free(*realms); + krb5_set_error_string (context, "malloc: out of memory"); + return ENOMEM; + } memcpy(tmp, start, tr + i - start); tmp[tr + i - start] = '\0'; r = make_realm(tmp); diff --git a/source4/heimdal/lib/krb5/v4_glue.c b/source4/heimdal/lib/krb5/v4_glue.c index 3f99df6391..37b1e35dd1 100644 --- a/source4/heimdal/lib/krb5/v4_glue.c +++ b/source4/heimdal/lib/krb5/v4_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: v4_glue.c 21572 2007-07-16 05:13:08Z lha $"); +RCSID("$Id: v4_glue.c 22071 2007-11-14 20:04:50Z lha $"); #include "krb5-v4compat.h" @@ -599,7 +599,7 @@ _krb5_krb_cr_err_reply(krb5_context context, RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_ERR_REPLY), error); RCHECK(ret, put_nir(sp, name, inst, realm), error); RCHECK(ret, krb5_store_int32(sp, time_ws), error); - /* If its a Kerberos 4 error-code, remove the et BASE */ + /* If it is a Kerberos 4 error-code, remove the et BASE */ if (e >= ERROR_TABLE_BASE_krb && e <= ERROR_TABLE_BASE_krb + 255) e -= ERROR_TABLE_BASE_krb; RCHECK(ret, krb5_store_int32(sp, e), error); -- cgit From a925f039ee382df0f3be434108416bab0d17e8c0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 1 Aug 2008 07:08:51 +0200 Subject: heimdal: update to lorikeet-heimdal rev 801 metze (This used to be commit d6c54a66fb23c784ef221a3c1cf766b72bdb5a0b) --- source4/heimdal/lib/krb5/acache.c | 71 ++- source4/heimdal/lib/krb5/addr_families.c | 75 +-- source4/heimdal/lib/krb5/auth_context.c | 18 +- source4/heimdal/lib/krb5/build_auth.c | 10 +- source4/heimdal/lib/krb5/cache.c | 256 ++++++++-- source4/heimdal/lib/krb5/changepw.c | 97 ++-- source4/heimdal/lib/krb5/config_file.c | 10 +- source4/heimdal/lib/krb5/constants.c | 6 +- source4/heimdal/lib/krb5/context.c | 78 +-- source4/heimdal/lib/krb5/convert_creds.c | 8 +- source4/heimdal/lib/krb5/copy_host_realm.c | 17 +- source4/heimdal/lib/krb5/crc.c | 4 +- source4/heimdal/lib/krb5/creds.c | 8 +- source4/heimdal/lib/krb5/crypto.c | 584 ++++++++++++++-------- source4/heimdal/lib/krb5/data.c | 4 +- source4/heimdal/lib/krb5/error_string.c | 146 ++++-- source4/heimdal/lib/krb5/expand_hostname.c | 7 +- source4/heimdal/lib/krb5/fcache.c | 204 +++++--- source4/heimdal/lib/krb5/generate_subkey.c | 4 +- source4/heimdal/lib/krb5/get_cred.c | 588 ++++++++++++++--------- source4/heimdal/lib/krb5/get_default_principal.c | 6 +- source4/heimdal/lib/krb5/get_default_realm.c | 4 +- source4/heimdal/lib/krb5/get_for_creds.c | 21 +- source4/heimdal/lib/krb5/get_host_realm.c | 16 +- source4/heimdal/lib/krb5/get_in_tkt.c | 377 ++++++++++++--- source4/heimdal/lib/krb5/init_creds.c | 14 +- source4/heimdal/lib/krb5/init_creds_pw.c | 110 ++--- source4/heimdal/lib/krb5/kcm.c | 56 ++- source4/heimdal/lib/krb5/keyblock.c | 15 +- source4/heimdal/lib/krb5/keytab.c | 57 +-- source4/heimdal/lib/krb5/keytab_any.c | 17 +- source4/heimdal/lib/krb5/keytab_file.c | 54 ++- source4/heimdal/lib/krb5/keytab_keyfile.c | 54 ++- source4/heimdal/lib/krb5/keytab_memory.c | 8 +- source4/heimdal/lib/krb5/krb5-private.h | 32 +- source4/heimdal/lib/krb5/krb5-protos.h | 83 +++- source4/heimdal/lib/krb5/krb5.h | 50 +- source4/heimdal/lib/krb5/krb5_err.et | 6 +- source4/heimdal/lib/krb5/krb5_locl.h | 30 +- source4/heimdal/lib/krb5/krbhst.c | 22 +- source4/heimdal/lib/krb5/locate_plugin.h | 4 +- source4/heimdal/lib/krb5/log.c | 24 +- source4/heimdal/lib/krb5/mcache.c | 15 +- source4/heimdal/lib/krb5/mk_priv.c | 4 +- source4/heimdal/lib/krb5/mk_rep.c | 12 +- source4/heimdal/lib/krb5/n-fold.c | 2 +- source4/heimdal/lib/krb5/pac.c | 113 ++--- source4/heimdal/lib/krb5/padata.c | 4 +- source4/heimdal/lib/krb5/pkinit.c | 415 ++++++++-------- source4/heimdal/lib/krb5/plugin.c | 19 +- source4/heimdal/lib/krb5/principal.c | 114 +++-- source4/heimdal/lib/krb5/rd_cred.c | 9 +- source4/heimdal/lib/krb5/rd_error.c | 36 +- source4/heimdal/lib/krb5/rd_rep.c | 4 +- source4/heimdal/lib/krb5/rd_req.c | 21 +- source4/heimdal/lib/krb5/replay.c | 31 +- source4/heimdal/lib/krb5/send_to_kdc.c | 62 ++- source4/heimdal/lib/krb5/send_to_kdc_plugin.h | 58 +++ source4/heimdal/lib/krb5/set_default_realm.c | 6 +- source4/heimdal/lib/krb5/ticket.c | 36 +- source4/heimdal/lib/krb5/time.c | 31 +- source4/heimdal/lib/krb5/transited.c | 42 +- source4/heimdal/lib/krb5/v4_glue.c | 71 +-- source4/heimdal/lib/krb5/warn.c | 8 +- 64 files changed, 2803 insertions(+), 1565 deletions(-) create mode 100644 source4/heimdal/lib/krb5/send_to_kdc_plugin.h (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c index 775239cf6d..8dd8687005 100644 --- a/source4/heimdal/lib/krb5/acache.c +++ b/source4/heimdal/lib/krb5/acache.c @@ -37,7 +37,7 @@ #include #endif -RCSID("$Id: acache.c 22669 2008-03-09 23:39:25Z lha $"); +RCSID("$Id: acache.c 23316 2008-06-23 04:32:32Z lha $"); /* XXX should we fetch these for each open ? */ static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; @@ -68,6 +68,7 @@ static const struct { { ccIteratorEnd, KRB5_CC_END }, { ccErrNoMem, KRB5_CC_NOMEM }, { ccErrServerUnavailable, KRB5_CC_NOSUPP }, + { ccErrInvalidCCache, KRB5_CC_BADNAME }, { ccNoError, 0 } }; @@ -114,15 +115,17 @@ init_ccapi(krb5_context context) cc_handle = dlopen(lib, RTLD_LAZY); if (cc_handle == NULL) { HEIMDAL_MUTEX_unlock(&acc_mutex); - krb5_set_error_string(context, "Failed to load %s", lib); + krb5_set_error_message(context, KRB5_CC_NOSUPP, + "Failed to load %s", lib); return KRB5_CC_NOSUPP; } init_func = (cc_initialize_func)dlsym(cc_handle, "cc_initialize"); HEIMDAL_MUTEX_unlock(&acc_mutex); if (init_func == NULL) { - krb5_set_error_string(context, "Failed to find cc_initialize" - "in %s: %s", lib, dlerror()); + krb5_set_error_message(context, KRB5_CC_NOSUPP, + "Failed to find cc_initialize" + "in %s: %s", lib, dlerror()); dlclose(cc_handle); return KRB5_CC_NOSUPP; } @@ -130,7 +133,7 @@ init_ccapi(krb5_context context) return 0; #else HEIMDAL_MUTEX_unlock(&acc_mutex); - krb5_set_error_string(context, "no support for shared object"); + krb5_set_error_message(context, KRB5_CC_NOSUPP, "no support for shared object"); return KRB5_CC_NOSUPP; #endif } @@ -141,7 +144,7 @@ make_cred_from_ccred(krb5_context context, krb5_creds *cred) { krb5_error_code ret; - int i; + unsigned int i; memset(cred, 0, sizeof(*cred)); @@ -255,7 +258,7 @@ make_cred_from_ccred(krb5_context context, nomem: ret = ENOMEM; - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); fail: krb5_free_cred_contents(context, cred); @@ -584,8 +587,10 @@ acc_close(krb5_context context, free(a->cache_name); a->cache_name = NULL; } - (*a->context->func->release)(a->context); - a->context = NULL; + if (a->context) { + (*a->context->func->release)(a->context); + a->context = NULL; + } krb5_data_free(&id->data); return 0; } @@ -620,7 +625,8 @@ acc_store_cred(krb5_context context, cc_int32 error; if (a->ccache == NULL) { - krb5_set_error_string(context, "No API credential found"); + krb5_set_error_message(context, KRB5_CC_NOTFOUND, + "No API credential found"); return KRB5_CC_NOTFOUND; } @@ -653,7 +659,8 @@ acc_get_principal(krb5_context context, cc_string_t name; if (a->ccache == NULL) { - krb5_set_error_string(context, "No API credential found"); + krb5_set_error_message(context, KRB5_CC_NOTFOUND, + "No API credential found"); return KRB5_CC_NOTFOUND; } @@ -679,7 +686,8 @@ acc_get_first (krb5_context context, int32_t error; if (a->ccache == NULL) { - krb5_set_error_string(context, "No API credential found"); + krb5_set_error_message(context, KRB5_CC_NOTFOUND, + "No API credential found"); return KRB5_CC_NOTFOUND; } @@ -744,7 +752,8 @@ acc_remove_cred(krb5_context context, char *client, *server; if (a->ccache == NULL) { - krb5_set_error_string(context, "No API credential found"); + krb5_set_error_message(context, KRB5_CC_NOTFOUND, + "No API credential found"); return KRB5_CC_NOTFOUND; } @@ -796,8 +805,8 @@ acc_remove_cred(krb5_context context, (*iter->func->release)(iter); if (ret) - krb5_set_error_string(context, "Can't find credential %s in cache", - server); + krb5_set_error_message(context, ret, + "Can't find credential %s in cache", server); free(server); free(client); @@ -812,7 +821,7 @@ acc_set_flags(krb5_context context, return 0; } -static krb5_error_code +static int acc_get_version(krb5_context context, krb5_ccache id) { @@ -837,7 +846,7 @@ acc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) iter = calloc(1, sizeof(*iter)); if (iter == NULL) { - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -940,7 +949,7 @@ acc_move(krb5_context context, krb5_ccache from, krb5_ccache to) } static krb5_error_code -acc_default_name(krb5_context context, char **str) +acc_get_default_name(krb5_context context, char **str) { krb5_error_code ret; cc_context_t cc; @@ -966,12 +975,30 @@ acc_default_name(krb5_context context, char **str) (*cc->func->release)(cc); if (*str == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "out of memory"); return ENOMEM; } return 0; } +static krb5_error_code +acc_set_default(krb5_context context, krb5_ccache id) +{ + krb5_acc *a = ACACHE(id); + cc_int32 error; + + if (a->ccache == NULL) { + krb5_set_error_message(context, KRB5_CC_NOTFOUND, + "No API credential found"); + return KRB5_CC_NOTFOUND; + } + + error = (*a->ccache->func->set_default)(a->ccache); + if (error) + return translate_cc_error(context, error); + + return 0; +} /** * Variable containing the API based credential cache implemention. @@ -979,7 +1006,8 @@ acc_default_name(krb5_context context, char **str) * @ingroup krb5_ccache */ -const krb5_cc_ops krb5_acc_ops = { +KRB5_LIB_VARIABLE const krb5_cc_ops krb5_acc_ops = { + KRB5_CC_OPS_VERSION, "API", acc_get_name, acc_resolve, @@ -1000,5 +1028,6 @@ const krb5_cc_ops krb5_acc_ops = { acc_get_cache_next, acc_end_cache_get, acc_move, - acc_default_name + acc_get_default_name, + acc_set_default }; diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c index f364f5974d..40abd874cc 100644 --- a/source4/heimdal/lib/krb5/addr_families.c +++ b/source4/heimdal/lib/krb5/addr_families.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: addr_families.c 22039 2007-11-10 11:47:35Z lha $"); +RCSID("$Id: addr_families.c 23316 2008-06-23 04:32:32Z lha $"); struct addr_operations { int af; @@ -202,7 +202,8 @@ ipv4_mask_boundary(krb5_context context, const krb5_address *inaddr, uint32_t l, h, m = 0xffffffff; if (len > 32) { - krb5_set_error_string(context, "IPv4 prefix too large (%ld)", len); + krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP, + "IPv4 prefix too large (%ld)", len); return KRB5_PROG_ATYPE_NOSUPP; } m = m << (32 - len); @@ -395,12 +396,14 @@ ipv6_mask_boundary(krb5_context context, const krb5_address *inaddr, int i, sub_len; if (len > 128) { - krb5_set_error_string(context, "IPv6 prefix too large (%ld)", len); + krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP, + "IPv6 prefix too large (%ld)", len); return KRB5_PROG_ATYPE_NOSUPP; } if (inaddr->address.length != sizeof(addr)) { - krb5_set_error_string(context, "IPv6 addr bad length"); + krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP, + "IPv6 addr bad length"); return KRB5_PROG_ATYPE_NOSUPP; } @@ -786,8 +789,9 @@ krb5_sockaddr2address (krb5_context context, { struct addr_operations *a = find_af(sa->sa_family); if (a == NULL) { - krb5_set_error_string (context, "Address family %d not supported", - sa->sa_family); + krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, + "Address family %d not supported", + sa->sa_family); return KRB5_PROG_ATYPE_NOSUPP; } return (*a->sockaddr2addr)(sa, addr); @@ -813,8 +817,9 @@ krb5_sockaddr2port (krb5_context context, { struct addr_operations *a = find_af(sa->sa_family); if (a == NULL) { - krb5_set_error_string (context, "Address family %d not supported", - sa->sa_family); + krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, + "Address family %d not supported", + sa->sa_family); return KRB5_PROG_ATYPE_NOSUPP; } return (*a->sockaddr2port)(sa, port); @@ -851,14 +856,16 @@ krb5_addr2sockaddr (krb5_context context, struct addr_operations *a = find_atype(addr->addr_type); if (a == NULL) { - krb5_set_error_string (context, "Address type %d not supported", - addr->addr_type); + krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, + "Address type %d not supported", + addr->addr_type); return KRB5_PROG_ATYPE_NOSUPP; } if (a->addr2sockaddr == NULL) { - krb5_set_error_string (context, - "Can't convert address type %d to sockaddr", - addr->addr_type); + krb5_set_error_message (context, + KRB5_PROG_ATYPE_NOSUPP, + "Can't convert address type %d to sockaddr", + addr->addr_type); return KRB5_PROG_ATYPE_NOSUPP; } (*a->addr2sockaddr)(addr, sa, sa_size, port); @@ -935,7 +942,8 @@ krb5_h_addr2sockaddr (krb5_context context, { struct addr_operations *a = find_af(af); if (a == NULL) { - krb5_set_error_string (context, "Address family %d not supported", af); + krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, + "Address family %d not supported", af); return KRB5_PROG_ATYPE_NOSUPP; } (*a->h_addr2sockaddr)(addr, sa, sa_size, port); @@ -963,7 +971,8 @@ krb5_h_addr2addr (krb5_context context, { struct addr_operations *a = find_af(af); if (a == NULL) { - krb5_set_error_string (context, "Address family %d not supported", af); + krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, + "Address family %d not supported", af); return KRB5_PROG_ATYPE_NOSUPP; } return (*a->h_addr2addr)(haddr, addr); @@ -996,7 +1005,8 @@ krb5_anyaddr (krb5_context context, struct addr_operations *a = find_af (af); if (a == NULL) { - krb5_set_error_string (context, "Address family %d not supported", af); + krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, + "Address family %d not supported", af); return KRB5_PROG_ATYPE_NOSUPP; } @@ -1089,7 +1099,8 @@ krb5_parse_address(krb5_context context, if((*at[i].parse_addr)(context, string, &addr) == 0) { ALLOC_SEQ(addresses, 1); if (addresses->val == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, + "malloc: out of memory"); return ENOMEM; } addresses->val[0] = addr; @@ -1100,9 +1111,12 @@ krb5_parse_address(krb5_context context, error = getaddrinfo (string, NULL, NULL, &ai); if (error) { + krb5_error_code ret2; save_errno = errno; - krb5_set_error_string (context, "%s: %s", string, gai_strerror(error)); - return krb5_eai_to_heim_errno(error, save_errno); + ret2 = krb5_eai_to_heim_errno(error, save_errno); + krb5_set_error_message (context, ret2, "%s: %s", + string, gai_strerror(error)); + return ret2; } n = 0; @@ -1111,7 +1125,8 @@ krb5_parse_address(krb5_context context, ALLOC_SEQ(addresses, n); if (addresses->val == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, + "malloc: out of memory"); freeaddrinfo(ai); return ENOMEM; } @@ -1154,15 +1169,17 @@ krb5_address_order(krb5_context context, struct addr_operations *a; a = find_atype(addr1->addr_type); if(a == NULL) { - krb5_set_error_string (context, "Address family %d not supported", - addr1->addr_type); + krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, + "Address family %d not supported", + addr1->addr_type); return KRB5_PROG_ATYPE_NOSUPP; } if(a->order_addr != NULL) return (*a->order_addr)(context, addr1, addr2); a = find_atype(addr2->addr_type); if(a == NULL) { - krb5_set_error_string (context, "Address family %d not supported", + krb5_set_error_message (context, KRB5_PROG_ATYPE_NOSUPP, + "Address family %d not supported", addr2->addr_type); return KRB5_PROG_ATYPE_NOSUPP; } @@ -1349,7 +1366,8 @@ krb5_append_addresses(krb5_context context, if(source->len > 0) { tmp = realloc(dest->val, (dest->len + source->len) * sizeof(*tmp)); if(tmp == NULL) { - krb5_set_error_string(context, "realloc: out of memory"); + krb5_set_error_message (context, ENOMEM, + "realloc: out of memory"); return ENOMEM; } dest->val = tmp; @@ -1391,13 +1409,15 @@ krb5_make_addrport (krb5_context context, *res = malloc (sizeof(**res)); if (*res == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, + "malloc: out of memory"); return ENOMEM; } (*res)->addr_type = KRB5_ADDRESS_ADDRPORT; ret = krb5_data_alloc (&(*res)->address, len); if (ret) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message (context, ret, + "malloc: out of memory"); free (*res); *res = NULL; return ret; @@ -1457,7 +1477,8 @@ krb5_address_prefixlen_boundary(krb5_context context, struct addr_operations *a = find_atype (inaddr->addr_type); if(a != NULL && a->mask_boundary != NULL) return (*a->mask_boundary)(context, inaddr, prefixlen, low, high); - krb5_set_error_string(context, "Address family %d doesn't support " + krb5_set_error_message(context, KRB5_PROG_ATYPE_NOSUPP, + "Address family %d doesn't support " "address mask operation", inaddr->addr_type); return KRB5_PROG_ATYPE_NOSUPP; } diff --git a/source4/heimdal/lib/krb5/auth_context.c b/source4/heimdal/lib/krb5/auth_context.c index 323f17a245..e4fb50e5b8 100644 --- a/source4/heimdal/lib/krb5/auth_context.c +++ b/source4/heimdal/lib/krb5/auth_context.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: auth_context.c 21745 2007-07-31 16:11:25Z lha $"); +RCSID("$Id: auth_context.c 23273 2008-06-23 03:25:00Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_auth_con_init(krb5_context context, @@ -43,13 +43,13 @@ krb5_auth_con_init(krb5_context context, ALLOC(p, 1); if(!p) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memset(p, 0, sizeof(*p)); ALLOC(p->authenticator, 1); if (!p->authenticator) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); free(p); return ENOMEM; } @@ -174,7 +174,8 @@ krb5_auth_con_genaddrs(krb5_context context, len = sizeof(ss_local); if(getsockname(fd, local, &len) < 0) { ret = errno; - krb5_set_error_string (context, "getsockname: %s", + krb5_set_error_message(context, ret, + "getsockname: %s", strerror(ret)); goto out; } @@ -191,7 +192,8 @@ krb5_auth_con_genaddrs(krb5_context context, len = sizeof(ss_remote); if(getpeername(fd, remote, &len) < 0) { ret = errno; - krb5_set_error_string (context, "getpeername: %s", strerror(ret)); + krb5_set_error_message(context, ret, + "getpeername: %s", strerror(ret)); goto out; } ret = krb5_sockaddr2address (context, remote, &remote_k_address); @@ -239,7 +241,7 @@ krb5_auth_con_getaddrs(krb5_context context, krb5_free_address (context, *local_addr); *local_addr = malloc (sizeof(**local_addr)); if (*local_addr == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } krb5_copy_address(context, @@ -250,7 +252,7 @@ krb5_auth_con_getaddrs(krb5_context context, krb5_free_address (context, *remote_addr); *remote_addr = malloc (sizeof(**remote_addr)); if (*remote_addr == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); krb5_free_address (context, *local_addr); *local_addr = NULL; return ENOMEM; @@ -450,7 +452,7 @@ krb5_auth_con_getauthenticator(krb5_context context, { *authenticator = malloc(sizeof(**authenticator)); if (*authenticator == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } diff --git a/source4/heimdal/lib/krb5/build_auth.c b/source4/heimdal/lib/krb5/build_auth.c index f8739c044d..fe3a5f523c 100644 --- a/source4/heimdal/lib/krb5/build_auth.c +++ b/source4/heimdal/lib/krb5/build_auth.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: build_auth.c 17033 2006-04-10 08:53:21Z lha $"); +RCSID("$Id: build_auth.c 23273 2008-06-23 03:25:00Z lha $"); static krb5_error_code make_etypelist(krb5_context context, @@ -62,7 +62,7 @@ make_etypelist(krb5_context context, ALLOC_SEQ(&ad, 1); if (ad.val == NULL) { free(buf); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -81,14 +81,14 @@ make_etypelist(krb5_context context, ALLOC(*auth_data, 1); if (*auth_data == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ALLOC_SEQ(*auth_data, 1); if ((*auth_data)->val == NULL) { free(buf); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -118,7 +118,7 @@ krb5_build_authenticator (krb5_context context, auth = calloc(1, sizeof(*auth)); if (auth == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index 5db6d2b2cf..34bfb4a350 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c 22127 2007-12-04 00:54:37Z lha $"); +RCSID("$Id: cache.c 23417 2008-07-26 18:36:33Z lha $"); /** * Add a new ccache type with operations `ops', overwriting any @@ -59,9 +59,10 @@ krb5_cc_register(krb5_context context, for(i = 0; i < context->num_cc_ops && context->cc_ops[i].prefix; i++) { if(strcmp(context->cc_ops[i].prefix, ops->prefix) == 0) { if(!override) { - krb5_set_error_string(context, - "ccache type %s already exists", - ops->prefix); + krb5_set_error_message(context, + KRB5_CC_TYPE_EXISTS, + "ccache type %s already exists", + ops->prefix); return KRB5_CC_TYPE_EXISTS; } break; @@ -72,7 +73,8 @@ krb5_cc_register(krb5_context context, (context->num_cc_ops + 1) * sizeof(*context->cc_ops)); if(o == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_CC_NOMEM, + "malloc: out of memory"); return KRB5_CC_NOMEM; } context->num_cc_ops++; @@ -98,7 +100,7 @@ _krb5_cc_allocate(krb5_context context, p = malloc (sizeof(*p)); if(p == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_CC_NOMEM, "malloc: out of memory"); return KRB5_CC_NOMEM; } p->ops = ops; @@ -166,7 +168,8 @@ krb5_cc_resolve(krb5_context context, if (strchr (name, ':') == NULL) return allocate_ccache (context, &krb5_fcc_ops, name, id); else { - krb5_set_error_string(context, "unknown ccache type %s", name); + krb5_set_error_message(context, KRB5_CC_UNKNOWN_TYPE, + "unknown ccache type %s", name); return KRB5_CC_UNKNOWN_TYPE; } } @@ -204,16 +207,14 @@ krb5_error_code KRB5_LIB_FUNCTION krb5_cc_new_unique(krb5_context context, const char *type, const char *hint, krb5_ccache *id) { - const krb5_cc_ops *ops = KRB5_DEFAULT_CCTYPE; + const krb5_cc_ops *ops; krb5_error_code ret; - if (type) { - ops = krb5_cc_get_prefix_ops(context, type); - if (ops == NULL) { - krb5_set_error_string(context, - "Credential cache type %s is unknown", type); - return KRB5_CC_UNKNOWN_TYPE; - } + ops = krb5_cc_get_prefix_ops(context, type); + if (ops == NULL) { + krb5_set_error_message(context, KRB5_CC_UNKNOWN_TYPE, + "Credential cache type %s is unknown", type); + return KRB5_CC_UNKNOWN_TYPE; } ret = _krb5_cc_allocate(context, ops, id); @@ -270,18 +271,20 @@ krb5_cc_get_full_name(krb5_context context, type = krb5_cc_get_type(context, id); if (type == NULL) { - krb5_set_error_string(context, "cache have no name of type"); + krb5_set_error_message(context, KRB5_CC_UNKNOWN_TYPE, + "cache have no name of type"); return KRB5_CC_UNKNOWN_TYPE; } name = krb5_cc_get_name(context, id); if (name == NULL) { - krb5_set_error_string(context, "cache of type %s have no name", type); + krb5_set_error_message(context, KRB5_CC_BADNAME, + "cache of type %s have no name", type); return KRB5_CC_BADNAME; } if (asprintf(str, "%s:%s", type, name) == -1) { - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); *str = NULL; return ENOMEM; } @@ -327,7 +330,8 @@ _krb5_expand_default_cc_name(krb5_context context, const char *str, char **res) if (tmp2 == NULL) { free(*res); *res = NULL; - krb5_set_error_string(context, "variable missing }"); + krb5_set_error_message(context, KRB5_CONFIG_BADFORMAT, + "variable missing }"); return KRB5_CONFIG_BADFORMAT; } if (strncasecmp(tmp, "%{uid}", 6) == 0) @@ -337,10 +341,11 @@ _krb5_expand_default_cc_name(krb5_context context, const char *str, char **res) else { free(*res); *res = NULL; - krb5_set_error_string(context, - "expand default cache unknown " - "variable \"%.*s\"", - (int)(tmp2 - tmp) - 2, tmp + 2); + krb5_set_error_message(context, + KRB5_CONFIG_BADFORMAT, + "expand default cache unknown " + "variable \"%.*s\"", + (int)(tmp2 - tmp) - 2, tmp + 2); return KRB5_CONFIG_BADFORMAT; } str = tmp2 + 1; @@ -351,7 +356,7 @@ _krb5_expand_default_cc_name(krb5_context context, const char *str, char **res) if (append == NULL) { free(*res); *res = NULL; - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -361,7 +366,8 @@ _krb5_expand_default_cc_name(krb5_context context, const char *str, char **res) free(append); free(*res); *res = NULL; - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, + "malloc: out of memory"); return ENOMEM; } *res = tmp; @@ -406,11 +412,29 @@ environment_changed(krb5_context context) } /** - * Set the default cc name for `context' to `name'. + * Switch the default default credential cache for a specific + * credcache type (and name for some implementations). + * + * @return Returns 0 or an error code. * * @ingroup krb5_ccache */ +krb5_error_code +krb5_cc_switch(krb5_context context, krb5_ccache id) +{ + + if (id->ops->set_default == NULL) + return 0; + + return (*id->ops->set_default)(context, id); +} + +/** + * Set the default cc name for `context' to `name'. + * + * @ingroup krb5_ccache + */ krb5_error_code KRB5_LIB_FUNCTION krb5_cc_set_default_name(krb5_context context, const char *name) @@ -440,7 +464,19 @@ krb5_cc_set_default_name(krb5_context context, const char *name) } if (e == NULL) { const krb5_cc_ops *ops = KRB5_DEFAULT_CCTYPE; - ret = (*ops->default_name)(context, &p); + e = krb5_config_get_string(context, NULL, "libdefaults", + "default_cc_type", NULL); + if (e) { + ops = krb5_cc_get_prefix_ops(context, e); + if (ops == NULL) { + krb5_set_error_message(context, + KRB5_CC_UNKNOWN_TYPE, + "Credential cache type %s " + "is unknown", e); + return KRB5_CC_UNKNOWN_TYPE; + } + } + ret = (*ops->get_default_name)(context, &p); if (ret) return ret; } @@ -452,7 +488,7 @@ krb5_cc_set_default_name(krb5_context context, const char *name) } if (p == NULL) { - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -499,7 +535,7 @@ krb5_cc_default(krb5_context context, const char *p = krb5_cc_default_name(context); if (p == NULL) { - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } return krb5_cc_resolve(context, p, id); @@ -728,9 +764,10 @@ krb5_cc_remove_cred(krb5_context context, krb5_creds *cred) { if(id->ops->remove_cred == NULL) { - krb5_set_error_string(context, - "ccache %s does not support remove_cred", - id->ops->prefix); + krb5_set_error_message(context, + EACCES, + "ccache %s does not support remove_cred", + id->ops->prefix); return EACCES; /* XXX */ } return (*id->ops->remove_cred)(context, id, which, cred); @@ -846,10 +883,12 @@ krb5_cc_clear_mcred(krb5_creds *mcred) /** * Get the cc ops that is registered in `context' to handle the - * `prefix'. `prefix' can be a complete credential cache name or a + * prefix. prefix can be a complete credential cache name or a * prefix, the function will only use part up to the first colon (:) - * if there is one. - * Returns NULL if ops not found. + * if there is one. If prefix the argument is NULL, the default ccache + * implemtation is returned. + + * @return Returns NULL if ops not found. * * @ingroup krb5_ccache */ @@ -861,12 +900,14 @@ krb5_cc_get_prefix_ops(krb5_context context, const char *prefix) char *p, *p1; int i; + if (prefix == NULL) + return KRB5_DEFAULT_CCTYPE; if (prefix[0] == '/') return &krb5_fcc_ops; p = strdup(prefix); if (p == NULL) { - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return NULL; } p1 = strchr(p, ':'); @@ -911,20 +952,22 @@ krb5_cc_cache_get_first (krb5_context context, ops = krb5_cc_get_prefix_ops(context, type); if (ops == NULL) { - krb5_set_error_string(context, "Unknown type \"%s\" when iterating " - "trying to iterate the credential caches", type); + krb5_set_error_message(context, KRB5_CC_UNKNOWN_TYPE, + "Unknown type \"%s\" when iterating " + "trying to iterate the credential caches", type); return KRB5_CC_UNKNOWN_TYPE; } if (ops->get_cache_first == NULL) { - krb5_set_error_string(context, "Credential cache type %s doesn't support " - "iterations over caches", ops->prefix); + krb5_set_error_message(context, KRB5_CC_NOSUPP, + "Credential cache type %s doesn't support " + "iterations over caches", ops->prefix); return KRB5_CC_NOSUPP; } *cursor = calloc(1, sizeof(**cursor)); if (*cursor == NULL) { - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -1028,8 +1071,10 @@ krb5_cc_cache_match (krb5_context context, krb5_unparse_name(context, client, &str); - krb5_set_error_string(context, "Principal %s not found in a " - "credential cache", str ? str : ""); + krb5_set_error_message(context, KRB5_CC_NOTFOUND, + "Principal %s not found in a " + "credential cache", + str ? str : ""); if (str) free(str); return KRB5_CC_NOTFOUND; @@ -1059,8 +1104,9 @@ krb5_cc_move(krb5_context context, krb5_ccache from, krb5_ccache to) krb5_error_code ret; if (strcmp(from->ops->prefix, to->ops->prefix) != 0) { - krb5_set_error_string(context, "Moving credentials between diffrent " - "types not yet supported"); + krb5_set_error_message(context, KRB5_CC_NOSUPP, + "Moving credentials between diffrent " + "types not yet supported"); return KRB5_CC_NOSUPP; } @@ -1071,3 +1117,123 @@ krb5_cc_move(krb5_context context, krb5_ccache from, krb5_ccache to) } return ret; } + +#define KRB5_CONF_NAME "@krb5_ccache_conf_data" + +static krb5_error_code +build_conf_principals(krb5_context context, krb5_ccache id, + krb5_const_principal principal, + const char *name, krb5_creds *cred) +{ + krb5_principal client; + krb5_error_code ret; + char *pname = NULL; + + memset(cred, 0, sizeof(*cred)); + + ret = krb5_cc_get_principal(context, id, &client); + if (ret) + return ret; + + if (principal) { + ret = krb5_unparse_name(context, principal, &pname); + if (ret) + return ret; + } + + ret = krb5_make_principal(context, &cred->server, + krb5_principal_get_realm(context, client), + KRB5_CONF_NAME, name, pname, NULL); + free(pname); + if (ret) { + krb5_free_principal(context, client); + return ret; + } + ret = krb5_copy_principal(context, client, &cred->client); + krb5_free_principal(context, client); + return ret; +} + +/** + * Store some configuration for the credential cache in the cache. + * Existing configuration under the same name is over-written. + * + * @param context a Keberos context + * @param id the credential cache to store the data for + * @param principal configuration for a specific principal, if + * NULL, global for the whole cache. + * @param name name under which the configuraion is stored. + * @param data data to store + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_set_config(krb5_context context, krb5_ccache id, + krb5_const_principal principal, + const char *name, krb5_data *data) +{ + krb5_error_code ret; + krb5_creds cred; + + ret = build_conf_principals(context, id, principal, name, &cred); + if (ret) + goto out; + + /* Remove old configuration */ + ret = krb5_cc_remove_cred(context, id, 0, &cred); + if (ret) + goto out; + + /* not that anyone care when this expire */ + cred.times.authtime = time(NULL); + cred.times.endtime = cred.times.authtime + 3600 * 24 * 30; + + ret = krb5_data_copy(&cred.ticket, data->data, data->length); + if (ret) + goto out; + + ret = krb5_cc_store_cred(context, id, &cred); + +out: + krb5_free_cred_contents (context, &cred); + return ret; +} + +/** + * Get some configuration for the credential cache in the cache. + * + * @param context a Keberos context + * @param id the credential cache to store the data for + * @param principal configuration for a specific principal, if + * NULL, global for the whole cache. + * @param name name under which the configuraion is stored. + * @param data data to fetched, free with krb5_data_free() + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_config(krb5_context context, krb5_ccache id, + krb5_const_principal principal, + const char *name, krb5_data *data) +{ + krb5_creds mcred, cred; + krb5_error_code ret; + + memset(&cred, 0, sizeof(cred)); + krb5_data_zero(data); + + ret = build_conf_principals(context, id, principal, name, &mcred); + if (ret) + goto out; + + ret = krb5_cc_retrieve_cred(context, id, 0, &mcred, &cred); + if (ret) + goto out; + + ret = krb5_data_copy(data, cred.ticket.data, cred.ticket.length); + +out: + krb5_free_cred_contents (context, &cred); + krb5_free_cred_contents (context, &mcred); + return ret; +} + diff --git a/source4/heimdal/lib/krb5/changepw.c b/source4/heimdal/lib/krb5/changepw.c index 703cf43eb6..ac1a2d312e 100644 --- a/source4/heimdal/lib/krb5/changepw.c +++ b/source4/heimdal/lib/krb5/changepw.c @@ -33,7 +33,11 @@ #include -RCSID("$Id: changepw.c 21505 2007-07-12 12:28:38Z lha $"); +RCSID("$Id: changepw.c 23445 2008-07-27 12:08:03Z lha $"); + +#undef __attribute__ +#define __attribute__(X) + static void str2data (krb5_data *d, @@ -141,7 +145,8 @@ chgpw_send_request (krb5_context context, if (sendmsg (sock, &msghdr, 0) < 0) { ret = errno; - krb5_set_error_string(context, "sendmsg %s: %s", host, strerror(ret)); + krb5_set_error_message(context, ret, "sendmsg %s: %s", + host, strerror(ret)); } krb5_data_free (&krb_priv_data); @@ -250,7 +255,8 @@ setpw_send_request (krb5_context context, if (sendmsg (sock, &msghdr, 0) < 0) { ret = errno; - krb5_set_error_string(context, "sendmsg %s: %s", host, strerror(ret)); + krb5_set_error_message(context, ret, "sendmsg %s: %s", + host, strerror(ret)); } krb5_data_free (&krb_priv_data); @@ -286,11 +292,12 @@ process_reply (krb5_context context, 0, NULL, NULL); if (ret < 0) { save_errno = errno; - krb5_set_error_string(context, "recvfrom %s: %s", - host, strerror(save_errno)); + krb5_set_error_message(context, save_errno, + "recvfrom %s: %s", + host, strerror(save_errno)); return save_errno; } else if (ret == 0) { - krb5_set_error_string(context, "recvfrom timeout %s", host); + krb5_set_error_message(context, 1,"recvfrom timeout %s", host); return 1; } len += ret; @@ -304,16 +311,18 @@ process_reply (krb5_context context, break; } if (len == sizeof(reply)) { - krb5_set_error_string(context, "message too large from %s", - host); + krb5_set_error_message(context, ENOMEM, + "message too large from %s", + host); return ENOMEM; } } else { ret = recvfrom (sock, reply, sizeof(reply), 0, NULL, NULL); if (ret < 0) { save_errno = errno; - krb5_set_error_string(context, "recvfrom %s: %s", - host, strerror(save_errno)); + krb5_set_error_message(context, save_errno, + "recvfrom %s: %s", + host, strerror(save_errno)); return save_errno; } len = ret; @@ -522,7 +531,7 @@ change_password_loop (krb5_context context, krb5_krbhst_handle handle = NULL; krb5_krbhst_info *hi; int sock; - int i; + unsigned int i; int done = 0; krb5_realm realm; @@ -571,6 +580,7 @@ change_password_loop (krb5_context context, sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol); if (sock < 0) continue; + rk_cloexec(sock); ret = connect(sock, a->ai_addr, a->ai_addrlen); if (ret < 0) { @@ -607,8 +617,9 @@ change_password_loop (krb5_context context, } if (sock >= FD_SETSIZE) { - krb5_set_error_string(context, "fd %d too large", sock); ret = ERANGE; + krb5_set_error_message(context, ret, + "fd %d too large", sock); close (sock); goto out; } @@ -647,24 +658,32 @@ change_password_loop (krb5_context context, out: krb5_krbhst_free (context, handle); krb5_auth_con_free (context, auth_context); - if (done) - return 0; - else { - if (ret == KRB5_KDC_UNREACH) { - krb5_set_error_string(context, - "unable to reach any changepw server " - " in realm %s", realm); - *result_code = KRB5_KPASSWD_HARDERROR; - } - return ret; + + if (ret == KRB5_KDC_UNREACH) { + krb5_set_error_message(context, + ret, + "unable to reach any changepw server " + " in realm %s", realm); + *result_code = KRB5_KPASSWD_HARDERROR; } + return ret; } +#ifndef HEIMDAL_SMALLER -/* - * change the password using the credentials in `creds' (for the - * principal indicated in them) to `newpw', storing the result of - * the operation in `result_*' and an error code or 0. +/** + * krb5_change_password() is deprecated, use krb5_set_password(). + * + * @param context a Keberos context + * @param creds + * @param newpw + * @param result_code + * @param result_code_string + * @param result_string + * + * @return On sucess password is changed. + + * @ingroup @krb5_deprecated */ krb5_error_code KRB5_LIB_FUNCTION @@ -674,6 +693,7 @@ krb5_change_password (krb5_context context, int *result_code, krb5_data *result_code_string, krb5_data *result_string) + __attribute__((deprecated)) { struct kpwd_proc *p = find_chpw_proto("change password"); @@ -688,9 +708,24 @@ krb5_change_password (krb5_context context, result_code, result_code_string, result_string, p); } +#endif /* HEIMDAL_SMALLER */ -/* +/** + * Change passwrod using creds. + * + * @param context a Keberos context + * @param creds The initial kadmin/passwd for the principal or an admin principal + * @param newpw The new password to set + * @param targprinc if unset, the default principal is used. + * @param result_code Result code, KRB5_KPASSWD_SUCCESS is when password is changed. + * @param result_code_string binary message from the server, contains + * at least the result_code. + * @param result_string A message from the kpasswd service or the + * library in human printable form. The string is NUL terminated. * + * @return On sucess and *result_code is KRB5_KPASSWD_SUCCESS, the password is changed. + + * @ingroup @krb5 */ krb5_error_code KRB5_LIB_FUNCTION @@ -707,8 +742,8 @@ krb5_set_password(krb5_context context, int i; *result_code = KRB5_KPASSWD_MALFORMED; - result_code_string->data = result_string->data = NULL; - result_code_string->length = result_string->length = 0; + krb5_data_zero(result_code_string); + krb5_data_zero(result_string); if (targprinc == NULL) { ret = krb5_get_default_principal(context, &principal); @@ -732,6 +767,8 @@ krb5_set_password(krb5_context context, return ret; } +#ifndef HEIMDAL_SMALLER + /* * */ @@ -797,6 +834,8 @@ krb5_set_password_using_ccache(krb5_context context, return ret; } +#endif /* !HEIMDAL_SMALLER */ + /* * */ diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c index ac5eba39dc..bf3c432397 100644 --- a/source4/heimdal/lib/krb5/config_file.c +++ b/source4/heimdal/lib/krb5/config_file.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: config_file.c 19213 2006-12-04 23:36:36Z lha $"); +RCSID("$Id: config_file.c 23280 2008-06-23 03:26:18Z lha $"); #ifndef HAVE_NETINFO @@ -295,7 +295,8 @@ krb5_config_parse_string_multi(krb5_context context, ret = krb5_config_parse_debug (&f, res, &lineno, &str); if (ret) { - krb5_set_error_string (context, "%s:%u: %s", "", lineno, str); + krb5_set_error_message (context, ret, "%s:%u: %s", + "", lineno, str); return ret; } return 0; @@ -314,14 +315,15 @@ krb5_config_parse_file_multi (krb5_context context, f.s = NULL; if(f.f == NULL) { ret = errno; - krb5_set_error_string (context, "open %s: %s", fname, strerror(ret)); + krb5_set_error_message (context, ret, "open %s: %s", + fname, strerror(ret)); return ret; } ret = krb5_config_parse_debug (&f, res, &lineno, &str); fclose(f.f); if (ret) { - krb5_set_error_string (context, "%s:%u: %s", fname, lineno, str); + krb5_set_error_message (context, ret, "%s:%u: %s", fname, lineno, str); return ret; } return 0; diff --git a/source4/heimdal/lib/krb5/constants.c b/source4/heimdal/lib/krb5/constants.c index 5188a1d3a8..8fffb0f402 100644 --- a/source4/heimdal/lib/krb5/constants.c +++ b/source4/heimdal/lib/krb5/constants.c @@ -33,11 +33,11 @@ #include "krb5_locl.h" -RCSID("$Id: constants.c 14253 2004-09-23 07:57:37Z joda $"); +RCSID("$Id: constants.c 23026 2008-04-17 10:02:03Z lha $"); -const char *krb5_config_file = +KRB5_LIB_VARIABLE const char *krb5_config_file = #ifdef __APPLE__ "/Library/Preferences/edu.mit.Kerberos:" #endif SYSCONFDIR "/krb5.conf:/etc/krb5.conf"; -const char *krb5_defkeyname = KEYTAB_DEFAULT; +KRB5_LIB_VARIABLE const char *krb5_defkeyname = KEYTAB_DEFAULT; diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index 256783310e..543dba396d 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: context.c 22293 2007-12-14 05:25:59Z lha $"); +RCSID("$Id: context.c 23420 2008-07-26 18:37:48Z lha $"); #define INIT_FIELD(C, T, E, D, F) \ (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ @@ -68,7 +68,7 @@ set_etypes (krb5_context context, etypes = malloc((i+1) * sizeof(*etypes)); if (etypes == NULL) { krb5_config_free_strings (etypes_str); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } for(j = 0, k = 0; j < i; j++) { @@ -246,6 +246,9 @@ krb5_init_context(krb5_context *context) krb5_cc_register(p, &krb5_acc_ops, TRUE); krb5_cc_register(p, &krb5_fcc_ops, TRUE); krb5_cc_register(p, &krb5_mcc_ops, TRUE); +#if 0 + krb5_cc_register(p, &krb5_scc_ops, TRUE); +#endif #ifdef HAVE_KCM krb5_cc_register(p, &krb5_kcm_ops, TRUE); #endif @@ -257,8 +260,6 @@ krb5_init_context(krb5_context *context) krb5_kt_register (p, &krb5_javakt_ops); krb5_kt_register (p, &krb5_mkt_ops); krb5_kt_register (p, &krb5_akf_ops); - krb5_kt_register (p, &krb4_fkt_ops); - krb5_kt_register (p, &krb5_srvtab_fkt_ops); krb5_kt_register (p, &krb5_any_ops); out: @@ -552,7 +553,7 @@ default_etypes(krb5_context context, krb5_enctype **etype) ep = realloc(e, (n + 2) * sizeof(*e)); if (ep == NULL) { free(e); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } e = ep; @@ -594,7 +595,7 @@ krb5_set_default_in_tkt_etypes(krb5_context context, ++i; ALLOC(p, i); if(!p) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memmove(p, etypes, i * sizeof(krb5_enctype)); @@ -623,26 +624,26 @@ krb5_error_code KRB5_LIB_FUNCTION krb5_get_default_in_tkt_etypes(krb5_context context, krb5_enctype **etypes) { - krb5_enctype *p; - int i; - krb5_error_code ret; - - if(context->etypes) { - for(i = 0; context->etypes[i]; i++); - ++i; - ALLOC(p, i); - if(!p) { - krb5_set_error_string (context, "malloc: out of memory"); - return ENOMEM; + krb5_enctype *p; + int i; + krb5_error_code ret; + + if(context->etypes) { + for(i = 0; context->etypes[i]; i++); + ++i; + ALLOC(p, i); + if(!p) { + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); + return ENOMEM; + } + memmove(p, context->etypes, i * sizeof(krb5_enctype)); + } else { + ret = default_etypes(context, &p); + if (ret) + return ret; } - memmove(p, context->etypes, i * sizeof(krb5_enctype)); - } else { - ret = default_etypes(context, &p); - if (ret) - return ret; - } - *etypes = p; - return 0; + *etypes = p; + return 0; } /** @@ -776,7 +777,7 @@ krb5_set_extra_addresses(krb5_context context, const krb5_addresses *addresses) if(context->extra_addresses == NULL) { context->extra_addresses = malloc(sizeof(*context->extra_addresses)); if(context->extra_addresses == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } } @@ -858,7 +859,7 @@ krb5_set_ignore_addresses(krb5_context context, const krb5_addresses *addresses) if(context->ignore_addresses == NULL) { context->ignore_addresses = malloc(sizeof(*context->ignore_addresses)); if(context->ignore_addresses == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } } @@ -986,7 +987,7 @@ krb5_get_dns_canonicalize_hostname (krb5_context context) * @param sec seconds part of offset. * @param usec micro seconds part of offset. * - * @return return non zero if the library uses DNS to canonicalize hostnames. + * @return returns zero * * @ingroup krb5 */ @@ -1001,6 +1002,27 @@ krb5_get_kdc_sec_offset (krb5_context context, int32_t *sec, int32_t *usec) return 0; } +/** + * Set current offset in time to the KDC. + * + * @param context Kerberos 5 context. + * @param sec seconds part of offset. + * @param usec micro seconds part of offset. + * + * @return returns zero + * + * @ingroup krb5 + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_kdc_sec_offset (krb5_context context, int32_t sec, int32_t usec) +{ + context->kdc_sec_offset = sec; + if (usec >= 0) + context->kdc_usec_offset = usec; + return 0; +} + /** * Get max time skew allowed. * diff --git a/source4/heimdal/lib/krb5/convert_creds.c b/source4/heimdal/lib/krb5/convert_creds.c index b2af0187ea..07943efb28 100644 --- a/source4/heimdal/lib/krb5/convert_creds.c +++ b/source4/heimdal/lib/krb5/convert_creds.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: convert_creds.c 22050 2007-11-11 11:20:46Z lha $"); +RCSID("$Id: convert_creds.c 23280 2008-06-23 03:26:18Z lha $"); #include "krb5-v4compat.h" @@ -97,7 +97,7 @@ krb524_convert_creds_kdc(krb5_context context, sp = krb5_storage_from_mem(reply.data, reply.length); if(sp == NULL) { ret = ENOMEM; - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); goto out2; } krb5_ret_int32(sp, &tmp); @@ -132,8 +132,8 @@ krb524_convert_creds_kdc(krb5_context context, goto out; memcpy(v4creds->session, v5_creds->session.keyvalue.data, 8); } else { - krb5_set_error_string(context, "converting credentials: %s", - krb5_get_err_text(context, ret)); + krb5_set_error_message (context, ret, "converting credentials: %s", + krb5_get_err_text(context, ret)); } out: krb5_storage_free(sp); diff --git a/source4/heimdal/lib/krb5/copy_host_realm.c b/source4/heimdal/lib/krb5/copy_host_realm.c index 8c4f39b4ac..cbe333850c 100644 --- a/source4/heimdal/lib/krb5/copy_host_realm.c +++ b/source4/heimdal/lib/krb5/copy_host_realm.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: copy_host_realm.c 22057 2007-11-11 15:13:13Z lha $"); +RCSID("$Id: copy_host_realm.c 23280 2008-06-23 03:26:18Z lha $"); /** * Copy the list of realms from `from' to `to'. @@ -53,24 +53,23 @@ krb5_copy_host_realm(krb5_context context, const krb5_realm *from, krb5_realm **to) { - int n, i; + unsigned int n, i; const krb5_realm *p; - for (n = 0, p = from; *p != NULL; ++p) + for (n = 1, p = from; *p != NULL; ++p) ++n; - ++n; - *to = malloc (n * sizeof(**to)); + + *to = calloc (n, sizeof(**to)); if (*to == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } - for (i = 0; i < n; ++i) - (*to)[i] = NULL; + for (i = 0, p = from; *p != NULL; ++p, ++i) { (*to)[i] = strdup(*p); if ((*to)[i] == NULL) { krb5_free_host_realm (context, *to); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } } diff --git a/source4/heimdal/lib/krb5/crc.c b/source4/heimdal/lib/krb5/crc.c index 072c29d689..e8ddecf7ba 100644 --- a/source4/heimdal/lib/krb5/crc.c +++ b/source4/heimdal/lib/krb5/crc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: crc.c 17442 2006-05-05 09:31:15Z lha $"); +RCSID("$Id: crc.c 22862 2008-04-07 18:49:55Z lha $"); static u_long table[256]; @@ -44,7 +44,7 @@ _krb5_crc_init_table(void) { static int flag = 0; unsigned long crc, poly; - int i, j; + unsigned int i, j; if(flag) return; poly = CRC_GEN; diff --git a/source4/heimdal/lib/krb5/creds.c b/source4/heimdal/lib/krb5/creds.c index 17ef46dfa3..938ec294a4 100644 --- a/source4/heimdal/lib/krb5/creds.c +++ b/source4/heimdal/lib/krb5/creds.c @@ -33,11 +33,13 @@ #include "krb5_locl.h" -RCSID("$Id: creds.c 22062 2007-11-11 15:41:50Z lha $"); +RCSID("$Id: creds.c 23280 2008-06-23 03:26:18Z lha $"); #undef __attribute__ #define __attribute__(X) +#ifndef HEIMDAL_SMALLER + /* keep this for compatibility with older code */ krb5_error_code KRB5_LIB_FUNCTION __attribute__((deprecated)) krb5_free_creds_contents (krb5_context context, krb5_creds *c) @@ -45,6 +47,8 @@ krb5_free_creds_contents (krb5_context context, krb5_creds *c) return krb5_free_cred_contents (context, c); } +#endif /* HEIMDAL_SMALLER */ + /** * Free content of krb5_creds. * @@ -152,7 +156,7 @@ krb5_copy_creds (krb5_context context, c = malloc (sizeof (*c)); if (c == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memset (c, 0, sizeof(*c)); diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 2e63490946..e91cb9391a 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -32,7 +32,8 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c 22200 2007-12-07 13:48:01Z lha $"); +RCSID("$Id: crypto.c 23454 2008-07-27 12:11:44Z lha $"); +#include #undef CRYPTO_DEBUG #ifdef CRYPTO_DEBUG @@ -111,7 +112,6 @@ struct checksum_type { struct encryption_type { krb5_enctype type; const char *name; - heim_oid *oid; size_t blocksize; size_t padsize; size_t confoundersize; @@ -178,7 +178,7 @@ static void krb5_DES_schedule(krb5_context context, struct key_data *key) { - DES_set_key(key->key->keyvalue.data, key->schedule->data); + DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data); } #ifdef ENABLE_AFS_STRING_TO_KEY @@ -245,12 +245,12 @@ krb5_DES_AFS3_Transarc_string_to_key (krb5_data pw, memcpy(&ivec, "kerberos", 8); memcpy(&temp_key, "kerberos", 8); DES_set_odd_parity (&temp_key); - DES_set_key (&temp_key, &schedule); + DES_set_key_unchecked (&temp_key, &schedule); DES_cbc_cksum ((void*)password, &ivec, passlen, &schedule, &ivec); memcpy(&temp_key, &ivec, 8); DES_set_odd_parity (&temp_key); - DES_set_key (&temp_key, &schedule); + DES_set_key_unchecked (&temp_key, &schedule); DES_cbc_cksum ((void*)password, key, passlen, &schedule, &ivec); memset(&schedule, 0, sizeof(schedule)); memset(&temp_key, 0, sizeof(temp_key)); @@ -305,7 +305,7 @@ DES_string_to_key_int(unsigned char *data, size_t length, DES_cblock *key) DES_set_odd_parity(key); if(DES_is_weak_key(key)) (*key)[7] ^= 0xF0; - DES_set_key(key, &schedule); + DES_set_key_unchecked(key, &schedule); DES_cbc_cksum((void*)data, key, length, &schedule, key); memset(&schedule, 0, sizeof(schedule)); DES_set_odd_parity(key); @@ -338,7 +338,7 @@ krb5_DES_string_to_key(krb5_context context, len = password.length + salt.saltvalue.length; s = malloc(len); if(len > 0 && s == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy(s, password.data, password.length); @@ -390,9 +390,9 @@ DES3_schedule(krb5_context context, { DES_cblock *k = key->key->keyvalue.data; DES_key_schedule *s = key->schedule->data; - DES_set_key(&k[0], &s[0]); - DES_set_key(&k[1], &s[1]); - DES_set_key(&k[2], &s[2]); + DES_set_key_unchecked(&k[0], &s[0]); + DES_set_key_unchecked(&k[1], &s[1]); + DES_set_key_unchecked(&k[2], &s[2]); } /* @@ -430,7 +430,7 @@ DES3_string_to_key(krb5_context context, len = password.length + salt.saltvalue.length; str = malloc(len); if(len != 0 && str == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy(str, password.data, password.length); @@ -444,7 +444,7 @@ DES3_string_to_key(krb5_context context, if (ret) { memset(str, 0, len); free(str); - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message (context, ret, "malloc: out of memory"); return ret; } @@ -453,7 +453,7 @@ DES3_string_to_key(krb5_context context, DES_set_odd_parity(keys + i); if(DES_is_weak_key(keys + i)) xor(keys + i, (const unsigned char*)"\0\0\0\0\0\0\0\xf0"); - DES_set_key(keys + i, &s[i]); + DES_set_key_unchecked(keys + i, &s[i]); } memset(&ivec, 0, sizeof(ivec)); DES_ede3_cbc_encrypt(tmp, @@ -491,7 +491,7 @@ DES3_string_to_key_derived(krb5_context context, s = malloc(len); if(len != 0 && s == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy(s, password.data, password.length); @@ -560,35 +560,49 @@ ARCFOUR_string_to_key(krb5_context context, krb5_data opaque, krb5_keyblock *key) { - char *s, *p; - size_t len; - int i; - MD4_CTX m; krb5_error_code ret; + uint16_t *s; + size_t len, i; + MD4_CTX m; - len = 2 * password.length; - s = malloc (len); + ret = wind_utf8ucs2_length(password.data, &len); + if (ret) { + krb5_set_error_message (context, ret, "Password not an UCS2 string"); + return ret; + } + + s = malloc (len * sizeof(s[0])); if (len != 0 && s == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - ret = ENOMEM; - goto out; + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); + return ENOMEM; } - for (p = s, i = 0; i < password.length; ++i) { - *p++ = ((char *)password.data)[i]; - *p++ = 0; + + ret = wind_utf8ucs2(password.data, s, &len); + if (ret) { + krb5_set_error_message (context, ret, "Password not an UCS2 string"); + goto out; } + + /* LE encoding */ MD4_Init (&m); - MD4_Update (&m, s, len); + for (i = 0; i < len; i++) { + unsigned char p; + p = (s[i] & 0xff); + MD4_Update (&m, &p, 1); + p = (s[i] >> 8) & 0xff; + MD4_Update (&m, &p, 1); + } + key->keytype = enctype; ret = krb5_data_alloc (&key->keyvalue, 16); if (ret) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); goto out; } MD4_Final (key->keyvalue.data, &m); - memset (s, 0, len); ret = 0; out: + memset (s, 0, len); free (s); return ret; } @@ -628,13 +642,13 @@ AES_string_to_key(krb5_context context, kd.schedule = NULL; ALLOC(kd.key, 1); if(kd.key == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } kd.key->keytype = enctype; ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); if (ret) { - krb5_set_error_string(context, "Failed to allocate pkcs5 key"); + krb5_set_error_message (context, ret, "malloc: out of memory"); return ret; } @@ -644,7 +658,8 @@ AES_string_to_key(krb5_context context, et->keytype->size, kd.key->keyvalue.data); if (ret != 1) { free_key_data(context, &kd); - krb5_set_error_string(context, "Error calculating s2k"); + krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP, + "Error calculating s2k"); return KRB5_PROG_KEYTYPE_NOSUPP; } @@ -847,21 +862,24 @@ krb5_salttype_to_string (krb5_context context, e = _find_enctype (etype); if (e == NULL) { - krb5_set_error_string(context, "encryption type %d not supported", - etype); + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + etype); return KRB5_PROG_ETYPE_NOSUPP; } for (st = e->keytype->string_to_key; st && st->type; st++) { if (st->type == stype) { *string = strdup (st->name); if (*string == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, + "malloc: out of memory"); return ENOMEM; } return 0; } } - krb5_set_error_string(context, "salttype %d not supported", stype); + krb5_set_error_message (context, HEIM_ERR_SALTTYPE_NOSUPP, + "salttype %d not supported", stype); return HEIM_ERR_SALTTYPE_NOSUPP; } @@ -876,8 +894,9 @@ krb5_string_to_salttype (krb5_context context, e = _find_enctype (etype); if (e == NULL) { - krb5_set_error_string(context, "encryption type %d not supported", - etype); + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + etype); return KRB5_PROG_ETYPE_NOSUPP; } for (st = e->keytype->string_to_key; st && st->type; st++) { @@ -886,7 +905,8 @@ krb5_string_to_salttype (krb5_context context, return 0; } } - krb5_set_error_string(context, "salttype %s not supported", string); + krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP, + "salttype %s not supported", string); return HEIM_ERR_SALTTYPE_NOSUPP; } @@ -988,16 +1008,18 @@ krb5_string_to_key_data_salt_opaque (krb5_context context, struct encryption_type *et =_find_enctype(enctype); struct salt_type *st; if(et == NULL) { - krb5_set_error_string(context, "encryption type %d not supported", - enctype); + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + enctype); return KRB5_PROG_ETYPE_NOSUPP; } for(st = et->keytype->string_to_key; st && st->type; st++) if(st->type == salt.salttype) return (*st->string_to_key)(context, enctype, password, salt, opaque, key); - krb5_set_error_string(context, "salt type %d not supported", - salt.salttype); + krb5_set_error_message(context, HEIM_ERR_SALTTYPE_NOSUPP, + "salt type %d not supported", + salt.salttype); return HEIM_ERR_SALTTYPE_NOSUPP; } @@ -1042,12 +1064,13 @@ krb5_keytype_to_string(krb5_context context, { struct key_type *kt = _find_keytype(keytype); if(kt == NULL) { - krb5_set_error_string(context, "key type %d not supported", keytype); + krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP, + "key type %d not supported", keytype); return KRB5_PROG_KEYTYPE_NOSUPP; } *string = strdup(kt->name); if(*string == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } return 0; @@ -1058,13 +1081,24 @@ krb5_string_to_keytype(krb5_context context, const char *string, krb5_keytype *keytype) { + char *end; int i; + for(i = 0; i < num_keytypes; i++) if(strcasecmp(keytypes[i]->name, string) == 0){ *keytype = keytypes[i]->type; return 0; } - krb5_set_error_string(context, "key type %s not supported", string); + + /* check if the enctype is a number */ + *keytype = strtol(string, &end, 0); + if(*end == '\0' && *keytype != 0) { + if (krb5_enctype_valid(context, *keytype) == 0) + return 0; + } + + krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP, + "key type %s not supported", string); return KRB5_PROG_KEYTYPE_NOSUPP; } @@ -1075,8 +1109,9 @@ krb5_enctype_keysize(krb5_context context, { struct encryption_type *et = _find_enctype(type); if(et == NULL) { - krb5_set_error_string(context, "encryption type %d not supported", - type); + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + type); return KRB5_PROG_ETYPE_NOSUPP; } *keysize = et->keytype->size; @@ -1090,7 +1125,8 @@ krb5_enctype_keybits(krb5_context context, { struct encryption_type *et = _find_enctype(type); if(et == NULL) { - krb5_set_error_string(context, "encryption type %d not supported", + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", type); return KRB5_PROG_ETYPE_NOSUPP; } @@ -1106,8 +1142,9 @@ krb5_generate_random_keyblock(krb5_context context, krb5_error_code ret; struct encryption_type *et = _find_enctype(type); if(et == NULL) { - krb5_set_error_string(context, "encryption type %d not supported", - type); + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + type); return KRB5_PROG_ETYPE_NOSUPP; } ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); @@ -1136,7 +1173,7 @@ _key_schedule(krb5_context context, return 0; ALLOC(key->schedule, 1); if(key->schedule == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = krb5_data_alloc(key->schedule, kt->schedule_size); @@ -1481,8 +1518,9 @@ krb5_hmac(krb5_context context, krb5_error_code ret; if (c == NULL) { - krb5_set_error_string (context, "checksum type %d not supported", - cktype); + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "checksum type %d not supported", + cktype); return KRB5_PROG_SUMTYPE_NOSUPP; } @@ -1797,7 +1835,7 @@ get_checksum_key(krb5_context context, *key = _new_derived_key(crypto, 0xff/* KRB5_KU_RFC1510_VARIANT */); if(*key == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = krb5_copy_keyblock(context, crypto->key.key, &(*key)->key); @@ -1832,9 +1870,10 @@ create_checksum (krb5_context context, } keyed_checksum = (ct->flags & F_KEYED) != 0; if(keyed_checksum && crypto == NULL) { - krb5_set_error_string (context, "Checksum type %s is keyed " - "but no crypto context (key) was passed in", - ct->name); + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "Checksum type %s is keyed " + "but no crypto context (key) was passed in", + ct->name); return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ } if(keyed_checksum) { @@ -1880,8 +1919,9 @@ krb5_create_checksum(krb5_context context, } if(ct == NULL) { - krb5_set_error_string (context, "checksum type %d not supported", - type); + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "checksum type %d not supported", + type); return KRB5_PROG_SUMTYPE_NOSUPP; } @@ -1911,7 +1951,8 @@ verify_checksum(krb5_context context, ct = _find_checksum(cksum->cksumtype); if (ct == NULL || (ct->flags & F_DISABLED)) { - krb5_set_error_string (context, "checksum type %d not supported", + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "checksum type %d not supported", cksum->cksumtype); return KRB5_PROG_SUMTYPE_NOSUPP; } @@ -1921,9 +1962,10 @@ verify_checksum(krb5_context context, } keyed_checksum = (ct->flags & F_KEYED) != 0; if(keyed_checksum && crypto == NULL) { - krb5_set_error_string (context, "Checksum type %s is keyed " - "but no crypto context (key) was passed in", - ct->name); + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "Checksum type %s is keyed " + "but no crypto context (key) was passed in", + ct->name); return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ } if(keyed_checksum) @@ -1963,8 +2005,9 @@ krb5_verify_checksum(krb5_context context, ct = _find_checksum(cksum->cksumtype); if(ct == NULL) { - krb5_set_error_string (context, "checksum type %d not supported", - cksum->cksumtype); + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "checksum type %d not supported", + cksum->cksumtype); return KRB5_PROG_SUMTYPE_NOSUPP; } @@ -1992,7 +2035,8 @@ krb5_crypto_get_checksum_type(krb5_context context, } if (ct == NULL) { - krb5_set_error_string (context, "checksum type not found"); + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "checksum type not found"); return KRB5_PROG_SUMTYPE_NOSUPP; } @@ -2009,8 +2053,9 @@ krb5_checksumsize(krb5_context context, { struct checksum_type *ct = _find_checksum(type); if(ct == NULL) { - krb5_set_error_string (context, "checksum type %d not supported", - type); + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "checksum type %d not supported", + type); return KRB5_PROG_SUMTYPE_NOSUPP; } *size = ct->checksumsize; @@ -2024,8 +2069,9 @@ krb5_checksum_is_keyed(krb5_context context, struct checksum_type *ct = _find_checksum(type); if(ct == NULL) { if (context) - krb5_set_error_string (context, "checksum type %d not supported", - type); + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "checksum type %d not supported", + type); return KRB5_PROG_SUMTYPE_NOSUPP; } return ct->flags & F_KEYED; @@ -2038,8 +2084,9 @@ krb5_checksum_is_collision_proof(krb5_context context, struct checksum_type *ct = _find_checksum(type); if(ct == NULL) { if (context) - krb5_set_error_string (context, "checksum type %d not supported", - type); + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "checksum type %d not supported", + type); return KRB5_PROG_SUMTYPE_NOSUPP; } return ct->flags & F_CPROOF; @@ -2052,8 +2099,9 @@ krb5_checksum_disable(krb5_context context, struct checksum_type *ct = _find_checksum(type); if(ct == NULL) { if (context) - krb5_set_error_string (context, "checksum type %d not supported", - type); + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "checksum type %d not supported", + type); return KRB5_PROG_SUMTYPE_NOSUPP; } ct->flags |= F_DISABLED; @@ -2478,7 +2526,7 @@ AES_PRF(krb5_context context, result.cksumtype = ct->type; ret = krb5_data_alloc(&result.checksum, ct->checksumsize); if (ret) { - krb5_set_error_string(context, "out memory"); + krb5_set_error_message(context, ret, "out memory"); return ret; } @@ -2519,7 +2567,6 @@ AES_PRF(krb5_context context, static struct encryption_type enctype_null = { ETYPE_NULL, "null", - NULL, 1, 1, 0, @@ -2534,7 +2581,6 @@ static struct encryption_type enctype_null = { static struct encryption_type enctype_des_cbc_crc = { ETYPE_DES_CBC_CRC, "des-cbc-crc", - NULL, 8, 8, 8, @@ -2549,7 +2595,6 @@ static struct encryption_type enctype_des_cbc_crc = { static struct encryption_type enctype_des_cbc_md4 = { ETYPE_DES_CBC_MD4, "des-cbc-md4", - NULL, 8, 8, 8, @@ -2564,7 +2609,6 @@ static struct encryption_type enctype_des_cbc_md4 = { static struct encryption_type enctype_des_cbc_md5 = { ETYPE_DES_CBC_MD5, "des-cbc-md5", - NULL, 8, 8, 8, @@ -2579,7 +2623,6 @@ static struct encryption_type enctype_des_cbc_md5 = { static struct encryption_type enctype_arcfour_hmac_md5 = { ETYPE_ARCFOUR_HMAC_MD5, "arcfour-hmac-md5", - NULL, 1, 1, 8, @@ -2594,7 +2637,6 @@ static struct encryption_type enctype_arcfour_hmac_md5 = { static struct encryption_type enctype_des3_cbc_md5 = { ETYPE_DES3_CBC_MD5, "des3-cbc-md5", - NULL, 8, 8, 8, @@ -2609,7 +2651,6 @@ static struct encryption_type enctype_des3_cbc_md5 = { static struct encryption_type enctype_des3_cbc_sha1 = { ETYPE_DES3_CBC_SHA1, "des3-cbc-sha1", - NULL, 8, 8, 8, @@ -2624,7 +2665,6 @@ static struct encryption_type enctype_des3_cbc_sha1 = { static struct encryption_type enctype_old_des3_cbc_sha1 = { ETYPE_OLD_DES3_CBC_SHA1, "old-des3-cbc-sha1", - NULL, 8, 8, 8, @@ -2639,7 +2679,6 @@ static struct encryption_type enctype_old_des3_cbc_sha1 = { static struct encryption_type enctype_aes128_cts_hmac_sha1 = { ETYPE_AES128_CTS_HMAC_SHA1_96, "aes128-cts-hmac-sha1-96", - NULL, 16, 1, 16, @@ -2654,7 +2693,6 @@ static struct encryption_type enctype_aes128_cts_hmac_sha1 = { static struct encryption_type enctype_aes256_cts_hmac_sha1 = { ETYPE_AES256_CTS_HMAC_SHA1_96, "aes256-cts-hmac-sha1-96", - NULL, 16, 1, 16, @@ -2669,7 +2707,6 @@ static struct encryption_type enctype_aes256_cts_hmac_sha1 = { static struct encryption_type enctype_des_cbc_none = { ETYPE_DES_CBC_NONE, "des-cbc-none", - NULL, 8, 8, 0, @@ -2684,7 +2721,6 @@ static struct encryption_type enctype_des_cbc_none = { static struct encryption_type enctype_des_cfb64_none = { ETYPE_DES_CFB64_NONE, "des-cfb64-none", - NULL, 1, 1, 0, @@ -2699,7 +2735,6 @@ static struct encryption_type enctype_des_cfb64_none = { static struct encryption_type enctype_des_pcbc_none = { ETYPE_DES_PCBC_NONE, "des-pcbc-none", - NULL, 8, 8, 0, @@ -2714,7 +2749,6 @@ static struct encryption_type enctype_des_pcbc_none = { static struct encryption_type enctype_des3_cbc_none = { ETYPE_DES3_CBC_NONE, "des3-cbc-none", - NULL, 8, 8, 0, @@ -2766,14 +2800,15 @@ krb5_enctype_to_string(krb5_context context, struct encryption_type *e; e = _find_enctype(etype); if(e == NULL) { - krb5_set_error_string (context, "encryption type %d not supported", - etype); + krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + etype); *string = NULL; return KRB5_PROG_ETYPE_NOSUPP; } *string = strdup(e->name); if(*string == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } return 0; @@ -2790,43 +2825,9 @@ krb5_string_to_enctype(krb5_context context, *etype = etypes[i]->type; return 0; } - krb5_set_error_string (context, "encryption type %s not supported", - string); - return KRB5_PROG_ETYPE_NOSUPP; -} - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_enctype_to_oid(krb5_context context, - krb5_enctype etype, - heim_oid *oid) -{ - struct encryption_type *et = _find_enctype(etype); - if(et == NULL) { - krb5_set_error_string (context, "encryption type %d not supported", - etype); - return KRB5_PROG_ETYPE_NOSUPP; - } - if(et->oid == NULL) { - krb5_set_error_string (context, "%s have not oid", et->name); - return KRB5_PROG_ETYPE_NOSUPP; - } - krb5_clear_error_string(context); - return der_copy_oid(et->oid, oid); -} - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_oid_to_enctype(krb5_context context, - const heim_oid *oid, - krb5_enctype *etype) -{ - int i; - for(i = 0; i < num_etypes; i++) { - if(etypes[i]->oid && der_heim_oid_cmp(etypes[i]->oid, oid) == 0) { - *etype = etypes[i]->type; - return 0; - } - } - krb5_set_error_string(context, "enctype for oid not supported"); + krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %s not supported", + string); return KRB5_PROG_ETYPE_NOSUPP; } @@ -2837,7 +2838,8 @@ krb5_enctype_to_keytype(krb5_context context, { struct encryption_type *e = _find_enctype(etype); if(e == NULL) { - krb5_set_error_string (context, "encryption type %d not supported", + krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", etype); return KRB5_PROG_ETYPE_NOSUPP; } @@ -2845,21 +2847,6 @@ krb5_enctype_to_keytype(krb5_context context, return 0; } -#if 0 -krb5_error_code KRB5_LIB_FUNCTION -krb5_keytype_to_enctype(krb5_context context, - krb5_keytype keytype, - krb5_enctype *etype) -{ - struct key_type *kt = _find_keytype(keytype); - krb5_warnx(context, "krb5_keytype_to_enctype(%u)", keytype); - if(kt == NULL) - return KRB5_PROG_KEYTYPE_NOSUPP; - *etype = kt->best_etype; - return 0; -} -#endif - krb5_error_code KRB5_LIB_FUNCTION krb5_keytype_to_enctypes (krb5_context context, krb5_keytype keytype, @@ -2877,7 +2864,7 @@ krb5_keytype_to_enctypes (krb5_context context, } ret = malloc(n * sizeof(*ret)); if (ret == NULL && n != 0) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } n = 0; @@ -2902,7 +2889,7 @@ krb5_keytype_to_enctypes_default (krb5_context context, unsigned *len, krb5_enctype **val) { - int i, n; + unsigned int i, n; krb5_enctype *ret; if (keytype != KEYTYPE_DES || context->etypes_des == NULL) @@ -2912,7 +2899,7 @@ krb5_keytype_to_enctypes_default (krb5_context context, ; ret = malloc (n * sizeof(*ret)); if (ret == NULL && n != 0) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } for (i = 0; i < n; ++i) @@ -2928,13 +2915,15 @@ krb5_enctype_valid(krb5_context context, { struct encryption_type *e = _find_enctype(etype); if(e == NULL) { - krb5_set_error_string (context, "encryption type %d not supported", - etype); + krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + etype); return KRB5_PROG_ETYPE_NOSUPP; } if (e->flags & F_DISABLED) { - krb5_set_error_string (context, "encryption type %s is disabled", - e->name); + krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %s is disabled", + e->name); return KRB5_PROG_ETYPE_NOSUPP; } return 0; @@ -2946,13 +2935,15 @@ krb5_cksumtype_valid(krb5_context context, { struct checksum_type *c = _find_checksum(ctype); if (c == NULL) { - krb5_set_error_string (context, "checksum type %d not supported", - ctype); + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "checksum type %d not supported", + ctype); return KRB5_PROG_SUMTYPE_NOSUPP; } if (c->flags & F_DISABLED) { - krb5_set_error_string (context, "checksum type %s is disabled", - c->name); + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "checksum type %s is disabled", + c->name); return KRB5_PROG_SUMTYPE_NOSUPP; } return 0; @@ -3010,7 +3001,7 @@ encrypt_internal_derived(krb5_context context, total_sz = block_sz + checksum_sz; p = calloc(1, total_sz); if(p == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -3077,7 +3068,7 @@ encrypt_internal(krb5_context context, block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ p = calloc(1, block_sz); if(p == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -3142,7 +3133,7 @@ encrypt_internal_special(krb5_context context, tmp = malloc (sz); if (tmp == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } p = tmp; @@ -3181,8 +3172,9 @@ decrypt_internal_derived(krb5_context context, checksum_sz = CHECKSUMSIZE(et->keyed_checksum); if (len < checksum_sz + et->confoundersize) { - krb5_set_error_string(context, "Encrypted data shorter then " - "checksum + confunder"); + krb5_set_error_message(context, KRB5_BAD_MSIZE, + "Encrypted data shorter then " + "checksum + confunder"); return KRB5_BAD_MSIZE; } @@ -3193,7 +3185,7 @@ decrypt_internal_derived(krb5_context context, p = malloc(len); if(len != 0 && p == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy(p, data, len); @@ -3238,7 +3230,7 @@ decrypt_internal_derived(krb5_context context, result->data = realloc(p, l); if(result->data == NULL && l != 0) { free(p); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } result->length = l; @@ -3267,7 +3259,7 @@ decrypt_internal(krb5_context context, checksum_sz = CHECKSUMSIZE(et->checksum); p = malloc(len); if(len != 0 && p == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy(p, data, len); @@ -3303,7 +3295,7 @@ decrypt_internal(krb5_context context, result->data = realloc(p, l); if(result->data == NULL && l != 0) { free(p); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } result->length = l; @@ -3332,7 +3324,7 @@ decrypt_internal_special(krb5_context context, p = malloc (len); if (p == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy(p, data, len); @@ -3347,7 +3339,7 @@ decrypt_internal_special(krb5_context context, result->data = realloc(p, sz); if(result->data == NULL && sz != 0) { free(p); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } result->length = sz; @@ -3463,6 +3455,7 @@ seed_something(void) fd = open(seedfile, O_RDONLY); if (fd >= 0) { ssize_t ret; + rk_cloexec(fd); ret = read(fd, buf, sizeof(buf)); if (ret > 0) RAND_add(buf, ret, 0.0); @@ -3547,13 +3540,13 @@ derive_key(krb5_context context, nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8); k = malloc(nblocks * et->blocksize); if(k == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = _krb5_n_fold(constant, len, k, et->blocksize); if (ret) { free(k); - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); return ret; } for(i = 0; i < nblocks; i++) { @@ -3570,7 +3563,7 @@ derive_key(krb5_context context, size_t res_len = (kt->bits + 7) / 8; if(len != 0 && c == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy(c, constant, len); @@ -3578,13 +3571,13 @@ derive_key(krb5_context context, k = malloc(res_len); if(res_len != 0 && k == NULL) { free(c); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = _krb5_n_fold(c, len, k, res_len); if (ret) { free(k); - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); return ret; } free(c); @@ -3600,10 +3593,10 @@ derive_key(krb5_context context, memcpy(key->key->keyvalue.data, k, key->key->keyvalue.length); break; default: - krb5_set_error_string(context, - "derive_key() called with unknown keytype (%u)", - kt->type); ret = KRB5_CRYPTO_INTERNAL; + krb5_set_error_message(context, ret, + "derive_key() called with unknown keytype (%u)", + kt->type); break; } if (key->schedule) { @@ -3645,8 +3638,9 @@ krb5_derive_key(krb5_context context, et = _find_enctype (etype); if (et == NULL) { - krb5_set_error_string(context, "encryption type %d not supported", - etype); + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + etype); return KRB5_PROG_ETYPE_NOSUPP; } @@ -3679,7 +3673,7 @@ _get_derived_key(krb5_context context, } d = _new_derived_key(crypto, usage); if(d == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } krb5_copy_keyblock(context, crypto->key.key, &d->key); @@ -3699,7 +3693,7 @@ krb5_crypto_init(krb5_context context, krb5_error_code ret; ALLOC(*crypto, 1); if(*crypto == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } if(etype == ETYPE_NULL) @@ -3708,14 +3702,16 @@ krb5_crypto_init(krb5_context context, if((*crypto)->et == NULL || ((*crypto)->et->flags & F_DISABLED)) { free(*crypto); *crypto = NULL; - krb5_set_error_string (context, "encryption type %d not supported", - etype); + krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + etype); return KRB5_PROG_ETYPE_NOSUPP; } if((*crypto)->et->keytype->size != key->keyvalue.length) { free(*crypto); *crypto = NULL; - krb5_set_error_string (context, "encryption key has bad length"); + krb5_set_error_message (context, KRB5_BAD_KEYSIZE, + "encryption key has bad length"); return KRB5_BAD_KEYSIZE; } ret = krb5_copy_keyblock(context, key, &(*crypto)->key.key); @@ -3803,8 +3799,9 @@ krb5_enctype_disable(krb5_context context, struct encryption_type *et = _find_enctype(enctype); if(et == NULL) { if (context) - krb5_set_error_string (context, "encryption type %d not supported", - enctype); + krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + enctype); return KRB5_PROG_ETYPE_NOSUPP; } et->flags |= F_DISABLED; @@ -3825,15 +3822,17 @@ krb5_string_to_key_derived(krb5_context context, u_char *tmp; if(et == NULL) { - krb5_set_error_string (context, "encryption type %d not supported", - etype); + krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + etype); return KRB5_PROG_ETYPE_NOSUPP; } keylen = et->keytype->bits / 8; ALLOC(kd.key, 1); if(kd.key == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, + "malloc: out of memory"); return ENOMEM; } ret = krb5_data_alloc(&kd.key->keyvalue, et->keytype->size); @@ -3845,13 +3844,13 @@ krb5_string_to_key_derived(krb5_context context, tmp = malloc (keylen); if(tmp == NULL) { krb5_free_keyblock(context, kd.key); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = _krb5_n_fold(str, len, tmp, keylen); if (ret) { free(tmp); - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); return ret; } kd.schedule = NULL; @@ -3970,14 +3969,16 @@ krb5_random_to_key(krb5_context context, krb5_error_code ret; struct encryption_type *et = _find_enctype(type); if(et == NULL) { - krb5_set_error_string(context, "encryption type %d not supported", - type); + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + type); return KRB5_PROG_ETYPE_NOSUPP; } if ((et->keytype->bits + 7) / 8 > size) { - krb5_set_error_string(context, "encryption key %s needs %d bytes " - "of random to make an encryption key out of it", - et->name, (int)et->keytype->size); + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "encryption key %s needs %d bytes " + "of random to make an encryption key out of it", + et->name, (int)et->keytype->size); return KRB5_PROG_ETYPE_NOSUPP; } ret = krb5_data_alloc(&key->keyvalue, et->keytype->size); @@ -4009,15 +4010,16 @@ _krb5_pk_octetstring2key(krb5_context context, unsigned char shaoutput[20]; if(et == NULL) { - krb5_set_error_string(context, "encryption type %d not supported", - type); + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + type); return KRB5_PROG_ETYPE_NOSUPP; } keylen = (et->keytype->bits + 7) / 8; keydata = malloc(keylen); if (keydata == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -4050,6 +4052,182 @@ _krb5_pk_octetstring2key(krb5_context context, return ret; } +static krb5_error_code +encode_uvinfo(krb5_context context, krb5_const_principal p, krb5_data *data) +{ + KRB5PrincipalName pn; + krb5_error_code ret; + size_t size; + + pn.principalName = p->name; + pn.realm = p->realm; + + ASN1_MALLOC_ENCODE(KRB5PrincipalName, data->data, data->length, + &pn, &size, ret); + if (ret) { + krb5_data_zero(data); + krb5_set_error_message(context, ret, + "Failed to encode KRB5PrincipalName"); + return ret; + } + if (data->length != size) + krb5_abortx(context, "asn1 compiler internal error"); + return 0; +} + +static krb5_error_code +encode_otherinfo(krb5_context context, + const AlgorithmIdentifier *ai, + krb5_const_principal client, + krb5_const_principal server, + krb5_enctype enctype, + const krb5_data *as_req, + const krb5_data *pk_as_rep, + const Ticket *ticket, + krb5_data *other) +{ + PkinitSP80056AOtherInfo otherinfo; + PkinitSuppPubInfo pubinfo; + krb5_error_code ret; + krb5_data pub; + size_t size; + + krb5_data_zero(other); + memset(&otherinfo, 0, sizeof(otherinfo)); + memset(&pubinfo, 0, sizeof(pubinfo)); + + pubinfo.enctype = enctype; + pubinfo.as_REQ = *as_req; + pubinfo.pk_as_rep = *pk_as_rep; + pubinfo.ticket = *ticket; + ASN1_MALLOC_ENCODE(PkinitSuppPubInfo, pub.data, pub.length, + &pubinfo, &size, ret); + if (ret) { + krb5_set_error_message(context, ret, "out of memory"); + return ret; + } + if (pub.length != size) + krb5_abortx(context, "asn1 compiler internal error"); + + ret = encode_uvinfo(context, client, &otherinfo.partyUInfo); + if (ret) { + free(pub.data); + return ret; + } + ret = encode_uvinfo(context, server, &otherinfo.partyVInfo); + if (ret) { + free(otherinfo.partyUInfo.data); + free(pub.data); + return ret; + } + + otherinfo.algorithmID = *ai; + otherinfo.suppPubInfo = &pub; + + ASN1_MALLOC_ENCODE(PkinitSP80056AOtherInfo, other->data, other->length, + &otherinfo, &size, ret); + free(otherinfo.partyUInfo.data); + free(otherinfo.partyVInfo.data); + free(pub.data); + if (ret) { + krb5_set_error_message(context, ret, "out of memory"); + return ret; + } + if (other->length != size) + krb5_abortx(context, "asn1 compiler internal error"); + + return 0; +} + +krb5_error_code +_krb5_pk_kdf(krb5_context context, + const struct AlgorithmIdentifier *ai, + const void *dhdata, + size_t dhsize, + krb5_const_principal client, + krb5_const_principal server, + krb5_enctype enctype, + const krb5_data *as_req, + const krb5_data *pk_as_rep, + const Ticket *ticket, + krb5_keyblock *key) +{ + struct encryption_type *et; + krb5_error_code ret; + krb5_data other; + size_t keylen, offset; + uint32_t counter; + unsigned char *keydata; + unsigned char shaoutput[20]; + + if (der_heim_oid_cmp(oid_id_pkinit_kdf_ah_sha1(), &ai->algorithm) != 0) { + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "kdf not supported"); + return KRB5_PROG_ETYPE_NOSUPP; + } + if (ai->parameters != NULL && + (ai->parameters->length != 2 || + memcmp(ai->parameters->data, "\x05\x00", 2) != 0)) + { + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "kdf params not NULL or the NULL-type"); + return KRB5_PROG_ETYPE_NOSUPP; + } + + et = _find_enctype(enctype); + if(et == NULL) { + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + enctype); + return KRB5_PROG_ETYPE_NOSUPP; + } + keylen = (et->keytype->bits + 7) / 8; + + keydata = malloc(keylen); + if (keydata == NULL) { + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); + return ENOMEM; + } + + ret = encode_otherinfo(context, ai, client, server, + enctype, as_req, pk_as_rep, ticket, &other); + if (ret) { + free(keydata); + return ret; + } + + offset = 0; + counter = 1; + do { + unsigned char cdata[4]; + SHA_CTX m; + + SHA1_Init(&m); + _krb5_put_int(cdata, counter, 4); + SHA1_Update(&m, cdata, 4); + SHA1_Update(&m, dhdata, dhsize); + SHA1_Update(&m, other.data, other.length); + SHA1_Final(shaoutput, &m); + + memcpy((unsigned char *)keydata + offset, + shaoutput, + min(keylen - offset, sizeof(shaoutput))); + + offset += sizeof(shaoutput); + counter++; + } while(offset < keylen); + memset(shaoutput, 0, sizeof(shaoutput)); + + free(other.data); + + ret = krb5_random_to_key(context, enctype, keydata, keylen, key); + memset(keydata, 0, sizeof(keylen)); + free(keydata); + + return ret; +} + + krb5_error_code KRB5_LIB_FUNCTION krb5_crypto_prf_length(krb5_context context, krb5_enctype type, @@ -4058,8 +4236,9 @@ krb5_crypto_prf_length(krb5_context context, struct encryption_type *et = _find_enctype(type); if(et == NULL || et->prf_length == 0) { - krb5_set_error_string(context, "encryption type %d not supported", - type); + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + type); return KRB5_PROG_ETYPE_NOSUPP; } @@ -4078,8 +4257,9 @@ krb5_crypto_prf(krb5_context context, krb5_data_zero(output); if(et->prf == NULL) { - krb5_set_error_string(context, "kerberos prf for %s not supported", - et->name); + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "kerberos prf for %s not supported", + et->name); return KRB5_PROG_ETYPE_NOSUPP; } diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c index eda1a8b259..2b78bfb32b 100644 --- a/source4/heimdal/lib/krb5/data.c +++ b/source4/heimdal/lib/krb5/data.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: data.c 22064 2007-11-11 16:28:14Z lha $"); +RCSID("$Id: data.c 23280 2008-06-23 03:26:18Z lha $"); /** * Reset the (potentially uninitalized) krb5_data structure. @@ -192,7 +192,7 @@ krb5_copy_data(krb5_context context, krb5_error_code ret; ALLOC(*outdata, 1); if(*outdata == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = der_copy_octet_string(indata, *outdata); diff --git a/source4/heimdal/lib/krb5/error_string.c b/source4/heimdal/lib/krb5/error_string.c index ff6e98a3dc..6679b76749 100644 --- a/source4/heimdal/lib/krb5/error_string.c +++ b/source4/heimdal/lib/krb5/error_string.c @@ -33,59 +33,71 @@ #include "krb5_locl.h" -RCSID("$Id: error_string.c 22142 2007-12-04 16:56:02Z lha $"); +RCSID("$Id: error_string.c 23274 2008-06-23 03:25:08Z lha $"); #undef __attribute__ #define __attribute__(X) -void KRB5_LIB_FUNCTION -krb5_free_error_string(krb5_context context, char *str) -{ - HEIMDAL_MUTEX_lock(context->mutex); - if (str != context->error_buf) - free(str); - HEIMDAL_MUTEX_unlock(context->mutex); -} - void KRB5_LIB_FUNCTION krb5_clear_error_string(krb5_context context) { HEIMDAL_MUTEX_lock(context->mutex); - if (context->error_string != NULL - && context->error_string != context->error_buf) + if (context->error_string) free(context->error_string); + context->error_code = 0; context->error_string = NULL; HEIMDAL_MUTEX_unlock(context->mutex); } -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_error_string(krb5_context context, const char *fmt, ...) - __attribute__((format (printf, 2, 3))) +/** + * Set the context full error string for a specific error code. + * + * @param context Kerberos 5 context + * @param ret The error code + * @param fmt Error string for the error code + * @param ... printf(3) style parameters. + * + * @ingroup krb5_error + */ + +void KRB5_LIB_FUNCTION +krb5_set_error_message(krb5_context context, krb5_error_code ret, + const char *fmt, ...) + __attribute__ ((format (printf, 3, 4))) { - krb5_error_code ret; va_list ap; va_start(ap, fmt); - ret = krb5_vset_error_string (context, fmt, ap); + krb5_vset_error_message (context, ret, fmt, ap); va_end(ap); - return ret; } -krb5_error_code KRB5_LIB_FUNCTION -krb5_vset_error_string(krb5_context context, const char *fmt, va_list args) - __attribute__ ((format (printf, 2, 0))) +/** + * Set the context full error string for a specific error code. + * + * @param context Kerberos 5 context + * @param ret The error code + * @param fmt Error string for the error code + * @param args printf(3) style parameters. + * + * @ingroup krb5_error + */ + + +void KRB5_LIB_FUNCTION +krb5_vset_error_message (krb5_context context, krb5_error_code ret, + const char *fmt, va_list args) + __attribute__ ((format (printf, 3, 0))) { + krb5_clear_error_string(context); HEIMDAL_MUTEX_lock(context->mutex); + context->error_code = ret; vasprintf(&context->error_string, fmt, args); - if(context->error_string == NULL) { - vsnprintf (context->error_buf, sizeof(context->error_buf), fmt, args); - context->error_string = context->error_buf; - } HEIMDAL_MUTEX_unlock(context->mutex); - return 0; } + /** * Return the error message in context. On error or no error string, * the function returns NULL. @@ -93,7 +105,7 @@ krb5_vset_error_string(krb5_context context, const char *fmt, va_list args) * @param context Kerberos 5 context * * @return an error string, needs to be freed with - * krb5_free_error_string(). The functions return NULL on error. + * krb5_free_error_message(). The functions return NULL on error. * * @ingroup krb5_error */ @@ -121,35 +133,99 @@ krb5_have_error_string(krb5_context context) } /** - * Return the error message for `code' in context. On error the - * function returns NULL. + * Return the error message for `code' in context. On memory + * allocation error the function returns NULL. * * @param context Kerberos 5 context * @param code Error code related to the error * * @return an error string, needs to be freed with - * krb5_free_error_string(). The functions return NULL on error. + * krb5_free_error_message(). The functions return NULL on error. * * @ingroup krb5_error */ -char * KRB5_LIB_FUNCTION +const char * KRB5_LIB_FUNCTION krb5_get_error_message(krb5_context context, krb5_error_code code) { const char *cstr; char *str; - str = krb5_get_error_string(context); - if (str) - return str; + HEIMDAL_MUTEX_lock(context->mutex); + if (context->error_string && + (code == context->error_code || context->error_code == 0)) + { + str = strdup(context->error_string); + if (str) { + HEIMDAL_MUTEX_unlock(context->mutex); + return str; + } + } + HEIMDAL_MUTEX_unlock(context->mutex); cstr = krb5_get_err_text(context, code); if (cstr) return strdup(cstr); - if (asprintf(&str, "", code) == -1) + if (asprintf(&str, "", (int)code) == -1) return NULL; return str; } + +/** + * Free the error message returned by krb5_get_error_message(). + * + * @param context Kerberos context + * @param msg error message to free, returned byg + * krb5_get_error_message(). + * + * @ingroup krb5_error + */ + +void KRB5_LIB_FUNCTION +krb5_free_error_message(krb5_context context, const char *msg) +{ + free(rk_UNCONST(msg)); +} + +#ifndef HEIMDAL_SMALLER + +/** + * Free the error message returned by krb5_get_error_string(), + * deprecated, use krb5_free_error_message(). + * + * @param context Kerberos context + * @param msg error message to free + * + * @ingroup krb5_error + */ + +void KRB5_LIB_FUNCTION __attribute__((deprecated)) +krb5_free_error_string(krb5_context context, char *str) +{ + krb5_free_error_message(context, str); +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_error_string(krb5_context context, const char *fmt, ...) + __attribute__((format (printf, 2, 3))) __attribute__((deprecated)) +{ + va_list ap; + + va_start(ap, fmt); + krb5_vset_error_message (context, 0, fmt, ap); + va_end(ap); + return 0; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_vset_error_string(krb5_context context, const char *fmt, va_list args) + __attribute__ ((format (printf, 2, 0))) __attribute__((deprecated)) +{ + krb5_vset_error_message(context, 0, fmt, args); + return 0; +} + +#endif /* !HEIMDAL_SMALLER */ diff --git a/source4/heimdal/lib/krb5/expand_hostname.c b/source4/heimdal/lib/krb5/expand_hostname.c index 28e39afb42..d06d576432 100644 --- a/source4/heimdal/lib/krb5/expand_hostname.c +++ b/source4/heimdal/lib/krb5/expand_hostname.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: expand_hostname.c 22229 2007-12-08 21:40:59Z lha $"); +RCSID("$Id: expand_hostname.c 23280 2008-06-23 03:26:18Z lha $"); static krb5_error_code copy_hostname(krb5_context context, @@ -42,7 +42,7 @@ copy_hostname(krb5_context context, { *new_hostname = strdup (orig_hostname); if (*new_hostname == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } strlwr (*new_hostname); @@ -76,7 +76,8 @@ krb5_expand_hostname (krb5_context context, *new_hostname = strdup (a->ai_canonname); freeaddrinfo (ai); if (*new_hostname == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, + "malloc: out of memory"); return ENOMEM; } else { return 0; diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c index 484df059ab..8951bdb24e 100644 --- a/source4/heimdal/lib/krb5/fcache.c +++ b/source4/heimdal/lib/krb5/fcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: fcache.c 22517 2008-01-24 11:45:51Z lha $"); +RCSID("$Id: fcache.c 23444 2008-07-27 12:07:47Z lha $"); typedef struct krb5_fcache{ char *filename; @@ -93,12 +93,12 @@ _krb5_xlock(krb5_context context, int fd, krb5_boolean exclusive, ret = 0; break; case EAGAIN: - krb5_set_error_string(context, "timed out locking cache file %s", - filename); + krb5_set_error_message(context, ret, "timed out locking cache file %s", + filename); break; default: - krb5_set_error_string(context, "error locking cache file %s: %s", - filename, strerror(ret)); + krb5_set_error_message(context, ret, "error locking cache file %s: %s", + filename, strerror(ret)); break; } return ret; @@ -127,13 +127,39 @@ _krb5_xunlock(krb5_context context, int fd) ret = 0; break; default: - krb5_set_error_string(context, - "Failed to unlock file: %s", strerror(ret)); + krb5_set_error_message(context, ret, + "Failed to unlock file: %s", + strerror(ret)); break; } return ret; } +static krb5_error_code +write_storage(krb5_context context, krb5_storage *sp, int fd) +{ + krb5_error_code ret; + krb5_data data; + ssize_t sret; + + ret = krb5_storage_to_data(sp, &data); + if (ret) { + krb5_set_error_message(context, ret, "malloc: out of memory"); + return ret; + } + sret = write(fd, data.data, data.length); + ret = (sret != data.length); + krb5_data_free(&data); + if (ret) { + ret = errno; + krb5_set_error_message(context, ret, + "Failed to write FILE credential data"); + return ret; + } + return 0; +} + + static krb5_error_code fcc_lock(krb5_context context, krb5_ccache id, int fd, krb5_boolean exclusive) @@ -153,13 +179,15 @@ fcc_resolve(krb5_context context, krb5_ccache *id, const char *res) krb5_fcache *f; f = malloc(sizeof(*f)); if(f == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_CC_NOMEM, + "malloc: out of memory"); return KRB5_CC_NOMEM; } f->filename = strdup(res); if(f->filename == NULL){ free(f); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_CC_NOMEM, + "malloc: out of memory"); return KRB5_CC_NOMEM; } f->version = 0; @@ -203,7 +231,7 @@ scrub_file (int fd) */ static krb5_error_code -erase_file(const char *filename) +erase_file(krb5_context context, const char *filename) { int fd; struct stat sb1, sb2; @@ -220,12 +248,20 @@ erase_file(const char *filename) else return errno; } + rk_cloexec(fd); + ret = _krb5_xlock(context, fd, 1, filename); + if (ret) { + close(fd); + return ret; + } if (unlink(filename) < 0) { + _krb5_xunlock(context, fd); close (fd); return errno; } ret = fstat (fd, &sb2); if (ret < 0) { + _krb5_xunlock(context, fd); close (fd); return errno; } @@ -233,6 +269,7 @@ erase_file(const char *filename) /* check if someone was playing with symlinks */ if (sb1.st_dev != sb2.st_dev || sb1.st_ino != sb2.st_ino) { + _krb5_xunlock(context, fd); close (fd); return EPERM; } @@ -240,11 +277,18 @@ erase_file(const char *filename) /* there are still hard links to this file */ if (sb2.st_nlink != 0) { + _krb5_xunlock(context, fd); close (fd); return 0; } ret = scrub_file (fd); + if (ret) { + _krb5_xunlock(context, fd); + close(fd); + return ret; + } + ret = _krb5_xunlock(context, fd); close (fd); return ret; } @@ -258,19 +302,21 @@ fcc_gen_new(krb5_context context, krb5_ccache *id) f = malloc(sizeof(*f)); if(f == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_CC_NOMEM, + "malloc: out of memory"); return KRB5_CC_NOMEM; } asprintf (&file, "%sXXXXXX", KRB5_DEFAULT_CCFILE_ROOT); if(file == NULL) { free(f); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_CC_NOMEM, + "malloc: out of memory"); return KRB5_CC_NOMEM; } fd = mkstemp(file); if(fd < 0) { int ret = errno; - krb5_set_error_string(context, "mkstemp %s", file); + krb5_set_error_message(context, ret, "mkstemp %s", file); free(f); free(file); return ret; @@ -323,11 +369,12 @@ fcc_open(krb5_context context, fd = open(filename, flags, mode); if(fd < 0) { ret = errno; - krb5_set_error_string(context, "open(%s): %s", filename, - strerror(ret)); + krb5_set_error_message(context, ret, "open(%s): %s", filename, + strerror(ret)); return ret; } - + rk_cloexec(fd); + if((ret = fcc_lock(context, id, fd, exclusive)) != 0) { close(fd); return ret; @@ -353,7 +400,7 @@ fcc_initialize(krb5_context context, return ret; { krb5_storage *sp; - sp = krb5_storage_from_fd(fd); + sp = krb5_storage_emem(); krb5_storage_set_eof_code(sp, KRB5_CC_END); if(context->fcache_vno != 0) f->version = context->fcache_vno; @@ -376,14 +423,16 @@ fcc_initialize(krb5_context context, } ret |= krb5_store_principal(sp, primary_principal); + ret |= write_storage(context, sp, fd); + krb5_storage_free(sp); } fcc_unlock(context, fd); if (close(fd) < 0) if (ret == 0) { ret = errno; - krb5_set_error_string (context, "close %s: %s", - FILENAME(id), strerror(ret)); + krb5_set_error_message (context, ret, "close %s: %s", + FILENAME(id), strerror(ret)); } return ret; } @@ -401,7 +450,7 @@ static krb5_error_code fcc_destroy(krb5_context context, krb5_ccache id) { - erase_file(FILENAME(id)); + erase_file(context, FILENAME(id)); return 0; } @@ -418,7 +467,8 @@ fcc_store_cred(krb5_context context, return ret; { krb5_storage *sp; - sp = krb5_storage_from_fd(fd); + + sp = krb5_storage_emem(); krb5_storage_set_eof_code(sp, KRB5_CC_END); storage_set_flags(context, sp, FCACHE(id)->version); if (!krb5_config_get_bool_default(context, NULL, TRUE, @@ -427,15 +477,18 @@ fcc_store_cred(krb5_context context, NULL)) krb5_storage_set_flags(sp, KRB5_STORAGE_CREDS_FLAGS_WRONG_BITORDER); ret = krb5_store_creds(sp, creds); + if (ret == 0) + ret = write_storage(context, sp, fd); krb5_storage_free(sp); } fcc_unlock(context, fd); - if (close(fd) < 0) + if (close(fd) < 0) { if (ret == 0) { ret = errno; - krb5_set_error_string (context, "close %s: %s", - FILENAME(id), strerror(ret)); + krb5_set_error_message (context, ret, "close %s: %s", + FILENAME(id), strerror(ret)); } + } return ret; } @@ -464,25 +517,27 @@ init_fcc (krb5_context context, ret = krb5_ret_int8(sp, &pvno); if(ret != 0) { if(ret == KRB5_CC_END) { - krb5_set_error_string(context, "Empty credential cache file: %s", - FILENAME(id)); ret = ENOENT; + krb5_set_error_message(context, ret, + "Empty credential cache file: %s", + FILENAME(id)); } else - krb5_set_error_string(context, "Error reading pvno in " - "cache file: %s", FILENAME(id)); + krb5_set_error_message(context, ret, "Error reading pvno in " + "cache file: %s", FILENAME(id)); goto out; } if(pvno != 5) { - krb5_set_error_string(context, "Bad version number in credential " - "cache file: %s", FILENAME(id)); ret = KRB5_CCACHE_BADVNO; + krb5_set_error_message(context, ret, "Bad version number in " + "credential cache file: %s", + FILENAME(id)); goto out; } ret = krb5_ret_int8(sp, &tag); /* should not be host byte order */ if(ret != 0) { - krb5_set_error_string(context, "Error reading tag in " - "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; + krb5_set_error_message(context, ret, "Error reading tag in " + "cache file: %s", FILENAME(id)); goto out; } FCACHE(id)->version = tag; @@ -494,8 +549,9 @@ init_fcc (krb5_context context, ret = krb5_ret_int16 (sp, &length); if(ret) { ret = KRB5_CC_FORMAT; - krb5_set_error_string(context, "Error reading tag length in " - "cache file: %s", FILENAME(id)); + krb5_set_error_message(context, ret, + "Error reading tag length in " + "cache file: %s", FILENAME(id)); goto out; } while(length > 0) { @@ -505,32 +561,32 @@ init_fcc (krb5_context context, ret = krb5_ret_int16 (sp, &dtag); if(ret) { - krb5_set_error_string(context, "Error reading dtag in " - "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; + krb5_set_error_message(context, ret, "Error reading dtag in " + "cache file: %s", FILENAME(id)); goto out; } ret = krb5_ret_int16 (sp, &data_len); if(ret) { - krb5_set_error_string(context, "Error reading dlength in " - "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; + krb5_set_error_message(context, ret, "Error reading dlength in " + "cache file: %s", FILENAME(id)); goto out; } switch (dtag) { case FCC_TAG_DELTATIME : ret = krb5_ret_int32 (sp, &context->kdc_sec_offset); if(ret) { - krb5_set_error_string(context, "Error reading kdc_sec in " - "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; + krb5_set_error_message(context, ret, "Error reading kdc_sec in " + "cache file: %s", FILENAME(id)); goto out; } ret = krb5_ret_int32 (sp, &context->kdc_usec_offset); if(ret) { - krb5_set_error_string(context, "Error reading kdc_usec in " - "cache file: %s", FILENAME(id)); ret = KRB5_CC_FORMAT; + krb5_set_error_message(context, ret, "Error reading kdc_usec in " + "cache file: %s", FILENAME(id)); goto out; } break; @@ -538,10 +594,11 @@ init_fcc (krb5_context context, for (i = 0; i < data_len; ++i) { ret = krb5_ret_int8 (sp, &dummy); if(ret) { - krb5_set_error_string(context, "Error reading unknown " - "tag in cache file: %s", - FILENAME(id)); ret = KRB5_CC_FORMAT; + krb5_set_error_message(context, ret, + "Error reading unknown " + "tag in cache file: %s", + FILENAME(id)); goto out; } } @@ -557,9 +614,9 @@ init_fcc (krb5_context context, break; default : ret = KRB5_CCACHE_BADVNO; - krb5_set_error_string(context, "Unknown version number (%d) in " - "credential cache file: %s", - (int)tag, FILENAME(id)); + krb5_set_error_message(context, ret, "Unknown version number (%d) in " + "credential cache file: %s", + (int)tag, FILENAME(id)); goto out; } *ret_sp = sp; @@ -610,7 +667,7 @@ fcc_get_first (krb5_context context, *cursor = malloc(sizeof(struct fcc_cursor)); if (*cursor == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memset(*cursor, 0, sizeof(struct fcc_cursor)); @@ -670,7 +727,7 @@ fcc_remove_cred(krb5_context context, krb5_creds *cred) { krb5_error_code ret; - krb5_ccache copy; + krb5_ccache copy, newfile; ret = krb5_cc_gen_new(context, &krb5_mcc_ops, ©); if (ret) @@ -688,12 +745,20 @@ fcc_remove_cred(krb5_context context, return ret; } - fcc_destroy(context, id); + ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &newfile); + if (ret) { + krb5_cc_destroy(context, copy); + return ret; + } - ret = krb5_cc_copy_cache(context, copy, id); + ret = krb5_cc_copy_cache(context, copy, newfile); krb5_cc_destroy(context, copy); + if (ret) { + krb5_cc_destroy(context, newfile); + return ret; + } - return ret; + return krb5_cc_move(context, newfile, id); } static krb5_error_code @@ -704,7 +769,7 @@ fcc_set_flags(krb5_context context, return 0; /* XXX */ } -static krb5_error_code +static int fcc_get_version(krb5_context context, krb5_ccache id) { @@ -722,7 +787,7 @@ fcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) iter = calloc(1, sizeof(*iter)); if (iter == NULL) { - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } iter->first = 1; @@ -775,10 +840,10 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) ret = rename(FILENAME(from), FILENAME(to)); if (ret && errno != EXDEV) { ret = errno; - krb5_set_error_string(context, - "Rename of file from %s to %s failed: %s", - FILENAME(from), FILENAME(to), - strerror(ret)); + krb5_set_error_message(context, ret, + "Rename of file from %s to %s failed: %s", + FILENAME(from), FILENAME(to), + strerror(ret)); return ret; } else if (ret && errno == EXDEV) { /* make a copy and delete the orignal */ @@ -801,21 +866,19 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) sz2 = write(fd2, buf, sz1); if (sz1 != sz2) { ret = EIO; - krb5_set_error_string(context, - "Failed to write data from one file " - "credential cache to the other"); + krb5_set_error_message(context, ret, + "Failed to write data from one file " + "credential cache to the other"); goto out2; } } if (sz1 < 0) { ret = EIO; - krb5_set_error_string(context, - "Failed to read data from one file " - "credential cache to the other"); + krb5_set_error_message(context, ret, + "Failed to read data from one file " + "credential cache to the other"); goto out2; } - erase_file(FILENAME(from)); - out2: fcc_unlock(context, fd2); close(fd2); @@ -824,8 +887,10 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) fcc_unlock(context, fd1); close(fd1); + erase_file(context, FILENAME(from)); + if (ret) { - erase_file(FILENAME(to)); + erase_file(context, FILENAME(to)); return ret; } } @@ -856,7 +921,8 @@ fcc_default_name(krb5_context context, char **str) * @ingroup krb5_ccache */ -const krb5_cc_ops krb5_fcc_ops = { +KRB5_LIB_VARIABLE const krb5_cc_ops krb5_fcc_ops = { + KRB5_CC_OPS_VERSION, "FILE", fcc_get_name, fcc_resolve, diff --git a/source4/heimdal/lib/krb5/generate_subkey.c b/source4/heimdal/lib/krb5/generate_subkey.c index fb99cbbf3f..fb7efbcd29 100644 --- a/source4/heimdal/lib/krb5/generate_subkey.c +++ b/source4/heimdal/lib/krb5/generate_subkey.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: generate_subkey.c 14455 2005-01-05 02:39:21Z lukeh $"); +RCSID("$Id: generate_subkey.c 23280 2008-06-23 03:26:18Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_generate_subkey(krb5_context context, @@ -53,7 +53,7 @@ krb5_generate_subkey_extended(krb5_context context, ALLOC(*subkey, 1); if (*subkey == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index fc78945c63..268550b229 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -1,39 +1,39 @@ /* - * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * All rights reserved. + * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: + * 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. + * 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. + * 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 the Institute nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. + * 3. Neither the name of the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 THE INSTITUTE 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. */ #include -RCSID("$Id: get_cred.c 22530 2008-01-27 11:48:16Z lha $"); +RCSID("$Id: get_cred.c 23280 2008-06-23 03:26:18Z lha $"); /* * Take the `body' and encode it into `padata' using the credentials @@ -41,12 +41,11 @@ RCSID("$Id: get_cred.c 22530 2008-01-27 11:48:16Z lha $"); */ static krb5_error_code -make_pa_tgs_req(krb5_context context, +make_pa_tgs_req(krb5_context context, krb5_auth_context ac, KDC_REQ_BODY *body, PA_DATA *padata, - krb5_creds *creds, - krb5_key_usage usage) + krb5_creds *creds) { u_char *buf; size_t buf_size; @@ -65,8 +64,7 @@ make_pa_tgs_req(krb5_context context, ret = _krb5_mk_req_internal(context, &ac, 0, &in_data, creds, &padata->padata_value, KRB5_KU_TGS_REQ_AUTH_CKSUM, - usage - /* KRB5_KU_TGS_REQ_AUTH */); + KRB5_KU_TGS_REQ_AUTH); out: free (buf); if(ret) @@ -101,7 +99,7 @@ set_auth_data (krb5_context context, ALLOC(req_body->enc_authorization_data, 1); if (req_body->enc_authorization_data == NULL) { free (buf); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = krb5_crypto_init(context, key, 0, &crypto); @@ -111,9 +109,9 @@ set_auth_data (krb5_context context, req_body->enc_authorization_data = NULL; return ret; } - krb5_encrypt_EncryptedData(context, + krb5_encrypt_EncryptedData(context, crypto, - KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, + KRB5_KU_TGS_REQ_AUTH_DAT_SUBKEY, /* KRB5_KU_TGS_REQ_AUTH_DAT_SESSION? */ buf, len, @@ -125,7 +123,7 @@ set_auth_data (krb5_context context, req_body->enc_authorization_data = NULL; } return 0; -} +} /* * Create a tgs-req in `t' with `addresses', `flags', `second_ticket' @@ -144,8 +142,7 @@ init_tgs_req (krb5_context context, unsigned nonce, const METHOD_DATA *padata, krb5_keyblock **subkey, - TGS_REQ *t, - krb5_key_usage usage) + TGS_REQ *t) { krb5_error_code ret = 0; @@ -156,14 +153,14 @@ init_tgs_req (krb5_context context, ALLOC_SEQ(&t->req_body.etype, 1); if(t->req_body.etype.val == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } t->req_body.etype.val[0] = in_creds->session.keytype; } else { - ret = krb5_init_etype(context, - &t->req_body.etype.len, - &t->req_body.etype.val, + ret = krb5_init_etype(context, + &t->req_body.etype.len, + &t->req_body.etype.val, NULL); } if (ret) @@ -176,7 +173,7 @@ init_tgs_req (krb5_context context, ALLOC(t->req_body.sname, 1); if (t->req_body.sname == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } @@ -192,39 +189,39 @@ init_tgs_req (krb5_context context, ALLOC(t->req_body.till, 1); if(t->req_body.till == NULL){ ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } *t->req_body.till = in_creds->times.endtime; - + t->req_body.nonce = nonce; if(second_ticket){ ALLOC(t->req_body.additional_tickets, 1); if (t->req_body.additional_tickets == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } ALLOC_SEQ(t->req_body.additional_tickets, 1); if (t->req_body.additional_tickets->val == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } - ret = copy_Ticket(second_ticket, t->req_body.additional_tickets->val); + ret = copy_Ticket(second_ticket, t->req_body.additional_tickets->val); if (ret) goto fail; } ALLOC(t->padata, 1); if (t->padata == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } ALLOC_SEQ(t->padata, 1 + padata->len); if (t->padata->val == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } { @@ -232,7 +229,7 @@ init_tgs_req (krb5_context context, for (i = 0; i < padata->len; i++) { ret = copy_PA_DATA(&padata->val[i], &t->padata->val[i + 1]); if (ret) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } } @@ -278,10 +275,9 @@ init_tgs_req (krb5_context context, ret = make_pa_tgs_req(context, ac, - &t->req_body, + &t->req_body, &t->padata->val[0], - krbtgt, - usage); + krbtgt); if(ret) { if (key) krb5_free_keyblock (context, key); @@ -315,7 +311,7 @@ _krb5_get_krbtgt(krb5_context context, if (ret) return ret; - ret = krb5_make_principal(context, + ret = krb5_make_principal(context, &tmp_cred.server, realm, KRB5_TGS_NAME, @@ -349,7 +345,7 @@ decrypt_tkt_with_subkey (krb5_context context, krb5_data data; size_t size; krb5_crypto crypto; - + ret = krb5_crypto_init(context, key, 0, &crypto); if (ret) return ret; @@ -373,33 +369,32 @@ decrypt_tkt_with_subkey (krb5_context context, } if (ret) return ret; - + ret = krb5_decode_EncASRepPart(context, data.data, data.length, - &dec_rep->enc_part, + &dec_rep->enc_part, &size); if (ret) ret = krb5_decode_EncTGSRepPart(context, data.data, data.length, - &dec_rep->enc_part, + &dec_rep->enc_part, &size); krb5_data_free (&data); return ret; } static krb5_error_code -get_cred_kdc_usage(krb5_context context, - krb5_ccache id, - krb5_kdc_flags flags, - krb5_addresses *addresses, - krb5_creds *in_creds, - krb5_creds *krbtgt, - krb5_principal impersonate_principal, - Ticket *second_ticket, - krb5_creds *out_creds, - krb5_key_usage usage) +get_cred_kdc(krb5_context context, + krb5_ccache id, + krb5_kdc_flags flags, + krb5_addresses *addresses, + krb5_creds *in_creds, + krb5_creds *krbtgt, + krb5_principal impersonate_principal, + Ticket *second_ticket, + krb5_creds *out_creds) { TGS_REQ req; krb5_data enc; @@ -412,7 +407,7 @@ get_cred_kdc_usage(krb5_context context, size_t len; Ticket second_ticket_data; METHOD_DATA padata; - + krb5_data_zero(&resp); krb5_data_zero(&enc); padata.val = NULL; @@ -420,10 +415,10 @@ get_cred_kdc_usage(krb5_context context, krb5_generate_random_block(&nonce, sizeof(nonce)); nonce &= 0xffffffff; - + if(flags.b.enc_tkt_in_skey && second_ticket == NULL){ - ret = decode_Ticket(in_creds->second_ticket.data, - in_creds->second_ticket.length, + ret = decode_Ticket(in_creds->second_ticket.data, + in_creds->second_ticket.length, &second_ticket_data, &len); if(ret) return ret; @@ -460,7 +455,7 @@ get_cred_kdc_usage(krb5_context context, KRB5_KU_OTHER_CKSUM, 0, data.data, - data.length, + data.length, &self.cksum); krb5_crypto_destroy(context, crypto); krb5_data_free(&data); @@ -491,14 +486,13 @@ get_cred_kdc_usage(krb5_context context, krbtgt, nonce, &padata, - &subkey, - &req, - usage); + &subkey, + &req); if (ret) goto out; ASN1_MALLOC_ENCODE(TGS_REQ, enc.data, enc.length, &req, &len, ret); - if (ret) + if (ret) goto out; if(enc.length != len) krb5_abortx(context, "internal error in ASN.1 encoder"); @@ -526,20 +520,26 @@ get_cred_kdc_usage(krb5_context context, goto out; memset(&rep, 0, sizeof(rep)); - if(decode_TGS_REP(resp.data, resp.length, &rep.kdc_rep, &len) == 0){ - ret = krb5_copy_principal(context, - in_creds->client, + if(decode_TGS_REP(resp.data, resp.length, &rep.kdc_rep, &len) == 0) { + unsigned eflags = 0; + + ret = krb5_copy_principal(context, + in_creds->client, &out_creds->client); if(ret) - goto out; - ret = krb5_copy_principal(context, - in_creds->server, + goto out2; + ret = krb5_copy_principal(context, + in_creds->server, &out_creds->server); if(ret) - goto out; + goto out2; /* this should go someplace else */ out_creds->times.endtime = in_creds->times.endtime; + /* XXX should do better testing */ + if (flags.b.constrained_delegation || impersonate_principal) + eflags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH; + ret = _krb5_extract_ticket(context, &rep, out_creds, @@ -548,10 +548,10 @@ get_cred_kdc_usage(krb5_context context, KRB5_KU_TGS_REP_ENC_PART_SESSION, &krbtgt->addresses, nonce, - EXTRACT_TICKET_ALLOW_CNAME_MISMATCH| - EXTRACT_TICKET_ALLOW_SERVER_MISMATCH, + eflags, decrypt_tkt_with_subkey, subkey); + out2: krb5_free_kdc_rep(context, &rep); } else if(krb5_rd_error(context, &resp, &error) == 0) { ret = krb5_error_from_rd_error(context, &error, in_creds); @@ -575,52 +575,50 @@ out: free(subkey); } return ret; - + } +/* + * same as above, just get local addresses first if the krbtgt have + * them and the realm is not addressless + */ + static krb5_error_code -get_cred_kdc(krb5_context context, - krb5_ccache id, - krb5_kdc_flags flags, - krb5_addresses *addresses, - krb5_creds *in_creds, - krb5_creds *krbtgt, - krb5_principal impersonate_principal, - Ticket *second_ticket, - krb5_creds *out_creds) +get_cred_kdc_address(krb5_context context, + krb5_ccache id, + krb5_kdc_flags flags, + krb5_addresses *addrs, + krb5_creds *in_creds, + krb5_creds *krbtgt, + krb5_principal impersonate_principal, + Ticket *second_ticket, + krb5_creds *out_creds) { krb5_error_code ret; + krb5_addresses addresses = { 0, NULL }; - ret = get_cred_kdc_usage(context, id, flags, addresses, in_creds, - krbtgt, impersonate_principal, second_ticket, - out_creds, KRB5_KU_TGS_REQ_AUTH); - if (ret == KRB5KRB_AP_ERR_BAD_INTEGRITY) { - krb5_clear_error_string (context); - ret = get_cred_kdc_usage(context, id, flags, addresses, in_creds, - krbtgt, impersonate_principal, second_ticket, - out_creds, KRB5_KU_AP_REQ_AUTH); - } - return ret; -} + /* + * Inherit the address-ness of the krbtgt if the address is not + * specified. + */ -/* same as above, just get local addresses first */ + if (addrs == NULL && krbtgt->addresses.len != 0) { + krb5_boolean noaddr; -static krb5_error_code -get_cred_kdc_la(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, - krb5_creds *in_creds, krb5_creds *krbtgt, - krb5_principal impersonate_principal, Ticket *second_ticket, - krb5_creds *out_creds) -{ - krb5_error_code ret; - krb5_addresses addresses, *addrs = &addresses; - - krb5_get_all_client_addrs(context, &addresses); - /* XXX this sucks. */ - if(addresses.len == 0) - addrs = NULL; - ret = get_cred_kdc(context, id, flags, addrs, - in_creds, krbtgt, impersonate_principal, second_ticket, - out_creds); + krb5_appdefault_boolean(context, NULL, krbtgt->server->realm, + "no-addresses", FALSE, &noaddr); + + if (!noaddr) { + krb5_get_all_client_addrs(context, &addresses); + /* XXX this sucks. */ + addrs = &addresses; + if(addresses.len == 0) + addrs = NULL; + } + } + ret = get_cred_kdc(context, id, flags, addrs, in_creds, + krbtgt, impersonate_principal, + second_ticket, out_creds); krb5_free_addresses(context, &addresses); return ret; } @@ -640,7 +638,7 @@ krb5_get_kdc_cred(krb5_context context, *out_creds = calloc(1, sizeof(**out_creds)); if(*out_creds == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = _krb5_get_krbtgt (context, @@ -651,7 +649,7 @@ krb5_get_kdc_cred(krb5_context context, free(*out_creds); return ret; } - ret = get_cred_kdc(context, id, flags, addresses, + ret = get_cred_kdc(context, id, flags, addresses, in_creds, krbtgt, NULL, NULL, *out_creds); krb5_free_creds (context, krbtgt); if(ret) @@ -659,8 +657,8 @@ krb5_get_kdc_cred(krb5_context context, return ret; } -static void -not_found(krb5_context context, krb5_const_principal p) +static int +not_found(krb5_context context, krb5_const_principal p, krb5_error_code code) { krb5_error_code ret; char *str; @@ -668,10 +666,11 @@ not_found(krb5_context context, krb5_const_principal p) ret = krb5_unparse_name(context, p, &str); if(ret) { krb5_clear_error_string(context); - return; + return code; } - krb5_set_error_string(context, "Matching credential (%s) not found", str); + krb5_set_error_message(context, code, "Matching credential (%s) not found", str); free(str); + return code; } static krb5_error_code @@ -686,24 +685,23 @@ find_cred(krb5_context context, krb5_cc_clear_mcred(&mcreds); mcreds.server = server; - ret = krb5_cc_retrieve_cred(context, id, KRB5_TC_DONT_MATCH_REALM, + ret = krb5_cc_retrieve_cred(context, id, KRB5_TC_DONT_MATCH_REALM, &mcreds, out_creds); if(ret == 0) return 0; while(tgts && *tgts){ - if(krb5_compare_creds(context, KRB5_TC_DONT_MATCH_REALM, + if(krb5_compare_creds(context, KRB5_TC_DONT_MATCH_REALM, &mcreds, *tgts)){ ret = krb5_copy_creds_contents(context, *tgts, out_creds); return ret; } tgts++; } - not_found(context, server); - return KRB5_CC_NOTFOUND; + return not_found(context, server, KRB5_CC_NOTFOUND); } static krb5_error_code -add_cred(krb5_context context, krb5_creds ***tgts, krb5_creds *tkt) +add_cred(krb5_context context, krb5_creds const *tkt, krb5_creds ***tgts) { int i; krb5_error_code ret; @@ -712,7 +710,7 @@ add_cred(krb5_context context, krb5_creds ***tgts, krb5_creds *tkt) for(i = 0; tmp && tmp[i]; i++); /* XXX */ tmp = realloc(tmp, (i+2)*sizeof(*tmp)); if(tmp == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } *tgts = tmp; @@ -737,14 +735,14 @@ get_cred(server) */ static krb5_error_code -get_cred_from_kdc_flags(krb5_context context, - krb5_kdc_flags flags, - krb5_ccache ccache, - krb5_creds *in_creds, - krb5_principal impersonate_principal, - Ticket *second_ticket, - krb5_creds **out_creds, - krb5_creds ***ret_tgts) +get_cred_kdc_capath(krb5_context context, + krb5_kdc_flags flags, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_principal impersonate_principal, + Ticket *second_ticket, + krb5_creds **out_creds, + krb5_creds ***ret_tgts) { krb5_error_code ret; krb5_creds *tgt, tmp_creds; @@ -759,7 +757,7 @@ get_cred_from_kdc_flags(krb5_context context, if(ret) return ret; - try_realm = krb5_config_get_string(context, NULL, "capaths", + try_realm = krb5_config_get_string(context, NULL, "capaths", client_realm, server_realm, NULL); if (try_realm == NULL) try_realm = client_realm; @@ -768,7 +766,7 @@ get_cred_from_kdc_flags(krb5_context context, &tmp_creds.server, try_realm, KRB5_TGS_NAME, - server_realm, + server_realm, NULL); if(ret){ krb5_free_principal(context, tmp_creds.client); @@ -776,32 +774,20 @@ get_cred_from_kdc_flags(krb5_context context, } { krb5_creds tgts; - /* XXX try krb5_cc_retrieve_cred first? */ - ret = find_cred(context, ccache, tmp_creds.server, + + ret = find_cred(context, ccache, tmp_creds.server, *ret_tgts, &tgts); if(ret == 0){ *out_creds = calloc(1, sizeof(**out_creds)); if(*out_creds == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); } else { - krb5_boolean noaddr; - - krb5_appdefault_boolean(context, NULL, tgts.server->realm, - "no-addresses", FALSE, &noaddr); - - if (noaddr) - ret = get_cred_kdc(context, ccache, flags, NULL, - in_creds, &tgts, - impersonate_principal, - second_ticket, - *out_creds); - else - ret = get_cred_kdc_la(context, ccache, flags, - in_creds, &tgts, - impersonate_principal, - second_ticket, - *out_creds); + ret = get_cred_kdc_address(context, ccache, flags, NULL, + in_creds, &tgts, + impersonate_principal, + second_ticket, + *out_creds); if (ret) { free (*out_creds); *out_creds = NULL; @@ -813,22 +799,21 @@ get_cred_from_kdc_flags(krb5_context context, return ret; } } - if(krb5_realm_compare(context, in_creds->client, in_creds->server)) { - not_found(context, in_creds->server); - return KRB5_CC_NOTFOUND; - } + if(krb5_realm_compare(context, in_creds->client, in_creds->server)) + return not_found(context, in_creds->server, KRB5_CC_NOTFOUND); + /* XXX this can loop forever */ while(1){ heim_general_string tgt_inst; - ret = get_cred_from_kdc_flags(context, flags, ccache, &tmp_creds, - NULL, NULL, &tgt, ret_tgts); + ret = get_cred_kdc_capath(context, flags, ccache, &tmp_creds, + NULL, NULL, &tgt, ret_tgts); if(ret) { krb5_free_principal(context, tmp_creds.server); krb5_free_principal(context, tmp_creds.client); return ret; } - ret = add_cred(context, ret_tgts, tgt); + ret = add_cred(context, tgt, ret_tgts); if(ret) { krb5_free_principal(context, tmp_creds.server); krb5_free_principal(context, tmp_creds.client); @@ -838,7 +823,7 @@ get_cred_from_kdc_flags(krb5_context context, if(strcmp(tgt_inst, server_realm) == 0) break; krb5_free_principal(context, tmp_creds.server); - ret = krb5_make_principal(context, &tmp_creds.server, + ret = krb5_make_principal(context, &tmp_creds.server, tgt_inst, KRB5_TGS_NAME, server_realm, NULL); if(ret) { krb5_free_principal(context, tmp_creds.server); @@ -857,22 +842,12 @@ get_cred_from_kdc_flags(krb5_context context, krb5_free_principal(context, tmp_creds.client); *out_creds = calloc(1, sizeof(**out_creds)); if(*out_creds == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); } else { - krb5_boolean noaddr; - - krb5_appdefault_boolean(context, NULL, tgt->server->realm, - "no-addresses", KRB5_ADDRESSLESS_DEFAULT, - &noaddr); - if (noaddr) - ret = get_cred_kdc (context, ccache, flags, NULL, - in_creds, tgt, NULL, NULL, - *out_creds); - else - ret = get_cred_kdc_la(context, ccache, flags, - in_creds, tgt, NULL, NULL, - *out_creds); + ret = get_cred_kdc_address (context, ccache, flags, NULL, + in_creds, tgt, impersonate_principal, + second_ticket, *out_creds); if (ret) { free (*out_creds); *out_creds = NULL; @@ -882,6 +857,185 @@ get_cred_from_kdc_flags(krb5_context context, return ret; } +static krb5_error_code +get_cred_kdc_referral(krb5_context context, + krb5_kdc_flags flags, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_principal impersonate_principal, + Ticket *second_ticket, + krb5_creds **out_creds, + krb5_creds ***ret_tgts) +{ + krb5_const_realm client_realm; + krb5_error_code ret; + krb5_creds tgt, referral, ticket; + int loop = 0; + + memset(&tgt, 0, sizeof(tgt)); + memset(&ticket, 0, sizeof(ticket)); + + flags.b.canonicalize = 1; + + *out_creds = NULL; + + client_realm = krb5_principal_get_realm(context, in_creds->client); + + /* find tgt for the clients base realm */ + { + krb5_principal tgtname; + + ret = krb5_make_principal(context, &tgtname, + client_realm, + KRB5_TGS_NAME, + client_realm, + NULL); + if(ret) + return ret; + + ret = find_cred(context, ccache, tgtname, *ret_tgts, &tgt); + krb5_free_principal(context, tgtname); + if (ret) + return ret; + } + + referral = *in_creds; + ret = krb5_copy_principal(context, in_creds->server, &referral.server); + if (ret) { + krb5_free_cred_contents(context, &tgt); + return ret; + } + ret = krb5_principal_set_realm(context, referral.server, client_realm); + if (ret) { + krb5_free_cred_contents(context, &tgt); + krb5_free_principal(context, referral.server); + return ret; + } + + while (loop++ < 17) { + krb5_creds **tickets; + krb5_creds mcreds; + char *referral_realm; + + /* Use cache if we are not doing impersonation or contrainte deleg */ + if (impersonate_principal == NULL || flags.b.constrained_delegation) { + krb5_cc_clear_mcred(&mcreds); + mcreds.server = referral.server; + ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcreds, &ticket); + } else + ret = EINVAL; + + if (ret) { + ret = get_cred_kdc_address (context, ccache, flags, NULL, + &referral, &tgt, impersonate_principal, + second_ticket, &ticket); + if (ret) + goto out; + } + + /* Did we get the right ticket ? */ + if (krb5_principal_compare_any_realm(context, + referral.server, + ticket.server)) + break; + + if (ticket.server->name.name_string.len != 2 && + strcmp(ticket.server->name.name_string.val[0], KRB5_TGS_NAME) != 0) + { + krb5_set_error_message(context, KRB5KRB_AP_ERR_NOT_US, + "Got back an non krbtgt ticket referrals"); + krb5_free_cred_contents(context, &ticket); + return KRB5KRB_AP_ERR_NOT_US; + } + + referral_realm = ticket.server->name.name_string.val[1]; + + /* check that there are no referrals loops */ + tickets = *ret_tgts; + + krb5_cc_clear_mcred(&mcreds); + mcreds.server = ticket.server; + + while(tickets && *tickets){ + if(krb5_compare_creds(context, + KRB5_TC_DONT_MATCH_REALM, + &mcreds, + *tickets)) + { + krb5_set_error_message(context, KRB5_GET_IN_TKT_LOOP, + "Referral from %s loops back to realm %s", + tgt.server->realm, + referral_realm); + krb5_free_cred_contents(context, &ticket); + return KRB5_GET_IN_TKT_LOOP; + } + tickets++; + } + + ret = add_cred(context, &ticket, ret_tgts); + if (ret) { + krb5_free_cred_contents(context, &ticket); + goto out; + } + + /* try realm in the referral */ + ret = krb5_principal_set_realm(context, + referral.server, + referral_realm); + krb5_free_cred_contents(context, &tgt); + tgt = ticket; + memset(&ticket, 0, sizeof(ticket)); + if (ret) + goto out; + } + + ret = krb5_copy_creds(context, &ticket, out_creds); + +out: + krb5_free_principal(context, referral.server); + krb5_free_cred_contents(context, &tgt); + return ret; +} + + +/* + * Glue function between referrals version and old client chasing + * codebase. + */ + +static krb5_error_code +get_cred_kdc_any(krb5_context context, + krb5_kdc_flags flags, + krb5_ccache ccache, + krb5_creds *in_creds, + krb5_principal impersonate_principal, + Ticket *second_ticket, + krb5_creds **out_creds, + krb5_creds ***ret_tgts) +{ + krb5_error_code ret; + + ret = get_cred_kdc_referral(context, + flags, + ccache, + in_creds, + impersonate_principal, + second_ticket, + out_creds, + ret_tgts); + if (ret == 0 || flags.b.canonicalize) + return ret; + return get_cred_kdc_capath(context, + flags, + ccache, + in_creds, + impersonate_principal, + second_ticket, + out_creds, + ret_tgts); +} + + krb5_error_code KRB5_LIB_FUNCTION krb5_get_cred_from_kdc_opt(krb5_context context, krb5_ccache ccache, @@ -892,9 +1046,9 @@ krb5_get_cred_from_kdc_opt(krb5_context context, { krb5_kdc_flags f; f.i = flags; - return get_cred_from_kdc_flags(context, f, ccache, - in_creds, NULL, NULL, - out_creds, ret_tgts); + return get_cred_kdc_any(context, f, ccache, + in_creds, NULL, NULL, + out_creds, ret_tgts); } krb5_error_code KRB5_LIB_FUNCTION @@ -904,10 +1058,10 @@ krb5_get_cred_from_kdc(krb5_context context, krb5_creds **out_creds, krb5_creds ***ret_tgts) { - return krb5_get_cred_from_kdc_opt(context, ccache, + return krb5_get_cred_from_kdc_opt(context, ccache, in_creds, out_creds, ret_tgts, 0); } - + krb5_error_code KRB5_LIB_FUNCTION krb5_get_credentials_with_flags(krb5_context context, @@ -921,18 +1075,18 @@ krb5_get_credentials_with_flags(krb5_context context, krb5_creds **tgts; krb5_creds *res_creds; int i; - + *out_creds = NULL; res_creds = calloc(1, sizeof(*res_creds)); if (res_creds == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } if (in_creds->session.keytype) options |= KRB5_TC_MATCH_KEYTYPE; - /* + /* * If we got a credential, check if credential is expired before * returning it. */ @@ -941,7 +1095,7 @@ krb5_get_credentials_with_flags(krb5_context context, in_creds->session.keytype ? KRB5_TC_MATCH_KEYTYPE : 0, in_creds, res_creds); - /* + /* * If we got a credential, check if credential is expired before * returning it, but only if KRB5_GC_EXPIRED_OK is not set. */ @@ -953,7 +1107,7 @@ krb5_get_credentials_with_flags(krb5_context context, *out_creds = res_creds; return 0; } - + krb5_timeofday(context, &timeret); if(res_creds->times.endtime > timeret) { *out_creds = res_creds; @@ -967,18 +1121,17 @@ krb5_get_credentials_with_flags(krb5_context context, return ret; } free(res_creds); - if(options & KRB5_GC_CACHED) { - not_found(context, in_creds->server); - return KRB5_CC_NOTFOUND; - } + if(options & KRB5_GC_CACHED) + return not_found(context, in_creds->server, KRB5_CC_NOTFOUND); + if(options & KRB5_GC_USER_USER) flags.b.enc_tkt_in_skey = 1; if (flags.b.enc_tkt_in_skey) options |= KRB5_GC_NO_STORE; tgts = NULL; - ret = get_cred_from_kdc_flags(context, flags, ccache, - in_creds, NULL, NULL, out_creds, &tgts); + ret = get_cred_kdc_any(context, flags, ccache, + in_creds, NULL, NULL, out_creds, &tgts); for(i = 0; tgts && tgts[i]; i++) { krb5_cc_store_cred(context, ccache, tgts[i]); krb5_free_creds(context, tgts[i]); @@ -1015,7 +1168,7 @@ krb5_get_creds_opt_alloc(krb5_context context, krb5_get_creds_opt *opt) { *opt = calloc(1, sizeof(**opt)); if (*opt == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } return 0; @@ -1079,14 +1232,14 @@ krb5_get_creds_opt_set_ticket(krb5_context context, opt->ticket = malloc(sizeof(*ticket)); if (opt->ticket == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = copy_Ticket(ticket, opt->ticket); if (ret) { free(opt->ticket); opt->ticket = NULL; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); return ret; } } @@ -1109,7 +1262,7 @@ krb5_get_creds(krb5_context context, krb5_creds **tgts; krb5_creds *res_creds; int i; - + memset(&in_creds, 0, sizeof(in_creds)); in_creds.server = rk_UNCONST(inprinc); @@ -1124,7 +1277,7 @@ krb5_get_creds(krb5_context context, res_creds = calloc(1, sizeof(*res_creds)); if (res_creds == NULL) { krb5_free_principal(context, in_creds.client); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -1133,7 +1286,7 @@ krb5_get_creds(krb5_context context, options |= KRB5_TC_MATCH_KEYTYPE; } - /* + /* * If we got a credential, check if credential is expired before * returning it. */ @@ -1141,7 +1294,7 @@ krb5_get_creds(krb5_context context, ccache, opt->enctype ? KRB5_TC_MATCH_KEYTYPE : 0, &in_creds, res_creds); - /* + /* * If we got a credential, check if credential is expired before * returning it, but only if KRB5_GC_EXPIRED_OK is not set. */ @@ -1154,7 +1307,7 @@ krb5_get_creds(krb5_context context, krb5_free_principal(context, in_creds.client); return 0; } - + krb5_timeofday(context, &timeret); if(res_creds->times.endtime > timeret) { *out_creds = res_creds; @@ -1171,9 +1324,8 @@ krb5_get_creds(krb5_context context, } free(res_creds); if(options & KRB5_GC_CACHED) { - not_found(context, in_creds.server); krb5_free_principal(context, in_creds.client); - return KRB5_CC_NOTFOUND; + return not_found(context, in_creds.server, KRB5_CC_NOTFOUND); } if(options & KRB5_GC_USER_USER) { flags.b.enc_tkt_in_skey = 1; @@ -1187,11 +1339,13 @@ krb5_get_creds(krb5_context context, flags.b.request_anonymous = 1; /* XXX ARGH confusion */ flags.b.constrained_delegation = 1; } + if (options & KRB5_GC_CANONICALIZE) + flags.b.canonicalize = 1; tgts = NULL; - ret = get_cred_from_kdc_flags(context, flags, ccache, - &in_creds, opt->self, opt->ticket, - out_creds, &tgts); + ret = get_cred_kdc_any(context, flags, ccache, + &in_creds, opt->self, opt->ticket, + out_creds, &tgts); krb5_free_principal(context, in_creds.client); for(i = 0; tgts && tgts[i]; i++) { krb5_cc_store_cred(context, ccache, tgts[i]); diff --git a/source4/heimdal/lib/krb5/get_default_principal.c b/source4/heimdal/lib/krb5/get_default_principal.c index 83fb2b0fa9..5a7a7829fc 100644 --- a/source4/heimdal/lib/krb5/get_default_principal.c +++ b/source4/heimdal/lib/krb5/get_default_principal.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_default_principal.c 14870 2005-04-20 20:53:29Z lha $"); +RCSID("$Id: get_default_principal.c 23280 2008-06-23 03:26:18Z lha $"); /* * Try to find out what's a reasonable default principal. @@ -85,8 +85,8 @@ _krb5_get_default_principal_local (krb5_context context, user = getlogin(); } if(user == NULL) { - krb5_set_error_string(context, - "unable to figure out current principal"); + krb5_set_error_message(context, ENOTTY, + "unable to figure out current principal"); return ENOTTY; /* XXX */ } ret = krb5_make_principal(context, princ, NULL, user, NULL); diff --git a/source4/heimdal/lib/krb5/get_default_realm.c b/source4/heimdal/lib/krb5/get_default_realm.c index 09c8577b26..1c996031e8 100644 --- a/source4/heimdal/lib/krb5/get_default_realm.c +++ b/source4/heimdal/lib/krb5/get_default_realm.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_default_realm.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id: get_default_realm.c 23280 2008-06-23 03:26:18Z lha $"); /* * Return a NULL-terminated list of default realms in `realms'. @@ -76,7 +76,7 @@ krb5_get_default_realm(krb5_context context, res = strdup (context->default_realms[0]); if (res == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } *realm = res; diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index cb8b7c8641..a8aac950ec 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_for_creds.c 22504 2008-01-21 15:49:58Z lha $"); +RCSID("$Id: get_for_creds.c 23316 2008-06-23 04:32:32Z lha $"); static krb5_error_code add_addrs(krb5_context context, @@ -51,8 +51,8 @@ add_addrs(krb5_context context, tmp = realloc(addr->val, (addr->len + n) * sizeof(*addr->val)); if (tmp == NULL && (addr->len + n) != 0) { - krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } addr->val = tmp; @@ -207,7 +207,6 @@ krb5_get_forwarded_creds (krb5_context context, krb5_kdc_flags kdc_flags; krb5_crypto crypto; struct addrinfo *ai; - int save_errno; krb5_creds *ticket; paddrs = NULL; @@ -238,10 +237,10 @@ krb5_get_forwarded_creds (krb5_context context, ret = getaddrinfo (hostname, NULL, NULL, &ai); if (ret) { - save_errno = errno; - krb5_set_error_string(context, "resolving %s: %s", + krb5_error_code ret2 = krb5_eai_to_heim_errno(ret, errno); + krb5_set_error_message(context, ret2, "resolving %s: %s", hostname, gai_strerror(ret)); - return krb5_eai_to_heim_errno(ret, save_errno); + return ret2; } ret = add_addrs (context, &addrs, ai); @@ -269,7 +268,7 @@ krb5_get_forwarded_creds (krb5_context context, ALLOC_SEQ(&cred.tickets, 1); if (cred.tickets.val == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out2; } ret = decode_Ticket(out_creds->ticket.data, @@ -282,7 +281,7 @@ krb5_get_forwarded_creds (krb5_context context, ALLOC_SEQ(&enc_krb_cred_part.ticket_info, 1); if (enc_krb_cred_part.ticket_info.val == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out4; } @@ -295,14 +294,14 @@ krb5_get_forwarded_creds (krb5_context context, ALLOC(enc_krb_cred_part.timestamp, 1); if (enc_krb_cred_part.timestamp == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out4; } *enc_krb_cred_part.timestamp = sec; ALLOC(enc_krb_cred_part.usec, 1); if (enc_krb_cred_part.usec == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out4; } *enc_krb_cred_part.usec = usec; @@ -346,7 +345,7 @@ krb5_get_forwarded_creds (krb5_context context, ALLOC(enc_krb_cred_part.r_address, 1); if (enc_krb_cred_part.r_address == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out4; } diff --git a/source4/heimdal/lib/krb5/get_host_realm.c b/source4/heimdal/lib/krb5/get_host_realm.c index d709e4b38d..f4c875b347 100644 --- a/source4/heimdal/lib/krb5/get_host_realm.c +++ b/source4/heimdal/lib/krb5/get_host_realm.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: get_host_realm.c 18541 2006-10-17 19:28:36Z lha $"); +RCSID("$Id: get_host_realm.c 23316 2008-06-23 04:32:32Z lha $"); /* To automagically find the correct realm of a host (without * [domain_realm] in krb5.conf) add a text record for your domain with @@ -55,7 +55,7 @@ copy_txt_to_realms (struct resource_record *head, krb5_realm **realms) { struct resource_record *rr; - int n, i; + unsigned int n, i; for(n = 0, rr = head; rr; rr = rr->next) if (rr->type == T_TXT) @@ -192,21 +192,22 @@ _krb5_get_host_realm_int (krb5_context context, p++; *realms = malloc(2 * sizeof(krb5_realm)); if (*realms == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } (*realms)[0] = strdup(p); if((*realms)[0] == NULL) { free(*realms); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } strupr((*realms)[0]); (*realms)[1] = NULL; return 0; } - krb5_set_error_string(context, "unable to find realm of host %s", host); + krb5_set_error_message(context, KRB5_ERR_HOST_REALM_UNKNOWN, + "unable to find realm of host %s", host); return KRB5_ERR_HOST_REALM_UNKNOWN; } @@ -248,8 +249,9 @@ krb5_get_host_realm(krb5_context context, */ ret = krb5_get_default_realms(context, realms); if (ret) { - krb5_set_error_string(context, "Unable to find realm of host %s", - host); + krb5_set_error_message(context, KRB5_ERR_HOST_REALM_UNKNOWN, + "Unable to find realm of host %s", + host); return KRB5_ERR_HOST_REALM_UNKNOWN; } } diff --git a/source4/heimdal/lib/krb5/get_in_tkt.c b/source4/heimdal/lib/krb5/get_in_tkt.c index a9ed3857d0..8bdc8c0eb2 100644 --- a/source4/heimdal/lib/krb5/get_in_tkt.c +++ b/source4/heimdal/lib/krb5/get_in_tkt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_in_tkt.c 20226 2007-02-16 03:31:50Z lha $"); +RCSID("$Id: get_in_tkt.c 23316 2008-06-23 04:32:32Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_init_etype (krb5_context context, @@ -41,7 +41,7 @@ krb5_init_etype (krb5_context context, krb5_enctype **val, const krb5_enctype *etypes) { - int i; + unsigned int i; krb5_error_code ret; krb5_enctype *tmp = NULL; @@ -60,7 +60,7 @@ krb5_init_etype (krb5_context context, *val = malloc(i * sizeof(**val)); if (i != 0 && *val == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto cleanup; } memmove (*val, @@ -72,6 +72,225 @@ cleanup: return ret; } +static krb5_error_code +check_server_referral(krb5_context context, + krb5_kdc_rep *rep, + unsigned flags, + krb5_const_principal requested, + krb5_const_principal returned, + const krb5_keyblock const * key) +{ + krb5_error_code ret; + PA_ServerReferralData ref; + krb5_crypto session; + EncryptedData ed; + size_t len; + krb5_data data; + PA_DATA *pa; + int i = 0, cmp; + + if (rep->kdc_rep.padata == NULL) + goto noreferral; + + pa = krb5_find_padata(rep->kdc_rep.padata->val, + rep->kdc_rep.padata->len, + KRB5_PADATA_SERVER_REFERRAL, &i); + if (pa == NULL) + goto noreferral; + + memset(&ed, 0, sizeof(ed)); + memset(&ref, 0, sizeof(ref)); + + ret = decode_EncryptedData(pa->padata_value.data, + pa->padata_value.length, + &ed, &len); + if (ret) + return ret; + if (len != pa->padata_value.length) { + free_EncryptedData(&ed); + krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, "Referral EncryptedData wrong"); + return KRB5KRB_AP_ERR_MODIFIED; + } + + ret = krb5_crypto_init(context, key, 0, &session); + if (ret) { + free_EncryptedData(&ed); + return ret; + } + + ret = krb5_decrypt_EncryptedData(context, session, + KRB5_KU_PA_SERVER_REFERRAL, + &ed, &data); + free_EncryptedData(&ed); + krb5_crypto_destroy(context, session); + if (ret) + return ret; + + ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len); + if (ret) { + krb5_data_free(&data); + return ret; + } + krb5_data_free(&data); + + if (strcmp(requested->realm, returned->realm) != 0) { + free_PA_ServerReferralData(&ref); + krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, + "server ref realm mismatch"); + return KRB5KRB_AP_ERR_MODIFIED; + } + + if (returned->name.name_string.len == 2 && + strcmp(returned->name.name_string.val[0], KRB5_TGS_NAME) == 0) + { + const char *realm = returned->name.name_string.val[1]; + + if (ref.referred_realm == NULL + || strcmp(*ref.referred_realm, realm) != 0) + { + free_PA_ServerReferralData(&ref); + krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, + "tgt returned with wrong ref"); + return KRB5KRB_AP_ERR_MODIFIED; + } + } else if (krb5_principal_compare(context, returned, requested) == 0) { + free_PA_ServerReferralData(&ref); + krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, + "req princ no same as returned"); + return KRB5KRB_AP_ERR_MODIFIED; + } + + if (ref.requested_principal_name) { + cmp = _krb5_principal_compare_PrincipalName(context, + requested, + ref.requested_principal_name); + if (!cmp) { + free_PA_ServerReferralData(&ref); + krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, + "compare requested failed"); + return KRB5KRB_AP_ERR_MODIFIED; + } + } else if (flags & EXTRACT_TICKET_AS_REQ) { + free_PA_ServerReferralData(&ref); + krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, + "Requested principal missing on AS-REQ"); + return KRB5KRB_AP_ERR_MODIFIED; + } + + free_PA_ServerReferralData(&ref); + + return ret; +noreferral: + if (krb5_principal_compare(context, requested, returned) == FALSE) { + krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, + "Not same server principal returned " + "as requested"); + return KRB5KRB_AP_ERR_MODIFIED; + } + return 0; +} + + +/* + * Verify referral data + */ + + +static krb5_error_code +check_client_referral(krb5_context context, + krb5_kdc_rep *rep, + krb5_const_principal requested, + krb5_const_principal mapped, + krb5_keyblock const * key) +{ + krb5_error_code ret; + PA_ClientCanonicalized canon; + krb5_crypto crypto; + krb5_data data; + PA_DATA *pa; + size_t len; + int i = 0; + + if (rep->kdc_rep.padata == NULL) + goto noreferral; + + pa = krb5_find_padata(rep->kdc_rep.padata->val, + rep->kdc_rep.padata->len, + KRB5_PADATA_CLIENT_CANONICALIZED, &i); + if (pa == NULL) + goto noreferral; + + ret = decode_PA_ClientCanonicalized(pa->padata_value.data, + pa->padata_value.length, + &canon, &len); + if (ret) { + krb5_set_error_message(context, ret, "Failed to decode " + "PA_ClientCanonicalized"); + return ret; + } + + ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length, + &canon.names, &len, ret); + if (ret) { + free_PA_ClientCanonicalized(&canon); + return ret; + } + if (data.length != len) + krb5_abortx(context, "internal asn.1 error"); + + ret = krb5_crypto_init(context, key, 0, &crypto); + if (ret) { + free(data.data); + free_PA_ClientCanonicalized(&canon); + return ret; + } + + ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES, + data.data, data.length, + &canon.canon_checksum); + krb5_crypto_destroy(context, crypto); + free(data.data); + if (ret) { + krb5_set_error_message(context, ret, "Failed to verify " + "client canonicalized data"); + free_PA_ClientCanonicalized(&canon); + return ret; + } + + if (!_krb5_principal_compare_PrincipalName(context, + requested, + &canon.names.requested_name)) + { + free_PA_ClientCanonicalized(&canon); + krb5_set_error_message(context, KRB5_PRINC_NOMATCH, + "Requested name doesn't match" + " in client referral"); + return KRB5_PRINC_NOMATCH; + } + if (!_krb5_principal_compare_PrincipalName(context, + mapped, + &canon.names.mapped_name)) + { + free_PA_ClientCanonicalized(&canon); + krb5_set_error_message(context, KRB5_PRINC_NOMATCH, + "Mapped name doesn't match" + " in client referral"); + return KRB5_PRINC_NOMATCH; + } + + return 0; + +noreferral: + if (krb5_principal_compare(context, requested, mapped) == FALSE) { + krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, + "Not same client principal returned " + "as requested"); + return KRB5KRB_AP_ERR_MODIFIED; + } + return 0; +} + + static krb5_error_code decrypt_tkt (krb5_context context, @@ -117,9 +336,9 @@ decrypt_tkt (krb5_context context, } int -_krb5_extract_ticket(krb5_context context, - krb5_kdc_rep *rep, - krb5_creds *creds, +_krb5_extract_ticket(krb5_context context, + krb5_kdc_rep *rep, + krb5_creds *creds, krb5_keyblock *key, krb5_const_pointer keyseed, krb5_key_usage key_usage, @@ -131,83 +350,86 @@ _krb5_extract_ticket(krb5_context context, { krb5_error_code ret; krb5_principal tmp_principal; - int tmp; size_t len; time_t tmp_time; krb5_timestamp sec_now; -/* - * HACK: - * this is really a ugly hack, to support using the Netbios Domain Name - * as realm against windows KDC's, they always return the full realm - * based on the DNS Name. - */ -flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; -flags |=EXTRACT_TICKET_ALLOW_CNAME_MISMATCH ; + /* decrypt */ + + if (decrypt_proc == NULL) + decrypt_proc = decrypt_tkt; + + ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep); + if (ret) + goto out; + + /* save session key */ + + creds->session.keyvalue.length = 0; + creds->session.keyvalue.data = NULL; + creds->session.keytype = rep->enc_part.key.keytype; + ret = krb5_data_copy (&creds->session.keyvalue, + rep->enc_part.key.keyvalue.data, + rep->enc_part.key.keyvalue.length); + if (ret) { + krb5_clear_error_string(context); + goto out; + } + + /* + * HACK: + * this is really a ugly hack, to support using the Netbios Domain Name + * as realm against windows KDC's, they always return the full realm + * based on the DNS Name. + */ + flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; + flags |=EXTRACT_TICKET_ALLOW_CNAME_MISMATCH ; + - ret = _krb5_principalname2krb5_principal (context, + /* compare client and save */ + ret = _krb5_principalname2krb5_principal (context, &tmp_principal, rep->kdc_rep.cname, rep->kdc_rep.crealm); if (ret) goto out; - /* compare client */ - - if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0){ - tmp = krb5_principal_compare (context, tmp_principal, creds->client); - if (!tmp) { + /* check client referral and save principal */ + /* anonymous here ? */ + if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) { + ret = check_client_referral(context, rep, + creds->client, + tmp_principal, + &creds->session); + if (ret) { krb5_free_principal (context, tmp_principal); - krb5_clear_error_string (context); - ret = KRB5KRB_AP_ERR_MODIFIED; goto out; } } - krb5_free_principal (context, creds->client); creds->client = tmp_principal; - /* extract ticket */ - ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, - &rep->kdc_rep.ticket, &len, ret); - if(ret) - goto out; - if (creds->ticket.length != len) - krb5_abortx(context, "internal error in ASN.1 encoder"); - creds->second_ticket.length = 0; - creds->second_ticket.data = NULL; - - /* compare server */ - + /* check server referral and save principal */ ret = _krb5_principalname2krb5_principal (context, &tmp_principal, rep->kdc_rep.ticket.sname, rep->kdc_rep.ticket.realm); if (ret) goto out; - if(flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH){ - krb5_free_principal(context, creds->server); - creds->server = tmp_principal; - tmp_principal = NULL; - } else { - tmp = krb5_principal_compare (context, tmp_principal, - creds->server); - krb5_free_principal (context, tmp_principal); - if (!tmp) { - ret = KRB5KRB_AP_ERR_MODIFIED; - krb5_clear_error_string (context); + if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){ + ret = check_server_referral(context, + rep, + flags, + creds->server, + tmp_principal, + &creds->session); + if (ret) { + krb5_free_principal (context, tmp_principal); goto out; } } - - /* decrypt */ - - if (decrypt_proc == NULL) - decrypt_proc = decrypt_tkt; - - ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep); - if (ret) - goto out; + krb5_free_principal(context, creds->server); + creds->server = tmp_principal; /* verify names */ if(flags & EXTRACT_TICKET_MATCH_REALM){ @@ -227,7 +449,7 @@ flags |=EXTRACT_TICKET_ALLOW_CNAME_MISMATCH ; if (nonce != rep->enc_part.nonce) { ret = KRB5KRB_AP_ERR_MODIFIED; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } @@ -254,7 +476,7 @@ flags |=EXTRACT_TICKET_ALLOW_CNAME_MISMATCH ; if (creds->times.starttime == 0 && abs(tmp_time - sec_now) > context->max_skew) { ret = KRB5KRB_AP_ERR_SKEW; - krb5_set_error_string (context, + krb5_set_error_message (context, ret, "time skew (%d) larger than max (%d)", abs(tmp_time - sec_now), (int)context->max_skew); @@ -307,12 +529,17 @@ flags |=EXTRACT_TICKET_ALLOW_CNAME_MISMATCH ; creds->authdata.len = 0; creds->authdata.val = NULL; - creds->session.keyvalue.length = 0; - creds->session.keyvalue.data = NULL; - creds->session.keytype = rep->enc_part.key.keytype; - ret = krb5_data_copy (&creds->session.keyvalue, - rep->enc_part.key.keyvalue.data, - rep->enc_part.key.keyvalue.length); + + /* extract ticket */ + ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length, + &rep->kdc_rep.ticket, &len, ret); + if(ret) + goto out; + if (creds->ticket.length != len) + krb5_abortx(context, "internal error in ASN.1 encoder"); + creds->second_ticket.length = 0; + creds->second_ticket.data = NULL; + out: memset (rep->enc_part.key.keyvalue.data, 0, @@ -402,7 +629,7 @@ add_padata(krb5_context context, } pa2 = realloc (md->val, (md->len + netypes) * sizeof(*md->val)); if (pa2 == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } md->val = pa2; @@ -449,13 +676,13 @@ init_as_req (krb5_context context, a->req_body.cname = malloc(sizeof(*a->req_body.cname)); if (a->req_body.cname == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } a->req_body.sname = malloc(sizeof(*a->req_body.sname)); if (a->req_body.sname == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } ret = _krb5_principal2principalname (a->req_body.cname, creds->client); @@ -472,7 +699,7 @@ init_as_req (krb5_context context, a->req_body.from = malloc(sizeof(*a->req_body.from)); if (a->req_body.from == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } *a->req_body.from = creds->times.starttime; @@ -485,7 +712,7 @@ init_as_req (krb5_context context, a->req_body.rtime = malloc(sizeof(*a->req_body.rtime)); if (a->req_body.rtime == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } *a->req_body.rtime = creds->times.renew_till; @@ -508,7 +735,7 @@ init_as_req (krb5_context context, a->req_body.addresses = malloc(sizeof(*a->req_body.addresses)); if (a->req_body.addresses == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } @@ -533,7 +760,7 @@ init_as_req (krb5_context context, ALLOC(a->padata, 1); if(a->padata == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } a->padata->val = NULL; @@ -572,7 +799,7 @@ init_as_req (krb5_context context, ALLOC(a->padata, 1); if (a->padata == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } a->padata->len = 0; @@ -590,9 +817,9 @@ init_as_req (krb5_context context, key_proc, keyseed, a->req_body.etype.val, a->req_body.etype.len, &salt); } else { - krb5_set_error_string (context, "pre-auth type %d not supported", - *ptypes); ret = KRB5_PREAUTH_BAD_TYPE; + krb5_set_error_message (context, ret, "pre-auth type %d not supported", + *ptypes); goto fail; } return 0; diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index a59c903bd9..74c9ff78e5 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c 21711 2007-07-27 14:22:02Z lha $"); +RCSID("$Id: init_creds.c 23316 2008-06-23 04:32:32Z lha $"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) @@ -52,13 +52,13 @@ krb5_get_init_creds_opt_alloc(krb5_context context, *opt = NULL; o = calloc(1, sizeof(*o)); if (o == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } krb5_get_init_creds_opt_init(o); o->opt_private = calloc(1, sizeof(*o->opt_private)); if (o->opt_private == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); free(o); return ENOMEM; } @@ -77,7 +77,7 @@ _krb5_get_init_creds_opt_copy(krb5_context context, *out = NULL; opt = calloc(1, sizeof(*opt)); if (opt == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } if (in) @@ -85,7 +85,7 @@ _krb5_get_init_creds_opt_copy(krb5_context context, if(opt->opt_private == NULL) { opt->opt_private = calloc(1, sizeof(*opt->opt_private)); if (opt->opt_private == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); free(opt); return ENOMEM; } @@ -327,7 +327,7 @@ require_ext_opt(krb5_context context, const char *type) { if (opt->opt_private == NULL) { - krb5_set_error_string(context, "%s on non extendable opt", type); + krb5_set_error_message(context, EINVAL, "%s on non extendable opt", type); return EINVAL; } return 0; @@ -381,7 +381,7 @@ krb5_get_init_creds_opt_get_error(krb5_context context, *error = malloc(sizeof(**error)); if (*error == NULL) { - krb5_set_error_string(context, "malloc - out memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 441adff8fd..e3098b0a92 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c 21931 2007-08-27 14:11:55Z lha $"); +RCSID("$Id: init_creds_pw.c 23316 2008-06-23 04:32:32Z lha $"); typedef struct krb5_get_init_creds_ctx { KDCOptions flags; @@ -165,14 +165,10 @@ init_cred (krb5_context context, } if (in_tkt_service) { - krb5_realm server_realm; - ret = krb5_parse_name (context, in_tkt_service, &cred->server); if (ret) goto out; - server_realm = strdup (client_realm); - free (*krb5_princ_realm(context, cred->server)); - krb5_princ_set_realm (context, cred->server, &server_realm); + krb5_principal_set_realm (context, cred->server, client_realm); } else { ret = krb5_make_principal(context, &cred->server, client_realm, KRB5_TGS_NAME, client_realm, @@ -340,7 +336,7 @@ get_init_creds_common(krb5_context context, etypes = malloc((options->etype_list_length + 1) * sizeof(krb5_enctype)); if (etypes == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy (etypes, options->etype_list, @@ -352,7 +348,7 @@ get_init_creds_common(krb5_context context, pre_auth_types = malloc((options->preauth_list_length + 1) * sizeof(krb5_preauthtype)); if (pre_auth_types == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy (pre_auth_types, options->preauth_list, @@ -445,12 +441,13 @@ change_password (krb5_context context, memset (buf2, 0, sizeof(buf2)); } - ret = krb5_change_password (context, - &cpw_cred, - buf1, - &result_code, - &result_code_string, - &result_string); + ret = krb5_set_password (context, + &cpw_cred, + buf1, + client, + &result_code, + &result_code_string, + &result_string); if (ret) goto out; asprintf (&p, "%s: %.*s\n", @@ -464,8 +461,8 @@ change_password (krb5_context context, strlcpy (newpw, buf1, newpw_sz); ret = 0; } else { - krb5_set_error_string (context, "failed changing password"); ret = ENOTTY; + krb5_set_error_message(context, ret, "failed changing password"); } out: @@ -507,8 +504,8 @@ krb5_get_init_creds_keytab(krb5_context context, a = malloc (sizeof(*a)); if (a == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } a->principal = ctx.cred.client; @@ -560,13 +557,13 @@ init_creds_init_as_req (krb5_context context, a->req_body.cname = malloc(sizeof(*a->req_body.cname)); if (a->req_body.cname == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } a->req_body.sname = malloc(sizeof(*a->req_body.sname)); if (a->req_body.sname == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } @@ -585,7 +582,7 @@ init_creds_init_as_req (krb5_context context, a->req_body.from = malloc(sizeof(*a->req_body.from)); if (a->req_body.from == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } *a->req_body.from = creds->times.starttime; @@ -598,7 +595,7 @@ init_creds_init_as_req (krb5_context context, a->req_body.rtime = malloc(sizeof(*a->req_body.rtime)); if (a->req_body.rtime == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } *a->req_body.rtime = creds->times.renew_till; @@ -621,7 +618,7 @@ init_creds_init_as_req (krb5_context context, a->req_body.addresses = malloc(sizeof(*a->req_body.addresses)); if (a->req_body.addresses == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } @@ -1036,7 +1033,7 @@ pa_data_to_md_pkinit(krb5_context context, ctx->pk_nonce, md); #else - krb5_set_error_string(context, "no support for PKINIT compiled in"); + krb5_set_error_message(context, EINVAL, "no support for PKINIT compiled in"); return EINVAL; #endif } @@ -1093,7 +1090,7 @@ process_pa_data_to_md(krb5_context context, ALLOC(*out_md, 1); if (*out_md == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } (*out_md)->len = 0; @@ -1191,15 +1188,15 @@ process_pa_data_to_key(krb5_context context, pa, key); #else - krb5_set_error_string(context, "no support for PKINIT compiled in"); ret = EINVAL; + krb5_set_error_message(context, ret, "no support for PKINIT compiled in"); #endif } else if (ctx->password) ret = pa_data_to_key_plain(context, creds->client, ctx, paid.salt, paid.s2kparams, etype, key); else { - krb5_set_error_string(context, "No usable pa data type"); ret = EINVAL; + krb5_set_error_message(context, ret, "No usable pa data type"); } free_paid(context, &paid); @@ -1325,8 +1322,8 @@ init_cred_loop(krb5_context context, &md, NULL); if (ret) - krb5_set_error_string(context, - "failed to decode METHOD DATA"); + krb5_set_error_message(context, ret, + "failed to decode METHOD DATA"); } else { /* XXX guess what the server want here add add md */ } @@ -1348,15 +1345,16 @@ init_cred_loop(krb5_context context, { krb5_keyblock *key = NULL; - unsigned flags = 0; + unsigned flags = EXTRACT_TICKET_AS_REQ; if (ctx->flags.request_anonymous) flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; if (ctx->flags.canonicalize) { - flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH; flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; flags |= EXTRACT_TICKET_MATCH_REALM; } + if (ctx->ic_flags & KRB5_INIT_CREDS_NO_C_CANON_CHECK) + flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH; ret = process_pa_data_to_key(context, ctx, creds, &ctx->as_req, &rep, hi, &key); @@ -1376,60 +1374,6 @@ init_cred_loop(krb5_context context, NULL); krb5_free_keyblock(context, key); } - /* - * Verify referral data - */ - if ((ctx->ic_flags & KRB5_INIT_CREDS_CANONICALIZE) && - (ctx->ic_flags & KRB5_INIT_CREDS_NO_C_CANON_CHECK) == 0) - { - PA_ClientCanonicalized canon; - krb5_crypto crypto; - krb5_data data; - PA_DATA *pa; - size_t len; - - pa = find_pa_data(rep.kdc_rep.padata, KRB5_PADATA_CLIENT_CANONICALIZED); - if (pa == NULL) { - ret = EINVAL; - krb5_set_error_string(context, "Client canonicalizion not signed"); - goto out; - } - - ret = decode_PA_ClientCanonicalized(pa->padata_value.data, - pa->padata_value.length, - &canon, &len); - if (ret) { - krb5_set_error_string(context, "Failed to decode " - "PA_ClientCanonicalized"); - goto out; - } - - ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length, - &canon.names, &len, ret); - if (ret) - goto out; - if (data.length != len) - krb5_abortx(context, "internal asn.1 error"); - - ret = krb5_crypto_init(context, &creds->session, 0, &crypto); - if (ret) { - free(data.data); - free_PA_ClientCanonicalized(&canon); - goto out; - } - - ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES, - data.data, data.length, - &canon.canon_checksum); - krb5_crypto_destroy(context, crypto); - free(data.data); - free_PA_ClientCanonicalized(&canon); - if (ret) { - krb5_set_error_string(context, "Failed to verify " - "client canonicalized data"); - goto out; - } - } out: if (stctx) krb5_sendto_ctx_free(context, stctx); diff --git a/source4/heimdal/lib/krb5/kcm.c b/source4/heimdal/lib/krb5/kcm.c index 8afaa6ea80..0c91fbb3a0 100644 --- a/source4/heimdal/lib/krb5/kcm.c +++ b/source4/heimdal/lib/krb5/kcm.c @@ -43,7 +43,7 @@ #include "kcm.h" -RCSID("$Id: kcm.c 22108 2007-12-03 17:23:53Z lha $"); +RCSID("$Id: kcm.c 23446 2008-07-27 12:08:37Z lha $"); typedef struct krb5_kcmcache { char *name; @@ -56,7 +56,8 @@ typedef struct krb5_kcmcache { #define KCMCURSOR(C) (*(uint32_t *)(C)) static krb5_error_code -try_door(krb5_context context, const krb5_kcmcache *k, +try_door(krb5_context context, + krb5_kcmcache *k, krb5_data *request_data, krb5_data *response_data) { @@ -70,6 +71,7 @@ try_door(krb5_context context, const krb5_kcmcache *k, fd = open(k->door_path, O_RDWR); if (fd < 0) return KRB5_CC_IO; + rk_cloexec(fd); arg.data_ptr = request_data->data; arg.data_size = request_data->length; @@ -95,7 +97,8 @@ try_door(krb5_context context, const krb5_kcmcache *k, } static krb5_error_code -try_unix_socket(krb5_context context, const krb5_kcmcache *k, +try_unix_socket(krb5_context context, + krb5_kcmcache *k, krb5_data *request_data, krb5_data *response_data) { @@ -105,7 +108,8 @@ try_unix_socket(krb5_context context, const krb5_kcmcache *k, fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd < 0) return KRB5_CC_IO; - + rk_cloexec(fd); + if (connect(fd, rk_UNCONST(&k->path), sizeof(k->path)) != 0) { close(fd); return KRB5_CC_IO; @@ -136,7 +140,7 @@ kcm_send_request(krb5_context context, return KRB5_CC_NOMEM; } - ret = KRB5_CC_IO; + ret = KRB5_CC_NOSUPP; for (i = 0; i < context->max_retries; i++) { ret = try_door(context, k, &request_data, response_data); @@ -151,7 +155,7 @@ kcm_send_request(krb5_context context, if (ret) { krb5_clear_error_string(context); - ret = KRB5_CC_IO; + ret = KRB5_CC_NOSUPP; } return ret; @@ -169,7 +173,7 @@ kcm_storage_request(krb5_context context, sp = krb5_storage_emem(); if (sp == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_CC_NOMEM, "malloc: out of memory"); return KRB5_CC_NOMEM; } @@ -187,7 +191,7 @@ kcm_storage_request(krb5_context context, *storage_p = sp; fail: if (ret) { - krb5_set_error_string(context, "Failed to encode request"); + krb5_set_error_message(context, ret, "Failed to encode request"); krb5_storage_free(sp); } @@ -202,7 +206,7 @@ kcm_alloc(krb5_context context, const char *name, krb5_ccache *id) k = malloc(sizeof(*k)); if (k == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_CC_NOMEM, "malloc: out of memory"); return KRB5_CC_NOMEM; } @@ -210,7 +214,7 @@ kcm_alloc(krb5_context context, const char *name, krb5_ccache *id) k->name = strdup(name); if (k->name == NULL) { free(k); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_CC_NOMEM, "malloc: out of memory"); return KRB5_CC_NOMEM; } } else @@ -822,7 +826,7 @@ kcm_set_flags(krb5_context context, return ret; } -static krb5_error_code +static int kcm_get_version(krb5_context context, krb5_ccache id) { @@ -832,8 +836,30 @@ kcm_get_version(krb5_context context, static krb5_error_code kcm_move(krb5_context context, krb5_ccache from, krb5_ccache to) { - krb5_set_error_string(context, "kcm_move not implemented"); - return EINVAL; + krb5_error_code ret; + krb5_kcmcache *oldk = KCMCACHE(from); + krb5_kcmcache *newk = KCMCACHE(to); + krb5_storage *request; + + ret = kcm_storage_request(context, KCM_OP_MOVE_CACHE, &request); + if (ret) + return ret; + + ret = krb5_store_stringz(request, oldk->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + + ret = krb5_store_stringz(request, newk->name); + if (ret) { + krb5_storage_free(request); + return ret; + } + ret = kcm_call(context, oldk, request, NULL, NULL); + + krb5_storage_free(request); + return ret; } static krb5_error_code @@ -850,7 +876,8 @@ kcm_default_name(krb5_context context, char **str) * @ingroup krb5_ccache */ -const krb5_cc_ops krb5_kcm_ops = { +KRB5_LIB_VARIABLE const krb5_cc_ops krb5_kcm_ops = { + KRB5_CC_OPS_VERSION, "KCM", kcm_get_name, kcm_resolve, @@ -1118,5 +1145,4 @@ _krb5_kcm_get_ticket(krb5_context context, return ret; } - #endif /* HAVE_KCM */ diff --git a/source4/heimdal/lib/krb5/keyblock.c b/source4/heimdal/lib/krb5/keyblock.c index ff4f972e57..fa19e1e726 100644 --- a/source4/heimdal/lib/krb5/keyblock.c +++ b/source4/heimdal/lib/krb5/keyblock.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keyblock.c 15167 2005-05-18 04:21:57Z lha $"); +RCSID("$Id: keyblock.c 23316 2008-06-23 04:32:32Z lha $"); void KRB5_LIB_FUNCTION krb5_keyblock_zero(krb5_keyblock *keyblock) @@ -81,7 +81,7 @@ krb5_copy_keyblock (krb5_context context, k = malloc (sizeof(*k)); if (k == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } *to = k; @@ -116,15 +116,16 @@ krb5_keyblock_init(krb5_context context, return ret; if (len != size) { - krb5_set_error_string(context, "Encryption key %d is %lu bytes " - "long, %lu was passed in", - type, (unsigned long)len, (unsigned long)size); + krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP, + "Encryption key %d is %lu bytes " + "long, %lu was passed in", + type, (unsigned long)len, (unsigned long)size); return KRB5_PROG_ETYPE_NOSUPP; } ret = krb5_data_copy(&key->keyvalue, data, len); if(ret) { - krb5_set_error_string(context, "malloc failed: %lu", - (unsigned long)len); + krb5_set_error_message(context, ret, "malloc failed: %lu", + (unsigned long)len); return ret; } key->keytype = type; diff --git a/source4/heimdal/lib/krb5/keytab.c b/source4/heimdal/lib/krb5/keytab.c index 79a3f20e79..09e130d850 100644 --- a/source4/heimdal/lib/krb5/keytab.c +++ b/source4/heimdal/lib/krb5/keytab.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab.c 22532 2008-01-27 11:59:18Z lha $"); +RCSID("$Id: keytab.c 23316 2008-06-23 04:32:32Z lha $"); /* * Register a new keytab in `ops' @@ -47,14 +47,15 @@ krb5_kt_register(krb5_context context, struct krb5_keytab_data *tmp; if (strlen(ops->prefix) > KRB5_KT_PREFIX_MAX_LEN - 1) { - krb5_set_error_string(context, "krb5_kt_register; prefix too long"); + krb5_set_error_message(context, KRB5_KT_BADNAME, + "krb5_kt_register; prefix too long"); return KRB5_KT_BADNAME; } tmp = realloc(context->kt_types, (context->num_kt_types + 1) * sizeof(*context->kt_types)); if(tmp == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy(&tmp[context->num_kt_types], ops, @@ -97,14 +98,15 @@ krb5_kt_resolve(krb5_context context, break; } if(i == context->num_kt_types) { - krb5_set_error_string(context, "unknown keytab type %.*s", - (int)type_len, type); + krb5_set_error_message(context, KRB5_KT_UNKNOWN_TYPE, + "unknown keytab type %.*s", + (int)type_len, type); return KRB5_KT_UNKNOWN_TYPE; } k = malloc (sizeof(*k)); if (k == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy(k, &context->kt_types[i], sizeof(*k)); @@ -265,7 +267,7 @@ krb5_kt_get_full_name(krb5_context context, return ret; if (asprintf(str, "%s:%s", type, name) == -1) { - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); *str = NULL; return ENOMEM; } @@ -377,12 +379,12 @@ krb5_kt_get_entry(krb5_context context, else kvno_str[0] = '\0'; - krb5_set_error_string (context, - "Failed to find %s%s in keytab %s (%s)", - princ, - kvno_str, - kt_name ? kt_name : "unknown keytab", - enctype_str ? enctype_str : "unknown enctype"); + krb5_set_error_message (context, KRB5_KT_NOTFOUND, + "Failed to find %s%s in keytab %s (%s)", + princ, + kvno_str, + kt_name ? kt_name : "unknown keytab", + enctype_str ? enctype_str : "unknown enctype"); free(kt_name); free(enctype_str); return KRB5_KT_NOTFOUND; @@ -443,9 +445,9 @@ krb5_kt_start_seq_get(krb5_context context, krb5_kt_cursor *cursor) { if(id->start_seq_get == NULL) { - krb5_set_error_string(context, - "start_seq_get is not supported in the %s " - " keytab", id->prefix); + krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP, + "start_seq_get is not supported in the %s " + " keytab", id->prefix); return HEIM_ERR_OPNOTSUPP; } return (*id->start_seq_get)(context, id, cursor); @@ -464,9 +466,9 @@ krb5_kt_next_entry(krb5_context context, krb5_kt_cursor *cursor) { if(id->next_entry == NULL) { - krb5_set_error_string(context, - "next_entry is not supported in the %s " - " keytab", id->prefix); + krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP, + "next_entry is not supported in the %s " + " keytab", id->prefix); return HEIM_ERR_OPNOTSUPP; } return (*id->next_entry)(context, id, entry, cursor); @@ -482,9 +484,9 @@ krb5_kt_end_seq_get(krb5_context context, krb5_kt_cursor *cursor) { if(id->end_seq_get == NULL) { - krb5_set_error_string(context, - "end_seq_get is not supported in the %s " - " keytab", id->prefix); + krb5_set_error_message(context, HEIM_ERR_OPNOTSUPP, + "end_seq_get is not supported in the %s " + " keytab", id->prefix); return HEIM_ERR_OPNOTSUPP; } return (*id->end_seq_get)(context, id, cursor); @@ -501,8 +503,9 @@ krb5_kt_add_entry(krb5_context context, krb5_keytab_entry *entry) { if(id->add == NULL) { - krb5_set_error_string(context, "Add is not supported in the %s keytab", - id->prefix); + krb5_set_error_message(context, KRB5_KT_NOWRITE, + "Add is not supported in the %s keytab", + id->prefix); return KRB5_KT_NOWRITE; } entry->timestamp = time(NULL); @@ -520,9 +523,9 @@ krb5_kt_remove_entry(krb5_context context, krb5_keytab_entry *entry) { if(id->remove == NULL) { - krb5_set_error_string(context, - "Remove is not supported in the %s keytab", - id->prefix); + krb5_set_error_message(context, KRB5_KT_NOWRITE, + "Remove is not supported in the %s keytab", + id->prefix); return KRB5_KT_NOWRITE; } return (*id->remove)(context, id, entry); diff --git a/source4/heimdal/lib/krb5/keytab_any.c b/source4/heimdal/lib/krb5/keytab_any.c index 54272d4845..9e93191045 100644 --- a/source4/heimdal/lib/krb5/keytab_any.c +++ b/source4/heimdal/lib/krb5/keytab_any.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_any.c 17035 2006-04-10 09:20:13Z lha $"); +RCSID("$Id: keytab_any.c 23316 2008-06-23 04:32:32Z lha $"); struct any_data { krb5_keytab kt; @@ -72,8 +72,8 @@ any_resolve(krb5_context context, const char *name, krb5_keytab id) a0 = a; a->name = strdup(buf); if (a->name == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto fail; } } else @@ -87,7 +87,7 @@ any_resolve(krb5_context context, const char *name, krb5_keytab id) prev = a; } if (a0 == NULL) { - krb5_set_error_string(context, "empty ANY: keytab"); + krb5_set_error_message(context, ENOENT, "empty ANY: keytab"); return ENOENT; } id->data = a0; @@ -134,7 +134,7 @@ any_start_seq_get(krb5_context context, c->data = malloc (sizeof(struct any_cursor_extra_data)); if(c->data == NULL){ - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ed = (struct any_cursor_extra_data *)c->data; @@ -206,8 +206,8 @@ any_add_entry(krb5_context context, while(a != NULL) { ret = krb5_kt_add_entry(context, a->kt, entry); if(ret != 0 && ret != KRB5_KT_NOWRITE) { - krb5_set_error_string(context, "failed to add entry to %s", - a->name); + krb5_set_error_message(context, ret, "failed to add entry to %s", + a->name); return ret; } a = a->next; @@ -229,8 +229,9 @@ any_remove_entry(krb5_context context, found++; else { if(ret != KRB5_KT_NOWRITE && ret != KRB5_KT_NOTFOUND) { - krb5_set_error_string(context, "failed to remove entry from %s", - a->name); + krb5_set_error_message(context, ret, + "Failed to remove keytab entry from %s", + a->name); return ret; } } diff --git a/source4/heimdal/lib/krb5/keytab_file.c b/source4/heimdal/lib/krb5/keytab_file.c index be195d96c2..e830ab3412 100644 --- a/source4/heimdal/lib/krb5/keytab_file.c +++ b/source4/heimdal/lib/krb5/keytab_file.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_file.c 22532 2008-01-27 11:59:18Z lha $"); +RCSID("$Id: keytab_file.c 23469 2008-07-27 12:17:12Z lha $"); #define KRB5_KT_VNO_1 1 #define KRB5_KT_VNO_2 2 @@ -62,7 +62,7 @@ krb5_kt_ret_data(krb5_context context, data->length = size; data->data = malloc(size); if (data->data == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = krb5_storage_read(sp, data->data, size); @@ -83,7 +83,7 @@ krb5_kt_ret_string(krb5_context context, return ret; *data = malloc(size + 1); if (*data == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = krb5_storage_read(sp, *data, size); @@ -168,22 +168,22 @@ krb5_kt_ret_principal(krb5_context context, ALLOC(p, 1); if(p == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = krb5_ret_int16(sp, &len); if(ret) { - krb5_set_error_string(context, - "Failed decoding length of keytab principal"); + krb5_set_error_message(context, ret, + "Failed decoding length of keytab principal"); goto out; } if(krb5_storage_is_flags(sp, KRB5_STORAGE_PRINCIPAL_WRONG_NUM_COMPONENTS)) len--; if (len < 0) { - krb5_set_error_string(context, - "Keytab principal contains invalid length"); ret = KRB5_KT_END; + krb5_set_error_message(context, ret, + "Keytab principal contains invalid length"); goto out; } ret = krb5_kt_ret_string(context, sp, &p->realm); @@ -191,8 +191,8 @@ krb5_kt_ret_principal(krb5_context context, goto out; p->name.name_string.val = calloc(len, sizeof(*p->name.name_string.val)); if(p->name.name_string.val == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } p->name.name_string.len = len; @@ -253,13 +253,13 @@ fkt_resolve(krb5_context context, const char *name, krb5_keytab id) d = malloc(sizeof(*d)); if(d == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } d->filename = strdup(name); if(d->filename == NULL) { free(d); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } d->flags = 0; @@ -334,10 +334,11 @@ fkt_start_seq_get_int(krb5_context context, c->fd = open (d->filename, flags); if (c->fd < 0) { ret = errno; - krb5_set_error_string(context, "keytab %s open failed: %s", - d->filename, strerror(ret)); + krb5_set_error_message(context, ret, "keytab %s open failed: %s", + d->filename, strerror(ret)); return ret; } + rk_cloexec(c->fd); ret = _krb5_xlock(context, c->fd, exclusive, d->filename); if (ret) { close(c->fd); @@ -347,7 +348,7 @@ fkt_start_seq_get_int(krb5_context context, if (c->sp == NULL) { _krb5_xunlock(context, c->fd); close(c->fd); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_eof_code(c->sp, KRB5_KT_END); @@ -492,10 +493,12 @@ fkt_add_entry(krb5_context context, fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600); if (fd < 0) { ret = errno; - krb5_set_error_string(context, "open(%s): %s", d->filename, - strerror(ret)); + krb5_set_error_message(context, ret, "open(%s): %s", d->filename, + strerror(ret)); return ret; } + rk_cloexec(fd); + ret = _krb5_xlock(context, fd, 1, d->filename); if (ret) { close(fd); @@ -510,6 +513,9 @@ fkt_add_entry(krb5_context context, storage_set_flags(context, sp, id->version); } else { int8_t pvno, tag; + + rk_cloexec(fd); + ret = _krb5_xlock(context, fd, 1, d->filename); if (ret) { close(fd); @@ -523,22 +529,22 @@ fkt_add_entry(krb5_context context, properly */ ret = fkt_setup_keytab(context, id, sp); if(ret) { - krb5_set_error_string(context, "%s: keytab is corrupted: %s", - d->filename, strerror(ret)); + krb5_set_error_message(context, ret, "%s: keytab is corrupted: %s", + d->filename, strerror(ret)); goto out; } storage_set_flags(context, sp, id->version); } else { if(pvno != 5) { ret = KRB5_KEYTAB_BADVNO; - krb5_set_error_string(context, "%s: %s", - d->filename, strerror(ret)); + krb5_set_error_message(context, ret, "%s: %s", + d->filename, strerror(ret)); goto out; } ret = krb5_ret_int8 (sp, &tag); if (ret) { - krb5_set_error_string(context, "%s: reading tag: %s", - d->filename, strerror(ret)); + krb5_set_error_message(context, ret, "%s: reading tag: %s", + d->filename, strerror(ret)); goto out; } id->version = tag; @@ -551,7 +557,7 @@ fkt_add_entry(krb5_context context, emem = krb5_storage_emem(); if(emem == NULL) { ret = ENOMEM; - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } ret = krb5_kt_store_principal(context, emem, entry->principal); diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c index aa612add09..7e14cbd329 100644 --- a/source4/heimdal/lib/krb5/keytab_keyfile.c +++ b/source4/heimdal/lib/krb5/keytab_keyfile.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_keyfile.c 22532 2008-01-27 11:59:18Z lha $"); +RCSID("$Id: keytab_keyfile.c 23316 2008-06-23 04:32:32Z lha $"); /* afs keyfile operations --------------------------------------- */ @@ -52,7 +52,7 @@ RCSID("$Id: keytab_keyfile.c 22532 2008-01-27 11:59:18Z lha $"); #define AFS_SERVERMAGICKRBCONF "/usr/afs/etc/krb.conf" struct akf_data { - int num_entries; + uint32_t num_entries; char *filename; char *cell; char *realm; @@ -72,13 +72,13 @@ get_cell_and_realm (krb5_context context, struct akf_data *d) f = fopen (AFS_SERVERTHISCELL, "r"); if (f == NULL) { ret = errno; - krb5_set_error_string (context, "open %s: %s", AFS_SERVERTHISCELL, - strerror(ret)); + krb5_set_error_message (context, ret, "open %s: %s", AFS_SERVERTHISCELL, + strerror(ret)); return ret; } if (fgets (buf, sizeof(buf), f) == NULL) { fclose (f); - krb5_set_error_string (context, "no cell in %s", AFS_SERVERTHISCELL); + krb5_set_error_message (context, EINVAL, "no cell in %s", AFS_SERVERTHISCELL); return EINVAL; } buf[strcspn(buf, "\n")] = '\0'; @@ -86,7 +86,7 @@ get_cell_and_realm (krb5_context context, struct akf_data *d) d->cell = strdup (buf); if (d->cell == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -96,8 +96,8 @@ get_cell_and_realm (krb5_context context, struct akf_data *d) free (d->cell); d->cell = NULL; fclose (f); - krb5_set_error_string (context, "no realm in %s", - AFS_SERVERMAGICKRBCONF); + krb5_set_error_message (context, EINVAL, "no realm in %s", + AFS_SERVERMAGICKRBCONF); return EINVAL; } buf[strcspn(buf, "\n")] = '\0'; @@ -111,7 +111,7 @@ get_cell_and_realm (krb5_context context, struct akf_data *d) if (d->realm == NULL) { free (d->cell); d->cell = NULL; - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } return 0; @@ -128,7 +128,7 @@ akf_resolve(krb5_context context, const char *name, krb5_keytab id) struct akf_data *d = malloc(sizeof (struct akf_data)); if (d == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -143,7 +143,7 @@ akf_resolve(krb5_context context, const char *name, krb5_keytab id) free (d->cell); free (d->realm); free (d); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } id->data = d; @@ -197,13 +197,13 @@ akf_start_seq_get(krb5_context context, c->fd = open (d->filename, O_RDONLY|O_BINARY, 0600); if (c->fd < 0) { ret = errno; - krb5_set_error_string(context, "keytab afs keyfil open %s failed: %s", - d->filename, strerror(ret)); + krb5_set_error_message(context, ret, "keytab afs keyfil open %s failed: %s", + d->filename, strerror(ret)); return ret; } c->sp = krb5_storage_from_fd(c->fd); - ret = krb5_ret_int32(c->sp, &d->num_entries); + ret = krb5_ret_uint32(c->sp, &d->num_entries); if(ret) { krb5_storage_free(c->sp); close(c->fd); @@ -250,7 +250,7 @@ akf_next_entry(krb5_context context, entry->keyblock.keyvalue.data = malloc (8); if (entry->keyblock.keyvalue.data == NULL) { krb5_free_principal (context, entry->principal); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); ret = ENOMEM; goto out; } @@ -307,8 +307,8 @@ akf_add_entry(krb5_context context, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600); if (fd < 0) { ret = errno; - krb5_set_error_string(context, "open(%s): %s", d->filename, - strerror(ret)); + krb5_set_error_message(context, ret, "open(%s): %s", d->filename, + strerror(ret)); return ret; } created = 1; @@ -317,7 +317,7 @@ akf_add_entry(krb5_context context, sp = krb5_storage_from_fd(fd); if(sp == NULL) { close(fd); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } if (created) @@ -327,7 +327,7 @@ akf_add_entry(krb5_context context, ret = errno; krb5_storage_free(sp); close(fd); - krb5_set_error_string (context, "seek: %s", strerror(ret)); + krb5_set_error_message(context, ret, "seek: %s", strerror(ret)); return ret; } @@ -350,11 +350,12 @@ akf_add_entry(krb5_context context, for (i = 0; i < len; i++) { ret = krb5_ret_int32(sp, &kvno); if (ret) { - krb5_set_error_string (context, "Failed to get kvno "); + krb5_set_error_message (context, ret, "Failed to get kvno "); goto out; } if(krb5_storage_seek(sp, 8, SEEK_CUR) < 0) { - krb5_set_error_string (context, "seek: %s", strerror(ret)); + ret = errno; + krb5_set_error_message (context, ret, "seek: %s", strerror(ret)); goto out; } if (kvno == entry->vno) { @@ -368,25 +369,26 @@ akf_add_entry(krb5_context context, if(krb5_storage_seek(sp, 0, SEEK_SET) < 0) { ret = errno; - krb5_set_error_string (context, "seek: %s", strerror(ret)); + krb5_set_error_message (context, ret, "seek: %s", strerror(ret)); goto out; } ret = krb5_store_int32(sp, len); if(ret) { - krb5_set_error_string(context, "keytab keyfile failed new length"); + ret = errno; + krb5_set_error_message (context, ret, "keytab keyfile failed new length"); return ret; } if(krb5_storage_seek(sp, (len - 1) * (8 + 4), SEEK_CUR) < 0) { ret = errno; - krb5_set_error_string (context, "seek to end: %s", strerror(ret)); + krb5_set_error_message (context, ret, "seek to end: %s", strerror(ret)); goto out; } ret = krb5_store_int32(sp, entry->vno); if(ret) { - krb5_set_error_string(context, "keytab keyfile failed store kvno"); + krb5_set_error_message(context, ret, "keytab keyfile failed store kvno"); goto out; } ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data, @@ -396,7 +398,7 @@ akf_add_entry(krb5_context context, ret = errno; else ret = ENOTTY; - krb5_set_error_string(context, "keytab keyfile failed to add key"); + krb5_set_error_message(context, ret, "keytab keyfile failed to add key"); goto out; } ret = 0; diff --git a/source4/heimdal/lib/krb5/keytab_memory.c b/source4/heimdal/lib/krb5/keytab_memory.c index 0ad8720c3f..eabee7c693 100644 --- a/source4/heimdal/lib/krb5/keytab_memory.c +++ b/source4/heimdal/lib/krb5/keytab_memory.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_memory.c 16352 2005-12-05 18:39:46Z lha $"); +RCSID("$Id: keytab_memory.c 23293 2008-06-23 03:28:22Z lha $"); /* memory operations -------------------------------------------- */ @@ -75,14 +75,14 @@ mkt_resolve(krb5_context context, const char *name, krb5_keytab id) d = calloc(1, sizeof(*d)); if(d == NULL) { HEIMDAL_MUTEX_unlock(&mkt_mutex); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } d->name = strdup(name); if (d->name == NULL) { HEIMDAL_MUTEX_unlock(&mkt_mutex); free(d); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } d->entries = NULL; @@ -176,7 +176,7 @@ mkt_add_entry(krb5_context context, krb5_keytab_entry *tmp; tmp = realloc(d->entries, (d->num_entries + 1) * sizeof(*d->entries)); if(tmp == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } d->entries = tmp; diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h index 7e04446fe0..867d08e3e5 100644 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ b/source4/heimdal/lib/krb5/krb5-private.h @@ -38,12 +38,6 @@ _krb5_dh_group_ok ( struct krb5_dh_moduli **/*moduli*/, char **/*name*/); -krb5_error_code KRB5_LIB_FUNCTION -_krb5_enctype_to_oid ( - krb5_context /*context*/, - krb5_enctype /*etype*/, - heim_oid */*oid*/); - krb5_error_code _krb5_expand_default_cc_name ( krb5_context /*context*/, @@ -283,12 +277,6 @@ _krb5_n_fold ( void */*key*/, size_t /*size*/); -krb5_error_code KRB5_LIB_FUNCTION -_krb5_oid_to_enctype ( - krb5_context /*context*/, - const heim_oid */*oid*/, - krb5_enctype */*etype*/); - krb5_error_code _krb5_pac_sign ( krb5_context /*context*/, @@ -321,6 +309,20 @@ _krb5_pk_allow_proxy_certificate ( void KRB5_LIB_FUNCTION _krb5_pk_cert_free (struct krb5_pk_cert */*cert*/); +krb5_error_code +_krb5_pk_kdf ( + krb5_context /*context*/, + const struct AlgorithmIdentifier */*ai*/, + const void */*dhdata*/, + size_t /*dhsize*/, + krb5_const_principal /*client*/, + krb5_const_principal /*server*/, + krb5_enctype /*enctype*/, + const krb5_data */*as_req*/, + const krb5_data */*pk_as_rep*/, + const Ticket */*ticket*/, + krb5_keyblock */*key*/); + krb5_error_code KRB5_LIB_FUNCTION _krb5_pk_load_id ( krb5_context /*context*/, @@ -401,6 +403,12 @@ _krb5_principal2principalname ( PrincipalName */*p*/, const krb5_principal /*from*/); +krb5_boolean KRB5_LIB_FUNCTION +_krb5_principal_compare_PrincipalName ( + krb5_context /*context*/, + krb5_const_principal /*princ1*/, + PrincipalName */*princ2*/); + krb5_error_code KRB5_LIB_FUNCTION _krb5_principalname2krb5_principal ( krb5_context /*context*/, diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h index 647d8886b7..ead66565e7 100644 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ b/source4/heimdal/lib/krb5/krb5-protos.h @@ -12,11 +12,13 @@ extern "C" { #endif -#ifndef KRB5_LIB_FUNCTION +#ifndef KRB5_LIB #if defined(_WIN32) -#define KRB5_LIB_FUNCTION _stdcall +#define KRB5_LIB_FUNCTION _stdcall __declspec(dllimport) +#define KRB5_LIB_VARIABLE __declspec(dllimport) #else #define KRB5_LIB_FUNCTION +#define KRB5_LIB_VARIABLE #endif #endif @@ -627,6 +629,14 @@ krb5_cc_gen_new ( const krb5_cc_ops */*ops*/, krb5_ccache */*id*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_get_config ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_const_principal /*principal*/, + const char */*name*/, + krb5_data */*data*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_get_full_name ( krb5_context /*context*/, @@ -726,6 +736,14 @@ krb5_cc_retrieve_cred ( const krb5_creds */*mcreds*/, krb5_creds */*creds*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_cc_set_config ( + krb5_context /*context*/, + krb5_ccache /*id*/, + krb5_const_principal /*principal*/, + const char */*name*/, + krb5_data */*data*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_cc_set_default_name ( krb5_context /*context*/, @@ -749,6 +767,11 @@ krb5_cc_store_cred ( krb5_ccache /*id*/, krb5_creds */*creds*/); +krb5_error_code +krb5_cc_switch ( + krb5_context /*context*/, + krb5_ccache /*id*/); + krb5_error_code KRB5_LIB_FUNCTION krb5_change_password ( krb5_context /*context*/, @@ -756,7 +779,8 @@ krb5_change_password ( const char */*newpw*/, int */*result_code*/, krb5_data */*result_code_string*/, - krb5_data */*result_string*/); + krb5_data */*result_string*/) + __attribute__((deprecated)); krb5_error_code KRB5_LIB_FUNCTION krb5_check_transited ( @@ -764,14 +788,14 @@ krb5_check_transited ( krb5_const_realm /*client_realm*/, krb5_const_realm /*server_realm*/, krb5_realm */*realms*/, - int /*num_realms*/, + unsigned int /*num_realms*/, int */*bad_realm*/); krb5_error_code KRB5_LIB_FUNCTION krb5_check_transited_realms ( krb5_context /*context*/, const char *const */*realms*/, - int /*num_realms*/, + unsigned int /*num_realms*/, int */*bad_realm*/); krb5_error_code KRB5_LIB_FUNCTION @@ -1462,14 +1486,14 @@ krb5_domain_x500_decode ( krb5_context /*context*/, krb5_data /*tr*/, char ***/*realms*/, - int */*num_realms*/, + unsigned int */*num_realms*/, const char */*client_realm*/, const char */*server_realm*/); krb5_error_code KRB5_LIB_FUNCTION krb5_domain_x500_encode ( char **/*realms*/, - int /*num_realms*/, + unsigned int /*num_realms*/, krb5_data */*encoding*/); krb5_error_code KRB5_LIB_FUNCTION @@ -1731,9 +1755,9 @@ krb5_free_error_contents ( krb5_error */*error*/); void KRB5_LIB_FUNCTION -krb5_free_error_string ( +krb5_free_error_message ( krb5_context /*context*/, - char */*str*/); + const char */*msg*/); krb5_error_code KRB5_LIB_FUNCTION krb5_free_host_realm ( @@ -1939,7 +1963,7 @@ krb5_get_err_text ( krb5_context /*context*/, krb5_error_code /*code*/); -char * KRB5_LIB_FUNCTION +const char * KRB5_LIB_FUNCTION krb5_get_error_message ( krb5_context /*context*/, krb5_error_code /*code*/); @@ -2969,6 +2993,12 @@ krb5_principal_match ( krb5_const_principal /*princ*/, krb5_const_principal /*pattern*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_principal_set_realm ( + krb5_context /*context*/, + krb5_principal /*principal*/, + krb5_const_realm /*realm*/); + void KRB5_LIB_FUNCTION krb5_principal_set_type ( krb5_context /*context*/, @@ -3450,12 +3480,20 @@ krb5_set_dns_canonicalize_hostname ( krb5_context /*context*/, krb5_boolean /*flag*/); +void KRB5_LIB_FUNCTION +krb5_set_error_message ( + krb5_context /*context*/, + krb5_error_code /*ret*/, + const char */*fmt*/, + ...) + __attribute__ ((format (printf, 3, 4))); + krb5_error_code KRB5_LIB_FUNCTION krb5_set_error_string ( krb5_context /*context*/, const char */*fmt*/, - ...) - __attribute__((format (printf, 2, 3))); + ...) __attribute__((format (printf, 2, 3))) + __attribute__((deprecated)); krb5_error_code KRB5_LIB_FUNCTION krb5_set_extra_addresses ( @@ -3472,6 +3510,12 @@ krb5_set_ignore_addresses ( krb5_context /*context*/, const krb5_addresses */*addresses*/); +krb5_error_code KRB5_LIB_FUNCTION +krb5_set_kdc_sec_offset ( + krb5_context /*context*/, + int32_t /*sec*/, + int32_t /*usec*/); + void KRB5_LIB_FUNCTION krb5_set_max_time_skew ( krb5_context /*context*/, @@ -4047,12 +4091,20 @@ krb5_vlog_msg ( va_list /*ap*/) __attribute__((format (printf, 5, 0))); +void KRB5_LIB_FUNCTION +krb5_vset_error_message ( + krb5_context /*context*/, + krb5_error_code /*ret*/, + const char */*fmt*/, + va_list /*args*/) + __attribute__ ((format (printf, 3, 0))); + krb5_error_code KRB5_LIB_FUNCTION krb5_vset_error_string ( krb5_context /*context*/, const char */*fmt*/, - va_list /*args*/) - __attribute__ ((format (printf, 2, 0))); + va_list args) __attribute__ ((format (printf, 2, 0))) + __attribute__((deprecated)); krb5_error_code KRB5_LIB_FUNCTION krb5_vwarn ( @@ -4107,6 +4159,9 @@ krb5_write_safe_message ( krb5_error_code KRB5_LIB_FUNCTION krb5_xfree (void */*ptr*/); +void KRB5_LIB_FUNCTION + __attribute__((deprecated)) krb5_free_error_string(krb5_context context, char *str); + #ifdef __cplusplus } #endif diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index 571eb6192a..b1e2781d52 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h 22100 2007-12-03 17:15:00Z lha $ */ +/* $Id: krb5.h 23026 2008-04-17 10:02:03Z lha $ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -363,6 +363,7 @@ typedef union { #define KRB5_GC_FORWARDABLE (1U << 4) #define KRB5_GC_NO_TRANSIT_CHECK (1U << 5) #define KRB5_GC_CONSTRAINED_DELEGATION (1U << 6) +#define KRB5_GC_CANONICALIZE (1U << 7) /* constants for compare_creds (and cc_retrieve_cred) */ #define KRB5_TC_DONT_MATCH_REALM (1U << 31) @@ -395,7 +396,10 @@ typedef struct krb5_creds { typedef struct krb5_cc_cache_cursor_data *krb5_cc_cache_cursor; +#define KRB5_CC_OPS_VERSION 1 + typedef struct krb5_cc_ops { + int version; const char *prefix; const char* (*get_name)(krb5_context, krb5_ccache); krb5_error_code (*resolve)(krb5_context, krb5_ccache *, const char *); @@ -419,7 +423,8 @@ typedef struct krb5_cc_ops { krb5_error_code (*get_cache_next)(krb5_context, krb5_cc_cursor, krb5_ccache *); krb5_error_code (*end_cache_get)(krb5_context, krb5_cc_cursor); krb5_error_code (*move)(krb5_context, krb5_ccache, krb5_ccache); - krb5_error_code (*default_name)(krb5_context, char **); + krb5_error_code (*get_default_name)(krb5_context, char **); + krb5_error_code (*set_default)(krb5_context, krb5_ccache); } krb5_cc_ops; struct krb5_log_facility; @@ -589,11 +594,6 @@ typedef EncAPRepPart krb5_ap_rep_enc_part; #define KRB5_DIGEST_NAME ("digest") -/* variables */ - -extern const char *krb5_config_file; -extern const char *krb5_defkeyname; - typedef enum { KRB5_PROMPT_TYPE_PASSWORD = 0x1, KRB5_PROMPT_TYPE_NEW_PASSWORD = 0x2, @@ -681,20 +681,6 @@ typedef struct krb5_verify_opt { #define KRB5_VERIFY_LREALMS 1 #define KRB5_VERIFY_NO_ADDRESSES 2 -extern const krb5_cc_ops krb5_acc_ops; -extern const krb5_cc_ops krb5_fcc_ops; -extern const krb5_cc_ops krb5_mcc_ops; -extern const krb5_cc_ops krb5_kcm_ops; - -extern const krb5_kt_ops krb5_fkt_ops; -extern const krb5_kt_ops krb5_wrfkt_ops; -extern const krb5_kt_ops krb5_javakt_ops; -extern const krb5_kt_ops krb5_mkt_ops; -extern const krb5_kt_ops krb5_akf_ops; -extern const krb5_kt_ops krb4_fkt_ops; -extern const krb5_kt_ops krb5_srvtab_fkt_ops; -extern const krb5_kt_ops krb5_any_ops; - #define KRB5_KPASSWD_VERS_CHANGEPW 1 #define KRB5_KPASSWD_VERS_SETPW 0xff80 @@ -739,6 +725,7 @@ enum { typedef krb5_error_code (*krb5_send_to_kdc_func)(krb5_context, void *, krb5_krbhst_info *, + time_t timeout, const krb5_data *, krb5_data *); @@ -776,5 +763,26 @@ struct sockaddr; #include +/* variables */ + +extern KRB5_LIB_VARIABLE const char *krb5_config_file; +extern KRB5_LIB_VARIABLE const char *krb5_defkeyname; + + +extern KRB5_LIB_VARIABLE const krb5_cc_ops krb5_acc_ops; +extern KRB5_LIB_VARIABLE const krb5_cc_ops krb5_fcc_ops; +extern KRB5_LIB_VARIABLE const krb5_cc_ops krb5_mcc_ops; +extern KRB5_LIB_VARIABLE const krb5_cc_ops krb5_kcm_ops; +extern KRB5_LIB_VARIABLE const krb5_cc_ops krb5_scc_ops; + +extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_fkt_ops; +extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_wrfkt_ops; +extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_javakt_ops; +extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_mkt_ops; +extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_akf_ops; +extern KRB5_LIB_VARIABLE const krb5_kt_ops krb4_fkt_ops; +extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_srvtab_fkt_ops; +extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_any_ops; + #endif /* __KRB5_H__ */ diff --git a/source4/heimdal/lib/krb5/krb5_err.et b/source4/heimdal/lib/krb5/krb5_err.et index 6714401e45..8e49ffcc4a 100644 --- a/source4/heimdal/lib/krb5/krb5_err.et +++ b/source4/heimdal/lib/krb5/krb5_err.et @@ -3,7 +3,7 @@ # # This might look like a com_err file, but is not # -id "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $" +id "$Id: krb5_err.et 23354 2008-07-15 11:23:34Z lha $" error_table krb5 @@ -110,7 +110,7 @@ error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not suppo index 128 prefix -error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $" +error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 23354 2008-07-15 11:23:34Z lha $" error_code KRB5_LIBOS_BADLOCKFLAG, "Invalid flag for file lock mode" error_code KRB5_LIBOS_CANTREADPWD, "Cannot read password" @@ -262,5 +262,7 @@ error_code KRB5_ERR_BAD_S2K_PARAMS, "Invalid key generation parameters from KDC" error_code KRB5_ERR_NO_SERVICE, "Service not available" error_code KRB5_CC_NOSUPP, "Credential cache function not supported" error_code KRB5_DELTAT_BADFORMAT, "Invalid format of Kerberos lifetime or clock skew string" +error_code KRB5_PLUGIN_NO_HANDLE, "Supplied data not handled by this plugin" +error_code KRB5_PLUGIN_OP_NOTSUPP, "Plugin does not support the operaton" end diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index 8b7c41cc80..aaabd4541b 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_locl.h 22226 2007-12-08 21:31:53Z lha $ */ +/* $Id: krb5_locl.h 23324 2008-06-26 03:54:45Z lha $ */ #ifndef __KRB5_LOCL_H__ #define __KRB5_LOCL_H__ @@ -131,6 +131,8 @@ struct sockaddr_dl; #include #include +#include + #include "crypto-headers.h" @@ -142,6 +144,7 @@ struct send_to_kdc; struct krb5_pk_identity; struct krb5_pk_cert; struct ContentInfo; +struct AlgorithmIdentifier; typedef struct krb5_pk_init_ctx_data *krb5_pk_init_ctx; struct krb5_dh_moduli; @@ -154,7 +157,7 @@ struct _krb5_krb_auth_data; #include #include #ifdef PKINIT -#include +#include #endif #include @@ -164,7 +167,7 @@ struct _krb5_krb_auth_data; #define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0) /* should this be public? */ -#define KEYTAB_DEFAULT "ANY:FILE:" SYSCONFDIR "/krb5.keytab,krb4:" SYSCONFDIR "/srvtab" +#define KEYTAB_DEFAULT "FILE:" SYSCONFDIR "/krb5.keytab" #define KEYTAB_DEFAULT_MODIFY "FILE:" SYSCONFDIR "/krb5.keytab" #define MODULI_FILE SYSCONFDIR "/krb5.moduli" @@ -227,7 +230,7 @@ typedef struct krb5_context_data { struct krb5_keytab_data *kt_types; /* registered keytab types */ const char *date_fmt; char *error_string; - char error_buf[256]; + krb5_error_code error_code; krb5_addresses *ignore_addresses; char *default_cc_name; char *default_cc_name_env; @@ -247,6 +250,7 @@ typedef struct krb5_context_data { #define EXTRACT_TICKET_ALLOW_CNAME_MISMATCH 1 #define EXTRACT_TICKET_ALLOW_SERVER_MISMATCH 2 #define EXTRACT_TICKET_MATCH_REALM 4 +#define EXTRACT_TICKET_AS_REQ 8 /* * Configurable options @@ -264,4 +268,22 @@ typedef struct krb5_context_data { #define KRB5_ADDRESSLESS_DEFAULT TRUE #endif +#ifdef PKINIT + +struct krb5_pk_identity { + hx509_context hx509ctx; + hx509_verify_ctx verify_ctx; + hx509_certs certs; + hx509_certs anchors; + hx509_certs certpool; + hx509_revoke_ctx revokectx; +}; + +enum krb5_pk_type { + PKINIT_WIN2K = 1, + PKINIT_27 = 2 +}; + +#endif /* PKINIT */ + #endif /* __KRB5_LOCL_H__ */ diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index 094fd4f9c6..3514a026b7 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -35,7 +35,7 @@ #include #include "locate_plugin.h" -RCSID("$Id: krbhst.c 21457 2007-07-10 12:53:25Z lha $"); +RCSID("$Id: krbhst.c 23447 2008-07-27 12:09:05Z lha $"); static int string_to_proto(const char *string) @@ -72,7 +72,8 @@ srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count, proto_num = string_to_proto(proto); if(proto_num < 0) { - krb5_set_error_string(context, "unknown protocol `%s'", proto); + krb5_set_error_message(context, EINVAL, + "unknown protocol `%s'", proto); return EINVAL; } @@ -96,7 +97,7 @@ srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count, *res = malloc(num_srv * sizeof(**res)); if(*res == NULL) { dns_free_data(r); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -247,7 +248,7 @@ _krb5_krbhost_info_move(krb5_context context, /* trailing NUL is included in structure */ *to = calloc(1, sizeof(**to) + hostnamelen); if(*to == NULL) { - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -522,7 +523,8 @@ plugin_get_hosts(krb5_context context, struct krb5_plugin *list = NULL, *e; krb5_error_code ret; - ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, "resolve", &list); + ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, + KRB5_PLUGIN_LOCATE, &list); if(ret != 0 || list == NULL) return; @@ -539,8 +541,9 @@ plugin_get_hosts(krb5_context context, (*service->init)(context, &ctx); ret = (*service->lookup)(ctx, type, kd->realm, 0, 0, add_locate, kd); (*service->fini)(ctx); - if (ret) { - krb5_set_error_string(context, "Plugin failed to lookup"); + if (ret && ret != KRB5_PLUGIN_NO_HANDLE) { + krb5_set_error_message(context, ret, + "Locate plugin failed to lookup: %d", ret); break; } } @@ -832,7 +835,7 @@ krb5_krbhst_init_flags(krb5_context context, def_port = ntohs(krb5_getportbyname (context, "krb524", "udp", 4444)); break; default: - krb5_set_error_string(context, "unknown krbhst type (%u)", type); + krb5_set_error_message(context, ENOTTY, "unknown krbhst type (%u)", type); return ENOTTY; } if((kd = common_init(context, realm, flags)) == NULL) @@ -920,7 +923,8 @@ gethostlist(krb5_context context, const char *realm, while(krb5_krbhst_next(context, handle, &hostinfo) == 0) nhost++; if(nhost == 0) { - krb5_set_error_string(context, "No KDC found for realm %s", realm); + krb5_set_error_message(context, KRB5_KDC_UNREACH, + "No KDC found for realm %s", realm); return KRB5_KDC_UNREACH; } *hostlist = calloc(nhost + 1, sizeof(**hostlist)); diff --git a/source4/heimdal/lib/krb5/locate_plugin.h b/source4/heimdal/lib/krb5/locate_plugin.h index 251712c894..a342617d38 100644 --- a/source4/heimdal/lib/krb5/locate_plugin.h +++ b/source4/heimdal/lib/krb5/locate_plugin.h @@ -31,13 +31,15 @@ * SUCH DAMAGE. */ -/* $Id: locate_plugin.h 18998 2006-11-12 19:00:03Z lha $ */ +/* $Id: locate_plugin.h 23351 2008-07-15 11:22:39Z lha $ */ #ifndef HEIMDAL_KRB5_LOCATE_PLUGIN_H #define HEIMDAL_KRB5_LOCATE_PLUGIN_H 1 #include +#define KRB5_PLUGIN_LOCATE "resolve" + enum locate_service_type { locate_service_kdc = 1, locate_service_master_kdc, diff --git a/source4/heimdal/lib/krb5/log.c b/source4/heimdal/lib/krb5/log.c index c04f50fd9a..721e3691ca 100644 --- a/source4/heimdal/lib/krb5/log.c +++ b/source4/heimdal/lib/krb5/log.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: log.c 19088 2006-11-21 08:08:46Z lha $"); +RCSID("$Id: log.c 23443 2008-07-27 12:07:25Z lha $"); struct facility { int min; @@ -121,13 +121,13 @@ krb5_initlog(krb5_context context, { krb5_log_facility *f = calloc(1, sizeof(*f)); if(f == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } f->program = strdup(program); if(f->program == NULL){ free(f); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } *fac = f; @@ -145,7 +145,7 @@ krb5_addlog_func(krb5_context context, { struct facility *fp = log_realloc(fac); if(fp == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } fp->min = min; @@ -187,7 +187,7 @@ open_syslog(krb5_context context, int i; if(sd == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } i = find_value(sev, syslogvals); @@ -242,7 +242,7 @@ open_file(krb5_context context, krb5_log_facility *fac, int min, int max, { struct file_data *fd = malloc(sizeof(*fd)); if(fd == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } fd->filename = filename; @@ -277,7 +277,8 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) if(n){ p = strchr(p, '/'); if(p == NULL) { - krb5_set_error_string (context, "failed to parse \"%s\"", orig); + krb5_set_error_message(context, HEIM_ERR_LOG_PARSE, + "failed to parse \"%s\"", orig); return HEIM_ERR_LOG_PARSE; } p++; @@ -292,7 +293,7 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) int keep_open = 0; fn = strdup(p + 5); if(fn == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } if(p[4] == '='){ @@ -300,16 +301,17 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) O_TRUNC | O_APPEND, 0666); if(i < 0) { ret = errno; - krb5_set_error_string (context, "open(%s): %s", fn, + krb5_set_error_message(context, ret, "open(%s): %s", fn, strerror(ret)); free(fn); return ret; } + rk_cloexec(i); file = fdopen(i, "a"); if(file == NULL){ ret = errno; close(i); - krb5_set_error_string (context, "fdopen(%s): %s", fn, + krb5_set_error_message(context, ret, "fdopen(%s): %s", fn, strerror(ret)); free(fn); return ret; @@ -333,8 +335,8 @@ krb5_addlog_dest(krb5_context context, krb5_log_facility *f, const char *orig) strlcpy(facility, "AUTH", sizeof(facility)); ret = open_syslog(context, f, min, max, severity, facility); }else{ - krb5_set_error_string (context, "unknown log type: %s", p); ret = HEIM_ERR_LOG_PARSE; /* XXX */ + krb5_set_error_message (context, ret, "unknown log type: %s", p); } return ret; } diff --git a/source4/heimdal/lib/krb5/mcache.c b/source4/heimdal/lib/krb5/mcache.c index 01bcb09d3b..682f9f6abd 100644 --- a/source4/heimdal/lib/krb5/mcache.c +++ b/source4/heimdal/lib/krb5/mcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: mcache.c 22107 2007-12-03 17:22:51Z lha $"); +RCSID("$Id: mcache.c 23316 2008-06-23 04:32:32Z lha $"); typedef struct krb5_mcache { char *name; @@ -119,7 +119,7 @@ mcc_resolve(krb5_context context, krb5_ccache *id, const char *res) m = mcc_alloc(res); if (m == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_CC_NOMEM, "malloc: out of memory"); return KRB5_CC_NOMEM; } @@ -138,7 +138,7 @@ mcc_gen_new(krb5_context context, krb5_ccache *id) m = mcc_alloc(NULL); if (m == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_CC_NOMEM, "malloc: out of memory"); return KRB5_CC_NOMEM; } @@ -237,7 +237,7 @@ mcc_store_cred(krb5_context context, l = malloc (sizeof(*l)); if (l == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_CC_NOMEM, "malloc: out of memory"); return KRB5_CC_NOMEM; } l->next = m->creds; @@ -348,7 +348,7 @@ mcc_get_cache_first(krb5_context context, krb5_cc_cursor *cursor) iter = calloc(1, sizeof(*iter)); if (iter == NULL) { - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -439,7 +439,7 @@ mcc_default_name(krb5_context context, char **str) { *str = strdup("MEMORY:"); if (*str == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } return 0; @@ -452,7 +452,8 @@ mcc_default_name(krb5_context context, char **str) * @ingroup krb5_ccache */ -const krb5_cc_ops krb5_mcc_ops = { +KRB5_LIB_VARIABLE const krb5_cc_ops krb5_mcc_ops = { + KRB5_CC_OPS_VERSION, "MEMORY", mcc_get_name, mcc_resolve, diff --git a/source4/heimdal/lib/krb5/mk_priv.c b/source4/heimdal/lib/krb5/mk_priv.c index 87e429af8c..3b4b6e30b7 100644 --- a/source4/heimdal/lib/krb5/mk_priv.c +++ b/source4/heimdal/lib/krb5/mk_priv.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_priv.c 16680 2006-02-01 12:39:26Z lha $"); +RCSID("$Id: mk_priv.c 23297 2008-06-23 03:28:53Z lha $"); krb5_error_code KRB5_LIB_FUNCTION @@ -138,7 +138,7 @@ krb5_mk_priv(krb5_context context, ret = krb5_data_copy(outbuf, buf + buf_size - len, len); if (ret) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); free(buf); return ENOMEM; } diff --git a/source4/heimdal/lib/krb5/mk_rep.c b/source4/heimdal/lib/krb5/mk_rep.c index 570a837201..069df42e26 100644 --- a/source4/heimdal/lib/krb5/mk_rep.c +++ b/source4/heimdal/lib/krb5/mk_rep.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_rep.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id: mk_rep.c 23316 2008-06-23 04:32:32Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_mk_rep(krb5_context context, @@ -61,18 +61,18 @@ krb5_mk_rep(krb5_context context, auth_context, auth_context->keyblock); if(ret) { - krb5_set_error_string (context, - "krb5_mk_rep: generating subkey"); free_EncAPRepPart(&body); + krb5_set_error_message(context, ret, + "krb5_mk_rep: generating subkey"); return ret; } } ret = krb5_copy_keyblock(context, auth_context->local_subkey, &body.subkey); if (ret) { - krb5_set_error_string (context, - "krb5_copy_keyblock: out of memory"); free_EncAPRepPart(&body); + krb5_set_error_message(context, ENOMEM, + "krb5_copy_keyblock: out of memory"); return ENOMEM; } } else @@ -84,7 +84,7 @@ krb5_mk_rep(krb5_context context, &auth_context->local_seqnumber); ALLOC(body.seq_number, 1); if (body.seq_number == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); free_EncAPRepPart(&body); return ENOMEM; } diff --git a/source4/heimdal/lib/krb5/n-fold.c b/source4/heimdal/lib/krb5/n-fold.c index 53528cfd1f..287f8cf64f 100644 --- a/source4/heimdal/lib/krb5/n-fold.c +++ b/source4/heimdal/lib/krb5/n-fold.c @@ -32,7 +32,7 @@ #include "krb5_locl.h" -RCSID("$Id: n-fold.c 22190 2007-12-06 16:24:22Z lha $"); +RCSID("$Id: n-fold.c 22923 2008-04-08 14:51:33Z lha $"); static krb5_error_code rr13(unsigned char *buf, size_t len) diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index 0b44ca1da3..fbc754efda 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: pac.c 22562 2008-02-03 17:38:35Z lha $"); +RCSID("$Id: pac.c 23316 2008-06-23 04:32:32Z lha $"); struct PAC_INFO_BUFFER { uint32_t type; @@ -93,14 +93,14 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, p = calloc(1, sizeof(*p)); if (p == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } sp = krb5_storage_from_readonly_mem(ptr, len); if (sp == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); @@ -108,21 +108,21 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, CHECK(ret, krb5_ret_uint32(sp, &tmp), out); CHECK(ret, krb5_ret_uint32(sp, &tmp2), out); if (tmp < 1) { - krb5_set_error_string(context, "PAC have too few buffer"); ret = EINVAL; /* Too few buffers */ + krb5_set_error_message(context, ret, "PAC have too few buffer"); goto out; } if (tmp2 != 0) { - krb5_set_error_string(context, "PAC have wrong version"); ret = EINVAL; /* Wrong version */ + krb5_set_error_message(context, ret, "PAC have wrong version"); goto out; } p->pac = calloc(1, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (tmp - 1))); if (p->pac == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } @@ -143,51 +143,52 @@ krb5_pac_parse(krb5_context context, const void *ptr, size_t len, /* consistency checks */ if (p->pac->buffers[i].offset_lo & (PAC_ALIGNMENT - 1)) { - krb5_set_error_string(context, "PAC out of allignment"); ret = EINVAL; + krb5_set_error_message(context, ret, "PAC out of allignment"); goto out; } if (p->pac->buffers[i].offset_hi) { - krb5_set_error_string(context, "PAC high offset set"); ret = EINVAL; + krb5_set_error_message(context, ret, "PAC high offset set"); goto out; } if (p->pac->buffers[i].offset_lo > len) { - krb5_set_error_string(context, "PAC offset off end"); ret = EINVAL; + krb5_set_error_message(context, ret, "PAC offset off end"); goto out; } if (p->pac->buffers[i].offset_lo < header_end) { - krb5_set_error_string(context, "PAC offset inside header: %d %d", - p->pac->buffers[i].offset_lo, header_end); ret = EINVAL; + krb5_set_error_message(context, ret, "PAC offset inside header: %lu %lu", + (unsigned long)p->pac->buffers[i].offset_lo, + (unsigned long)header_end); goto out; } if (p->pac->buffers[i].buffersize > len - p->pac->buffers[i].offset_lo){ - krb5_set_error_string(context, "PAC length off end"); ret = EINVAL; + krb5_set_error_message(context, ret, "PAC length off end"); goto out; } /* let save pointer to data we need later */ if (p->pac->buffers[i].type == PAC_SERVER_CHECKSUM) { if (p->server_checksum) { - krb5_set_error_string(context, "PAC have two server checksums"); ret = EINVAL; + krb5_set_error_message(context, ret, "PAC have two server checksums"); goto out; } p->server_checksum = &p->pac->buffers[i]; } else if (p->pac->buffers[i].type == PAC_PRIVSVR_CHECKSUM) { if (p->privsvr_checksum) { - krb5_set_error_string(context, "PAC have two KDC checksums"); ret = EINVAL; + krb5_set_error_message(context, ret, "PAC have two KDC checksums"); goto out; } p->privsvr_checksum = &p->pac->buffers[i]; } else if (p->pac->buffers[i].type == PAC_LOGON_NAME) { if (p->logon_name) { - krb5_set_error_string(context, "PAC have two logon names"); ret = EINVAL; + krb5_set_error_message(context, ret, "PAC have two logon names"); goto out; } p->logon_name = &p->pac->buffers[i]; @@ -224,14 +225,14 @@ krb5_pac_init(krb5_context context, krb5_pac *pac) p = calloc(1, sizeof(*p)); if (p == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } p->pac = calloc(1, sizeof(*p->pac)); if (p->pac == NULL) { free(p); - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -239,7 +240,7 @@ krb5_pac_init(krb5_context context, krb5_pac *pac) if (ret) { free (p->pac); free(p); - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); return ret; } @@ -262,7 +263,7 @@ krb5_pac_add_buffer(krb5_context context, krb5_pac p, ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * len)); if (ptr == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } p->pac = ptr; @@ -280,7 +281,7 @@ krb5_pac_add_buffer(krb5_context context, krb5_pac p, old_end = p->data.length; len = p->data.length + data->length + PAC_INFO_BUFFER_SIZE; if (len < p->data.length) { - krb5_set_error_string(context, "integer overrun"); + krb5_set_error_message(context, EINVAL, "integer overrun"); return EINVAL; } @@ -289,7 +290,7 @@ krb5_pac_add_buffer(krb5_context context, krb5_pac p, ret = krb5_data_realloc(&p->data, len); if (ret) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); return ret; } @@ -330,7 +331,7 @@ krb5_pac_get_buffer(krb5_context context, krb5_pac p, if (type == PAC_PRIVSVR_CHECKSUM || type == PAC_SERVER_CHECKSUM) { ret = krb5_data_alloc(data, 16); if (ret) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); return ret; } memset(data->data, 0, data->length); @@ -346,13 +347,13 @@ krb5_pac_get_buffer(krb5_context context, krb5_pac p, ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len); if (ret) { - krb5_set_error_string(context, "Out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); return ret; } return 0; } - krb5_set_error_string(context, "No PAC buffer of type %lu was found", - (unsigned long)type); + krb5_set_error_message(context, ENOENT, "No PAC buffer of type %lu was found", + (unsigned long)type); return ENOENT; } @@ -371,7 +372,7 @@ krb5_pac_get_types(krb5_context context, *types = calloc(p->pac->numbuffers, sizeof(*types)); if (*types == NULL) { *len = 0; - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } for (i = 0; i < p->pac->numbuffers; i++) @@ -415,7 +416,7 @@ verify_checksum(krb5_context context, sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo, sig->buffersize); if (sp == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); @@ -426,21 +427,21 @@ verify_checksum(krb5_context context, sig->buffersize - krb5_storage_seek(sp, 0, SEEK_CUR); cksum.checksum.data = malloc(cksum.checksum.length); if (cksum.checksum.data == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } ret = krb5_storage_read(sp, cksum.checksum.data, cksum.checksum.length); if (ret != cksum.checksum.length) { - krb5_set_error_string(context, "PAC checksum missing checksum"); ret = EINVAL; + krb5_set_error_message(context, ret, "PAC checksum missing checksum"); goto out; } if (!krb5_checksum_is_keyed(context, cksum.cksumtype)) { - krb5_set_error_string (context, "Checksum type %d not keyed", - cksum.cksumtype); ret = EINVAL; + krb5_set_error_message(context, ret, "Checksum type %d not keyed", + cksum.cksumtype); goto out; } @@ -487,7 +488,7 @@ create_checksum(krb5_context context, return ret; if (cksum.checksum.length != siglen) { - krb5_set_error_string(context, "pac checksum wrong length"); + krb5_set_error_message(context, EINVAL, "pac checksum wrong length"); free_Checksum(&cksum); return EINVAL; } @@ -530,7 +531,7 @@ verify_logonname(krb5_context context, sp = krb5_storage_from_readonly_mem((const char *)data->data + logon_name->offset_lo, logon_name->buffersize); if (sp == NULL) { - krb5_set_error_string(context, "Out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -545,27 +546,27 @@ verify_logonname(krb5_context context, t2 = ((uint64_t)time2 << 32) | time1; if (t1 != t2) { krb5_storage_free(sp); - krb5_set_error_string(context, "PAC timestamp mismatch"); + krb5_set_error_message(context, EINVAL, "PAC timestamp mismatch"); return EINVAL; } } CHECK(ret, krb5_ret_uint16(sp, &len), out); if (len == 0) { krb5_storage_free(sp); - krb5_set_error_string(context, "PAC logon name length missing"); + krb5_set_error_message(context, EINVAL, "PAC logon name length missing"); return EINVAL; } s = malloc(len); if (s == NULL) { krb5_storage_free(sp); - krb5_set_error_string(context, "Out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = krb5_storage_read(sp, s, len); if (ret != len) { krb5_storage_free(sp); - krb5_set_error_string(context, "Failed to read PAC logon name"); + krb5_set_error_message(context, EINVAL, "Failed to read PAC logon name"); return EINVAL; } krb5_storage_free(sp); @@ -577,33 +578,33 @@ verify_logonname(krb5_context context, ucs2 = malloc(sizeof(ucs2[0]) * ucs2len); if (ucs2 == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = wind_ucs2read(s, len, &flags, ucs2, &ucs2len); free(s); if (ret) { free(ucs2); - krb5_set_error_string(context, "Failed to convert string to UCS-2"); + krb5_set_error_message(context, ret, "Failed to convert string to UCS-2"); return ret; } ret = wind_ucs2utf8_length(ucs2, ucs2len, &u8len); if (ret) { free(ucs2); - krb5_set_error_string(context, "Failed to count length of UCS-2 string"); + krb5_set_error_message(context, ret, "Failed to count length of UCS-2 string"); return ret; } u8len += 1; /* Add space for NUL */ s = malloc(u8len); if (s == NULL) { free(ucs2); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = wind_ucs2utf8(ucs2, ucs2len, s, &u8len); free(ucs2); if (ret) { - krb5_set_error_string(context, "Failed to convert to UTF-8"); + krb5_set_error_message(context, ret, "Failed to convert to UTF-8"); return ret; } } @@ -613,8 +614,8 @@ verify_logonname(krb5_context context, return ret; if (krb5_principal_compare_any_realm(context, principal, p2) != TRUE) { - krb5_set_error_string(context, "PAC logon name mismatch"); ret = EINVAL; + krb5_set_error_message(context, ret, "PAC logon name mismatch"); } krb5_free_principal(context, p2); return ret; @@ -644,7 +645,7 @@ build_logon_name(krb5_context context, sp = krb5_storage_emem(); if (sp == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); @@ -710,15 +711,15 @@ krb5_pac_verify(krb5_context context, krb5_error_code ret; if (pac->server_checksum == NULL) { - krb5_set_error_string(context, "PAC missing server checksum"); + krb5_set_error_message(context, EINVAL, "PAC missing server checksum"); return EINVAL; } if (pac->privsvr_checksum == NULL) { - krb5_set_error_string(context, "PAC missing kdc checksum"); + krb5_set_error_message(context, EINVAL, "PAC missing kdc checksum"); return EINVAL; } if (pac->logon_name == NULL) { - krb5_set_error_string(context, "PAC missing logon name"); + krb5_set_error_message(context, EINVAL, "PAC missing logon name"); return EINVAL; } @@ -795,7 +796,7 @@ fill_zeros(krb5_context context, krb5_storage *sp, size_t len) l = sizeof(zeros); sret = krb5_storage_write(sp, zeros, l); if (sret <= 0) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } len -= sret; @@ -823,7 +824,7 @@ pac_checksum(krb5_context context, return ret; if (krb5_checksum_is_keyed(context, cktype) == FALSE) { - krb5_set_error_string(context, "PAC checksum type is not keyed"); + krb5_set_error_message(context, EINVAL, "PAC checksum type is not keyed"); return EINVAL; } @@ -868,7 +869,7 @@ _krb5_pac_sign(krb5_context context, ptr = realloc(p->pac, sizeof(*p->pac) + (sizeof(p->pac->buffers[0]) * (p->pac->numbuffers + num - 1))); if (ptr == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } p->pac = ptr; @@ -906,7 +907,7 @@ _krb5_pac_sign(krb5_context context, /* Encode PAC */ sp = krb5_storage_emem(); if (sp == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE); @@ -914,7 +915,7 @@ _krb5_pac_sign(krb5_context context, spdata = krb5_storage_emem(); if (spdata == NULL) { krb5_storage_free(sp); - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_flags(spdata, KRB5_STORAGE_BYTEORDER_LE); @@ -953,8 +954,8 @@ _krb5_pac_sign(krb5_context context, sret = krb5_storage_write(spdata, ptr, len); if (sret != len) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } /* XXX if not aligned, fill_zeros */ @@ -985,21 +986,21 @@ _krb5_pac_sign(krb5_context context, /* export PAC */ ret = krb5_storage_to_data(spdata, &d); if (ret) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } ret = krb5_storage_write(sp, d.data, d.length); if (ret != d.length) { krb5_data_free(&d); - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } krb5_data_free(&d); ret = krb5_storage_to_data(sp, &d); if (ret) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } diff --git a/source4/heimdal/lib/krb5/padata.c b/source4/heimdal/lib/krb5/padata.c index b2b70f52e7..9dc3fe69a5 100644 --- a/source4/heimdal/lib/krb5/padata.c +++ b/source4/heimdal/lib/krb5/padata.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: padata.c 15469 2005-06-17 04:28:35Z lha $"); +RCSID("$Id: padata.c 23300 2008-06-23 03:29:22Z lha $"); PA_DATA * krb5_find_padata(PA_DATA *val, unsigned len, int type, int *idx) @@ -52,7 +52,7 @@ krb5_padata_add(krb5_context context, METHOD_DATA *md, pa = realloc (md->val, (md->len + 1) * sizeof(*md->val)); if (pa == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } md->val = pa; diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c index 4a585bff07..1e82971c6e 100755 --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c 22673 2008-03-10 15:00:05Z lha $"); +RCSID("$Id: pkinit.c 23450 2008-07-27 12:10:10Z lha $"); struct krb5_dh_moduli { char *name; @@ -45,8 +45,6 @@ struct krb5_dh_moduli { #ifdef PKINIT -#include -#include #include #include #include @@ -56,22 +54,6 @@ struct krb5_dh_moduli { #include -#include - -enum { - COMPAT_WIN2K = 1, - COMPAT_IETF = 2 -}; - -struct krb5_pk_identity { - hx509_context hx509ctx; - hx509_verify_ctx verify_ctx; - hx509_certs certs; - hx509_certs anchors; - hx509_certs certpool; - hx509_revoke_ctx revokectx; -}; - struct krb5_pk_cert { hx509_cert cert; }; @@ -82,7 +64,7 @@ struct krb5_pk_init_ctx_data { krb5_data *clientDHNonce; struct krb5_dh_moduli **m; hx509_peer_info peer; - int type; + enum krb5_pk_type type; unsigned int require_binding:1; unsigned int require_eku:1; unsigned int require_krbtgt_otherName:1; @@ -91,11 +73,11 @@ struct krb5_pk_init_ctx_data { }; static void -_krb5_pk_copy_error(krb5_context context, - hx509_context hx509ctx, - int hxret, - const char *fmt, - ...) +pk_copy_error(krb5_context context, + hx509_context hx509ctx, + int hxret, + const char *fmt, + ...) __attribute__ ((format (printf, 4, 5))); /* @@ -132,7 +114,7 @@ integer_to_BN(krb5_context context, const char *field, const heim_integer *f) bn = BN_bin2bn((const unsigned char *)f->data, f->length, NULL); if (bn == NULL) { - krb5_set_error_string(context, "PKINIT: parsing BN failed %s", field); + krb5_set_error_message(context, ENOMEM, "PKINIT: parsing BN failed %s", field); return NULL; } BN_set_negative(bn, f->negative); @@ -167,16 +149,16 @@ find_cert(krb5_context context, struct krb5_pk_identity *id, for (i = 0; i < sizeof(cf)/sizeof(cf[0]); i++) { ret = hx509_query_match_eku(q, cf[i].oid); if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Failed setting %s OID", cf[i].type); + pk_copy_error(context, id->hx509ctx, ret, + "Failed setting %s OID", cf[i].type); return ret; } ret = hx509_certs_find(id->hx509ctx, id->certs, q, cert); if (ret == 0) break; - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Failed cert for finding %s OID", cf[i].type); + pk_copy_error(context, id->hx509ctx, ret, + "Failed cert for finding %s OID", cf[i].type); } return ret; } @@ -196,8 +178,8 @@ create_signature(krb5_context context, ret = hx509_query_alloc(id->hx509ctx, &q); if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Allocate query to find signing certificate"); + pk_copy_error(context, id->hx509ctx, ret, + "Allocate query to find signing certificate"); return ret; } @@ -222,8 +204,8 @@ create_signature(krb5_context context, sd_data); hx509_cert_free(cert); if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Create CMS signedData"); + pk_copy_error(context, id->hx509ctx, ret, + "Create CMS signedData"); return ret; } @@ -374,7 +356,7 @@ build_auth_pack(krb5_context context, ALLOC(a->pkAuthenticator.paChecksum, 1); if (a->pkAuthenticator.paChecksum == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -524,7 +506,7 @@ pk_mk_padata(krb5_context context, krb5_data_zero(&sd_buf); memset(&content_info, 0, sizeof(content_info)); - if (ctx->type == COMPAT_WIN2K) { + if (ctx->type == PKINIT_WIN2K) { AuthPack_Win2k ap; krb5_timestamp sec; int32_t usec; @@ -554,14 +536,15 @@ pk_mk_padata(krb5_context context, &ap, &size, ret); free_AuthPack_Win2k(&ap); if (ret) { - krb5_set_error_string(context, "AuthPack_Win2k: %d", ret); + krb5_set_error_message(context, ret, "AuthPack_Win2k: %d", + (int)ret); goto out; } if (buf.length != size) krb5_abortx(context, "internal ASN1 encoder error"); oid = oid_id_pkcs7_data(); - } else if (ctx->type == COMPAT_IETF) { + } else if (ctx->type == PKINIT_27) { AuthPack ap; memset(&ap, 0, sizeof(ap)); @@ -575,7 +558,7 @@ pk_mk_padata(krb5_context context, ASN1_MALLOC_ENCODE(AuthPack, buf.data, buf.length, &ap, &size, ret); free_AuthPack(&ap); if (ret) { - krb5_set_error_string(context, "AuthPack: %d", ret); + krb5_set_error_message(context, ret, "AuthPack: %d", (int)ret); goto out; } if (buf.length != size) @@ -594,12 +577,12 @@ pk_mk_padata(krb5_context context, ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &sd_buf, &buf); krb5_data_free(&sd_buf); if (ret) { - krb5_set_error_string(context, - "ContentInfo wrapping of signedData failed"); + krb5_set_error_message(context, ret, + "ContentInfo wrapping of signedData failed"); goto out; } - if (ctx->type == COMPAT_WIN2K) { + if (ctx->type == PKINIT_WIN2K) { PA_PK_AS_REQ_Win2k winreq; pa_type = KRB5_PADATA_PK_AS_REQ_WIN; @@ -612,7 +595,7 @@ pk_mk_padata(krb5_context context, &winreq, &size, ret); free_PA_PK_AS_REQ_Win2k(&winreq); - } else if (ctx->type == COMPAT_IETF) { + } else if (ctx->type == PKINIT_27) { PA_PK_AS_REQ req; pa_type = KRB5_PADATA_PK_AS_REQ; @@ -624,14 +607,15 @@ pk_mk_padata(krb5_context context, req.trustedCertifiers = calloc(1, sizeof(*req.trustedCertifiers)); if (req.trustedCertifiers == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); free_PA_PK_AS_REQ(&req); goto out; } ret = build_edi(context, ctx->id->hx509ctx, ctx->id->anchors, req.trustedCertifiers); if (ret) { - krb5_set_error_string(context, "pk-init: failed to build trustedCertifiers"); + krb5_set_error_message(context, ret, "pk-init: failed to build trustedCertifiers"); free_PA_PK_AS_REQ(&req); goto out; } @@ -646,7 +630,7 @@ pk_mk_padata(krb5_context context, } else krb5_abortx(context, "internal pkinit error"); if (ret) { - krb5_set_error_string(context, "PA-PK-AS-REQ %d", ret); + krb5_set_error_message(context, ret, "PA-PK-AS-REQ %d", (int)ret); goto out; } if (buf.length != size) @@ -656,10 +640,10 @@ pk_mk_padata(krb5_context context, if (ret) free(buf.data); - if (ret == 0 && ctx->type == COMPAT_WIN2K) + if (ret == 0 && ctx->type == PKINIT_WIN2K) krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0); -out: + out: free_ContentInfo(&content_info); return ret; @@ -691,9 +675,9 @@ _krb5_pk_mk_padata(krb5_context context, req_body->realm, "pkinit_win2k_require_binding", NULL); - ctx->type = COMPAT_WIN2K; + ctx->type = PKINIT_WIN2K; } else - ctx->type = COMPAT_IETF; + ctx->type = PKINIT_27; ctx->require_eku = krb5_config_get_bool_default(context, NULL, @@ -753,8 +737,8 @@ _krb5_pk_verify_sign(krb5_context context, content, &signer_certs); if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "CMS verify signed failed"); + pk_copy_error(context, id->hx509ctx, ret, + "CMS verify signed failed"); return ret; } @@ -767,12 +751,12 @@ _krb5_pk_verify_sign(krb5_context context, ret = hx509_get_one_cert(id->hx509ctx, signer_certs, &(*signer)->cert); if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Failed to get on of the signer certs"); + pk_copy_error(context, id->hx509ctx, ret, + "Failed to get on of the signer certs"); goto out; } -out: + out: hx509_certs_free(&signer_certs); if (ret) { if (*signer) { @@ -800,29 +784,28 @@ get_reply_key_win(krb5_context context, &key_pack, &size); if (ret) { - krb5_set_error_string(context, "PKINIT decoding reply key failed"); + krb5_set_error_message(context, ret, "PKINIT decoding reply key failed"); free_ReplyKeyPack_Win2k(&key_pack); return ret; } if (key_pack.nonce != nonce) { - krb5_set_error_string(context, "PKINIT enckey nonce is wrong"); + krb5_set_error_message(context, ret, "PKINIT enckey nonce is wrong"); free_ReplyKeyPack_Win2k(&key_pack); return KRB5KRB_AP_ERR_MODIFIED; } *key = malloc (sizeof (**key)); if (*key == NULL) { - krb5_set_error_string(context, "PKINIT failed allocating reply key"); free_ReplyKeyPack_Win2k(&key_pack); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = copy_EncryptionKey(&key_pack.replyKey, *key); free_ReplyKeyPack_Win2k(&key_pack); if (ret) { - krb5_set_error_string(context, "PKINIT failed copying reply key"); + krb5_set_error_message(context, ret, "PKINIT failed copying reply key"); free(*key); *key = NULL; } @@ -845,7 +828,7 @@ get_reply_key(krb5_context context, &key_pack, &size); if (ret) { - krb5_set_error_string(context, "PKINIT decoding reply key failed"); + krb5_set_error_message(context, ret, "PKINIT decoding reply key failed"); free_ReplyKeyPack(&key_pack); return ret; } @@ -876,16 +859,15 @@ get_reply_key(krb5_context context, *key = malloc (sizeof (**key)); if (*key == NULL) { - krb5_set_error_string(context, "PKINIT failed allocating reply key"); free_ReplyKeyPack(&key_pack); - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = copy_EncryptionKey(&key_pack.replyKey, *key); free_ReplyKeyPack(&key_pack); if (ret) { - krb5_set_error_string(context, "PKINIT failed copying reply key"); + krb5_set_error_message(context, ret, "PKINIT failed copying reply key"); free(*key); *key = NULL; } @@ -907,7 +889,7 @@ pk_verify_host(krb5_context context, ret = hx509_cert_check_eku(ctx->id->hx509ctx, host->cert, oid_id_pkkdcekuoid(), 0); if (ret) { - krb5_set_error_string(context, "No PK-INIT KDC EKU in kdc certificate"); + krb5_set_error_message(context, ret, "No PK-INIT KDC EKU in kdc certificate"); return ret; } } @@ -920,8 +902,8 @@ pk_verify_host(krb5_context context, oid_id_pkinit_san(), &list); if (ret) { - krb5_set_error_string(context, "Failed to find the PK-INIT " - "subjectAltName in the KDC certificate"); + krb5_set_error_message(context, ret, "Failed to find the PK-INIT " + "subjectAltName in the KDC certificate"); return ret; } @@ -934,8 +916,8 @@ pk_verify_host(krb5_context context, &r, NULL); if (ret) { - krb5_set_error_string(context, "Failed to decode the PK-INIT " - "subjectAltName in the KDC certificate"); + krb5_set_error_message(context, ret, "Failed to decode the PK-INIT " + "subjectAltName in the KDC certificate"); break; } @@ -944,11 +926,11 @@ pk_verify_host(krb5_context context, strcmp(r.principalName.name_string.val[0], KRB5_TGS_NAME) != 0 || strcmp(r.principalName.name_string.val[1], realm) != 0 || strcmp(r.realm, realm) != 0) - { - krb5_set_error_string(context, "KDC have wrong realm name in " - "the certificate"); - ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; - } + { + ret = KRB5_KDC_ERR_INVALID_CERTIFICATE; + krb5_set_error_message(context, ret, "KDC have wrong realm name in " + "the certificate"); + } free_KRB5PrincipalName(&r); if (ret) @@ -967,8 +949,8 @@ pk_verify_host(krb5_context context, hi->ai->ai_addr, hi->ai->ai_addrlen); if (ret) - krb5_set_error_string(context, "Address mismatch in " - "the KDC certificate"); + krb5_set_error_message(context, ret, "Address mismatch in " + "the KDC certificate"); } return ret; } @@ -993,7 +975,7 @@ pk_rd_pa_reply_enckey(krb5_context context, heim_oid contentType = { 0, NULL }; if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), dataType)) { - krb5_set_error_string(context, "PKINIT: Invalid content type"); + krb5_set_error_message(context, EINVAL, "PKINIT: Invalid content type"); return EINVAL; } @@ -1003,11 +985,12 @@ pk_rd_pa_reply_enckey(krb5_context context, indata->data, indata->length, NULL, + 0, &contentType, &content); if (ret) { - _krb5_pk_copy_error(context, ctx->id->hx509ctx, ret, - "Failed to unenvelope CMS data in PK-INIT reply"); + pk_copy_error(context, ctx->id->hx509ctx, ret, + "Failed to unenvelope CMS data in PK-INIT reply"); return ret; } der_free_oid(&contentType); @@ -1031,14 +1014,14 @@ pk_rd_pa_reply_enckey(krb5_context context, #endif /* win2k uses ContentInfo */ - if (type == COMPAT_WIN2K) { + if (type == PKINIT_WIN2K) { heim_oid type; heim_octet_string out; ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL); if (der_heim_oid_cmp(&type, oid_id_pkcs7_signedData())) { ret = EINVAL; /* XXX */ - krb5_set_error_string(context, "PKINIT: Invalid content type"); + krb5_set_error_message(context, ret, "PKINIT: Invalid content type"); der_free_oid(&type); der_free_octet_string(&out); goto out; @@ -1048,7 +1031,7 @@ pk_rd_pa_reply_enckey(krb5_context context, ret = krb5_data_copy(&content, out.data, out.length); der_free_octet_string(&out); if (ret) { - krb5_set_error_string(context, "PKINIT: out of memory"); + krb5_set_error_message(context, ret, "PKINIT: out of memory"); goto out; } } @@ -1070,28 +1053,28 @@ pk_rd_pa_reply_enckey(krb5_context context, } #if 0 - if (type == COMPAT_WIN2K) { + if (type == PKINIT_WIN2K) { if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) { - krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; + krb5_set_error_message(context, ret, "PKINIT: reply key, wrong oid"); goto out; } } else { if (der_heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) { - krb5_set_error_string(context, "PKINIT: reply key, wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; + krb5_set_error_message(context, ret, "PKINIT: reply key, wrong oid"); goto out; } } #endif switch(type) { - case COMPAT_WIN2K: + case PKINIT_WIN2K: ret = get_reply_key(context, &content, req_buffer, key); if (ret != 0 && ctx->require_binding == 0) ret = get_reply_key_win(context, &content, nonce, key); break; - case COMPAT_IETF: + case PKINIT_27: ret = get_reply_key(context, &content, req_buffer, key); break; } @@ -1137,7 +1120,7 @@ pk_rd_pa_reply_dh(krb5_context context, memset(&kdc_dh_info, 0, sizeof(kdc_dh_info)); if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), dataType)) { - krb5_set_error_string(context, "PKINIT: Invalid content type"); + krb5_set_error_message(context, EINVAL, "PKINIT: Invalid content type"); return EINVAL; } @@ -1157,8 +1140,8 @@ pk_rd_pa_reply_dh(krb5_context context, goto out; if (der_heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) { - krb5_set_error_string(context, "pkinit - dh reply contains wrong oid"); ret = KRB5KRB_AP_ERR_MSG_TYPE; + krb5_set_error_message(context, ret, "pkinit - dh reply contains wrong oid"); goto out; } @@ -1168,35 +1151,35 @@ pk_rd_pa_reply_dh(krb5_context context, &size); if (ret) { - krb5_set_error_string(context, "pkinit - " - "failed to decode KDC DH Key Info"); + krb5_set_error_message(context, ret, "pkinit - " + "failed to decode KDC DH Key Info"); goto out; } if (kdc_dh_info.nonce != nonce) { - krb5_set_error_string(context, "PKINIT: DH nonce is wrong"); ret = KRB5KRB_AP_ERR_MODIFIED; + krb5_set_error_message(context, ret, "PKINIT: DH nonce is wrong"); goto out; } if (kdc_dh_info.dhKeyExpiration) { if (k_n == NULL) { - krb5_set_error_string(context, "pkinit; got key expiration " - "without server nonce"); ret = KRB5KRB_ERR_GENERIC; + krb5_set_error_message(context, ret, "pkinit; got key expiration " + "without server nonce"); goto out; } if (c_n == NULL) { - krb5_set_error_string(context, "pkinit; got DH reuse but no " - "client nonce"); ret = KRB5KRB_ERR_GENERIC; + krb5_set_error_message(context, ret, "pkinit; got DH reuse but no " + "client nonce"); goto out; } } else { if (k_n) { - krb5_set_error_string(context, "pkinit: got server nonce " - "without key expiration"); ret = KRB5KRB_ERR_GENERIC; + krb5_set_error_message(context, ret, "pkinit: got server nonce " + "without key expiration"); goto out; } c_n = NULL; @@ -1210,15 +1193,15 @@ pk_rd_pa_reply_dh(krb5_context context, DHPublicKey k; ret = decode_DHPublicKey(p, size, &k, NULL); if (ret) { - krb5_set_error_string(context, "pkinit: can't decode " - "without key expiration"); + krb5_set_error_message(context, ret, "pkinit: can't decode " + "without key expiration"); goto out; } kdc_dh_pubkey = integer_to_BN(context, "DHPublicKey", &k); free_DHPublicKey(&k); if (kdc_dh_pubkey == NULL) { - ret = KRB5KRB_ERR_GENERIC; + ret = ENOMEM; goto out; } } @@ -1230,8 +1213,8 @@ pk_rd_pa_reply_dh(krb5_context context, dh_gen_key = malloc(size); if (dh_gen_key == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } memset(dh_gen_key, 0, size - dh_gen_keylen); @@ -1239,16 +1222,16 @@ pk_rd_pa_reply_dh(krb5_context context, dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen), kdc_dh_pubkey, ctx->dh); if (dh_gen_keylen == -1) { - krb5_set_error_string(context, - "PKINIT: Can't compute Diffie-Hellman key"); ret = KRB5KRB_ERR_GENERIC; + krb5_set_error_message(context, ret, + "PKINIT: Can't compute Diffie-Hellman key"); goto out; } *key = malloc (sizeof (**key)); if (*key == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } @@ -1258,8 +1241,8 @@ pk_rd_pa_reply_dh(krb5_context context, c_n, k_n, *key); if (ret) { - krb5_set_error_string(context, - "PKINIT: can't create key from DH key"); + krb5_set_error_message(context, ret, + "PKINIT: can't create key from DH key"); free(*key); *key = NULL; goto out; @@ -1298,13 +1281,13 @@ _krb5_pk_rd_pa_reply(krb5_context context, size_t size; /* Check for IETF PK-INIT first */ - if (ctx->type == COMPAT_IETF) { + if (ctx->type == PKINIT_27) { PA_PK_AS_REP rep; heim_octet_string os, data; heim_oid oid; if (pa->padata_type != KRB5_PADATA_PK_AS_REP) { - krb5_set_error_string(context, "PKINIT: wrong padata recv"); + krb5_set_error_message(context, EINVAL, "PKINIT: wrong padata recv"); return EINVAL; } @@ -1313,7 +1296,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, &rep, &size); if (ret) { - krb5_set_error_string(context, "Failed to decode pkinit AS rep"); + krb5_set_error_message(context, ret, "Failed to decode pkinit AS rep"); return ret; } @@ -1326,15 +1309,15 @@ _krb5_pk_rd_pa_reply(krb5_context context, break; default: free_PA_PK_AS_REP(&rep); - krb5_set_error_string(context, "PKINIT: -27 reply " - "invalid content type"); + krb5_set_error_message(context, EINVAL, "PKINIT: -27 reply " + "invalid content type"); return EINVAL; } ret = hx509_cms_unwrap_ContentInfo(&os, &oid, &data, NULL); if (ret) { free_PA_PK_AS_REP(&rep); - krb5_set_error_string(context, "PKINIT: failed to unwrap CI"); + krb5_set_error_message(context, ret, "PKINIT: failed to unwrap CI"); return ret; } @@ -1346,7 +1329,7 @@ _krb5_pk_rd_pa_reply(krb5_context context, nonce, pa, key); break; case choice_PA_PK_AS_REP_encKeyPack: - ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &data, &oid, realm, + ret = pk_rd_pa_reply_enckey(context, PKINIT_27, &data, &oid, realm, ctx, etype, hi, nonce, req_buffer, pa, key); break; default: @@ -1356,14 +1339,14 @@ _krb5_pk_rd_pa_reply(krb5_context context, der_free_oid(&oid); free_PA_PK_AS_REP(&rep); - } else if (ctx->type == COMPAT_WIN2K) { + } else if (ctx->type == PKINIT_WIN2K) { PA_PK_AS_REP_Win2k w2krep; /* Check for Windows encoding of the AS-REP pa data */ #if 0 /* should this be ? */ if (pa->padata_type != KRB5_PADATA_PK_AS_REP) { - krb5_set_error_string(context, "PKINIT: wrong padata recv"); + krb5_set_error_message(context, EINVAL, "PKINIT: wrong padata recv"); return EINVAL; } #endif @@ -1375,8 +1358,8 @@ _krb5_pk_rd_pa_reply(krb5_context context, &w2krep, &size); if (ret) { - krb5_set_error_string(context, "PKINIT: Failed decoding windows " - "pkinit reply %d", ret); + krb5_set_error_message(context, ret, "PKINIT: Failed decoding windows " + "pkinit reply %d", (int)ret); return ret; } @@ -1391,11 +1374,11 @@ _krb5_pk_rd_pa_reply(krb5_context context, &oid, &data, NULL); free_PA_PK_AS_REP_Win2k(&w2krep); if (ret) { - krb5_set_error_string(context, "PKINIT: failed to unwrap CI"); + krb5_set_error_message(context, ret, "PKINIT: failed to unwrap CI"); return ret; } - ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &data, &oid, realm, + ret = pk_rd_pa_reply_enckey(context, PKINIT_WIN2K, &data, &oid, realm, ctx, etype, hi, nonce, req_buffer, pa, key); der_free_octet_string(&data); der_free_oid(&oid); @@ -1404,15 +1387,15 @@ _krb5_pk_rd_pa_reply(krb5_context context, } default: free_PA_PK_AS_REP_Win2k(&w2krep); - krb5_set_error_string(context, "PKINIT: win2k reply invalid " - "content type"); ret = EINVAL; + krb5_set_error_message(context, ret, "PKINIT: win2k reply invalid " + "content type"); break; } } else { - krb5_set_error_string(context, "PKINIT: unknown reply type"); ret = EINVAL; + krb5_set_error_message(context, ret, "PKINIT: unknown reply type"); } return ret; @@ -1486,13 +1469,14 @@ _krb5_pk_load_id(krb5_context context, *ret_id = NULL; if (anchor_id == NULL) { - krb5_set_error_string(context, "PKINIT: No anchor given"); + krb5_set_error_message(context, HEIM_PKINIT_NO_VALID_CA, + "PKINIT: No anchor given"); return HEIM_PKINIT_NO_VALID_CA; } if (user_id == NULL) { - krb5_set_error_string(context, - "PKINIT: No user certificate given"); + krb5_set_error_message(context, HEIM_PKINIT_NO_PRIVATE_KEY, + "PKINIT: No user certificate given"); return HEIM_PKINIT_NO_PRIVATE_KEY; } @@ -1500,7 +1484,7 @@ _krb5_pk_load_id(krb5_context context, id = calloc(1, sizeof(*id)); if (id == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -1524,23 +1508,23 @@ _krb5_pk_load_id(krb5_context context, ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs); if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Failed to init cert certs"); + pk_copy_error(context, id->hx509ctx, ret, + "Failed to init cert certs"); goto out; } ret = hx509_certs_init(id->hx509ctx, anchor_id, 0, NULL, &id->anchors); if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Failed to init anchors"); + pk_copy_error(context, id->hx509ctx, ret, + "Failed to init anchors"); goto out; } ret = hx509_certs_init(id->hx509ctx, "MEMORY:pkinit-cert-chain", 0, NULL, &id->certpool); if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Failed to init chain"); + pk_copy_error(context, id->hx509ctx, ret, + "Failed to init chain"); goto out; } @@ -1548,9 +1532,9 @@ _krb5_pk_load_id(krb5_context context, ret = hx509_certs_append(id->hx509ctx, id->certpool, NULL, *chain_list); if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Failed to laod chain %s", - *chain_list); + pk_copy_error(context, id->hx509ctx, ret, + "Failed to laod chain %s", + *chain_list); goto out; } chain_list++; @@ -1559,8 +1543,8 @@ _krb5_pk_load_id(krb5_context context, if (revoke_list) { ret = hx509_revoke_init(id->hx509ctx, &id->revokectx); if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Failed init revoke list"); + pk_copy_error(context, id->hx509ctx, ret, + "Failed init revoke list"); goto out; } @@ -1569,8 +1553,8 @@ _krb5_pk_load_id(krb5_context context, id->revokectx, *revoke_list); if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Failed load revoke list"); + pk_copy_error(context, id->hx509ctx, ret, + "Failed load revoke list"); goto out; } revoke_list++; @@ -1580,15 +1564,15 @@ _krb5_pk_load_id(krb5_context context, ret = hx509_verify_init_ctx(id->hx509ctx, &id->verify_ctx); if (ret) { - _krb5_pk_copy_error(context, id->hx509ctx, ret, - "Failed init verify context"); + pk_copy_error(context, id->hx509ctx, ret, + "Failed init verify context"); goto out; } hx509_verify_attach_anchors(id->verify_ctx, id->anchors); hx509_verify_attach_revoke(id->verify_ctx, id->revokectx); -out: + out: if (ret) { hx509_verify_destroy_ctx(id->verify_ctx); hx509_certs_free(&id->certs); @@ -1622,10 +1606,10 @@ select_dh_group(krb5_context context, DH *dh, unsigned long bits, break; } if (moduli[i] == NULL) { - krb5_set_error_string(context, - "Did not find a DH group parameter " - "matching requirement of %lu bits", - bits); + krb5_set_error_message(context, EINVAL, + "Did not find a DH group parameter " + "matching requirement of %lu bits", + bits); return EINVAL; } m = moduli[i]; @@ -1644,6 +1628,39 @@ select_dh_group(krb5_context context, DH *dh, unsigned long bits, return 0; } +/* + * + */ + +static void +pk_copy_error(krb5_context context, + hx509_context hx509ctx, + int hxret, + const char *fmt, + ...) +{ + va_list va; + char *s, *f; + + va_start(va, fmt); + vasprintf(&f, fmt, va); + va_end(va); + if (f == NULL) { + krb5_clear_error_string(context); + return; + } + + s = hx509_get_error_string(hx509ctx, hxret); + if (s == NULL) { + krb5_clear_error_string(context); + free(f); + return; + } + krb5_set_error_message(context, hxret, "%s: %s", f, s); + free(s); + free(f); +} + #endif /* PKINIT */ static int @@ -1654,15 +1671,15 @@ parse_integer(krb5_context context, char **p, const char *file, int lineno, char *p1; p1 = strsep(p, " \t"); if (p1 == NULL) { - krb5_set_error_string(context, "moduli file %s missing %s on line %d", - file, name, lineno); + krb5_set_error_message(context, EINVAL, "moduli file %s missing %s on line %d", + file, name, lineno); return EINVAL; } ret = der_parse_hex_heim_integer(p1, integer); if (ret) { - krb5_set_error_string(context, "moduli file %s failed parsing %s " - "on line %d", - file, name, lineno); + krb5_set_error_message(context, ret, "moduli file %s failed parsing %s " + "on line %d", + file, name, lineno); return ret; } @@ -1684,7 +1701,7 @@ _krb5_parse_moduli_line(krb5_context context, m1 = calloc(1, sizeof(*m1)); if (m1 == NULL) { - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -1696,28 +1713,28 @@ _krb5_parse_moduli_line(krb5_context context, p1 = strsep(&p, " \t"); if (p1 == NULL) { - krb5_set_error_string(context, "moduli file %s missing name " - "on line %d", file, lineno); + krb5_set_error_message(context, ret, "moduli file %s missing name " + "on line %d", file, lineno); goto out; } m1->name = strdup(p1); if (p1 == NULL) { - krb5_set_error_string(context, "malloc - out of memeory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc - out of memeory"); goto out; } p1 = strsep(&p, " \t"); if (p1 == NULL) { - krb5_set_error_string(context, "moduli file %s missing bits on line %d", - file, lineno); + krb5_set_error_message(context, ret, "moduli file %s missing bits on line %d", + file, lineno); goto out; } m1->bits = atoi(p1); if (m1->bits == 0) { - krb5_set_error_string(context, "moduli file %s have un-parsable " - "bits on line %d", file, lineno); + krb5_set_error_message(context, ret, "moduli file %s have un-parsable " + "bits on line %d", file, lineno); goto out; } @@ -1734,7 +1751,7 @@ _krb5_parse_moduli_line(krb5_context context, *m = m1; return 0; -out: + out: free(m1->name); der_free_heim_integer(&m1->p); der_free_heim_integer(&m1->g); @@ -1826,7 +1843,7 @@ _krb5_parse_moduli(krb5_context context, const char *file, m = calloc(1, sizeof(m[0]) * 3); if (m == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -1855,6 +1872,7 @@ _krb5_parse_moduli(krb5_context context, const char *file, *moduli = m; return 0; } + rk_cloexec_file(f); while(fgets(buf, sizeof(buf), f) != NULL) { struct krb5_dh_moduli *element; @@ -1864,8 +1882,8 @@ _krb5_parse_moduli(krb5_context context, const char *file, m2 = realloc(m, (n + 2) * sizeof(m[0])); if (m2 == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); _krb5_free_moduli(m); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } m = m2; @@ -1903,19 +1921,23 @@ _krb5_dh_group_ok(krb5_context context, unsigned long bits, if (der_heim_integer_cmp(&moduli[i]->g, g) == 0 && der_heim_integer_cmp(&moduli[i]->p, p) == 0 && (q == NULL || der_heim_integer_cmp(&moduli[i]->q, q) == 0)) - { - if (bits && bits > moduli[i]->bits) { - krb5_set_error_string(context, "PKINIT: DH group parameter %s " - "no accepted, not enough bits generated", - moduli[i]->name); - return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + { + if (bits && bits > moduli[i]->bits) { + krb5_set_error_message(context, + KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED, + "PKINIT: DH group parameter %s " + "no accepted, not enough bits generated", + moduli[i]->name); + return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; + } + if (name) + *name = strdup(moduli[i]->name); + return 0; } - if (name) - *name = strdup(moduli[i]->name); - return 0; - } } - krb5_set_error_string(context, "PKINIT: DH group parameter no ok"); + krb5_set_error_message(context, + KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED, + "PKINIT: DH group parameter no ok"); return KRB5_KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED; } @@ -1930,7 +1952,7 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt) ctx = opt->opt_private->pk_init_ctx; if (ctx->dh) DH_free(ctx->dh); - ctx->dh = NULL; + ctx->dh = NULL; if (ctx->id) { hx509_verify_destroy_ctx(ctx->id->verify_ctx); hx509_certs_free(&ctx->id->certs); @@ -1970,14 +1992,14 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, char *anchors = NULL; if (opt->opt_private == NULL) { - krb5_set_error_string(context, "PKINIT: on non extendable opt"); + krb5_set_error_message(context, EINVAL, "PKINIT: on non extendable opt"); return EINVAL; } opt->opt_private->pk_init_ctx = calloc(1, sizeof(*opt->opt_private->pk_init_ctx)); if (opt->opt_private->pk_init_ctx == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } opt->opt_private->pk_init_ctx->dh = NULL; @@ -2047,8 +2069,8 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, opt->opt_private->pk_init_ctx->dh = DH_new(); if (opt->opt_private->pk_init_ctx->dh == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); _krb5_get_init_creds_opt_free_pkinit(opt); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -2061,48 +2083,15 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context, } if (DH_generate_key(opt->opt_private->pk_init_ctx->dh) != 1) { - krb5_set_error_string(context, "pkinit: failed to generate DH key"); _krb5_get_init_creds_opt_free_pkinit(opt); + krb5_set_error_message(context, ENOMEM, "pkinit: failed to generate DH key"); return ENOMEM; } } return 0; #else - krb5_set_error_string(context, "no support for PKINIT compiled in"); + krb5_set_error_message(context, EINVAL, "no support for PKINIT compiled in"); return EINVAL; #endif } - -/* - * - */ - -static void -_krb5_pk_copy_error(krb5_context context, - hx509_context hx509ctx, - int hxret, - const char *fmt, - ...) -{ - va_list va; - char *s, *f; - - va_start(va, fmt); - vasprintf(&f, fmt, va); - va_end(va); - if (f == NULL) { - krb5_clear_error_string(context); - return; - } - - s = hx509_get_error_string(hx509ctx, hxret); - if (s == NULL) { - krb5_clear_error_string(context); - free(f); - return; - } - krb5_set_error_string(context, "%s: %s", f, s); - free(s); - free(f); -} diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c index bae28496aa..8dda27fa59 100644 --- a/source4/heimdal/lib/krb5/plugin.c +++ b/source4/heimdal/lib/krb5/plugin.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: plugin.c 22033 2007-11-10 10:39:47Z lha $"); +RCSID("$Id: plugin.c 23451 2008-07-27 12:10:30Z lha $"); #ifdef HAVE_DLFCN_H #include #endif @@ -87,7 +87,7 @@ loadlib(krb5_context context, { *e = calloc(1, sizeof(**e)); if (*e == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -99,8 +99,8 @@ loadlib(krb5_context context, if ((*e)->dsohandle == NULL) { free(*e); *e = NULL; - krb5_set_error_string(context, "Failed to load %s: %s", - lib, dlerror()); + krb5_set_error_message(context, ENOMEM, "Failed to load %s: %s", + lib, dlerror()); return ENOMEM; } @@ -139,14 +139,14 @@ krb5_plugin_register(krb5_context context, e = calloc(1, sizeof(*e)); if (e == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } e->type = type; e->name = strdup(name); if (e->name == NULL) { free(e); - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } e->symbol = symbol; @@ -185,8 +185,8 @@ _krb5_plugin_find(krb5_context context, e = calloc(1, sizeof(*e)); if (e == NULL) { HEIMDAL_MUTEX_unlock(&plugin_mutex); - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } e->symbol = p->symbol; @@ -210,12 +210,13 @@ _krb5_plugin_find(krb5_context context, d = opendir(*di); if (d == NULL) continue; + rk_cloexec(dirfd(d)); while ((entry = readdir(d)) != NULL) { asprintf(&path, "%s/%s", *di, entry->d_name); if (path == NULL) { - krb5_set_error_string(context, "out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } ret = loadlib(context, type, name, path, &e); @@ -233,7 +234,7 @@ _krb5_plugin_find(krb5_context context, #endif /* HAVE_DLOPEN */ if (*list == NULL) { - krb5_set_error_string(context, "Did not find a plugin for %s", name); + krb5_set_error_message(context, ENOENT, "Did not find a plugin for %s", name); return ENOENT; } diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index cdad477115..0d6d72dbcf 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -57,7 +57,7 @@ host/admin@H5L.ORG #include #include "resolve.h" -RCSID("$Id: principal.c 22549 2008-01-29 09:37:25Z lha $"); +RCSID("$Id: principal.c 23316 2008-06-23 04:32:32Z lha $"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -149,8 +149,9 @@ krb5_parse_name_flags(krb5_context context, #define RFLAGS (KRB5_PRINCIPAL_PARSE_NO_REALM|KRB5_PRINCIPAL_PARSE_MUST_REALM) if ((flags & RFLAGS) == RFLAGS) { - krb5_set_error_string(context, "Can't require both realm and " - "no realm at the same time"); + krb5_set_error_message(context, KRB5_ERR_NO_SERVICE, + "Can't require both realm and " + "no realm at the same time"); return KRB5_ERR_NO_SERVICE; } #undef RFLAGS @@ -163,7 +164,7 @@ krb5_parse_name_flags(krb5_context context, for(p = name; *p; p++){ if(*p=='\\'){ if(!p[1]) { - krb5_set_error_string (context, + krb5_set_error_message(context, KRB5_PARSE_MALFORMED, "trailing \\ in principal name"); return KRB5_PARSE_MALFORMED; } @@ -176,7 +177,7 @@ krb5_parse_name_flags(krb5_context context, } comp = calloc(ncomp, sizeof(*comp)); if (comp == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -184,7 +185,7 @@ krb5_parse_name_flags(krb5_context context, p = start = q = s = strdup(name); if (start == NULL) { free (comp); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } while(*p){ @@ -200,9 +201,9 @@ krb5_parse_name_flags(krb5_context context, else if(c == '0') c = '\0'; else if(c == '\0') { - krb5_set_error_string (context, - "trailing \\ in principal name"); ret = KRB5_PARSE_MALFORMED; + krb5_set_error_message(context, ret, + "trailing \\ in principal name"); goto exit; } }else if(enterprise && first_at) { @@ -210,15 +211,15 @@ krb5_parse_name_flags(krb5_context context, first_at = 0; }else if((c == '/' && !enterprise) || c == '@'){ if(got_realm){ - krb5_set_error_string (context, - "part after realm in principal name"); ret = KRB5_PARSE_MALFORMED; + krb5_set_error_message(context, ret, + "part after realm in principal name"); goto exit; }else{ comp[n] = malloc(q - start + 1); if (comp[n] == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto exit; } memcpy(comp[n], start, q - start); @@ -231,33 +232,33 @@ krb5_parse_name_flags(krb5_context context, continue; } if(got_realm && (c == ':' || c == '/' || c == '\0')) { - krb5_set_error_string (context, - "part after realm in principal name"); ret = KRB5_PARSE_MALFORMED; + krb5_set_error_message(context, ret, + "part after realm in principal name"); goto exit; } *q++ = c; } if(got_realm){ if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { - krb5_set_error_string (context, "realm found in 'short' principal " - "expected to be without one"); ret = KRB5_PARSE_MALFORMED; + krb5_set_error_message(context, ret, "realm found in 'short' principal " + "expected to be without one"); goto exit; } realm = malloc(q - start + 1); if (realm == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto exit; } memcpy(realm, start, q - start); realm[q - start] = 0; }else{ if (flags & KRB5_PRINCIPAL_PARSE_MUST_REALM) { - krb5_set_error_string (context, "realm NOT found in principal " - "expected to be with one"); ret = KRB5_PARSE_MALFORMED; + krb5_set_error_message(context, ret, "realm NOT found in principal " + "expected to be with one"); goto exit; } else if (flags & KRB5_PRINCIPAL_PARSE_NO_REALM) { realm = NULL; @@ -269,8 +270,8 @@ krb5_parse_name_flags(krb5_context context, comp[n] = malloc(q - start + 1); if (comp[n] == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto exit; } memcpy(comp[n], start, q - start); @@ -279,8 +280,8 @@ krb5_parse_name_flags(krb5_context context, } *principal = malloc(sizeof(**principal)); if (*principal == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); ret = ENOMEM; + krb5_set_error_message(context, ret, "malloc: out of memory"); goto exit; } if (enterprise) @@ -350,7 +351,8 @@ unparse_name_fixed(krb5_context context, int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0; if (!no_realm && princ_realm(principal) == NULL) { - krb5_set_error_string(context, "Realm missing from principal, " + krb5_set_error_message(context, ERANGE, + "Realm missing from principal, " "can't unparse"); return ERANGE; } @@ -360,7 +362,7 @@ unparse_name_fixed(krb5_context context, add_char(name, idx, len, '/'); idx = quote_string(princ_ncomp(principal, i), name, idx, len, display); if(idx == len) { - krb5_set_error_string(context, "Out of space printing principal"); + krb5_set_error_message(context, ERANGE, "Out of space printing principal"); return ERANGE; } } @@ -379,8 +381,8 @@ unparse_name_fixed(krb5_context context, add_char(name, idx, len, '@'); idx = quote_string(princ_realm(principal), name, idx, len, display); if(idx == len) { - krb5_set_error_string(context, - "Out of space printing realm of principal"); + krb5_set_error_message(context, ERANGE, + "Out of space printing realm of principal"); return ERANGE; } } @@ -446,7 +448,7 @@ unparse_name(krb5_context context, len++; /* '\0' */ *name = malloc(len); if(*name == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } ret = unparse_name_fixed(context, principal, *name, len, flags); @@ -511,6 +513,22 @@ krb5_princ_set_realm(krb5_context context, princ_realm(principal) = *realm; } +krb5_error_code KRB5_LIB_FUNCTION +krb5_principal_set_realm(krb5_context context, + krb5_principal principal, + krb5_const_realm realm) +{ + if (princ_realm(principal)) + free(princ_realm(principal)); + + princ_realm(principal) = strdup(realm); + if (princ_realm(principal) == NULL) { + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); + return ENOMEM; + } + return 0; +} + krb5_error_code KRB5_LIB_FUNCTION krb5_build_principal(krb5_context context, @@ -537,13 +555,13 @@ append_component(krb5_context context, krb5_principal p, tmp = realloc(princ_comp(p), (len + 1) * sizeof(*tmp)); if(tmp == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } princ_comp(p) = tmp; princ_ncomp(p, len) = malloc(comp_len + 1); if (princ_ncomp(p, len) == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy (princ_ncomp(p, len), comp, comp_len); @@ -591,7 +609,7 @@ build_principal(krb5_context context, p = calloc(1, sizeof(*p)); if (p == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } princ_type(p) = KRB5_NT_PRINCIPAL; @@ -599,7 +617,7 @@ build_principal(krb5_context context, princ_realm(p) = strdup(realm); if(p->realm == NULL){ free(p); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -675,12 +693,12 @@ krb5_copy_principal(krb5_context context, { krb5_principal p = malloc(sizeof(*p)); if (p == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } if(copy_Principal(inprinc, p)) { free(p); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } *outprinc = p; @@ -706,6 +724,22 @@ krb5_principal_compare_any_realm(krb5_context context, return TRUE; } +krb5_boolean KRB5_LIB_FUNCTION +_krb5_principal_compare_PrincipalName(krb5_context context, + krb5_const_principal princ1, + PrincipalName *princ2) +{ + int i; + if (princ_num_comp(princ1) != princ2->name_string.len) + return FALSE; + for(i = 0; i < princ_num_comp(princ1); i++){ + if(strcmp(princ_ncomp(princ1, i), princ2->name_string.val[i]) != 0) + return FALSE; + } + return TRUE; +} + + /* * return TRUE iff princ1 == princ2 */ @@ -909,7 +943,7 @@ krb5_425_conv_principal_ext2(krb5_context context, #endif if (passed) { if (inst == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } strlwr(inst); @@ -1160,7 +1194,7 @@ krb5_524_conv_principal(krb5_context context, i = principal->name.name_string.val[1]; break; default: - krb5_set_error_string (context, + krb5_set_error_message(context, KRB5_PARSE_MALFORMED, "cannot convert a %d component principal", principal->name.name_string.len); return KRB5_PARSE_MALFORMED; @@ -1186,17 +1220,17 @@ krb5_524_conv_principal(krb5_context context, } if (strlcpy (name, n, aname_sz) >= aname_sz) { - krb5_set_error_string (context, + krb5_set_error_message(context, KRB5_PARSE_MALFORMED, "too long name component to convert"); return KRB5_PARSE_MALFORMED; } if (strlcpy (instance, i, aname_sz) >= aname_sz) { - krb5_set_error_string (context, + krb5_set_error_message(context, KRB5_PARSE_MALFORMED, "too long instance component to convert"); return KRB5_PARSE_MALFORMED; } if (strlcpy (realm, r, aname_sz) >= aname_sz) { - krb5_set_error_string (context, + krb5_set_error_message(context, KRB5_PARSE_MALFORMED, "too long realm component to convert"); return KRB5_PARSE_MALFORMED; } @@ -1219,8 +1253,9 @@ krb5_sname_to_principal (krb5_context context, char **realms, *host = NULL; if(type != KRB5_NT_SRV_HST && type != KRB5_NT_UNKNOWN) { - krb5_set_error_string (context, "unsupported name type %d", - type); + krb5_set_error_message(context, KRB5_SNAME_UNSUPP_NAMETYPE, + "unsupported name type %d", + (int)type); return KRB5_SNAME_UNSUPP_NAMETYPE; } if(hostname == NULL) { @@ -1280,6 +1315,7 @@ krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype) return 0; } } - krb5_set_error_string(context, "Failed to find name type %s", str); + krb5_set_error_message(context, KRB5_PARSE_MALFORMED, + "Failed to find name type %s", str); return KRB5_PARSE_MALFORMED; } diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c index c3f732201f..26aa3f2d79 100644 --- a/source4/heimdal/lib/krb5/rd_cred.c +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_cred.c 20304 2007-04-11 11:15:05Z lha $"); +RCSID("$Id: rd_cred.c 23316 2008-06-23 04:32:32Z lha $"); static krb5_error_code compare_addrs(krb5_context context, @@ -49,7 +49,8 @@ compare_addrs(krb5_context context, krb5_print_address (a, a_str, sizeof(a_str), &len); krb5_print_address (b, b_str, sizeof(b_str), &len); - krb5_set_error_string(context, "%s: %s != %s", message, b_str, a_str); + krb5_set_error_message(context, KRB5KRB_AP_ERR_BADADDR, + "%s: %s != %s", message, b_str, a_str); return KRB5KRB_AP_ERR_BADADDR; } @@ -244,7 +245,7 @@ krb5_rd_cred(krb5_context context, if (*ret_creds == NULL) { ret = ENOMEM; - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } @@ -255,7 +256,7 @@ krb5_rd_cred(krb5_context context, creds = calloc(1, sizeof(*creds)); if(creds == NULL) { ret = ENOMEM; - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } diff --git a/source4/heimdal/lib/krb5/rd_error.c b/source4/heimdal/lib/krb5/rd_error.c index e7646467af..9e50af539a 100644 --- a/source4/heimdal/lib/krb5/rd_error.c +++ b/source4/heimdal/lib/krb5/rd_error.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: rd_error.c 21057 2007-06-12 17:22:31Z lha $"); +RCSID("$Id: rd_error.c 23316 2008-06-23 04:32:32Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_error(krb5_context context, @@ -78,7 +78,7 @@ krb5_error_from_rd_error(krb5_context context, ret = error->error_code; if (error->e_text != NULL) { - krb5_set_error_string(context, "%s", *error->e_text); + krb5_set_error_message(context, ret, "%s", *error->e_text); } else { char clientname[256], servername[256]; @@ -91,28 +91,28 @@ krb5_error_from_rd_error(krb5_context context, switch (ret) { case KRB5KDC_ERR_NAME_EXP : - krb5_set_error_string(context, "Client %s%s%s expired", - creds ? "(" : "", - creds ? clientname : "", - creds ? ")" : ""); + krb5_set_error_message(context, ret, "Client %s%s%s expired", + creds ? "(" : "", + creds ? clientname : "", + creds ? ")" : ""); break; case KRB5KDC_ERR_SERVICE_EXP : - krb5_set_error_string(context, "Server %s%s%s expired", - creds ? "(" : "", - creds ? servername : "", - creds ? ")" : ""); + krb5_set_error_message(context, ret, "Server %s%s%s expired", + creds ? "(" : "", + creds ? servername : "", + creds ? ")" : ""); break; case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN : - krb5_set_error_string(context, "Client %s%s%s unknown", - creds ? "(" : "", - creds ? clientname : "", - creds ? ")" : ""); + krb5_set_error_message(context, ret, "Client %s%s%s unknown", + creds ? "(" : "", + creds ? clientname : "", + creds ? ")" : ""); break; case KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN : - krb5_set_error_string(context, "Server %s%s%s unknown", - creds ? "(" : "", - creds ? servername : "", - creds ? ")" : ""); + krb5_set_error_message(context, ret, "Server %s%s%s unknown", + creds ? "(" : "", + creds ? servername : "", + creds ? ")" : ""); break; default : krb5_clear_error_string(context); diff --git a/source4/heimdal/lib/krb5/rd_rep.c b/source4/heimdal/lib/krb5/rd_rep.c index 8c9b7bb441..0e6e3d09af 100644 --- a/source4/heimdal/lib/krb5/rd_rep.c +++ b/source4/heimdal/lib/krb5/rd_rep.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_rep.c 17890 2006-08-21 09:19:22Z lha $"); +RCSID("$Id: rd_rep.c 23304 2008-06-23 03:29:56Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_rep(krb5_context context, @@ -79,7 +79,7 @@ krb5_rd_rep(krb5_context context, *repl = malloc(sizeof(**repl)); if (*repl == NULL) { ret = ENOMEM; - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } ret = krb5_decode_EncAPRepPart(context, diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 0f33b97164..ddf1f69ae4 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_req.c 22235 2007-12-08 21:52:07Z lha $"); +RCSID("$Id: rd_req.c 23415 2008-07-26 18:35:44Z lha $"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, @@ -133,7 +133,7 @@ static krb5_error_code check_transited(krb5_context context, Ticket *ticket, EncTicketPart *enc) { char **realms; - int num_realms; + unsigned int num_realms; krb5_error_code ret; /* @@ -389,11 +389,6 @@ krb5_verify_ap_req2(krb5_context context, t->ticket.crealm); if (ret) goto out; - /* save key */ - - ret = krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock); - if (ret) goto out; - ret = decrypt_authenticator (context, &t->ticket.key, &ap_req->authenticator, @@ -479,6 +474,10 @@ krb5_verify_ap_req2(krb5_context context, } } + /* save key */ + ret = krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock); + if (ret) goto out; + if (ap_req_options) { *ap_req_options = 0; if (ac->keytype != ETYPE_NULL) @@ -533,7 +532,7 @@ krb5_rd_req_in_ctx_alloc(krb5_context context, krb5_rd_req_in_ctx *ctx) { *ctx = calloc(1, sizeof(**ctx)); if (*ctx == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "out of memory"); return ENOMEM; } (*ctx)->check_pac = (context->flags & KRB5_CTX_F_CHECK_PAC) ? 1 : 0; @@ -616,7 +615,7 @@ _krb5_rd_req_out_ctx_alloc(krb5_context context, krb5_rd_req_out_ctx *ctx) { *ctx = calloc(1, sizeof(**ctx)); if (*ctx == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "out of memory"); return ENOMEM; } return 0; @@ -805,9 +804,9 @@ krb5_rd_req_ctx(krb5_context context, } if (ap_req.ap_options.use_session_key && (*auth_context)->keyblock == NULL) { - krb5_set_error_string(context, "krb5_rd_req: user to user auth " - "without session key given"); ret = KRB5KRB_AP_ERR_NOKEY; + krb5_set_error_message(context, ret, "krb5_rd_req: user to user auth " + "without session key given"); goto out; } diff --git a/source4/heimdal/lib/krb5/replay.c b/source4/heimdal/lib/krb5/replay.c index 12894d96a9..7639bfa2ce 100644 --- a/source4/heimdal/lib/krb5/replay.c +++ b/source4/heimdal/lib/krb5/replay.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: replay.c 17047 2006-04-10 17:13:49Z lha $"); +RCSID("$Id: replay.c 23467 2008-07-27 12:16:37Z lha $"); struct krb5_rcache_data { char *name; @@ -47,7 +47,7 @@ krb5_rc_resolve(krb5_context context, { id->name = strdup(name); if(id->name == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_RC_MALLOC, "malloc: out of memory"); return KRB5_RC_MALLOC; } return 0; @@ -60,13 +60,14 @@ krb5_rc_resolve_type(krb5_context context, { *id = NULL; if(strcmp(type, "FILE")) { - krb5_set_error_string (context, "replay cache type %s not supported", - type); + krb5_set_error_message (context, KRB5_RC_TYPE_NOTFOUND, + "replay cache type %s not supported", + type); return KRB5_RC_TYPE_NOTFOUND; } *id = calloc(1, sizeof(**id)); if(*id == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, KRB5_RC_MALLOC, "malloc: out of memory"); return KRB5_RC_MALLOC; } return 0; @@ -82,7 +83,8 @@ krb5_rc_resolve_full(krb5_context context, *id = NULL; if(strncmp(string_name, "FILE:", 5)) { - krb5_set_error_string (context, "replay cache type %s not supported", + krb5_set_error_message(context, KRB5_RC_TYPE_NOTFOUND, + "replay cache type %s not supported", string_name); return KRB5_RC_TYPE_NOTFOUND; } @@ -132,7 +134,7 @@ krb5_rc_initialize(krb5_context context, if(f == NULL) { ret = errno; - krb5_set_error_string (context, "open(%s): %s", id->name, + krb5_set_error_message(context, ret, "open(%s): %s", id->name, strerror(ret)); return ret; } @@ -157,7 +159,7 @@ krb5_rc_destroy(krb5_context context, if(remove(id->name) < 0) { ret = errno; - krb5_set_error_string (context, "remove(%s): %s", id->name, + krb5_set_error_message(context, ret, "remove(%s): %s", id->name, strerror(ret)); return ret; } @@ -204,10 +206,11 @@ krb5_rc_store(krb5_context context, f = fopen(id->name, "r"); if(f == NULL) { ret = errno; - krb5_set_error_string (context, "open(%s): %s", id->name, + krb5_set_error_message(context, ret, "open(%s): %s", id->name, strerror(ret)); return ret; } + rk_cloexec_file(f); fread(&tmp, sizeof(ent), 1, f); t = ent.stamp - tmp.stamp; while(fread(&tmp, sizeof(ent), 1, f)){ @@ -222,13 +225,15 @@ krb5_rc_store(krb5_context context, if(ferror(f)){ ret = errno; fclose(f); - krb5_set_error_string (context, "%s: %s", id->name, strerror(ret)); + krb5_set_error_message(context, ret, "%s: %s", + id->name, strerror(ret)); return ret; } fclose(f); f = fopen(id->name, "a"); if(f == NULL) { - krb5_set_error_string (context, "open(%s): %s", id->name, + krb5_set_error_message(context, KRB5_RC_IO_UNKNOWN, + "open(%s): %s", id->name, strerror(errno)); return KRB5_RC_IO_UNKNOWN; } @@ -288,7 +293,7 @@ krb5_get_server_rcache(krb5_context context, char *name; if(tmp == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } strvisx(tmp, piece->data, piece->length, VIS_WHITE | VIS_OCTAL); @@ -299,7 +304,7 @@ krb5_get_server_rcache(krb5_context context, #endif free(tmp); if(name == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index 2582a615c0..1ddb5afd1f 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -32,8 +32,9 @@ */ #include "krb5_locl.h" +#include "send_to_kdc_plugin.h" -RCSID("$Id: send_to_kdc.c 21934 2007-08-27 14:21:04Z lha $"); +RCSID("$Id: send_to_kdc.c 23448 2008-07-27 12:09:22Z lha $"); struct send_to_kdc { krb5_send_to_kdc_func func; @@ -290,6 +291,7 @@ send_via_proxy (krb5_context context, s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); if (s < 0) continue; + rk_cloexec(s); if (connect (s, a->ai_addr, a->ai_addrlen) < 0) { close (s); continue; @@ -316,6 +318,46 @@ send_via_proxy (krb5_context context, return 1; } +static krb5_error_code +send_via_plugin(krb5_context context, + krb5_krbhst_info *hi, + time_t timeout, + const krb5_data *send_data, + krb5_data *receive) +{ + struct krb5_plugin *list = NULL, *e; + krb5_error_code ret; + + ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, KRB5_PLUGIN_SEND_TO_KDC, &list); + if(ret != 0 || list == NULL) + return KRB5_PLUGIN_NO_HANDLE; + + for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) { + krb5plugin_send_to_kdc_ftable *service; + void *ctx; + + service = _krb5_plugin_get_symbol(e); + if (service->minor_version != 0) + continue; + + (*service->init)(context, &ctx); + ret = (*service->send_to_kdc)(context, ctx, hi, + timeout, send_data, receive); + (*service->fini)(ctx); + if (ret == 0) + break; + if (ret != KRB5_PLUGIN_NO_HANDLE) { + krb5_set_error_message(context, ret, + "Plugin %s failed to lookup with error: %d", + KRB5_PLUGIN_SEND_TO_KDC, ret); + break; + } + } + _krb5_plugin_free(list); + return KRB5_PLUGIN_NO_HANDLE; +} + + /* * Send the data `send' to one host from `handle` and get back the reply * in `receive'. @@ -343,12 +385,19 @@ krb5_sendto (krb5_context context, struct send_to_kdc *s = context->send_to_kdc; ret = (*s->func)(context, s->data, - hi, send_data, receive); + hi, context->kdc_timeout, send_data, receive); if (ret == 0 && receive->length != 0) goto out; continue; } + ret = send_via_plugin(context, hi, context->kdc_timeout, + send_data, receive); + if (ret == 0 && receive->length != 0) + goto out; + else if (ret != KRB5_PLUGIN_NO_HANDLE) + continue; + if(hi->proto == KRB5_KRBHST_HTTP && context->http_proxy) { if (send_via_proxy (context, hi, send_data, receive) == 0) { ret = 0; @@ -365,6 +414,7 @@ krb5_sendto (krb5_context context, fd = socket (a->ai_family, a->ai_socktype, a->ai_protocol); if (fd < 0) continue; + rk_cloexec(fd); if (connect (fd, a->ai_addr, a->ai_addrlen) < 0) { close (fd); continue; @@ -439,7 +489,7 @@ krb5_set_send_to_kdc_func(krb5_context context, context->send_to_kdc = malloc(sizeof(*context->send_to_kdc)); if (context->send_to_kdc == NULL) { - krb5_set_error_string(context, "Out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } @@ -460,7 +510,7 @@ krb5_sendto_ctx_alloc(krb5_context context, krb5_sendto_ctx *ctx) { *ctx = calloc(1, sizeof(**ctx)); if (*ctx == NULL) { - krb5_set_error_string(context, "out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } return 0; @@ -566,8 +616,8 @@ krb5_sendto_context(krb5_context context, if (handle) krb5_krbhst_free(context, handle); if (ret == KRB5_KDC_UNREACH) - krb5_set_error_string(context, - "unable to reach any KDC in realm %s", realm); + krb5_set_error_message(context, ret, + "unable to reach any KDC in realm %s", realm); if (ret) krb5_data_free(receive); if (freectx) diff --git a/source4/heimdal/lib/krb5/send_to_kdc_plugin.h b/source4/heimdal/lib/krb5/send_to_kdc_plugin.h new file mode 100644 index 0000000000..e0c2979e28 --- /dev/null +++ b/source4/heimdal/lib/krb5/send_to_kdc_plugin.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2008 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. + */ + +/* $Id$ */ + +#ifndef HEIMDAL_KRB5_SEND_TO_KDC_PLUGIN_H +#define HEIMDAL_KRB5_SEND_TO_KDC_PLUGIN_H 1 + +#include + +#define KRB5_PLUGIN_SEND_TO_KDC "send_to_kdc" + +typedef krb5_error_code +(*krb5plugin_send_to_kdc_func)(krb5_context, + void *, + krb5_krbhst_info *, + time_t timeout, + const krb5_data *, + krb5_data *); + +typedef struct krb5plugin_send_to_kdc_ftable { + int minor_version; + krb5_error_code (*init)(krb5_context, void **); + void (*fini)(void *); + krb5plugin_send_to_kdc_func send_to_kdc; +} krb5plugin_send_to_kdc_ftable; + +#endif /* HEIMDAL_KRB5_SEND_TO_KDC_PLUGIN_H */ diff --git a/source4/heimdal/lib/krb5/set_default_realm.c b/source4/heimdal/lib/krb5/set_default_realm.c index 98040bc2e9..55abf2ea7d 100644 --- a/source4/heimdal/lib/krb5/set_default_realm.c +++ b/source4/heimdal/lib/krb5/set_default_realm.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: set_default_realm.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id: set_default_realm.c 23309 2008-06-23 03:30:41Z lha $"); /* * Convert the simple string `s' into a NULL-terminated and freshly allocated @@ -46,13 +46,13 @@ string_to_list (krb5_context context, const char *s, krb5_realm **list) *list = malloc (2 * sizeof(**list)); if (*list == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } (*list)[0] = strdup (s); if ((*list)[0] == NULL) { free (*list); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } (*list)[1] = NULL; diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c index 7eb4d32fad..5eff64e12d 100644 --- a/source4/heimdal/lib/krb5/ticket.c +++ b/source4/heimdal/lib/krb5/ticket.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: ticket.c 19544 2006-12-28 20:49:18Z lha $"); +RCSID("$Id: ticket.c 23310 2008-06-23 03:30:49Z lha $"); krb5_error_code KRB5_LIB_FUNCTION krb5_free_ticket(krb5_context context, @@ -57,7 +57,7 @@ krb5_copy_ticket(krb5_context context, *to = NULL; tmp = malloc(sizeof(*tmp)); if(tmp == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){ @@ -118,9 +118,10 @@ find_type_in_ad(krb5_context context, int i; if (level > 9) { - krb5_set_error_string(context, "Authorization data nested deeper " - "then %d levels, stop searching", level); ret = ENOENT; /* XXX */ + krb5_set_error_message(context, ret, + "Authorization data nested deeper " + "then %d levels, stop searching", level); goto out; } @@ -133,7 +134,7 @@ find_type_in_ad(krb5_context context, if (!*found && ad->val[i].ad_type == type) { ret = der_copy_octet_string(&ad->val[i].ad_data, data); if (ret) { - krb5_set_error_string(context, "malloc - out of memory"); + krb5_set_error_message(context, ret, "malloc: out of memory"); goto out; } *found = TRUE; @@ -147,8 +148,8 @@ find_type_in_ad(krb5_context context, &child, NULL); if (ret) { - krb5_set_error_string(context, "Failed to decode " - "IF_RELEVANT with %d", ret); + krb5_set_error_message(context, ret, "Failed to decode " + "IF_RELEVANT with %d", (int)ret); goto out; } ret = find_type_in_ad(context, type, data, found, FALSE, @@ -167,8 +168,8 @@ find_type_in_ad(krb5_context context, &child, NULL); if (ret) { - krb5_set_error_string(context, "Failed to decode " - "AD_KDCIssued with %d", ret); + krb5_set_error_message(context, ret, "Failed to decode " + "AD_KDCIssued with %d", ret); goto out; } if (failp) { @@ -211,17 +212,17 @@ find_type_in_ad(krb5_context context, case KRB5_AUTHDATA_AND_OR: if (!failp) break; - krb5_set_error_string(context, "Authorization data contains " - "AND-OR element that is unknown to the " - "application"); ret = ENOENT; /* XXX */ + krb5_set_error_message(context, ret, "Authorization data contains " + "AND-OR element that is unknown to the " + "application"); goto out; default: if (!failp) break; - krb5_set_error_string(context, "Authorization data contains " - "unknown type (%d) ", ad->val[i].ad_type); ret = ENOENT; /* XXX */ + krb5_set_error_message(context, ret, "Authorization data contains " + "unknown type (%d) ", ad->val[i].ad_type); goto out; } } @@ -255,7 +256,8 @@ krb5_ticket_get_authorization_data_type(krb5_context context, ad = ticket->ticket.authorization_data; if (ticket->ticket.authorization_data == NULL) { - krb5_set_error_string(context, "Ticket have not authorization data"); + krb5_set_error_message(context, ENOENT, + "Ticket have not authorization data"); return ENOENT; /* XXX */ } @@ -264,8 +266,8 @@ krb5_ticket_get_authorization_data_type(krb5_context context, if (ret) return ret; if (!found) { - krb5_set_error_string(context, "Ticket have not authorization " - "data of type %d", type); + krb5_set_error_message(context, ENOENT, "Ticket have not " + "authorization data of type %d", type); return ENOENT; /* XXX */ } return 0; diff --git a/source4/heimdal/lib/krb5/time.c b/source4/heimdal/lib/krb5/time.c index 4cd992d48f..46f88a86cd 100644 --- a/source4/heimdal/lib/krb5/time.c +++ b/source4/heimdal/lib/krb5/time.c @@ -33,12 +33,20 @@ #include "krb5_locl.h" -RCSID("$Id: time.c 14308 2004-10-13 17:57:11Z lha $"); +RCSID("$Id: time.c 23260 2008-06-21 15:22:37Z lha $"); -/* +/** * Set the absolute time that the caller knows the kdc has so the * kerberos library can calculate the relative diffrence beteen the * KDC time and local system time. + * + * @param context Keberos 5 context. + * @param sec The applications new of "now" in seconds + * @param usec The applications new of "now" in micro seconds + + * @return Kerberos 5 error code, see krb5_get_error_message(). + * + * @ingroup krb5 */ krb5_error_code KRB5_LIB_FUNCTION @@ -51,12 +59,21 @@ krb5_set_real_time (krb5_context context, gettimeofday(&tv, NULL); context->kdc_sec_offset = sec - tv.tv_sec; - context->kdc_usec_offset = usec - tv.tv_usec; - if (context->kdc_usec_offset < 0) { - context->kdc_sec_offset--; - context->kdc_usec_offset += 1000000; - } + /** + * If the caller passes in a negative usec, its assumed to be + * unknown and the function will use the current time usec. + */ + if (usec >= 0) { + context->kdc_usec_offset = usec - tv.tv_usec; + + if (context->kdc_usec_offset < 0) { + context->kdc_sec_offset--; + context->kdc_usec_offset += 1000000; + } + } else + context->kdc_usec_offset = tv.tv_usec; + return 0; } diff --git a/source4/heimdal/lib/krb5/transited.c b/source4/heimdal/lib/krb5/transited.c index 9b67ecc04f..58b00a4b7a 100644 --- a/source4/heimdal/lib/krb5/transited.c +++ b/source4/heimdal/lib/krb5/transited.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: transited.c 21745 2007-07-31 16:11:25Z lha $"); +RCSID("$Id: transited.c 23316 2008-06-23 04:32:32Z lha $"); /* this is an attempt at one of the most horrible `compression' schemes that has ever been invented; it's so amazingly brain-dead @@ -88,7 +88,7 @@ make_path(krb5_context context, struct tr_realm *r, break; tmp = calloc(1, sizeof(*tmp)); if(tmp == NULL){ - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } tmp->next = path; @@ -96,7 +96,7 @@ make_path(krb5_context context, struct tr_realm *r, path->realm = strdup(p); if(path->realm == NULL){ r->next = path; /* XXX */ - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM;; } } @@ -112,7 +112,7 @@ make_path(krb5_context context, struct tr_realm *r, break; tmp = calloc(1, sizeof(*tmp)); if(tmp == NULL){ - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } tmp->next = path; @@ -120,7 +120,7 @@ make_path(krb5_context context, struct tr_realm *r, path->realm = malloc(p - from + 1); if(path->realm == NULL){ r->next = path; /* XXX */ - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy(path->realm, from, p - from); @@ -186,7 +186,7 @@ expand_realms(krb5_context context, tmp = realloc(r->realm, len); if(tmp == NULL){ free_realms(realms); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } r->realm = tmp; @@ -200,7 +200,7 @@ expand_realms(krb5_context context, tmp = malloc(len); if(tmp == NULL){ free_realms(realms); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } strlcpy(tmp, prev_realm, len); @@ -286,7 +286,7 @@ decode_realms(krb5_context context, if(tr[i] == ','){ tmp = malloc(tr + i - start + 1); if(tmp == NULL){ - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy(tmp, start, tr + i - start); @@ -294,7 +294,7 @@ decode_realms(krb5_context context, r = make_realm(tmp); if(r == NULL){ free_realms(*realms); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } *realms = append_realm(*realms, r); @@ -304,7 +304,7 @@ decode_realms(krb5_context context, tmp = malloc(tr + i - start + 1); if(tmp == NULL){ free(*realms); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } memcpy(tmp, start, tr + i - start); @@ -312,7 +312,7 @@ decode_realms(krb5_context context, r = make_realm(tmp); if(r == NULL){ free_realms(*realms); - krb5_set_error_string (context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } *realms = append_realm(*realms, r); @@ -323,7 +323,7 @@ decode_realms(krb5_context context, krb5_error_code KRB5_LIB_FUNCTION krb5_domain_x500_decode(krb5_context context, - krb5_data tr, char ***realms, int *num_realms, + krb5_data tr, char ***realms, unsigned int *num_realms, const char *client_realm, const char *server_realm) { struct tr_realm *r = NULL; @@ -385,11 +385,12 @@ krb5_domain_x500_decode(krb5_context context, } krb5_error_code KRB5_LIB_FUNCTION -krb5_domain_x500_encode(char **realms, int num_realms, krb5_data *encoding) +krb5_domain_x500_encode(char **realms, unsigned int num_realms, + krb5_data *encoding) { char *s = NULL; int len = 0; - int i; + unsigned int i; krb5_data_zero(encoding); if (num_realms == 0) return 0; @@ -420,7 +421,7 @@ krb5_check_transited(krb5_context context, krb5_const_realm client_realm, krb5_const_realm server_realm, krb5_realm *realms, - int num_realms, + unsigned int num_realms, int *bad_realm) { char **tr_realms; @@ -442,8 +443,9 @@ krb5_check_transited(krb5_context context, } if(p == NULL || *p == NULL) { krb5_config_free_strings(tr_realms); - krb5_set_error_string (context, "no transit through realm %s", - realms[i]); + krb5_set_error_message (context, KRB5KRB_AP_ERR_ILL_CR_TKT, + "no transit through realm %s", + realms[i]); if(bad_realm) *bad_realm = i; return KRB5KRB_AP_ERR_ILL_CR_TKT; @@ -456,7 +458,7 @@ krb5_check_transited(krb5_context context, krb5_error_code KRB5_LIB_FUNCTION krb5_check_transited_realms(krb5_context context, const char *const *realms, - int num_realms, + unsigned int num_realms, int *bad_realm) { int i; @@ -472,9 +474,9 @@ krb5_check_transited_realms(krb5_context context, char **p; for(p = bad_realms; *p; p++) if(strcmp(*p, realms[i]) == 0) { - krb5_set_error_string (context, "no transit through realm %s", - *p); ret = KRB5KRB_AP_ERR_ILL_CR_TKT; + krb5_set_error_message (context, ret, + "no transit through realm %s", *p); if(bad_realm) *bad_realm = i; break; diff --git a/source4/heimdal/lib/krb5/v4_glue.c b/source4/heimdal/lib/krb5/v4_glue.c index 37b1e35dd1..55570c44dd 100644 --- a/source4/heimdal/lib/krb5/v4_glue.c +++ b/source4/heimdal/lib/krb5/v4_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: v4_glue.c 22071 2007-11-14 20:04:50Z lha $"); +RCSID("$Id: v4_glue.c 23452 2008-07-27 12:10:54Z lha $"); #include "krb5-v4compat.h" @@ -147,7 +147,7 @@ write_v4_cc(krb5_context context, const char *tkfile, ret = get_krb4_cc_name(tkfile, &path); if (ret) { - krb5_set_error_string(context, + krb5_set_error_message(context, ret, "krb5_krb_tf_setup: failed getting " "the krb4 credentials cache name"); return ret; @@ -156,15 +156,16 @@ write_v4_cc(krb5_context context, const char *tkfile, fd = open(path, O_WRONLY|O_CREAT, 0600); if (fd < 0) { ret = errno; - krb5_set_error_string(context, + krb5_set_error_message(context, ret, "krb5_krb_tf_setup: error opening file %s", path); free(path); return ret; } + rk_cloexec(fd); if (fstat(fd, &sb) != 0 || !S_ISREG(sb.st_mode)) { - krb5_set_error_string(context, + krb5_set_error_message(context, ret, "krb5_krb_tf_setup: tktfile %s is not a file", path); free(path); @@ -179,9 +180,9 @@ write_v4_cc(krb5_context context, const char *tkfile, break; } if (i == KRB5_TF_LCK_RETRY_COUNT) { - krb5_set_error_string(context, - "krb5_krb_tf_setup: failed to lock %s", - path); + krb5_set_error_message(context, KRB5_FCC_PERM, + "krb5_krb_tf_setup: failed to lock %s", + path); free(path); close(fd); return KRB5_FCC_PERM; @@ -191,9 +192,9 @@ write_v4_cc(krb5_context context, const char *tkfile, ret = ftruncate(fd, 0); if (ret < 0) { flock(fd, LOCK_UN); - krb5_set_error_string(context, - "krb5_krb_tf_setup: failed to truncate %s", - path); + krb5_set_error_message(context, KRB5_FCC_PERM, + "krb5_krb_tf_setup: failed to truncate %s", + path); free(path); close(fd); return KRB5_FCC_PERM; @@ -291,7 +292,7 @@ _krb5_krb_dest_tkt(krb5_context context, const char *tkfile) ret = get_krb4_cc_name(tkfile, &path); if (ret) { - krb5_set_error_string(context, + krb5_set_error_message(context, ret, "krb5_krb_tf_setup: failed getting " "the krb4 credentials cache name"); return ret; @@ -299,7 +300,7 @@ _krb5_krb_dest_tkt(krb5_context context, const char *tkfile) if (unlink(path) < 0) { ret = errno; - krb5_set_error_string(context, + krb5_set_error_message(context, ret, "krb5_krb_dest_tkt failed removing the cache " "with error %s", strerror(ret)); } @@ -421,7 +422,7 @@ _krb5_krb_create_ticket(krb5_context context, sp = krb5_storage_emem(); if (sp == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); @@ -448,7 +449,7 @@ _krb5_krb_create_ticket(krb5_context context, error: krb5_storage_free(sp); if (ret) - krb5_set_error_string(context, "Failed to encode kerberos 4 ticket"); + krb5_set_error_message(context, ret, "Failed to encode kerberos 4 ticket"); return ret; } @@ -477,7 +478,7 @@ _krb5_krb_create_ciph(krb5_context context, sp = krb5_storage_emem(); if (sp == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); @@ -507,7 +508,7 @@ _krb5_krb_create_ciph(krb5_context context, error: krb5_storage_free(sp); if (ret) - krb5_set_error_string(context, "Failed to encode kerberos 4 ticket"); + krb5_set_error_message(context, ret, "Failed to encode kerberos 4 ticket"); return ret; } @@ -535,7 +536,7 @@ _krb5_krb_create_auth_reply(krb5_context context, sp = krb5_storage_emem(); if (sp == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); @@ -559,7 +560,7 @@ _krb5_krb_create_auth_reply(krb5_context context, error: krb5_storage_free(sp); if (ret) - krb5_set_error_string(context, "Failed to encode kerberos 4 ticket"); + krb5_set_error_message(context, ret, "Failed to encode kerberos 4 ticket"); return ret; } @@ -590,7 +591,7 @@ _krb5_krb_cr_err_reply(krb5_context context, sp = krb5_storage_emem(); if (sp == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); @@ -610,7 +611,7 @@ _krb5_krb_cr_err_reply(krb5_context context, error: krb5_storage_free(sp); if (ret) - krb5_set_error_string(context, "Failed to encode kerberos 4 error"); + krb5_set_error_message(context, ret, "Failed to encode kerberos 4 error"); return 0; } @@ -661,7 +662,7 @@ _krb5_krb_decomp_ticket(krb5_context context, sp = krb5_storage_from_data(&ticket); if (sp == NULL) { krb5_data_free(&ticket); - krb5_set_error_string(context, "alloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "alloc: out of memory"); return ENOMEM; } @@ -720,7 +721,7 @@ _krb5_krb_decomp_ticket(krb5_context context, *sinstance = NULL; } _krb5_krb_free_auth_data(context, ad); - krb5_set_error_string(context, "Failed to decode v4 ticket"); + krb5_set_error_message(context, ret, "Failed to decode v4 ticket"); } return ret; } @@ -769,7 +770,7 @@ _krb5_krb_rd_req(krb5_context context, sp = krb5_storage_from_data(authent); if (sp == NULL) { - krb5_set_error_string(context, "alloc: out of memory"); + krb5_set_error_message(context, ENOMEM, "alloc: out of memory"); return ENOMEM; } @@ -777,19 +778,19 @@ _krb5_krb_rd_req(krb5_context context, ret = krb5_ret_int8(sp, &pvno); if (ret) { - krb5_set_error_string(context, "Failed reading v4 pvno"); + krb5_set_error_message(context, ret, "Failed reading v4 pvno"); goto error; } if (pvno != KRB_PROT_VERSION) { ret = KRB4ET_RD_AP_VERSION; - krb5_set_error_string(context, "Failed v4 pvno not 4"); + krb5_set_error_message(context, ret, "Failed v4 pvno not 4"); goto error; } ret = krb5_ret_int8(sp, &type); if (ret) { - krb5_set_error_string(context, "Failed readin v4 type"); + krb5_set_error_message(context, ret, "Failed readin v4 type"); goto error; } @@ -798,7 +799,7 @@ _krb5_krb_rd_req(krb5_context context, if(type != AUTH_MSG_APPL_REQUEST && type != AUTH_MSG_APPL_REQUEST_MUTUAL) { ret = KRB4ET_RD_AP_MSG_TYPE; - krb5_set_error_string(context, "Not a valid v4 request type"); + krb5_set_error_message(context, ret, "Not a valid v4 request type"); goto error; } @@ -811,7 +812,7 @@ _krb5_krb_rd_req(krb5_context context, size = krb5_storage_read(sp, ticket.data, ticket.length); if (size != ticket.length) { ret = KRB4ET_INTK_PROT; - krb5_set_error_string(context, "Failed reading v4 ticket"); + krb5_set_error_message(context, ret, "Failed reading v4 ticket"); goto error; } @@ -826,7 +827,7 @@ _krb5_krb_rd_req(krb5_context context, size = krb5_storage_read(sp, eaut.data, eaut.length); if (size != eaut.length) { ret = KRB4ET_INTK_PROT; - krb5_set_error_string(context, "Failed reading v4 authenticator"); + krb5_set_error_message(context, ret, "Failed reading v4 authenticator"); goto error; } @@ -840,7 +841,7 @@ _krb5_krb_rd_req(krb5_context context, sp = krb5_storage_from_data(&aut); if (sp == NULL) { ret = ENOMEM; - krb5_set_error_string(context, "alloc: out of memory"); + krb5_set_error_message(context, ret, "alloc: out of memory"); goto error; } @@ -860,14 +861,14 @@ _krb5_krb_rd_req(krb5_context context, if (strcmp(ad->pname, r_name) != 0 || strcmp(ad->pinst, r_instance) != 0 || strcmp(ad->prealm, r_realm) != 0) { - krb5_set_error_string(context, "v4 principal mismatch"); ret = KRB4ET_RD_AP_INCON; + krb5_set_error_message(context, ret, "v4 principal mismatch"); goto error; } if (from_addr && ad->address && from_addr != ad->address) { - krb5_set_error_string(context, "v4 bad address in ticket"); ret = KRB4ET_RD_AP_BADD; + krb5_set_error_message(context, ret, "v4 bad address in ticket"); goto error; } @@ -875,7 +876,7 @@ _krb5_krb_rd_req(krb5_context context, delta_t = abs((int)(tv.tv_sec - r_time_sec)); if (delta_t > CLOCK_SKEW) { ret = KRB4ET_RD_AP_TIME; - krb5_set_error_string(context, "v4 clock skew"); + krb5_set_error_message(context, ret, "v4 clock skew"); goto error; } @@ -885,13 +886,13 @@ _krb5_krb_rd_req(krb5_context context, if ((tkt_age < 0) && (-tkt_age > CLOCK_SKEW)) { ret = KRB4ET_RD_AP_NYV; - krb5_set_error_string(context, "v4 clock skew for expiration"); + krb5_set_error_message(context, ret, "v4 clock skew for expiration"); goto error; } if (tv.tv_sec > _krb5_krb_life_to_time(ad->time_sec, ad->life)) { ret = KRB4ET_RD_AP_EXP; - krb5_set_error_string(context, "v4 ticket expired"); + krb5_set_error_message(context, ret, "v4 ticket expired"); goto error; } diff --git a/source4/heimdal/lib/krb5/warn.c b/source4/heimdal/lib/krb5/warn.c index 85f143b8b4..97a6cc9e0a 100644 --- a/source4/heimdal/lib/krb5/warn.c +++ b/source4/heimdal/lib/krb5/warn.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: warn.c 19086 2006-11-21 08:06:40Z lha $"); +RCSID("$Id: warn.c 23206 2008-05-29 02:13:41Z lha $"); static krb5_error_code _warnerr(krb5_context context, int do_errtext, krb5_error_code code, int level, const char *fmt, va_list ap) @@ -47,7 +47,7 @@ _warnerr(krb5_context context, int do_errtext, char xfmt[7] = ""; const char *args[2], **arg; char *msg = NULL; - char *err_str = NULL; + const char *err_str = NULL; args[0] = args[1] = NULL; arg = args; @@ -65,7 +65,7 @@ _warnerr(krb5_context context, int do_errtext, strlcat(xfmt, "%s", sizeof(xfmt)); - err_str = krb5_get_error_string(context); + err_str = krb5_get_error_message(context, code); if (err_str != NULL) { *arg++ = err_str; } else { @@ -82,7 +82,7 @@ _warnerr(krb5_context context, int do_errtext, else warnx(xfmt, args[0], args[1]); free(msg); - free(err_str); + krb5_free_error_message(context, err_str); return 0; } -- cgit From 610b1ada1535b2ae1b38adde4de112ee6dc23a2c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 8 Aug 2008 15:22:39 +0200 Subject: krb5: always generate the acceptor subkey as the same enctype as the used service key With this patch samba4 can use gsskrb5_get_subkey() to get the session key. metze (This used to be commit dbb94133e0313cae933d261af0bf1210807a6d11) --- source4/heimdal/lib/krb5/rd_req.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index ddf1f69ae4..e80aaa6789 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -463,6 +463,8 @@ krb5_verify_ap_req2(krb5_context context, ac->keytype = ETYPE_NULL; +#if 0 +/* it's bad to use a different enctype as the client */ if (etypes.val) { int i; @@ -473,6 +475,7 @@ krb5_verify_ap_req2(krb5_context context, } } } +#endif /* save key */ ret = krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock); -- cgit From e75f1072b6c3735690d7b20682036b8bc5977dc5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 13 Aug 2008 07:22:36 +0200 Subject: Revert "krb5: always generate the acceptor subkey as the same enctype as the used service key" This reverts commit dbb94133e0313cae933d261af0bf1210807a6d11. As we fixed gensec_gssapi to only return a session key when it's have the correct session key, this hack isn't needed anymore. metze (This used to be commit 697cd1896bccaa55ee422f17d9312d787ca699ed) --- source4/heimdal/lib/krb5/rd_req.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index e80aaa6789..ddf1f69ae4 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -463,8 +463,6 @@ krb5_verify_ap_req2(krb5_context context, ac->keytype = ETYPE_NULL; -#if 0 -/* it's bad to use a different enctype as the client */ if (etypes.val) { int i; @@ -475,7 +473,6 @@ krb5_verify_ap_req2(krb5_context context, } } } -#endif /* save key */ ret = krb5_copy_keyblock(context, &t->ticket.key, &ac->keyblock); -- cgit From 1c4b84ee4fc0f30b5e2418e029c31fb99570a325 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Aug 2008 12:19:52 +0200 Subject: heimdal_build: add a fake sqlite keytab implementation This remove a difference against lorikeet-heimdal. metze (This used to be commit 4314df3561dfe60228db0af220549300b0137c85) --- source4/heimdal/lib/krb5/context.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index 543dba396d..9f17b8c205 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -246,9 +246,7 @@ krb5_init_context(krb5_context *context) krb5_cc_register(p, &krb5_acc_ops, TRUE); krb5_cc_register(p, &krb5_fcc_ops, TRUE); krb5_cc_register(p, &krb5_mcc_ops, TRUE); -#if 0 krb5_cc_register(p, &krb5_scc_ops, TRUE); -#endif #ifdef HAVE_KCM krb5_cc_register(p, &krb5_kcm_ops, TRUE); #endif -- cgit From f09f67d24d0504cbb29d4344b3bd443f0e7e0b90 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Aug 2008 11:25:10 +0200 Subject: heimdal: remove unused old files metze (This used to be commit 94cef56212d7d7c1150aea760dba24bda7190442) --- source4/heimdal/lib/krb5/keytab_krb4.c | 458 --------------------------------- 1 file changed, 458 deletions(-) delete mode 100644 source4/heimdal/lib/krb5/keytab_krb4.c (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/keytab_krb4.c b/source4/heimdal/lib/krb5/keytab_krb4.c deleted file mode 100644 index 32bb00141a..0000000000 --- a/source4/heimdal/lib/krb5/keytab_krb4.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * Copyright (c) 1997 - 2002 Kungliga Tekniska Högskolan - * (Royal Institute of Technology, Stockholm, Sweden). - * 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 the Institute 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 THE INSTITUTE 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 THE INSTITUTE 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. - */ - -#include "krb5_locl.h" - -RCSID("$Id: keytab_krb4.c 22532 2008-01-27 11:59:18Z lha $"); - -struct krb4_kt_data { - char *filename; -}; - -static krb5_error_code -krb4_kt_resolve(krb5_context context, const char *name, krb5_keytab id) -{ - struct krb4_kt_data *d; - - d = malloc (sizeof(*d)); - if (d == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); - return ENOMEM; - } - d->filename = strdup (name); - if (d->filename == NULL) { - free(d); - krb5_set_error_string (context, "malloc: out of memory"); - return ENOMEM; - } - id->data = d; - return 0; -} - -static krb5_error_code -krb4_kt_get_name (krb5_context context, - krb5_keytab id, - char *name, - size_t name_sz) -{ - struct krb4_kt_data *d = id->data; - - strlcpy (name, d->filename, name_sz); - return 0; -} - -static krb5_error_code -krb4_kt_close (krb5_context context, - krb5_keytab id) -{ - struct krb4_kt_data *d = id->data; - - free (d->filename); - free (d); - return 0; -} - -struct krb4_cursor_extra_data { - krb5_keytab_entry entry; - int num; -}; - -static int -open_flock(const char *filename, int flags, int mode) -{ - int lock_mode; - int tries = 0; - int fd = open(filename, flags, mode); - if(fd < 0) - return fd; - if((flags & O_ACCMODE) == O_RDONLY) - lock_mode = LOCK_SH | LOCK_NB; - else - lock_mode = LOCK_EX | LOCK_NB; - while(flock(fd, lock_mode) < 0) { - if(++tries < 5) { - sleep(1); - } else { - close(fd); - return -1; - } - } - return fd; -} - - - -static krb5_error_code -krb4_kt_start_seq_get_int (krb5_context context, - krb5_keytab id, - int flags, - krb5_kt_cursor *c) -{ - struct krb4_kt_data *d = id->data; - struct krb4_cursor_extra_data *ed; - int ret; - - ed = malloc (sizeof(*ed)); - if (ed == NULL) { - krb5_set_error_string (context, "malloc: out of memory"); - return ENOMEM; - } - ed->entry.principal = NULL; - ed->num = -1; - c->data = ed; - c->fd = open_flock (d->filename, flags, 0); - if (c->fd < 0) { - ret = errno; - free (ed); - krb5_set_error_string(context, "keytab krb5 open %s failed: %s", - d->filename, strerror(ret)); - return ret; - } - c->sp = krb5_storage_from_fd(c->fd); - if(c->sp == NULL) { - close(c->fd); - free(ed); - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - krb5_storage_set_eof_code(c->sp, KRB5_KT_END); - return 0; -} - -static krb5_error_code -krb4_kt_start_seq_get (krb5_context context, - krb5_keytab id, - krb5_kt_cursor *c) -{ - return krb4_kt_start_seq_get_int (context, id, O_BINARY | O_RDONLY, c); -} - -static krb5_error_code -read_v4_entry (krb5_context context, - struct krb4_kt_data *d, - krb5_kt_cursor *c, - struct krb4_cursor_extra_data *ed) -{ - unsigned char des_key[8]; - krb5_error_code ret; - char *service, *instance, *realm; - int8_t kvno; - - ret = krb5_ret_stringz(c->sp, &service); - if (ret) - return ret; - ret = krb5_ret_stringz(c->sp, &instance); - if (ret) { - free (service); - return ret; - } - ret = krb5_ret_stringz(c->sp, &realm); - if (ret) { - free (service); - free (instance); - return ret; - } - ret = krb5_425_conv_principal (context, service, instance, realm, - &ed->entry.principal); - free (service); - free (instance); - free (realm); - if (ret) - return ret; - ret = krb5_ret_int8(c->sp, &kvno); - if (ret) { - krb5_free_principal (context, ed->entry.principal); - return ret; - } - ret = krb5_storage_read(c->sp, des_key, sizeof(des_key)); - if (ret < 0) { - krb5_free_principal(context, ed->entry.principal); - return ret; - } - if (ret < 8) { - krb5_free_principal(context, ed->entry.principal); - return EINVAL; - } - ed->entry.vno = kvno; - ret = krb5_data_copy (&ed->entry.keyblock.keyvalue, - des_key, sizeof(des_key)); - if (ret) - return ret; - ed->entry.timestamp = time(NULL); - ed->num = 0; - return 0; -} - -static krb5_error_code -krb4_kt_next_entry (krb5_context context, - krb5_keytab id, - krb5_keytab_entry *entry, - krb5_kt_cursor *c) -{ - krb5_error_code ret; - struct krb4_kt_data *d = id->data; - struct krb4_cursor_extra_data *ed = c->data; - const krb5_enctype keytypes[] = {ETYPE_DES_CBC_MD5, - ETYPE_DES_CBC_MD4, - ETYPE_DES_CBC_CRC}; - - if (ed->num == -1) { - ret = read_v4_entry (context, d, c, ed); - if (ret) - return ret; - } - ret = krb5_kt_copy_entry_contents (context, - &ed->entry, - entry); - if (ret) - return ret; - entry->keyblock.keytype = keytypes[ed->num]; - if (++ed->num == 3) { - krb5_kt_free_entry (context, &ed->entry); - ed->num = -1; - } - return 0; -} - -static krb5_error_code -krb4_kt_end_seq_get (krb5_context context, - krb5_keytab id, - krb5_kt_cursor *c) -{ - struct krb4_cursor_extra_data *ed = c->data; - - krb5_storage_free (c->sp); - if (ed->num != -1) - krb5_kt_free_entry (context, &ed->entry); - free (c->data); - close (c->fd); - return 0; -} - -static krb5_error_code -krb4_store_keytab_entry(krb5_context context, - krb5_keytab_entry *entry, - krb5_storage *sp) -{ - krb5_error_code ret; -#define ANAME_SZ 40 -#define INST_SZ 40 -#define REALM_SZ 40 - char service[ANAME_SZ]; - char instance[INST_SZ]; - char realm[REALM_SZ]; - ret = krb5_524_conv_principal (context, entry->principal, - service, instance, realm); - if (ret) - return ret; - if (entry->keyblock.keyvalue.length == 8 - && entry->keyblock.keytype == ETYPE_DES_CBC_MD5) { - ret = krb5_store_stringz(sp, service); - ret = krb5_store_stringz(sp, instance); - ret = krb5_store_stringz(sp, realm); - ret = krb5_store_int8(sp, entry->vno); - ret = krb5_storage_write(sp, entry->keyblock.keyvalue.data, 8); - } - return 0; -} - -static krb5_error_code -krb4_kt_add_entry (krb5_context context, - krb5_keytab id, - krb5_keytab_entry *entry) -{ - struct krb4_kt_data *d = id->data; - krb5_storage *sp; - krb5_error_code ret; - int fd; - - fd = open_flock (d->filename, O_WRONLY | O_APPEND | O_BINARY, 0); - if (fd < 0) { - fd = open_flock (d->filename, - O_WRONLY | O_APPEND | O_BINARY | O_CREAT, 0600); - if (fd < 0) { - ret = errno; - krb5_set_error_string(context, "open(%s): %s", d->filename, - strerror(ret)); - return ret; - } - } - sp = krb5_storage_from_fd(fd); - if(sp == NULL) { - close(fd); - return ENOMEM; - } - krb5_storage_set_eof_code(sp, KRB5_KT_END); - ret = krb4_store_keytab_entry(context, entry, sp); - krb5_storage_free(sp); - if(close (fd) < 0) - return errno; - return ret; -} - -static krb5_error_code -krb4_kt_remove_entry(krb5_context context, - krb5_keytab id, - krb5_keytab_entry *entry) -{ - struct krb4_kt_data *d = id->data; - krb5_error_code ret; - krb5_keytab_entry e; - krb5_kt_cursor cursor; - krb5_storage *sp; - int remove_flag = 0; - - sp = krb5_storage_emem(); - if (sp == NULL) { - krb5_set_error_string(context, "malloc: out of memory"); - return ENOMEM; - } - ret = krb5_kt_start_seq_get(context, id, &cursor); - if (ret) { - krb5_storage_free(sp); - return ret; - } - while(krb5_kt_next_entry(context, id, &e, &cursor) == 0) { - if(!krb5_kt_compare(context, &e, entry->principal, - entry->vno, entry->keyblock.keytype)) { - ret = krb4_store_keytab_entry(context, &e, sp); - if(ret) { - krb5_kt_free_entry(context, &e); - krb5_storage_free(sp); - return ret; - } - } else - remove_flag = 1; - krb5_kt_free_entry(context, &e); - } - krb5_kt_end_seq_get(context, id, &cursor); - if(remove_flag) { - int fd; - unsigned char buf[1024]; - ssize_t n; - krb5_data data; - struct stat st; - - krb5_storage_to_data(sp, &data); - krb5_storage_free(sp); - - fd = open_flock (d->filename, O_RDWR | O_BINARY, 0); - if(fd < 0) { - memset(data.data, 0, data.length); - krb5_data_free(&data); - if(errno == EACCES || errno == EROFS) { - krb5_set_error_string(context, "failed to open %s for writing", - d->filename); - return KRB5_KT_NOWRITE; - } - return errno; - } - - if(write(fd, data.data, data.length) != data.length) { - memset(data.data, 0, data.length); - krb5_data_free(&data); - close(fd); - krb5_set_error_string(context, "failed writing to file %s", - d->filename); - return errno; - } - memset(data.data, 0, data.length); - if(fstat(fd, &st) < 0) { - krb5_data_free(&data); - close(fd); - krb5_set_error_string(context, "failed getting size of file %s", - d->filename); - return errno; - } - st.st_size -= data.length; - memset(buf, 0, sizeof(buf)); - while(st.st_size > 0) { - n = min(st.st_size, sizeof(buf)); - n = write(fd, buf, n); - if(n <= 0) { - krb5_data_free(&data); - close(fd); - krb5_set_error_string(context, "failed writing to file %s", - d->filename); - return errno; - - } - st.st_size -= n; - } - if(ftruncate(fd, data.length) < 0) { - krb5_data_free(&data); - close(fd); - krb5_set_error_string(context, "failed truncating file %s", - d->filename); - return errno; - } - krb5_data_free(&data); - if(close(fd) < 0) { - krb5_set_error_string(context, "error closing %s", - d->filename); - return errno; - } - return 0; - } else { - krb5_storage_free(sp); - krb5_set_error_string(context, "Keytab entry not found"); - return KRB5_KT_NOTFOUND; - } -} - - -const krb5_kt_ops krb4_fkt_ops = { - "krb4", - krb4_kt_resolve, - krb4_kt_get_name, - krb4_kt_close, - NULL, /* get */ - krb4_kt_start_seq_get, - krb4_kt_next_entry, - krb4_kt_end_seq_get, - krb4_kt_add_entry, /* add_entry */ - krb4_kt_remove_entry /* remove_entry */ -}; - -const krb5_kt_ops krb5_srvtab_fkt_ops = { - "SRVTAB", - krb4_kt_resolve, - krb4_kt_get_name, - krb4_kt_close, - NULL, /* get */ - krb4_kt_start_seq_get, - krb4_kt_next_entry, - krb4_kt_end_seq_get, - krb4_kt_add_entry, /* add_entry */ - krb4_kt_remove_entry /* remove_entry */ -}; -- cgit From 9080b5d979e2af4de1022513bdaa303306b1ca9b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Aug 2008 11:20:54 +0200 Subject: heimdal_build: autogenerate the heimdal private/proto headers Now it's possible to just use a plain heimdal tree in source/heimdal/ without any pregenerated files. metze (This used to be commit da333ca7113f78eeacab4f93b401f075114c7d88) --- source4/heimdal/lib/krb5/krb5-private.h | 455 ---- source4/heimdal/lib/krb5/krb5-protos.h | 4169 ------------------------------- 2 files changed, 4624 deletions(-) delete mode 100644 source4/heimdal/lib/krb5/krb5-private.h delete mode 100644 source4/heimdal/lib/krb5/krb5-protos.h (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/krb5-private.h b/source4/heimdal/lib/krb5/krb5-private.h deleted file mode 100644 index 867d08e3e5..0000000000 --- a/source4/heimdal/lib/krb5/krb5-private.h +++ /dev/null @@ -1,455 +0,0 @@ -/* This is a generated file */ -#ifndef __krb5_private_h__ -#define __krb5_private_h__ - -#include - -void KRB5_LIB_FUNCTION -_krb5_aes_cts_encrypt ( - const unsigned char */*in*/, - unsigned char */*out*/, - size_t /*len*/, - const AES_KEY */*key*/, - unsigned char */*ivec*/, - const int /*encryptp*/); - -krb5_error_code -_krb5_cc_allocate ( - krb5_context /*context*/, - const krb5_cc_ops */*ops*/, - krb5_ccache */*id*/); - -void -_krb5_crc_init_table (void); - -uint32_t -_krb5_crc_update ( - const char */*p*/, - size_t /*len*/, - uint32_t /*res*/); - -krb5_error_code -_krb5_dh_group_ok ( - krb5_context /*context*/, - unsigned long /*bits*/, - heim_integer */*p*/, - heim_integer */*g*/, - heim_integer */*q*/, - struct krb5_dh_moduli **/*moduli*/, - char **/*name*/); - -krb5_error_code -_krb5_expand_default_cc_name ( - krb5_context /*context*/, - const char */*str*/, - char **/*res*/); - -int -_krb5_extract_ticket ( - krb5_context /*context*/, - krb5_kdc_rep */*rep*/, - krb5_creds */*creds*/, - krb5_keyblock */*key*/, - krb5_const_pointer /*keyseed*/, - krb5_key_usage /*key_usage*/, - krb5_addresses */*addrs*/, - unsigned /*nonce*/, - unsigned /*flags*/, - krb5_decrypt_proc /*decrypt_proc*/, - krb5_const_pointer /*decryptarg*/); - -void -_krb5_free_krbhst_info (krb5_krbhst_info */*hi*/); - -void -_krb5_free_moduli (struct krb5_dh_moduli **/*moduli*/); - -krb5_error_code -_krb5_get_default_principal_local ( - krb5_context /*context*/, - krb5_principal */*princ*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_get_host_realm_int ( - krb5_context /*context*/, - const char */*host*/, - krb5_boolean /*use_dns*/, - krb5_realm **/*realms*/); - -krb5_error_code -_krb5_get_init_creds_opt_copy ( - krb5_context /*context*/, - const krb5_get_init_creds_opt */*in*/, - krb5_get_init_creds_opt **/*out*/); - -void KRB5_LIB_FUNCTION -_krb5_get_init_creds_opt_free_krb5_error (krb5_get_init_creds_opt */*opt*/); - -void KRB5_LIB_FUNCTION -_krb5_get_init_creds_opt_free_pkinit (krb5_get_init_creds_opt */*opt*/); - -void KRB5_LIB_FUNCTION -_krb5_get_init_creds_opt_set_krb5_error ( - krb5_context /*context*/, - krb5_get_init_creds_opt */*opt*/, - const KRB_ERROR */*error*/); - -krb5_ssize_t KRB5_LIB_FUNCTION -_krb5_get_int ( - void */*buffer*/, - unsigned long */*value*/, - size_t /*size*/); - -krb5_error_code -_krb5_get_krbtgt ( - krb5_context /*context*/, - krb5_ccache /*id*/, - krb5_realm /*realm*/, - krb5_creds **/*cred*/); - -krb5_error_code -_krb5_kcm_chmod ( - krb5_context /*context*/, - krb5_ccache /*id*/, - uint16_t /*mode*/); - -krb5_error_code -_krb5_kcm_chown ( - krb5_context /*context*/, - krb5_ccache /*id*/, - uint32_t /*uid*/, - uint32_t /*gid*/); - -krb5_error_code -_krb5_kcm_get_initial_ticket ( - krb5_context /*context*/, - krb5_ccache /*id*/, - krb5_principal /*server*/, - krb5_keyblock */*key*/); - -krb5_error_code -_krb5_kcm_get_ticket ( - krb5_context /*context*/, - krb5_ccache /*id*/, - krb5_kdc_flags /*flags*/, - krb5_enctype /*enctype*/, - krb5_principal /*server*/); - -krb5_boolean -_krb5_kcm_is_running (krb5_context /*context*/); - -krb5_error_code -_krb5_kcm_noop ( - krb5_context /*context*/, - krb5_ccache /*id*/); - -krb5_error_code -_krb5_kdc_retry ( - krb5_context /*context*/, - krb5_sendto_ctx /*ctx*/, - void */*data*/, - const krb5_data */*reply*/, - int */*action*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_krb_cr_err_reply ( - krb5_context /*context*/, - const char */*name*/, - const char */*inst*/, - const char */*realm*/, - uint32_t /*time_ws*/, - uint32_t /*e*/, - const char */*e_string*/, - krb5_data */*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_krb_create_auth_reply ( - krb5_context /*context*/, - const char */*pname*/, - const char */*pinst*/, - const char */*prealm*/, - int32_t /*time_ws*/, - int /*n*/, - uint32_t /*x_date*/, - unsigned char /*kvno*/, - const krb5_data */*cipher*/, - krb5_data */*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_krb_create_ciph ( - krb5_context /*context*/, - const krb5_keyblock */*session*/, - const char */*service*/, - const char */*instance*/, - const char */*realm*/, - uint32_t /*life*/, - unsigned char /*kvno*/, - const krb5_data */*ticket*/, - uint32_t /*kdc_time*/, - const krb5_keyblock */*key*/, - krb5_data */*enc_data*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_krb_create_ticket ( - krb5_context /*context*/, - unsigned char /*flags*/, - const char */*pname*/, - const char */*pinstance*/, - const char */*prealm*/, - int32_t /*paddress*/, - const krb5_keyblock */*session*/, - int16_t /*life*/, - int32_t /*life_sec*/, - const char */*sname*/, - const char */*sinstance*/, - const krb5_keyblock */*key*/, - krb5_data */*enc_data*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_krb_decomp_ticket ( - krb5_context /*context*/, - const krb5_data */*enc_ticket*/, - const krb5_keyblock */*key*/, - const char */*local_realm*/, - char **/*sname*/, - char **/*sinstance*/, - struct _krb5_krb_auth_data */*ad*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_krb_dest_tkt ( - krb5_context /*context*/, - const char */*tkfile*/); - -void KRB5_LIB_FUNCTION -_krb5_krb_free_auth_data ( - krb5_context /*context*/, - struct _krb5_krb_auth_data */*ad*/); - -time_t KRB5_LIB_FUNCTION -_krb5_krb_life_to_time ( - int /*start*/, - int /*life_*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_krb_rd_req ( - krb5_context /*context*/, - krb5_data */*authent*/, - const char */*service*/, - const char */*instance*/, - const char */*local_realm*/, - int32_t /*from_addr*/, - const krb5_keyblock */*key*/, - struct _krb5_krb_auth_data */*ad*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_krb_tf_setup ( - krb5_context /*context*/, - struct credentials */*v4creds*/, - const char */*tkfile*/, - int /*append*/); - -int KRB5_LIB_FUNCTION -_krb5_krb_time_to_life ( - time_t /*start*/, - time_t /*end*/); - -krb5_error_code -_krb5_krbhost_info_move ( - krb5_context /*context*/, - krb5_krbhst_info */*from*/, - krb5_krbhst_info **/*to*/); - -krb5_error_code -_krb5_mk_req_internal ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/, - const krb5_flags /*ap_req_options*/, - krb5_data */*in_data*/, - krb5_creds */*in_creds*/, - krb5_data */*outbuf*/, - krb5_key_usage /*checksum_usage*/, - krb5_key_usage /*encrypt_usage*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_n_fold ( - const void */*str*/, - size_t /*len*/, - void */*key*/, - size_t /*size*/); - -krb5_error_code -_krb5_pac_sign ( - krb5_context /*context*/, - krb5_pac /*p*/, - time_t /*authtime*/, - krb5_principal /*principal*/, - const krb5_keyblock */*server_key*/, - const krb5_keyblock */*priv_key*/, - krb5_data */*data*/); - -krb5_error_code -_krb5_parse_moduli ( - krb5_context /*context*/, - const char */*file*/, - struct krb5_dh_moduli ***/*moduli*/); - -krb5_error_code -_krb5_parse_moduli_line ( - krb5_context /*context*/, - const char */*file*/, - int /*lineno*/, - char */*p*/, - struct krb5_dh_moduli **/*m*/); - -void KRB5_LIB_FUNCTION -_krb5_pk_allow_proxy_certificate ( - struct krb5_pk_identity */*id*/, - int /*boolean*/); - -void KRB5_LIB_FUNCTION -_krb5_pk_cert_free (struct krb5_pk_cert */*cert*/); - -krb5_error_code -_krb5_pk_kdf ( - krb5_context /*context*/, - const struct AlgorithmIdentifier */*ai*/, - const void */*dhdata*/, - size_t /*dhsize*/, - krb5_const_principal /*client*/, - krb5_const_principal /*server*/, - krb5_enctype /*enctype*/, - const krb5_data */*as_req*/, - const krb5_data */*pk_as_rep*/, - const Ticket */*ticket*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_pk_load_id ( - krb5_context /*context*/, - struct krb5_pk_identity **/*ret_id*/, - const char */*user_id*/, - const char */*anchor_id*/, - char * const */*chain_list*/, - char * const */*revoke_list*/, - krb5_prompter_fct /*prompter*/, - void */*prompter_data*/, - char */*password*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_pk_mk_ContentInfo ( - krb5_context /*context*/, - const krb5_data */*buf*/, - const heim_oid */*oid*/, - struct ContentInfo */*content_info*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_pk_mk_padata ( - krb5_context /*context*/, - void */*c*/, - const KDC_REQ_BODY */*req_body*/, - unsigned /*nonce*/, - METHOD_DATA */*md*/); - -krb5_error_code -_krb5_pk_octetstring2key ( - krb5_context /*context*/, - krb5_enctype /*type*/, - const void */*dhdata*/, - size_t /*dhsize*/, - const heim_octet_string */*c_n*/, - const heim_octet_string */*k_n*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_pk_rd_pa_reply ( - krb5_context /*context*/, - const char */*realm*/, - void */*c*/, - krb5_enctype /*etype*/, - const krb5_krbhst_info */*hi*/, - unsigned /*nonce*/, - const krb5_data */*req_buffer*/, - PA_DATA */*pa*/, - krb5_keyblock **/*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_pk_verify_sign ( - krb5_context /*context*/, - const void */*data*/, - size_t /*length*/, - struct krb5_pk_identity */*id*/, - heim_oid */*contentType*/, - krb5_data */*content*/, - struct krb5_pk_cert **/*signer*/); - -krb5_error_code -_krb5_plugin_find ( - krb5_context /*context*/, - enum krb5_plugin_type /*type*/, - const char */*name*/, - struct krb5_plugin **/*list*/); - -void -_krb5_plugin_free (struct krb5_plugin */*list*/); - -struct krb5_plugin * -_krb5_plugin_get_next (struct krb5_plugin */*p*/); - -void * -_krb5_plugin_get_symbol (struct krb5_plugin */*p*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_principal2principalname ( - PrincipalName */*p*/, - const krb5_principal /*from*/); - -krb5_boolean KRB5_LIB_FUNCTION -_krb5_principal_compare_PrincipalName ( - krb5_context /*context*/, - krb5_const_principal /*princ1*/, - PrincipalName */*princ2*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_principalname2krb5_principal ( - krb5_context /*context*/, - krb5_principal */*principal*/, - const PrincipalName /*from*/, - const Realm /*realm*/); - -krb5_ssize_t KRB5_LIB_FUNCTION -_krb5_put_int ( - void */*buffer*/, - unsigned long /*value*/, - size_t /*size*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_rd_req_out_ctx_alloc ( - krb5_context /*context*/, - krb5_rd_req_out_ctx */*ctx*/); - -krb5_error_code KRB5_LIB_FUNCTION -_krb5_s4u2self_to_checksumdata ( - krb5_context /*context*/, - const PA_S4U2Self */*self*/, - krb5_data */*data*/); - -int -_krb5_send_and_recv_tcp ( - int /*fd*/, - time_t /*tmout*/, - const krb5_data */*req*/, - krb5_data */*rep*/); - -int -_krb5_xlock ( - krb5_context /*context*/, - int /*fd*/, - krb5_boolean /*exclusive*/, - const char */*filename*/); - -int -_krb5_xunlock ( - krb5_context /*context*/, - int /*fd*/); - -#endif /* __krb5_private_h__ */ diff --git a/source4/heimdal/lib/krb5/krb5-protos.h b/source4/heimdal/lib/krb5/krb5-protos.h deleted file mode 100644 index ead66565e7..0000000000 --- a/source4/heimdal/lib/krb5/krb5-protos.h +++ /dev/null @@ -1,4169 +0,0 @@ -/* This is a generated file */ -#ifndef __krb5_protos_h__ -#define __krb5_protos_h__ - -#include - -#if !defined(__GNUC__) && !defined(__attribute__) -#define __attribute__(x) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef KRB5_LIB -#if defined(_WIN32) -#define KRB5_LIB_FUNCTION _stdcall __declspec(dllimport) -#define KRB5_LIB_VARIABLE __declspec(dllimport) -#else -#define KRB5_LIB_FUNCTION -#define KRB5_LIB_VARIABLE -#endif -#endif - -krb5_error_code KRB5_LIB_FUNCTION -krb524_convert_creds_kdc ( - krb5_context /*context*/, - krb5_creds */*in_cred*/, - struct credentials */*v4creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb524_convert_creds_kdc_ccache ( - krb5_context /*context*/, - krb5_ccache /*ccache*/, - krb5_creds */*in_cred*/, - struct credentials */*v4creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_425_conv_principal ( - krb5_context /*context*/, - const char */*name*/, - const char */*instance*/, - const char */*realm*/, - krb5_principal */*princ*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_425_conv_principal_ext ( - krb5_context /*context*/, - const char */*name*/, - const char */*instance*/, - const char */*realm*/, - krb5_boolean (*/*func*/)(krb5_context, krb5_principal), - krb5_boolean /*resolve*/, - krb5_principal */*principal*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_425_conv_principal_ext2 ( - krb5_context /*context*/, - const char */*name*/, - const char */*instance*/, - const char */*realm*/, - krb5_boolean (*/*func*/)(krb5_context, void *, krb5_principal), - void */*funcctx*/, - krb5_boolean /*resolve*/, - krb5_principal */*princ*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_524_conv_principal ( - krb5_context /*context*/, - const krb5_principal /*principal*/, - char */*name*/, - char */*instance*/, - char */*realm*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_abort ( - krb5_context /*context*/, - krb5_error_code /*code*/, - const char */*fmt*/, - ...) - __attribute__ ((noreturn, format (printf, 3, 4))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_abortx ( - krb5_context /*context*/, - const char */*fmt*/, - ...) - __attribute__ ((noreturn, format (printf, 2, 3))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_acl_match_file ( - krb5_context /*context*/, - const char */*file*/, - const char */*format*/, - ...); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_acl_match_string ( - krb5_context /*context*/, - const char */*string*/, - const char */*format*/, - ...); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_add_et_list ( - krb5_context /*context*/, - void (*/*func*/)(struct et_list **)); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_add_extra_addresses ( - krb5_context /*context*/, - krb5_addresses */*addresses*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_add_ignore_addresses ( - krb5_context /*context*/, - krb5_addresses */*addresses*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_addlog_dest ( - krb5_context /*context*/, - krb5_log_facility */*f*/, - const char */*orig*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_addlog_func ( - krb5_context /*context*/, - krb5_log_facility */*fac*/, - int /*min*/, - int /*max*/, - krb5_log_log_func_t /*log_func*/, - krb5_log_close_func_t /*close_func*/, - void */*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_addr2sockaddr ( - krb5_context /*context*/, - const krb5_address */*addr*/, - struct sockaddr */*sa*/, - krb5_socklen_t */*sa_size*/, - int /*port*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_address_compare ( - krb5_context /*context*/, - const krb5_address */*addr1*/, - const krb5_address */*addr2*/); - -int KRB5_LIB_FUNCTION -krb5_address_order ( - krb5_context /*context*/, - const krb5_address */*addr1*/, - const krb5_address */*addr2*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_address_prefixlen_boundary ( - krb5_context /*context*/, - const krb5_address */*inaddr*/, - unsigned long /*prefixlen*/, - krb5_address */*low*/, - krb5_address */*high*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_address_search ( - krb5_context /*context*/, - const krb5_address */*addr*/, - const krb5_addresses */*addrlist*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_aname_to_localname ( - krb5_context /*context*/, - krb5_const_principal /*aname*/, - size_t /*lnsize*/, - char */*lname*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_anyaddr ( - krb5_context /*context*/, - int /*af*/, - struct sockaddr */*sa*/, - krb5_socklen_t */*sa_size*/, - int /*port*/); - -void KRB5_LIB_FUNCTION -krb5_appdefault_boolean ( - krb5_context /*context*/, - const char */*appname*/, - krb5_const_realm /*realm*/, - const char */*option*/, - krb5_boolean /*def_val*/, - krb5_boolean */*ret_val*/); - -void KRB5_LIB_FUNCTION -krb5_appdefault_string ( - krb5_context /*context*/, - const char */*appname*/, - krb5_const_realm /*realm*/, - const char */*option*/, - const char */*def_val*/, - char **/*ret_val*/); - -void KRB5_LIB_FUNCTION -krb5_appdefault_time ( - krb5_context /*context*/, - const char */*appname*/, - krb5_const_realm /*realm*/, - const char */*option*/, - time_t /*def_val*/, - time_t */*ret_val*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_append_addresses ( - krb5_context /*context*/, - krb5_addresses */*dest*/, - const krb5_addresses */*source*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_addflags ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - int32_t /*addflags*/, - int32_t */*flags*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_free ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_genaddrs ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - int /*fd*/, - int /*flags*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_generatelocalsubkey ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_getaddrs ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_address **/*local_addr*/, - krb5_address **/*remote_addr*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_getauthenticator ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_authenticator */*authenticator*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_getcksumtype ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_cksumtype */*cksumtype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_getflags ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - int32_t */*flags*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_getkey ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_keyblock **/*keyblock*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_getkeytype ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_keytype */*keytype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_getlocalseqnumber ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - int32_t */*seqnumber*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_getlocalsubkey ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_keyblock **/*keyblock*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_getrcache ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_rcache */*rcache*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_getremotesubkey ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_keyblock **/*keyblock*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_init ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_removeflags ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - int32_t /*removeflags*/, - int32_t */*flags*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_setaddrs ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_address */*local_addr*/, - krb5_address */*remote_addr*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_setaddrs_from_fd ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - void */*p_fd*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_setcksumtype ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_cksumtype /*cksumtype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_setflags ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - int32_t /*flags*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_setkey ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_keyblock */*keyblock*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_setkeytype ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_keytype /*keytype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_setlocalseqnumber ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - int32_t /*seqnumber*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_setlocalsubkey ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_keyblock */*keyblock*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_setrcache ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_rcache /*rcache*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_setremoteseqnumber ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - int32_t /*seqnumber*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_setremotesubkey ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_keyblock */*keyblock*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_con_setuserkey ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_keyblock */*keyblock*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_auth_getremoteseqnumber ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - int32_t */*seqnumber*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_build_ap_req ( - krb5_context /*context*/, - krb5_enctype /*enctype*/, - krb5_creds */*cred*/, - krb5_flags /*ap_options*/, - krb5_data /*authenticator*/, - krb5_data */*retdata*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_build_authenticator ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_enctype /*enctype*/, - krb5_creds */*cred*/, - Checksum */*cksum*/, - Authenticator **/*auth_result*/, - krb5_data */*result*/, - krb5_key_usage /*usage*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_build_principal ( - krb5_context /*context*/, - krb5_principal */*principal*/, - int /*rlen*/, - krb5_const_realm /*realm*/, - ...); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_build_principal_ext ( - krb5_context /*context*/, - krb5_principal */*principal*/, - int /*rlen*/, - krb5_const_realm /*realm*/, - ...); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_build_principal_va ( - krb5_context /*context*/, - krb5_principal */*principal*/, - int /*rlen*/, - krb5_const_realm /*realm*/, - va_list /*ap*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_build_principal_va_ext ( - krb5_context /*context*/, - krb5_principal */*principal*/, - int /*rlen*/, - krb5_const_realm /*realm*/, - va_list /*ap*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_block_size ( - krb5_context /*context*/, - krb5_enctype /*enctype*/, - size_t */*blocksize*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_checksum_length ( - krb5_context /*context*/, - krb5_cksumtype /*cksumtype*/, - size_t */*length*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_decrypt ( - krb5_context /*context*/, - const krb5_keyblock /*key*/, - krb5_keyusage /*usage*/, - const krb5_data */*ivec*/, - krb5_enc_data */*input*/, - krb5_data */*output*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_encrypt ( - krb5_context /*context*/, - const krb5_keyblock */*key*/, - krb5_keyusage /*usage*/, - const krb5_data */*ivec*/, - const krb5_data */*input*/, - krb5_enc_data */*output*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_encrypt_length ( - krb5_context /*context*/, - krb5_enctype /*enctype*/, - size_t /*inputlen*/, - size_t */*length*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_enctype_compare ( - krb5_context /*context*/, - krb5_enctype /*e1*/, - krb5_enctype /*e2*/, - krb5_boolean */*similar*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_get_checksum ( - krb5_context /*context*/, - const krb5_checksum */*cksum*/, - krb5_cksumtype */*type*/, - krb5_data **/*data*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_c_is_coll_proof_cksum (krb5_cksumtype /*ctype*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_c_is_keyed_cksum (krb5_cksumtype /*ctype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_keylengths ( - krb5_context /*context*/, - krb5_enctype /*enctype*/, - size_t */*ilen*/, - size_t */*keylen*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_make_checksum ( - krb5_context /*context*/, - krb5_cksumtype /*cksumtype*/, - const krb5_keyblock */*key*/, - krb5_keyusage /*usage*/, - const krb5_data */*input*/, - krb5_checksum */*cksum*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_make_random_key ( - krb5_context /*context*/, - krb5_enctype /*enctype*/, - krb5_keyblock */*random_key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_prf ( - krb5_context /*context*/, - const krb5_keyblock */*key*/, - const krb5_data */*input*/, - krb5_data */*output*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_prf_length ( - krb5_context /*context*/, - krb5_enctype /*type*/, - size_t */*length*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_set_checksum ( - krb5_context /*context*/, - krb5_checksum */*cksum*/, - krb5_cksumtype /*type*/, - const krb5_data */*data*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_c_valid_cksumtype (krb5_cksumtype /*ctype*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_c_valid_enctype (krb5_enctype /*etype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_c_verify_checksum ( - krb5_context /*context*/, - const krb5_keyblock */*key*/, - krb5_keyusage /*usage*/, - const krb5_data */*data*/, - const krb5_checksum */*cksum*/, - krb5_boolean */*valid*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_cache_end_seq_get ( - krb5_context /*context*/, - krb5_cc_cache_cursor /*cursor*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_cache_get_first ( - krb5_context /*context*/, - const char */*type*/, - krb5_cc_cache_cursor */*cursor*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_cache_match ( - krb5_context /*context*/, - krb5_principal /*client*/, - const char */*type*/, - krb5_ccache */*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_cache_next ( - krb5_context /*context*/, - krb5_cc_cache_cursor /*cursor*/, - krb5_ccache */*id*/); - -void KRB5_LIB_FUNCTION -krb5_cc_clear_mcred (krb5_creds */*mcred*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_close ( - krb5_context /*context*/, - krb5_ccache /*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_copy_cache ( - krb5_context /*context*/, - const krb5_ccache /*from*/, - krb5_ccache /*to*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_copy_cache_match ( - krb5_context /*context*/, - const krb5_ccache /*from*/, - krb5_ccache /*to*/, - krb5_flags /*whichfields*/, - const krb5_creds * /*mcreds*/, - unsigned int */*matched*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_default ( - krb5_context /*context*/, - krb5_ccache */*id*/); - -const char* KRB5_LIB_FUNCTION -krb5_cc_default_name (krb5_context /*context*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_destroy ( - krb5_context /*context*/, - krb5_ccache /*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_end_seq_get ( - krb5_context /*context*/, - const krb5_ccache /*id*/, - krb5_cc_cursor */*cursor*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_gen_new ( - krb5_context /*context*/, - const krb5_cc_ops */*ops*/, - krb5_ccache */*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_get_config ( - krb5_context /*context*/, - krb5_ccache /*id*/, - krb5_const_principal /*principal*/, - const char */*name*/, - krb5_data */*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_get_full_name ( - krb5_context /*context*/, - krb5_ccache /*id*/, - char **/*str*/); - -const char* KRB5_LIB_FUNCTION -krb5_cc_get_name ( - krb5_context /*context*/, - krb5_ccache /*id*/); - -const krb5_cc_ops * -krb5_cc_get_ops ( - krb5_context /*context*/, - krb5_ccache /*id*/); - -const krb5_cc_ops * -krb5_cc_get_prefix_ops ( - krb5_context /*context*/, - const char */*prefix*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_get_principal ( - krb5_context /*context*/, - krb5_ccache /*id*/, - krb5_principal */*principal*/); - -const char* KRB5_LIB_FUNCTION -krb5_cc_get_type ( - krb5_context /*context*/, - krb5_ccache /*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_get_version ( - krb5_context /*context*/, - const krb5_ccache /*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_initialize ( - krb5_context /*context*/, - krb5_ccache /*id*/, - krb5_principal /*primary_principal*/); - -krb5_error_code -krb5_cc_move ( - krb5_context /*context*/, - krb5_ccache /*from*/, - krb5_ccache /*to*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_new_unique ( - krb5_context /*context*/, - const char */*type*/, - const char */*hint*/, - krb5_ccache */*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_next_cred ( - krb5_context /*context*/, - const krb5_ccache /*id*/, - krb5_cc_cursor */*cursor*/, - krb5_creds */*creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_next_cred_match ( - krb5_context /*context*/, - const krb5_ccache /*id*/, - krb5_cc_cursor * /*cursor*/, - krb5_creds * /*creds*/, - krb5_flags /*whichfields*/, - const krb5_creds * /*mcreds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_register ( - krb5_context /*context*/, - const krb5_cc_ops */*ops*/, - krb5_boolean /*override*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_remove_cred ( - krb5_context /*context*/, - krb5_ccache /*id*/, - krb5_flags /*which*/, - krb5_creds */*cred*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_resolve ( - krb5_context /*context*/, - const char */*name*/, - krb5_ccache */*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_retrieve_cred ( - krb5_context /*context*/, - krb5_ccache /*id*/, - krb5_flags /*whichfields*/, - const krb5_creds */*mcreds*/, - krb5_creds */*creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_set_config ( - krb5_context /*context*/, - krb5_ccache /*id*/, - krb5_const_principal /*principal*/, - const char */*name*/, - krb5_data */*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_set_default_name ( - krb5_context /*context*/, - const char */*name*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_set_flags ( - krb5_context /*context*/, - krb5_ccache /*id*/, - krb5_flags /*flags*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_start_seq_get ( - krb5_context /*context*/, - const krb5_ccache /*id*/, - krb5_cc_cursor */*cursor*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cc_store_cred ( - krb5_context /*context*/, - krb5_ccache /*id*/, - krb5_creds */*creds*/); - -krb5_error_code -krb5_cc_switch ( - krb5_context /*context*/, - krb5_ccache /*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_change_password ( - krb5_context /*context*/, - krb5_creds */*creds*/, - const char */*newpw*/, - int */*result_code*/, - krb5_data */*result_code_string*/, - krb5_data */*result_string*/) - __attribute__((deprecated)); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_check_transited ( - krb5_context /*context*/, - krb5_const_realm /*client_realm*/, - krb5_const_realm /*server_realm*/, - krb5_realm */*realms*/, - unsigned int /*num_realms*/, - int */*bad_realm*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_check_transited_realms ( - krb5_context /*context*/, - const char *const */*realms*/, - unsigned int /*num_realms*/, - int */*bad_realm*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_checksum_disable ( - krb5_context /*context*/, - krb5_cksumtype /*type*/); - -void KRB5_LIB_FUNCTION -krb5_checksum_free ( - krb5_context /*context*/, - krb5_checksum */*cksum*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_checksum_is_collision_proof ( - krb5_context /*context*/, - krb5_cksumtype /*type*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_checksum_is_keyed ( - krb5_context /*context*/, - krb5_cksumtype /*type*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_checksumsize ( - krb5_context /*context*/, - krb5_cksumtype /*type*/, - size_t */*size*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_cksumtype_valid ( - krb5_context /*context*/, - krb5_cksumtype /*ctype*/); - -void KRB5_LIB_FUNCTION -krb5_clear_error_string (krb5_context /*context*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_closelog ( - krb5_context /*context*/, - krb5_log_facility */*fac*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_compare_creds ( - krb5_context /*context*/, - krb5_flags /*whichfields*/, - const krb5_creds * /*mcreds*/, - const krb5_creds * /*creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_config_file_free ( - krb5_context /*context*/, - krb5_config_section */*s*/); - -void KRB5_LIB_FUNCTION -krb5_config_free_strings (char **/*strings*/); - -const void * -krb5_config_get ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - int /*type*/, - ...); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_config_get_bool ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - ...); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_config_get_bool_default ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - krb5_boolean /*def_value*/, - ...); - -int KRB5_LIB_FUNCTION -krb5_config_get_int ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - ...); - -int KRB5_LIB_FUNCTION -krb5_config_get_int_default ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - int /*def_value*/, - ...); - -const krb5_config_binding * -krb5_config_get_list ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - ...); - -const void * -krb5_config_get_next ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - const krb5_config_binding **/*pointer*/, - int /*type*/, - ...); - -const char* KRB5_LIB_FUNCTION -krb5_config_get_string ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - ...); - -const char* KRB5_LIB_FUNCTION -krb5_config_get_string_default ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - const char */*def_value*/, - ...); - -char** -krb5_config_get_strings ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - ...); - -int KRB5_LIB_FUNCTION -krb5_config_get_time ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - ...); - -int KRB5_LIB_FUNCTION -krb5_config_get_time_default ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - int /*def_value*/, - ...); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_config_parse_file ( - krb5_context /*context*/, - const char */*fname*/, - krb5_config_section **/*res*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_config_parse_file_multi ( - krb5_context /*context*/, - const char */*fname*/, - krb5_config_section **/*res*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_config_parse_string_multi ( - krb5_context /*context*/, - const char */*string*/, - krb5_config_section **/*res*/); - -const void * -krb5_config_vget ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - int /*type*/, - va_list /*args*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_config_vget_bool ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - va_list /*args*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_config_vget_bool_default ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - krb5_boolean /*def_value*/, - va_list /*args*/); - -int KRB5_LIB_FUNCTION -krb5_config_vget_int ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - va_list /*args*/); - -int KRB5_LIB_FUNCTION -krb5_config_vget_int_default ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - int /*def_value*/, - va_list /*args*/); - -const krb5_config_binding * -krb5_config_vget_list ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - va_list /*args*/); - -const void * -krb5_config_vget_next ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - const krb5_config_binding **/*pointer*/, - int /*type*/, - va_list /*args*/); - -const char* KRB5_LIB_FUNCTION -krb5_config_vget_string ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - va_list /*args*/); - -const char* KRB5_LIB_FUNCTION -krb5_config_vget_string_default ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - const char */*def_value*/, - va_list /*args*/); - -char ** KRB5_LIB_FUNCTION -krb5_config_vget_strings ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - va_list /*args*/); - -int KRB5_LIB_FUNCTION -krb5_config_vget_time ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - va_list /*args*/); - -int KRB5_LIB_FUNCTION -krb5_config_vget_time_default ( - krb5_context /*context*/, - const krb5_config_section */*c*/, - int /*def_value*/, - va_list /*args*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_copy_address ( - krb5_context /*context*/, - const krb5_address */*inaddr*/, - krb5_address */*outaddr*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_copy_addresses ( - krb5_context /*context*/, - const krb5_addresses */*inaddr*/, - krb5_addresses */*outaddr*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_copy_checksum ( - krb5_context /*context*/, - const krb5_checksum */*old*/, - krb5_checksum **/*new*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_copy_creds ( - krb5_context /*context*/, - const krb5_creds */*incred*/, - krb5_creds **/*outcred*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_copy_creds_contents ( - krb5_context /*context*/, - const krb5_creds */*incred*/, - krb5_creds */*c*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_copy_data ( - krb5_context /*context*/, - const krb5_data */*indata*/, - krb5_data **/*outdata*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_copy_host_realm ( - krb5_context /*context*/, - const krb5_realm */*from*/, - krb5_realm **/*to*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_copy_keyblock ( - krb5_context /*context*/, - const krb5_keyblock */*inblock*/, - krb5_keyblock **/*to*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_copy_keyblock_contents ( - krb5_context /*context*/, - const krb5_keyblock */*inblock*/, - krb5_keyblock */*to*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_copy_principal ( - krb5_context /*context*/, - krb5_const_principal /*inprinc*/, - krb5_principal */*outprinc*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_copy_ticket ( - krb5_context /*context*/, - const krb5_ticket */*from*/, - krb5_ticket **/*to*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_create_checksum ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - krb5_key_usage /*usage*/, - int /*type*/, - void */*data*/, - size_t /*len*/, - Checksum */*result*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_destroy ( - krb5_context /*context*/, - krb5_crypto /*crypto*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_get_checksum_type ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - krb5_cksumtype */*type*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_getblocksize ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - size_t */*blocksize*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_getconfoundersize ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - size_t */*confoundersize*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_getenctype ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - krb5_enctype */*enctype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_getpadsize ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - size_t */*padsize*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_init ( - krb5_context /*context*/, - const krb5_keyblock */*key*/, - krb5_enctype /*etype*/, - krb5_crypto */*crypto*/); - -size_t -krb5_crypto_overhead ( - krb5_context /*context*/, - krb5_crypto /*crypto*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_prf ( - krb5_context /*context*/, - const krb5_crypto /*crypto*/, - const krb5_data */*input*/, - krb5_data */*output*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_crypto_prf_length ( - krb5_context /*context*/, - krb5_enctype /*type*/, - size_t */*length*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_data_alloc ( - krb5_data */*p*/, - int /*len*/); - -int KRB5_LIB_FUNCTION -krb5_data_cmp ( - const krb5_data */*data1*/, - const krb5_data */*data2*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_data_copy ( - krb5_data */*p*/, - const void */*data*/, - size_t /*len*/); - -void KRB5_LIB_FUNCTION -krb5_data_free (krb5_data */*p*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_data_realloc ( - krb5_data */*p*/, - int /*len*/); - -void KRB5_LIB_FUNCTION -krb5_data_zero (krb5_data */*p*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decode_Authenticator ( - krb5_context /*context*/, - const void */*data*/, - size_t /*length*/, - Authenticator */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decode_ETYPE_INFO ( - krb5_context /*context*/, - const void */*data*/, - size_t /*length*/, - ETYPE_INFO */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decode_ETYPE_INFO2 ( - krb5_context /*context*/, - const void */*data*/, - size_t /*length*/, - ETYPE_INFO2 */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decode_EncAPRepPart ( - krb5_context /*context*/, - const void */*data*/, - size_t /*length*/, - EncAPRepPart */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decode_EncASRepPart ( - krb5_context /*context*/, - const void */*data*/, - size_t /*length*/, - EncASRepPart */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decode_EncKrbCredPart ( - krb5_context /*context*/, - const void */*data*/, - size_t /*length*/, - EncKrbCredPart */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decode_EncTGSRepPart ( - krb5_context /*context*/, - const void */*data*/, - size_t /*length*/, - EncTGSRepPart */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decode_EncTicketPart ( - krb5_context /*context*/, - const void */*data*/, - size_t /*length*/, - EncTicketPart */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decode_ap_req ( - krb5_context /*context*/, - const krb5_data */*inbuf*/, - krb5_ap_req */*ap_req*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decrypt ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - unsigned /*usage*/, - void */*data*/, - size_t /*len*/, - krb5_data */*result*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decrypt_EncryptedData ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - unsigned /*usage*/, - const EncryptedData */*e*/, - krb5_data */*result*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decrypt_ivec ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - unsigned /*usage*/, - void */*data*/, - size_t /*len*/, - krb5_data */*result*/, - void */*ivec*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_decrypt_ticket ( - krb5_context /*context*/, - Ticket */*ticket*/, - krb5_keyblock */*key*/, - EncTicketPart */*out*/, - krb5_flags /*flags*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_derive_key ( - krb5_context /*context*/, - const krb5_keyblock */*key*/, - krb5_enctype /*etype*/, - const void */*constant*/, - size_t /*constant_len*/, - krb5_keyblock **/*derived_key*/); - -krb5_error_code -krb5_digest_alloc ( - krb5_context /*context*/, - krb5_digest */*digest*/); - -void -krb5_digest_free (krb5_digest /*digest*/); - -krb5_error_code -krb5_digest_get_client_binding ( - krb5_context /*context*/, - krb5_digest /*digest*/, - char **/*type*/, - char **/*binding*/); - -const char * -krb5_digest_get_identifier ( - krb5_context /*context*/, - krb5_digest /*digest*/); - -const char * -krb5_digest_get_opaque ( - krb5_context /*context*/, - krb5_digest /*digest*/); - -const char * -krb5_digest_get_rsp ( - krb5_context /*context*/, - krb5_digest /*digest*/); - -const char * -krb5_digest_get_server_nonce ( - krb5_context /*context*/, - krb5_digest /*digest*/); - -krb5_error_code -krb5_digest_get_session_key ( - krb5_context /*context*/, - krb5_digest /*digest*/, - krb5_data */*data*/); - -krb5_error_code -krb5_digest_get_tickets ( - krb5_context /*context*/, - krb5_digest /*digest*/, - Ticket **/*tickets*/); - -krb5_error_code -krb5_digest_init_request ( - krb5_context /*context*/, - krb5_digest /*digest*/, - krb5_realm /*realm*/, - krb5_ccache /*ccache*/); - -krb5_error_code -krb5_digest_probe ( - krb5_context /*context*/, - krb5_realm /*realm*/, - krb5_ccache /*ccache*/, - unsigned */*flags*/); - -krb5_boolean -krb5_digest_rep_get_status ( - krb5_context /*context*/, - krb5_digest /*digest*/); - -krb5_error_code -krb5_digest_request ( - krb5_context /*context*/, - krb5_digest /*digest*/, - krb5_realm /*realm*/, - krb5_ccache /*ccache*/); - -krb5_error_code -krb5_digest_set_authentication_user ( - krb5_context /*context*/, - krb5_digest /*digest*/, - krb5_principal /*authentication_user*/); - -krb5_error_code -krb5_digest_set_authid ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*authid*/); - -krb5_error_code -krb5_digest_set_client_nonce ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*nonce*/); - -krb5_error_code -krb5_digest_set_digest ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*dgst*/); - -krb5_error_code -krb5_digest_set_hostname ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*hostname*/); - -krb5_error_code -krb5_digest_set_identifier ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*id*/); - -krb5_error_code -krb5_digest_set_method ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*method*/); - -krb5_error_code -krb5_digest_set_nonceCount ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*nonce_count*/); - -krb5_error_code -krb5_digest_set_opaque ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*opaque*/); - -krb5_error_code -krb5_digest_set_qop ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*qop*/); - -krb5_error_code -krb5_digest_set_realm ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*realm*/); - -int -krb5_digest_set_responseData ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*response*/); - -krb5_error_code -krb5_digest_set_server_cb ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*type*/, - const char */*binding*/); - -krb5_error_code -krb5_digest_set_server_nonce ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*nonce*/); - -krb5_error_code -krb5_digest_set_type ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*type*/); - -krb5_error_code -krb5_digest_set_uri ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*uri*/); - -krb5_error_code -krb5_digest_set_username ( - krb5_context /*context*/, - krb5_digest /*digest*/, - const char */*username*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_domain_x500_decode ( - krb5_context /*context*/, - krb5_data /*tr*/, - char ***/*realms*/, - unsigned int */*num_realms*/, - const char */*client_realm*/, - const char */*server_realm*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_domain_x500_encode ( - char **/*realms*/, - unsigned int /*num_realms*/, - krb5_data */*encoding*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_eai_to_heim_errno ( - int /*eai_errno*/, - int /*system_error*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_encode_Authenticator ( - krb5_context /*context*/, - void */*data*/, - size_t /*length*/, - Authenticator */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_encode_ETYPE_INFO ( - krb5_context /*context*/, - void */*data*/, - size_t /*length*/, - ETYPE_INFO */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_encode_ETYPE_INFO2 ( - krb5_context /*context*/, - void */*data*/, - size_t /*length*/, - ETYPE_INFO2 */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_encode_EncAPRepPart ( - krb5_context /*context*/, - void */*data*/, - size_t /*length*/, - EncAPRepPart */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_encode_EncASRepPart ( - krb5_context /*context*/, - void */*data*/, - size_t /*length*/, - EncASRepPart */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_encode_EncKrbCredPart ( - krb5_context /*context*/, - void */*data*/, - size_t /*length*/, - EncKrbCredPart */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_encode_EncTGSRepPart ( - krb5_context /*context*/, - void */*data*/, - size_t /*length*/, - EncTGSRepPart */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_encode_EncTicketPart ( - krb5_context /*context*/, - void */*data*/, - size_t /*length*/, - EncTicketPart */*t*/, - size_t */*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_encrypt ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - unsigned /*usage*/, - const void */*data*/, - size_t /*len*/, - krb5_data */*result*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_encrypt_EncryptedData ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - unsigned /*usage*/, - void */*data*/, - size_t /*len*/, - int /*kvno*/, - EncryptedData */*result*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_encrypt_ivec ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - unsigned /*usage*/, - const void */*data*/, - size_t /*len*/, - krb5_data */*result*/, - void */*ivec*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_enctype_disable ( - krb5_context /*context*/, - krb5_enctype /*enctype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_enctype_keybits ( - krb5_context /*context*/, - krb5_enctype /*type*/, - size_t */*keybits*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_enctype_keysize ( - krb5_context /*context*/, - krb5_enctype /*type*/, - size_t */*keysize*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_enctype_to_keytype ( - krb5_context /*context*/, - krb5_enctype /*etype*/, - krb5_keytype */*keytype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_enctype_to_string ( - krb5_context /*context*/, - krb5_enctype /*etype*/, - char **/*string*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_enctype_valid ( - krb5_context /*context*/, - krb5_enctype /*etype*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_enctypes_compatible_keys ( - krb5_context /*context*/, - krb5_enctype /*etype1*/, - krb5_enctype /*etype2*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_err ( - krb5_context /*context*/, - int /*eval*/, - krb5_error_code /*code*/, - const char */*fmt*/, - ...) - __attribute__ ((noreturn, format (printf, 4, 5))); - -krb5_error_code KRB5_LIB_FUNCTION - __attribute__((deprecated)) krb5_free_creds_contents (krb5_context context, krb5_creds *c); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_error_from_rd_error ( - krb5_context /*context*/, - const krb5_error */*error*/, - const krb5_creds */*creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_errx ( - krb5_context /*context*/, - int /*eval*/, - const char */*fmt*/, - ...) - __attribute__ ((noreturn, format (printf, 3, 4))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_expand_hostname ( - krb5_context /*context*/, - const char */*orig_hostname*/, - char **/*new_hostname*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_expand_hostname_realms ( - krb5_context /*context*/, - const char */*orig_hostname*/, - char **/*new_hostname*/, - char ***/*realms*/); - -PA_DATA * -krb5_find_padata ( - PA_DATA */*val*/, - unsigned /*len*/, - int /*type*/, - int */*idx*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_format_time ( - krb5_context /*context*/, - time_t /*t*/, - char */*s*/, - size_t /*len*/, - krb5_boolean /*include_time*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_free_address ( - krb5_context /*context*/, - krb5_address */*address*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_free_addresses ( - krb5_context /*context*/, - krb5_addresses */*addresses*/); - -void KRB5_LIB_FUNCTION -krb5_free_ap_rep_enc_part ( - krb5_context /*context*/, - krb5_ap_rep_enc_part */*val*/); - -void KRB5_LIB_FUNCTION -krb5_free_authenticator ( - krb5_context /*context*/, - krb5_authenticator */*authenticator*/); - -void KRB5_LIB_FUNCTION -krb5_free_checksum ( - krb5_context /*context*/, - krb5_checksum */*cksum*/); - -void KRB5_LIB_FUNCTION -krb5_free_checksum_contents ( - krb5_context /*context*/, - krb5_checksum */*cksum*/); - -void KRB5_LIB_FUNCTION -krb5_free_config_files (char **/*filenames*/); - -void KRB5_LIB_FUNCTION -krb5_free_context (krb5_context /*context*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_free_cred_contents ( - krb5_context /*context*/, - krb5_creds */*c*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_free_creds ( - krb5_context /*context*/, - krb5_creds */*c*/); - -void KRB5_LIB_FUNCTION -krb5_free_data ( - krb5_context /*context*/, - krb5_data */*p*/); - -void KRB5_LIB_FUNCTION -krb5_free_data_contents ( - krb5_context /*context*/, - krb5_data */*data*/); - -void KRB5_LIB_FUNCTION -krb5_free_error ( - krb5_context /*context*/, - krb5_error */*error*/); - -void KRB5_LIB_FUNCTION -krb5_free_error_contents ( - krb5_context /*context*/, - krb5_error */*error*/); - -void KRB5_LIB_FUNCTION -krb5_free_error_message ( - krb5_context /*context*/, - const char */*msg*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_free_host_realm ( - krb5_context /*context*/, - krb5_realm */*realmlist*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_free_kdc_rep ( - krb5_context /*context*/, - krb5_kdc_rep */*rep*/); - -void KRB5_LIB_FUNCTION -krb5_free_keyblock ( - krb5_context /*context*/, - krb5_keyblock */*keyblock*/); - -void KRB5_LIB_FUNCTION -krb5_free_keyblock_contents ( - krb5_context /*context*/, - krb5_keyblock */*keyblock*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_free_krbhst ( - krb5_context /*context*/, - char **/*hostlist*/); - -void KRB5_LIB_FUNCTION -krb5_free_principal ( - krb5_context /*context*/, - krb5_principal /*p*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_free_salt ( - krb5_context /*context*/, - krb5_salt /*salt*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_free_ticket ( - krb5_context /*context*/, - krb5_ticket */*ticket*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_fwd_tgt_creds ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - const char */*hostname*/, - krb5_principal /*client*/, - krb5_principal /*server*/, - krb5_ccache /*ccache*/, - int /*forwardable*/, - krb5_data */*out_data*/); - -void KRB5_LIB_FUNCTION -krb5_generate_random_block ( - void */*buf*/, - size_t /*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_generate_random_keyblock ( - krb5_context /*context*/, - krb5_enctype /*type*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_generate_seq_number ( - krb5_context /*context*/, - const krb5_keyblock */*key*/, - uint32_t */*seqno*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_generate_subkey ( - krb5_context /*context*/, - const krb5_keyblock */*key*/, - krb5_keyblock **/*subkey*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_generate_subkey_extended ( - krb5_context /*context*/, - const krb5_keyblock */*key*/, - krb5_enctype /*etype*/, - krb5_keyblock **/*subkey*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_all_client_addrs ( - krb5_context /*context*/, - krb5_addresses */*res*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_all_server_addrs ( - krb5_context /*context*/, - krb5_addresses */*res*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_cred_from_kdc ( - krb5_context /*context*/, - krb5_ccache /*ccache*/, - krb5_creds */*in_creds*/, - krb5_creds **/*out_creds*/, - krb5_creds ***/*ret_tgts*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_cred_from_kdc_opt ( - krb5_context /*context*/, - krb5_ccache /*ccache*/, - krb5_creds */*in_creds*/, - krb5_creds **/*out_creds*/, - krb5_creds ***/*ret_tgts*/, - krb5_flags /*flags*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_credentials ( - krb5_context /*context*/, - krb5_flags /*options*/, - krb5_ccache /*ccache*/, - krb5_creds */*in_creds*/, - krb5_creds **/*out_creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_credentials_with_flags ( - krb5_context /*context*/, - krb5_flags /*options*/, - krb5_kdc_flags /*flags*/, - krb5_ccache /*ccache*/, - krb5_creds */*in_creds*/, - krb5_creds **/*out_creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_creds ( - krb5_context /*context*/, - krb5_get_creds_opt /*opt*/, - krb5_ccache /*ccache*/, - krb5_const_principal /*inprinc*/, - krb5_creds **/*out_creds*/); - -void KRB5_LIB_FUNCTION -krb5_get_creds_opt_add_options ( - krb5_context /*context*/, - krb5_get_creds_opt /*opt*/, - krb5_flags /*options*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_creds_opt_alloc ( - krb5_context /*context*/, - krb5_get_creds_opt */*opt*/); - -void KRB5_LIB_FUNCTION -krb5_get_creds_opt_free ( - krb5_context /*context*/, - krb5_get_creds_opt /*opt*/); - -void KRB5_LIB_FUNCTION -krb5_get_creds_opt_set_enctype ( - krb5_context /*context*/, - krb5_get_creds_opt /*opt*/, - krb5_enctype /*enctype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_creds_opt_set_impersonate ( - krb5_context /*context*/, - krb5_get_creds_opt /*opt*/, - krb5_const_principal /*self*/); - -void KRB5_LIB_FUNCTION -krb5_get_creds_opt_set_options ( - krb5_context /*context*/, - krb5_get_creds_opt /*opt*/, - krb5_flags /*options*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_creds_opt_set_ticket ( - krb5_context /*context*/, - krb5_get_creds_opt /*opt*/, - const Ticket */*ticket*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_default_config_files (char ***/*pfilenames*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_default_in_tkt_etypes ( - krb5_context /*context*/, - krb5_enctype **/*etypes*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_default_principal ( - krb5_context /*context*/, - krb5_principal */*princ*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_default_realm ( - krb5_context /*context*/, - krb5_realm */*realm*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_default_realms ( - krb5_context /*context*/, - krb5_realm **/*realms*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_get_dns_canonicalize_hostname (krb5_context /*context*/); - -const char* KRB5_LIB_FUNCTION -krb5_get_err_text ( - krb5_context /*context*/, - krb5_error_code /*code*/); - -const char * KRB5_LIB_FUNCTION -krb5_get_error_message ( - krb5_context /*context*/, - krb5_error_code /*code*/); - -char * KRB5_LIB_FUNCTION -krb5_get_error_string (krb5_context /*context*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_extra_addresses ( - krb5_context /*context*/, - krb5_addresses */*addresses*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_fcache_version ( - krb5_context /*context*/, - int */*version*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_forwarded_creds ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_ccache /*ccache*/, - krb5_flags /*flags*/, - const char */*hostname*/, - krb5_creds */*in_creds*/, - krb5_data */*out_data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_host_realm ( - krb5_context /*context*/, - const char */*targethost*/, - krb5_realm **/*realms*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_ignore_addresses ( - krb5_context /*context*/, - krb5_addresses */*addresses*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_in_cred ( - krb5_context /*context*/, - krb5_flags /*options*/, - const krb5_addresses */*addrs*/, - const krb5_enctype */*etypes*/, - const krb5_preauthtype */*ptypes*/, - const krb5_preauthdata */*preauth*/, - krb5_key_proc /*key_proc*/, - krb5_const_pointer /*keyseed*/, - krb5_decrypt_proc /*decrypt_proc*/, - krb5_const_pointer /*decryptarg*/, - krb5_creds */*creds*/, - krb5_kdc_rep */*ret_as_reply*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_in_tkt ( - krb5_context /*context*/, - krb5_flags /*options*/, - const krb5_addresses */*addrs*/, - const krb5_enctype */*etypes*/, - const krb5_preauthtype */*ptypes*/, - krb5_key_proc /*key_proc*/, - krb5_const_pointer /*keyseed*/, - krb5_decrypt_proc /*decrypt_proc*/, - krb5_const_pointer /*decryptarg*/, - krb5_creds */*creds*/, - krb5_ccache /*ccache*/, - krb5_kdc_rep */*ret_as_reply*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_in_tkt_with_keytab ( - krb5_context /*context*/, - krb5_flags /*options*/, - krb5_addresses */*addrs*/, - const krb5_enctype */*etypes*/, - const krb5_preauthtype */*pre_auth_types*/, - krb5_keytab /*keytab*/, - krb5_ccache /*ccache*/, - krb5_creds */*creds*/, - krb5_kdc_rep */*ret_as_reply*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_in_tkt_with_password ( - krb5_context /*context*/, - krb5_flags /*options*/, - krb5_addresses */*addrs*/, - const krb5_enctype */*etypes*/, - const krb5_preauthtype */*pre_auth_types*/, - const char */*password*/, - krb5_ccache /*ccache*/, - krb5_creds */*creds*/, - krb5_kdc_rep */*ret_as_reply*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_in_tkt_with_skey ( - krb5_context /*context*/, - krb5_flags /*options*/, - krb5_addresses */*addrs*/, - const krb5_enctype */*etypes*/, - const krb5_preauthtype */*pre_auth_types*/, - const krb5_keyblock */*key*/, - krb5_ccache /*ccache*/, - krb5_creds */*creds*/, - krb5_kdc_rep */*ret_as_reply*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_init_creds ( - krb5_context /*context*/, - krb5_creds */*creds*/, - krb5_principal /*client*/, - krb5_prompter_fct /*prompter*/, - void */*data*/, - krb5_deltat /*start_time*/, - const char */*in_tkt_service*/, - krb5_get_init_creds_opt */*options*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_init_creds_keyblock ( - krb5_context /*context*/, - krb5_creds */*creds*/, - krb5_principal /*client*/, - krb5_keyblock */*keyblock*/, - krb5_deltat /*start_time*/, - const char */*in_tkt_service*/, - krb5_get_init_creds_opt */*options*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_init_creds_keytab ( - krb5_context /*context*/, - krb5_creds */*creds*/, - krb5_principal /*client*/, - krb5_keytab /*keytab*/, - krb5_deltat /*start_time*/, - const char */*in_tkt_service*/, - krb5_get_init_creds_opt */*options*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_alloc ( - krb5_context /*context*/, - krb5_get_init_creds_opt **/*opt*/); - -void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_free ( - krb5_context /*context*/, - krb5_get_init_creds_opt */*opt*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_get_error ( - krb5_context /*context*/, - krb5_get_init_creds_opt */*opt*/, - KRB_ERROR **/*error*/); - -void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_init (krb5_get_init_creds_opt */*opt*/); - -void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_address_list ( - krb5_get_init_creds_opt */*opt*/, - krb5_addresses */*addresses*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_addressless ( - krb5_context /*context*/, - krb5_get_init_creds_opt */*opt*/, - krb5_boolean /*addressless*/); - -void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_anonymous ( - krb5_get_init_creds_opt */*opt*/, - int /*anonymous*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_canonicalize ( - krb5_context /*context*/, - krb5_get_init_creds_opt */*opt*/, - krb5_boolean /*req*/); - -void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_default_flags ( - krb5_context /*context*/, - const char */*appname*/, - krb5_const_realm /*realm*/, - krb5_get_init_creds_opt */*opt*/); - -void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_etype_list ( - krb5_get_init_creds_opt */*opt*/, - krb5_enctype */*etype_list*/, - int /*etype_list_length*/); - -void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_forwardable ( - krb5_get_init_creds_opt */*opt*/, - int /*forwardable*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_pa_password ( - krb5_context /*context*/, - krb5_get_init_creds_opt */*opt*/, - const char */*password*/, - krb5_s2k_proc /*key_proc*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_pac_request ( - krb5_context /*context*/, - krb5_get_init_creds_opt */*opt*/, - krb5_boolean /*req_pac*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_pkinit ( - krb5_context /*context*/, - krb5_get_init_creds_opt */*opt*/, - krb5_principal /*principal*/, - const char */*user_id*/, - const char */*x509_anchors*/, - char * const * /*pool*/, - char * const * /*pki_revoke*/, - int /*flags*/, - krb5_prompter_fct /*prompter*/, - void */*prompter_data*/, - char */*password*/); - -void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_preauth_list ( - krb5_get_init_creds_opt */*opt*/, - krb5_preauthtype */*preauth_list*/, - int /*preauth_list_length*/); - -void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_proxiable ( - krb5_get_init_creds_opt */*opt*/, - int /*proxiable*/); - -void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_renew_life ( - krb5_get_init_creds_opt */*opt*/, - krb5_deltat /*renew_life*/); - -void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_salt ( - krb5_get_init_creds_opt */*opt*/, - krb5_data */*salt*/); - -void KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_tkt_life ( - krb5_get_init_creds_opt */*opt*/, - krb5_deltat /*tkt_life*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_init_creds_opt_set_win2k ( - krb5_context /*context*/, - krb5_get_init_creds_opt */*opt*/, - krb5_boolean /*req*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_init_creds_password ( - krb5_context /*context*/, - krb5_creds */*creds*/, - krb5_principal /*client*/, - const char */*password*/, - krb5_prompter_fct /*prompter*/, - void */*data*/, - krb5_deltat /*start_time*/, - const char */*in_tkt_service*/, - krb5_get_init_creds_opt */*in_options*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_kdc_cred ( - krb5_context /*context*/, - krb5_ccache /*id*/, - krb5_kdc_flags /*flags*/, - krb5_addresses */*addresses*/, - Ticket */*second_ticket*/, - krb5_creds */*in_creds*/, - krb5_creds **out_creds ); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_kdc_sec_offset ( - krb5_context /*context*/, - int32_t */*sec*/, - int32_t */*usec*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_krb524hst ( - krb5_context /*context*/, - const krb5_realm */*realm*/, - char ***/*hostlist*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_krb_admin_hst ( - krb5_context /*context*/, - const krb5_realm */*realm*/, - char ***/*hostlist*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_krb_changepw_hst ( - krb5_context /*context*/, - const krb5_realm */*realm*/, - char ***/*hostlist*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_krbhst ( - krb5_context /*context*/, - const krb5_realm */*realm*/, - char ***/*hostlist*/); - -time_t KRB5_LIB_FUNCTION -krb5_get_max_time_skew (krb5_context /*context*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_pw_salt ( - krb5_context /*context*/, - krb5_const_principal /*principal*/, - krb5_salt */*salt*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_renewed_creds ( - krb5_context /*context*/, - krb5_creds */*creds*/, - krb5_const_principal /*client*/, - krb5_ccache /*ccache*/, - const char */*in_tkt_service*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_get_server_rcache ( - krb5_context /*context*/, - const krb5_data */*piece*/, - krb5_rcache */*id*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_get_use_admin_kdc (krb5_context /*context*/); - -krb5_log_facility * KRB5_LIB_FUNCTION -krb5_get_warn_dest (krb5_context /*context*/); - -size_t -krb5_get_wrapped_length ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - size_t /*data_len*/); - -int KRB5_LIB_FUNCTION -krb5_getportbyname ( - krb5_context /*context*/, - const char */*service*/, - const char */*proto*/, - int /*default_port*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_h_addr2addr ( - krb5_context /*context*/, - int /*af*/, - const char */*haddr*/, - krb5_address */*addr*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_h_addr2sockaddr ( - krb5_context /*context*/, - int /*af*/, - const char */*addr*/, - struct sockaddr */*sa*/, - krb5_socklen_t */*sa_size*/, - int /*port*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_h_errno_to_heim_errno (int /*eai_errno*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_have_error_string (krb5_context /*context*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_hmac ( - krb5_context /*context*/, - krb5_cksumtype /*cktype*/, - const void */*data*/, - size_t /*len*/, - unsigned /*usage*/, - krb5_keyblock */*key*/, - Checksum */*result*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_init_context (krb5_context */*context*/); - -void KRB5_LIB_FUNCTION -krb5_init_ets (krb5_context /*context*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_init_etype ( - krb5_context /*context*/, - unsigned */*len*/, - krb5_enctype **/*val*/, - const krb5_enctype */*etypes*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_initlog ( - krb5_context /*context*/, - const char */*program*/, - krb5_log_facility **/*fac*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_is_thread_safe (void); - -const krb5_enctype * KRB5_LIB_FUNCTION -krb5_kerberos_enctypes (krb5_context /*context*/); - -krb5_enctype -krb5_keyblock_get_enctype (const krb5_keyblock */*block*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_keyblock_init ( - krb5_context /*context*/, - krb5_enctype /*type*/, - const void */*data*/, - size_t /*size*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_keyblock_key_proc ( - krb5_context /*context*/, - krb5_keytype /*type*/, - krb5_data */*salt*/, - krb5_const_pointer /*keyseed*/, - krb5_keyblock **/*key*/); - -void KRB5_LIB_FUNCTION -krb5_keyblock_zero (krb5_keyblock */*keyblock*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_keytab_key_proc ( - krb5_context /*context*/, - krb5_enctype /*enctype*/, - krb5_salt /*salt*/, - krb5_const_pointer /*keyseed*/, - krb5_keyblock **/*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_keytype_to_enctypes ( - krb5_context /*context*/, - krb5_keytype /*keytype*/, - unsigned */*len*/, - krb5_enctype **/*val*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_keytype_to_enctypes_default ( - krb5_context /*context*/, - krb5_keytype /*keytype*/, - unsigned */*len*/, - krb5_enctype **/*val*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_keytype_to_string ( - krb5_context /*context*/, - krb5_keytype /*keytype*/, - char **/*string*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_krbhst_format_string ( - krb5_context /*context*/, - const krb5_krbhst_info */*host*/, - char */*hostname*/, - size_t /*hostlen*/); - -void KRB5_LIB_FUNCTION -krb5_krbhst_free ( - krb5_context /*context*/, - krb5_krbhst_handle /*handle*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_krbhst_get_addrinfo ( - krb5_context /*context*/, - krb5_krbhst_info */*host*/, - struct addrinfo **/*ai*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_krbhst_init ( - krb5_context /*context*/, - const char */*realm*/, - unsigned int /*type*/, - krb5_krbhst_handle */*handle*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_krbhst_init_flags ( - krb5_context /*context*/, - const char */*realm*/, - unsigned int /*type*/, - int /*flags*/, - krb5_krbhst_handle */*handle*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_krbhst_next ( - krb5_context /*context*/, - krb5_krbhst_handle /*handle*/, - krb5_krbhst_info **/*host*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_krbhst_next_as_string ( - krb5_context /*context*/, - krb5_krbhst_handle /*handle*/, - char */*hostname*/, - size_t /*hostlen*/); - -void KRB5_LIB_FUNCTION -krb5_krbhst_reset ( - krb5_context /*context*/, - krb5_krbhst_handle /*handle*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_add_entry ( - krb5_context /*context*/, - krb5_keytab /*id*/, - krb5_keytab_entry */*entry*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_close ( - krb5_context /*context*/, - krb5_keytab /*id*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_kt_compare ( - krb5_context /*context*/, - krb5_keytab_entry */*entry*/, - krb5_const_principal /*principal*/, - krb5_kvno /*vno*/, - krb5_enctype /*enctype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_copy_entry_contents ( - krb5_context /*context*/, - const krb5_keytab_entry */*in*/, - krb5_keytab_entry */*out*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_default ( - krb5_context /*context*/, - krb5_keytab */*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_default_modify_name ( - krb5_context /*context*/, - char */*name*/, - size_t /*namesize*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_default_name ( - krb5_context /*context*/, - char */*name*/, - size_t /*namesize*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_end_seq_get ( - krb5_context /*context*/, - krb5_keytab /*id*/, - krb5_kt_cursor */*cursor*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_free_entry ( - krb5_context /*context*/, - krb5_keytab_entry */*entry*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_get_entry ( - krb5_context /*context*/, - krb5_keytab /*id*/, - krb5_const_principal /*principal*/, - krb5_kvno /*kvno*/, - krb5_enctype /*enctype*/, - krb5_keytab_entry */*entry*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_get_full_name ( - krb5_context /*context*/, - krb5_keytab /*keytab*/, - char **/*str*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_get_name ( - krb5_context /*context*/, - krb5_keytab /*keytab*/, - char */*name*/, - size_t /*namesize*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_get_type ( - krb5_context /*context*/, - krb5_keytab /*keytab*/, - char */*prefix*/, - size_t /*prefixsize*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_next_entry ( - krb5_context /*context*/, - krb5_keytab /*id*/, - krb5_keytab_entry */*entry*/, - krb5_kt_cursor */*cursor*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_read_service_key ( - krb5_context /*context*/, - krb5_pointer /*keyprocarg*/, - krb5_principal /*principal*/, - krb5_kvno /*vno*/, - krb5_enctype /*enctype*/, - krb5_keyblock **/*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_register ( - krb5_context /*context*/, - const krb5_kt_ops */*ops*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_remove_entry ( - krb5_context /*context*/, - krb5_keytab /*id*/, - krb5_keytab_entry */*entry*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_resolve ( - krb5_context /*context*/, - const char */*name*/, - krb5_keytab */*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_kt_start_seq_get ( - krb5_context /*context*/, - krb5_keytab /*id*/, - krb5_kt_cursor */*cursor*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_kuserok ( - krb5_context /*context*/, - krb5_principal /*principal*/, - const char */*luser*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_log ( - krb5_context /*context*/, - krb5_log_facility */*fac*/, - int /*level*/, - const char */*fmt*/, - ...) - __attribute__((format (printf, 4, 5))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_log_msg ( - krb5_context /*context*/, - krb5_log_facility */*fac*/, - int /*level*/, - char **/*reply*/, - const char */*fmt*/, - ...) - __attribute__((format (printf, 5, 6))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_make_addrport ( - krb5_context /*context*/, - krb5_address **/*res*/, - const krb5_address */*addr*/, - int16_t /*port*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_make_principal ( - krb5_context /*context*/, - krb5_principal */*principal*/, - krb5_const_realm /*realm*/, - ...); - -size_t KRB5_LIB_FUNCTION -krb5_max_sockaddr_size (void); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_mk_error ( - krb5_context /*context*/, - krb5_error_code /*error_code*/, - const char */*e_text*/, - const krb5_data */*e_data*/, - const krb5_principal /*client*/, - const krb5_principal /*server*/, - time_t */*client_time*/, - int */*client_usec*/, - krb5_data */*reply*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_mk_priv ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - const krb5_data */*userdata*/, - krb5_data */*outbuf*/, - krb5_replay_data */*outdata*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_mk_rep ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_data */*outbuf*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_mk_req ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/, - const krb5_flags /*ap_req_options*/, - const char */*service*/, - const char */*hostname*/, - krb5_data */*in_data*/, - krb5_ccache /*ccache*/, - krb5_data */*outbuf*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_mk_req_exact ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/, - const krb5_flags /*ap_req_options*/, - const krb5_principal /*server*/, - krb5_data */*in_data*/, - krb5_ccache /*ccache*/, - krb5_data */*outbuf*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_mk_req_extended ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/, - const krb5_flags /*ap_req_options*/, - krb5_data */*in_data*/, - krb5_creds */*in_creds*/, - krb5_data */*outbuf*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_mk_safe ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - const krb5_data */*userdata*/, - krb5_data */*outbuf*/, - krb5_replay_data */*outdata*/); - -krb5_ssize_t KRB5_LIB_FUNCTION -krb5_net_read ( - krb5_context /*context*/, - void */*p_fd*/, - void */*buf*/, - size_t /*len*/); - -krb5_ssize_t KRB5_LIB_FUNCTION -krb5_net_write ( - krb5_context /*context*/, - void */*p_fd*/, - const void */*buf*/, - size_t /*len*/); - -krb5_ssize_t KRB5_LIB_FUNCTION -krb5_net_write_block ( - krb5_context /*context*/, - void */*p_fd*/, - const void */*buf*/, - size_t /*len*/, - time_t /*timeout*/); - -krb5_error_code -krb5_ntlm_alloc ( - krb5_context /*context*/, - krb5_ntlm */*ntlm*/); - -krb5_error_code -krb5_ntlm_free ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/); - -krb5_error_code -krb5_ntlm_init_get_challange ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - krb5_data */*challange*/); - -krb5_error_code -krb5_ntlm_init_get_flags ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - uint32_t */*flags*/); - -krb5_error_code -krb5_ntlm_init_get_opaque ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - krb5_data */*opaque*/); - -krb5_error_code -krb5_ntlm_init_get_targetinfo ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - krb5_data */*data*/); - -krb5_error_code -krb5_ntlm_init_get_targetname ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - char **/*name*/); - -krb5_error_code -krb5_ntlm_init_request ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - krb5_realm /*realm*/, - krb5_ccache /*ccache*/, - uint32_t /*flags*/, - const char */*hostname*/, - const char */*domainname*/); - -krb5_error_code -krb5_ntlm_rep_get_sessionkey ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - krb5_data */*data*/); - -krb5_boolean -krb5_ntlm_rep_get_status ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/); - -krb5_error_code -krb5_ntlm_req_set_flags ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - uint32_t /*flags*/); - -krb5_error_code -krb5_ntlm_req_set_lm ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - void */*hash*/, - size_t /*len*/); - -krb5_error_code -krb5_ntlm_req_set_ntlm ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - void */*hash*/, - size_t /*len*/); - -krb5_error_code -krb5_ntlm_req_set_opaque ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - krb5_data */*opaque*/); - -krb5_error_code -krb5_ntlm_req_set_session ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - void */*sessionkey*/, - size_t /*length*/); - -krb5_error_code -krb5_ntlm_req_set_targetname ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - const char */*targetname*/); - -krb5_error_code -krb5_ntlm_req_set_username ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - const char */*username*/); - -krb5_error_code -krb5_ntlm_request ( - krb5_context /*context*/, - krb5_ntlm /*ntlm*/, - krb5_realm /*realm*/, - krb5_ccache /*ccache*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_openlog ( - krb5_context /*context*/, - const char */*program*/, - krb5_log_facility **/*fac*/); - -krb5_error_code -krb5_pac_add_buffer ( - krb5_context /*context*/, - krb5_pac /*p*/, - uint32_t /*type*/, - const krb5_data */*data*/); - -void -krb5_pac_free ( - krb5_context /*context*/, - krb5_pac /*pac*/); - -krb5_error_code -krb5_pac_get_buffer ( - krb5_context /*context*/, - krb5_pac /*p*/, - uint32_t /*type*/, - krb5_data */*data*/); - -krb5_error_code -krb5_pac_get_types ( - krb5_context /*context*/, - krb5_pac /*p*/, - size_t */*len*/, - uint32_t **/*types*/); - -krb5_error_code -krb5_pac_init ( - krb5_context /*context*/, - krb5_pac */*pac*/); - -krb5_error_code -krb5_pac_parse ( - krb5_context /*context*/, - const void */*ptr*/, - size_t /*len*/, - krb5_pac */*pac*/); - -krb5_error_code -krb5_pac_verify ( - krb5_context /*context*/, - const krb5_pac /*pac*/, - time_t /*authtime*/, - krb5_const_principal /*principal*/, - const krb5_keyblock */*server*/, - const krb5_keyblock */*privsvr*/); - -int KRB5_LIB_FUNCTION -krb5_padata_add ( - krb5_context /*context*/, - METHOD_DATA */*md*/, - int /*type*/, - void */*buf*/, - size_t /*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_parse_address ( - krb5_context /*context*/, - const char */*string*/, - krb5_addresses */*addresses*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_parse_name ( - krb5_context /*context*/, - const char */*name*/, - krb5_principal */*principal*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_parse_name_flags ( - krb5_context /*context*/, - const char */*name*/, - int /*flags*/, - krb5_principal */*principal*/); - -krb5_error_code -krb5_parse_nametype ( - krb5_context /*context*/, - const char */*str*/, - int32_t */*nametype*/); - -const char* KRB5_LIB_FUNCTION -krb5_passwd_result_to_string ( - krb5_context /*context*/, - int /*result*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_password_key_proc ( - krb5_context /*context*/, - krb5_enctype /*type*/, - krb5_salt /*salt*/, - krb5_const_pointer /*keyseed*/, - krb5_keyblock **/*key*/); - -krb5_error_code -krb5_plugin_register ( - krb5_context /*context*/, - enum krb5_plugin_type /*type*/, - const char */*name*/, - void */*symbol*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_prepend_config_files ( - const char */*filelist*/, - char **/*pq*/, - char ***/*ret_pp*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_prepend_config_files_default ( - const char */*filelist*/, - char ***/*pfilenames*/); - -krb5_realm * KRB5_LIB_FUNCTION -krb5_princ_realm ( - krb5_context /*context*/, - krb5_principal /*principal*/); - -void KRB5_LIB_FUNCTION -krb5_princ_set_realm ( - krb5_context /*context*/, - krb5_principal /*principal*/, - krb5_realm */*realm*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_principal_compare ( - krb5_context /*context*/, - krb5_const_principal /*princ1*/, - krb5_const_principal /*princ2*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_principal_compare_any_realm ( - krb5_context /*context*/, - krb5_const_principal /*princ1*/, - krb5_const_principal /*princ2*/); - -const char* KRB5_LIB_FUNCTION -krb5_principal_get_comp_string ( - krb5_context /*context*/, - krb5_const_principal /*principal*/, - unsigned int /*component*/); - -const char* KRB5_LIB_FUNCTION -krb5_principal_get_realm ( - krb5_context /*context*/, - krb5_const_principal /*principal*/); - -int KRB5_LIB_FUNCTION -krb5_principal_get_type ( - krb5_context /*context*/, - krb5_const_principal /*principal*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_principal_match ( - krb5_context /*context*/, - krb5_const_principal /*princ*/, - krb5_const_principal /*pattern*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_principal_set_realm ( - krb5_context /*context*/, - krb5_principal /*principal*/, - krb5_const_realm /*realm*/); - -void KRB5_LIB_FUNCTION -krb5_principal_set_type ( - krb5_context /*context*/, - krb5_principal /*principal*/, - int /*type*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_print_address ( - const krb5_address */*addr*/, - char */*str*/, - size_t /*len*/, - size_t */*ret_len*/); - -int KRB5_LIB_FUNCTION -krb5_program_setup ( - krb5_context */*context*/, - int /*argc*/, - char **/*argv*/, - struct getargs */*args*/, - int /*num_args*/, - void (*/*usage*/)(int, struct getargs*, int)); - -int KRB5_LIB_FUNCTION -krb5_prompter_posix ( - krb5_context /*context*/, - void */*data*/, - const char */*name*/, - const char */*banner*/, - int /*num_prompts*/, - krb5_prompt prompts[]); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_random_to_key ( - krb5_context /*context*/, - krb5_enctype /*type*/, - const void */*data*/, - size_t /*size*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rc_close ( - krb5_context /*context*/, - krb5_rcache /*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rc_default ( - krb5_context /*context*/, - krb5_rcache */*id*/); - -const char* KRB5_LIB_FUNCTION -krb5_rc_default_name (krb5_context /*context*/); - -const char* KRB5_LIB_FUNCTION -krb5_rc_default_type (krb5_context /*context*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rc_destroy ( - krb5_context /*context*/, - krb5_rcache /*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rc_expunge ( - krb5_context /*context*/, - krb5_rcache /*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rc_get_lifespan ( - krb5_context /*context*/, - krb5_rcache /*id*/, - krb5_deltat */*auth_lifespan*/); - -const char* KRB5_LIB_FUNCTION -krb5_rc_get_name ( - krb5_context /*context*/, - krb5_rcache /*id*/); - -const char* KRB5_LIB_FUNCTION -krb5_rc_get_type ( - krb5_context /*context*/, - krb5_rcache /*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rc_initialize ( - krb5_context /*context*/, - krb5_rcache /*id*/, - krb5_deltat /*auth_lifespan*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rc_recover ( - krb5_context /*context*/, - krb5_rcache /*id*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rc_resolve ( - krb5_context /*context*/, - krb5_rcache /*id*/, - const char */*name*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rc_resolve_full ( - krb5_context /*context*/, - krb5_rcache */*id*/, - const char */*string_name*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rc_resolve_type ( - krb5_context /*context*/, - krb5_rcache */*id*/, - const char */*type*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rc_store ( - krb5_context /*context*/, - krb5_rcache /*id*/, - krb5_donot_replay */*rep*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_cred ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_data */*in_data*/, - krb5_creds ***/*ret_creds*/, - krb5_replay_data */*outdata*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_cred2 ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - krb5_ccache /*ccache*/, - krb5_data */*in_data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_error ( - krb5_context /*context*/, - const krb5_data */*msg*/, - KRB_ERROR */*result*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_priv ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - const krb5_data */*inbuf*/, - krb5_data */*outbuf*/, - krb5_replay_data */*outdata*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_rep ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - const krb5_data */*inbuf*/, - krb5_ap_rep_enc_part **/*repl*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/, - const krb5_data */*inbuf*/, - krb5_const_principal /*server*/, - krb5_keytab /*keytab*/, - krb5_flags */*ap_req_options*/, - krb5_ticket **/*ticket*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req_ctx ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/, - const krb5_data */*inbuf*/, - krb5_const_principal /*server*/, - krb5_rd_req_in_ctx /*inctx*/, - krb5_rd_req_out_ctx */*outctx*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req_in_ctx_alloc ( - krb5_context /*context*/, - krb5_rd_req_in_ctx */*ctx*/); - -void KRB5_LIB_FUNCTION -krb5_rd_req_in_ctx_free ( - krb5_context /*context*/, - krb5_rd_req_in_ctx /*ctx*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req_in_set_keyblock ( - krb5_context /*context*/, - krb5_rd_req_in_ctx /*in*/, - krb5_keyblock */*keyblock*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req_in_set_keytab ( - krb5_context /*context*/, - krb5_rd_req_in_ctx /*in*/, - krb5_keytab /*keytab*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req_in_set_pac_check ( - krb5_context /*context*/, - krb5_rd_req_in_ctx /*in*/, - krb5_boolean /*flag*/); - -void KRB5_LIB_FUNCTION -krb5_rd_req_out_ctx_free ( - krb5_context /*context*/, - krb5_rd_req_out_ctx /*ctx*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req_out_get_ap_req_options ( - krb5_context /*context*/, - krb5_rd_req_out_ctx /*out*/, - krb5_flags */*ap_req_options*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req_out_get_keyblock ( - krb5_context /*context*/, - krb5_rd_req_out_ctx /*out*/, - krb5_keyblock **/*keyblock*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req_out_get_ticket ( - krb5_context /*context*/, - krb5_rd_req_out_ctx /*out*/, - krb5_ticket **/*ticket*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_req_with_keyblock ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/, - const krb5_data */*inbuf*/, - krb5_const_principal /*server*/, - krb5_keyblock */*keyblock*/, - krb5_flags */*ap_req_options*/, - krb5_ticket **/*ticket*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_rd_safe ( - krb5_context /*context*/, - krb5_auth_context /*auth_context*/, - const krb5_data */*inbuf*/, - krb5_data */*outbuf*/, - krb5_replay_data */*outdata*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_read_message ( - krb5_context /*context*/, - krb5_pointer /*p_fd*/, - krb5_data */*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_read_priv_message ( - krb5_context /*context*/, - krb5_auth_context /*ac*/, - krb5_pointer /*p_fd*/, - krb5_data */*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_read_safe_message ( - krb5_context /*context*/, - krb5_auth_context /*ac*/, - krb5_pointer /*p_fd*/, - krb5_data */*data*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_realm_compare ( - krb5_context /*context*/, - krb5_const_principal /*princ1*/, - krb5_const_principal /*princ2*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_recvauth ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/, - krb5_pointer /*p_fd*/, - const char */*appl_version*/, - krb5_principal /*server*/, - int32_t /*flags*/, - krb5_keytab /*keytab*/, - krb5_ticket **/*ticket*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_recvauth_match_version ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/, - krb5_pointer /*p_fd*/, - krb5_boolean (*/*match_appl_version*/)(const void *, const char*), - const void */*match_data*/, - krb5_principal /*server*/, - int32_t /*flags*/, - krb5_keytab /*keytab*/, - krb5_ticket **/*ticket*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_address ( - krb5_storage */*sp*/, - krb5_address */*adr*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_addrs ( - krb5_storage */*sp*/, - krb5_addresses */*adr*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_authdata ( - krb5_storage */*sp*/, - krb5_authdata */*auth*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_creds ( - krb5_storage */*sp*/, - krb5_creds */*creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_creds_tag ( - krb5_storage */*sp*/, - krb5_creds */*creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_data ( - krb5_storage */*sp*/, - krb5_data */*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_int16 ( - krb5_storage */*sp*/, - int16_t */*value*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_int32 ( - krb5_storage */*sp*/, - int32_t */*value*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_int8 ( - krb5_storage */*sp*/, - int8_t */*value*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_keyblock ( - krb5_storage */*sp*/, - krb5_keyblock */*p*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_principal ( - krb5_storage */*sp*/, - krb5_principal */*princ*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_string ( - krb5_storage */*sp*/, - char **/*string*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_stringnl ( - krb5_storage */*sp*/, - char **/*string*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_stringz ( - krb5_storage */*sp*/, - char **/*string*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_times ( - krb5_storage */*sp*/, - krb5_times */*times*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_uint16 ( - krb5_storage */*sp*/, - uint16_t */*value*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_uint32 ( - krb5_storage */*sp*/, - uint32_t */*value*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ret_uint8 ( - krb5_storage */*sp*/, - uint8_t */*value*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_salttype_to_string ( - krb5_context /*context*/, - krb5_enctype /*etype*/, - krb5_salttype /*stype*/, - char **/*string*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_sendauth ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/, - krb5_pointer /*p_fd*/, - const char */*appl_version*/, - krb5_principal /*client*/, - krb5_principal /*server*/, - krb5_flags /*ap_req_options*/, - krb5_data */*in_data*/, - krb5_creds */*in_creds*/, - krb5_ccache /*ccache*/, - krb5_error **/*ret_error*/, - krb5_ap_rep_enc_part **/*rep_result*/, - krb5_creds **/*out_creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_sendto ( - krb5_context /*context*/, - const krb5_data */*send_data*/, - krb5_krbhst_handle /*handle*/, - krb5_data */*receive*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_sendto_context ( - krb5_context /*context*/, - krb5_sendto_ctx /*ctx*/, - const krb5_data */*send_data*/, - const krb5_realm /*realm*/, - krb5_data */*receive*/); - -void KRB5_LIB_FUNCTION -krb5_sendto_ctx_add_flags ( - krb5_sendto_ctx /*ctx*/, - int /*flags*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_sendto_ctx_alloc ( - krb5_context /*context*/, - krb5_sendto_ctx */*ctx*/); - -void KRB5_LIB_FUNCTION -krb5_sendto_ctx_free ( - krb5_context /*context*/, - krb5_sendto_ctx /*ctx*/); - -int KRB5_LIB_FUNCTION -krb5_sendto_ctx_get_flags (krb5_sendto_ctx /*ctx*/); - -void KRB5_LIB_FUNCTION -krb5_sendto_ctx_set_func ( - krb5_sendto_ctx /*ctx*/, - krb5_sendto_ctx_func /*func*/, - void */*data*/); - -void KRB5_LIB_FUNCTION -krb5_sendto_ctx_set_type ( - krb5_sendto_ctx /*ctx*/, - int /*type*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_sendto_kdc ( - krb5_context /*context*/, - const krb5_data */*send_data*/, - const krb5_realm */*realm*/, - krb5_data */*receive*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_sendto_kdc_flags ( - krb5_context /*context*/, - const krb5_data */*send_data*/, - const krb5_realm */*realm*/, - krb5_data */*receive*/, - int /*flags*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_config_files ( - krb5_context /*context*/, - char **/*filenames*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_default_in_tkt_etypes ( - krb5_context /*context*/, - const krb5_enctype */*etypes*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_default_realm ( - krb5_context /*context*/, - const char */*realm*/); - -void KRB5_LIB_FUNCTION -krb5_set_dns_canonicalize_hostname ( - krb5_context /*context*/, - krb5_boolean /*flag*/); - -void KRB5_LIB_FUNCTION -krb5_set_error_message ( - krb5_context /*context*/, - krb5_error_code /*ret*/, - const char */*fmt*/, - ...) - __attribute__ ((format (printf, 3, 4))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_error_string ( - krb5_context /*context*/, - const char */*fmt*/, - ...) __attribute__((format (printf, 2, 3))) - __attribute__((deprecated)); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_extra_addresses ( - krb5_context /*context*/, - const krb5_addresses */*addresses*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_fcache_version ( - krb5_context /*context*/, - int /*version*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_ignore_addresses ( - krb5_context /*context*/, - const krb5_addresses */*addresses*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_kdc_sec_offset ( - krb5_context /*context*/, - int32_t /*sec*/, - int32_t /*usec*/); - -void KRB5_LIB_FUNCTION -krb5_set_max_time_skew ( - krb5_context /*context*/, - time_t /*t*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_password ( - krb5_context /*context*/, - krb5_creds */*creds*/, - const char */*newpw*/, - krb5_principal /*targprinc*/, - int */*result_code*/, - krb5_data */*result_code_string*/, - krb5_data */*result_string*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_password_using_ccache ( - krb5_context /*context*/, - krb5_ccache /*ccache*/, - const char */*newpw*/, - krb5_principal /*targprinc*/, - int */*result_code*/, - krb5_data */*result_code_string*/, - krb5_data */*result_string*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_real_time ( - krb5_context /*context*/, - krb5_timestamp /*sec*/, - int32_t /*usec*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_send_to_kdc_func ( - krb5_context /*context*/, - krb5_send_to_kdc_func /*func*/, - void */*data*/); - -void KRB5_LIB_FUNCTION -krb5_set_use_admin_kdc ( - krb5_context /*context*/, - krb5_boolean /*flag*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_set_warn_dest ( - krb5_context /*context*/, - krb5_log_facility */*fac*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_sname_to_principal ( - krb5_context /*context*/, - const char */*hostname*/, - const char */*sname*/, - int32_t /*type*/, - krb5_principal */*ret_princ*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_sock_to_principal ( - krb5_context /*context*/, - int /*sock*/, - const char */*sname*/, - int32_t /*type*/, - krb5_principal */*ret_princ*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_sockaddr2address ( - krb5_context /*context*/, - const struct sockaddr */*sa*/, - krb5_address */*addr*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_sockaddr2port ( - krb5_context /*context*/, - const struct sockaddr */*sa*/, - int16_t */*port*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_sockaddr_uninteresting (const struct sockaddr */*sa*/); - -void KRB5_LIB_FUNCTION -krb5_std_usage ( - int /*code*/, - struct getargs */*args*/, - int /*num_args*/); - -void KRB5_LIB_FUNCTION -krb5_storage_clear_flags ( - krb5_storage */*sp*/, - krb5_flags /*flags*/); - -krb5_storage * KRB5_LIB_FUNCTION -krb5_storage_emem (void); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_storage_free (krb5_storage */*sp*/); - -krb5_storage * KRB5_LIB_FUNCTION -krb5_storage_from_data (krb5_data */*data*/); - -krb5_storage * KRB5_LIB_FUNCTION -krb5_storage_from_fd (int /*fd*/); - -krb5_storage * KRB5_LIB_FUNCTION -krb5_storage_from_mem ( - void */*buf*/, - size_t /*len*/); - -krb5_storage * KRB5_LIB_FUNCTION -krb5_storage_from_readonly_mem ( - const void */*buf*/, - size_t /*len*/); - -krb5_flags KRB5_LIB_FUNCTION -krb5_storage_get_byteorder ( - krb5_storage */*sp*/, - krb5_flags /*byteorder*/); - -krb5_boolean KRB5_LIB_FUNCTION -krb5_storage_is_flags ( - krb5_storage */*sp*/, - krb5_flags /*flags*/); - -krb5_ssize_t KRB5_LIB_FUNCTION -krb5_storage_read ( - krb5_storage */*sp*/, - void */*buf*/, - size_t /*len*/); - -off_t KRB5_LIB_FUNCTION -krb5_storage_seek ( - krb5_storage */*sp*/, - off_t /*offset*/, - int /*whence*/); - -void KRB5_LIB_FUNCTION -krb5_storage_set_byteorder ( - krb5_storage */*sp*/, - krb5_flags /*byteorder*/); - -void KRB5_LIB_FUNCTION -krb5_storage_set_eof_code ( - krb5_storage */*sp*/, - int /*code*/); - -void KRB5_LIB_FUNCTION -krb5_storage_set_flags ( - krb5_storage */*sp*/, - krb5_flags /*flags*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_storage_to_data ( - krb5_storage */*sp*/, - krb5_data */*data*/); - -krb5_ssize_t KRB5_LIB_FUNCTION -krb5_storage_write ( - krb5_storage */*sp*/, - const void */*buf*/, - size_t /*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_address ( - krb5_storage */*sp*/, - krb5_address /*p*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_addrs ( - krb5_storage */*sp*/, - krb5_addresses /*p*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_authdata ( - krb5_storage */*sp*/, - krb5_authdata /*auth*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_creds ( - krb5_storage */*sp*/, - krb5_creds */*creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_creds_tag ( - krb5_storage */*sp*/, - krb5_creds */*creds*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_data ( - krb5_storage */*sp*/, - krb5_data /*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_int16 ( - krb5_storage */*sp*/, - int16_t /*value*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_int32 ( - krb5_storage */*sp*/, - int32_t /*value*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_int8 ( - krb5_storage */*sp*/, - int8_t /*value*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_keyblock ( - krb5_storage */*sp*/, - krb5_keyblock /*p*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_principal ( - krb5_storage */*sp*/, - krb5_const_principal /*p*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_string ( - krb5_storage */*sp*/, - const char */*s*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_stringnl ( - krb5_storage */*sp*/, - const char */*s*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_stringz ( - krb5_storage */*sp*/, - const char */*s*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_times ( - krb5_storage */*sp*/, - krb5_times /*times*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_uint16 ( - krb5_storage */*sp*/, - uint16_t /*value*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_uint32 ( - krb5_storage */*sp*/, - uint32_t /*value*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_store_uint8 ( - krb5_storage */*sp*/, - uint8_t /*value*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_string_to_deltat ( - const char */*string*/, - krb5_deltat */*deltat*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_string_to_enctype ( - krb5_context /*context*/, - const char */*string*/, - krb5_enctype */*etype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_string_to_key ( - krb5_context /*context*/, - krb5_enctype /*enctype*/, - const char */*password*/, - krb5_principal /*principal*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_string_to_key_data ( - krb5_context /*context*/, - krb5_enctype /*enctype*/, - krb5_data /*password*/, - krb5_principal /*principal*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_string_to_key_data_salt ( - krb5_context /*context*/, - krb5_enctype /*enctype*/, - krb5_data /*password*/, - krb5_salt /*salt*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_string_to_key_data_salt_opaque ( - krb5_context /*context*/, - krb5_enctype /*enctype*/, - krb5_data /*password*/, - krb5_salt /*salt*/, - krb5_data /*opaque*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_string_to_key_derived ( - krb5_context /*context*/, - const void */*str*/, - size_t /*len*/, - krb5_enctype /*etype*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_string_to_key_salt ( - krb5_context /*context*/, - krb5_enctype /*enctype*/, - const char */*password*/, - krb5_salt /*salt*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_string_to_key_salt_opaque ( - krb5_context /*context*/, - krb5_enctype /*enctype*/, - const char */*password*/, - krb5_salt /*salt*/, - krb5_data /*opaque*/, - krb5_keyblock */*key*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_string_to_keytype ( - krb5_context /*context*/, - const char */*string*/, - krb5_keytype */*keytype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_string_to_salttype ( - krb5_context /*context*/, - krb5_enctype /*etype*/, - const char */*string*/, - krb5_salttype */*salttype*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ticket_get_authorization_data_type ( - krb5_context /*context*/, - krb5_ticket */*ticket*/, - int /*type*/, - krb5_data */*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ticket_get_client ( - krb5_context /*context*/, - const krb5_ticket */*ticket*/, - krb5_principal */*client*/); - -time_t KRB5_LIB_FUNCTION -krb5_ticket_get_endtime ( - krb5_context /*context*/, - const krb5_ticket */*ticket*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_ticket_get_server ( - krb5_context /*context*/, - const krb5_ticket */*ticket*/, - krb5_principal */*server*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_timeofday ( - krb5_context /*context*/, - krb5_timestamp */*timeret*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name ( - krb5_context /*context*/, - krb5_const_principal /*principal*/, - char **/*name*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_fixed ( - krb5_context /*context*/, - krb5_const_principal /*principal*/, - char */*name*/, - size_t /*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_fixed_flags ( - krb5_context /*context*/, - krb5_const_principal /*principal*/, - int /*flags*/, - char */*name*/, - size_t /*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_fixed_short ( - krb5_context /*context*/, - krb5_const_principal /*principal*/, - char */*name*/, - size_t /*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_flags ( - krb5_context /*context*/, - krb5_const_principal /*principal*/, - int /*flags*/, - char **/*name*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_unparse_name_short ( - krb5_context /*context*/, - krb5_const_principal /*principal*/, - char **/*name*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_us_timeofday ( - krb5_context /*context*/, - krb5_timestamp */*sec*/, - int32_t */*usec*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_vabort ( - krb5_context /*context*/, - krb5_error_code /*code*/, - const char */*fmt*/, - va_list /*ap*/) - __attribute__ ((noreturn, format (printf, 3, 0))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_vabortx ( - krb5_context /*context*/, - const char */*fmt*/, - va_list /*ap*/) - __attribute__ ((noreturn, format (printf, 2, 0))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_verify_ap_req ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/, - krb5_ap_req */*ap_req*/, - krb5_const_principal /*server*/, - krb5_keyblock */*keyblock*/, - krb5_flags /*flags*/, - krb5_flags */*ap_req_options*/, - krb5_ticket **/*ticket*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_verify_ap_req2 ( - krb5_context /*context*/, - krb5_auth_context */*auth_context*/, - krb5_ap_req */*ap_req*/, - krb5_const_principal /*server*/, - krb5_keyblock */*keyblock*/, - krb5_flags /*flags*/, - krb5_flags */*ap_req_options*/, - krb5_ticket **/*ticket*/, - krb5_key_usage /*usage*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_verify_authenticator_checksum ( - krb5_context /*context*/, - krb5_auth_context /*ac*/, - void */*data*/, - size_t /*len*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_verify_checksum ( - krb5_context /*context*/, - krb5_crypto /*crypto*/, - krb5_key_usage /*usage*/, - void */*data*/, - size_t /*len*/, - Checksum */*cksum*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_verify_init_creds ( - krb5_context /*context*/, - krb5_creds */*creds*/, - krb5_principal /*ap_req_server*/, - krb5_keytab /*ap_req_keytab*/, - krb5_ccache */*ccache*/, - krb5_verify_init_creds_opt */*options*/); - -void KRB5_LIB_FUNCTION -krb5_verify_init_creds_opt_init (krb5_verify_init_creds_opt */*options*/); - -void KRB5_LIB_FUNCTION -krb5_verify_init_creds_opt_set_ap_req_nofail ( - krb5_verify_init_creds_opt */*options*/, - int /*ap_req_nofail*/); - -int KRB5_LIB_FUNCTION -krb5_verify_opt_alloc ( - krb5_context /*context*/, - krb5_verify_opt **/*opt*/); - -void KRB5_LIB_FUNCTION -krb5_verify_opt_free (krb5_verify_opt */*opt*/); - -void KRB5_LIB_FUNCTION -krb5_verify_opt_init (krb5_verify_opt */*opt*/); - -void KRB5_LIB_FUNCTION -krb5_verify_opt_set_ccache ( - krb5_verify_opt */*opt*/, - krb5_ccache /*ccache*/); - -void KRB5_LIB_FUNCTION -krb5_verify_opt_set_flags ( - krb5_verify_opt */*opt*/, - unsigned int /*flags*/); - -void KRB5_LIB_FUNCTION -krb5_verify_opt_set_keytab ( - krb5_verify_opt */*opt*/, - krb5_keytab /*keytab*/); - -void KRB5_LIB_FUNCTION -krb5_verify_opt_set_secure ( - krb5_verify_opt */*opt*/, - krb5_boolean /*secure*/); - -void KRB5_LIB_FUNCTION -krb5_verify_opt_set_service ( - krb5_verify_opt */*opt*/, - const char */*service*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_verify_user ( - krb5_context /*context*/, - krb5_principal /*principal*/, - krb5_ccache /*ccache*/, - const char */*password*/, - krb5_boolean /*secure*/, - const char */*service*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_verify_user_lrealm ( - krb5_context /*context*/, - krb5_principal /*principal*/, - krb5_ccache /*ccache*/, - const char */*password*/, - krb5_boolean /*secure*/, - const char */*service*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_verify_user_opt ( - krb5_context /*context*/, - krb5_principal /*principal*/, - const char */*password*/, - krb5_verify_opt */*opt*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_verr ( - krb5_context /*context*/, - int /*eval*/, - krb5_error_code /*code*/, - const char */*fmt*/, - va_list /*ap*/) - __attribute__ ((noreturn, format (printf, 4, 0))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_verrx ( - krb5_context /*context*/, - int /*eval*/, - const char */*fmt*/, - va_list /*ap*/) - __attribute__ ((noreturn, format (printf, 3, 0))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_vlog ( - krb5_context /*context*/, - krb5_log_facility */*fac*/, - int /*level*/, - const char */*fmt*/, - va_list /*ap*/) - __attribute__((format (printf, 4, 0))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_vlog_msg ( - krb5_context /*context*/, - krb5_log_facility */*fac*/, - char **/*reply*/, - int /*level*/, - const char */*fmt*/, - va_list /*ap*/) - __attribute__((format (printf, 5, 0))); - -void KRB5_LIB_FUNCTION -krb5_vset_error_message ( - krb5_context /*context*/, - krb5_error_code /*ret*/, - const char */*fmt*/, - va_list /*args*/) - __attribute__ ((format (printf, 3, 0))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_vset_error_string ( - krb5_context /*context*/, - const char */*fmt*/, - va_list args) __attribute__ ((format (printf, 2, 0))) - __attribute__((deprecated)); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_vwarn ( - krb5_context /*context*/, - krb5_error_code /*code*/, - const char */*fmt*/, - va_list /*ap*/) - __attribute__ ((format (printf, 3, 0))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_vwarnx ( - krb5_context /*context*/, - const char */*fmt*/, - va_list /*ap*/) - __attribute__ ((format (printf, 2, 0))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_warn ( - krb5_context /*context*/, - krb5_error_code /*code*/, - const char */*fmt*/, - ...) - __attribute__ ((format (printf, 3, 4))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_warnx ( - krb5_context /*context*/, - const char */*fmt*/, - ...) - __attribute__ ((format (printf, 2, 3))); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_write_message ( - krb5_context /*context*/, - krb5_pointer /*p_fd*/, - krb5_data */*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_write_priv_message ( - krb5_context /*context*/, - krb5_auth_context /*ac*/, - krb5_pointer /*p_fd*/, - krb5_data */*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_write_safe_message ( - krb5_context /*context*/, - krb5_auth_context /*ac*/, - krb5_pointer /*p_fd*/, - krb5_data */*data*/); - -krb5_error_code KRB5_LIB_FUNCTION -krb5_xfree (void */*ptr*/); - -void KRB5_LIB_FUNCTION - __attribute__((deprecated)) krb5_free_error_string(krb5_context context, char *str); - -#ifdef __cplusplus -} -#endif - -#endif /* __krb5_protos_h__ */ -- cgit From 243321b4bbe273cf3a9105ca132caa2b53e2f263 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Aug 2008 19:35:52 +0200 Subject: heimdal: import heimdal's trunk svn rev 23697 + lorikeet-heimdal patches This is based on f56a3b1846c7d462542f2e9527f4d0ed8a34748d in my heimdal-wip repo. metze (This used to be commit 467a1f2163a63cdf1a4c83a69473db50e8794f53) --- source4/heimdal/lib/krb5/acache.c | 2 +- source4/heimdal/lib/krb5/add_et_list.c | 2 +- source4/heimdal/lib/krb5/addr_families.c | 2 +- source4/heimdal/lib/krb5/appdefault.c | 2 +- source4/heimdal/lib/krb5/asn1_glue.c | 2 +- source4/heimdal/lib/krb5/auth_context.c | 2 +- source4/heimdal/lib/krb5/build_ap_req.c | 2 +- source4/heimdal/lib/krb5/build_auth.c | 2 +- source4/heimdal/lib/krb5/cache.c | 2 +- source4/heimdal/lib/krb5/changepw.c | 4 +- source4/heimdal/lib/krb5/codec.c | 2 +- source4/heimdal/lib/krb5/config_file.c | 2 +- source4/heimdal/lib/krb5/config_file_netinfo.c | 2 +- source4/heimdal/lib/krb5/constants.c | 2 +- source4/heimdal/lib/krb5/context.c | 15 +- source4/heimdal/lib/krb5/convert_creds.c | 2 +- source4/heimdal/lib/krb5/copy_host_realm.c | 2 +- source4/heimdal/lib/krb5/crc.c | 2 +- source4/heimdal/lib/krb5/creds.c | 2 +- source4/heimdal/lib/krb5/crypto.c | 1607 ++++++++++++--------- source4/heimdal/lib/krb5/data.c | 2 +- source4/heimdal/lib/krb5/eai_to_heim_errno.c | 2 +- source4/heimdal/lib/krb5/error_string.c | 24 +- source4/heimdal/lib/krb5/expand_hostname.c | 2 +- source4/heimdal/lib/krb5/fcache.c | 12 +- source4/heimdal/lib/krb5/free.c | 2 +- source4/heimdal/lib/krb5/free_host_realm.c | 2 +- source4/heimdal/lib/krb5/generate_seq_number.c | 2 +- source4/heimdal/lib/krb5/generate_subkey.c | 2 +- source4/heimdal/lib/krb5/get_cred.c | 2 +- source4/heimdal/lib/krb5/get_default_principal.c | 2 +- source4/heimdal/lib/krb5/get_default_realm.c | 2 +- source4/heimdal/lib/krb5/get_for_creds.c | 2 +- source4/heimdal/lib/krb5/get_host_realm.c | 2 +- source4/heimdal/lib/krb5/get_in_tkt.c | 5 +- source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c | 2 +- source4/heimdal/lib/krb5/get_port.c | 2 +- source4/heimdal/lib/krb5/heim_err.et | 2 +- source4/heimdal/lib/krb5/heim_threads.h | 2 +- source4/heimdal/lib/krb5/init_creds.c | 2 +- source4/heimdal/lib/krb5/init_creds_pw.c | 2 +- source4/heimdal/lib/krb5/k524_err.et | 2 +- source4/heimdal/lib/krb5/kcm.c | 4 +- source4/heimdal/lib/krb5/keyblock.c | 2 +- source4/heimdal/lib/krb5/keytab.c | 3 +- source4/heimdal/lib/krb5/keytab_any.c | 2 +- source4/heimdal/lib/krb5/keytab_file.c | 10 +- source4/heimdal/lib/krb5/keytab_keyfile.c | 8 +- source4/heimdal/lib/krb5/keytab_memory.c | 2 +- source4/heimdal/lib/krb5/krb5-v4compat.h | 2 +- source4/heimdal/lib/krb5/krb5.h | 24 +- source4/heimdal/lib/krb5/krb5_ccapi.h | 2 +- source4/heimdal/lib/krb5/krb5_err.et | 4 +- source4/heimdal/lib/krb5/krb5_locl.h | 12 +- source4/heimdal/lib/krb5/krbhst.c | 2 +- source4/heimdal/lib/krb5/locate_plugin.h | 2 +- source4/heimdal/lib/krb5/log.c | 6 +- source4/heimdal/lib/krb5/mcache.c | 2 +- source4/heimdal/lib/krb5/misc.c | 2 +- source4/heimdal/lib/krb5/mit_glue.c | 2 +- source4/heimdal/lib/krb5/mk_error.c | 2 +- source4/heimdal/lib/krb5/mk_priv.c | 2 +- source4/heimdal/lib/krb5/mk_rep.c | 2 +- source4/heimdal/lib/krb5/mk_req.c | 2 +- source4/heimdal/lib/krb5/mk_req_ext.c | 2 +- source4/heimdal/lib/krb5/n-fold.c | 2 +- source4/heimdal/lib/krb5/pac.c | 4 +- source4/heimdal/lib/krb5/padata.c | 2 +- source4/heimdal/lib/krb5/pkinit.c | 4 +- source4/heimdal/lib/krb5/plugin.c | 2 +- source4/heimdal/lib/krb5/principal.c | 11 +- source4/heimdal/lib/krb5/prompter_posix.c | 2 +- source4/heimdal/lib/krb5/rd_cred.c | 2 +- source4/heimdal/lib/krb5/rd_error.c | 2 +- source4/heimdal/lib/krb5/rd_priv.c | 21 +- source4/heimdal/lib/krb5/rd_rep.c | 2 +- source4/heimdal/lib/krb5/rd_req.c | 2 +- source4/heimdal/lib/krb5/replay.c | 2 +- source4/heimdal/lib/krb5/send_to_kdc.c | 6 +- source4/heimdal/lib/krb5/set_default_realm.c | 2 +- source4/heimdal/lib/krb5/store.c | 2 +- source4/heimdal/lib/krb5/store_emem.c | 2 +- source4/heimdal/lib/krb5/store_fd.c | 2 +- source4/heimdal/lib/krb5/store_mem.c | 2 +- source4/heimdal/lib/krb5/ticket.c | 2 +- source4/heimdal/lib/krb5/time.c | 2 +- source4/heimdal/lib/krb5/transited.c | 2 +- source4/heimdal/lib/krb5/v4_glue.c | 6 +- source4/heimdal/lib/krb5/version.c | 2 +- source4/heimdal/lib/krb5/warn.c | 2 +- 90 files changed, 1098 insertions(+), 832 deletions(-) mode change 100755 => 100644 source4/heimdal/lib/krb5/heim_threads.h mode change 100755 => 100644 source4/heimdal/lib/krb5/mit_glue.c mode change 100755 => 100644 source4/heimdal/lib/krb5/pkinit.c (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c index 8dd8687005..fb38abedfd 100644 --- a/source4/heimdal/lib/krb5/acache.c +++ b/source4/heimdal/lib/krb5/acache.c @@ -37,7 +37,7 @@ #include #endif -RCSID("$Id: acache.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); /* XXX should we fetch these for each open ? */ static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER; diff --git a/source4/heimdal/lib/krb5/add_et_list.c b/source4/heimdal/lib/krb5/add_et_list.c index 5455d8ac99..e61f775eef 100644 --- a/source4/heimdal/lib/krb5/add_et_list.c +++ b/source4/heimdal/lib/krb5/add_et_list.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: add_et_list.c 22603 2008-02-21 18:44:57Z lha $"); +RCSID("$Id$"); /** * Add a specified list of error messages to the et list in context. diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c index 40abd874cc..dcb9a97154 100644 --- a/source4/heimdal/lib/krb5/addr_families.c +++ b/source4/heimdal/lib/krb5/addr_families.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: addr_families.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); struct addr_operations { int af; diff --git a/source4/heimdal/lib/krb5/appdefault.c b/source4/heimdal/lib/krb5/appdefault.c index b0bb171f4a..a5b6e67e30 100644 --- a/source4/heimdal/lib/krb5/appdefault.c +++ b/source4/heimdal/lib/krb5/appdefault.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: appdefault.c 14465 2005-01-05 05:40:59Z lukeh $"); +RCSID("$Id$"); void KRB5_LIB_FUNCTION krb5_appdefault_boolean(krb5_context context, const char *appname, diff --git a/source4/heimdal/lib/krb5/asn1_glue.c b/source4/heimdal/lib/krb5/asn1_glue.c index b3f775b4be..84c9cd8b68 100644 --- a/source4/heimdal/lib/krb5/asn1_glue.c +++ b/source4/heimdal/lib/krb5/asn1_glue.c @@ -37,7 +37,7 @@ #include "krb5_locl.h" -RCSID("$Id: asn1_glue.c 21745 2007-07-31 16:11:25Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION _krb5_principal2principalname (PrincipalName *p, diff --git a/source4/heimdal/lib/krb5/auth_context.c b/source4/heimdal/lib/krb5/auth_context.c index e4fb50e5b8..cbb186d6c3 100644 --- a/source4/heimdal/lib/krb5/auth_context.c +++ b/source4/heimdal/lib/krb5/auth_context.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: auth_context.c 23273 2008-06-23 03:25:00Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_auth_con_init(krb5_context context, diff --git a/source4/heimdal/lib/krb5/build_ap_req.c b/source4/heimdal/lib/krb5/build_ap_req.c index b1968fe817..92051ba68a 100644 --- a/source4/heimdal/lib/krb5/build_ap_req.c +++ b/source4/heimdal/lib/krb5/build_ap_req.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: build_ap_req.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_build_ap_req (krb5_context context, diff --git a/source4/heimdal/lib/krb5/build_auth.c b/source4/heimdal/lib/krb5/build_auth.c index fe3a5f523c..eb106dc23f 100644 --- a/source4/heimdal/lib/krb5/build_auth.c +++ b/source4/heimdal/lib/krb5/build_auth.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: build_auth.c 23273 2008-06-23 03:25:00Z lha $"); +RCSID("$Id$"); static krb5_error_code make_etypelist(krb5_context context, diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c index 34bfb4a350..02db405f7e 100644 --- a/source4/heimdal/lib/krb5/cache.c +++ b/source4/heimdal/lib/krb5/cache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: cache.c 23417 2008-07-26 18:36:33Z lha $"); +RCSID("$Id$"); /** * Add a new ccache type with operations `ops', overwriting any diff --git a/source4/heimdal/lib/krb5/changepw.c b/source4/heimdal/lib/krb5/changepw.c index ac1a2d312e..d57ed9e3b8 100644 --- a/source4/heimdal/lib/krb5/changepw.c +++ b/source4/heimdal/lib/krb5/changepw.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: changepw.c 23445 2008-07-27 12:08:03Z lha $"); +RCSID("$Id$"); #undef __attribute__ #define __attribute__(X) @@ -577,7 +577,7 @@ change_password_loop (krb5_context context, for (a = ai; !done && a != NULL; a = a->ai_next) { int replied = 0; - sock = socket (a->ai_family, a->ai_socktype, a->ai_protocol); + sock = socket (a->ai_family, a->ai_socktype | SOCK_CLOEXEC, a->ai_protocol); if (sock < 0) continue; rk_cloexec(sock); diff --git a/source4/heimdal/lib/krb5/codec.c b/source4/heimdal/lib/krb5/codec.c index 0d36b4b442..478f77ecef 100644 --- a/source4/heimdal/lib/krb5/codec.c +++ b/source4/heimdal/lib/krb5/codec.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: codec.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_decode_EncTicketPart (krb5_context context, diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c index bf3c432397..f7f7957b04 100644 --- a/source4/heimdal/lib/krb5/config_file.c +++ b/source4/heimdal/lib/krb5/config_file.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: config_file.c 23280 2008-06-23 03:26:18Z lha $"); +RCSID("$Id$"); #ifndef HAVE_NETINFO diff --git a/source4/heimdal/lib/krb5/config_file_netinfo.c b/source4/heimdal/lib/krb5/config_file_netinfo.c index 1e01e7c5ff..d51739ae37 100644 --- a/source4/heimdal/lib/krb5/config_file_netinfo.c +++ b/source4/heimdal/lib/krb5/config_file_netinfo.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: config_file_netinfo.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id$"); /* * Netinfo implementation from Luke Howard diff --git a/source4/heimdal/lib/krb5/constants.c b/source4/heimdal/lib/krb5/constants.c index 8fffb0f402..dc96bcb632 100644 --- a/source4/heimdal/lib/krb5/constants.c +++ b/source4/heimdal/lib/krb5/constants.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: constants.c 23026 2008-04-17 10:02:03Z lha $"); +RCSID("$Id$"); KRB5_LIB_VARIABLE const char *krb5_config_file = #ifdef __APPLE__ diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index 9f17b8c205..358ab20349 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: context.c 23420 2008-07-26 18:37:48Z lha $"); +RCSID("$Id$"); #define INIT_FIELD(C, T, E, D, F) \ (C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \ @@ -192,6 +192,19 @@ init_context_from_config_file(krb5_context context) INIT_FLAG(context, flags, KRB5_CTX_F_CHECK_PAC, TRUE, "check_pac"); context->default_cc_name = NULL; context->default_cc_name_set = 0; + + ret = krb5_config_get_bool_default(context, NULL, FALSE, + "libdefaults", + "allow_weak_crypto", NULL); + if (ret) { + krb5_enctype_enable(context, ETYPE_DES_CBC_CRC); + krb5_enctype_enable(context, ETYPE_DES_CBC_MD4); + krb5_enctype_enable(context, ETYPE_DES_CBC_MD5); + krb5_enctype_enable(context, ETYPE_DES_CBC_NONE); + krb5_enctype_enable(context, ETYPE_DES_CFB64_NONE); + krb5_enctype_enable(context, ETYPE_DES_PCBC_NONE); + } + return 0; } diff --git a/source4/heimdal/lib/krb5/convert_creds.c b/source4/heimdal/lib/krb5/convert_creds.c index 07943efb28..d74f121207 100644 --- a/source4/heimdal/lib/krb5/convert_creds.c +++ b/source4/heimdal/lib/krb5/convert_creds.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: convert_creds.c 23280 2008-06-23 03:26:18Z lha $"); +RCSID("$Id$"); #include "krb5-v4compat.h" diff --git a/source4/heimdal/lib/krb5/copy_host_realm.c b/source4/heimdal/lib/krb5/copy_host_realm.c index cbe333850c..db06e56fb6 100644 --- a/source4/heimdal/lib/krb5/copy_host_realm.c +++ b/source4/heimdal/lib/krb5/copy_host_realm.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: copy_host_realm.c 23280 2008-06-23 03:26:18Z lha $"); +RCSID("$Id$"); /** * Copy the list of realms from `from' to `to'. diff --git a/source4/heimdal/lib/krb5/crc.c b/source4/heimdal/lib/krb5/crc.c index e8ddecf7ba..cdb40b8110 100644 --- a/source4/heimdal/lib/krb5/crc.c +++ b/source4/heimdal/lib/krb5/crc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: crc.c 22862 2008-04-07 18:49:55Z lha $"); +RCSID("$Id$"); static u_long table[256]; diff --git a/source4/heimdal/lib/krb5/creds.c b/source4/heimdal/lib/krb5/creds.c index 938ec294a4..d194041766 100644 --- a/source4/heimdal/lib/krb5/creds.c +++ b/source4/heimdal/lib/krb5/creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: creds.c 23280 2008-06-23 03:26:18Z lha $"); +RCSID("$Id$"); #undef __attribute__ #define __attribute__(X) diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index e91cb9391a..6675647736 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997 - 2005 Kungliga Tekniska Högskolan + * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * @@ -32,15 +32,25 @@ */ #include "krb5_locl.h" -RCSID("$Id: crypto.c 23454 2008-07-27 12:11:44Z lha $"); +RCSID("$Id$"); #include -#undef CRYPTO_DEBUG -#ifdef CRYPTO_DEBUG -static void krb5_crypto_debug(krb5_context, int, size_t, krb5_keyblock*); +#undef __attribute__ +#define __attribute__(X) + +#ifndef HEIMDAL_SMALLER +#define WEAK_ENCTYPES 1 +#define DES3_OLD_ENCTYPE 1 #endif +#ifdef HAVE_OPENSSL /* XXX forward decl for hcrypto glue */ +const EVP_CIPHER * _krb5_EVP_hcrypto_aes_128_cts(void); +const EVP_CIPHER * _krb5_EVP_hcrypto_aes_256_cts(void); +#define EVP_hcrypto_aes_128_cts _krb5_EVP_hcrypto_aes_128_cts +#define EVP_hcrypto_aes_256_cts _krb5_EVP_hcrypto_aes_256_cts +#endif + struct key_data { krb5_keyblock *key; krb5_data *schedule; @@ -82,13 +92,12 @@ struct key_type { size_t bits; size_t size; size_t schedule_size; -#if 0 - krb5_enctype best_etype; -#endif void (*random_key)(krb5_context, krb5_keyblock*); - void (*schedule)(krb5_context, struct key_data *); + void (*schedule)(krb5_context, struct key_type *, struct key_data *); struct salt_type *string_to_key; void (*random_to_key)(krb5_context, krb5_keyblock*, const void*, size_t); + void (*cleanup)(krb5_context, struct key_data *); + const EVP_CIPHER *(*evp)(void); }; struct checksum_type { @@ -97,11 +106,11 @@ struct checksum_type { size_t blocksize; size_t checksumsize; unsigned flags; - void (*checksum)(krb5_context context, - struct key_data *key, - const void *buf, size_t len, - unsigned usage, - Checksum *csum); + krb5_enctype (*checksum)(krb5_context context, + struct key_data *key, + const void *buf, size_t len, + unsigned usage, + Checksum *csum); krb5_error_code (*verify)(krb5_context context, struct key_data *key, const void *buf, size_t len, @@ -152,7 +161,9 @@ static krb5_error_code hmac(krb5_context context, unsigned usage, struct key_data *keyblock, Checksum *result); -static void free_key_data(krb5_context context, struct key_data *key); +static void free_key_data(krb5_context, + struct key_data *, + struct encryption_type *); static krb5_error_code usage2arcfour (krb5_context, unsigned *); static void xor (DES_cblock *, const unsigned char *); @@ -160,9 +171,14 @@ static void xor (DES_cblock *, const unsigned char *); * * ************************************************************/ -static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER; +struct evp_schedule { + EVP_CIPHER_CTX ectx; + EVP_CIPHER_CTX dctx; +}; +static HEIMDAL_MUTEX crypto_mutex = HEIMDAL_MUTEX_INITIALIZER; + static void krb5_DES_random_key(krb5_context context, krb5_keyblock *key) @@ -174,12 +190,16 @@ krb5_DES_random_key(krb5_context context, } while(DES_is_weak_key(k)); } +#ifdef WEAK_ENCTYPES static void -krb5_DES_schedule(krb5_context context, - struct key_data *key) +krb5_DES_schedule_old(krb5_context context, + struct key_type *kt, + struct key_data *key) { DES_set_key_unchecked(key->key->keyvalue.data, key->schedule->data); } +#endif /* WEAK_ENCTYPES */ + #ifdef ENABLE_AFS_STRING_TO_KEY @@ -384,17 +404,6 @@ DES3_random_key(krb5_context context, DES_is_weak_key(&k[2])); } -static void -DES3_schedule(krb5_context context, - struct key_data *key) -{ - DES_cblock *k = key->key->keyvalue.data; - DES_key_schedule *s = key->schedule->data; - DES_set_key_unchecked(&k[0], &s[0]); - DES_set_key_unchecked(&k[1], &s[1]); - DES_set_key_unchecked(&k[2], &s[2]); -} - /* * A = A xor B. A & B are 8 bytes. */ @@ -413,6 +422,7 @@ xor (DES_cblock *key, const unsigned char *b) a[7] ^= b[7]; } +#ifdef DES3_OLD_ENCTYPE static krb5_error_code DES3_string_to_key(krb5_context context, krb5_enctype enctype, @@ -476,6 +486,7 @@ DES3_string_to_key(krb5_context context, free(str); return 0; } +#endif static krb5_error_code DES3_string_to_key_derived(krb5_context context, @@ -546,6 +557,7 @@ DES3_random_to_key(krb5_context context, static void ARCFOUR_schedule(krb5_context context, + struct key_type *kt, struct key_data *kd) { RC4_set_key (kd->schedule->data, @@ -561,20 +573,30 @@ ARCFOUR_string_to_key(krb5_context context, krb5_keyblock *key) { krb5_error_code ret; - uint16_t *s; + uint16_t *s = NULL; size_t len, i; - MD4_CTX m; + EVP_MD_CTX *m; + + m = EVP_MD_CTX_create(); + if (m == NULL) { + ret = ENOMEM; + krb5_set_error_message(context, ret, "Malloc: out of memory"); + goto out; + } + + EVP_DigestInit_ex(m, EVP_md4(), NULL); ret = wind_utf8ucs2_length(password.data, &len); if (ret) { krb5_set_error_message (context, ret, "Password not an UCS2 string"); - return ret; + goto out; } s = malloc (len * sizeof(s[0])); if (len != 0 && s == NULL) { krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); - return ENOMEM; + ret = ENOMEM; + goto out; } ret = wind_utf8ucs2(password.data, s, &len); @@ -584,13 +606,12 @@ ARCFOUR_string_to_key(krb5_context context, } /* LE encoding */ - MD4_Init (&m); for (i = 0; i < len; i++) { unsigned char p; p = (s[i] & 0xff); - MD4_Update (&m, &p, 1); + EVP_DigestUpdate (m, &p, 1); p = (s[i] >> 8) & 0xff; - MD4_Update (&m, &p, 1); + EVP_DigestUpdate (m, &p, 1); } key->keytype = enctype; @@ -599,10 +620,12 @@ ARCFOUR_string_to_key(krb5_context context, krb5_set_error_message (context, ENOMEM, "malloc: out of memory"); goto out; } - MD4_Final (key->keyvalue.data, &m); - ret = 0; + EVP_DigestFinal_ex (m, key->keyvalue.data, NULL); + out: - memset (s, 0, len); + EVP_MD_CTX_destroy(m); + if (s) + memset (s, 0, len); free (s); return ret; } @@ -657,7 +680,7 @@ AES_string_to_key(krb5_context context, iter, et->keytype->size, kd.key->keyvalue.data); if (ret != 1) { - free_key_data(context, &kd); + free_key_data(context, &kd, et); krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP, "Error calculating s2k"); return KRB5_PROG_KEYTYPE_NOSUPP; @@ -666,26 +689,30 @@ AES_string_to_key(krb5_context context, ret = derive_key(context, et, &kd, "kerberos", strlen("kerberos")); if (ret == 0) ret = krb5_copy_keyblock_contents(context, kd.key, key); - free_key_data(context, &kd); + free_key_data(context, &kd, et); return ret; } -struct krb5_aes_schedule { - AES_KEY ekey; - AES_KEY dkey; -}; - static void -AES_schedule(krb5_context context, - struct key_data *kd) +evp_schedule(krb5_context context, struct key_type *kt, struct key_data *kd) { - struct krb5_aes_schedule *key = kd->schedule->data; - int bits = kd->key->keyvalue.length * 8; + struct evp_schedule *key = kd->schedule->data; + const EVP_CIPHER *c = (*kt->evp)(); + + EVP_CIPHER_CTX_init(&key->ectx); + EVP_CIPHER_CTX_init(&key->dctx); + + EVP_CipherInit_ex(&key->ectx, c, NULL, kd->key->keyvalue.data, NULL, 1); + EVP_CipherInit_ex(&key->dctx, c, NULL, kd->key->keyvalue.data, NULL, 0); +} - memset(key, 0, sizeof(*key)); - AES_set_encrypt_key(kd->key->keyvalue.data, bits, &key->ekey); - AES_set_decrypt_key(kd->key->keyvalue.data, bits, &key->dkey); +static void +evp_cleanup(krb5_context context, struct key_data *kd) +{ + struct evp_schedule *key = kd->schedule->data; + EVP_CIPHER_CTX_cleanup(&key->ectx); + EVP_CIPHER_CTX_cleanup(&key->dctx); } /* @@ -708,6 +735,7 @@ static struct salt_type des_salt[] = { { 0 } }; +#ifdef DES3_OLD_ENCTYPE static struct salt_type des3_salt[] = { { KRB5_PW_SALT, @@ -716,6 +744,7 @@ static struct salt_type des3_salt[] = { }, { 0 } }; +#endif static struct salt_type des3_salt_derived[] = { { @@ -759,40 +788,62 @@ static struct key_type keytype_null = { NULL }; -static struct key_type keytype_des = { +#ifdef WEAK_ENCTYPES +static struct key_type keytype_des_old = { KEYTYPE_DES, - "des", + "des-old", 56, - sizeof(DES_cblock), + 8, sizeof(DES_key_schedule), krb5_DES_random_key, - krb5_DES_schedule, + krb5_DES_schedule_old, des_salt, krb5_DES_random_to_key }; +#endif /* WEAK_ENCTYPES */ + +static struct key_type keytype_des = { + KEYTYPE_DES, + "des", + 56, + 8, + sizeof(struct evp_schedule), + krb5_DES_random_key, + evp_schedule, + des_salt, + krb5_DES_random_to_key, + evp_cleanup, + EVP_des_cbc +}; +#ifdef DES3_OLD_ENCTYPE static struct key_type keytype_des3 = { KEYTYPE_DES3, "des3", 168, - 3 * sizeof(DES_cblock), - 3 * sizeof(DES_key_schedule), + 24, + sizeof(struct evp_schedule), DES3_random_key, - DES3_schedule, + evp_schedule, des3_salt, - DES3_random_to_key + DES3_random_to_key, + evp_cleanup, + EVP_des_ede3_cbc }; +#endif static struct key_type keytype_des3_derived = { KEYTYPE_DES3, "des3", 168, - 3 * sizeof(DES_cblock), - 3 * sizeof(DES_key_schedule), + 24, + sizeof(struct evp_schedule), DES3_random_key, - DES3_schedule, + evp_schedule, des3_salt_derived, - DES3_random_to_key + DES3_random_to_key, + evp_cleanup, + EVP_des_ede3_cbc }; static struct key_type keytype_aes128 = { @@ -800,10 +851,13 @@ static struct key_type keytype_aes128 = { "aes-128", 128, 16, - sizeof(struct krb5_aes_schedule), + sizeof(struct evp_schedule), + NULL, + evp_schedule, + AES_salt, NULL, - AES_schedule, - AES_salt + evp_cleanup, + EVP_hcrypto_aes_128_cts }; static struct key_type keytype_aes256 = { @@ -811,10 +865,13 @@ static struct key_type keytype_aes256 = { "aes-256", 256, 32, - sizeof(struct krb5_aes_schedule), + sizeof(struct evp_schedule), NULL, - AES_schedule, - AES_salt + evp_schedule, + AES_salt, + NULL, + evp_cleanup, + EVP_hcrypto_aes_256_cts }; static struct key_type keytype_arcfour = { @@ -832,7 +889,9 @@ static struct key_type *keytypes[] = { &keytype_null, &keytype_des, &keytype_des3_derived, +#ifdef DES3_OLD_ENCTYPE &keytype_des3, +#endif &keytype_aes128, &keytype_aes256, &keytype_arcfour @@ -1057,51 +1116,6 @@ krb5_string_to_key_salt_opaque (krb5_context context, pw, salt, opaque, key); } -krb5_error_code KRB5_LIB_FUNCTION -krb5_keytype_to_string(krb5_context context, - krb5_keytype keytype, - char **string) -{ - struct key_type *kt = _find_keytype(keytype); - if(kt == NULL) { - krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP, - "key type %d not supported", keytype); - return KRB5_PROG_KEYTYPE_NOSUPP; - } - *string = strdup(kt->name); - if(*string == NULL) { - krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); - return ENOMEM; - } - return 0; -} - -krb5_error_code KRB5_LIB_FUNCTION -krb5_string_to_keytype(krb5_context context, - const char *string, - krb5_keytype *keytype) -{ - char *end; - int i; - - for(i = 0; i < num_keytypes; i++) - if(strcasecmp(keytypes[i]->name, string) == 0){ - *keytype = keytypes[i]->type; - return 0; - } - - /* check if the enctype is a number */ - *keytype = strtol(string, &end, 0); - if(*end == '\0' && *keytype != 0) { - if (krb5_enctype_valid(context, *keytype) == 0) - return 0; - } - - krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP, - "key type %s not supported", string); - return KRB5_PROG_KEYTYPE_NOSUPP; -} - krb5_error_code KRB5_LIB_FUNCTION krb5_enctype_keysize(krb5_context context, krb5_enctype type, @@ -1182,7 +1196,7 @@ _key_schedule(krb5_context context, key->schedule = NULL; return ret; } - (*kt->schedule)(context, key); + (*kt->schedule)(context, kt, key); return 0; } @@ -1190,7 +1204,7 @@ _key_schedule(krb5_context context, * * ************************************************************/ -static void +static krb5_error_code NONE_checksum(krb5_context context, struct key_data *key, const void *data, @@ -1198,9 +1212,10 @@ NONE_checksum(krb5_context context, unsigned usage, Checksum *C) { + return 0; } -static void +static krb5_error_code CRC32_checksum(krb5_context context, struct key_data *key, const void *data, @@ -1216,9 +1231,10 @@ CRC32_checksum(krb5_context context, r[1] = (crc >> 8) & 0xff; r[2] = (crc >> 16) & 0xff; r[3] = (crc >> 24) & 0xff; + return 0; } -static void +static krb5_error_code RSA_MD4_checksum(krb5_context context, struct key_data *key, const void *data, @@ -1226,64 +1242,74 @@ RSA_MD4_checksum(krb5_context context, unsigned usage, Checksum *C) { - MD4_CTX m; - - MD4_Init (&m); - MD4_Update (&m, data, len); - MD4_Final (C->checksum.data, &m); + if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md4(), NULL) != 1) + krb5_abortx(context, "md4 checksum failed"); + return 0; } -static void -RSA_MD4_DES_checksum(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *cksum) +static krb5_error_code +des_checksum(krb5_context context, + const EVP_MD *evp_md, + struct key_data *key, + const void *data, + size_t len, + Checksum *cksum) { - MD4_CTX md4; + struct evp_schedule *ctx = key->schedule->data; + EVP_MD_CTX *m; DES_cblock ivec; unsigned char *p = cksum->checksum.data; krb5_generate_random_block(p, 8); - MD4_Init (&md4); - MD4_Update (&md4, p, 8); - MD4_Update (&md4, data, len); - MD4_Final (p + 8, &md4); + + m = EVP_MD_CTX_create(); + if (m == NULL) { + krb5_set_error_message(context, ENOMEM, "Malloc: out of memory"); + return ENOMEM; + } + + EVP_DigestInit_ex(m, evp_md, NULL); + EVP_DigestUpdate(m, p, 8); + EVP_DigestUpdate(m, data, len); + EVP_DigestFinal_ex (m, p + 8, NULL); + EVP_MD_CTX_destroy(m); memset (&ivec, 0, sizeof(ivec)); - DES_cbc_encrypt(p, - p, - 24, - key->schedule->data, - &ivec, - DES_ENCRYPT); + EVP_CipherInit_ex(&ctx->ectx, NULL, NULL, NULL, (void *)&ivec, -1); + EVP_Cipher(&ctx->ectx, p, p, 24); + + return 0; } static krb5_error_code -RSA_MD4_DES_verify(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *C) +des_verify(krb5_context context, + const EVP_MD *evp_md, + struct key_data *key, + const void *data, + size_t len, + Checksum *C) { - MD4_CTX md4; + struct evp_schedule *ctx = key->schedule->data; + EVP_MD_CTX *m; unsigned char tmp[24]; unsigned char res[16]; DES_cblock ivec; krb5_error_code ret = 0; + m = EVP_MD_CTX_create(); + if (m == NULL) { + krb5_set_error_message(context, ENOMEM, "Malloc: out of memory"); + return ENOMEM; + } + memset(&ivec, 0, sizeof(ivec)); - DES_cbc_encrypt(C->checksum.data, - (void*)tmp, - C->checksum.length, - key->schedule->data, - &ivec, - DES_DECRYPT); - MD4_Init (&md4); - MD4_Update (&md4, tmp, 8); /* confounder */ - MD4_Update (&md4, data, len); - MD4_Final (res, &md4); + EVP_CipherInit_ex(&ctx->dctx, NULL, NULL, NULL, (void *)&ivec, -1); + EVP_Cipher(&ctx->dctx, tmp, C->checksum.data, 24); + + EVP_DigestInit_ex(m, evp_md, NULL); + EVP_DigestUpdate(m, tmp, 8); /* confounder */ + EVP_DigestUpdate(m, data, len); + EVP_DigestFinal_ex (m, res, NULL); + EVP_MD_CTX_destroy(m); if(memcmp(res, tmp + 8, sizeof(res)) != 0) { krb5_clear_error_string (context); ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; @@ -1293,7 +1319,29 @@ RSA_MD4_DES_verify(krb5_context context, return ret; } -static void +static krb5_error_code +RSA_MD4_DES_checksum(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *cksum) +{ + return des_checksum(context, EVP_md4(), key, data, len, cksum); +} + +static krb5_error_code +RSA_MD4_DES_verify(krb5_context context, + struct key_data *key, + const void *data, + size_t len, + unsigned usage, + Checksum *C) +{ + return des_verify(context, EVP_md5(), key, data, len, C); +} + +static krb5_error_code RSA_MD5_checksum(krb5_context context, struct key_data *key, const void *data, @@ -1301,14 +1349,12 @@ RSA_MD5_checksum(krb5_context context, unsigned usage, Checksum *C) { - MD5_CTX m; - - MD5_Init (&m); - MD5_Update(&m, data, len); - MD5_Final (C->checksum.data, &m); + if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_md5(), NULL) != 1) + krb5_abortx(context, "md5 checksum failed"); + return 0; } -static void +static krb5_error_code RSA_MD5_DES_checksum(krb5_context context, struct key_data *key, const void *data, @@ -1316,22 +1362,7 @@ RSA_MD5_DES_checksum(krb5_context context, unsigned usage, Checksum *C) { - MD5_CTX md5; - DES_cblock ivec; - unsigned char *p = C->checksum.data; - - krb5_generate_random_block(p, 8); - MD5_Init (&md5); - MD5_Update (&md5, p, 8); - MD5_Update (&md5, data, len); - MD5_Final (p + 8, &md5); - memset (&ivec, 0, sizeof(ivec)); - DES_cbc_encrypt(p, - p, - 24, - key->schedule->data, - &ivec, - DES_ENCRYPT); + return des_checksum(context, EVP_md5(), key, data, len, C); } static krb5_error_code @@ -1342,34 +1373,10 @@ RSA_MD5_DES_verify(krb5_context context, unsigned usage, Checksum *C) { - MD5_CTX md5; - unsigned char tmp[24]; - unsigned char res[16]; - DES_cblock ivec; - DES_key_schedule *sched = key->schedule->data; - krb5_error_code ret = 0; - - memset(&ivec, 0, sizeof(ivec)); - DES_cbc_encrypt(C->checksum.data, - (void*)tmp, - C->checksum.length, - &sched[0], - &ivec, - DES_DECRYPT); - MD5_Init (&md5); - MD5_Update (&md5, tmp, 8); /* confounder */ - MD5_Update (&md5, data, len); - MD5_Final (res, &md5); - if(memcmp(res, tmp + 8, sizeof(res)) != 0) { - krb5_clear_error_string (context); - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; - } - memset(tmp, 0, sizeof(tmp)); - memset(res, 0, sizeof(res)); - return ret; + return des_verify(context, EVP_md5(), key, data, len, C); } -static void +static krb5_error_code RSA_MD5_DES3_checksum(krb5_context context, struct key_data *key, const void *data, @@ -1377,23 +1384,7 @@ RSA_MD5_DES3_checksum(krb5_context context, unsigned usage, Checksum *C) { - MD5_CTX md5; - DES_cblock ivec; - unsigned char *p = C->checksum.data; - DES_key_schedule *sched = key->schedule->data; - - krb5_generate_random_block(p, 8); - MD5_Init (&md5); - MD5_Update (&md5, p, 8); - MD5_Update (&md5, data, len); - MD5_Final (p + 8, &md5); - memset (&ivec, 0, sizeof(ivec)); - DES_ede3_cbc_encrypt(p, - p, - 24, - &sched[0], &sched[1], &sched[2], - &ivec, - DES_ENCRYPT); + return des_checksum(context, EVP_md5(), key, data, len, C); } static krb5_error_code @@ -1404,34 +1395,10 @@ RSA_MD5_DES3_verify(krb5_context context, unsigned usage, Checksum *C) { - MD5_CTX md5; - unsigned char tmp[24]; - unsigned char res[16]; - DES_cblock ivec; - DES_key_schedule *sched = key->schedule->data; - krb5_error_code ret = 0; - - memset(&ivec, 0, sizeof(ivec)); - DES_ede3_cbc_encrypt(C->checksum.data, - (void*)tmp, - C->checksum.length, - &sched[0], &sched[1], &sched[2], - &ivec, - DES_DECRYPT); - MD5_Init (&md5); - MD5_Update (&md5, tmp, 8); /* confounder */ - MD5_Update (&md5, data, len); - MD5_Final (res, &md5); - if(memcmp(res, tmp + 8, sizeof(res)) != 0) { - krb5_clear_error_string (context); - ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; - } - memset(tmp, 0, sizeof(tmp)); - memset(res, 0, sizeof(res)); - return ret; + return des_verify(context, EVP_md5(), key, data, len, C); } -static void +static krb5_error_code SHA1_checksum(krb5_context context, struct key_data *key, const void *data, @@ -1439,11 +1406,9 @@ SHA1_checksum(krb5_context context, unsigned usage, Checksum *C) { - SHA_CTX m; - - SHA1_Init(&m); - SHA1_Update(&m, data, len); - SHA1_Final(C->checksum.data, &m); + if (EVP_Digest(data, len, C->checksum.data, NULL, EVP_sha1(), NULL) != 1) + krb5_abortx(context, "sha1 checksum failed"); + return 0; } /* HMAC according to RFC2104 */ @@ -1535,7 +1500,7 @@ krb5_hmac(krb5_context context, return ret; } -static void +static krb5_error_code SP_HMAC_SHA1_checksum(krb5_context context, struct key_data *key, const void *data, @@ -1555,13 +1520,14 @@ SP_HMAC_SHA1_checksum(krb5_context context, if (ret) krb5_abortx(context, "hmac failed"); memcpy(result->checksum.data, res.checksum.data, result->checksum.length); + return 0; } /* * checksum according to section 5. of draft-brezak-win2k-krb-rc4-hmac-03.txt */ -static void +static krb5_error_code HMAC_MD5_checksum(krb5_context context, struct key_data *key, const void *data, @@ -1569,7 +1535,7 @@ HMAC_MD5_checksum(krb5_context context, unsigned usage, Checksum *result) { - MD5_CTX md5; + EVP_MD_CTX *m; struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); const char signature[] = "signaturekey"; Checksum ksign_c; @@ -1580,61 +1546,34 @@ HMAC_MD5_checksum(krb5_context context, unsigned char ksign_c_data[16]; krb5_error_code ret; + m = EVP_MD_CTX_create(); + if (m == NULL) { + krb5_set_error_message(context, ENOMEM, "Malloc: out of memory"); + return ENOMEM; + } ksign_c.checksum.length = sizeof(ksign_c_data); ksign_c.checksum.data = ksign_c_data; ret = hmac(context, c, signature, sizeof(signature), 0, key, &ksign_c); - if (ret) - krb5_abortx(context, "hmac failed"); + if (ret) { + EVP_MD_CTX_destroy(m); + return ret; + } ksign.key = &kb; kb.keyvalue = ksign_c.checksum; - MD5_Init (&md5); - t[0] = (usage >> 0) & 0xFF; - t[1] = (usage >> 8) & 0xFF; - t[2] = (usage >> 16) & 0xFF; - t[3] = (usage >> 24) & 0xFF; - MD5_Update (&md5, t, 4); - MD5_Update (&md5, data, len); - MD5_Final (tmp, &md5); - ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result); - if (ret) - krb5_abortx(context, "hmac failed"); -} - -/* - * same as previous but being used while encrypting. - */ - -static void -HMAC_MD5_checksum_enc(krb5_context context, - struct key_data *key, - const void *data, - size_t len, - unsigned usage, - Checksum *result) -{ - struct checksum_type *c = _find_checksum (CKSUMTYPE_RSA_MD5); - Checksum ksign_c; - struct key_data ksign; - krb5_keyblock kb; - unsigned char t[4]; - unsigned char ksign_c_data[16]; - krb5_error_code ret; - + EVP_DigestInit_ex(m, EVP_md5(), NULL); t[0] = (usage >> 0) & 0xFF; t[1] = (usage >> 8) & 0xFF; t[2] = (usage >> 16) & 0xFF; t[3] = (usage >> 24) & 0xFF; + EVP_DigestUpdate(m, t, 4); + EVP_DigestUpdate(m, data, len); + EVP_DigestFinal_ex (m, tmp, NULL); + EVP_MD_CTX_destroy(m); - ksign_c.checksum.length = sizeof(ksign_c_data); - ksign_c.checksum.data = ksign_c_data; - ret = hmac(context, c, t, sizeof(t), 0, key, &ksign_c); - if (ret) - krb5_abortx(context, "hmac failed"); - ksign.key = &kb; - kb.keyvalue = ksign_c.checksum; - ret = hmac(context, c, data, len, 0, &ksign, result); + ret = hmac(context, c, tmp, sizeof(tmp), 0, &ksign, result); if (ret) - krb5_abortx(context, "hmac failed"); + return ret; + return 0; } static struct checksum_type checksum_none = { @@ -1673,33 +1612,6 @@ static struct checksum_type checksum_rsa_md4_des = { RSA_MD4_DES_checksum, RSA_MD4_DES_verify }; -#if 0 -static struct checksum_type checksum_des_mac = { - CKSUMTYPE_DES_MAC, - "des-mac", - 0, - 0, - 0, - DES_MAC_checksum -}; -static struct checksum_type checksum_des_mac_k = { - CKSUMTYPE_DES_MAC_K, - "des-mac-k", - 0, - 0, - 0, - DES_MAC_K_checksum -}; -static struct checksum_type checksum_rsa_md4_des_k = { - CKSUMTYPE_RSA_MD4_DES_K, - "rsa-md4-des-k", - 0, - 0, - 0, - RSA_MD4_DES_K_checksum, - RSA_MD4_DES_K_verify -}; -#endif static struct checksum_type checksum_rsa_md5 = { CKSUMTYPE_RSA_MD5, "rsa-md5", @@ -1718,6 +1630,7 @@ static struct checksum_type checksum_rsa_md5_des = { RSA_MD5_DES_checksum, RSA_MD5_DES_verify }; +#ifdef DES3_OLD_ENCTYPE static struct checksum_type checksum_rsa_md5_des3 = { CKSUMTYPE_RSA_MD5_DES3, "rsa-md5-des3", @@ -1727,6 +1640,7 @@ static struct checksum_type checksum_rsa_md5_des3 = { RSA_MD5_DES3_checksum, RSA_MD5_DES3_verify }; +#endif static struct checksum_type checksum_sha1 = { CKSUMTYPE_SHA1, "sha1", @@ -1776,35 +1690,21 @@ static struct checksum_type checksum_hmac_md5 = { NULL }; -static struct checksum_type checksum_hmac_md5_enc = { - CKSUMTYPE_HMAC_MD5_ENC, - "hmac-md5-enc", - 64, - 16, - F_KEYED | F_CPROOF | F_PSEUDO, - HMAC_MD5_checksum_enc, - NULL -}; - static struct checksum_type *checksum_types[] = { &checksum_none, &checksum_crc32, &checksum_rsa_md4, &checksum_rsa_md4_des, -#if 0 - &checksum_des_mac, - &checksum_des_mac_k, - &checksum_rsa_md4_des_k, -#endif &checksum_rsa_md5, &checksum_rsa_md5_des, +#ifdef DES3_OLD_ENCTYPE &checksum_rsa_md5_des3, +#endif &checksum_sha1, &checksum_hmac_sha1_des3, &checksum_hmac_sha1_aes128, &checksum_hmac_sha1_aes256, - &checksum_hmac_md5, - &checksum_hmac_md5_enc + &checksum_hmac_md5 }; static int num_checksums = sizeof(checksum_types) / sizeof(checksum_types[0]); @@ -1886,8 +1786,7 @@ create_checksum (krb5_context context, ret = krb5_data_alloc(&result->checksum, ct->checksumsize); if (ret) return (ret); - (*ct->checksum)(context, dkey, data, len, usage, result); - return 0; + return (*ct->checksum)(context, dkey, data, len, usage, result); } static int @@ -1968,9 +1867,11 @@ verify_checksum(krb5_context context, ct->name); return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */ } - if(keyed_checksum) + if(keyed_checksum) { ret = get_checksum_key(context, crypto, usage, ct, &dkey); - else + if (ret) + return ret; + } else dkey = NULL; if(ct->verify) return (*ct->verify)(context, dkey, data, len, usage, cksum); @@ -1979,7 +1880,11 @@ verify_checksum(krb5_context context, if (ret) return ret; - (*ct->checksum)(context, dkey, data, len, usage, &c); + ret = (*ct->checksum)(context, dkey, data, len, usage, &c); + if (ret) { + krb5_data_free(&c.checksum); + return ret; + } if(c.checksum.length != cksum->checksum.length || memcmp(c.checksum.data, cksum->checksum.data, c.checksum.length)) { @@ -2125,7 +2030,37 @@ NULL_encrypt(krb5_context context, } static krb5_error_code -DES_CBC_encrypt_null_ivec(krb5_context context, +evp_encrypt(krb5_context context, + struct key_data *key, + void *data, + size_t len, + krb5_boolean encryptp, + int usage, + void *ivec) +{ + struct evp_schedule *ctx = key->schedule->data; + EVP_CIPHER_CTX *c; + c = encryptp ? &ctx->ectx : &ctx->dctx; + if (ivec == NULL) { + /* alloca ? */ + size_t len = EVP_CIPHER_CTX_iv_length(c); + void *loiv = malloc(len); + if (loiv == NULL) { + krb5_clear_error_string(context); + return ENOMEM; + } + memset(loiv, 0, len); + EVP_CipherInit_ex(c, NULL, NULL, NULL, loiv, -1); + free(loiv); + } else + EVP_CipherInit_ex(c, NULL, NULL, NULL, ivec, -1); + EVP_Cipher(c, data, data, len); + return 0; +} + +#ifdef WEAK_ENCTYPES +static krb5_error_code +evp_des_encrypt_null_ivec(krb5_context context, struct key_data *key, void *data, size_t len, @@ -2133,15 +2068,18 @@ DES_CBC_encrypt_null_ivec(krb5_context context, int usage, void *ignore_ivec) { + struct evp_schedule *ctx = key->schedule->data; + EVP_CIPHER_CTX *c; DES_cblock ivec; - DES_key_schedule *s = key->schedule->data; memset(&ivec, 0, sizeof(ivec)); - DES_cbc_encrypt(data, data, len, s, &ivec, encryptp); + c = encryptp ? &ctx->ectx : &ctx->dctx; + EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1); + EVP_Cipher(c, data, data, len); return 0; } static krb5_error_code -DES_CBC_encrypt_key_ivec(krb5_context context, +evp_des_encrypt_key_ivec(krb5_context context, struct key_data *key, void *data, size_t len, @@ -2149,29 +2087,13 @@ DES_CBC_encrypt_key_ivec(krb5_context context, int usage, void *ignore_ivec) { + struct evp_schedule *ctx = key->schedule->data; + EVP_CIPHER_CTX *c; DES_cblock ivec; - DES_key_schedule *s = key->schedule->data; memcpy(&ivec, key->key->keyvalue.data, sizeof(ivec)); - DES_cbc_encrypt(data, data, len, s, &ivec, encryptp); - return 0; -} - -static krb5_error_code -DES3_CBC_encrypt(krb5_context context, - struct key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ivec) -{ - DES_cblock local_ivec; - DES_key_schedule *s = key->schedule->data; - if(ivec == NULL) { - ivec = &local_ivec; - memset(local_ivec, 0, sizeof(local_ivec)); - } - DES_ede3_cbc_encrypt(data, data, len, &s[0], &s[1], &s[2], ivec, encryptp); + c = encryptp ? &ctx->ectx : &ctx->dctx; + EVP_CipherInit_ex(c, NULL, NULL, NULL, (void *)&ivec, -1); + EVP_Cipher(c, data, data, len); return 0; } @@ -2209,114 +2131,7 @@ DES_PCBC_encrypt_key_ivec(krb5_context context, DES_pcbc_encrypt(data, data, len, s, &ivec, encryptp); return 0; } - -/* - * AES draft-raeburn-krb-rijndael-krb-02 - */ - -void KRB5_LIB_FUNCTION -_krb5_aes_cts_encrypt(const unsigned char *in, unsigned char *out, - size_t len, const AES_KEY *key, - unsigned char *ivec, const int encryptp) -{ - unsigned char tmp[AES_BLOCK_SIZE]; - int i; - - /* - * In the framework of kerberos, the length can never be shorter - * then at least one blocksize. - */ - - if (encryptp) { - - while(len > AES_BLOCK_SIZE) { - for (i = 0; i < AES_BLOCK_SIZE; i++) - tmp[i] = in[i] ^ ivec[i]; - AES_encrypt(tmp, out, key); - memcpy(ivec, out, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - - for (i = 0; i < len; i++) - tmp[i] = in[i] ^ ivec[i]; - for (; i < AES_BLOCK_SIZE; i++) - tmp[i] = 0 ^ ivec[i]; - - AES_encrypt(tmp, out - AES_BLOCK_SIZE, key); - - memcpy(out, ivec, len); - memcpy(ivec, out - AES_BLOCK_SIZE, AES_BLOCK_SIZE); - - } else { - unsigned char tmp2[AES_BLOCK_SIZE]; - unsigned char tmp3[AES_BLOCK_SIZE]; - - while(len > AES_BLOCK_SIZE * 2) { - memcpy(tmp, in, AES_BLOCK_SIZE); - AES_decrypt(in, out, key); - for (i = 0; i < AES_BLOCK_SIZE; i++) - out[i] ^= ivec[i]; - memcpy(ivec, tmp, AES_BLOCK_SIZE); - len -= AES_BLOCK_SIZE; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - - len -= AES_BLOCK_SIZE; - - memcpy(tmp, in, AES_BLOCK_SIZE); /* save last iv */ - AES_decrypt(in, tmp2, key); - - memcpy(tmp3, in + AES_BLOCK_SIZE, len); - memcpy(tmp3 + len, tmp2 + len, AES_BLOCK_SIZE - len); /* xor 0 */ - - for (i = 0; i < len; i++) - out[i + AES_BLOCK_SIZE] = tmp2[i] ^ tmp3[i]; - - AES_decrypt(tmp3, out, key); - for (i = 0; i < AES_BLOCK_SIZE; i++) - out[i] ^= ivec[i]; - memcpy(ivec, tmp, AES_BLOCK_SIZE); - } -} - -static krb5_error_code -AES_CTS_encrypt(krb5_context context, - struct key_data *key, - void *data, - size_t len, - krb5_boolean encryptp, - int usage, - void *ivec) -{ - struct krb5_aes_schedule *aeskey = key->schedule->data; - char local_ivec[AES_BLOCK_SIZE]; - AES_KEY *k; - - if (encryptp) - k = &aeskey->ekey; - else - k = &aeskey->dkey; - - if (len < AES_BLOCK_SIZE) - krb5_abortx(context, "invalid use of AES_CTS_encrypt"); - if (len == AES_BLOCK_SIZE) { - if (encryptp) - AES_encrypt(data, data, k); - else - AES_decrypt(data, data, k); - } else { - if(ivec == NULL) { - memset(local_ivec, 0, sizeof(local_ivec)); - ivec = local_ivec; - } - _krb5_aes_cts_encrypt(data, data, len, k, ivec, encryptp); - } - - return 0; -} +#endif /* * section 6 of draft-brezak-win2k-krb-rc4-hmac-03 @@ -2530,7 +2345,11 @@ AES_PRF(krb5_context context, return ret; } - (*ct->checksum)(context, NULL, in->data, in->length, 0, &result); + ret = (*ct->checksum)(context, NULL, in->data, in->length, 0, &result); + if (ret) { + krb5_data_free(&result.checksum); + return ret; + } if (result.checksum.length < crypto->et->blocksize) krb5_abortx(context, "internal prf error"); @@ -2546,12 +2365,13 @@ AES_PRF(krb5_context context, krb5_abortx(context, "malloc failed"); { - AES_KEY key; - - AES_set_encrypt_key(derived->keyvalue.data, - crypto->et->keytype->bits, &key); - AES_encrypt(result.checksum.data, out->data, &key); - memset(&key, 0, sizeof(key)); + const EVP_CIPHER *c = (*crypto->et->keytype->evp)(); + EVP_CIPHER_CTX ctx; + /* XXX blksz 1 for cts, so we can't use that */ + EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */ + EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1); + EVP_Cipher(&ctx, out->data, result.checksum.data, 16); + EVP_CIPHER_CTX_cleanup(&ctx); } krb5_data_free(&result.checksum); @@ -2578,48 +2398,6 @@ static struct encryption_type enctype_null = { 0, NULL }; -static struct encryption_type enctype_des_cbc_crc = { - ETYPE_DES_CBC_CRC, - "des-cbc-crc", - 8, - 8, - 8, - &keytype_des, - &checksum_crc32, - NULL, - 0, - DES_CBC_encrypt_key_ivec, - 0, - NULL -}; -static struct encryption_type enctype_des_cbc_md4 = { - ETYPE_DES_CBC_MD4, - "des-cbc-md4", - 8, - 8, - 8, - &keytype_des, - &checksum_rsa_md4, - &checksum_rsa_md4_des, - 0, - DES_CBC_encrypt_null_ivec, - 0, - NULL -}; -static struct encryption_type enctype_des_cbc_md5 = { - ETYPE_DES_CBC_MD5, - "des-cbc-md5", - 8, - 8, - 8, - &keytype_des, - &checksum_rsa_md5, - &checksum_rsa_md5_des, - 0, - DES_CBC_encrypt_null_ivec, - 0, - NULL -}; static struct encryption_type enctype_arcfour_hmac_md5 = { ETYPE_ARCFOUR_HMAC_MD5, "arcfour-hmac-md5", @@ -2634,6 +2412,7 @@ static struct encryption_type enctype_arcfour_hmac_md5 = { 0, NULL }; +#ifdef DES3_OLD_ENCTYPE static struct encryption_type enctype_des3_cbc_md5 = { ETYPE_DES3_CBC_MD5, "des3-cbc-md5", @@ -2644,10 +2423,11 @@ static struct encryption_type enctype_des3_cbc_md5 = { &checksum_rsa_md5, &checksum_rsa_md5_des3, 0, - DES3_CBC_encrypt, + evp_encrypt, 0, NULL }; +#endif static struct encryption_type enctype_des3_cbc_sha1 = { ETYPE_DES3_CBC_SHA1, "des3-cbc-sha1", @@ -2658,10 +2438,11 @@ static struct encryption_type enctype_des3_cbc_sha1 = { &checksum_sha1, &checksum_hmac_sha1_des3, F_DERIVED, - DES3_CBC_encrypt, + evp_encrypt, 0, NULL }; +#ifdef DES3_OLD_ENCTYPE static struct encryption_type enctype_old_des3_cbc_sha1 = { ETYPE_OLD_DES3_CBC_SHA1, "old-des3-cbc-sha1", @@ -2672,10 +2453,11 @@ static struct encryption_type enctype_old_des3_cbc_sha1 = { &checksum_sha1, &checksum_hmac_sha1_des3, 0, - DES3_CBC_encrypt, + evp_encrypt, 0, NULL }; +#endif static struct encryption_type enctype_aes128_cts_hmac_sha1 = { ETYPE_AES128_CTS_HMAC_SHA1_96, "aes128-cts-hmac-sha1-96", @@ -2686,7 +2468,7 @@ static struct encryption_type enctype_aes128_cts_hmac_sha1 = { &checksum_sha1, &checksum_hmac_sha1_aes128, F_DERIVED, - AES_CTS_encrypt, + evp_encrypt, 16, AES_PRF }; @@ -2700,10 +2482,67 @@ static struct encryption_type enctype_aes256_cts_hmac_sha1 = { &checksum_sha1, &checksum_hmac_sha1_aes256, F_DERIVED, - AES_CTS_encrypt, + evp_encrypt, 16, AES_PRF }; +static struct encryption_type enctype_des3_cbc_none = { + ETYPE_DES3_CBC_NONE, + "des3-cbc-none", + 8, + 8, + 0, + &keytype_des3_derived, + &checksum_none, + NULL, + F_PSEUDO, + evp_encrypt, + 0, + NULL +}; +#ifdef WEAK_ENCTYPES +static struct encryption_type enctype_des_cbc_crc = { + ETYPE_DES_CBC_CRC, + "des-cbc-crc", + 8, + 8, + 8, + &keytype_des, + &checksum_crc32, + NULL, + F_DISABLED, + evp_des_encrypt_key_ivec, + 0, + NULL +}; +static struct encryption_type enctype_des_cbc_md4 = { + ETYPE_DES_CBC_MD4, + "des-cbc-md4", + 8, + 8, + 8, + &keytype_des, + &checksum_rsa_md4, + &checksum_rsa_md4_des, + F_DISABLED, + evp_des_encrypt_null_ivec, + 0, + NULL +}; +static struct encryption_type enctype_des_cbc_md5 = { + ETYPE_DES_CBC_MD5, + "des-cbc-md5", + 8, + 8, + 8, + &keytype_des, + &checksum_rsa_md5, + &checksum_rsa_md5_des, + F_DISABLED, + evp_des_encrypt_null_ivec, + 0, + NULL +}; static struct encryption_type enctype_des_cbc_none = { ETYPE_DES_CBC_NONE, "des-cbc-none", @@ -2713,8 +2552,8 @@ static struct encryption_type enctype_des_cbc_none = { &keytype_des, &checksum_none, NULL, - F_PSEUDO, - DES_CBC_encrypt_null_ivec, + F_PSEUDO|F_DISABLED, + evp_des_encrypt_null_ivec, 0, NULL }; @@ -2724,10 +2563,10 @@ static struct encryption_type enctype_des_cfb64_none = { 1, 1, 0, - &keytype_des, + &keytype_des_old, &checksum_none, NULL, - F_PSEUDO, + F_PSEUDO|F_DISABLED, DES_CFB64_encrypt_null_ivec, 0, NULL @@ -2738,44 +2577,35 @@ static struct encryption_type enctype_des_pcbc_none = { 8, 8, 0, - &keytype_des, + &keytype_des_old, &checksum_none, NULL, - F_PSEUDO, + F_PSEUDO|F_DISABLED, DES_PCBC_encrypt_key_ivec, 0, NULL }; -static struct encryption_type enctype_des3_cbc_none = { - ETYPE_DES3_CBC_NONE, - "des3-cbc-none", - 8, - 8, - 0, - &keytype_des3_derived, - &checksum_none, - NULL, - F_PSEUDO, - DES3_CBC_encrypt, - 0, - NULL -}; +#endif /* WEAK_ENCTYPES */ static struct encryption_type *etypes[] = { - &enctype_null, - &enctype_des_cbc_crc, - &enctype_des_cbc_md4, - &enctype_des_cbc_md5, + &enctype_aes256_cts_hmac_sha1, + &enctype_aes128_cts_hmac_sha1, + &enctype_des3_cbc_sha1, + &enctype_des3_cbc_none, /* used by the gss-api mech */ &enctype_arcfour_hmac_md5, +#ifdef DES3_OLD_ENCTYPE &enctype_des3_cbc_md5, - &enctype_des3_cbc_sha1, &enctype_old_des3_cbc_sha1, - &enctype_aes128_cts_hmac_sha1, - &enctype_aes256_cts_hmac_sha1, +#endif +#ifdef WEAK_ENCTYPES + &enctype_des_cbc_crc, + &enctype_des_cbc_md4, + &enctype_des_cbc_md5, &enctype_des_cbc_none, &enctype_des_cfb64_none, &enctype_des_pcbc_none, - &enctype_des3_cbc_none +#endif + &enctype_null }; static unsigned num_etypes = sizeof(etypes) / sizeof(etypes[0]); @@ -2878,37 +2708,6 @@ krb5_keytype_to_enctypes (krb5_context context, return 0; } -/* - * First take the configured list of etypes for `keytype' if available, - * else, do `krb5_keytype_to_enctypes'. - */ - -krb5_error_code KRB5_LIB_FUNCTION -krb5_keytype_to_enctypes_default (krb5_context context, - krb5_keytype keytype, - unsigned *len, - krb5_enctype **val) -{ - unsigned int i, n; - krb5_enctype *ret; - - if (keytype != KEYTYPE_DES || context->etypes_des == NULL) - return krb5_keytype_to_enctypes (context, keytype, len, val); - - for (n = 0; context->etypes_des[n]; ++n) - ; - ret = malloc (n * sizeof(*ret)); - if (ret == NULL && n != 0) { - krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); - return ENOMEM; - } - for (i = 0; i < n; ++i) - ret[i] = context->etypes_des[i]; - *len = n; - *val = ret; - return 0; -} - krb5_error_code KRB5_LIB_FUNCTION krb5_enctype_valid(krb5_context context, krb5_enctype etype) @@ -3032,9 +2831,6 @@ encrypt_internal_derived(krb5_context context, ret = _key_schedule(context, dkey); if(ret) goto fail; -#ifdef CRYPTO_DEBUG - krb5_crypto_debug(context, 1, block_sz, dkey->key); -#endif ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec); if (ret) goto fail; @@ -3098,9 +2894,6 @@ encrypt_internal(krb5_context context, ret = _key_schedule(context, &crypto->key); if(ret) goto fail; -#ifdef CRYPTO_DEBUG - krb5_crypto_debug(context, 1, block_sz, crypto->key.key); -#endif ret = (*et->encrypt)(context, &crypto->key, p, block_sz, 1, 0, ivec); if (ret) { memset(p, 0, block_sz); @@ -3202,9 +2995,6 @@ decrypt_internal_derived(krb5_context context, free(p); return ret; } -#ifdef CRYPTO_DEBUG - krb5_crypto_debug(context, 0, len, dkey->key); -#endif ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec); if (ret) { free(p); @@ -3269,9 +3059,6 @@ decrypt_internal(krb5_context context, free(p); return ret; } -#ifdef CRYPTO_DEBUG - krb5_crypto_debug(context, 0, len, crypto->key.key); -#endif ret = (*et->encrypt)(context, &crypto->key, p, len, 0, 0, ivec); if (ret) { free(p); @@ -3346,9 +3133,389 @@ decrypt_internal_special(krb5_context context, return 0; } +/** + * Inline encrypt a kerberos message + * + * @param context Kerberos context + * @param crypto Kerberos crypto context + * @param usage Key usage for this buffer + * @param data array of buffers to process + * @param num_data length of array + * @param ivec initial cbc/cts vector + * + * @return Return an error code or 0. + * @ingroup krb5_crypto + * + * Kerberos encrypted data look like this: + * + * 1. KRB5_CRYPTO_TYPE_HEADER + * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in + * any order, however the receiver have to aware of the + * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used headers and + * trailers. + * 3. KRB5_CRYPTO_TYPE_TRAILER + */ -krb5_error_code KRB5_LIB_FUNCTION -krb5_encrypt_ivec(krb5_context context, +static krb5_crypto_iov * +find_iv(krb5_crypto_iov *data, int num_data, int type) +{ + int i; + for (i = 0; i < num_data; i++) + if (data[i].flags == type) + return &data[i]; + return NULL; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt_iov_ivec(krb5_context context, + krb5_crypto crypto, + unsigned usage, + krb5_crypto_iov *data, + size_t num_data, + void *ivec) +{ + size_t headersz, trailersz, len; + size_t i, sz, block_sz, pad_sz; + Checksum cksum; + unsigned char *p, *q; + krb5_error_code ret; + struct key_data *dkey; + const struct encryption_type *et = crypto->et; + krb5_crypto_iov *tiv, *piv, *hiv; + + if(!derived_crypto(context, crypto)) { + krb5_clear_error_string(context); + return KRB5_CRYPTO_INTERNAL; + } + + headersz = et->confoundersize; + trailersz = CHECKSUMSIZE(et->keyed_checksum); + + for (len = 0, i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER && + data[i].flags == KRB5_CRYPTO_TYPE_DATA) { + len += data[i].data.length; + } + } + + sz = headersz + len; + block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ + + pad_sz = block_sz - sz; + trailersz += pad_sz; + + /* header */ + + hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (hiv == NULL || hiv->data.length != headersz) + return KRB5_BAD_MSIZE; + + krb5_generate_random_block(hiv->data.data, hiv->data.length); + + /* padding */ + + piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING); + /* its ok to have no TYPE_PADDING if there is no padding */ + if (piv == NULL && pad_sz != 0) + return KRB5_BAD_MSIZE; + if (piv) { + if (piv->data.length < pad_sz) + return KRB5_BAD_MSIZE; + piv->data.length = pad_sz; + } + + + /* trailer */ + + tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (tiv == NULL || tiv->data.length != trailersz) + return KRB5_BAD_MSIZE; + + + /* + * XXX replace with EVP_Sign? at least make create_checksum an iov + * function. + * XXX CTS EVP is broken, can't handle multi buffers :( + */ + + len = hiv->data.length; + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && + data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) + continue; + len += data[i].data.length; + } + + p = q = malloc(len); + + memcpy(q, hiv->data.data, hiv->data.length); + q += hiv->data.length; + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && + data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) + continue; + memcpy(q, data[i].data.data, data[i].data.length); + q += data[i].data.length; + } + + ret = create_checksum(context, + et->keyed_checksum, + crypto, + INTEGRITY_USAGE(usage), + p, + len, + &cksum); + free(p); + if(ret == 0 && cksum.checksum.length != trailersz) { + free_Checksum (&cksum); + krb5_clear_error_string (context); + ret = KRB5_CRYPTO_INTERNAL; + } + if(ret) + return ret; + + /* save cksum at end */ + memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length); + free_Checksum (&cksum); + + /* now encrypt data */ + + ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); + if(ret) + return ret; + ret = _key_schedule(context, dkey); + if(ret) + return ret; + + /* XXX replace with EVP_Cipher */ + + len = hiv->data.length; + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && + data[i].flags != KRB5_CRYPTO_TYPE_PADDING) + continue; + len += data[i].data.length; + } + + p = q = malloc(len); + if(p == NULL) + return ENOMEM; + + memcpy(q, hiv->data.data, hiv->data.length); + q += hiv->data.length; + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && + data[i].flags != KRB5_CRYPTO_TYPE_PADDING) + continue; + memcpy(q, data[i].data.data, data[i].data.length); + q += data[i].data.length; + } + + ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); + if(ret) { + free(p); + return ret; + } + ret = _key_schedule(context, dkey); + if(ret) { + free(p); + return ret; + } + + ret = (*et->encrypt)(context, dkey, p, len, 1, usage, ivec); + if (ret) { + free(p); + return ret; + } + + /* now copy data back to buffers */ + q = p; + memcpy(hiv->data.data, q, hiv->data.length); + q += hiv->data.length; + + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && + data[i].flags != KRB5_CRYPTO_TYPE_PADDING) + continue; + memcpy(data[i].data.data, q, data[i].data.length); + q += data[i].data.length; + } + free(p); + + return ret; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_decrypt_iov_ivec(krb5_context context, + krb5_crypto crypto, + unsigned usage, + krb5_crypto_iov *data, + size_t num_data, + void *ivec) +{ + size_t headersz, trailersz, len; + size_t i, sz, block_sz, pad_sz; + Checksum cksum; + unsigned char *p, *q; + krb5_error_code ret; + struct key_data *dkey; + struct encryption_type *et = crypto->et; + krb5_crypto_iov *tiv, *hiv; + + if(!derived_crypto(context, crypto)) { + krb5_clear_error_string(context); + return KRB5_CRYPTO_INTERNAL; + } + + headersz = et->confoundersize; + trailersz = CHECKSUMSIZE(et->keyed_checksum); + + for (len = 0, i = 0; i < num_data; i++) + if (data[i].flags == KRB5_CRYPTO_TYPE_DATA) + len += data[i].data.length; + + sz = headersz + len; + block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */ + + pad_sz = block_sz - sz; + trailersz += pad_sz; + + /* header */ + + hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER); + if (hiv == NULL || hiv->data.length < headersz) + return KRB5_BAD_MSIZE; + hiv->data.length = headersz; + + /* trailer */ + + tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER); + if (tiv == NULL || tiv->data.length < trailersz) + return KRB5_BAD_MSIZE; + tiv->data.length = trailersz; + + /* body */ + + /* XXX replace with EVP_Cipher */ + + for (len = 0, i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER && + data[i].flags != KRB5_CRYPTO_TYPE_DATA) + continue; + len += data[i].data.length; + } + + p = q = malloc(len); + if (p == NULL) + return ENOMEM; + + memcpy(q, hiv->data.data, hiv->data.length); + q += hiv->data.length; + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) + continue; + memcpy(q, data[i].data.data, data[i].data.length); + q += data[i].data.length; + } + + ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey); + if(ret) { + free(p); + return ret; + } + ret = _key_schedule(context, dkey); + if(ret) { + free(p); + return ret; + } + + ret = (*et->encrypt)(context, dkey, p, len, 0, usage, ivec); + if (ret) { + free(p); + return ret; + } + + /* XXX now copy data back to buffers */ + q = p; + memcpy(hiv->data.data, q, hiv->data.length); + q += hiv->data.length; + len -= hiv->data.length; + + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA) + continue; + if (len < data[i].data.length) + data[i].data.length = len; + memcpy(data[i].data.data, q, data[i].data.length); + q += data[i].data.length; + len -= data[i].data.length; + } + free(p); + if (len) + krb5_abortx(context, "data still in the buffer"); + + len = hiv->data.length; + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && + data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) + continue; + len += data[i].data.length; + } + + p = q = malloc(len); + + memcpy(q, hiv->data.data, hiv->data.length); + q += hiv->data.length; + for (i = 0; i < num_data; i++) { + if (data[i].flags != KRB5_CRYPTO_TYPE_DATA && + data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY) + continue; + memcpy(q, data[i].data.data, data[i].data.length); + q += data[i].data.length; + } + + cksum.checksum.data = tiv->data.data; + cksum.checksum.length = tiv->data.length; + cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum); + + ret = verify_checksum(context, + crypto, + INTEGRITY_USAGE(usage), + p, + len, + &cksum); + free(p); + if(ret) + return ret; + + return 0; +} + + +size_t KRB5_LIB_FUNCTION +krb5_crypto_length(krb5_context context, + krb5_crypto crypto, + int type) +{ + if (!derived_crypto(context, crypto)) + return (size_t)-1; + switch(type) { + case KRB5_CRYPTO_TYPE_EMPTY: + return 0; + case KRB5_CRYPTO_TYPE_HEADER: + return crypto->et->blocksize; + case KRB5_CRYPTO_TYPE_PADDING: + if (crypto->et->padsize > 1) + return crypto->et->padsize; + return 0; + case KRB5_CRYPTO_TYPE_TRAILER: + return CHECKSUMSIZE(crypto->et->keyed_checksum); + } + return (size_t)-1; +} + +krb5_error_code KRB5_LIB_FUNCTION +krb5_encrypt_ivec(krb5_context context, krb5_crypto crypto, unsigned usage, const void *data, @@ -3452,7 +3619,7 @@ seed_something(void) so use 0 for the entropy estimate */ if (RAND_file_name(seedfile, sizeof(seedfile))) { int fd; - fd = open(seedfile, O_RDONLY); + fd = open(seedfile, O_RDONLY | O_BINARY | O_CLOEXEC); if (fd >= 0) { ssize_t ret; rk_cloexec(fd); @@ -3652,7 +3819,7 @@ krb5_derive_key(krb5_context context, ret = derive_key(context, et, &d, constant, constant_len); if (ret == 0) ret = krb5_copy_keyblock(context, d.key, derived_key); - free_key_data(context, &d); + free_key_data(context, &d, et); return ret; } @@ -3727,19 +3894,23 @@ krb5_crypto_init(krb5_context context, } static void -free_key_data(krb5_context context, struct key_data *key) +free_key_data(krb5_context context, struct key_data *key, + struct encryption_type *et) { krb5_free_keyblock(context, key->key); if(key->schedule) { + if (et->keytype->cleanup) + (*et->keytype->cleanup)(context, key); memset(key->schedule->data, 0, key->schedule->length); krb5_free_data(context, key->schedule); } } static void -free_key_usage(krb5_context context, struct key_usage *ku) +free_key_usage(krb5_context context, struct key_usage *ku, + struct encryption_type *et) { - free_key_data(context, &ku->key); + free_key_data(context, &ku->key, et); } krb5_error_code KRB5_LIB_FUNCTION @@ -3749,9 +3920,9 @@ krb5_crypto_destroy(krb5_context context, int i; for(i = 0; i < crypto->num_key_usage; i++) - free_key_usage(context, &crypto->key_usage[i]); + free_key_usage(context, &crypto->key_usage[i], crypto->et); free(crypto->key_usage); - free_key_data(context, &crypto->key); + free_key_data(context, &crypto->key, crypto->et); free (crypto); return 0; } @@ -3792,6 +3963,18 @@ krb5_crypto_getconfoundersize(krb5_context context, return 0; } + +/** + * Disable encryption type + * + * @param context Kerberos 5 context + * @param enctype encryption type to disable + * + * @return Return an error code or 0. + * + * @ingroup krb5_crypto + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_enctype_disable(krb5_context context, krb5_enctype enctype) @@ -3808,6 +3991,34 @@ krb5_enctype_disable(krb5_context context, return 0; } +/** + * Enable encryption type + * + * @param context Kerberos 5 context + * @param enctype encryption type to enable + * + * @return Return an error code or 0. + * + * @ingroup krb5_crypto + */ + +krb5_error_code KRB5_LIB_FUNCTION +krb5_enctype_enable(krb5_context context, + krb5_enctype enctype) +{ + struct encryption_type *et = _find_enctype(enctype); + if(et == NULL) { + if (context) + krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, + "encryption type %d not supported", + enctype); + return KRB5_PROG_ETYPE_NOSUPP; + } + et->flags &= ~F_DISABLED; + return 0; +} + + krb5_error_code KRB5_LIB_FUNCTION krb5_string_to_key_derived(krb5_context context, const void *str, @@ -3862,8 +4073,12 @@ krb5_string_to_key_derived(krb5_context context, &kd, "kerberos", /* XXX well known constant */ strlen("kerberos")); + if (ret) { + free_key_data(context, &kd, et); + return ret; + } ret = krb5_copy_keyblock_contents(context, kd.key, key); - free_key_data(context, &kd); + free_key_data(context, &kd, et); return ret; } @@ -4265,108 +4480,86 @@ krb5_crypto_prf(krb5_context context, return (*et->prf)(context, crypto, input, output); } - +#ifndef HEIMDAL_SMALLER +/* + * First take the configured list of etypes for `keytype' if available, + * else, do `krb5_keytype_to_enctypes'. + */ -#ifdef CRYPTO_DEBUG - -static krb5_error_code -krb5_get_keyid(krb5_context context, - krb5_keyblock *key, - uint32_t *keyid) +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctypes_default (krb5_context context, + krb5_keytype keytype, + unsigned *len, + krb5_enctype **val) + __attribute__((deprecated)) { - MD5_CTX md5; - unsigned char tmp[16]; + unsigned int i, n; + krb5_enctype *ret; - MD5_Init (&md5); - MD5_Update (&md5, key->keyvalue.data, key->keyvalue.length); - MD5_Final (tmp, &md5); - *keyid = (tmp[12] << 24) | (tmp[13] << 16) | (tmp[14] << 8) | tmp[15]; + if (keytype != KEYTYPE_DES || context->etypes_des == NULL) + return krb5_keytype_to_enctypes (context, keytype, len, val); + + for (n = 0; context->etypes_des[n]; ++n) + ; + ret = malloc (n * sizeof(*ret)); + if (ret == NULL && n != 0) { + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); + return ENOMEM; + } + for (i = 0; i < n; ++i) + ret[i] = context->etypes_des[i]; + *len = n; + *val = ret; return 0; } -static void -krb5_crypto_debug(krb5_context context, - int encryptp, - size_t len, - krb5_keyblock *key) +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_string(krb5_context context, + krb5_keytype keytype, + char **string) + __attribute__((deprecated)) { - uint32_t keyid; - char *kt; - krb5_get_keyid(context, key, &keyid); - krb5_enctype_to_string(context, key->keytype, &kt); - krb5_warnx(context, "%s %lu bytes with key-id %#x (%s)", - encryptp ? "encrypting" : "decrypting", - (unsigned long)len, - keyid, - kt); - free(kt); + struct key_type *kt = _find_keytype(keytype); + if(kt == NULL) { + krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP, + "key type %d not supported", keytype); + return KRB5_PROG_KEYTYPE_NOSUPP; + } + *string = strdup(kt->name); + if(*string == NULL) { + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); + return ENOMEM; + } + return 0; } -#endif /* CRYPTO_DEBUG */ -#if 0 -int -main() +krb5_error_code KRB5_LIB_FUNCTION +krb5_string_to_keytype(krb5_context context, + const char *string, + krb5_keytype *keytype) + __attribute__((deprecated)) { -#if 0 - int i; - krb5_context context; - krb5_crypto crypto; - struct key_data *d; - krb5_keyblock key; - char constant[4]; - unsigned usage = ENCRYPTION_USAGE(3); - krb5_error_code ret; - - ret = krb5_init_context(&context); - if (ret) - errx (1, "krb5_init_context failed: %d", ret); - - key.keytype = ETYPE_NEW_DES3_CBC_SHA1; - key.keyvalue.data = "\xb3\x85\x58\x94\xd9\xdc\x7c\xc8" - "\x25\xe9\x85\xab\x3e\xb5\xfb\x0e" - "\xc8\xdf\xab\x26\x86\x64\x15\x25"; - key.keyvalue.length = 24; - - krb5_crypto_init(context, &key, 0, &crypto); - - d = _new_derived_key(crypto, usage); - if(d == NULL) - krb5_errx(context, 1, "_new_derived_key failed"); - krb5_copy_keyblock(context, crypto->key.key, &d->key); - _krb5_put_int(constant, usage, 4); - derive_key(context, crypto->et, d, constant, sizeof(constant)); - return 0; -#else + char *end; int i; - krb5_context context; - krb5_crypto crypto; - struct key_data *d; - krb5_keyblock key; - krb5_error_code ret; - Checksum res; - - char *data = "what do ya want for nothing?"; - ret = krb5_init_context(&context); - if (ret) - errx (1, "krb5_init_context failed: %d", ret); - - key.keytype = ETYPE_NEW_DES3_CBC_SHA1; - key.keyvalue.data = "Jefe"; - /* "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"; */ - key.keyvalue.length = 4; + for(i = 0; i < num_keytypes; i++) + if(strcasecmp(keytypes[i]->name, string) == 0){ + *keytype = keytypes[i]->type; + return 0; + } - d = ecalloc(1, sizeof(*d)); - d->key = &key; - res.checksum.length = 20; - res.checksum.data = emalloc(res.checksum.length); - SP_HMAC_SHA1_checksum(context, d, data, 28, &res); + /* check if the enctype is a number */ + *keytype = strtol(string, &end, 0); + if(*end == '\0' && *keytype != 0) { + if (krb5_enctype_valid(context, *keytype) == 0) + return 0; + } - return 0; -#endif + krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP, + "key type %s not supported", string); + return KRB5_PROG_KEYTYPE_NOSUPP; } #endif diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c index 2b78bfb32b..0286316214 100644 --- a/source4/heimdal/lib/krb5/data.c +++ b/source4/heimdal/lib/krb5/data.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: data.c 23280 2008-06-23 03:26:18Z lha $"); +RCSID("$Id$"); /** * Reset the (potentially uninitalized) krb5_data structure. diff --git a/source4/heimdal/lib/krb5/eai_to_heim_errno.c b/source4/heimdal/lib/krb5/eai_to_heim_errno.c index 19315cea86..c06e8fb9bb 100644 --- a/source4/heimdal/lib/krb5/eai_to_heim_errno.c +++ b/source4/heimdal/lib/krb5/eai_to_heim_errno.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: eai_to_heim_errno.c 22065 2007-11-11 16:41:06Z lha $"); +RCSID("$Id$"); /** * Convert the getaddrinfo() error code to a Kerberos et error code. diff --git a/source4/heimdal/lib/krb5/error_string.c b/source4/heimdal/lib/krb5/error_string.c index 6679b76749..17bc30572b 100644 --- a/source4/heimdal/lib/krb5/error_string.c +++ b/source4/heimdal/lib/krb5/error_string.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: error_string.c 23274 2008-06-23 03:25:08Z lha $"); +RCSID("$Id$"); #undef __attribute__ #define __attribute__(X) @@ -199,7 +199,7 @@ krb5_free_error_message(krb5_context context, const char *msg) * @param context Kerberos context * @param msg error message to free * - * @ingroup krb5_error + * @ingroup krb5_deprecated */ void KRB5_LIB_FUNCTION __attribute__((deprecated)) @@ -208,6 +208,16 @@ krb5_free_error_string(krb5_context context, char *str) krb5_free_error_message(context, str); } +/** + * Set the error message returned by krb5_get_error_string(), + * deprecated, use krb5_set_error_message(). + * + * @param context Kerberos context + * @param msg error message to free + * + * @ingroup krb5_deprecated + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_set_error_string(krb5_context context, const char *fmt, ...) __attribute__((format (printf, 2, 3))) __attribute__((deprecated)) @@ -220,6 +230,16 @@ krb5_set_error_string(krb5_context context, const char *fmt, ...) return 0; } +/** + * Set the error message returned by krb5_get_error_string(), + * deprecated, use krb5_set_error_message(). + * + * @param context Kerberos context + * @param msg error message to free + * + * @ingroup krb5_deprecated + */ + krb5_error_code KRB5_LIB_FUNCTION krb5_vset_error_string(krb5_context context, const char *fmt, va_list args) __attribute__ ((format (printf, 2, 0))) __attribute__((deprecated)) diff --git a/source4/heimdal/lib/krb5/expand_hostname.c b/source4/heimdal/lib/krb5/expand_hostname.c index d06d576432..4ada4b8110 100644 --- a/source4/heimdal/lib/krb5/expand_hostname.c +++ b/source4/heimdal/lib/krb5/expand_hostname.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: expand_hostname.c 23280 2008-06-23 03:26:18Z lha $"); +RCSID("$Id$"); static krb5_error_code copy_hostname(krb5_context context, diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c index 8951bdb24e..fc11893452 100644 --- a/source4/heimdal/lib/krb5/fcache.c +++ b/source4/heimdal/lib/krb5/fcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: fcache.c 23444 2008-07-27 12:07:47Z lha $"); +RCSID("$Id$"); typedef struct krb5_fcache{ char *filename; @@ -395,7 +395,7 @@ fcc_initialize(krb5_context context, unlink (filename); - ret = fcc_open(context, id, &fd, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600); + ret = fcc_open(context, id, &fd, O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, 0600); if(ret) return ret; { @@ -462,7 +462,7 @@ fcc_store_cred(krb5_context context, int ret; int fd; - ret = fcc_open(context, id, &fd, O_WRONLY | O_APPEND | O_BINARY, 0); + ret = fcc_open(context, id, &fd, O_WRONLY | O_APPEND | O_BINARY | O_CLOEXEC, 0); if(ret) return ret; { @@ -503,7 +503,7 @@ init_fcc (krb5_context context, krb5_storage *sp; krb5_error_code ret; - ret = fcc_open(context, id, &fd, O_RDONLY | O_BINARY, 0); + ret = fcc_open(context, id, &fd, O_RDONLY | O_BINARY | O_CLOEXEC, 0); if(ret) return ret; @@ -851,14 +851,14 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to) int fd1, fd2; char buf[BUFSIZ]; - ret = fcc_open(context, from, &fd1, O_RDONLY | O_BINARY, 0); + ret = fcc_open(context, from, &fd1, O_RDONLY | O_BINARY | O_CLOEXEC, 0); if(ret) return ret; unlink(FILENAME(to)); ret = fcc_open(context, to, &fd2, - O_WRONLY | O_CREAT | O_EXCL | O_BINARY, 0600); + O_WRONLY | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, 0600); if(ret) goto out1; diff --git a/source4/heimdal/lib/krb5/free.c b/source4/heimdal/lib/krb5/free.c index 1b0bd05412..d0eac84ca1 100644 --- a/source4/heimdal/lib/krb5/free.c +++ b/source4/heimdal/lib/krb5/free.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: free.c 15175 2005-05-18 10:06:16Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *rep) diff --git a/source4/heimdal/lib/krb5/free_host_realm.c b/source4/heimdal/lib/krb5/free_host_realm.c index 6b13ce7d0e..a9287de5fd 100644 --- a/source4/heimdal/lib/krb5/free_host_realm.c +++ b/source4/heimdal/lib/krb5/free_host_realm.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: free_host_realm.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id$"); /* * Free all memory allocated by `realmlist' diff --git a/source4/heimdal/lib/krb5/generate_seq_number.c b/source4/heimdal/lib/krb5/generate_seq_number.c index 8a04f048c8..472fff7fd5 100644 --- a/source4/heimdal/lib/krb5/generate_seq_number.c +++ b/source4/heimdal/lib/krb5/generate_seq_number.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: generate_seq_number.c 17442 2006-05-05 09:31:15Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_generate_seq_number(krb5_context context, diff --git a/source4/heimdal/lib/krb5/generate_subkey.c b/source4/heimdal/lib/krb5/generate_subkey.c index fb7efbcd29..aa68d14df6 100644 --- a/source4/heimdal/lib/krb5/generate_subkey.c +++ b/source4/heimdal/lib/krb5/generate_subkey.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: generate_subkey.c 23280 2008-06-23 03:26:18Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_generate_subkey(krb5_context context, diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 268550b229..c19a5e4abc 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_cred.c 23280 2008-06-23 03:26:18Z lha $"); +RCSID("$Id$"); /* * Take the `body' and encode it into `padata' using the credentials diff --git a/source4/heimdal/lib/krb5/get_default_principal.c b/source4/heimdal/lib/krb5/get_default_principal.c index 5a7a7829fc..6a56218ed7 100644 --- a/source4/heimdal/lib/krb5/get_default_principal.c +++ b/source4/heimdal/lib/krb5/get_default_principal.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_default_principal.c 23280 2008-06-23 03:26:18Z lha $"); +RCSID("$Id$"); /* * Try to find out what's a reasonable default principal. diff --git a/source4/heimdal/lib/krb5/get_default_realm.c b/source4/heimdal/lib/krb5/get_default_realm.c index 1c996031e8..8e8c1ef974 100644 --- a/source4/heimdal/lib/krb5/get_default_realm.c +++ b/source4/heimdal/lib/krb5/get_default_realm.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_default_realm.c 23280 2008-06-23 03:26:18Z lha $"); +RCSID("$Id$"); /* * Return a NULL-terminated list of default realms in `realms'. diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c index a8aac950ec..f005460e3f 100644 --- a/source4/heimdal/lib/krb5/get_for_creds.c +++ b/source4/heimdal/lib/krb5/get_for_creds.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_for_creds.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); static krb5_error_code add_addrs(krb5_context context, diff --git a/source4/heimdal/lib/krb5/get_host_realm.c b/source4/heimdal/lib/krb5/get_host_realm.c index f4c875b347..e226598101 100644 --- a/source4/heimdal/lib/krb5/get_host_realm.c +++ b/source4/heimdal/lib/krb5/get_host_realm.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: get_host_realm.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); /* To automagically find the correct realm of a host (without * [domain_realm] in krb5.conf) add a text record for your domain with diff --git a/source4/heimdal/lib/krb5/get_in_tkt.c b/source4/heimdal/lib/krb5/get_in_tkt.c index 8bdc8c0eb2..c835a9a29e 100644 --- a/source4/heimdal/lib/krb5/get_in_tkt.c +++ b/source4/heimdal/lib/krb5/get_in_tkt.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_in_tkt.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_init_etype (krb5_context context, @@ -383,8 +383,7 @@ _krb5_extract_ticket(krb5_context context, * based on the DNS Name. */ flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH; - flags |=EXTRACT_TICKET_ALLOW_CNAME_MISMATCH ; - + flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH; /* compare client and save */ ret = _krb5_principalname2krb5_principal (context, diff --git a/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c b/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c index 52f95c4bc4..78a1c340ac 100644 --- a/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c +++ b/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: get_in_tkt_with_keytab.c 15477 2005-06-17 04:56:44Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_keytab_key_proc (krb5_context context, diff --git a/source4/heimdal/lib/krb5/get_port.c b/source4/heimdal/lib/krb5/get_port.c index 85587ea766..895c21a433 100644 --- a/source4/heimdal/lib/krb5/get_port.c +++ b/source4/heimdal/lib/krb5/get_port.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: get_port.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id$"); int KRB5_LIB_FUNCTION krb5_getportbyname (krb5_context context, diff --git a/source4/heimdal/lib/krb5/heim_err.et b/source4/heimdal/lib/krb5/heim_err.et index 1b8ab49bc1..547a14e04c 100644 --- a/source4/heimdal/lib/krb5/heim_err.et +++ b/source4/heimdal/lib/krb5/heim_err.et @@ -3,7 +3,7 @@ # # This might look like a com_err file, but is not # -id "$Id: heim_err.et 13352 2004-02-13 16:23:40Z lha $" +id "$Id$" error_table heim diff --git a/source4/heimdal/lib/krb5/heim_threads.h b/source4/heimdal/lib/krb5/heim_threads.h old mode 100755 new mode 100644 index 3c27d13d81..c550499499 --- a/source4/heimdal/lib/krb5/heim_threads.h +++ b/source4/heimdal/lib/krb5/heim_threads.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: heim_threads.h 14409 2004-12-18 16:03:38Z lha $ */ +/* $Id$ */ /* * Provide wrapper macros for thread synchronization primitives so we diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c index 74c9ff78e5..b2b3b6550d 100644 --- a/source4/heimdal/lib/krb5/init_creds.c +++ b/source4/heimdal/lib/krb5/init_creds.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); void KRB5_LIB_FUNCTION krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt) diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index e3098b0a92..f56d069b37 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: init_creds_pw.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); typedef struct krb5_get_init_creds_ctx { KDCOptions flags; diff --git a/source4/heimdal/lib/krb5/k524_err.et b/source4/heimdal/lib/krb5/k524_err.et index 0ca25f74d4..4827b397af 100644 --- a/source4/heimdal/lib/krb5/k524_err.et +++ b/source4/heimdal/lib/krb5/k524_err.et @@ -3,7 +3,7 @@ # # This might look like a com_err file, but is not # -id "$Id: k524_err.et 10141 2001-06-20 02:45:58Z joda $" +id "$Id$" error_table k524 diff --git a/source4/heimdal/lib/krb5/kcm.c b/source4/heimdal/lib/krb5/kcm.c index 0c91fbb3a0..d5f38c5aaf 100644 --- a/source4/heimdal/lib/krb5/kcm.c +++ b/source4/heimdal/lib/krb5/kcm.c @@ -43,7 +43,7 @@ #include "kcm.h" -RCSID("$Id: kcm.c 23446 2008-07-27 12:08:37Z lha $"); +RCSID("$Id$"); typedef struct krb5_kcmcache { char *name; @@ -105,7 +105,7 @@ try_unix_socket(krb5_context context, krb5_error_code ret; int fd; - fd = socket(AF_UNIX, SOCK_STREAM, 0); + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); if (fd < 0) return KRB5_CC_IO; rk_cloexec(fd); diff --git a/source4/heimdal/lib/krb5/keyblock.c b/source4/heimdal/lib/krb5/keyblock.c index fa19e1e726..38a856624e 100644 --- a/source4/heimdal/lib/krb5/keyblock.c +++ b/source4/heimdal/lib/krb5/keyblock.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keyblock.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); void KRB5_LIB_FUNCTION krb5_keyblock_zero(krb5_keyblock *keyblock) diff --git a/source4/heimdal/lib/krb5/keytab.c b/source4/heimdal/lib/krb5/keytab.c index 09e130d850..f3e6b9e8f4 100644 --- a/source4/heimdal/lib/krb5/keytab.c +++ b/source4/heimdal/lib/krb5/keytab.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); /* * Register a new keytab in `ops' @@ -341,6 +341,7 @@ krb5_kt_get_entry(krb5_context context, if (ret) { /* This is needed for krb5_verify_init_creds, but keep error * string from previous error for the human. */ + context->error_code = KRB5_KT_NOTFOUND; return KRB5_KT_NOTFOUND; } diff --git a/source4/heimdal/lib/krb5/keytab_any.c b/source4/heimdal/lib/krb5/keytab_any.c index 9e93191045..a4b15394a5 100644 --- a/source4/heimdal/lib/krb5/keytab_any.c +++ b/source4/heimdal/lib/krb5/keytab_any.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_any.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); struct any_data { krb5_keytab kt; diff --git a/source4/heimdal/lib/krb5/keytab_file.c b/source4/heimdal/lib/krb5/keytab_file.c index e830ab3412..17f2d57742 100644 --- a/source4/heimdal/lib/krb5/keytab_file.c +++ b/source4/heimdal/lib/krb5/keytab_file.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_file.c 23469 2008-07-27 12:17:12Z lha $"); +RCSID("$Id$"); #define KRB5_KT_VNO_1 1 #define KRB5_KT_VNO_2 2 @@ -385,7 +385,7 @@ fkt_start_seq_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *c) { - return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY, 0, c); + return fkt_start_seq_get_int(context, id, O_RDONLY | O_BINARY | O_CLOEXEC, 0, c); } static krb5_error_code @@ -488,9 +488,9 @@ fkt_add_entry(krb5_context context, krb5_data keytab; int32_t len; - fd = open (d->filename, O_RDWR | O_BINARY); + fd = open (d->filename, O_RDWR | O_BINARY | O_CLOEXEC); if (fd < 0) { - fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY, 0600); + fd = open (d->filename, O_RDWR | O_CREAT | O_EXCL | O_BINARY | O_CLOEXEC, 0600); if (fd < 0) { ret = errno; krb5_set_error_message(context, ret, "open(%s): %s", d->filename, @@ -632,7 +632,7 @@ fkt_remove_entry(krb5_context context, int found = 0; krb5_error_code ret; - ret = fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY, 1, &cursor); + ret = fkt_start_seq_get_int(context, id, O_RDWR | O_BINARY | O_CLOEXEC, 1, &cursor); if(ret != 0) goto out; /* return other error here? */ while(fkt_next_entry_int(context, id, &e, &cursor, diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c index 7e14cbd329..3339a96319 100644 --- a/source4/heimdal/lib/krb5/keytab_keyfile.c +++ b/source4/heimdal/lib/krb5/keytab_keyfile.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_keyfile.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); /* afs keyfile operations --------------------------------------- */ @@ -194,7 +194,7 @@ akf_start_seq_get(krb5_context context, int32_t ret; struct akf_data *d = id->data; - c->fd = open (d->filename, O_RDONLY|O_BINARY, 0600); + c->fd = open (d->filename, O_RDONLY | O_BINARY | O_CLOEXEC, 0600); if (c->fd < 0) { ret = errno; krb5_set_error_message(context, ret, "keytab afs keyfil open %s failed: %s", @@ -301,10 +301,10 @@ akf_add_entry(krb5_context context, return 0; } - fd = open (d->filename, O_RDWR | O_BINARY); + fd = open (d->filename, O_RDWR | O_BINARY | O_CLOEXEC); if (fd < 0) { fd = open (d->filename, - O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600); + O_RDWR | O_BINARY | O_CREAT | O_EXCL | O_CLOEXEC, 0600); if (fd < 0) { ret = errno; krb5_set_error_message(context, ret, "open(%s): %s", d->filename, diff --git a/source4/heimdal/lib/krb5/keytab_memory.c b/source4/heimdal/lib/krb5/keytab_memory.c index eabee7c693..5f648d9bce 100644 --- a/source4/heimdal/lib/krb5/keytab_memory.c +++ b/source4/heimdal/lib/krb5/keytab_memory.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: keytab_memory.c 23293 2008-06-23 03:28:22Z lha $"); +RCSID("$Id$"); /* memory operations -------------------------------------------- */ diff --git a/source4/heimdal/lib/krb5/krb5-v4compat.h b/source4/heimdal/lib/krb5/krb5-v4compat.h index dfd7e94460..9470f10337 100644 --- a/source4/heimdal/lib/krb5/krb5-v4compat.h +++ b/source4/heimdal/lib/krb5/krb5-v4compat.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5-v4compat.h 21575 2007-07-16 07:44:54Z lha $ */ +/* $Id$ */ #ifndef __KRB5_V4COMPAT_H__ #define __KRB5_V4COMPAT_H__ diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h index b1e2781d52..aedabcc350 100644 --- a/source4/heimdal/lib/krb5/krb5.h +++ b/source4/heimdal/lib/krb5/krb5.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5.h 23026 2008-04-17 10:02:03Z lha $ */ +/* $Id$ */ #ifndef __KRB5_H__ #define __KRB5_H__ @@ -761,6 +761,28 @@ struct credentials; /* this is to keep the compiler happy */ struct getargs; struct sockaddr; +/** + * Semi private, not stable yet + */ + +typedef struct krb5_crypto_iov { + unsigned int flags; + /* ignored */ +#define KRB5_CRYPTO_TYPE_EMPTY 0 + /* OUT krb5_crypto_length(KRB5_CRYPTO_TYPE_HEADER) */ +#define KRB5_CRYPTO_TYPE_HEADER 1 + /* IN and OUT */ +#define KRB5_CRYPTO_TYPE_DATA 2 + /* IN */ +#define KRB5_CRYPTO_TYPE_SIGN_ONLY 3 + /* (only for encryption) OUT krb5_crypto_length(KRB5_CRYPTO_TYPE_TRAILER) */ +#define KRB5_CRYPTO_TYPE_PADDING 4 + /* OUT krb5_crypto_length(KRB5_CRYPTO_TYPE_TRAILER) */ +#define KRB5_CRYPTO_TYPE_TRAILER 5 + krb5_data data; +} krb5_crypto_iov; + + #include /* variables */ diff --git a/source4/heimdal/lib/krb5/krb5_ccapi.h b/source4/heimdal/lib/krb5/krb5_ccapi.h index 59a38425c2..7a8ac584a1 100644 --- a/source4/heimdal/lib/krb5/krb5_ccapi.h +++ b/source4/heimdal/lib/krb5/krb5_ccapi.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_ccapi.h 22090 2007-12-02 23:23:43Z lha $ */ +/* $Id$ */ #ifndef KRB5_CCAPI_H #define KRB5_CCAPI_H 1 diff --git a/source4/heimdal/lib/krb5/krb5_err.et b/source4/heimdal/lib/krb5/krb5_err.et index 8e49ffcc4a..c076992d0b 100644 --- a/source4/heimdal/lib/krb5/krb5_err.et +++ b/source4/heimdal/lib/krb5/krb5_err.et @@ -3,7 +3,7 @@ # # This might look like a com_err file, but is not # -id "$Id: krb5_err.et 23354 2008-07-15 11:23:34Z lha $" +id "$Id$" error_table krb5 @@ -110,7 +110,7 @@ error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not suppo index 128 prefix -error_code KRB5_ERR_RCSID, "$Id: krb5_err.et 23354 2008-07-15 11:23:34Z lha $" +error_code KRB5_ERR_RCSID, "$Id$" error_code KRB5_LIBOS_BADLOCKFLAG, "Invalid flag for file lock mode" error_code KRB5_LIBOS_CANTREADPWD, "Cannot read password" diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h index aaabd4541b..73075bf56c 100644 --- a/source4/heimdal/lib/krb5/krb5_locl.h +++ b/source4/heimdal/lib/krb5/krb5_locl.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: krb5_locl.h 23324 2008-06-26 03:54:45Z lha $ */ +/* $Id$ */ #ifndef __KRB5_LOCL_H__ #define __KRB5_LOCL_H__ @@ -133,6 +133,7 @@ struct sockaddr_dl; #include +#define HC_DEPRECATED_CRYPTO #include "crypto-headers.h" @@ -176,6 +177,15 @@ struct _krb5_krb_auth_data; #define O_BINARY 0 #endif +#ifndef O_CLOEXEC +#define O_CLOEXEC 0 +#endif + +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#endif + + #define KRB5_BUFSIZ 1024 typedef enum { diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c index 3514a026b7..8e49818c50 100644 --- a/source4/heimdal/lib/krb5/krbhst.c +++ b/source4/heimdal/lib/krb5/krbhst.c @@ -35,7 +35,7 @@ #include #include "locate_plugin.h" -RCSID("$Id: krbhst.c 23447 2008-07-27 12:09:05Z lha $"); +RCSID("$Id$"); static int string_to_proto(const char *string) diff --git a/source4/heimdal/lib/krb5/locate_plugin.h b/source4/heimdal/lib/krb5/locate_plugin.h index a342617d38..baca037ebc 100644 --- a/source4/heimdal/lib/krb5/locate_plugin.h +++ b/source4/heimdal/lib/krb5/locate_plugin.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: locate_plugin.h 23351 2008-07-15 11:22:39Z lha $ */ +/* $Id$ */ #ifndef HEIMDAL_KRB5_LOCATE_PLUGIN_H #define HEIMDAL_KRB5_LOCATE_PLUGIN_H 1 diff --git a/source4/heimdal/lib/krb5/log.c b/source4/heimdal/lib/krb5/log.c index 721e3691ca..2ed061c80b 100644 --- a/source4/heimdal/lib/krb5/log.c +++ b/source4/heimdal/lib/krb5/log.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: log.c 23443 2008-07-27 12:07:25Z lha $"); +RCSID("$Id$"); struct facility { int min; @@ -358,12 +358,12 @@ krb5_openlog(krb5_context context, if(p == NULL) p = krb5_config_get_strings(context, NULL, "logging", "default", NULL); if(p){ - for(q = p; *q; q++) + for(q = p; *q && ret == 0; q++) ret = krb5_addlog_dest(context, *fac, *q); krb5_config_free_strings(p); }else ret = krb5_addlog_dest(context, *fac, "SYSLOG"); - return 0; + return ret; } krb5_error_code KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/mcache.c b/source4/heimdal/lib/krb5/mcache.c index 682f9f6abd..3f26b27a46 100644 --- a/source4/heimdal/lib/krb5/mcache.c +++ b/source4/heimdal/lib/krb5/mcache.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: mcache.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); typedef struct krb5_mcache { char *name; diff --git a/source4/heimdal/lib/krb5/misc.c b/source4/heimdal/lib/krb5/misc.c index 8050bdb9b4..1ed4f08d77 100644 --- a/source4/heimdal/lib/krb5/misc.c +++ b/source4/heimdal/lib/krb5/misc.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: misc.c 21174 2007-06-19 10:10:58Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION _krb5_s4u2self_to_checksumdata(krb5_context context, diff --git a/source4/heimdal/lib/krb5/mit_glue.c b/source4/heimdal/lib/krb5/mit_glue.c old mode 100755 new mode 100644 index 7440d54762..c157c5d365 --- a/source4/heimdal/lib/krb5/mit_glue.c +++ b/source4/heimdal/lib/krb5/mit_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: mit_glue.c 20042 2007-01-23 20:37:43Z lha $"); +RCSID("$Id$"); /* * Glue for MIT API diff --git a/source4/heimdal/lib/krb5/mk_error.c b/source4/heimdal/lib/krb5/mk_error.c index 7046649934..d4c3867edd 100644 --- a/source4/heimdal/lib/krb5/mk_error.c +++ b/source4/heimdal/lib/krb5/mk_error.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: mk_error.c 15457 2005-06-16 21:16:40Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_mk_error(krb5_context context, diff --git a/source4/heimdal/lib/krb5/mk_priv.c b/source4/heimdal/lib/krb5/mk_priv.c index 3b4b6e30b7..a1a9ea4dff 100644 --- a/source4/heimdal/lib/krb5/mk_priv.c +++ b/source4/heimdal/lib/krb5/mk_priv.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_priv.c 23297 2008-06-23 03:28:53Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION diff --git a/source4/heimdal/lib/krb5/mk_rep.c b/source4/heimdal/lib/krb5/mk_rep.c index 069df42e26..65c97b5803 100644 --- a/source4/heimdal/lib/krb5/mk_rep.c +++ b/source4/heimdal/lib/krb5/mk_rep.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_rep.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_mk_rep(krb5_context context, diff --git a/source4/heimdal/lib/krb5/mk_req.c b/source4/heimdal/lib/krb5/mk_req.c index 5f64f01e95..1068aaa668 100644 --- a/source4/heimdal/lib/krb5/mk_req.c +++ b/source4/heimdal/lib/krb5/mk_req.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_req.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_mk_req_exact(krb5_context context, diff --git a/source4/heimdal/lib/krb5/mk_req_ext.c b/source4/heimdal/lib/krb5/mk_req_ext.c index b6d55c8815..645dadee22 100644 --- a/source4/heimdal/lib/krb5/mk_req_ext.c +++ b/source4/heimdal/lib/krb5/mk_req_ext.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: mk_req_ext.c 19511 2006-12-27 12:07:22Z lha $"); +RCSID("$Id$"); krb5_error_code _krb5_mk_req_internal(krb5_context context, diff --git a/source4/heimdal/lib/krb5/n-fold.c b/source4/heimdal/lib/krb5/n-fold.c index 287f8cf64f..147f6aeac7 100644 --- a/source4/heimdal/lib/krb5/n-fold.c +++ b/source4/heimdal/lib/krb5/n-fold.c @@ -32,7 +32,7 @@ #include "krb5_locl.h" -RCSID("$Id: n-fold.c 22923 2008-04-08 14:51:33Z lha $"); +RCSID("$Id$"); static krb5_error_code rr13(unsigned char *buf, size_t len) diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index fbc754efda..ac7e3eda9b 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: pac.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); struct PAC_INFO_BUFFER { uint32_t type; @@ -819,7 +819,7 @@ pac_checksum(krb5_context context, return ret; ret = krb5_crypto_get_checksum_type(context, crypto, &cktype); - ret = krb5_crypto_destroy(context, crypto); + krb5_crypto_destroy(context, crypto); if (ret) return ret; diff --git a/source4/heimdal/lib/krb5/padata.c b/source4/heimdal/lib/krb5/padata.c index 9dc3fe69a5..2cd3c18287 100644 --- a/source4/heimdal/lib/krb5/padata.c +++ b/source4/heimdal/lib/krb5/padata.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: padata.c 23300 2008-06-23 03:29:22Z lha $"); +RCSID("$Id$"); PA_DATA * krb5_find_padata(PA_DATA *val, unsigned len, int type, int *idx) diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c old mode 100755 new mode 100644 index 1e82971c6e..634ef26c7f --- a/source4/heimdal/lib/krb5/pkinit.c +++ b/source4/heimdal/lib/krb5/pkinit.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: pkinit.c 23450 2008-07-27 12:10:10Z lha $"); +RCSID("$Id$"); struct krb5_dh_moduli { char *name; @@ -381,7 +381,7 @@ build_auth_pack(krb5_context context, ret = krb5_data_alloc(a->clientDHNonce, 40); if (a->clientDHNonce == NULL) { krb5_clear_error_string(context); - return ENOMEM; + return ret; } memset(a->clientDHNonce->data, 0, a->clientDHNonce->length); ret = krb5_copy_data(context, a->clientDHNonce, diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c index 8dda27fa59..fb1ee32285 100644 --- a/source4/heimdal/lib/krb5/plugin.c +++ b/source4/heimdal/lib/krb5/plugin.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: plugin.c 23451 2008-07-27 12:10:30Z lha $"); +RCSID("$Id$"); #ifdef HAVE_DLFCN_H #include #endif diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index 0d6d72dbcf..3a1d184c3d 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -57,7 +57,7 @@ host/admin@H5L.ORG #include #include "resolve.h" -RCSID("$Id: principal.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); #define princ_num_comp(P) ((P)->name.name_string.len) #define princ_type(P) ((P)->name.name_type) @@ -1259,7 +1259,14 @@ krb5_sname_to_principal (krb5_context context, return KRB5_SNAME_UNSUPP_NAMETYPE; } if(hostname == NULL) { - gethostname(localhost, sizeof(localhost)); + ret = gethostname(localhost, sizeof(localhost) - 1); + if (ret != 0) { + ret = errno; + krb5_set_error_message(context, ret, + "Failed to get local hostname"); + return ret; + } + localhost[sizeof(localhost) - 1] = '\0'; hostname = localhost; } if(sname == NULL) diff --git a/source4/heimdal/lib/krb5/prompter_posix.c b/source4/heimdal/lib/krb5/prompter_posix.c index e0f407fb24..840bb328ca 100644 --- a/source4/heimdal/lib/krb5/prompter_posix.c +++ b/source4/heimdal/lib/krb5/prompter_posix.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: prompter_posix.c 13863 2004-05-25 21:46:46Z lha $"); +RCSID("$Id$"); int KRB5_LIB_FUNCTION krb5_prompter_posix (krb5_context context, diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c index 26aa3f2d79..e2807c20d0 100644 --- a/source4/heimdal/lib/krb5/rd_cred.c +++ b/source4/heimdal/lib/krb5/rd_cred.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_cred.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); static krb5_error_code compare_addrs(krb5_context context, diff --git a/source4/heimdal/lib/krb5/rd_error.c b/source4/heimdal/lib/krb5/rd_error.c index 9e50af539a..9f23d8df29 100644 --- a/source4/heimdal/lib/krb5/rd_error.c +++ b/source4/heimdal/lib/krb5/rd_error.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: rd_error.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_error(krb5_context context, diff --git a/source4/heimdal/lib/krb5/rd_priv.c b/source4/heimdal/lib/krb5/rd_priv.c index ed7a2ccc52..da8f44febb 100644 --- a/source4/heimdal/lib/krb5/rd_priv.c +++ b/source4/heimdal/lib/krb5/rd_priv.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_priv.c 21751 2007-07-31 20:42:20Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_priv(krb5_context context, @@ -50,14 +50,18 @@ krb5_rd_priv(krb5_context context, krb5_keyblock *key; krb5_crypto crypto; - if (outbuf) - krb5_data_zero(outbuf); + krb5_data_zero(outbuf); if ((auth_context->flags & - (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && - outdata == NULL) { - krb5_clear_error_string (context); - return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */ + (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) + { + if (outdata == NULL) { + krb5_clear_error_string (context); + return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */ + } + /* if these fields are not present in the priv-part, silently + return zero */ + memset(outdata, 0, sizeof(*outdata)); } memset(&priv, 0, sizeof(priv)); @@ -165,9 +169,6 @@ krb5_rd_priv(krb5_context context, if ((auth_context->flags & (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) { - /* if these fields are not present in the priv-part, silently - return zero */ - memset(outdata, 0, sizeof(*outdata)); if(part.timestamp) outdata->timestamp = *part.timestamp; if(part.usec) diff --git a/source4/heimdal/lib/krb5/rd_rep.c b/source4/heimdal/lib/krb5/rd_rep.c index 0e6e3d09af..846de26c60 100644 --- a/source4/heimdal/lib/krb5/rd_rep.c +++ b/source4/heimdal/lib/krb5/rd_rep.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_rep.c 23304 2008-06-23 03:29:56Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_rd_rep(krb5_context context, diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index ddf1f69ae4..ef91f9fdd6 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -33,7 +33,7 @@ #include -RCSID("$Id: rd_req.c 23415 2008-07-26 18:35:44Z lha $"); +RCSID("$Id$"); static krb5_error_code decrypt_tkt_enc_part (krb5_context context, diff --git a/source4/heimdal/lib/krb5/replay.c b/source4/heimdal/lib/krb5/replay.c index 7639bfa2ce..cd717f27ac 100644 --- a/source4/heimdal/lib/krb5/replay.c +++ b/source4/heimdal/lib/krb5/replay.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: replay.c 23467 2008-07-27 12:16:37Z lha $"); +RCSID("$Id$"); struct krb5_rcache_data { char *name; diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index 1ddb5afd1f..45b728aa6c 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "send_to_kdc_plugin.h" -RCSID("$Id: send_to_kdc.c 23448 2008-07-27 12:09:22Z lha $"); +RCSID("$Id$"); struct send_to_kdc { krb5_send_to_kdc_func func; @@ -288,7 +288,7 @@ send_via_proxy (krb5_context context, return krb5_eai_to_heim_errno(ret, errno); for (a = ai; a != NULL; a = a->ai_next) { - s = socket (a->ai_family, a->ai_socktype, a->ai_protocol); + s = socket (a->ai_family, a->ai_socktype, a->ai_protocol | SOCK_CLOEXEC); if (s < 0) continue; rk_cloexec(s); @@ -411,7 +411,7 @@ krb5_sendto (krb5_context context, continue; for (a = ai; a != NULL; a = a->ai_next) { - fd = socket (a->ai_family, a->ai_socktype, a->ai_protocol); + fd = socket (a->ai_family, a->ai_socktype | SOCK_CLOEXEC, a->ai_protocol); if (fd < 0) continue; rk_cloexec(fd); diff --git a/source4/heimdal/lib/krb5/set_default_realm.c b/source4/heimdal/lib/krb5/set_default_realm.c index 55abf2ea7d..c21ac453a2 100644 --- a/source4/heimdal/lib/krb5/set_default_realm.c +++ b/source4/heimdal/lib/krb5/set_default_realm.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: set_default_realm.c 23309 2008-06-23 03:30:41Z lha $"); +RCSID("$Id$"); /* * Convert the simple string `s' into a NULL-terminated and freshly allocated diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c index c9cbbb5cef..321ca633a6 100644 --- a/source4/heimdal/lib/krb5/store.c +++ b/source4/heimdal/lib/krb5/store.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store.c 22071 2007-11-14 20:04:50Z lha $"); +RCSID("$Id$"); #define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V)) #define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE) diff --git a/source4/heimdal/lib/krb5/store_emem.c b/source4/heimdal/lib/krb5/store_emem.c index c38c1b53c3..3cb561ec77 100644 --- a/source4/heimdal/lib/krb5/store_emem.c +++ b/source4/heimdal/lib/krb5/store_emem.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store_emem.c 22574 2008-02-05 20:31:55Z lha $"); +RCSID("$Id$"); typedef struct emem_storage{ unsigned char *base; diff --git a/source4/heimdal/lib/krb5/store_fd.c b/source4/heimdal/lib/krb5/store_fd.c index 15f86fcac3..21fa171c28 100644 --- a/source4/heimdal/lib/krb5/store_fd.c +++ b/source4/heimdal/lib/krb5/store_fd.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store_fd.c 17779 2006-06-30 21:23:19Z lha $"); +RCSID("$Id$"); typedef struct fd_storage { int fd; diff --git a/source4/heimdal/lib/krb5/store_mem.c b/source4/heimdal/lib/krb5/store_mem.c index e6e62b5a62..6d8306051a 100644 --- a/source4/heimdal/lib/krb5/store_mem.c +++ b/source4/heimdal/lib/krb5/store_mem.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include "store-int.h" -RCSID("$Id: store_mem.c 20307 2007-04-11 11:16:28Z lha $"); +RCSID("$Id$"); typedef struct mem_storage{ unsigned char *base; diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c index 5eff64e12d..77ce8cb221 100644 --- a/source4/heimdal/lib/krb5/ticket.c +++ b/source4/heimdal/lib/krb5/ticket.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: ticket.c 23310 2008-06-23 03:30:49Z lha $"); +RCSID("$Id$"); krb5_error_code KRB5_LIB_FUNCTION krb5_free_ticket(krb5_context context, diff --git a/source4/heimdal/lib/krb5/time.c b/source4/heimdal/lib/krb5/time.c index 46f88a86cd..7a9b36372c 100644 --- a/source4/heimdal/lib/krb5/time.c +++ b/source4/heimdal/lib/krb5/time.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: time.c 23260 2008-06-21 15:22:37Z lha $"); +RCSID("$Id$"); /** * Set the absolute time that the caller knows the kdc has so the diff --git a/source4/heimdal/lib/krb5/transited.c b/source4/heimdal/lib/krb5/transited.c index 58b00a4b7a..c9db832348 100644 --- a/source4/heimdal/lib/krb5/transited.c +++ b/source4/heimdal/lib/krb5/transited.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: transited.c 23316 2008-06-23 04:32:32Z lha $"); +RCSID("$Id$"); /* this is an attempt at one of the most horrible `compression' schemes that has ever been invented; it's so amazingly brain-dead diff --git a/source4/heimdal/lib/krb5/v4_glue.c b/source4/heimdal/lib/krb5/v4_glue.c index 55570c44dd..baa4bd6892 100644 --- a/source4/heimdal/lib/krb5/v4_glue.c +++ b/source4/heimdal/lib/krb5/v4_glue.c @@ -32,7 +32,7 @@ */ #include "krb5_locl.h" -RCSID("$Id: v4_glue.c 23452 2008-07-27 12:10:54Z lha $"); +RCSID("$Id$"); #include "krb5-v4compat.h" @@ -348,12 +348,12 @@ storage_to_etext(krb5_context context, krb5_ssize_t size; krb5_data data; - /* multiple of eight bytes */ + /* multiple of eight bytes, don't round up */ size = krb5_storage_seek(sp, 0, SEEK_END); if (size < 0) return KRB4ET_RD_AP_UNDEC; - size = 8 - (size & 7); + size = ((size+7) & ~7) - size; ret = krb5_storage_write(sp, eightzeros, size); if (ret != size) diff --git a/source4/heimdal/lib/krb5/version.c b/source4/heimdal/lib/krb5/version.c index f7ccff5bc8..cbc4f8c3e1 100644 --- a/source4/heimdal/lib/krb5/version.c +++ b/source4/heimdal/lib/krb5/version.c @@ -33,7 +33,7 @@ #include "krb5_locl.h" -RCSID("$Id: version.c 7464 1999-12-02 17:05:13Z joda $"); +RCSID("$Id$"); /* this is just to get a version stamp in the library file */ diff --git a/source4/heimdal/lib/krb5/warn.c b/source4/heimdal/lib/krb5/warn.c index 97a6cc9e0a..c7fe5640b5 100644 --- a/source4/heimdal/lib/krb5/warn.c +++ b/source4/heimdal/lib/krb5/warn.c @@ -34,7 +34,7 @@ #include "krb5_locl.h" #include -RCSID("$Id: warn.c 23206 2008-05-29 02:13:41Z lha $"); +RCSID("$Id$"); static krb5_error_code _warnerr(krb5_context context, int do_errtext, krb5_error_code code, int level, const char *fmt, va_list ap) -- cgit From 0b16d70f3941712ed7889d57ecbc45fe0fa68916 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Thu, 28 Aug 2008 16:19:16 +1000 Subject: Don't wipe the PAC checksums, the caller may actually need them. (This used to be commit 9db5a966fce0b71a0d2167b4aff70cc081abc1cc) --- source4/heimdal/lib/krb5/pac.c | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c index ac7e3eda9b..9a145c48e6 100644 --- a/source4/heimdal/lib/krb5/pac.c +++ b/source4/heimdal/lib/krb5/pac.c @@ -324,20 +324,6 @@ krb5_pac_get_buffer(krb5_context context, krb5_pac p, krb5_error_code ret; uint32_t i; - /* - * Hide the checksums from external consumers - */ - - if (type == PAC_PRIVSVR_CHECKSUM || type == PAC_SERVER_CHECKSUM) { - ret = krb5_data_alloc(data, 16); - if (ret) { - krb5_set_error_message(context, ret, "malloc: out of memory"); - return ret; - } - memset(data->data, 0, data->length); - return 0; - } - for (i = 0; i < p->pac->numbuffers; i++) { size_t len = p->pac->buffers[i].buffersize; size_t offset = p->pac->buffers[i].offset_lo; -- cgit From baf0b360812dc8532f9420e224bf3ee3a51fb04a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 3 Sep 2008 14:20:30 +1000 Subject: Merge krb5_cksumtype_to_enctype from Heimdal svn -r 23719 (This used to be commit cc1df3c002e6af25add3c8ae20e7efc2ab6f2fa8) --- source4/heimdal/lib/krb5/crypto.c | 102 ++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 32 deletions(-) (limited to 'source4/heimdal/lib/krb5') diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 6675647736..9379c6fdf1 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -2677,37 +2677,6 @@ krb5_enctype_to_keytype(krb5_context context, return 0; } -krb5_error_code KRB5_LIB_FUNCTION -krb5_keytype_to_enctypes (krb5_context context, - krb5_keytype keytype, - unsigned *len, - krb5_enctype **val) -{ - int i; - unsigned n = 0; - krb5_enctype *ret; - - for (i = num_etypes - 1; i >= 0; --i) { - if (etypes[i]->keytype->type == keytype - && !(etypes[i]->flags & F_PSEUDO)) - ++n; - } - ret = malloc(n * sizeof(*ret)); - if (ret == NULL && n != 0) { - krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); - return ENOMEM; - } - n = 0; - for (i = num_etypes - 1; i >= 0; --i) { - if (etypes[i]->keytype->type == keytype - && !(etypes[i]->flags & F_PSEUDO)) - ret[n++] = etypes[i]->type; - } - *len = n; - *val = ret; - return 0; -} - krb5_error_code KRB5_LIB_FUNCTION krb5_enctype_valid(krb5_context context, krb5_enctype etype) @@ -2728,6 +2697,44 @@ krb5_enctype_valid(krb5_context context, return 0; } +/** + * Return the coresponding encryption type for a checksum type. + * + * @param context Kerberos context + * @param ctype The checksum type to get the result enctype for + * @param etype The returned encryption, when the matching etype is + * not found, etype is set to ETYPE_NULL. + * + * @return Return an error code for an failure or 0 on success. + * @ingroup krb5_crypto + */ + + +krb5_error_code KRB5_LIB_FUNCTION +krb5_cksumtype_to_enctype(krb5_context context, + krb5_cksumtype ctype, + krb5_enctype *etype) +{ + int i; + + *etype = ETYPE_NULL; + + for(i = 0; i < num_etypes; i++) { + if(etypes[i]->keyed_checksum && + etypes[i]->keyed_checksum->type == ctype) + { + *etype = etypes[i]->type; + return 0; + } + } + + krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP, + "ckecksum type %d not supported", + (int)ctype); + return KRB5_PROG_SUMTYPE_NOSUPP; +} + + krb5_error_code KRB5_LIB_FUNCTION krb5_cksumtype_valid(krb5_context context, krb5_cksumtype ctype) @@ -3491,7 +3498,6 @@ krb5_decrypt_iov_ivec(krb5_context context, return 0; } - size_t KRB5_LIB_FUNCTION krb5_crypto_length(krb5_context context, krb5_crypto crypto, @@ -4562,4 +4568,36 @@ krb5_string_to_keytype(krb5_context context, "key type %s not supported", string); return KRB5_PROG_KEYTYPE_NOSUPP; } + +krb5_error_code KRB5_LIB_FUNCTION +krb5_keytype_to_enctypes (krb5_context context, + krb5_keytype keytype, + unsigned *len, + krb5_enctype **val) +{ + int i; + unsigned n = 0; + krb5_enctype *ret; + + for (i = num_etypes - 1; i >= 0; --i) { + if (etypes[i]->keytype->type == keytype + && !(etypes[i]->flags & F_PSEUDO)) + ++n; + } + ret = malloc(n * sizeof(*ret)); + if (ret == NULL && n != 0) { + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); + return ENOMEM; + } + n = 0; + for (i = num_etypes - 1; i >= 0; --i) { + if (etypes[i]->keytype->type == keytype + && !(etypes[i]->flags & F_PSEUDO)) + ret[n++] = etypes[i]->type; + } + *len = n; + *val = ret; + return 0; +} + #endif -- cgit