From 858146ae8401069a5a27b75e291314689749c45c Mon Sep 17 00:00:00 2001 From: Will Fiveash Date: Wed, 21 Jan 2009 19:16:22 +0000 Subject: [PATCH] Merge with current head of trunk: svn merge -r21722:HEAD svn+ssh://wfiveash@svn.mit.edu/krb5/trunk Everything compiles. git-svn-id: svn://anonsvn.mit.edu/krb5/branches/mkey_migrate@21769 dc483132-0cff-0310-8789-dd5450dbe970 --- src/include/k5-int.h | 78 +---- src/kadmin/passwd/unit-test/Makefile.in | 4 +- src/kadmin/passwd/unit-test/config/unix.exp | 41 +++ src/kadmin/server/network.c | 39 ++- src/kdc/do_as_req.c | 17 +- src/kdc/do_tgs_req.c | 5 +- src/kdc/kdc_preauth.c | 3 +- src/kdc/kdc_util.c | 176 ++++++----- src/kdc/kdc_util.h | 5 +- src/kdc/network.c | 38 +-- src/lib/crypto/cksumtypes.c | 37 +-- src/lib/crypto/cksumtypes.h | 29 ++ src/lib/crypto/etypes.c | 112 ++----- src/lib/crypto/etypes.h | 36 +++ src/lib/crypto/string_to_cksumtype.c | 14 +- src/lib/crypto/string_to_enctype.c | 16 +- src/lib/gssapi/krb5/accept_sec_context.c | 29 ++ src/lib/gssapi/krb5/gssapi_krb5.c | 10 +- src/lib/gssapi/krb5/k5sealv3.c | 4 +- src/lib/gssapi/krb5/k5sealv3iov.c | 4 +- src/lib/gssapi/krb5/k5unseal.c | 40 ++- src/lib/gssapi/krb5/k5unsealiov.c | 92 ++++-- src/lib/gssapi/krb5/util_crypt.c | 68 +++-- src/lib/gssapi/libgssapi_krb5.exports | 2 - src/lib/gssapi/mechglue/Makefile.in | 6 - src/lib/gssapi/mechglue/deps | 16 - .../gssapi/mechglue/g_export_name_object.c | 74 ----- src/lib/gssapi/mechglue/g_imp_name_object.c | 124 -------- src/lib/gssapi/mechglue/g_initialize.c | 2 - src/lib/gssapi/mechglue/mglueP.h | 15 - src/lib/gssapi/spnego/spnego_mech.c | 2 - src/lib/kadm5/clnt/client_init.c | 6 +- src/lib/kadm5/srv/svr_principal.c | 126 ++++---- src/lib/kadm5/unit-test/Makefile.in | 20 +- src/lib/kadm5/unit-test/config/unix.exp | 41 +++ src/lib/krb5/krb/auth_con.c | 10 + src/lib/krb5/krb/mk_cred.c | 1 + src/lib/krb5/krb/mk_priv.c | 1 + src/lib/krb5/krb/mk_req_ext.c | 24 +- src/lib/krb5/krb/mk_safe.c | 1 + src/lib/krb5/krb/pac.c | 4 +- src/lib/krb5/krb/rd_cred.c | 1 + src/lib/krb5/krb/rd_priv.c | 1 + src/lib/krb5/krb/rd_rep.c | 2 +- src/lib/krb5/krb/rd_req_dec.c | 9 +- src/lib/krb5/krb/rd_safe.c | 1 + src/lib/krb5/krb/sendauth.c | 29 +- src/lib/krb5/libkrb5.exports | 2 + src/lib/krb5/os/accessor.c | 1 + src/lib/krb5/os/deps | 4 +- src/lib/krb5/os/hst_realm.c | 10 +- src/lib/krb5/os/net_write.c | 51 +++- src/lib/krb5/os/os-proto.h | 5 +- src/lib/krb5/os/write_msg.c | 49 +++- src/lib/krb5/rcache/Makefile.in | 10 +- src/lib/krb5/rcache/deps | 10 + src/lib/krb5/rcache/rc_conv.c | 41 +++ src/lib/krb5/rcache/rc_dfl.c | 274 ++++++++++++++---- src/lib/krb5/rcache/t_replay.c | 270 +++++++++++++++++ src/lib/rpc/unit-test/Makefile.in | 2 +- src/lib/rpc/xdr.c | 61 ++++ src/tests/asn.1/Makefile.in | 2 +- src/tests/asn.1/deps | 12 + src/tests/threads/t_rcache.c | 1 + 64 files changed, 1393 insertions(+), 827 deletions(-) delete mode 100644 src/lib/gssapi/mechglue/g_export_name_object.c delete mode 100644 src/lib/gssapi/mechglue/g_imp_name_object.c create mode 100644 src/lib/krb5/rcache/t_replay.c diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 181ead4f1a..0b9eae8e58 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 1989,1990,1991,1992,1993,1994,1995,2000,2001, 2003,2006,2007,2008 by the Massachusetts Institute of Technology, + * Copyright (C) 1989,1990,1991,1992,1993,1994,1995,2000,2001, 2003,2006,2007,2008,2009 by the Massachusetts Institute of Technology, * Cambridge, MA, USA. All Rights Reserved. * * This software is being provided to you, the LICENSEE, by the @@ -657,69 +657,6 @@ struct krb5_aead_provider { size_t num_data); }; -typedef void (*krb5_encrypt_length_func) (const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - size_t inputlen, size_t *length); - -typedef krb5_error_code (*krb5_crypt_func) (const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - const krb5_keyblock *key, krb5_keyusage keyusage, - const krb5_data *ivec, - const krb5_data *input, krb5_data *output); - -typedef krb5_error_code (*krb5_str2key_func) (const struct krb5_enc_provider *enc, const krb5_data *string, - const krb5_data *salt, const krb5_data *parm, krb5_keyblock *key); - -typedef krb5_error_code (*krb5_prf_func)( - const struct krb5_enc_provider *enc, - const struct krb5_hash_provider *hash, - const krb5_keyblock *key, - const krb5_data *in, krb5_data *out); - -struct krb5_keytypes { - krb5_enctype etype; - char *in_string; - char *out_string; - const struct krb5_enc_provider *enc; - const struct krb5_hash_provider *hash; - size_t prf_length; - krb5_encrypt_length_func encrypt_len; - krb5_crypt_func encrypt; - krb5_crypt_func decrypt; - krb5_str2key_func str2key; - krb5_prf_func prf; - krb5_cksumtype required_ctype; - const struct krb5_aead_provider *aead; -}; - -struct krb5_cksumtypes { - krb5_cksumtype ctype; - unsigned int flags; - char *in_string; - char *out_string; - /* if the hash is keyed, this is the etype it is keyed with. - Actually, it can be keyed by any etype which has the same - enc_provider as the specified etype. DERIVE checksums can - be keyed with any valid etype. */ - krb5_enctype keyed_etype; - /* I can't statically initialize a union, so I'm just going to use - two pointers here. The keyhash is used if non-NULL. If NULL, - then HMAC/hash with derived keys is used if the relevant flag - is set. Otherwise, a non-keyed hash is computed. This is all - kind of messy, but so is the krb5 api. */ - const struct krb5_keyhash_provider *keyhash; - const struct krb5_hash_provider *hash; - /* This just gets uglier and uglier. In the key derivation case, - we produce an hmac. To make the hmac code work, we can't hack - the output size indicated by the hash provider, but we may want - a truncated hmac. If we want truncation, this is the number of - bytes we truncate to; it should be 0 otherwise. */ - unsigned int trunc_size; -}; - -#define KRB5_CKSUMFLAG_DERIVE 0x0001 -#define KRB5_CKSUMFLAG_NOT_COLL_PROOF 0x0002 - /* * in here to deal with stuff from lib/crypto */ @@ -1964,7 +1901,7 @@ void krb5int_free_srv_dns_data(struct srv_dns_entry *); /* To keep happy libraries which are (for now) accessing internal stuff */ /* Make sure to increment by one when changing the struct */ -#define KRB5INT_ACCESS_STRUCT_VERSION 12 +#define KRB5INT_ACCESS_STRUCT_VERSION 13 #ifndef ANAME_SZ struct ktext; /* from krb.h, for krb524 support */ @@ -1977,6 +1914,7 @@ typedef struct _krb5int_access { const krb5_keyblock *key, unsigned int icount, const krb5_data *input, krb5_data *output); + krb5_error_code (* krb5_auth_con_get_subkey_enctype)(krb5_context, krb5_auth_context, krb5_enctype *); /* service location and communication */ krb5_error_code (*sendto_udp) (krb5_context, const krb5_data *msg, const struct addrlist *, struct sendto_callback_info*, krb5_data *reply, @@ -2182,6 +2120,7 @@ typedef struct _krb5_donot_replay { krb5_ui_4 hash; char *server; /* null-terminated */ char *client; /* null-terminated */ + char *msghash; /* null-terminated */ krb5_int32 cusec; krb5_timestamp ctime; } krb5_donot_replay; @@ -2206,6 +2145,9 @@ krb5_error_code krb5_auth_to_rep (krb5_context, krb5_tkt_authent *, krb5_donot_replay *); +krb5_error_code krb5_rc_hash_message + (krb5_context context, + const krb5_data *message, char **out); krb5_error_code KRB5_CALLCONV krb5_rc_initialize @@ -2581,6 +2523,11 @@ krb5_error_code krb5_auth_con_getpermetypes krb5_auth_context, krb5_enctype **); +krb5_error_code krb5_auth_con_get_subkey_enctype + (krb5_context context, + krb5_auth_context, + krb5_enctype *); + krb5_error_code KRB5_CALLCONV krb5int_server_decrypt_ticket_keyblock (krb5_context context, @@ -2589,6 +2536,7 @@ krb5int_server_decrypt_ticket_keyblock krb5_error_code krb5_read_message (krb5_context, krb5_pointer, krb5_data *); krb5_error_code krb5_write_message (krb5_context, krb5_pointer, krb5_data *); +krb5_error_code krb5int_write_messages (krb5_context, krb5_pointer, krb5_data *, int); int krb5_net_read (krb5_context, int , char *, int); int krb5_net_write (krb5_context, int , const char *, int); diff --git a/src/kadmin/passwd/unit-test/Makefile.in b/src/kadmin/passwd/unit-test/Makefile.in index 969ee8207e..37dfaca33f 100644 --- a/src/kadmin/passwd/unit-test/Makefile.in +++ b/src/kadmin/passwd/unit-test/Makefile.in @@ -16,10 +16,10 @@ unit-test-body:: $(ENV_SETUP) $(RUNTEST) --tool kpasswd KPASSWD=../kpasswd \ KINIT=$(BUILDTOP)/clients/kinit/kinit \ KDESTROY=$(BUILDTOP)/clients/kdestroy/kdestroy \ - PRIOCNTL_HACK=@PRIOCNTL_HACK@ + PRIOCNTL_HACK=@PRIOCNTL_HACK@ VALGRIND="$(VALGRIND)" unit-test-setup:: - $(ENV_SETUP) $(START_SERVERS) + $(ENV_SETUP) $(VALGRIND) $(START_SERVERS) unit-test-cleanup:: $(ENV_SETUP) $(STOP_SERVERS) diff --git a/src/kadmin/passwd/unit-test/config/unix.exp b/src/kadmin/passwd/unit-test/config/unix.exp index bd8382e19e..479d772437 100644 --- a/src/kadmin/passwd/unit-test/config/unix.exp +++ b/src/kadmin/passwd/unit-test/config/unix.exp @@ -1,3 +1,44 @@ +if { [string length $VALGRIND] } { + rename spawn valgrind_aux_spawn + proc spawn { args } { + global VALGRIND + upvar 1 spawn_id spawn_id + set newargs {} + set inflags 1 + set eatnext 0 + foreach arg $args { + if { $arg == "-ignore" \ + || $arg == "-open" \ + || $arg == "-leaveopen" } { + lappend newargs $arg + set eatnext 1 + continue + } + if [string match "-*" $arg] { + lappend newargs $arg + continue + } + if { $eatnext } { + set eatnext 0 + lappend newargs $arg + continue + } + if { $inflags } { + set inflags 0 + # Only run valgrind for local programs, not + # system ones. +#&&![string match "/bin/sh" $arg] sh is used to start kadmind! + if [string match "/" [string index $arg 0]]&&![string match "/bin/ls" $arg]&&![regexp {/kshd$} $arg] { + set newargs [concat $newargs $VALGRIND] + } + } + lappend newargs $arg + } + set pid [eval valgrind_aux_spawn $newargs] + return $pid + } +} + # Hack around Solaris 9 kernel race condition that causes last output # from a pty to get dropped. if { $PRIOCNTL_HACK } { diff --git a/src/kadmin/server/network.c b/src/kadmin/server/network.c index d0f8afab89..df3f01cf06 100644 --- a/src/kadmin/server/network.c +++ b/src/kadmin/server/network.c @@ -1,7 +1,7 @@ /* * kadmin/server/network.c * - * Copyright 1990,2000,2007,2008 by the Massachusetts Institute of Technology. + * Copyright 1990,2000,2007,2008,2009 by the Massachusetts Institute of Technology. * * Export of this software from the United States of America may * require a specific license from the United States Government. @@ -180,13 +180,16 @@ static const char *paddr (struct sockaddr *sa) /* kadmin data. */ -enum kadm_conn_type { CONN_UDP, CONN_UDP_PKTINFO, CONN_TCP_LISTENER, - CONN_TCP, CONN_ROUTING, CONN_RPC_LISTENER, CONN_RPC }; +enum conn_type { + CONN_UDP, CONN_UDP_PKTINFO, CONN_TCP_LISTENER, CONN_TCP, + CONN_RPC_LISTENER, CONN_RPC, + CONN_ROUTING +}; /* Per-connection info. */ struct connection { int fd; - enum kadm_conn_type type; + enum conn_type type; void (*service)(void *handle, struct connection *, const char *, int); union { /* Type-specific information. */ @@ -331,10 +334,6 @@ static krb5_error_code add_rpc_service(int port, u_long prognum, u_long versnum, return 0; } - -#define USE_AF AF_INET -#define USE_TYPE SOCK_DGRAM - #define USE_AF AF_INET #define USE_TYPE SOCK_DGRAM @@ -351,7 +350,7 @@ struct socksetup { }; static struct connection * -add_fd (struct socksetup *data, int sock, enum kadm_conn_type conntype, +add_fd (struct socksetup *data, int sock, enum conn_type conntype, void (*service)(void *handle, struct connection *, const char *, int)) { struct connection *newconn; @@ -1147,8 +1146,13 @@ recv_from_to(int s, void *buf, size_t len, int flags, struct sockaddr *to, socklen_t *tolen) { #if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE) - if (to && tolen) + if (to && tolen) { + /* Clobber with something recognizeable in case we try to use + the address. */ + memset(to, 0x40, *tolen); *tolen = 0; + } + return recvfrom(s, buf, len, flags, from, fromlen); #else int r; @@ -1160,6 +1164,10 @@ recv_from_to(int s, void *buf, size_t len, int flags, if (!to || !tolen) return recvfrom(s, buf, len, flags, from, fromlen); + /* Clobber with something recognizeable in case we can't extract + the address but try to use it anyways. */ + memset(to, 0x40, *tolen); + iov.iov_base = buf; iov.iov_len = len; memset(&msg, 0, sizeof(msg)); @@ -1393,6 +1401,17 @@ static void process_packet(void *handle, } #endif + if (daddr_len == 0 && conn->type == CONN_UDP) { + /* If the PKTINFO option isn't set, this socket should be + bound to a specific local address. This info probably + should've been saved in our socket data structure at setup + time. */ + daddr_len = sizeof(daddr); + if (getsockname(port_fd, (struct sockaddr *)&daddr, &daddr_len) != 0) + daddr_len = 0; + /* On failure, keep going anyways. */ + } + request.length = cc; request.data = pktbuf; faddr.address = &addr; diff --git a/src/kdc/do_as_req.c b/src/kdc/do_as_req.c index d0279a0d61..0756d4c944 100644 --- a/src/kdc/do_as_req.c +++ b/src/kdc/do_as_req.c @@ -2,7 +2,7 @@ * kdc/do_as_req.c * * Portions Copyright (C) 2007 Apple Inc. - * Copyright 1990,1991,2007,2008 by the Massachusetts Institute of Technology. + * Copyright 1990,1991,2007,2008,2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -99,7 +99,7 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, krb5_error_code errcode; int c_nprincs = 0, s_nprincs = 0; krb5_boolean more; - krb5_timestamp kdc_time, authtime; + krb5_timestamp kdc_time, authtime = 0; krb5_keyblock session_key; const char *status; krb5_key_data *server_key, *client_key; @@ -561,9 +561,6 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length); free(reply.enc_part.ciphertext.data); - log_as_req(from, request, &reply, cname, sname, authtime, 0, 0, 0); - did_log = 1; - #ifdef KRBCONF_KDC_MODIFIES_KDB /* * If we get this far, we successfully did the AS_REQ. @@ -573,6 +570,10 @@ process_as_req(krb5_kdc_req *request, krb5_data *req_pkt, #endif /* KRBCONF_KDC_MODIFIES_KDB */ update_client = 1; + log_as_req(from, request, &reply, &client, cname, &server, sname, + authtime, 0, 0, 0); + did_log = 1; + goto egress; errout: @@ -580,10 +581,6 @@ errout: /* fall through */ egress: - if (update_client) { - audit_as_request(request, &client, &server, authtime, errcode); - } - if (pa_context) free_padata_context(kdc_context, &pa_context); @@ -591,7 +588,7 @@ egress: emsg = krb5_get_error_message(kdc_context, errcode); if (status) { - log_as_req(from, request, &reply, cname, sname, 0, + log_as_req(from, request, &reply, &client, cname, &server, sname, 0, status, errcode, emsg); did_log = 1; } diff --git a/src/kdc/do_tgs_req.c b/src/kdc/do_tgs_req.c index 3812698808..9c96734e6a 100644 --- a/src/kdc/do_tgs_req.c +++ b/src/kdc/do_tgs_req.c @@ -1,7 +1,7 @@ /* * kdc/do_tgs_req.c * - * Copyright 1990,1991,2001,2007,2008 by the Massachusetts Institute of Technology. + * Copyright 1990,1991,2001,2007,2008,2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -282,6 +282,7 @@ tgt_again: */ if ((errcode = kdc_get_server_key(request->second_ticket[st_idx], c_flags, + TRUE, /* match_enctype */ &st_client, &st_nprincs, &st_sealing_key, @@ -839,7 +840,7 @@ cleanup: if (errcode) emsg = krb5_get_error_message (kdc_context, errcode); log_tgs_req(from, request, &reply, cname, sname, altcname, authtime, - status, errcode, emsg); + c_flags, s4u_name, status, errcode, emsg); if (errcode) { krb5_free_error_message (kdc_context, emsg); emsg = NULL; diff --git a/src/kdc/kdc_preauth.c b/src/kdc/kdc_preauth.c index d1acf01e1d..00b8531d86 100644 --- a/src/kdc/kdc_preauth.c +++ b/src/kdc/kdc_preauth.c @@ -1161,6 +1161,7 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, */ switch(retval) { case 0: /* in case of PA-PAC-REQUEST with no PA-ENC-TIMESTAMP */ + case KRB5KRB_AP_ERR_BAD_INTEGRITY: case KRB5KRB_AP_ERR_SKEW: case KRB5KDC_ERR_ETYPE_NOSUPP: /* rfc 4556 */ @@ -1184,7 +1185,6 @@ check_padata (krb5_context context, krb5_db_entry *client, krb5_data *req_pkt, /* This value is shared with KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED. */ /* case KRB5KDC_ERR_KEY_TOO_WEAK: */ return retval; - case KRB5KRB_AP_ERR_BAD_INTEGRITY: default: return KRB5KDC_ERR_PREAUTH_FAILED; } @@ -2407,6 +2407,7 @@ verify_sam_response(krb5_context context, krb5_db_entry *client, /* Now check the replay cache. */ rep.client = princ_psr; rep.server = "SAM/rc"; /* Should not match any principal name. */ + rep.msghash = NULL; rep.ctime = psr->stime; rep.cusec = psr->susec; retval = krb5_rc_store(kdc_context, kdc_rcache, &rep); diff --git a/src/kdc/kdc_util.c b/src/kdc/kdc_util.c index 0d6b96e507..a9a89636e2 100644 --- a/src/kdc/kdc_util.c +++ b/src/kdc/kdc_util.c @@ -1,7 +1,7 @@ /* * kdc/kdc_util.c * - * Copyright 1990,1991,2007,2008 by the Massachusetts Institute of Technology. + * Copyright 1990,1991,2007,2008,2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -292,7 +292,8 @@ kdc_process_tgs_req(krb5_kdc_req *request, const krb5_fulladdr *from, goto cleanup_auth_context; #endif - if ((retval = kdc_get_server_key(apreq->ticket, 0, krbtgt, nprincs, &key, &kvno))) + if ((retval = kdc_get_server_key(apreq->ticket, 0, foreign_server, + krbtgt, nprincs, &key, &kvno))) goto cleanup_auth_context; /* * We do not use the KDB keytab because other parts of the TGS need the TGT key. @@ -408,11 +409,11 @@ cleanup: */ krb5_error_code kdc_get_server_key(krb5_ticket *ticket, unsigned int flags, - krb5_db_entry *server, + krb5_boolean match_enctype, krb5_db_entry *server, int *nprincs, krb5_keyblock **key, krb5_kvno *kvno) { krb5_error_code retval; - krb5_boolean more; + krb5_boolean more, similar; krb5_key_data * server_key; krb5_keyblock * tmp_mkey; @@ -433,34 +434,55 @@ kdc_get_server_key(krb5_ticket *ticket, unsigned int flags, char *sname; if (!krb5_unparse_name(kdc_context, ticket->server, &sname)) { + limit_string(sname); krb5_klog_syslog(LOG_ERR,"TGS_REQ: UNKNOWN SERVER: server='%s'", sname); free(sname); } return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN); } + if (server->attributes & KRB5_KDB_DISALLOW_SVR || + server->attributes & KRB5_KDB_DISALLOW_ALL_TIX) { + retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; + goto errout; + } retval = krb5_dbe_find_mkey(kdc_context, master_keylist, server, &tmp_mkey); if (retval) goto errout; retval = krb5_dbe_find_enctype(kdc_context, server, - ticket->enc_part.enctype, -1, - (krb5_int32)ticket->enc_part.kvno, &server_key); + match_enctype ? ticket->enc_part.enctype : -1, + -1, (krb5_int32)ticket->enc_part.kvno, + &server_key); if (retval) goto errout; if (!server_key) { retval = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN; goto errout; } - *kvno = server_key->key_data_kvno; if ((*key = (krb5_keyblock *)malloc(sizeof **key))) { retval = krb5_dbekd_decrypt_key_data(kdc_context, tmp_mkey, server_key, *key, NULL); } else retval = ENOMEM; + retval = krb5_c_enctype_compare(kdc_context, ticket->enc_part.enctype, + (*key)->enctype, &similar); + if (retval) + goto errout; + if (!similar) { + retval = KRB5_KDB_NO_PERMITTED_KEY; + goto errout; + } + (*key)->enctype = ticket->enc_part.enctype; + *kvno = server_key->key_data_kvno; errout: + if (retval != 0) { + krb5_db_free_principal(kdc_context, server, *nprincs); + *nprincs = 0; + } + return retval; } @@ -1698,11 +1720,8 @@ sign_db_authdata (krb5_context context, krb5_data rep_data; *ret_authdata = NULL; - if (ad_entry != NULL) { - assert(ad_nprincs != NULL); - memset(ad_entry, 0, sizeof(*ad_entry)); - *ad_nprincs = 0; - } + memset(ad_entry, 0, sizeof(*ad_entry)); + *ad_nprincs = 0; memset(&req, 0, sizeof(req)); memset(&rep, 0, sizeof(rep)); @@ -1994,7 +2013,7 @@ check_allowed_to_delegate_to(krb5_context context, /* Must be in same realm */ if (!krb5_realm_compare(context, server->princ, proxy)) { - return KRB5_IN_TKT_REALM_MISMATCH; /* XXX */ + return KRB5KDC_ERR_BADOPTION; } req.server = server; @@ -2103,84 +2122,6 @@ kdc_check_transited_list(krb5_context context, return code; } -krb5_error_code -audit_as_request(krb5_kdc_req *request, - krb5_db_entry *client, - krb5_db_entry *server, - krb5_timestamp authtime, - krb5_error_code errcode) -{ - krb5_error_code code; - kdb_audit_as_req req; - krb5_data req_data; - krb5_data rep_data; - - memset(&req, 0, sizeof(req)); - - req.request = request; - req.client = client; - req.server = server; - req.authtime = authtime; - req.error_code = errcode; - - req_data.data = (void *)&req; - req_data.length = sizeof(req); - - rep_data.data = NULL; - rep_data.length = 0; - - code = krb5_db_invoke(kdc_context, - KRB5_KDB_METHOD_AUDIT_AS, - &req_data, - &rep_data); - if (code == KRB5_KDB_DBTYPE_NOSUP) { - return 0; - } - - assert(rep_data.length == 0); - - return code; -} - -krb5_error_code -audit_tgs_request(krb5_kdc_req *request, - krb5_const_principal client, - krb5_db_entry *server, - krb5_timestamp authtime, - krb5_error_code errcode) -{ - krb5_error_code code; - kdb_audit_tgs_req req; - krb5_data req_data; - krb5_data rep_data; - - memset(&req, 0, sizeof(req)); - - req.request = request; - req.client = client; - req.server = server; - req.authtime = authtime; - req.error_code = errcode; - - req_data.data = (void *)&req; - req_data.length = sizeof(req); - - rep_data.data = NULL; - rep_data.length = 0; - - code = krb5_db_invoke(kdc_context, - KRB5_KDB_METHOD_AUDIT_TGS, - &req_data, - &rep_data); - if (code == KRB5_KDB_DBTYPE_NOSUP) { - return 0; - } - - assert(rep_data.length == 0); - - return code; -} - krb5_error_code validate_transit_path(krb5_context context, krb5_const_principal client, @@ -2212,10 +2153,12 @@ validate_transit_path(krb5_context context, /* "status" is null to indicate success. */ /* Someday, pass local address/port as well. */ +/* Currently no info about name canonicalization is logged. */ void log_as_req(const krb5_fulladdr *from, krb5_kdc_req *request, krb5_kdc_rep *reply, - const char *cname, const char *sname, + krb5_db_entry *client, const char *cname, + krb5_db_entry *server, const char *sname, krb5_timestamp authtime, const char *status, krb5_error_code errcode, const char *emsg) { @@ -2255,15 +2198,45 @@ log_as_req(const krb5_fulladdr *from, audit_krb5kdc_as_req(some in_addr *, (in_port_t)from->port, 0, cname, sname, errcode); #endif +#if 1 + { + kdb_audit_as_req req; + krb5_data req_data; + krb5_data rep_data; + + memset(&req, 0, sizeof(req)); + + req.request = request; + req.client = client; + req.server = server; + req.authtime = authtime; + req.error_code = errcode; + + req_data.data = (void *)&req; + req_data.length = sizeof(req); + + rep_data.data = NULL; + rep_data.length = 0; + + (void) krb5_db_invoke(kdc_context, + KRB5_KDB_METHOD_AUDIT_AS, + &req_data, + &rep_data); + assert(rep_data.length == 0); + } +#endif } /* Here "status" must be non-null. Error code - KRB5KDC_ERR_SERVER_NOMATCH is handled specially. */ + KRB5KDC_ERR_SERVER_NOMATCH is handled specially. + + Currently no info about name canonicalization is logged. */ void log_tgs_req(const krb5_fulladdr *from, krb5_kdc_req *request, krb5_kdc_rep *reply, const char *cname, const char *sname, const char *altcname, krb5_timestamp authtime, + unsigned int c_flags, const char *s4u_name, const char *status, krb5_error_code errcode, const char *emsg) { char ktypestr[128]; @@ -2285,7 +2258,7 @@ log_tgs_req(const krb5_fulladdr *from, /* Differences: server-nomatch message logs 2nd ticket's client name (useful), and doesn't log ktypestr (probably not important). */ - if (errcode != KRB5KDC_ERR_SERVER_NOMATCH) + if (errcode != KRB5KDC_ERR_SERVER_NOMATCH) { krb5_klog_syslog(LOG_INFO, "TGS_REQ (%s) %s: %s: authtime %d, %s%s %s for %s%s%s", ktypestr, @@ -2296,7 +2269,19 @@ log_tgs_req(const krb5_fulladdr *from, sname ? sname : "", errcode ? ", " : "", errcode ? emsg : ""); - else + if (s4u_name) { + assert(isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION) || + isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)); + if (isflagset(c_flags, KRB5_KDB_FLAG_PROTOCOL_TRANSITION)) + krb5_klog_syslog(LOG_INFO, + "... PROTOCOL-TRANSITION s4u-client=%s", + s4u_name); + else if (isflagset(c_flags, KRB5_KDB_FLAG_CONSTRAINED_DELEGATION)) + krb5_klog_syslog(LOG_INFO, + "... CONSTRAINED-DELEGATION s4u-client=%s", + s4u_name); + } + } else krb5_klog_syslog(LOG_INFO, "TGS_REQ %s: %s: authtime %d, %s for %s, 2nd tkt client %s", fromstring, status, authtime, @@ -2306,6 +2291,7 @@ log_tgs_req(const krb5_fulladdr *from, /* OpenSolaris: audit_krb5kdc_tgs_req(...) or audit_krb5kdc_tgs_req_2ndtktmm(...) */ + /* ... krb5_db_invoke ... */ } void diff --git a/src/kdc/kdc_util.h b/src/kdc/kdc_util.h index 0d8e36bfd2..b70f98a6e2 100644 --- a/src/kdc/kdc_util.h +++ b/src/kdc/kdc_util.h @@ -69,6 +69,7 @@ krb5_error_code kdc_process_tgs_req krb5_keyblock **); krb5_error_code kdc_get_server_key (krb5_ticket *, unsigned int, + krb5_boolean match_enctype, krb5_db_entry *, int *, krb5_keyblock **, krb5_kvno *); @@ -283,7 +284,8 @@ validate_transit_path(krb5_context context, void log_as_req(const krb5_fulladdr *from, krb5_kdc_req *request, krb5_kdc_rep *reply, - const char *cname, const char *sname, + krb5_db_entry *client, const char *cname, + krb5_db_entry *server, const char *sname, krb5_timestamp authtime, const char *status, krb5_error_code errcode, const char *emsg); void @@ -291,6 +293,7 @@ log_tgs_req(const krb5_fulladdr *from, krb5_kdc_req *request, krb5_kdc_rep *reply, const char *cname, const char *sname, const char *altcname, krb5_timestamp authtime, + unsigned int c_flags, const char *s4u_name, const char *status, krb5_error_code errcode, const char *emsg); void log_tgs_alt_tgt(krb5_principal p); diff --git a/src/kdc/network.c b/src/kdc/network.c index 98f074cce7..fffaa1e788 100644 --- a/src/kdc/network.c +++ b/src/kdc/network.c @@ -1,7 +1,7 @@ /* * kdc/network.c * - * Copyright 1990,2000,2007,2008 by the Massachusetts Institute of Technology. + * Copyright 1990,2000,2007,2008,2009 by the Massachusetts Institute of Technology. * * Export of this software from the United States of America may * require a specific license from the United States Government. @@ -175,26 +175,18 @@ static const char *paddr (struct sockaddr *sa) /* KDC data. */ -enum kdc_conn_type { CONN_UDP, CONN_UDP_PKTINFO, CONN_TCP_LISTENER, CONN_TCP, CONN_ROUTING }; +enum conn_type { + CONN_UDP, CONN_UDP_PKTINFO, CONN_TCP_LISTENER, CONN_TCP, + CONN_ROUTING +}; /* Per-connection info. */ struct connection { int fd; - enum kdc_conn_type type; + enum conn_type type; void (*service)(struct connection *, const char *, int); union { /* Type-specific information. */ -#if 0 - struct { - int x; - } udp; - struct { - int x; - } udp_pktinfo; - struct { - int x; - } tcp_listener; -#endif struct { /* connection */ struct sockaddr_storage addr_s; @@ -316,7 +308,7 @@ struct socksetup { }; static struct connection * -add_fd (struct socksetup *data, int sock, enum kdc_conn_type conntype, +add_fd (struct socksetup *data, int sock, enum conn_type conntype, void (*service)(struct connection *, const char *, int)) { struct connection *newconn; @@ -527,7 +519,7 @@ setup_tcp_listener_ports(struct socksetup *data) /* Sockets are created, prepare to listen on them. */ if (s4 >= 0) { - if (add_tcp_listener_fd(data, s4) == 0) + if (add_tcp_listener_fd(data, s4) == NULL) close(s4); else { FD_SET(s4, &sstate.rfds); @@ -539,7 +531,7 @@ setup_tcp_listener_ports(struct socksetup *data) } #ifdef KRB5_USE_INET6 if (s6 >= 0) { - if (add_tcp_listener_fd(data, s6) == 0) { + if (add_tcp_listener_fd(data, s6) == NULL) { close(s6); s6 = -1; } else { @@ -1012,8 +1004,12 @@ recv_from_to(int s, void *buf, size_t len, int flags, struct sockaddr *to, socklen_t *tolen) { #if (!defined(IP_PKTINFO) && !defined(IPV6_PKTINFO)) || !defined(CMSG_SPACE) - if (to && tolen) + if (to && tolen) { + /* Clobber with something recognizeable in case we try to use + the address. */ + memset(to, 0x40, *tolen); *tolen = 0; + } return recvfrom(s, buf, len, flags, from, fromlen); #else int r; @@ -1025,6 +1021,10 @@ recv_from_to(int s, void *buf, size_t len, int flags, if (!to || !tolen) return recvfrom(s, buf, len, flags, from, fromlen); + /* Clobber with something recognizeable in case we can't extract + the address but try to use it anyways. */ + memset(to, 0x40, *tolen); + iov.iov_base = buf; iov.iov_len = len; memset(&msg, 0, sizeof(msg)); @@ -1306,7 +1306,7 @@ static void accept_tcp_connection(struct connection *conn, const char *prog, sockdata.retval = 0; newconn = add_tcp_data_fd(&sockdata, s); - if (newconn == 0) + if (newconn == NULL) return; if (getnameinfo((struct sockaddr *)&addr_s, addrlen, diff --git a/src/lib/crypto/cksumtypes.c b/src/lib/crypto/cksumtypes.c index fca48e29a5..037e53f495 100644 --- a/src/lib/crypto/cksumtypes.c +++ b/src/lib/crypto/cksumtypes.c @@ -31,69 +31,58 @@ const struct krb5_cksumtypes krb5_cksumtypes_list[] = { { CKSUMTYPE_CRC32, KRB5_CKSUMFLAG_NOT_COLL_PROOF, - "crc32", "CRC-32", + "crc32", { 0 }, "CRC-32", 0, NULL, &krb5int_hash_crc32 }, { CKSUMTYPE_RSA_MD4, 0, - "md4", "RSA-MD4", + "md4", { 0 }, "RSA-MD4", 0, NULL, &krb5int_hash_md4 }, { CKSUMTYPE_RSA_MD4_DES, 0, - "md4-des", "RSA-MD4 with DES cbc mode", + "md4-des", { 0 }, "RSA-MD4 with DES cbc mode", ENCTYPE_DES_CBC_CRC, &krb5int_keyhash_md4des, NULL }, { CKSUMTYPE_DESCBC, 0, - "des-cbc", "DES cbc mode", + "des-cbc", { 0 }, "DES cbc mode", ENCTYPE_DES_CBC_CRC, &krb5int_keyhash_descbc, NULL }, { CKSUMTYPE_RSA_MD5, 0, - "md5", "RSA-MD5", + "md5", { 0 }, "RSA-MD5", 0, NULL, &krb5int_hash_md5 }, { CKSUMTYPE_RSA_MD5_DES, 0, - "md5-des", "RSA-MD5 with DES cbc mode", + "md5-des", { 0 }, "RSA-MD5 with DES cbc mode", ENCTYPE_DES_CBC_CRC, &krb5int_keyhash_md5des, NULL }, { CKSUMTYPE_NIST_SHA, 0, - "sha", "NIST-SHA", + "sha", { 0 }, "NIST-SHA", 0, NULL, &krb5int_hash_sha1 }, { CKSUMTYPE_HMAC_SHA1_DES3, KRB5_CKSUMFLAG_DERIVE, - "hmac-sha1-des3", "HMAC-SHA1 DES3 key", + "hmac-sha1-des3", { "hmac-sha1-des3-kd" }, "HMAC-SHA1 DES3 key", 0, NULL, &krb5int_hash_sha1 }, - { CKSUMTYPE_HMAC_SHA1_DES3, KRB5_CKSUMFLAG_DERIVE, - "hmac-sha1-des3-kd", "HMAC-SHA1 DES3 key", /* alias */ - 0, NULL, - &krb5int_hash_sha1 }, - { CKSUMTYPE_HMAC_MD5_ARCFOUR, 0, - "hmac-md5-rc4", "Microsoft HMAC MD5 (RC4 key)", - ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_hmac_md5, - NULL }, - { CKSUMTYPE_HMAC_MD5_ARCFOUR, 0, - "hmac-md5-enc", "Microsoft HMAC MD5 (RC4 key)", /*Heimdal alias*/ - ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_hmac_md5, - NULL }, { CKSUMTYPE_HMAC_MD5_ARCFOUR, 0, - "hmac-md5-earcfour", "Microsoft HMAC MD5 (RC4 key)", /* alias*/ + "hmac-md5-rc4", { "hmac-md5-enc", "hmac-md5-earcfour" }, + "Microsoft HMAC MD5 (RC4 key)", ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_hmac_md5, NULL }, { CKSUMTYPE_HMAC_SHA1_96_AES128, KRB5_CKSUMFLAG_DERIVE, - "hmac-sha1-96-aes128", "HMAC-SHA1 AES128 key", + "hmac-sha1-96-aes128", { 0 }, "HMAC-SHA1 AES128 key", 0, NULL, &krb5int_hash_sha1, 12 }, { CKSUMTYPE_HMAC_SHA1_96_AES256, KRB5_CKSUMFLAG_DERIVE, - "hmac-sha1-96-aes256", "HMAC-SHA1 AES256 key", + "hmac-sha1-96-aes256", { 0 }, "HMAC-SHA1 AES256 key", 0, NULL, &krb5int_hash_sha1, 12 }, { CKSUMTYPE_MD5_HMAC_ARCFOUR, 0, - "md5-hmac-rc4", "Microsoft MD5 HMAC (RC4 key)", + "md5-hmac-rc4", { 0 }, "Microsoft MD5 HMAC (RC4 key)", ENCTYPE_ARCFOUR_HMAC, &krb5int_keyhash_md5_hmac, NULL } }; diff --git a/src/lib/crypto/cksumtypes.h b/src/lib/crypto/cksumtypes.h index ef23169fab..71409d4272 100644 --- a/src/lib/crypto/cksumtypes.h +++ b/src/lib/crypto/cksumtypes.h @@ -26,5 +26,34 @@ #include "k5-int.h" +struct krb5_cksumtypes { + krb5_cksumtype ctype; + unsigned int flags; + char *name; + char *aliases[2]; + char *out_string; + /* if the hash is keyed, this is the etype it is keyed with. + Actually, it can be keyed by any etype which has the same + enc_provider as the specified etype. DERIVE checksums can + be keyed with any valid etype. */ + krb5_enctype keyed_etype; + /* I can't statically initialize a union, so I'm just going to use + two pointers here. The keyhash is used if non-NULL. If NULL, + then HMAC/hash with derived keys is used if the relevant flag + is set. Otherwise, a non-keyed hash is computed. This is all + kind of messy, but so is the krb5 api. */ + const struct krb5_keyhash_provider *keyhash; + const struct krb5_hash_provider *hash; + /* This just gets uglier and uglier. In the key derivation case, + we produce an hmac. To make the hmac code work, we can't hack + the output size indicated by the hash provider, but we may want + a truncated hmac. If we want truncation, this is the number of + bytes we truncate to; it should be 0 otherwise. */ + unsigned int trunc_size; +}; + +#define KRB5_CKSUMFLAG_DERIVE 0x0001 +#define KRB5_CKSUMFLAG_NOT_COLL_PROOF 0x0002 + extern const struct krb5_cksumtypes krb5_cksumtypes_list[]; extern const unsigned int krb5_cksumtypes_length; diff --git a/src/lib/crypto/etypes.c b/src/lib/crypto/etypes.c index de11787d14..c300f3b2c1 100644 --- a/src/lib/crypto/etypes.c +++ b/src/lib/crypto/etypes.c @@ -42,7 +42,7 @@ const struct krb5_keytypes krb5_enctypes_list[] = { { ENCTYPE_DES_CBC_CRC, - "des-cbc-crc", "DES cbc mode with CRC-32", + "des-cbc-crc", { 0 }, "DES cbc mode with CRC-32", &krb5int_enc_des, &krb5int_hash_crc32, 8, krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt, @@ -51,7 +51,7 @@ const struct krb5_keytypes krb5_enctypes_list[] = { CKSUMTYPE_RSA_MD5, NULL /*AEAD*/ }, { ENCTYPE_DES_CBC_MD4, - "des-cbc-md4", "DES cbc mode with RSA-MD4", + "des-cbc-md4", { 0 }, "DES cbc mode with RSA-MD4", &krb5int_enc_des, &krb5int_hash_md4, 8, krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt, @@ -60,7 +60,7 @@ const struct krb5_keytypes krb5_enctypes_list[] = { CKSUMTYPE_RSA_MD4, NULL /*AEAD*/ }, { ENCTYPE_DES_CBC_MD5, - "des-cbc-md5", "DES cbc mode with RSA-MD5", + "des-cbc-md5", { "des" }, "DES cbc mode with RSA-MD5", &krb5int_enc_des, &krb5int_hash_md5, 8, krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt, @@ -68,18 +68,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { NULL, /*PRF*/ CKSUMTYPE_RSA_MD5, NULL /*AEAD*/ }, - { ENCTYPE_DES_CBC_MD5, - "des", "DES cbc mode with RSA-MD5", /* alias */ - &krb5int_enc_des, &krb5int_hash_md5, - 8, - krb5_old_encrypt_length, krb5_old_encrypt, krb5_old_decrypt, - krb5int_des_string_to_key, - NULL, /*PRF*/ - CKSUMTYPE_RSA_MD5, - NULL /*AEAD*/ }, - { ENCTYPE_DES_CBC_RAW, - "des-cbc-raw", "DES cbc mode raw", + "des-cbc-raw", { 0 }, "DES cbc mode raw", &krb5int_enc_des, NULL, 8, krb5_raw_encrypt_length, krb5_raw_encrypt, krb5_raw_decrypt, @@ -88,7 +78,7 @@ const struct krb5_keytypes krb5_enctypes_list[] = { 0, &krb5int_aead_raw }, { ENCTYPE_DES3_CBC_RAW, - "des3-cbc-raw", "Triple DES cbc mode raw", + "des3-cbc-raw", { 0 }, "Triple DES cbc mode raw", &krb5int_enc_des3, NULL, 8, krb5_raw_encrypt_length, krb5_raw_encrypt, krb5_raw_decrypt, @@ -98,25 +88,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { &krb5int_aead_raw }, { ENCTYPE_DES3_CBC_SHA1, - "des3-cbc-sha1", "Triple DES cbc mode with HMAC/sha1", - &krb5int_enc_des3, &krb5int_hash_sha1, - 8, - krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt, - krb5int_dk_string_to_key, - NULL, /*PRF*/ - CKSUMTYPE_HMAC_SHA1_DES3, - &krb5int_aead_dk }, - { ENCTYPE_DES3_CBC_SHA1, /* alias */ - "des3-hmac-sha1", "Triple DES cbc mode with HMAC/sha1", - &krb5int_enc_des3, &krb5int_hash_sha1, - 8, - krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt, - krb5int_dk_string_to_key, - NULL, /*PRF*/ - CKSUMTYPE_HMAC_SHA1_DES3, - &krb5int_aead_dk }, - { ENCTYPE_DES3_CBC_SHA1, /* alias */ - "des3-cbc-sha1-kd", "Triple DES cbc mode with HMAC/sha1", + "des3-cbc-sha1", { "des3-hmac-sha1", "des3-cbc-sha1-kd" }, + "Triple DES cbc mode with HMAC/sha1", &krb5int_enc_des3, &krb5int_hash_sha1, 8, krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt, @@ -126,7 +99,7 @@ const struct krb5_keytypes krb5_enctypes_list[] = { &krb5int_aead_dk }, { ENCTYPE_DES_HMAC_SHA1, - "des-hmac-sha1", "DES with HMAC/sha1", + "des-hmac-sha1", { 0 }, "DES with HMAC/sha1", &krb5int_enc_des, &krb5int_hash_sha1, 8, krb5_dk_encrypt_length, krb5_dk_encrypt, krb5_dk_decrypt, @@ -135,34 +108,8 @@ const struct krb5_keytypes krb5_enctypes_list[] = { 0, NULL }, { ENCTYPE_ARCFOUR_HMAC, - "arcfour-hmac","ArcFour with HMAC/md5", &krb5int_enc_arcfour, - &krb5int_hash_md5, - 0, -krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, - krb5_arcfour_decrypt, krb5int_arcfour_string_to_key, - NULL, /*PRF*/ - CKSUMTYPE_HMAC_MD5_ARCFOUR, - &krb5int_aead_arcfour }, - { ENCTYPE_ARCFOUR_HMAC, /* alias */ - "rc4-hmac", "ArcFour with HMAC/md5", &krb5int_enc_arcfour, - &krb5int_hash_md5, - 0, - krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, - krb5_arcfour_decrypt, krb5int_arcfour_string_to_key, - NULL, /*PRF*/ - CKSUMTYPE_HMAC_MD5_ARCFOUR, - &krb5int_aead_arcfour }, - { ENCTYPE_ARCFOUR_HMAC, /* alias */ - "arcfour-hmac-md5", "ArcFour with HMAC/md5", &krb5int_enc_arcfour, - &krb5int_hash_md5, - 0, - krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, - krb5_arcfour_decrypt, krb5int_arcfour_string_to_key, - NULL, /*PRF*/ - CKSUMTYPE_HMAC_MD5_ARCFOUR, - &krb5int_aead_arcfour }, - { ENCTYPE_ARCFOUR_HMAC_EXP, - "arcfour-hmac-exp", "Exportable ArcFour with HMAC/md5", + "arcfour-hmac", { "rc4-hmac", "arcfour-hmac-md5" }, + "ArcFour with HMAC/md5", &krb5int_enc_arcfour, &krb5int_hash_md5, 0, @@ -171,18 +118,9 @@ krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, NULL, /*PRF*/ CKSUMTYPE_HMAC_MD5_ARCFOUR, &krb5int_aead_arcfour }, - { ENCTYPE_ARCFOUR_HMAC_EXP, /* alias */ - "rc4-hmac-exp", "Exportable ArcFour with HMAC/md5", - &krb5int_enc_arcfour, - &krb5int_hash_md5, - 0, - krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, - krb5_arcfour_decrypt, krb5int_arcfour_string_to_key, - NULL, /*PRF*/ - CKSUMTYPE_HMAC_MD5_ARCFOUR, - &krb5int_aead_arcfour }, - { ENCTYPE_ARCFOUR_HMAC_EXP, /* alias */ - "arcfour-hmac-md5-exp", "Exportable ArcFour with HMAC/md5", + { ENCTYPE_ARCFOUR_HMAC_EXP, + "arcfour-hmac-exp", { "rc4-hmac-exp", "arcfour-hmac-md5-exp" }, + "Exportable ArcFour with HMAC/md5", &krb5int_enc_arcfour, &krb5int_hash_md5, 0, @@ -193,16 +131,8 @@ krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, &krb5int_aead_arcfour }, { ENCTYPE_AES128_CTS_HMAC_SHA1_96, - "aes128-cts-hmac-sha1-96", "AES-128 CTS mode with 96-bit SHA-1 HMAC", - &krb5int_enc_aes128, &krb5int_hash_sha1, - 16, - krb5int_aes_encrypt_length, krb5int_aes_dk_encrypt, krb5int_aes_dk_decrypt, - krb5int_aes_string_to_key, - krb5int_dk_prf, - CKSUMTYPE_HMAC_SHA1_96_AES128, - &krb5int_aead_aes }, - { ENCTYPE_AES128_CTS_HMAC_SHA1_96, /* alias */ - "aes128-cts", "AES-128 CTS mode with 96-bit SHA-1 HMAC", + "aes128-cts-hmac-sha1-96", { "aes128-cts" }, + "AES-128 CTS mode with 96-bit SHA-1 HMAC", &krb5int_enc_aes128, &krb5int_hash_sha1, 16, krb5int_aes_encrypt_length, krb5int_aes_dk_encrypt, krb5int_aes_dk_decrypt, @@ -211,16 +141,8 @@ krb5_arcfour_encrypt_length, krb5_arcfour_encrypt, CKSUMTYPE_HMAC_SHA1_96_AES128, &krb5int_aead_aes }, { ENCTYPE_AES256_CTS_HMAC_SHA1_96, - "aes256-cts-hmac-sha1-96", "AES-256 CTS mode with 96-bit SHA-1 HMAC", - &krb5int_enc_aes256, &krb5int_hash_sha1, - 16, - krb5int_aes_encrypt_length, krb5int_aes_dk_encrypt, krb5int_aes_dk_decrypt, - krb5int_aes_string_to_key, - krb5int_dk_prf, - CKSUMTYPE_HMAC_SHA1_96_AES256, - &krb5int_aead_aes }, - { ENCTYPE_AES256_CTS_HMAC_SHA1_96, /* alias */ - "aes256-cts", "AES-256 CTS mode with 96-bit SHA-1 HMAC", + "aes256-cts-hmac-sha1-96", { "aes256-cts" }, + "AES-256 CTS mode with 96-bit SHA-1 HMAC", &krb5int_enc_aes256, &krb5int_hash_sha1, 16, krb5int_aes_encrypt_length, krb5int_aes_dk_encrypt, krb5int_aes_dk_decrypt, diff --git a/src/lib/crypto/etypes.h b/src/lib/crypto/etypes.h index ca94e56ffa..af2718d826 100644 --- a/src/lib/crypto/etypes.h +++ b/src/lib/crypto/etypes.h @@ -26,5 +26,41 @@ #include "k5-int.h" +typedef void (*krb5_encrypt_length_func) (const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + size_t inputlen, size_t *length); + +typedef krb5_error_code (*krb5_crypt_func) (const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, krb5_keyusage keyusage, + const krb5_data *ivec, + const krb5_data *input, krb5_data *output); + +typedef krb5_error_code (*krb5_str2key_func) (const struct krb5_enc_provider *enc, const krb5_data *string, + const krb5_data *salt, const krb5_data *parm, krb5_keyblock *key); + +typedef krb5_error_code (*krb5_prf_func)( + const struct krb5_enc_provider *enc, + const struct krb5_hash_provider *hash, + const krb5_keyblock *key, + const krb5_data *in, krb5_data *out); + +struct krb5_keytypes { + krb5_enctype etype; + char *name; + char *aliases[2]; + char *out_string; + const struct krb5_enc_provider *enc; + const struct krb5_hash_provider *hash; + size_t prf_length; + krb5_encrypt_length_func encrypt_len; + krb5_crypt_func encrypt; + krb5_crypt_func decrypt; + krb5_str2key_func str2key; + krb5_prf_func prf; + krb5_cksumtype required_ctype; + const struct krb5_aead_provider *aead; +}; + extern const struct krb5_keytypes krb5_enctypes_list[]; extern const int krb5_enctypes_length; diff --git a/src/lib/crypto/string_to_cksumtype.c b/src/lib/crypto/string_to_cksumtype.c index a796851457..5a3c70d731 100644 --- a/src/lib/crypto/string_to_cksumtype.c +++ b/src/lib/crypto/string_to_cksumtype.c @@ -30,13 +30,23 @@ krb5_error_code KRB5_CALLCONV krb5_string_to_cksumtype(char *string, krb5_cksumtype *cksumtypep) { - unsigned int i; + unsigned int i, j; for (i=0; iproto == 0 && + (ctx->gss_flags & GSS_C_DCE_STYLE) == 0 && + (ap_req_options & AP_OPTS_USE_SUBKEY)) { + code = (*kaccess.krb5_auth_con_get_subkey_enctype) (context, + auth_context, + &negotiated_etype); + if (code != 0) { + major_status = GSS_S_FAILURE; + goto fail; + } + + switch (negotiated_etype) { + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_CRC: + case ENCTYPE_DES3_CBC_SHA1: + case ENCTYPE_ARCFOUR_HMAC: + case ENCTYPE_ARCFOUR_HMAC_EXP: + ap_req_options &= ~(AP_OPTS_USE_SUBKEY); + break; + } + } + if (ctx->proto == 1 || (ctx->gss_flags & GSS_C_DCE_STYLE) || (ap_req_options & AP_OPTS_USE_SUBKEY)) cfx_generate_subkey = CFX_ACCEPTOR_SUBKEY; diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c index 16ab581a9b..a7f4f9e23d 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.c +++ b/src/lib/gssapi/krb5/gssapi_krb5.c @@ -386,11 +386,13 @@ krb5_gss_inquire_sec_context_by_oid (OM_uint32 *minor_status, /* * gss_inquire_cred_by_oid() methods */ +#if 0 static struct { gss_OID_desc oid; OM_uint32 (*func)(OM_uint32 *, const gss_cred_id_t, const gss_OID, gss_buffer_set_t *); } krb5_gss_inquire_cred_by_oid_ops[] = { }; +#endif static OM_uint32 krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status, @@ -425,6 +427,7 @@ krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status, cred = (krb5_gss_cred_id_t) cred_handle; +#if 0 for (i = 0; i < sizeof(krb5_gss_inquire_cred_by_oid_ops)/ sizeof(krb5_gss_inquire_cred_by_oid_ops[0]); i++) { if (g_OID_prefix_equal(desired_object, &krb5_gss_inquire_cred_by_oid_ops[i].oid)) { @@ -434,6 +437,7 @@ krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status, data_set); } } +#endif *minor_status = EINVAL; @@ -443,11 +447,13 @@ krb5_gss_inquire_cred_by_oid(OM_uint32 *minor_status, /* * gss_set_sec_context_option() methods */ +#if 0 static struct { gss_OID_desc oid; OM_uint32 (*func)(OM_uint32 *, gss_ctx_id_t *, const gss_OID, const gss_buffer_t); } krb5_gss_set_sec_context_option_ops[] = { }; +#endif static OM_uint32 krb5_gss_set_sec_context_option (OM_uint32 *minor_status, @@ -480,6 +486,7 @@ krb5_gss_set_sec_context_option (OM_uint32 *minor_status, return GSS_S_NO_CONTEXT; } +#if 0 for (i = 0; i < sizeof(krb5_gss_set_sec_context_option_ops)/ sizeof(krb5_gss_set_sec_context_option_ops[0]); i++) { if (g_OID_prefix_equal(desired_object, &krb5_gss_set_sec_context_option_ops[i].oid)) { @@ -489,6 +496,7 @@ krb5_gss_set_sec_context_option (OM_uint32 *minor_status, value); } } +#endif *minor_status = EINVAL; @@ -661,8 +669,6 @@ static struct gss_config krb5_mechanism = { krb5_gss_wrap_size_limit, krb5_gss_export_name, NULL, /* store_cred */ - NULL, /* import_name_object */ - NULL, /* export_name_object */ krb5_gss_inquire_sec_context_by_oid, krb5_gss_inquire_cred_by_oid, krb5_gss_set_sec_context_option, diff --git a/src/lib/gssapi/krb5/k5sealv3.c b/src/lib/gssapi/krb5/k5sealv3.c index 71e832e15b..b12284fb19 100644 --- a/src/lib/gssapi/krb5/k5sealv3.c +++ b/src/lib/gssapi/krb5/k5sealv3.c @@ -320,8 +320,8 @@ gss_krb5int_unseal_token_v3(krb5_context *contextptr, krb5_keyblock *key; krb5_cksumtype cksumtype; - assert(ctx->big_endian == 0); - assert(ctx->proto == 1); + if (ctx->big_endian != 0) + goto defective; if (qop_state) *qop_state = GSS_C_QOP_DEFAULT; diff --git a/src/lib/gssapi/krb5/k5sealv3iov.c b/src/lib/gssapi/krb5/k5sealv3iov.c index 41e6132cd9..e39665febe 100644 --- a/src/lib/gssapi/krb5/k5sealv3iov.c +++ b/src/lib/gssapi/krb5/k5sealv3iov.c @@ -297,8 +297,8 @@ gss_krb5int_unseal_v3_iov(krb5_context context, krb5_cksumtype cksumtype; int conf_flag = 0; - assert(ctx->big_endian == 0); - assert(ctx->proto == 1); + if (ctx->big_endian != 0) + return GSS_S_DEFECTIVE_TOKEN; if (qop_state != NULL) *qop_state = GSS_C_QOP_DEFAULT; diff --git a/src/lib/gssapi/krb5/k5unseal.c b/src/lib/gssapi/krb5/k5unseal.c index 4b70fd02ad..a94ac9ef05 100644 --- a/src/lib/gssapi/krb5/k5unseal.c +++ b/src/lib/gssapi/krb5/k5unseal.c @@ -494,6 +494,7 @@ kg_unseal(minor_status, context_handle, input_token_buffer, unsigned int bodysize; int err; int toktype2; + int vfyflags = 0; OM_uint32 ret; /* validate the context handle */ @@ -515,26 +516,49 @@ kg_unseal(minor_status, context_handle, input_token_buffer, ptr = (unsigned char *) input_token_buffer->value; - toktype2 = kg_map_toktype(ctx->proto, toktype); err = g_verify_token_header(ctx->mech_used, - &bodysize, &ptr, toktype2, + &bodysize, &ptr, -1, input_token_buffer->length, - !ctx->proto); + vfyflags); if (err) { *minor_status = err; return GSS_S_DEFECTIVE_TOKEN; } - if (ctx->proto == 0) - ret = kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize, - message_buffer, conf_state, qop_state, - toktype); - else + if (bodysize < 2) { + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + return GSS_S_DEFECTIVE_TOKEN; + } + + toktype2 = load_16_be(ptr); + + ptr += 2; + bodysize -= 2; + + switch (toktype2) { + case KG2_TOK_MIC_MSG: + case KG2_TOK_WRAP_MSG: + case KG2_TOK_DEL_CTX: ret = gss_krb5int_unseal_token_v3(&ctx->k5_context, minor_status, ctx, ptr, bodysize, message_buffer, conf_state, qop_state, toktype); + break; + case KG_TOK_MIC_MSG: + case KG_TOK_WRAP_MSG: + case KG_TOK_DEL_CTX: + ret = kg_unseal_v1(ctx->k5_context, minor_status, ctx, ptr, bodysize, + message_buffer, conf_state, qop_state, + toktype); + break; + default: + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + ret = GSS_S_DEFECTIVE_TOKEN; + break; + } + if (ret != 0) save_error_info (*minor_status, ctx->k5_context); + return ret; } diff --git a/src/lib/gssapi/krb5/k5unsealiov.c b/src/lib/gssapi/krb5/k5unsealiov.c index c72e2db39c..a9d4c9effb 100644 --- a/src/lib/gssapi/krb5/k5unsealiov.c +++ b/src/lib/gssapi/krb5/k5unsealiov.c @@ -172,7 +172,7 @@ kg_unseal_v1_iov(krb5_context context, iov, iov_count); krb5_free_keyblock(context, enc_key); } else { - code = kg_decrypt_iov(context, ctx->proto, + code = kg_decrypt_iov(context, 0, ((ctx->gss_flags & GSS_C_DCE_STYLE) != 0), 0 /*EC*/, 0 /*RRC*/, ctx->enc, KG_USAGE_SEAL, NULL, @@ -325,8 +325,7 @@ kg_unseal_iov_token(OM_uint32 *minor_status, gss_qop_t *qop_state, gss_iov_buffer_desc *iov, int iov_count, - int toktype, - int toktype2) + int toktype) { krb5_error_code code; krb5_context context = ctx->k5_context; @@ -336,6 +335,7 @@ kg_unseal_iov_token(OM_uint32 *minor_status, gss_iov_buffer_t trailer; size_t input_length; unsigned int bodysize; + int toktype2; int vfyflags = 0; header = kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER); @@ -364,26 +364,46 @@ kg_unseal_iov_token(OM_uint32 *minor_status, input_length += trailer->buffer.length; } - if (ctx->proto == 0) - vfyflags |= G_VFY_TOKEN_HDR_WRAPPER_REQUIRED; if (ctx->gss_flags & GSS_C_DCE_STYLE) vfyflags |= G_VFY_TOKEN_HDR_IGNORE_SEQ_SIZE; code = g_verify_token_header(ctx->mech_used, - &bodysize, &ptr, toktype2, - input_length, vfyflags); + &bodysize, &ptr, -1, + input_length, 0); if (code != 0) { - *minor_status = code; + *minor_status = code; + return GSS_S_DEFECTIVE_TOKEN; + } + + if (bodysize < 2) { + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; return GSS_S_DEFECTIVE_TOKEN; } - if (ctx->proto == 0) + toktype2 = load_16_be(ptr); + + ptr += 2; + bodysize -= 2; + + switch (toktype2) { + case KG2_TOK_MIC_MSG: + case KG2_TOK_WRAP_MSG: + case KG2_TOK_DEL_CTX: + code = gss_krb5int_unseal_v3_iov(context, minor_status, ctx, iov, iov_count, + conf_state, qop_state, toktype); + break; + case KG_TOK_MIC_MSG: + case KG_TOK_WRAP_MSG: + case KG_TOK_DEL_CTX: code = kg_unseal_v1_iov(context, minor_status, ctx, iov, iov_count, (size_t)(ptr - (unsigned char *)header->buffer.value), conf_state, qop_state, toktype); - else - code = gss_krb5int_unseal_v3_iov(context, minor_status, ctx, iov, iov_count, - conf_state, qop_state, toktype); + break; + default: + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + code = GSS_S_DEFECTIVE_TOKEN; + break; + } if (code != 0) save_error_info(*minor_status, context); @@ -402,21 +422,19 @@ kg_unseal_stream_iov(OM_uint32 *minor_status, gss_qop_t *qop_state, gss_iov_buffer_desc *iov, int iov_count, - int toktype, - int toktype2) + int toktype) { unsigned char *ptr; unsigned int bodysize; OM_uint32 code = 0, major_status = GSS_S_FAILURE; krb5_context context = ctx->k5_context; - int conf_req_flag; + int conf_req_flag, toktype2; int i = 0, j; gss_iov_buffer_desc *tiov = NULL; gss_iov_buffer_t stream, data = NULL; gss_iov_buffer_t theader, tdata = NULL, tpadding, ttrailer; assert(toktype == KG_TOK_WRAP_MSG); - assert(toktype2 == KG_TOK_WRAP_MSG || toktype2 == KG2_TOK_WRAP_MSG); if (toktype != KG_TOK_WRAP_MSG || (ctx->gss_flags & GSS_C_DCE_STYLE)) { code = EINVAL; @@ -429,14 +447,23 @@ kg_unseal_stream_iov(OM_uint32 *minor_status, ptr = (unsigned char *)stream->buffer.value; code = g_verify_token_header(ctx->mech_used, - &bodysize, &ptr, toktype2, - stream->buffer.length, - ctx->proto ? 0 : G_VFY_TOKEN_HDR_WRAPPER_REQUIRED); + &bodysize, &ptr, -1, + stream->buffer.length, 0); if (code != 0) { major_status = GSS_S_DEFECTIVE_TOKEN; goto cleanup; } + if (bodysize < 2) { + *minor_status = (OM_uint32)G_BAD_TOK_HEADER; + return GSS_S_DEFECTIVE_TOKEN; + } + + toktype2 = load_16_be(ptr); + + ptr += 2; + bodysize -= 2; + tiov = (gss_iov_buffer_desc *)calloc((size_t)iov_count + 2, sizeof(gss_iov_buffer_desc)); if (tiov == NULL) { code = ENOMEM; @@ -489,7 +516,10 @@ kg_unseal_stream_iov(OM_uint32 *minor_status, ttrailer = &tiov[i++]; ttrailer->type = GSS_IOV_BUFFER_TYPE_TRAILER; - if (ctx->proto == 1) { + switch (toktype2) { + case KG2_TOK_MIC_MSG: + case KG2_TOK_WRAP_MSG: + case KG2_TOK_DEL_CTX: { size_t ec, rrc; krb5_enctype enctype = ctx->enc->enctype; unsigned int k5_headerlen = 0; @@ -525,7 +555,11 @@ kg_unseal_stream_iov(OM_uint32 *minor_status, ttrailer->buffer.length = ec + (conf_req_flag ? 16 : 0 /* E(Header) */) + k5_trailerlen; ttrailer->buffer.value = (unsigned char *)stream->buffer.value + stream->buffer.length - ttrailer->buffer.length; - } else { + break; + } + case KG_TOK_MIC_MSG: + case KG_TOK_WRAP_MSG: + case KG_TOK_DEL_CTX: theader->buffer.length += ctx->cksum_size + kg_confounder_size(context, ctx->enc); /* @@ -538,6 +572,13 @@ kg_unseal_stream_iov(OM_uint32 *minor_status, /* no TRAILER for pre-CFX */ ttrailer->buffer.length = 0; ttrailer->buffer.value = NULL; + + break; + default: + code = (OM_uint32)G_BAD_TOK_HEADER; + major_status = GSS_S_DEFECTIVE_TOKEN; + goto cleanup; + break; } /* IOV: -----------0-------------+---1---+--2--+----------------3--------------*/ @@ -573,7 +614,7 @@ kg_unseal_stream_iov(OM_uint32 *minor_status, assert(i <= iov_count + 2); major_status = kg_unseal_iov_token(&code, ctx, conf_state, qop_state, - tiov, i, toktype, toktype2); + tiov, i, toktype); if (major_status == GSS_S_COMPLETE) *data = *tdata; else if (tdata->type & GSS_IOV_BUFFER_FLAG_ALLOCATED) { @@ -603,7 +644,6 @@ kg_unseal_iov(OM_uint32 *minor_status, { krb5_gss_ctx_id_rec *ctx; OM_uint32 code; - int toktype2; if (!kg_validate_ctx_id(context_handle)) { *minor_status = (OM_uint32)G_VALIDATE_FAILED; @@ -616,14 +656,12 @@ kg_unseal_iov(OM_uint32 *minor_status, return GSS_S_NO_CONTEXT; } - toktype2 = kg_map_toktype(ctx->proto, toktype); - if (kg_locate_iov(iov, iov_count, GSS_IOV_BUFFER_TYPE_STREAM) != NULL) { code = kg_unseal_stream_iov(minor_status, ctx, conf_state, qop_state, - iov, iov_count, toktype, toktype2); + iov, iov_count, toktype); } else { code = kg_unseal_iov_token(minor_status, ctx, conf_state, qop_state, - iov, iov_count, toktype, toktype2); + iov, iov_count, toktype); } return code; diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c index d718ae0b18..e2f306e979 100644 --- a/src/lib/gssapi/krb5/util_crypt.c +++ b/src/lib/gssapi/krb5/util_crypt.c @@ -56,6 +56,34 @@ const char const kg_arcfour_l40[] = "fortybits"; +static krb5_error_code +kg_copy_keys(krb5_context context, + krb5_gss_ctx_id_rec *ctx, + krb5_keyblock *subkey) +{ + krb5_error_code code; + + if (ctx->enc != NULL) { + krb5_free_keyblock(context, ctx->enc); + ctx->enc = NULL; + } + + code = krb5_copy_keyblock(context, subkey, &ctx->enc); + if (code != 0) + return code; + + if (ctx->seq != NULL) { + krb5_free_keyblock(context, ctx->seq); + ctx->seq = NULL; + } + + code = krb5_copy_keyblock(context, subkey, &ctx->seq); + if (code != 0) + return code; + + return 0; +} + krb5_error_code kg_setup_keys(krb5_context context, krb5_gss_ctx_id_rec *ctx, @@ -72,23 +100,17 @@ kg_setup_keys(krb5_context context, *cksumtype = 0; ctx->proto = 0; - code = krb5int_accessor(&kaccess, KRB5INT_ACCESS_VERSION); - if (code != 0) - return code; - - if (ctx->enc != NULL) { - krb5_free_keyblock(context, ctx->enc); - ctx->enc = NULL; + if (ctx->enc == NULL) { + ctx->signalg = -1; + ctx->sealalg = -1; } - code = krb5_copy_keyblock(context, subkey, &ctx->enc); + + code = krb5int_accessor(&kaccess, KRB5INT_ACCESS_VERSION); if (code != 0) return code; - if (ctx->seq != NULL) { - krb5_free_keyblock(context, ctx->seq); - ctx->seq = NULL; - } - code = krb5_copy_keyblock(context, subkey, &ctx->seq); + code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, subkey->enctype, + cksumtype); if (code != 0) return code; @@ -96,6 +118,10 @@ kg_setup_keys(krb5_context context, case ENCTYPE_DES_CBC_MD5: case ENCTYPE_DES_CBC_MD4: case ENCTYPE_DES_CBC_CRC: + code = kg_copy_keys(context, ctx, subkey); + if (code != 0) + return code; + ctx->enc->enctype = ENCTYPE_DES_CBC_RAW; ctx->seq->enctype = ENCTYPE_DES_CBC_RAW; ctx->signalg = SGN_ALG_DES_MAC_MD5; @@ -107,6 +133,10 @@ kg_setup_keys(krb5_context context, ctx->enc->contents[i] ^= 0xF0; break; case ENCTYPE_DES3_CBC_SHA1: + code = kg_copy_keys(context, ctx, subkey); + if (code != 0) + return code; + ctx->enc->enctype = ENCTYPE_DES3_CBC_RAW; ctx->seq->enctype = ENCTYPE_DES3_CBC_RAW; ctx->signalg = SGN_ALG_HMAC_SHA1_DES3_KD; @@ -115,19 +145,17 @@ kg_setup_keys(krb5_context context, break; case ENCTYPE_ARCFOUR_HMAC: case ENCTYPE_ARCFOUR_HMAC_EXP: + code = kg_copy_keys(context, ctx, subkey); + if (code != 0) + return code; + ctx->signalg = SGN_ALG_HMAC_MD5; ctx->cksum_size = 8; ctx->sealalg = SEAL_ALG_MICROSOFT_RC4; break; default: - ctx->signalg = -1; - ctx->sealalg = -1; ctx->proto = 1; - - code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, subkey->enctype, - cksumtype); - if (code != 0) - return code; + break; } return 0; diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports index 524533843f..69f390e451 100644 --- a/src/lib/gssapi/libgssapi_krb5.exports +++ b/src/lib/gssapi/libgssapi_krb5.exports @@ -23,11 +23,9 @@ gss_display_name gss_display_status gss_duplicate_name gss_export_name -gss_export_name_object gss_export_sec_context gss_get_mic gss_import_name -gss_import_name_object gss_import_sec_context gss_indicate_mechs gss_init_sec_context diff --git a/src/lib/gssapi/mechglue/Makefile.in b/src/lib/gssapi/mechglue/Makefile.in index 13a750b230..927b3755ca 100644 --- a/src/lib/gssapi/mechglue/Makefile.in +++ b/src/lib/gssapi/mechglue/Makefile.in @@ -25,10 +25,8 @@ SRCS = \ $(srcdir)/g_dup_name.c \ $(srcdir)/g_exp_sec_context.c \ $(srcdir)/g_export_name.c \ - $(srcdir)/g_export_name_object.c \ $(srcdir)/g_glue.c \ $(srcdir)/g_imp_name.c \ - $(srcdir)/g_imp_name_object.c \ $(srcdir)/g_imp_sec_context.c \ $(srcdir)/g_init_sec_context.c \ $(srcdir)/g_initialize.c \ @@ -71,10 +69,8 @@ OBJS = \ $(OUTPRE)g_dup_name.$(OBJEXT) \ $(OUTPRE)g_exp_sec_context.$(OBJEXT) \ $(OUTPRE)g_export_name.$(OBJEXT) \ - $(OUTPRE)g_export_name_object.$(OBJEXT) \ $(OUTPRE)g_glue.$(OBJEXT) \ $(OUTPRE)g_imp_name.$(OBJEXT) \ - $(OUTPRE)g_imp_name_object.$(OBJEXT) \ $(OUTPRE)g_imp_sec_context.$(OBJEXT) \ $(OUTPRE)g_init_sec_context.$(OBJEXT) \ $(OUTPRE)g_initialize.$(OBJEXT) \ @@ -117,10 +113,8 @@ STLIBOBJS = \ g_dup_name.o \ g_exp_sec_context.o \ g_export_name.o \ - g_export_name_object.o \ g_glue.o \ g_imp_name.o \ - g_imp_name_object.o \ g_imp_sec_context.o \ g_init_sec_context.o \ g_initialize.o \ diff --git a/src/lib/gssapi/mechglue/deps b/src/lib/gssapi/mechglue/deps index f67f754d01..c54fae9f27 100644 --- a/src/lib/gssapi/mechglue/deps +++ b/src/lib/gssapi/mechglue/deps @@ -105,14 +105,6 @@ g_export_name.so g_export_name.po $(OUTPRE)g_export_name.$(OBJEXT): \ $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ ../generic/gssapi_err_generic.h g_export_name.c mechglue.h \ mglueP.h -g_export_name_object.so g_export_name_object.po $(OUTPRE)g_export_name_object.$(OBJEXT): \ - $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ - $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ - $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ - $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ - $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ - ../generic/gssapi_err_generic.h g_export_name_object.c \ - mechglue.h mglueP.h g_glue.so g_glue.po $(OUTPRE)g_glue.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/gssapi/gssapi.h $(BUILDTOP)/include/gssapi/gssapi_ext.h \ $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ @@ -128,14 +120,6 @@ g_imp_name.so g_imp_name.po $(OUTPRE)g_imp_name.$(OBJEXT): \ $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ ../generic/gssapi_err_generic.h g_imp_name.c mechglue.h \ mglueP.h -g_imp_name_object.so g_imp_name_object.po $(OUTPRE)g_imp_name_object.$(OBJEXT): \ - $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ - $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ - $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-platform.h \ - $(SRCTOP)/include/k5-thread.h $(srcdir)/../generic/gssapiP_generic.h \ - $(srcdir)/../generic/gssapi_ext.h $(srcdir)/../generic/gssapi_generic.h \ - ../generic/gssapi_err_generic.h g_imp_name_object.c \ - mechglue.h mglueP.h g_imp_sec_context.so g_imp_sec_context.po $(OUTPRE)g_imp_sec_context.$(OBJEXT): \ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/gssapi/gssapi.h \ $(BUILDTOP)/include/gssapi/gssapi_ext.h $(COM_ERR_DEPS) \ diff --git a/src/lib/gssapi/mechglue/g_export_name_object.c b/src/lib/gssapi/mechglue/g_export_name_object.c deleted file mode 100644 index 4005070438..0000000000 --- a/src/lib/gssapi/mechglue/g_export_name_object.c +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 1996,1997, by Sun Microsystems, Inc. - * All rights reserved. - */ - -/* #pragma ident "@(#)g_export_name.c 1.11 00/07/17 SMI" */ - -/* - * glue routine gss_export_name_object_object_object_object - * - * Will either call the mechanism defined gss_export_name, or if one is - * not defined will call a generic_gss_export_name routine. - */ - -#include -#ifdef HAVE_STDLIB_H -#include -#endif -#include -#include - -OM_uint32 KRB5_CALLCONV -gss_export_name_object(minor_status, - input_name, - desired_name_type, - output_name) -OM_uint32 * minor_status; -const gss_name_t input_name; -gss_OID desired_name_type; -void ** output_name; -{ - gss_union_name_t union_name; - gss_mechanism mech; - OM_uint32 major_status; - - if (minor_status != NULL) - *minor_status = 0; - - if (output_name != NULL) - *output_name = NULL; - - if (minor_status == NULL) - return GSS_S_CALL_INACCESSIBLE_WRITE; - - if (input_name == NULL) - return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; - - if (desired_name_type == GSS_C_NO_OID) - return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAMETYPE; - - if (output_name == NULL) - return GSS_S_CALL_INACCESSIBLE_WRITE; - - union_name = (gss_union_name_t)input_name; - - if (union_name->mech_type == GSS_C_NO_OID) - return GSS_S_NAME_NOT_MN; - - mech = gssint_get_mechanism(union_name->mech_type); - if (mech == NULL) - return GSS_S_BAD_MECH; - - if (mech->gss_export_name_object == NULL) - return GSS_S_UNAVAILABLE; - - major_status = mech->gss_export_name_object(minor_status, - input_name, - desired_name_type, - output_name); - if (major_status != GSS_S_COMPLETE) - map_error(minor_status, mech); - - return major_status; -} diff --git a/src/lib/gssapi/mechglue/g_imp_name_object.c b/src/lib/gssapi/mechglue/g_imp_name_object.c deleted file mode 100644 index 83f327bd70..0000000000 --- a/src/lib/gssapi/mechglue/g_imp_name_object.c +++ /dev/null @@ -1,124 +0,0 @@ -/* #pragma ident "@(#)g_imp_name.c 1.26 04/02/23 SMI" */ - -/* - * Copyright 1996 by Sun Microsystems, Inc. - * - * Permission to use, copy, modify, distribute, and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appears in all copies and - * that both that copyright notice and this permission notice appear in - * supporting documentation, and that the name of Sun Microsystems not be used - * in advertising or publicity pertaining to distribution of the software - * without specific, written prior permission. Sun Microsystems makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR - * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF - * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR - * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. - */ - -/* - * glue routine gss_import_name_object - * - */ - -#include "mglueP.h" -#include -#ifdef HAVE_STDLIB_H -#include -#endif -#include -#include - -static OM_uint32 -val_imp_name_object_args( - OM_uint32 *minor_status, - void *input_name, - gss_OID input_name_type, - gss_name_t *output_name) -{ - if (minor_status == NULL) - return GSS_S_CALL_INACCESSIBLE_WRITE; - - *minor_status = 0; - - if (output_name == NULL) - return GSS_S_CALL_INACCESSIBLE_WRITE; - - if (input_name_type == GSS_C_NO_OID) - return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAMETYPE; - - if (input_name == NULL) - return GSS_S_CALL_INACCESSIBLE_READ | GSS_S_BAD_NAME; - - return GSS_S_COMPLETE; -} - -OM_uint32 KRB5_CALLCONV -gss_import_name_object(minor_status, - input_name, - input_name_type, - output_name) -OM_uint32 * minor_status; -void * input_name; -gss_OID input_name_type; -gss_name_t * output_name; -{ - gss_union_name_t union_name = NULL; - gss_mechanism mech = NULL; - gss_name_t internal_name = GSS_C_NO_NAME; - OM_uint32 tmp, major_status = GSS_S_FAILURE; - gss_OID_set mechlist = GSS_C_NO_OID_SET; - size_t i; - - major_status = val_imp_name_object_args(minor_status, - input_name, - input_name_type, - output_name); - if (major_status != GSS_S_COMPLETE) - return major_status; - - major_status = gss_indicate_mechs(minor_status, &mechlist); - if (major_status != GSS_S_COMPLETE) - return major_status; - - major_status = GSS_S_BAD_NAMETYPE; - - for (i = 0; i < mechlist->count; i++) { - mech = gssint_get_mechanism(&mechlist->elements[i]); - if (mech == NULL || mech->gss_import_name_object == NULL) - continue; - - major_status = mech->gss_import_name_object(minor_status, - input_name, - input_name_type, - &internal_name); - if (major_status != GSS_S_BAD_NAMETYPE) - break; - } - - if (major_status == GSS_S_COMPLETE) { - assert(internal_name != GSS_C_NO_NAME); - - major_status = gssint_convert_name_to_union_name(minor_status, - mech, - internal_name, - &union_name); - if (major_status != GSS_S_COMPLETE) { - if (mech->gss_release_name != NULL) - mech->gss_release_name(&tmp, &internal_name); - } else - *output_name = (gss_name_t)union_name; - } else - map_error(minor_status, mech); - - generic_gss_release_oid_set(&tmp, &mechlist); - - return major_status; -} - diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c index e762341c5d..a6f0bbc8dd 100644 --- a/src/lib/gssapi/mechglue/g_initialize.c +++ b/src/lib/gssapi/mechglue/g_initialize.c @@ -750,8 +750,6 @@ build_dynamicMech(void *dl, const gss_OID mech_type) GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_wrap_size_limit); GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_export_name); GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_store_cred); - GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_import_name_object); - GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_export_name_object); GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_inquire_sec_context_by_oid); GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_inquire_cred_by_oid); GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_set_sec_context_option); diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h index 52195f2931..001636146e 100644 --- a/src/lib/gssapi/mechglue/mglueP.h +++ b/src/lib/gssapi/mechglue/mglueP.h @@ -370,21 +370,6 @@ typedef struct gss_config { gss_cred_usage_t * /* cred_usage_stored */ /* */); - OM_uint32 (*gss_import_name_object) - ( - OM_uint32 *, /* minor_status */ - void *, /* input_name */ - gss_OID, /* input_name_type */ - gss_name_t * /* output_name */ - /* */); - - OM_uint32 (*gss_export_name_object) - ( - OM_uint32 *, /* minor_status */ - gss_name_t, /* input_name */ - gss_OID, /* desired_name_type */ - void ** /* output_name */ - /* */); /* GGF extensions */ diff --git a/src/lib/gssapi/spnego/spnego_mech.c b/src/lib/gssapi/spnego/spnego_mech.c index 44aea26436..5321de0bef 100644 --- a/src/lib/gssapi/spnego/spnego_mech.c +++ b/src/lib/gssapi/spnego/spnego_mech.c @@ -247,8 +247,6 @@ static struct gss_config spnego_mechanism = spnego_gss_wrap_size_limit, /* gss_wrap_size_limit */ NULL, /* gss_export_name */ NULL, /* gss_store_cred */ - NULL, /* gss_import_name_object */ - NULL, /* gss_export_name_object */ spnego_gss_inquire_sec_context_by_oid, /* gss_inquire_sec_context_by_oid */ NULL, /* gss_inquire_cred_by_oid */ spnego_gss_set_sec_context_option, /* gss_set_sec_context_option */ diff --git a/src/lib/kadm5/clnt/client_init.c b/src/lib/kadm5/clnt/client_init.c index d5fe5b0f12..82bec3c4ef 100644 --- a/src/lib/kadm5/clnt/client_init.c +++ b/src/lib/kadm5/clnt/client_init.c @@ -541,8 +541,12 @@ kadm5_gic_iter(kadm5_server_handle_t handle, goto error; } - if (init_type != INIT_CREDS) + /* Credentials for kadmin don't need to be forwardable or proxiable. */ + if (init_type != INIT_CREDS) { krb5_get_init_creds_opt_init(&opt); + krb5_get_init_creds_opt_set_forwardable(&opt, 0); + krb5_get_init_creds_opt_set_proxiable(&opt, 0); + } if (init_type == INIT_PASS) { code = krb5_get_init_creds_password(ctx, &outcreds, client, pass, diff --git a/src/lib/kadm5/srv/svr_principal.c b/src/lib/kadm5/srv/svr_principal.c index 9833a2bb49..6528133db4 100644 --- a/src/lib/kadm5/srv/svr_principal.c +++ b/src/lib/kadm5/srv/svr_principal.c @@ -38,27 +38,26 @@ static int decrypt_key_data(krb5_context context, krb5_keyblock *mkey, int n_key_data, krb5_key_data *key_data, krb5_keyblock **keyblocks, int *n_keys); -static krb5_error_code +static krb5_error_code kadm5_copy_principal(krb5_context context, krb5_const_principal inprinc, krb5_principal *outprinc) { register krb5_principal tempprinc; register int i, nelems; - + tempprinc = (krb5_principal)krb5_db_alloc(context, NULL, sizeof(krb5_principal_data)); - + if (tempprinc == 0) return ENOMEM; - + memcpy(tempprinc, inprinc, sizeof(krb5_principal_data)); - + nelems = (int) krb5_princ_size(context, inprinc); tempprinc->data = krb5_db_alloc(context, NULL, nelems * sizeof(krb5_data)); - if (tempprinc->data == 0) { krb5_db_free(context, (char *)tempprinc); return ENOMEM; } - + for (i = 0; i < nelems; i++) { unsigned int len = krb5_princ_component(context, inprinc, i)->length; krb5_princ_component(context, tempprinc, i)->length = len; @@ -74,7 +73,7 @@ kadm5_copy_principal(krb5_context context, krb5_const_principal inprinc, krb5_pr memcpy(krb5_princ_component(context, tempprinc, i)->data, krb5_princ_component(context, inprinc, i)->data, len); } - + tempprinc->realm.data = krb5_db_alloc(context, NULL, tempprinc->realm.length = inprinc->realm.length); if (!tempprinc->realm.data && tempprinc->realm.length) { @@ -87,19 +86,19 @@ kadm5_copy_principal(krb5_context context, krb5_const_principal inprinc, krb5_pr if (tempprinc->realm.length) memcpy(tempprinc->realm.data, inprinc->realm.data, inprinc->realm.length); - + *outprinc = tempprinc; return 0; } - + static void kadm5_free_principal(krb5_context context, krb5_principal val) { register krb5_int32 i; - + if (!val) return; - + if (val->data) { i = krb5_princ_size(context, val); while(--i >= 0) @@ -119,7 +118,7 @@ kadm5_ret_t krb5_copy_key_data_contents(context, from, to) krb5_key_data *from, *to; { int i, idx; - + *to = *from; idx = (from->key_data_ver == 1 ? 1 : 2); @@ -170,7 +169,7 @@ static void cleanup_key_data(context, count, data) krb5_key_data * data; { int i, j; - + for (i = 0; i < count; i++) for (j = 0; j < data[i].key_data_ver; j++) if (data[i].key_data_length[j]) @@ -247,7 +246,7 @@ kadm5_create_principal_3(void *server_handle, if ((mask & KADM5_POLICY)) { if ((ret = kadm5_get_policy(handle->lhandle, entry->policy, &polent)) != KADM5_OK) { - if(ret == EINVAL) + if(ret == EINVAL) return KADM5_BAD_POLICY; else return ret; @@ -273,14 +272,14 @@ kadm5_create_principal_3(void *server_handle, kdb.magic = KRB5_KDB_MAGIC_NUMBER; kdb.len = KRB5_KDB_V1_BASE_LENGTH; /* gag me with a chainsaw */ - if ((mask & KADM5_ATTRIBUTES)) + if ((mask & KADM5_ATTRIBUTES)) kdb.attributes = entry->attributes; else kdb.attributes = handle->params.flags; if ((mask & KADM5_MAX_LIFE)) - kdb.max_life = entry->max_life; - else + kdb.max_life = entry->max_life; + else kdb.max_life = handle->params.max_life; if (mask & KADM5_MAX_RLIFE) @@ -302,7 +301,7 @@ kadm5_create_principal_3(void *server_handle, } if ((mask & KADM5_PW_EXPIRATION)) kdb.pw_expiration = entry->pw_expiration; - + kdb.last_success = 0; kdb.last_failed = 0; kdb.fail_auth_count = 0; @@ -437,7 +436,7 @@ kadm5_create_principal_3(void *server_handle, return KADM5_OK; } - + kadm5_ret_t kadm5_delete_principal(void *server_handle, krb5_principal principal) { @@ -622,7 +621,7 @@ kadm5_modify_principal(void *server_handle, KADM5_REF_COUNT))))) goto done; - if ((mask & KADM5_ATTRIBUTES)) + if ((mask & KADM5_ATTRIBUTES)) kdb.attributes = entry->attributes; if ((mask & KADM5_MAX_LIFE)) kdb.max_life = entry->max_life; @@ -634,7 +633,7 @@ kadm5_modify_principal(void *server_handle, kdb.max_renewable_life = entry->max_renewable_life; if (mask & KADM5_FAIL_AUTH_COUNT) kdb.fail_auth_count = entry->fail_auth_count; - + if((mask & KADM5_KVNO)) { for (i = 0; i < kdb.n_key_data; i++) kdb.key_data[i].key_data_kvno = entry->kvno; @@ -675,7 +674,7 @@ done: kdb_free_entry(handle, &kdb, &adb); return ret; } - + kadm5_ret_t kadm5_rename_principal(void *server_handle, krb5_principal source, krb5_principal target) @@ -778,7 +777,7 @@ kadm5_get_principal(void *server_handle, krb5_principal principal, if ((mask & KADM5_PRINCIPAL) && (ret = krb5_copy_principal(handle->context, kdb.princ, - &entry->principal))) { + &entry->principal))) { goto done; } @@ -800,12 +799,12 @@ kadm5_get_principal(void *server_handle, krb5_principal principal, /* values that must be checked separately against the mask */ if ((mask & KADM5_MOD_NAME) || (mask & KADM5_MOD_TIME)) { ret = krb5_dbe_lookup_mod_princ_data(handle->context, &kdb, - &(entry->mod_date), + &(entry->mod_date), &(entry->mod_name)); if (ret) { goto done; } - + if (! (mask & KADM5_MOD_TIME)) entry->mod_date = 0; if (! (mask & KADM5_MOD_NAME)) { @@ -821,7 +820,7 @@ kadm5_get_principal(void *server_handle, krb5_principal principal, for (entry->kvno = 0, i=0; i entry->kvno) entry->kvno = kdb.key_data[i].key_data_kvno; - + ret = krb5_dbe_lookup_mkvno(handle->context, &kdb, &entry->mkvno); if (ret) goto done; @@ -857,7 +856,7 @@ kadm5_get_principal(void *server_handle, krb5_principal principal, krb5_tl_data *tl, *tl2; entry->tl_data = NULL; - + tl = kdb.tl_data; while (tl) { if (tl->tl_data_type > 255) { @@ -869,7 +868,7 @@ kadm5_get_principal(void *server_handle, krb5_principal principal, entry->tl_data = tl2; entry->n_tl_data++; } - + tl = tl->tl_data_next; } } @@ -882,7 +881,7 @@ kadm5_get_principal(void *server_handle, krb5_principal principal, ret = ENOMEM; goto done; } - } else + } else entry->key_data = NULL; for (i = 0; i < entry->n_key_data; i++) @@ -907,7 +906,7 @@ kadm5_get_principal(void *server_handle, krb5_principal principal, ret = ENOMEM; goto done; } - + newv1->principal = entry->principal; newv1->princ_expire_time = entry->princ_expire_time; newv1->last_pwd_change = entry->last_pwd_change; @@ -987,15 +986,15 @@ check_pw_reuse(krb5_context context, &pw_hist_data[y].key_data[z], &histkey, NULL); if (ret) - return(ret); - + return(ret); + if ((newkey.length == histkey.length) && (newkey.enctype == histkey.enctype) && (memcmp(newkey.contents, histkey.contents, histkey.length) == 0)) { krb5_free_keyblock_contents(context, &histkey); krb5_free_keyblock_contents(context, &newkey); - + return(KADM5_PASS_REUSE); } krb5_free_keyblock_contents(context, &histkey); @@ -1034,7 +1033,7 @@ int create_history_entry(krb5_context context, krb5_keyblock *mkey, int n_key_da int i, ret; krb5_keyblock key; krb5_keysalt salt; - + hist->key_data = (krb5_key_data*)malloc(n_key_data*sizeof(krb5_key_data)); if (hist->key_data == NULL) return ENOMEM; @@ -1054,7 +1053,7 @@ int create_history_entry(krb5_context context, krb5_keyblock *mkey, int n_key_da &hist->key_data[i]); if (ret) return ret; - + krb5_free_keyblock_contents(context, &key); /* krb5_free_keysalt(context, &salt); */ } @@ -1127,7 +1126,7 @@ static kadm5_ret_t add_to_history(krb5_context context, } if (adb->old_keys == NULL) return(ENOMEM); - + memset(&adb->old_keys[nkeys], 0, sizeof(osa_pw_hist_ent)); nkeys = ++adb->old_key_len; /* @@ -1227,7 +1226,7 @@ kadm5_set_use_password_server (void) #ifdef USE_PASSWORD_SERVER /* - * kadm5_launch_task () runs a program (task_path) to synchronize the + * kadm5_launch_task () runs a program (task_path) to synchronize the * Apple password server with the Kerberos database. Password server * programs can receive arguments on the command line (task_argv) * and a block of data via stdin (data_buffer). @@ -1240,11 +1239,11 @@ kadm5_set_use_password_server (void) static kadm5_ret_t kadm5_launch_task (krb5_context context, const char *task_path, char * const task_argv[], - const char *buffer) + const char *buffer) { kadm5_ret_t ret; int data_pipe[2]; - + ret = pipe (data_pipe); if (ret) ret = errno; @@ -1257,20 +1256,20 @@ kadm5_launch_task (krb5_context context, close (data_pipe[1]); } else if (pid == 0) { /* The child: */ - + if (dup2 (data_pipe[0], STDIN_FILENO) == -1) _exit (1); close (data_pipe[0]); close (data_pipe[1]); - + execv (task_path, task_argv); - + _exit (1); /* Fail if execv fails */ } else { /* The parent: */ int status; - + ret = 0; close (data_pipe[0]); @@ -1355,7 +1354,7 @@ kadm5_chpass_principal_3(void *server_handle, kdb_free_entry(handle, &kdb, &adb); return(ret); } - + if ((adb.aux_attributes & KADM5_POLICY)) { if ((ret = kadm5_get_policy(handle->lhandle, adb.policy, &pol))) goto done; @@ -1388,7 +1387,7 @@ kadm5_chpass_principal_3(void *server_handle, ret = krb5_timeofday(handle->context, &now); if (ret) goto done; - + if ((adb.aux_attributes & KADM5_POLICY)) { /* the policy was loaded before */ @@ -1423,7 +1422,7 @@ kadm5_chpass_principal_3(void *server_handle, 1, &hist); if (ret) goto done; - + if (pol.pw_history_num > 1) { if (adb.admin_history_kvno != hist_kvno) { ret = KADM5_BAD_HIST_KEY; @@ -1470,10 +1469,10 @@ kadm5_chpass_principal_3(void *server_handle, ret = kadm5_launch_task (handle->context, path, argv, password); } - + if (pstring != NULL) free (pstring); - + if (ret) goto done; } @@ -1498,7 +1497,7 @@ done: krb5_db_free_principal(handle->context, &kdb, 1); if (have_pol && (ret2 = kadm5_free_policy_ent(handle->lhandle, &pol)) - && !ret) + && !ret) ret = ret2; return ret; @@ -1570,7 +1569,7 @@ kadm5_randkey_principal_3(void *server_handle, if ((adb.aux_attributes & KADM5_POLICY)) { if ((ret = kadm5_get_policy(handle->lhandle, adb.policy, - &pol)) != KADM5_OK) + &pol)) != KADM5_OK) goto done; have_pol = 1; @@ -1625,7 +1624,7 @@ kadm5_randkey_principal_3(void *server_handle, -1, -1, &key_data); if (ret) goto done; - + ret = decrypt_key_data(handle->context, act_mkey, 1, key_data, keyblocks, NULL); if (ret) @@ -1637,8 +1636,8 @@ kadm5_randkey_principal_3(void *server_handle, if (ret) goto done; } - } - + } + /* key data changed, let the database provider know */ kdb.mask = KADM5_KEY_DATA /* | KADM5_RANDKEY_USED */; @@ -1694,7 +1693,7 @@ kadm5_setv4key_principal(void *server_handle, if (keyblock->enctype != ENCTYPE_DES_CBC_CRC) return KADM5_SETV4KEY_INVAL_ENCTYPE; - + if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) return(ret); @@ -1704,7 +1703,7 @@ kadm5_setv4key_principal(void *server_handle, if (kdb.key_data != NULL) cleanup_key_data(handle->context, kdb.n_key_data, kdb.key_data); - + kdb.key_data = (krb5_key_data*)krb5_db_alloc(handle->context, NULL, sizeof(krb5_key_data)); if (kdb.key_data == NULL) return ENOMEM; @@ -1758,7 +1757,7 @@ kadm5_setv4key_principal(void *server_handle, if ((adb.aux_attributes & KADM5_POLICY)) { if ((ret = kadm5_get_policy(handle->lhandle, adb.policy, - &pol)) != KADM5_OK) + &pol)) != KADM5_OK) goto done; have_pol = 1; @@ -1795,7 +1794,7 @@ kadm5_setv4key_principal(void *server_handle, goto done; } #endif - + if (pol.pw_max_life) kdb.pw_expiration = now + pol.pw_max_life; else @@ -1897,7 +1896,7 @@ kadm5_setkey_principal_3(void *server_handle, if ((ret = kdb_get_entry(handle, principal, &kdb, &adb))) return(ret); - + for (kvno = 0, i=0; i kvno) kvno = kdb.key_data[i].key_data_kvno; @@ -1911,7 +1910,7 @@ kadm5_setkey_principal_3(void *server_handle, n_old_keys = 0; old_key_data = NULL; } - + kdb.key_data = (krb5_key_data*)krb5_db_alloc(handle->context, NULL, (n_keys+n_old_keys) *sizeof(krb5_key_data)); if (kdb.key_data == NULL) { @@ -1996,7 +1995,7 @@ kadm5_setkey_principal_3(void *server_handle, if ((adb.aux_attributes & KADM5_POLICY)) { if ((ret = kadm5_get_policy(handle->lhandle, adb.policy, - &pol)) != KADM5_OK) + &pol)) != KADM5_OK) goto done; have_pol = 1; @@ -2033,7 +2032,7 @@ kadm5_setkey_principal_3(void *server_handle, goto done; } #endif - + if (pol.pw_max_life) kdb.pw_expiration = now + pol.pw_max_life; else @@ -2136,7 +2135,7 @@ static int decrypt_key_data(krb5_context context, krb5_keyblock *mkey, for (i = 0; i < n_key_data; i++) { ret = krb5_dbekd_decrypt_key_data(context, mkey, - &key_data[i], + &key_data[i], &keys[i], NULL); if (ret) { for (; i >= 0; i--) { @@ -2237,4 +2236,3 @@ kadm5_ret_t kadm5_decrypt_key(void *server_handle, return KADM5_OK; } - diff --git a/src/lib/kadm5/unit-test/Makefile.in b/src/lib/kadm5/unit-test/Makefile.in index 8a3cad51cc..f7f7fd85fe 100644 --- a/src/lib/kadm5/unit-test/Makefile.in +++ b/src/lib/kadm5/unit-test/Makefile.in @@ -87,28 +87,28 @@ unit-test-server: unit-test-server-setup unit-test-server-body \ unit-test-server-cleanup test-randkey:: randkey-test - $(ENV_SETUP) ./randkey-test + $(ENV_SETUP) $(VALGRIND) ./randkey-test test-handle-server:: server-handle-test - $(ENV_SETUP) ./server-handle-test + $(ENV_SETUP) $(VALGRIND) ./server-handle-test test-handle-client:: client-handle-test - $(ENV_SETUP) ./client-handle-test + $(ENV_SETUP) $(VALGRIND) ./client-handle-test test-noauth: init-test - $(ENV_SETUP) ./init-test + $(ENV_SETUP) $(VALGRIND) ./init-test test-destroy: destroy-test - $(ENV_SETUP) ./destroy-test + $(ENV_SETUP) $(VALGRIND) ./destroy-test unit-test-client-setup:: - $(ENV_SETUP) $(START_SERVERS) + $(ENV_SETUP) $(VALGRIND) $(START_SERVERS) unit-test-client-cleanup:: $(ENV_SETUP) $(STOP_SERVERS) unit-test-server-setup:: - $(ENV_SETUP) $(START_SERVERS_LOCAL) + $(ENV_SETUP) $(VALGRIND) $(START_SERVERS_LOCAL) unit-test-server-cleanup:: $(ENV_SETUP) $(STOP_SERVERS_LOCAL) @@ -118,7 +118,8 @@ unit-test-client-body: site.exp test-noauth test-destroy test-handle-client KINIT=$(BUILDTOP)/clients/kinit/kinit \ KDESTROY=$(BUILDTOP)/clients/kdestroy/kdestroy \ KADMIN_LOCAL=$(BUILDTOP)/kadmin/cli/kadmin.local \ - PRIOCNTL_HACK=@PRIOCNTL_HACK@ $(RUNTESTFLAGS) + PRIOCNTL_HACK=@PRIOCNTL_HACK@ VALGRIND="$(VALGRIND)" \ + $(RUNTESTFLAGS) -mv api.log capi.log -mv api.sum capi.sum @@ -126,7 +127,8 @@ unit-test-server-body: site.exp test-handle-server lock-test $(ENV_SETUP) $(RUNTEST) --tool api RPC=0 API=$(SRVTCL) \ LOCKTEST=./lock-test \ KADMIN_LOCAL=$(BUILDTOP)/kadmin/cli/kadmin.local \ - PRIOCNTL_HACK=@PRIOCNTL_HACK@ $(RUNTESTFLAGS) + PRIOCNTL_HACK=@PRIOCNTL_HACK@ VALGRIND="$(VALGRIND)" \ + $(RUNTESTFLAGS) -mv api.log sapi.log -mv api.sum sapi.sum diff --git a/src/lib/kadm5/unit-test/config/unix.exp b/src/lib/kadm5/unit-test/config/unix.exp index a78515f915..3f36655470 100644 --- a/src/lib/kadm5/unit-test/config/unix.exp +++ b/src/lib/kadm5/unit-test/config/unix.exp @@ -14,6 +14,47 @@ if {[info exists exp_version_4]} { set wait_status_index 3 } +if { [string length $VALGRIND] } { + rename spawn valgrind_aux_spawn + proc spawn { args } { + global VALGRIND + upvar 1 spawn_id spawn_id + set newargs {} + set inflags 1 + set eatnext 0 + foreach arg $args { + if { $arg == "-ignore" \ + || $arg == "-open" \ + || $arg == "-leaveopen" } { + lappend newargs $arg + set eatnext 1 + continue + } + if [string match "-*" $arg] { + lappend newargs $arg + continue + } + if { $eatnext } { + set eatnext 0 + lappend newargs $arg + continue + } + if { $inflags } { + set inflags 0 + # Only run valgrind for local programs, not + # system ones. +#&&![string match "/bin/sh" $arg] sh is used to start kadmind! + if [string match "/" [string index $arg 0]]&&![string match "/bin/ls" $arg]&&![regexp {/kshd$} $arg] { + set newargs [concat $newargs $VALGRIND] + } + } + lappend newargs $arg + } + set pid [eval valgrind_aux_spawn $newargs] + return $pid + } +} + # Hack around Solaris 9 kernel race condition that causes last output # from a pty to get dropped. if { $PRIOCNTL_HACK } { diff --git a/src/lib/krb5/krb/auth_con.c b/src/lib/krb5/krb/auth_con.c index 7c1858553d..7af96403f2 100644 --- a/src/lib/krb5/krb/auth_con.c +++ b/src/lib/krb5/krb/auth_con.c @@ -556,3 +556,13 @@ chk_heimdal_seqnum(krb5_ui_4 exp_seq, krb5_ui_4 in_seq) else return 0; } + +krb5_error_code +krb5_auth_con_get_subkey_enctype(krb5_context context, + krb5_auth_context auth_context, + krb5_enctype *etype) +{ + *etype = auth_context->negotiated_etype; + return 0; +} + diff --git a/src/lib/krb5/krb/mk_cred.c b/src/lib/krb5/krb/mk_cred.c index 8611e14097..a63b07ac69 100644 --- a/src/lib/krb5/krb/mk_cred.c +++ b/src/lib/krb5/krb/mk_cred.c @@ -258,6 +258,7 @@ krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, goto error; replay.server = ""; /* XXX */ + replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { diff --git a/src/lib/krb5/krb/mk_priv.c b/src/lib/krb5/krb/mk_priv.c index 08cbee969a..2a56bd0971 100644 --- a/src/lib/krb5/krb/mk_priv.c +++ b/src/lib/krb5/krb/mk_priv.c @@ -214,6 +214,7 @@ krb5_mk_priv(krb5_context context, krb5_auth_context auth_context, } replay.server = ""; /* XXX */ + replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { diff --git a/src/lib/krb5/krb/mk_req_ext.c b/src/lib/krb5/krb/mk_req_ext.c index 4a9d03551f..0d24017ee7 100644 --- a/src/lib/krb5/krb/mk_req_ext.c +++ b/src/lib/krb5/krb/mk_req_ext.c @@ -343,23 +343,15 @@ make_etype_list(krb5_context context, for (etypes.length = 0; etypes.etypes[etypes.length] != ENCTYPE_NULL; etypes.length++) - ; - - /* - * RFC 4537: - * - * If the enctype of the ticket session key is included in the enctype - * list sent by the client, it SHOULD be the last on the list; - */ - for (i = 0; i < etypes.length; i++) { - if (etypes.etypes[i] == tkt_enctype) { - krb5_enctype etype; - - etype = etypes.etypes[etypes.length - 1]; - etypes.etypes[etypes.length - 1] = tkt_enctype; - etypes.etypes[i] = etype; + { + /* + * RFC 4537: + * + * If the enctype of the ticket session key is included in the enctype + * list sent by the client, it SHOULD be the last on the list; + */ + if (etypes.length && etypes.etypes[etypes.length - 1] == tkt_enctype) break; - } } code = encode_krb5_etype_list(&etypes, &enc_etype_list); diff --git a/src/lib/krb5/krb/mk_safe.c b/src/lib/krb5/krb/mk_safe.c index 0517f42750..01abfab961 100644 --- a/src/lib/krb5/krb/mk_safe.c +++ b/src/lib/krb5/krb/mk_safe.c @@ -239,6 +239,7 @@ krb5_mk_safe(krb5_context context, krb5_auth_context auth_context, } replay.server = ""; /* XXX */ + replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { diff --git a/src/lib/krb5/krb/pac.c b/src/lib/krb5/krb/pac.c index ca7bdce514..3cfc188c51 100644 --- a/src/lib/krb5/krb/pac.c +++ b/src/lib/krb5/krb/pac.c @@ -378,7 +378,7 @@ krb5_pac_parse(krb5_context context, } static krb5_error_code -k5_time_to_seconds_since_1970(krb5_ui_8 ntTime, krb5_timestamp *elapsedSeconds) +k5_time_to_seconds_since_1970(krb5_int64 ntTime, krb5_timestamp *elapsedSeconds) { krb5_ui_8 abstime; @@ -419,7 +419,7 @@ k5_pac_validate_client(krb5_context context, unsigned char *p; krb5_timestamp pac_authtime; krb5_ui_2 pac_princname_length; - krb5_ui_8 pac_nt_authtime; + krb5_int64 pac_nt_authtime; krb5_principal pac_principal; ret = k5_pac_locate_buffer(context, pac, PAC_CLIENT_INFO, &client_info); diff --git a/src/lib/krb5/krb/rd_cred.c b/src/lib/krb5/krb/rd_cred.c index 3c76506b2f..5e159ab802 100644 --- a/src/lib/krb5/krb/rd_cred.c +++ b/src/lib/krb5/krb/rd_cred.c @@ -210,6 +210,7 @@ krb5_rd_cred(krb5_context context, krb5_auth_context auth_context, goto error; replay.server = ""; /* XXX */ + replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { diff --git a/src/lib/krb5/krb/rd_priv.c b/src/lib/krb5/krb/rd_priv.c index 618726efe2..66b29b0fa3 100644 --- a/src/lib/krb5/krb/rd_priv.c +++ b/src/lib/krb5/krb/rd_priv.c @@ -235,6 +235,7 @@ krb5_rd_priv(krb5_context context, krb5_auth_context auth_context, goto error; replay.server = ""; /* XXX */ + replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { diff --git a/src/lib/krb5/krb/rd_rep.c b/src/lib/krb5/krb/rd_rep.c index 1e6e0e1e82..2d495ae8f4 100644 --- a/src/lib/krb5/krb/rd_rep.c +++ b/src/lib/krb5/krb/rd_rep.c @@ -151,7 +151,7 @@ krb5_rd_rep_dce(krb5_context context, krb5_auth_context auth_context, krb5_error_code retval; krb5_ap_rep * reply; krb5_data scratch; - krb5_ap_rep_enc_part *repl; + krb5_ap_rep_enc_part *repl = NULL; if (!krb5_is_ap_rep(inbuf)) return KRB5KRB_AP_ERR_MSG_TYPE; diff --git a/src/lib/krb5/krb/rd_req_dec.c b/src/lib/krb5/krb/rd_req_dec.c index bbf7ed6a72..618151100a 100644 --- a/src/lib/krb5/krb/rd_req_dec.c +++ b/src/lib/krb5/krb/rd_req_dec.c @@ -349,7 +349,13 @@ krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context, tktauthent.ticket = req->ticket; tktauthent.authenticator = (*auth_context)->authentp; if (!(retval = krb5_auth_to_rep(context, &tktauthent, &rep))) { - retval = krb5_rc_store(context, (*auth_context)->rcache, &rep); + retval = krb5_rc_hash_message(context, + &req->authenticator.ciphertext, + &rep.msghash); + if (!retval) { + retval = krb5_rc_store(context, (*auth_context)->rcache, &rep); + krb5_xfree(rep.msghash); + } krb5_xfree(rep.server); krb5_xfree(rep.client); } @@ -421,7 +427,6 @@ krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context, desired_etypes[desired_etypes_len++] = (*auth_context)->authentp->subkey->enctype; } desired_etypes[desired_etypes_len++] = req->ticket->enc_part2->session->enctype; - desired_etypes[desired_etypes_len++] = req->ticket->enc_part.enctype; desired_etypes[desired_etypes_len] = ENCTYPE_NULL; if (((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) == 0) { diff --git a/src/lib/krb5/krb/rd_safe.c b/src/lib/krb5/krb/rd_safe.c index 98d73733c3..d14d9d4287 100644 --- a/src/lib/krb5/krb/rd_safe.c +++ b/src/lib/krb5/krb/rd_safe.c @@ -241,6 +241,7 @@ krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, goto error; replay.server = ""; /* XXX */ + replay.msghash = NULL; replay.cusec = replaydata.usec; replay.ctime = replaydata.timestamp; if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { diff --git a/src/lib/krb5/krb/sendauth.c b/src/lib/krb5/krb/sendauth.c index 5b56343075..35684bebbe 100644 --- a/src/lib/krb5/krb/sendauth.c +++ b/src/lib/krb5/krb/sendauth.c @@ -1,7 +1,7 @@ /* * lib/krb5/krb/sendauth.c * - * Copyright 1991 by the Massachusetts Institute of Technology. + * Copyright 1991, 2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -38,14 +38,19 @@ static const char sendauth_version[] = "KRB5_SENDAUTH_V1.0"; krb5_error_code KRB5_CALLCONV -krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, 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 **error, krb5_ap_rep_enc_part **rep_result, krb5_creds **out_creds) +krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, + krb5_pointer fd, 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 **error, krb5_ap_rep_enc_part **rep_result, + krb5_creds **out_creds) { krb5_octet result; krb5_creds creds; krb5_creds * credsp = NULL; krb5_creds * credspout = NULL; krb5_error_code retval = 0; - krb5_data inbuf, outbuf; + krb5_data inbuf, outbuf[2]; int len; krb5_ccache use_ccache = 0; @@ -58,13 +63,11 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe * over the length of the application version strings followed * by the string itself. */ - outbuf.length = strlen(sendauth_version) + 1; - outbuf.data = (char *) sendauth_version; - if ((retval = krb5_write_message(context, fd, &outbuf))) - return(retval); - outbuf.length = strlen(appl_version) + 1; - outbuf.data = appl_version; - if ((retval = krb5_write_message(context, fd, &outbuf))) + outbuf[0].length = strlen(sendauth_version) + 1; + outbuf[0].data = (char *) sendauth_version; + outbuf[1].length = strlen(appl_version) + 1; + outbuf[1].data = appl_version; + if ((retval = krb5int_write_messages(context, fd, outbuf, 2))) return(retval); /* * Now, read back a byte: 0 means no error, 1 means bad sendauth @@ -154,15 +157,15 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe if ((retval = krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, credsp, - &outbuf))) + &outbuf[0]))) goto error_return; /* * First write the length of the AP_REQ message, then write * the message itself. */ - retval = krb5_write_message(context, fd, &outbuf); - free(outbuf.data); + retval = krb5_write_message(context, fd, &outbuf[0]); + free(outbuf[0].data); if (retval) goto error_return; diff --git a/src/lib/krb5/libkrb5.exports b/src/lib/krb5/libkrb5.exports index 30c198d1cf..803fac806c 100644 --- a/src/lib/krb5/libkrb5.exports +++ b/src/lib/krb5/libkrb5.exports @@ -401,6 +401,7 @@ krb5_rc_free_entry krb5_rc_get_lifespan krb5_rc_get_name krb5_rc_get_type +krb5_rc_hash_message krb5_rc_initialize krb5_rc_io_close krb5_rc_io_creat @@ -414,6 +415,7 @@ krb5_rc_io_sync krb5_rc_io_unmark krb5_rc_io_write krb5_rc_recover +krb5_rc_recover_or_initialize krb5_rc_register_type krb5_rc_resolve krb5_rc_resolve_full diff --git a/src/lib/krb5/os/accessor.c b/src/lib/krb5/os/accessor.c index cdbb598418..1bf171a6f3 100644 --- a/src/lib/krb5/os/accessor.c +++ b/src/lib/krb5/os/accessor.c @@ -53,6 +53,7 @@ krb5int_accessor(krb5int_access *internals, krb5_int32 version) #endif S (free_addrlist, krb5int_free_addrlist), S (krb5_hmac, krb5_hmac), + S (krb5_auth_con_get_subkey_enctype, krb5_auth_con_get_subkey_enctype), S (md5_hash_provider, &krb5int_hash_md5), S (arcfour_enc_provider, &krb5int_enc_arcfour), S (sendto_udp, &krb5int_sendto), diff --git a/src/lib/krb5/os/deps b/src/lib/krb5/os/deps index d86f8b25bd..d868ada25c 100644 --- a/src/lib/krb5/os/deps +++ b/src/lib/krb5/os/deps @@ -277,7 +277,7 @@ net_write.so net_write.po $(OUTPRE)net_write.$(OBJEXT): \ $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ - $(SRCTOP)/include/socket-utils.h net_write.c + $(SRCTOP)/include/socket-utils.h net_write.c os-proto.h osconfig.so osconfig.po $(OUTPRE)osconfig.$(OBJEXT): \ $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ @@ -429,7 +429,7 @@ write_msg.so write_msg.po $(OUTPRE)write_msg.$(OBJEXT): \ $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ - $(SRCTOP)/include/socket-utils.h write_msg.c + $(SRCTOP)/include/socket-utils.h os-proto.h write_msg.c t_an_to_ln.so t_an_to_ln.po $(OUTPRE)t_an_to_ln.$(OBJEXT): \ $(BUILDTOP)/include/krb5/krb5.h $(COM_ERR_DEPS) $(SRCTOP)/include/krb5.h \ t_an_to_ln.c diff --git a/src/lib/krb5/os/hst_realm.c b/src/lib/krb5/os/hst_realm.c index 36c0e48608..fda0dfde2c 100644 --- a/src/lib/krb5/os/hst_realm.c +++ b/src/lib/krb5/os/hst_realm.c @@ -1,7 +1,7 @@ /* * lib/krb5/os/hst_realm.c * - * Copyright 1990,1991,2002 by the Massachusetts Institute of Technology. + * Copyright 1990,1991,2002,2008 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -208,7 +208,9 @@ krb5_get_host_realm(krb5_context context, const char *host, char ***realmsp) printf("get_host_realm(host:%s) called\n",host); #endif - krb5int_clean_hostname(context, host, local_host, sizeof local_host); + retval = krb5int_clean_hostname(context, host, local_host, sizeof local_host); + if (retval) + return retval; /* Search for the best match for the host or domain. @@ -350,7 +352,9 @@ krb5_get_fallback_host_realm(krb5_context context, krb5_data *hdata, char ***rea printf("get_fallback_host_realm(host >%s<) called\n",host); #endif - krb5int_clean_hostname(context, host, local_host, sizeof local_host); + retval = krb5int_clean_hostname(context, host, local_host, sizeof local_host); + if (retval) + return retval; /* * Try looking up a _kerberos. TXT record in DNS. This diff --git a/src/lib/krb5/os/net_write.c b/src/lib/krb5/os/net_write.c index e4981543aa..35765fb387 100644 --- a/src/lib/krb5/os/net_write.c +++ b/src/lib/krb5/os/net_write.c @@ -1,7 +1,7 @@ /* * lib/krb5/os/net_write.c * - * Copyright 1987, 1988, 1990 by the Massachusetts Institute of Technology. + * Copyright 1987, 1988, 1990, 2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -26,6 +26,7 @@ */ #include "k5-int.h" +#include "os-proto.h" /* * krb5_net_write() writes "len" bytes from "buf" to the file @@ -37,25 +38,45 @@ */ int -krb5_net_write(krb5_context context, int fd, register const char *buf, int len) +krb5_net_write(krb5_context context, int fd, const char *buf, int len) { - int cc; - register int wrlen = len; - do { - cc = SOCKET_WRITE((SOCKET)fd, buf, wrlen); + sg_buf sg; + SG_SET(&sg, buf, len); + return krb5int_net_writev(context, fd, &sg, 1); +} + +int +krb5int_net_writev(krb5_context context, int fd, sg_buf *sgp, int nsg) +{ + int cc, len = 0; + SOCKET_WRITEV_TEMP tmp; + + while (nsg > 0) { + /* Skip any empty data blocks. */ + if (SG_LEN(sgp) == 0) { + sgp++, nsg--; + continue; + } + cc = SOCKET_WRITEV((SOCKET)fd, sgp, nsg, tmp); if (cc < 0) { if (SOCKET_ERRNO == SOCKET_EINTR) continue; - /* XXX this interface sucks! */ - errno = SOCKET_ERRNO; - - return(cc); + /* XXX this interface sucks! */ + errno = SOCKET_ERRNO; + return -1; } - else { - buf += cc; - wrlen -= cc; + len += cc; + while (cc > 0) { + if ((unsigned)cc < SG_LEN(sgp)) { + SG_ADVANCE(sgp, (unsigned)cc); + cc = 0; + } else { + cc -= SG_LEN(sgp); + sgp++, nsg--; + assert(nsg > 0 || cc == 0); + } } - } while (wrlen > 0); - return(len); + } + return len; } diff --git a/src/lib/krb5/os/os-proto.h b/src/lib/krb5/os/os-proto.h index 33acd0c466..bb2e00ec20 100644 --- a/src/lib/krb5/os/os-proto.h +++ b/src/lib/krb5/os/os-proto.h @@ -1,7 +1,7 @@ /* * lib/krb5/os/os-proto.h * - * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * Copyright 1990,1991,2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -62,6 +62,9 @@ int _krb5_use_dns_realm (krb5_context); int _krb5_use_dns_kdc (krb5_context); int _krb5_conf_boolean (const char *); +/* The io vector is *not* const here, unlike writev()! */ +int krb5int_net_writev (krb5_context, int, sg_buf *, int); + #include "k5-thread.h" extern k5_mutex_t krb5int_us_time_mutex; diff --git a/src/lib/krb5/os/write_msg.c b/src/lib/krb5/os/write_msg.c index d75a32796d..e6001e8c67 100644 --- a/src/lib/krb5/os/write_msg.c +++ b/src/lib/krb5/os/write_msg.c @@ -1,7 +1,7 @@ /* * lib/krb5/os/write_msg.c * - * Copyright 1991 by the Massachusetts Institute of Technology. + * Copyright 1991, 2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -29,19 +29,48 @@ #include "k5-int.h" #include +#include "os-proto.h" +/* Try to write a series of messages with as few write(v) system calls + as possible, to avoid Nagle/DelayedAck problems. Cheating here a + little -- I know the only cases we have at the moment will send one + or two messages in a call. Sending more will work, but not as + efficiently. */ krb5_error_code -krb5_write_message(krb5_context context, krb5_pointer fdp, krb5_data *outbuf) +krb5int_write_messages(krb5_context context, krb5_pointer fdp, krb5_data *outbuf, int nbufs) { - krb5_int32 len; - int fd = *( (int *) fdp); + int fd = *( (int *) fdp); + + while (nbufs) { + int nbufs1; + sg_buf sg[4]; + krb5_int32 len[2]; - len = htonl(outbuf->length); - if (krb5_net_write(context, fd, (char *)&len, 4) < 0) { - return(errno); + if (nbufs > 1) + nbufs1 = 2; + else + nbufs1 = 1; + len[0] = htonl(outbuf[0].length); + SG_SET(&sg[0], &len[0], 4); + SG_SET(&sg[1], outbuf[0].length ? outbuf[0].data : NULL, + outbuf[0].length); + if (nbufs1 == 2) { + len[1] = htonl(outbuf[1].length); + SG_SET(&sg[2], &len[1], 4); + SG_SET(&sg[3], outbuf[1].length ? outbuf[1].data : NULL, + outbuf[1].length); } - if (outbuf->length && (krb5_net_write(context, fd, outbuf->data, outbuf->length) < 0)) { - return(errno); + if (krb5int_net_writev(context, fd, sg, nbufs1 * 2) < 0) { + return errno; } - return(0); + outbuf += nbufs1; + nbufs -= nbufs1; + } + return(0); +} + +krb5_error_code +krb5_write_message(krb5_context context, krb5_pointer fdp, krb5_data *outbuf) +{ + return krb5int_write_messages(context, fdp, outbuf, 1); } diff --git a/src/lib/krb5/rcache/Makefile.in b/src/lib/krb5/rcache/Makefile.in index d4c1336234..abbcc32de6 100644 --- a/src/lib/krb5/rcache/Makefile.in +++ b/src/lib/krb5/rcache/Makefile.in @@ -2,6 +2,8 @@ thisconfigdir=../../.. myfulldir=lib/krb5/rcache mydir=lib/krb5/rcache BUILDTOP=$(REL)..$(S)..$(S).. +PROG_LIBPATH=-L$(TOPLIBD) +PROG_RPATH=$(KRB5_LIBDIR) DEFS= ##DOS##BUILDTOP = ..\..\.. @@ -36,12 +38,18 @@ SRCS= \ $(srcdir)/rc_none.c \ $(srcdir)/rc_conv.c \ $(srcdir)/ser_rc.c \ - $(srcdir)/rcfns.c + $(srcdir)/rcfns.c \ + $(srcdir)/t_replay.c ##DOS##LIBOBJS = $(OBJS) all-unix:: all-libobjs clean-unix:: clean-libobjs +T_REPLAY_OBJS= t_replay.o + +t_replay: $(T_REPLAY_OBJS) $(KRB5_BASE_DEPLIBS) + $(CC_LINK) -o t_replay $(T_REPLAY_OBJS) $(KRB5_BASE_LIBS) + @libobj_frag@ diff --git a/src/lib/krb5/rcache/deps b/src/lib/krb5/rcache/deps index b2f02ae6cb..e77adf1b5f 100644 --- a/src/lib/krb5/rcache/deps +++ b/src/lib/krb5/rcache/deps @@ -81,3 +81,13 @@ rcfns.so rcfns.po $(OUTPRE)rcfns.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(SRCTOP)/include/krb5/locate_plugin.h $(SRCTOP)/include/krb5/preauth_plugin.h \ $(SRCTOP)/include/port-sockets.h $(SRCTOP)/include/socket-utils.h \ rc-int.h rcfns.c +t_replay.so t_replay.po $(OUTPRE)t_replay.$(OBJEXT): \ + $(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \ + $(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \ + $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h $(SRCTOP)/include/k5-err.h \ + $(SRCTOP)/include/k5-gmt_mktime.h $(SRCTOP)/include/k5-int-pkinit.h \ + $(SRCTOP)/include/k5-int.h $(SRCTOP)/include/k5-platform.h \ + $(SRCTOP)/include/k5-plugin.h $(SRCTOP)/include/k5-thread.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h t_replay.c diff --git a/src/lib/krb5/rcache/rc_conv.c b/src/lib/krb5/rcache/rc_conv.c index 16ed9e7eb8..3370f45df0 100644 --- a/src/lib/krb5/rcache/rc_conv.c +++ b/src/lib/krb5/rcache/rc_conv.c @@ -36,3 +36,44 @@ krb5_auth_to_rep(krb5_context context, krb5_tkt_authent *auth, krb5_donot_replay } return 0; } + +/* + * Generate a printable hash value for a message for use in a replay + * record. It is not necessary for this hash function to be + * collision-proof (the only thing you can do with a second preimage + * is produce a false replay error) but it is necessary for the + * function to be consistent across implementations. We do an unkeyed + * MD5 hash of the message and convert it into uppercase hex + * representation. + */ +krb5_error_code +krb5_rc_hash_message(krb5_context context, const krb5_data *message, + char **out) +{ + krb5_error_code retval; + krb5_checksum cksum; + char *hash, *ptr; + unsigned int i; + + *out = NULL; + + /* Calculate the binary checksum. */ + retval = krb5_c_make_checksum(context, CKSUMTYPE_RSA_MD5, 0, 0, + message, &cksum); + if (retval) + return retval; + + /* Convert the checksum into printable form. */ + hash = malloc(cksum.length * 2 + 1); + if (!hash) { + krb5_free_checksum_contents(context, &cksum); + return KRB5_RC_MALLOC; + } + ptr = hash; + for (i = 0, ptr = hash; i < cksum.length; i++, ptr += 2) + snprintf(ptr, 3, "%02X", cksum.contents[i]); + *ptr = '\0'; + *out = hash; + krb5_free_checksum_contents(context, &cksum); + return 0; +} diff --git a/src/lib/krb5/rcache/rc_dfl.c b/src/lib/krb5/rcache/rc_dfl.c index aa0b3a5f98..44013dafc0 100644 --- a/src/lib/krb5/rcache/rc_dfl.c +++ b/src/lib/krb5/rcache/rc_dfl.c @@ -10,7 +10,6 @@ /* * An implementation for the default replay cache type. */ -#define FREE(x) ((void) free((char *) (x))) #include "rc_base.h" #include "rc_dfl.h" #include "rc_io.h" @@ -85,8 +84,12 @@ cmp(krb5_donot_replay *old, krb5_donot_replay *new1, krb5_deltat t) if ((old->cusec == new1->cusec) && /* most likely to distinguish */ (old->ctime == new1->ctime) && (strcmp(old->client, new1->client) == 0) && - (strcmp(old->server, new1->server) == 0)) /* always true */ - return CMP_REPLAY; + (strcmp(old->server, new1->server) == 0)) { /* always true */ + /* If both records include message hashes, compare them as well. */ + if (old->msghash == NULL || new1->msghash == NULL || + strcmp(old->msghash, new1->msghash) == 0) + return CMP_REPLAY; + } return CMP_HOHUM; } @@ -128,7 +131,7 @@ struct authlist static int rc_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep, - krb5_int32 now) + krb5_int32 now, krb5_boolean fromfile) { struct dfl_data *t = (struct dfl_data *)id->data; unsigned int rephash; @@ -140,7 +143,20 @@ rc_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep, switch(cmp(&ta->rep, rep, t->lifespan)) { case CMP_REPLAY: - return CMP_REPLAY; + if (fromfile) { + /* + * This is an expected collision between a hash + * extension record and a normal-format record. Make + * sure the message hash is included in the stored + * record and carry on. + */ + if (!ta->rep.msghash && rep->msghash) { + if (!(ta->rep.msghash = strdup(rep->msghash))) + return CMP_MALLOC; + } + return CMP_HOHUM; + } else + return CMP_REPLAY; case CMP_HOHUM: if (alive(now, &ta->rep, t->lifespan) == CMP_EXPIRED) t->nummisses++; @@ -154,20 +170,26 @@ rc_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep, if (!(ta = (struct authlist *) malloc(sizeof(struct authlist)))) return CMP_MALLOC; + ta->rep = *rep; + ta->rep.client = ta->rep.server = ta->rep.msghash = NULL; + if (!(ta->rep.client = strdup(rep->client))) + goto error; + if (!(ta->rep.server = strdup(rep->server))) + goto error; + if (rep->msghash && !(ta->rep.msghash = strdup(rep->msghash))) + goto error; ta->na = t->a; t->a = ta; ta->nh = t->h[rephash]; t->h[rephash] = ta; - ta->rep = *rep; - if (!(ta->rep.client = strdup(rep->client))) { - FREE(ta); - return CMP_MALLOC; - } - if (!(ta->rep.server = strdup(rep->server))) { - FREE(ta->rep.client); - FREE(ta); - return CMP_MALLOC; - } - return CMP_HOHUM; +error: + if (ta->rep.client) + free(ta->rep.client); + if (ta->rep.server) + free(ta->rep.server); + if (ta->rep.msghash) + free(ta->rep.msghash); + free(ta); + return CMP_MALLOC; } char * KRB5_CALLCONV @@ -233,20 +255,22 @@ krb5_rc_dfl_close_no_free(krb5_context context, krb5_rcache id) struct dfl_data *t = (struct dfl_data *)id->data; struct authlist *q; - FREE(t->h); + free(t->h); if (t->name) - FREE(t->name); + free(t->name); while ((q = t->a)) { t->a = q->na; - FREE(q->rep.client); - FREE(q->rep.server); - FREE(q); + free(q->rep.client); + free(q->rep.server); + if (q->rep.msghash) + free(q->rep.msghash); + free(q); } #ifndef NOIOSTUFF (void) krb5_rc_io_close(context, &t->d); #endif - FREE(t); + free(t); return 0; } @@ -328,15 +352,111 @@ krb5_rc_free_entry(krb5_context context, krb5_donot_replay **rep) { if (rp->client) free(rp->client); - if (rp->server) free(rp->server); + if (rp->msghash) + free(rp->msghash); rp->client = NULL; rp->server = NULL; + rp->msghash = NULL; free(rp); } } +/* + * Parse a string in the format :, with the length + * represented in ASCII decimal. On parse failure, return 0 but set + * *result to NULL. + */ +static krb5_error_code +parse_counted_string(char **strptr, char **result) +{ + char *str = *strptr, *end; + unsigned long len; + + *result = NULL; + + /* Parse the length, expecting a ':' afterwards. */ + errno = 0; + len = strtoul(str, &end, 10); + if (errno != 0 || *end != ':' || len > strlen(end + 1)) + return 0; + + /* Allocate space for *result and copy the data. */ + *result = malloc(len + 1); + if (!*result) + return KRB5_RC_MALLOC; + memcpy(*result, end + 1, len); + (*result)[len] = '\0'; + *strptr = end + 1 + len; + return 0; +} + +/* + * Hash extension records have the format: + * client = + * server = HASH: : : + * Spaces in the client and server string are represented with + * with backslashes. Client and server lengths are represented in + * ASCII decimal (which is different from the 32-bit binary we use + * elsewhere in the replay cache). + * + * On parse failure, we leave the record unmodified. + */ +static krb5_error_code +check_hash_extension(krb5_donot_replay *rep) +{ + char *msghash = NULL, *client = NULL, *server = NULL, *str, *end; + krb5_error_code retval = 0; + + /* Check if this appears to match the hash extension format. */ + if (*rep->client) + return 0; + if (strncmp(rep->server, "HASH:", 5) != 0) + return 0; + + /* Parse out the message hash. */ + str = rep->server + 5; + end = strchr(str, ' '); + if (!end) + return 0; + msghash = malloc(end - str + 1); + if (!msghash) + return KRB5_RC_MALLOC; + memcpy(msghash, str, end - str); + msghash[end - str] = '\0'; + str = end + 1; + + /* Parse out the client and server. */ + retval = parse_counted_string(&str, &client); + if (retval != 0 || client == NULL) + goto error; + if (*str != ' ') + goto error; + str++; + retval = parse_counted_string(&str, &server); + if (retval != 0 || server == NULL) + goto error; + if (*str) + goto error; + + free(rep->client); + free(rep->server); + rep->client = client; + rep->server = server; + rep->msghash = msghash; + return 0; + +error: + if (msghash) + free(msghash); + if (client) + free(client); + if (server) + free(server); + return retval; +} + static krb5_error_code krb5_rc_io_fetch(krb5_context context, struct dfl_data *t, krb5_donot_replay *rep, int maxlen) @@ -345,7 +465,7 @@ krb5_rc_io_fetch(krb5_context context, struct dfl_data *t, unsigned int len; krb5_error_code retval; - rep->client = rep->server = 0; + rep->client = rep->server = rep->msghash = NULL; retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &len2, sizeof(len2)); @@ -395,6 +515,10 @@ krb5_rc_io_fetch(krb5_context context, struct dfl_data *t, if (retval) goto errout; + retval = check_hash_extension(rep); + if (retval) + goto errout; + return 0; errout: @@ -402,6 +526,8 @@ errout: krb5_xfree(rep->client); if (rep->server) krb5_xfree(rep->server); + if (rep->msghash) + krb5_xfree(rep->msghash); rep->client = rep->server = 0; return retval; } @@ -443,8 +569,7 @@ krb5_rc_dfl_recover_locked(krb5_context context, krb5_rcache id) retval = KRB5_RC_MALLOC; goto io_fail; } - rep->client = NULL; - rep->server = NULL; + rep->client = rep->server = rep->msghash = NULL; if (krb5_timeofday(context, &now)) now = 0; @@ -463,21 +588,22 @@ krb5_rc_dfl_recover_locked(krb5_context context, krb5_rcache id) else if (retval != 0) goto io_fail; - if (alive(now, rep, t->lifespan) != CMP_EXPIRED) { - if (rc_store(context, id, rep, now) == CMP_MALLOC) { + if (rc_store(context, id, rep, now, TRUE) == CMP_MALLOC) { retval = KRB5_RC_MALLOC; goto io_fail; } } else { expired_entries++; } + /* * free fields allocated by rc_io_fetch */ - FREE(rep->server); - FREE(rep->client); - rep->server = 0; - rep->client = 0; + free(rep->server); + free(rep->client); + if (rep->msghash) + free(rep->msghash); + rep->client = rep->server = rep->msghash = NULL; } retval = 0; krb5_rc_io_unmark(context, &t->d); @@ -529,27 +655,65 @@ static krb5_error_code krb5_rc_io_store(krb5_context context, struct dfl_data *t, krb5_donot_replay *rep) { - unsigned int clientlen, serverlen, len; - char *buf, *ptr; + size_t clientlen, serverlen; + unsigned int len; krb5_error_code ret; + struct k5buf buf; + char *ptr; + + clientlen = strlen(rep->client); + serverlen = strlen(rep->server); - clientlen = strlen(rep->client) + 1; - serverlen = strlen(rep->server) + 1; - len = sizeof(clientlen) + clientlen + sizeof(serverlen) + serverlen + - sizeof(rep->cusec) + sizeof(rep->ctime); - buf = malloc(len); - if (buf == 0) + if (rep->msghash) { + /* + * Write a hash extension record, to be followed by a record + * in regular format (without the message hash) for the + * benefit of old implementations. + */ + struct k5buf extbuf; + char *extstr; + + /* Format the extension value so we know its length. */ + krb5int_buf_init_dynamic(&extbuf); + krb5int_buf_add_fmt(&extbuf, "HASH:%s %lu:%s %lu:%s", rep->msghash, + (unsigned long) clientlen, rep->client, + (unsigned long) serverlen, rep->server); + extstr = krb5int_buf_data(&extbuf); + if (!extstr) + return KRB5_RC_MALLOC; + + /* + * Put the extension value into the server field of a + * regular-format record, with an empty client field. + */ + krb5int_buf_init_dynamic(&buf); + len = 1; + krb5int_buf_add_len(&buf, (char *) &len, sizeof(len)); + krb5int_buf_add_len(&buf, "", 1); + len = strlen(extstr) + 1; + krb5int_buf_add_len(&buf, (char *) &len, sizeof(len)); + krb5int_buf_add_len(&buf, extstr, len); + krb5int_buf_add_len(&buf, (char *) &rep->cusec, sizeof(rep->cusec)); + krb5int_buf_add_len(&buf, (char *) &rep->ctime, sizeof(rep->ctime)); + free(extstr); + } else /* No extension record needed. */ + krb5int_buf_init_dynamic(&buf); + + len = clientlen + 1; + krb5int_buf_add_len(&buf, (char *) &len, sizeof(len)); + krb5int_buf_add_len(&buf, rep->client, len); + len = serverlen + 1; + krb5int_buf_add_len(&buf, (char *) &len, sizeof(len)); + krb5int_buf_add_len(&buf, rep->server, len); + krb5int_buf_add_len(&buf, (char *) &rep->cusec, sizeof(rep->cusec)); + krb5int_buf_add_len(&buf, (char *) &rep->ctime, sizeof(rep->ctime)); + + ptr = krb5int_buf_data(&buf); + if (ptr == NULL) return KRB5_RC_MALLOC; - ptr = buf; - memcpy(ptr, &clientlen, sizeof(clientlen)); ptr += sizeof(clientlen); - memcpy(ptr, rep->client, clientlen); ptr += clientlen; - memcpy(ptr, &serverlen, sizeof(serverlen)); ptr += sizeof(serverlen); - memcpy(ptr, rep->server, serverlen); ptr += serverlen; - memcpy(ptr, &rep->cusec, sizeof(rep->cusec)); ptr += sizeof(rep->cusec); - memcpy(ptr, &rep->ctime, sizeof(rep->ctime)); ptr += sizeof(rep->ctime); - - ret = krb5_rc_io_write(context, &t->d, buf, len); - free(buf); + + ret = krb5_rc_io_write(context, &t->d, ptr, krb5int_buf_len(&buf)); + krb5int_free_buf(&buf); return ret; } @@ -570,7 +734,7 @@ krb5_rc_dfl_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep) if (ret) return ret; - switch(rc_store(context, id, rep, now)) { + switch(rc_store(context, id, rep, now, FALSE)) { case CMP_MALLOC: k5_mutex_unlock(&id->lock); return KRB5_RC_MALLOC; @@ -626,9 +790,11 @@ krb5_rc_dfl_expunge_locked(krb5_context context, krb5_rcache id) for (q = &t->a; *q; q = qt) { qt = &(*q)->na; if (alive(now, &(*q)->rep, t->lifespan) == CMP_EXPIRED) { - FREE((*q)->rep.client); - FREE((*q)->rep.server); - FREE(*q); + free((*q)->rep.client); + free((*q)->rep.server); + if ((*q)->rep.msghash) + free((*q)->rep.msghash); + free(*q); *q = *qt; /* why doesn't this feel right? */ } } diff --git a/src/lib/krb5/rcache/t_replay.c b/src/lib/krb5/rcache/t_replay.c new file mode 100644 index 0000000000..427991c2ef --- /dev/null +++ b/src/lib/krb5/rcache/t_replay.c @@ -0,0 +1,270 @@ +/* -*- mode: c; indent-tabs-mode: nil -*- */ +/* + * test/threads/t_replay.c + * + * Copyright (C) 2009 by the Massachusetts Institute of Technology. + * All rights reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * t_replay.c: Command-line interfaces to aid testing of replay cache + * + */ + +#include +#include +#include +#include + +#include "k5-int.h" + +static void usage(const char *progname) +{ + fprintf(stderr, "%s: Usage:\n", progname); + fprintf(stderr, " %s dump \n", progname); + fprintf(stderr, " %s store " + " \n", progname); + fprintf(stderr, " %s expunge \n", progname); + exit(1); +} + +static char *read_counted_string(FILE *fp) +{ + unsigned int len; + char *str; + + if (fread(&len, sizeof(len), 1, fp) != 1) + return NULL; + if (len == 0 || len > 10000) + return NULL; + if ((str = malloc(len)) == NULL) + return NULL; + if (fread(str, 1, len, fp) != len) + return NULL; + if (str[len - 1] != 0) + return NULL; + return str; +} + +static void dump_rcache(const char *filename) +{ + FILE *fp; + krb5_deltat lifespan; + krb5_int16 vno; + + fp = fopen(filename, "r"); + if (!fp) { + fprintf(stderr, "Can't open filename: %s\n", strerror(errno)); + return; + } + if (fread(&vno, sizeof(vno), 1, fp) != 1) + return; + if (fread(&lifespan, sizeof(lifespan), 1, fp) != 1) + return; + printf("Lifespan: %ld\n", (long) lifespan); + while (1) { + char *str; + krb5_int32 usec; + krb5_timestamp timestamp; + + printf("---\n"); + + if (!(str = read_counted_string(fp))) + return; + printf("Client: %s\n", str); + free(str); + + if (!(str = read_counted_string(fp))) + return; + printf("Server: %s\n", str); + free(str); + + if (fread(&usec, sizeof(usec), 1, fp) != 1) + return; + printf("Microseconds: %ld\n", (long) usec); + + if (fread(×tamp, sizeof(timestamp), 1, fp) != 1) + return; + printf("Timestamp: %ld\n", (long) timestamp); + } +} + +static void store(krb5_context ctx, char *rcspec, char *client, char *server, + char *msg, krb5_timestamp timestamp, krb5_int32 usec, + krb5_timestamp now_timestamp, krb5_int32 now_usec) +{ + krb5_rcache rc = NULL; + krb5_error_code retval = 0; + char *hash = NULL; + krb5_donot_replay rep; + + if (now_timestamp > 0) + krb5_set_debugging_time(ctx, now_timestamp, now_usec); + if ((retval = krb5_rc_resolve_full(ctx, &rc, rcspec))) + goto cleanup; + if ((retval = krb5_rc_recover_or_initialize(ctx, rc, ctx->clockskew))) + goto cleanup; + if (msg) { + krb5_data d; + + d.data = msg; + d.length = strlen(msg); + if ((retval = krb5_rc_hash_message(ctx, &d, &hash))) + goto cleanup; + } + rep.client = client; + rep.server = server; + rep.msghash = hash; + rep.cusec = usec; + rep.ctime = timestamp; + retval = krb5_rc_store(ctx, rc, &rep); +cleanup: + if (retval == KRB5KRB_AP_ERR_REPEAT) + printf("Replay\n"); + else if (!retval) + printf("Entry successfully stored\n"); + else + fprintf(stderr, "Failure: %s\n", krb5_get_error_message(ctx, retval)); + if (rc) + krb5_rc_close(ctx, rc); + if (hash) + free(hash); +} + +static void expunge(krb5_context ctx, char *rcspec, + krb5_timestamp now_timestamp, krb5_int32 now_usec) +{ + krb5_rcache rc = NULL; + krb5_error_code retval = 0; + + if (now_timestamp > 0) + krb5_set_debugging_time(ctx, now_timestamp, now_usec); + if ((retval = krb5_rc_resolve_full(ctx, &rc, rcspec))) + goto cleanup; + if ((retval = krb5_rc_recover_or_initialize(ctx, rc, ctx->clockskew))) + goto cleanup; + retval = krb5_rc_expunge(ctx, rc); +cleanup: + if (!retval) + printf("Cache successfully expunged\n"); + else + fprintf(stderr, "Failure: %s\n", krb5_get_error_message(ctx, retval)); + if (rc) + krb5_rc_close(ctx, rc); +} + +int main(int argc, char **argv) +{ + krb5_context ctx; + krb5_error_code retval; + const char *progname; + + retval = krb5_init_context(&ctx); + if (retval) { + fprintf(stderr, "krb5_init_context returned error %ld\n", + (long) retval); + exit(1); + } + progname = argv[0]; + + /* Parse arguments. */ + argc--; argv++; + while (argc) { + if (strcmp(*argv, "dump") == 0) { + /* + * Without going through the rcache interface, dump a + * named dfl-format rcache file to stdout. Takes a full + * pathname argument. + */ + const char *filename; + + argc--; argv++; + if (!argc) usage(progname); + filename = *argv; + dump_rcache(filename); + } else if (strcmp(*argv, "store") == 0) { + /* + * Using the rcache interface, store a replay record. + * Takes an rcache spec like dfl:host as the first + * argument. If non-empty, the "msg" argument will be + * hashed and provided in the replay record. The + * now-timestamp argument can be 0 to use the current + * time. + */ + char *rcspec, *client, *server, *msg; + krb5_timestamp timestamp, now_timestamp; + krb5_int32 usec, now_usec; + + argc--; argv++; + if (!argc) usage(progname); + rcspec = *argv; + argc--; argv++; + if (!argc) usage(progname); + client = *argv; + argc--; argv++; + if (!argc) usage(progname); + server = *argv; + argc--; argv++; + if (!argc) usage(progname); + msg = (**argv) ? *argv : NULL; + argc--; argv++; + if (!argc) usage(progname); + timestamp = (krb5_timestamp) atol(*argv); + argc--; argv++; + if (!argc) usage(progname); + usec = (krb5_int32) atol(*argv); + argc--; argv++; + if (!argc) usage(progname); + now_timestamp = (krb5_timestamp) atol(*argv); + argc--; argv++; + if (!argc) usage(progname); + now_usec = (krb5_int32) atol(*argv); + + store(ctx, rcspec, client, server, msg, timestamp, usec, + now_timestamp, now_usec); + } else if (strcmp(*argv, "expunge") == 0) { + /* + * Using the rcache interface, expunge a replay cache. + * The now-timestamp argument can be 0 to use the current + * time. + */ + char *rcspec; + krb5_timestamp now_timestamp; + krb5_int32 now_usec; + + argc--; argv++; + if (!argc) usage(progname); + rcspec = *argv; + argc--; argv++; + if (!argc) usage(progname); + now_timestamp = (krb5_timestamp) atol(*argv); + argc--; argv++; + if (!argc) usage(progname); + now_usec = (krb5_int32) atol(*argv); + expunge(ctx, rcspec, now_timestamp, now_usec); + } else + usage(progname); + argc--; argv++; + } + + krb5_free_context(ctx); + + return 0; +} diff --git a/src/lib/rpc/unit-test/Makefile.in b/src/lib/rpc/unit-test/Makefile.in index ee6f66e603..2b98dbba66 100644 --- a/src/lib/rpc/unit-test/Makefile.in +++ b/src/lib/rpc/unit-test/Makefile.in @@ -49,7 +49,7 @@ unit-test-ok:: unit-test-body PASS=@PASS@ unit-test-body: $(RM) krb5cc_rpc_test_* - $(ENV_SETUP) $(START_SERVERS) + $(ENV_SETUP) $(VALGRIND) $(START_SERVERS) RPC_TEST_SRVTAB=/tmp/rpc_test_v5srvtab.$$$$ ; export RPC_TEST_SRVTAB ; \ trap "echo Failed, cleaning up... ; rm -f $$RPC_TEST_SRVTAB ; $(ENV_SETUP) $(STOP_SERVERS) ; trap '' 0 ; exit 1" 0 1 2 3 14 15 ; \ if $(ENV_SETUP) \ diff --git a/src/lib/rpc/xdr.c b/src/lib/rpc/xdr.c index ec0d27717f..417786572c 100644 --- a/src/lib/rpc/xdr.c +++ b/src/lib/rpc/xdr.c @@ -54,6 +54,10 @@ static char sccsid[] = "@(#)xdr.c 1.35 87/08/12"; #define XDR_TRUE ((long) 1) #define LASTUNSIGNED ((u_int) 0-1) +#ifdef USE_VALGRIND +#include +#endif + /* * for unit alignment */ @@ -93,6 +97,9 @@ xdr_int(XDR *xdrs, int *ip) switch (xdrs->x_op) { case XDR_ENCODE: +#ifdef USE_VALGRIND + VALGRIND_CHECK_DEFINED(*ip); +#endif if (*ip > 0x7fffffffL || *ip < -0x7fffffffL - 1L) return (FALSE); @@ -126,6 +133,9 @@ xdr_u_int(XDR *xdrs, u_int *up) switch (xdrs->x_op) { case XDR_ENCODE: +#ifdef USE_VALGRIND + VALGRIND_CHECK_DEFINED(*up); +#endif if (*up > 0xffffffffUL) return (FALSE); @@ -158,6 +168,9 @@ xdr_long(XDR *xdrs, long *lp) switch (xdrs->x_op) { case XDR_ENCODE: +#ifdef USE_VALGRIND + VALGRIND_CHECK_DEFINED(*lp); +#endif if (*lp > 0x7fffffffL || *lp < -0x7fffffffL - 1L) return (FALSE); @@ -181,6 +194,9 @@ xdr_u_long(XDR *xdrs, u_long *ulp) switch (xdrs->x_op) { case XDR_ENCODE: +#ifdef USE_VALGRIND + VALGRIND_CHECK_DEFINED(*ulp); +#endif if (*ulp > 0xffffffffUL) return (FALSE); @@ -206,6 +222,9 @@ xdr_short(register XDR *xdrs, short *sp) switch (xdrs->x_op) { case XDR_ENCODE: +#ifdef USE_VALGRIND + VALGRIND_CHECK_DEFINED(*sp); +#endif l = (long) *sp; return (XDR_PUTLONG(xdrs, &l)); @@ -236,6 +255,9 @@ xdr_u_short(register XDR *xdrs, u_short *usp) switch (xdrs->x_op) { case XDR_ENCODE: +#ifdef USE_VALGRIND + VALGRIND_CHECK_DEFINED(*usp); +#endif l = (u_long) *usp; return (XDR_PUTLONG(xdrs, (long *) &l)); @@ -261,6 +283,15 @@ xdr_char(XDR *xdrs, char *cp) { int i; +#ifdef USE_VALGRIND + switch (xdrs->x_op) { + case XDR_ENCODE: + VALGRIND_CHECK_DEFINED(*cp); + break; + default: + break; + } +#endif i = (*cp); if (!xdr_int(xdrs, &i)) { return (FALSE); @@ -277,6 +308,15 @@ xdr_u_char(XDR *xdrs, u_char *cp) { u_int u; +#ifdef USE_VALGRIND + switch (xdrs->x_op) { + case XDR_ENCODE: + VALGRIND_CHECK_DEFINED(*cp); + break; + default: + break; + } +#endif u = (*cp); if (!xdr_u_int(xdrs, &u)) { return (FALSE); @@ -296,6 +336,9 @@ xdr_bool(register XDR *xdrs, bool_t *bp) switch (xdrs->x_op) { case XDR_ENCODE: +#ifdef USE_VALGRIND + VALGRIND_CHECK_DEFINED(*bp); +#endif lb = *bp ? XDR_TRUE : XDR_FALSE; return (XDR_PUTLONG(xdrs, &lb)); @@ -324,6 +367,15 @@ xdr_enum(XDR *xdrs, enum_t *ep) /* * enums are treated as ints */ +#ifdef USE_VALGRIND + switch (xdrs->x_op) { + case XDR_ENCODE: + VALGRIND_CHECK_DEFINED(*ep); + break; + default: + break; + } +#endif if (sizeof (enum sizecheck) == sizeof (long)) { return (xdr_long(xdrs, (long *)ep)); } else if (sizeof (enum sizecheck) == sizeof (int)) { @@ -373,6 +425,9 @@ xdr_opaque(XDR *xdrs, caddr_t cp, u_int cnt) } if (xdrs->x_op == XDR_ENCODE) { +#ifdef USE_VALGRIND + VALGRIND_CHECK_READABLE((volatile void *)cp, cnt); +#endif if (!XDR_PUTBYTES(xdrs, cp, cnt)) { return (FALSE); } @@ -463,6 +518,9 @@ xdr_int32(XDR *xdrs, int32_t *ip) switch (xdrs->x_op) { case XDR_ENCODE: +#ifdef USE_VALGRIND + VALGRIND_CHECK_DEFINED(*ip); +#endif l = *ip; return (xdr_long(xdrs, &l)); @@ -487,6 +545,9 @@ xdr_u_int32(XDR *xdrs, uint32_t *up) switch (xdrs->x_op) { case XDR_ENCODE: +#ifdef USE_VALGRIND + VALGRIND_CHECK_DEFINED(*up); +#endif ul = *up; return (xdr_u_long(xdrs, &ul)); diff --git a/src/tests/asn.1/Makefile.in b/src/tests/asn.1/Makefile.in index 8bfa46e601..25f9bdc367 100644 --- a/src/tests/asn.1/Makefile.in +++ b/src/tests/asn.1/Makefile.in @@ -8,7 +8,7 @@ LDAP=@LDAP@ RUN_SETUP = @KRB5_RUN_ENV@ -SRCS= $(srcdir)/krb5_encode_test.c $(srcdir)/krb5_encode_test.c \ +SRCS= $(srcdir)/krb5_encode_test.c $(srcdir)/krb5_decode_test.c \ $(srcdir)/ktest.c $(srcdir)/ktest_equal.c $(srcdir)/utility.c \ $(srcdir)/trval.c $(srcdir)/t_trval.c diff --git a/src/tests/asn.1/deps b/src/tests/asn.1/deps index 13fabb706b..4291da6ad8 100644 --- a/src/tests/asn.1/deps +++ b/src/tests/asn.1/deps @@ -13,6 +13,18 @@ $(OUTPRE)krb5_encode_test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/krb5/asn.1/asn1buf.h \ $(SRCTOP)/lib/krb5/asn.1/krbasn1.h debug.h krb5_encode_test.c \ ktest.h utility.h +$(OUTPRE)krb5_decode_test.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ + $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ + $(SRCTOP)/include/k5-err.h $(SRCTOP)/include/k5-gmt_mktime.h \ + $(SRCTOP)/include/k5-int-pkinit.h $(SRCTOP)/include/k5-int.h \ + $(SRCTOP)/include/k5-platform.h $(SRCTOP)/include/k5-plugin.h \ + $(SRCTOP)/include/k5-thread.h $(SRCTOP)/include/kdb.h \ + $(SRCTOP)/include/krb5.h $(SRCTOP)/include/krb5/locate_plugin.h \ + $(SRCTOP)/include/krb5/preauth_plugin.h $(SRCTOP)/include/port-sockets.h \ + $(SRCTOP)/include/socket-utils.h $(SRCTOP)/lib/krb5/asn.1/asn1buf.h \ + $(SRCTOP)/lib/krb5/asn.1/krbasn1.h debug.h krb5_decode_test.c \ + ktest.h ktest_equal.h utility.h $(OUTPRE)ktest.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \ $(BUILDTOP)/include/profile.h $(COM_ERR_DEPS) $(SRCTOP)/include/k5-buf.h \ diff --git a/src/tests/threads/t_rcache.c b/src/tests/threads/t_rcache.c index 06f4d3b194..3a654a4b32 100644 --- a/src/tests/threads/t_rcache.c +++ b/src/tests/threads/t_rcache.c @@ -62,6 +62,7 @@ static void try_one (struct tinfo *t) buf); r.server = buf; r.client = (t->my_cusec & 7) + "abcdefgh@ATHENA.MIT.EDU"; + r.msghash = NULL; if (t->now != t->my_ctime) { if (t->my_ctime != 0) { snprintf(buf2, sizeof(buf2), "%3d: %ld %5d\n", t->idx, -- 2.47.2