diff --git a/cf/db.m4 b/cf/db.m4 index 3fbdfd813..ff10f76eb 100644 --- a/cf/db.m4 +++ b/cf/db.m4 @@ -42,7 +42,6 @@ AS_IF([test "x$with_berkeley_db" != xno], db4/db.h \ db3/db.h \ db.h \ - db_185.h \ ])]) dnl db_create is used by db3 and db4 and db5 @@ -70,32 +69,29 @@ dnl db_create is used by db3 and db4 and db5 DBLIB="" fi AC_DEFINE(HAVE_DB3, 1, [define if you have a berkeley db3/4/5 library]) - else + fi dnl dbopen is used by db1/db2 - AC_FIND_FUNC_NO_LIBS(dbopen, db2 db, [ - #include - #if defined(HAVE_DB2_DB_H) - #include - #elif defined(HAVE_DB_185_H) - #include - #elif defined(HAVE_DB_H) - #include - #else - #error no db.h - #endif - ],[NULL, 0, 0, 0, NULL]) + AC_FIND_FUNC_NO_LIBS(dbopen, db2 db, [ + #include + #if defined(HAVE_DB2_DB_H) + #include + #elif defined(HAVE_DB_H) + #include + #else + #error no db.h + #endif + ],[NULL, 0, 0, 0, NULL]) - if test "$ac_cv_func_dbopen" = "yes"; then - db_type=db1 - if test "$ac_cv_funclib_dbopen" != "yes"; then - DBLIB="$ac_cv_funclib_dbopen" - else - DBLIB="" - fi - AC_DEFINE(HAVE_DB1, 1, [define if you have a berkeley db1/2 library]) + if test "$ac_cv_func_dbopen" = "yes"; then + db_type=db1 + if test "$ac_cv_funclib_dbopen" != "yes"; then + DBLIB="$ac_cv_funclib_dbopen" + else + DBLIB="" fi + AC_DEFINE(HAVE_DB1, 1, [define if you have a berkeley db1/2 library]) fi dnl test for ndbm compatability diff --git a/lib/gssapi/krb5/accept_sec_context.c b/lib/gssapi/krb5/accept_sec_context.c index a5e9d054c..e607e08f5 100644 --- a/lib/gssapi/krb5/accept_sec_context.c +++ b/lib/gssapi/krb5/accept_sec_context.c @@ -36,6 +36,24 @@ HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER; krb5_keytab _gsskrb5_keytab; +static krb5_error_code +validate_keytab(krb5_context context, const char *name, krb5_keytab *id) +{ + krb5_error_code ret; + + ret = krb5_kt_resolve(context, name, id); + if (ret) + return ret; + + ret = krb5_kt_have_content(context, *id); + if (ret) { + krb5_kt_close(context, *id); + *id = NULL; + } + + return ret; +} + OM_uint32 _gsskrb5_register_acceptor_identity (const char *identity) { @@ -55,15 +73,23 @@ _gsskrb5_register_acceptor_identity (const char *identity) if (identity == NULL) { ret = krb5_kt_default(context, &_gsskrb5_keytab); } else { - char *p = NULL; - - ret = asprintf(&p, "FILE:%s", identity); - if(ret < 0 || p == NULL) { - HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); - return GSS_S_FAILURE; + /* + * First check if we can the keytab as is and if it has content... + */ + ret = validate_keytab(context, identity, &_gsskrb5_keytab); + /* + * if it doesn't, lets prepend FILE: and try again + */ + if (ret) { + char *p = NULL; + ret = asprintf(&p, "FILE:%s", identity); + if(ret < 0 || p == NULL) { + HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); + return GSS_S_FAILURE; + } + ret = validate_keytab(context, p, &_gsskrb5_keytab); + free(p); } - ret = krb5_kt_resolve(context, p, &_gsskrb5_keytab); - free(p); } HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); if(ret) diff --git a/lib/gssapi/krb5/acquire_cred.c b/lib/gssapi/krb5/acquire_cred.c index d0042e874..3116f0d95 100644 --- a/lib/gssapi/krb5/acquire_cred.c +++ b/lib/gssapi/krb5/acquire_cred.c @@ -81,17 +81,18 @@ __gsskrb5_ccache_lifetime(OM_uint32 *minor_status, static krb5_error_code get_keytab(krb5_context context, krb5_keytab *keytab) { - char kt_name[256]; krb5_error_code kret; HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex); if (_gsskrb5_keytab != NULL) { - kret = krb5_kt_get_name(context, - _gsskrb5_keytab, - kt_name, sizeof(kt_name)); - if (kret == 0) - kret = krb5_kt_resolve(context, kt_name, keytab); + char *name = NULL; + + kret = krb5_kt_get_full_name(context, _gsskrb5_keytab, &name); + if (kret == 0) { + kret = krb5_kt_resolve(context, name, keytab); + krb5_xfree(name); + } } else kret = krb5_kt_default(context, keytab); diff --git a/lib/gssapi/krb5/add_cred.c b/lib/gssapi/krb5/add_cred.c index a326613ed..6c45b0660 100644 --- a/lib/gssapi/krb5/add_cred.c +++ b/lib/gssapi/krb5/add_cred.c @@ -123,23 +123,11 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_add_cred ( } if (cred->keytab) { - char name[KRB5_KT_PREFIX_MAX_LEN + MAXPATHLEN]; - int len; + char *name = NULL; ret = GSS_S_FAILURE; - kret = krb5_kt_get_type(context, cred->keytab, - name, KRB5_KT_PREFIX_MAX_LEN); - if (kret) { - *minor_status = kret; - goto failure; - } - len = strlen(name); - name[len++] = ':'; - - kret = krb5_kt_get_name(context, cred->keytab, - name + len, - sizeof(name) - len); + kret = krb5_kt_get_full_name(context, cred->keytab, &name); if (kret) { *minor_status = kret; goto failure; @@ -147,6 +135,7 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_add_cred ( kret = krb5_kt_resolve(context, name, &handle->keytab); + krb5_xfree(name); if (kret){ *minor_status = kret; goto failure; diff --git a/lib/hdb/hdb-mitdb.c b/lib/hdb/hdb-mitdb.c index 85bfc2a37..3c0998480 100644 --- a/lib/hdb/hdb-mitdb.c +++ b/lib/hdb/hdb-mitdb.c @@ -205,7 +205,7 @@ mdb_value2entry(krb5_context context, krb5_data *data, krb5_kvno kvno, hdb_entry uint32_t u32; uint16_t u16, num_keys, num_tl; size_t i, j; - char *p = NULL; + char *p; sp = krb5_storage_from_data(data); if (sp == NULL) { @@ -215,7 +215,21 @@ mdb_value2entry(krb5_context context, krb5_data *data, krb5_kvno kvno, hdb_entry krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE); - /* 16: baselength */ + /* + * 16: baselength + * + * The story here is that these 16 bits have to be a constant: + * KDB_V1_BASE_LENGTH. Once upon a time a different value here + * would have been used to indicate the presence of "extra data" + * between the "base" contents and the {principal name, TL data, + * keys} that follow it. Nothing supports such "extra data" + * nowadays, so neither do we here. + * + * XXX But... surely we ought to log about this extra data, or skip + * it, or something, in case anyone has MIT KDBs with ancient + * entries in them... Logging would allow the admin to know which + * entries to dump with MIT krb5's kdb5_util. + */ CHECK(ret = krb5_ret_uint16(sp, &u16)); if (u16 != KDB_V1_BASE_LENGTH) { ret = EINVAL; goto out; } /* 32: attributes */ @@ -273,28 +287,44 @@ mdb_value2entry(krb5_context context, krb5_data *data, krb5_kvno kvno, hdb_entry CHECK(ret = krb5_ret_uint16(sp, &u16)); /* length: principal */ { + /* + * Note that the principal name includes the NUL in the entry, + * but we don't want to take chances, so we add an extra NUL. + */ p = malloc(u16 + 1); + if (p == NULL) { + ret = ENOMEM; + goto out; + } krb5_storage_read(sp, p, u16); p[u16] = '\0'; CHECK(ret = krb5_parse_name(context, p, &entry->principal)); - free(p); p = NULL; + free(p); } /* for num tl data times 16: tl data type 16: tl data length length: length */ for (i = 0; i < num_tl; i++) { + /* 16: TL data type */ CHECK(ret = krb5_ret_uint16(sp, &u16)); + /* 16: TL data length */ CHECK(ret = krb5_ret_uint16(sp, &u16)); krb5_storage_seek(sp, u16, SEEK_CUR); } - /* for num key data times - 16: version (num keyblocks) - 16: kvno - for version times: - 16: type - 16: length - length: keydata */ + /* + * for num key data times + * 16: "version" + * 16: kvno + * for version times: + * 16: type + * 16: length + * length: keydata + * + * "version" here is really 1 or 2, the first meaning there's only + * keys for this kvno, the second meaning there's keys and salt[s?]. + * That's right... hold that gag reflex, you can do it. + */ for (i = 0; i < num_keys; i++) { int keep = 0; uint16_t version; @@ -304,16 +334,28 @@ mdb_value2entry(krb5_context context, krb5_data *data, krb5_kvno kvno, hdb_entry version = u16; CHECK(ret = krb5_ret_uint16(sp, &u16)); - if (((entry->kvno < u16) && kvno == 0) || kvno == u16) { + /* + * First time through, and until we find one matching key, + * entry->kvno == 0. + */ + if ((entry->kvno < u16) && (kvno == 0 || kvno == u16)) { keep = 1; entry->kvno = u16; - for (j = 0; j < entry->keys.len; j++) { + /* + * Found a higher kvno than earlier, so free the old highest + * kvno keys. + * + * XXX Of course, we actually want to extract the old kvnos + * as well, for some of the kadm5 APIs. We shouldn't free + * these keys, but keep them elsewhere. + */ + for (j = 0; j < entry->keys.len; j++) free_Key(&entry->keys.val[j]); - free(entry->keys.val); - entry->keys.len = 0; - entry->keys.val = NULL; - } + free(entry->keys.val); + entry->keys.len = 0; + entry->keys.val = NULL; } else if (entry->kvno == u16) + /* Accumulate keys */ keep = 1; if (keep) { @@ -332,28 +374,40 @@ mdb_value2entry(krb5_context context, krb5_data *data, krb5_kvno kvno, hdb_entry memset(k, 0, sizeof(*k)); entry->keys.len += 1; - entry->keys.val[i].mkvno = malloc(sizeof(*entry->keys.val[i].mkvno)); - if (entry->keys.val[i].mkvno == NULL) { + k->mkvno = malloc(sizeof(*k->mkvno)); + if (k->mkvno == NULL) { ret = ENOMEM; goto out; } - *entry->keys.val[i].mkvno = 1; + *k->mkvno = 1; for (j = 0; j < version; j++) { uint16_t type; CHECK(ret = krb5_ret_uint16(sp, &type)); CHECK(ret = krb5_ret_uint16(sp, &u16)); - if (j == 0) { /* key */ + if (j == 0) { + /* This "version" means we have a key */ k->key.keytype = type; if (u16 < 2) { ret = EINVAL; goto out; } + /* + * MIT stores keys encrypted keys as {16-bit length + * of plaintext key, {encrypted key}}. The reason + * for this is that the Kerberos cryptosystem is not + * length-preserving. Heimdal's approach is to + * truncate the plaintext to the expected length of + * the key given its enctype, so we ignore this + * 16-bit length-of-plaintext-key field. + */ krb5_storage_seek(sp, 2, SEEK_CUR); /* skip real length */ - k->key.keyvalue.length = u16 - 2; + k->key.keyvalue.length = u16 - 2; /* adjust cipher len */ k->key.keyvalue.data = malloc(k->key.keyvalue.length); - krb5_storage_read(sp, k->key.keyvalue.data, k->key.keyvalue.length); - } else if (j == 1) { /* salt */ + krb5_storage_read(sp, k->key.keyvalue.data, + k->key.keyvalue.length); + } else if (j == 1) { + /* This "version" means we have a salt */ k->salt = calloc(1, sizeof(*k->salt)); if (k->salt == NULL) { ret = ENOMEM; @@ -371,15 +425,27 @@ mdb_value2entry(krb5_context context, krb5_data *data, krb5_kvno kvno, hdb_entry } fix_salt(context, entry, entry->keys.len - 1); } else { + /* + * Whatever this "version" might be, we skip it + * + * XXX A krb5.conf parameter requesting that we log + * about strangeness like this, or return an error + * from here, might be nice. + */ krb5_storage_seek(sp, u16, SEEK_CUR); } } } else { - /* skip */ + /* + * XXX For now we skip older kvnos, but we should extract + * them... + */ for (j = 0; j < version; j++) { + /* enctype */ CHECK(ret = krb5_ret_uint16(sp, &u16)); + /* encrypted key (or plaintext salt) */ CHECK(ret = krb5_ret_uint16(sp, &u16)); - krb5_storage_seek(sp, u16, u16); + krb5_storage_seek(sp, u16, SEEK_CUR); } } } @@ -391,9 +457,9 @@ mdb_value2entry(krb5_context context, krb5_data *data, krb5_kvno kvno, hdb_entry return 0; out: - if (p) - free(p); - free_hdb_entry(entry); + if (ret == HEIM_ERR_EOF) + /* Better error code than "end of file" */ + ret = HEIM_ERR_BAD_HDBENT_ENCODING; return ret; } diff --git a/lib/krb5/addr_families.c b/lib/krb5/addr_families.c index cccf1cbc9..7c47da206 100644 --- a/lib/krb5/addr_families.c +++ b/lib/krb5/addr_families.c @@ -44,6 +44,7 @@ struct addr_operations { 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 *); + krb5_boolean (*is_loopback)(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 *); @@ -136,6 +137,17 @@ ipv4_uninteresting (const struct sockaddr *sa) return FALSE; } +static krb5_boolean +ipv4_is_loopback (const struct sockaddr *sa) +{ + const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa; + + if ((ntohl(sin4->sin_addr.s_addr) >> 24) == IN_LOOPBACKNET) + return TRUE; + + return FALSE; +} + static void ipv4_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port) { @@ -310,11 +322,19 @@ 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) + return IN6_IS_ADDR_LINKLOCAL(in6) || IN6_IS_ADDR_V4COMPAT(in6); } +static krb5_boolean +ipv6_is_loopback (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_LOOPBACK(in6)); +} + static void ipv6_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port) { @@ -713,8 +733,8 @@ static struct addr_operations at[] = { ipv4_addr2sockaddr, ipv4_h_addr2sockaddr, ipv4_h_addr2addr, - ipv4_uninteresting, ipv4_anyaddr, ipv4_print_addr, ipv4_parse_addr, - NULL, NULL, NULL, ipv4_mask_boundary }, + ipv4_uninteresting, ipv4_is_loopback, 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, @@ -722,18 +742,18 @@ static struct addr_operations at[] = { ipv6_addr2sockaddr, ipv6_h_addr2sockaddr, ipv6_h_addr2addr, - ipv6_uninteresting, ipv6_anyaddr, ipv6_print_addr, ipv6_parse_addr, - NULL, NULL, NULL, ipv6_mask_boundary } , + ipv6_uninteresting, ipv6_is_loopback, ipv6_anyaddr, ipv6_print_addr, + ipv6_parse_addr, NULL, NULL, NULL, ipv6_mask_boundary } , #endif #ifndef HEIMDAL_SMALLER /* fake address type */ {KRB5_ADDRESS_ARANGE, KRB5_ADDRESS_ARANGE, sizeof(struct arange), - NULL, NULL, NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, arange_print_addr, arange_parse_addr, arange_order_addr, arange_free, arange_copy }, #endif {KRB5_ADDRESS_ADDRPORT, KRB5_ADDRESS_ADDRPORT, 0, - NULL, NULL, NULL, NULL, NULL, + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, addrport_print_addr, NULL, NULL, NULL, NULL } }; @@ -912,6 +932,15 @@ krb5_sockaddr_uninteresting(const struct sockaddr *sa) return (*a->uninteresting)(sa); } +KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL +krb5_sockaddr_is_loopback(const struct sockaddr *sa) +{ + struct addr_operations *a = find_af(sa->sa_family); + if (a == NULL || a->is_loopback == NULL) + return TRUE; + return (*a->is_loopback)(sa); +} + /** * krb5_h_addr2sockaddr initializes a "struct sockaddr sa" from af and * the "struct hostent" (see gethostbyname(3) ) h_addr_list diff --git a/lib/krb5/get_addrs.c b/lib/krb5/get_addrs.c index 829b2acc1..0e2bfcf66 100644 --- a/lib/krb5/get_addrs.c +++ b/lib/krb5/get_addrs.c @@ -82,8 +82,8 @@ gethostname_fallback (krb5_context context, krb5_addresses *res) } enum { - LOOP = 1, /* do include loopback interfaces */ - LOOP_IF_NONE = 2, /* include loopback if no other if's */ + LOOP = 1, /* do include loopback addrs */ + LOOP_IF_NONE = 2, /* include loopback addrs if no others */ EXTRA_ADDRESSES = 4, /* include extra addresses */ SCAN_INTERFACES = 8 /* scan interfaces for addresses */ }; @@ -146,11 +146,9 @@ find_all_addresses (krb5_context context, krb5_addresses *res, int flags) continue; if (krb5_sockaddr_uninteresting(ifa->ifa_addr)) continue; - if ((ifa->ifa_flags & IFF_LOOPBACK) != 0) { + if (krb5_sockaddr_is_loopback(ifa->ifa_addr) && (flags & LOOP) == 0) /* We'll deal with the LOOP_IF_NONE case later. */ - if ((flags & LOOP) == 0) - continue; - } + continue; ret = krb5_sockaddr2address(context, ifa->ifa_addr, &res->val[idx]); if (ret) { @@ -189,24 +187,22 @@ find_all_addresses (krb5_context context, krb5_addresses *res, int flags) 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 (!krb5_sockaddr_is_loopback(ifa->ifa_addr)) + continue; + if ((ifa->ifa_flags & IFF_LOOPBACK) == 0) + /* Presumably loopback addrs are only used on loopback ifs! */ + continue; + ret = krb5_sockaddr2address(context, + ifa->ifa_addr, &res->val[idx]); + if (ret) + continue; /* We don't consider this failure fatal */ + if((flags & EXTRA_ADDRESSES) && + krb5_address_search(context, &res->val[idx], + &ignore_addresses)) { + krb5_free_address(context, &res->val[idx]); + continue; } + idx++; } } diff --git a/lib/krb5/heim_err.et b/lib/krb5/heim_err.et index 2e8a0d18d..c47f77092 100644 --- a/lib/krb5/heim_err.et +++ b/lib/krb5/heim_err.et @@ -19,6 +19,7 @@ error_code BAD_MKEY, "Failed to get the master key" error_code SERVICE_NOMATCH, "Unacceptable service used" error_code NOT_SEEKABLE, "File descriptor not seekable" error_code TOO_BIG, "Offset too large" +error_code BAD_HDBENT_ENCODING, "Invalid HDB entry encoding" index 64 prefix HEIM_PKINIT diff --git a/lib/krb5/keytab.c b/lib/krb5/keytab.c index 96c0bce27..f70fb3967 100644 --- a/lib/krb5/keytab.c +++ b/lib/krb5/keytab.c @@ -166,29 +166,27 @@ krb5_kt_register(krb5_context context, } static const char * -keytab_name(const char * name, const char ** ptype, size_t * ptype_len) +keytab_name(const char *name, const char **type, size_t *type_len) { - const char * residual; + const char *residual; residual = strchr(name, ':'); - if (residual == NULL - + if (residual == NULL || + name[0] == '/' #ifdef _WIN32 - /* Avoid treating : as a keytab type * specification */ - || name + 1 == residual #endif ) { - *ptype = "FILE"; - *ptype_len = strlen(*ptype); + *type = "FILE"; + *type_len = strlen(*type); residual = name; } else { - *ptype = name; - *ptype_len = residual - name; + *type = name; + *type_len = residual - name; residual++; } @@ -850,3 +848,46 @@ krb5_kt_remove_entry(krb5_context context, } return (*id->remove)(context, id, entry); } + +/** + * Return true if the keytab exists and have entries + * + * @param context a Keberos context. + * @param id a keytab. + * + * @return Return an error code or 0, see krb5_get_error_message(). + * + * @ingroup krb5_keytab + */ + +KRB5_LIB_FUNCTION krb5_boolean KRB5_LIB_CALL +krb5_kt_have_content(krb5_context context, + krb5_keytab id) +{ + krb5_keytab_entry entry; + krb5_kt_cursor cursor; + krb5_error_code ret; + char *name; + + ret = krb5_kt_start_seq_get(context, id, &cursor); + if (ret) + goto notfound; + + ret = krb5_kt_next_entry(context, id, &entry, &cursor); + krb5_kt_end_seq_get(context, id, &cursor); + if (ret) + goto notfound; + + krb5_kt_free_entry(context, &entry); + + return 0; + + notfound: + ret = krb5_kt_get_full_name(context, id, &name); + if (ret == 0) { + krb5_set_error_message(context, KRB5_KT_NOTFOUND, + N_("No entry in keytab: %s", ""), name); + free(name); + } + return KRB5_KT_NOTFOUND; +} diff --git a/lib/krb5/test_config.c b/lib/krb5/test_config.c index 4ca103aa2..08062275f 100644 --- a/lib/krb5/test_config.c +++ b/lib/krb5/test_config.c @@ -224,7 +224,8 @@ check_escaped_strings(void) } if (*s || *e) - errx(1, "Configuation string list for value [%s] has incorrect length.\n"); + errx(1, "Configuation string list for value [%s] has incorrect length.", + config_strings_tests[i].name); krb5_config_free_strings(ps); } diff --git a/lib/krb5/test_keytab.c b/lib/krb5/test_keytab.c index 33f2f1595..ca2bc4feb 100644 --- a/lib/krb5/test_keytab.c +++ b/lib/krb5/test_keytab.c @@ -54,6 +54,10 @@ test_empty_keytab(krb5_context context, const char *keytab) krb5_kt_remove_entry(context, id, &entry); + ret = krb5_kt_have_content(context, id); + if (ret == 0) + krb5_errx(context, 1, "supposed to be empty keytab isn't"); + ret = krb5_kt_close(context, id); if (ret) krb5_err(context, 1, ret, "krb5_kt_close"); diff --git a/lib/krb5/version-script.map b/lib/krb5/version-script.map index abda458fc..a7913110e 100644 --- a/lib/krb5/version-script.map +++ b/lib/krb5/version-script.map @@ -421,6 +421,7 @@ HEIMDAL_KRB5_2.0 { krb5_kt_get_full_name; krb5_kt_get_name; krb5_kt_get_type; + krb5_kt_have_content; krb5_kt_next_entry; krb5_kt_read_service_key; krb5_kt_register; diff --git a/lib/otp/Makefile.am b/lib/otp/Makefile.am index 920ec3090..e0d4c700d 100644 --- a/lib/otp/Makefile.am +++ b/lib/otp/Makefile.am @@ -16,11 +16,15 @@ lib_LTLIBRARIES = libotp.la libotp_la_LDFLAGS = -version-info 1:5:1 libotp_la_LIBADD = $(LIB_hcrypto) $(LIB_roken) $(LIB_NDBM) +if HAVE_DB1 +ndbm_wrap = ndbm_wrap.c ndbm_wrap.h +else if HAVE_DB3 ndbm_wrap = ndbm_wrap.c ndbm_wrap.h else ndbm_wrap = endif +endif dist_libotp_la_SOURCES = \ otp.c \ diff --git a/lib/roken/roken.h.in b/lib/roken/roken.h.in index 1ca3c10dc..8be137137 100644 --- a/lib/roken/roken.h.in +++ b/lib/roken/roken.h.in @@ -932,6 +932,7 @@ strptime (const char *, const char *, struct tm *); #endif #ifndef HAVE_GETTIMEOFDAY +#define gettimeofday rk_gettimeofday ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL gettimeofday (struct timeval *, void *); #endif