From 533024be44861c8d2c8ba3232738c7d2dbbe2e4f Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Sat, 27 Mar 2010 11:55:22 +1100 Subject: s4:heimdal: import lorikeet-heimdal-201003262338 (commit f4e0dc17709829235f057e0e100d34802d3929ff) --- source4/heimdal/lib/asn1/krb5.asn1 | 5 +- source4/heimdal/lib/gssapi/gssapi/gssapi.h | 10 +- .../lib/gssapi/mech/gss_accept_sec_context.c | 4 +- .../lib/gssapi/mech/gss_decapsulate_token.c | 4 +- .../lib/gssapi/mech/gss_encapsulate_token.c | 4 +- source4/heimdal/lib/gssapi/mech/gss_import_name.c | 25 +++++ .../heimdal/lib/gssapi/mech/gss_init_sec_context.c | 57 +++++++++++ source4/heimdal/lib/gssapi/mech/gss_release_name.c | 15 +++ source4/heimdal/lib/hcrypto/hmac.c | 4 +- source4/heimdal/lib/hcrypto/rand-unix.c | 12 ++- source4/heimdal/lib/hcrypto/rand.c | 19 +++- source4/heimdal/lib/hcrypto/randi.h | 1 + source4/heimdal/lib/hdb/hdb.h | 2 + source4/heimdal/lib/hdb/ndbm.c | 107 ++++++++++++--------- source4/heimdal/lib/hx509/crypto.c | 2 +- source4/heimdal/lib/hx509/sel-lex.l | 4 + source4/heimdal/lib/krb5/constants.c | 1 + source4/heimdal/lib/krb5/context.c | 36 ++++--- source4/heimdal/lib/krb5/crypto.c | 54 +++++++++-- source4/heimdal/lib/krb5/get_cred.c | 4 +- source4/heimdal/lib/krb5/init_creds_pw.c | 12 +-- source4/heimdal/lib/krb5/principal.c | 14 +++ source4/heimdal/lib/krb5/rd_req.c | 2 +- source4/heimdal/lib/krb5/send_to_kdc.c | 2 +- source4/heimdal/lib/krb5/ticket.c | 12 ++- source4/heimdal/lib/roken/resolve.c | 36 ++++--- source4/heimdal/lib/roken/roken.h.in | 16 ++- source4/heimdal/lib/roken/socket.c | 21 ++++ source4/heimdal/lib/roken/strerror_r.c | 14 +-- 29 files changed, 365 insertions(+), 134 deletions(-) (limited to 'source4/heimdal/lib') diff --git a/source4/heimdal/lib/asn1/krb5.asn1 b/source4/heimdal/lib/asn1/krb5.asn1 index ed663fcf5f..b9a566de7b 100644 --- a/source4/heimdal/lib/asn1/krb5.asn1 +++ b/source4/heimdal/lib/asn1/krb5.asn1 @@ -190,8 +190,9 @@ AUTHDATA-TYPE ::= INTEGER { KRB5-AUTHDATA-OSF-DCE-PKI-CERTID(66), KRB5-AUTHDATA-WIN2K-PAC(128), KRB5-AUTHDATA-GSS-API-ETYPE-NEGOTIATION(129), -- Authenticator only - KRB5-AUTHDATA-SIGNTICKET-OLD(-17), - KRB5-AUTHDATA-SIGNTICKET(142) + KRB5-AUTHDATA-SIGNTICKET-OLDER(-17), + KRB5-AUTHDATA-SIGNTICKET-OLD(142), + KRB5-AUTHDATA-SIGNTICKET(512) } -- checksumtypes diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi.h b/source4/heimdal/lib/gssapi/gssapi/gssapi.h index 730737a46a..3f217d38cb 100644 --- a/source4/heimdal/lib/gssapi/gssapi/gssapi.h +++ b/source4/heimdal/lib/gssapi/gssapi/gssapi.h @@ -862,18 +862,18 @@ OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_unseal int * /*qop_state*/ ); -/* +/** * */ OM_uint32 GSSAPI_LIB_FUNCTION -gss_encapsulate_token(gss_buffer_t /* input_token */, - gss_OID /* oid */, +gss_encapsulate_token(const gss_buffer_t /* input_token */, + const gss_OID /* oid */, gss_buffer_t /* output_token */); OM_uint32 GSSAPI_LIB_FUNCTION -gss_decapsulate_token(gss_buffer_t /* input_token */, - gss_OID /* oid */, +gss_decapsulate_token(const gss_buffer_t /* input_token */, + const gss_OID /* oid */, gss_buffer_t /* output_token */); diff --git a/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c index 1529ab1137..5775db837b 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c +++ b/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c @@ -263,8 +263,8 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status, if (mech_ret_flags & GSS_C_DELEG_FLAG) { if (!delegated_cred_handle) { m->gm_release_cred(minor_status, &delegated_mc); - if (ret_flags) - *ret_flags &= ~GSS_C_DELEG_FLAG; + mech_ret_flags &= + ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG); } else if (gss_oid_equal(mech_ret_type, &m->gm_mech_oid) == 0) { /* * If the returned mech_type is not the same diff --git a/source4/heimdal/lib/gssapi/mech/gss_decapsulate_token.c b/source4/heimdal/lib/gssapi/mech/gss_decapsulate_token.c index 8db0832d86..95a6c68445 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_decapsulate_token.c +++ b/source4/heimdal/lib/gssapi/mech/gss_decapsulate_token.c @@ -34,8 +34,8 @@ #include "mech_locl.h" OM_uint32 GSSAPI_LIB_FUNCTION -gss_decapsulate_token(gss_buffer_t input_token, - gss_OID oid, +gss_decapsulate_token(const gss_buffer_t input_token, + const gss_OID oid, gss_buffer_t output_token) { GSSAPIContextToken ct; diff --git a/source4/heimdal/lib/gssapi/mech/gss_encapsulate_token.c b/source4/heimdal/lib/gssapi/mech/gss_encapsulate_token.c index e14b00f9ce..7a3e165364 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_encapsulate_token.c +++ b/source4/heimdal/lib/gssapi/mech/gss_encapsulate_token.c @@ -34,8 +34,8 @@ #include "mech_locl.h" OM_uint32 GSSAPI_LIB_FUNCTION -gss_encapsulate_token(gss_buffer_t input_token, - gss_OID oid, +gss_encapsulate_token(const gss_buffer_t input_token, + const gss_OID oid, gss_buffer_t output_token) { GSSAPIContextToken ct; diff --git a/source4/heimdal/lib/gssapi/mech/gss_import_name.c b/source4/heimdal/lib/gssapi/mech/gss_import_name.c index 19ab75a84c..6ae2302abd 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_import_name.c +++ b/source4/heimdal/lib/gssapi/mech/gss_import_name.c @@ -138,6 +138,31 @@ _gss_import_export_name(OM_uint32 *minor_status, return (GSS_S_COMPLETE); } +/** + * Import a name internal or mechanism name + * + * Type of name and their format: + * - GSS_C_NO_OID + * - GSS_C_NT_USER_NAME + * - GSS_C_NT_HOSTBASED_SERVICE + * - GSS_C_NT_EXPORT_NAME + * - GSS_C_NT_ANONYMOUS + * - GSS_KRB5_NT_PRINCIPAL_NAME + * + * For more information about @ref internalVSmechname. + * + * @param minor_status minor status code + * @param input_name_buffer import name buffer + * @param input_name_type type of the import name buffer + * @param output_name the resulting type, release with + * gss_release_name(), independent of input_name + * + * @returns a gss_error code, see gss_display_status() about printing + * the error code. + * + * @ingroup gssapi + */ + OM_uint32 GSSAPI_LIB_FUNCTION gss_import_name(OM_uint32 *minor_status, const gss_buffer_t input_name_buffer, diff --git a/source4/heimdal/lib/gssapi/mech/gss_init_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_init_sec_context.c index dfebe26109..1bcc639345 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_init_sec_context.c +++ b/source4/heimdal/lib/gssapi/mech/gss_init_sec_context.c @@ -44,6 +44,63 @@ _gss_mech_cred_find(gss_cred_id_t cred_handle, gss_OID mech_type) return GSS_C_NO_CREDENTIAL; } +/** + * As the initiator build a context with an acceptor. + * + * Returns in the major + * - GSS_S_COMPLETE - if the context if build + * - GSS_S_CONTINUE_NEEDED - if the caller needs to continue another + * round of gss_i nit_sec_context + * - error code - any other error code + * + * @param minor_status minor status code. + * + * @param context_handle a pointer to a context handle, will be + * returned as long as there is not an error. + * + * @param target_name the target name of acceptor, created using + * gss_import_name(). The name is can be of any name types the + * mechanism supports, check supported name types with + * gss_inquire_names_for_mech(). + * + * @param input_mech_type mechanism type to use, if GSS_C_NO_OID is + * used, Kerberos (GSS_KRB5_MECHANISM) will be tried. Other + * available mechanism are listed in the @ref gssapi_mechs_intro + * section. + * + * @param req_flags flags using when building the context, see @ref + * gssapi_context_ flags + * + * @param time_req time requested this context should be valid in + * seconds, common used value is GSS_C_INDEFINITE + * + * @param input_chan_bindings Channel bindings used, if not exepected + * otherwise, used GSS_C_NO_CHANNEL_BINDINGS + * + * @param input_token input token sent from the acceptor, for the + * initial packet the buffer of { NULL, 0 } should be used. + * + * @param actual_mech_type the actual mech used, MUST NOT be freed + * since it pointing to static memory. + * + * @param output_token if there is an output token, regardless of + * complete, continue_needed, or error it should be sent to the + * acceptor + * + * @param ret_flags return what flags was negotitated, caller should + * check if they are accetable. For example, if + * GSS_C_MUTUAL_FLAG was negotiated with the acceptor or not. + * + * @param time_rec amount of time this context is valid for + * + * @returns a gss_error code, see gss_display_status() about printing + * the error code. + * + * @ingroup gssapi + */ + + + OM_uint32 GSSAPI_LIB_FUNCTION gss_init_sec_context(OM_uint32 * minor_status, const gss_cred_id_t initiator_cred_handle, diff --git a/source4/heimdal/lib/gssapi/mech/gss_release_name.c b/source4/heimdal/lib/gssapi/mech/gss_release_name.c index 84553ee05d..47786725ac 100644 --- a/source4/heimdal/lib/gssapi/mech/gss_release_name.c +++ b/source4/heimdal/lib/gssapi/mech/gss_release_name.c @@ -28,6 +28,21 @@ #include "mech_locl.h" +/** + * Free a name + * + * import_name can point to NULL or be NULL, or a pointer to a + * gss_name_t structure. If it was a pointer to gss_name_t, the + * pointer will be set to NULL on success and failure. + * + * @param minor_status minor status code + * @param input_name name to free + * + * @returns a gss_error code, see gss_display_status() about printing + * the error code. + * + * @ingroup gssapi + */ OM_uint32 GSSAPI_LIB_FUNCTION gss_release_name(OM_uint32 *minor_status, gss_name_t *input_name) diff --git a/source4/heimdal/lib/hcrypto/hmac.c b/source4/heimdal/lib/hcrypto/hmac.c index dcd836d0be..d11bd98769 100644 --- a/source4/heimdal/lib/hcrypto/hmac.c +++ b/source4/heimdal/lib/hcrypto/hmac.c @@ -52,12 +52,12 @@ HMAC_CTX_cleanup(HMAC_CTX *ctx) ctx->buf = NULL; } if (ctx->opad) { - memset(ctx->ipad, 0, ctx->key_length); + memset(ctx->opad, 0, EVP_MD_block_size(ctx->md)); free(ctx->opad); ctx->opad = NULL; } if (ctx->ipad) { - memset(ctx->ipad, 0, ctx->key_length); + memset(ctx->ipad, 0, EVP_MD_block_size(ctx->md)); free(ctx->ipad); ctx->ipad = NULL; } diff --git a/source4/heimdal/lib/hcrypto/rand-unix.c b/source4/heimdal/lib/hcrypto/rand-unix.c index 4c1f33da59..63dc97fbfa 100644 --- a/source4/heimdal/lib/hcrypto/rand-unix.c +++ b/source4/heimdal/lib/hcrypto/rand-unix.c @@ -46,8 +46,8 @@ * Unix /dev/random */ -static int -get_device_fd(int flags) +int +_hc_unix_device_fd(int flags, char **fn) { static const char *rnd_devices[] = { "/dev/urandom", @@ -61,6 +61,8 @@ get_device_fd(int flags) for(p = rnd_devices; *p; p++) { int fd = open(*p, flags | O_NDELAY); if(fd >= 0) { + if (fn) + *fn = *p; rk_cloexec(fd); return fd; } @@ -76,7 +78,7 @@ unix_seed(const void *indata, int size) if (size <= 0) return; - fd = get_device_fd(O_WRONLY); + fd = _hc_unix_device_fd(O_WRONLY, NULL); if (fd < 0) return; @@ -97,7 +99,7 @@ unix_bytes(unsigned char *outdata, int size) else if (size == 0) return 1; - fd = get_device_fd(O_RDONLY); + fd = _hc_unix_device_fd(O_RDONLY, NULL); if (fd < 0) return 0; @@ -139,7 +141,7 @@ unix_status(void) { int fd; - fd = get_device_fd(O_RDONLY); + fd = _hc_unix_device_fd(O_RDONLY, NULL); if (fd < 0) return 0; close(fd); diff --git a/source4/heimdal/lib/hcrypto/rand.c b/source4/heimdal/lib/hcrypto/rand.c index 9f0438a34e..d360ffcab4 100644 --- a/source4/heimdal/lib/hcrypto/rand.c +++ b/source4/heimdal/lib/hcrypto/rand.c @@ -342,23 +342,32 @@ RAND_write_file(const char *filename) const char * RAND_file_name(char *filename, size_t size) { - const char *e = NULL; + char *e = NULL; int pathp = 0, ret; if (!issuid()) { e = getenv("RANDFILE"); - if (e == NULL) { + if (e == NULL) e = getenv("HOME"); - if (e) - pathp = 1; - } + if (e) + pathp = 1; } /* * Here we really want to call getpwuid(getuid()) but this will * cause recursive lookups if the nss library uses * gssapi/krb5/hcrypto to authenticate to the ldap servers. + * + * So at least return the unix /dev/random if we have one */ +#ifndef _WIN32 + if (e == NULL) { + int fd; + fd = _hc_unix_device_fd(O_RDONLY, &e); + if (fd >= 0) + close(fd); + } +#endif if (e == NULL) return NULL; diff --git a/source4/heimdal/lib/hcrypto/randi.h b/source4/heimdal/lib/hcrypto/randi.h index c6c617af22..a6d921413a 100644 --- a/source4/heimdal/lib/hcrypto/randi.h +++ b/source4/heimdal/lib/hcrypto/randi.h @@ -45,5 +45,6 @@ extern const RAND_METHOD hc_rand_timer_method; extern const RAND_METHOD hc_rand_w32crypto_method; const RAND_METHOD * RAND_timer_method(void); +int _hc_unix_device_fd(int, char **); #endif /* _HEIM_RANDI_H */ diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h index 91b6753722..d118555121 100644 --- a/source4/heimdal/lib/hdb/hdb.h +++ b/source4/heimdal/lib/hdb/hdb.h @@ -158,6 +158,8 @@ typedef struct HDB{ krb5_error_code (*hdb_unlock)(krb5_context, struct HDB*); /** * Rename the data base. + * + * Assume that the database is not hdb_open'ed and not locked. */ krb5_error_code (*hdb_rename)(krb5_context, struct HDB*, const char*); /** diff --git a/source4/heimdal/lib/hdb/ndbm.c b/source4/heimdal/lib/hdb/ndbm.c index d97a98ed6b..bad3c49742 100644 --- a/source4/heimdal/lib/hdb/ndbm.c +++ b/source4/heimdal/lib/hdb/ndbm.c @@ -131,40 +131,59 @@ NDBM_nextkey(krb5_context context, HDB *db, unsigned flags,hdb_entry_ex *entry) } static krb5_error_code -NDBM_rename(krb5_context context, HDB *db, const char *new_name) +open_lock_file(krb5_context context, const char *db_name, int *fd) { - /* XXX this function will break */ - struct ndbm_db *d = db->hdb_db; + char *lock_file; + + /* lock old and new databases */ + asprintf(&lock_file, "%s.lock", db_name); + if(lock_file == NULL) { + krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); + return ENOMEM; + } + + *fd = open(lock_file, O_RDWR | O_CREAT, 0600); + free(lock_file); + if(*fd < 0) { + int ret = errno; + krb5_set_error_message(context, ret, "open(%s): %s", lock_file, + strerror(ret)); + return ret; + } + return 0; +} + +static krb5_error_code +NDBM_rename(krb5_context context, HDB *db, const char *new_name) +{ int ret; char *old_dir, *old_pag, *new_dir, *new_pag; - char *new_lock; - int lock_fd; + int old_lock_fd, new_lock_fd; /* lock old and new databases */ - ret = db->hdb_lock(context, db, HDB_WLOCK); - if(ret) + ret = open_lock_file(context, db->hdb_name, &old_lock_fd); + if (ret) + return ret; + + ret = hdb_lock(old_lock_fd, HDB_WLOCK); + if(ret) { + close(old_lock_fd); return ret; - asprintf(&new_lock, "%s.lock", new_name); - if(new_lock == NULL) { - db->hdb_unlock(context, db); - krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); - return ENOMEM; } - lock_fd = open(new_lock, O_RDWR | O_CREAT, 0600); - if(lock_fd < 0) { - ret = errno; - db->hdb_unlock(context, db); - krb5_set_error_message(context, ret, "open(%s): %s", new_lock, - strerror(ret)); - free(new_lock); + + ret = open_lock_file(context, new_name, &new_lock_fd); + if (ret) { + hdb_unlock(old_lock_fd); + close(old_lock_fd); return ret; } - free(new_lock); - ret = hdb_lock(lock_fd, HDB_WLOCK); + + ret = hdb_lock(new_lock_fd, HDB_WLOCK); if(ret) { - db->hdb_unlock(context, db); - close(lock_fd); + hdb_unlock(old_lock_fd); + close(old_lock_fd); + close(new_lock_fd); return ret; } @@ -174,22 +193,25 @@ NDBM_rename(krb5_context context, HDB *db, const char *new_name) asprintf(&new_pag, "%s.pag", new_name); ret = rename(old_dir, new_dir) || rename(old_pag, new_pag); + if (ret) { + ret = errno; + if (ret == 0) + ret = EPERM; + krb5_set_error_message(context, ret, "rename: %s", strerror(ret)); + } + free(old_dir); free(old_pag); free(new_dir); free(new_pag); - hdb_unlock(lock_fd); - db->hdb_unlock(context, db); - if(ret) { - ret = errno; - close(lock_fd); - krb5_set_error_message(context, ret, "rename: %s", strerror(ret)); - return ret; - } + hdb_unlock(new_lock_fd); + hdb_unlock(old_lock_fd); + close(new_lock_fd); + close(old_lock_fd); - close(d->lock_fd); - d->lock_fd = lock_fd; + if(ret) + return ret; free(db->hdb_name); db->hdb_name = strdup(new_name); @@ -277,38 +299,31 @@ NDBM_open(krb5_context context, HDB *db, int flags, mode_t mode) { krb5_error_code ret; struct ndbm_db *d = malloc(sizeof(*d)); - char *lock_file; if(d == NULL) { krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } - asprintf(&lock_file, "%s.lock", (char*)db->hdb_name); - if(lock_file == NULL) { - free(d); - krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); - return ENOMEM; - } + d->db = dbm_open((char*)db->hdb_name, flags, mode); if(d->db == NULL){ ret = errno; free(d); - free(lock_file); krb5_set_error_message(context, ret, "dbm_open(%s): %s", db->hdb_name, strerror(ret)); return ret; } - d->lock_fd = open(lock_file, O_RDWR | O_CREAT, 0600); - if(d->lock_fd < 0){ + + ret = open_lock_file(context, db->hdb_name, &d->lock_fd); + if (ret) { ret = errno; dbm_close(d->db); free(d); - krb5_set_error_message(context, ret, "open(%s): %s", lock_file, + krb5_set_error_message(context, ret, "open(lock file): %s", strerror(ret)); - free(lock_file); return ret; } - free(lock_file); + db->hdb_db = d; if((flags & O_ACCMODE) == O_RDONLY) ret = hdb_check_db_format(context, db); diff --git a/source4/heimdal/lib/hx509/crypto.c b/source4/heimdal/lib/hx509/crypto.c index bee64c145f..77be4413ac 100644 --- a/source4/heimdal/lib/hx509/crypto.c +++ b/source4/heimdal/lib/hx509/crypto.c @@ -740,7 +740,7 @@ rsa_create_signature(hx509_context context, if (ret <= 0) { ret = HX509_CMS_FAILED_CREATE_SIGATURE; hx509_set_error_string(context, 0, ret, - "RSA private decrypt failed: %d", ret); + "RSA private encrypt failed: %d", ret); return ret; } if (ret > sig->length) diff --git a/source4/heimdal/lib/hx509/sel-lex.l b/source4/heimdal/lib/hx509/sel-lex.l index e9bbbc6087..4c9396750a 100644 --- a/source4/heimdal/lib/hx509/sel-lex.l +++ b/source4/heimdal/lib/hx509/sel-lex.l @@ -53,6 +53,10 @@ static int lex_input(char *, int); struct hx_expr_input _hx509_expr_input; +#ifndef YY_NULL +#define YY_NULL 0 +#endif + #define YY_NO_UNPUT 1 #undef YY_INPUT diff --git a/source4/heimdal/lib/krb5/constants.c b/source4/heimdal/lib/krb5/constants.c index b85f0cf607..6223fb5d6b 100644 --- a/source4/heimdal/lib/krb5/constants.c +++ b/source4/heimdal/lib/krb5/constants.c @@ -42,6 +42,7 @@ KRB5_LIB_VARIABLE const char *krb5_config_file = "~/Library/Preferences/edu.mit.Kerberos:" "/Library/Preferences/edu.mit.Kerberos:" #endif /* __APPLE__ */ +"~/.krb5/config:" SYSCONFDIR "/krb5.conf" #ifndef _WIN32 ":/etc/krb5.conf" diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c index dff7a700c4..adcbb703ee 100644 --- a/source4/heimdal/lib/krb5/context.c +++ b/source4/heimdal/lib/krb5/context.c @@ -535,7 +535,8 @@ krb5_free_context(krb5_context context) krb5_set_send_to_kdc_func(context, NULL, NULL); #ifdef PKINIT - hx509_context_free(&context->hx509ctx); + if (context->hx509ctx) + hx509_context_free(&context->hx509ctx); #endif HEIMDAL_MUTEX_destroy(context->mutex); @@ -824,23 +825,33 @@ KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_set_default_in_tkt_etypes(krb5_context context, const krb5_enctype *etypes) { + krb5_error_code ret; krb5_enctype *p = NULL; - int i; + unsigned int n, m; 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); + for (n = 0; etypes[n]; n++) + ; + n++; + ALLOC(p, n); if(!p) { - krb5_set_error_message (context, ENOMEM, N_("malloc: out of memory", "")); + krb5_set_error_message (context, ENOMEM, + N_("malloc: out of memory", "")); return ENOMEM; } - memmove(p, etypes, i * sizeof(krb5_enctype)); + for (n = 0, m = 0; etypes[n]; n++) { + ret = krb5_enctype_valid(context, etypes[n]); + if (ret) + continue; + p[m++] = etypes[n]; + } + p[m] = ETYPE_NULL; + if (m == 0) { + free(p); + krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP, + N_("no valid enctype set", "")); + return KRB5_PROG_ETYPE_NOSUPP; + } } if(context->etypes) free(context->etypes); @@ -1375,6 +1386,7 @@ _krb5_homedir_access(krb5_context context) * @param allow allow if TRUE home directory * @return the old value * + * @ingroup krb5 */ krb5_boolean diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c index 5906d43f5f..ed8765542c 100644 --- a/source4/heimdal/lib/krb5/crypto.c +++ b/source4/heimdal/lib/krb5/crypto.c @@ -67,6 +67,7 @@ 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_WEAK 128 /* enctype is considered weak */ struct salt_type { krb5_salttype type; @@ -2612,7 +2613,7 @@ static struct encryption_type enctype_des_cbc_crc = { &keytype_des, &checksum_crc32, NULL, - F_DISABLED, + F_DISABLED|F_WEAK, evp_des_encrypt_key_ivec, 0, NULL @@ -2626,7 +2627,7 @@ static struct encryption_type enctype_des_cbc_md4 = { &keytype_des, &checksum_rsa_md4, &checksum_rsa_md4_des, - F_DISABLED, + F_DISABLED|F_WEAK, evp_des_encrypt_null_ivec, 0, NULL @@ -2640,7 +2641,7 @@ static struct encryption_type enctype_des_cbc_md5 = { &keytype_des, &checksum_rsa_md5, &checksum_rsa_md5_des, - F_DISABLED, + F_DISABLED|F_WEAK, evp_des_encrypt_null_ivec, 0, NULL @@ -2654,7 +2655,7 @@ static struct encryption_type enctype_des_cbc_none = { &keytype_des, &checksum_none, NULL, - F_PSEUDO|F_DISABLED, + F_PSEUDO|F_DISABLED|F_WEAK, evp_des_encrypt_null_ivec, 0, NULL @@ -2668,7 +2669,7 @@ static struct encryption_type enctype_des_cfb64_none = { &keytype_des_old, &checksum_none, NULL, - F_PSEUDO|F_DISABLED, + F_PSEUDO|F_DISABLED|F_WEAK, DES_CFB64_encrypt_null_ivec, 0, NULL @@ -2682,7 +2683,7 @@ static struct encryption_type enctype_des_pcbc_none = { &keytype_des_old, &checksum_none, NULL, - F_PSEUDO|F_DISABLED, + F_PSEUDO|F_DISABLED|F_WEAK, DES_PCBC_encrypt_key_ivec, 0, NULL @@ -3143,8 +3144,14 @@ decrypt_internal(krb5_context context, krb5_clear_error_message(context); return KRB5_BAD_MSIZE; } - checksum_sz = CHECKSUMSIZE(et->checksum); + if (len < checksum_sz + et->confoundersize) { + krb5_set_error_message(context, KRB5_BAD_MSIZE, + N_("Encrypted data shorter then " + "checksum + confunder", "")); + return KRB5_BAD_MSIZE; + } + p = malloc(len); if(len != 0 && p == NULL) { krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", "")); @@ -3206,6 +3213,12 @@ decrypt_internal_special(krb5_context context, krb5_clear_error_message(context); return KRB5_BAD_MSIZE; } + if (len < cksum_sz + et->confoundersize) { + krb5_set_error_message(context, KRB5_BAD_MSIZE, + N_("Encrypted data shorter then " + "checksum + confunder", "")); + return KRB5_BAD_MSIZE; + } p = malloc (len); if (p == NULL) { @@ -4402,6 +4415,33 @@ krb5_enctype_enable(krb5_context context, return 0; } +/** + * Enable or disable all weak encryption types + * + * @param context Kerberos 5 context + * @param enable true to enable, false to disable + * + * @return Return an error code or 0. + * + * @ingroup krb5_crypto + */ + +KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL +krb5_allow_weak_crypto(krb5_context context, + krb5_boolean enable) +{ + int i; + + for(i = 0; i < num_etypes; i++) + if(etypes[i]->flags & F_WEAK) { + if(enable) + etypes[i]->flags &= ~F_DISABLED; + else + etypes[i]->flags |= F_DISABLED; + } + return 0; +} + KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_string_to_key_derived(krb5_context context, diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c index 3d76391fa8..75e44f0cd4 100644 --- a/source4/heimdal/lib/krb5/get_cred.c +++ b/source4/heimdal/lib/krb5/get_cred.c @@ -952,9 +952,7 @@ get_cred_kdc_referral(krb5_context context, ticket.server)) break; - if (ticket.server->name.name_string.len != 2 && - strcmp(ticket.server->name.name_string.val[0], KRB5_TGS_NAME) != 0) - { + if (!krb5_principal_is_krbtgt(context, ticket.server)) { krb5_set_error_message(context, KRB5KRB_AP_ERR_NOT_US, N_("Got back an non krbtgt " "ticket referrals", "")); diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c index 4637a6d941..f443788075 100644 --- a/source4/heimdal/lib/krb5/init_creds_pw.c +++ b/source4/heimdal/lib/krb5/init_creds_pw.c @@ -134,12 +134,12 @@ free_init_creds_ctx(krb5_context context, krb5_init_creds_context ctx) free (ctx->pre_auth_types); if (ctx->in_tkt_service) free(ctx->in_tkt_service); - if (ctx->password) { - memset(ctx->password, 0, strlen(ctx->password)); - free(ctx->password); - } if (ctx->keytab_data) free(ctx->keytab_data); + if (ctx->password) { + memset(ctx->password, 0, strlen(ctx->password)); + free(ctx->password); + } krb5_data_free(&ctx->req_buffer); krb5_free_cred_contents(context, &ctx->cred); free_METHOD_DATA(&ctx->md); @@ -1436,8 +1436,8 @@ krb5_init_creds_set_password(krb5_context context, const char *password) { if (ctx->password) { - memset(ctx->password, 0, strlen(ctx->password)); - free(ctx->password); + memset(ctx->password, 0, strlen(ctx->password)); + free(ctx->password); } if (password) { ctx->password = strdup(password); diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c index 00c967a72e..8e6341fd62 100644 --- a/source4/heimdal/lib/krb5/principal.c +++ b/source4/heimdal/lib/krb5/principal.c @@ -1551,3 +1551,17 @@ krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype) N_("Failed to find name type %s", ""), str); return KRB5_PARSE_MALFORMED; } + +/** + * Check if the cname part of the principal is a krbtgt principal + * + * @ingroup krb5_principal + */ + +krb5_boolean +krb5_principal_is_krbtgt(krb5_context context, krb5_const_principal p) +{ + return p->name.name_string.len == 2 && + strcmp(p->name.name_string.val[0], KRB5_TGS_NAME) == 0; + +} diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c index 6b2ffbdaac..9f6a85b1a2 100644 --- a/source4/heimdal/lib/krb5/rd_req.c +++ b/source4/heimdal/lib/krb5/rd_req.c @@ -821,7 +821,7 @@ out: * @param inbuf the (AP-REQ) authentication buffer * * @param server the server with authenticate as, if NULL the function - * will try to find any available credential in the keytab + * will try to find any avaiable credentintial in the keytab * that will verify the reply. The function will prefer the * server the server client specified in the AP-REQ, but if * there is no mach, it will try all keytab entries for a diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c index a9be31e819..9ff52fa545 100644 --- a/source4/heimdal/lib/krb5/send_to_kdc.c +++ b/source4/heimdal/lib/krb5/send_to_kdc.c @@ -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 | SOCK_CLOEXEC); + s = socket (a->ai_family, a->ai_socktype | SOCK_CLOEXEC, a->ai_protocol); if (s < 0) continue; rk_cloexec(s); diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c index 4d8da93579..e7d4d9532d 100644 --- a/source4/heimdal/lib/krb5/ticket.c +++ b/source4/heimdal/lib/krb5/ticket.c @@ -443,9 +443,7 @@ check_server_referral(krb5_context context, return KRB5KRB_AP_ERR_MODIFIED; } - if (returned->name.name_string.len == 2 && - strcmp(returned->name.name_string.val[0], KRB5_TGS_NAME) == 0) - { + if (krb5_principal_is_krbtgt(context, returned)) { const char *realm = returned->name.name_string.val[1]; if (ref.referred_realm == NULL @@ -485,7 +483,13 @@ check_server_referral(krb5_context context, return ret; noreferral: - if (krb5_principal_compare(context, requested, returned) == FALSE) { + /* + * Expect excact match or that we got a krbtgt + */ + if (krb5_principal_compare(context, requested, returned) != TRUE && + (krb5_realm_compare(context, requested, returned) != TRUE && + krb5_principal_is_krbtgt(context, returned) != TRUE)) + { krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED, N_("Not same server principal returned " "as requested", "")); diff --git a/source4/heimdal/lib/roken/resolve.c b/source4/heimdal/lib/roken/resolve.c index 0c0fc1dd92..e112274a68 100644 --- a/source4/heimdal/lib/roken/resolve.c +++ b/source4/heimdal/lib/roken/resolve.c @@ -521,8 +521,7 @@ dns_lookup_int(const char *domain, int rr_class, int rr_type) { struct rk_dns_reply *r; void *reply = NULL; - int size; - int len; + int size, len; #if defined(HAVE_DNS_SEARCH) struct sockaddr_storage from; uint32_t fromsize = sizeof(from); @@ -540,15 +539,12 @@ dns_lookup_int(const char *domain, int rr_class, int rr_type) return NULL; /* is this the best we can do? */ #endif - size = 0; - len = 1000; - do { + len = 1500; + while(1) { if (reply) { free(reply); reply = NULL; } - if (size <= len) - size = len; if (_resolve_debug) { #if defined(HAVE_DNS_SEARCH) dns_set_debug(handle, 1); @@ -556,27 +552,37 @@ dns_lookup_int(const char *domain, int rr_class, int rr_type) state.options |= RES_DEBUG; #endif fprintf(stderr, "dns_lookup(%s, %d, %s), buffer size %d\n", domain, - rr_class, rk_dns_type_to_string(rr_type), size); + rr_class, rk_dns_type_to_string(rr_type), len); } - reply = malloc(size); + reply = malloc(len); if (reply == NULL) { resolve_free_handle(handle); return NULL; } - len = resolve_search(handle, domain, rr_class, rr_type, reply, size); + size = resolve_search(handle, domain, rr_class, rr_type, reply, len); if (_resolve_debug) { fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n", - domain, rr_class, rk_dns_type_to_string(rr_type), len); - } - if (len <= 0) { + domain, rr_class, rk_dns_type_to_string(rr_type), size); + } + if (size > len) { + /* resolver thinks it know better, go for it */ + len = size; + } else if (size > 0) { + /* got a good reply */ + break; + } else if (size <= 0 && len < rk_DNS_MAX_PACKET_SIZE) { + len *= 2; + if (len > rk_DNS_MAX_PACKET_SIZE) + len = rk_DNS_MAX_PACKET_SIZE; + } else { + /* the end, leave */ resolve_free_handle(handle); free(reply); return NULL; } - } while (size < len && len < rk_DNS_MAX_PACKET_SIZE); - resolve_free_handle(handle); + } len = min(len, size); r = parse_reply(reply, len); diff --git a/source4/heimdal/lib/roken/roken.h.in b/source4/heimdal/lib/roken/roken.h.in index 0492db4d6b..76b083c797 100644 --- a/source4/heimdal/lib/roken/roken.h.in +++ b/source4/heimdal/lib/roken/roken.h.in @@ -471,7 +471,7 @@ ROKEN_LIB_FUNCTION int ROKEN_LIB_CALL getdtablesize(void); ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL strerror(int); #endif -#if !defined(HAVE_STRERROR_R) && !defined(strerror_r) && !defined(STRERROR_R_PROTO_COMPATIBLE) +#if (!defined(HAVE_STRERROR_R) && !defined(strerror_r)) || (!defined(STRERROR_R_PROTO_COMPATIBLE) && defined(HAVE_STRERROR_R)) int ROKEN_LIB_FUNCTION rk_strerror_r(int, char *, size_t); #else #define rk_strerror_r strerror_r @@ -652,8 +652,14 @@ ROKEN_LIB_FUNCTION unsigned short ROKEN_LIB_CALL bswap16(unsigned short); int rk_flock(int fd, int operation); #endif /* HAVE_FLOCK */ -#if defined(SunOS) || defined(_AIX) +#ifndef HAVE_DIRFD +#ifdef HAVE_DIR_DD_FD #define dirfd(x) ((x)->dd_fd) +#else +#ifndef _WIN32 /* Windows code never calls dirfd */ +#error Missing dirfd() and ->dd_fd +#endif +#endif #endif ROKEN_LIB_FUNCTION time_t ROKEN_LIB_CALL tm2time (struct tm, int); @@ -1033,6 +1039,12 @@ void rk_qsort(void *, size_t, size_t, int (*)(const void *, const void *)); #endif +#if defined(__linux__) && SOCK_CLOEXEC && !defined(SOCKET_WRAPPER_REPLACE) +#undef socket +#define socket(_fam,_type,_prot) rk_socket(_fam,_type,_prot) +int ROKEN_LIB_FUNCTION rk_socket(int, int, int); +#endif + #ifdef SOCKET_WRAPPER_REPLACE #include #endif diff --git a/source4/heimdal/lib/roken/socket.c b/source4/heimdal/lib/roken/socket.c index bfc4b7102b..bd800ac5a1 100644 --- a/source4/heimdal/lib/roken/socket.c +++ b/source4/heimdal/lib/roken/socket.c @@ -315,3 +315,24 @@ socket_to_fd(rk_socket_t sock, int flags) return _open_osfhandle((intptr_t) sock, flags); #endif } + +#ifndef HEIMDAL_SMALLER +#undef socket + +int rk_socket(int, int, int); + +int +rk_socket(int domain, int type, int protocol) +{ + int s; + s = socket (domain, type, protocol); +#ifdef SOCK_CLOEXEC + if ((SOCK_CLOEXEC & type) && s < 0 && errno == EINVAL) { + type &= ~SOCK_CLOEXEC; + s = socket (domain, type, protocol); + } +#endif + return s; +} + +#endif /* HEIMDAL_SMALLER */ diff --git a/source4/heimdal/lib/roken/strerror_r.c b/source4/heimdal/lib/roken/strerror_r.c index 63dae09a7d..5155c28cb5 100644 --- a/source4/heimdal/lib/roken/strerror_r.c +++ b/source4/heimdal/lib/roken/strerror_r.c @@ -33,11 +33,12 @@ #include -#if !defined(HAVE_STRERROR_R) && !defined(STRERROR_R_PROTO_COMPATIBLE) +#if (!defined(HAVE_STRERROR_R) && !defined(strerror_r)) || (!defined(STRERROR_R_PROTO_COMPATIBLE) && defined(HAVE_STRERROR_R)) #include #include #include +#include "roken.h" #ifdef _MSC_VER @@ -58,11 +59,6 @@ rk_strerror_r(int eno, char * strerrbuf, size_t buflen) #else /* _MSC_VER */ -#ifndef HAVE_STRERROR_R -extern int sys_nerr; -extern char *sys_errlist[]; -#endif - int ROKEN_LIB_FUNCTION rk_strerror_r(int eno, char *strerrbuf, size_t buflen) { @@ -76,11 +72,7 @@ rk_strerror_r(int eno, char *strerrbuf, size_t buflen) return 0; #else int ret; - if(eno < 0 || eno >= sys_nerr) { - snprintf(strerrbuf, buflen, "Error %d occurred.", eno); - return EINVAL; - } - ret = snprintf(strerrbuf, buflen, "%s", sys_errlist[eno]); + ret = strlcpy(strerrbuf, buflen, strerror(eno)); if (ret > buflen) return ERANGE; return 0; -- cgit