summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/Makefile.com12
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/aes/aes_s2k.c29
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/coll_proof_cksum.c7
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/des/afsstring2key.c11
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/dk/stringtokey.c37
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/enctype_compare.c7
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/hash_provider/hash_md5.c25
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/hash_provider/hash_sha1.c14
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/keyed_checksum_types.c11
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/keyed_cksum.c26
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/keyhash_provider/hmac_md5.c28
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/keyhash_provider/k5_md5des.c27
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/keylengths.c62
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/make_random_key.c19
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/md4/md4.c45
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/old/des_stringtokey.c38
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/old_api_glue.c286
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/pbkdf2.c12
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/random_to_key.c75
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/state.c11
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/string_to_enctype.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/string_to_key.c54
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/crypto/valid_enctype.c15
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/et/com_err.c120
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/et/internal.h3
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/et/krb5_err.c44
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/et/mit-sipb-copyright.h4
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/autoconf.h20
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/cache-addrinfo.h129
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/cm.h45
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/db.h3
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/fake-addrinfo.h1186
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/k5-int-pkinit.h271
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/krb5/adm_proto.h161
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/krb5/kdb.h11
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/locate_plugin.h61
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/osconf.h120
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/port-sockets.h9
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/preauth_plugin.h508
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/include/socket-utils.h10
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_decode.c5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_encode.c68
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_get.c4
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_decode.c479
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_decode.h47
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_encode.c444
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_encode.h69
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krb5_decode.c157
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krb5_encode.c129
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krbasn1.h6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc-int.h3
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_file.c291
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_memory.c193
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_retr.c153
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccbase.c188
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccdefault.c85
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccdefops.c17
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccfns.c52
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_file.c49
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_srvtab.c8
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktadd.c13
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktbase.c25
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktdefault.c11
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktfns.c21
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktfr_entry.c14
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktremove.c13
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/read_servi.c36
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/addr_order.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/addr_srch.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/appdefault.c27
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/auth_con.c270
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/bld_pr_ext.c5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/bld_princ.c13
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/chk_trans.c139
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/chpw.c59
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/conv_princ.c67
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_addrs.c7
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_creds.c15
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_data.c13
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_tick.c11
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/cp_key_cnt.c11
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/decode_kdc.c5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/encode_kdc.c5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/free_rtree.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/fwd_tgt.c97
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gc_frm_kdc.c53
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gc_via_tkt.c30
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gen_seqnum.c7
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gen_subkey.c8
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_creds.c54
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c593
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_keytab.c79
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_opt.c387
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_pwd.c260
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/int-proto.h12
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/kdc_rep_dc.c20
-rw-r--r--[-rwxr-xr-x]usr/src/lib/gss_mechs/mech_krb5/krb5/krb/krb5_libinit.c28
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_cred.c45
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_priv.c64
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_rep.c45
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_req.c19
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_req_ext.c91
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_safe.c70
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/pr_to_salt.c5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/preauth.c581
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/preauth2.c881
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_cred.c84
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_error.c4
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_priv.c53
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_rep.c50
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_req.c15
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_req_dec.c226
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_safe.c65
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/recvauth.c26
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/send_tgs.c43
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/sendauth.c55
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/set_realm.c7
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/srv_rcache.c16
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/str_conv.c21
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/tgtname.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/valid_times.c11
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/krb/vfy_increds.c36
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/accessor.c32
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/an_to_ln.c79
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/changepw.c524
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/def_realm.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnsglue.c37
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnsglue.h15
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnssrv.c2
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/free_hstrl.c3
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/free_krbhs.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/full_ipadr.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/gen_rname.c7
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/genaddrs.c22
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/gmt_mktime.c46
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/hostaddr.c11
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/hst_realm.c13
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/krbfileio.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/ktdefname.c20
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/kuserok.c82
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/localaddr.c3
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/locate_kdc.c554
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/lock_file.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/mk_faddr.c4
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/net_read.c5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/net_write.c5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/os-proto.h5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/osconfig.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/port2ip.c4
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/prompter.c5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/read_msg.c15
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/read_pwd.c10
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/sendto_kdc.c584
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/sn2princ.c247
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/unlck_file.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/ustime.c5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/os/write_msg.c7
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/posix/daemon.c11
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc-int.h5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_base.c113
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_base.h2
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_conv.c5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_file.c203
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_file.h16
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_io.c227
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_mem.h5
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_none.c50
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rcdef.c16
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/ser_rc.c12
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mapfile-vers16
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c422
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/acquire_cred.c64
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/add_cred.c8
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/disp_com_err_status.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/export_sec_context.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/gss_libinit.c7
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/indicate_mechs.c4
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/init_sec_context.c48
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/inq_cred.c9
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/inq_names.c7
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/krb5_gss_glue.c9
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/process_context_token.c6
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/rel_oid.c7
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/mech/set_ccache.c4
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/profile/prof_file.c74
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/profile/prof_get.c19
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/profile/prof_init.c98
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/profile/prof_int.h50
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/profile/prof_parse.c23
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/profile/prof_tree.c20
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/support/fake-addrinfo.c1313
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/support/init-addrinfo.c70
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/support/plugins.c29
-rw-r--r--usr/src/lib/gss_mechs/mech_krb5/support/threads.c293
-rw-r--r--usr/src/lib/krb5/kadm5/adb.h28
-rw-r--r--usr/src/lib/krb5/kadm5/admin.h14
-rw-r--r--usr/src/lib/krb5/kadm5/admin_xdr.h7
-rw-r--r--usr/src/lib/krb5/kadm5/alt_prof.c223
-rw-r--r--usr/src/lib/krb5/kadm5/chpass_util.c22
-rw-r--r--usr/src/lib/krb5/kadm5/clnt/changepw.c13
-rw-r--r--usr/src/lib/krb5/kadm5/clnt/chpw.c373
-rw-r--r--usr/src/lib/krb5/kadm5/clnt/client_init.c46
-rw-r--r--usr/src/lib/krb5/kadm5/clnt/client_internal.h9
-rw-r--r--usr/src/lib/krb5/kadm5/clnt/client_principal.c40
-rw-r--r--usr/src/lib/krb5/kadm5/clnt/client_rpc.c372
-rw-r--r--usr/src/lib/krb5/kadm5/clnt/clnt_policy.c21
-rw-r--r--usr/src/lib/krb5/kadm5/clnt/clnt_privs.c63
-rw-r--r--usr/src/lib/krb5/kadm5/clnt/logger.c256
-rw-r--r--usr/src/lib/krb5/kadm5/clnt/mapfile-vers45
-rw-r--r--usr/src/lib/krb5/kadm5/get_admhst.c113
-rw-r--r--usr/src/lib/krb5/kadm5/kadm_host_srv_names.c3
-rw-r--r--usr/src/lib/krb5/kadm5/kadm_rpc.h240
-rw-r--r--usr/src/lib/krb5/kadm5/kadm_rpc_xdr.c19
-rw-r--r--usr/src/lib/krb5/kadm5/misc_free.c8
-rw-r--r--usr/src/lib/krb5/kadm5/server_internal.h13
-rw-r--r--usr/src/lib/krb5/kadm5/srv/adb_xdr.c10
-rw-r--r--usr/src/lib/krb5/kadm5/srv/logger.c183
-rw-r--r--usr/src/lib/krb5/kadm5/srv/server_acl.c13
-rw-r--r--usr/src/lib/krb5/kadm5/srv/server_acl.h10
-rw-r--r--usr/src/lib/krb5/kadm5/srv/server_dict.c9
-rw-r--r--usr/src/lib/krb5/kadm5/srv/server_init.c11
-rw-r--r--usr/src/lib/krb5/kadm5/srv/server_kdb.c15
-rw-r--r--usr/src/lib/krb5/kadm5/srv/server_misc.c5
-rw-r--r--usr/src/lib/krb5/kadm5/srv/svr_chpass_util.c6
-rw-r--r--usr/src/lib/krb5/kadm5/srv/svr_iters.c7
-rw-r--r--usr/src/lib/krb5/kadm5/srv/svr_misc_free.c6
-rw-r--r--usr/src/lib/krb5/kadm5/srv/svr_policy.c15
-rw-r--r--usr/src/lib/krb5/kadm5/srv/svr_principal.c512
-rw-r--r--usr/src/lib/krb5/kadm5/srv/xdr_alloc.c116
-rw-r--r--usr/src/lib/krb5/kadm5/str_conv.c5
-rw-r--r--usr/src/lib/krb5/kdb/decrypt_key.c14
-rw-r--r--usr/src/lib/krb5/kdb/encrypt_key.c16
-rw-r--r--usr/src/lib/krb5/kdb/kdb_cpw.c133
-rw-r--r--usr/src/lib/krb5/kdb/keytab.c7
-rw-r--r--usr/src/lib/krb5/plugins/Makefile6
-rw-r--r--usr/src/lib/krb5/plugins/kdb/db2/adb_policy.c5
-rw-r--r--usr/src/lib/krb5/plugins/kdb/db2/db2_exp.c3
-rw-r--r--usr/src/lib/krb5/plugins/kdb/db2/kdb_db2.c4
-rw-r--r--usr/src/lib/krb5/plugins/kdb/db2/libdb2/hash/dbm.c7
-rw-r--r--usr/src/lib/krb5/plugins/kdb/db2/libdb2/hash/hash.c8
-rw-r--r--usr/src/lib/krb5/plugins/kdb/db2/libdb2/include/db-int.h5
-rw-r--r--usr/src/lib/krb5/plugins/kdb/db2/libdb2/include/db-ndbm.h5
-rw-r--r--usr/src/lib/krb5/plugins/kdb/db2/libdb2/mpool/mpool.c7
-rw-r--r--usr/src/lib/krb5/plugins/kdb/db2/pol_xdr.c4
-rw-r--r--usr/src/lib/krb5/plugins/kdb/ldap/Makefile.com4
-rw-r--r--usr/src/lib/krb5/plugins/kdb/ldap/ldap_exp.c5
-rw-r--r--usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c6
-rw-r--r--usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h9
-rw-r--r--usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c8
-rw-r--r--usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c8
-rw-r--r--usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c16
-rw-r--r--usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c4
-rw-r--r--usr/src/lib/krb5/plugins/preauth/Makefile49
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/Makefile55
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/Makefile.com94
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/i386/Makefile29
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/mapfile-vers37
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h364
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_accessor.c118
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_accessor.h83
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c1510
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto.h624
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c5982
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.h273
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c685
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_lib.c479
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_matching.c843
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_profile.c380
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_srv.c1426
-rw-r--r--usr/src/lib/krb5/plugins/preauth/pkinit/sparc/Makefile29
270 files changed, 26322 insertions, 6492 deletions
diff --git a/usr/src/lib/gss_mechs/mech_krb5/Makefile.com b/usr/src/lib/gss_mechs/mech_krb5/Makefile.com
index 29ab0eda14..0405ef777a 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/Makefile.com
+++ b/usr/src/lib/gss_mechs/mech_krb5/Makefile.com
@@ -22,7 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
#
#
@@ -49,7 +48,8 @@ CRYPTO = cksumtype_to_string.o \
keyed_checksum_types.o keyed_cksum.o \
make_random_key.o string_to_cksumtype.o \
string_to_enctype.o string_to_key.o valid_cksumtype.o \
- valid_enctype.o pkcs11slot.o state.o pbkdf2.o old_api_glue.o
+ valid_enctype.o pkcs11slot.o state.o pbkdf2.o old_api_glue.o \
+ keylengths.o random_to_key.o
CRYPTO_UTS= cksumtypes.o decrypt.o encrypt.o encrypt_length.o \
etypes.o nfold.o verify_checksum.o default_state.o \
@@ -136,7 +136,7 @@ K5_KRB= addr_comp.o addr_order.o addr_srch.o \
recvauth.o send_tgs.o sendauth.o srv_rcache.o str_conv.o \
tgtname.o valid_times.o walk_rtree.o appdefault.o deltat.o \
enc_helper.o gic_keytab.o gic_opt.o gic_pwd.o preauth2.o \
- vfy_increds.o vic_opt.o set_realm.o krb5_libinit.o chpw.o \
+ preauth.o vfy_increds.o vic_opt.o set_realm.o krb5_libinit.o chpw.o \
init_keyblock.o init_allocated_keyblock.o get_set_keyblock.o kerrs.o \
getuid.o
@@ -191,7 +191,7 @@ GSSAPI_UTS= gen_oids.o
PROFILE_OBJS= prof_tree.o prof_file.o prof_parse.o prof_init.o \
prof_set.o prof_get.o
-SUPPORT_OBJS= fake-addrinfo.o threads.o errors.o plugins.o
+SUPPORT_OBJS= fake-addrinfo.o init-addrinfo.o threads.o errors.o plugins.o
KWARN_OBJS= kwarnd_clnt_stubs.o kwarnd_clnt.o kwarnd_handle.o kwarnd_xdr.o
@@ -487,9 +487,9 @@ include $(REL_PATH)/../../Makefile.targ
OS_FLAGS = -DHAVE_LIBSOCKET -DHAVE_LIBNSL -DTIME_WITH_SYS_TIME \
-DHAVE_UNISTD_H -DHAVE_SYS_TIME_H -DHAVE_REGEX_H \
-DHAVE_REGEXP_H -DHAVE_RE_COMP -DHAVE_REGCOMP \
- -DPOSIX_TYPES -DNDBM -DAN_TO_LN_RULES \
+ -DPOSIX_TYPES -DNDBM \
-DHAVE_STDLIB_H -DHAVE_STDARG_H -DHAVE_SYS_TYPES_H \
- -DHAVE_NETINET_IN_H -DUSE_LOGIN_LIBRARY -DHAVE_SRAND48 \
+ -DHAVE_NETINET_IN_H -DHAVE_SRAND48 \
-DHAVE_SRAND -DHAVE_SRANDOM -DHAVE_GETPID \
-DHAVE_ERRNO -DHAVE_STRFTIME -DHAVE_STRPTIME -DHAVE_STRERROR \
-DHAVE_STAT -DSIZEOF_INT=4 -DPROVIDE_KERNEL_IMPORT \
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/aes/aes_s2k.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/aes/aes_s2k.c
index e0b7a2482b..9cb8c6ef36 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/aes/aes_s2k.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/aes/aes_s2k.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/crypto/aes/aes_s2k.c
@@ -34,31 +33,37 @@
* krb5int_aes_string_to_key
*/
-#include <k5-int.h>
-#include <dk.h>
+#include "k5-int.h"
+#include "dk.h"
+#include "aes_s2k.h"
#define DEFAULT_ITERATION_COUNT 4096 /* was 0xb000L in earlier drafts */
#define MAX_ITERATION_COUNT 0x1000000L
krb5_error_code
krb5int_aes_string_to_key(krb5_context context,
- const struct krb5_enc_provider *enc,
- const krb5_data *string,
- const krb5_data *salt,
- const krb5_data *params,
- krb5_keyblock *key)
+ const struct krb5_enc_provider *enc,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key)
{
unsigned long iter_count;
krb5_data out;
static const krb5_data usage = { KV5M_DATA, 8, "kerberos" };
krb5_error_code err;
+ /* Solaris Kerberos */
krb5_keyblock *inkey = NULL;
if (params) {
unsigned char *p = (unsigned char *) params->data;
if (params->length != 4)
return KRB5_ERR_BAD_S2K_PARAMS;
- iter_count = ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | (p[3]));
+ /* The first two need casts in case 'int' is 16 bits. */
+ iter_count = (((unsigned long)p[0] << 24)
+ | ((unsigned long)p[1] << 16)
+ | (p[2] << 8)
+ | (p[3]));
if (iter_count == 0) {
/*
iter_count = (1L << 16) << 16;
@@ -80,11 +85,12 @@ krb5int_aes_string_to_key(krb5_context context,
* Dense key space, no parity bits or anything, so take a shortcut
* and use the key contents buffer for the generated bytes.
*/
+ /* Solaris Kerberos */
if (key->length != 16 && key->length != 32)
return KRB5_CRYPTO_INTERNAL;
out.data = (char *) key->contents;
out.length = key->length;
-
+ /* Solaris Kerberos */
err = krb5int_pbkdf2_hmac_sha1 (context, &out, iter_count, key->enctype,
string, salt);
if (err) {
@@ -93,6 +99,7 @@ krb5int_aes_string_to_key(krb5_context context,
}
/*
+ * Solaris Kerberos:
* The derive key operation below will not work correctly
* if the input and output key pointers are to the same
* data. This is because the key object handle (PKCS#11)
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/coll_proof_cksum.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/coll_proof_cksum.c
index 141e3c9cd5..5c3ea48d34 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/coll_proof_cksum.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/coll_proof_cksum.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
*
@@ -25,8 +24,8 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <cksumtypes.h>
+#include "k5-int.h"
+#include "cksumtypes.h"
krb5_boolean KRB5_CALLCONV
krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype)
@@ -47,5 +46,5 @@ krb5_c_is_coll_proof_cksum(krb5_cksumtype ctype)
krb5_boolean KRB5_CALLCONV
is_coll_proof_cksum(krb5_cksumtype ctype)
{
- return krb5_c_is_coll_proof_cksum (ctype);
+ return krb5_c_is_coll_proof_cksum (ctype);
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/des/afsstring2key.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/des/afsstring2key.c
index c194ea6012..a0c7847296 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/des/afsstring2key.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/des/afsstring2key.c
@@ -3,7 +3,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/crypto/des/string2key.c
@@ -80,6 +79,7 @@ mit_afs_string_to_key (krb5_context context,
krb5_keyblock *keyblock, const krb5_data *data,
const krb5_data *salt)
{
+ /* Solaris Kerberos */
krb5_error_code retval = KRB5_PROG_ETYPE_NOSUPP;
/* EXPORT DELETE START */
/* totally different approach from MIT string2key. */
@@ -90,6 +90,7 @@ mit_afs_string_to_key (krb5_context context,
char *realm = salt->data;
unsigned int i, j;
krb5_octet *key = keyblock->contents;
+ /* Solaris Kerberos */
krb5_keyblock usekey;
if (data->length <= 8) {
@@ -133,7 +134,6 @@ mit_afs_string_to_key (krb5_context context,
mit_des_cblock ikey, tkey;
unsigned int pw_len = salt->length+data->length;
unsigned char *password = malloc(pw_len+1);
-
if (!password) return ENOMEM;
/* Some bound checks from the original code are elided here as
@@ -149,6 +149,7 @@ mit_afs_string_to_key (krb5_context context,
memcpy (tkey, ikey, sizeof(tkey));
mit_des_fixup_key_parity (tkey);
+ /* Solaris Kerberos */
usekey.enctype = ENCTYPE_DES_CBC_CRC;
usekey.contents = tkey;
usekey.length = 8;
@@ -157,7 +158,7 @@ mit_afs_string_to_key (krb5_context context,
memcpy (ikey, tkey, sizeof(ikey));
mit_des_fixup_key_parity (tkey);
-
+ /* Solaris Kerberos */
if (usekey.hKey != CK_INVALID_HANDLE) {
(void) C_DestroyObject(krb_ctx_hSession(context), usekey.hKey);
usekey.hKey = CK_INVALID_HANDLE;
@@ -170,6 +171,7 @@ mit_afs_string_to_key (krb5_context context,
/* now fix up key parity again */
mit_des_fixup_key_parity(key);
+ /* Solaris Kerberos */
if (usekey.hKey != CK_INVALID_HANDLE) {
(void) C_DestroyObject(krb_ctx_hSession(context), usekey.hKey);
usekey.hKey = CK_INVALID_HANDLE;
@@ -383,6 +385,7 @@ char *afs_crypt(const char *pw, const char *salt,
for(i=0; i<66; i++)
block[i] = 0;
+ /* Solaris Kerberos */
for(i=0; ((c= *pw) != NULL) && i<64; pw++){
for(j=0; j<7; j++, i++)
block[i] = (c>>(6-j)) & 01;
@@ -435,7 +438,7 @@ char *afs_crypt(const char *pw, const char *salt,
static void krb5_afs_crypt_setkey(char *key, char *E, char (*KS)[48])
{
- int i, j, k;
+ register int i, j, k;
int t;
/*
* The C and D arrays used to calculate the key schedule.
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/dk/stringtokey.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/dk/stringtokey.c
index 6f97457c40..d8cea570eb 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/dk/stringtokey.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/dk/stringtokey.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
@@ -31,19 +30,17 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <dk.h>
+#include "dk.h"
-static unsigned char kerberos[] = "kerberos";
+static const unsigned char kerberos[] = "kerberos";
#define kerberos_len (sizeof(kerberos)-1)
krb5_error_code
-krb5_dk_string_to_key(
- krb5_context context,
- krb5_const struct krb5_enc_provider *enc,
- krb5_const krb5_data *string,
- krb5_const krb5_data *salt,
- krb5_const krb5_data *parms,
- krb5_keyblock *key)
+krb5int_dk_string_to_key(
+ krb5_context context,
+ const struct krb5_enc_provider *enc,
+ const krb5_data *string, const krb5_data *salt,
+ const krb5_data *parms, krb5_keyblock *key)
{
krb5_error_code ret;
size_t keybytes, keylength, concatlen;
@@ -72,35 +69,37 @@ krb5_dk_string_to_key(
/* construct input string ( = string + salt), fold it, make_key it */
- (void) memcpy(concat, string->data, string->length);
+ memcpy(concat, string->data, string->length);
if (salt)
- (void) memcpy(concat+string->length, salt->data, salt->length);
+ memcpy(concat+string->length, salt->data, salt->length);
krb5_nfold(concatlen*8, concat, keybytes*8, foldstring);
indata.length = keybytes;
- indata.data = (char *)foldstring;
+ indata.data = (char *) foldstring;
+ /* Solaris Kerberos */
memset(&foldkey, 0, sizeof (krb5_keyblock));
foldkey.enctype = key->enctype;
foldkey.length = keylength;
foldkey.contents = foldkeydata;
+ /* Solaris Kerberos */
(*(enc->make_key))(context, &indata, &foldkey);
/* now derive the key from this one */
indata.length = kerberos_len;
- indata.data = (char *)kerberos;
-
+ indata.data = (char *) kerberos;
+ /* Solaris Kerberos */
if ((ret = krb5_derive_key(context, enc, &foldkey, key, &indata)))
(void) memset(key->contents, 0, key->length);
/* ret is set correctly by the prior call */
- (void) memset(concat, 0, concatlen);
- (void) memset(foldstring, 0, keybytes);
- (void) memset(foldkeydata, 0, keylength);
+ memset(concat, 0, concatlen);
+ memset(foldstring, 0, keybytes);
+ memset(foldkeydata, 0, keylength);
free(foldkeydata);
free(foldstring);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/enctype_compare.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/enctype_compare.c
index 157c5b43ca..a2add40d48 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/enctype_compare.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/enctype_compare.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
*
@@ -25,13 +24,13 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <etypes.h>
+#include "k5-int.h"
+#include "etypes.h"
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
krb5_c_enctype_compare(krb5_context context, krb5_enctype e1, krb5_enctype e2,
- krb5_boolean *similar)
+ krb5_boolean *similar)
{
int i, j;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/hash_provider/hash_md5.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/hash_provider/hash_md5.c
index c8d7b89ca8..74e5bcc167 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/hash_provider/hash_md5.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/hash_provider/hash_md5.c
@@ -1,20 +1,19 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
- *
+ *
* 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
@@ -25,20 +24,25 @@
* permission. FundsXpress makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
- *
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <hash_provider.h>
+#include "k5-int.h"
+/* Solaris Kerberos */
+#if 0
+#include "rsa-md5.h"
+#endif
+#include "hash_provider.h"
static krb5_error_code
k5_md5_hash(krb5_context context,
- unsigned int icount, krb5_const krb5_data *input,
- krb5_data *output)
+ unsigned int icount, krb5_const krb5_data *input,
+ krb5_data *output)
{
+ /* Solaris Kerberos */
CK_MECHANISM mechanism;
mechanism.mechanism = CKM_MD5;
@@ -48,6 +52,7 @@ k5_md5_hash(krb5_context context,
return(k5_ef_hash(context, &mechanism, icount, input, output));
}
+/* Solaris Kerberos */
const struct krb5_hash_provider krb5int_hash_md5 = {
MD5_CKSUM_LENGTH,
MD5_BLOCKSIZE,
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/hash_provider/hash_sha1.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/hash_provider/hash_sha1.c
index 71f441cbd4..c579c57c48 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/hash_provider/hash_sha1.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/hash_provider/hash_sha1.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
@@ -31,13 +30,14 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <hash_provider.h>
+#include "k5-int.h"
+#include "hash_provider.h"
+/* Solaris Kerberos */
static krb5_error_code
k5_sha1_hash(krb5_context context,
- unsigned int icount, krb5_const krb5_data *input,
- krb5_data *output)
+ unsigned int icount, krb5_const krb5_data *input,
+ krb5_data *output)
{
CK_MECHANISM mechanism;
@@ -50,7 +50,7 @@ k5_sha1_hash(krb5_context context,
return(0);
}
-const struct krb5_hash_provider krb5_hash_sha1 = {
+const struct krb5_hash_provider krb5int_hash_sha1 = {
SHS_DIGESTSIZE,
SHS_DATASIZE,
k5_sha1_hash
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/keyed_checksum_types.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/keyed_checksum_types.c
index f926c5b34a..f12b5865c6 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/keyed_checksum_types.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/keyed_checksum_types.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
*
@@ -25,12 +24,11 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <etypes.h>
-#include <cksumtypes.h>
+#include "k5-int.h"
+#include "etypes.h"
+#include "cksumtypes.h"
-static int etype_match(e1, e2)
- krb5_enctype e1, e2;
+static int etype_match(krb5_enctype e1, krb5_enctype e2)
{
int i1, i2;
@@ -48,7 +46,6 @@ static int etype_match(e1, e2)
}
/*ARGSUSED*/
-
krb5_error_code KRB5_CALLCONV
krb5_c_keyed_checksum_types(krb5_context context, krb5_enctype enctype,
unsigned int *count, krb5_cksumtype **cksumtypes)
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/keyed_cksum.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/keyed_cksum.c
index 8af42e9f4a..38529b2b4c 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/keyed_cksum.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/keyed_cksum.c
@@ -1,20 +1,14 @@
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
- *
+ *
* 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
@@ -25,14 +19,14 @@
* permission. FundsXpress makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
- *
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <cksumtypes.h>
+#include "k5-int.h"
+#include "cksumtypes.h"
krb5_boolean KRB5_CALLCONV
krb5_c_is_keyed_cksum(krb5_cksumtype ctype)
@@ -52,5 +46,11 @@ krb5_c_is_keyed_cksum(krb5_cksumtype ctype)
/* ick, but it's better than coredumping, which is what the
old code would have done */
- return(0);
+ return 0; /* error case */
+}
+
+krb5_boolean KRB5_CALLCONV
+is_keyed_cksum(krb5_cksumtype ctype)
+{
+ return krb5_c_is_keyed_cksum (ctype);
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/keyhash_provider/hmac_md5.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/keyhash_provider/hmac_md5.c
index 55450c15dd..96e692cec4 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/keyhash_provider/hmac_md5.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/keyhash_provider/hmac_md5.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/crypto/keyhash_provider/hmac_md5.c
@@ -37,10 +36,10 @@
* Implemented based on draft-brezak-win2k-krb-rc4-hmac-03
*/
-#include <k5-int.h>
-#include <arcfour.h>
-#include <hash_provider.h>
-#include <keyhash_provider.h>
+#include "k5-int.h"
+#include "keyhash_provider.h"
+#include "arcfour.h"
+#include "hash_provider.h"
static krb5_error_code
k5_hmac_md5_hash (krb5_context context,
@@ -64,14 +63,15 @@ k5_hmac_md5_hash (krb5_context context,
ks.length = key->length;
ds.data = malloc(ds.length);
if (ds.data == NULL)
- return (ENOMEM);
+ return ENOMEM;
ks.contents = (void *) ds.data;
ks_constant.data = "signaturekey";
ks_constant.length = strlen(ks_constant.data)+1; /* Including null*/
+ /* Solaris Kerberos */
ret = krb5_hmac(context, &krb5int_hash_md5, key, 1,
- &ks_constant, &ds);
+ &ks_constant, &ds);
if (ret)
goto cleanup;
@@ -81,6 +81,7 @@ k5_hmac_md5_hash (krb5_context context,
t[2] = (ms_usage >>16) & 0xff;
t[3] = (ms_usage>>24) & 0XFF;
+ /* Solaris Kerberos */
mechanism.mechanism = CKM_MD5;
mechanism.pParameter = NULL_PTR;
mechanism.ulParameterLen = 0;
@@ -126,10 +127,11 @@ cleanup:
return (ret);
}
-const struct krb5_keyhash_provider
-krb5int_keyhash_hmac_md5 = {
- 16,
- k5_hmac_md5_hash,
- NULL /*checksum again*/
+
+
+const struct krb5_keyhash_provider krb5int_keyhash_hmac_md5 = {
+ 16,
+ k5_hmac_md5_hash,
+ NULL /*checksum again*/
};
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/keyhash_provider/k5_md5des.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/keyhash_provider/k5_md5des.c
index e347b062d2..9fc19a8882 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/keyhash_provider/k5_md5des.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/keyhash_provider/k5_md5des.c
@@ -1,20 +1,19 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
- *
+ *
* 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
@@ -25,15 +24,15 @@
* permission. FundsXpress makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
- *
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <des_int.h>
-#include <keyhash_provider.h>
+#include "k5-int.h"
+#include "des_int.h"
+#include "keyhash_provider.h"
#define CONFLENGTH 8
@@ -47,11 +46,9 @@
/*ARGSUSED*/
static krb5_error_code
-k5_md5des_hash(krb5_context context,
- krb5_const krb5_keyblock *key,
- krb5_keyusage usage,
- krb5_const krb5_data *ivec,
- krb5_const krb5_data *input, krb5_data *output)
+k5_md5des_hash(krb5_context context, krb5_const krb5_keyblock *key,
+ krb5_keyusage usage, const krb5_data *ivec,
+ const krb5_data *input, krb5_data *output)
{
krb5_error_code ret = 0;
krb5_data data;
@@ -274,7 +271,7 @@ cleanup:
return(ret);
}
-const struct krb5_keyhash_provider krb5_keyhash_md5des = {
+const struct krb5_keyhash_provider krb5int_keyhash_md5des = {
CONFLENGTH + MD5_CKSUM_LENGTH,
k5_md5des_hash,
k5_md5des_verify
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/keylengths.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/keylengths.c
new file mode 100644
index 0000000000..419638e470
--- /dev/null
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/keylengths.c
@@ -0,0 +1,62 @@
+/*
+ * COPYRIGHT (c) 2006
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+
+#include "k5-int.h"
+#include "etypes.h"
+
+/*
+ * keybytes is the number of bytes required as input to make a key,
+ * keylength is the length of the final key in bytes
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_c_keylengths(krb5_context context, krb5_enctype enctype,
+ size_t *keybytes, size_t *keylength)
+{
+ int i;
+
+ if (keybytes == NULL && keylength == NULL)
+ return(EINVAL);
+
+ for (i=0; i<krb5_enctypes_length; i++) {
+ if (krb5_enctypes_list[i].etype == enctype)
+ break;
+ }
+
+ if (i == krb5_enctypes_length)
+ return(KRB5_BAD_ENCTYPE);
+
+ if (keybytes)
+ *keybytes = krb5_enctypes_list[i].enc->keybytes;
+ if (keylength)
+ *keylength = krb5_enctypes_list[i].enc->keylength;
+
+ return(0);
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/make_random_key.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/make_random_key.c
index 1cdcf655fe..e6c6c9d4a2 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/make_random_key.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/make_random_key.c
@@ -3,18 +3,17 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
- *
+ *
* 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
@@ -25,18 +24,18 @@
* permission. FundsXpress makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
- *
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <etypes.h>
+#include "k5-int.h"
+#include "etypes.h"
krb5_error_code KRB5_CALLCONV
krb5_c_make_random_key(krb5_context context, krb5_enctype enctype,
- krb5_keyblock *random_key)
+ krb5_keyblock *random_key)
{
int i;
krb5_error_code ret;
@@ -78,6 +77,8 @@ krb5_c_make_random_key(krb5_context context, krb5_enctype enctype,
random_key->magic = KV5M_KEYBLOCK;
random_key->enctype = enctype;
random_key->length = keylength;
+
+ /* Solaris Kerberos */
random_key->dk_list = NULL;
#ifdef _KERNEL
random_key->kef_key = NULL;
@@ -85,6 +86,7 @@ krb5_c_make_random_key(krb5_context context, krb5_enctype enctype,
random_key->hKey = CK_INVALID_HANDLE;
#endif
+ /* Solaris Kerberos */
ret = ((*(enc->make_key))(context, &random_data, random_key));
cleanup:
@@ -94,6 +96,7 @@ cleanup:
if (ret) {
memset(random_key->contents, 0, keylength);
free(random_key->contents);
+ /* Solaris Kerberos */
random_key->contents = NULL;
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/md4/md4.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/md4/md4.c
index adbd01186a..7541093805 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/md4/md4.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/md4/md4.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/crypto/md4/md4.c
@@ -42,8 +41,8 @@
**********************************************************************
*/
-#include <k5-int.h>
-#include <rsa-md4.h>
+#include "k5-int.h"
+#include "rsa-md4.h"
/* forward declaration */
static void Transform (krb5_ui_4 *, krb5_ui_4 *);
@@ -83,8 +82,7 @@ static const unsigned char PADDING[64] = {
(a) = ROTATE_LEFT ((a), (s));}
void
-krb5_MD4Init (mdContext)
-krb5_MD4_CTX *mdContext;
+krb5_MD4Init (krb5_MD4_CTX *mdContext)
{
mdContext->i[0] = mdContext->i[1] = (krb5_ui_4)0;
@@ -97,10 +95,7 @@ krb5_MD4_CTX *mdContext;
}
void
-krb5_MD4Update (mdContext, inBuf, inLen)
-krb5_MD4_CTX *mdContext;
-const unsigned char *inBuf;
-unsigned int inLen;
+krb5_MD4Update (krb5_MD4_CTX *mdContext, const unsigned char *inBuf, unsigned int inLen)
{
krb5_ui_4 in[16];
int mdi;
@@ -133,8 +128,7 @@ unsigned int inLen;
}
void
-krb5_MD4Final (mdContext)
-krb5_MD4_CTX *mdContext;
+krb5_MD4Final (krb5_MD4_CTX *mdContext)
{
krb5_ui_4 in[16];
int mdi;
@@ -175,12 +169,32 @@ krb5_MD4_CTX *mdContext;
/* Basic MD4 step. Transform buf based on in.
*/
-static void Transform (buf, in)
-krb5_ui_4 *buf;
-krb5_ui_4 *in;
+static void Transform (krb5_ui_4 *buf, krb5_ui_4 *in)
{
register krb5_ui_4 a = buf[0], b = buf[1], c = buf[2], d = buf[3];
+#ifdef CONFIG_SMALL
+ int i;
+#define ROTATE { krb5_ui_4 temp; temp = d, d = c, c = b, b = a, a = temp; }
+ for (i = 0; i < 16; i++) {
+ static const unsigned char round1consts[] = { 3, 7, 11, 19, };
+ FF (a, b, c, d, in[i], round1consts[i%4]); ROTATE;
+ }
+ for (i = 0; i < 16; i++) {
+ static const unsigned char round2indices[] = {
+ 0,4,8,12,1,5,9,13,2,6,10,14,3,7,11,15
+ };
+ static const unsigned char round2consts[] = { 3, 5, 9, 13 };
+ GG (a, b, c, d, in[round2indices[i]], round2consts[i%4]); ROTATE;
+ }
+ for (i = 0; i < 16; i++) {
+ static const unsigned char round3indices[] = {
+ 0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15
+ };
+ static const unsigned char round3consts[] = { 3, 9, 11, 15 };
+ HH (a, b, c, d, in[round3indices[i]], round3consts[i%4]); ROTATE;
+ }
+#else
/* Round 1 */
FF (a, b, c, d, in[ 0], 3);
FF (d, a, b, c, in[ 1], 7);
@@ -234,6 +248,7 @@ krb5_ui_4 *in;
HH (d, a, b, c, in[11], 9);
HH (c, d, a, b, in[ 7], 11);
HH (b, c, d, a, in[15], 15);
+#endif
buf[0] += a;
buf[1] += b;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/old/des_stringtokey.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/old/des_stringtokey.c
index 0b6fe20e5a..0100041540 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/old/des_stringtokey.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/old/des_stringtokey.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
*
@@ -25,39 +24,40 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <old.h>
+#include "k5-int.h"
+#include "old.h"
#include <des_int.h>
/* XXX */
extern krb5_error_code mit_des_string_to_key_int
(krb5_context context,
- krb5_keyblock * keyblock,
- const krb5_data * data,
- const krb5_data * salt);
+ krb5_keyblock * keyblock,
+ const krb5_data * data,
+ const krb5_data * salt);
/*ARGSUSED*/
krb5_error_code
-krb5_des_string_to_key(krb5_context context,
- const struct krb5_enc_provider *enc,
- const krb5_data *string,
- const krb5_data *salt,
- krb5_const krb5_data *parm,
- krb5_keyblock *key)
+krb5int_des_string_to_key(krb5_context context,
+ const struct krb5_enc_provider *enc,
+ const krb5_data *string,
+ const krb5_data *salt, const krb5_data *parm,
+ krb5_keyblock *key)
{
int type;
- if (parm) {
- if (parm->length != 1)
+ if (parm ) {
+ if (parm->length != 1)
return KRB5_ERR_BAD_S2K_PARAMS;
type = parm->data[0];
- } else type = 0;
-
+ }
+ else type = 0;
switch(type) {
case 0:
- return mit_des_string_to_key_int(context, key, string, salt);
+ /* Solaris Kerberos */
+ return(mit_des_string_to_key_int(context, key, string, salt));
case 1:
- return mit_afs_string_to_key(context, key, string, salt);
+ /* Solaris Kerberos */
+ return mit_afs_string_to_key(context, key, string, salt);
default:
- return KRB5_ERR_BAD_S2K_PARAMS;
+ return KRB5_ERR_BAD_S2K_PARAMS;
}
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/old_api_glue.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/old_api_glue.c
index 8b24096389..4bb7b0c6f5 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/old_api_glue.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/old_api_glue.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
@@ -39,6 +38,90 @@
*/
krb5_error_code KRB5_CALLCONV
+krb5_encrypt(krb5_context context, krb5_const_pointer inptr,
+ krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock,
+ krb5_pointer ivec)
+{
+ krb5_data inputd, ivecd;
+ krb5_enc_data outputd;
+ size_t blocksize, outlen;
+ krb5_error_code ret;
+
+ if (ivec) {
+ if ((ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize)))
+ return(ret);
+
+ ivecd.length = blocksize;
+ ivecd.data = ivec;
+ }
+
+ /* size is the length of the input cleartext data */
+ inputd.length = size;
+ inputd.data = (char*)inptr;
+
+ /* The size of the output buffer isn't part of the old api. Not too
+ safe. So, we assume here that it's big enough. */
+ if ((ret = krb5_c_encrypt_length(context, eblock->key->enctype, size,
+ &outlen)))
+ return(ret);
+
+ outputd.ciphertext.length = outlen;
+ outputd.ciphertext.data = outptr;
+
+ return(krb5_c_encrypt(context, eblock->key, 0, ivec?&ivecd:0,
+ &inputd, &outputd));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_decrypt(krb5_context context, krb5_const_pointer inptr,
+ krb5_pointer outptr, size_t size, krb5_encrypt_block *eblock,
+ krb5_pointer ivec)
+{
+ krb5_enc_data inputd;
+ krb5_data outputd, ivecd;
+ size_t blocksize;
+ krb5_error_code ret;
+
+ if (ivec) {
+ if ((ret = krb5_c_block_size(context, eblock->key->enctype, &blocksize)))
+ return(ret);
+
+ ivecd.length = blocksize;
+ ivecd.data = ivec;
+ }
+
+ /* size is the length of the input ciphertext data */
+ inputd.enctype = eblock->key->enctype;
+ inputd.ciphertext.length = size;
+ /* Solaris Kerberos */
+ inputd.ciphertext.data = (char*)inptr;
+
+ /* we don't really know how big this is, but the code tends to assume
+ that the output buffer size should be the same as the input
+ buffer size */
+ outputd.length = size;
+ outputd.data = outptr;
+
+ return(krb5_c_decrypt(context, eblock->key, 0, ivec?&ivecd:0,
+ &inputd, &outputd));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_process_key(krb5_context context, krb5_encrypt_block *eblock,
+ const krb5_keyblock *key)
+{
+ eblock->key = (krb5_keyblock *) key;
+
+ return(0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_finish_key(krb5_context context, krb5_encrypt_block *eblock)
+{
+ return(0);
+}
+
+krb5_error_code KRB5_CALLCONV
krb5_string_to_key(krb5_context context, const krb5_encrypt_block *eblock,
krb5_keyblock *keyblock, const krb5_data *data,
const krb5_data *salt)
@@ -48,8 +131,51 @@ krb5_string_to_key(krb5_context context, const krb5_encrypt_block *eblock,
}
krb5_error_code KRB5_CALLCONV
+krb5_init_random_key(krb5_context context, const krb5_encrypt_block *eblock,
+ const krb5_keyblock *keyblock, krb5_pointer *ptr)
+{
+ krb5_data data;
+
+ data.length = keyblock->length;
+ data.data = (char *) keyblock->contents;
+
+ return(krb5_c_random_seed(context, &data));
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_finish_random_key(krb5_context context, const krb5_encrypt_block *eblock,
+ krb5_pointer *ptr)
+{
+ return(0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_random_key(krb5_context context, const krb5_encrypt_block *eblock,
+ krb5_pointer ptr, krb5_keyblock **keyblock)
+{
+ krb5_keyblock *key;
+ krb5_error_code ret;
+
+ if ((key = (krb5_keyblock *) malloc(sizeof(krb5_keyblock))) == NULL)
+ return(ENOMEM);
+
+ if ((ret = krb5_c_make_random_key(context, eblock->crypto_entry, key)))
+ free(key);
+
+ *keyblock = key;
+
+ return(ret);
+}
+
+krb5_enctype KRB5_CALLCONV
+krb5_eblock_enctype(krb5_context context, const krb5_encrypt_block *eblock)
+{
+ return(eblock->crypto_entry);
+}
+
+krb5_error_code KRB5_CALLCONV
krb5_use_enctype(krb5_context context, krb5_encrypt_block *eblock,
- krb5_enctype enctype)
+ krb5_enctype enctype)
{
eblock->crypto_entry = enctype;
@@ -57,23 +183,161 @@ krb5_use_enctype(krb5_context context, krb5_encrypt_block *eblock,
}
size_t KRB5_CALLCONV
-krb5_checksum_size(krb5_context context, krb5_cksumtype ctype)
+krb5_encrypt_size(size_t length, krb5_enctype crypto)
{
- size_t ret;
+ size_t ret;
- if (krb5_c_checksum_length(context, ctype, &ret))
- return(-1); /* XXX */
+ if (krb5_c_encrypt_length(/* XXX */ 0, crypto, length, &ret))
+ return(-1); /* XXX */
- return(ret);
+ return(ret);
}
size_t KRB5_CALLCONV
-krb5_encrypt_size(size_t length, krb5_enctype crypto)
+krb5_checksum_size(krb5_context context, krb5_cksumtype ctype)
{
size_t ret;
- if (krb5_c_encrypt_length(/* XXX */ 0, crypto, length, &ret))
- return(-1); /* XXX */
+ if (krb5_c_checksum_length(context, ctype, &ret))
+ return(-1); /* XXX */
+
+ return(ret);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_calculate_checksum(krb5_context context, krb5_cksumtype ctype,
+ krb5_const_pointer in, size_t in_length,
+ krb5_const_pointer seed, size_t seed_length,
+ krb5_checksum *outcksum)
+{
+ krb5_data input;
+ krb5_keyblock key;
+ krb5_error_code ret;
+ krb5_checksum cksum;
+
+ /* Solaris Kerberos */
+ input.data = (char*)in;
+ input.length = in_length;
+
+ key.length = seed_length;
+ /* Solaris Kerberos */
+ key.contents = (unsigned char*)seed;
+
+ if ((ret = krb5_c_make_checksum(context, ctype, &key, 0, &input, &cksum)))
+ return(ret);
+
+ if (outcksum->length < cksum.length) {
+ memset(cksum.contents, 0, cksum.length);
+ free(cksum.contents);
+ return(KRB5_BAD_MSIZE);
+ }
+
+ outcksum->magic = cksum.magic;
+ outcksum->checksum_type = cksum.checksum_type;
+ memcpy(outcksum->contents, cksum.contents, cksum.length);
+ outcksum->length = cksum.length;
+
+ free(cksum.contents);
+
+ return(0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_verify_checksum(krb5_context context, krb5_cksumtype ctype,
+ const krb5_checksum *cksum, krb5_const_pointer in,
+ size_t in_length, krb5_const_pointer seed,
+ size_t seed_length)
+{
+ krb5_data input;
+ krb5_keyblock key;
+ krb5_error_code ret;
+ krb5_boolean valid;
+
+ /* Solaris Kerberos */
+ input.data = (char*)in;
+ input.length = in_length;
+
+ key.length = seed_length;
+ /* Solaris Kerberos */
+ key.contents = (unsigned char*)seed;
+
+ if ((ret = krb5_c_verify_checksum(context, &key, 0, &input, cksum,
+ &valid)))
+ return(ret);
+
+ if (!valid)
+ return(KRB5KRB_AP_ERR_BAD_INTEGRITY);
+
+ return(0);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_random_confounder(size_t size, krb5_pointer ptr)
+{
+ krb5_data random_data;
+
+ random_data.length = size;
+ random_data.data = ptr;
+
+ return(krb5_c_random_make_octets(/* XXX */ 0, &random_data));
+}
+
+krb5_error_code krb5_encrypt_data(krb5_context context, krb5_keyblock *key,
+ krb5_pointer ivec, krb5_data *data,
+ krb5_enc_data *enc_data)
+{
+ krb5_error_code ret;
+ size_t enclen, blocksize;
+ krb5_data ivecd;
+
+ if ((ret = krb5_c_encrypt_length(context, key->enctype, data->length,
+ &enclen)))
+ return(ret);
+
+ if (ivec) {
+ if ((ret = krb5_c_block_size(context, key->enctype, &blocksize)))
+ return(ret);
+
+ ivecd.length = blocksize;
+ ivecd.data = ivec;
+ }
+
+ enc_data->magic = KV5M_ENC_DATA;
+ enc_data->kvno = 0;
+ enc_data->enctype = key->enctype;
+ enc_data->ciphertext.length = enclen;
+ if ((enc_data->ciphertext.data = malloc(enclen)) == NULL)
+ return(ENOMEM);
+
+ if ((ret = krb5_c_encrypt(context, key, 0, ivec?&ivecd:0, data, enc_data)))
+ free(enc_data->ciphertext.data);
+
+ return(ret);
+}
+
+krb5_error_code krb5_decrypt_data(krb5_context context, krb5_keyblock *key,
+ krb5_pointer ivec, krb5_enc_data *enc_data,
+ krb5_data *data)
+{
+ krb5_error_code ret;
+ krb5_data ivecd;
+ size_t blocksize;
+
+ if (ivec) {
+ if ((ret = krb5_c_block_size(context, key->enctype, &blocksize)))
+ return(ret);
+
+ ivecd.length = blocksize;
+ ivecd.data = ivec;
+ }
+
+ data->length = enc_data->ciphertext.length;
+ if ((data->data = (char *) malloc(data->length)) == NULL)
+ return(ENOMEM);
+
+ if ((ret = krb5_c_decrypt(context, key, 0, ivec?&ivecd:0, enc_data, data)))
+ free(data->data);
+ /* Solaris Kerberos */
return(ret);
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/pbkdf2.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/pbkdf2.c
index 10d65add12..666b04d43c 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/pbkdf2.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/pbkdf2.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/crypto/pbkdf2.c
@@ -15,7 +14,7 @@
* 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
@@ -29,7 +28,7 @@
* 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.
- *
+ *
*
* Implementation of PBKDF2 from RFC 2898.
* Not currently used; likely to be used when we get around to AES support.
@@ -38,10 +37,11 @@
#ifndef _KERNEL
#include <ctype.h>
-#include <k5-int.h>
-#include <hash_provider.h>
+#include "k5-int.h"
+#include "hash_provider.h"
/*
+ * Solaris Kerberos:
* MIT code ripped out, use PBKDF2 algorithm from PKCS#11
* provider.
*/
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/random_to_key.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/random_to_key.c
new file mode 100644
index 0000000000..41f27f5e39
--- /dev/null
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/random_to_key.c
@@ -0,0 +1,75 @@
+/*
+ * COPYRIGHT (c) 2006
+ * The Regents of the University of Michigan
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+
+/*
+ * Create a key given random data. It is assumed that random_key has
+ * already been initialized and random_key->contents have been allocated
+ * with the correct length.
+ */
+#include "k5-int.h"
+#include "etypes.h"
+
+krb5_error_code KRB5_CALLCONV
+krb5_c_random_to_key(krb5_context context, krb5_enctype enctype,
+ krb5_data *random_data, krb5_keyblock *random_key)
+{
+ int i;
+ krb5_error_code ret;
+ const struct krb5_enc_provider *enc;
+
+ if (random_data == NULL || random_key == NULL)
+ return(EINVAL);
+
+ if (random_key->contents == NULL)
+ return(EINVAL);
+
+ for (i=0; i<krb5_enctypes_length; i++) {
+ if (krb5_enctypes_list[i].etype == enctype)
+ break;
+ }
+
+ if (i == krb5_enctypes_length)
+ return(KRB5_BAD_ENCTYPE);
+
+ enc = krb5_enctypes_list[i].enc;
+
+ if (random_key->length != enc->keylength)
+ return(KRB5_BAD_KEYSIZE);
+
+ /* Solaris Kerberos */
+ ret = ((*(enc->make_key))(context, random_data, random_key));
+
+ if (ret) {
+ memset(random_key->contents, 0, random_key->length);
+ }
+
+ return(ret);
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/state.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/state.c
index 42463870e3..4c655f58df 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/state.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/state.c
@@ -1,8 +1,7 @@
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/crypto/state.c
@@ -38,8 +37,8 @@
* krb5_c_init_state and krb5_c_free_state used by clients of the
* Kerberos crypto library.
*/
-#include <k5-int.h>
-#include <etypes.h>
+#include "k5-int.h"
+#include "etypes.h"
krb5_error_code KRB5_CALLCONV
krb5_c_init_state (krb5_context context, const krb5_keyblock *key,
@@ -55,6 +54,7 @@ krb5_c_init_state (krb5_context context, const krb5_keyblock *key,
if (i == krb5_enctypes_length)
return(KRB5_BAD_ENCTYPE);
+ /* Solaris Kerberos */
return (*(krb5_enctypes_list[i].enc->init_state))
(context, key, keyusage, new_state);
}
@@ -73,6 +73,7 @@ krb5_c_free_state (krb5_context context, const krb5_keyblock *key,
if (i == krb5_enctypes_length)
return(KRB5_BAD_ENCTYPE);
- return (*(krb5_enctypes_list[i].enc->free_state))
+ /* Solaris Kerberos */
+ return (*(krb5_enctypes_list[i].enc->free_state))
(context, state);
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/string_to_enctype.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/string_to_enctype.c
index 5a52832f7d..9d3245bf01 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/string_to_enctype.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/string_to_enctype.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
*
@@ -25,8 +24,9 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <etypes.h>
+#include "k5-int.h"
+#include "etypes.h"
+
krb5_error_code KRB5_CALLCONV
krb5_string_to_enctype(char *string, krb5_enctype *enctypep)
{
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/string_to_key.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/string_to_key.c
index eb182f1736..9554a43fa5 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/string_to_key.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/string_to_key.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
*
@@ -30,22 +29,22 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <etypes.h>
+#include "k5-int.h"
+#include "etypes.h"
krb5_error_code KRB5_CALLCONV
krb5_c_string_to_key_with_params(krb5_context context,
- krb5_enctype enctype,
- const krb5_data *string,
- const krb5_data *salt,
- const krb5_data *params,
- krb5_keyblock *key);
+ krb5_enctype enctype,
+ const krb5_data *string,
+ const krb5_data *salt,
+ const krb5_data *params,
+ krb5_keyblock *key);
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
krb5_c_string_to_key(krb5_context context, krb5_enctype enctype,
- const krb5_data *string, const krb5_data *salt,
- krb5_keyblock *key)
+ const krb5_data *string, const krb5_data *salt,
+ krb5_keyblock *key)
{
return krb5_c_string_to_key_with_params(context, enctype, string, salt,
NULL, key);
@@ -53,7 +52,7 @@ krb5_c_string_to_key(krb5_context context, krb5_enctype enctype,
krb5_error_code KRB5_CALLCONV
krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype,
- const krb5_data *string,
+ const krb5_data *string,
const krb5_data *salt,
const krb5_data *params, krb5_keyblock *key)
{
@@ -64,7 +63,7 @@ krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype,
for (i=0; i<krb5_enctypes_length; i++) {
if (krb5_enctypes_list[i].etype == enctype)
- break;
+ break;
}
if (i == krb5_enctypes_length)
@@ -72,21 +71,21 @@ krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype,
enc = krb5_enctypes_list[i].enc;
/* xxx AFS string2key function is indicated by a special length in
-* the salt in much of the code. However only the DES enctypes can
-* deal with this. Using s2kparams would be a much better solution.*/
+ * the salt in much of the code. However only the DES enctypes can
+ * deal with this. Using s2kparams would be a much better solution.*/
if (salt && salt->length == SALT_TYPE_AFS_LENGTH) {
- switch (enctype) {
- case ENCTYPE_DES_CBC_CRC:
- case ENCTYPE_DES_CBC_MD4:
- case ENCTYPE_DES_CBC_MD5:
- break;
- default:
- return (KRB5_CRYPTO_INTERNAL);
- }
+ switch (enctype) {
+ case ENCTYPE_DES_CBC_CRC:
+ case ENCTYPE_DES_CBC_MD4:
+ case ENCTYPE_DES_CBC_MD5:
+ break;
+ default:
+ return (KRB5_CRYPTO_INTERNAL);
+ }
}
-
- keybytes = enc->keybytes;
- keylength = enc->keylength;
+
+ keybytes = enc->keybytes;
+ keylength = enc->keylength;
if ((key->contents = (krb5_octet *) malloc(keylength)) == NULL)
return(ENOMEM);
@@ -94,14 +93,17 @@ krb5_c_string_to_key_with_params(krb5_context context, krb5_enctype enctype,
key->magic = KV5M_KEYBLOCK;
key->enctype = enctype;
key->length = keylength;
+ /* Solaris Kerberos */
key->dk_list = NULL;
key->hKey = CK_INVALID_HANDLE;
+ /* Solaris Kerberos */
ret = (*krb5_enctypes_list[i].str2key)(context, enc, string, salt,
params, key);
if (ret) {
memset(key->contents, 0, keylength);
free(key->contents);
+ /* Solaris Kerberos */
key->contents = NULL;
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/crypto/valid_enctype.c b/usr/src/lib/gss_mechs/mech_krb5/crypto/valid_enctype.c
index 88ea50d0cc..d44cd0f7af 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/crypto/valid_enctype.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/crypto/valid_enctype.c
@@ -1,20 +1,19 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright (C) 1998 by the FundsXpress, INC.
- *
+ *
* 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
@@ -25,14 +24,14 @@
* permission. FundsXpress makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
- *
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <etypes.h>
+#include "k5-int.h"
+#include "etypes.h"
krb5_boolean KRB5_CALLCONV
krb5_c_valid_enctype(krb5_enctype etype)
diff --git a/usr/src/lib/gss_mechs/mech_krb5/et/com_err.c b/usr/src/lib/gss_mechs/mech_krb5/et/com_err.c
index b6b3dfc04e..1f612f9755 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/et/com_err.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/et/com_err.c
@@ -3,11 +3,10 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright 1997 by Massachusetts Institute of Technology
- *
+ *
* Copyright 1987, 1988 by MIT Student Information Processing Board
*
* Permission to use, copy, modify, and distribute this software
@@ -26,26 +25,34 @@
* provided "as is" without express or implied warranty.
*/
-
#include <stdio.h>
#include <string.h>
+#include <stdlib.h>
#include <locale.h>
#include "com_err.h"
#include "error_table.h"
-#if defined(_MSDOS) || defined(_WIN32)
+#if defined(_WIN32)
#include <io.h>
#endif
-#ifdef macintosh
-#include "icons.h"
-static void MacMessageBox(char *errbuf);
-#endif
+
+k5_mutex_t com_err_hook_lock = K5_MUTEX_PARTIAL_INITIALIZER;
static void default_com_err_proc
(const char *whoami, errcode_t code,
const char *fmt, va_list ap);
+#if defined(_WIN32)
+BOOL isGuiApp() {
+ DWORD mypid;
+ HANDLE myprocess;
+ mypid = GetCurrentProcessId();
+ myprocess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, mypid);
+ return GetGuiResources(myprocess, 1) > 0;
+ }
+#endif
+
/*
* Solaris Kerberos:
* It is sometimes desirable to have more than a single hook called
@@ -136,11 +143,9 @@ my_gettext(int msg_idx)
/* Solaris Kerberos: this code is significantly altered from
* the MIT 1.2.1 version to work with internationalization */
-static void default_com_err_proc(whoami, code, fmt, ap)
- const char *whoami;
- errcode_t code;
- const char *fmt;
- va_list ap;
+
+static void default_com_err_proc (const char *whoami, errcode_t code,
+ const char *fmt, va_list ap)
{
char whilebuf[1024] = "";
@@ -209,49 +214,70 @@ static void default_com_err_proc(whoami, code, fmt, ap)
fflush(stderr);
}
-void KRB5_CALLCONV com_err_va(whoami, code, fmt, ap)
- const char *whoami;
- errcode_t code;
- const char *fmt;
- va_list ap;
+void KRB5_CALLCONV com_err_va(const char *whoami,
+ errcode_t code,
+ const char *fmt,
+ va_list ap)
{
- int i;
-
- for (i = 0; i < hook_count; i++) {
- (com_err_hook[i])(whoami, code, fmt, ap);
- }
+ int err;
+ int i;
+ err = com_err_finish_init();
+ if (err)
+ goto best_try;
+ err = k5_mutex_lock(&com_err_hook_lock);
+ if (err)
+ goto best_try;
+ for (i = 0; i < hook_count; i++) {
+ (com_err_hook[i])(whoami, code, fmt, ap);
+ }
+ k5_mutex_unlock(&com_err_hook_lock);
+ return;
+
+best_try:
+ /* Yikes. Our library initialization failed or we couldn't lock
+ the lock we want. We could be in trouble. Gosh, we should
+ probably print an error message. Oh, wait. That's what we're
+ trying to do. In fact, if we're losing on initialization here,
+ there's a good chance it has to do with failed initialization
+ of the caller. */
+
+ for (i = 0; i < hook_count; i++) {
+ (com_err_hook[i])(whoami, code, fmt, ap);
+ }
+ assert(err == 0);
+ abort();
}
-#ifndef ET_VARARGS
-void KRB5_CALLCONV_C com_err(const char *whoami,
- errcode_t code,
- const char *fmt, ...)
-#else
-void KRB5_CALLCONV_C com_err(whoami, code, fmt, va_alist)
- const char *whoami;
- errcode_t code;
- const char *fmt;
- va_dcl
-#endif
+void KRB5_CALLCONV_C com_err(const char *whoami,
+ errcode_t code,
+ const char *fmt, ...)
{
va_list ap;
-#ifdef ET_VARARGS
- va_start(ap);
-#else
va_start(ap, fmt);
-#endif
com_err_va(whoami, code, fmt, ap);
va_end(ap);
}
-#if !(defined(_MSDOS)||defined(_WIN32))
-et_old_error_hook_func set_com_err_hook (new_proc)
- et_old_error_hook_func new_proc;
+/* Make a separate function because the assert invocations below
+ use the macro expansion on some platforms, which may be insanely
+ long and incomprehensible. */
+static int com_err_lock_hook_handle(void)
+{
+ return k5_mutex_lock(&com_err_hook_lock);
+}
+
+et_old_error_hook_func set_com_err_hook (et_old_error_hook_func new_proc)
{
int i;
- et_old_error_hook_func x = com_err_hook[0];
+ et_old_error_hook_func x;
+
+ /* Broken initialization? What can we do? */
+ assert(com_err_finish_init() == 0);
+ assert(com_err_lock_hook_handle() == 0);
+
+ x = com_err_hook[0];
for (i = 0; i < hook_count; i++)
com_err_hook[i] = NULL;
@@ -259,23 +285,27 @@ et_old_error_hook_func set_com_err_hook (new_proc)
com_err_hook[0] = new_proc;
hook_count = 1;
+ k5_mutex_unlock(&com_err_hook_lock);
return x;
}
et_old_error_hook_func reset_com_err_hook ()
{
int i;
- et_old_error_hook_func x = com_err_hook[0];
+ et_old_error_hook_func x;
+ /* Broken initialization? What can we do? */
+ assert(com_err_finish_init() == 0);
+ assert(com_err_lock_hook_handle() == 0);
+ x = com_err_hook[0];
for (i = 0; i < hook_count; i++)
com_err_hook[i] = NULL;
com_err_hook[0] = default_com_err_proc;
hook_count = 1;
-
+ k5_mutex_unlock(&com_err_hook_lock);
return x;
}
-#endif
/*
* Solaris Kerberos:
diff --git a/usr/src/lib/gss_mechs/mech_krb5/et/internal.h b/usr/src/lib/gss_mechs/mech_krb5/et/internal.h
index 27b329012a..57b5cd58e5 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/et/internal.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/et/internal.h
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* internal include file for com_err package
*/
@@ -11,6 +10,6 @@ extern char const * const sys_errlist[];
extern const int sys_nerr;
#endif
-#if defined(__STDC__) && !defined(HDR_HAS_PERROR) && !defined(_MSDOS) && !defined(WIN32)
+#if defined(__STDC__) && !defined(HDR_HAS_PERROR) && !defined(WIN32)
void perror (const char *);
#endif
diff --git a/usr/src/lib/gss_mechs/mech_krb5/et/krb5_err.c b/usr/src/lib/gss_mechs/mech_krb5/et/krb5_err.c
index f9017f813d..951a5b6e63 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/et/krb5_err.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/et/krb5_err.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <locale.h>
#include <security/cryptoki.h>
@@ -102,7 +101,8 @@ switch (errorno) {
"KRB5 error code 28"));
case 29:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 29"));
+ "A service is not available that is required to "
+ "process the request"));
case 30:
return (dgettext(TEXT_DOMAIN,
"KRB5 error code 30"));
@@ -168,10 +168,10 @@ switch (errorno) {
"Inappropriate type of checksum in message"));
case 51:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 51"));
+ "Policy rejects transited path"));
case 52:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 52"));
+ "Response too big for UDP, retry with TCP"));
case 53:
return (dgettext(TEXT_DOMAIN,
"KRB5 error code 53"));
@@ -201,19 +201,19 @@ switch (errorno) {
"Field is too long for this implementation"));
case 62:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 62"));
+ "Client not trusted"));
case 63:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 63"));
+ "KDC not trusted"));
case 64:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 64"));
+ "Invalid signature"));
case 65:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 65"));
+ "Key parameters not accepted"));
case 66:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 66"));
+ "Certificate mismatch"));
case 67:
return (dgettext(TEXT_DOMAIN,
"KRB5 error code 67"));
@@ -225,40 +225,40 @@ switch (errorno) {
"KRB5 error code 69"));
case 70:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 70"));
+ "Can't verify certificate"));
case 71:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 71"));
+ "Invalid certificate"));
case 72:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 72"));
+ "Revoked certificate"));
case 73:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 73"));
+ "Revocation status unknown"));
case 74:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 74"));
+ "Revocation status unavailable"));
case 75:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 75"));
+ "Client name mismatch"));
case 76:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 76"));
+ "KDC name mismatch"));
case 77:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 77"));
+ "Inconsistent key purpose"));
case 78:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 78"));
+ "Digest in certificate not accepted"));
case 79:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 79"));
+ "Checksum must be included"));
case 80:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 80"));
+ "Digest in signed-data not accepted"));
case 81:
return (dgettext(TEXT_DOMAIN,
- "KRB5 error code 81"));
+ "Public key encryption not supported"));
case 82:
return (dgettext(TEXT_DOMAIN,
"KRB5 error code 82"));
diff --git a/usr/src/lib/gss_mechs/mech_krb5/et/mit-sipb-copyright.h b/usr/src/lib/gss_mechs/mech_krb5/et/mit-sipb-copyright.h
index d02d196bbb..d7c4ee096e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/et/mit-sipb-copyright.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/et/mit-sipb-copyright.h
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
Copyright 1987, 1988 by the Student Information Processing Board
@@ -12,6 +11,9 @@ this permission notice appear in supporting documentation,
and that the names of M.I.T. and the M.I.T. S.I.P.B. 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. and the M.I.T. S.I.P.B. make no representations about
the suitability of this software for any purpose. It is
provided "as is" without express or implied warranty.
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/autoconf.h b/usr/src/lib/gss_mechs/mech_krb5/include/autoconf.h
index 9266877ca7..932ed0c842 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/include/autoconf.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/autoconf.h
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/* autoconf.h. Generated automatically by configure. */
/* autoconf.h.in. Generated automatically from configure.in by autoheader. */
/* Edited to remove KRB4 compatible and SIZEOF_LONG
@@ -50,6 +49,23 @@
#define KRB5_USE_INET 1
#define KRB5_USE_INET6 1
+/* Solaris Kerberos - 163 Resync */
+#define LIBDIR "/usr/lib"
+
+/* Type of getpeername second argument. */
+#define GETPEERNAME_ARG2_TYPE GETSOCKNAME_ARG2_TYPE
+
+/* Type of getpeername second argument. */
+#define GETPEERNAME_ARG3_TYPE GETSOCKNAME_ARG3_TYPE
+
+/* Type of pointer target for argument 2 to getsockname */
+#define GETSOCKNAME_ARG2_TYPE struct sockaddr
+
+/* Type of pointer target for argument 3 to getsockname */
+#define GETSOCKNAME_ARG3_TYPE socklen_t
+
+#define HAVE_GETEUID 1
+
/* Define if you have the getaddrinfo function */
#define HAVE_GETADDRINFO 1
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/cache-addrinfo.h b/usr/src/lib/gss_mechs/mech_krb5/include/cache-addrinfo.h
new file mode 100644
index 0000000000..685a166327
--- /dev/null
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/cache-addrinfo.h
@@ -0,0 +1,129 @@
+
+/*
+ * Copyright (C) 2004 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA. All Rights Reserved.
+ *
+ * This software is being provided to you, the LICENSEE, by the
+ * Massachusetts Institute of Technology (M.I.T.) under the following
+ * license. By obtaining, using and/or copying this software, you agree
+ * that you have read, understood, and will comply with these terms and
+ * conditions:
+ *
+ * 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 or
+ * royalty is hereby granted, provided that you agree to comply with the
+ * following copyright notice and statements, including the disclaimer, and
+ * that the same appear on ALL copies of the software and documentation,
+ * including modifications that you make for internal use or for
+ * distribution:
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
+ * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+ *
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT
+ * be used in advertising or publicity pertaining to distribution of the
+ * software. Title to copyright in this software and any associated
+ * documentation shall at all times remain with M.I.T., and USER agrees to
+ * preserve same.
+ *
+ * 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.
+ */
+
+/* Approach overview:
+
+ If a system version is available but buggy, save handles to it,
+ redefine the names to refer to static functions defined here, and
+ in those functions, call the system versions and fix up the
+ returned data. Use the native data structures and flag values.
+
+ If no system version exists, use gethostby* and fake it. Define
+ the data structures and flag values locally.
+
+
+ On Mac OS X, getaddrinfo results aren't cached (though
+ gethostbyname results are), so we need to build a cache here. Now
+ things are getting really messy. Because the cache is in use, we
+ use getservbyname, and throw away thread safety. (Not that the
+ cache is thread safe, but when we get locking support, that'll be
+ dealt with.) This code needs tearing down and rebuilding, soon.
+
+
+ Note that recent Windows developers' code has an interesting hack:
+ When you include the right header files, with the right set of
+ macros indicating system versions, you'll get an inline function
+ that looks for getaddrinfo (or whatever) in the system library, and
+ calls it if it's there. If it's not there, it fakes it with
+ gethostby* calls.
+
+ We're taking a simpler approach: A system provides these routines or
+ it does not.
+
+ Someday, we may want to take into account different versions (say,
+ different revs of GNU libc) where some are broken in one way, and
+ some work or are broken in another way. Cross that bridge when we
+ come to it. */
+
+/* To do, maybe:
+
+ + For AIX 4.3.3, using the RFC 2133 definition: Implement
+ AI_NUMERICHOST. It's not defined in the header file.
+
+ For certain (old?) versions of GNU libc, AI_NUMERICHOST is
+ defined but not implemented.
+
+ + Use gethostbyname2, inet_aton and other IPv6 or thread-safe
+ functions if available. But, see
+ http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=135182 for one
+ gethostbyname2 problem on Linux. And besides, if a platform is
+ supporting IPv6 at all, they really should be doing getaddrinfo
+ by now.
+
+ + inet_ntop, inet_pton
+
+ + Conditionally export/import the function definitions, so a
+ library can have a single copy instead of multiple.
+
+ + Upgrade host requirements to include working implementations of
+ these functions, and throw all this away. Pleeease? :-) */
+
+#include "port-sockets.h"
+#include "socket-utils.h"
+#include "k5-platform.h"
+#include "k5-thread.h"
+
+#include "fake-addrinfo.h"
+
+#if defined (__APPLE__) && defined (__MACH__)
+#define FAI_CACHE
+#endif
+
+struct face {
+ struct in_addr *addrs4;
+ struct in6_addr *addrs6;
+ unsigned int naddrs4, naddrs6;
+ time_t expiration;
+ char *canonname, *name;
+ struct face *next;
+};
+
+/* fake addrinfo cache */
+struct fac {
+ k5_mutex_t lock;
+ struct face *data;
+};
+
+extern struct fac krb5int_fac;
+
+extern int krb5int_init_fac (void);
+extern void krb5int_fini_fac (void);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/cm.h b/usr/src/lib/gss_mechs/mech_krb5/include/cm.h
index 6007790c63..716e6cb593 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/include/cm.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/cm.h
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* include/cm.h
*
@@ -25,16 +24,60 @@
* or implied warranty.
*/
+/* Since fd_set is large on some platforms (8K on AIX 5.2), this
+ probably shouldn't be allocated in automatic storage. */
struct select_state {
int max, nfds;
fd_set rfds, wfds, xfds;
struct timeval end_time; /* magic: tv_sec==0 => never time out */
};
+
/* Select state flags. */
#define SSF_READ 0x01
#define SSF_WRITE 0x02
#define SSF_EXCEPTION 0x04
+
+static const char *const state_strings[] = {
+ "INITIALIZING", "CONNECTING", "WRITING", "READING", "FAILED"
+};
+
+
+/* connection states */
+enum conn_states { INITIALIZING, CONNECTING, WRITING, READING, FAILED };
+struct incoming_krb5_message {
+ size_t bufsizebytes_read;
+ size_t bufsize;
+ char *buf;
+ char *pos;
+ unsigned char bufsizebytes[4];
+ size_t n_left;
+};
+struct conn_state {
+ SOCKET fd;
+ krb5_error_code err;
+ enum conn_states state;
+ unsigned int is_udp : 1;
+ int (*service)(struct conn_state *, struct select_state *, int);
+ struct addrinfo *addr;
+ struct {
+ struct {
+ sg_buf sgbuf[2];
+ sg_buf *sgp;
+ int sg_count;
+ unsigned char msg_len_buf[4];
+ } out;
+ struct incoming_krb5_message in;
+ } x;
+};
+
+struct sendto_callback_info {
+ int (*pfn_callback) (struct conn_state *, void *, krb5_data *);
+ void (*pfn_cleanup) (void *, krb5_data *);
+ void *context;
+};
+
+
krb5_error_code krb5int_cm_call_select (const struct select_state *,
struct select_state *, int *);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/db.h b/usr/src/lib/gss_mechs/mech_krb5/include/db.h
index 2b74608be6..ad86d0af9c 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/include/db.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/db.h
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
@@ -79,7 +78,7 @@ typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE;
* is so that the access methods can skip copying the key/data pair when
* the DB_LOCK flag isn't set.
*/
-#if SIZEOF_INT == 4
+#if UINT_MAX >= 0xffffffffUL
#define DB_LOCK 0x20000000 /* Do locking. */
#define DB_SHMEM 0x40000000 /* Use shared memory. */
#define DB_TXN 0x80000000 /* Do transactions. */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/fake-addrinfo.h b/usr/src/lib/gss_mechs/mech_krb5/include/fake-addrinfo.h
index dbc03de925..952b43f0bf 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/include/fake-addrinfo.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/fake-addrinfo.h
@@ -42,10 +42,10 @@
/* Approach overview:
If a system version is available but buggy, save handles to it (via
- inline functions), redefine the names to refer to static functions
- defined here, and in those functions, call the system versions and
- fix up the returned data. Use the native data structures and flag
- values.
+ inline functions in a support library), redefine the names to refer
+ to library functions, and in those functions, call the system
+ versions and fix up the returned data. Use the native data
+ structures and flag values.
If no system version exists, use gethostby* and fake it. Define
the data structures and flag values locally.
@@ -99,253 +99,11 @@
#ifndef FAI_DEFINED
#define FAI_DEFINED
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include "port-sockets.h"
#include "socket-utils.h"
-#include "k5-platform.h"
-#include "k5-thread.h"
-
-#include <stdio.h> /* for sprintf */
-#include <errno.h>
-
-#ifdef S_SPLINT_S
-/*@-incondefs@*/
-extern int
-getaddrinfo (/*@in@*/ /*@null@*/ const char *,
- /*@in@*/ /*@null@*/ const char *,
- /*@in@*/ /*@null@*/ const struct addrinfo *,
- /*@out@*/ struct addrinfo **)
- ;
-extern void
-freeaddrinfo (/*@only@*/ /*@out@*/ struct addrinfo *)
- ;
-extern int
-getnameinfo (const struct sockaddr *addr, socklen_t addrsz,
- /*@out@*/ /*@null@*/ char *h, socklen_t hsz,
- /*@out@*/ /*@null@*/ char *s, socklen_t ssz,
- int flags)
- /*@requires (maxSet(h)+1) >= hsz /\ (maxSet(s)+1) >= ssz @*/
- /* too hard: maxRead(addr) >= (addrsz-1) */
- /*@modifies *h, *s@*/;
-extern /*@dependent@*/ char *gai_strerror (int code) /*@*/;
-/*@=incondefs@*/
-#endif
-
-
-#if defined (__APPLE__) && defined (__MACH__)
-#define FAI_CACHE
-#endif
-
-#if (defined (__linux__) && defined(HAVE_GETADDRINFO)) || defined (_AIX)
-/* See comments below. */
-# define WRAP_GETADDRINFO
-#endif
-
-#if defined (__linux__) && defined(HAVE_GETADDRINFO)
-# define COPY_FIRST_CANONNAME
-#endif
-
-#ifdef _AIX
-# define NUMERIC_SERVICE_BROKEN
-# define COPY_FIRST_CANONNAME
-#endif
-
-
-#ifdef COPY_FIRST_CANONNAME
-# include <string.h>
-#endif
-
-#ifdef NUMERIC_SERVICE_BROKEN
-# include <ctype.h> /* isdigit */
-# include <stdlib.h> /* strtoul */
-#endif
-
-#ifdef _WIN32
-#define HAVE_GETADDRINFO 1
-#define HAVE_GETNAMEINFO 1
-#endif
-
-
-/* Do we actually have *any* systems we care about that don't provide
- either getaddrinfo or one of these two flavors of
- gethostbyname_r? */
-#if !defined(HAVE_GETHOSTBYNAME_R) || defined(THREADSAFE_GETHOSTBYNAME)
-#define GET_HOST_BY_NAME(NAME, HP, ERR) \
- { (HP) = gethostbyname (NAME); (ERR) = h_errno; }
-#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \
- { (HP) = gethostbyaddr ((ADDR), (ADDRLEN), (FAMILY)); (ERR) = h_errno; }
-#else
-#ifdef _AIX /* XXX should have a feature test! */
-#define GET_HOST_BY_NAME(NAME, HP, ERR) \
- { \
- struct hostent my_h_ent; \
- struct hostent_data my_h_ent_data; \
- (HP) = (gethostbyname_r((NAME), &my_h_ent, &my_h_ent_data) \
- ? 0 \
- : &my_h_ent); \
- (ERR) = h_errno; \
- }
-/*
-#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \
- { \
- struct hostent my_h_ent; \
- struct hostent_data my_h_ent_data; \
- (HP) = (gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent, \
- &my_h_ent_data) \
- ? 0 \
- : &my_h_ent); \
- (ERR) = my_h_err; \
- }
-*/
-#else
-#ifdef GETHOSTBYNAME_R_RETURNS_INT
-#define GET_HOST_BY_NAME(NAME, HP, ERR) \
- { \
- struct hostent my_h_ent, *my_hp; \
- int my_h_err; \
- char my_h_buf[8192]; \
- (HP) = (gethostbyname_r((NAME), &my_h_ent, \
- my_h_buf, sizeof (my_h_buf), &my_hp, \
- &my_h_err) \
- ? 0 \
- : &my_h_ent); \
- (ERR) = my_h_err; \
- }
-#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \
- { \
- struct hostent my_h_ent, *my_hp; \
- int my_h_err; \
- char my_h_buf[8192]; \
- (HP) = (gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent, \
- my_h_buf, sizeof (my_h_buf), &my_hp, \
- &my_h_err) \
- ? 0 \
- : &my_h_ent); \
- (ERR) = my_h_err; \
- }
-#else
-#define GET_HOST_BY_NAME(NAME, HP, ERR) \
- { \
- struct hostent my_h_ent; \
- int my_h_err; \
- char my_h_buf[8192]; \
- (HP) = gethostbyname_r((NAME), &my_h_ent, \
- my_h_buf, sizeof (my_h_buf), &my_h_err); \
- (ERR) = my_h_err; \
- }
-#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \
- { \
- struct hostent my_h_ent; \
- int my_h_err; \
- char my_h_buf[8192]; \
- (HP) = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent, \
- my_h_buf, sizeof (my_h_buf), &my_h_err); \
- (ERR) = my_h_err; \
- }
-#endif /* returns int? */
-#endif /* _AIX */
-#endif
-
-/* Now do the same for getservby* functions. */
-#ifndef HAVE_GETSERVBYNAME_R
-#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR) \
- ((SP) = getservbyname (NAME, PROTO), (ERR) = (SP) ? 0 : -1)
-#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR) \
- ((SP) = getservbyport (PORT, PROTO), (ERR) = (SP) ? 0 : -1)
-#else
-#ifdef GETSERVBYNAME_R_RETURNS_INT
-#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR) \
- { \
- struct servent my_s_ent, *my_sp; \
- int my_s_err; \
- char my_s_buf[8192]; \
- (SP) = (getservbyname_r((NAME), (PROTO), &my_s_ent, \
- my_s_buf, sizeof (my_s_buf), &my_sp, \
- &my_s_err) \
- ? 0 \
- : &my_s_ent); \
- (ERR) = my_s_err; \
- }
-#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR) \
- { \
- struct servent my_s_ent, *my_sp; \
- int my_s_err; \
- char my_s_buf[8192]; \
- (SP) = (getservbyport_r((PORT), (PROTO), &my_s_ent, \
- my_s_buf, sizeof (my_s_buf), &my_sp, \
- &my_s_err) \
- ? 0 \
- : &my_s_ent); \
- (ERR) = my_s_err; \
- }
-#else
-/* returns ptr -- IRIX? */
-#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR) \
- { \
- struct servent my_s_ent; \
- char my_s_buf[8192]; \
- (SP) = getservbyname_r((NAME), (PROTO), &my_s_ent, \
- my_s_buf, sizeof (my_s_buf)); \
- (ERR) = (SP) == NULL; \
- }
-
-#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR) \
- { \
- struct servent my_s_ent, *my_sp; \
- char my_s_buf[8192]; \
- my_sp = getservbyport_r((PORT), (PROTO), &my_s_ent, \
- my_s_buf, sizeof (my_s_buf)); \
- (SP) = my_sp; \
- (ERR) = my_sp == 0; \
- (ERR) = (ERR); /* avoid "unused" warning */ \
- }
-#endif
-#endif
-
-#if defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
-static inline int
-system_getaddrinfo (const char *name, const char *serv,
- const struct addrinfo *hint,
- struct addrinfo **res)
-{
- return getaddrinfo(name, serv, hint, res);
-}
-
-static inline void
-system_freeaddrinfo (struct addrinfo *ai)
-{
- freeaddrinfo(ai);
-}
-
-/* Note: Implementations written to RFC 2133 use size_t, while RFC
- 2553 implementations use socklen_t, for the second parameter.
-
- Mac OS X (10.2) and AIX 4.3.3 appear to be in the RFC 2133 camp,
- but we don't have an autoconf test for that right now. */
-static inline int
-system_getnameinfo (const struct sockaddr *sa, socklen_t salen,
- char *host, size_t hostlen, char *serv, size_t servlen,
- int flags)
-{
- return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
-}
-#endif
-
-#if !defined (HAVE_GETADDRINFO) || defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
-
-#undef getaddrinfo
-#define getaddrinfo my_fake_getaddrinfo
-#undef freeaddrinfo
-#define freeaddrinfo my_fake_freeaddrinfo
-
-#endif
#if !defined (HAVE_GETADDRINFO)
-#undef gai_strerror
-#define gai_strerror my_fake_gai_strerror
#undef addrinfo
#define addrinfo my_fake_addrinfo
@@ -423,144 +181,6 @@ struct addrinfo {
#endif /* ! HAVE_GETADDRINFO */
-#if (!defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)) && defined(DEBUG_ADDRINFO)
-/* Some debug routines. */
-
-static const char *protoname (int p, char *buf) {
-#define X(N) if (p == IPPROTO_ ## N) return #N
-
- X(TCP);
- X(UDP);
- X(ICMP);
- X(IPV6);
-#ifdef IPPROTO_GRE
- X(GRE);
-#endif
- X(NONE);
- X(RAW);
-#ifdef IPPROTO_COMP
- X(COMP);
-#endif
-
- sprintf(buf, " %-2d", p);
- return buf;
-}
-
-static const char *socktypename (int t, char *buf) {
- switch (t) {
- case SOCK_DGRAM: return "DGRAM";
- case SOCK_STREAM: return "STREAM";
- case SOCK_RAW: return "RAW";
- case SOCK_RDM: return "RDM";
- case SOCK_SEQPACKET: return "SEQPACKET";
- }
- sprintf(buf, " %-2d", t);
- return buf;
-}
-
-static const char *familyname (int f, char *buf) {
- switch (f) {
- default:
- sprintf(buf, "AF %d", f);
- return buf;
- case AF_INET: return "AF_INET";
- case AF_INET6: return "AF_INET6";
-#ifdef AF_UNIX
- case AF_UNIX: return "AF_UNIX";
-#endif
- }
-}
-
-static void debug_dump_getaddrinfo_args (const char *name, const char *serv,
- const struct addrinfo *hint)
-{
- const char *sep;
- fprintf(stderr,
- "getaddrinfo(hostname %s, service %s,\n"
- " hints { ",
- name ? name : "(null)", serv ? serv : "(null)");
- if (hint) {
- char buf[30];
- sep = "";
-#define Z(FLAG) if (hint->ai_flags & AI_##FLAG) fprintf(stderr, "%s%s", sep, #FLAG), sep = "|"
- Z(CANONNAME);
- Z(PASSIVE);
-#ifdef AI_NUMERICHOST
- Z(NUMERICHOST);
-#endif
- if (sep[0] == 0)
- fprintf(stderr, "no-flags");
- if (hint->ai_family)
- fprintf(stderr, " %s", familyname(hint->ai_family, buf));
- if (hint->ai_socktype)
- fprintf(stderr, " SOCK_%s", socktypename(hint->ai_socktype, buf));
- if (hint->ai_protocol)
- fprintf(stderr, " IPPROTO_%s", protoname(hint->ai_protocol, buf));
- } else
- fprintf(stderr, "(null)");
- fprintf(stderr, " }):\n");
-}
-
-static void debug_dump_error (int err)
-{
- fprintf(stderr, "error %d: %s\n", err, gai_strerror(err));
-}
-
-static void debug_dump_addrinfos (const struct addrinfo *ai)
-{
- int count = 0;
- fprintf(stderr, "addrinfos returned:\n");
- while (ai) {
- fprintf(stderr, "%p...", ai);
- fprintf(stderr, " socktype=%s", socktypename(ai->ai_socktype));
- fprintf(stderr, " ai_family=%s", familyname(ai->ai_family));
- if (ai->ai_family != ai->ai_addr->sa_family)
- fprintf(stderr, " sa_family=%s",
- familyname(ai->ai_addr->sa_family));
- fprintf(stderr, "\n");
- ai = ai->ai_next;
- count++;
- }
- fprintf(stderr, "end addrinfos returned (%d)\n");
-}
-
-#endif
-
-#if !defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)
-
-static
-int getaddrinfo (const char *name, const char *serv,
- const struct addrinfo *hint, struct addrinfo **result);
-
-static
-void freeaddrinfo (struct addrinfo *ai);
-
-#endif
-
-#if !defined (HAVE_GETADDRINFO)
-
-#define HAVE_FAKE_GETADDRINFO /* was not originally HAVE_GETADDRINFO */
-#define HAVE_GETADDRINFO
-#define NEED_FAKE_GETNAMEINFO
-#undef HAVE_GETNAMEINFO
-#define HAVE_GETNAMEINFO 1
-
-#undef getnameinfo
-#define getnameinfo my_fake_getnameinfo
-
-static
-char *gai_strerror (int code);
-
-#endif
-
-#if !defined (HAVE_GETADDRINFO)
-static
-int getnameinfo (const struct sockaddr *addr, socklen_t len,
- char *host, socklen_t hostlen,
- char *service, socklen_t servicelen,
- int flags);
-#endif
-
/* Fudge things on older gai implementations. */
/* AIX 4.3.3 is based on RFC 2133; no AI_NUMERICHOST. */
#ifndef AI_NUMERICHOST
@@ -582,790 +202,32 @@ int getnameinfo (const struct sockaddr *addr, socklen_t len,
# define AI_DEFAULT (AI_ADDRCONFIG|AI_V4MAPPED)
#endif
-#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
-#define NEED_FAKE_GETADDRINFO
-#endif
-
-#if defined(NEED_FAKE_GETADDRINFO) || defined(WRAP_GETADDRINFO)
-#include <stdlib.h>
-#endif
-
-struct face {
- struct in_addr *addrs4;
- struct in6_addr *addrs6;
- unsigned int naddrs4, naddrs6;
- time_t expiration;
- char *canonname, *name;
- struct face *next;
-};
-
-/* fake addrinfo cache */
-struct fac {
- k5_mutex_t lock;
- struct face *data;
-};
-extern struct fac krb5int_fac;
-
-#ifdef NEED_FAKE_GETADDRINFO
-#include <string.h> /* for strspn */
-
-static inline int translate_h_errno (int h);
-
-static inline int fai_add_entry (struct addrinfo **result, void *addr,
- int port, const struct addrinfo *template)
-{
- struct addrinfo *n = malloc (sizeof (struct addrinfo));
- if (n == 0)
- return EAI_MEMORY;
- if (template->ai_family != AF_INET
-#ifdef KRB5_USE_INET6
- && template->ai_family != AF_INET6
-#endif
- )
- return EAI_FAMILY;
- *n = *template;
- if (template->ai_family == AF_INET) {
- struct sockaddr_in *sin4;
- sin4 = malloc (sizeof (struct sockaddr_in));
- if (sin4 == 0)
- return EAI_MEMORY;
- n->ai_addr = (struct sockaddr *) sin4;
- sin4->sin_family = AF_INET;
- sin4->sin_addr = *(struct in_addr *)addr;
- sin4->sin_port = port;
-#ifdef HAVE_SA_LEN
- sin4->sin_len = sizeof (struct sockaddr_in);
-#endif
- }
-#ifdef KRB5_USE_INET6
- if (template->ai_family == AF_INET6) {
- struct sockaddr_in6 *sin6;
- sin6 = malloc (sizeof (struct sockaddr_in6));
- if (sin6 == 0)
- return EAI_MEMORY;
- n->ai_addr = (struct sockaddr *) sin6;
- sin6->sin6_family = AF_INET6;
- sin6->sin6_addr = *(struct in6_addr *)addr;
- sin6->sin6_port = port;
-#ifdef HAVE_SA_LEN
- sin6->sin6_len = sizeof (struct sockaddr_in6);
-#endif
- }
-#endif
- n->ai_next = *result;
- *result = n;
- return 0;
-}
-
-#ifdef FAI_CACHE
-/* fake addrinfo cache entries */
-#define CACHE_ENTRY_LIFETIME 15 /* seconds */
-
-static void plant_face (const char *name, struct face *entry)
-{
- entry->name = strdup(name);
- if (entry->name == NULL)
- /* @@ Wastes memory. */
- return;
- k5_mutex_assert_locked(&krb5int_fac.lock);
- entry->next = krb5int_fac.data;
- entry->expiration = time(0) + CACHE_ENTRY_LIFETIME;
- krb5int_fac.data = entry;
-#ifdef DEBUG_ADDRINFO
- printf("added cache entry '%s' at %p: %d ipv4, %d ipv6; expire %d\n",
- name, entry, entry->naddrs4, entry->naddrs6, entry->expiration);
-#endif
-}
-
-static int find_face (const char *name, struct face **entry)
-{
- struct face *fp, **fpp;
- time_t now = time(0);
-
- /* First, scan for expired entries and free them.
- (Future improvement: Integrate these two loops.) */
-#ifdef DEBUG_ADDRINFO
- printf("scanning cache at %d for '%s'...\n", now, name);
-#endif
- k5_mutex_assert_locked(&krb5int_fac.lock);
- for (fpp = &krb5int_fac.data; *fpp; ) {
- fp = *fpp;
-#ifdef DEBUG_ADDRINFO
- printf(" checking expiration time of @%p: %d\n",
- fp, fp->expiration);
-#endif
- if (fp->expiration < now) {
-#ifdef DEBUG_ADDRINFO
- printf("\texpiring cache entry\n");
-#endif
- free(fp->name);
- free(fp->canonname);
- free(fp->addrs4);
- free(fp->addrs6);
- *fpp = fp->next;
- free(fp);
- /* Stay at this point in the list, and check again. */
- } else
- /* Move forward. */
- fpp = &(*fpp)->next;
- }
-
- for (fp = krb5int_fac.data; fp; fp = fp->next) {
-#ifdef DEBUG_ADDRINFO
- printf(" comparing entry @%p\n", fp);
-#endif
- if (!strcasecmp(fp->name, name)) {
-#ifdef DEBUG_ADDRINFO
- printf("\tMATCH!\n");
-#endif
- *entry = fp;
- return 1;
- }
- }
- return 0;
-}
-
-#endif
-
-extern int krb5int_lock_fac(void), krb5int_unlock_fac(void);
-
-static inline int fai_add_hosts_by_name (const char *name,
- struct addrinfo *template,
- int portnum, int flags,
- struct addrinfo **result)
-{
-#ifdef FAI_CACHE
-
- struct face *ce;
- int i, r, err;
-
- err = krb5int_lock_fac();
- if (err) {
- errno = err;
- return EAI_SYSTEM;
- }
- if (!find_face(name, &ce)) {
- struct addrinfo myhints = { 0 }, *ai, *ai2;
- int i4, i6, aierr;
-
-#ifdef DEBUG_ADDRINFO
- printf("looking up new data for '%s'...\n", name);
-#endif
- myhints.ai_socktype = SOCK_STREAM;
- myhints.ai_flags = AI_CANONNAME;
- /* Don't set ai_family -- we want to cache all address types,
- because the next lookup may not use the same constraints as
- the current one. We *could* cache them separately, so that
- we never have to look up an IPv6 address if we are always
- asked for IPv4 only, but let's deal with that later, if we
- have to. */
- aierr = system_getaddrinfo(name, "telnet", &myhints, &ai);
- if (aierr) {
- krb5int_unlock_fac();
- return aierr;
- }
- ce = malloc(sizeof(struct face));
- memset(ce, 0, sizeof(*ce));
- ce->expiration = time(0) + 30;
- for (ai2 = ai; ai2; ai2 = ai2->ai_next) {
-#ifdef DEBUG_ADDRINFO
- printf(" found an address in family %d...\n", ai2->ai_family);
-#endif
- switch (ai2->ai_family) {
- case AF_INET:
- ce->naddrs4++;
- break;
- case AF_INET6:
- ce->naddrs6++;
- break;
- default:
- break;
- }
- }
- ce->addrs4 = calloc(ce->naddrs4, sizeof(*ce->addrs4));
- if (ce->addrs4 == NULL && ce->naddrs4 != 0) {
- krb5int_unlock_fac();
- system_freeaddrinfo(ai);
- return EAI_MEMORY;
- }
- ce->addrs6 = calloc(ce->naddrs6, sizeof(*ce->addrs6));
- if (ce->addrs6 == NULL && ce->naddrs6 != 0) {
- krb5int_unlock_fac();
- free(ce->addrs4);
- system_freeaddrinfo(ai);
- return EAI_MEMORY;
- }
- for (ai2 = ai, i4 = i6 = 0; ai2; ai2 = ai2->ai_next) {
- switch (ai2->ai_family) {
- case AF_INET:
- ce->addrs4[i4++] = ((struct sockaddr_in *)ai2->ai_addr)->sin_addr;
- break;
- case AF_INET6:
- ce->addrs6[i6++] = ((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr;
- break;
- default:
- break;
- }
- }
- ce->canonname = ai->ai_canonname ? strdup(ai->ai_canonname) : 0;
- system_freeaddrinfo(ai);
- plant_face(name, ce);
- }
- template->ai_family = AF_INET6;
- template->ai_addrlen = sizeof(struct sockaddr_in6);
- for (i = 0; i < ce->naddrs6; i++) {
- r = fai_add_entry (result, &ce->addrs6[i], portnum, template);
- if (r) {
- krb5int_unlock_fac();
- return r;
- }
- }
- template->ai_family = AF_INET;
- template->ai_addrlen = sizeof(struct sockaddr_in);
- for (i = 0; i < ce->naddrs4; i++) {
- r = fai_add_entry (result, &ce->addrs4[i], portnum, template);
- if (r) {
- krb5int_unlock_fac();
- return r;
- }
- }
- if (*result && (flags & AI_CANONNAME))
- (*result)->ai_canonname = (ce->canonname
- ? strdup(ce->canonname)
- : NULL);
- krb5int_unlock_fac();
- return 0;
-
-#else
-
- struct hostent *hp;
- int i, r;
- int herr;
-
- GET_HOST_BY_NAME (name, hp, herr);
- if (hp == 0)
- return translate_h_errno (herr);
- for (i = 0; hp->h_addr_list[i]; i++) {
- r = fai_add_entry (result, hp->h_addr_list[i], portnum, template);
- if (r)
- return r;
- }
- if (*result && (flags & AI_CANONNAME))
- (*result)->ai_canonname = strdup (hp->h_name);
- return 0;
-
-#endif
-}
-
-static inline void
-fake_freeaddrinfo (struct addrinfo *ai)
-{
- struct addrinfo *next;
- while (ai) {
- next = ai->ai_next;
- if (ai->ai_canonname)
- free (ai->ai_canonname);
- if (ai->ai_addr)
- free (ai->ai_addr);
- free (ai);
- ai = next;
- }
-}
-
-static inline int
-fake_getaddrinfo (const char *name, const char *serv,
- const struct addrinfo *hint, struct addrinfo **result)
-{
- struct addrinfo *res = 0;
- int ret;
- int port = 0, socktype;
- int flags;
- struct addrinfo template;
-
-#ifdef DEBUG_ADDRINFO
- debug_dump_getaddrinfo_args(name, serv, hint);
-#endif
-
- if (hint != 0) {
- if (hint->ai_family != 0 && hint->ai_family != AF_INET)
- return EAI_NODATA;
- socktype = hint->ai_socktype;
- flags = hint->ai_flags;
- } else {
- socktype = 0;
- flags = 0;
- }
-
- if (serv) {
- size_t numlen = strspn (serv, "0123456789");
- if (serv[numlen] == '\0') {
- /* pure numeric */
- unsigned long p = strtoul (serv, 0, 10);
- if (p == 0 || p > 65535)
- return EAI_NONAME;
- port = htons (p);
- } else {
- struct servent *sp;
- int try_dgram_too = 0, s_err;
-
- if (socktype == 0) {
- try_dgram_too = 1;
- socktype = SOCK_STREAM;
- }
- try_service_lookup:
- GET_SERV_BY_NAME(serv, socktype == SOCK_STREAM ? "tcp" : "udp",
- sp, s_err);
- if (sp == 0) {
- if (try_dgram_too) {
- socktype = SOCK_DGRAM;
- goto try_service_lookup;
- }
- return EAI_SERVICE;
- }
- port = sp->s_port;
- }
- }
-
- if (name == 0) {
- name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1";
- flags |= AI_NUMERICHOST;
- }
-
- template.ai_family = AF_INET;
- template.ai_addrlen = sizeof (struct sockaddr_in);
- template.ai_socktype = socktype;
- template.ai_protocol = 0;
- template.ai_flags = 0;
- template.ai_canonname = 0;
- template.ai_next = 0;
- template.ai_addr = 0;
-
- /* If NUMERICHOST is set, parse a numeric address.
- If it's not set, don't accept such names. */
- if (flags & AI_NUMERICHOST) {
- struct in_addr addr4;
-#if 0
- ret = inet_aton (name, &addr4);
- if (ret)
- return EAI_NONAME;
-#else
- addr4.s_addr = inet_addr (name);
- if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1)
- /* 255.255.255.255 or parse error, both bad */
- return EAI_NONAME;
-#endif
- ret = fai_add_entry (&res, &addr4, port, &template);
- } else {
- ret = fai_add_hosts_by_name (name, &template, port, flags,
- &res);
- }
-
- if (ret && ret != NO_ADDRESS) {
- fake_freeaddrinfo (res);
- return ret;
- }
- if (res == 0)
- return NO_ADDRESS;
- *result = res;
- return 0;
-}
-
-#ifdef NEED_FAKE_GETNAMEINFO
-static inline int
-fake_getnameinfo (const struct sockaddr *sa, socklen_t len,
- char *host, socklen_t hostlen,
- char *service, socklen_t servicelen,
- int flags)
-{
- struct hostent *hp;
- const struct sockaddr_in *sinp;
- struct servent *sp;
- size_t hlen, slen;
-
- if (sa->sa_family != AF_INET) {
- return EAI_FAMILY;
- }
- sinp = (const struct sockaddr_in *) sa;
-
- hlen = hostlen;
- if (hostlen < 0 || hlen != hostlen) {
- errno = EINVAL;
- return EAI_SYSTEM;
- }
- slen = servicelen;
- if (servicelen < 0 || slen != servicelen) {
- errno = EINVAL;
- return EAI_SYSTEM;
- }
-
- if (host) {
- if (flags & NI_NUMERICHOST) {
-#if (defined(__GNUC__) && defined(__mips__)) || 1 /* thread safety always */
- /* The inet_ntoa call, passing a struct, fails on IRIX 6.5
- using gcc 2.95; we get back "0.0.0.0". Since this in a
- configuration still important at Athena, here's the
- workaround, which also happens to be thread-safe.... */
- const unsigned char *uc;
- char tmpbuf[20];
- numeric_host:
- uc = (const unsigned char *) &sinp->sin_addr;
- sprintf(tmpbuf, "%d.%d.%d.%d", uc[0], uc[1], uc[2], uc[3]);
- strncpy(host, tmpbuf, hlen);
-#else
- char *p;
- numeric_host:
- p = inet_ntoa (sinp->sin_addr);
- strncpy (host, p, hlen);
-#endif
- } else {
- int herr;
- GET_HOST_BY_ADDR((const char *) &sinp->sin_addr,
- sizeof (struct in_addr),
- sa->sa_family, hp, herr);
- if (hp == 0) {
- if (herr == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */
- goto numeric_host;
- return translate_h_errno (herr);
- }
- /* According to the Open Group spec, getnameinfo can
- silently truncate, but must still return a
- null-terminated string. */
- strncpy (host, hp->h_name, hlen);
- }
- host[hostlen-1] = 0;
- }
-
- if (service) {
- if (flags & NI_NUMERICSERV) {
- char numbuf[10];
- int port;
- numeric_service:
- port = ntohs (sinp->sin_port);
- if (port < 0 || port > 65535)
- return EAI_FAIL;
- sprintf (numbuf, "%d", port);
- strncpy (service, numbuf, slen);
- } else {
- int serr;
- GET_SERV_BY_PORT(sinp->sin_port,
- (flags & NI_DGRAM) ? "udp" : "tcp",
- sp, serr);
- if (sp == 0)
- goto numeric_service;
- strncpy (service, sp->s_name, slen);
- }
- service[servicelen-1] = 0;
- }
-
- return 0;
-}
-#endif
-
-#if defined(HAVE_FAKE_GETADDRINFO) || defined(NEED_FAKE_GETNAMEINFO)
-
-static inline
-char *gai_strerror (int code)
-{
- switch (code) {
- case EAI_ADDRFAMILY: return "address family for nodename not supported";
- case EAI_AGAIN: return "temporary failure in name resolution";
- case EAI_BADFLAGS: return "bad flags to getaddrinfo/getnameinfo";
- case EAI_FAIL: return "non-recoverable failure in name resolution";
- case EAI_FAMILY: return "ai_family not supported";
- case EAI_MEMORY: return "out of memory";
- case EAI_NODATA: return "no address associated with hostname";
- case EAI_NONAME: return "name does not exist";
- case EAI_SERVICE: return "service name not supported for specified socket type";
- case EAI_SOCKTYPE: return "ai_socktype not supported";
- case EAI_SYSTEM: return strerror (errno);
- default: return "bogus getaddrinfo error?";
- }
-}
-#endif
-
-static inline int translate_h_errno (int h)
-{
- switch (h) {
- case 0:
- return 0;
-#ifdef NETDB_INTERNAL
- case NETDB_INTERNAL:
- if (errno == ENOMEM)
- return EAI_MEMORY;
- return EAI_SYSTEM;
-#endif
- case HOST_NOT_FOUND:
- return EAI_NONAME;
- case TRY_AGAIN:
- return EAI_AGAIN;
- case NO_RECOVERY:
- return EAI_FAIL;
- case NO_DATA:
-#if NO_DATA != NO_ADDRESS
- case NO_ADDRESS:
-#endif
- return EAI_NODATA;
- default:
- return EAI_SYSTEM;
- }
-}
-
-#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
-static inline
-int getaddrinfo (const char *name, const char *serv,
- const struct addrinfo *hint, struct addrinfo **result)
-{
- return fake_getaddrinfo(name, serv, hint, result);
-}
-
-static inline
-void freeaddrinfo (struct addrinfo *ai)
-{
- fake_freeaddrinfo(ai);
-}
-
-#ifdef NEED_FAKE_GETNAMEINFO
-static inline
-int getnameinfo (const struct sockaddr *sa, socklen_t len,
- char *host, socklen_t hostlen,
- char *service, socklen_t servicelen,
- int flags)
-{
- return fake_getnameinfo(sa, len, host, hostlen, service, servicelen,
- flags);
-}
-#endif /* NEED_FAKE_GETNAMEINFO */
-#endif /* HAVE_FAKE_GETADDRINFO */
-#endif /* NEED_FAKE_GETADDRINFO */
-
-
-#ifdef WRAP_GETADDRINFO
-
-static inline
-int
-getaddrinfo (const char *name, const char *serv, const struct addrinfo *hint,
- struct addrinfo **result)
-{
- int aierr;
-#if defined(_AIX) || defined(COPY_FIRST_CANONNAME)
- struct addrinfo *ai;
-#endif
-#ifdef NUMERIC_SERVICE_BROKEN
- int service_is_numeric = 0;
- int service_port = 0;
- int socket_type = 0;
-#endif
-
-#ifdef DEBUG_ADDRINFO
- debug_dump_getaddrinfo_args(name, serv, hint);
-#endif
-
-#ifdef NUMERIC_SERVICE_BROKEN
- /* AIX 4.3.3 is broken. (Or perhaps out of date?)
-
- If a numeric service is provided, and it doesn't correspond to
- a known service name for tcp or udp (as appropriate), an error
- code (for "host not found") is returned. If the port maps to a
- known service for both udp and tcp, all is well. */
- if (serv && serv[0] && isdigit(serv[0])) {
- unsigned long lport;
- char *end;
- lport = strtoul(serv, &end, 10);
- if (!*end) {
- if (lport > 65535)
- return EAI_SOCKTYPE;
- service_is_numeric = 1;
- service_port = htons(lport);
- serv = "discard"; /* defined for both udp and tcp */
- if (hint)
- socket_type = hint->ai_socktype;
- }
- }
-#endif
-
- aierr = system_getaddrinfo (name, serv, hint, result);
- if (aierr || *result == 0) {
-#ifdef DEBUG_ADDRINFO
- debug_dump_error(aierr);
-#endif
- return aierr;
- }
-
- /* Linux libc version 6 (libc-2.2.4.so on Debian) is broken.
-
- RFC 2553 says that when AI_CANONNAME is set, the ai_canonname
- flag of the first returned structure has the canonical name of
- the host. Instead, GNU libc sets ai_canonname in each returned
- structure to the name that the corresponding address maps to,
- if any, or a printable numeric form.
-
- RFC 2553 bis and the new Open Group spec say that field will be
- the canonical name if it can be determined, otherwise, the
- provided hostname or a copy of it.
-
- IMNSHO, "canonical name" means CNAME processing and not PTR
- processing, but I can see arguing it. Using the numeric form
- when that's not the form provided is just wrong. So, let's fix
- it.
-
- The glibc 2.2.5 sources indicate that the canonical name is
- *not* allocated separately, it's just some extra storage tacked
- on the end of the addrinfo structure. So, let's try this
- approach: If getaddrinfo sets ai_canonname, we'll replace the
- *first* one with allocated storage, and free up that pointer in
- freeaddrinfo if it's set; the other ai_canonname fields will be
- left untouched. And we'll just pray that the application code
- won't mess around with the list structure; if we start doing
- that, we'll have to start replacing and freeing all of the
- ai_canonname fields.
-
- Ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=133668 .
-
- Since it's dependent on the target hostname, it's hard to check
- for at configure time. Always do it on Linux for now. When
- they get around to fixing it, add a compile-time or run-time
- check for the glibc version in use.
-
- Some Windows documentation says that even when AI_CANONNAME is
- set, the returned ai_canonname field can be null. The NetBSD
- 1.5 implementation also does this, if the input hostname is a
- numeric host address string. That case isn't handled well at
- the moment.
-
- Libc version 5 didn't have getaddrinfo at all. */
-
-#ifdef COPY_FIRST_CANONNAME
- /*
- * This code must *always* return an error, return a null
- * ai_canonname, or return an ai_canonname allocated here using
- * malloc, so that freeaddrinfo can always free a non-null
- * ai_canonname. Note that it really doesn't matter if the
- * AI_CANONNAME flag was set.
- */
- ai = *result;
- if (ai->ai_canonname) {
- struct hostent *hp;
- const char *name2 = 0;
- int i, herr;
-
- /*
- * Current versions of GET_HOST_BY_NAME will fail if the
- * target hostname has IPv6 addresses only. Make sure it
- * fails fairly cleanly.
- */
- GET_HOST_BY_NAME (name, hp, herr);
- if (hp == 0) {
- /*
- * This case probably means it's an IPv6-only name. If
- * ai_canonname is a numeric address, get rid of it.
- */
- if (ai->ai_canonname && strchr(ai->ai_canonname, ':'))
- ai->ai_canonname = 0;
- name2 = ai->ai_canonname ? ai->ai_canonname : name;
- } else {
- /* Sometimes gethostbyname will be directed to /etc/hosts
- first, and sometimes that file will have entries with
- the unqualified name first. So take the first entry
- that looks like it could be a FQDN. */
- for (i = 0; hp->h_aliases[i]; i++) {
- if (strchr(hp->h_aliases[i], '.') != 0) {
- name2 = hp->h_aliases[i];
- break;
- }
- }
- /* Give up, just use the first name (h_name ==
- h_aliases[0] on all systems I've seen). */
- if (hp->h_aliases[i] == 0)
- name2 = hp->h_name;
- }
-
- ai->ai_canonname = strdup(name2);
- if (name2 != 0 && ai->ai_canonname == 0) {
- system_freeaddrinfo(ai);
- *result = 0;
-#ifdef DEBUG_ADDRINFO
- debug_dump_error(EAI_MEMORY);
-#endif
- return EAI_MEMORY;
- }
- /* Zap the remaining ai_canonname fields glibc fills in, in
- case the application messes around with the list
- structure. */
- while ((ai = ai->ai_next) != NULL)
- ai->ai_canonname = 0;
- }
-#endif
-
-#ifdef NUMERIC_SERVICE_BROKEN
- if (service_port != 0) {
- for (ai = *result; ai; ai = ai->ai_next) {
- if (socket_type != 0 && ai->ai_socktype == 0)
- /* Is this check actually needed? */
- ai->ai_socktype = socket_type;
- switch (ai->ai_family) {
- case AF_INET:
- ((struct sockaddr_in *)ai->ai_addr)->sin_port = service_port;
- break;
- case AF_INET6:
- ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = service_port;
- break;
- }
- }
- }
-#endif
-
-#ifdef _AIX
- for (ai = *result; ai; ai = ai->ai_next) {
- /* AIX 4.3.3 libc is broken. It doesn't set the family or len
- fields of the sockaddr structures. Usually, sa_family is
- zero, but I've seen it set to 1 in some cases also (maybe
- just leftover from previous contents of the memory
- block?). So, always override what libc returned. */
- ai->ai_addr->sa_family = ai->ai_family;
-#ifdef HAVE_SA_LEN /* always true on AIX, actually */
- ai->ai_addr->sa_len = ai->ai_addrlen;
-#endif
- }
-#endif
-
- /* Not dealt with currently:
-
- - Some versions of GNU libc can lose some IPv4 addresses in
- certain cases when multiple IPv4 and IPv6 addresses are
- available. */
-
-#ifdef DEBUG_ADDRINFO
- debug_dump_addrinfos(*result);
-#endif
-
- return 0;
-}
-
-static inline
-void freeaddrinfo (struct addrinfo *ai)
-{
-#ifdef COPY_FIRST_CANONNAME
- if (ai) {
- free(ai->ai_canonname);
- ai->ai_canonname = 0;
- system_freeaddrinfo(ai);
- }
-#else
- system_freeaddrinfo(ai);
-#endif
-}
-#endif /* WRAP_GETADDRINFO */
-
#if defined(KRB5_USE_INET6) && defined(NEED_INSIXADDR_ANY)
/* If compiling with IPv6 support and C library does not define in6addr_any */
+extern const struct in6_addr krb5int_in6addr_any;
#undef in6addr_any
#define in6addr_any krb5int_in6addr_any
-static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
#endif
-#ifdef ADDRINFO_UNDEF_INLINE
-# undef inline
-# undef ADDRINFO_UNDEF_INLINE
+/* Call out to stuff defined in libkrb5support. */
+extern int krb5int_getaddrinfo (const char *node, const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **aip);
+extern void krb5int_freeaddrinfo (struct addrinfo *ai);
+extern const char *krb5int_gai_strerror(int err);
+extern int krb5int_getnameinfo (const struct sockaddr *sa, socklen_t salen,
+ char *hbuf, size_t hbuflen,
+ char *sbuf, size_t sbuflen,
+ int flags);
+#ifndef IMPLEMENT_FAKE_GETADDRINFO
+#undef getaddrinfo
+#define getaddrinfo krb5int_getaddrinfo
+#undef freeaddrinfo
+#define freeaddrinfo krb5int_freeaddrinfo
+#undef gai_strerror
+#define gai_strerror krb5int_gai_strerror
+#undef getnameinfo
+#define getnameinfo krb5int_getnameinfo
#endif
#endif /* FAI_DEFINED */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/k5-int-pkinit.h b/usr/src/lib/gss_mechs/mech_krb5/include/k5-int-pkinit.h
new file mode 100644
index 0000000000..e6d65840eb
--- /dev/null
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/k5-int-pkinit.h
@@ -0,0 +1,271 @@
+
+/*
+ * COPYRIGHT (C) 2006
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifndef _KRB5_INT_PKINIT_H
+#define _KRB5_INT_PKINIT_H
+
+/*
+ * pkinit structures
+ */
+
+/* PKAuthenticator */
+typedef struct _krb5_pk_authenticator {
+ krb5_int32 cusec; /* (0..999999) */
+ krb5_timestamp ctime;
+ krb5_int32 nonce; /* (0..4294967295) */
+ krb5_checksum paChecksum;
+} krb5_pk_authenticator;
+
+/* PKAuthenticator draft9 */
+typedef struct _krb5_pk_authenticator_draft9 {
+ krb5_principal kdcName;
+ krb5_octet_data kdcRealm;
+ krb5_int32 cusec; /* (0..999999) */
+ krb5_timestamp ctime;
+ krb5_int32 nonce; /* (0..4294967295) */
+} krb5_pk_authenticator_draft9;
+
+/* AlgorithmIdentifier */
+typedef struct _krb5_algorithm_identifier {
+ krb5_octet_data algorithm; /* OID */
+ krb5_octet_data parameters; /* Optional */
+} krb5_algorithm_identifier;
+
+/* SubjectPublicKeyInfo */
+typedef struct _krb5_subject_pk_info {
+ krb5_algorithm_identifier algorithm;
+ krb5_octet_data subjectPublicKey; /* BIT STRING */
+} krb5_subject_pk_info;
+
+/* AuthPack */
+typedef struct _krb5_auth_pack {
+ krb5_pk_authenticator pkAuthenticator;
+ krb5_subject_pk_info *clientPublicValue; /* Optional */
+ krb5_algorithm_identifier **supportedCMSTypes; /* Optional */
+ krb5_octet_data clientDHNonce; /* Optional */
+} krb5_auth_pack;
+
+/* AuthPack draft9 */
+typedef struct _krb5_auth_pack_draft9 {
+ krb5_pk_authenticator_draft9 pkAuthenticator;
+ krb5_subject_pk_info *clientPublicValue; /* Optional */
+} krb5_auth_pack_draft9;
+
+/* ExternalPrincipalIdentifier */
+typedef struct _krb5_external_principal_identifier {
+ krb5_octet_data subjectName; /* Optional */
+ krb5_octet_data issuerAndSerialNumber; /* Optional */
+ krb5_octet_data subjectKeyIdentifier; /* Optional */
+} krb5_external_principal_identifier;
+
+/* TrustedCas */
+typedef struct _krb5_trusted_ca {
+ enum {
+ choice_trusted_cas_UNKNOWN = -1,
+ choice_trusted_cas_principalName = 0,
+ choice_trusted_cas_caName = 1,
+ choice_trusted_cas_issuerAndSerial = 2
+ } choice;
+ union {
+ krb5_principal principalName;
+ krb5_octet_data caName; /* fully-qualified X.500 "Name" as defined by X.509 (der-encoded) */
+ krb5_octet_data issuerAndSerial; /* Optional -- IssuerAndSerialNumber (der-encoded) */
+ } u;
+} krb5_trusted_ca;
+
+/* typed data */
+typedef struct _krb5_typed_data {
+ krb5_magic magic;
+ krb5_int32 type;
+ unsigned int length;
+ krb5_octet *data;
+} krb5_typed_data;
+
+/* PA-PK-AS-REQ (Draft 9 -- PA TYPE 14) */
+typedef struct _krb5_pa_pk_as_req_draft9 {
+ krb5_octet_data signedAuthPack;
+ krb5_trusted_ca **trustedCertifiers; /* Optional array */
+ krb5_octet_data kdcCert; /* Optional */
+ krb5_octet_data encryptionCert;
+} krb5_pa_pk_as_req_draft9;
+
+/* PA-PK-AS-REQ (rfc4556 -- PA TYPE 16) */
+typedef struct _krb5_pa_pk_as_req {
+ krb5_octet_data signedAuthPack;
+ krb5_external_principal_identifier **trustedCertifiers; /* Optional array */
+ krb5_octet_data kdcPkId; /* Optional */
+} krb5_pa_pk_as_req;
+
+/* DHRepInfo */
+typedef struct _krb5_dh_rep_info {
+ krb5_octet_data dhSignedData;
+ krb5_octet_data serverDHNonce; /* Optional */
+} krb5_dh_rep_info;
+
+/* KDCDHKeyInfo */
+typedef struct _krb5_kdc_dh_key_info {
+ krb5_octet_data subjectPublicKey; /* BIT STRING */
+ krb5_int32 nonce; /* (0..4294967295) */
+ krb5_timestamp dhKeyExpiration; /* Optional */
+} krb5_kdc_dh_key_info;
+
+/* KDCDHKeyInfo draft9*/
+typedef struct _krb5_kdc_dh_key_info_draft9 {
+ krb5_octet_data subjectPublicKey; /* BIT STRING */
+ krb5_int32 nonce; /* (0..4294967295) */
+} krb5_kdc_dh_key_info_draft9;
+
+/* ReplyKeyPack */
+typedef struct _krb5_reply_key_pack {
+ krb5_keyblock replyKey;
+ krb5_checksum asChecksum;
+} krb5_reply_key_pack;
+
+/* ReplyKeyPack */
+typedef struct _krb5_reply_key_pack_draft9 {
+ krb5_keyblock replyKey;
+ krb5_int32 nonce;
+} krb5_reply_key_pack_draft9;
+
+/* PA-PK-AS-REP (Draft 9 -- PA TYPE 15) */
+typedef struct _krb5_pa_pk_as_rep_draft9 {
+ enum {
+ choice_pa_pk_as_rep_draft9_UNKNOWN = -1,
+ choice_pa_pk_as_rep_draft9_dhSignedData = 0,
+ choice_pa_pk_as_rep_draft9_encKeyPack = 1
+ } choice;
+ union {
+ krb5_octet_data dhSignedData;
+ krb5_octet_data encKeyPack;
+ } u;
+} krb5_pa_pk_as_rep_draft9;
+
+/* PA-PK-AS-REP (rfc4556 -- PA TYPE 17) */
+typedef struct _krb5_pa_pk_as_rep {
+ enum {
+ choice_pa_pk_as_rep_UNKNOWN = -1,
+ choice_pa_pk_as_rep_dhInfo = 0,
+ choice_pa_pk_as_rep_encKeyPack = 1
+ } choice;
+ union {
+ krb5_dh_rep_info dh_Info;
+ krb5_octet_data encKeyPack;
+ } u;
+} krb5_pa_pk_as_rep;
+
+/*
+ * Begin "asn1.h"
+ */
+
+/*************************************************************************
+ * Prototypes for pkinit asn.1 encode routines
+ *************************************************************************/
+
+krb5_error_code encode_krb5_pa_pk_as_req
+ (const krb5_pa_pk_as_req *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_pa_pk_as_req_draft9
+ (const krb5_pa_pk_as_req_draft9 *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_pa_pk_as_rep
+ (const krb5_pa_pk_as_rep *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_pa_pk_as_rep_draft9
+ (const krb5_pa_pk_as_rep_draft9 *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_auth_pack
+ (const krb5_auth_pack *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_auth_pack_draft9
+ (const krb5_auth_pack_draft9 *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_kdc_dh_key_info
+ (const krb5_kdc_dh_key_info *rep, krb5_data **code);
+
+krb5_error_code encode_krb5_reply_key_pack
+ (const krb5_reply_key_pack *, krb5_data **code);
+
+krb5_error_code encode_krb5_reply_key_pack_draft9
+ (const krb5_reply_key_pack_draft9 *, krb5_data **code);
+
+krb5_error_code encode_krb5_typed_data
+ (const krb5_typed_data **, krb5_data **code);
+
+krb5_error_code encode_krb5_td_trusted_certifiers
+ (const krb5_external_principal_identifier **, krb5_data **code);
+
+krb5_error_code encode_krb5_td_dh_parameters
+ (const krb5_algorithm_identifier **, krb5_data **code);
+
+/*************************************************************************
+ * Prototypes for pkinit asn.1 decode routines
+ *************************************************************************/
+
+krb5_error_code decode_krb5_pa_pk_as_req
+ (const krb5_data *, krb5_pa_pk_as_req **);
+
+krb5_error_code decode_krb5_pa_pk_as_req_draft9
+ (const krb5_data *, krb5_pa_pk_as_req_draft9 **);
+
+krb5_error_code decode_krb5_pa_pk_as_rep
+ (const krb5_data *, krb5_pa_pk_as_rep **);
+
+krb5_error_code decode_krb5_pa_pk_as_rep_draft9
+ (const krb5_data *, krb5_pa_pk_as_rep_draft9 **);
+
+krb5_error_code decode_krb5_auth_pack
+ (const krb5_data *, krb5_auth_pack **);
+
+krb5_error_code decode_krb5_auth_pack_draft9
+ (const krb5_data *, krb5_auth_pack_draft9 **);
+
+krb5_error_code decode_krb5_kdc_dh_key_info
+ (const krb5_data *, krb5_kdc_dh_key_info **);
+
+krb5_error_code decode_krb5_principal_name
+ (const krb5_data *, krb5_principal_data **);
+
+krb5_error_code decode_krb5_reply_key_pack
+ (const krb5_data *, krb5_reply_key_pack **);
+
+krb5_error_code decode_krb5_reply_key_pack_draft9
+ (const krb5_data *, krb5_reply_key_pack_draft9 **);
+
+krb5_error_code decode_krb5_typed_data
+ (const krb5_data *, krb5_typed_data ***);
+
+krb5_error_code decode_krb5_td_trusted_certifiers
+ (const krb5_data *, krb5_external_principal_identifier ***);
+
+krb5_error_code decode_krb5_td_dh_parameters
+ (const krb5_data *, krb5_algorithm_identifier ***);
+
+#endif /* _KRB5_INT_PKINIT_H */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/krb5/adm_proto.h b/usr/src/lib/gss_mechs/mech_krb5/include/krb5/adm_proto.h
index 5f981669d7..f2bd465f73 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/include/krb5/adm_proto.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/krb5/adm_proto.h
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* include/krb5/adm_proto.h
*
@@ -36,7 +35,7 @@ struct _krb5_db_entry;
typedef struct _krb5_db_entry krb5_db_entry;
#endif /* KRB5_KDB5__ */
-/* Ditto for adm.h or kadm5/admin.h */
+/* Ditto for adm.h */
/*
* XXXX krb5_realm params is defined in two header files!!!!
@@ -56,96 +55,12 @@ typedef struct ___krb5_key_salt_tuple krb5_key_salt_tuple;
* Function prototypes.
*/
-/* adm_conn.c */
-krb5_error_code KRB5_CALLCONV krb5_adm_connect
- (krb5_context,
- char *,
- char *,
- char *,
- int *,
- krb5_auth_context *,
- krb5_ccache *,
- char *,
- krb5_timestamp);
- void KRB5_CALLCONV krb5_adm_disconnect
- (krb5_context,
- int *,
- krb5_auth_context,
- krb5_ccache);
-
-#if !defined(_MSDOS) && !defined(_WIN32) && !defined(macintosh)
-/* adm_kw_dec.c */
-krb5_error_code krb5_adm_proto_to_dbent
- (krb5_context,
- krb5_int32,
- krb5_data *,
- krb5_ui_4 *,
- krb5_db_entry *,
- char **);
-
-/* adm_kw_enc.c */
-krb5_error_code krb5_adm_dbent_to_proto
- (krb5_context,
- krb5_ui_4,
- krb5_db_entry *,
- char *,
- krb5_int32 *,
- krb5_data **);
-#endif /* !(windows or macintosh) */
-
-/* adm_kt_dec.c */
-krb5_error_code krb5_adm_proto_to_ktent
- (krb5_context,
- krb5_int32,
- krb5_data *,
- krb5_keytab_entry *);
-
-/* adm_kt_enc.c */
-krb5_error_code krb5_adm_ktent_to_proto
- (krb5_context,
- krb5_keytab_entry *,
- krb5_int32 *,
- krb5_data **);
-
-/* adm_rw.c */
-void KRB5_CALLCONV krb5_free_adm_data
- (krb5_context,
- krb5_int32,
- krb5_data *);
-
-krb5_error_code KRB5_CALLCONV krb5_send_adm_cmd
- (krb5_context,
- krb5_pointer,
- krb5_auth_context,
- krb5_int32,
- krb5_data *);
-krb5_error_code krb5_send_adm_reply
- (krb5_context,
- krb5_pointer,
- krb5_auth_context,
- krb5_int32,
- krb5_int32,
- krb5_data *);
-krb5_error_code krb5_read_adm_cmd
- (krb5_context,
- krb5_pointer,
- krb5_auth_context,
- krb5_int32 *,
- krb5_data **);
-krb5_error_code KRB5_CALLCONV krb5_read_adm_reply
- (krb5_context,
- krb5_pointer,
- krb5_auth_context,
- krb5_int32 *,
- krb5_int32 *,
- krb5_data **);
-
/* logger.c */
krb5_error_code krb5_klog_init
(krb5_context,
- char *,
- char *,
- krb5_boolean);
+ char *,
+ char *,
+ krb5_boolean);
void krb5_klog_close (krb5_context);
int krb5_klog_syslog (int, const char *, ...);
void krb5_klog_reopen (krb5_context);
@@ -155,65 +70,63 @@ krb5_error_code krb5_aprof_init
(char *, char *, krb5_pointer *);
krb5_error_code krb5_aprof_getvals
(krb5_pointer, const char **, char ***);
+krb5_error_code krb5_aprof_get_boolean
+ (krb5_pointer, const char **, int, krb5_boolean *);
krb5_error_code krb5_aprof_get_deltat
(krb5_pointer,
- const char **,
- krb5_boolean,
- krb5_deltat *);
+ const char **,
+ krb5_boolean,
+ krb5_deltat *);
krb5_error_code krb5_aprof_get_string
(krb5_pointer, const char **, krb5_boolean, char **);
krb5_error_code krb5_aprof_get_int32
(krb5_pointer,
- const char **,
- krb5_boolean,
- krb5_int32 *);
+ const char **,
+ krb5_boolean,
+ krb5_int32 *);
krb5_error_code krb5_aprof_finish (krb5_pointer);
krb5_error_code krb5_read_realm_params (krb5_context,
- char *,
- char *,
- char *,
- krb5_realm_params **);
+ char *,
+ krb5_realm_params **);
krb5_error_code krb5_free_realm_params (krb5_context,
- krb5_realm_params *);
+ krb5_realm_params *);
/* str_conv.c */
krb5_error_code
krb5_string_to_flags (char *,
- const char *,
- const char *,
- krb5_flags *);
+ const char *,
+ const char *,
+ krb5_flags *);
krb5_error_code
krb5_flags_to_string (krb5_flags,
- const char *,
- char *,
- size_t);
+ const char *,
+ char *,
+ size_t);
krb5_error_code
krb5_input_flag_to_string (int,
- char *,
- size_t);
+ char *,
+ size_t);
/* keysalt.c */
krb5_boolean
krb5_keysalt_is_present (krb5_key_salt_tuple *,
- krb5_int32,
- krb5_enctype,
- krb5_int32);
+ krb5_int32,
+ krb5_enctype,
+ krb5_int32);
krb5_error_code
-krb5_keysalt_iterate
- (krb5_key_salt_tuple *,
- krb5_int32,
- krb5_boolean,
- krb5_error_code (*)
- (krb5_key_salt_tuple *,
- krb5_pointer),
- krb5_pointer);
+krb5_keysalt_iterate (krb5_key_salt_tuple *,
+ krb5_int32,
+ krb5_boolean,
+ krb5_error_code (*) (krb5_key_salt_tuple *,
+ krb5_pointer),
+ krb5_pointer);
krb5_error_code
krb5_string_to_keysalts (char *,
- const char *,
- const char *,
- krb5_boolean,
- krb5_key_salt_tuple **,
- krb5_int32 *);
+ const char *,
+ const char *,
+ krb5_boolean,
+ krb5_key_salt_tuple **,
+ krb5_int32 *);
#endif /* KRB5_ADM_PROTO_H__ */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/krb5/kdb.h b/usr/src/lib/gss_mechs/mech_krb5/include/krb5/kdb.h
index a54eef98bd..c68914f143 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/include/krb5/kdb.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/krb5/kdb.h
@@ -61,9 +61,6 @@
#ifndef KRB5_KDB5__
#define KRB5_KDB5__
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-
/* Salt types */
#define KRB5_KDB_SALTTYPE_NORMAL 0
#define KRB5_KDB_SALTTYPE_V4 1
@@ -92,8 +89,6 @@
#define KRB5_KDB_CREATE_BTREE 0x00000001
#define KRB5_KDB_CREATE_HASH 0x00000002
-#if !defined(_WIN32)
-
/*
* Note --- these structures cannot be modified without changing the
* database version number in libkdb.a, but should be expandable by
@@ -138,7 +133,7 @@ typedef struct _krb5_keysalt {
typedef struct _krb5_db_entry_new {
krb5_magic magic; /* NOT saved */
krb5_ui_2 len;
- krb5_ui_4 mask; /* members currently changed/set */
+ krb5_ui_4 mask; /* members currently changed/set */
krb5_flags attributes;
krb5_deltat max_life;
krb5_deltat max_renewable_life;
@@ -174,6 +169,7 @@ typedef struct __krb5_key_salt_tuple {
#define KRB5_TL_SECURID_STATE 0x0006
#define KRB5_TL_DB_ARGS 0x7fff
#endif /* SECURID */
+#define KRB5_TL_USER_CERTIFICATE 0x0007
/*
* Determines the number of failed KDC requests before DISALLOW_ALL_TIX is set
@@ -188,6 +184,7 @@ typedef struct __krb5_key_salt_tuple {
#define KRB5_KDC_MKEY_1 "Enter KDC database master key"
#define KRB5_KDC_MKEY_2 "Re-enter KDC database master key to verify"
+
extern char *krb5_mkey_pwd_prompt1;
extern char *krb5_mkey_pwd_prompt2;
@@ -196,6 +193,7 @@ extern char *krb5_mkey_pwd_prompt2;
*
* Data encoding is little-endian.
*/
+#include "k5-platform.h"
#define krb5_kdb_decode_int16(cp, i16) \
*((krb5_int16 *) &(i16)) = (((krb5_int16) ((unsigned char) (cp)[0]))| \
((krb5_int16) ((unsigned char) (cp)[1]) << 8))
@@ -536,5 +534,4 @@ krb5_db_free_policy( krb5_context kcontext,
#define KRB5_KDB_DEF_FLAGS 0
-#endif /* !defined(_WIN32) */
#endif /* KRB5_KDB5__ */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/locate_plugin.h b/usr/src/lib/gss_mechs/mech_krb5/include/locate_plugin.h
new file mode 100644
index 0000000000..cec24c9fce
--- /dev/null
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/locate_plugin.h
@@ -0,0 +1,61 @@
+
+/*
+ * <krb5/locate_plugin.h>
+ *
+ * Copyright 2006 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.
+ *
+ *
+ * Service location plugin definitions for Kerberos 5.
+ */
+
+#ifndef KRB5_LOCATE_PLUGIN_H_INCLUDED
+#define KRB5_LOCATE_PLUGIN_H_INCLUDED
+#include <krb5.h>
+
+enum locate_service_type {
+ locate_service_kdc = 1,
+ locate_service_master_kdc,
+ locate_service_kadmin,
+ locate_service_krb524,
+ locate_service_kpasswd
+};
+
+typedef struct krb5plugin_service_locate_ftable {
+ int minor_version; /* currently 0 */
+ /* Per-context setup and teardown. Returned void* blob is
+ private to the plugin. */
+ krb5_error_code (*init)(krb5_context, void **);
+ void (*fini)(void *);
+ /* Callback function returns non-zero if the plugin function
+ should quit and return; this may be because of an error, or may
+ indicate we've already contacted the service, whatever. The
+ lookup function should only return an error if it detects a
+ problem, not if the callback function tells it to quit. */
+ krb5_error_code (*lookup)(void *,
+ enum locate_service_type svc, const char *realm,
+ int socktype, int family,
+ int (*cbfunc)(void *,int,struct sockaddr *),
+ void *cbdata);
+} krb5plugin_service_locate_ftable;
+/* extern krb5plugin_service_locate_ftable service_locator; */
+#endif
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/osconf.h b/usr/src/lib/gss_mechs/mech_krb5/include/osconf.h
index e16e3f5f2c..524bcdc4d1 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/include/osconf.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/osconf.h
@@ -1,28 +1,20 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#ifndef _KRB5_OSCONF_H
-#define _KRB5_OSCONF_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
/*
* include/krb5/stock/osconf.h
*
- * Copyright 1990, 1991 by the Massachusetts Institute of Technology.
+ * Copyright 1990,1991 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
@@ -30,39 +22,72 @@ extern "C" {
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
- *
+ *
*
* Site- and OS- dependant configuration.
*/
+#ifndef KRB5_OSCONF__
+#define KRB5_OSCONF__
-/* Don't try to pull in autoconf.h for Windows, since it's not used */
+#if !defined(_WIN32)
+ /* Don't try to pull in autoconf.h for Windows, since it's not used */
#ifndef KRB5_AUTOCONF__
-#define KRB5_AUTOCONF__
+#define KRB5_AUTOCONF__
#include "autoconf.h"
#endif
+#endif
+
+#if defined(__MACH__) && defined(__APPLE__)
+# include <TargetConditionals.h>
+#endif
-#define DEFAULT_SECURE_PROFILE_PATH "/etc/krb5/krb5.conf"
-#define DEFAULT_PROFILE_PATH DEFAULT_SECURE_PROFILE_PATH
+#if defined(_WIN32)
+#define DEFAULT_PROFILE_FILENAME "krb5.ini"
+#define DEFAULT_LNAME_FILENAME "/aname"
+#define DEFAULT_KEYTAB_NAME "FILE:%s\\krb5kt"
+#else /* !_WINDOWS */
+#if TARGET_OS_MAC
+#define DEFAULT_SECURE_PROFILE_PATH "/Library/Preferences/edu.mit.Kerberos:/etc/krb5.conf:@SYSCONFDIR/krb5.conf"
+#define DEFAULT_PROFILE_PATH ("~/Library/Preferences/edu.mit.Kerberos" ":" DEFAULT_SECURE_PROFILE_PATH)
+#define KRB5_PLUGIN_BUNDLE_DIR "/System/Library/KerberosPlugins/KerberosFrameworkPlugins"
+#define KDB5_PLUGIN_BUNDLE_DIR "/System/Library/KerberosPlugins/KerberosDatabasePlugins"
+#else
+/* Solaris Kerberos */
+#define DEFAULT_SECURE_PROFILE_PATH "/etc/krb5/krb5.conf"
+#define DEFAULT_PROFILE_PATH DEFAULT_SECURE_PROFILE_PATH
+#endif
+/* Solaris Kerberos */
#define DEFAULT_KEYTAB_NAME "FILE:/etc/krb5/krb5.keytab"
-#define DEFAULT_KEYTAB "WRFILE:/etc/krb5/krb5.keytab"
+#endif /* _WINDOWS */
/* Solaris Kerberos: default for where ldap bind passwds stored */
#define DEF_SERVICE_PASSWD_FILE "/var/krb5/service_passwd"
-
-#define DEFAULT_KDB_FILE "/var/krb5/principal"
+/* Solaris Kerberos */
+#define DEFAULT_KDB_FILE "/var/krb5/principal"
#define DEFAULT_KEYFILE_STUB "/var/krb5/.k5."
-#define KRB5_DEFAULT_ADMIN_ACL "/etc/krb5/krb5_adm.acl"
+#define KRB5_DEFAULT_ADMIN_ACL "/etc/krb5/krb5_adm.acl"
+
+#define DEFAULT_ADMIN_ACL "@LOCALSTATEDIR/krb5kdc/kadm_old.acl"
/* Location of KDC profile */
+/* Solaris Kerberos */
#define DEFAULT_KDC_PROFILE "/etc/krb5/kdc.conf"
#define KDC_PROFILE_ENV "KRB5_KDC_PROFILE"
+#if TARGET_OS_MAC
+#define DEFAULT_KDB_LIB_PATH { KDB5_PLUGIN_BUNDLE_DIR, "@MODULEDIR/kdb", NULL }
+#else
+/* Solaris Kerberos */
#define DEFAULT_KDB_LIB_PATH { "/usr/lib/krb5", NULL }
+#endif
/*
* SUNW14resync
@@ -72,20 +97,20 @@ extern "C" {
#define DEFAULT_KDC_ENCTYPE ENCTYPE_DES_CBC_CRC
#define KDCRCACHE "dfl:krb5kdc_rcache"
-#define KDC_PORTNAME "kerberos" /* for /etc/services or equiv. */
-#define KDC_SECONDARY_PORTNAME "kerberos-sec" /* For backwards */
+#define KDC_PORTNAME "kerberos" /* for /etc/services or equiv. */
+#define KDC_SECONDARY_PORTNAME "kerberos-sec" /* For backwards */
/* compatibility with */
/* port 750 clients */
-#define DEFAULT_KPASSWD_PORT 464 /* assigned by IANA */
-#define KPASSWD_PORTNAME "kpasswd"
+#define KRB5_DEFAULT_PORT 88
+#define KRB5_DEFAULT_SEC_PORT 750
-#define KRB5_DEFAULT_PORT 88
-#define KRB5_DEFAULT_SEC_PORT 750
+#define DEFAULT_KPASSWD_PORT 464
+#define KPASSWD_PORTNAME "kpasswd"
-#define DEFAULT_KDC_UDP_PORTLIST "88, 750"
+#define DEFAULT_KDC_UDP_PORTLIST "88,750"
/* Solaris Kerberos: enabled TCP by default on port 88 */
-#define DEFAULT_KDC_TCP_PORTLIST "88"
+#define DEFAULT_KDC_TCP_PORTLIST "88"
/* Solaris Kerberos: control # of kdc tcp connection */
#define DEFAULT_KDC_TCP_CONNECTIONS 30
@@ -94,31 +119,28 @@ extern "C" {
/*
* Defaults for the KADM5 admin system.
*/
-#define DEFAULT_KADM5_KEYTAB "/etc/krb5/kadm5.keytab"
-#define DEFAULT_KADM5_ACL_FILE "/etc/krb5/kadm5.acl"
-#define DEFAULT_KADM5_PORT 749 /* assigned by IANA */
+/* Solaris Kerberos */
+#define DEFAULT_KADM5_KEYTAB "/etc/krb5/kadm5.keytab"
+#define DEFAULT_KADM5_ACL_FILE "/etc/krb5/kadm5.acl"
+#define DEFAULT_KADM5_PORT 749 /* assigned by IANA */
-#define MAX_DGRAM_SIZE 4096
-#define MAX_SKDC_TIMEOUT 30
-#define SKDC_TIMEOUT_SHIFT 2 /* left shift of timeout for backoff */
-#define SKDC_TIMEOUT_1 1 /* seconds for first timeout */
+#define MAX_DGRAM_SIZE 4096
+#define MAX_SKDC_TIMEOUT 30
+#define SKDC_TIMEOUT_SHIFT 2 /* left shift of timeout for backoff */
+#define SKDC_TIMEOUT_1 1 /* seconds for first timeout */
-#define KRB5_ENV_CCNAME "KRB5CCNAME"
+#define KRB5_ENV_CCNAME "KRB5CCNAME"
/*
* krb5 slave support follows
*/
-#define KPROP_DEFAULT_FILE "/var/krb5/slave_datatrans"
-#define KPROPD_DEFAULT_FILE "/var/krb5/from_master"
-#define KPROPD_DEFAULT_KDB5_UTIL "/usr/sbin/kdb5_util"
-#define KPROPD_DEFAULT_KRB_DB DEFAULT_KDB_FILE
-#define KPROPD_ACL_FILE "/etc/krb5/kpropd.acl"
-
-#define HAVE_GETEUID 1
-
-#ifdef __cplusplus
-}
-#endif
+/* Solaris Kerberos */
+#define KPROP_DEFAULT_FILE "/var/krb5/slave_datatrans"
+#define KPROPD_DEFAULT_FILE "/var/krb5/from_master"
+#define KPROPD_DEFAULT_KDB5_UTIL "/usr/sbin/kdb5_util"
+#define KPROPD_DEFAULT_KDB5_EDIT "/usr/sbin/kdb5_edit"
+#define KPROPD_DEFAULT_KRB_DB DEFAULT_KDB_FILE
+#define KPROPD_ACL_FILE "/etc/krb5/kpropd.acl"
-#endif /* !_KRB5_OSCONF_H */
+#endif /* KRB5_OSCONF__ */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/port-sockets.h b/usr/src/lib/gss_mechs/mech_krb5/include/port-sockets.h
index 02b39d4e33..d901d3c5d5 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/include/port-sockets.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/port-sockets.h
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
#ifndef _PORT_SOCKET_H
#define _PORT_SOCKET_H
@@ -67,12 +66,18 @@ typedef WSABUF sg_buf;
#define ETIMEDOUT WSAETIMEDOUT
#endif
-#else /* not _WIN32 */
+#elif defined(__palmos__)
/* If this source file requires it, define struct sockaddr_in
(and possibly other things related to network I/O). */
#include "autoconf.h"
+#include <netdb.h>
+typedef int socklen_t;
+
+#else /* UNIX variants */
+
+#include "autoconf.h"
#include <sys/types.h>
#include <netinet/in.h> /* For struct sockaddr_in and in_addr */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/preauth_plugin.h b/usr/src/lib/gss_mechs/mech_krb5/include/preauth_plugin.h
new file mode 100644
index 0000000000..5b15ceedb5
--- /dev/null
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/preauth_plugin.h
@@ -0,0 +1,508 @@
+
+/*
+ * <krb5/preauth_plugin.h>
+ *
+ * Copyright (c) 2006 Red Hat, Inc.
+ * Portions copyright (c) 2006 Massachusetts Institute of Technology
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Red Hat, Inc., nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+ * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+ * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Preauthentication plugin definitions for Kerberos 5.
+ */
+
+#ifndef KRB5_PREAUTH_PLUGIN_H_INCLUDED
+#define KRB5_PREAUTH_PLUGIN_H_INCLUDED
+#include <krb5.h>
+
+/*
+ * While arguments of these types are passed-in, for the most part a preauth
+ * module can treat them as opaque. If we need keying data, we can ask for
+ * it directly.
+ */
+struct _krb5_db_entry_new;
+struct _krb5_key_data;
+struct _krb5_preauth_client_rock;
+
+/*
+ * Preauth mechanism property flags, unified from previous definitions in the
+ * KDC and libkrb5 sources.
+ */
+
+/* Provides a real answer which we can send back to the KDC (client-only). The
+ * client assumes that one real answer will be enough. */
+#define PA_REAL 0x00000001
+
+/* Doesn't provide a real answer, but must be given a chance to run before any
+ * REAL mechanism callbacks (client-only). */
+#define PA_INFO 0x00000002
+
+/* Causes the KDC to include this mechanism in a list of supported preauth
+ * types if the user's DB entry flags the user as requiring hardware-based
+ * preauthentication (server-only). */
+#define PA_HARDWARE 0x00000004
+
+/* Causes the KDC to include this mechanism in a list of supported preauth
+ * types if the user's DB entry flags the user as requiring preauthentication,
+ * and to fail preauthentication if we can't verify the client data. The
+ * flipside of PA_SUFFICIENT (server-only). */
+#define PA_REQUIRED 0x00000008
+
+/* Causes the KDC to include this mechanism in a list of supported preauth
+ * types if the user's DB entry flags the user as requiring preauthentication,
+ * and to mark preauthentication as successful if we can verify the client
+ * data. The flipside of PA_REQUIRED (server-only). */
+#define PA_SUFFICIENT 0x00000010
+
+/* Marks this preauthentication mechanism as one which changes the key which is
+ * used for encrypting the response to the client. Modules which have this
+ * flag have their server_return_proc called before modules which do not, and
+ * are passed over if a previously-called module has modified the encrypting
+ * key (server-only). */
+#define PA_REPLACES_KEY 0x00000020
+
+/* Causes the KDC to check with this preauthentication module even if the
+ * client has no entry in the realm database. If the module returns a success
+ * code, continue processing and assume that its return_padata callback will
+ * supply us with a key for encrypting the AS reply (server-only). */
+/* #define PA_VIRTUAL (0x00000040 | PA_REPLACES_KEY) */
+
+/* Not really a padata type, so don't include it in any list of preauth types
+ * which gets sent over the wire. */
+#define PA_PSEUDO 0x00000080
+
+
+/***************************************************************************
+ *
+ * Client-side preauthentication plugin interface definition.
+ *
+ ***************************************************************************/
+
+/*
+ * A callback which will obtain the user's long-term AS key by prompting the
+ * user for the password, then salting it properly, and so on. For the moment,
+ * it's identical to the get_as_key callback used inside of libkrb5, but we
+ * define a new typedef here instead of making the existing one public to
+ * isolate ourselves from potential future changes.
+ */
+typedef krb5_error_code
+(*preauth_get_as_key_proc)(krb5_context,
+ krb5_principal,
+ krb5_enctype,
+ krb5_prompter_fct,
+ void *prompter_data,
+ krb5_data *salt,
+ krb5_data *s2kparams,
+ krb5_keyblock *as_key,
+ void *gak_data);
+
+/*
+ * A client module's callback functions are allowed to request various
+ * information to enable it to process a request.
+ */
+enum krb5plugin_preauth_client_request_type {
+ /* The returned krb5_data item holds the enctype used to encrypt the
+ * encrypted portion of the AS_REP packet. */
+ krb5plugin_preauth_client_get_etype = 1,
+ /* Free the data returned from krb5plugin_preauth_client_req_get_etype */
+ krb5plugin_preauth_client_free_etype = 2
+};
+typedef krb5_error_code
+(*preauth_get_client_data_proc)(krb5_context,
+ struct _krb5_preauth_client_rock *,
+ krb5_int32 request_type,
+ krb5_data **);
+
+/* Per-plugin initialization/cleanup. The init function is called
+ * by libkrb5 when the plugin is loaded, and the fini function is
+ * called before the plugin is unloaded. Both are optional and
+ * may be called multiple times in case the plugin is used in
+ * multiple contexts. The returned context lives the lifetime of
+ * the krb5_context */
+typedef krb5_error_code
+(*preauth_client_plugin_init_proc)(krb5_context context,
+ void **plugin_context);
+typedef void
+(*preauth_client_plugin_fini_proc)(krb5_context context,
+ void *plugin_context);
+
+/* A callback which returns flags indicating if the module is a "real" or
+ * an "info" mechanism, and so on. This function is called for each entry
+ * in the client_pa_type_list. */
+typedef int
+(*preauth_client_get_flags_proc)(krb5_context context,
+ krb5_preauthtype pa_type);
+
+/* Per-request initialization/cleanup. The request_init function is
+ * called when beginning to process a get_init_creds request and the
+ * request_fini function is called when processing of the request is
+ * complete. This is optional. It may be called multiple times in
+ * the lifetime of a krb5_context. */
+typedef void
+(*preauth_client_request_init_proc)(krb5_context context,
+ void *plugin_context,
+ void **request_context);
+typedef void
+(*preauth_client_request_fini_proc)(krb5_context context,
+ void *plugin_context,
+ void *request_context);
+
+/* Client function which processes server-supplied data in pa_data,
+ * returns created data in out_pa_data, storing any of its own state in
+ * client_context if data for the associated preauthentication type is
+ * needed. It is also called after the AS-REP is received if the AS-REP
+ * includes preauthentication data of the associated type.
+ * NOTE! the encoded_previous_request will be NULL the first time this
+ * function is called, because it is expected to only ever contain the data
+ * obtained from a previous call to this function. */
+typedef krb5_error_code
+(*preauth_client_process_proc)(krb5_context context,
+ void *plugin_context,
+ void *request_context,
+ krb5_get_init_creds_opt *opt,
+ preauth_get_client_data_proc get_data_proc,
+ struct _krb5_preauth_client_rock *rock,
+ krb5_kdc_req *request,
+ krb5_data *encoded_request_body,
+ krb5_data *encoded_previous_request,
+ krb5_pa_data *pa_data,
+ krb5_prompter_fct prompter,
+ void *prompter_data,
+ preauth_get_as_key_proc gak_fct,
+ void *gak_data,
+ krb5_data *salt,
+ krb5_data *s2kparams,
+ krb5_keyblock *as_key,
+ krb5_pa_data ***out_pa_data);
+
+/* Client function which can attempt to use e-data in the error response to
+ * try to recover from the given error. If this function is not NULL, and
+ * it stores data in out_pa_data which is different data from the contents
+ * of in_pa_data, then the client library will retransmit the request. */
+typedef krb5_error_code
+(*preauth_client_tryagain_proc)(krb5_context context,
+ void *plugin_context,
+ void *request_context,
+ krb5_get_init_creds_opt *opt,
+ preauth_get_client_data_proc get_data_proc,
+ struct _krb5_preauth_client_rock *rock,
+ krb5_kdc_req *request,
+ krb5_data *encoded_request_body,
+ krb5_data *encoded_previous_request,
+ krb5_pa_data *in_pa_data,
+ krb5_error *error,
+ krb5_prompter_fct prompter,
+ void *prompter_data,
+ preauth_get_as_key_proc gak_fct,
+ void *gak_data,
+ krb5_data *salt,
+ krb5_data *s2kparams,
+ krb5_keyblock *as_key,
+ krb5_pa_data ***out_pa_data);
+
+/*
+ * Client function which receives krb5_get_init_creds_opt information.
+ * The attr and value information supplied should be copied locally by
+ * the module if it wishes to reference it after returning from this call.
+ */
+typedef krb5_error_code
+(*preauth_client_supply_gic_opts_proc)(krb5_context context,
+ void *plugin_context,
+ krb5_get_init_creds_opt *opt,
+ const char *attr,
+ const char *value);
+
+/*
+ * The function table / structure which a preauth client module must export as
+ * "preauthentication_client_0". If the interfaces work correctly, future
+ * versions of the table will add either more callbacks or more arguments to
+ * callbacks, and in both cases we'll be able to wrap the v0 functions.
+ */
+typedef struct krb5plugin_preauth_client_ftable_v1 {
+ /* Not-usually-visible name. */
+ char *name;
+
+ /* Pointer to zero-terminated list of pa_types which this module can
+ * provide services for. */
+ krb5_preauthtype *pa_type_list;
+
+ /* Pointer to zero-terminated list of enc_types which this module claims
+ * to add support for. */
+ krb5_enctype *enctype_list;
+
+ /* Per-plugin initialization/cleanup. The init function is called
+ * by libkrb5 when the plugin is loaded, and the fini function is
+ * called before the plugin is unloaded. Both are optional and
+ * may be called multiple times in case the plugin is used in
+ * multiple contexts. The returned context lives the lifetime of
+ * the krb5_context */
+ preauth_client_plugin_init_proc init;
+ preauth_client_plugin_fini_proc fini;
+
+ /* A callback which returns flags indicating if the module is a "real" or
+ * an "info" mechanism, and so on. This function is called for each entry
+ * in the client_pa_type_list. */
+ preauth_client_get_flags_proc flags;
+
+ /* Per-request initialization/cleanup. The request_init function is
+ * called when beginning to process a get_init_creds request and the
+ * request_fini function is called when processing of the request is
+ * complete. This is optional. It may be called multiple times in
+ * the lifetime of a krb5_context. */
+ preauth_client_request_init_proc request_init;
+ preauth_client_request_fini_proc request_fini;
+
+ /* Client function which processes server-supplied data in pa_data,
+ * returns created data in out_pa_data, storing any of its own state in
+ * client_context if data for the associated preauthentication type is
+ * needed. It is also called after the AS-REP is received if the AS-REP
+ * includes preauthentication data of the associated type.
+ * NOTE! the encoded_previous_request will be NULL the first time this
+ * function is called, because it is expected to only ever contain the data
+ * obtained from a previous call to this function. */
+ preauth_client_process_proc process;
+
+ /* Client function which can attempt to use e-data in the error response to
+ * try to recover from the given error. If this function is not NULL, and
+ * it stores data in out_pa_data which is different data from the contents
+ * of in_pa_data, then the client library will retransmit the request. */
+ preauth_client_tryagain_proc tryagain;
+
+ /*
+ * Client function which receives krb5_get_init_creds_opt information.
+ * The attr and value information supplied should be copied locally by
+ * the module if it wishes to reference it after returning from this call.
+ */
+ preauth_client_supply_gic_opts_proc gic_opts;
+
+} krb5plugin_preauth_client_ftable_v1;
+
+
+/***************************************************************************
+ *
+ * Server-side preauthentication plugin interface definition.
+ *
+ ***************************************************************************/
+
+/*
+ * A server module's callback functions are allowed to request specific types
+ * of information about the given client or server record or request, even
+ * though the database records themselves are opaque to the module.
+ */
+enum krb5plugin_preauth_entry_request_type {
+ /* The returned krb5_data item holds a DER-encoded X.509 certificate. */
+ krb5plugin_preauth_entry_request_certificate = 1,
+ /* The returned krb5_data_item holds a krb5_deltat. */
+ krb5plugin_preauth_entry_max_time_skew = 2,
+ /* The returned krb5_data_item holds an array of krb5_keyblock structures,
+ * terminated by an entry with key type = 0.
+ * Each keyblock should have its contents freed in turn, and then the data
+ * item itself should be freed. */
+ krb5plugin_preauth_keys = 3,
+ /* The returned krb5_data_item holds the request structure, re-encoded
+ * using DER. Unless the client implementation is the same as the server
+ * implementation, there's a good chance that the result will not match
+ * what the client sent, so don't go creating any fatal errors if it
+ * doesn't match up. */
+ krb5plugin_preauth_request_body = 4
+};
+
+typedef krb5_error_code
+(*preauth_get_entry_data_proc)(krb5_context,
+ krb5_kdc_req *,
+ struct _krb5_db_entry_new *,
+ krb5_int32 request_type,
+ krb5_data **);
+
+/* Preauth plugin initialization function */
+typedef krb5_error_code
+(*preauth_server_init_proc)(krb5_context context,
+ void **plugin_context,
+ const char** realmnames);
+
+/* Preauth plugin cleanup function */
+typedef void
+(*preauth_server_fini_proc)(krb5_context context, void *plugin_context);
+
+/* Return the flags which the KDC should use for this module. This is a
+ * callback instead of a static value because the module may or may not
+ * wish to count itself as a hardware preauthentication module (in other
+ * words, the flags may be affected by the configuration, for example if a
+ * site administrator can force a particular preauthentication type to be
+ * supported using only hardware). This function is called for each entry
+ * entry in the server_pa_type_list. */
+typedef int
+(*preauth_server_flags_proc)(krb5_context context, krb5_preauthtype patype);
+
+/* Get preauthentication data to send to the client as part of the "you
+ * need to use preauthentication" error. The module doesn't need to
+ * actually provide data if the protocol doesn't require it, but it should
+ * return either zero or non-zero to control whether its padata type is
+ * included in the list which is sent back to the client. Is not allowed
+ * to create a context because we have no guarantee that the client will
+ * ever call again (or that it will hit this server if it does), in which
+ * case a context might otherwise hang around forever. */
+typedef krb5_error_code
+(*preauth_server_edata_proc)(krb5_context,
+ krb5_kdc_req *request,
+ struct _krb5_db_entry_new *client,
+ struct _krb5_db_entry_new *server,
+ preauth_get_entry_data_proc,
+ void *pa_module_context,
+ krb5_pa_data *data);
+
+/* Verify preauthentication data sent by the client, setting the
+ * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
+ * field as appropriate, and returning nonzero on failure. Can create
+ * context data for consumption by the return_proc or freepa_proc below. */
+typedef krb5_error_code
+(*preauth_server_verify_proc)(krb5_context context,
+ struct _krb5_db_entry_new *client,
+ krb5_data *req_pkt,
+ krb5_kdc_req *request,
+ krb5_enc_tkt_part *enc_tkt_reply,
+ krb5_pa_data *data,
+ preauth_get_entry_data_proc,
+ void *pa_module_context,
+ void **pa_request_context,
+ krb5_data **e_data,
+ krb5_authdata ***authz_data);
+
+/* Generate preauthentication response data to send to the client as part
+ * of the AS-REP. If it needs to override the key which is used to encrypt
+ * the response, it can do so. The module is expected (but not required,
+ * if a preauth_server_free_reqcontext_proc is also provided) to free any
+ * context data it saved in "pa_request_context". */
+typedef krb5_error_code
+(*preauth_server_return_proc)(krb5_context context,
+ krb5_pa_data * padata,
+ struct _krb5_db_entry_new *client,
+ krb5_data *req_pkt,
+ krb5_kdc_req *request,
+ krb5_kdc_rep *reply,
+ struct _krb5_key_data *client_keys,
+ krb5_keyblock *encrypting_key,
+ krb5_pa_data **send_pa,
+ preauth_get_entry_data_proc,
+ void *pa_module_context,
+ void **pa_request_context);
+
+/* Free up the server-side per-request context, in cases where
+ * server_return_proc() didn't or for whatever reason was not called.
+ * Can be NULL. */
+typedef krb5_error_code
+(*preauth_server_free_reqcontext_proc)(krb5_context,
+ void *pa_module_context,
+ void **request_pa_context);
+
+/*
+ * The function table / structure which a preauth server module must export as
+ * "preauthentication_server_0". NOTE: replace "0" with "1" for the type and
+ * variable names if this gets picked up by upstream. If the interfaces work
+ * correctly, future versions of the table will add either more callbacks or
+ * more arguments to callbacks, and in both cases we'll be able to wrap the v0
+ * functions.
+ */
+typedef struct krb5plugin_preauth_server_ftable_v1 {
+ /* Not-usually-visible name. */
+ char *name;
+
+ /* Pointer to zero-terminated list of pa_types which this module can
+ * provide services for. */
+ krb5_preauthtype *pa_type_list;
+
+ /* Per-plugin initialization/cleanup. The init function is called by the
+ * KDC when the plugin is loaded, and the fini function is called before
+ * the plugin is unloaded. Both are optional. */
+ preauth_server_init_proc init_proc;
+ preauth_server_fini_proc fini_proc;
+
+ /* Return the flags which the KDC should use for this module. This is a
+ * callback instead of a static value because the module may or may not
+ * wish to count itself as a hardware preauthentication module (in other
+ * words, the flags may be affected by the configuration, for example if a
+ * site administrator can force a particular preauthentication type to be
+ * supported using only hardware). This function is called for each entry
+ * entry in the server_pa_type_list. */
+ preauth_server_flags_proc flags_proc;
+
+ /* Get preauthentication data to send to the client as part of the "you
+ * need to use preauthentication" error. The module doesn't need to
+ * actually provide data if the protocol doesn't require it, but it should
+ * return either zero or non-zero to control whether its padata type is
+ * included in the list which is sent back to the client. Is not allowed
+ * to create a context because we have no guarantee that the client will
+ * ever call again (or that it will hit this server if it does), in which
+ * case a context might otherwise hang around forever. */
+ preauth_server_edata_proc edata_proc;
+
+ /* Verify preauthentication data sent by the client, setting the
+ * TKT_FLG_PRE_AUTH or TKT_FLG_HW_AUTH flag in the enc_tkt_reply's "flags"
+ * field as appropriate, and returning nonzero on failure. Can create
+ * context data for consumption by the return_proc or freepa_proc below. */
+ preauth_server_verify_proc verify_proc;
+
+ /* Generate preauthentication response data to send to the client as part
+ * of the AS-REP. If it needs to override the key which is used to encrypt
+ * the response, it can do so. The module is expected (but not required,
+ * if a freepa_proc is also provided) to free any context data it saved in
+ * "request_pa_context". */
+ preauth_server_return_proc return_proc;
+
+ /* Free up the server-side per-request context, in cases where
+ * server_return_proc() didn't or for whatever reason was not called.
+ * Can be NULL. */
+ preauth_server_free_reqcontext_proc freepa_reqcontext_proc;
+
+} krb5plugin_preauth_server_ftable_v1;
+
+
+/*
+ * This function allows a preauth plugin to obtain preauth
+ * options. The preauth_data returned from this function
+ * should be freed by calling krb5_get_init_creds_opt_free_pa().
+ *
+ * The 'opt' pointer supplied to this function must have been
+ * obtained using krb5_get_init_creds_opt_alloc()
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_opt_get_pa
+ (krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ int *num_preauth_data,
+ krb5_gic_opt_pa_data **preauth_data);
+
+/*
+ * This function frees the preauth_data that was returned by
+ * krb5_get_init_creds_opt_get_pa().
+ */
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_free_pa
+ (krb5_context context,
+ int num_preauth_data,
+ krb5_gic_opt_pa_data *preauth_data);
+
+#endif /* KRB5_PREAUTH_PLUGIN_H_INCLUDED */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/include/socket-utils.h b/usr/src/lib/gss_mechs/mech_krb5/include/socket-utils.h
index 8785c37a58..da9a2b4c8e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/include/socket-utils.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/include/socket-utils.h
@@ -1,12 +1,11 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
- * Copyright (C) 2001 by the Massachusetts Institute of Technology,
+ * Copyright (C) 2001,2005 by the Massachusetts Institute of Technology,
* Cambridge, MA, USA. All Rights Reserved.
*
* This software is being provided to you, the LICENSEE, by the
@@ -59,11 +58,10 @@
/* for HAVE_SOCKLEN_T, KRB5_USE_INET6, etc */
#include "autoconf.h"
-#if 0 /* SUNW14resync */
-#include "krb5/autoconf.h"
/* for sockaddr_storage */
#include "port-sockets.h"
-#endif /* SUNW14resync */
+/* for "inline" if needed */
+#include "k5-platform.h"
#if defined (__GNUC__)
/*
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_decode.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_decode.c
index 0c7996cc1b..b0ab134922 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_decode.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_decode.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* src/lib/krb5/asn.1/asn1_decode.c
@@ -57,7 +56,7 @@ if(asn1class != UNIVERSAL || construction != PRIMITIVE || tagnum != type)\
#define cleanup()\
return 0
-time_t gmt_mktime (struct tm *);
+extern time_t krb5int_gmt_mktime (struct tm *);
asn1_error_code asn1_decode_integer(asn1buf *buf, long int *val)
{
@@ -252,7 +251,7 @@ asn1_error_code asn1_decode_generaltime(asn1buf *buf, time_t *val)
ts.tm_min = 10*c2i(s[10]) + c2i(s[11]);
ts.tm_sec = 10*c2i(s[12]) + c2i(s[13]);
ts.tm_isdst = -1;
- t = gmt_mktime(&ts);
+ t = krb5int_gmt_mktime(&ts);
free(s);
if(t == -1) return ASN1_BAD_TIMEFORMAT;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_encode.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_encode.c
index 8c874a6116..1805b57028 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_encode.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_encode.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* src/lib/krb5/asn.1/asn1_encode.c
@@ -241,44 +240,49 @@ asn1_error_code asn1_encode_generaltime(asn1buf *buf, time_t val,
* Time encoding: YYYYMMDDhhmmssZ
*/
if (gmt_time == 0) {
- sp = "19700101000000Z";
- } else {
-
- /*
- * Sanity check this just to be paranoid, as gmtime can return NULL,
- * and some bogus implementations might overrun on the sprintf.
- */
+ sp = "19700101000000Z";
+ } else {
+
+ /*
+ * Sanity check this just to be paranoid, as gmtime can return NULL,
+ * and some bogus implementations might overrun on the sprintf.
+ */
#ifdef HAVE_GMTIME_R
- if (gmtime_r(&gmt_time, &gtimebuf) == NULL)
- return ASN1_BAD_GMTIME;
+# ifdef GMTIME_R_RETURNS_INT
+ if (gmtime_r(&gmt_time, &gtimebuf) != 0)
+ return ASN1_BAD_GMTIME;
+# else
+ if (gmtime_r(&gmt_time, &gtimebuf) == NULL)
+ return ASN1_BAD_GMTIME;
+# endif
#else
- gtime = gmtime(&gmt_time);
- if (gtime == NULL)
- return ASN1_BAD_GMTIME;
- memcpy(&gtimebuf, gtime, sizeof(gtimebuf));
+ gtime = gmtime(&gmt_time);
+ if (gtime == NULL)
+ return ASN1_BAD_GMTIME;
+ memcpy(&gtimebuf, gtime, sizeof(gtimebuf));
#endif
- gtime = &gtimebuf;
-
- if (gtime->tm_year > 8099 || gtime->tm_mon > 11 ||
- gtime->tm_mday > 31 || gtime->tm_hour > 23 ||
- gtime->tm_min > 59 || gtime->tm_sec > 59)
- return ASN1_BAD_GMTIME;
- sprintf(s, "%04d%02d%02d%02d%02d%02dZ",
- 1900+gtime->tm_year, gtime->tm_mon+1, gtime->tm_mday,
- gtime->tm_hour, gtime->tm_min, gtime->tm_sec);
- sp = s;
- }
+ gtime = &gtimebuf;
+
+ if (gtime->tm_year > 8099 || gtime->tm_mon > 11 ||
+ gtime->tm_mday > 31 || gtime->tm_hour > 23 ||
+ gtime->tm_min > 59 || gtime->tm_sec > 59)
+ return ASN1_BAD_GMTIME;
+ sprintf(s, "%04d%02d%02d%02d%02d%02dZ",
+ 1900+gtime->tm_year, gtime->tm_mon+1, gtime->tm_mday,
+ gtime->tm_hour, gtime->tm_min, gtime->tm_sec);
+ sp = s;
+ }
retval = asn1buf_insert_charstring(buf,15,sp);
if(retval) return retval;
sum = 15;
- retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_GENERALTIME,sum,&length);
- if(retval) return retval;
- sum += length;
-
- *retlen = sum;
- return 0;
+ retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,ASN1_GENERALTIME,sum,&length);
+ if(retval) return retval;
+ sum += length;
+
+ *retlen = sum;
+ return 0;
}
asn1_error_code asn1_encode_generalstring(asn1buf *buf, unsigned int len,
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_get.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_get.c
index c55086cffe..8da5fd8806 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_get.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_get.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* src/lib/krb5/asn.1/asn1_get.c
*
@@ -66,7 +64,7 @@ asn1_get_tag_2(asn1buf *buf, taginfo *t)
retval = asn1buf_remove_octet(buf,&o);
if (retval) return retval;
tn = (tn<<7) + (asn1_tagnum)(o&0x7F);
- }while(tn&0x80);
+ }while(o&0x80);
t->tagnum = tn;
}
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_decode.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_decode.c
index bcbb78fca1..50084132f3 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_decode.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_decode.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* src/lib/krb5/asn.1/asn1_k_decode.c
*
@@ -166,6 +165,28 @@
} else { len = 0; var = 0; }
/*
+ * Deal with implicitly tagged fields
+ */
+#define get_implicit_octet_string(len, var, tagexpect) \
+ if (tagnum != (tagexpect)) return ASN1_MISSING_FIELD; \
+ if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \
+ return ASN1_BAD_ID; \
+ retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var)); \
+ if (retval) return retval; \
+ (len) = taglen; \
+ next_tag()
+
+#define opt_implicit_octet_string(len, var, tagexpect) \
+ if (tagnum == (tagexpect)) { \
+ if (asn1class != CONTEXT_SPECIFIC || construction != PRIMITIVE) \
+ return ASN1_BAD_ID; \
+ retval = asn1buf_remove_octetstring(&subbuf, taglen, &(var)); \
+ if (retval) return retval; \
+ (len) = taglen; \
+ next_tag(); \
+ } else { (len) = 0; (var) = NULL; }
+
+/*
* begin_structure
*
* Declares some variables for decoding SEQUENCE types. This is meant
@@ -182,6 +203,20 @@
if (retval) return retval; \
next_tag()
+/*
+ * This is used for structures which have no tagging.
+ * It is the same as begin_structure() except next_tag()
+ * is not called.
+ */
+#define begin_structure_no_tag() \
+ asn1buf subbuf; \
+ int seqindef; \
+ int indef; \
+ retval = asn1_get_sequence(buf, &length, &seqindef); \
+ if (retval) return retval; \
+ retval = asn1buf_imbed(&subbuf, buf, length, seqindef); \
+ if (retval) return retval
+
/* skip trailing garbage */
#define end_structure() \
retval = asn1buf_sync(buf, &subbuf, asn1class, tagnum, \
@@ -189,6 +224,37 @@
if (retval) return retval
/*
+ * begin_choice
+ *
+ * Declares some variables for decoding CHOICE types. This is meant
+ * to be called in an inner block that ends with a call to
+ * end_choice().
+ */
+#define begin_choice() \
+ asn1buf subbuf; \
+ int seqindef; \
+ int indef; \
+ taginfo t; \
+ retval = asn1_get_tag_2(buf, &t); \
+ if (retval) return retval; \
+ tagnum = t.tagnum; \
+ taglen = t.length; \
+ indef = t.indef; \
+ length = t.length; \
+ seqindef = t.indef; \
+ asn1class = t.asn1class; \
+ construction = t.construction; \
+ retval = asn1buf_imbed(&subbuf, buf, length, seqindef); \
+ if (retval) return retval
+
+/* skip trailing garbage */
+#define end_choice() \
+ length -= t.length; \
+ retval = asn1buf_sync(buf, &subbuf, t.asn1class, t.tagnum, \
+ length, t.indef, seqindef); \
+ if (retval) return retval
+
+/*
* sequence_of
*
* Declares some variables for decoding SEQUENCE OF types. This is
@@ -375,7 +441,7 @@ asn1_error_code asn1_decode_principal_name(asn1buf *buf, krb5_principal *val)
if((*val)->data == NULL) return ENOMEM;
retval = asn1_decode_generalstring(&seqbuf,
&((*val)->data[size-1].length),
- &((*val)->data[size-1].data));
+ &((*val)->data[size-1].data));
if(retval) return retval;
}
(*val)->length = size;
@@ -535,7 +601,7 @@ asn1_error_code asn1_decode_ticket(asn1buf *buf, krb5_ticket *val)
taginfo t;
retval = asn1_get_tag_2(buf, &t);
if (retval) return retval;
- }
+ }
cleanup();
}
@@ -1107,3 +1173,408 @@ asn1_error_code asn1_decode_predicted_sam_response(asn1buf *buf, krb5_predicted_
}
cleanup();
}
+
+/* PKINIT */
+
+asn1_error_code asn1_decode_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier *val)
+{
+ setup();
+ {
+ begin_structure();
+ opt_implicit_octet_string(val->subjectName.length, val->subjectName.data, 0);
+ opt_implicit_octet_string(val->issuerAndSerialNumber.length, val->issuerAndSerialNumber.data, 1);
+ opt_implicit_octet_string(val->subjectKeyIdentifier.length, val->subjectKeyIdentifier.data, 2);
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_sequence_of_external_principal_identifier(asn1buf *buf, krb5_external_principal_identifier ***val)
+{
+ decode_array_body(krb5_external_principal_identifier,asn1_decode_external_principal_identifier);
+}
+
+asn1_error_code asn1_decode_pa_pk_as_req(asn1buf *buf, krb5_pa_pk_as_req *val)
+{
+ setup();
+ {
+ begin_structure();
+ get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0);
+ opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_external_principal_identifier, NULL);
+ opt_implicit_octet_string(val->kdcPkId.length, val->kdcPkId.data, 2);
+ end_structure();
+ }
+ cleanup();
+}
+
+#if 0 /* XXX This needs to be tested!!! XXX */
+asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val)
+{
+ setup();
+ {
+ char *start, *end;
+ size_t alloclen;
+
+ begin_explicit_choice();
+ if (t.tagnum == choice_trusted_cas_principalName) {
+ val->choice = choice_trusted_cas_principalName;
+ } else if (t.tagnum == choice_trusted_cas_caName) {
+ val->choice = choice_trusted_cas_caName;
+ start = subbuf.next;
+ {
+ sequence_of_no_tagvars(&subbuf);
+ unused_var(size);
+ end_sequence_of_no_tagvars(&subbuf);
+ }
+ end = subbuf.next;
+ alloclen = end - start;
+ val->u.caName.data = malloc(alloclen);
+ if (val->u.caName.data == NULL)
+ return ENOMEM;
+ memcpy(val->u.caName.data, start, alloclen);
+ val->u.caName.length = alloclen;
+ next_tag();
+ } else if (t.tagnum == choice_trusted_cas_issuerAndSerial) {
+ val->choice = choice_trusted_cas_issuerAndSerial;
+ start = subbuf.next;
+ {
+ sequence_of_no_tagvars(&subbuf);
+ unused_var(size);
+ end_sequence_of_no_tagvars(&subbuf);
+ }
+ end = subbuf.next;
+ alloclen = end - start;
+ val->u.issuerAndSerial.data = malloc(alloclen);
+ if (val->u.issuerAndSerial.data == NULL)
+ return ENOMEM;
+ memcpy(val->u.issuerAndSerial.data, start, alloclen);
+ val->u.issuerAndSerial.length = alloclen;
+ next_tag();
+ } else return ASN1_BAD_ID;
+ end_explicit_choice();
+ }
+ cleanup();
+}
+#else
+asn1_error_code asn1_decode_trusted_ca(asn1buf *buf, krb5_trusted_ca *val)
+{
+ setup();
+ { begin_choice();
+ if (tagnum == choice_trusted_cas_principalName) {
+ val->choice = choice_trusted_cas_principalName;
+ asn1_decode_krb5_principal_name(&subbuf, &(val->u.principalName));
+ } else if (tagnum == choice_trusted_cas_caName) {
+ val->choice = choice_trusted_cas_caName;
+ get_implicit_octet_string(val->u.caName.length, val->u.caName.data, choice_trusted_cas_caName);
+ } else if (tagnum == choice_trusted_cas_issuerAndSerial) {
+ val->choice = choice_trusted_cas_issuerAndSerial;
+ get_implicit_octet_string(val->u.issuerAndSerial.length, val->u.issuerAndSerial.data,
+ choice_trusted_cas_issuerAndSerial);
+ } else return ASN1_BAD_ID;
+ end_choice();
+ }
+ cleanup();
+}
+#endif
+
+asn1_error_code asn1_decode_sequence_of_trusted_ca(asn1buf *buf, krb5_trusted_ca ***val)
+{
+ decode_array_body(krb5_trusted_ca, asn1_decode_trusted_ca);
+}
+
+asn1_error_code asn1_decode_pa_pk_as_req_draft9(asn1buf *buf, krb5_pa_pk_as_req_draft9 *val)
+{
+ setup();
+ { begin_structure();
+ get_implicit_octet_string(val->signedAuthPack.length, val->signedAuthPack.data, 0);
+ opt_field(val->trustedCertifiers, 1, asn1_decode_sequence_of_trusted_ca, NULL);
+ opt_lenfield(val->kdcCert.length, val->kdcCert.data, 2, asn1_decode_octetstring);
+ opt_lenfield(val->encryptionCert.length, val->encryptionCert.data, 2, asn1_decode_octetstring);
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_dh_rep_info(asn1buf *buf, krb5_dh_rep_info *val)
+{
+ setup();
+ { begin_structure();
+ get_implicit_octet_string(val->dhSignedData.length, val->dhSignedData.data, 0);
+
+ opt_lenfield(val->serverDHNonce.length, val->serverDHNonce.data, 1, asn1_decode_octetstring);
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_pk_authenticator(asn1buf *buf, krb5_pk_authenticator *val)
+{
+ setup();
+ { begin_structure();
+ get_field(val->cusec, 0, asn1_decode_int32);
+ get_field(val->ctime, 1, asn1_decode_kerberos_time);
+ get_field(val->nonce, 2, asn1_decode_int32);
+ opt_lenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_decode_octetstring);
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_pk_authenticator_draft9(asn1buf *buf, krb5_pk_authenticator_draft9 *val)
+{
+ setup();
+ { begin_structure();
+ alloc_field(val->kdcName,krb5_principal_data);
+ get_field(val->kdcName, 0, asn1_decode_principal_name);
+ get_field(val->kdcName, 1, asn1_decode_realm);
+ get_field(val->cusec, 2, asn1_decode_int32);
+ get_field(val->ctime, 3, asn1_decode_kerberos_time);
+ get_field(val->nonce, 4, asn1_decode_int32);
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_algorithm_identifier(asn1buf *buf, krb5_algorithm_identifier *val) {
+
+ setup();
+ { begin_structure_no_tag();
+ /*
+ * Forbid indefinite encoding because we don't read enough tag
+ * information from the trailing octets ("ANY DEFINED BY") to
+ * synchronize EOC tags, etc.
+ */
+ if (seqindef) return ASN1_BAD_FORMAT;
+ /*
+ * Set up tag variables because we don't actually call anything
+ * that fetches tag info for us; it's all buried in the decoder
+ * primitives.
+ */
+ tagnum = ASN1_TAGNUM_CEILING;
+ asn1class = UNIVERSAL;
+ construction = PRIMITIVE;
+ taglen = 0;
+ indef = 0;
+ retval = asn1_decode_oid(&subbuf, &val->algorithm.length,
+ &val->algorithm.data);
+ if(retval) return retval;
+ val->parameters.length = 0;
+ val->parameters.data = NULL;
+
+ if(length > subbuf.next - subbuf.base) {
+ unsigned int size = length - (subbuf.next - subbuf.base);
+ retval = asn1buf_remove_octetstring(&subbuf, size,
+ &val->parameters.data);
+ if(retval) return retval;
+ val->parameters.length = size;
+ }
+
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_subject_pk_info(asn1buf *buf, krb5_subject_pk_info *val)
+{
+ asn1_octet unused;
+ setup();
+ { begin_structure_no_tag();
+
+ retval = asn1_decode_algorithm_identifier(&subbuf, &val->algorithm);
+ if (retval) return retval;
+
+ /* SubjectPublicKey encoded as a BIT STRING */
+ next_tag();
+ if (asn1class != UNIVERSAL || construction != PRIMITIVE ||
+ tagnum != ASN1_BITSTRING)
+ return ASN1_BAD_ID;
+
+ retval = asn1buf_remove_octet(&subbuf, &unused);
+ if(retval) return retval;
+
+ /* Number of unused bits must be between 0 and 7. */
+ /* What to do if unused is not zero? */
+ if (unused > 7) return ASN1_BAD_FORMAT;
+ taglen--;
+
+ val->subjectPublicKey.length = 0;
+ val->subjectPublicKey.data = NULL;
+ retval = asn1buf_remove_octetstring(&subbuf, taglen,
+ &val->subjectPublicKey.data);
+ if(retval) return retval;
+ val->subjectPublicKey.length = taglen;
+ /*
+ * We didn't call any macro that does next_tag(); do so now to
+ * preload tag of any trailing encodings.
+ */
+ next_tag();
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_sequence_of_algorithm_identifier(asn1buf *buf, krb5_algorithm_identifier ***val)
+{
+ decode_array_body(krb5_algorithm_identifier, asn1_decode_algorithm_identifier);
+}
+
+asn1_error_code asn1_decode_kdc_dh_key_info (asn1buf *buf, krb5_kdc_dh_key_info *val)
+{
+ setup();
+ { begin_structure();
+ retval = asn1buf_remove_octetstring(&subbuf, taglen, &val->subjectPublicKey.data);
+ if(retval) return retval;
+ val->subjectPublicKey.length = taglen;
+ next_tag();
+ get_field(val->nonce, 1, asn1_decode_int32);
+ opt_field(val->dhKeyExpiration, 2, asn1_decode_kerberos_time, 0);
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_reply_key_pack (asn1buf *buf, krb5_reply_key_pack *val)
+{
+ setup();
+ { begin_structure();
+ get_field(val->replyKey, 0, asn1_decode_encryption_key);
+ get_field(val->asChecksum, 1, asn1_decode_checksum);
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_reply_key_pack_draft9 (asn1buf *buf, krb5_reply_key_pack_draft9 *val)
+{
+ setup();
+ { begin_structure();
+ get_field(val->replyKey, 0, asn1_decode_encryption_key);
+ get_field(val->nonce, 1, asn1_decode_int32);
+ end_structure();
+ }
+ cleanup();
+}
+
+
+asn1_error_code asn1_decode_krb5_principal_name (asn1buf *buf, krb5_principal *val)
+{
+ setup();
+ { begin_structure();
+ get_field(*val, 0, asn1_decode_realm);
+ get_field(*val, 1, asn1_decode_principal_name);
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_auth_pack(asn1buf *buf, krb5_auth_pack *val)
+{
+ setup();
+ { begin_structure();
+ get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator);
+ if (tagnum == 1) { alloc_field(val->clientPublicValue, krb5_subject_pk_info); }
+ /* can't call opt_field because it does decoder(&subbuf, &(val)); */
+ if (asn1buf_remains(&subbuf, seqindef)) {
+ if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
+ && (tagnum || taglen || asn1class != UNIVERSAL))
+ return ASN1_BAD_ID;
+ if (tagnum == 1) {
+ retval = asn1_decode_subject_pk_info(&subbuf,
+ val->clientPublicValue);
+ if (!taglen && indef) { get_eoc(); }
+ next_tag();
+ } else val->clientPublicValue = NULL;
+ }
+ /* can't call opt_field because it does decoder(&subbuf, &(val)); */
+ if (asn1buf_remains(&subbuf, seqindef)) {
+ if (tagnum == 2) {
+ asn1_decode_sequence_of_algorithm_identifier(&subbuf, &val->supportedCMSTypes);
+ if (!taglen && indef) { get_eoc(); }
+ next_tag();
+ } else val->supportedCMSTypes = NULL;
+ }
+ opt_lenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_decode_octetstring);
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_auth_pack_draft9(asn1buf *buf, krb5_auth_pack_draft9 *val)
+{
+ setup();
+ { begin_structure();
+ get_field(val->pkAuthenticator, 0, asn1_decode_pk_authenticator_draft9);
+ if (tagnum == 1) {
+ alloc_field(val->clientPublicValue, krb5_subject_pk_info);
+ /* can't call opt_field because it does decoder(&subbuf, &(val)); */
+ if (asn1buf_remains(&subbuf, seqindef)) {
+ if ((asn1class != CONTEXT_SPECIFIC || construction != CONSTRUCTED)
+ && (tagnum || taglen || asn1class != UNIVERSAL))
+ return ASN1_BAD_ID;
+ if (tagnum == 1) {
+ retval = asn1_decode_subject_pk_info(&subbuf,
+ val->clientPublicValue);
+ if (!taglen && indef) { get_eoc(); }
+ next_tag();
+ } else val->clientPublicValue = NULL;
+ }
+ }
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_pa_pk_as_rep(asn1buf *buf, krb5_pa_pk_as_rep *val)
+{
+ setup();
+ { begin_choice();
+ if (tagnum == choice_pa_pk_as_rep_dhInfo) {
+ val->choice = choice_pa_pk_as_rep_dhInfo;
+ get_field_body(val->u.dh_Info, asn1_decode_dh_rep_info);
+ } else if (tagnum == choice_pa_pk_as_rep_encKeyPack) {
+ val->choice = choice_pa_pk_as_rep_encKeyPack;
+ get_implicit_octet_string(val->u.encKeyPack.length, val->u.encKeyPack.data,
+ choice_pa_pk_as_rep_encKeyPack);
+ } else {
+ val->choice = choice_pa_pk_as_rep_UNKNOWN;
+ }
+ end_choice();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_pa_pk_as_rep_draft9(asn1buf *buf, krb5_pa_pk_as_rep_draft9 *val)
+{
+ setup();
+ { begin_structure();
+ if (tagnum == choice_pa_pk_as_rep_draft9_dhSignedData) {
+ val->choice = choice_pa_pk_as_rep_draft9_dhSignedData;
+ get_lenfield(val->u.dhSignedData.length, val->u.dhSignedData.data,
+ choice_pa_pk_as_rep_draft9_dhSignedData, asn1_decode_octetstring);
+ } else if (tagnum == choice_pa_pk_as_rep_draft9_encKeyPack) {
+ val->choice = choice_pa_pk_as_rep_draft9_encKeyPack;
+ get_lenfield(val->u.encKeyPack.length, val->u.encKeyPack.data,
+ choice_pa_pk_as_rep_draft9_encKeyPack, asn1_decode_octetstring);
+ } else {
+ val->choice = choice_pa_pk_as_rep_draft9_UNKNOWN;
+ }
+ end_structure();
+ }
+ cleanup();
+}
+
+asn1_error_code asn1_decode_sequence_of_typed_data(asn1buf *buf, krb5_typed_data ***val)
+{
+ decode_array_body(krb5_typed_data,asn1_decode_typed_data);
+}
+
+asn1_error_code asn1_decode_typed_data(asn1buf *buf, krb5_typed_data *val)
+{
+ setup();
+ { begin_structure();
+ get_field(val->type,0,asn1_decode_int32);
+ get_lenfield(val->length,val->data,1,asn1_decode_octetstring);
+ end_structure();
+ }
+ cleanup();
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_decode.h b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_decode.h
index a93af704b0..72c4e293c0 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_decode.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_decode.h
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* src/lib/krb5/asn.1/asn1_k_decode.h
*
@@ -161,6 +159,44 @@ asn1_error_code asn1_decode_sam_response_2
(asn1buf *buf, krb5_sam_response_2 *val);
asn1_error_code asn1_decode_predicted_sam_response
(asn1buf *buf, krb5_predicted_sam_response *val);
+asn1_error_code asn1_decode_external_principal_identifier
+ (asn1buf *buf, krb5_external_principal_identifier *val);
+asn1_error_code asn1_decode_pa_pk_as_req
+ (asn1buf *buf, krb5_pa_pk_as_req *val);
+asn1_error_code asn1_decode_trusted_ca
+ (asn1buf *buf, krb5_trusted_ca *val);
+asn1_error_code asn1_decode_pa_pk_as_req_draft9
+ (asn1buf *buf, krb5_pa_pk_as_req_draft9 *val);
+asn1_error_code asn1_decode_dh_rep_info
+ (asn1buf *buf, krb5_dh_rep_info *val);
+asn1_error_code asn1_decode_pk_authenticator
+ (asn1buf *buf, krb5_pk_authenticator *val);
+asn1_error_code asn1_decode_pk_authenticator_draft9
+ (asn1buf *buf, krb5_pk_authenticator_draft9 *val);
+asn1_error_code asn1_decode_subject_pk_info
+ (asn1buf *buf, krb5_subject_pk_info *val);
+asn1_error_code asn1_decode_algorithm_identifier
+ (asn1buf *buf, krb5_algorithm_identifier *val);
+asn1_error_code asn1_decode_auth_pack
+ (asn1buf *buf, krb5_auth_pack *val);
+asn1_error_code asn1_decode_auth_pack_draft9
+ (asn1buf *buf, krb5_auth_pack_draft9 *val);
+asn1_error_code asn1_decode_pa_pk_as_rep
+ (asn1buf *buf, krb5_pa_pk_as_rep *val);
+asn1_error_code asn1_decode_pa_pk_as_rep_draft9
+ (asn1buf *buf, krb5_pa_pk_as_rep_draft9 *val);
+asn1_error_code asn1_decode_kdc_dh_key_info
+ (asn1buf *buf, krb5_kdc_dh_key_info *val);
+asn1_error_code asn1_decode_krb5_principal_name
+ (asn1buf *buf, krb5_principal *val);
+asn1_error_code asn1_decode_reply_key_pack
+ (asn1buf *buf, krb5_reply_key_pack *val);
+asn1_error_code asn1_decode_reply_key_pack_draft9
+ (asn1buf *buf, krb5_reply_key_pack_draft9 *val);
+asn1_error_code asn1_decode_sequence_of_typed_data
+ (asn1buf *buf, krb5_typed_data ***val);
+asn1_error_code asn1_decode_typed_data
+ (asn1buf *buf, krb5_typed_data *val);
/* arrays */
asn1_error_code asn1_decode_authorization_data
@@ -189,6 +225,11 @@ asn1_error_code asn1_decode_etype_info
(asn1buf *buf, krb5_etype_info_entry ***val);
asn1_error_code asn1_decode_etype_info2
(asn1buf *buf, krb5_etype_info_entry ***val, krb5_boolean v1_3_behavior);
-
+asn1_error_code asn1_decode_sequence_of_external_principal_identifier
+ (asn1buf *buf, krb5_external_principal_identifier ***val);
+asn1_error_code asn1_decode_sequence_of_trusted_ca
+ (asn1buf *buf, krb5_trusted_ca ***val);
+asn1_error_code asn1_decode_sequence_of_algorithm_identifier
+ (asn1buf *buf, krb5_algorithm_identifier ***val);
#endif
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_encode.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_encode.c
index f9ec0abc25..9e5cbaf3fd 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_encode.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_encode.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* src/lib/krb5/asn.1/asn1_k_encode.c
*
@@ -105,6 +103,50 @@
return retval; }\
sum += length; }
+/* asn1_addfield_implicit -- add an implicitly tagged field, or component, to the encoding */
+#define asn1_addfield_implicit(value,tag,encoder)\
+{ retval = encoder(buf,value,&length);\
+ if(retval){\
+ asn1buf_destroy(&buf);\
+ return retval; }\
+ sum += length;\
+ retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,length,&length); \
+ if(retval){\
+ asn1buf_destroy(&buf);\
+ return retval; }\
+ sum += length; }
+
+/* asn1_insert_implicit_octetstring -- add an octet string with implicit tagging */
+#define asn1_insert_implicit_octetstring(len,value,tag)\
+{ retval = asn1buf_insert_octetstring(buf,len,value);\
+ if(retval){\
+ asn1buf_destroy(&buf);\
+ return retval; }\
+ sum += len;\
+ retval = asn1_make_tag(buf,CONTEXT_SPECIFIC,PRIMITIVE,tag,len,&length); \
+ if(retval){\
+ asn1buf_destroy(&buf);\
+ return retval; }\
+ sum += length; }
+
+/* asn1_insert_implicit_bitstring -- add a bitstring with implicit tagging */
+#define asn1_insert_implicit_bitstring(len,value,tag)\
+{ retval = asn1buf_insert_octetstring(buf,len,value);\
+ if(retval){\
+ asn1buf_destroy(&buf);\
+ return retval; }\
+ sum += len;\
+ retval = asn1buf_insert_octet(buf, 0);\
+ if(retval){\
+ asn1buf_destroy(&buf);\
+ return retval; }\
+ sum++;\
+ retval = asn1_make_tag(buf,UNIVERSAL,PRIMITIVE,tag,len+1,&length); \
+ if(retval){\
+ asn1buf_destroy(&buf);\
+ return retval; }\
+ sum += length; }
+
/* form a sequence (by adding a sequence header to the current encoding) */
#define asn1_makeseq()\
retval = asn1_make_sequence(buf,sum,&length);\
@@ -720,13 +762,17 @@ asn1_error_code asn1_encode_etype_info_entry(asn1buf *buf, const krb5_etype_info
if(val == NULL || (val->length > 0 && val->length != KRB5_ETYPE_NO_SALT &&
val->salt == NULL))
return ASN1_MISSING_FIELD;
- if(val->s2kparams.data != NULL)
+ if(val->s2kparams.data != NULL) {
+ /* Solaris Kerberos */
asn1_addlenfield(val->s2kparams.length, (const uchar_t *)val->s2kparams.data, 2,
asn1_encode_octetstring);
+ }
if (val->length >= 0 && val->length != KRB5_ETYPE_NO_SALT){
- if (etype_info2)
+ if (etype_info2) {
+ /* Solaris Kerberos */
asn1_addlenfield(val->length, (const char *)val->salt,1,
asn1_encode_generalstring)
+ }
else asn1_addlenfield(val->length,val->salt,1,
asn1_encode_octetstring);
}
@@ -961,3 +1007,393 @@ asn1_error_code asn1_encode_krb_saved_safe_body(asn1buf *buf, const krb5_data *b
*retlen = body->length;
return 0;
}
+
+/*
+ * PKINIT
+ */
+
+asn1_error_code asn1_encode_pk_authenticator(asn1buf *buf, const krb5_pk_authenticator *val, unsigned int *retlen)
+{
+ asn1_setup();
+ asn1_addlenfield(val->paChecksum.length, val->paChecksum.contents, 3, asn1_encode_octetstring);
+ asn1_addfield(val->nonce, 2, asn1_encode_integer);
+ asn1_addfield(val->ctime, 1, asn1_encode_kerberos_time);
+ asn1_addfield(val->cusec, 0, asn1_encode_integer);
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_pk_authenticator_draft9(asn1buf *buf, const krb5_pk_authenticator_draft9 *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ asn1_addfield(val->nonce, 4, asn1_encode_integer);
+ asn1_addfield(val->ctime, 3, asn1_encode_kerberos_time);
+ asn1_addfield(val->cusec, 2, asn1_encode_integer);
+ asn1_addfield(val->kdcName, 1, asn1_encode_realm);
+ asn1_addfield(val->kdcName, 0, asn1_encode_principal_name);
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+
+asn1_error_code asn1_encode_algorithm_identifier(asn1buf *buf, const krb5_algorithm_identifier *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ if (val->parameters.length != 0) {
+ retval = asn1buf_insert_octetstring(buf, val->parameters.length,
+ val->parameters.data);
+ if(retval) {
+ asn1buf_destroy(&buf);
+ return retval;
+ }
+ sum += val->parameters.length;
+ }
+
+ retval = asn1_encode_oid(buf, val->algorithm.length,
+ val->algorithm.data,
+ &length);
+
+ if(retval) {
+ asn1buf_destroy(&buf);
+ return retval;
+ }
+ sum += length;
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_subject_pk_info(asn1buf *buf, const krb5_subject_pk_info *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,ASN1_BITSTRING);
+
+ if (val->algorithm.parameters.length != 0) {
+ retval = asn1buf_insert_octetstring(buf, val->algorithm.parameters.length,
+ val->algorithm.parameters.data);
+ if(retval) {
+ asn1buf_destroy(&buf);
+ return retval;
+ }
+ sum += val->algorithm.parameters.length;
+ }
+
+ retval = asn1_encode_oid(buf, val->algorithm.algorithm.length,
+ val->algorithm.algorithm.data,
+ &length);
+
+ if(retval) {
+ asn1buf_destroy(&buf);
+ return retval;
+ }
+ sum += length;
+
+ retval = asn1_make_etag(buf, UNIVERSAL, ASN1_SEQUENCE,
+ val->algorithm.parameters.length + length,
+ &length);
+
+ if(retval) {
+ asn1buf_destroy(&buf);
+ return retval;
+ }
+ sum += length;
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_algorithm_identifier(asn1buf *buf, const krb5_algorithm_identifier **val, unsigned int *retlen)
+{
+ asn1_setup();
+ int i;
+
+ if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+
+ for(i=0; val[i] != NULL; i++);
+ for(i--; i>=0; i--){
+ retval = asn1_encode_algorithm_identifier(buf,val[i],&length);
+ if(retval) return retval;
+ sum += length;
+ }
+ asn1_makeseq();
+
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_auth_pack(asn1buf *buf, const krb5_auth_pack *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ if (val->clientDHNonce.length != 0)
+ asn1_addlenfield(val->clientDHNonce.length, val->clientDHNonce.data, 3, asn1_encode_octetstring);
+ if (val->supportedCMSTypes != NULL)
+ asn1_addfield((const krb5_algorithm_identifier **)val->supportedCMSTypes,2,asn1_encode_sequence_of_algorithm_identifier);
+ if (val->clientPublicValue != NULL)
+ asn1_addfield(val->clientPublicValue,1,asn1_encode_subject_pk_info);
+ asn1_addfield(&(val->pkAuthenticator),0,asn1_encode_pk_authenticator);
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_auth_pack_draft9(asn1buf *buf, const krb5_auth_pack_draft9 *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ if (val->clientPublicValue != NULL)
+ asn1_addfield(val->clientPublicValue, 1, asn1_encode_subject_pk_info);
+ asn1_addfield(&(val->pkAuthenticator), 0, asn1_encode_pk_authenticator_draft9);
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_external_principal_identifier(asn1buf *buf, const krb5_external_principal_identifier *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ /* Verify there is something to encode */
+ if (val->subjectKeyIdentifier.length == 0 && val->issuerAndSerialNumber.length == 0 && val->subjectName.length == 0)
+ return ASN1_MISSING_FIELD;
+
+ if (val->subjectKeyIdentifier.length != 0)
+ asn1_insert_implicit_octetstring(val->subjectKeyIdentifier.length,val->subjectKeyIdentifier.data,2);
+
+ if (val->issuerAndSerialNumber.length != 0)
+ asn1_insert_implicit_octetstring(val->issuerAndSerialNumber.length,val->issuerAndSerialNumber.data,1);
+
+ if (val->subjectName.length != 0)
+ asn1_insert_implicit_octetstring(val->subjectName.length,val->subjectName.data,0);
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_external_principal_identifier(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen)
+{
+ asn1_setup();
+ int i;
+
+ if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+
+ for(i=0; val[i] != NULL; i++);
+ for(i--; i>=0; i--){
+ retval = asn1_encode_external_principal_identifier(buf,val[i],&length);
+ if(retval) return retval;
+ sum += length;
+ }
+ asn1_makeseq();
+
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_pa_pk_as_req(asn1buf *buf, const krb5_pa_pk_as_req *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ if (val->kdcPkId.length != 0)
+ asn1_insert_implicit_octetstring(val->kdcPkId.length,val->kdcPkId.data,2);
+
+ if (val->trustedCertifiers != NULL)
+ asn1_addfield((const krb5_external_principal_identifier **)val->trustedCertifiers,1,asn1_encode_sequence_of_external_principal_identifier);
+
+ asn1_insert_implicit_octetstring(val->signedAuthPack.length,val->signedAuthPack.data,0);
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_trusted_ca(asn1buf *buf, const krb5_trusted_ca *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ switch (val->choice) {
+ case choice_trusted_cas_issuerAndSerial:
+ asn1_insert_implicit_octetstring(val->u.issuerAndSerial.length,val->u.issuerAndSerial.data,2);
+ break;
+ case choice_trusted_cas_caName:
+ asn1_insert_implicit_octetstring(val->u.caName.length,val->u.caName.data,1);
+ break;
+ case choice_trusted_cas_principalName:
+ asn1_addfield_implicit(val->u.principalName,0,asn1_encode_principal_name);
+ break;
+ default:
+ return ASN1_MISSING_FIELD;
+ }
+
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_trusted_ca(asn1buf *buf, const krb5_trusted_ca **val, unsigned int *retlen)
+{
+ asn1_setup();
+ int i;
+
+ if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+
+ for(i=0; val[i] != NULL; i++);
+ for(i--; i>=0; i--){
+ retval = asn1_encode_trusted_ca(buf,val[i],&length);
+ if(retval) return retval;
+ sum += length;
+ }
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_pa_pk_as_req_draft9(asn1buf *buf, const krb5_pa_pk_as_req_draft9 *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ if (val->encryptionCert.length != 0)
+ asn1_insert_implicit_octetstring(val->encryptionCert.length,val->encryptionCert.data,3);
+
+ if (val->kdcCert.length != 0)
+ asn1_insert_implicit_octetstring(val->kdcCert.length,val->kdcCert.data,2);
+
+ if (val->trustedCertifiers != NULL)
+ asn1_addfield((const krb5_trusted_ca **)val->trustedCertifiers,1,asn1_encode_sequence_of_trusted_ca);
+
+ asn1_insert_implicit_octetstring(val->signedAuthPack.length,val->signedAuthPack.data,0);
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_dh_rep_info(asn1buf *buf, const krb5_dh_rep_info *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ if (val->serverDHNonce.length != 0)
+ asn1_insert_implicit_octetstring(val->serverDHNonce.length,val->serverDHNonce.data,1);
+
+ asn1_insert_implicit_octetstring(val->dhSignedData.length,val->dhSignedData.data,0);
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_kdc_dh_key_info(asn1buf *buf, const krb5_kdc_dh_key_info *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ if (val->dhKeyExpiration != 0)
+ asn1_addfield(val->dhKeyExpiration, 2, asn1_encode_kerberos_time);
+ asn1_addfield(val->nonce, 1, asn1_encode_integer);
+
+ asn1_insert_implicit_bitstring(val->subjectPublicKey.length,val->subjectPublicKey.data,3);
+ retval = asn1_make_etag(buf, CONTEXT_SPECIFIC, 0,
+ val->subjectPublicKey.length + 1 + length,
+ &length);
+ if(retval) {
+ asn1buf_destroy(&buf);
+ return retval;
+ }
+ sum += length;
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_reply_key_pack(asn1buf *buf, const krb5_reply_key_pack *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ asn1_addfield(&(val->asChecksum), 1, asn1_encode_checksum);
+ asn1_addfield(&(val->replyKey), 0, asn1_encode_encryption_key);
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_reply_key_pack_draft9(asn1buf *buf, const krb5_reply_key_pack_draft9 *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ asn1_addfield(val->nonce, 1, asn1_encode_integer);
+ asn1_addfield(&(val->replyKey), 0, asn1_encode_encryption_key);
+
+ asn1_makeseq();
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_pa_pk_as_rep(asn1buf *buf, const krb5_pa_pk_as_rep *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ switch (val->choice)
+ {
+ case choice_pa_pk_as_rep_dhInfo:
+ asn1_addfield(&(val->u.dh_Info), choice_pa_pk_as_rep_dhInfo, asn1_encode_dh_rep_info);
+ break;
+ case choice_pa_pk_as_rep_encKeyPack:
+ asn1_insert_implicit_octetstring(val->u.encKeyPack.length,val->u.encKeyPack.data,1);
+ break;
+ default:
+ return ASN1_MISSING_FIELD;
+ }
+
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_pa_pk_as_rep_draft9(asn1buf *buf, const krb5_pa_pk_as_rep_draft9 *val, unsigned int *retlen)
+{
+ asn1_setup();
+
+ switch (val->choice)
+ {
+ case choice_pa_pk_as_rep_draft9_dhSignedData:
+ asn1_insert_implicit_octetstring(val->u.dhSignedData.length,val->u.dhSignedData.data,0);
+ break;
+ case choice_pa_pk_as_rep_encKeyPack:
+ asn1_insert_implicit_octetstring(val->u.encKeyPack.length,val->u.encKeyPack.data,1);
+ break;
+ default:
+ return ASN1_MISSING_FIELD;
+ }
+
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_td_trusted_certifiers(asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen)
+{
+ asn1_setup();
+ retval = asn1_encode_sequence_of_external_principal_identifier(buf, val, &length);
+ if (retval) {
+ asn1buf_destroy(&buf);
+ return retval;
+ }
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_sequence_of_typed_data(asn1buf *buf, const krb5_typed_data **val, unsigned int *retlen)
+{
+ asn1_setup();
+ int i;
+
+ if(val == NULL || val[0] == NULL) return ASN1_MISSING_FIELD;
+
+ for(i=0; val[i] != NULL; i++);
+ for(i--; i>=0; i--){
+ retval = asn1_encode_typed_data(buf,val[i],&length);
+ if(retval) return retval;
+ sum += length;
+ }
+ asn1_makeseq();
+
+ asn1_cleanup();
+}
+
+asn1_error_code asn1_encode_typed_data(asn1buf *buf, const krb5_typed_data *val, unsigned int *retlen)
+{
+ asn1_setup();
+ asn1_addlenfield(val->length, val->data, 1, asn1_encode_octetstring);
+ asn1_addfield(val->type, 0, asn1_encode_integer);
+ asn1_makeseq();
+ asn1_cleanup();
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_encode.h b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_encode.h
index 546e72b1d6..b5f24c42b7 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_encode.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/asn1_k_encode.h
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* src/lib/krb5/asn.1/asn1_k_encode.h
*
@@ -271,4 +269,71 @@ asn1_error_code asn1_encode_predicted_sam_response
asn1_error_code asn1_encode_krb_saved_safe_body
(asn1buf *buf, const krb5_data *body, unsigned int *retlen);
+/* PKINIT */
+
+asn1_error_code asn1_encode_pk_authenticator
+ (asn1buf *buf, const krb5_pk_authenticator *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_pk_authenticator_draft9
+ (asn1buf *buf, const krb5_pk_authenticator_draft9 *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_algorithm_identifier
+ (asn1buf *buf, const krb5_algorithm_identifier *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_subject_pk_info
+ (asn1buf *buf, const krb5_subject_pk_info *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_algorithm_identifier
+ (asn1buf *buf, const krb5_algorithm_identifier **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_auth_pack
+ (asn1buf *buf, const krb5_auth_pack *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_auth_pack_draft9
+ (asn1buf *buf, const krb5_auth_pack_draft9 *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_external_principal_identifier
+ (asn1buf *buf, const krb5_external_principal_identifier *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_external_principal_identifier
+ (asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_pa_pk_as_req
+ (asn1buf *buf, const krb5_pa_pk_as_req *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_trusted_ca
+ (asn1buf *buf, const krb5_trusted_ca *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_trusted_ca
+ (asn1buf *buf, const krb5_trusted_ca **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_pa_pk_as_req_draft9
+ (asn1buf *buf, const krb5_pa_pk_as_req_draft9 *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_dh_rep_info
+ (asn1buf *buf, const krb5_dh_rep_info *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_kdc_dh_key_info
+ (asn1buf *buf, const krb5_kdc_dh_key_info *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_reply_key_pack
+ (asn1buf *buf, const krb5_reply_key_pack *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_reply_key_pack_draft9
+ (asn1buf *buf, const krb5_reply_key_pack_draft9 *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_pa_pk_as_rep
+ (asn1buf *buf, const krb5_pa_pk_as_rep *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_pa_pk_as_rep_draft9
+ (asn1buf *buf, const krb5_pa_pk_as_rep_draft9 *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_td_trusted_certifiers
+ (asn1buf *buf, const krb5_external_principal_identifier **val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_typed_data
+ (asn1buf *buf, const krb5_typed_data *val, unsigned int *retlen);
+
+asn1_error_code asn1_encode_sequence_of_typed_data
+ (asn1buf *buf, const krb5_typed_data **val, unsigned int *retlen);
#endif
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krb5_decode.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krb5_decode.c
index 9fec5ecee1..cbd6a12941 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krb5_decode.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krb5_decode.c
@@ -1,11 +1,4 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
* src/lib/krb5/asn.1/krb5_decode.c
*
* Copyright 1994 by the Massachusetts Institute of Technology.
@@ -31,7 +24,7 @@
* or implied warranty.
*/
-#include "krb5.h"
+#include "k5-int.h"
#include "krbasn1.h"
#include "asn1_k_decode.h"
#include "asn1_decode.h"
@@ -533,6 +526,7 @@ krb5_error_code decode_krb5_safe_with_body(
setup();
alloc_field(*rep,krb5_safe);
clear_field(rep,checksum);
+ tmpbody.magic = 0;
check_apptag(20);
{ begin_structure();
@@ -940,3 +934,150 @@ krb5_error_code decode_krb5_predicted_sam_response(const krb5_data *code, krb5_p
cleanup(free);
}
+krb5_error_code decode_krb5_pa_pk_as_req(const krb5_data *code, krb5_pa_pk_as_req **rep)
+{
+ setup_buf_only();
+ alloc_field(*rep, krb5_pa_pk_as_req);
+
+ retval = asn1_decode_pa_pk_as_req(&buf, *rep);
+ if (retval) clean_return(retval);
+
+ cleanup(free);
+}
+
+krb5_error_code decode_krb5_pa_pk_as_req_draft9(const krb5_data *code, krb5_pa_pk_as_req_draft9 **rep)
+{
+ setup_buf_only();
+ alloc_field(*rep, krb5_pa_pk_as_req_draft9);
+
+ retval = asn1_decode_pa_pk_as_req_draft9(&buf, *rep);
+ if (retval) clean_return(retval);
+
+ cleanup(free);
+}
+
+krb5_error_code decode_krb5_pa_pk_as_rep(const krb5_data *code, krb5_pa_pk_as_rep **rep)
+{
+ setup_buf_only();
+ alloc_field(*rep, krb5_pa_pk_as_rep);
+
+ retval = asn1_decode_pa_pk_as_rep(&buf, *rep);
+ if (retval) clean_return(retval);
+
+ cleanup(free);
+}
+
+krb5_error_code decode_krb5_pa_pk_as_rep_draft9(const krb5_data *code, krb5_pa_pk_as_rep_draft9 **rep)
+{
+ setup_buf_only();
+ alloc_field(*rep, krb5_pa_pk_as_rep_draft9);
+
+ retval = asn1_decode_pa_pk_as_rep_draft9(&buf, *rep);
+ if (retval) clean_return(retval);
+
+ cleanup(free);
+}
+
+krb5_error_code decode_krb5_auth_pack(const krb5_data *code, krb5_auth_pack **rep)
+{
+ setup_buf_only();
+ alloc_field(*rep, krb5_auth_pack);
+
+ retval = asn1_decode_auth_pack(&buf, *rep);
+ if (retval) clean_return(retval);
+
+ cleanup(free);
+}
+
+krb5_error_code decode_krb5_auth_pack_draft9(const krb5_data *code, krb5_auth_pack_draft9 **rep)
+{
+ setup_buf_only();
+ alloc_field(*rep, krb5_auth_pack_draft9);
+
+ retval = asn1_decode_auth_pack_draft9(&buf, *rep);
+ if (retval) clean_return(retval);
+
+ cleanup(free);
+}
+
+krb5_error_code decode_krb5_kdc_dh_key_info(const krb5_data *code, krb5_kdc_dh_key_info **rep)
+{
+ setup_buf_only();
+ alloc_field(*rep, krb5_kdc_dh_key_info);
+
+ retval = asn1_decode_kdc_dh_key_info(&buf, *rep);
+ if (retval) clean_return(retval);
+
+ cleanup(free);
+}
+
+krb5_error_code decode_krb5_principal_name(const krb5_data *code, krb5_principal_data **rep)
+{
+ setup_buf_only();
+ alloc_field(*rep, krb5_principal_data);
+
+ retval = asn1_decode_krb5_principal_name(&buf, rep);
+ if (retval) clean_return(retval);
+
+ cleanup(free);
+}
+
+krb5_error_code decode_krb5_reply_key_pack(const krb5_data *code, krb5_reply_key_pack **rep)
+{
+ setup_buf_only();
+ alloc_field(*rep, krb5_reply_key_pack);
+
+ retval = asn1_decode_reply_key_pack(&buf, *rep);
+ if (retval)
+ goto error_out;
+
+ cleanup_manual();
+error_out:
+ if (rep && *rep) {
+ if ((*rep)->replyKey.contents)
+ free((*rep)->replyKey.contents);
+ if ((*rep)->asChecksum.contents)
+ free((*rep)->asChecksum.contents);
+ free(*rep);
+ *rep = NULL;
+ }
+ return retval;
+}
+
+krb5_error_code decode_krb5_reply_key_pack_draft9(const krb5_data *code, krb5_reply_key_pack_draft9 **rep)
+{
+ setup_buf_only();
+ alloc_field(*rep, krb5_reply_key_pack_draft9);
+
+ retval = asn1_decode_reply_key_pack_draft9(&buf, *rep);
+ if (retval) clean_return(retval);
+
+ cleanup(free);
+}
+
+krb5_error_code decode_krb5_typed_data(const krb5_data *code, krb5_typed_data ***rep)
+{
+ setup_buf_only();
+ retval = asn1_decode_sequence_of_typed_data(&buf, rep);
+ if (retval) clean_return(retval);
+
+ cleanup(free);
+}
+
+krb5_error_code decode_krb5_td_trusted_certifiers(const krb5_data *code, krb5_external_principal_identifier ***rep)
+{
+ setup_buf_only();
+ retval = asn1_decode_sequence_of_external_principal_identifier(&buf, rep);
+ if (retval) clean_return(retval);
+
+ cleanup(free);
+}
+
+krb5_error_code decode_krb5_td_dh_parameters(const krb5_data *code, krb5_algorithm_identifier ***rep)
+{
+ setup_buf_only();
+ retval = asn1_decode_sequence_of_algorithm_identifier(&buf, rep);
+ if (retval) clean_return(retval);
+
+ cleanup(free);
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krb5_encode.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krb5_encode.c
index 4b1d62dd9d..4cb800de6f 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krb5_encode.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krb5_encode.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* src/lib/krb5/asn.1/krb5_encode.c
@@ -26,7 +25,7 @@
* or implied warranty.
*/
-#include "krb5.h"
+#include "k5-int.h"
#include "asn1_k_encode.h"
#include "asn1_encode.h"
#include "krbasn1.h"
@@ -699,6 +698,23 @@ krb5_error_code encode_krb5_authdata(const krb5_authdata **rep, krb5_data **code
krb5_cleanup();
}
+krb5_error_code encode_krb5_authdata_elt(const krb5_authdata *rep, krb5_data **code)
+{
+ asn1_error_code retval;
+ asn1buf *buf=NULL;
+ unsigned int length;
+
+ if(rep == NULL) return ASN1_MISSING_FIELD;
+
+ retval = asn1buf_create(&buf);
+ if(retval) return retval;
+
+ retval = asn1_encode_krb5_authdata_elt(buf,rep, &length);
+ if(retval) return retval;
+
+ krb5_cleanup();
+}
+
krb5_error_code encode_krb5_alt_method(const krb5_alt_method *rep, krb5_data **code)
{
krb5_setup();
@@ -883,9 +899,118 @@ krb5_error_code encode_krb5_setpw_req(const krb5_principal target,
krb5_addfield(target,2,asn1_encode_realm);
krb5_addfield(target,1,asn1_encode_principal_name);
+ /* Solaris Kerberos */
krb5_addlenfield(strlen(password), (const unsigned char *)password,0,asn1_encode_octetstring);
krb5_makeseq();
krb5_cleanup();
}
+
+krb5_error_code encode_krb5_pa_pk_as_req(const krb5_pa_pk_as_req *rep, krb5_data **code)
+{
+ krb5_setup();
+ retval = asn1_encode_pa_pk_as_req(buf,rep,&length);
+ if(retval) return retval;
+ sum += length;
+ krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_pa_pk_as_req_draft9(const krb5_pa_pk_as_req_draft9 *rep, krb5_data **code)
+{
+ krb5_setup();
+ retval = asn1_encode_pa_pk_as_req_draft9(buf,rep,&length);
+ if(retval) return retval;
+ sum += length;
+ krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_pa_pk_as_rep(const krb5_pa_pk_as_rep *rep, krb5_data **code)
+{
+ krb5_setup();
+ retval = asn1_encode_pa_pk_as_rep(buf,rep,&length);
+ if(retval) return retval;
+ sum += length;
+ krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_pa_pk_as_rep_draft9(const krb5_pa_pk_as_rep_draft9 *rep, krb5_data **code)
+{
+ krb5_setup();
+ retval = asn1_encode_pa_pk_as_rep_draft9(buf,rep,&length);
+ if(retval) return retval;
+ sum += length;
+ krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_auth_pack(const krb5_auth_pack *rep, krb5_data **code)
+{
+ krb5_setup();
+ retval = asn1_encode_auth_pack(buf,rep,&length);
+ if(retval) return retval;
+ sum += length;
+ krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_auth_pack_draft9(const krb5_auth_pack_draft9 *rep, krb5_data **code)
+{
+ krb5_setup();
+ retval = asn1_encode_auth_pack_draft9(buf,rep,&length);
+ if(retval) return retval;
+ sum += length;
+ krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_kdc_dh_key_info(const krb5_kdc_dh_key_info *rep, krb5_data **code)
+{
+ krb5_setup();
+ retval = asn1_encode_kdc_dh_key_info(buf,rep,&length);
+ if(retval) return retval;
+ sum += length;
+ krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_reply_key_pack(const krb5_reply_key_pack *rep, krb5_data **code)
+{
+ krb5_setup();
+ retval = asn1_encode_reply_key_pack(buf,rep,&length);
+ if(retval) return retval;
+ sum += length;
+ krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_reply_key_pack_draft9(const krb5_reply_key_pack_draft9 *rep, krb5_data **code)
+{
+ krb5_setup();
+ retval = asn1_encode_reply_key_pack_draft9(buf,rep,&length);
+ if(retval) return retval;
+ sum += length;
+ krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_td_trusted_certifiers(const krb5_external_principal_identifier **rep, krb5_data **code)
+{
+ krb5_setup();
+ retval = asn1_encode_td_trusted_certifiers(buf,rep,&length);
+ if(retval) return retval;
+ sum += length;
+ krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_typed_data(const krb5_typed_data **rep, krb5_data **code)
+{
+ krb5_setup();
+ retval = asn1_encode_sequence_of_typed_data(buf,rep,&length);
+ if(retval) return retval;
+ sum += length;
+ krb5_cleanup();
+}
+
+krb5_error_code encode_krb5_td_dh_parameters(const krb5_algorithm_identifier **rep, krb5_data **code)
+{
+ krb5_setup();
+ retval = asn1_encode_sequence_of_algorithm_identifier(buf,rep,&length);
+ if(retval) return retval;
+ sum += length;
+ krb5_cleanup();
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krbasn1.h b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krbasn1.h
index df3237260b..7a45298ada 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krbasn1.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/asn.1/krbasn1.h
@@ -1,9 +1,7 @@
#ifndef __KRBASN1_H__
#define __KRBASN1_H__
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#include <k5-int.h>
+#include "k5-int.h"
#include <stdio.h>
#include <errno.h>
#include <limits.h> /* For INT_MAX */
@@ -59,7 +57,7 @@ typedef int asn1_tagnum;
#define ASN1_OCTETSTRING 4
#define ASN1_NULL 5
#define ASN1_OBJECTIDENTIFIER 6
-#define ASN1_ENUMERATED 10
+#define ASN1_ENUMERATED 10
#define ASN1_SEQUENCE 16
#define ASN1_SET 17
#define ASN1_PRINTABLESTRING 19
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc-int.h b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc-int.h
index eac6ed7295..430e4c3755 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc-int.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc-int.h
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/krb5/ccache/file/cc-int.h
*
@@ -45,6 +43,7 @@ void
krb5int_cc_finalize(void);
extern k5_mutex_t krb5int_mcc_mutex;
+extern k5_mutex_t krb5int_krcc_mutex;
extern k5_mutex_t krb5int_cc_file_mutex;
#endif /* __KRB5_CCACHE_H__ */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_file.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_file.c
index 17302a9d38..724dacb24e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_file.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_file.c
@@ -34,8 +34,6 @@
* implementation of file-based credentials cache
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
If OPENCLOSE is defined, each of the functions opens and closes the
file whenever it needs to access it. Otherwise, the file is opened
@@ -86,8 +84,6 @@ etc.
#include <syslog.h> /* Solaris Kerberos */
#include <ctype.h>
-#define NEED_SOCKETS /* Only for ntohs, etc. */
-#define NEED_LOWLEVEL_IO
#include <stdio.h>
#include <errno.h>
@@ -443,9 +439,9 @@ krb5_fcc_read(krb5_context context, krb5_ccache id, krb5_pointer buf, unsigned i
* KRB5_CC_NOMEM
*/
-#define ALLOC(NUM,TYPE) \
- (((NUM) <= (((size_t)0-1)/ sizeof(TYPE))) \
- ? (TYPE *) calloc((NUM), sizeof(TYPE)) \
+#define ALLOC(NUM,TYPE) \
+ (((NUM) <= (((size_t)0-1)/ sizeof(TYPE))) \
+ ? (TYPE *) calloc((NUM), sizeof(TYPE)) \
: (errno = ENOMEM,(TYPE *) 0))
static krb5_error_code
@@ -458,7 +454,9 @@ krb5_fcc_read_principal(krb5_context context, krb5_ccache id, krb5_principal *pr
int i;
k5_assert_locked(&((krb5_fcc_data *) id->data)->lock);
-
+
+ *princ = NULL;
+
if (data->version == KRB5_FCC_FVNO_1) {
type = KRB5_NT_UNKNOWN;
} else {
@@ -554,15 +552,18 @@ krb5_fcc_read_addrs(krb5_context context, krb5_ccache id, krb5_address ***addrs)
if ((*addrs)[i] == NULL) {
krb5_free_addresses(context, *addrs);
return KRB5_CC_NOMEM;
- }
+ }
+ (*addrs)[i]->contents = NULL;
kret = krb5_fcc_read_addr(context, id, (*addrs)[i]);
CHECK(kret);
}
return KRB5_OK;
errout:
- if (*addrs)
+ if (*addrs) {
krb5_free_addresses(context, *addrs);
+ *addrs = NULL;
+ }
return kret;
}
@@ -599,6 +600,7 @@ krb5_fcc_read_keyblock(krb5_context context, krb5_ccache id, krb5_keyblock *keyb
return KRB5_CC_NOMEM;
if ( keyblock->length == 0 )
return KRB5_OK;
+ /* Solaris Kerberos */
keyblock->contents = calloc(keyblock->length, sizeof(krb5_octet));
if (keyblock->contents == NULL)
return KRB5_CC_NOMEM;
@@ -609,8 +611,10 @@ krb5_fcc_read_keyblock(krb5_context context, krb5_ccache id, krb5_keyblock *keyb
return KRB5_OK;
errout:
- if (keyblock->contents)
+ if (keyblock->contents) {
krb5_xfree(keyblock->contents);
+ keyblock->contents = NULL;
+ }
return kret;
}
@@ -648,8 +652,10 @@ krb5_fcc_read_data(krb5_context context, krb5_ccache id, krb5_data *data)
data->data[data->length] = 0; /* Null terminate, just in case.... */
return KRB5_OK;
errout:
- if (data->data)
+ if (data->data) {
krb5_xfree(data->data);
+ data->data = NULL;
+ }
return kret;
}
@@ -691,8 +697,10 @@ krb5_fcc_read_addr(krb5_context context, krb5_ccache id, krb5_address *addr)
return KRB5_OK;
errout:
- if (addr->contents)
+ if (addr->contents) {
krb5_xfree(addr->contents);
+ addr->contents = NULL;
+ }
return kret;
}
@@ -820,15 +828,18 @@ krb5_fcc_read_authdata(krb5_context context, krb5_ccache id, krb5_authdata ***a)
if ((*a)[i] == NULL) {
krb5_free_authdata(context, *a);
return KRB5_CC_NOMEM;
- }
+ }
+ (*a)[i]->contents = NULL;
kret = krb5_fcc_read_authdatum(context, id, (*a)[i]);
CHECK(kret);
}
return KRB5_OK;
errout:
- if (*a)
+ if (*a) {
krb5_free_authdata(context, *a);
+ *a = NULL;
+ }
return kret;
}
@@ -869,8 +880,10 @@ krb5_fcc_read_authdatum(krb5_context context, krb5_ccache id, krb5_authdata *a)
return KRB5_OK;
errout:
- if (a->contents)
+ if (a->contents) {
krb5_xfree(a->contents);
+ a->contents = NULL;
+ }
return kret;
}
@@ -1202,8 +1215,7 @@ krb5_fcc_close_file (krb5_context context, krb5_fcc_data *data)
((SIZE) < BUFSIZE ? (abort(),0) : setbuf(FILE, BUF))
#endif
-
-
+/* Solaris Kerberos */
static krb5_error_code
krb5_fcc_open_nounlink(char *filename, int open_flag, int *ret_fd, int *new)
{
@@ -1357,6 +1369,7 @@ krb5_fcc_open_file (krb5_context context, krb5_ccache id, int mode)
}
switch(mode) {
+ /* Solaris Kerberos */
case FCC_OPEN_AND_ERASE_NOUNLINK:
open_flag = O_RDWR;
break;
@@ -1397,9 +1410,8 @@ fcc_retry:
lock_flag = KRB5_LOCKMODE_SHARED;
else
lock_flag = KRB5_LOCKMODE_EXCLUSIVE;
-
if ((retval = krb5_lock_file(context, f, lock_flag))) {
- (void) close(f);
+ (void) close(f);
if (retval == EAGAIN && retries++ < LOCK_RETRIES) {
/* Solaris Kerberos wait some time before retrying */
if (poll(NULL, 0, WAIT_LENGTH) == 0)
@@ -1432,7 +1444,7 @@ fcc_retry:
KRB5_CC_IO);
goto done;
}
- data->file = f;
+ data->file = f;
if (data->version == KRB5_FCC_FVNO_4) {
/* V4 of the credentials cache format allows for header tags */
@@ -1983,13 +1995,13 @@ krb5_fcc_start_seq_get(krb5_context context, krb5_ccache id,
/* Make sure we start reading right after the primary principal */
kret = krb5_fcc_skip_header(context, id);
if (kret) {
- /* SUNW14resync - fix mem leak */
+ /* Solaris Kerberos - fix mem leak */
krb5_xfree(fcursor);
goto done;
}
kret = krb5_fcc_skip_principal(context, id);
if (kret) {
- /* SUNW14resync - fix mem leak */
+ /* Solaris Kerberos - fix mem leak */
krb5_xfree(fcursor);
goto done;
}
@@ -2132,115 +2144,165 @@ krb5_fcc_generate_new (krb5_context context, krb5_ccache *id)
{
krb5_ccache lid;
int ret;
- krb5_error_code retcode = 0;
+ krb5_error_code kret = 0;
char scratch[sizeof(TKT_ROOT)+6+1]; /* +6 for the scratch part, +1 for
NUL */
krb5_fcc_data *data;
+ krb5_int16 fcc_fvno = htons(context->fcc_default_format);
+ krb5_int16 fcc_flen = 0;
+ int errsave, cnt;
+ struct fcc_set *setptr;
- /* Allocate memory */
- lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
- if (lid == NULL)
- return KRB5_CC_NOMEM;
-
- lid->ops = &krb5_fcc_ops;
+ /* Set master lock */
+ kret = k5_mutex_lock(&krb5int_cc_file_mutex);
+ if (kret)
+ return kret;
(void) strcpy(scratch, TKT_ROOT);
(void) strcat(scratch, "XXXXXX");
#ifdef HAVE_MKSTEMP
ret = mkstemp(scratch);
if (ret == -1) {
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
return krb5_fcc_interpret(context, errno);
- } else close(ret);
+ }
#else /*HAVE_MKSTEMP*/
mktemp(scratch);
+ /* Make sure the file name is reserved */
+ ret = THREEPARAMOPEN(scratch, O_CREAT | O_EXCL | O_WRONLY | O_BINARY, 0);
+ if (ret == -1) {
+ return krb5_fcc_interpret(context, errno);
+ }
#endif
- lid->data = (krb5_pointer) malloc(sizeof(krb5_fcc_data));
- if (lid->data == NULL) {
- krb5_xfree(lid);
+ /* Allocate memory */
+ data = (krb5_pointer) malloc(sizeof(krb5_fcc_data));
+ if (data == NULL) {
+ close(ret);
+ unlink(scratch);
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
return KRB5_CC_NOMEM;
}
- ((krb5_fcc_data *) lid->data)->filename = (char *)
- malloc(strlen(scratch) + 1);
- if (((krb5_fcc_data *) lid->data)->filename == NULL) {
- krb5_xfree(((krb5_fcc_data *) lid->data));
- krb5_xfree(lid);
+ data->filename = strdup(scratch);
+ if (data->filename == NULL) {
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
+ free(data);
+ close(ret);
+ unlink(scratch);
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
return KRB5_CC_NOMEM;
}
+ kret = k5_mutex_init(&data->lock);
+ if (kret) {
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
+ free(data->filename);
+ free(data);
+ close(ret);
+ unlink(scratch);
+ return kret;
+ }
+ kret = k5_mutex_lock(&data->lock);
+ if (kret) {
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_mutex_destroy(&data->lock);
+ free(data->filename);
+ free(data);
+ close(ret);
+ unlink(scratch);
+ return kret;
+ }
+
/*
* The file is initially closed at the end of this call...
*/
- ((krb5_fcc_data *) lid->data)->flags = 0;
- ((krb5_fcc_data *) lid->data)->file = -1;
- ((krb5_fcc_data *) lid->data)->valid_bytes = 0;
- data = (krb5_fcc_data *) lid->data;
-
- retcode = k5_mutex_init(&data->lock);
- if (retcode)
- goto err_out;
+ data->flags = 0;
+ data->file = -1;
+ data->valid_bytes = 0;
+ /* data->version,mode filled in for real later */
+ data->version = data->mode = 0;
- /* Set up the filename */
- strcpy(((krb5_fcc_data *) lid->data)->filename, scratch);
- /* Make sure the file name is reserved */
- ret = THREEPARAMOPEN(((krb5_fcc_data *) lid->data)->filename,
- O_CREAT | O_EXCL | O_WRONLY | O_BINARY, 0);
- if (ret == -1) {
- retcode = krb5_fcc_interpret(context, errno);
- goto err_out;
- } else {
- krb5_int16 fcc_fvno = htons(context->fcc_default_format);
- krb5_int16 fcc_flen = 0;
- int errsave, cnt;
-
- /* Ignore user's umask, set mode = 0600 */
+ /* Ignore user's umask, set mode = 0600 */
#ifndef HAVE_FCHMOD
#ifdef HAVE_CHMOD
- chmod(((krb5_fcc_data *) lid->data)->filename, S_IRUSR | S_IWUSR);
+ chmod(data->filename, S_IRUSR | S_IWUSR);
#endif
#else
- fchmod(ret, S_IRUSR | S_IWUSR);
+ fchmod(ret, S_IRUSR | S_IWUSR);
#endif
- if ((cnt = write(ret, (char *)&fcc_fvno, sizeof(fcc_fvno)))
- != sizeof(fcc_fvno)) {
- errsave = errno;
- (void) close(ret);
- (void) unlink(((krb5_fcc_data *) lid->data)->filename);
- retcode = (cnt == -1) ? krb5_fcc_interpret(context, errsave) : KRB5_CC_IO;
- goto err_out;
- }
- /* For version 4 we save a length for the rest of the header */
- if (context->fcc_default_format == KRB5_FCC_FVNO_4) {
- if ((cnt = write(ret, (char *)&fcc_flen, sizeof(fcc_flen)))
- != sizeof(fcc_flen)) {
- errsave = errno;
- (void) close(ret);
- (void) unlink(((krb5_fcc_data *) lid->data)->filename);
- retcode = (cnt == -1) ? krb5_fcc_interpret(context, errsave) : KRB5_CC_IO;
- goto err_out;
- }
- }
- if (close(ret) == -1) {
- errsave = errno;
- (void) unlink(((krb5_fcc_data *) lid->data)->filename);
- retcode = krb5_fcc_interpret(context, errsave);
- goto err_out;
+ if ((cnt = write(ret, (char *)&fcc_fvno, sizeof(fcc_fvno)))
+ != sizeof(fcc_fvno)) {
+ errsave = errno;
+ (void) close(ret);
+ (void) unlink(data->filename);
+ kret = (cnt == -1) ? krb5_fcc_interpret(context, errsave) : KRB5_CC_IO;
+ goto err_out;
+ }
+ /* For version 4 we save a length for the rest of the header */
+ if (context->fcc_default_format == KRB5_FCC_FVNO_4) {
+ if ((cnt = write(ret, (char *)&fcc_flen, sizeof(fcc_flen)))
+ != sizeof(fcc_flen)) {
+ errsave = errno;
+ (void) close(ret);
+ (void) unlink(data->filename);
+ kret = (cnt == -1) ? krb5_fcc_interpret(context, errsave) : KRB5_CC_IO;
+ goto err_out;
}
- *id = lid;
- /* default to open/close on every trn - otherwise destroy
- will get as to state confused */
- ((krb5_fcc_data *) lid->data)->flags = KRB5_TC_OPENCLOSE;
- krb5_change_cache ();
- return KRB5_OK;
}
+ if (close(ret) == -1) {
+ errsave = errno;
+ (void) unlink(data->filename);
+ kret = krb5_fcc_interpret(context, errsave);
+ goto err_out;
+ }
+
+
+ setptr = malloc(sizeof(struct fcc_set));
+ if (setptr == NULL) {
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_mutex_destroy(&data->lock);
+ free(data->filename);
+ free(data);
+ (void) close(ret);
+ (void) unlink(scratch);
+ return KRB5_CC_NOMEM;
+ }
+ setptr->refcount = 1;
+ setptr->data = data;
+ setptr->next = fccs;
+ fccs = setptr;
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
+
+ k5_mutex_assert_locked(&data->lock);
+ k5_mutex_unlock(&data->lock);
+ lid = (krb5_ccache) malloc(sizeof(struct _krb5_ccache));
+ if (lid == NULL) {
+ dereference(context, data);
+ return KRB5_CC_NOMEM;
+ }
+
+ lid->ops = &krb5_fcc_ops;
+ lid->data = data;
+ lid->magic = KV5M_CCACHE;
+
+ /* default to open/close on every trn - otherwise destroy
+ will get as to state confused */
+ ((krb5_fcc_data *) lid->data)->flags = KRB5_TC_OPENCLOSE;
+
+ *id = lid;
+
+
+ krb5_change_cache ();
+ return KRB5_OK;
err_out:
- krb5_xfree(((krb5_fcc_data *) lid->data)->filename);
- krb5_xfree(((krb5_fcc_data *) lid->data));
- krb5_xfree(lid);
- return retcode;
+ k5_mutex_unlock(&krb5int_cc_file_mutex);
+ k5_mutex_destroy(&data->lock);
+ free(data->filename);
+ free(data);
+ return kret;
}
/*
@@ -2412,6 +2474,30 @@ krb5_fcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags)
return ret;
}
+/*
+ * Requires:
+ * id is a cred cache returned by krb5_fcc_resolve or
+ * krb5_fcc_generate_new, but has not been opened by krb5_fcc_initialize.
+ *
+ * Modifies:
+ * id (mutex only; temporary)
+ *
+ * Effects:
+ * Returns the operational flags of id.
+ */
+static krb5_error_code KRB5_CALLCONV
+krb5_fcc_get_flags(krb5_context context, krb5_ccache id, krb5_flags *flags)
+{
+ krb5_error_code ret = KRB5_OK;
+
+ ret = k5_mutex_lock(&((krb5_fcc_data *) id->data)->lock);
+ if (ret)
+ return ret;
+ *flags = ((krb5_fcc_data *) id->data)->flags;
+ k5_mutex_unlock(&((krb5_fcc_data *) id->data)->lock);
+ return ret;
+}
+
static krb5_error_code
krb5_fcc_interpret(krb5_context context, int errnum)
@@ -2459,6 +2545,9 @@ krb5_fcc_interpret(krb5_context context, int errnum)
case ENXIO:
default:
retval = KRB5_CC_IO; /* XXX */
+ krb5_set_error_message(context, retval,
+ "Credentials cache I/O operation failed (%s)",
+ strerror(errnum));
}
return retval;
}
@@ -2480,6 +2569,7 @@ const krb5_cc_ops krb5_fcc_ops = {
krb5_fcc_end_seq_get,
krb5_fcc_remove_cred,
krb5_fcc_set_flags,
+ krb5_fcc_get_flags,
};
#if defined(_WIN32)
@@ -2540,4 +2630,11 @@ const krb5_cc_ops krb5_cc_file_ops = {
krb5_fcc_end_seq_get,
krb5_fcc_remove_cred,
krb5_fcc_set_flags,
+ krb5_fcc_get_flags,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
};
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_memory.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_memory.c
index 0d7b7e02cd..6e6a9b4f15 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_memory.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_memory.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/ccache/cc_memory.c
@@ -82,6 +81,19 @@ static krb5_error_code KRB5_CALLCONV krb5_mcc_store
static krb5_error_code KRB5_CALLCONV krb5_mcc_set_flags
(krb5_context, krb5_ccache id , krb5_flags flags );
+static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_new(
+ krb5_context,
+ krb5_cc_ptcursor *);
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_next(
+ krb5_context,
+ krb5_cc_ptcursor,
+ krb5_ccache *);
+
+static krb5_error_code KRB5_CALLCONV krb5_mcc_ptcursor_free(
+ krb5_context,
+ krb5_cc_ptcursor *);
+
extern const krb5_cc_ops krb5_mcc_ops;
extern krb5_error_code krb5_change_cache (void);
@@ -104,6 +116,10 @@ typedef struct krb5_mcc_list_node {
krb5_mcc_data *cache;
} krb5_mcc_list_node;
+struct krb5_mcc_ptcursor_data {
+ struct krb5_mcc_list_node *cur;
+};
+
k5_mutex_t krb5int_mcc_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
static krb5_mcc_list_node *mcc_head = 0;
@@ -242,7 +258,7 @@ krb5_mcc_resolve (krb5_context context, krb5_ccache *id, const char *residual)
err = k5_mutex_lock(&krb5int_mcc_mutex);
if (err) {
- /* SUNW14resync - fix mem leak */
+ /* Solaris Kerberos - fix mem leak */
krb5_xfree(lid);
return err;
}
@@ -450,6 +466,8 @@ new_mcc_data (const char *name, krb5_mcc_data **dataptr)
return 0;
}
+static krb5_error_code random_string (krb5_context, char *, unsigned int);
+
/*
* Effects:
* Creates a new file cred cache whose name is guaranteed to be
@@ -464,11 +482,12 @@ new_mcc_data (const char *name, krb5_mcc_data **dataptr)
* krb5_ccache. id is undefined.
* system errors (from open)
*/
+
krb5_error_code KRB5_CALLCONV
krb5_mcc_generate_new (krb5_context context, krb5_ccache *id)
{
krb5_ccache lid;
- char scratch[6+1]; /* 6 for the scratch part, +1 for NUL */
+ char uniquename[8];
krb5_error_code err;
krb5_mcc_data *d;
@@ -478,27 +497,78 @@ krb5_mcc_generate_new (krb5_context context, krb5_ccache *id)
return KRB5_CC_NOMEM;
lid->ops = &krb5_mcc_ops;
-
- (void) strcpy(scratch, "XXXXXX");
- mktemp(scratch);
-
+
err = k5_mutex_lock(&krb5int_mcc_mutex);
if (err) {
free(lid);
return err;
}
- err = new_mcc_data(scratch, &d);
+
+ /* Check for uniqueness with mutex locked to avoid race conditions */
+ while (1) {
+ krb5_mcc_list_node *ptr;
+
+ random_string (context, uniquename, sizeof (uniquename));
+
+ for (ptr = mcc_head; ptr; ptr=ptr->next) {
+ if (!strcmp(ptr->cache->name, uniquename)) {
+ break; /* got a match, loop again */
+ }
+ }
+ if (!ptr) break; /* got to the end without finding a match */
+ }
+
+ err = new_mcc_data(uniquename, &d);
+
k5_mutex_unlock(&krb5int_mcc_mutex);
if (err) {
krb5_xfree(lid);
return err;
}
lid->data = d;
- *id = lid; /* SUNW14resync - fix to 1.4.2 */
+ *id = lid;
krb5_change_cache ();
return KRB5_OK;
}
+/* Utility routine: Creates a random memory ccache name.
+ * This algorithm was selected because it creates readable
+ * random ccache names in a fixed size buffer. */
+
+static krb5_error_code
+random_string (krb5_context context, char *string, unsigned int length)
+{
+ static const unsigned char charlist[] =
+ "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ krb5_error_code err = 0;
+ unsigned char *bytes = NULL;
+ unsigned int bytecount = length - 1;
+
+ if (!err) {
+ bytes = malloc (bytecount);
+ if (bytes == NULL) { err = ENOMEM; }
+ }
+
+ if (!err) {
+ krb5_data data;
+ data.length = bytecount;
+ data.data = (char *) bytes;
+ err = krb5_c_random_make_octets (context, &data);
+ }
+
+ if (!err) {
+ unsigned int i;
+ for (i = 0; i < bytecount; i++) {
+ string [i] = charlist[bytes[i] % (sizeof (charlist) - 1)];
+ }
+ string[length - 1] = '\0';
+ }
+
+ if (bytes != NULL) { free (bytes); }
+
+ return err;
+}
+
/*
* Requires:
* id is a file credential cache
@@ -575,6 +645,13 @@ krb5_mcc_set_flags(krb5_context context, krb5_ccache id, krb5_flags flags)
return KRB5_OK;
}
+static krb5_error_code KRB5_CALLCONV
+krb5_mcc_get_flags(krb5_context context, krb5_ccache id, krb5_flags *flags)
+{
+ *flags = 0;
+ return KRB5_OK;
+}
+
/* store: Save away creds in the ccache. */
krb5_error_code KRB5_CALLCONV
krb5_mcc_store(krb5_context ctx, krb5_ccache id, krb5_creds *creds)
@@ -593,7 +670,8 @@ krb5_mcc_store(krb5_context ctx, krb5_ccache id, krb5_creds *creds)
}
err = k5_mutex_lock(&mptr->lock);
if (err) {
- /* SUNW14resync - fix mem leak */
+ /* Solaris Kerberos - fix mem leaks */
+ krb5_free_creds(ctx, new_node->creds);
free(new_node);
return err;
}
@@ -603,6 +681,92 @@ krb5_mcc_store(krb5_context ctx, krb5_ccache id, krb5_creds *creds)
return 0;
}
+static krb5_error_code KRB5_CALLCONV
+krb5_mcc_ptcursor_new(
+ krb5_context context,
+ krb5_cc_ptcursor *cursor)
+{
+ krb5_error_code ret = 0;
+ krb5_cc_ptcursor n = NULL;
+ struct krb5_mcc_ptcursor_data *cdata = NULL;
+
+ *cursor = NULL;
+
+ n = malloc(sizeof(*n));
+ if (n == NULL)
+ return ENOMEM;
+ n->ops = &krb5_mcc_ops;
+ cdata = malloc(sizeof(struct krb5_mcc_ptcursor_data));
+ if (cdata == NULL) {
+ ret = ENOMEM;
+ goto errout;
+ }
+ n->data = cdata;
+ ret = k5_mutex_lock(&krb5int_mcc_mutex);
+ if (ret)
+ goto errout;
+ cdata->cur = mcc_head;
+ ret = k5_mutex_unlock(&krb5int_mcc_mutex);
+ if (ret)
+ goto errout;
+
+errout:
+ if (ret) {
+ krb5_mcc_ptcursor_free(context, &n);
+ }
+ *cursor = n;
+ return ret;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_mcc_ptcursor_next(
+ krb5_context context,
+ krb5_cc_ptcursor cursor,
+ krb5_ccache *ccache)
+{
+ krb5_error_code ret = 0;
+ struct krb5_mcc_ptcursor_data *cdata = NULL;
+
+ *ccache = NULL;
+ cdata = cursor->data;
+ if (cdata->cur == NULL)
+ return 0;
+
+ *ccache = malloc(sizeof(**ccache));
+ if (*ccache == NULL)
+ return ENOMEM;
+
+ (*ccache)->ops = &krb5_mcc_ops;
+ (*ccache)->data = cdata->cur->cache;
+ ret = k5_mutex_lock(&krb5int_mcc_mutex);
+ if (ret)
+ goto errout;
+ cdata->cur = cdata->cur->next;
+ ret = k5_mutex_unlock(&krb5int_mcc_mutex);
+ if (ret)
+ goto errout;
+errout:
+ if (ret && *ccache != NULL) {
+ free(*ccache);
+ *ccache = NULL;
+ }
+ return ret;
+}
+
+static krb5_error_code KRB5_CALLCONV
+krb5_mcc_ptcursor_free(
+ krb5_context context,
+ krb5_cc_ptcursor *cursor)
+{
+ if (*cursor == NULL)
+ return 0;
+ if ((*cursor)->data != NULL)
+ free((*cursor)->data);
+ free(*cursor);
+ *cursor = NULL;
+ return 0;
+}
+
const krb5_cc_ops krb5_mcc_ops = {
0,
"MEMORY",
@@ -620,4 +784,11 @@ const krb5_cc_ops krb5_mcc_ops = {
krb5_mcc_end_seq_get,
krb5_mcc_remove_cred,
krb5_mcc_set_flags,
+ krb5_mcc_get_flags,
+ krb5_mcc_ptcursor_new,
+ krb5_mcc_ptcursor_next,
+ krb5_mcc_ptcursor_free,
+ NULL,
+ NULL,
+ NULL,
};
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_retr.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_retr.c
index c1dd94d76d..7ba3a90909 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_retr.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/cc_retr.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/ccache/cc_retr.c
@@ -15,7 +14,7 @@
* 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
@@ -29,11 +28,11 @@
* 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.
- *
+ *
*
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include "cc-int.h"
#define KRB5_OK 0
@@ -71,7 +70,7 @@ srvname_match(krb5_context context, const krb5_creds *mcreds, const krb5_creds *
{
krb5_boolean retval;
krb5_principal_data p1, p2;
-
+
retval = krb5_principal_compare(context, mcreds->client,creds->client);
if (retval != TRUE)
return retval;
@@ -85,7 +84,7 @@ srvname_match(krb5_context context, const krb5_creds *mcreds, const krb5_creds *
}
static krb5_boolean
-authdata_match(krb5_authdata *const *mdata, krb5_authdata *const *data)
+authdata_match(krb5_authdata *const *mdata, krb5_authdata *const *data)
{
const krb5_authdata *mdatap, *datap;
@@ -97,13 +96,13 @@ authdata_match(krb5_authdata *const *mdata, krb5_authdata *const *data)
if (data == NULL)
return *mdata == NULL;
-
+
/*LINTED*/
while ((mdatap = *mdata) && (datap = *data)) {
if ((mdatap->ad_type != datap->ad_type) ||
(mdatap->length != datap->length) ||
(memcmp ((char *)mdatap->contents,
- (char *)datap->contents, (unsigned) mdatap->length) != 0))
+ (char *)datap->contents, (unsigned) mdatap->length) != 0))
return FALSE;
mdata++;
data++;
@@ -125,8 +124,8 @@ data_match(const krb5_data *data1, const krb5_data *data2)
if (data1->length != data2->length)
return FALSE;
else
- return memcmp(data1->data, data2->data, (unsigned) data1->length)
- ? FALSE : TRUE;
+ return memcmp(data1->data, data2->data, (unsigned) data1->length)
+ ? FALSE : TRUE;
}
static int
@@ -145,7 +144,7 @@ pref (krb5_enctype my_ktype, int nktypes, krb5_enctype *ktypes)
* with the fields specified by whichfields. If one if found, it is
* returned in creds, which should be freed by the caller with
* krb5_free_credentials().
- *
+ *
* The fields are interpreted in the following way (all constants are
* preceded by KRB5_TC_). MATCH_IS_SKEY requires the is_skey field to
* match exactly. MATCH_TIMES requires the requested lifetime to be
@@ -201,7 +200,9 @@ krb5int_cc_creds_match_request(krb5_context context, krb5_flags whichfields, krb
}
static krb5_error_code
-krb5_cc_retrieve_cred_seq (krb5_context context, krb5_ccache id, krb5_flags whichfields, krb5_creds *mcreds, krb5_creds *creds, int nktypes, krb5_enctype *ktypes)
+krb5_cc_retrieve_cred_seq (krb5_context context, krb5_ccache id,
+ krb5_flags whichfields, krb5_creds *mcreds,
+ krb5_creds *creds, int nktypes, krb5_enctype *ktypes)
{
/* This function could be considerably faster if it kept indexing */
/* information.. sounds like a "next version" idea to me. :-) */
@@ -214,18 +215,28 @@ krb5_cc_retrieve_cred_seq (krb5_context context, krb5_ccache id, krb5_flags whic
int pref;
} fetched, best;
int have_creds = 0;
+ krb5_flags oflags = 0;
#define fetchcreds (fetched.creds)
+ /* Solaris Kerberos */
memset(&best, 0, sizeof (best));
memset(&fetched, 0, sizeof (fetched));
- kret = krb5_cc_start_seq_get(context, id, &cursor);
+ kret = krb5_cc_get_flags(context, id, &oflags);
if (kret != KRB5_OK)
return kret;
+ if (oflags & KRB5_TC_OPENCLOSE)
+ (void) krb5_cc_set_flags(context, id, oflags & ~KRB5_TC_OPENCLOSE);
+ kret = krb5_cc_start_seq_get(context, id, &cursor);
+ if (kret != KRB5_OK) {
+ if (oflags & KRB5_TC_OPENCLOSE)
+ krb5_cc_set_flags(context, id, oflags);
+ return kret;
+ }
while ((kret = krb5_cc_next_cred(context, id, &cursor, &fetchcreds)) == KRB5_OK) {
- if (krb5int_cc_creds_match_request(context, whichfields, mcreds, &fetchcreds))
- {
+ if (krb5int_cc_creds_match_request(context, whichfields, mcreds, &fetchcreds))
+ {
if (ktypes) {
fetched.pref = pref (fetchcreds.keyblock.enctype,
nktypes, ktypes);
@@ -240,9 +251,12 @@ krb5_cc_retrieve_cred_seq (krb5_context context, krb5_ccache id, krb5_flags whic
continue;
}
} else {
- (void) krb5_cc_end_seq_get(context, id, &cursor);
+ krb5_cc_end_seq_get(context, id, &cursor);
*creds = fetchcreds;
+ /* Solaris Kerberos */
creds->keyblock.hKey = CK_INVALID_HANDLE;
+ if (oflags & KRB5_TC_OPENCLOSE)
+ krb5_cc_set_flags(context, id, oflags);
return KRB5_OK;
}
}
@@ -252,9 +266,12 @@ krb5_cc_retrieve_cred_seq (krb5_context context, krb5_ccache id, krb5_flags whic
}
/* If we get here, a match wasn't found */
- (void) krb5_cc_end_seq_get(context, id, &cursor);
+ krb5_cc_end_seq_get(context, id, &cursor);
+ if (oflags & KRB5_TC_OPENCLOSE)
+ krb5_cc_set_flags(context, id, oflags);
if (have_creds) {
*creds = best.creds;
+ /* Solaris Kerberos */
creds->keyblock.hKey = CK_INVALID_HANDLE;
return KRB5_OK;
} else
@@ -281,7 +298,107 @@ krb5_cc_retrieve_cred_default (krb5_context context, krb5_ccache id, krb5_flags
free (ktypes);
return ret;
} else {
+ /* Solaris Kerberos */
return krb5_cc_retrieve_cred_seq (context, id, flags, mcreds, creds,
0, (krb5_enctype *)NULL);
}
}
+
+/* The following function duplicates some of the functionality above and */
+/* should probably be merged with it at some point. It is used by the */
+/* CCAPI krb5_cc_remove to figure out if the opaque credentials object */
+/* returned by the CCAPI is the same creds as the caller passed in. */
+/* Unlike the code above it requires that all structures be identical. */
+
+krb5_boolean KRB5_CALLCONV
+krb5_creds_compare (krb5_context in_context,
+ krb5_creds *in_creds,
+ krb5_creds *in_compare_creds)
+{
+ /* Set to 0 when we hit the first mismatch and then fall through */
+ int equal = 1;
+
+ if (equal) {
+ equal = krb5_principal_compare (in_context, in_creds->client,
+ in_compare_creds->client);
+ }
+
+ if (equal) {
+ equal = krb5_principal_compare (in_context, in_creds->server,
+ in_compare_creds->server);
+ }
+
+ if (equal) {
+ equal = (in_creds->keyblock.enctype == in_compare_creds->keyblock.enctype &&
+ in_creds->keyblock.length == in_compare_creds->keyblock.length &&
+ (!in_creds->keyblock.length ||
+ !memcmp (in_creds->keyblock.contents, in_compare_creds->keyblock.contents,
+ in_creds->keyblock.length)));
+ }
+
+ if (equal) {
+ equal = (in_creds->times.authtime == in_compare_creds->times.authtime &&
+ in_creds->times.starttime == in_compare_creds->times.starttime &&
+ in_creds->times.endtime == in_compare_creds->times.endtime &&
+ in_creds->times.renew_till == in_compare_creds->times.renew_till);
+ }
+
+ if (equal) {
+ equal = (in_creds->is_skey == in_compare_creds->is_skey);
+ }
+
+ if (equal) {
+ equal = (in_creds->ticket_flags == in_compare_creds->ticket_flags);
+ }
+
+ if (equal) {
+ krb5_address **addresses = in_creds->addresses;
+ krb5_address **compare_addresses = in_compare_creds->addresses;
+ unsigned int i;
+
+ if (addresses && compare_addresses) {
+ for (i = 0; (equal && addresses[i] && compare_addresses[i]); i++) {
+ equal = krb5_address_compare (in_context, addresses[i],
+ compare_addresses[i]);
+ }
+ if (equal) { equal = (!addresses[i] && !compare_addresses[i]); }
+ } else {
+ if (equal) { equal = (!addresses && !compare_addresses); }
+ }
+ }
+
+ if (equal) {
+ equal = (in_creds->ticket.length == in_compare_creds->ticket.length &&
+ (!in_creds->ticket.length ||
+ !memcmp (in_creds->ticket.data, in_compare_creds->ticket.data,
+ in_creds->ticket.length)));
+ }
+
+ if (equal) {
+ equal = (in_creds->second_ticket.length == in_compare_creds->second_ticket.length &&
+ (!in_creds->second_ticket.length ||
+ !memcmp (in_creds->second_ticket.data, in_compare_creds->second_ticket.data,
+ in_creds->second_ticket.length)));
+ }
+
+ if (equal) {
+ krb5_authdata **authdata = in_creds->authdata;
+ krb5_authdata **compare_authdata = in_compare_creds->authdata;
+ unsigned int i;
+
+ if (authdata && compare_authdata) {
+ for (i = 0; (equal && authdata[i] && compare_authdata[i]); i++) {
+ equal = (authdata[i]->ad_type == compare_authdata[i]->ad_type &&
+ authdata[i]->length == compare_authdata[i]->length &&
+ (!authdata[i]->length ||
+ !memcmp (authdata[i]->contents, compare_authdata[i]->contents,
+ authdata[i]->length)));
+ }
+ if (equal) { equal = (!authdata[i] && !compare_authdata[i]); }
+ } else {
+ if (equal) { equal = (!authdata && !compare_authdata); }
+ }
+ }
+
+ return equal;
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccbase.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccbase.c
index 7a9fb70d54..89ec1ad9ca 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccbase.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccbase.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/krb5/ccache/ccbase.c
*
@@ -30,7 +28,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -45,22 +43,53 @@ struct krb5_cc_typelist {
const krb5_cc_ops *ops;
struct krb5_cc_typelist *next;
};
+
+struct krb5_cc_typecursor {
+ struct krb5_cc_typelist *tptr;
+};
+/* typedef krb5_cc_typecursor in k5-int.h */
+
extern const krb5_cc_ops krb5_mcc_ops;
+#ifdef USE_KEYRING_CCACHE
+extern const krb5_cc_ops krb5_krcc_ops;
+#endif
#ifdef _WIN32
extern const krb5_cc_ops krb5_lcc_ops;
static struct krb5_cc_typelist cc_lcc_entry = { &krb5_lcc_ops, NULL };
static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_lcc_entry };
#else
+
+#ifdef USE_CCAPI_V3
+extern const krb5_cc_ops krb5_cc_stdcc_ops;
+static struct krb5_cc_typelist cc_stdcc_entry = { &krb5_cc_stdcc_ops, NULL };
+static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, &cc_stdcc_entry };
+#else
+
static struct krb5_cc_typelist cc_mcc_entry = { &krb5_mcc_ops, NULL };
+#endif /* USE_CCAPI_V3 */
+
+#ifdef USE_KEYRING_CCACHE
+static struct krb5_cc_typelist cc_file_entry = { &krb5_cc_file_ops,
+ &cc_mcc_entry };
+static struct krb5_cc_typelist cc_krcc_entry = { &krb5_krcc_ops,
+ &cc_file_entry };
+#endif /* USE_KEYRING_CCACHE */
#endif
static struct krb5_cc_typelist cc_fcc_entry = { &krb5_cc_file_ops,
&cc_mcc_entry };
-
-static struct krb5_cc_typelist *cc_typehead = &cc_fcc_entry;
+#ifdef USE_KEYRING_CCACHE
+#define INITIAL_TYPEHEAD (&cc_krcc_entry)
+#else
+#define INITIAL_TYPEHEAD (&cc_fcc_entry)
+#endif
+static struct krb5_cc_typelist *cc_typehead = INITIAL_TYPEHEAD;
static k5_mutex_t cc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER;
+static krb5_error_code
+krb5int_cc_getops(krb5_context, const char *, const krb5_cc_ops **);
+
int
krb5int_cc_initialize(void)
{
@@ -75,6 +104,11 @@ krb5int_cc_initialize(void)
err = k5_mutex_finish_init(&krb5int_cc_file_mutex);
if (err)
return err;
+#ifdef USE_KEYRING_CCACHE
+ err = k5_mutex_finish_init(&krb5int_krcc_mutex);
+ if (err)
+ return err;
+#endif
return 0;
}
@@ -85,7 +119,10 @@ krb5int_cc_finalize(void)
k5_mutex_destroy(&cc_typelist_lock);
k5_mutex_destroy(&krb5int_cc_file_mutex);
k5_mutex_destroy(&krb5int_mcc_mutex);
- for (t = cc_typehead; t != &cc_fcc_entry; t = t_next) {
+#ifdef USE_KEYRING_CCACHE
+ k5_mutex_destroy(&krb5int_krcc_mutex);
+#endif
+ for (t = cc_typehead; t != INITIAL_TYPEHEAD; t = t_next) {
t_next = t->next;
free(t);
}
@@ -143,16 +180,17 @@ krb5_cc_register(krb5_context context, krb5_cc_ops *ops, krb5_boolean override)
krb5_error_code KRB5_CALLCONV
krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache)
{
- struct krb5_cc_typelist *tlist;
char *pfx, *cp;
const char *resid;
unsigned int pfxlen;
krb5_error_code err;
+ const krb5_cc_ops *ops;
/* Solaris Kerberos */
if (!name)
return KRB5_CC_BADNAME;
+ pfx = NULL;
cp = strchr (name, ':');
if (!cp) {
if (krb5_cc_dfl_ops)
@@ -163,9 +201,9 @@ krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache)
pfxlen = cp - name;
- if ( pfxlen == 1 && isalpha(name[0]) ) {
- /* We found a drive letter not a prefix - use FILE: */
- pfx = strdup("FILE:");
+ if ( pfxlen == 1 && isalpha((unsigned char) name[0]) ) {
+ /* We found a drive letter not a prefix - use FILE */
+ pfx = strdup("FILE");
if (!pfx)
return ENOMEM;
@@ -183,24 +221,136 @@ krb5_cc_resolve (krb5_context context, const char *name, krb5_ccache *cache)
*cache = (krb5_ccache) 0;
- err = k5_mutex_lock(&cc_typelist_lock);
- if (err) {
+ err = krb5int_cc_getops(context, pfx, &ops);
+ if (pfx != NULL)
free(pfx);
+ if (err)
return err;
- }
+
+ return ops->resolve(context, cache, resid);
+}
+
+/*
+ * cc_getops
+ *
+ * Internal function to return the ops vector for a given ccache
+ * prefix string.
+ */
+static krb5_error_code
+krb5int_cc_getops(
+ krb5_context context,
+ const char *pfx,
+ const krb5_cc_ops **ops)
+{
+ krb5_error_code err;
+ struct krb5_cc_typelist *tlist;
+
+ err = k5_mutex_lock(&cc_typelist_lock);
+ if (err)
+ return err;
+
for (tlist = cc_typehead; tlist; tlist = tlist->next) {
if (strcmp (tlist->ops->prefix, pfx) == 0) {
- krb5_error_code (KRB5_CALLCONV *ccresolver)() = tlist->ops->resolve;
+ *ops = tlist->ops;
k5_mutex_unlock(&cc_typelist_lock);
- free(pfx);
- return (*ccresolver)(context, cache, resid);
+ return 0;
}
}
k5_mutex_unlock(&cc_typelist_lock);
if (krb5_cc_dfl_ops && !strcmp (pfx, krb5_cc_dfl_ops->prefix)) {
- free (pfx);
- return (*krb5_cc_dfl_ops->resolve)(context, cache, resid);
+ *ops = krb5_cc_dfl_ops;
+ return 0;
}
- free(pfx);
return KRB5_CC_UNKNOWN_TYPE;
}
+
+/*
+ * cc_new_unique
+ *
+ * Generate a new unique ccache, given a ccache type and a hint
+ * string. Ignores the hint string for now.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_cc_new_unique(
+ krb5_context context,
+ const char *type,
+ const char *hint,
+ krb5_ccache *id)
+{
+ const krb5_cc_ops *ops;
+ krb5_error_code err;
+
+ *id = NULL;
+
+ err = krb5int_cc_getops(context, type, &ops);
+ if (err)
+ return err;
+
+ return ops->gen_new(context, id);
+}
+
+/*
+ * cc_typecursor
+ *
+ * Note: to avoid copying the typelist at cursor creation time, among
+ * other things, we assume that the only additions ever occur to the
+ * typelist.
+ */
+krb5_error_code
+krb5int_cc_typecursor_new(krb5_context context, krb5_cc_typecursor *t)
+{
+ krb5_error_code err = 0;
+ krb5_cc_typecursor n = NULL;
+
+ *t = NULL;
+ n = malloc(sizeof(*n));
+ if (n == NULL)
+ return ENOMEM;
+
+ err = k5_mutex_lock(&cc_typelist_lock);
+ if (err)
+ goto errout;
+ n->tptr = cc_typehead;
+ err = k5_mutex_unlock(&cc_typelist_lock);
+ if (err)
+ goto errout;
+
+ *t = n;
+errout:
+ if (err)
+ free(n);
+ return err;
+}
+
+krb5_error_code
+krb5int_cc_typecursor_next(
+ krb5_context context,
+ krb5_cc_typecursor t,
+ const krb5_cc_ops **ops)
+{
+ krb5_error_code err = 0;
+
+ *ops = NULL;
+ if (t->tptr == NULL)
+ return 0;
+
+ err = k5_mutex_lock(&cc_typelist_lock);
+ if (err)
+ goto errout;
+ *ops = t->tptr->ops;
+ t->tptr = t->tptr->next;
+ err = k5_mutex_unlock(&cc_typelist_lock);
+ if (err)
+ goto errout;
+
+errout:
+ return err;
+}
+
+krb5_error_code
+krb5int_cc_typecursor_free(krb5_context context, krb5_cc_typecursor *t)
+{
+ free(*t);
+ *t = NULL;
+ return 0;
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccdefault.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccdefault.c
index 2c232ded50..d36b104749 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccdefault.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccdefault.c
@@ -1,11 +1,4 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
* lib/krb5/ccache/ccdefault.c
*
* Copyright 1990 by the Massachusetts Institute of Technology.
@@ -15,7 +8,7 @@
* 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
@@ -29,24 +22,29 @@
* 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.
- *
+ *
*
* Find default credential cache
*/
-#include <k5-int.h>
+#include "k5-int.h"
-/*
- * Solaris Kerberos: the following is specific to the Macintosh
- */
-#if defined(USE_LOGIN_LIBRARY) && defined(macintosh)
-#include <KerberosLoginInternal.h>
+#if defined(USE_LOGIN_LIBRARY)
+#include "KerberosLoginPrivate.h"
+#elif defined(USE_LEASH)
+static void (*pLeash_AcquireInitialTicketsIfNeeded)(krb5_context,krb5_principal,char*,int) = NULL;
+static HANDLE hLeashDLL = INVALID_HANDLE_VALUE;
+#ifdef _WIN64
+#define LEASH_DLL "leashw64.dll"
+#else
+#define LEASH_DLL "leashw32.dll"
#endif
+#endif
+
krb5_error_code KRB5_CALLCONV
krb5_cc_default(krb5_context context, krb5_ccache *ccache)
{
- krb5_error_code retval;
krb5_os_context os_ctx;
if (!context || context->magic != KV5M_CONTEXT)
@@ -59,27 +57,58 @@ krb5_cc_default(krb5_context context, krb5_ccache *ccache)
/* This is the internal function which opens the default ccache. On platforms supporting
the login library's automatic popup dialog to get tickets, this function also updated the
- library's internal view of the current principal associated with this cache.
-
+ library's internal view of the current principal associated with this cache.
+
All krb5 and GSS functions which need to open a cache to get a tgt to obtain service tickets
should call this function, not krb5_cc_default() */
krb5_error_code KRB5_CALLCONV
krb5int_cc_default(krb5_context context, krb5_ccache *ccache)
{
+ if (!context || context->magic != KV5M_CONTEXT) {
+ return KV5M_CONTEXT;
+ }
- if (!context || context->magic != KV5M_CONTEXT) {
- return KV5M_CONTEXT;
- }
-
-/*
- * Solaris Kerberos: the following is specific to the Macintosh
- */
#ifdef USE_LOGIN_LIBRARY
-
- /* MIT14resync; not needed for Solaris Kerberos */
+ {
+ /* make sure the default cache has tix before you open it */
+ KLStatus err = klNoErr;
+ char *outCacheName = NULL;
+
+ /* Try to make sure a krb5 tgt is in the cache */
+ err = __KLInternalAcquireInitialTicketsForCache (krb5_cc_default_name (context), kerberosVersion_V5,
+ NULL, NULL, &outCacheName);
+ if (err == klNoErr) {
+ /* This function tries to get tickets and put them in the specified
+ cache, however, if the cache does not exist, it may choose to put
+ them elsewhere (ie: the system default) so we set that here */
+ if (strcmp (krb5_cc_default_name (context), outCacheName) != 0) {
+ krb5_cc_set_default_name (context, outCacheName);
+ }
+ KLDisposeString (outCacheName);
+ }
+ }
+#else
+#ifdef USE_LEASH
+ if ( hLeashDLL == INVALID_HANDLE_VALUE ) {
+ hLeashDLL = LoadLibrary(LEASH_DLL);
+ if ( hLeashDLL != INVALID_HANDLE_VALUE ) {
+ (FARPROC) pLeash_AcquireInitialTicketsIfNeeded =
+ GetProcAddress(hLeashDLL, "not_an_API_Leash_AcquireInitialTicketsIfNeeded");
+ }
+ }
+
+ if ( pLeash_AcquireInitialTicketsIfNeeded ) {
+ char ccname[256]="";
+ pLeash_AcquireInitialTicketsIfNeeded(context, NULL, ccname, sizeof(ccname));
+ if (ccname[0]) {
+ if (strcmp (krb5_cc_default_name (context),ccname) != 0) {
+ krb5_cc_set_default_name (context, ccname);
+ }
+ }
+ }
+#endif
#endif
-
return krb5_cc_default (context, ccache);
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccdefops.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccdefops.c
index b4dc34569f..cdeab0674c 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccdefops.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccdefops.c
@@ -1,11 +1,4 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
* lib/krb5/ccache/ccdefops.c
*
* Copyright 1990 by the Massachusetts Institute of Technology.
@@ -15,7 +8,7 @@
* 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
@@ -29,20 +22,20 @@
* 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.
- *
+ *
*
* Default credentials cache determination. This is a separate file
* so that the user can more easily override it.
*/
-#include <k5-int.h>
+#include "k5-int.h"
#if defined(USE_CCAPI)
/*
* Macs use the shared, memory based credentials cache
* Windows may also use the ccapi cache, but only if the Krbcc32.dll
- * can be found; otherwise it falls back to using the old
+ * can be found; otherwise it falls back to using the old
* file-based ccache.
*/
#include "stdcc.h" /* from ccapi subdir */
@@ -51,7 +44,7 @@ const krb5_cc_ops *krb5_cc_dfl_ops = &krb5_cc_stdcc_ops;
#else
-#include "fcc.h" /* From file subdir */
+#include "fcc.h"
const krb5_cc_ops *krb5_cc_dfl_ops = &krb5_cc_file_ops;
#endif
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccfns.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccfns.c
index a40db67868..15bc87df6b 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccfns.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/ccache/ccfns.c
@@ -1,9 +1,7 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/krb5/ccache/ccfns.c
*
- * Copyright 2000 by the Massachusetts Institute of Technology.
+ * Copyright 2000, 2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -67,7 +65,29 @@ krb5_error_code KRB5_CALLCONV
krb5_cc_store_cred (krb5_context context, krb5_ccache cache,
krb5_creds *creds)
{
- return cache->ops->store(context, cache, creds);
+ krb5_error_code ret;
+ krb5_ticket *tkt;
+ krb5_principal s1, s2;
+
+ ret = cache->ops->store(context, cache, creds);
+ if (ret) return ret;
+
+ /*
+ * If creds->server and the server in the decoded ticket differ,
+ * store both principals.
+ */
+ s1 = creds->server;
+ ret = decode_krb5_ticket(&creds->ticket, &tkt);
+ /* Bail out on errors in case someone is storing a non-ticket. */
+ if (ret) return 0;
+ s2 = tkt->server;
+ if (!krb5_principal_compare(context, s1, s2)) {
+ creds->server = s2;
+ ret = cache->ops->store(context, cache, creds);
+ creds->server = s1;
+ }
+ krb5_free_ticket(context, tkt);
+ return ret;
}
krb5_error_code KRB5_CALLCONV
@@ -75,7 +95,23 @@ krb5_cc_retrieve_cred (krb5_context context, krb5_ccache cache,
krb5_flags flags, krb5_creds *mcreds,
krb5_creds *creds)
{
- return cache->ops->retrieve(context, cache, flags, mcreds, creds);
+ krb5_error_code ret;
+ krb5_data tmprealm;
+
+ ret = cache->ops->retrieve(context, cache, flags, mcreds, creds);
+ if (ret != KRB5_CC_NOTFOUND)
+ return ret;
+ if (!krb5_is_referral_realm(&mcreds->server->realm))
+ return ret;
+
+ /*
+ * Retry using client's realm if service has referral realm.
+ */
+ tmprealm = mcreds->server->realm;
+ mcreds->server->realm = mcreds->client->realm;
+ ret = cache->ops->retrieve(context, cache, flags, mcreds, creds);
+ mcreds->server->realm = tmprealm;
+ return ret;
}
krb5_error_code KRB5_CALLCONV
@@ -119,6 +155,12 @@ krb5_cc_set_flags (krb5_context context, krb5_ccache cache, krb5_flags flags)
return cache->ops->set_flags(context, cache, flags);
}
+krb5_error_code KRB5_CALLCONV
+krb5_cc_get_flags (krb5_context context, krb5_ccache cache, krb5_flags *flags)
+{
+ return cache->ops->get_flags(context, cache, flags);
+}
+
const char * KRB5_CALLCONV
krb5_cc_get_type (krb5_context context, krb5_ccache cache)
{
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_file.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_file.c
index dfbca86739..5677cd4496 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_file.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_file.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/keytab/kt_file.c
@@ -32,7 +31,6 @@
*
*/
-#define NEED_SOCKETS
#include "k5-int.h"
#include <stdio.h>
@@ -201,6 +199,7 @@ krb5_ktfile_resolve(krb5_context context, const char *name, krb5_keytab *id)
err = k5_mutex_init(&data->lock);
if (err) {
+ krb5_xfree(data);
krb5_xfree(*id);
return err;
}
@@ -415,6 +414,7 @@ krb5_ktfile_get_name(krb5_context context, krb5_keytab id, char *name, unsigned
name++;
len -= strlen(id->ops->prefix)+1;
+ /* Solaris Kerberos */
if (len < strlen(KTFILENAME(id))+1)
return(KRB5_KT_NAME_TOOLONG);
strcpy(name, KTFILENAME(id));
@@ -468,6 +468,10 @@ krb5_ktfile_get_next(krb5_context context, krb5_keytab id, krb5_keytab_entry *en
kerror = KTLOCK(id);
if (kerror)
return kerror;
+ if (KTFILEP(id) == NULL) {
+ KTUNLOCK(id);
+ return KRB5_KT_IOERR;
+ }
if (fseek(KTFILEP(id), *fileoff, 0) == -1) {
KTUNLOCK(id);
return KRB5_KT_END;
@@ -566,7 +570,8 @@ krb5_ktf_keytab_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
ktdata->name : ktfile_def_name);
kret = 0;
- *sizep += required;
+ if (!kret)
+ *sizep += required;
}
return(kret);
}
@@ -584,7 +589,7 @@ krb5_ktf_keytab_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet
size_t remain;
krb5_ktfile_data *ktdata;
krb5_int32 file_is_open;
- krb5_int32 file_pos[2];
+ krb5_int64 file_pos;
char *ktname;
size_t namelen;
const char *fnamep;
@@ -602,8 +607,7 @@ krb5_ktf_keytab_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet
ktdata = (krb5_ktfile_data *) keytab->data;
file_is_open = 0;
- file_pos[0] = 0;
- file_pos[1] = 0;
+ file_pos = 0;
/* Calculate the length of the name */
namelen = (keytab->ops && keytab->ops->prefix) ?
@@ -637,12 +641,7 @@ krb5_ktf_keytab_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet
file_is_open = 0;
#endif
fpos = ftell(ktdata->openf);
-#if SIZEOF_LONG == 4
- file_pos[0] = fpos;
-#else /* SIZEOF_LONG == 4 */
- file_pos[0] = fpos & 0xffffffff;
- file_pos[1] = (fpos >> 32) & 0xffffffff;
-#endif /* SIZEOF_LONG == 4 */
+ file_pos = fpos; /* XX range check? */
}
}
@@ -659,8 +658,7 @@ krb5_ktf_keytab_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet
(void) krb5_ser_pack_int32(file_is_open, &bp, &remain);
/* Put the file position */
- (void) krb5_ser_pack_int32(file_pos[0], &bp, &remain);
- (void) krb5_ser_pack_int32(file_pos[1], &bp, &remain);
+ (void) krb5_ser_pack_int64(file_pos, &bp, &remain);
/* Put the version */
(void) krb5_ser_pack_int32((krb5_int32) ((ktdata) ?
@@ -693,7 +691,7 @@ krb5_ktf_keytab_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octe
char *ktname;
krb5_ktfile_data *ktdata;
krb5_int32 file_is_open;
- krb5_int32 foffbuf[2];
+ krb5_int64 foff;
bp = *buffer;
remain = *lenremain;
@@ -731,10 +729,7 @@ krb5_ktf_keytab_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octe
if (remain >= (sizeof(krb5_int32)*5)) {
(void) krb5_ser_unpack_int32(&file_is_open,
&bp, &remain);
- (void) krb5_ser_unpack_int32(&foffbuf[0],
- &bp, &remain);
- (void) krb5_ser_unpack_int32(&foffbuf[1],
- &bp, &remain);
+ (void) krb5_ser_unpack_int64(&foff, &bp, &remain);
(void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
ktdata->version = (int) ibuf;
@@ -756,11 +751,7 @@ krb5_ktf_keytab_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octe
kret = krb5_ktfileint_openr(kcontext,
keytab);
if (!kret) {
-#if SIZEOF_LONG == 4
- fpos = foffbuf[0];
-#else /* SIZEOF_LONG == 4 */
- fpos = foffbuf[0] | ((long) foffbuf[1] << 32);
-#endif /* SIZEOF_LONG == 4 */
+ fpos = foff; /* XX range check? */
fseek(KTFILEP(keytab), fpos, SEEK_SET);
}
}
@@ -812,6 +803,7 @@ krb5_ktfile_wresolve(krb5_context context, const char *name, krb5_keytab *id)
err = k5_mutex_init(&data->lock);
if (err) {
+ krb5_xfree(data);
krb5_xfree(*id);
return err;
}
@@ -1061,9 +1053,11 @@ typedef krb5_int16 krb5_kt_vno;
#define xfread(a, b, c, d) fread((char *)a, b, (unsigned) c, d)
#ifdef ANSI_STDIO
+/* Solaris Kerberos */
static char *const fopen_mode_rbplus= "rb+F";
static char *const fopen_mode_rb = "rbF";
#else
+/* Solaris Kerberos */
static char *const fopen_mode_rbplus= "r+F";
static char *const fopen_mode_rb = "rF";
#endif
@@ -1113,7 +1107,10 @@ krb5_ktfileint_open(krb5_context context, krb5_keytab id, int mode)
} else {
/* gotta verify it instead... */
if (!xfread(&kt_vno, sizeof(kt_vno), 1, KTFILEP(id))) {
- kerror = errno;
+ if (feof(KTFILEP(id)))
+ kerror = KRB5_KEYTAB_BADVNO;
+ else
+ kerror = errno;
(void) krb5_unlock_file(context, fileno(KTFILEP(id)));
(void) fclose(KTFILEP(id));
return kerror;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_srvtab.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_srvtab.c
index 4738d80f80..7674ca345e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_srvtab.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/kt_srvtab.c
@@ -1,8 +1,7 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/keytab/srvtab/kts_resolv.c
@@ -30,7 +29,6 @@
* or implied warranty.
*/
-#define NEED_SOCKETS
#include "k5-int.h"
#include <stdio.h>
@@ -126,6 +124,7 @@ krb5_ktsrvtab_resolve(krb5_context context, const char *name, krb5_keytab *id)
FILE *fp;
/* Make sure we can open the srvtab file for reading. */
+ /* Solaris Kerberos */
fp = fopen(name, "rF");
if (!fp)
return(errno);
@@ -273,6 +272,7 @@ krb5_ktsrvtab_get_name(krb5_context context, krb5_keytab id, char *name, unsigne
name++;
len -= strlen(id->ops->prefix)+1;
+ /* Solaris Kerberos */
if (len < strlen(KTFILENAME(id))+1)
return(KRB5_KT_NAME_TOOLONG);
strcpy(name, KTFILENAME(id));
@@ -391,8 +391,10 @@ const struct _krb5_kt_ops krb5_kts_ops = {
#include <stdio.h>
#ifdef ANSI_STDIO
+/* Solaris Kerberos */
#define READ_MODE "rbF"
#else
+/* Solaris Kerberos */
#define READ_MODE "rF"
#endif
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktadd.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktadd.c
index ec808596c2..b7c1b92164 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktadd.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktadd.c
@@ -1,11 +1,4 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
* lib/krb5/keytab/ktadd.c
*
* Copyright 1990 by the Massachusetts Institute of Technology.
@@ -15,7 +8,7 @@
* 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
@@ -29,12 +22,12 @@
* 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.
- *
+ *
*
* krb5_kt_add_entry()
*/
-#include <k5-int.h>
+#include "k5-int.h"
krb5_error_code KRB5_CALLCONV
krb5_kt_add_entry (krb5_context context, krb5_keytab id, krb5_keytab_entry *entry)
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktbase.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktbase.c
index fec98c2e42..b6edb7092d 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktbase.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktbase.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/keytab/ktbase.c
@@ -34,9 +33,9 @@
* Registration functions for keytab.
*/
-#include <k5-int.h>
-#include <k5-thread.h>
-#include <kt-int.h>
+#include "k5-int.h"
+#include "k5-thread.h"
+#include "kt-int.h"
extern const krb5_kt_ops krb5_ktf_ops;
extern const krb5_kt_ops krb5_ktf_writable_ops;
@@ -46,14 +45,17 @@ struct krb5_kt_typelist {
const krb5_kt_ops *ops;
const struct krb5_kt_typelist *next;
};
+/* Solaris Kerberos */
static const struct krb5_kt_typelist krb5_kt_typelist_wrfile = {
&krb5_ktf_writable_ops,
0
};
-static const struct krb5_kt_typelist krb5_kt_typelist_file = {
+/* Solaris Kerberos */
+static const struct krb5_kt_typelist krb5_kt_typelist_file = {
&krb5_ktf_ops,
&krb5_kt_typelist_wrfile
};
+/* Solaris Kerberos */
static const struct krb5_kt_typelist krb5_kt_typelist_srvtab = {
&krb5_kts_ops,
&krb5_kt_typelist_file
@@ -72,6 +74,7 @@ krb5int_kt_finalize(void)
{
struct krb5_kt_typelist *t, *t_next;
k5_mutex_destroy(&kt_typehead_lock);
+ /* Solaris Kerberos */
for (t = (struct krb5_kt_typelist *)kt_typehead; t != &krb5_kt_typelist_srvtab;
t = t_next) {
t_next = (struct krb5_kt_typelist *)t->next;
@@ -139,9 +142,9 @@ krb5_kt_resolve (krb5_context context, const char *name, krb5_keytab *ktid)
pfxlen = cp - name;
- if ( pfxlen == 1 && isalpha(name[0]) ) {
- /* We found a drive letter not a prefix - use FILE: */
- pfx = strdup("FILE:");
+ if ( pfxlen == 1 && isalpha((unsigned char) name[0]) ) {
+ /* We found a drive letter not a prefix - use FILE */
+ pfx = strdup("FILE");
if (!pfx)
return ENOMEM;
@@ -177,7 +180,6 @@ krb5_kt_resolve (krb5_context context, const char *name, krb5_keytab *ktid)
return KRB5_KT_UNKNOWN_TYPE;
}
-
/*
* Routines to deal with externalizingt krb5_keytab.
* krb5_keytab_size();
@@ -209,6 +211,7 @@ krb5_keytab_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
krb5_ser_handle shandle;
kret = EINVAL;
+ /* Solaris Kerberos */
keytab = (krb5_keytab) arg;
shandle = (krb5_ser_handle) keytab->ops->serializer;
if ((keytab != NULL) && (keytab->ops) &&
@@ -225,6 +228,7 @@ krb5_keytab_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **bu
krb5_ser_handle shandle;
kret = EINVAL;
+ /* Solaris Kerberos */
keytab = (krb5_keytab) arg;
shandle = (krb5_ser_handle) keytab->ops->serializer;
if ((keytab != NULL) && (keytab->ops) &&
@@ -240,6 +244,7 @@ krb5_keytab_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **
krb5_ser_handle shandle;
kret = EINVAL;
+ /* Solaris Kerberos */
shandle = (krb5_ser_handle) krb5_kt_dfl_ops.serializer;
if ((shandle != NULL) && (shandle->internalizer))
kret = (*shandle->internalizer)(kcontext, argp, buffer, lenremain);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktdefault.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktdefault.c
index 57c6b28505..971f29f599 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktdefault.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktdefault.c
@@ -1,11 +1,4 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
* lib/krb5/keytab/ktdefault.c
*
* Copyright 1990 by the Massachusetts Institute of Technology.
@@ -29,12 +22,12 @@
* 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.
- *
+ *
*
* Get a default keytab.
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include <stdio.h>
krb5_error_code KRB5_CALLCONV
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktfns.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktfns.c
index 538b9b2dcf..63fa6399b6 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktfns.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktfns.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/krb5/keytab/ktfns.c
*
@@ -56,7 +54,24 @@ krb5_kt_get_entry(krb5_context context, krb5_keytab keytab,
krb5_const_principal principal, krb5_kvno vno,
krb5_enctype enctype, krb5_keytab_entry *entry)
{
- return krb5_x((keytab)->ops->get,(context, keytab, principal, vno, enctype, entry));
+ krb5_error_code err;
+ krb5_principal_data princ_data;
+
+ if (krb5_is_referral_realm(&principal->realm)) {
+ char *realm;
+ princ_data = *principal;
+ principal = &princ_data;
+ err = krb5_get_default_realm(context, &realm);
+ if (err)
+ return err;
+ princ_data.realm.data = realm;
+ princ_data.realm.length = strlen(realm);
+ }
+ err = krb5_x((keytab)->ops->get,(context, keytab, principal, vno, enctype,
+ entry));
+ if (principal == &princ_data)
+ krb5_free_default_realm(context, princ_data.realm.data);
+ return err;
}
krb5_error_code KRB5_CALLCONV
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktfr_entry.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktfr_entry.c
index e8dff34054..ab552a065c 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktfr_entry.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktfr_entry.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/keytab/ktfr_entry.c
@@ -29,25 +28,24 @@
* 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.
- *
+ *
*
* krb5_kt_free_entry()
*/
-#include <k5-int.h>
+#include "k5-int.h"
krb5_error_code KRB5_CALLCONV
krb5_free_keytab_entry_contents (krb5_context context, krb5_keytab_entry *entry)
-
-
{
if (!entry)
return 0;
-
+
krb5_free_principal(context, entry->principal);
if (entry->key.contents) {
memset((char *)entry->key.contents, 0, entry->key.length);
- krb5_free_keyblock_contents(context, &entry->key);
+ /* Solaris Kerberos */
+ krb5_free_keyblock_contents(context, &entry->key);
}
return 0;
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktremove.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktremove.c
index a37418fb18..d101a70651 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktremove.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/ktremove.c
@@ -1,11 +1,4 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
* lib/krb5/keytab/ktremove.c
*
* Copyright 1990 by the Massachusetts Institute of Technology.
@@ -15,7 +8,7 @@
* 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
@@ -29,12 +22,12 @@
* 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.
- *
+ *
*
* krb5_kt_remove_entry()
*/
-#include <k5-int.h>
+#include "k5-int.h"
krb5_error_code KRB5_CALLCONV
krb5_kt_remove_entry (krb5_context context, krb5_keytab id, krb5_keytab_entry *entry)
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/read_servi.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/read_servi.c
index 47f2a8e753..c49abf6c5e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/read_servi.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/keytab/read_servi.c
@@ -1,11 +1,4 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
* lib/krb5/keytab/read_servi.c
*
* Copyright 1990 by the Massachusetts Institute of Technology.
@@ -15,7 +8,7 @@
* 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
@@ -29,24 +22,24 @@
* 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.
+ *
*
- *
- * This routine is designed to be passed to krb5_rd_req.
+ * This routine is designed to be passed to krb5_rd_req.
* It is a convenience function that reads a key out of a keytab.
- * It handles all of the opening and closing of the keytab
- * internally.
+ * It handles all of the opening and closing of the keytab
+ * internally.
*/
-#include <k5-int.h>
+#include "k5-int.h"
#define KSUCCESS 0
/*
- * effects: If keyprocarg is not NULL, it is taken to be the name of a
- * keytab. Otherwise, the default keytab will be used. This
+ * effects: If keyprocarg is not NULL, it is taken to be the name of a
+ * keytab. Otherwise, the default keytab will be used. This
* routine opens the keytab and finds the principal associated with
- * principal, vno, and enctype and returns the resulting key in *key
- * or returning an error code if it is not found.
+ * principal, vno, and enctype and returns the resulting key in *key
+ * or returning an error code if it is not found.
* returns: Either KSUCCESS or error code.
* errors: error code if not found or keyprocarg is invalid.
*/
@@ -57,17 +50,17 @@ krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg, krb5_pri
char keytabname[MAX_KEYTAB_NAME_LEN + 1]; /* + 1 for NULL termination */
krb5_keytab id;
krb5_keytab_entry entry;
-
+
/*
- * Get the name of the file that we should use.
+ * Get the name of the file that we should use.
*/
if (!keyprocarg) {
- if ((kerror = krb5_kt_default_name(context, (char *)keytabname,
+ if ((kerror = krb5_kt_default_name(context, (char *)keytabname,
sizeof(keytabname) - 1))!= KSUCCESS)
return (kerror);
} else {
memset(keytabname, 0, sizeof(keytabname));
- (void) strncpy(keytabname, (char *)keyprocarg,
+ (void) strncpy(keytabname, (char *)keyprocarg,
sizeof(keytabname) - 1);
}
@@ -75,6 +68,7 @@ krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg, krb5_pri
return (kerror);
kerror = krb5_kt_get_entry(context, id, principal, vno, enctype, &entry);
+ /* Solaris Kerberos */
(void) krb5_kt_close(context, id);
if (kerror)
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/addr_order.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/addr_order.c
index f70535d73b..de724acc9e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/addr_order.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/addr_order.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/addr_order.c
*
@@ -28,7 +27,7 @@
* krb5_address_order()
*/
-#include <k5-int.h>
+#include "k5-int.h"
#ifndef min
#define min(a,b) ((a) < (b) ? (a) : (b))
@@ -40,8 +39,7 @@
*/
/*ARGSUSED*/
int KRB5_CALLCONV
-krb5_address_order(krb5_context context, krb5_const krb5_address *addr1,
- krb5_const krb5_address *addr2)
+krb5_address_order(krb5_context context, const krb5_address *addr1, const krb5_address *addr2)
{
int dir;
register int i;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/addr_srch.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/addr_srch.c
index 820ce0781e..efab59f8fd 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/addr_srch.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/addr_srch.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/addr_srch.c
*
@@ -28,15 +27,14 @@
* krb5_address_search()
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*
* if addr is listed in addrlist, or addrlist is null, return TRUE.
* if not listed, return FALSE
*/
krb5_boolean
-krb5_address_search(krb5_context context, krb5_const krb5_address *addr,
- krb5_address *krb5_const *addrlist)
+krb5_address_search(krb5_context context, const krb5_address *addr, krb5_address *const *addrlist)
{
if (!addrlist)
return TRUE;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/appdefault.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/appdefault.c
index 5a24a4c77c..94788899b6 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/appdefault.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/appdefault.c
@@ -1,27 +1,21 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
* appdefault - routines designed to be called from applications to
* handle the [appdefaults] profile section
*/
+
#include <stdio.h>
#include <string.h>
-#include <k5-int.h>
+#include "k5-int.h"
/*xxx Duplicating this is annoying; try to work on a better way.*/
-static const char *conf_yes[] = {
+static const char *const conf_yes[] = {
"y", "yes", "true", "t", "1", "on",
0,
};
-static const char *conf_no[] = {
+static const char *const conf_no[] = {
"n", "no", "false", "nil", "0", "off",
0,
};
@@ -41,9 +35,7 @@ static int conf_boolean(char *s)
return 0;
}
-static krb5_error_code appdefault_get(krb5_context context,
- const char *appname, const krb5_data *realm,
- const char *option, char **ret_value)
+static krb5_error_code appdefault_get(krb5_context context, const char *appname, const krb5_data *realm, const char *option, char **ret_value)
{
profile_t profile;
const char *names[5];
@@ -144,10 +136,7 @@ goodbye:
}
void KRB5_CALLCONV
-krb5_appdefault_boolean(krb5_context context,
- const char *appname, const krb5_data *realm,
- const char *option, int default_value,
- int *ret_value)
+krb5_appdefault_boolean(krb5_context context, const char *appname, const krb5_data *realm, const char *option, int default_value, int *ret_value)
{
char *string = NULL;
krb5_error_code retval;
@@ -162,9 +151,7 @@ krb5_appdefault_boolean(krb5_context context,
}
void KRB5_CALLCONV
-krb5_appdefault_string(krb5_context context, const char *appname,
- const krb5_data *realm, const char *option,
- const char *default_value, char **ret_value)
+krb5_appdefault_string(krb5_context context, const char *appname, const krb5_data *realm, const char *option, const char *default_value, char **ret_value)
{
krb5_error_code retval;
char *string;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/auth_con.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/auth_con.c
index b4f6a8cb2a..b2fe350ef3 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/auth_con.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/auth_con.c
@@ -1,33 +1,28 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-#include <k5-int.h>
-#include <auth_con.h>
+#include "k5-int.h"
+#include "auth_con.h"
static krb5_boolean chk_heimdal_seqnum(krb5_ui_4, krb5_ui_4);
/*ARGSUSED*/
static krb5_error_code
-actx_copy_addr(krb5_context context, const krb5_address *inad,
- krb5_address **outad)
+actx_copy_addr(krb5_context context, const krb5_address *inad, krb5_address **outad)
{
krb5_address *tmpad;
- if (!(tmpad = (krb5_address *)MALLOC(sizeof(*tmpad))))
+ if (!(tmpad = (krb5_address *)malloc(sizeof(*tmpad))))
return ENOMEM;
-#ifdef HAVE_C_STRUCTURE_ASSIGNMENT
*tmpad = *inad;
-#else
- (void) memcpy(tmpad, inad, sizeof(krb5_address));
-#endif
- if (!(tmpad->contents = (krb5_octet *)MALLOC(inad->length))) {
+ if (!(tmpad->contents = (krb5_octet *)malloc(inad->length))) {
krb5_xfree(tmpad);
return ENOMEM;
}
+ /* Solaris Kerberos */
(void) memcpy((char *)tmpad->contents, (char *)inad->contents, inad->length);
*outad = tmpad;
return 0;
@@ -40,11 +35,12 @@ krb5_auth_con_init(krb5_context context, krb5_auth_context *auth_context)
(krb5_auth_context)MALLOC(sizeof(struct _krb5_auth_context));
if (!*auth_context)
return ENOMEM;
-
+
+ /* Solaris Kerberos */
(void) memset(*auth_context, 0, sizeof(struct _krb5_auth_context));
/* Default flags, do time not seq */
- (*auth_context)->auth_context_flags =
+ (*auth_context)->auth_context_flags =
KRB5_AUTH_CONTEXT_DO_TIME | KRB5_AUTH_CONN_INITIALIZED;
(*auth_context)->req_cksumtype = context->default_ap_req_sumtype;
@@ -58,37 +54,35 @@ krb5_auth_con_init(krb5_context context, krb5_auth_context *auth_context)
krb5_error_code KRB5_CALLCONV
krb5_auth_con_free(krb5_context context, krb5_auth_context auth_context)
{
- if (auth_context->local_addr)
+ if (auth_context->local_addr)
krb5_free_address(context, auth_context->local_addr);
- if (auth_context->remote_addr)
+ if (auth_context->remote_addr)
krb5_free_address(context, auth_context->remote_addr);
- if (auth_context->local_port)
+ if (auth_context->local_port)
krb5_free_address(context, auth_context->local_port);
- if (auth_context->remote_port)
+ if (auth_context->remote_port)
krb5_free_address(context, auth_context->remote_port);
- if (auth_context->authentp)
+ if (auth_context->authentp)
krb5_free_authenticator(context, auth_context->authentp);
- if (auth_context->keyblock)
+ if (auth_context->keyblock)
krb5_free_keyblock(context, auth_context->keyblock);
- if (auth_context->send_subkey)
+ if (auth_context->send_subkey)
krb5_free_keyblock(context, auth_context->send_subkey);
- if (auth_context->recv_subkey)
+ if (auth_context->recv_subkey)
krb5_free_keyblock(context, auth_context->recv_subkey);
+ /* Solaris Kerberos */
if (auth_context->rcache)
(void) krb5_rc_close(context, auth_context->rcache);
if (auth_context->permitted_etypes)
krb5_xfree(auth_context->permitted_etypes);
- FREE(auth_context, sizeof(krb5_auth_context));
+ free(auth_context);
return 0;
}
-krb5_error_code KRB5_CALLCONV
-krb5_auth_con_setaddrs(krb5_context context,
- krb5_auth_context auth_context,
- krb5_address *local_addr,
- krb5_address *remote_addr)
+krb5_error_code
+krb5_auth_con_setaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address *local_addr, krb5_address *remote_addr)
{
- krb5_error_code retval = 0;
+ krb5_error_code retval;
/* Free old addresses */
if (auth_context->local_addr)
@@ -96,6 +90,7 @@ krb5_auth_con_setaddrs(krb5_context context,
if (auth_context->remote_addr)
(void) krb5_free_address(context, auth_context->remote_addr);
+ retval = 0;
if (local_addr)
retval = actx_copy_addr(context,
local_addr,
@@ -113,11 +108,8 @@ krb5_auth_con_setaddrs(krb5_context context,
return retval;
}
-krb5_error_code
-krb5_auth_con_getaddrs(krb5_context context,
- krb5_auth_context auth_context,
- krb5_address **local_addr,
- krb5_address **remote_addr)
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_getaddrs(krb5_context context, krb5_auth_context auth_context, krb5_address **local_addr, krb5_address **remote_addr)
{
krb5_error_code retval;
@@ -135,12 +127,8 @@ krb5_auth_con_getaddrs(krb5_context context,
return retval;
}
-krb5_error_code
-krb5_auth_con_setports(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_address * local_port,
- krb5_address * remote_port)
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_setports(krb5_context context, krb5_auth_context auth_context, krb5_address *local_port, krb5_address *remote_port)
{
krb5_error_code retval;
@@ -177,10 +165,7 @@ krb5_auth_con_setports(
* with the session key sent by the client.
*/
krb5_error_code KRB5_CALLCONV
-krb5_auth_con_setuseruserkey(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_keyblock * keyblock)
+krb5_auth_con_setuseruserkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock *keyblock)
{
if (auth_context->keyblock)
krb5_free_keyblock(context, auth_context->keyblock);
@@ -188,10 +173,7 @@ krb5_auth_con_setuseruserkey(
}
krb5_error_code KRB5_CALLCONV
-krb5_auth_con_getkey(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_keyblock ** keyblock)
+krb5_auth_con_getkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
{
if (auth_context->keyblock)
return krb5_copy_keyblock(context, auth_context->keyblock, keyblock);
@@ -200,19 +182,13 @@ krb5_auth_con_getkey(
}
krb5_error_code KRB5_CALLCONV
-krb5_auth_con_getlocalsubkey(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_keyblock * * keyblock)
+krb5_auth_con_getlocalsubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
{
return krb5_auth_con_getsendsubkey(context, auth_context, keyblock);
}
krb5_error_code KRB5_CALLCONV
-krb5_auth_con_getremotesubkey(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_keyblock **keyblock)
+krb5_auth_con_getremotesubkey(krb5_context context, krb5_auth_context auth_context, krb5_keyblock **keyblock)
{
return krb5_auth_con_getrecvsubkey(context, auth_context, keyblock);
}
@@ -226,7 +202,7 @@ krb5_auth_con_setsendsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keybloc
if (keyblock !=NULL)
return krb5_copy_keyblock(ctx, keyblock, &ac->send_subkey);
else
- return 0;
+ return 0;
}
krb5_error_code KRB5_CALLCONV
@@ -238,7 +214,7 @@ krb5_auth_con_setrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keybloc
if (keyblock != NULL)
return krb5_copy_keyblock(ctx, keyblock, &ac->recv_subkey);
else
- return 0;
+ return 0;
}
krb5_error_code KRB5_CALLCONV
@@ -261,10 +237,7 @@ krb5_auth_con_getrecvsubkey(krb5_context ctx, krb5_auth_context ac, krb5_keybloc
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
-krb5_auth_con_set_req_cksumtype(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_cksumtype cksumtype)
+krb5_auth_con_set_req_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
{
auth_context->req_cksumtype = cksumtype;
return 0;
@@ -272,10 +245,7 @@ krb5_auth_con_set_req_cksumtype(
/*ARGSUSED*/
krb5_error_code
-krb5_auth_con_set_safe_cksumtype(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_cksumtype cksumtype)
+krb5_auth_con_set_safe_cksumtype(krb5_context context, krb5_auth_context auth_context, krb5_cksumtype cksumtype)
{
auth_context->safe_cksumtype = cksumtype;
return 0;
@@ -283,20 +253,14 @@ krb5_auth_con_set_safe_cksumtype(
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
-krb5_auth_con_getlocalseqnumber(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_int32 * seqnumber)
+krb5_auth_con_getlocalseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
{
*seqnumber = auth_context->local_seq_number;
return 0;
}
krb5_error_code KRB5_CALLCONV
-krb5_auth_con_getauthenticator(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_authenticator **authenticator)
+krb5_auth_con_getauthenticator(krb5_context context, krb5_auth_context auth_context, krb5_authenticator **authenticator)
{
return (krb5_copy_authenticator(context, auth_context->authentp,
authenticator));
@@ -304,19 +268,14 @@ krb5_auth_con_getauthenticator(
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
-krb5_auth_con_getremoteseqnumber(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_int32 * seqnumber)
+krb5_auth_con_getremoteseqnumber(krb5_context context, krb5_auth_context auth_context, krb5_int32 *seqnumber)
{
*seqnumber = auth_context->remote_seq_number;
return 0;
}
-krb5_error_code
-krb5_auth_con_initivector(
- krb5_context context,
- krb5_auth_context auth_context)
+krb5_error_code KRB5_CALLCONV
+krb5_auth_con_initivector(krb5_context context, krb5_auth_context auth_context)
{
krb5_error_code ret;
@@ -326,7 +285,7 @@ krb5_auth_con_initivector(
if ((ret = krb5_c_block_size(context, auth_context->keyblock->enctype,
&blocksize)))
return(ret);
- if ((auth_context->i_vector = (krb5_pointer)MALLOC(blocksize))) {
+ if ((auth_context->i_vector = (krb5_pointer)malloc(blocksize))) {
memset(auth_context->i_vector, 0, blocksize);
return 0;
}
@@ -337,10 +296,7 @@ krb5_auth_con_initivector(
/*ARGSUSED*/
krb5_error_code
-krb5_auth_con_setivector(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_pointer ivector)
+krb5_auth_con_setivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer ivector)
{
auth_context->i_vector = ivector;
return 0;
@@ -348,10 +304,7 @@ krb5_auth_con_setivector(
/*ARGSUSED*/
krb5_error_code
-krb5_auth_con_getivector(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_pointer * ivector)
+krb5_auth_con_getivector(krb5_context context, krb5_auth_context auth_context, krb5_pointer *ivector)
{
*ivector = auth_context->i_vector;
return 0;
@@ -359,10 +312,7 @@ krb5_auth_con_getivector(
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
-krb5_auth_con_setflags(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_int32 flags)
+krb5_auth_con_setflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 flags)
{
auth_context->auth_context_flags = flags;
return 0;
@@ -370,10 +320,7 @@ krb5_auth_con_setflags(
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
-krb5_auth_con_getflags(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_int32 * flags)
+krb5_auth_con_getflags(krb5_context context, krb5_auth_context auth_context, krb5_int32 *flags)
{
*flags = auth_context->auth_context_flags;
return 0;
@@ -381,32 +328,23 @@ krb5_auth_con_getflags(
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
-krb5_auth_con_setrcache(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_rcache rcache)
+krb5_auth_con_setrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache rcache)
{
auth_context->rcache = rcache;
return 0;
}
-
+
/*ARGSUSED*/
krb5_error_code
-krb5_auth_con_getrcache(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_rcache * rcache)
+krb5_auth_con_getrcache(krb5_context context, krb5_auth_context auth_context, krb5_rcache *rcache)
{
*rcache = auth_context->rcache;
return 0;
}
-
+
/*ARGSUSED*/
krb5_error_code
-krb5_auth_con_setpermetypes(
- krb5_context context,
- krb5_auth_context auth_context,
- const krb5_enctype * permetypes)
+krb5_auth_con_setpermetypes(krb5_context context, krb5_auth_context auth_context, const krb5_enctype *permetypes)
{
krb5_enctype * newpe;
int i;
@@ -415,7 +353,7 @@ krb5_auth_con_setpermetypes(
;
i++; /* include the zero */
- if ((newpe = (krb5_enctype *) MALLOC(i*sizeof(krb5_enctype)))
+ if ((newpe = (krb5_enctype *) malloc(i*sizeof(krb5_enctype)))
== NULL)
return(ENOMEM);
@@ -424,6 +362,7 @@ krb5_auth_con_setpermetypes(
auth_context->permitted_etypes = newpe;
+ /* Solaris Kerberos */
(void) memcpy(newpe, permetypes, i*sizeof(krb5_enctype));
return 0;
@@ -431,10 +370,7 @@ krb5_auth_con_setpermetypes(
/*ARGSUSED*/
krb5_error_code
-krb5_auth_con_getpermetypes(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_enctype ** permetypes)
+krb5_auth_con_getpermetypes(krb5_context context, krb5_auth_context auth_context, krb5_enctype **permetypes)
{
krb5_enctype * newpe;
int i;
@@ -448,7 +384,7 @@ krb5_auth_con_getpermetypes(
;
i++; /* include the zero */
- if ((newpe = (krb5_enctype *) MALLOC(i*sizeof(krb5_enctype)))
+ if ((newpe = (krb5_enctype *) malloc(i*sizeof(krb5_enctype)))
== NULL)
return(ENOMEM);
@@ -461,47 +397,26 @@ krb5_auth_con_getpermetypes(
krb5_error_code KRB5_CALLCONV
krb5_auth_con_set_checksum_func( krb5_context context,
- krb5_auth_context auth_context,
- krb5_mk_req_checksum_func func,
- void *data)
+ krb5_auth_context auth_context,
+ krb5_mk_req_checksum_func func,
+ void *data)
{
auth_context->checksum_func = func;
auth_context->checksum_func_data = data;
return 0;
}
-static krb5_boolean
-chk_heimdal_seqnum(krb5_ui_4 exp_seq, krb5_ui_4 in_seq)
-{
- if (( exp_seq & 0xFF800000) == 0x00800000
- && (in_seq & 0xFF800000) == 0xFF800000
- && (in_seq & 0x00FFFFFF) == exp_seq)
- return 1;
- else if (( exp_seq & 0xFFFF8000) == 0x00008000
- && (in_seq & 0xFFFF8000) == 0xFFFF8000
- && (in_seq & 0x0000FFFF) == exp_seq)
- return 1;
- else if (( exp_seq & 0xFFFFFF80) == 0x00000080
- && (in_seq & 0xFFFFFF80) == 0xFFFFFF80
- && (in_seq & 0x000000FF) == exp_seq)
- return 1;
- else
- return 0;
-}
-
-
krb5_error_code KRB5_CALLCONV
krb5_auth_con_get_checksum_func( krb5_context context,
- krb5_auth_context auth_context,
- krb5_mk_req_checksum_func *func,
- void **data)
+ krb5_auth_context auth_context,
+ krb5_mk_req_checksum_func *func,
+ void **data)
{
*func = auth_context->checksum_func;
*data = auth_context->checksum_func_data;
return 0;
}
-
/*
* krb5int_auth_con_chkseqnum
*
@@ -517,7 +432,7 @@ krb5_auth_con_get_checksum_func( krb5_context context,
* X.690 BER (and consequently DER, which are the required encoding
* rules in RFC1510) encode all integer types as signed integers.
* This means that the MSB being set on the first octet of the
- * contents of the encoding indicates a negative value. Heimdal does
+ * contents of the encoding indicates a negative value. Heimdal does
* not prepend the required zero octet to unsigned integer encodings
* which would otherwise have the MSB of the first octet of their
* encodings set.
@@ -544,10 +459,10 @@ krb5_auth_con_get_checksum_func( krb5_context context,
* only set after we can unambiguously determine the sanity of the
* sending implementation. Once one of these flags is set, we accept
* only the sequence numbers appropriate to the remote implementation
- * type. We can make the determination in two different ways. The
+ * type. We can make the determination in two different ways. The
* first is to note the receipt of a "negative" sequence number when a
- * "positive" one was expected. The second is to note the receipt of
- * a sequence number that wraps through "zero" in a weird way. The
+ * "positive" one was expected. The second is to note the receipt of
+ * a sequence number that wraps through "zero" in a weird way. The
* latter corresponds to the receipt of an initial sequence number in
* the ambiguous range.
*
@@ -559,7 +474,7 @@ krb5_auth_con_get_checksum_func( krb5_context context,
*
* We have to do special treatment when receiving sequence numbers
* between 0xFF800000..0xFFFFFFFF, or when wrapping through zero
- * weirdly (due to ambiguous initial sequence number). If we are
+ * weirdly (due to ambiguous initial sequence number). If we are
* expecting a value corresponding to an ambiguous Heimdal counter
* value, and we receive an exact match, we can mark the remote end as
* sane.
@@ -579,36 +494,37 @@ krb5int_auth_con_chkseqnum(
*/
if (ac->auth_context_flags & KRB5_AUTH_CONN_SANE_SEQ)
return in_seq == exp_seq;
+
/*
* If sender is not known to be sane, first check the ambiguous
* range of received values, 0xFF800000..0xFFFFFFFF.
*/
if ((in_seq & 0xFF800000) == 0xFF800000) {
/*
- * If expected sequence number is in the range
+ * If expected sequence number is in the range
* 0xFF800000..0xFFFFFFFF, then we can't make any
* determinations about the sanity of the sending
* implementation.
*/
if ((exp_seq & 0xFF800000) == 0xFF800000 && in_seq == exp_seq)
- return 1;
+ return 1;
/*
- * If sender is not known for certain to be a broken Heimdal
+ * If sender is not known for certain to be a broken Heimdal
* implementation, check for exact match.
*/
if (!(ac->auth_context_flags & KRB5_AUTH_CONN_HEIMDAL_SEQ)
- && in_seq == exp_seq)
- return 1;
+ && in_seq == exp_seq)
+ return 1;
/*
- * Now apply hairy algorithm for matching sequence numbers
+ * Now apply hairy algorithm for matching sequence numbers
* sent by broken Heimdal implementations. If it matches, we
* know for certain it's a broken Heimdal sender.
*/
if (chk_heimdal_seqnum(exp_seq, in_seq)) {
- ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ;
- return 1;
+ ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ;
+ return 1;
}
- return 0;
+ return 0;
}
/*
@@ -617,10 +533,10 @@ krb5int_auth_con_chkseqnum(
* it matches the received value, sender is known to be sane.
*/
if (in_seq == exp_seq) {
- if (( exp_seq & 0xFFFFFF80) == 0x00000080
- || (exp_seq & 0xFFFF8000) == 0x00008000
- || (exp_seq & 0xFF800000) == 0x00800000)
- ac->auth_context_flags |= KRB5_AUTH_CONN_SANE_SEQ;
+ if (( exp_seq & 0xFFFFFF80) == 0x00000080
+ || (exp_seq & 0xFFFF8000) == 0x00008000
+ || (exp_seq & 0xFF800000) == 0x00800000)
+ ac->auth_context_flags |= KRB5_AUTH_CONN_SANE_SEQ;
return 1;
}
@@ -636,13 +552,31 @@ krb5int_auth_con_chkseqnum(
case 0x100:
case 0x10000:
case 0x1000000:
- ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ;
- exp_seq = in_seq;
- return 1;
+ ac->auth_context_flags |= KRB5_AUTH_CONN_HEIMDAL_SEQ;
+ exp_seq = in_seq;
+ return 1;
default:
- return 0;
+ return 0;
}
}
return 0;
}
+static krb5_boolean
+chk_heimdal_seqnum(krb5_ui_4 exp_seq, krb5_ui_4 in_seq)
+{
+ if (( exp_seq & 0xFF800000) == 0x00800000
+ && (in_seq & 0xFF800000) == 0xFF800000
+ && (in_seq & 0x00FFFFFF) == exp_seq)
+ return 1;
+ else if (( exp_seq & 0xFFFF8000) == 0x00008000
+ && (in_seq & 0xFFFF8000) == 0xFFFF8000
+ && (in_seq & 0x0000FFFF) == exp_seq)
+ return 1;
+ else if (( exp_seq & 0xFFFFFF80) == 0x00000080
+ && (in_seq & 0xFFFFFF80) == 0xFFFFFF80
+ && (in_seq & 0x000000FF) == exp_seq)
+ return 1;
+ else
+ return 0;
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/bld_pr_ext.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/bld_pr_ext.c
index ed7159a9cb..1b55a8c6d8 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/bld_pr_ext.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/bld_pr_ext.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/bld_pr_ext.c
*
@@ -28,14 +27,14 @@
* Build a principal from a list of lengths and strings
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include <stdarg.h>
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV_C
krb5_build_principal_ext(krb5_context context, krb5_principal * princ,
- unsigned int rlen, const char * realm, ...)
+ unsigned int rlen, const char * realm, ...)
{
va_list ap;
register int i, count = 0;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/bld_princ.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/bld_princ.c
index 62948a44e0..505bde065e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/bld_princ.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/bld_princ.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/bld_princ.c
*
@@ -29,12 +28,12 @@
*/
#include <stdarg.h>
-#include <k5-int.h>
+#include "k5-int.h"
/*ARGSUSED*/
krb5_error_code
-krb5_build_principal_va(krb5_context context, krb5_principal princ,
- unsigned int rlen, const char *realm, va_list ap)
+KRB5_CALLCONV
+krb5_build_principal_va(krb5_context context, krb5_principal princ, unsigned int rlen, const char *realm, va_list ap)
{
register int i, count = 0;
register char *next;
@@ -92,9 +91,9 @@ krb5_build_principal_va(krb5_context context, krb5_principal princ,
}
krb5_error_code KRB5_CALLCONV_C
-krb5_build_principal(krb5_context context, krb5_principal * princ,
- unsigned int rlen,
- const char * realm, ...)
+krb5_build_principal(krb5_context context, krb5_principal * princ,
+ unsigned int rlen,
+ const char * realm, ...)
{
va_list ap;
krb5_error_code retval;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/chk_trans.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/chk_trans.c
index 8e5dd23223..9fe73c878b 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/chk_trans.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/chk_trans.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/chk_trans.c
*
@@ -27,9 +26,22 @@
*
* krb5_check_transited_list()
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include <stdarg.h>
+#if defined (TEST) || defined (TEST2)
+# undef DEBUG
+# define DEBUG
+#endif
+
+#ifdef DEBUG
+#define verbose krb5int_chk_trans_verbose
+static int verbose = 0;
+# define Tprintf(ARGS) if (verbose) printf ARGS
+#else
+# define Tprintf(ARGS) (void)(0)
+#endif
+
#define MAXLEN 512
static krb5_error_code
@@ -38,9 +50,13 @@ process_intermediates (krb5_error_code (*fn)(krb5_data *, void *), void *data,
unsigned int len1, len2, i;
char *p1, *p2;
+ Tprintf (("process_intermediates(%.*s,%.*s)\n",
+ (int) n1->length, n1->data, (int) n2->length, n2->data));
+
len1 = n1->length;
len2 = n2->length;
+ Tprintf (("(walking intermediates now)\n"));
/* Simplify... */
if (len1 > len2) {
const krb5_data *p;
@@ -54,8 +70,11 @@ process_intermediates (krb5_error_code (*fn)(krb5_data *, void *), void *data,
/* Okay, now len1 is always shorter or equal. */
if (len1 == len2) {
if (memcmp (n1->data, n2->data, len1)) {
+ Tprintf (("equal length but different strings in path: '%.*s' '%.*s'\n",
+ (int) n1->length, n1->data, (int) n2->length, n2->data));
return KRB5KRB_AP_ERR_ILL_CR_TKT;
}
+ Tprintf (("(end intermediates)\n"));
return 0;
}
/* Now len1 is always shorter. */
@@ -67,9 +86,13 @@ process_intermediates (krb5_error_code (*fn)(krb5_data *, void *), void *data,
if (p1[0] == '/') {
/* X.500 style names, with common prefix. */
if (p2[0] != '/') {
+ Tprintf (("mixed name formats in path: x500='%.*s' domain='%.*s'\n",
+ (int) len1, p1, (int) len2, p2));
return KRB5KRB_AP_ERR_ILL_CR_TKT;
}
if (memcmp (p1, p2, len1)) {
+ Tprintf (("x500 names with different prefixes '%.*s' '%.*s'\n",
+ (int) len1, p1, (int) len2, p2));
return KRB5KRB_AP_ERR_ILL_CR_TKT;
}
for (i = len1 + 1; i < len2; i++)
@@ -86,12 +109,17 @@ process_intermediates (krb5_error_code (*fn)(krb5_data *, void *), void *data,
} else {
/* Domain style names, with common suffix. */
if (p2[0] == '/') {
+ Tprintf (("mixed name formats in path: domain='%.*s' x500='%.*s'\n",
+ (int) len1, p1, (int) len2, p2));
return KRB5KRB_AP_ERR_ILL_CR_TKT;
}
if (memcmp (p1, p2 + (len2 - len1), len1)) {
+ Tprintf (("domain names with different suffixes '%.*s' '%.*s'\n",
+ (int) len1, p1, (int) len2, p2));
return KRB5KRB_AP_ERR_ILL_CR_TKT;
}
for (i = len2 - len1 - 1; i > 0; i--) {
+ Tprintf (("looking at '%.*s'\n", (int) (len2 - i), p2+i));
if (p2[i-1] == '.') {
krb5_data d;
krb5_error_code r;
@@ -104,6 +132,7 @@ process_intermediates (krb5_error_code (*fn)(krb5_data *, void *), void *data,
}
}
}
+ Tprintf (("(end intermediates)\n"));
return 0;
}
@@ -114,6 +143,7 @@ maybe_join (krb5_data *last, krb5_data *buf, int bufsiz)
return 0;
if (buf->data[0] == '/') {
if (last->length + buf->length > bufsiz) {
+ Tprintf (("too big: last=%d cur=%d max=%d\n", last->length, buf->length, bufsiz));
return KRB5KRB_AP_ERR_ILL_CR_TKT;
}
memmove (buf->data+last->length, buf->data, buf->length);
@@ -124,6 +154,7 @@ maybe_join (krb5_data *last, krb5_data *buf, int bufsiz)
empty; the strcat will be a no-op. It should probably
be an error case, but let's be flexible. */
if (last->length+buf->length > bufsiz) {
+ Tprintf (("too big\n"));
return KRB5KRB_AP_ERR_ILL_CR_TKT;
}
memcpy (buf->data + buf->length, last->data, last->length);
@@ -164,7 +195,13 @@ foreach_realm (krb5_error_code (*fn)(krb5_data *comp,void *data), void *data,
last_component.data = last;
last_component.length = 0;
+#define print_data(fmt,d) Tprintf((fmt,(int)(d)->length,(d)->data))
+ print_data ("client realm: %.*s\n", crealm);
+ print_data ("server realm: %.*s\n", srealm);
+ print_data ("transit enc.: %.*s\n", transit);
+
if (transit->length == 0) {
+ Tprintf (("no other realms transited\n"));
return 0;
}
@@ -225,6 +262,8 @@ foreach_realm (krb5_error_code (*fn)(krb5_data *comp,void *data), void *data,
}
}
/* At end. Must be normal state. */
+ if (next_lit)
+ Tprintf (("ending in next-char-literal state\n"));
/* Process trailing element or comma. */
if (bufp == buf) {
/* Trailing comma. */
@@ -266,10 +305,12 @@ check_realm_in_list (krb5_data *realm, void *data)
struct check_data *cdata = data;
int i;
+ Tprintf ((".. checking '%.*s'\n", (int) realm->length, realm->data));
for (i = 0; cdata->tgs[i]; i++) {
if (same_data (krb5_princ_realm (cdata->ctx, cdata->tgs[i]), realm))
return 0;
}
+ Tprintf (("BAD!\n"));
return KRB5KRB_AP_ERR_ILL_CR_TKT;
}
@@ -281,30 +322,34 @@ krb5_check_transited_list (krb5_context ctx, const krb5_data *trans_in,
struct check_data cdata;
krb5_error_code r;
- /*
- * Work around buggy implementations that include NULL terminator in length.
- */
trans.length = trans_in->length;
trans.data = (char *) trans_in->data;
if (trans.length && (trans.data[trans.length-1] == '\0'))
trans.length--;
+ Tprintf (("krb5_check_transited_list(trans=\"%.*s\", crealm=\"%.*s\", srealm=\"%.*s\")\n",
+ (int) trans.length, trans.data,
+ (int) crealm->length, crealm->data,
+ (int) srealm->length, srealm->data));
if (trans.length == 0)
return 0;
-
r = krb5_walk_realm_tree (ctx, crealm, srealm, &cdata.tgs,
KRB5_REALM_BRANCH_CHAR);
if (r) {
+ Tprintf (("error %ld\n", (long) r));
return r;
}
#ifdef DEBUG /* avoid compiler warning about 'd' unused */
{
int i;
+ Tprintf (("tgs list = {\n"));
for (i = 0; cdata.tgs[i]; i++) {
char *name;
r = krb5_unparse_name (ctx, cdata.tgs[i], &name);
+ Tprintf (("\t'%s'\n", name));
free (name);
}
+ Tprintf (("}\n"));
}
#endif
cdata.ctx = ctx;
@@ -312,3 +357,85 @@ krb5_check_transited_list (krb5_context ctx, const krb5_data *trans_in,
krb5_free_realm_tree (ctx, cdata.tgs);
return r;
}
+
+#ifdef TEST
+
+static krb5_error_code
+print_a_realm (krb5_data *realm, void *data)
+{
+ printf ("%.*s\n", (int) realm->length, realm->data);
+ return 0;
+}
+
+int main (int argc, char *argv[]) {
+ const char *me;
+ krb5_data crealm, srealm, transit;
+ krb5_error_code r;
+ int expand_only = 0;
+
+ me = strrchr (argv[0], '/');
+ me = me ? me+1 : argv[0];
+
+ while (argc > 3 && argv[1][0] == '-') {
+ if (!strcmp ("-v", argv[1]))
+ verbose++, argc--, argv++;
+ else if (!strcmp ("-x", argv[1]))
+ expand_only++, argc--, argv++;
+ else
+ goto usage;
+ }
+
+ if (argc != 4) {
+ usage:
+ printf ("usage: %s [-v] [-x] clientRealm serverRealm transitEncoding\n",
+ me);
+ return 1;
+ }
+
+ crealm.data = argv[1];
+ crealm.length = strlen(argv[1]);
+ srealm.data = argv[2];
+ srealm.length = strlen(argv[2]);
+ transit.data = argv[3];
+ transit.length = strlen(argv[3]);
+
+ if (expand_only) {
+
+ printf ("client realm: %s\n", argv[1]);
+ printf ("server realm: %s\n", argv[2]);
+ printf ("transit enc.: %s\n", argv[3]);
+
+ if (argv[3][0] == 0) {
+ printf ("no other realms transited\n");
+ return 0;
+ }
+
+ r = foreach_realm (print_a_realm, NULL, &crealm, &srealm, &transit);
+ if (r)
+ printf ("--> returned error %ld\n", (long) r);
+ return r != 0;
+
+ } else {
+
+ /* Actually check the values against the supplied krb5.conf file. */
+ krb5_context ctx;
+ r = krb5_init_context (&ctx);
+ if (r) {
+ com_err (me, r, "initializing krb5 context");
+ return 1;
+ }
+ r = krb5_check_transited_list (ctx, &transit, &crealm, &srealm);
+ if (r == KRB5KRB_AP_ERR_ILL_CR_TKT) {
+ printf ("NO\n");
+ } else if (r == 0) {
+ printf ("YES\n");
+ } else {
+ printf ("kablooey!\n");
+ com_err (me, r, "checking transited-realm list");
+ return 1;
+ }
+ return 0;
+ }
+}
+
+#endif /* TEST */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/chpw.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/chpw.c
index f964132e87..f9a26bf38d 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/chpw.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/chpw.c
@@ -1,22 +1,21 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
** set password functions added by Paul W. Nelson, Thursby Software Systems, Inc.
*/
#include <string.h>
#include "k5-int.h"
-/* #include "krb5_err.h" gtb */
+/* Solaris Kerberos */
+/* #include "krb5_err.h" */
#include "auth_con.h"
krb5_error_code
-krb5int_mk_chpw_req(krb5_context context, krb5_auth_context auth_context, krb5_data *ap_req, char *passwd, krb5_data *packet)
+krb5int_mk_chpw_req(
+ krb5_context context,
+ krb5_auth_context auth_context,
+ krb5_data *ap_req,
+ char *passwd,
+ krb5_data *packet)
{
krb5_error_code ret = 0;
krb5_data clearpw;
@@ -40,15 +39,15 @@ krb5int_mk_chpw_req(krb5_context context, krb5_auth_context auth_context, krb5_d
packet->length = 6 + ap_req->length + cipherpw.length;
packet->data = (char *) malloc(packet->length);
if (packet->data == NULL)
- {
+ {
ret = ENOMEM;
goto cleanup;
- }
+ }
ptr = packet->data;
/* length */
- *ptr++ = (packet->length>>8) & 0xff;
+ *ptr++ = (packet->length>> 8) & 0xff;
*ptr++ = packet->length & 0xff;
/* version == 0x0001 big-endian */
@@ -87,7 +86,8 @@ krb5int_rd_chpw_rep(krb5_context context, krb5_auth_context auth_context, krb5_d
krb5_error_code ret;
krb5_data cipherresult;
krb5_data clearresult;
- krb5_error *krberror;
+ /* Solaris Kerberos */
+ krb5_error *krberror = NULL;
krb5_replay_data replay;
krb5_keyblock *tmp;
@@ -103,8 +103,35 @@ krb5int_rd_chpw_rep(krb5_context context, krb5_auth_context auth_context, krb5_d
plen = (*ptr++ & 0xff);
plen = (plen<<8) | (*ptr++ & 0xff);
- if (plen != packet->length)
- return(KRB5KRB_AP_ERR_MODIFIED);
+ if (plen != packet->length)
+ {
+ /*
+ * MS KDCs *may* send back a KRB_ERROR. Although
+ * not 100% correct via RFC3244, it's something
+ * we can workaround here.
+ */
+ if (krb5_is_krb_error(packet)) {
+
+ if ((ret = krb5_rd_error(context, packet, &krberror)))
+ return(ret);
+
+ if (krberror->e_data.data == NULL) {
+ ret = ERROR_TABLE_BASE_krb5 + (krb5_error_code) krberror->error;
+ krb5_free_error(context, krberror);
+ return (ret);
+ }
+ }
+ else
+ {
+ return(KRB5KRB_AP_ERR_MODIFIED);
+ }
+ }
+
+ /* Solaris Kerberos */
+ if (krberror != NULL) {
+ krb5_free_error(context, krberror);
+ krberror = NULL;
+ }
/* verify version number */
@@ -374,7 +401,7 @@ krb5int_rd_setpw_rep( krb5_context context, krb5_auth_context auth_context, krb5
/*
** set password version is 0xff80, change password version is 1
*/
- if (version_number != 0xff80 && version_number != 1)
+ if (version_number != 1 && version_number != 0xff80)
return(KRB5KDC_ERR_BAD_PVNO);
/*
** now fill in ap_rep with the reply -
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/conv_princ.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/conv_princ.c
index a6d60ea88e..9c0d9fe47a 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/conv_princ.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/conv_princ.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/conv_princ.c
@@ -15,7 +14,7 @@
* 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
@@ -29,10 +28,10 @@
* 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.
- *
+ *
* Build a principal from a V4 specification, or separate a V5
* principal into name, instance, and realm.
- *
+ *
* NOTE: This is highly site specific, and is only really necessary
* for sites who need to convert from V4 to V5. It is used by both
* the KDC and the kdb5_convert program. Since its use is highly
@@ -40,7 +39,7 @@
* hard-coded in this file.
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include <string.h>
#include <ctype.h>
@@ -52,10 +51,10 @@
#define INST_SZ 40
struct krb_convert {
- char *v4_str;
- char *v5_str;
- unsigned int flags : 8;
- unsigned int len : 8;
+ char *v4_str;
+ char *v5_str;
+ unsigned int flags : 8;
+ unsigned int len : 8;
};
#define DO_REALM_CONVERSION 0x00000001
@@ -126,7 +125,7 @@ static const struct krb_convert sconv_list[] = {
* char *strnchr(s, c, n)
* char *s;
* char c;
- * int n;
+ * unsigned int n;
*
* returns a pointer to the first occurrence of character c in the
* string s, or a NULL pointer if c does not occur in in the string;
@@ -135,12 +134,12 @@ static const struct krb_convert sconv_list[] = {
* This falls in the "should have been in the ANSI C library"
* category. :-)
*/
-static char *strnchr(register char *s, register char c,
- register unsigned int n)
+static char *strnchr(register char *s, register char c,
+ register unsigned int n)
{
- if (n < 1)
+ if (n < 1)
return 0;
-
+
while (n-- && *s) {
if (*s == c)
return s;
@@ -156,13 +155,13 @@ static char *strnchr(register char *s, register char c,
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
krb5_524_conv_principal(krb5_context context, krb5_const_principal princ,
- char *name, char *inst, char *realm)
+ char *name, char *inst, char *realm)
{
const struct krb_convert *p;
const krb5_data *compo;
char *c, *tmp_realm, *tmp_prealm;
unsigned int tmp_realm_len;
- int retval;
+ int retval;
*name = *inst = '\0';
switch (krb5_princ_size(context, princ)) {
@@ -225,7 +224,7 @@ krb5_524_conv_principal(krb5_context context, krb5_const_principal princ,
strncpy(tmp_prealm, compo->data, compo->length);
tmp_prealm[compo->length] = '\0';
- /* Ask for v4_realm corresponding to
+ /* Ask for v4_realm corresponding to
krb5 principal realm from krb5.conf realms stanza */
if (context->profile == 0)
@@ -234,7 +233,7 @@ krb5_524_conv_principal(krb5_context context, krb5_const_principal princ,
tmp_prealm, "v4_realm", 0,
&tmp_realm);
free(tmp_prealm);
- if (retval) {
+ if (retval) {
return retval;
} else {
if (tmp_realm == 0) {
@@ -256,25 +255,27 @@ krb5_524_conv_principal(krb5_context context, krb5_const_principal princ,
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
-krb5_425_conv_principal(krb5_context context, const char *name, const char *instance, const char *realm, krb5_principal *princ)
+krb5_425_conv_principal(krb5_context context, const char *name,
+ const char *instance, const char *realm,
+ krb5_principal *princ)
{
const struct krb_convert *p;
char buf[256]; /* V4 instances are limited to 40 characters */
krb5_error_code retval;
- char **full_name = 0;
char *domain, *cp;
- const char *names[5];
+ char **full_name = 0;
+ const char *names[5], *names2[2];
void* iterator = NULL;
char** v4realms = NULL;
char* realm_name = NULL;
char* dummy_value = NULL;
-
+
/* First, convert the realm, since the v4 realm is not necessarily the same as the v5 realm
- To do that, iterate over all the realms in the config file, looking for a matching
+ To do that, iterate over all the realms in the config file, looking for a matching
v4_realm line */
- names [0] = "realms";
- names [1] = NULL;
- retval = profile_iterator_create (context -> profile, names, PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, &iterator);
+ names2 [0] = "realms";
+ names2 [1] = NULL;
+ retval = profile_iterator_create (context -> profile, names2, PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, &iterator);
while (retval == 0) {
retval = profile_iterator (&iterator, &realm_name, &dummy_value);
if ((retval == 0) && (realm_name != NULL)) {
@@ -307,7 +308,7 @@ krb5_425_conv_principal(krb5_context context, const char *name, const char *inst
dummy_value = NULL;
}
}
-
+
if (instance) {
if (instance[0] == '\0') {
instance = 0;
@@ -315,7 +316,7 @@ krb5_425_conv_principal(krb5_context context, const char *name, const char *inst
}
p = sconv_list;
/*CONSTCOND*/
- while (TRUE) {
+ while (1) {
if (!p->v4_str)
goto not_service;
if (!strcmp(p->v4_str, name))
@@ -340,8 +341,8 @@ krb5_425_conv_principal(krb5_context context, const char *name, const char *inst
return retval;
if (domain) {
for (cp = domain; *cp; cp++)
- if (isupper((int) (*cp)))
- *cp = tolower((int) *cp);
+ if (isupper((unsigned char) (*cp)))
+ *cp = tolower((unsigned char) *cp);
strncat(buf, ".", sizeof(buf) - 1 - strlen(buf));
strncat(buf, domain, sizeof(buf) - 1 - strlen(buf));
krb5_xfree(domain);
@@ -350,8 +351,8 @@ krb5_425_conv_principal(krb5_context context, const char *name, const char *inst
}
}
}
-
-not_service:
+
+not_service:
retval = krb5_build_principal(context, princ, strlen(realm), realm, name,
instance, NULL);
if (iterator) profile_iterator_free (&iterator);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_addrs.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_addrs.c
index bc31ecab20..c8d38a2281 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_addrs.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_addrs.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/copy_addrs.c
*
@@ -28,7 +27,7 @@
* krb5_copy_addresses()
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
@@ -38,11 +37,7 @@ krb5_copy_addr(krb5_context context, const krb5_address *inad, krb5_address **ou
if (!(tmpad = (krb5_address *)malloc(sizeof(*tmpad))))
return ENOMEM;
-#ifdef HAVE_C_STRUCTURE_ASSIGNMENT
*tmpad = *inad;
-#else
- memcpy(tmpad, inad, sizeof(krb5_address));
-#endif
if (!(tmpad->contents = (krb5_octet *)malloc(inad->length))) {
krb5_xfree(tmpad);
return ENOMEM;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_creds.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_creds.c
index d277543362..9f1429c08e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_creds.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_creds.c
@@ -1,11 +1,4 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
* lib/krb5/krb/copy_creds.c
*
* Copyright 1990,1991 by the Massachusetts Institute of Technology.
@@ -34,7 +27,7 @@
* krb5_copy_cred()
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*
* Copy credentials, allocating fresh storage where needed.
@@ -50,11 +43,7 @@ krb5_copy_creds(krb5_context context, const krb5_creds *incred, krb5_creds **out
if (!(tempcred = (krb5_creds *)malloc(sizeof(*tempcred))))
return ENOMEM;
-#ifdef HAVE_C_STRUCTURE_ASSIGNMENT
- *tempcred = *incred; /* copy everything quickly */
-#else
- memcpy(tempcred, incred, sizeof(krb5_creds));
-#endif
+ *tempcred = *incred;
retval = krb5_copy_principal(context, incred->client, &tempcred->client);
if (retval)
goto cleanlast;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_data.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_data.c
index 183956a502..f7ac6388dd 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_data.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_data.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/copy_data.c
*
@@ -28,7 +27,7 @@
* krb5_copy_data()
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*
* Copy a data structure, with fresh allocation.
@@ -61,7 +60,7 @@ krb5_copy_data(krb5_context context, const krb5_data *indata, krb5_data **outdat
return 0;
}
-krb5_error_code
+krb5_error_code
krb5int_copy_data_contents(krb5_context context, const krb5_data *indata, krb5_data *outdata)
{
if (!indata) {
@@ -71,14 +70,12 @@ krb5int_copy_data_contents(krb5_context context, const krb5_data *indata, krb5_d
outdata->length = indata->length;
if (outdata->length) {
if (!(outdata->data = malloc(outdata->length))) {
- krb5_xfree(outdata);
- return ENOMEM;
+ return ENOMEM;
}
- memcpy((char *)outdata->data, (char *)indata->data, outdata->length);
+ memcpy((char *)outdata->data, (char *)indata->data, outdata->length);
} else
- outdata->data = 0;
+ outdata->data = 0;
outdata->magic = KV5M_DATA;
return 0;
}
-
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_tick.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_tick.c
index 1fbeefa24c..43268e50f2 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_tick.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/copy_tick.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/copy_tick.c
*
@@ -28,7 +27,7 @@
* krb5_copy_ticket()
*/
-#include <k5-int.h>
+#include "k5-int.h"
static krb5_error_code
krb5_copy_enc_tkt_part(krb5_context context, const krb5_enc_tkt_part *partfrom, krb5_enc_tkt_part **partto)
@@ -38,11 +37,7 @@ krb5_copy_enc_tkt_part(krb5_context context, const krb5_enc_tkt_part *partfrom,
if (!(tempto = (krb5_enc_tkt_part *)malloc(sizeof(*tempto))))
return ENOMEM;
-#ifdef HAVE_C_STRUCTURE_ASSIGNMENT
*tempto = *partfrom;
-#else
- memcpy(tempto, partfrom, sizeof(krb5_enc_tkt_part));
-#endif
retval = krb5_copy_keyblock(context, partfrom->session,
&tempto->session);
if (retval) {
@@ -105,11 +100,7 @@ krb5_copy_ticket(krb5_context context, const krb5_ticket *from, krb5_ticket **pt
if (!(tempto = (krb5_ticket *)malloc(sizeof(*tempto))))
return ENOMEM;
-#ifdef HAVE_C_STRUCTURE_ASSIGNMENT
*tempto = *from;
-#else
- memcpy(tempto, from, sizeof(krb5_ticket));
-#endif
retval = krb5_copy_principal(context, from->server, &tempto->server);
if (retval) {
krb5_xfree(tempto);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/cp_key_cnt.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/cp_key_cnt.c
index f26a490e5d..6a623aa447 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/cp_key_cnt.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/cp_key_cnt.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/cp_key_cnt.c
*
@@ -33,18 +32,16 @@
* krb5_copy_keyblock()
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*
* Copy a keyblock, including alloc'ed storage.
*/
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
-krb5_copy_keyblock_contents(
- krb5_context context,
- const krb5_keyblock *from,
- krb5_keyblock *to)
+krb5_copy_keyblock_contents(krb5_context context, const krb5_keyblock *from, krb5_keyblock *to)
{
+ /* Solaris Kerberos */
krb5_error_code ret = EINVAL;
if (to != NULL && from != NULL) {
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/decode_kdc.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/decode_kdc.c
index 8ce9e8d489..cdfc4ffbde 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/decode_kdc.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/decode_kdc.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/decode_kdc.c
*
@@ -28,7 +27,7 @@
* krb5_decode_kdc_rep() function.
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*
Takes a KDC_REP message and decrypts encrypted part using etype and
@@ -69,7 +68,7 @@ krb5_decode_kdc_rep(krb5_context context, krb5_data *enc_rep, const krb5_keybloc
return retval;
if ((retval = krb5_kdc_rep_decrypt_proc(context, key, &usage,
- local_dec_rep)))
+ local_dec_rep)))
krb5_free_kdc_rep(context, local_dec_rep);
else
*dec_rep = local_dec_rep;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/encode_kdc.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/encode_kdc.c
index d0df5605e4..8b879c0159 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/encode_kdc.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/encode_kdc.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/encode_kdc.c
*
@@ -28,7 +27,7 @@
* krb5_encode_kdc_rep() function.
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*
Takes KDC rep parts in *rep and *encpart, and formats it into *enc_rep,
@@ -55,7 +54,7 @@ krb5_encode_kdc_rep(krb5_context context, krb5_msgtype type,
krb5_enc_kdc_rep_part tmp_encpart;
krb5_keyusage usage;
- if (!valid_enctype(dec_rep->enc_part.enctype))
+ if (!krb5_c_valid_enctype(dec_rep->enc_part.enctype))
return KRB5_PROG_ETYPE_NOSUPP;
switch (type) {
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/free_rtree.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/free_rtree.c
index cc861b0652..7914d3f239 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/free_rtree.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/free_rtree.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/free_rtree.c
*
@@ -17,7 +16,10 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/fwd_tgt.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/fwd_tgt.c
index 7a3944aa13..69ba165e54 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/fwd_tgt.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/fwd_tgt.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/get_in_tkt.c
@@ -31,31 +30,32 @@
* or implied warranty.
*/
-#define NEED_SOCKETS
-#include <k5-int.h>
+#include "k5-int.h"
+#ifdef HAVE_MEMORY_H
#include <memory.h>
+#endif
/* helper function: convert flags to necessary KDC options */
#define flags2options(flags) (flags & KDC_TKT_COMMON_MASK)
/* Get a TGT for use at the remote host */
krb5_error_code KRB5_CALLCONV
-krb5_fwd_tgt_creds(
- krb5_context context,
- krb5_auth_context auth_context,
- char *rhost,
- krb5_principal client,
- krb5_principal server,
- krb5_ccache cc,
- int forwardable, /* Should forwarded TGT also be forwardable? */
- krb5_data *outbuf)
+krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, char *rhost, krb5_principal client, krb5_principal server, krb5_ccache cc, int forwardable, krb5_data *outbuf)
+
+
+
+
+
+
+ /* Should forwarded TGT also be forwardable? */
+
{
krb5_replay_data replaydata;
krb5_data * scratch = 0;
- krb5_address **addrs = 0;
+ krb5_address **addrs = NULL;
krb5_error_code retval;
krb5_creds creds, tgt;
- krb5_creds *pcreds = 0;
+ krb5_creds *pcreds;
krb5_flags kdcoptions;
int close_cc = 0;
int free_rhost = 0;
@@ -67,13 +67,13 @@ krb5_fwd_tgt_creds(
memset((char *)&tgt, 0, sizeof(creds));
if (cc == 0) {
- if ((retval = krb5int_cc_default(context, &cc)))
+ if ((retval = krb5int_cc_default(context, &cc)))
goto errout;
- close_cc = 1;
+ close_cc = 1;
}
retval = krb5_auth_con_getkey (context, auth_context, &session_key);
if (retval)
- goto errout;
+ goto errout;
if (session_key) {
enctype = session_key->enctype;
krb5_free_keyblock (context, session_key);
@@ -86,19 +86,19 @@ krb5_fwd_tgt_creds(
retval = krb5_copy_principal (context, server, &in.server);
if (retval)
- goto punt;
+ goto punt;
retval = krb5_copy_principal (context, client, &in.client);
if (retval)
- goto punt;
+ goto punt;
retval = krb5_get_credentials (context, 0, cc, &in, &out);
if (retval)
- goto punt;
- /* Got the credentials. Okay, now record the enctype and
+ goto punt;
+ /* Got the credentials. Okay, now record the enctype and
throw them away. */
enctype = out->keyblock.enctype;
krb5_free_creds (context, out);
punt:
- krb5_free_cred_contents (context, &in);
+ krb5_free_cred_contents (context, &in);
}
if ((retval = krb5_copy_principal(context, client, &creds.client)))
@@ -132,34 +132,35 @@ krb5_fwd_tgt_creds(
retval = KRB5_NO_TKT_SUPPLIED;
goto errout;
}
-
+
if (tgt.addresses && *tgt.addresses) {
- if (rhost == NULL) {
- if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) {
- retval = KRB5_FWD_BAD_PRINCIPAL;
- goto errout;
- }
-
- if (krb5_princ_size(context, server) < 2) {
- retval = KRB5_CC_BADNAME;
- goto errout;
- }
+ if (rhost == NULL) {
+ if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) {
+retval = KRB5_FWD_BAD_PRINCIPAL;
+ goto errout;
+ }
- rhost = malloc(server->data[1].length+1);
- if (!rhost) {
- retval = ENOMEM;
- goto errout;
- }
- free_rhost = 1;
- (void) memcpy(rhost, server->data[1].data, server->data[1].length);
- rhost[server->data[1].length] = '\0';
+ if (krb5_princ_size(context, server) < 2){
+ retval = KRB5_CC_BADNAME;
+ goto errout;
+ }
+
+ rhost = malloc(server->data[1].length+1);
+ if (!rhost) {
+ retval = ENOMEM;
+ goto errout;
}
+ free_rhost = 1;
+ /* Solaris Kerberos */
+ (void) memcpy(rhost, server->data[1].data, server->data[1].length);
+ rhost[server->data[1].length] = '\0';
+ }
retval = krb5_os_hostaddr(context, rhost, &addrs);
if (retval)
goto errout;
}
-
+
creds.keyblock.enctype = enctype;
creds.times = tgt.times;
creds.times.starttime = 0;
@@ -173,16 +174,17 @@ krb5_fwd_tgt_creds(
if (enctype) {
creds.keyblock.enctype = 0;
if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions,
- addrs, &creds, &pcreds)))
+ addrs, &creds, &pcreds)))
goto errout;
- } else goto errout;
+ }
+ else goto errout;
}
-
retval = krb5_mk_1cred(context, auth_context, pcreds,
&scratch, &replaydata);
krb5_free_creds(context, pcreds);
- /* Solaris Kerberos: changed this logic from the MIT 1.2.1 version to be
+ /*
+ * Solaris Kerberos: changed this logic from the MIT 1.2.1 version to be
* more robust.
*/
if (scratch) {
@@ -197,6 +199,7 @@ krb5_fwd_tgt_creds(
errout:
if (addrs)
krb5_free_addresses(context, addrs);
+ /* Solaris Kerberos */
if (close_cc)
(void) krb5_cc_close(context, cc);
if (free_rhost)
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gc_frm_kdc.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gc_frm_kdc.c
index 07f853cb0d..bcd96cdd0e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gc_frm_kdc.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gc_frm_kdc.c
@@ -1,12 +1,11 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
- * Copyright (c) 1994,2003,2005,2007 by the Massachusetts Institute of Technology.
+ * Copyright (c) 1994,2003,2005 by the Massachusetts Institute of Technology.
* Copyright (c) 1994 CyberSAFE Corporation
* Copyright (c) 1993 Open Computing Security Group
* Copyright (c) 1990,1991 by the Massachusetts Institute of Technology.
@@ -38,7 +37,7 @@
* along the way.
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include <stdio.h>
#include "int-proto.h"
@@ -408,7 +407,7 @@ static krb5_error_code
try_ccache(struct tr_state *ts, krb5_creds *tgtq)
{
krb5_error_code retval;
- krb5_timestamp saved_endtime;
+ krb5_timestamp saved_endtime;
TR_DBG(ts, "try_ccache");
/*
@@ -547,10 +546,10 @@ try_kdc(struct tr_state *ts, krb5_creds *tgtq)
ts->cur_tgt->addresses,
&ltgtq, &tmp_out_cred);
if (retval) {
- ts->ntgts--;
- ts->nxt_tgt = ts->cur_tgt;
- TR_DBG_RET(ts, "try_kdc", retval);
- return retval;
+ ts->ntgts--;
+ ts->nxt_tgt = ts->cur_tgt;
+ TR_DBG_RET(ts, "try_kdc", retval);
+ return retval;
}
/*
@@ -903,7 +902,7 @@ krb5_get_cred_from_kdc_opt(krb5_context context, krb5_ccache ccache,
server->realm.data[server->realm.length] = 0;
}
/*
- * Retrieve initial TGT to match the specified server, either for the
+ * Retreive initial TGT to match the specified server, either for the
* local realm in the default (referral) case or for the remote
* realm if we're starting someplace non-local.
*/
@@ -983,7 +982,6 @@ krb5_get_cred_from_kdc_opt(krb5_context context, krb5_ccache ccache,
/* Whether or not that succeeded, we're done. */
goto cleanup;
}
- else {
/* Referral request succeeded; let's see what it is. */
if (krb5_principal_compare(context, in_cred->server,
(*out_cred)->server)) {
@@ -991,6 +989,38 @@ krb5_get_cred_from_kdc_opt(krb5_context context, krb5_ccache ccache,
"for requested server principal\n"));
DUMP_PRINC("gc_from_kdc final referred reply",
in_cred->server);
+
+ /*
+ * Check if the return enctype is one that we requested if
+ * needed.
+ */
+ if (old_use_conf_ktypes || context->tgs_ktype_count == 0)
+ goto cleanup;
+ for (i = 0; i < context->tgs_ktype_count; i++) {
+ if ((*out_cred)->keyblock.enctype == context->tgs_ktypes[i]) {
+ /* Found an allowable etype, so we're done */
+ goto cleanup;
+ }
+ }
+ /*
+ * We need to try again, but this time use the
+ * tgs_ktypes in the context. At this point we should
+ * have all the tgts to succeed.
+ */
+
+ /* Free "wrong" credential */
+ krb5_free_creds(context, *out_cred);
+ *out_cred = NULL;
+ /* Re-establish tgs etypes */
+ context->use_conf_ktypes = old_use_conf_ktypes;
+ retval = krb5_get_cred_via_tkt(context, tgtptr,
+ KDC_OPT_CANONICALIZE |
+ FLAGS2OPTS(tgtptr->ticket_flags) |
+ kdcopt |
+ (in_cred->second_ticket.length ?
+ KDC_OPT_ENC_TKT_IN_SKEY : 0),
+ tgtptr->addresses,
+ in_cred, out_cred);
goto cleanup;
}
else if (IS_TGS_PRINC(context, (*out_cred)->server)) {
@@ -1055,7 +1085,6 @@ krb5_get_cred_from_kdc_opt(krb5_context context, krb5_ccache ccache,
krb5_free_creds(context, *out_cred);
*out_cred = NULL;
break;
- }
}
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gc_via_tkt.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gc_via_tkt.c
index 93fb5f1a70..8ee5721a7c 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gc_via_tkt.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gc_via_tkt.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/gc_via_tgt.c
*
@@ -243,6 +242,35 @@ krb5_get_cred_via_tkt (krb5_context context, krb5_creds *tkt,
goto error_4;
retval = (krb5_error_code) err_reply->error + ERROR_TABLE_BASE_krb5;
+ if (err_reply->text.length > 0) {
+#if 0
+ const char *m;
+#endif
+ switch (err_reply->error) {
+ case KRB_ERR_GENERIC:
+ krb5_set_error_message(context, retval,
+ "KDC returned error string: %s",
+ err_reply->text.data);
+ break;
+ default:
+#if 0 /* We should stop the KDC from sending back this text, because
+ if the local language doesn't match the KDC's language, we'd
+ just wind up printing out the error message in two languages.
+ Well, when we get some localization. Which is already
+ happening in KfM. */
+ m = error_message(retval);
+ /* Special case: MIT KDC may return this same string
+ in the e-text field. */
+ if (strlen (m) == err_reply->text.length-1
+ && !strcmp(m, err_reply->text.data))
+ break;
+ krb5_set_error_message(context, retval,
+ "%s (KDC supplied additional data: %s)",
+ m, err_reply->text.data);
+#endif
+ break;
+ }
+ }
krb5_free_error(context, err_reply);
goto error_4;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gen_seqnum.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gen_seqnum.c
index 23a8a34ec8..815529cf53 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gen_seqnum.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gen_seqnum.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/gen_seqnum.c
*
@@ -35,7 +34,7 @@
* then taking the output and slicing it up.
*/
-#include <k5-int.h>
+#include "k5-int.h"
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
@@ -54,7 +53,7 @@ krb5_generate_seq_number(krb5_context context, const krb5_keyblock *key, krb5_ui
seed.length = key->length;
- seed.data = (char *)key->contents;
+ seed.data = key->contents;
if ((retval = krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed)))
return(retval);
#endif /* 0 */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gen_subkey.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gen_subkey.c
index 3fa1a80ce7..bc2ee772e6 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gen_subkey.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gen_subkey.c
@@ -1,8 +1,7 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/gen_subkey.c
*
- * Copyright 1991 by the Massachusetts Institute of Technology.
+ * Copyright 1991, 2002 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -28,7 +27,7 @@
* Routine to automatically generate a subsession key based on an input key.
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*ARGSUSED*/
krb5_error_code
@@ -45,7 +44,7 @@ krb5_generate_subkey(krb5_context context, const krb5_keyblock *key, krb5_keyblo
krb5_data seed;
seed.length = key->length;
- seed.data = (char *)key->contents;
+ seed.data = key->contents;
if ((retval = krb5_c_random_add_entropy(context, KRB5_C_RANDSOURCE_TRUSTEDPARTY, &seed)))
return(retval);
#endif /* 0 */
@@ -53,6 +52,7 @@ krb5_generate_subkey(krb5_context context, const krb5_keyblock *key, krb5_keyblo
if ((*subkey = (krb5_keyblock *) malloc(sizeof(krb5_keyblock))) == NULL)
return(ENOMEM);
+ /* Solaris Kerberos */
(void) memset(*subkey, 0, sizeof(krb5_keyblock));
if ((retval = krb5_c_make_random_key(context, key->enctype, *subkey))) {
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_creds.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_creds.c
index e0a9834271..202015ee36 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_creds.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_creds.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/get_creds.c
@@ -15,7 +14,7 @@
* 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
@@ -29,7 +28,7 @@
* 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.
- *
+ *
*
* krb5_get_credentials()
*/
@@ -50,7 +49,7 @@
returns errors from encryption routines, system errors
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*ARGSUSED*/
static krb5_error_code
@@ -58,6 +57,7 @@ krb5_get_credentials_core(krb5_context context, krb5_flags options,
krb5_creds *in_creds, krb5_creds *mcreds,
krb5_flags *fields)
{
+ /* Solaris Kerberos */
krb5_error_code ret = 0;
if (!in_creds || !in_creds->server || !in_creds->client)
@@ -66,6 +66,7 @@ krb5_get_credentials_core(krb5_context context, krb5_flags options,
memset((char *)mcreds, 0, sizeof(krb5_creds));
mcreds->magic = KV5M_CREDS;
/*
+ * Solaris Kerberos:
* Set endtime appropriately to make sure we do not rope in
* expired creds. If endtime is set to 0 (which it almost always
* is, courtesy memset/calloc) the krb5_cc_retrieve_cred() call in
@@ -90,7 +91,7 @@ krb5_get_credentials_core(krb5_context context, krb5_flags options,
mcreds->authdata = in_creds->authdata;
mcreds->server = in_creds->server;
mcreds->client = in_creds->client;
-
+
*fields = KRB5_TC_MATCH_TIMES /*XXX |KRB5_TC_MATCH_SKEY_TYPE */
| KRB5_TC_MATCH_AUTHDATA
| KRB5_TC_SUPPORTED_KTYPES;
@@ -101,13 +102,13 @@ krb5_get_credentials_core(krb5_context context, krb5_flags options,
*fields |= KRB5_TC_MATCH_KTYPE;
ret = krb5_get_tgs_ktypes (context, mcreds->server, &ktypes);
for (i = 0; ktypes[i]; i++)
- if (ktypes[i] == mcreds->keyblock.enctype)
+ if (ktypes[i] == mcreds->keyblock.enctype)
break;
if (ktypes[i] == 0)
- ret = KRB5_CC_NOT_KTYPE;
+ ret = KRB5_CC_NOT_KTYPE;
free (ktypes);
if (ret)
- return ret;
+ return ret;
}
if (options & KRB5_GC_USER_USER) {
/* also match on identical 2nd tkt and tkt encrypted in a
@@ -147,6 +148,7 @@ krb5_get_credentials(krb5_context context, krb5_flags options,
ncreds->magic = KV5M_CREDS;
/* The caller is now responsible for cleaning up in_creds */
+ /* Solaris Kerberos */
if ((retval = krb5_cc_retrieve_cred(context, ccache, fields, &mcreds,
ncreds)) !=0) {
krb5_xfree(ncreds);
@@ -169,6 +171,7 @@ krb5_get_credentials(krb5_context context, krb5_flags options,
register int i = 0;
krb5_error_code rv2;
while (tgts[i]) {
+ /* Solaris Kerberos */
if ((rv2 = krb5_cc_store_cred(context, ccache, tgts[i])) != 0) {
retval = rv2;
break;
@@ -192,8 +195,16 @@ krb5_get_credentials(krb5_context context, krb5_flags options,
&& not_ktype)
retval = KRB5_CC_NOT_KTYPE;
- if (!retval)
+ if (!retval) {
+ /* the purpose of the krb5_get_credentials call is to
+ * obtain a set of credentials for the caller. the
+ * krb5_cc_store_cred() call is to optimize performance
+ * for future calls. Ignore any errors, since the credentials
+ * are still valid even if we fail to store them in the cache.
+ */
+ /* Solaris Kerberos */
retval = krb5_cc_store_cred(context, ccache, *out_creds);
+ }
return retval;
}
@@ -201,7 +212,7 @@ krb5_get_credentials(krb5_context context, krb5_flags options,
#define INT_GC_RENEW 2
/*ARGSUSED*/
-static krb5_error_code
+static krb5_error_code
krb5_get_credentials_val_renew_core(krb5_context context, krb5_flags options,
krb5_ccache ccache, krb5_creds *in_creds,
krb5_creds **out_creds, int which)
@@ -212,11 +223,11 @@ krb5_get_credentials_val_renew_core(krb5_context context, krb5_flags options,
switch(which) {
case INT_GC_VALIDATE:
- retval = krb5_get_cred_from_kdc_validate(context, ccache,
+ retval = krb5_get_cred_from_kdc_validate(context, ccache,
in_creds, out_creds, &tgts);
break;
case INT_GC_RENEW:
- retval = krb5_get_cred_from_kdc_renew(context, ccache,
+ retval = krb5_get_cred_from_kdc_renew(context, ccache,
in_creds, out_creds, &tgts);
break;
default:
@@ -229,8 +240,9 @@ krb5_get_credentials_val_renew_core(krb5_context context, krb5_flags options,
retval = krb5_cc_get_principal(context, ccache, &tmp);
if (retval) return retval;
-
+
retval = krb5_cc_initialize(context, ccache, tmp);
+ /* Solaris Kerberos */
if (retval) {
krb5_free_principal(context, tmp);
return retval;
@@ -246,8 +258,8 @@ krb5_get_credentials_validate(krb5_context context, krb5_flags options,
krb5_ccache ccache, krb5_creds *in_creds,
krb5_creds **out_creds)
{
- return(krb5_get_credentials_val_renew_core(context, options, ccache,
- in_creds, out_creds,
+ return(krb5_get_credentials_val_renew_core(context, options, ccache,
+ in_creds, out_creds,
INT_GC_VALIDATE));
}
@@ -257,8 +269,8 @@ krb5_get_credentials_renew(krb5_context context, krb5_flags options,
krb5_creds **out_creds)
{
- return(krb5_get_credentials_val_renew_core(context, options, ccache,
- in_creds, out_creds,
+ return(krb5_get_credentials_val_renew_core(context, options, ccache,
+ in_creds, out_creds,
INT_GC_RENEW));
}
@@ -313,12 +325,12 @@ krb5_validate_or_renew_creds(krb5_context context, krb5_creds *creds,
}
if (validate)
- ret = krb5_get_cred_from_kdc_validate(context, ccache,
+ ret = krb5_get_cred_from_kdc_validate(context, ccache,
&in_creds, &out_creds, &tgts);
else
- ret = krb5_get_cred_from_kdc_renew(context, ccache,
+ ret = krb5_get_cred_from_kdc_renew(context, ccache,
&in_creds, &out_creds, &tgts);
-
+
/* ick. copy the struct contents, free the container */
if (out_creds) {
*creds = *out_creds;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c
index fec64093f2..130abeca1c 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/get_in_tkt.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"$
/*
* lib/krb5/krb/get_in_tkt.c
@@ -36,10 +35,9 @@
#include <string.h>
-#include <k5-int.h>
-#include <krb5.h>
-#include <int-proto.h>
-#include <os-proto.h>
+#include "k5-int.h"
+#include "int-proto.h"
+#include "os-proto.h"
/*
All-purpose initial ticket routine, usually called via
@@ -48,7 +46,7 @@
Attempts to get an initial ticket for creds->client to use server
creds->server, (realm is taken from creds->client), with options
options, and using creds->times.starttime, creds->times.endtime,
- creds->times.renew_till as from, till, and rtime.
+ creds->times.renew_till as from, till, and rtime.
creds->times.renew_till is ignored unless the RENEWABLE option is requested.
key_proc is called to fill in the key to be used for decryption.
@@ -69,6 +67,7 @@
*/
+/* Solaris Kerberos */
#define max(a, b) ((a) > (b) ? (a) : (b))
/* some typedef's for the function args to make things look a bit cleaner */
@@ -82,11 +81,14 @@ typedef krb5_error_code (*git_key_proc) (krb5_context,
typedef krb5_error_code (*git_decrypt_proc) (krb5_context,
const krb5_keyblock *,
krb5_const_pointer,
- krb5_kdc_rep *);
+ krb5_kdc_rep * );
-static krb5_error_code make_preauth_list (krb5_context,
+static krb5_error_code make_preauth_list (krb5_context,
krb5_preauthtype *,
int, krb5_pa_data ***);
+static krb5_error_code sort_krb5_padata_sequence(krb5_context context,
+ krb5_data *realm,
+ krb5_pa_data **padata);
/*
* This function performs 32 bit bounded addition so we can generate
@@ -114,10 +116,9 @@ static krb5_int32 krb5int_addint32 (krb5_int32 x, krb5_int32 y)
static krb5_error_code
send_as_request(krb5_context context,
krb5_kdc_req *request,
- krb5_timestamp *time_now,
krb5_error ** ret_err_reply,
krb5_kdc_rep ** ret_as_reply,
- int *use_master)
+ int *use_master)
{
krb5_kdc_rep *as_reply = 0;
krb5_error_code retval;
@@ -125,17 +126,16 @@ send_as_request(krb5_context context,
krb5_data reply;
char k4_version; /* same type as *(krb5_data::data) */
int tcp_only = 0;
+ krb5_timestamp time_now;
reply.data = 0;
-
- if ((retval = krb5_timeofday(context, time_now)))
- goto cleanup;
- /*
- * XXX we know they are the same size... and we should do
- * something better than just the current time
- */
- request->nonce = (krb5_int32) *time_now;
+ /* set the nonce if the caller expects us to do it */
+ if (request->nonce == 0) {
+ if ((retval = krb5_timeofday(context, &time_now)))
+ goto cleanup;
+ request->nonce = (krb5_int32) time_now;
+ }
/* encode & send to KDC */
if ((retval = encode_krb5_as_req(request, &packet)) != 0)
@@ -154,7 +154,7 @@ send_again:
krb5_error *err_reply;
if ((retval = decode_krb5_error(&reply, &err_reply)))
- /* some other error code--??? */
+ /* some other error code--??? */
goto cleanup;
if (ret_err_reply) {
@@ -235,18 +235,17 @@ decrypt_as_reply(krb5_context context,
krb5_error_code retval;
krb5_keyblock * decrypt_key = 0;
krb5_data salt;
-
- KRB5_LOG0(KRB5_INFO, "decrypt_as_reply() start");
-
+
if (as_reply->enc_part2)
return 0;
if (key)
decrypt_key = key;
+ /* Solaris Kerberos */
else if (request != NULL) {
if ((retval = krb5_principal2salt(context, request->client, &salt)))
return(retval);
-
+
retval = (*key_proc)(context, as_reply->enc_part.enctype,
&salt, keyseed, &decrypt_key);
krb5_xfree(salt.data);
@@ -258,7 +257,8 @@ decrypt_as_reply(krb5_context context,
return (EINVAL);
}
- /* Solaris kerberos: Overwriting the decrypt_key->enctype because the
+ /*
+ * Solaris kerberos: Overwriting the decrypt_key->enctype because the
* decrypt key's enctype may not be an exact match with the enctype that the
* KDC used to encrypt this part of the AS reply. This assumes the
* as_reply->enc_part.enctype has been validated which is done by checking
@@ -290,9 +290,6 @@ decrypt_as_reply(krb5_context context,
cleanup:
if (!key && decrypt_key)
krb5_free_keyblock(context, decrypt_key);
-
- KRB5_LOG(KRB5_INFO, "decrypt_as_reply() end, retval = %d", retval);
-
return (retval);
}
@@ -303,12 +300,12 @@ verify_as_reply(krb5_context context,
krb5_kdc_rep *as_reply)
{
krb5_error_code retval;
-
+
/* check the contents for sanity: */
if (!as_reply->enc_part2->times.starttime)
as_reply->enc_part2->times.starttime =
as_reply->enc_part2->times.authtime;
-
+
if (!krb5_principal_compare(context, as_reply->client, request->client)
|| !krb5_principal_compare(context, as_reply->enc_part2->server, request->server)
|| !krb5_principal_compare(context, as_reply->ticket->server, request->server)
@@ -387,7 +384,7 @@ stash_as_reply(krb5_context context,
goto cleanup;
/* fill in the credentials */
- if ((retval = krb5_copy_keyblock_contents(context,
+ if ((retval = krb5_copy_keyblock_contents(context,
as_reply->enc_part2->session,
&creds->keyblock)))
goto cleanup;
@@ -410,7 +407,7 @@ stash_as_reply(krb5_context context,
krb5_xfree(packet);
/* store it in the ccache! */
- if (ccache)
+ if (ccache) /* Solaris Kerberos */
if ((retval = krb5_cc_store_cred(context, ccache, creds)) !=0)
goto cleanup;
@@ -459,13 +456,13 @@ make_preauth_list(krb5_context context,
for (nptypes=0, ptypep = ptypes; *ptypep; ptypep++, nptypes++)
;
}
-
+
/* allocate space for a NULL to terminate the list */
-
+
if ((preauthp =
(krb5_pa_data **) malloc((nptypes+1)*sizeof(krb5_pa_data *))) == NULL)
return(ENOMEM);
-
+
for (i=0; i<nptypes; i++) {
if ((preauthp[i] =
(krb5_pa_data *) malloc(sizeof(krb5_pa_data))) == NULL) {
@@ -479,18 +476,16 @@ make_preauth_list(krb5_context context,
preauthp[i]->length = 0;
preauthp[i]->contents = 0;
}
-
+
/* fill in the terminating NULL */
-
+
preauthp[nptypes] = NULL;
-
+
*ret_list = preauthp;
return 0;
}
#define MAX_IN_TKT_LOOPS 16
-/* SUNW14resync - Solaris krb does not use this (appearently) */
-#if 0
static const krb5_enctype get_in_tkt_enctypes[] = {
ENCTYPE_DES3_CBC_SHA1,
ENCTYPE_ARCFOUR_HMAC,
@@ -499,7 +494,204 @@ static const krb5_enctype get_in_tkt_enctypes[] = {
ENCTYPE_DES_CBC_CRC,
0
};
-#endif
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_in_tkt(krb5_context context,
+ const krb5_flags options,
+ krb5_address * const * addrs,
+ krb5_enctype * ktypes,
+ krb5_preauthtype * ptypes,
+ git_key_proc key_proc,
+ krb5_const_pointer keyseed,
+ git_decrypt_proc decrypt_proc,
+ krb5_const_pointer decryptarg,
+ krb5_creds * creds,
+ krb5_ccache ccache,
+ krb5_kdc_rep ** ret_as_reply)
+{
+ krb5_error_code retval;
+ krb5_timestamp time_now;
+ krb5_keyblock * decrypt_key = 0;
+ krb5_kdc_req request;
+ krb5_pa_data **padata = 0;
+ krb5_error * err_reply;
+ krb5_kdc_rep * as_reply = 0;
+ krb5_pa_data ** preauth_to_use = 0;
+ int loopcount = 0;
+ krb5_int32 do_more = 0;
+ int use_master = 0;
+
+ if (! krb5_realm_compare(context, creds->client, creds->server))
+ return KRB5_IN_TKT_REALM_MISMATCH;
+
+ if (ret_as_reply)
+ *ret_as_reply = 0;
+
+ /*
+ * Set up the basic request structure
+ */
+ request.magic = KV5M_KDC_REQ;
+ request.msg_type = KRB5_AS_REQ;
+ request.addresses = 0;
+ request.ktype = 0;
+ request.padata = 0;
+ if (addrs)
+ request.addresses = (krb5_address **) addrs;
+ else
+ if ((retval = krb5_os_localaddr(context, &request.addresses)))
+ goto cleanup;
+ request.kdc_options = options;
+ request.client = creds->client;
+ request.server = creds->server;
+ request.nonce = 0;
+ request.from = creds->times.starttime;
+ request.till = creds->times.endtime;
+ request.rtime = creds->times.renew_till;
+
+ request.ktype = malloc (sizeof(get_in_tkt_enctypes));
+ if (request.ktype == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ memcpy(request.ktype, get_in_tkt_enctypes, sizeof(get_in_tkt_enctypes));
+ for (request.nktypes = 0;request.ktype[request.nktypes];request.nktypes++);
+ if (ktypes) {
+ int i, req, next = 0;
+ for (req = 0; ktypes[req]; req++) {
+ if (ktypes[req] == request.ktype[next]) {
+ next++;
+ continue;
+ }
+ for (i = next + 1; i < request.nktypes; i++)
+ if (ktypes[req] == request.ktype[i]) {
+ /* Found the enctype we want, but not in the
+ position we want. Move it, but keep the old
+ one from the desired slot around in case it's
+ later in our requested-ktypes list. */
+ krb5_enctype t;
+ t = request.ktype[next];
+ request.ktype[next] = request.ktype[i];
+ request.ktype[i] = t;
+ next++;
+ break;
+ }
+ /* If we didn't find it, don't do anything special, just
+ drop it. */
+ }
+ request.ktype[next] = 0;
+ request.nktypes = next;
+ }
+ request.authorization_data.ciphertext.length = 0;
+ request.authorization_data.ciphertext.data = 0;
+ request.unenc_authdata = 0;
+ request.second_ticket = 0;
+
+ /*
+ * If a list of preauth types are passed in, convert it to a
+ * preauth_to_use list.
+ */
+ if (ptypes) {
+ retval = make_preauth_list(context, ptypes, -1, &preauth_to_use);
+ if (retval)
+ goto cleanup;
+ }
+
+ while (1) {
+ if (loopcount++ > MAX_IN_TKT_LOOPS) {
+ retval = KRB5_GET_IN_TKT_LOOP;
+ goto cleanup;
+ }
+
+ if ((retval = krb5_obtain_padata(context, preauth_to_use, key_proc,
+ keyseed, creds, &request)) != 0)
+ goto cleanup;
+ if (preauth_to_use)
+ krb5_free_pa_data(context, preauth_to_use);
+ preauth_to_use = 0;
+
+ err_reply = 0;
+ as_reply = 0;
+
+ if ((retval = krb5_timeofday(context, &time_now)))
+ goto cleanup;
+
+ /*
+ * XXX we know they are the same size... and we should do
+ * something better than just the current time
+ */
+ request.nonce = (krb5_int32) time_now;
+
+ if ((retval = send_as_request(context, &request, &err_reply,
+ &as_reply, &use_master)))
+ goto cleanup;
+
+ if (err_reply) {
+ if (err_reply->error == KDC_ERR_PREAUTH_REQUIRED &&
+ err_reply->e_data.length > 0) {
+ retval = decode_krb5_padata_sequence(&err_reply->e_data,
+ &preauth_to_use);
+ krb5_free_error(context, err_reply);
+ if (retval)
+ goto cleanup;
+ retval = sort_krb5_padata_sequence(context,
+ &request.server->realm,
+ padata);
+ if (retval)
+ goto cleanup;
+ continue;
+ } else {
+ retval = (krb5_error_code) err_reply->error
+ + ERROR_TABLE_BASE_krb5;
+ krb5_free_error(context, err_reply);
+ goto cleanup;
+ }
+ } else if (!as_reply) {
+ retval = KRB5KRB_AP_ERR_MSG_TYPE;
+ goto cleanup;
+ }
+ if ((retval = krb5_process_padata(context, &request, as_reply,
+ key_proc, keyseed, decrypt_proc,
+ &decrypt_key, creds,
+ &do_more)) != 0)
+ goto cleanup;
+
+ if (!do_more)
+ break;
+ }
+
+ if ((retval = decrypt_as_reply(context, &request, as_reply, key_proc,
+ keyseed, decrypt_key, decrypt_proc,
+ decryptarg)))
+ goto cleanup;
+
+ if ((retval = verify_as_reply(context, time_now, &request, as_reply)))
+ goto cleanup;
+
+ if ((retval = stash_as_reply(context, time_now, &request, as_reply,
+ creds, ccache)))
+ goto cleanup;
+
+cleanup:
+ if (request.ktype)
+ free(request.ktype);
+ if (!addrs && request.addresses)
+ krb5_free_addresses(context, request.addresses);
+ if (request.padata)
+ krb5_free_pa_data(context, request.padata);
+ if (padata)
+ krb5_free_pa_data(context, padata);
+ if (preauth_to_use)
+ krb5_free_pa_data(context, preauth_to_use);
+ if (decrypt_key)
+ krb5_free_keyblock(context, decrypt_key);
+ if (as_reply) {
+ if (ret_as_reply)
+ *ret_as_reply = as_reply;
+ else
+ krb5_free_kdc_rep(context, as_reply);
+ }
+ return (retval);
+}
/* begin libdefaults parsing code. This should almost certainly move
somewhere else, but I don't know where the correct somewhere else
@@ -551,11 +743,12 @@ krb5_libdefault_string(krb5_context context, const krb5_data *realm,
strncpy(realmstr, realm->data, realm->length);
realmstr[realm->length] = '\0';
- if (!context || (context->magic != KV5M_CONTEXT))
+ if (!context || (context->magic != KV5M_CONTEXT))
return KV5M_CONTEXT;
profile = context->profile;
-
+
+ /* Solaris Kerberos */
names[0] = "realms";
/*
@@ -580,7 +773,7 @@ krb5_libdefault_string(krb5_context context, const krb5_data *realm,
* [libdefaults]
* option = <boolean>
*/
-
+
names[0] = "libdefaults";
names[1] = option;
names[2] = 0;
@@ -589,7 +782,7 @@ krb5_libdefault_string(krb5_context context, const krb5_data *realm,
goto goodbye;
goodbye:
- if (!nameval)
+ if (!nameval)
return(ENOENT);
if (!nameval[0]) {
@@ -628,6 +821,79 @@ krb5_libdefault_boolean(krb5_context context, const krb5_data *realm,
return(0);
}
+/* Sort a pa_data sequence so that types named in the "preferred_preauth_types"
+ * libdefaults entry are listed before any others. */
+static krb5_error_code
+sort_krb5_padata_sequence(krb5_context context, krb5_data *realm,
+ krb5_pa_data **padata)
+{
+ int i, j, base;
+ krb5_error_code ret;
+ const char *p;
+ long l;
+ char *q, *preauth_types = NULL;
+ krb5_pa_data *tmp;
+ int need_free_string = 1;
+
+ if ((padata == NULL) || (padata[0] == NULL)) {
+ return 0;
+ }
+
+ ret = krb5_libdefault_string(context, realm, "preferred_preauth_types",
+ &preauth_types);
+ if ((ret != 0) || (preauth_types == NULL)) {
+ /* Try to use PKINIT first. */
+ preauth_types = "17, 16, 15, 14";
+ need_free_string = 0;
+ }
+
+#ifdef DEBUG
+ fprintf (stderr, "preauth data types before sorting:");
+ for (i = 0; padata[i]; i++) {
+ fprintf (stderr, " %d", padata[i]->pa_type);
+ }
+ fprintf (stderr, "\n");
+#endif
+
+ base = 0;
+ for (p = preauth_types; *p != '\0';) {
+ /* skip whitespace to find an entry */
+ p += strspn(p, ", ");
+ if (*p != '\0') {
+ /* see if we can extract a number */
+ l = strtol(p, &q, 10);
+ if ((q != NULL) && (q > p)) {
+ /* got a valid number; search for a matchin entry */
+ for (i = base; padata[i] != NULL; i++) {
+ /* bubble the matching entry to the front of the list */
+ if (padata[i]->pa_type == l) {
+ tmp = padata[i];
+ for (j = i; j > base; j--)
+ padata[j] = padata[j - 1];
+ padata[base] = tmp;
+ base++;
+ break;
+ }
+ }
+ p = q;
+ } else {
+ break;
+ }
+ }
+ }
+ if (need_free_string)
+ free(preauth_types);
+
+#ifdef DEBUG
+ fprintf (stderr, "preauth data types after sorting:");
+ for (i = 0; padata[i]; i++)
+ fprintf (stderr, " %d", padata[i]->pa_type);
+ fprintf (stderr, "\n");
+#endif
+
+ return 0;
+}
+
krb5_error_code KRB5_CALLCONV
krb5_get_init_creds(krb5_context context,
krb5_creds *creds,
@@ -636,7 +902,7 @@ krb5_get_init_creds(krb5_context context,
void *prompter_data,
krb5_deltat start_time,
char *in_tkt_service,
- krb5_get_init_creds_opt *options,
+ krb5_gic_opt_ext *options,
krb5_gic_get_as_key_fct gak_fct,
void *gak_data,
int *use_master,
@@ -644,12 +910,12 @@ krb5_get_init_creds(krb5_context context,
{
krb5_error_code ret;
krb5_kdc_req request;
- krb5_pa_data **padata;
+ krb5_data *encoded_request_body, *encoded_previous_request;
+ krb5_pa_data **preauth_to_use, **kdc_padata;
int tempint;
char *tempstr = NULL;
krb5_deltat tkt_life;
krb5_deltat renew_life;
- krb5_deltat max_life;
int loopcount;
krb5_data salt;
krb5_data s2kparams;
@@ -658,6 +924,7 @@ krb5_get_init_creds(krb5_context context,
krb5_kdc_rep *local_as_reply;
krb5_timestamp time_now;
krb5_enctype etype = 0;
+ krb5_preauth_client_rock get_data_rock;
/* initialize everything which will be freed at cleanup */
@@ -667,13 +934,19 @@ krb5_get_init_creds(krb5_context context,
request.ktype = NULL;
request.addresses = NULL;
request.padata = NULL;
- padata = NULL;
+ encoded_request_body = NULL;
+ encoded_previous_request = NULL;
+ preauth_to_use = NULL;
+ kdc_padata = NULL;
+ as_key.length = 0;
salt.length = 0;
salt.data = NULL;
(void) memset(&as_key, 0, sizeof(as_key));
- local_as_reply = 0;
+ local_as_reply = 0;
+
+ err_reply = NULL;
/*
* Set up the basic request structure
@@ -681,6 +954,9 @@ krb5_get_init_creds(krb5_context context,
request.magic = KV5M_KDC_REQ;
request.msg_type = KRB5_AS_REQ;
+ /* request.nonce is filled in when we send a request to the kdc */
+ request.nonce = 0;
+
/* request.padata is filled in later */
request.kdc_options = context->kdc_default_options;
@@ -694,7 +970,7 @@ krb5_get_init_creds(krb5_context context,
/*EMPTY*/
;
else
- tempint = 0;
+ tempint = 0;
if (tempint)
request.kdc_options |= KDC_OPT_FORWARDABLE;
@@ -707,12 +983,12 @@ krb5_get_init_creds(krb5_context context,
/*EMPTY*/
;
else
- tempint = 0;
+ tempint = 0;
if (tempint)
request.kdc_options |= KDC_OPT_PROXIABLE;
/* allow_postdate */
-
+
if (start_time > 0)
request.kdc_options |= (KDC_OPT_ALLOW_POSTDATE|KDC_OPT_POSTDATED);
@@ -727,15 +1003,11 @@ krb5_get_init_creds(krb5_context context,
} else if ((ret = krb5_libdefault_string(context, &client->realm,
"ticket_lifetime", &tempstr))
== 0) {
- if ((ret = krb5_string_to_deltat(tempstr, &tkt_life))) {
- free(tempstr);
- tempstr = NULL;
+ ret = krb5_string_to_deltat(tempstr, &tkt_life);
+ free(tempstr);
+ if (ret) {
goto cleanup;
}
- if (tempstr) {
- free(tempstr);
- tempstr = NULL;
- }
} else {
/* this used to be hardcoded in kinit.c */
tkt_life = 24*60*60;
@@ -749,20 +1021,17 @@ krb5_get_init_creds(krb5_context context,
} else if ((ret = krb5_libdefault_string(context, &client->realm,
"renew_lifetime", &tempstr))
== 0) {
- if ((ret = krb5_string_to_deltat(tempstr, &renew_life))) {
- free(tempstr);
+ ret = krb5_string_to_deltat(tempstr, &renew_life);
+ free(tempstr);
+ if (ret) {
goto cleanup;
}
- if (tempstr) {
- free(tempstr);
- tempstr = NULL;
- }
} else {
renew_life = 0;
}
if (renew_life > 0)
request.kdc_options |= KDC_OPT_RENEWABLE;
-
+
if (renew_life > 0) {
request.rtime = krb5int_addint32(request.from, renew_life);
if (request.rtime < request.till) {
@@ -774,13 +1043,13 @@ krb5_get_init_creds(krb5_context context,
} else {
request.rtime = 0;
}
-
+
/* client */
request.client = client;
/* service */
-
+
if (in_tkt_service) {
/* this is ugly, because so are the data structures involved. I'm
in the library, so I'm going to manipulate the data structures
@@ -814,7 +1083,9 @@ krb5_get_init_creds(krb5_context context,
goto cleanup;
}
- /* nonce is filled in by send_as_request */
+ krb5_preauth_request_context_init(context);
+
+ /* nonce is filled in by send_as_request if we don't take care of it */
if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST)) {
request.ktype = options->etype_list;
@@ -859,8 +1130,8 @@ krb5_get_init_creds(krb5_context context,
if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST)) {
if ((ret = make_preauth_list(context, options->preauth_list,
- options->preauth_list_length,
- &padata)))
+ options->preauth_list_length,
+ &preauth_to_use)))
goto cleanup;
}
@@ -870,48 +1141,122 @@ krb5_get_init_creds(krb5_context context,
if (options && (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT)) {
salt = *options->salt;
} else {
- salt.length = (unsigned int)-1;
+ salt.length = SALT_TYPE_AFS_LENGTH;
salt.data = NULL;
}
- /* now, loop processing preauth data and talking to the kdc */
+ /* set the request nonce */
+ if ((ret = krb5_timeofday(context, &time_now)))
+ goto cleanup;
+ /*
+ * XXX we know they are the same size... and we should do
+ * something better than just the current time
+ */
+ request.nonce = (krb5_int32) time_now;
+
+ /* give the preauth plugins a chance to prep the request body */
+ krb5_preauth_prepare_request(context, options, &request);
+ ret = encode_krb5_kdc_req_body(&request, &encoded_request_body);
+ if (ret)
+ goto cleanup;
+
+ get_data_rock.magic = CLIENT_ROCK_MAGIC;
+ get_data_rock.as_reply = NULL;
+
+ /* now, loop processing preauth data and talking to the kdc */
for (loopcount = 0; loopcount < MAX_IN_TKT_LOOPS; loopcount++) {
if (request.padata) {
krb5_free_pa_data(context, request.padata);
request.padata = NULL;
}
+ if (!err_reply) {
+ /* either our first attempt, or retrying after PREAUTH_NEEDED */
+ if ((ret = krb5_do_preauth(context,
+ &request,
+ encoded_request_body,
+ encoded_previous_request,
+ preauth_to_use, &request.padata,
+ &salt, &s2kparams, &etype, &as_key,
+ prompter, prompter_data,
+ gak_fct, gak_data,
+ &get_data_rock, options)))
+ goto cleanup;
+ } else {
+ if (preauth_to_use != NULL) {
+ /*
+ * Retry after an error other than PREAUTH_NEEDED,
+ * using e-data to figure out what to change.
+ */
+ ret = krb5_do_preauth_tryagain(context,
+ &request,
+ encoded_request_body,
+ encoded_previous_request,
+ preauth_to_use, &request.padata,
+ err_reply,
+ &salt, &s2kparams, &etype,
+ &as_key,
+ prompter, prompter_data,
+ gak_fct, gak_data,
+ &get_data_rock, options);
+ } else {
+ /* No preauth supplied, so can't query the plug-ins. */
+ ret = KRB5KRB_ERR_GENERIC;
+ }
+ if (ret) {
+ /* couldn't come up with anything better */
+ ret = err_reply->error + ERROR_TABLE_BASE_krb5;
+ }
+ krb5_free_error(context, err_reply);
+ err_reply = NULL;
+ if (ret)
+ goto cleanup;
+ }
- if ((ret = krb5_do_preauth(context, &request,
- padata, &request.padata,
- &salt, &s2kparams, &etype, &as_key, prompter,
- prompter_data, gak_fct, gak_data)))
+ if (encoded_previous_request != NULL) {
+ krb5_free_data(context, encoded_previous_request);
+ encoded_previous_request = NULL;
+ }
+ ret = encode_krb5_as_req(&request, &encoded_previous_request);
+ if (ret)
goto cleanup;
- if (padata) {
- krb5_free_pa_data(context, padata);
- padata = 0;
- }
-
err_reply = 0;
local_as_reply = 0;
- if ((ret = send_as_request(context, &request, &time_now, &err_reply,
+ if ((ret = send_as_request(context, &request, &err_reply,
&local_as_reply, use_master)))
goto cleanup;
if (err_reply) {
if (err_reply->error == KDC_ERR_PREAUTH_REQUIRED &&
err_reply->e_data.length > 0) {
+ /* reset the list of preauth types to try */
+ if (preauth_to_use) {
+ krb5_free_pa_data(context, preauth_to_use);
+ preauth_to_use = NULL;
+ }
ret = decode_krb5_padata_sequence(&err_reply->e_data,
- &padata);
+ &preauth_to_use);
krb5_free_error(context, err_reply);
+ err_reply = NULL;
+ if (ret)
+ goto cleanup;
+ ret = sort_krb5_padata_sequence(context,
+ &request.server->realm,
+ preauth_to_use);
if (ret)
goto cleanup;
+ /* continue to next iteration */
} else {
- ret = (krb5_error_code) err_reply->error
- + ERROR_TABLE_BASE_krb5;
- krb5_free_error(context, err_reply);
- goto cleanup;
+ if (err_reply->e_data.length > 0) {
+ /* continue to next iteration */
+ } else {
+ /* error + no hints = give up */
+ ret = (krb5_error_code) err_reply->error
+ + ERROR_TABLE_BASE_krb5;
+ krb5_free_error(context, err_reply);
+ goto cleanup;
+ }
}
} else if (local_as_reply) {
break;
@@ -927,22 +1272,26 @@ krb5_get_init_creds(krb5_context context,
}
/* process any preauth data in the as_reply */
-
- if ((ret = krb5_do_preauth(context, &request,
- local_as_reply->padata, &padata,
- &salt, &s2kparams, &etype, &as_key, prompter,
- prompter_data, gak_fct, gak_data)))
+ krb5_clear_preauth_context_use_counts(context);
+ if ((ret = sort_krb5_padata_sequence(context, &request.server->realm,
+ local_as_reply->padata)))
+ goto cleanup;
+ get_data_rock.as_reply = local_as_reply;
+ if ((ret = krb5_do_preauth(context,
+ &request,
+ encoded_request_body, encoded_previous_request,
+ local_as_reply->padata, &kdc_padata,
+ &salt, &s2kparams, &etype, &as_key, prompter,
+ prompter_data, gak_fct, gak_data,
+ &get_data_rock, options)))
goto cleanup;
-
- /* XXX if there's padata on output, something is wrong, but it's
- not obviously an error */
/* XXX For 1.1.1 and prior KDC's, when SAM is used w/ USE_SAD_AS_KEY,
the AS_REP comes back encrypted in the user's longterm key
instead of in the SAD. If there was a SAM preauth, there
will be an as_key here which will be the SAD. If that fails,
use the gak_fct to get the password, and try again. */
-
+
/* XXX because etypes are handled poorly (particularly wrt SAM,
where the etype is fixed by the kdc), we may want to try
decrypt_as_reply twice. If there's an as_key available, try
@@ -951,40 +1300,37 @@ krb5_get_init_creds(krb5_context context,
again. */
if (as_key.length)
- ret = decrypt_as_reply(context, (krb5_kdc_req *)NULL, local_as_reply,
- (git_key_proc)NULL, (krb5_const_pointer)NULL,
- &as_key, krb5_kdc_rep_decrypt_proc,
- (krb5_const_pointer)NULL);
+ ret = decrypt_as_reply(context, NULL, local_as_reply, NULL,
+ NULL, &as_key, krb5_kdc_rep_decrypt_proc,
+ NULL);
else
ret = -1;
-
+
if (ret) {
/* if we haven't get gotten a key, get it now */
if ((ret = ((*gak_fct)(context, request.client,
- local_as_reply->enc_part.enctype,
- prompter, prompter_data, &salt, &s2kparams,
- &as_key, gak_data))))
+ local_as_reply->enc_part.enctype,
+ prompter, prompter_data, &salt, &s2kparams,
+ &as_key, gak_data))))
goto cleanup;
- if ((ret=decrypt_as_reply(context, (krb5_kdc_req *)NULL,
- local_as_reply, (git_key_proc)NULL,
- (krb5_const_pointer)NULL, &as_key,
- krb5_kdc_rep_decrypt_proc,
- (krb5_const_pointer)NULL)))
+ if ((ret = decrypt_as_reply(context, NULL, local_as_reply, NULL,
+ NULL, &as_key, krb5_kdc_rep_decrypt_proc,
+ NULL)))
goto cleanup;
}
if ((ret = verify_as_reply(context, time_now, &request, local_as_reply)))
goto cleanup;
- /*
- * XXX this should be inside stash_as_reply, but as long as
- * get_in_tkt is still around using that arg as an in/out, I can't
- * do that
- */
+ /* XXX this should be inside stash_as_reply, but as long as
+ get_in_tkt is still around using that arg as an in/out, I can't
+ do that */
+ /* Solaris Kerberos */
(void) memset(creds, 0, sizeof(*creds));
+ /* Solaris Kerberos */
if ((ret = stash_as_reply(context, time_now, &request, local_as_reply,
creds, (krb5_ccache)NULL)))
goto cleanup;
@@ -994,6 +1340,15 @@ krb5_get_init_creds(krb5_context context,
ret = 0;
cleanup:
+ krb5_preauth_request_context_fini(context);
+ if (encoded_previous_request != NULL) {
+ krb5_free_data(context, encoded_previous_request);
+ encoded_previous_request = NULL;
+ }
+ if (encoded_request_body != NULL) {
+ krb5_free_data(context, encoded_request_body);
+ encoded_request_body = NULL;
+ }
if (request.server)
krb5_free_principal(context, request.server);
if (request.ktype &&
@@ -1003,8 +1358,10 @@ cleanup:
(!(options &&
(options->flags & KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST))))
krb5_free_addresses(context, request.addresses);
- if (padata)
- krb5_free_pa_data(context, padata);
+ if (preauth_to_use)
+ krb5_free_pa_data(context, preauth_to_use);
+ if (kdc_padata)
+ krb5_free_pa_data(context, kdc_padata);
if (request.padata)
krb5_free_pa_data(context, request.padata);
if (as_key.length)
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_keytab.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_keytab.c
index d2c90b6e76..351d5917ae 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_keytab.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_keytab.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/gic_keytab.c
@@ -31,20 +30,20 @@
* or implied warranty.
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*ARGSUSED*/
static krb5_error_code
krb5_get_as_key_keytab(
- krb5_context context,
- krb5_principal client,
- krb5_enctype etype,
- krb5_prompter_fct prompter,
- void *prompter_data,
- krb5_data *salt,
- krb5_data *params,
- krb5_keyblock *as_key,
- void *gak_data)
+ krb5_context context,
+ krb5_principal client,
+ krb5_enctype etype,
+ krb5_prompter_fct prompter,
+ void *prompter_data,
+ krb5_data *salt,
+ krb5_data *params,
+ krb5_keyblock *as_key,
+ void *gak_data)
{
krb5_keytab keytab = (krb5_keytab) gak_data;
krb5_error_code ret;
@@ -66,6 +65,7 @@ krb5_get_as_key_keytab(
if (!krb5_c_valid_enctype(etype))
return(KRB5_PROG_ETYPE_NOSUPP);
+ /* Solaris Kerberos */
if ((ret = krb5_kt_get_entry(context, keytab, client,
0, /* don't have vno available */
etype, &kt_ent)) != NULL)
@@ -84,32 +84,37 @@ krb5_get_as_key_keytab(
}
krb5_error_code KRB5_CALLCONV
-krb5_get_init_creds_keytab(
- krb5_context context,
- krb5_creds *creds,
- krb5_principal client,
- krb5_keytab arg_keytab,
- krb5_deltat start_time,
- char *in_tkt_service,
- krb5_get_init_creds_opt *options)
+krb5_get_init_creds_keytab(krb5_context context,
+ krb5_creds *creds,
+ krb5_principal client,
+ krb5_keytab arg_keytab,
+ krb5_deltat start_time,
+ char *in_tkt_service,
+ krb5_get_init_creds_opt *options)
{
krb5_error_code ret, ret2;
int use_master;
krb5_keytab keytab;
+ krb5_gic_opt_ext *opte = NULL;
if (arg_keytab == NULL) {
- if ((ret = krb5_kt_default(context, &keytab)))
- return ret;
+ if ((ret = krb5_kt_default(context, &keytab)))
+ return ret;
} else {
- keytab = arg_keytab;
+ keytab = arg_keytab;
}
+ ret = krb5int_gic_opt_to_opte(context, options, &opte, 1,
+ "krb5_get_init_creds_keytab");
+ if (ret)
+ return ret;
+
use_master = 0;
/* first try: get the requested tkt from any kdc */
ret = krb5_get_init_creds(context, creds, client, NULL, NULL,
- start_time, in_tkt_service, options,
+ start_time, in_tkt_service, opte,
krb5_get_as_key_keytab, (void *) keytab,
&use_master,NULL);
@@ -130,7 +135,7 @@ krb5_get_init_creds_keytab(
use_master = 1;
ret2 = krb5_get_init_creds(context, creds, client, NULL, NULL,
- start_time, in_tkt_service, options,
+ start_time, in_tkt_service, opte,
krb5_get_as_key_keytab, (void *) keytab,
&use_master, NULL);
@@ -142,7 +147,9 @@ krb5_get_init_creds_keytab(
/* if the master is unreachable, return the error from the
slave we were able to contact */
- if ((ret2 == KRB5_KDC_UNREACH) || (ret2 == KRB5_REALM_CANT_RESOLVE))
+ if ((ret2 == KRB5_KDC_UNREACH) ||
+ (ret2 == KRB5_REALM_CANT_RESOLVE) ||
+ (ret2 == KRB5_REALM_UNKNOWN))
goto cleanup;
ret = ret2;
@@ -152,12 +159,13 @@ krb5_get_init_creds_keytab(
do any prompting or changing for keytabs, that's it. */
cleanup:
+ if (opte && krb5_gic_opt_is_shadowed(opte))
+ krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
if (arg_keytab == NULL)
- (void) krb5_kt_close(context, keytab);
+ (void) krb5_kt_close(context, keytab); /* Solaris Kerberos */
return(ret);
}
-
krb5_error_code KRB5_CALLCONV
krb5_get_in_tkt_with_keytab(krb5_context context, krb5_flags options,
krb5_address *const *addrs, krb5_enctype *ktypes,
@@ -166,15 +174,18 @@ krb5_get_in_tkt_with_keytab(krb5_context context, krb5_flags options,
krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
{
krb5_error_code retval;
- krb5_get_init_creds_opt opt;
+ krb5_gic_opt_ext *opte;
char * server = NULL;
krb5_keytab keytab;
krb5_principal client_princ, server_princ;
int use_master = 0;
- krb5int_populate_gic_opt(context, &opt,
- options, addrs, ktypes,
- pre_auth_types, creds);
+ retval = krb5int_populate_gic_opt(context, &opte,
+ options, addrs, ktypes,
+ pre_auth_types, creds);
+ if (retval)
+ return retval;
+
if (arg_keytab == NULL) {
retval = krb5_kt_default(context, &keytab);
if (retval)
@@ -190,10 +201,11 @@ krb5_get_in_tkt_with_keytab(krb5_context context, krb5_flags options,
retval = krb5_get_init_creds (context,
creds, creds->client,
krb5_prompter_posix, NULL,
- 0, server, &opt,
+ 0, server, opte,
krb5_get_as_key_keytab, (void *)keytab,
&use_master, ret_as_reply);
krb5_free_unparsed_name( context, server);
+ krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
if (retval) {
goto cleanup;
}
@@ -212,3 +224,4 @@ krb5_get_in_tkt_with_keytab(krb5_context context, krb5_flags options,
krb5_kt_close(context, keytab);
return retval;
}
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_opt.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_opt.c
index 87e92d7b75..227391ae42 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_opt.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_opt.c
@@ -1,10 +1,17 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-#include <k5-int.h>
+#include "k5-int.h"
+#include "int-proto.h"
+
+static void
+init_common(krb5_get_init_creds_opt *opt)
+{
+ opt->flags |= KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
+}
void KRB5_CALLCONV
krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
{
- opt->flags = 0;
+ opt->flags = 0;
+ init_common(opt);
}
void KRB5_CALLCONV
@@ -64,3 +71,377 @@ krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt, krb5_data *salt)
opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT;
opt->salt = salt;
}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_set_change_password_prompt(krb5_get_init_creds_opt *opt, int prompt)
+{
+ if (prompt)
+ opt->flags |= KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
+ else
+ opt->flags &= ~KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT;
+}
+
+/*
+ * Extending the krb5_get_init_creds_opt structure. The original
+ * krb5_get_init_creds_opt structure is defined publicly. The
+ * new extended version is private. The original interface
+ * assumed a pre-allocated structure which was passed to
+ * krb5_get_init_creds_init(). The new interface assumes that
+ * the caller will call krb5_get_init_creds_alloc() and
+ * krb5_get_init_creds_free().
+ *
+ * Callers MUST NOT call krb5_get_init_creds_init() after allocating an
+ * opts structure using krb5_get_init_creds_alloc(). To do so will
+ * introduce memory leaks. Unfortunately, there is no way to enforce
+ * this behavior.
+ *
+ * Two private flags are added for backward compatibility.
+ * KRB5_GET_INIT_CREDS_OPT_EXTENDED says that the structure was allocated
+ * with the new krb5_get_init_creds_opt_alloc() function.
+ * KRB5_GET_INIT_CREDS_OPT_SHADOWED is set to indicate that the extended
+ * structure is a shadow copy of an original krb5_get_init_creds_opt
+ * structure.
+ * If KRB5_GET_INIT_CREDS_OPT_SHADOWED is set after a call to
+ * krb5int_gic_opt_to_opte(), the resulting extended structure should be
+ * freed (using krb5_get_init_creds_free). Otherwise, the original
+ * structure was already extended and there is no need to free it.
+ */
+
+/* Forward prototype */
+static void
+free_gic_opt_ext_preauth_data(krb5_context context,
+ krb5_gic_opt_ext *opte);
+
+static krb5_error_code
+krb5int_gic_opte_private_alloc(krb5_context context, krb5_gic_opt_ext *opte)
+{
+ if (NULL == opte || !krb5_gic_opt_is_extended(opte))
+ return EINVAL;
+
+ opte->opt_private = calloc(1, sizeof(*opte->opt_private));
+ if (NULL == opte->opt_private) {
+ return ENOMEM;
+ }
+ /* Allocate any private stuff */
+ opte->opt_private->num_preauth_data = 0;
+ opte->opt_private->preauth_data = NULL;
+ return 0;
+}
+
+static krb5_error_code
+krb5int_gic_opte_private_free(krb5_context context, krb5_gic_opt_ext *opte)
+{
+ if (NULL == opte || !krb5_gic_opt_is_extended(opte))
+ return EINVAL;
+
+ /* Free up any private stuff */
+ if (opte->opt_private->preauth_data != NULL)
+ free_gic_opt_ext_preauth_data(context, opte);
+ free(opte->opt_private);
+ opte->opt_private = NULL;
+ return 0;
+}
+
+static krb5_gic_opt_ext *
+krb5int_gic_opte_alloc(krb5_context context)
+{
+ krb5_gic_opt_ext *opte;
+ krb5_error_code code;
+
+ opte = calloc(1, sizeof(*opte));
+ if (NULL == opte)
+ return NULL;
+ opte->flags = KRB5_GET_INIT_CREDS_OPT_EXTENDED;
+
+ code = krb5int_gic_opte_private_alloc(context, opte);
+ if (code) {
+ krb5int_set_error(&context->err, code,
+ "krb5int_gic_opte_alloc: krb5int_gic_opte_private_alloc failed");
+ free(opte);
+ return NULL;
+ }
+ return(opte);
+}
+
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_opt_alloc(krb5_context context,
+ krb5_get_init_creds_opt **opt)
+{
+ krb5_gic_opt_ext *opte;
+
+ if (NULL == opt)
+ return EINVAL;
+ *opt = NULL;
+
+ /*
+ * We return a new extended structure cast as a krb5_get_init_creds_opt
+ */
+ opte = krb5int_gic_opte_alloc(context);
+ if (NULL == opte)
+ return ENOMEM;
+
+ *opt = (krb5_get_init_creds_opt *) opte;
+ init_common(*opt);
+ return 0;
+}
+
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_free(krb5_context context,
+ krb5_get_init_creds_opt *opt)
+{
+ krb5_gic_opt_ext *opte;
+
+ if (NULL == opt)
+ return;
+
+ /* Don't touch it if we didn't allocate it */
+ if (!krb5_gic_opt_is_extended(opt))
+ return;
+
+ opte = (krb5_gic_opt_ext *)opt;
+ if (opte->opt_private)
+ krb5int_gic_opte_private_free(context, opte);
+
+ free(opte);
+}
+
+static krb5_error_code
+krb5int_gic_opte_copy(krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ krb5_gic_opt_ext **opte)
+{
+ krb5_gic_opt_ext *oe;
+
+ oe = krb5int_gic_opte_alloc(context);
+ if (NULL == oe)
+ return ENOMEM;
+
+ if (opt)
+ memcpy(oe, opt, sizeof(*opt));
+
+ /*
+ * Fix the flags -- the EXTENDED flag would have been
+ * overwritten by the copy if there was one. The
+ * SHADOWED flag is necessary to ensure that the
+ * krb5_gic_opt_ext structure that was allocated
+ * here will be freed by the library because the
+ * application is unaware of its existence.
+ */
+ oe->flags |= ( KRB5_GET_INIT_CREDS_OPT_EXTENDED |
+ KRB5_GET_INIT_CREDS_OPT_SHADOWED);
+
+ *opte = oe;
+ return 0;
+}
+
+/*
+ * Convert a krb5_get_init_creds_opt pointer to a pointer to
+ * an extended, krb5_gic_opt_ext pointer. If the original
+ * pointer already points to an extended structure, then simply
+ * return the original pointer. Otherwise, if 'force' is non-zero,
+ * allocate an extended structure and copy the original over it.
+ * If the original pointer did not point to an extended structure
+ * and 'force' is zero, then return an error. This is used in
+ * cases where the original *should* be an extended structure.
+ */
+krb5_error_code
+krb5int_gic_opt_to_opte(krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ krb5_gic_opt_ext **opte,
+ unsigned int force,
+ const char *where)
+{
+ if (!krb5_gic_opt_is_extended(opt)) {
+ if (force) {
+ return krb5int_gic_opte_copy(context, opt, opte);
+ } else {
+ krb5int_set_error(&context->err, EINVAL,
+ "%s: attempt to convert non-extended krb5_get_init_creds_opt",
+ where);
+ return EINVAL;
+ }
+ }
+ /* If it is already extended, just return it */
+ *opte = (krb5_gic_opt_ext *)opt;
+ return 0;
+}
+
+static void
+free_gic_opt_ext_preauth_data(krb5_context context,
+ krb5_gic_opt_ext *opte)
+{
+ int i;
+
+ if (NULL == opte || !krb5_gic_opt_is_extended(opte))
+ return;
+ if (NULL == opte->opt_private || NULL == opte->opt_private->preauth_data)
+ return;
+
+ for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
+ if (opte->opt_private->preauth_data[i].attr != NULL)
+ free(opte->opt_private->preauth_data[i].attr);
+ if (opte->opt_private->preauth_data[i].value != NULL)
+ free(opte->opt_private->preauth_data[i].value);
+ }
+ free(opte->opt_private->preauth_data);
+ opte->opt_private->preauth_data = NULL;
+ opte->opt_private->num_preauth_data = 0;
+}
+
+static krb5_error_code
+add_gic_opt_ext_preauth_data(krb5_context context,
+ krb5_gic_opt_ext *opte,
+ const char *attr,
+ const char *value)
+{
+ size_t newsize;
+ int i;
+ krb5_gic_opt_pa_data *newpad;
+
+ newsize = opte->opt_private->num_preauth_data + 1;
+ newsize = newsize * sizeof(*opte->opt_private->preauth_data);
+ if (opte->opt_private->preauth_data == NULL)
+ newpad = malloc(newsize);
+ else
+ newpad = realloc(opte->opt_private->preauth_data, newsize);
+ if (newpad == NULL)
+ return ENOMEM;
+
+ i = opte->opt_private->num_preauth_data;
+ newpad[i].attr = strdup(attr);
+ if (newpad[i].attr == NULL)
+ return ENOMEM;
+ newpad[i].value = strdup(value);
+ if (newpad[i].value == NULL) {
+ free(newpad[i].attr);
+ return ENOMEM;
+ }
+ opte->opt_private->num_preauth_data += 1;
+ opte->opt_private->preauth_data = newpad;
+ return 0;
+}
+
+/*
+ * This function allows the caller to supply options to preauth
+ * plugins. Preauth plugin modules are given a chance to look
+ * at each option at the time this function is called in ordre
+ * to check the validity of the option.
+ * The 'opt' pointer supplied to this function must have been
+ * obtained using krb5_get_init_creds_opt_alloc()
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_opt_set_pa(krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ const char *attr,
+ const char *value)
+{
+ krb5_error_code retval;
+ krb5_gic_opt_ext *opte;
+
+ retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
+ "krb5_get_init_creds_opt_set_pa");
+ if (retval)
+ return retval;
+
+ /*
+ * Copy the option into the extended get_init_creds_opt structure
+ */
+ retval = add_gic_opt_ext_preauth_data(context, opte, attr, value);
+ if (retval)
+ return retval;
+
+ /*
+ * Give the plugins a chance to look at the option now.
+ */
+ retval = krb5_preauth_supply_preauth_data(context, opte, attr, value);
+ return retval;
+}
+
+/*
+ * This function allows a preauth plugin to obtain preauth
+ * options. The preauth_data returned from this function
+ * should be freed by calling krb5_get_init_creds_opt_free_pa().
+ *
+ * The 'opt' pointer supplied to this function must have been
+ * obtained using krb5_get_init_creds_opt_alloc()
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_get_init_creds_opt_get_pa(krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ int *num_preauth_data,
+ krb5_gic_opt_pa_data **preauth_data)
+{
+ krb5_error_code retval;
+ krb5_gic_opt_ext *opte;
+ krb5_gic_opt_pa_data *p = NULL;
+ int i;
+ size_t allocsize;
+
+ retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
+ "krb5_get_init_creds_opt_get_pa");
+ if (retval)
+ return retval;
+
+ if (num_preauth_data == NULL || preauth_data == NULL)
+ return EINVAL;
+
+ *num_preauth_data = 0;
+ *preauth_data = NULL;
+
+ if (opte->opt_private->num_preauth_data == 0)
+ return 0;
+
+ allocsize =
+ opte->opt_private->num_preauth_data * sizeof(krb5_gic_opt_pa_data);
+ p = malloc(allocsize);
+ if (p == NULL)
+ return ENOMEM;
+
+ /* Init these to make cleanup easier */
+ for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
+ p[i].attr = NULL;
+ p[i].value = NULL;
+ }
+
+ for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
+ p[i].attr = strdup(opte->opt_private->preauth_data[i].attr);
+ p[i].value = strdup(opte->opt_private->preauth_data[i].value);
+ if (p[i].attr == NULL || p[i].value == NULL)
+ goto cleanup;
+ }
+ *num_preauth_data = i;
+ *preauth_data = p;
+ return 0;
+cleanup:
+ for (i = 0; i < opte->opt_private->num_preauth_data; i++) {
+ if (p[i].attr != NULL)
+ free(p[i].attr);
+ if (p[i].value != NULL)
+ free(p[i].value);
+ }
+ free(p);
+ return ENOMEM;
+}
+
+/*
+ * This function frees the preauth_data that was returned by
+ * krb5_get_init_creds_opt_get_pa().
+ */
+void KRB5_CALLCONV
+krb5_get_init_creds_opt_free_pa(krb5_context context,
+ int num_preauth_data,
+ krb5_gic_opt_pa_data *preauth_data)
+{
+ int i;
+
+ if (num_preauth_data <= 0 || preauth_data == NULL)
+ return;
+
+ for (i = 0; i < num_preauth_data; i++) {
+ if (preauth_data[i].attr != NULL)
+ free(preauth_data[i].attr);
+ if (preauth_data[i].value != NULL)
+ free(preauth_data[i].value);
+ }
+ free(preauth_data);
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_pwd.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_pwd.c
index 2df0f4e512..1deca3028e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_pwd.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/gic_pwd.c
@@ -1,16 +1,11 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-/*
- * Gets initial credentials upon authentication
- */
-
-#include <k5-int.h>
-#include <com_err.h>
+#include "k5-int.h"
+#include "com_err.h"
#include <admin.h>
#include <locale.h>
#include <syslog.h>
@@ -46,15 +41,15 @@ krb5_error_code __krb5_get_init_creds_password(krb5_context,
static krb5_error_code
krb5_get_as_key_password(
- krb5_context context,
- krb5_principal client,
- krb5_enctype etype,
- krb5_prompter_fct prompter,
- void *prompter_data,
- krb5_data *salt,
- krb5_data *params,
- krb5_keyblock *as_key,
- void *gak_data)
+ krb5_context context,
+ krb5_principal client,
+ krb5_enctype etype,
+ krb5_prompter_fct prompter,
+ void *prompter_data,
+ krb5_data *salt,
+ krb5_data *params,
+ krb5_keyblock *as_key,
+ void *gak_data)
{
krb5_data *password;
krb5_error_code ret;
@@ -83,10 +78,10 @@ krb5_get_as_key_password(
if (password->data[0] == '\0') {
if (prompter == NULL)
- prompter = krb5_prompter_posix;
+ prompter = krb5_prompter_posix; /* Solaris Kerberos */
if ((ret = krb5_unparse_name(context, client, &clientstr)))
- return(ret);
+ return(ret);
strcpy(promptstr, "Password for ");
strncat(promptstr, clientstr, sizeof(promptstr)-strlen(promptstr)-1);
@@ -109,8 +104,7 @@ krb5_get_as_key_password(
krb5int_set_prompt_types(context, 0);
}
- if ((salt->length == -1 || salt->length == SALT_TYPE_AFS_LENGTH) &&
- (salt->data == NULL)) {
+ if ((salt->length == -1 || salt->length == SALT_TYPE_AFS_LENGTH) && (salt->data == NULL)) {
if ((ret = krb5_principal2salt(context, client, &defsalt)))
return(ret);
@@ -120,7 +114,7 @@ krb5_get_as_key_password(
}
ret = krb5_c_string_to_key_with_params(context, etype, password, salt,
- params->data?params:NULL, as_key);
+ params->data?params:NULL, as_key);
if (defsalt.length)
krb5_xfree(defsalt.data);
@@ -129,16 +123,15 @@ krb5_get_as_key_password(
}
krb5_error_code KRB5_CALLCONV
-krb5_get_init_creds_password(
- krb5_context context,
- krb5_creds *creds,
- krb5_principal client,
- char *password,
- krb5_prompter_fct prompter,
- void *data,
- krb5_deltat start_time,
- char *in_tkt_service,
- krb5_get_init_creds_opt *options)
+krb5_get_init_creds_password(krb5_context context,
+ krb5_creds *creds,
+ krb5_principal client,
+ char *password,
+ krb5_prompter_fct prompter,
+ void *data,
+ krb5_deltat start_time,
+ char *in_tkt_service,
+ krb5_get_init_creds_opt *options)
{
/*
* Solaris Kerberos:
@@ -176,11 +169,13 @@ __krb5_get_init_creds_password(
krb5_kdc_rep *as_reply;
int tries;
krb5_creds chpw_creds;
- krb5_get_init_creds_opt chpw_opts;
+ krb5_get_init_creds_opt *chpw_opts = NULL;
krb5_data pw0, pw1;
char banner[1024], pw0array[1024], pw1array[1024];
krb5_prompt prompt[2];
krb5_prompt_type prompt_types[sizeof(prompt)/sizeof(prompt[0])];
+ krb5_gic_opt_ext *opte = NULL;
+ krb5_gic_opt_ext *chpw_opte = NULL;
char admin_realm[1024], *cpw_service=NULL, *princ_str=NULL;
kadm5_config_params params;
@@ -192,7 +187,7 @@ __krb5_get_init_creds_password(
pw0.data = pw0array;
- if (password) {
+ if (password && password[0]) {
if ((pw0.length = strlen(password)) > sizeof(pw0array)) {
ret = EINVAL;
goto cleanup;
@@ -207,10 +202,15 @@ __krb5_get_init_creds_password(
pw1.data[0] = '\0';
pw1.length = sizeof(pw1array);
+ ret = krb5int_gic_opt_to_opte(context, options, &opte, 1,
+ "krb5_get_init_creds_password");
+ if (ret)
+ goto cleanup;
+
/* first try: get the requested tkt from any kdc */
ret = krb5_get_init_creds(context, creds, client, prompter, data,
- start_time, in_tkt_service, options,
+ start_time, in_tkt_service, opte,
krb5_get_as_key_password, (void *) &pw0,
&use_master, &as_reply);
@@ -235,35 +235,35 @@ __krb5_get_init_creds_password(
use_master = 1;
if (as_reply) {
- krb5_free_kdc_rep( context, as_reply);
- as_reply = NULL;
+ krb5_free_kdc_rep( context, as_reply);
+ as_reply = NULL;
}
-
ret2 = krb5_get_init_creds(context, creds, client, prompter, data,
- start_time, in_tkt_service, options,
+ start_time, in_tkt_service, opte,
krb5_get_as_key_password, (void *) &pw0,
&use_master, &as_reply);
-
+
if (ret2 == 0) {
ret = 0;
goto cleanup;
}
/* if the master is unreachable, return the error from the
- slave we were able to contact */
-
- if ((ret2 == KRB5_KDC_UNREACH) ||
- (ret2 == KRB5_REALM_CANT_RESOLVE) ||
- (ret2 == KRB5_REALM_UNKNOWN))
- goto cleanup;
-
- ret = ret2;
+ slave we were able to contact or reset the use_master flag */
+
+ if ((ret2 != KRB5_KDC_UNREACH) &&
+ (ret2 != KRB5_REALM_CANT_RESOLVE) &&
+ (ret2 != KRB5_REALM_UNKNOWN))
+ ret = ret2;
+ else
+ use_master = 0;
}
-#ifdef USE_LOGIN_LIBRARY
+/* Solaris Kerberos: 163 resync */
+/* #ifdef USE_LOGIN_LIBRARY */
if (ret == KRB5KDC_ERR_KEY_EXP)
- goto cleanup; /* Login library will deal appropriately with this error */
-#endif
+ goto cleanup; /* Login library will deal appropriately with this error */
+/* #endif */
/* at this point, we have an error from the master. if the error
is not password expired, or if it is but there's no prompter,
@@ -273,12 +273,20 @@ __krb5_get_init_creds_password(
(prompter == NULL))
goto cleanup;
- /* ok, we have an expired password. Give the user a few chances
+ /* historically the default has been to prompt for password change.
+ * if the change password prompt option has not been set, we continue
+ * to prompt. Prompting is only disabled if the option has been set
+ * and the value has been set to false.
+ */
+ if (!(options->flags & KRB5_GET_INIT_CREDS_OPT_CHG_PWD_PRMPT))
+ goto cleanup;
+
+ /* ok, we have an expired password. Give the user a few chances
to change it */
- /* Solaris Kerberos:
- *
+ /*
+ * Solaris Kerberos:
* Get the correct change password service principal name to use.
* This is necessary because SEAM based admin servers require
* a slightly different service principal name than MIT/MS servers.
@@ -324,7 +332,7 @@ __krb5_get_init_creds_password(
prompt[1].reply = &pw1;
prompt_types[1] = KRB5_PROMPT_TYPE_NEW_PASSWORD_AGAIN;
- strcpy(banner, "Password expired. You must change it now.");
+ strcpy(banner, "Password expired. You must change it now.");
for (tries = 3; tries; tries--) {
pw0.length = sizeof(pw0array);
@@ -333,7 +341,7 @@ __krb5_get_init_creds_password(
/* PROMPTER_INVOCATION */
krb5int_set_prompt_types(context, prompt_types);
if ((ret = ((*prompter)(context, data, 0, banner,
- sizeof(prompt)/sizeof(prompt[0]), prompt))))
+ sizeof(prompt)/sizeof(prompt[0]), prompt))))
goto cleanup;
krb5int_set_prompt_types(context, 0);
@@ -346,16 +354,18 @@ __krb5_get_init_creds_password(
sprintf(banner, "%s. Please try again.", error_message(ret));
} else {
int result_code;
+ krb5_data code_string;
+ krb5_data result_string;
- result_code = kadm5_chpass_principal_util(server_handle, client,
- pw0.data,
- NULL /* don't need pw back */,
- banner,
- sizeof(banner));
+ if ((ret = krb5_change_password(context, &chpw_creds, pw0array,
+ &result_code, &code_string,
+ &result_string)))
+ goto cleanup;
/* the change succeeded. go on */
if (result_code == 0) {
+ krb5_xfree(result_string.data);
break;
}
@@ -364,8 +374,26 @@ __krb5_get_init_creds_password(
ret = KRB5_CHPW_FAIL;
if (result_code != KRB5_KPASSWD_SOFTERROR) {
+ krb5_xfree(result_string.data);
goto cleanup;
}
+
+ /* the error was soft, so try again */
+
+ /* 100 is I happen to know that no code_string will be longer
+ than 100 chars */
+
+ if (result_string.length > (sizeof(banner)-100))
+ result_string.length = sizeof(banner)-100;
+
+ sprintf(banner, "%.*s%s%.*s. Please try again.\n",
+ (int) code_string.length, code_string.data,
+ result_string.length ? ": " : "",
+ (int) result_string.length,
+ result_string.data ? result_string.data : "");
+
+ krb5_xfree(code_string.data);
+ krb5_xfree(result_string.data);
}
}
@@ -377,7 +405,7 @@ __krb5_get_init_creds_password(
is final. */
ret = krb5_get_init_creds(context, creds, client, prompter, data,
- start_time, in_tkt_service, options,
+ start_time, in_tkt_service, opte,
krb5_get_as_key_password, (void *) &pw0,
&use_master, &as_reply);
@@ -415,45 +443,46 @@ cleanup:
/* ignore an error here */
/* PROMPTER_INVOCATION */
(*prompter)(context, data, 0, banner, 0, 0);
- } else if (prompter &&
- (!in_tkt_service ||
- (strcmp(in_tkt_service, "kadmin/changepw") != 0)) &&
- as_reply->enc_part2 && as_reply->enc_part2->last_req) {
- /*
- * Check the last_req fields
- */
-
- for (last_req = as_reply->enc_part2->last_req; *last_req; last_req++)
- if ((*last_req)->lr_type == KRB5_LRQ_ALL_PW_EXPTIME ||
- (*last_req)->lr_type == KRB5_LRQ_ONE_PW_EXPTIME) {
- krb5_deltat delta;
- char ts[256];
-
- if ((ret = krb5_timeofday(context, &now)))
- break;
-
- if ((ret = krb5_timestamp_to_string((*last_req)->value,
- ts, sizeof(ts))))
- break;
- delta = (*last_req)->value - now;
-
- if (delta < 3600)
- sprintf(banner,
- "Warning: Your password will expire in less than one "
- "hour on %s", ts);
- else if (delta < 86400*2)
- sprintf(banner,
- "Warning: Your password will expire in %d hour%s on %s",
- delta / 3600, delta < 7200 ? "" : "s", ts);
- else
- sprintf(banner,
- "Warning: Your password will expire in %d days on %s",
- delta / 86400, ts);
- /* ignore an error here */
- /* PROMPTER_INVOCATION */
- (*prompter)(context, data, 0, banner, 0, 0);
- }
- } /* prompter && !in_tkt_service */
+ } else if (prompter &&
+ (!in_tkt_service ||
+ (strcmp(in_tkt_service, "kadmin/changepw") != 0)) &&
+ as_reply->enc_part2 && as_reply->enc_part2->last_req) {
+ /*
+ * Check the last_req fields
+ */
+
+ for (last_req = as_reply->enc_part2->last_req; *last_req; last_req++)
+ if ((*last_req)->lr_type == KRB5_LRQ_ALL_PW_EXPTIME ||
+ (*last_req)->lr_type == KRB5_LRQ_ONE_PW_EXPTIME) {
+ krb5_deltat delta;
+ char ts[256];
+
+ if ((ret = krb5_timeofday(context, &now)))
+ break;
+
+ if ((ret = krb5_timestamp_to_string((*last_req)->value,
+ ts, sizeof(ts))))
+ break;
+
+ delta = (*last_req)->value - now;
+
+ if (delta < 3600)
+ sprintf(banner,
+ "Warning: Your password will expire in less than one "
+ "hour on %s", ts);
+ else if (delta < 86400*2)
+ sprintf(banner,
+ "Warning: Your password will expire in %d hour%s on %s",
+ delta / 3600, delta < 7200 ? "" : "s", ts);
+ else
+ sprintf(banner,
+ "Warning: Your password will expire in %d days on %s",
+ delta / 86400, ts);
+ /* ignore an error here */
+ /* PROMPTER_INVOCATION */
+ (*prompter)(context, data, 0, banner, 0, 0);
+ }
+ }
}
free(cpw_service);
@@ -474,14 +503,15 @@ cleanup:
return(ret);
}
-
-void krb5int_populate_gic_opt (
- krb5_context context, krb5_get_init_creds_opt *opt,
+krb5_error_code krb5int_populate_gic_opt (
+ krb5_context context, krb5_gic_opt_ext **opte,
krb5_flags options, krb5_address * const *addrs, krb5_enctype *ktypes,
krb5_preauthtype *pre_auth_types, krb5_creds *creds)
{
int i;
krb5_int32 starttime;
+ krb5_get_init_creds_opt *opt;
+
krb5_get_init_creds_opt_init(opt);
if (addrs)
@@ -507,6 +537,8 @@ void krb5int_populate_gic_opt (
if (creds->times.starttime) starttime = creds->times.starttime;
krb5_get_init_creds_opt_set_tkt_life(opt, creds->times.endtime - starttime);
}
+ return krb5int_gic_opt_to_opte(context, opt, opte, 0,
+ "krb5int_populate_gic_opt");
}
/*
@@ -539,10 +571,10 @@ krb5_get_in_tkt_with_password(krb5_context context, krb5_flags options,
krb5_error_code retval;
krb5_data pw0;
char pw0array[1024];
- krb5_get_init_creds_opt opt;
char * server;
krb5_principal server_princ, client_princ;
int use_master = 0;
+ krb5_gic_opt_ext *opte = NULL;
pw0array[0] = '\0';
pw0.data = pw0array;
@@ -556,21 +588,26 @@ krb5_get_in_tkt_with_password(krb5_context context, krb5_flags options,
} else {
pw0.length = sizeof(pw0array);
}
- krb5int_populate_gic_opt(context, &opt,
- options, addrs, ktypes,
- pre_auth_types, creds);
- retval = krb5_unparse_name( context, creds->server, &server);
+ retval = krb5int_populate_gic_opt(context, &opte,
+ options, addrs, ktypes,
+ pre_auth_types, creds);
if (retval)
return (retval);
+ retval = krb5_unparse_name( context, creds->server, &server);
+ if (retval) {
+ return (retval);
+ krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
+ }
server_princ = creds->server;
client_princ = creds->client;
retval = krb5_get_init_creds (context,
creds, creds->client,
krb5_prompter_posix, NULL,
- 0, server, &opt,
+ 0, server, opte,
krb5_get_as_key_password, &pw0,
&use_master, ret_as_reply);
krb5_free_unparsed_name( context, server);
+ krb5_get_init_creds_opt_free(context, (krb5_get_init_creds_opt *)opte);
if (retval) {
return (retval);
}
@@ -585,4 +622,5 @@ krb5_get_in_tkt_with_password(krb5_context context, krb5_flags options,
if ((retval = krb5_cc_store_cred(context, ccache, creds)))
return (retval);
return retval;
-}
+ }
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/int-proto.h b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/int-proto.h
index e0f1ba1a8a..5c576c3fd6 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/int-proto.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/int-proto.h
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/int-proto.h
*
@@ -17,7 +16,10 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
@@ -46,5 +48,11 @@ krb5_error_code krb5_ser_checksum_init (krb5_context);
krb5_error_code krb5_ser_keyblock_init (krb5_context);
krb5_error_code krb5_ser_principal_init (krb5_context);
+krb5_error_code
+krb5_preauth_supply_preauth_data(krb5_context context,
+ krb5_gic_opt_ext *opte,
+ const char *attr,
+ const char *value);
+
#endif /* KRB5_INT_FUNC_PROTO__ */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/kdc_rep_dc.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/kdc_rep_dc.c
index 60104c0a65..42559b2f17 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/kdc_rep_dc.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/kdc_rep_dc.c
@@ -1,11 +1,4 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
* lib/krb5/krb/kdc_rep_dc.c
*
* Copyright 1990 by the Massachusetts Institute of Technology.
@@ -15,7 +8,7 @@
* 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
@@ -29,12 +22,12 @@
* 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.
- *
+ *
*
* krb5_kdc_rep_decrypt_proc()
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*
* Decrypt the encrypted portion of the KDC_REP message, using the key
@@ -64,11 +57,10 @@ krb5_kdc_rep_decrypt_proc(krb5_context context, const krb5_keyblock *key, krb5_c
return(ENOMEM);
}
- /*(void) (dec_rep->enc_part.enctype);*/
+ /*dec_rep->enc_part.enctype;*/
- retval = krb5_c_decrypt(context, key, usage, 0, &dec_rep->enc_part,
- &scratch);
- if (retval) {
+ if ((retval = krb5_c_decrypt(context, key, usage, 0, &dec_rep->enc_part,
+ &scratch))) {
free(scratch.data);
return(retval);
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/krb5_libinit.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/krb5_libinit.c
index 3b65992775..45658709e7 100755..100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/krb5_libinit.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/krb5_libinit.c
@@ -1,16 +1,15 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <assert.h>
#include "autoconf.h"
#include "com_err.h"
-#include "krb5.h"
-#if 0 /* SUNW14resync */
+#include "k5-int.h"
+#if 0 /* Solaris Kerberos */
#include "krb5_err.h"
#include "kv5m_err.h"
#include "asn1_err.h"
@@ -42,6 +41,10 @@ int krb5int_lib_init(void)
krb5int_set_error_info_callout_fn (error_message);
+#ifdef SHOW_INITFINI_FUNCS
+ printf("krb5int_lib_init\n");
+#endif
+
#if !USE_BUNDLE_ERROR_STRINGS
add_error_table(&et_krb5_error_table);
add_error_table(&et_kv5m_error_table);
@@ -62,6 +65,7 @@ int krb5int_lib_init(void)
err = k5_mutex_finish_init(&krb5int_us_time_mutex);
if (err)
return err;
+
return 0;
}
@@ -77,12 +81,22 @@ krb5_error_code krb5int_initialize_library (void)
void krb5int_lib_fini(void)
{
- if (!INITIALIZER_RAN(krb5int_lib_init) || PROGRAM_EXITING())
+ if (!INITIALIZER_RAN(krb5int_lib_init) || PROGRAM_EXITING()) {
+#ifdef SHOW_INITFINI_FUNCS
+ printf("krb5int_lib_fini: skipping\n");
+#endif
return;
+ }
+
+#ifdef SHOW_INITFINI_FUNCS
+ printf("krb5int_lib_fini\n");
+#endif
+
+ k5_mutex_destroy(&krb5int_us_time_mutex);
- krb5int_rc_terminate();
- krb5int_kt_finalize();
krb5int_cc_finalize();
+ krb5int_kt_finalize();
+ krb5int_rc_terminate();
#if defined(_WIN32) || defined(USE_CCAPI)
krb5_stdcc_shutdown();
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_cred.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_cred.c
index ad63f299a6..cfe825b1ea 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_cred.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_cred.c
@@ -1,22 +1,21 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* NAME
* cred.c
- *
+ *
* DESCRIPTION
* Provide an interface to assemble and disassemble krb5_cred
* structures.
*
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include "cleanup.h"
-#include <auth_con.h>
+#include "auth_con.h"
#include <stddef.h> /* NULL */
#include <stdlib.h> /* malloc */
@@ -61,7 +60,7 @@ encrypt_credencpart(krb5_context context, krb5_cred_enc_part *pcredpart, krb5_ke
pencdata->ciphertext.data = 0;
}
- memset(scratch->data, 0, scratch->length);
+ memset(scratch->data, 0, scratch->length);
krb5_free_data(context, scratch);
return retval;
@@ -94,7 +93,7 @@ krb5_mk_ncred_basic(krb5_context context, krb5_creds **ppcreds, krb5_int32 nppcr
if (credenc.ticket_info == NULL)
return ENOMEM;
memset(credenc.ticket_info, 0, size);
-
+
/*
* For each credential in the list, initialize a cred info
* structure and copy the ticket into the ticket list.
@@ -111,7 +110,7 @@ krb5_mk_ncred_basic(krb5_context context, krb5_creds **ppcreds, krb5_int32 nppcr
credenc.ticket_info[i]->times = ppcreds[i]->times;
credenc.ticket_info[i]->flags = ppcreds[i]->ticket_flags;
- if ((retval = decode_krb5_ticket(&ppcreds[i]->ticket,
+ if ((retval = decode_krb5_ticket(&ppcreds[i]->ticket,
&pcred->tickets[i])))
goto cleanup;
@@ -155,8 +154,8 @@ cleanup:
krb5_error_code KRB5_CALLCONV
krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, krb5_creds **ppcreds, krb5_data **ppdata, krb5_replay_data *outdata)
{
- krb5_address * premote_fulladdr = NULL;
- krb5_address * plocal_fulladdr = NULL;
+ krb5_address * premote_fulladdr = NULL;
+ krb5_address * plocal_fulladdr = NULL;
krb5_address remote_fulladdr;
krb5_address local_fulladdr;
krb5_error_code retval;
@@ -178,11 +177,11 @@ krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, krb5_creds *
*/
for (ncred = 0; ppcreds[ncred]; ncred++);
- if ((pcred = (krb5_cred *)malloc(sizeof(krb5_cred))) == NULL)
+ if ((pcred = (krb5_cred *)malloc(sizeof(krb5_cred))) == NULL)
return ENOMEM;
memset(pcred, 0, sizeof(krb5_cred));
- if ((pcred->tickets
+ if ((pcred->tickets
= (krb5_ticket **)malloc(sizeof(krb5_ticket *) * (ncred + 1))) == NULL) {
retval = ENOMEM;
free(pcred);
@@ -190,8 +189,8 @@ krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, krb5_creds *
memset(pcred->tickets, 0, sizeof(krb5_ticket *) * (ncred +1));
/* Get keyblock */
- if ((keyblock = auth_context->send_subkey) == NULL)
- keyblock = auth_context->keyblock;
+ if ((keyblock = auth_context->send_subkey) == NULL)
+ keyblock = auth_context->keyblock;
/* Get replay info */
if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
@@ -224,7 +223,7 @@ krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, krb5_creds *
if (auth_context->local_addr) {
if (auth_context->local_port) {
if ((retval = krb5_make_fulladdr(context, auth_context->local_addr,
- auth_context->local_port,
+ auth_context->local_port,
&local_fulladdr)))
goto error;
plocal_fulladdr = &local_fulladdr;
@@ -236,7 +235,7 @@ krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, krb5_creds *
if (auth_context->remote_addr) {
if (auth_context->remote_port) {
if ((retval = krb5_make_fulladdr(context,auth_context->remote_addr,
- auth_context->remote_port,
+ auth_context->remote_port,
&remote_fulladdr)))
goto error;
premote_fulladdr = &remote_fulladdr;
@@ -247,7 +246,7 @@ krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, krb5_creds *
/* Setup creds structure */
if ((retval = krb5_mk_ncred_basic(context, ppcreds, ncred, keyblock,
- &replaydata, plocal_fulladdr,
+ &replaydata, plocal_fulladdr,
premote_fulladdr, pcred))) {
goto error;
}
@@ -262,8 +261,7 @@ krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context, krb5_creds *
replay.server = ""; /* XXX */
replay.cusec = replaydata.usec;
replay.ctime = replaydata.timestamp;
- retval = krb5_rc_store(context, auth_context->rcache, &replay);
- if (retval) {
+ if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
/* should we really error out here? XXX */
krb5_xfree(replay.client);
goto error;
@@ -282,7 +280,7 @@ error:
krb5_free_cred(context, pcred);
if (retval) {
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
+ if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
|| (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
auth_context->local_seq_number--;
}
@@ -298,9 +296,9 @@ krb5_error_code KRB5_CALLCONV
krb5_mk_1cred(krb5_context context, krb5_auth_context auth_context, krb5_creds *pcreds, krb5_data **ppdata, krb5_replay_data *outdata)
{
krb5_error_code retval;
- krb5_creds **ppcreds;
+ krb5_creds **ppcreds;
- if ((ppcreds = (krb5_creds **)malloc(sizeof(*ppcreds) * 2)) == NULL) {
+ if ((ppcreds = (krb5_creds **)malloc(sizeof(*ppcreds) * 2)) == NULL) {
return ENOMEM;
}
@@ -309,7 +307,8 @@ krb5_mk_1cred(krb5_context context, krb5_auth_context auth_context, krb5_creds *
retval = krb5_mk_ncred(context, auth_context, ppcreds,
ppdata, outdata);
-
+
free(ppcreds);
return retval;
}
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_priv.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_priv.c
index 591e8c943f..7ba03d6135 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_priv.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_priv.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/mk_priv.c
@@ -15,7 +14,7 @@
* 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
@@ -29,26 +28,18 @@
* 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.
- *
+ *
*
* krb5_mk_priv()
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include "cleanup.h"
-#include <auth_con.h>
+#include "auth_con.h"
/*ARGSUSED*/
static krb5_error_code
-krb5_mk_priv_basic(
- krb5_context context,
- const krb5_data * userdata,
- const krb5_keyblock * keyblock,
- krb5_replay_data * replaydata,
- krb5_address * local_addr,
- krb5_address * remote_addr,
- krb5_pointer i_vector,
- krb5_data * outbuf)
+krb5_mk_priv_basic(krb5_context context, const krb5_data *userdata, const krb5_keyblock *keyblock, krb5_replay_data *replaydata, krb5_address *local_addr, krb5_address *remote_addr, krb5_pointer i_vector, krb5_data *outbuf)
{
krb5_error_code retval;
krb5_priv privmsg;
@@ -57,7 +48,7 @@ krb5_mk_priv_basic(
size_t blocksize, enclen;
privmsg.enc_part.kvno = 0; /* XXX allow user-set? */
- privmsg.enc_part.enctype = keyblock->enctype;
+ privmsg.enc_part.enctype = keyblock->enctype;
privmsg_enc_part.user_data = *userdata;
privmsg_enc_part.s_address = local_addr;
@@ -94,13 +85,13 @@ krb5_mk_priv_basic(
ivdata.data = i_vector;
}
- retval = krb5_c_encrypt(context, keyblock, KRB5_KEYUSAGE_KRB_PRIV_ENCPART,
- i_vector?&ivdata:0, scratch1, &privmsg.enc_part);
- if (retval)
+ if ((retval = krb5_c_encrypt(context, keyblock,
+ KRB5_KEYUSAGE_KRB_PRIV_ENCPART,
+ i_vector?&ivdata:0,
+ scratch1, &privmsg.enc_part)))
goto clean_encpart;
- retval = encode_krb5_priv(&privmsg, &scratch2);
- if (retval)
+ if ((retval = encode_krb5_priv(&privmsg, &scratch2)))
goto clean_encpart;
*outbuf = *scratch2;
@@ -108,27 +99,24 @@ krb5_mk_priv_basic(
retval = 0;
clean_encpart:
- memset(privmsg.enc_part.ciphertext.data, 0,
- privmsg.enc_part.ciphertext.length);
- free(privmsg.enc_part.ciphertext.data);
+ memset(privmsg.enc_part.ciphertext.data, 0,
+ privmsg.enc_part.ciphertext.length);
+ free(privmsg.enc_part.ciphertext.data);
privmsg.enc_part.ciphertext.length = 0;
privmsg.enc_part.ciphertext.data = 0;
clean_scratch:
memset(scratch1->data, 0, scratch1->length);
- krb5_free_data(context, scratch1);
+ krb5_free_data(context, scratch1);
return retval;
}
krb5_error_code KRB5_CALLCONV
-krb5_mk_priv(
- krb5_context context,
- krb5_auth_context auth_context,
- const krb5_data *userdata,
- krb5_data *outbuf,
- krb5_replay_data *outdata)
+krb5_mk_priv(krb5_context context, krb5_auth_context auth_context,
+ const krb5_data *userdata, krb5_data *outbuf,
+ krb5_replay_data *outdata)
{
krb5_error_code retval;
krb5_keyblock * keyblock;
@@ -170,7 +158,7 @@ krb5_mk_priv(
} else {
outdata->seq = replaydata.seq;
}
- }
+ }
{
krb5_address * premote_fulladdr = NULL;
@@ -182,7 +170,7 @@ krb5_mk_priv(
if (auth_context->local_addr) {
if (auth_context->local_port) {
if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
- auth_context->local_port,
+ auth_context->local_port,
&local_fulladdr))) {
CLEANUP_PUSH(local_fulladdr.contents, free);
plocal_fulladdr = &local_fulladdr;
@@ -197,7 +185,7 @@ krb5_mk_priv(
if (auth_context->remote_addr) {
if (auth_context->remote_port) {
if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
- auth_context->remote_port,
+ auth_context->remote_port,
&remote_fulladdr))){
CLEANUP_PUSH(remote_fulladdr.contents, free);
premote_fulladdr = &remote_fulladdr;
@@ -210,7 +198,7 @@ krb5_mk_priv(
}
}
- if ((retval = krb5_mk_priv_basic(context, userdata, keyblock, &replaydata,
+ if ((retval = krb5_mk_priv_basic(context, userdata, keyblock, &replaydata,
plocal_fulladdr, premote_fulladdr,
auth_context->i_vector, outbuf))) {
CLEANUP_DONE();
@@ -223,7 +211,7 @@ krb5_mk_priv(
if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
krb5_donot_replay replay;
- if ((retval = krb5_gen_replay_name(context, auth_context->local_addr,
+ if ((retval = krb5_gen_replay_name(context, auth_context->local_addr,
"_priv", &replay.client))) {
krb5_xfree(outbuf);
goto error;
@@ -232,8 +220,7 @@ krb5_mk_priv(
replay.server = ""; /* XXX */
replay.cusec = replaydata.usec;
replay.ctime = replaydata.timestamp;
- retval = krb5_rc_store(context, auth_context->rcache, &replay);
- if (retval) {
+ if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
/* should we really error out here? XXX */
krb5_xfree(replay.client);
goto error;
@@ -250,3 +237,4 @@ error:
return retval;
}
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_rep.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_rep.c
index 9f85f73066..393f634bb1 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_rep.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_rep.c
@@ -1,11 +1,4 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
* lib/krb5/krb/mk_rep.c
*
* Copyright 1990 by the Massachusetts Institute of Technology.
@@ -15,7 +8,7 @@
* 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
@@ -29,13 +22,13 @@
* 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.
- *
+ *
*
* krb5_mk_rep()
*/
-#include <k5-int.h>
-#include <auth_con.h>
+#include "k5-int.h"
+#include "auth_con.h"
/*
Formats a KRB_AP_REP message into outbuf.
@@ -64,43 +57,39 @@ krb5_mk_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *out
return(retval);
}
- repl.ctime = auth_context->authentp->ctime;
- repl.cusec = auth_context->authentp->cusec;
+ repl.ctime = auth_context->authentp->ctime;
+ repl.cusec = auth_context->authentp->cusec;
if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_USE_SUBKEY) {
retval = krb5int_generate_and_save_subkey (context, auth_context,
- auth_context->keyblock);
+ auth_context->keyblock);
if (retval)
- return retval;
+ return retval;
repl.subkey = auth_context->send_subkey;
} else
- repl.subkey = auth_context->authentp->subkey;
-
+ repl.subkey = auth_context->authentp->subkey;
repl.seq_number = auth_context->local_seq_number;
/* encode it before encrypting */
- retval = encode_krb5_ap_rep_enc_part(&repl, &scratch);
- if (retval)
+ if ((retval = encode_krb5_ap_rep_enc_part(&repl, &scratch)))
return retval;
- retval = krb5_encrypt_helper(context, auth_context->keyblock,
- KRB5_KEYUSAGE_AP_REP_ENCPART,
- scratch, &reply.enc_part);
- if (retval)
+ if ((retval = krb5_encrypt_helper(context, auth_context->keyblock,
+ KRB5_KEYUSAGE_AP_REP_ENCPART,
+ scratch, &reply.enc_part)))
goto cleanup_scratch;
- retval = encode_krb5_ap_rep(&reply, &toutbuf);
- if (!retval) {
+ if (!(retval = encode_krb5_ap_rep(&reply, &toutbuf))) {
*outbuf = *toutbuf;
krb5_xfree(toutbuf);
}
memset(reply.enc_part.ciphertext.data, 0, reply.enc_part.ciphertext.length);
- free(reply.enc_part.ciphertext.data);
- reply.enc_part.ciphertext.length = 0;
+ free(reply.enc_part.ciphertext.data);
+ reply.enc_part.ciphertext.length = 0;
reply.enc_part.ciphertext.data = 0;
cleanup_scratch:
- memset(scratch->data, 0, scratch->length);
+ memset(scratch->data, 0, scratch->length);
krb5_free_data(context, scratch);
return retval;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_req.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_req.c
index 50aa32e7e1..8c800adefa 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_req.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_req.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/mk_req.c
@@ -15,7 +14,7 @@
* 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
@@ -29,13 +28,13 @@
* 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.
- *
+ *
*
* krb5_mk_req() routine.
*/
-#include <k5-int.h>
-#include <auth_con.h>
+#include "k5-int.h"
+#include "auth_con.h"
/*
Formats a KRB_AP_REQ message into outbuf.
@@ -45,7 +44,7 @@
TGS request with default parameters is used in an attempt to obtain
such credentials, and they are stored in ccache.
- kdc_options specifies the options requested for the
+ kdc_options specifies the options requested for the
ap_req_options specifies the KRB_AP_REQ options desired.
checksum specifies the checksum to be used in the authenticator.
@@ -66,7 +65,7 @@ krb5_mk_req(krb5_context context, krb5_auth_context *auth_context,
krb5_creds * credsp;
krb5_creds creds;
- retval = krb5_sname_to_principal(context, hostname, service,
+ retval = krb5_sname_to_principal(context, hostname, service,
KRB5_NT_SRV_HST, &server);
if (retval)
return retval;
@@ -76,14 +75,16 @@ krb5_mk_req(krb5_context context, krb5_auth_context *auth_context,
if ((retval = krb5_copy_principal(context, server, &creds.server)))
goto cleanup_princ;
+ /* Solaris Kerberos */
if ((retval = krb5_cc_get_principal(context, ccache, &creds.client)) != 0)
goto cleanup_creds;
+ /* Solaris Kerberos */
if ((retval = krb5_get_credentials(context, 0,
ccache, &creds, &credsp)) != 0)
goto cleanup_creds;
- retval = krb5_mk_req_extended(context, auth_context, ap_req_options,
+ retval = krb5_mk_req_extended(context, auth_context, ap_req_options,
in_data, credsp, outbuf);
krb5_free_creds(context, credsp);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_req_ext.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_req_ext.c
index f09ae4843c..a83a1efcda 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_req_ext.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_req_ext.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/mk_req_ext.c
@@ -15,7 +14,7 @@
* 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
@@ -29,14 +28,14 @@
* 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.
- *
+ *
*
* krb5_mk_req_extended()
*/
-#include <k5-int.h>
-#include <auth_con.h>
+#include "k5-int.h"
+#include "auth_con.h"
/*
Formats a KRB_AP_REQ message into outbuf, with more complete options than
@@ -71,7 +70,7 @@
returns system errors
*/
-static krb5_error_code
+static krb5_error_code
krb5_generate_authenticator (krb5_context,
krb5_authenticator *, krb5_principal,
krb5_checksum *, krb5_keyblock *,
@@ -88,9 +87,9 @@ krb5int_generate_and_save_subkey (krb5_context context,
* we have /dev/random and PKCS#11 to handle Random Numbers.
*/
/* Provide some more fodder for random number code.
- This isn't strong cryptographically; the point here is not
- to guarantee randomness, but to make it less likely that multiple
- sessions could pick the same subkey. */
+ This isn't strong cryptographically; the point here is not
+ to guarantee randomness, but to make it less likely that multiple
+ sessions could pick the same subkey. */
struct {
krb5_int32 sec, usec;
} rnd_data;
@@ -103,6 +102,7 @@ krb5int_generate_and_save_subkey (krb5_context context,
#endif
krb5_error_code retval;
+ /* Solaris Kerberos */
if (auth_context->send_subkey != NULL) {
krb5_free_keyblock(context, auth_context->send_subkey);
auth_context->send_subkey = NULL;
@@ -111,6 +111,7 @@ krb5int_generate_and_save_subkey (krb5_context context,
if ((retval = krb5_generate_subkey(context, keyblock, &auth_context->send_subkey)))
return retval;
+ /* Solaris Kerberos */
if (auth_context->recv_subkey != NULL) {
krb5_free_keyblock(context, auth_context->recv_subkey);
auth_context->recv_subkey = NULL;
@@ -126,13 +127,9 @@ krb5int_generate_and_save_subkey (krb5_context context,
}
krb5_error_code KRB5_CALLCONV
-krb5_mk_req_extended(
- krb5_context context,
- krb5_auth_context * auth_context,
- const krb5_flags ap_req_options,
- krb5_data * in_data,
- krb5_creds * in_creds,
- krb5_data * outbuf)
+krb5_mk_req_extended(krb5_context context, krb5_auth_context *auth_context,
+ krb5_flags ap_req_options, krb5_data *in_data,
+ krb5_creds *in_creds, krb5_data *outbuf)
{
krb5_error_code retval;
krb5_checksum checksum;
@@ -146,16 +143,16 @@ krb5_mk_req_extended(
request.ap_options = ap_req_options & AP_OPTS_WIRE_MASK;
request.authenticator.ciphertext.data = 0;
request.ticket = 0;
-
- if (!in_creds->ticket.length)
+
+ if (!in_creds->ticket.length)
return(KRB5_NO_TKT_SUPPLIED);
/* we need a native ticket */
if ((retval = decode_krb5_ticket(&(in_creds)->ticket, &request.ticket)))
return(retval);
-
+
/* verify that the ticket is not expired */
- if ((retval = krb5_validate_times(context, &in_creds->times)))
+ if ((retval = krb5_validate_times(context, &in_creds->times)) != 0)
goto cleanup;
/* generate auth_context if needed */
@@ -165,19 +162,20 @@ krb5_mk_req_extended(
*auth_context = new_auth_context;
}
- /* set auth context keyblock */
if ((*auth_context)->keyblock != NULL) {
krb5_free_keyblock(context, (*auth_context)->keyblock);
(*auth_context)->keyblock = NULL;
}
- if ((retval = krb5_copy_keyblock(context, &in_creds->keyblock,
+
+ /* set auth context keyblock */
+ if ((retval = krb5_copy_keyblock(context, &in_creds->keyblock,
&((*auth_context)->keyblock))))
goto cleanup;
/* generate seq number if needed */
if ((((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE)
|| ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
- && ((*auth_context)->local_seq_number == 0))
+ && ((*auth_context)->local_seq_number == 0))
if ((retval = krb5_generate_seq_number(context, &in_creds->keyblock,
&(*auth_context)->local_seq_number)))
goto cleanup;
@@ -185,34 +183,35 @@ krb5_mk_req_extended(
/* generate subkey if needed */
if (!in_data &&(*auth_context)->checksum_func) {
- retval = (*auth_context)->checksum_func(context,
- *auth_context,
- (*auth_context)->checksum_func_data,
- &in_data);
+ retval = (*auth_context)->checksum_func( context,
+ *auth_context,
+ (*auth_context)->checksum_func_data,
+ &in_data);
if (retval)
- goto cleanup;
+ goto cleanup;
}
if ((ap_req_options & AP_OPTS_USE_SUBKEY)&&(!(*auth_context)->send_subkey)) {
retval = krb5int_generate_and_save_subkey (context, *auth_context,
- &in_creds->keyblock);
+ &in_creds->keyblock);
if (retval)
- goto cleanup;
+ goto cleanup;
}
+
if (in_data) {
- if ((*auth_context)->req_cksumtype == 0x8003) {
+
+ if ((*auth_context)->req_cksumtype == 0x8003) {
/* XXX Special hack for GSSAPI */
checksum.checksum_type = 0x8003;
checksum.length = in_data->length;
checksum.contents = (krb5_octet *) in_data->data;
} else {
- retval = krb5_c_make_checksum(context,
+ if ((retval = krb5_c_make_checksum(context,
(*auth_context)->req_cksumtype,
(*auth_context)->keyblock,
KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM,
- in_data, &checksum);
- if (retval)
+ in_data, &checksum)))
goto cleanup_cksum;
}
checksump = &checksum;
@@ -237,7 +236,7 @@ krb5_mk_req_extended(
if ((retval = encode_krb5_authenticator((*auth_context)->authentp,
&scratch)))
goto cleanup_cksum;
-
+
/* Null out these fields, to prevent pointer sharing problems;
* they were supplied by the caller
*/
@@ -246,19 +245,14 @@ krb5_mk_req_extended(
(*auth_context)->authentp->authorization_data = NULL;
/* call the encryption routine */
- retval = krb5_encrypt_helper(context, &in_creds->keyblock,
+ if ((retval = krb5_encrypt_helper(context, &in_creds->keyblock,
KRB5_KEYUSAGE_AP_REQ_AUTH,
- scratch, &request.authenticator);
- if (retval)
+ scratch, &request.authenticator)))
goto cleanup_cksum;
if ((retval = encode_krb5_ap_req(&request, &toutbuf)))
goto cleanup_cksum;
-#ifdef HAVE_C_STRUCTURE_ASSIGNMENT
*outbuf = *toutbuf;
-#else
- memcpy(outbuf, toutbuf, sizeof(krb5_data));
-#endif
krb5_xfree(toutbuf);
@@ -283,17 +277,10 @@ cleanup:
}
static krb5_error_code
-krb5_generate_authenticator(
- krb5_context context,
- krb5_authenticator *authent,
- krb5_principal client,
- krb5_checksum *cksum,
- krb5_keyblock *key,
- krb5_ui_4 seq_number,
- krb5_authdata **authorization)
+krb5_generate_authenticator(krb5_context context, krb5_authenticator *authent, krb5_principal client, krb5_checksum *cksum, krb5_keyblock *key, krb5_ui_4 seq_number, krb5_authdata **authorization)
{
krb5_error_code retval;
-
+
authent->client = client;
authent->checksum = cksum;
if (key) {
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_safe.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_safe.c
index 22b179ca50..7c2accf9af 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_safe.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/mk_safe.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/mk_safe.c
@@ -15,7 +14,7 @@
* 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
@@ -29,14 +28,14 @@
* 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.
- *
+ *
*
* krb5_mk_safe()
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include "cleanup.h"
-#include <auth_con.h>
+#include "auth_con.h"
#ifdef KRB5_DEBUG
#include <sys/types.h>
@@ -62,15 +61,10 @@
*/
/*ARGSUSED*/
static krb5_error_code
-krb5_mk_safe_basic(
- krb5_context context,
- const krb5_data * userdata,
- const krb5_keyblock * keyblock,
- krb5_replay_data * replaydata,
- const krb5_address * local_addr,
- const krb5_address * remote_addr,
- const krb5_cksumtype sumtype,
- krb5_data * outbuf)
+krb5_mk_safe_basic(krb5_context context, const krb5_data *userdata,
+ const krb5_keyblock *keyblock, krb5_replay_data *replaydata,
+ krb5_address *local_addr, krb5_address *remote_addr,
+ krb5_cksumtype sumtype, krb5_data *outbuf)
{
krb5_error_code retval;
krb5_safe safemsg;
@@ -78,12 +72,13 @@ krb5_mk_safe_basic(
krb5_checksum safe_checksum;
krb5_data *scratch1, *scratch2;
+ /* Solaris Kerberos */
KRB5_LOG0(KRB5_INFO, "krb5_mk_safe_basic() start");
if (!krb5_c_valid_cksumtype(sumtype))
return KRB5_PROG_SUMTYPE_NOSUPP;
- if (!krb5_c_is_coll_proof_cksum(sumtype) ||
- !krb5_c_is_keyed_cksum(sumtype))
+ if (!krb5_c_is_coll_proof_cksum(sumtype)
+ || !krb5_c_is_keyed_cksum(sumtype))
return KRB5KRB_AP_ERR_INAPP_CKSUM;
safemsg.user_data = *userdata;
@@ -95,10 +90,10 @@ krb5_mk_safe_basic(
safemsg.usec = replaydata->usec;
safemsg.seq_number = replaydata->seq;
- /*
+ /*
* To do the checksum stuff, we need to encode the message with a
* zero-length zero-type checksum, then checksum the encoding, then
- * re-encode with the checksum.
+ * re-encode with the checksum.
*/
safe_checksum.length = 0;
@@ -107,11 +102,13 @@ krb5_mk_safe_basic(
safemsg.checksum = &safe_checksum;
+ /* Solaris Kerberos */
if ((retval = encode_krb5_safe(&safemsg, &scratch1))){
KRB5_LOG(KRB5_ERR, "krb5_mk_safe_basic() end, error retval=%d", retval);
return retval;
}
+ /* Solaris Kerberos */
if ((retval = krb5_c_make_checksum(context, sumtype, keyblock,
KRB5_KEYUSAGE_KRB_SAFE_CKSUM,
scratch1, &safe_checksum)) != 0){
@@ -120,6 +117,8 @@ krb5_mk_safe_basic(
}
safemsg.checksum = &safe_checksum;
+
+ /* Solaris Kerberos */
if ((retval = encode_krb5_safe(&safemsg, &scratch2))) {
KRB5_LOG(KRB5_ERR, "krb5_mk_safe_basic() error retval=%d", retval);
goto cleanup_checksum;
@@ -131,25 +130,21 @@ krb5_mk_safe_basic(
cleanup_checksum:
krb5_xfree(safe_checksum.contents);
-cleanup_scratch:
- memset((char *)scratch1->data, 0, scratch1->length);
+ memset((char *)scratch1->data, 0, scratch1->length);
krb5_free_data(context, scratch1);
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_INFO, "krb5_mk_safe_basic() end, retval=%d", retval);
return retval;
}
krb5_error_code KRB5_CALLCONV
-krb5_mk_safe(
- krb5_context context,
- krb5_auth_context auth_context,
- const krb5_data *userdata,
- krb5_data *outbuf,
- krb5_replay_data *outdata)
+krb5_mk_safe(krb5_context context, krb5_auth_context auth_context, const krb5_data *userdata, krb5_data *outbuf, krb5_replay_data *outdata)
{
krb5_error_code retval;
krb5_keyblock * keyblock;
krb5_replay_data replaydata;
+ /* Solaris Kerberos */
KRB5_LOG0(KRB5_INFO, "krb5_mk_safe() start");
/* Clear replaydata block */
@@ -160,6 +155,7 @@ krb5_mk_safe(
keyblock = auth_context->keyblock;
/* Get replay info */
+ /* Solaris Kerberos */
if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
(auth_context->rcache == NULL)){
KRB5_LOG(KRB5_ERR, "krb5_mk_safe() end error retval=%d", KRB5_RC_REQUIRED);
@@ -170,6 +166,7 @@ krb5_mk_safe(
(auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
(outdata == NULL)){
/* Need a better error */
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_mk_safe() end error retval=%d", KRB5_RC_REQUIRED);
return KRB5_RC_REQUIRED;
}
@@ -178,6 +175,7 @@ krb5_mk_safe(
(auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) {
if ((retval = krb5_us_timeofday(context, &replaydata.timestamp,
&replaydata.usec))){
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_mk_safe() end error retval=%d", retval);
return retval;
}
@@ -192,7 +190,7 @@ krb5_mk_safe(
if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) {
outdata->seq = replaydata.seq;
}
- }
+ }
{
krb5_address * premote_fulladdr = NULL;
@@ -206,7 +204,7 @@ krb5_mk_safe(
if (auth_context->local_addr) {
if (auth_context->local_port) {
if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
- auth_context->local_port,
+ auth_context->local_port,
&local_fulladdr))){
CLEANUP_PUSH(local_fulladdr.contents, free);
plocal_fulladdr = &local_fulladdr;
@@ -222,7 +220,7 @@ krb5_mk_safe(
if (auth_context->remote_addr) {
if (auth_context->remote_port) {
if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
- auth_context->remote_port,
+ auth_context->remote_port,
&remote_fulladdr))){
CLEANUP_PUSH(remote_fulladdr.contents, free);
premote_fulladdr = &remote_fulladdr;
@@ -259,8 +257,7 @@ krb5_mk_safe(
sumtype = sumtypes[i];
krb5_free_cksumtypes (context, sumtypes);
}
-
- if ((retval = krb5_mk_safe_basic(context, userdata, keyblock, &replaydata,
+ if ((retval = krb5_mk_safe_basic(context, userdata, keyblock, &replaydata,
plocal_fulladdr, premote_fulladdr,
sumtype, outbuf))) {
CLEANUP_DONE();
@@ -273,7 +270,7 @@ krb5_mk_safe(
if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
krb5_donot_replay replay;
- if ((retval = krb5_gen_replay_name(context, auth_context->local_addr,
+ if ((retval = krb5_gen_replay_name(context, auth_context->local_addr,
"_safe", &replay.client))) {
krb5_xfree(outbuf);
goto error;
@@ -282,6 +279,7 @@ krb5_mk_safe(
replay.server = ""; /* XXX */
replay.cusec = replaydata.usec;
replay.ctime = replaydata.timestamp;
+ /* Solaris Kerberos */
if ((retval = krb5_rc_store(context, auth_context->rcache, &replay)) != 0) {
/* should we really error out here? XXX */
krb5_xfree(outbuf);
@@ -289,15 +287,17 @@ krb5_mk_safe(
}
krb5_xfree(replay.client);
}
-
+ /* Solaris Kerberos */
KRB5_LOG0(KRB5_INFO, "krb5_mk_safe() end");
return 0;
error:
if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
+ (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
auth_context->local_seq_number--;
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_mk_safe() end error retval=%d", retval);
return retval;
}
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/pr_to_salt.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/pr_to_salt.c
index b476817ff6..4aadba6cbb 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/pr_to_salt.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/pr_to_salt.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/pr_to_salt.c
*
@@ -28,7 +27,7 @@
* krb5_principal2salt()
*/
-#include <k5-int.h>
+#include "k5-int.h"
static krb5_error_code krb5_principal2salt_internal
(krb5_context, krb5_const_principal, krb5_data *ret, int);
@@ -40,7 +39,7 @@ static krb5_error_code krb5_principal2salt_internal
static krb5_error_code
krb5_principal2salt_internal(krb5_context context, register krb5_const_principal pr, krb5_data *ret, int use_realm)
{
- unsigned int size = 0, offset = 0;
+ unsigned int size = 0, offset=0;
krb5_int32 nelem;
register int i;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/preauth.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/preauth.c
new file mode 100644
index 0000000000..0e7c279e14
--- /dev/null
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/preauth.c
@@ -0,0 +1,581 @@
+/*
+ * Copyright 1995 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.
+ *
+ */
+
+/*
+ * This file contains routines for establishing, verifying, and any other
+ * necessary functions, for utilizing the pre-authentication field of the
+ * kerberos kdc request, with various hardware/software verification devices.
+ */
+
+#include "k5-int.h"
+#include <stdio.h>
+#include <time.h>
+
+static krb5_error_code obtain_enc_ts_padata
+ (krb5_context,
+ krb5_pa_data *,
+ krb5_etype_info,
+ krb5_keyblock *,
+ krb5_error_code ( * )(krb5_context,
+ const krb5_enctype,
+ krb5_data *,
+ krb5_const_pointer,
+ krb5_keyblock **),
+ krb5_const_pointer,
+ krb5_creds *,
+ krb5_kdc_req *,
+ krb5_pa_data **);
+
+static krb5_error_code process_pw_salt
+ (krb5_context,
+ krb5_pa_data *,
+ krb5_kdc_req *,
+ krb5_kdc_rep *,
+ krb5_error_code ( * )(krb5_context,
+ const krb5_enctype,
+ krb5_data *,
+ krb5_const_pointer,
+ krb5_keyblock **),
+ krb5_const_pointer,
+ krb5_error_code ( * )(krb5_context,
+ const krb5_keyblock *,
+ krb5_const_pointer,
+ krb5_kdc_rep * ),
+ krb5_keyblock **,
+ krb5_creds *,
+ krb5_int32 *,
+ krb5_int32 *);
+
+static krb5_error_code obtain_sam_padata
+ (krb5_context,
+ krb5_pa_data *,
+ krb5_etype_info,
+ krb5_keyblock *,
+ krb5_error_code ( * )(krb5_context,
+ const krb5_enctype,
+ krb5_data *,
+ krb5_const_pointer,
+ krb5_keyblock **),
+ krb5_const_pointer,
+ krb5_creds *,
+ krb5_kdc_req *,
+ krb5_pa_data **);
+
+static const krb5_preauth_ops preauth_systems[] = {
+ {
+ KV5M_PREAUTH_OPS,
+ KRB5_PADATA_ENC_TIMESTAMP,
+ 0,
+ obtain_enc_ts_padata,
+ 0,
+ },
+ {
+ KV5M_PREAUTH_OPS,
+ KRB5_PADATA_PW_SALT,
+ 0,
+ 0,
+ process_pw_salt,
+ },
+ {
+ KV5M_PREAUTH_OPS,
+ KRB5_PADATA_AFS3_SALT,
+ 0,
+ 0,
+ process_pw_salt,
+ },
+ {
+ KV5M_PREAUTH_OPS,
+ KRB5_PADATA_SAM_CHALLENGE,
+ 0,
+ obtain_sam_padata,
+ 0,
+ },
+ { KV5M_PREAUTH_OPS, -1 }
+};
+
+static krb5_error_code find_pa_system
+ (krb5_preauthtype type, const krb5_preauth_ops **Preauth_proc);
+
+/* some typedef's for the function args to make things look a bit cleaner */
+
+typedef krb5_error_code (*git_key_proc) (krb5_context,
+ const krb5_enctype,
+ krb5_data *,
+ krb5_const_pointer,
+ krb5_keyblock **);
+
+typedef krb5_error_code (*git_decrypt_proc) (krb5_context,
+ const krb5_keyblock *,
+ krb5_const_pointer,
+ krb5_kdc_rep *);
+
+krb5_error_code krb5_obtain_padata(krb5_context context, krb5_pa_data **preauth_to_use, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_creds *creds, krb5_kdc_req *request)
+{
+ krb5_error_code retval;
+ krb5_etype_info etype_info = 0;
+ krb5_pa_data ** pa;
+ krb5_pa_data ** send_pa_list;
+ krb5_pa_data ** send_pa;
+ const krb5_preauth_ops *ops;
+ krb5_keyblock * def_enc_key = 0;
+ krb5_enctype enctype;
+ krb5_data salt;
+ krb5_data scratch;
+ int size;
+ int f_salt = 0;
+
+ if (preauth_to_use == NULL)
+ return 0;
+
+ for (pa = preauth_to_use, size=0; *pa; pa++, size++) {
+ if ((*pa)->pa_type == KRB5_PADATA_ETYPE_INFO) {
+ /* XXX use the first one. Is there another way to disambiguate? */
+ if (etype_info)
+ continue;
+
+ scratch.length = (*pa)->length;
+ scratch.data = (char *) (*pa)->contents;
+ retval = decode_krb5_etype_info(&scratch, &etype_info);
+ if (retval)
+ return retval;
+ if (etype_info[0] == NULL) {
+ krb5_free_etype_info(context, etype_info);
+ etype_info = NULL;
+ }
+ }
+ }
+
+ if ((send_pa_list = malloc((size+1) * sizeof(krb5_pa_data *))) == NULL)
+ return ENOMEM;
+
+ send_pa = send_pa_list;
+ *send_pa = 0;
+
+ enctype = request->ktype[0];
+ salt.data = 0;
+ salt.length = SALT_TYPE_NO_LENGTH;
+ if (etype_info) {
+ enctype = etype_info[0]->etype;
+ salt.data = (char *) etype_info[0]->salt;
+ if(etype_info[0]->length == KRB5_ETYPE_NO_SALT)
+ salt.length = SALT_TYPE_NO_LENGTH; /* XXX */
+ else
+ salt.length = etype_info[0]->length;
+ }
+ if (salt.length == SALT_TYPE_NO_LENGTH) {
+ /*
+ * This will set the salt length
+ */
+ if ((retval = krb5_principal2salt(context, request->client, &salt)))
+ return(retval);
+ f_salt = 1;
+ }
+
+ if ((retval = (*key_proc)(context, enctype, &salt, key_seed,
+ &def_enc_key)))
+ goto cleanup;
+
+
+ for (pa = preauth_to_use; *pa; pa++) {
+ if (find_pa_system((*pa)->pa_type, &ops))
+ continue;
+
+ if (ops->obtain == 0)
+ continue;
+
+ retval = ((ops)->obtain)(context, *pa, etype_info, def_enc_key,
+ key_proc, key_seed, creds,
+ request, send_pa);
+ if (retval)
+ goto cleanup;
+
+ if (*send_pa)
+ send_pa++;
+ *send_pa = 0;
+ }
+
+ retval = 0;
+
+ if (send_pa_list[0]) {
+ request->padata = send_pa_list;
+ send_pa_list = 0;
+ }
+
+cleanup:
+ if (etype_info)
+ krb5_free_etype_info(context, etype_info);
+ if (f_salt)
+ krb5_xfree(salt.data);
+ if (send_pa_list)
+ krb5_free_pa_data(context, send_pa_list);
+ if (def_enc_key)
+ krb5_free_keyblock(context, def_enc_key);
+ return retval;
+
+}
+
+krb5_error_code
+krb5_process_padata(krb5_context context, krb5_kdc_req *request, krb5_kdc_rep *as_reply, git_key_proc key_proc, krb5_const_pointer keyseed, git_decrypt_proc decrypt_proc, krb5_keyblock **decrypt_key, krb5_creds *creds, krb5_int32 *do_more)
+{
+ krb5_error_code retval = 0;
+ const krb5_preauth_ops * ops;
+ krb5_pa_data ** pa;
+ krb5_int32 done = 0;
+
+ *do_more = 0; /* By default, we don't need to repeat... */
+ if (as_reply->padata == 0)
+ return 0;
+
+ for (pa = as_reply->padata; *pa; pa++) {
+ if (find_pa_system((*pa)->pa_type, &ops))
+ continue;
+
+ if (ops->process == 0)
+ continue;
+
+ retval = ((ops)->process)(context, *pa, request, as_reply,
+ key_proc, keyseed, decrypt_proc,
+ decrypt_key, creds, do_more, &done);
+ if (retval)
+ goto cleanup;
+ if (done)
+ break;
+ }
+
+cleanup:
+ return retval;
+}
+
+/*
+ * This routine is the "obtain" function for the ENC_TIMESTAMP
+ * preauthentication type. It take the current time and encrypts it
+ * in the user's key.
+ */
+static krb5_error_code
+obtain_enc_ts_padata(krb5_context context, krb5_pa_data *in_padata, krb5_etype_info etype_info, krb5_keyblock *def_enc_key, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_creds *creds, krb5_kdc_req *request, krb5_pa_data **out_padata)
+{
+ krb5_pa_enc_ts pa_enc;
+ krb5_error_code retval;
+ krb5_data * scratch;
+ krb5_enc_data enc_data;
+ krb5_pa_data * pa;
+
+ retval = krb5_us_timeofday(context, &pa_enc.patimestamp, &pa_enc.pausec);
+ if (retval)
+ return retval;
+
+ if ((retval = encode_krb5_pa_enc_ts(&pa_enc, &scratch)) != 0)
+ return retval;
+
+ enc_data.ciphertext.data = 0;
+
+ if ((retval = krb5_encrypt_helper(context, def_enc_key,
+ KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS,
+ scratch, &enc_data)))
+ goto cleanup;
+
+ krb5_free_data(context, scratch);
+ scratch = 0;
+
+ if ((retval = encode_krb5_enc_data(&enc_data, &scratch)) != 0)
+ goto cleanup;
+
+ if ((pa = malloc(sizeof(krb5_pa_data))) == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ pa->magic = KV5M_PA_DATA;
+ pa->pa_type = KRB5_PADATA_ENC_TIMESTAMP;
+ pa->length = scratch->length;
+ pa->contents = (krb5_octet *) scratch->data;
+
+ *out_padata = pa;
+
+ krb5_xfree(scratch);
+ scratch = 0;
+
+ retval = 0;
+
+cleanup:
+ if (scratch)
+ krb5_free_data(context, scratch);
+ if (enc_data.ciphertext.data)
+ krb5_xfree(enc_data.ciphertext.data);
+ return retval;
+}
+
+static krb5_error_code
+process_pw_salt(krb5_context context, krb5_pa_data *padata, krb5_kdc_req *request, krb5_kdc_rep *as_reply, git_key_proc key_proc, krb5_const_pointer keyseed, git_decrypt_proc decrypt_proc, krb5_keyblock **decrypt_key, krb5_creds *creds, krb5_int32 *do_more, krb5_int32 *done)
+{
+ krb5_error_code retval;
+ krb5_data salt;
+
+ if (*decrypt_key != 0)
+ return 0;
+
+ salt.data = (char *) padata->contents;
+ salt.length =
+ (padata->pa_type == KRB5_PADATA_AFS3_SALT)?(SALT_TYPE_AFS_LENGTH):(padata->length);
+
+ if ((retval = (*key_proc)(context, as_reply->enc_part.enctype,
+ &salt, keyseed, decrypt_key))) {
+ *decrypt_key = 0;
+ return retval;
+ }
+
+ return 0;
+}
+
+static krb5_error_code
+find_pa_system(krb5_preauthtype type, const krb5_preauth_ops **preauth)
+{
+ const krb5_preauth_ops *ap = preauth_systems;
+
+ while ((ap->type != -1) && (ap->type != type))
+ ap++;
+ if (ap->type == -1)
+ return(KRB5_PREAUTH_BAD_TYPE);
+ *preauth = ap;
+ return 0;
+}
+
+
+extern const char *krb5_default_pwd_prompt1;
+
+static krb5_error_code
+sam_get_pass_from_user(krb5_context context, krb5_etype_info etype_info, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_kdc_req *request, krb5_keyblock **new_enc_key, const char *prompt)
+{
+ krb5_enctype enctype;
+ krb5_error_code retval;
+ const char *oldprompt;
+
+ /* enctype = request->ktype[0]; */
+ enctype = ENCTYPE_DES_CBC_MD5;
+/* hack with this first! */
+ oldprompt = krb5_default_pwd_prompt1;
+ krb5_default_pwd_prompt1 = prompt;
+ {
+ krb5_data newpw;
+ newpw.data = 0; newpw.length = 0;
+ /* we don't keep the new password, just the key... */
+ retval = (*key_proc)(context, enctype, 0,
+ (krb5_const_pointer)&newpw, new_enc_key);
+ krb5_xfree(newpw.data);
+ }
+ krb5_default_pwd_prompt1 = oldprompt;
+ return retval;
+}
+static
+char *handle_sam_labels(krb5_sam_challenge *sc)
+{
+ char *label = sc->sam_challenge_label.data;
+ unsigned int label_len = sc->sam_challenge_label.length;
+ char *prompt = sc->sam_response_prompt.data;
+ unsigned int prompt_len = sc->sam_response_prompt.length;
+ char *challenge = sc->sam_challenge.data;
+ unsigned int challenge_len = sc->sam_challenge.length;
+ char *prompt1, *p;
+ char *sep1 = ": [";
+ char *sep2 = "]\n";
+ char *sep3 = ": ";
+
+ if (sc->sam_cksum.length == 0) {
+ /* or invalid -- but lets just handle presence now XXX */
+ switch (sc->sam_type) {
+ case PA_SAM_TYPE_ENIGMA: /* Enigma Logic */
+ label = "Challenge for Enigma Logic mechanism";
+ break;
+ case PA_SAM_TYPE_DIGI_PATH: /* Digital Pathways */
+ case PA_SAM_TYPE_DIGI_PATH_HEX: /* Digital Pathways */
+ label = "Challenge for Digital Pathways mechanism";
+ break;
+ case PA_SAM_TYPE_ACTIVCARD_DEC: /* Digital Pathways */
+ case PA_SAM_TYPE_ACTIVCARD_HEX: /* Digital Pathways */
+ label = "Challenge for Activcard mechanism";
+ break;
+ case PA_SAM_TYPE_SKEY_K0: /* S/key where KDC has key 0 */
+ label = "Challenge for Enhanced S/Key mechanism";
+ break;
+ case PA_SAM_TYPE_SKEY: /* Traditional S/Key */
+ label = "Challenge for Traditional S/Key mechanism";
+ break;
+ case PA_SAM_TYPE_SECURID: /* Security Dynamics */
+ label = "Challenge for Security Dynamics mechanism";
+ break;
+ case PA_SAM_TYPE_SECURID_PREDICT: /* predictive Security Dynamics */
+ label = "Challenge for Security Dynamics mechanism";
+ break;
+ }
+ prompt = "Passcode";
+ label_len = strlen(label);
+ prompt_len = strlen(prompt);
+ }
+
+ /* example:
+ Challenge for Digital Pathways mechanism: [134591]
+ Passcode:
+ */
+ p = prompt1 = malloc(label_len + strlen(sep1) +
+ challenge_len + strlen(sep2) +
+ prompt_len+ strlen(sep3) + 1);
+ if (p == NULL)
+ return NULL;
+ if (challenge_len) {
+ strncpy(p, label, label_len); p += label_len;
+ strcpy(p, sep1); p += strlen(sep1);
+ strncpy(p, challenge, challenge_len); p += challenge_len;
+ strcpy(p, sep2); p += strlen(sep2);
+ }
+ strncpy(p, prompt, prompt_len); p += prompt_len;
+ strcpy(p, sep3); /* p += strlen(sep3); */
+ return prompt1;
+}
+
+/*
+ * This routine is the "obtain" function for the SAM_CHALLENGE
+ * preauthentication type. It presents the challenge...
+ */
+static krb5_error_code
+obtain_sam_padata(krb5_context context, krb5_pa_data *in_padata, krb5_etype_info etype_info, krb5_keyblock *def_enc_key, git_key_proc key_proc, krb5_const_pointer key_seed, krb5_creds *creds, krb5_kdc_req *request, krb5_pa_data **out_padata)
+{
+ krb5_error_code retval;
+ krb5_data * scratch;
+ krb5_data tmpsam;
+ krb5_pa_data * pa;
+ krb5_sam_challenge *sam_challenge = 0;
+ krb5_sam_response sam_response;
+ /* these two get encrypted and stuffed in to sam_response */
+ krb5_enc_sam_response_enc enc_sam_response_enc;
+ krb5_keyblock * sam_use_key = 0;
+ char * prompt;
+
+ tmpsam.length = in_padata->length;
+ tmpsam.data = (char *) in_padata->contents;
+ retval = decode_krb5_sam_challenge(&tmpsam, &sam_challenge);
+ if (retval)
+ return retval;
+
+ if (sam_challenge->sam_flags & KRB5_SAM_MUST_PK_ENCRYPT_SAD) {
+ return KRB5_SAM_UNSUPPORTED;
+ }
+
+ enc_sam_response_enc.sam_nonce = sam_challenge->sam_nonce;
+ if (!sam_challenge->sam_nonce) {
+ retval = krb5_us_timeofday(context,
+ &enc_sam_response_enc.sam_timestamp,
+ &enc_sam_response_enc.sam_usec);
+ sam_response.sam_patimestamp = enc_sam_response_enc.sam_timestamp;
+ }
+ if (retval)
+ return retval;
+ if (sam_challenge->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) {
+ /* encrypt passcode in key by stuffing it here */
+ unsigned int pcsize = 256;
+ char *passcode = malloc(pcsize+1);
+ if (passcode == NULL)
+ return ENOMEM;
+ prompt = handle_sam_labels(sam_challenge);
+ if (prompt == NULL) {
+ free(passcode);
+ return ENOMEM;
+ }
+ retval = krb5_read_password(context, prompt, 0, passcode, &pcsize);
+ free(prompt);
+
+ if (retval) {
+ free(passcode);
+ return retval;
+ }
+ enc_sam_response_enc.sam_sad.data = passcode;
+ enc_sam_response_enc.sam_sad.length = pcsize;
+ } else if (sam_challenge->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) {
+ prompt = handle_sam_labels(sam_challenge);
+ if (prompt == NULL)
+ return ENOMEM;
+ retval = sam_get_pass_from_user(context, etype_info, key_proc,
+ key_seed, request, &sam_use_key,
+ prompt);
+ free(prompt);
+ if (retval)
+ return retval;
+ enc_sam_response_enc.sam_sad.length = 0;
+ } else {
+ /* what *was* it? */
+ return KRB5_SAM_UNSUPPORTED;
+ }
+
+ /* so at this point, either sam_use_key is generated from the passcode
+ * or enc_sam_response_enc.sam_sad is set to it, and we use
+ * def_enc_key instead. */
+ /* encode the encoded part of the response */
+ if ((retval = encode_krb5_enc_sam_response_enc(&enc_sam_response_enc,
+ &scratch)) != 0)
+ return retval;
+
+ if ((retval = krb5_encrypt_data(context,
+ sam_use_key?sam_use_key:def_enc_key,
+ 0, scratch,
+ &sam_response.sam_enc_nonce_or_ts)))
+ goto cleanup;
+
+ krb5_free_data(context, scratch);
+ scratch = 0;
+
+ /* sam_enc_key is reserved for future use */
+ sam_response.sam_enc_key.ciphertext.length = 0;
+
+ /* copy things from the challenge */
+ sam_response.sam_nonce = sam_challenge->sam_nonce;
+ sam_response.sam_flags = sam_challenge->sam_flags;
+ sam_response.sam_track_id = sam_challenge->sam_track_id;
+ sam_response.sam_type = sam_challenge->sam_type;
+ sam_response.magic = KV5M_SAM_RESPONSE;
+
+ if ((retval = encode_krb5_sam_response(&sam_response, &scratch)) != 0)
+ return retval;
+
+ if ((pa = malloc(sizeof(krb5_pa_data))) == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ pa->magic = KV5M_PA_DATA;
+ pa->pa_type = KRB5_PADATA_SAM_RESPONSE;
+ pa->length = scratch->length;
+ pa->contents = (krb5_octet *) scratch->data;
+ scratch = 0; /* so we don't free it! */
+
+ *out_padata = pa;
+
+ retval = 0;
+
+cleanup:
+ if (scratch)
+ krb5_free_data(context, scratch);
+ if (sam_challenge)
+ krb5_xfree(sam_challenge);
+ return retval;
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/preauth2.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/preauth2.c
index f1e2794d44..033ae15cc5 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/preauth2.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/preauth2.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright 1995, 2003 by the Massachusetts Institute of Technology. All
@@ -36,14 +35,27 @@
* kerberos kdc request, with various hardware/software verification devices.
*/
-#include <k5-int.h>
+#include "k5-int.h"
+#include "osconf.h"
+#include <preauth_plugin.h>
+#include "int-proto.h"
+
+#if !defined(_WIN32)
+#include <unistd.h>
+#endif
+
+#if TARGET_OS_MAC
+static const char *objdirs[] = { KRB5_PLUGIN_BUNDLE_DIR, LIBDIR "/krb5/plugins/preauth", NULL }; /* should be a list */
+#else
+/* Solaris Kerberos */
+static const char *objdirs[] = { LIBDIR "/krb5/plugins/preauth", NULL };
+#endif
typedef krb5_error_code (*pa_function)(krb5_context,
krb5_kdc_req *request,
krb5_pa_data *in_padata,
krb5_pa_data **out_padata,
- krb5_data *salt,
- krb5_data *s2kparams,
+ krb5_data *salt, krb5_data *s2kparams,
krb5_enctype *etype,
krb5_keyblock *as_key,
krb5_prompter_fct prompter_fct,
@@ -57,17 +69,528 @@ typedef struct _pa_types_t {
int flags;
} pa_types_t;
-#define PA_REAL 0x0001
-#define PA_INFO 0x0002
+/* Create the per-krb5_context context. This means loading the modules
+ * if we haven't done that yet (applications which never obtain initial
+ * credentials should never hit this routine), breaking up the module's
+ * list of support pa_types so that we can iterate over the modules more
+ * easily, and copying over the relevant parts of the module's table. */
+void KRB5_CALLCONV
+krb5_init_preauth_context(krb5_context kcontext)
+{
+ int n_modules, n_tables, i, j, k;
+ void **tables;
+ struct krb5plugin_preauth_client_ftable_v1 *table;
+ krb5_preauth_context *context = NULL;
+ void *plugin_context;
+ krb5_preauthtype pa_type;
+ void **rcpp;
+
+ /* Only do this once for each krb5_context */
+ if (kcontext->preauth_context != NULL)
+ return;
+
+ /* load the plugins for the current context */
+ if (PLUGIN_DIR_OPEN(&kcontext->preauth_plugins) == 0) {
+ if (krb5int_open_plugin_dirs(objdirs, NULL,
+ &kcontext->preauth_plugins,
+ &kcontext->err) != 0) {
+ return;
+ }
+ }
+
+ /* pull out the module function tables for all of the modules */
+ tables = NULL;
+ if (krb5int_get_plugin_dir_data(&kcontext->preauth_plugins,
+ "preauthentication_client_1",
+ &tables,
+ &kcontext->err) != 0) {
+ return;
+ }
+ if (tables == NULL) {
+ return;
+ }
+
+ /* count how many modules we ended up loading, and how many preauth
+ * types we may claim to support as a result */
+ n_modules = 0;
+ for (n_tables = 0;
+ (tables != NULL) && (tables[n_tables] != NULL);
+ n_tables++) {
+ table = tables[n_tables];
+ if ((table->pa_type_list != NULL) && (table->process != NULL)) {
+ for (j = 0; table->pa_type_list[j] > 0; j++) {
+ n_modules++;
+ }
+ }
+ }
+
+ /* allocate the space we need */
+ context = malloc(sizeof(*context));
+ if (context == NULL) {
+ krb5int_free_plugin_dir_data(tables);
+ return;
+ }
+ context->modules = malloc(sizeof(context->modules[0]) * n_modules);
+ if (context->modules == NULL) {
+ krb5int_free_plugin_dir_data(tables);
+ free(context);
+ return;
+ }
+ memset(context->modules, 0, sizeof(context->modules[0]) * n_modules);
+ context->n_modules = n_modules;
+
+ /* fill in the structure */
+ k = 0;
+ for (i = 0; i < n_tables; i++) {
+ table = tables[i];
+ if ((table->pa_type_list != NULL) && (table->process != NULL)) {
+ plugin_context = NULL;
+ if ((table->init != NULL) &&
+ ((*table->init)(kcontext, &plugin_context) != 0)) {
+#ifdef DEBUG
+ fprintf (stderr, "init err, skipping module \"%s\"\n",
+ table->name);
+#endif
+ continue;
+ }
+
+ rcpp = NULL;
+ for (j = 0; table->pa_type_list[j] > 0; j++) {
+ pa_type = table->pa_type_list[j];
+ context->modules[k].pa_type = pa_type;
+ context->modules[k].enctypes = table->enctype_list;
+ context->modules[k].plugin_context = plugin_context;
+ /* Only call client_fini once per plugin */
+ if (j == 0)
+ context->modules[k].client_fini = table->fini;
+ else
+ context->modules[k].client_fini = NULL;
+ context->modules[k].ftable = table;
+ context->modules[k].name = table->name;
+ context->modules[k].flags = (*table->flags)(kcontext, pa_type);
+ context->modules[k].use_count = 0;
+ context->modules[k].client_process = table->process;
+ context->modules[k].client_tryagain = table->tryagain;
+ if (j == 0)
+ context->modules[k].client_supply_gic_opts = table->gic_opts;
+ else
+ context->modules[k].client_supply_gic_opts = NULL;
+ context->modules[k].request_context = NULL;
+ /*
+ * Only call request_init and request_fini once per plugin.
+ * Only the first module within each plugin will ever
+ * have request_context filled in. Every module within
+ * the plugin will have its request_context_pp pointing
+ * to that entry's request_context. That way all the
+ * modules within the plugin share the same request_context
+ */
+ if (j == 0) {
+ context->modules[k].client_req_init = table->request_init;
+ context->modules[k].client_req_fini = table->request_fini;
+ rcpp = &context->modules[k].request_context;
+ } else {
+ context->modules[k].client_req_init = NULL;
+ context->modules[k].client_req_fini = NULL;
+ }
+ context->modules[k].request_context_pp = rcpp;
+#ifdef DEBUG
+ fprintf (stderr, "init module \"%s\", pa_type %d, flag %d\n",
+ context->modules[k].name,
+ context->modules[k].pa_type,
+ context->modules[k].flags);
+#endif
+ k++;
+ }
+ }
+ }
+ krb5int_free_plugin_dir_data(tables);
+
+ /* return the result */
+ kcontext->preauth_context = context;
+}
+
+/* Zero the use counts for the modules herein. Usually used before we
+ * start processing any data from the server, at which point every module
+ * will again be able to take a crack at whatever the server sent. */
+void KRB5_CALLCONV
+krb5_clear_preauth_context_use_counts(krb5_context context)
+{
+ int i;
+ if (context->preauth_context != NULL) {
+ for (i = 0; i < context->preauth_context->n_modules; i++) {
+ context->preauth_context->modules[i].use_count = 0;
+ }
+ }
+}
+
+/*
+ * Give all the preauth plugins a look at the preauth option which
+ * has just been set
+ */
+krb5_error_code
+krb5_preauth_supply_preauth_data(krb5_context context,
+ krb5_gic_opt_ext *opte,
+ const char *attr,
+ const char *value)
+{
+ krb5_error_code retval;
+ int i;
+ void *pctx;
+ const char *emsg = NULL;
+
+ if (context->preauth_context == NULL)
+ krb5_init_preauth_context(context);
+ if (context->preauth_context == NULL) {
+ retval = EINVAL;
+ krb5int_set_error(&context->err, retval,
+ "krb5_preauth_supply_preauth_data: "
+ "Unable to initialize preauth context");
+ return retval;
+ }
+
+ /*
+ * Go down the list of preauth modules, and supply them with the
+ * attribute/value pair.
+ */
+ for (i = 0; i < context->preauth_context->n_modules; i++) {
+ if (context->preauth_context->modules[i].client_supply_gic_opts == NULL)
+ continue;
+ pctx = context->preauth_context->modules[i].plugin_context;
+ retval = (*context->preauth_context->modules[i].client_supply_gic_opts)
+ (context, pctx,
+ (krb5_get_init_creds_opt *)opte, attr, value);
+ if (retval) {
+ emsg = krb5_get_error_message(context, retval);
+ krb5int_set_error(&context->err, retval, "Preauth plugin %s: %s",
+ context->preauth_context->modules[i].name, emsg);
+ break;
+ }
+ }
+ return retval;
+}
+
+/* Free the per-krb5_context preauth_context. This means clearing any
+ * plugin-specific context which may have been created, and then
+ * freeing the context itself. */
+void KRB5_CALLCONV
+krb5_free_preauth_context(krb5_context context)
+{
+ int i;
+ void *pctx;
+ if (context->preauth_context != NULL) {
+ for (i = 0; i < context->preauth_context->n_modules; i++) {
+ pctx = context->preauth_context->modules[i].plugin_context;
+ if (context->preauth_context->modules[i].client_fini != NULL) {
+ (*context->preauth_context->modules[i].client_fini)(context, pctx);
+ }
+ memset(&context->preauth_context->modules[i], 0,
+ sizeof(context->preauth_context->modules[i]));
+ }
+ if (context->preauth_context->modules != NULL) {
+ free(context->preauth_context->modules);
+ context->preauth_context->modules = NULL;
+ }
+ free(context->preauth_context);
+ context->preauth_context = NULL;
+ }
+}
+
+/* Initialize the per-AS-REQ context. This means calling the client_req_init
+ * function to give the plugin a chance to allocate a per-request context. */
+void KRB5_CALLCONV
+krb5_preauth_request_context_init(krb5_context context)
+{
+ int i;
+ void *rctx, *pctx;
+
+ /* Limit this to only one attempt per context? */
+ if (context->preauth_context == NULL)
+ krb5_init_preauth_context(context);
+ if (context->preauth_context != NULL) {
+ for (i = 0; i < context->preauth_context->n_modules; i++) {
+ pctx = context->preauth_context->modules[i].plugin_context;
+ if (context->preauth_context->modules[i].client_req_init != NULL) {
+ rctx = context->preauth_context->modules[i].request_context_pp;
+ (*context->preauth_context->modules[i].client_req_init) (context, pctx, rctx);
+ }
+ }
+ }
+}
+
+/* Free the per-AS-REQ context. This means clearing any request-specific
+ * context which the plugin may have created. */
+void KRB5_CALLCONV
+krb5_preauth_request_context_fini(krb5_context context)
+{
+ int i;
+ void *rctx, *pctx;
+ if (context->preauth_context != NULL) {
+ for (i = 0; i < context->preauth_context->n_modules; i++) {
+ pctx = context->preauth_context->modules[i].plugin_context;
+ rctx = context->preauth_context->modules[i].request_context;
+ if (rctx != NULL) {
+ if (context->preauth_context->modules[i].client_req_fini != NULL) {
+ (*context->preauth_context->modules[i].client_req_fini)(context, pctx, rctx);
+ }
+ context->preauth_context->modules[i].request_context = NULL;
+ }
+ }
+ }
+}
+
+/* Add the named encryption type to the existing list of ktypes. */
+static void
+grow_ktypes(krb5_enctype **out_ktypes, int *out_nktypes, krb5_enctype ktype)
+{
+ int i;
+ krb5_enctype *ktypes;
+ for (i = 0; i < *out_nktypes; i++) {
+ if ((*out_ktypes)[i] == ktype)
+ return;
+ }
+ ktypes = malloc((*out_nktypes + 2) * sizeof(ktype));
+ if (ktypes) {
+ for (i = 0; i < *out_nktypes; i++)
+ ktypes[i] = (*out_ktypes)[i];
+ ktypes[i++] = ktype;
+ ktypes[i] = 0;
+ free(*out_ktypes);
+ *out_ktypes = ktypes;
+ *out_nktypes = i;
+ }
+}
+
+/*
+ * Add the given list of pa_data items to the existing list of items.
+ * Factored out here to make reading the do_preauth logic easier to read.
+ */
+static int
+grow_pa_list(krb5_pa_data ***out_pa_list, int *out_pa_list_size,
+ krb5_pa_data **addition, int num_addition)
+{
+ krb5_pa_data **pa_list;
+ int i, j;
+
+ if (out_pa_list == NULL || addition == NULL) {
+ return EINVAL;
+ }
+
+ if (*out_pa_list == NULL) {
+ /* Allocate room for the new additions and a NULL terminator. */
+ pa_list = malloc((num_addition + 1) * sizeof(krb5_pa_data *));
+ if (pa_list == NULL)
+ return ENOMEM;
+ for (i = 0; i < num_addition; i++)
+ pa_list[i] = addition[i];
+ pa_list[i] = NULL;
+ *out_pa_list = pa_list;
+ *out_pa_list_size = num_addition;
+ } else {
+ /*
+ * Allocate room for the existing entries plus
+ * the new additions and a NULL terminator.
+ */
+ pa_list = malloc((*out_pa_list_size + num_addition + 1)
+ * sizeof(krb5_pa_data *));
+ if (pa_list == NULL)
+ return ENOMEM;
+ for (i = 0; i < *out_pa_list_size; i++)
+ pa_list[i] = (*out_pa_list)[i];
+ for (j = 0; j < num_addition;)
+ pa_list[i++] = addition[j++];
+ pa_list[i] = NULL;
+ free(*out_pa_list);
+ *out_pa_list = pa_list;
+ *out_pa_list_size = i;
+ }
+ return 0;
+}
+
+/*
+ * Retrieve a specific piece of information required by the plugin and
+ * return it in a new krb5_data item. There are separate request_types
+ * to obtain the data and free it.
+ *
+ * This may require massaging data into a contrived format, but it will
+ * hopefully keep us from having to reveal library-internal functions
+ * or data to the plugin modules.
+ */
+
+static krb5_error_code
+client_data_proc(krb5_context kcontext,
+ krb5_preauth_client_rock *rock,
+ krb5_int32 request_type,
+ krb5_data **retdata)
+{
+ krb5_data *ret;
+ char *data;
+
+ if (rock->magic != CLIENT_ROCK_MAGIC)
+ return EINVAL;
+ if (retdata == NULL)
+ return EINVAL;
+
+ switch (request_type) {
+ case krb5plugin_preauth_client_get_etype:
+ {
+ krb5_enctype *eptr;
+ if (rock->as_reply == NULL)
+ return ENOENT;
+ ret = malloc(sizeof(krb5_data));
+ if (ret == NULL)
+ return ENOMEM;
+ data = malloc(sizeof(krb5_enctype));
+ if (data == NULL) {
+ free(ret);
+ return ENOMEM;
+ }
+ ret->data = data;
+ ret->length = sizeof(krb5_enctype);
+ eptr = (krb5_enctype *)data;
+ *eptr = rock->as_reply->enc_part.enctype;
+ *retdata = ret;
+ return 0;
+ }
+ break;
+ case krb5plugin_preauth_client_free_etype:
+ ret = *retdata;
+ if (ret == NULL)
+ return 0;
+ if (ret->data)
+ free(ret->data);
+ free(ret);
+ return 0;
+ break;
+ default:
+ return EINVAL;
+ }
+}
+
+/* Tweak the request body, for now adding any enctypes which the module claims
+ * to add support for to the list, but in the future perhaps doing more
+ * involved things. */
+void KRB5_CALLCONV
+krb5_preauth_prepare_request(krb5_context kcontext,
+ krb5_gic_opt_ext *opte,
+ krb5_kdc_req *request)
+{
+ int i, j;
+
+ if (kcontext->preauth_context == NULL) {
+ return;
+ }
+ /* Add the module-specific enctype list to the request, but only if
+ * it's something we can safely modify. */
+ if (!(opte && (opte->flags & KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST))) {
+ for (i = 0; i < kcontext->preauth_context->n_modules; i++) {
+ if (kcontext->preauth_context->modules[i].enctypes == NULL)
+ continue;
+ for (j = 0; kcontext->preauth_context->modules[i].enctypes[j] != 0; j++) {
+ grow_ktypes(&request->ktype, &request->nktypes,
+ kcontext->preauth_context->modules[i].enctypes[j]);
+ }
+ }
+ }
+}
+
+/* Find the first module which provides for the named preauth type which also
+ * hasn't had a chance to run yet (INFO modules don't count, because as a rule
+ * they don't generate preauth data), and run it. */
+static krb5_error_code
+krb5_run_preauth_plugins(krb5_context kcontext,
+ int module_required_flags,
+ krb5_kdc_req *request,
+ krb5_data *encoded_request_body,
+ krb5_data *encoded_previous_request,
+ krb5_pa_data *in_padata,
+ krb5_prompter_fct prompter,
+ void *prompter_data,
+ preauth_get_as_key_proc gak_fct,
+ krb5_data *salt,
+ krb5_data *s2kparams,
+ void *gak_data,
+ krb5_preauth_client_rock *get_data_rock,
+ krb5_keyblock *as_key,
+ krb5_pa_data ***out_pa_list,
+ int *out_pa_list_size,
+ int *module_ret,
+ int *module_flags,
+ krb5_gic_opt_ext *opte)
+{
+ int i;
+ krb5_pa_data **out_pa_data;
+ krb5_error_code ret;
+ struct _krb5_preauth_context_module *module;
+
+ if (kcontext->preauth_context == NULL) {
+ return ENOENT;
+ }
+ /* iterate over all loaded modules */
+ for (i = 0; i < kcontext->preauth_context->n_modules; i++) {
+ module = &kcontext->preauth_context->modules[i];
+ /* skip over those which don't match the preauth type */
+ if (module->pa_type != in_padata->pa_type)
+ continue;
+ /* skip over those which don't match the flags (INFO vs REAL, mainly) */
+ if ((module->flags & module_required_flags) == 0)
+ continue;
+ /* if it's a REAL module, try to call it only once per library call */
+ if (module_required_flags & PA_REAL) {
+ if (module->use_count > 0) {
+#ifdef DEBUG
+ fprintf(stderr, "skipping already-used module \"%s\"(%d)\n",
+ module->name, module->pa_type);
+#endif
+ continue;
+ }
+ module->use_count++;
+ }
+ /* run the module's callback function */
+ out_pa_data = NULL;
+#ifdef DEBUG
+ fprintf(stderr, "using module \"%s\" (%d), flags = %d\n",
+ module->name, module->pa_type, module->flags);
+#endif
+ ret = module->client_process(kcontext,
+ module->plugin_context,
+ *module->request_context_pp,
+ (krb5_get_init_creds_opt *)opte,
+ client_data_proc,
+ get_data_rock,
+ request,
+ encoded_request_body,
+ encoded_previous_request,
+ in_padata,
+ prompter, prompter_data,
+ gak_fct, gak_data, salt, s2kparams,
+ as_key,
+ &out_pa_data);
+ /* Make note of the module's flags and status. */
+ *module_flags = module->flags;
+ *module_ret = ret;
+ /* Save the new preauth data item. */
+ if (out_pa_data != NULL) {
+ int j;
+ for (j = 0; out_pa_data[j] != NULL; j++);
+ ret = grow_pa_list(out_pa_list, out_pa_list_size, out_pa_data, j);
+ free(out_pa_data);
+ if (ret != 0)
+ return ret;
+ }
+ break;
+ }
+ if (i >= kcontext->preauth_context->n_modules) {
+ return ENOENT;
+ }
+ return 0;
+}
-/*ARGSUSED*/
static
krb5_error_code pa_salt(krb5_context context,
krb5_kdc_req *request,
krb5_pa_data *in_padata,
krb5_pa_data **out_padata,
- krb5_data *salt,
- krb5_data *s2kparams,
+ krb5_data *salt, krb5_data *s2kparams,
krb5_enctype *etype,
krb5_keyblock *as_key,
krb5_prompter_fct prompter, void *prompter_data,
@@ -75,13 +598,15 @@ krb5_error_code pa_salt(krb5_context context,
{
krb5_data tmp;
+ /* Solaris Kerberos - resync */
tmp.data = (char *)in_padata->contents;
tmp.length = in_padata->length;
krb5_free_data_contents(context, salt);
krb5int_copy_data_contents(context, &tmp, salt);
+
if (in_padata->pa_type == KRB5_PADATA_AFS3_SALT)
- salt->length = -1;
+ salt->length = SALT_TYPE_AFS_LENGTH;
return(0);
}
@@ -109,19 +634,20 @@ krb5_error_code pa_enc_timestamp(krb5_context context,
if (as_key->length == 0) {
#ifdef DEBUG
+ /* Solaris Kerberos */
if (salt != NULL && salt->data != NULL) {
- fprintf (stderr, "%s:%d: salt len=%d", __FILE__, __LINE__,
+ fprintf (stderr, "%s:%d: salt len=%d", __FILE__, __LINE__,
salt->length);
- if (salt->length > 0)
- fprintf (stderr, " '%*s'", salt->length, salt->data);
+ if ((int) salt->length > 0)
+ fprintf (stderr, " '%.*s'", salt->length, salt->data);
fprintf (stderr, "; *etype=%d request->ktype[0]=%d\n",
*etype, request->ktype[0]);
}
#endif
if ((ret = ((*gak_fct)(context, request->client,
- *etype ? *etype : request->ktype[0],
- prompter, prompter_data,
- salt, s2kparams, as_key, gak_data))))
+ *etype ? *etype : request->ktype[0],
+ prompter, prompter_data,
+ salt, s2kparams, as_key, gak_data))))
return(ret);
}
@@ -258,11 +784,13 @@ krb5_error_code pa_sam(krb5_context context,
krb5_enc_sam_response_enc enc_sam_response_enc;
krb5_data * scratch;
krb5_pa_data * pa;
+
+ /* Solaris Kerberos */
krb5_enc_data * enc_data;
size_t enclen;
if (prompter == NULL)
- return (EIO);
+ return EIO;
tmpsam.length = in_padata->length;
tmpsam.data = (char *) in_padata->contents;
@@ -273,25 +801,25 @@ krb5_error_code pa_sam(krb5_context context,
krb5_xfree(sam_challenge);
return(KRB5_SAM_UNSUPPORTED);
}
+
/* If we need the password from the user (USE_SAD_AS_KEY not set), */
- /* then get it here. Exception for "old" KDCs with CryptoCard */
- /* support which uses the USE_SAD_AS_KEY flag, but still needs pwd */
+ /* then get it here. Exception for "old" KDCs with CryptoCard */
+ /* support which uses the USE_SAD_AS_KEY flag, but still needs pwd */
if (!(sam_challenge->sam_flags & KRB5_SAM_USE_SAD_AS_KEY) ||
(sam_challenge->sam_type == PA_SAM_TYPE_CRYPTOCARD)) {
/* etype has either been set by caller or by KRB5_PADATA_ETYPE_INFO */
/* message from the KDC. If it is not set, pick an enctype that we */
- /* think the KDC will have for us. */
+ /* think the KDC will have for us. */
if (etype && *etype == 0)
- *etype = ENCTYPE_DES_CBC_CRC;
+ *etype = ENCTYPE_DES_CBC_CRC;
if ((ret = (gak_fct)(context, request->client, *etype, prompter,
prompter_data, salt, s2kparams, as_key, gak_data)))
return(ret);
}
-
sprintf(name, "%.*s",
SAMDATA(sam_challenge->sam_type_name, "SAM Authentication",
sizeof(name) - 1));
@@ -341,7 +869,7 @@ krb5_error_code pa_sam(krb5_context context,
/* XXX What if more than one flag is set? */
if (sam_challenge->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD) {
- /* Most of this should be taken care of before we get here. We */
+ /* Most of this should be taken care of before we get here. We */
/* will need the user's password and as_key to encrypt the SAD */
/* and we want to preserve ordering of user prompts (first */
/* password, then SAM data) so that user's won't be confused. */
@@ -353,7 +881,7 @@ krb5_error_code pa_sam(krb5_context context,
/* generate a salt using the requested principal */
- if ((salt->length == -1) && (salt->data == NULL)) {
+ if ((salt->length == -1 || salt->length == SALT_TYPE_AFS_LENGTH) && (salt->data == NULL)) {
if ((ret = krb5_principal2salt(context, request->client,
&defsalt))) {
krb5_xfree(sam_challenge);
@@ -391,7 +919,7 @@ krb5_error_code pa_sam(krb5_context context,
}
#if 0
- if ((salt->length == -1) && (salt->data == NULL)) {
+ if ((salt->length == SALT_TYPE_AFS_LENGTH) && (salt->data == NULL)) {
if (ret = krb5_principal2salt(context, request->client,
&defsalt)) {
krb5_xfree(sam_challenge);
@@ -440,7 +968,7 @@ krb5_error_code pa_sam(krb5_context context,
/* encode the encoded part of the response */
if ((ret = encode_krb5_enc_sam_response_enc(&enc_sam_response_enc,
- &scratch)))
+ &scratch)))
return(ret);
/*
@@ -569,7 +1097,7 @@ krb5_error_code pa_sam_2(krb5_context context,
/* most likely go on to try the AS_REQ against master KDC */
if (!(sc2b->sam_flags & KRB5_SAM_USE_SAD_AS_KEY)) {
- /* We will need the password to obtain the key used for */
+ /* We will need the password to obtain the key used for */
/* the checksum, and encryption of the sam_response. */
/* Go ahead and get it now, preserving the ordering of */
/* prompts for the user. */
@@ -620,13 +1148,13 @@ krb5_error_code pa_sam_2(krb5_context context,
/* Generate salt used by string_to_key() */
if ((salt->length == -1) && (salt->data == NULL)) {
- if ((retval =
- krb5_principal2salt(context, request->client, &defsalt))) {
+ if ((retval =
+ krb5_principal2salt(context, request->client, &defsalt))) {
krb5_free_sam_challenge_2(context, sc2);
krb5_free_sam_challenge_2_body(context, sc2b);
return(retval);
}
- salt = &defsalt;
+ salt = &defsalt;
} else {
defsalt.length = 0;
}
@@ -640,7 +1168,7 @@ krb5_error_code pa_sam_2(krb5_context context,
as_key->length = 0;
}
- /* generate a key using the supplied password */
+ /* generate a key using the supplied password */
retval = krb5_c_string_to_key(context, sc2b->sam_etype,
(krb5_data *)gak_data, salt, as_key);
@@ -651,33 +1179,34 @@ krb5_error_code pa_sam_2(krb5_context context,
return(retval);
}
- if (!(sc2b->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD)) {
+ if (!(sc2b->sam_flags & KRB5_SAM_SEND_ENCRYPTED_SAD)) {
/* as_key = combine_key (as_key, string_to_key(SAD)) */
krb5_keyblock tmp_kb;
- retval = krb5_c_string_to_key(context, sc2b->sam_etype,
+ retval = krb5_c_string_to_key(context, sc2b->sam_etype,
&response_data, salt, &tmp_kb);
- if (retval) {
+ if (retval) {
krb5_free_sam_challenge_2(context, sc2);
- krb5_free_sam_challenge_2_body(context, sc2b);
+ krb5_free_sam_challenge_2_body(context, sc2b);
if (defsalt.length) krb5_xfree(defsalt.data);
return(retval);
}
- /* This should be a call to the crypto library some day */
+ /* This should be a call to the crypto library some day */
/* key types should already match the sam_etype */
retval = krb5int_c_combine_keys(context, as_key, &tmp_kb, as_key);
- if (retval) {
+ if (retval) {
krb5_free_sam_challenge_2(context, sc2);
- krb5_free_sam_challenge_2_body(context, sc2b);
+ krb5_free_sam_challenge_2_body(context, sc2b);
if (defsalt.length) krb5_xfree(defsalt.data);
return(retval);
}
- krb5_free_keyblock_contents(context, &tmp_kb);
+ krb5_free_keyblock_contents(context, &tmp_kb);
}
- if (defsalt.length)
+
+ if (defsalt.length)
krb5_xfree(defsalt.data);
} else {
@@ -688,7 +1217,7 @@ krb5_error_code pa_sam_2(krb5_context context,
as_key->length = 0;
}
- /* generate a key using the supplied password */
+ /* generate a key using the supplied password */
retval = krb5_c_string_to_key(context, sc2b->sam_etype,
&response_data, salt, as_key);
@@ -705,7 +1234,7 @@ krb5_error_code pa_sam_2(krb5_context context,
/* Now we have a key, verify the checksum on the sam_challenge */
cksum = sc2->sam_cksum;
-
+
while (*cksum) {
/* Check this cksum */
retval = krb5_c_verify_checksum(context, as_key,
@@ -718,14 +1247,14 @@ krb5_error_code pa_sam_2(krb5_context context,
krb5_free_sam_challenge_2_body(context, sc2b);
return(retval);
}
- if (valid_cksum)
+ if (valid_cksum)
break;
cksum++;
}
if (!valid_cksum) {
- /* If KRB5_SAM_SEND_ENCRYPTED_SAD is set, then password is only */
+ /* If KRB5_SAM_SEND_ENCRYPTED_SAD is set, then password is only */
/* source for checksum key. Therefore, a bad checksum means a */
/* bad password. Don't give that direct feedback to someone */
/* trying to brute-force passwords. */
@@ -734,13 +1263,13 @@ krb5_error_code pa_sam_2(krb5_context context,
krb5_free_sam_challenge_2(context, sc2);
krb5_free_sam_challenge_2_body(context, sc2b);
/*
- * Note: We return AP_ERR_BAD_INTEGRITY so upper-level applications
+ * Note: We return AP_ERR_BAD_INTEGRITY so upper-level applications
* can interpret that as "password incorrect", which is probably
* the best error we can return in this situation.
*/
return(KRB5KRB_AP_ERR_BAD_INTEGRITY);
}
-
+
/* fill in enc_sam_response_enc_2 */
enc_sam_response_enc_2.magic = KV5M_ENC_SAM_RESPONSE_ENC_2;
enc_sam_response_enc_2.sam_nonce = sc2b->sam_nonce;
@@ -771,7 +1300,7 @@ krb5_error_code pa_sam_2(krb5_context context,
/* enc_sam_response_enc_2 from above */
retval = krb5_c_encrypt_length(context, as_key->enctype, scratch->length,
- &ciph_len);
+ &ciph_len);
if (retval) {
krb5_free_sam_challenge_2(context, sc2);
krb5_free_sam_challenge_2_body(context, sc2b);
@@ -810,7 +1339,7 @@ krb5_error_code pa_sam_2(krb5_context context,
return (retval);
}
- /* Almost there, just need to make padata ! */
+ /* Almost there, just need to make padata ! */
sam_padata = malloc(sizeof(krb5_pa_data));
if (sam_padata == NULL) {
krb5_free_data(context, scratch);
@@ -827,8 +1356,7 @@ krb5_error_code pa_sam_2(krb5_context context,
return(0);
}
-
-static pa_types_t pa_types[] = {
+static const pa_types_t pa_types[] = {
{
KRB5_PADATA_PW_SALT,
pa_salt,
@@ -845,7 +1373,7 @@ static pa_types_t pa_types[] = {
PA_REAL,
},
{
- KRB5_PADATA_SAM_CHALLENGE_2,
+ KRB5_PADATA_SAM_CHALLENGE_2,
pa_sam_2,
PA_REAL,
},
@@ -861,15 +1389,95 @@ static pa_types_t pa_types[] = {
},
};
-krb5_error_code
+/*
+ * If one of the modules can adjust its AS_REQ data using the contents of the
+ * err_reply, return 0. If it's the sort of correction which requires that we
+ * ask the user another question, we let the calling application deal with it.
+ */
+krb5_error_code KRB5_CALLCONV
+krb5_do_preauth_tryagain(krb5_context kcontext,
+ krb5_kdc_req *request,
+ krb5_data *encoded_request_body,
+ krb5_data *encoded_previous_request,
+ krb5_pa_data **padata,
+ krb5_pa_data ***return_padata,
+ krb5_error *err_reply,
+ krb5_data *salt, krb5_data *s2kparams,
+ krb5_enctype *etype,
+ krb5_keyblock *as_key,
+ krb5_prompter_fct prompter, void *prompter_data,
+ krb5_gic_get_as_key_fct gak_fct, void *gak_data,
+ krb5_preauth_client_rock *get_data_rock,
+ krb5_gic_opt_ext *opte)
+{
+ krb5_error_code ret;
+ krb5_pa_data **out_padata;
+ krb5_preauth_context *context;
+ struct _krb5_preauth_context_module *module;
+ int i, j;
+ int out_pa_list_size = 0;
+
+ ret = KRB5KRB_ERR_GENERIC;
+ if (kcontext->preauth_context == NULL) {
+ return KRB5KRB_ERR_GENERIC;
+ }
+ context = kcontext->preauth_context;
+ if (context == NULL) {
+ return KRB5KRB_ERR_GENERIC;
+ }
+
+ for (i = 0; padata[i] != NULL && padata[i]->pa_type != 0; i++) {
+ out_padata = NULL;
+ for (j = 0; j < context->n_modules; j++) {
+ module = &context->modules[j];
+ if (module->pa_type != padata[i]->pa_type) {
+ continue;
+ }
+ if (module->client_tryagain == NULL) {
+ continue;
+ }
+ if ((*module->client_tryagain)(kcontext,
+ module->plugin_context,
+ *module->request_context_pp,
+ (krb5_get_init_creds_opt *)opte,
+ client_data_proc,
+ get_data_rock,
+ request,
+ encoded_request_body,
+ encoded_previous_request,
+ padata[i],
+ err_reply,
+ prompter, prompter_data,
+ gak_fct, gak_data, salt, s2kparams,
+ as_key,
+ &out_padata) == 0) {
+ if (out_padata != NULL) {
+ int k;
+ for (k = 0; out_padata[k] != NULL; k++);
+ grow_pa_list(return_padata, &out_pa_list_size,
+ out_padata, k);
+ free(out_padata);
+ return 0;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+krb5_error_code KRB5_CALLCONV
krb5_do_preauth(krb5_context context,
krb5_kdc_req *request,
+ krb5_data *encoded_request_body,
+ krb5_data *encoded_previous_request,
krb5_pa_data **in_padata, krb5_pa_data ***out_padata,
krb5_data *salt, krb5_data *s2kparams,
krb5_enctype *etype,
krb5_keyblock *as_key,
krb5_prompter_fct prompter, void *prompter_data,
- krb5_gic_get_as_key_fct gak_fct, void *gak_data)
+ krb5_gic_get_as_key_fct gak_fct, void *gak_data,
+ krb5_preauth_client_rock *get_data_rock,
+ krb5_gic_opt_ext *opte)
{
int h, i, j, out_pa_list_size;
int seen_etype_info2 = 0;
@@ -880,6 +1488,7 @@ krb5_do_preauth(krb5_context context,
static const int paorder[] = { PA_INFO, PA_REAL };
int realdone;
+ /* Solaris Kerberos */
KRB5_LOG0(KRB5_INFO, "krb5_do_preauth() start");
if (in_padata == NULL) {
@@ -888,9 +1497,10 @@ krb5_do_preauth(krb5_context context,
}
#ifdef DEBUG
+ /* Solaris Kerberos */
if (salt && salt->data && salt->length > 0) {
fprintf (stderr, "salt len=%d", salt->length);
- if (salt->length > 0)
+ if ((int) salt->length > 0)
fprintf (stderr, " '%*s'", salt->length, salt->data);
fprintf (stderr, "; preauth data types:");
for (i = 0; in_padata[i]; i++) {
@@ -911,7 +1521,7 @@ krb5_do_preauth(krb5_context context,
int k, l, etype_found, valid_etype_found;
/*
* This is really gross, but is necessary to prevent
- * lossge when talking to a 1.0.x KDC, which returns an
+ * lossage when talking to a 1.0.x KDC, which returns an
* erroneous PA-PW-SALT when it returns a KRB-ERROR
* requiring additional preauth.
*/
@@ -924,23 +1534,24 @@ krb5_do_preauth(krb5_context context,
if (seen_etype_info2 || pa_type != KRB5_PADATA_ETYPE_INFO2)
continue;
if (pa_type == KRB5_PADATA_ETYPE_INFO2) {
- krb5_free_etype_info( context, etype_info);
+ krb5_free_etype_info( context, etype_info);
etype_info = NULL;
- }
+ }
}
scratch.length = in_padata[i]->length;
scratch.data = (char *) in_padata[i]->contents;
if (pa_type == KRB5_PADATA_ETYPE_INFO2) {
- seen_etype_info2++;
- ret = decode_krb5_etype_info2(&scratch, &etype_info);
+ seen_etype_info2++;
+ ret = decode_krb5_etype_info2(&scratch, &etype_info);
}
else ret = decode_krb5_etype_info(&scratch, &etype_info);
if (ret) {
- ret = 0; /*Ignore error and etype_info element*/
- krb5_free_etype_info( context, etype_info);
- etype_info = NULL;
- continue;
+ ret = 0; /*Ignore error and etype_info element*/
+ if (etype_info)
+ krb5_free_etype_info( context, etype_info);
+ etype_info = NULL;
+ continue;
}
if (etype_info[0] == NULL) {
krb5_free_etype_info(context, etype_info);
@@ -952,7 +1563,7 @@ krb5_do_preauth(krb5_context context,
* etype-info (preferring client request ktype order).
*/
for (etype_found = 0, valid_etype_found = 0, k = 0;
- !etype_found && k < request->nktypes; k++) {
+ !etype_found && k < request->nktypes; k++) {
for (l = 0; etype_info[l]; l++) {
if (etype_info[l]->etype == request->ktype[k]) {
etype_found++;
@@ -966,36 +1577,46 @@ krb5_do_preauth(krb5_context context,
}
}
if (!etype_found) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "error !etype_found, "
"valid_etype_found = %d",
valid_etype_found);
- if (valid_etype_found) {
+ if (valid_etype_found) {
/* supported enctype but not requested */
- ret = KRB5_CONFIG_ETYPE_NOSUPP;
- goto cleanup;
- }
- else {
- /* unsupported enctype */
- ret = KRB5_PROG_ETYPE_NOSUPP;
- goto cleanup;
- }
+ ret = KRB5_CONFIG_ETYPE_NOSUPP;
+ goto cleanup;
+ }
+ else {
+ /* unsupported enctype */
+ ret = KRB5_PROG_ETYPE_NOSUPP;
+ goto cleanup;
+ }
}
scratch.data = (char *) etype_info[l]->salt;
scratch.length = etype_info[l]->length;
krb5_free_data_contents(context, salt);
- if (scratch.length == KRB5_ETYPE_NO_SALT)
+ if (scratch.length == KRB5_ETYPE_NO_SALT)
salt->data = NULL;
else
- if ((ret = krb5int_copy_data_contents( context,
- &scratch, salt)) != 0)
- goto cleanup;
+ if ((ret = krb5int_copy_data_contents( context, &scratch, salt)) != 0)
+ goto cleanup;
*etype = etype_info[l]->etype;
krb5_free_data_contents(context, s2kparams);
if ((ret = krb5int_copy_data_contents(context,
- &etype_info[l]->s2kparams,
- s2kparams)) != 0)
+ &etype_info[l]->s2kparams,
+ s2kparams)) != 0)
goto cleanup;
+#ifdef DEBUG
+ for (j = 0; etype_info[j]; j++) {
+ krb5_etype_info_entry *e = etype_info[j];
+ fprintf (stderr, "etype info %d: etype %d salt len=%d",
+ j, e->etype, e->length);
+ if (e->length > 0 && e->length != KRB5_ETYPE_NO_SALT)
+ fprintf (stderr, " '%.*s'", e->length, e->salt);
+ fprintf (stderr, "\n");
+ }
+#endif
break;
}
case KRB5_PADATA_PW_SALT:
@@ -1006,69 +1627,89 @@ krb5_do_preauth(krb5_context context,
default:
;
}
- for (j=0; pa_types[j].type >= 0; j++) {
+ /* Try the internally-provided preauth type list. */
+ if (!realdone) for (j=0; pa_types[j].type >= 0; j++) {
if ((in_padata[i]->pa_type == pa_types[j].type) &&
(pa_types[j].flags & paorder[h])) {
+#ifdef DEBUG
+ fprintf (stderr, "calling internal function for pa_type "
+ "%d, flag %d\n", pa_types[j].type, paorder[h]);
+#endif
out_pa = NULL;
if ((ret = ((*pa_types[j].fct)(context, request,
- in_padata[i], &out_pa,
- salt, s2kparams, etype, as_key,
- prompter, prompter_data,
- gak_fct, gak_data)))) {
- goto cleanup;
+ in_padata[i], &out_pa,
+ salt, s2kparams, etype, as_key,
+ prompter, prompter_data,
+ gak_fct, gak_data)))) {
+ goto cleanup;
}
- if (out_pa) {
- if (out_pa_list == NULL) {
- if ((out_pa_list =
- (krb5_pa_data **)
- malloc(2*sizeof(krb5_pa_data *)))
- == NULL) {
- ret = ENOMEM;
- goto cleanup;
- }
- } else {
- if ((out_pa_list =
- (krb5_pa_data **)
- realloc(out_pa_list,
- (out_pa_list_size+2)*
- sizeof(krb5_pa_data *)))
- == NULL) {
- /* XXX this will leak the pointers which
- have already been allocated. oh well. */
- ret = ENOMEM;
- goto cleanup;
- }
- }
-
- out_pa_list[out_pa_list_size++] = out_pa;
+ ret = grow_pa_list(&out_pa_list, &out_pa_list_size,
+ &out_pa, 1);
+ if (ret != 0) {
+ goto cleanup;
}
if (paorder[h] == PA_REAL)
realdone = 1;
}
}
+
+ /* Try to use plugins now. */
+ if (!realdone) {
+ krb5_init_preauth_context(context);
+ if (context->preauth_context != NULL) {
+ int module_ret, module_flags;
+#ifdef DEBUG
+ fprintf (stderr, "trying modules for pa_type %d, flag %d\n",
+ in_padata[i]->pa_type, paorder[h]);
+#endif
+ ret = krb5_run_preauth_plugins(context,
+ paorder[h],
+ request,
+ encoded_request_body,
+ encoded_previous_request,
+ in_padata[i],
+ prompter,
+ prompter_data,
+ gak_fct,
+ salt, s2kparams,
+ gak_data,
+ get_data_rock,
+ as_key,
+ &out_pa_list,
+ &out_pa_list_size,
+ &module_ret,
+ &module_flags,
+ opte);
+ if (ret == 0) {
+ if (module_ret == 0) {
+ if (paorder[h] == PA_REAL) {
+ realdone = 1;
+ }
+ }
+ }
+ }
+ }
}
}
- if (out_pa_list)
- out_pa_list[out_pa_list_size++] = NULL;
-
*out_padata = out_pa_list;
if (etype_info)
- krb5_free_etype_info(context, etype_info);
-
+ krb5_free_etype_info(context, etype_info);
+
+ /* Solaris Kerberos */
KRB5_LOG0(KRB5_INFO, "krb5_do_preauth() end");
return(0);
-cleanup:
+ cleanup:
if (out_pa_list) {
- out_pa_list[out_pa_list_size++] = NULL;
- krb5_free_pa_data(context, out_pa_list);
+ out_pa_list[out_pa_list_size++] = NULL;
+ krb5_free_pa_data(context, out_pa_list);
}
if (etype_info)
- krb5_free_etype_info(context, etype_info);
+ krb5_free_etype_info(context, etype_info);
+ /* Solaris Kerberos */
KRB5_LOG0(KRB5_INFO, "krb5_do_preauth() end");
return (ret);
-
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_cred.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_cred.c
index c2e2db769d..bbaf5f5f8c 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_cred.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_cred.c
@@ -1,13 +1,12 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-#include <k5-int.h>
+#include "k5-int.h"
#include "cleanup.h"
-#include <auth_con.h>
+#include "auth_con.h"
#include <stddef.h> /* NULL */
#include <stdlib.h> /* malloc */
@@ -19,27 +18,24 @@
* decrypt the enc_part of a krb5_cred
*/
/*ARGSUSED*/
-static krb5_error_code
-decrypt_credencdata(
- krb5_context context,
- krb5_cred * pcred,
- krb5_keyblock * pkeyblock,
- krb5_cred_enc_part * pcredenc)
+static krb5_error_code
+decrypt_credencdata(krb5_context context, krb5_cred *pcred, krb5_keyblock *pkeyblock, krb5_cred_enc_part *pcredenc)
{
krb5_cred_enc_part * ppart = NULL;
krb5_error_code retval;
krb5_data scratch;
scratch.length = pcred->enc_part.ciphertext.length;
- if (!(scratch.data = (char *)malloc(scratch.length)))
+ if (!(scratch.data = (char *)malloc(scratch.length)))
return ENOMEM;
if (pkeyblock != NULL) {
- if ((retval = krb5_c_decrypt(context, pkeyblock,
- KRB5_KEYUSAGE_KRB_CRED_ENCPART, 0,
- &pcred->enc_part, &scratch)))
- goto cleanup;
+ if ((retval = krb5_c_decrypt(context, pkeyblock,
+ KRB5_KEYUSAGE_KRB_CRED_ENCPART, 0,
+ &pcred->enc_part, &scratch)))
+ goto cleanup;
} else {
+ /* Solaris Kerberos */
(void) memcpy(scratch.data, pcred->enc_part.ciphertext.data, scratch.length);
}
@@ -47,7 +43,6 @@ decrypt_credencdata(
if ((retval = decode_krb5_enc_cred_part(&scratch, &ppart)))
goto cleanup;
- /* this is a struct copy so ppart must be freed */
*pcredenc = *ppart;
retval = 0;
@@ -56,6 +51,7 @@ cleanup:
memset(ppart, 0, sizeof(*ppart));
krb5_xfree(ppart);
}
+ /* Solaris Kerberos */
(void) memset(scratch.data, 0, scratch.length);
krb5_xfree(scratch.data);
@@ -63,13 +59,8 @@ cleanup:
}
/*----------------------- krb5_rd_cred_basic -----------------------*/
-static krb5_error_code
-krb5_rd_cred_basic(
- krb5_context context,
- krb5_data * pcreddata,
- krb5_keyblock * pkeyblock,
- krb5_replay_data * replaydata,
- krb5_creds *** pppcreds)
+static krb5_error_code
+krb5_rd_cred_basic(krb5_context context, krb5_data *pcreddata, krb5_keyblock *pkeyblock, krb5_replay_data *replaydata, krb5_creds ***pppcreds)
{
krb5_error_code retval;
krb5_cred * pcred;
@@ -81,11 +72,13 @@ krb5_rd_cred_basic(
if ((retval = decode_krb5_cred(pcreddata, &pcred)))
return retval;
+ /* Solaris Kerberos */
(void) memset(&encpart, 0, sizeof(encpart));
if ((retval = decrypt_credencdata(context, pcred, pkeyblock, &encpart)))
goto cleanup_cred;
+
replaydata->timestamp = encpart.timestamp;
replaydata->usec = encpart.usec;
replaydata->seq = encpart.nonce;
@@ -96,7 +89,7 @@ krb5_rd_cred_basic(
*/
for (ncreds = 0; pcred->tickets[ncreds]; ncreds++);
- if ((*pppcreds =
+ if ((*pppcreds =
(krb5_creds **)malloc((size_t)(sizeof(krb5_creds *) *
(ncreds + 1)))) == NULL) {
retval = ENOMEM;
@@ -121,6 +114,7 @@ krb5_rd_cred_basic(
(*pppcreds)[i] = pcur;
(*pppcreds)[i+1] = 0;
pinfo = encpart.ticket_info[i++];
+ /* Solaris Kerberos */
(void) memset(pcur, 0, sizeof(krb5_creds));
if ((retval = krb5_copy_principal(context, pinfo->client,
@@ -135,7 +129,7 @@ krb5_rd_cred_basic(
&pcur->keyblock)))
goto cleanup;
- if ((retval = krb5_copy_addresses(context, pinfo->caddrs,
+ if ((retval = krb5_copy_addresses(context, pinfo->caddrs,
&pcur->addresses)))
goto cleanup;
@@ -151,6 +145,7 @@ krb5_rd_cred_basic(
pcur->times = pinfo->times;
pcur->ticket_flags = pinfo->flags;
pcur->authdata = NULL; /* not used */
+ /* Solaris Kerberos */
(void) memset(&pcur->second_ticket, 0, sizeof(pcur->second_ticket));
}
@@ -179,12 +174,7 @@ cleanup_cred:
* outputs the nonce and an array of the forwarded credentials.
*/
krb5_error_code KRB5_CALLCONV
-krb5_rd_cred(
- krb5_context context,
- krb5_auth_context auth_context,
- krb5_data * pcreddata,
- krb5_creds * * * pppcreds,
- krb5_replay_data * outdata)
+krb5_rd_cred(krb5_context context, krb5_auth_context auth_context, krb5_data *pcreddata, krb5_creds ***pppcreds, krb5_replay_data *outdata)
{
krb5_error_code retval;
krb5_keyblock * keyblock;
@@ -204,21 +194,20 @@ krb5_rd_cred(
(auth_context->rcache == NULL))
return KRB5_RC_REQUIRED;
- /*
- * If decrypting with the first keyblock we try fails, perhaps the
- * credentials are stored in the session key so try decrypting with
- * that.
- */
+
+/* If decrypting with the first keyblock we try fails, perhaps the
+ * credentials are stored in the session key so try decrypting with
+ * that.
+*/
if ((retval = krb5_rd_cred_basic(context, pcreddata, keyblock,
- &replaydata, pppcreds))) {
+ &replaydata, pppcreds))) {
if ((retval = krb5_rd_cred_basic(context, pcreddata,
- auth_context->keyblock,
- &replaydata, pppcreds))) {
- return retval;
- }
+ auth_context->keyblock,
+ &replaydata, pppcreds))) {
+ return retval;
}
-
-
+ }
+
if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
krb5_donot_replay replay;
krb5_timestamp currenttime;
@@ -239,8 +228,8 @@ krb5_rd_cred(
replay.cusec = replaydata.usec;
replay.ctime = replaydata.timestamp;
if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
- krb5_xfree(replay.client);
- goto error;
+ krb5_xfree(replay.client);
+ goto error;
}
krb5_xfree(replay.client);
}
@@ -260,10 +249,11 @@ krb5_rd_cred(
outdata->seq = replaydata.seq;
}
-error:
+error:;
if (retval) {
- krb5_free_tgt_creds(context, *pppcreds);
+ krb5_free_tgt_creds(context, *pppcreds);
*pppcreds = NULL;
}
return retval;
}
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_error.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_error.c
index e3fe0e47a2..8060cb70ef 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_error.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_error.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/rd_error.c
*
@@ -28,7 +27,7 @@
* krb5_rd_error() routine
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*
* Parses an error message from enc_errbuf and returns an allocated
@@ -48,3 +47,4 @@ krb5_rd_error(krb5_context context, const krb5_data *enc_errbuf, krb5_error **de
return KRB5KRB_AP_ERR_MSG_TYPE;
return(decode_krb5_error(enc_errbuf, dec_error));
}
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_priv.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_priv.c
index 585ea34593..ab4fc40ad8 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_priv.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_priv.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/rd_priv.c
@@ -15,7 +14,7 @@
* 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
@@ -29,14 +28,14 @@
* 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.
- *
+ *
*
* krb5_rd_priv()
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include "cleanup.h"
-#include <auth_con.h>
+#include "auth_con.h"
#define in_clock_skew(date) (labs((date)-currenttime) < context->clockskew)
@@ -46,7 +45,7 @@ Parses a KRB_PRIV message from inbuf, placing the confidential user
data in *outbuf.
key specifies the key to be used for decryption of the message.
-
+
remote_addr and local_addr specify the full
addresses (host and port) of the sender and receiver.
@@ -62,15 +61,7 @@ Returns system errors, integrity errors.
*/
static krb5_error_code
-krb5_rd_priv_basic(
- krb5_context context,
- const krb5_data * inbuf,
- const krb5_keyblock * keyblock,
- const krb5_address * local_addr,
- const krb5_address * remote_addr,
- krb5_pointer i_vector,
- krb5_replay_data * replaydata,
- krb5_data * outbuf)
+krb5_rd_priv_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyblock *keyblock, const krb5_address *local_addr, const krb5_address *remote_addr, krb5_pointer i_vector, krb5_replay_data *replaydata, krb5_data *outbuf)
{
krb5_error_code retval;
krb5_priv * privmsg;
@@ -85,7 +76,7 @@ krb5_rd_priv_basic(
/* decode private message */
if ((retval = decode_krb5_priv(inbuf, &privmsg)))
return retval;
-
+
if (i_vector) {
if ((retval = krb5_c_block_size(context, keyblock->enctype,
&blocksize)))
@@ -102,7 +93,7 @@ krb5_rd_priv_basic(
}
if ((retval = krb5_c_decrypt(context, keyblock,
- KRB5_KEYUSAGE_KRB_PRIV_ENCPART,
+ KRB5_KEYUSAGE_KRB_PRIV_ENCPART,
i_vector?&ivdata:0,
&privmsg->enc_part, &scratch)))
goto cleanup_scratch;
@@ -115,7 +106,7 @@ krb5_rd_priv_basic(
retval = KRB5KRB_AP_ERR_BADADDR;
goto cleanup_data;
}
-
+
if (privmsg_enc_part->r_address) {
if (local_addr) {
if (!krb5_address_compare(context, local_addr,
@@ -129,7 +120,7 @@ krb5_rd_priv_basic(
if ((retval = krb5_os_localaddr(context, &our_addrs))) {
goto cleanup_data;
}
- if (!krb5_address_search(context, privmsg_enc_part->r_address,
+ if (!krb5_address_search(context, privmsg_enc_part->r_address,
our_addrs)) {
krb5_free_addresses(context, our_addrs);
retval = KRB5KRB_AP_ERR_BADADDR;
@@ -153,23 +144,19 @@ cleanup_data:;
krb5_free_priv_enc_part(context, privmsg_enc_part);
cleanup_scratch:;
- (void) memset(scratch.data, 0, scratch.length);
+ /* Solaris Kerberos */
+ (void) memset(scratch.data, 0, scratch.length);
krb5_xfree(scratch.data);
cleanup_privmsg:;
- krb5_xfree(privmsg->enc_part.ciphertext.data);
+ krb5_xfree(privmsg->enc_part.ciphertext.data);
krb5_xfree(privmsg);
return retval;
}
krb5_error_code KRB5_CALLCONV
-krb5_rd_priv(
- krb5_context context,
- krb5_auth_context auth_context,
- const krb5_data * inbuf,
- krb5_data * outbuf,
- krb5_replay_data * outdata)
+krb5_rd_priv(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_data *outbuf, krb5_replay_data *outdata)
{
krb5_error_code retval;
krb5_keyblock * keyblock;
@@ -199,7 +186,7 @@ krb5_rd_priv(
if (auth_context->local_addr) {
if (auth_context->local_port) {
if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
- auth_context->local_port,
+ auth_context->local_port,
&local_fulladdr))){
CLEANUP_PUSH(local_fulladdr.contents, free);
plocal_fulladdr = &local_fulladdr;
@@ -214,7 +201,7 @@ krb5_rd_priv(
if (auth_context->remote_addr) {
if (auth_context->remote_port) {
if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
- auth_context->remote_port,
+ auth_context->remote_port,
&remote_fulladdr))){
CLEANUP_PUSH(remote_fulladdr.contents, free);
premote_fulladdr = &remote_fulladdr;
@@ -251,15 +238,14 @@ krb5_rd_priv(
goto error;
}
- if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr,
+ if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr,
"_priv", &replay.client)))
goto error;
replay.server = ""; /* XXX */
replay.cusec = replaydata.usec;
replay.ctime = replaydata.timestamp;
- retval = krb5_rc_store(context, auth_context->rcache, &replay);
- if (retval) {
+ if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
krb5_xfree(replay.client);
goto error;
}
@@ -290,3 +276,4 @@ error:;
return retval;
}
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_rep.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_rep.c
index 45c48383db..6742d8a038 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_rep.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_rep.c
@@ -1,11 +1,4 @@
/*
- * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
* lib/krb5/krb/rd_rep.c
*
* Copyright 1990,1991 by the Massachusetts Institute of Technology.
@@ -15,7 +8,7 @@
* 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
@@ -29,31 +22,27 @@
* 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.
- *
+ *
*
* krb5_rd_rep()
*/
-#include <k5-int.h>
-#include <auth_con.h>
+#include "k5-int.h"
+#include "auth_con.h"
/*
* Parses a KRB_AP_REP message, returning its contents.
- *
+ *
* repl is filled in with with a pointer to allocated memory containing
- * the fields from the encrypted response.
- *
+ * the fields from the encrypted response.
+ *
* the key in kblock is used to decrypt the message.
- *
+ *
* returns system errors, encryption errors, replay errors
*/
krb5_error_code KRB5_CALLCONV
-krb5_rd_rep(
- krb5_context context,
- krb5_auth_context auth_context,
- const krb5_data * inbuf,
- krb5_ap_rep_enc_part * *repl)
+krb5_rd_rep(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_ap_rep_enc_part **repl)
{
krb5_error_code retval;
krb5_ap_rep * reply;
@@ -75,15 +64,13 @@ krb5_rd_rep(
return(ENOMEM);
}
- retval = krb5_c_decrypt(context, auth_context->keyblock,
+ if ((retval = krb5_c_decrypt(context, auth_context->keyblock,
KRB5_KEYUSAGE_AP_REP_ENCPART, 0,
- &reply->enc_part, &scratch);
- if (retval)
+ &reply->enc_part, &scratch)))
goto clean_scratch;
/* now decode the decrypted stuff */
retval = decode_krb5_ap_rep_enc_part(&scratch, repl);
-
if (retval)
goto clean_scratch;
@@ -99,28 +86,29 @@ krb5_rd_rep(
if (auth_context->recv_subkey) {
krb5_free_keyblock(context, auth_context->recv_subkey);
auth_context->recv_subkey = NULL;
- }
+ }
retval = krb5_copy_keyblock(context, (*repl)->subkey,
- &auth_context->recv_subkey);
+ &auth_context->recv_subkey);
if (retval)
goto clean_scratch;
if (auth_context->send_subkey) {
krb5_free_keyblock(context, auth_context->send_subkey);
auth_context->send_subkey = NULL;
- }
+ }
retval = krb5_copy_keyblock(context, (*repl)->subkey,
- &auth_context->send_subkey);
+ &auth_context->send_subkey);
if (retval) {
krb5_free_keyblock(context, auth_context->send_subkey);
auth_context->send_subkey = NULL;
- }
+ }
}
+
/* Get remote sequence number */
auth_context->remote_seq_number = (*repl)->seq_number;
clean_scratch:
- memset(scratch.data, 0, scratch.length);
-errout:
+ memset(scratch.data, 0, scratch.length);
+
krb5_free_ap_rep(context, reply);
free(scratch.data);
return retval;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_req.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_req.c
index 425b75fba3..9a2f4589d7 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_req.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_req.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/rd_req.c
*
@@ -28,8 +27,8 @@
* krb5_rd_req()
*/
-#include <k5-int.h>
-#include <auth_con.h>
+#include "k5-int.h"
+#include "auth_con.h"
/*
* Parses a KRB_AP_REQ message, returning its contents.
@@ -45,8 +44,16 @@
*
* returns system errors, encryption errors, replay errors
*/
+
krb5_error_code KRB5_CALLCONV
krb5_rd_req(krb5_context context, krb5_auth_context *auth_context, const krb5_data *inbuf, krb5_const_principal server, krb5_keytab keytab, krb5_flags *ap_req_options, krb5_ticket **ticket)
+
+
+
+ /* XXX do we really need this */
+
+
+
{
krb5_error_code retval;
krb5_ap_req * request;
@@ -78,7 +85,7 @@ krb5_rd_req(krb5_context context, krb5_auth_context *auth_context, const krb5_da
/* Get an rcache if necessary. */
if (((*auth_context)->rcache == NULL)
&& ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME)
- && server) {
+&& server) {
if ((retval = krb5_get_server_rcache(context,
krb5_princ_component(context,server,0), &(*auth_context)->rcache)))
goto cleanup_auth_context;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_req_dec.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_req_dec.c
index 625cc8ce53..54df8db453 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_req_dec.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_req_dec.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/rd_req_dec.c
@@ -16,7 +15,7 @@
* 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
@@ -31,13 +30,13 @@
* CyberSAFE Corporation make any representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
- *
+ *
*
* krb5_rd_req_decoded()
*/
-#include <k5-int.h>
-#include <auth_con.h>
+#include "k5-int.h"
+#include "auth_con.h"
/*
* essentially the same as krb_rd_req, but uses a decoded AP_REQ as
@@ -45,24 +44,24 @@
*/
/*
* Parses a KRB_AP_REQ message, returning its contents.
- *
+ *
* server specifies the expected server's name for the ticket; if NULL, then
* any server will be accepted if the key can be found, and the caller should
* verify that the principal is something it trusts.
- *
+ *
* rcache specifies a replay detection cache used to store authenticators and
* server names
- *
+ *
* keyproc specifies a procedure to generate a decryption key for the
* ticket. If keyproc is non-NULL, keyprocarg is passed to it, and the result
* used as a decryption key. If keyproc is NULL, then fetchfrom is checked;
* if it is non-NULL, it specifies a parameter name from which to retrieve the
* decryption key. If fetchfrom is NULL, then the default key store is
* consulted.
- *
+ *
* authdat is set to point at allocated storage structures; the caller
- * should free them when finished.
- *
+ * should free them when finished.
+ *
* returns system errors, encryption errors, replay errors
*/
@@ -73,11 +72,7 @@ static krb5_error_code decrypt_authenticator
#define in_clock_skew(date) (labs((date)-currenttime) < context->clockskew)
static krb5_error_code
-krb5_rd_req_decrypt_tkt_part(
- krb5_context context,
- const krb5_ap_req * req,
- krb5_keytab keytab)
-
+krb5_rd_req_decrypt_tkt_part(krb5_context context, const krb5_ap_req *req, krb5_keytab keytab)
{
krb5_error_code retval;
krb5_enctype enctype;
@@ -85,13 +80,16 @@ krb5_rd_req_decrypt_tkt_part(
enctype = req->ticket->enc_part.enctype;
+ /* Solaris Kerberos: */
memset(&ktent, 0, sizeof(krb5_keytab_entry));
- retval = krb5_kt_get_entry(context, keytab, req->ticket->server,
- req->ticket->enc_part.kvno, enctype, &ktent);
- if (retval)
+ if ((retval = krb5_kt_get_entry(context, keytab, req->ticket->server,
+ req->ticket->enc_part.kvno,
+ enctype, &ktent)))
return retval;
+
/*
+ * Solaris Kerberos:
* If we get this far then we know that the enc types are similar,
* therefore we should change the enc type to match that of what
* we are decrypting.
@@ -99,27 +97,45 @@ krb5_rd_req_decrypt_tkt_part(
ktent.key.enctype = enctype;
retval = krb5_decrypt_tkt_part(context, &ktent.key, req->ticket);
+ /* Upon error, Free keytab entry first, then return */
(void) krb5_kt_free_entry(context, &ktent);
return retval;
}
static krb5_error_code
-krb5_rd_req_decoded_opt(
- krb5_context context,
- krb5_auth_context * auth_context,
- const krb5_ap_req * req,
- krb5_const_principal server,
- krb5_keytab keytab,
- krb5_flags * ap_req_options,
- krb5_ticket ** ticket,
- int check_valid_flag)
+krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context,
+ const krb5_ap_req *req, krb5_const_principal server,
+ krb5_keytab keytab, krb5_flags *ap_req_options,
+ krb5_ticket **ticket, int check_valid_flag)
{
krb5_error_code retval = 0;
krb5_timestamp currenttime;
-
- if (server && !krb5_principal_compare(context, server, req->ticket->server))
- return KRB5KRB_AP_WRONG_PRINC;
+ krb5_principal_data princ_data;
+
+ req->ticket->enc_part2 == NULL;
+ if (server && krb5_is_referral_realm(&server->realm)) {
+ char *realm;
+ princ_data = *server;
+ server = &princ_data;
+ retval = krb5_get_default_realm(context, &realm);
+ if (retval)
+ return retval;
+ princ_data.realm.data = realm;
+ princ_data.realm.length = strlen(realm);
+ }
+ if (server && !krb5_principal_compare(context, server, req->ticket->server)) {
+ char *found_name = 0, *wanted_name = 0;
+ if (krb5_unparse_name(context, server, &wanted_name) == 0
+ && krb5_unparse_name(context, req->ticket->server, &found_name) == 0)
+ krb5_set_error_message(context, KRB5KRB_AP_WRONG_PRINC,
+ "Wrong principal in request (found %s, wanted %s)",
+ found_name, wanted_name);
+ krb5_free_unparsed_name(context, wanted_name);
+ krb5_free_unparsed_name(context, found_name);
+ retval = KRB5KRB_AP_WRONG_PRINC;
+ goto cleanup;
+ }
/* if (req->ap_options & AP_OPTS_USE_SESSION_KEY)
do we need special processing here ? */
@@ -128,18 +144,18 @@ krb5_rd_req_decoded_opt(
if ((*auth_context)->keyblock) { /* User to User authentication */
if ((retval = krb5_decrypt_tkt_part(context, (*auth_context)->keyblock,
req->ticket)))
- return retval;
+goto cleanup;
krb5_free_keyblock(context, (*auth_context)->keyblock);
(*auth_context)->keyblock = NULL;
} else {
if ((retval = krb5_rd_req_decrypt_tkt_part(context, req, keytab)))
- return retval;
+ goto cleanup;
}
/* XXX this is an evil hack. check_valid_flag is set iff the call
is not from inside the kdc. we can use this to determine which
key usage to use */
- if ((retval = decrypt_authenticator(context, req,
+ if ((retval = decrypt_authenticator(context, req,
&((*auth_context)->authentp),
check_valid_flag)))
goto cleanup;
@@ -150,8 +166,8 @@ krb5_rd_req_decoded_opt(
goto cleanup;
}
- if ((*auth_context)->remote_addr &&
- !krb5_address_search(context, (*auth_context)->remote_addr,
+ if ((*auth_context)->remote_addr &&
+ !krb5_address_search(context, (*auth_context)->remote_addr,
req->ticket->enc_part2->caddrs)) {
retval = KRB5KRB_AP_ERR_BADADDR;
goto cleanup;
@@ -163,7 +179,7 @@ krb5_rd_req_decoded_opt(
/* Single hop cross-realm tickets only */
- {
+ {
krb5_transited *trans = &(req->ticket->enc_part2->transited);
/* If the transited list is empty, then we have at most one hop */
@@ -175,17 +191,17 @@ krb5_rd_req_decoded_opt(
/* No cross-realm tickets */
- {
+ {
char * lrealm;
krb5_data * realm;
krb5_transited * trans;
-
+
realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
trans = &(req->ticket->enc_part2->transited);
/*
- * If the transited list is empty, then we have at most one hop
- * So we also have to check that the client's realm is the local one
+ * If the transited list is empty, then we have at most one hop
+ * So we also have to check that the client's realm is the local one
*/
krb5_get_default_realm(context, &lrealm);
if ((trans->tr_contents.data && trans->tr_contents.data[0]) ||
@@ -199,25 +215,25 @@ krb5_rd_req_decoded_opt(
#else
/* Hierarchical Cross-Realm */
-
+
{
- krb5_data * realm;
- krb5_transited * trans;
-
+ krb5_data * realm;
+ krb5_transited * trans;
+
realm = krb5_princ_realm(context, req->ticket->enc_part2->client);
trans = &(req->ticket->enc_part2->transited);
/*
- * If the transited list is not empty, then check that all realms
- * transited are within the hierarchy between the client's realm
- * and the local realm.
- */
+ * If the transited list is not empty, then check that all realms
+ * transited are within the hierarchy between the client's realm
+ * and the local realm.
+ */
if (trans->tr_contents.data && trans->tr_contents.data[0]) {
- retval = krb5_check_transited_list(context, &(trans->tr_contents),
- realm,
- krb5_princ_realm (context,
- server));
- }
+ retval = krb5_check_transited_list(context, &(trans->tr_contents),
+ realm,
+ krb5_princ_realm (context,
+ server));
+ }
}
#endif
@@ -269,15 +285,21 @@ krb5_rd_req_decoded_opt(
/*EMPTY*/
;
} else if ((*auth_context)->permitted_etypes == NULL) {
+ int etype;
/* check against the default set */
if ((!krb5_is_permitted_enctype(context,
- req->ticket->enc_part.enctype)) ||
+ etype = req->ticket->enc_part.enctype)) ||
(!krb5_is_permitted_enctype(context,
- req->ticket->enc_part2->session->enctype)) ||
+ etype = req->ticket->enc_part2->session->enctype)) ||
(((*auth_context)->authentp->subkey) &&
!krb5_is_permitted_enctype(context,
- (*auth_context)->authentp->subkey->enctype))) {
+ etype = (*auth_context)->authentp->subkey->enctype))) {
+ char enctype_name[30];
retval = KRB5_NOPERM_ETYPE;
+ if (krb5_enctype_to_string(etype, enctype_name, sizeof(enctype_name)) == 0)
+ krb5_set_error_message(context, retval,
+ "Encryption type %s not permitted",
+ enctype_name);
goto cleanup;
}
} else {
@@ -289,7 +311,13 @@ krb5_rd_req_decoded_opt(
req->ticket->enc_part.enctype)
break;
if (!(*auth_context)->permitted_etypes[i]) {
+ char enctype_name[30];
retval = KRB5_NOPERM_ETYPE;
+ if (krb5_enctype_to_string(req->ticket->enc_part.enctype,
+ enctype_name, sizeof(enctype_name)) == 0)
+ krb5_set_error_message(context, retval,
+ "Encryption type %s not permitted",
+ enctype_name);
goto cleanup;
}
@@ -298,7 +326,13 @@ krb5_rd_req_decoded_opt(
req->ticket->enc_part2->session->enctype)
break;
if (!(*auth_context)->permitted_etypes[i]) {
+ char enctype_name[30];
retval = KRB5_NOPERM_ETYPE;
+ if (krb5_enctype_to_string(req->ticket->enc_part2->session->enctype,
+ enctype_name, sizeof(enctype_name)) == 0)
+ krb5_set_error_message(context, retval,
+ "Encryption type %s not permitted",
+ enctype_name);
goto cleanup;
}
@@ -308,16 +342,22 @@ krb5_rd_req_decoded_opt(
(*auth_context)->authentp->subkey->enctype)
break;
if (!(*auth_context)->permitted_etypes[i]) {
+ char enctype_name[30];
retval = KRB5_NOPERM_ETYPE;
+ if (krb5_enctype_to_string((*auth_context)->authentp->subkey->enctype,
+ enctype_name,
+ sizeof(enctype_name)) == 0)
+ krb5_set_error_message(context, retval,
+ "Encryption type %s not permitted",
+ enctype_name);
goto cleanup;
}
}
}
(*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number;
-
if ((*auth_context)->authentp->subkey) {
-
+ /* Solaris Kerberos */
if ((*auth_context)->recv_subkey != NULL) {
krb5_free_keyblock(context, (*auth_context)->recv_subkey);
(*auth_context)->recv_subkey = NULL;
@@ -327,24 +367,24 @@ krb5_rd_req_decoded_opt(
(*auth_context)->authentp->subkey,
&((*auth_context)->recv_subkey))))
goto cleanup;
-
+ /* Solaris Kerberos */
if ((*auth_context)->send_subkey != NULL) {
krb5_free_keyblock(context, (*auth_context)->send_subkey);
(*auth_context)->send_subkey = NULL;
}
retval = krb5_copy_keyblock(context, (*auth_context)->authentp->subkey,
- &((*auth_context)->send_subkey));
+ &((*auth_context)->send_subkey));
if (retval) {
- krb5_free_keyblock(context, (*auth_context)->recv_subkey);
- (*auth_context)->recv_subkey = NULL;
- goto cleanup;
+ krb5_free_keyblock(context, (*auth_context)->recv_subkey);
+ (*auth_context)->recv_subkey = NULL;
+ goto cleanup;
}
} else {
(*auth_context)->recv_subkey = 0;
(*auth_context)->send_subkey = 0;
}
-
+ /* Solaris Kerberos */
if ((*auth_context)->keyblock != NULL) {
krb5_free_keyblock(context, (*auth_context)->keyblock);
(*auth_context)->keyblock = NULL;
@@ -354,13 +394,13 @@ krb5_rd_req_decoded_opt(
goto cleanup;
/*
- * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used
+ * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used
* then the default sequence number is the one's complement of the
* sequence number sent ot us.
*/
- if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) &&
+ if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) &&
(*auth_context)->remote_seq_number) {
- (*auth_context)->local_seq_number ^=
+ (*auth_context)->local_seq_number ^=
(*auth_context)->remote_seq_number;
}
@@ -370,48 +410,44 @@ krb5_rd_req_decoded_opt(
if (ap_req_options)
*ap_req_options = req->ap_options;
retval = 0;
-
+
cleanup:
+ if (server == &princ_data)
+ krb5_free_default_realm(context, princ_data.realm.data);
if (retval) {
/* only free if we're erroring out...otherwise some
applications will need the output. */
- krb5_free_enc_tkt_part(context, req->ticket->enc_part2);
+ if (req->ticket->enc_part2)
+ krb5_free_enc_tkt_part(context, req->ticket->enc_part2);
req->ticket->enc_part2 = NULL;
}
return retval;
}
krb5_error_code
-krb5_rd_req_decoded(
- krb5_context context,
- krb5_auth_context * auth_context,
- const krb5_ap_req * req,
- krb5_const_principal server,
- krb5_keytab keytab,
- krb5_flags * ap_req_options,
- krb5_ticket ** ticket)
+krb5_rd_req_decoded(krb5_context context, krb5_auth_context *auth_context,
+ const krb5_ap_req *req, krb5_const_principal server,
+ krb5_keytab keytab, krb5_flags *ap_req_options,
+ krb5_ticket **ticket)
{
krb5_error_code retval;
retval = krb5_rd_req_decoded_opt(context, auth_context,
- req, server, keytab,
+ req, server, keytab,
ap_req_options, ticket,
1); /* check_valid_flag */
return retval;
}
krb5_error_code
-krb5_rd_req_decoded_anyflag(
- krb5_context context,
- krb5_auth_context * auth_context,
- const krb5_ap_req * req,
- krb5_const_principal server,
- krb5_keytab keytab,
- krb5_flags * ap_req_options,
- krb5_ticket ** ticket)
+krb5_rd_req_decoded_anyflag(krb5_context context,
+ krb5_auth_context *auth_context,
+ const krb5_ap_req *req,
+ krb5_const_principal server, krb5_keytab keytab,
+ krb5_flags *ap_req_options, krb5_ticket **ticket)
{
krb5_error_code retval;
retval = krb5_rd_req_decoded_opt(context, auth_context,
- req, server, keytab,
+ req, server, keytab,
ap_req_options, ticket,
0); /* don't check_valid_flag */
return retval;
@@ -419,11 +455,8 @@ krb5_rd_req_decoded_anyflag(
/*ARGSUSED*/
static krb5_error_code
-decrypt_authenticator(
- krb5_context context,
- const krb5_ap_req *request,
- krb5_authenticator **authpp,
- int is_ap_req)
+decrypt_authenticator(krb5_context context, const krb5_ap_req *request,
+ krb5_authenticator **authpp, int is_ap_req)
{
krb5_authenticator *local_auth;
krb5_error_code retval;
@@ -436,11 +469,10 @@ decrypt_authenticator(
if (!(scratch.data = malloc(scratch.length)))
return(ENOMEM);
- retval = krb5_c_decrypt(context, sesskey,
+ if ((retval = krb5_c_decrypt(context, sesskey,
is_ap_req?KRB5_KEYUSAGE_AP_REQ_AUTH:
KRB5_KEYUSAGE_TGS_REQ_AUTH, 0,
- &request->authenticator, &scratch);
- if (retval) {
+ &request->authenticator, &scratch))) {
free(scratch.data);
return(retval);
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_safe.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_safe.c
index f07523a9f2..17d3046478 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_safe.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/rd_safe.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/rd_safe.c
@@ -15,7 +14,7 @@
* 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
@@ -29,14 +28,14 @@
* 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.
- *
+ *
*
* krb5_rd_safe()
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include "cleanup.h"
-#include <auth_con.h>
+#include "auth_con.h"
#define in_clock_skew(date) (labs((date)-currenttime) < context->clockskew)
@@ -45,7 +44,7 @@
data in *outbuf.
key specifies the key to be used for decryption of the message.
-
+
sender_addr and recv_addr specify the full addresses (host and port) of
the sender and receiver.
@@ -64,15 +63,18 @@ krb5_rd_safe_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyb
krb5_data *scratch;
krb5_boolean valid;
+ /* Solaris Kerberos */
KRB5_LOG0(KRB5_INFO, "krb5_rd_safe_basic() start");
- if (!krb5_is_krb_safe(inbuf)){
+ if (!krb5_is_krb_safe(inbuf)) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_rd_safe_basic() end, error retval=%d",
KRB5KRB_AP_ERR_MSG_TYPE);
return KRB5KRB_AP_ERR_MSG_TYPE;
}
- if ((retval = decode_krb5_safe_with_body(inbuf, &message, &safe_body))){
+ if ((retval = decode_krb5_safe_with_body(inbuf, &message, &safe_body))) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_rd_safe_basic() end, error retval=%d",
retval);
return retval;
@@ -80,6 +82,7 @@ krb5_rd_safe_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyb
if (!krb5_c_valid_cksumtype(message->checksum->checksum_type)) {
retval = KRB5_PROG_SUMTYPE_NOSUPP;
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_rd_safe_basic() error retval=%d",
retval);
goto cleanup;
@@ -87,6 +90,7 @@ krb5_rd_safe_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyb
if (!krb5_c_is_coll_proof_cksum(message->checksum->checksum_type) ||
!krb5_c_is_keyed_cksum(message->checksum->checksum_type)) {
retval = KRB5KRB_AP_ERR_INAPP_CKSUM;
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_rd_safe_basic() error retval=%d",
retval);
goto cleanup;
@@ -94,6 +98,7 @@ krb5_rd_safe_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyb
if (!krb5_address_compare(context, sender_addr, message->s_address)) {
retval = KRB5KRB_AP_ERR_BADADDR;
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_rd_safe_basic() error retval=%d",
retval);
goto cleanup;
@@ -103,6 +108,7 @@ krb5_rd_safe_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyb
if (recv_addr) {
if (!krb5_address_compare(context, recv_addr, message->r_address)) {
retval = KRB5KRB_AP_ERR_BADADDR;
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_rd_safe_basic() error retval=%d",
retval);
goto cleanup;
@@ -110,15 +116,16 @@ krb5_rd_safe_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyb
} else {
krb5_address **our_addrs;
- if ((retval = krb5_os_localaddr(context, &our_addrs))){
+ if ((retval = krb5_os_localaddr(context, &our_addrs))) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_rd_safe_basic() error retval=%d",
retval);
goto cleanup;
}
-
if (!krb5_address_search(context, message->r_address, our_addrs)) {
krb5_free_addresses(context, our_addrs);
retval = KRB5KRB_AP_ERR_BADADDR;
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_rd_safe_basic() error retval=%d",
retval);
goto cleanup;
@@ -142,34 +149,36 @@ krb5_rd_safe_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyb
message->checksum = &our_cksum;
- if ((retval = encode_krb5_safe_with_body(message, &safe_body, &scratch))){
+ if ((retval = encode_krb5_safe_with_body(message, &safe_body, &scratch))) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_rd_safe_basic() error retval=%d",
retval);
goto cleanup;
}
message->checksum = his_cksum;
-
+
retval = krb5_c_verify_checksum(context, keyblock,
KRB5_KEYUSAGE_KRB_SAFE_CKSUM,
scratch, his_cksum, &valid);
(void) memset((char *)scratch->data, 0, scratch->length);
krb5_free_data(context, scratch);
-
+
if (!valid) {
/*
- * Checksum over only the KRB-SAFE-BODY, like RFC 1510 says, in
+ * Checksum over only the KRB-SAFE-BODY, like RFC 1510 says, in
* case someone actually implements it correctly.
*/
retval = krb5_c_verify_checksum(context, keyblock,
- KRB5_KEYUSAGE_KRB_SAFE_CKSUM,
- &safe_body, his_cksum, &valid);
+ KRB5_KEYUSAGE_KRB_SAFE_CKSUM,
+ &safe_body, his_cksum, &valid);
if (!valid) {
- retval = KRB5KRB_AP_ERR_MODIFIED;
- KRB5_LOG(KRB5_ERR, "krb5_rd_safe_basic() error retval=%d",
+ retval = KRB5KRB_AP_ERR_MODIFIED;
+ /* Solaris Kerberos */
+ KRB5_LOG(KRB5_ERR, "krb5_rd_safe_basic() error retval=%d",
retval);
- goto cleanup;
+ goto cleanup;
}
}
@@ -180,9 +189,10 @@ krb5_rd_safe_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyb
*outbuf = message->user_data;
message->user_data.data = NULL;
retval = 0;
-
+
cleanup:
krb5_free_safe(context, message);
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_INFO, "krb5_rd_safe_basic() end, retval=%d",
retval);
return retval;
@@ -197,12 +207,12 @@ krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, const krb5_da
if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
(auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
- (outdata == NULL))
+ (outdata == NULL))
/* Need a better error */
return KRB5_RC_REQUIRED;
if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
- (auth_context->rcache == NULL))
+ (auth_context->rcache == NULL))
return KRB5_RC_REQUIRED;
/* Get keyblock */
@@ -219,7 +229,7 @@ krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, const krb5_da
if (auth_context->local_addr) {
if (auth_context->local_port) {
if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
- auth_context->local_port,
+ auth_context->local_port,
&local_fulladdr))){
CLEANUP_PUSH(local_fulladdr.contents, free);
plocal_fulladdr = &local_fulladdr;
@@ -234,7 +244,7 @@ krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, const krb5_da
if (auth_context->remote_addr) {
if (auth_context->remote_port) {
if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
- auth_context->remote_port,
+ auth_context->remote_port,
&remote_fulladdr))){
CLEANUP_PUSH(remote_fulladdr.contents, free);
premote_fulladdr = &remote_fulladdr;
@@ -269,14 +279,14 @@ krb5_rd_safe(krb5_context context, krb5_auth_context auth_context, const krb5_da
goto error;
}
- if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr,
+ if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr,
"_safe", &replay.client)))
goto error;
replay.server = ""; /* XXX */
replay.cusec = replaydata.usec;
replay.ctime = replaydata.timestamp;
- if ((retval = krb5_rc_store(context, auth_context->rcache, &replay)) != 0) {
+ if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
krb5_xfree(replay.client);
goto error;
}
@@ -307,3 +317,4 @@ error:
return retval;
}
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/recvauth.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/recvauth.c
index b09e4101de..6a5973f8ec 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/recvauth.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/recvauth.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/recvauth.c
@@ -15,7 +14,7 @@
* 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
@@ -29,15 +28,14 @@
* 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.
- *
+ *
*
* convenience sendauth/recvauth functions
*/
-#define NEED_SOCKETS
-#include <k5-int.h>
-#include <auth_con.h>
-#include <com_err.h>
+#include "k5-int.h"
+#include "auth_con.h"
+#include "com_err.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
@@ -159,14 +157,14 @@ recvauth_common(krb5_context context,
* Setup the replay cache.
*/
if (server) {
- problem = krb5_get_server_rcache(context,
+ problem = krb5_get_server_rcache(context,
krb5_princ_component(context, server, 0), &rcache);
} else {
null_server.length = 7;
null_server.data = "default";
problem = krb5_get_server_rcache(context, &null_server, &rcache);
}
- if (!problem)
+ if (!problem)
problem = krb5_auth_con_setrcache(context, *auth_context, rcache);
local_rcache = 1;
}
@@ -187,7 +185,7 @@ recvauth_common(krb5_context context,
memset((char *)&error, 0, sizeof(error));
krb5_us_timeofday(context, &error.stime, &error.susec);
- if(server)
+ if(server)
error.server = server;
else {
/* If this fails - ie. ENOMEM we are hosed
@@ -206,12 +204,13 @@ recvauth_common(krb5_context context,
goto cleanup;
}
strcpy(error.text.data, message);
+ /* Solaris Kerberos */
if ((retval = krb5_mk_error(context, &error, &outbuf)) != 0) {
free(error.text.data);
goto cleanup;
}
free(error.text.data);
- if(need_error_free)
+ if(need_error_free)
krb5_free_principal(context, error.server);
} else {
@@ -243,6 +242,7 @@ cleanup:;
if (local_authcon) {
krb5_auth_con_free(context, *auth_context);
} else if (local_rcache && rcache != NULL) {
+ /* Solaris Kerberos */
(void) krb5_rc_close(context, rcache);
krb5_auth_con_setrcache(context, *auth_context, NULL);
}
@@ -253,7 +253,7 @@ cleanup:;
krb5_error_code KRB5_CALLCONV
krb5_recvauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, char *appl_version, krb5_principal server, krb5_int32 flags, krb5_keytab keytab, krb5_ticket **ticket)
{
- return recvauth_common(context, auth_context, fd, appl_version,
+ return recvauth_common (context, auth_context, fd, appl_version,
server, flags, keytab, ticket, 0);
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/send_tgs.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/send_tgs.c
index 6fd00f6ae4..c08c6b9bc3 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/send_tgs.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/send_tgs.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/send_tgs.c
@@ -15,7 +14,7 @@
* 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
@@ -29,34 +28,34 @@
* 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.
- *
+ *
*
* krb5_send_tgs()
*/
-#include <k5-int.h>
+#include "k5-int.h"
/*
Sends a request to the TGS and waits for a response.
options is used for the options in the KRB_TGS_REQ.
timestruct values are used for from, till, rtime " " "
- enctype is used for enctype " " ", and to encrypt the authorization data,
+ enctype is used for enctype " " ", and to encrypt the authorization data,
sname is used for sname " " "
addrs, if non-NULL, is used for addresses " " "
authorization_dat, if non-NULL, is used for authorization_dat " " "
second_ticket, if required by options, is used for the 2nd ticket in the req.
in_cred is used for the ticket & session key in the KRB_AP_REQ header " " "
(the KDC realm is extracted from in_cred->server's realm)
-
+
The response is placed into *rep.
rep->response.data is set to point at allocated storage which should be
freed by the caller when finished.
returns system errors
*/
-static krb5_error_code
+static krb5_error_code
krb5_send_tgs_basic(krb5_context context, krb5_data *in_data, krb5_creds *in_cred, krb5_data *outbuf)
-{
+{
krb5_error_code retval;
krb5_checksum checksum;
krb5_authenticator authent;
@@ -65,11 +64,10 @@ krb5_send_tgs_basic(krb5_context context, krb5_data *in_data, krb5_creds *in_cre
krb5_data * toutbuf;
/* Generate checksum */
- retval = krb5_c_make_checksum(context, context->kdc_req_sumtype,
+ if ((retval = krb5_c_make_checksum(context, context->kdc_req_sumtype,
&in_cred->keyblock,
KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
- in_data, &checksum);
- if (retval) {
+ in_data, &checksum))) {
free(checksum.contents);
return(retval);
}
@@ -103,7 +101,7 @@ krb5_send_tgs_basic(krb5_context context, krb5_data *in_data, krb5_creds *in_cre
/* Cleanup scratch and scratch data */
goto cleanup_data;
- /* call the encryption routine */
+ /* call the encryption routine */
if ((retval = krb5_encrypt_helper(context, &in_cred->keyblock,
KRB5_KEYUSAGE_TGS_REQ_AUTH,
scratch, &request.authenticator)))
@@ -113,7 +111,7 @@ krb5_send_tgs_basic(krb5_context context, krb5_data *in_data, krb5_creds *in_cre
*outbuf = *toutbuf;
krb5_xfree(toutbuf);
-cleanup:
+
memset(request.authenticator.ciphertext.data, 0,
request.authenticator.ciphertext.length);
free(request.authenticator.ciphertext.data);
@@ -125,7 +123,6 @@ cleanup_data:
memset(scratch->data, 0, scratch->length);
free(scratch->data);
-cleanup_scratch:
free(scratch);
return retval;
@@ -149,7 +146,7 @@ krb5_send_tgs(krb5_context context, krb5_flags kdcoptions,
krb5_pa_data ap_req_padata;
int tcp_only = 0, use_master;
- /*
+ /*
* in_creds MUST be a valid credential NOT just a partially filled in
* place holder for us to get credentials for the caller.
*/
@@ -180,10 +177,10 @@ krb5_send_tgs(krb5_context context, krb5_flags kdcoptions,
&scratch)))
return(retval);
- retval = krb5_encrypt_helper(context, &in_cred->keyblock,
+ if ((retval = krb5_encrypt_helper(context, &in_cred->keyblock,
KRB5_KEYUSAGE_TGS_REQ_AD_SESSKEY,
- scratch, &tgsreq.authorization_data);
- if (retval) {
+ scratch,
+ &tgsreq.authorization_data))) {
krb5_xfree(tgsreq.authorization_data.ciphertext.data);
krb5_free_data(context, scratch);
return retval;
@@ -237,7 +234,7 @@ krb5_send_tgs(krb5_context context, krb5_flags kdcoptions,
krb5_pa_data * const * counter;
register unsigned int i = 0;
for (counter = padata; *counter; counter++, i++);
- combined_padata = (krb5_pa_data **)malloc(i+2);
+ combined_padata = malloc((i+2) * sizeof(*combined_padata));
if (!combined_padata) {
krb5_xfree(ap_req_padata.contents);
retval = ENOMEM;
@@ -279,6 +276,7 @@ send_again:
if (!tcp_only) {
krb5_error *err_reply;
retval = decode_krb5_error(&rep->response, &err_reply);
+ /* Solaris Kerberos */
if (retval == 0) {
if (err_reply->error == KRB_ERR_RESPONSE_TOO_BIG) {
tcp_only = 1;
@@ -299,7 +297,7 @@ send_again:
krb5_free_data(context, scratch);
send_tgs_error_2:;
- if (sec_ticket)
+ if (sec_ticket)
krb5_free_ticket(context, sec_ticket);
send_tgs_error_1:;
@@ -307,10 +305,9 @@ send_tgs_error_1:;
krb5_xfree(tgsreq.ktype);
if (tgsreq.authorization_data.ciphertext.data) {
memset(tgsreq.authorization_data.ciphertext.data, 0,
- tgsreq.authorization_data.ciphertext.length);
+ tgsreq.authorization_data.ciphertext.length);
krb5_xfree(tgsreq.authorization_data.ciphertext.data);
}
-
return retval;
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/sendauth.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/sendauth.c
index 5498150ba3..f3f51d32f6 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/sendauth.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/sendauth.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/sendauth.c
@@ -15,7 +14,7 @@
* 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
@@ -29,16 +28,15 @@
* 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.
- *
+ *
*
* convenience sendauth/recvauth functions
*/
-#define NEED_SOCKETS
-#include <k5-int.h>
-#include <com_err.h>
-#include <auth_con.h>
+#include "k5-int.h"
+#include "com_err.h"
+#include "auth_con.h"
#include <errno.h>
#include <stdio.h>
#include <string.h>
@@ -50,8 +48,8 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe
{
krb5_octet result;
krb5_creds creds;
- krb5_creds * credsp = NULL;
- krb5_creds * credspout = NULL;
+ krb5_creds * credsp = NULL;
+ krb5_creds * credspout = NULL;
krb5_error_code retval = 0;
krb5_data inbuf, outbuf;
int len;
@@ -64,7 +62,7 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe
* First, send over the length of the sendauth version string;
* then, we send over the sendauth version. Next, we send
* over the length of the application version strings followed
- * by the string itself.
+ * by the string itself.
*/
outbuf.length = strlen(sendauth_version) + 1;
outbuf.data = (char *) sendauth_version;
@@ -103,6 +101,7 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe
if (!in_creds || !in_creds->ticket.length) {
if (ccache)
use_ccache = ccache;
+ /* Solaris Kerberos */
else if ((retval = krb5int_cc_default(context, &use_ccache)) != 0)
goto error_return;
}
@@ -111,7 +110,7 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe
&creds.server)))
goto error_return;
if (client)
- retval = krb5_copy_principal(context, client,
+ retval = krb5_copy_principal(context, client,
&creds.client);
else
retval = krb5_cc_get_principal(context, use_ccache,
@@ -128,6 +127,7 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe
in_creds = &creds;
}
if (!in_creds->ticket.length) {
+ /* Solaris Kerberos */
if ((retval = krb5_get_credentials(context, 0,
use_ccache, in_creds, &credsp)) != 0)
goto error_return;
@@ -142,22 +142,27 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe
not to guarantee randomness, but to make it less likely
that multiple sessions could pick the same subkey. */
char rnd_data[1024];
- size_t len;
+ GETPEERNAME_ARG3_TYPE len2;
krb5_data d;
d.length = sizeof (rnd_data);
d.data = rnd_data;
- len = sizeof (rnd_data);
- if (getpeername (*(int*)fd, (struct sockaddr *) rnd_data, &len) == 0) {
- d.length = len;
+ len2 = sizeof (rnd_data);
+ if (getpeername (*(int*)fd, (GETPEERNAME_ARG2_TYPE *) rnd_data,
+ &len2) == 0) {
+ d.length = len2;
+ /* Solaris Kerberos */
(void) krb5_c_random_seed (context, &d);
}
- len = sizeof (rnd_data);
- if (getsockname (*(int*)fd, (struct sockaddr *) rnd_data, &len) == 0) {
- d.length = len;
+ len2 = sizeof (rnd_data);
+ if (getsockname (*(int*)fd, (GETSOCKNAME_ARG2_TYPE *) rnd_data,
+ &len2) == 0) {
+ d.length = len2;
+ /* Solaris Kerberos */
(void) krb5_c_random_seed (context, &d);
}
}
+ /* Solaris Kerberos */
if ((retval = krb5_mk_req_extended(context, auth_context,
ap_req_options, in_data, credsp,
&outbuf)) != 0)
@@ -178,11 +183,13 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe
* authentication was rejected, and we need to return the
* error structure.
*/
+ /* Solaris Kerberos */
if ((retval = krb5_read_message(context, fd, &inbuf)) != 0)
goto error_return;
if (inbuf.length) {
if (error) {
+ /* Solaris Kerberos */
if ((retval = krb5_rd_error(context, &inbuf, error)) != 0) {
krb5_xfree(inbuf.data);
goto error_return;
@@ -199,10 +206,11 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe
*/
if ((ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) {
krb5_ap_rep_enc_part *repl = 0;
-
+ /* Solaris Kerberos */
if ((retval = krb5_read_message(context, fd, &inbuf)) != 0)
goto error_return;
+ /* Solaris Kerberos */
if ((retval = krb5_rd_rep(context, *auth_context, &inbuf,
&repl)) != 0) {
if (repl)
@@ -216,7 +224,7 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe
* If the user wants to look at the AP_REP message,
* copy it for him
*/
- if (rep_result)
+ if (rep_result)
*rep_result = repl;
else
krb5_free_ap_rep_enc_part(context, repl);
@@ -230,8 +238,11 @@ krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointe
error_return:
krb5_free_cred_contents(context, &creds);
if (credspout != NULL)
- krb5_free_creds(context, credspout);
+ krb5_free_creds(context, credspout);
+ /* Solaris Kerberos */
if (!ccache && use_ccache)
(void) krb5_cc_close(context, use_ccache);
return(retval);
}
+
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/set_realm.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/set_realm.c
index d6f856faf3..08d71b9131 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/set_realm.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/set_realm.c
@@ -1,6 +1,5 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
@@ -38,12 +37,12 @@ krb5_set_principal_realm(krb5_context context, krb5_principal principal, const c
char *newrealm;
if (!realm || !*realm)
- return EINVAL;
+ return EINVAL; /* Solaris Kerberos */
length = strlen(realm);
newrealm = malloc(length+1); /* Include room for the null */
if (!newrealm)
- return ENOMEM;
+ return ENOMEM; /* Solaris Kerberos */
strcpy(newrealm, realm);
(void) krb5_xfree(krb5_princ_realm(context,principal)->data);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/srv_rcache.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/srv_rcache.c
index 15cfc31871..645d815a75 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/srv_rcache.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/srv_rcache.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/srv_rcache.c
@@ -15,7 +14,7 @@
* 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
@@ -29,15 +28,16 @@
* 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.
- *
+ *
*
* Allocate & prepare a default replay cache for a server.
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include <ctype.h>
#include <stdio.h>
+/* Macro for valid RC name characters*/
#define isvalidrcname(x) ((!ispunct(x))&&isgraph(x))
krb5_error_code KRB5_CALLCONV
krb5_get_server_rcache(krb5_context context, const krb5_data *piece,
@@ -57,12 +57,12 @@ krb5_get_server_rcache(krb5_context context, const krb5_data *piece,
if (piece == NULL)
return ENOMEM;
-
+
cachetype = krb5_rc_default_type(context);
/*
- * Solaris: Check to see if something other than the default replay cache
- * name will be used. If so then skip over the construction of
+ * Solaris Kerberos: Check to see if something other than the default replay
+ * cache name will be used. If so then skip over the construction of
* said name.
*/
if ((def_env = krb5_rc_default_name(context)) != 0) {
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/str_conv.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/str_conv.c
index 33fdecb546..bd4664a865 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/str_conv.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/str_conv.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/kadm/str_conv.c
@@ -70,7 +69,8 @@ struct salttype_lookup_entry {
/*
* Lookup tables.
*/
-#include <krb5/kdb.h>
+
+#include "kdb.h"
static const struct salttype_lookup_entry salttype_table[] = {
/* salt type input specifier output string */
/*----------------------------- --------------- ---------------*/
@@ -161,18 +161,14 @@ krb5_string_to_timestamp(char *string, krb5_timestamp *timestampp)
struct tm timebuf;
time_t now, ret_time;
char *s;
-/*
- * Solaris Kerberos:
- * The format strings shouldn't conflict with SCCS keywords
- */
static const char * const atime_format_table[] = {
- "%Y" "%m" "%d" "%H" "%M" "%S", /* yyyymmddhhmmss */
+ "%Y%m%d%H%M%S", /* yyyymmddhhmmss */
"%Y.%m.%d.%H.%M.%S", /* yyyy.mm.dd.hh.mm.ss */
- "%y" "%m" "%d" "%H" "%M" "%S", /* yymmddhhmmss */
+ "%y%m%d%H%M%S", /* yymmddhhmmss */
"%y.%m.%d.%H.%M.%S", /* yy.mm.dd.hh.mm.ss */
- "%y" "%m" "%d" "%H" "%M", /* yymmddhhmm */
- "%H" "%M" "%S", /* hhmmss */
- "%H" "%M", /* hhmm */
+ "%y%m%d%H%M", /* yymmddhhmm */
+ "%H%M%S", /* hhmmss */
+ "%H%M", /* hhmm */
"%T", /* hh:mm:ss */
"%R", /* hh:mm */
/* The following not really supported unless native strptime present */
@@ -279,6 +275,7 @@ krb5_timestamp_to_sfstring(krb5_timestamp timestamp, char *buffer, size_t buflen
return((ndone) ? 0 : ENOMEM);
}
+/* Solaris Kerberos */
#ifdef SUNW_INC_DEAD_CODE
/* relative time (delta-t) conversions */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/tgtname.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/tgtname.c
index 2df606adb6..4ca2416233 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/tgtname.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/tgtname.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/tgtname.c
*
@@ -17,7 +16,10 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/valid_times.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/valid_times.c
index 4da220ae31..9c53d7d919 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/valid_times.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/valid_times.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/krb/valid_times.c
*
@@ -17,7 +16,10 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
@@ -34,9 +36,8 @@
* field in a krb5_ticket.
*/
-krb5_error_code krb5_validate_times(context, times)
- krb5_context context;
- krb5_ticket_times * times;
+krb5_error_code
+krb5_validate_times(krb5_context context, krb5_ticket_times *times)
{
krb5_timestamp currenttime, starttime;
krb5_error_code retval;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/vfy_increds.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/vfy_increds.c
index e86e2eb49c..d3720d3eaa 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/vfy_increds.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/krb/vfy_increds.c
@@ -1,12 +1,12 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include "int-proto.h"
+/* Solaris Kerberos */
extern krb5_error_code krb5_libdefault_boolean();
static krb5_error_code
@@ -18,14 +18,18 @@ krb5_cc_copy_creds_except(krb5_context context, krb5_ccache incc, krb5_ccache ou
krb5_creds creds;
flags = 0; /* turns off OPENCLOSE mode */
+ /* Solaris Kerberos */
if ((code = krb5_cc_set_flags(context, incc, flags)) != NULL)
return(code);
+ /* Solaris Kerberos */
if ((code = krb5_cc_set_flags(context, outcc, flags)) != NULL)
return(code);
+ /* Solaris Kerberos */
if ((code = krb5_cc_start_seq_get(context, incc, &cur)) != NULL)
goto cleanup;
+ /* Solaris Kerberos */
while ((code = krb5_cc_next_cred(context, incc, &cur, &creds)) == NULL) {
if (krb5_principal_compare(context, princ, creds.server))
continue;
@@ -44,11 +48,13 @@ krb5_cc_copy_creds_except(krb5_context context, krb5_ccache incc, krb5_ccache ou
cleanup:
flags = KRB5_TC_OPENCLOSE;
+ /* Solaris Kerberos */
if (code)
(void) krb5_cc_set_flags(context, incc, flags);
else
code = krb5_cc_set_flags(context, incc, flags);
+ /* Solaris Kerberos */
if (code)
(void) krb5_cc_set_flags(context, outcc, flags);
else
@@ -83,6 +89,7 @@ krb5_verify_init_creds(krb5_context context,
authcon = NULL;
ap_req.data = NULL;
+ /* Solaris Kerberos */
if (server_arg)
server = server_arg;
else if (ret = krb5_sname_to_principal(context, NULL, NULL,
@@ -101,12 +108,15 @@ krb5_verify_init_creds(krb5_context context,
ret = krb5_kt_default(context, &keytab);
}
- /* Warning: be very, very careful when modifying the logic here */
+ /*
+ * Solaris Kerberos:
+ * Warning: be very, very careful when modifying the logic here
+ */
if (keytab == NULL ||
(ret = krb5_kt_get_entry(context, keytab, server, 0, 0, &kte))) {
/* this means there is no keying material. This is ok, as long as
it is not prohibited by the configuration */
-
+ /* Solaris Kerberos */
int nofail = 1; /* Solaris Kerberos: default return error if keytab problems */
if (options &&
@@ -115,6 +125,7 @@ krb5_verify_init_creds(krb5_context context,
nofail = options->ap_req_nofail;
} else {
/*
+ * Solaris Kerberos:
* Check verify_ap_req_nofail if set in config file. Note this logic
* assumes that krb5_libdefault_boolean will not set nofail to a
* default value if verify_ap_req_nofail is not explictly set in
@@ -139,7 +150,7 @@ krb5_verify_init_creds(krb5_context context,
if (krb5_principal_compare(context, server, creds->server)) {
/* make an ap_req */
if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, creds,
- &ap_req)))
+ &ap_req)))
goto cleanup;
} else {
/* this is unclean, but it's the easiest way without ripping the
@@ -153,10 +164,11 @@ krb5_verify_init_creds(krb5_context context,
if ((ret = krb5_cc_resolve(context, "MEMORY:rd_req", &ccache)))
goto cleanup;
-
+ /* Solaris Kerberos */
if ((ret = krb5_cc_initialize(context, ccache, creds->client)) != NULL)
goto cleanup;
+ /* Solaris Kerberos */
if ((ret = krb5_cc_store_cred(context, ccache, creds)) != NULL)
goto cleanup;
@@ -169,12 +181,12 @@ krb5_verify_init_creds(krb5_context context,
in_creds.times.endtime += 5*60;
if ((ret = krb5_get_credentials(context, 0, ccache, &in_creds,
- &out_creds)))
+ &out_creds)))
goto cleanup;
/* make an ap_req */
if ((ret = krb5_mk_req_extended(context, &authcon, 0, NULL, out_creds,
- &ap_req)))
+ &ap_req)))
goto cleanup;
}
@@ -187,7 +199,7 @@ krb5_verify_init_creds(krb5_context context,
/* verify the ap_req */
if ((ret = krb5_rd_req(context, &authcon, &ap_req, server, keytab,
- NULL, NULL)))
+ NULL, NULL)))
goto cleanup;
/* if we get this far, then the verification succeeded. We can
@@ -199,10 +211,12 @@ krb5_verify_init_creds(krb5_context context,
retcc = NULL;
+ /* Solaris Kerberos */
if (((ret = krb5_cc_resolve(context, "MEMORY:rd_req2", &retcc)) != NULL) ||
((ret = krb5_cc_initialize(context, retcc, creds->client)) != NULL) ||
((ret = krb5_cc_copy_creds_except(context, ccache, retcc,
creds->server)) != NULL)) {
+ /* Solaris Kerberos */
if (retcc)
(void) krb5_cc_destroy(context, retcc);
} else {
@@ -220,8 +234,10 @@ krb5_verify_init_creds(krb5_context context,
cleanup:
if (!server_arg && server)
krb5_free_principal(context, server);
+ /* Solaris Kerberos */
if (!keytab_arg && keytab)
(void) krb5_kt_close(context, keytab);
+ /* Solaris Kerberos */
if (ccache)
(void) krb5_cc_destroy(context, ccache);
if (out_creds)
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/accessor.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/accessor.c
index 7540d0386d..a6b1c9c680 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/accessor.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/accessor.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/krb5/os/accessor.c
*
@@ -79,6 +77,36 @@ krb5int_accessor(krb5int_access *internals, krb5_int32 version)
S (krb5_ser_unpack_int64, krb5_ser_unpack_int64),
S (asn1_ldap_encode_sequence_of_keys, krb5int_ldap_encode_sequence_of_keys),
S (asn1_ldap_decode_sequence_of_keys, krb5int_ldap_decode_sequence_of_keys),
+ S (encode_krb5_pa_pk_as_req, encode_krb5_pa_pk_as_req),
+ S (encode_krb5_pa_pk_as_req_draft9, encode_krb5_pa_pk_as_req_draft9),
+ S (encode_krb5_pa_pk_as_rep, encode_krb5_pa_pk_as_rep),
+ S (encode_krb5_pa_pk_as_rep_draft9, encode_krb5_pa_pk_as_rep_draft9),
+ S (encode_krb5_auth_pack, encode_krb5_auth_pack),
+ S (encode_krb5_auth_pack_draft9, encode_krb5_auth_pack_draft9),
+ S (encode_krb5_kdc_dh_key_info, encode_krb5_kdc_dh_key_info),
+ S (encode_krb5_reply_key_pack, encode_krb5_reply_key_pack),
+ S (encode_krb5_reply_key_pack_draft9, encode_krb5_reply_key_pack_draft9),
+ S (encode_krb5_typed_data, encode_krb5_typed_data),
+ S (encode_krb5_td_trusted_certifiers, encode_krb5_td_trusted_certifiers),
+ S (encode_krb5_td_dh_parameters, encode_krb5_td_dh_parameters),
+ S (decode_krb5_pa_pk_as_req, decode_krb5_pa_pk_as_req),
+ S (decode_krb5_pa_pk_as_req_draft9, decode_krb5_pa_pk_as_req_draft9),
+ S (decode_krb5_pa_pk_as_rep, decode_krb5_pa_pk_as_rep),
+ S (decode_krb5_pa_pk_as_rep_draft9, decode_krb5_pa_pk_as_rep_draft9),
+ S (decode_krb5_auth_pack, decode_krb5_auth_pack),
+ S (decode_krb5_auth_pack_draft9, decode_krb5_auth_pack_draft9),
+ S (decode_krb5_kdc_dh_key_info, decode_krb5_kdc_dh_key_info),
+ S (decode_krb5_principal_name, decode_krb5_principal_name),
+ S (decode_krb5_reply_key_pack, decode_krb5_reply_key_pack),
+ S (decode_krb5_reply_key_pack_draft9, decode_krb5_reply_key_pack_draft9),
+ S (decode_krb5_typed_data, decode_krb5_typed_data),
+ S (decode_krb5_td_trusted_certifiers, decode_krb5_td_trusted_certifiers),
+ S (decode_krb5_td_dh_parameters, decode_krb5_td_dh_parameters),
+ S (decode_krb5_as_req, decode_krb5_as_req),
+ S (encode_krb5_kdc_req_body, encode_krb5_kdc_req_body),
+ S (krb5_free_kdc_req, krb5_free_kdc_req),
+ S (krb5int_set_prompt_types, krb5int_set_prompt_types),
+ S (encode_krb5_authdata_elt, encode_krb5_authdata_elt),
#if DESIGNATED_INITIALIZERS
};
#else
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/an_to_ln.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/an_to_ln.c
index 6296380170..0a42126049 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/an_to_ln.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/an_to_ln.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/an_to_ln.c
@@ -15,7 +14,7 @@
* 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
@@ -29,21 +28,18 @@
* 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.
- *
+ *
*
* krb5_aname_to_localname()
*/
-
/*
* We're only to AN_TO_LN rules at this point, and not doing the
* database lookup (moved from configure script)
*/
-#ifndef AN_TO_LN_RULES
#define AN_TO_LN_RULES
-#endif
-#include <k5-int.h>
+#include "k5-int.h"
#include <ctype.h>
#if HAVE_REGEX_H
#include <regex.h>
@@ -68,13 +64,6 @@
#define KDBM_OPEN(db, fl, mo) dbm_open(db, fl, mo)
#define KDBM_CLOSE(db) dbm_close(db)
#define KDBM_FETCH(db, key) dbm_fetch(db, key)
-#else /*ANAME_DB*/
-extern DBM *db_dbm_open (char *, int, int);
-extern void db_dbm_close (DBM *);
-extern datum db_dbm_fetch (DBM *, datum);
-#define KDBM_OPEN(db, fl, mo) db_dbm_open(db, fl, mo)
-#define KDBM_CLOSE(db) db_dbm_close(db)
-#define KDBM_FETCH(db, key) db_dbm_fetch(db, key)
#endif /*ANAME_DB*/
/*
@@ -198,7 +187,7 @@ db_an_to_ln(context, dbname, aname, lnsize, lname)
* <rule> ...
* Where: <rule> is of the form:
* "s/" <regexp> "/" <text> "/" ["g"]
- *
+ *
* In order to be able to select rule validity, the native system must support
* one of compile(3), re_comp(3) or regcomp(3). In order to be able to
* transform (e.g. substitute), the native system must support regcomp(3) or
@@ -208,7 +197,7 @@ db_an_to_ln(context, dbname, aname, lnsize, lname)
/*
* aname_do_match() - Does our name match the parenthesized regular
* expression?
- *
+ *
* Chew up the match portion of the regular expression and update *contextp.
* If no re_comp() or regcomp(), then always return a match.
*/
@@ -256,8 +245,7 @@ aname_do_match(char *string, char **contextp)
#elif HAVE_REGEXPR_H
compile(regexp,
regexp_buffer,
- &regexp_buffer[RE_BUF_SIZE],
- '\0');
+ &regexp_buffer[RE_BUF_SIZE]);
if (step(string, regexp_buffer)) {
if ((loc1 == string) &&
(loc2 == &string[strlen(string)]))
@@ -290,8 +278,8 @@ aname_do_match(char *string, char **contextp)
* string.
*/
#define use_bytes(x) \
- out_used += (x); \
- if (out_used > MAX_FORMAT_BUFFER) goto mem_err
+ out_used += (x); \
+ if (out_used > MAX_FORMAT_BUFFER) goto mem_err
static int
do_replacement(char *regexp, char *repl, int doall, char *in, char *out)
@@ -342,8 +330,7 @@ do_replacement(char *regexp, char *repl, int doall, char *in, char *out)
compile(regexp,
regexp_buffer,
- &regexp_buffer[RE_BUF_SIZE],
- '\0');
+ &regexp_buffer[RE_BUF_SIZE]);
cp = in;
op = out;
matched = 0;
@@ -406,6 +393,7 @@ aname_replacer(char *string, char **contextp, char **result)
kret = ENOMEM;
*result = (char *) NULL;
/* Allocate the formatting buffers */
+ /* Solaris Kerberos */
if (((in = (char *) malloc(MAX_FORMAT_BUFFER)) != NULL) &&
((out = (char *) malloc(MAX_FORMAT_BUFFER)) != NULL)) {
/*
@@ -421,10 +409,11 @@ aname_replacer(char *string, char **contextp, char **result)
*/
for (cp = *contextp; *cp; ) {
/* Skip leading whitespace */
- while (isspace(*cp))
+ while (isspace((int) (*cp)))
cp++;
/*
+ * Solaris Kerberos
* Find our separators. First two characters must be "s<sep>"
* We must also find another "<sep>" followed by another * "<sep>".
*/
@@ -446,6 +435,7 @@ aname_replacer(char *string, char **contextp, char **result)
/* Figure out sizes of strings and allocate them */
rule_size = (size_t) (ep - &cp[2]);
repl_size = (size_t) (tp - &ep[1]);
+ /* Solaris Kerberos */
if (((rule = (char *) malloc(rule_size+1)) != NULL) &&
((repl = (char *) malloc(repl_size+1)) != NULL)) {
@@ -511,8 +501,7 @@ aname_replacer(char *string, char **contextp, char **result)
* the principal name.
*/
static krb5_error_code
-rule_an_to_ln(krb5_context context, char *rule,
- krb5_const_principal aname, const int lnsize, char *lname)
+rule_an_to_ln(krb5_context context, char *rule, krb5_const_principal aname, const unsigned int lnsize, char *lname)
{
krb5_error_code kret;
char *current;
@@ -555,9 +544,12 @@ rule_an_to_ln(krb5_context context, char *rule,
if (*current == '$') {
if ((sscanf(current+1, "%d", &compind) == 1) &&
(compind <= num_comps) &&
- (datap = (compind > 0) ?
- krb5_princ_component(context, aname, compind-1) :
- krb5_princ_realm(context, aname))) {
+ (datap =
+ (compind > 0)
+ ? krb5_princ_component(context, aname,
+ compind-1)
+ : krb5_princ_realm(context, aname))
+ ) {
if ((datap->length < MAX_FORMAT_BUFFER)
&& (selstring_used+datap->length
< MAX_FORMAT_BUFFER)) {
@@ -573,7 +565,7 @@ rule_an_to_ln(krb5_context context, char *rule,
*cout = '\0';
current++;
/* Point past number */
- while (isdigit((int) *current))
+ while (isdigit((int) (*current)))
current++;
}
else
@@ -691,20 +683,18 @@ an_to_ln_realm_chk(
* that name is returned as the lname.
*/
static krb5_error_code
-default_an_to_ln(krb5_context context, krb5_const_principal aname,
- const int lnsize, char *lname)
+default_an_to_ln(krb5_context context, krb5_const_principal aname, const unsigned int lnsize, char *lname)
{
krb5_error_code retval;
char *def_realm;
unsigned int realm_length;
realm_length = krb5_princ_realm(context, aname)->length;
-
-
+
if ((retval = krb5_get_default_realm(context, &def_realm))) {
return(retval);
}
-
+ /* Solaris Kerberos */
/* compare against default realm and auth_to_local_realm(s) */
if ((((size_t) realm_length != strlen(def_realm)) ||
(memcmp(def_realm, krb5_princ_realm(context, aname)->data,
@@ -718,11 +708,11 @@ default_an_to_ln(krb5_context context, krb5_const_principal aname,
if (krb5_princ_size(context, aname) != 1) {
if (krb5_princ_size(context, aname) == 2 ) {
/* Check to see if 2nd component is the local realm. */
- if (strncmp(krb5_princ_component(context, aname, 1)->data,
- def_realm, realm_length) ||
- realm_length !=
- krb5_princ_component(context, aname, 1)->length) {
+ if ( strncmp(krb5_princ_component(context, aname,1)->data,def_realm,
+ realm_length) ||
+ realm_length != krb5_princ_component(context, aname,1)->length) {
/* XXX an_to_ln_realm_chk ? */
+ /* Solaris Kerberos */
free(def_realm);
return KRB5_LNAME_NOTRANS;
}
@@ -730,13 +720,14 @@ default_an_to_ln(krb5_context context, krb5_const_principal aname,
else {
/* no components or more than one component to non-realm part of name
--no translation. */
+ /* Solaris Kerberos */
free(def_realm);
return KRB5_LNAME_NOTRANS;
}
}
free(def_realm);
- strncpy(lname, krb5_princ_component(context, aname,0)->data,
+ strncpy(lname, krb5_princ_component(context, aname,0)->data,
min(krb5_princ_component(context, aname,0)->length,lnsize));
if (lnsize <= krb5_princ_component(context, aname,0)->length ) {
retval = KRB5_CONFIG_NOTENUFSPACE;
@@ -759,9 +750,8 @@ default_an_to_ln(krb5_context context, krb5_const_principal aname,
returns system errors, NOT_ENOUGH_SPACE
*/
-krb5_error_code
-krb5_aname_to_localname(krb5_context context,
- krb5_const_principal aname, const int lnsize_in, char *lname)
+krb5_error_code KRB5_CALLCONV
+krb5_aname_to_localname(krb5_context context, krb5_const_principal aname, const int lnsize_in, char *lname)
{
krb5_error_code kret;
char *realm;
@@ -775,7 +765,7 @@ krb5_aname_to_localname(krb5_context context,
unsigned int lnsize;
if (lnsize_in < 0)
- return KRB5_CONFIG_NOTENUFSPACE;
+ return KRB5_CONFIG_NOTENUFSPACE;
lnsize = lnsize_in; /* Unsigned */
@@ -914,3 +904,4 @@ krb5_aname_to_localname(krb5_context context,
}
return(kret);
}
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/changepw.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/changepw.c
index 760f47e1e9..816713dc44 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/changepw.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/changepw.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/krb5/os/changepw.c
*
@@ -29,12 +27,13 @@
/*
* krb5_set_password - Implements set password per RFC 3244
* Added by Paul W. Nelson, Thursby Software Systems, Inc.
+ * Modified by Todd Stecher, Isilon Systems, to use krb1.4 socket infrastructure
*/
-#define NEED_SOCKETS
#include "fake-addrinfo.h"
#include "k5-int.h"
#include "os-proto.h"
+#include "cm.h"
#include <stdio.h>
#include <errno.h>
@@ -43,31 +42,42 @@
#define GETSOCKNAME_ARG3_TYPE int
#endif
+struct sendto_callback_context {
+ krb5_context context;
+ krb5_auth_context auth_context;
+ krb5_principal set_password_for;
+ char *newpw;
+ krb5_data ap_req;
+};
+
+
/*
* Wrapper function for the two backends
*/
static krb5_error_code
krb5_locate_kpasswd(krb5_context context, const krb5_data *realm,
- struct addrlist *addrlist)
+ struct addrlist *addrlist, krb5_boolean useTcp)
{
krb5_error_code code;
+ int sockType = (useTcp ? SOCK_STREAM : SOCK_DGRAM);
+
+ code = krb5int_locate_server (context, realm, addrlist,
+ locate_service_kpasswd, sockType, 0);
- code = krb5int_locate_server (context, realm, addrlist, 0,
- "kpasswd_server", "_kpasswd", 0,
- htons(DEFAULT_KPASSWD_PORT), 0, 0);
if (code == KRB5_REALM_CANT_RESOLVE || code == KRB5_REALM_UNKNOWN) {
- code = krb5int_locate_server (context, realm, addrlist, 0,
- "admin_server", "_kerberos-adm", 1,
- DEFAULT_KPASSWD_PORT, 0, 0);
+ code = krb5int_locate_server (context, realm, addrlist,
+ locate_service_kadmin, SOCK_STREAM, 0);
if (!code) {
/* Success with admin_server but now we need to change the
- port number to use DEFAULT_KPASSWD_PORT. */
+ port number to use DEFAULT_KPASSWD_PORT and the socktype. */
int i;
- for ( i=0;i<addrlist->naddrs;i++ ) {
- struct addrinfo *a = addrlist->addrs[i];
+ for (i=0; i<addrlist->naddrs; i++) {
+ struct addrinfo *a = addrlist->addrs[i].ai;
if (a->ai_family == AF_INET)
sa2sin (a->ai_addr)->sin_port = htons(DEFAULT_KPASSWD_PORT);
+ if (sockType != SOCK_STREAM)
+ a->ai_socktype = sockType;
}
}
}
@@ -75,252 +85,227 @@ krb5_locate_kpasswd(krb5_context context, const krb5_data *realm,
}
-/*
-** The logic for setting and changing a password is mostly the same
-** krb5_change_set_password handles both cases
-** if set_password_for is NULL, then a password change is performed,
-** otherwise, the password is set for the principal indicated in set_password_for
-*/
-krb5_error_code KRB5_CALLCONV
-krb5_change_set_password(
- krb5_context context, krb5_creds *creds, char *newpw, krb5_principal set_password_for,
- int *result_code, krb5_data *result_code_string, krb5_data *result_string)
+/**
+ * This routine is used for a callback in sendto_kdc.c code. Simply
+ * put, we need the client addr to build the krb_priv portion of the
+ * password request.
+ */
+
+
+static void kpasswd_sendto_msg_cleanup (void* callback_context, krb5_data* message)
{
- krb5_auth_context auth_context;
- krb5_data ap_req, chpw_req, chpw_rep;
- krb5_address local_kaddr, remote_kaddr;
- char *code_string;
- krb5_error_code code = 0;
- int i;
- GETSOCKNAME_ARG3_TYPE addrlen;
- struct sockaddr_storage local_addr, remote_addr, tmp_addr;
- int cc, local_result_code;
- /* platforms seem to be consistant and use the same types */
- GETSOCKNAME_ARG3_TYPE tmp_len;
- SOCKET s1 = INVALID_SOCKET, s2 = INVALID_SOCKET;
- int tried_one = 0;
- struct addrlist al = ADDRLIST_INIT;
-
-
- /* Initialize values so that cleanup call can safely check for NULL */
- auth_context = NULL;
- memset(&chpw_req, 0, sizeof(krb5_data));
- memset(&chpw_rep, 0, sizeof(krb5_data));
- memset(&ap_req, 0, sizeof(krb5_data));
-
- /* initialize auth_context so that we know we have to free it */
- if ((code = krb5_auth_con_init(context, &auth_context)))
- goto cleanup;
-
- if ((code = krb5_mk_req_extended(context, &auth_context,
- AP_OPTS_USE_SUBKEY,
- NULL, creds, &ap_req)))
- goto cleanup;
-
- if ((code = krb5_locate_kpasswd(context,
- krb5_princ_realm(context, creds->server),
- &al)))
- goto cleanup;
-
- /* this is really obscure. s1 is used for all communications. it
- is left unconnected in case the server is multihomed and routes
- are asymmetric. s2 is connected to resolve routes and get
- addresses. this is the *only* way to get proper addresses for
- multihomed hosts if routing is asymmetric.
-
- A related problem in the server, but not the client, is that
- many os's have no way to disconnect a connected udp socket, so
- the s2 socket needs to be closed and recreated for each
- request. The s1 socket must not be closed, or else queued
- requests will be lost.
-
- A "naive" client implementation (one socket, no connect,
- hostname resolution to get the local ip addr) will work and
- interoperate if the client is single-homed. */
-
- if ((s1 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
- code = SOCKET_ERRNO;
- goto cleanup;
- }
+ struct sendto_callback_context *ctx = callback_context;
+ krb5_free_data_contents(ctx->context, message);
+}
+
+
+static int kpasswd_sendto_msg_callback(struct conn_state *conn, void *callback_context, krb5_data* message)
+{
+ krb5_error_code code = 0;
+ struct sockaddr_storage local_addr;
+ krb5_address local_kaddr;
+ struct sendto_callback_context *ctx = callback_context;
+ GETSOCKNAME_ARG3_TYPE addrlen;
+ krb5_data output;
+
+ memset (message, 0, sizeof(krb5_data));
+
+ /*
+ * We need the local addr from the connection socket
+ */
+ addrlen = sizeof(local_addr);
- if ((s2 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
+ if (getsockname(conn->fd, ss2sa(&local_addr), &addrlen) < 0) {
code = SOCKET_ERRNO;
goto cleanup;
}
- /*
- * This really should try fallback addresses in cases of timeouts.
- * For now, where the MIT KDC implementation only supports one
- * kpasswd server machine anyways, we'll only try the first IPv4
- * address we can connect() to. This isn't right for multi-homed
- * servers; oh well.
- */
- for (i=0; i<al.naddrs; i++) {
- fd_set fdset;
- struct timeval timeout;
+ /* some brain-dead OS's don't return useful information from
+ * the getsockname call. Namely, windows and solaris. */
- /* XXX Now the locate_ functions can return IPv6 addresses. */
- if (al.addrs[i]->ai_family != AF_INET)
- continue;
+ if (ss2sin(&local_addr)->sin_addr.s_addr != 0) {
+ local_kaddr.addrtype = ADDRTYPE_INET;
+ local_kaddr.length = sizeof(ss2sin(&local_addr)->sin_addr);
+ local_kaddr.contents = (krb5_octet *) &ss2sin(&local_addr)->sin_addr;
+ } else {
+ krb5_address **addrs;
- tried_one = 1;
- if (connect(s2, al.addrs[i]->ai_addr, al.addrs[i]->ai_addrlen) == SOCKET_ERROR) {
- if (SOCKET_ERRNO == ECONNREFUSED || SOCKET_ERRNO == EHOSTUNREACH)
- continue; /* try the next addr */
+ code = krb5_os_localaddr(ctx->context, &addrs);
+ if (code)
+ goto cleanup;
- code = SOCKET_ERRNO;
+ local_kaddr.magic = addrs[0]->magic;
+ local_kaddr.addrtype = addrs[0]->addrtype;
+ local_kaddr.length = addrs[0]->length;
+ local_kaddr.contents = malloc(addrs[0]->length);
+ if (local_kaddr.contents == NULL && addrs[0]->length != 0) {
+ code = errno;
+ krb5_free_addresses(ctx->context, addrs);
goto cleanup;
}
+ memcpy(local_kaddr.contents, addrs[0]->contents, addrs[0]->length);
- addrlen = sizeof(local_addr);
+ krb5_free_addresses(ctx->context, addrs);
+ }
- if (getsockname(s2, ss2sa(&local_addr), &addrlen) < 0) {
- if (SOCKET_ERRNO == ECONNREFUSED || SOCKET_ERRNO == EHOSTUNREACH)
- continue; /* try the next addr */
- code = SOCKET_ERRNO;
- goto cleanup;
- }
+ /*
+ * TBD: Does this tamper w/ the auth context in such a way
+ * to break us? Yes - provide 1 per conn-state / host...
+ */
- /* some brain-dead OS's don't return useful information from
- * the getsockname call. Namely, windows and solaris. */
- if (ss2sin(&local_addr)->sin_addr.s_addr != 0) {
- local_kaddr.addrtype = ADDRTYPE_INET;
- local_kaddr.length = sizeof(ss2sin(&local_addr)->sin_addr);
- local_kaddr.contents = (krb5_octet *) &ss2sin(&local_addr)->sin_addr;
- } else {
- krb5_address **addrs;
+ if ((code = krb5_auth_con_setaddrs(ctx->context, ctx->auth_context,
+ &local_kaddr, NULL)))
+ goto cleanup;
- krb5_os_localaddr(context, &addrs);
+ if (ctx->set_password_for)
+ code = krb5int_mk_setpw_req(ctx->context,
+ ctx->auth_context,
+ &ctx->ap_req,
+ ctx->set_password_for,
+ ctx->newpw,
+ &output);
+ else
+ code = krb5int_mk_chpw_req(ctx->context,
+ ctx->auth_context,
+ &ctx->ap_req,
+ ctx->newpw,
+ &output);
+ if (code)
+ goto cleanup;
- local_kaddr.magic = addrs[0]->magic;
- local_kaddr.addrtype = addrs[0]->addrtype;
- local_kaddr.length = addrs[0]->length;
- local_kaddr.contents = malloc(addrs[0]->length);
- memcpy(local_kaddr.contents, addrs[0]->contents, addrs[0]->length);
+ message->length = output.length;
+ message->data = output.data;
- krb5_free_addresses(context, addrs);
- }
+cleanup:
+ return code;
+}
+
+
+/*
+** The logic for setting and changing a password is mostly the same
+** krb5_change_set_password handles both cases
+** if set_password_for is NULL, then a password change is performed,
+** otherwise, the password is set for the principal indicated in set_password_for
+*/
+krb5_error_code KRB5_CALLCONV
+krb5_change_set_password(krb5_context context, krb5_creds *creds, char *newpw,
+ krb5_principal set_password_for,
+ int *result_code, krb5_data *result_code_string,
+ krb5_data *result_string)
+{
+ krb5_data chpw_rep;
+ krb5_address remote_kaddr;
+ krb5_boolean useTcp = 0;
+ GETSOCKNAME_ARG3_TYPE addrlen;
+ krb5_error_code code = 0;
+ char *code_string;
+ int local_result_code;
+
+ struct sendto_callback_context callback_ctx;
+ struct sendto_callback_info callback_info;
+ struct sockaddr_storage remote_addr;
+ struct addrlist al = ADDRLIST_INIT;
+
+ memset( &callback_ctx, 0, sizeof(struct sendto_callback_context));
+ callback_ctx.context = context;
+ callback_ctx.newpw = newpw;
+ callback_ctx.set_password_for = set_password_for;
+
+ if ((code = krb5_auth_con_init(callback_ctx.context,
+ &callback_ctx.auth_context)))
+ goto cleanup;
+
+ if ((code = krb5_mk_req_extended(callback_ctx.context,
+ &callback_ctx.auth_context,
+ AP_OPTS_USE_SUBKEY,
+ NULL,
+ creds,
+ &callback_ctx.ap_req)))
+ goto cleanup;
+
+ do {
+ if ((code = krb5_locate_kpasswd(callback_ctx.context,
+ krb5_princ_realm(callback_ctx.context,
+ creds->server),
+ &al, useTcp)))
+ break;
addrlen = sizeof(remote_addr);
- if (getpeername(s2, ss2sa(&remote_addr), &addrlen) < 0) {
- if (SOCKET_ERRNO == ECONNREFUSED || SOCKET_ERRNO == EHOSTUNREACH)
- continue; /* try the next addr */
- code = SOCKET_ERRNO;
- goto cleanup;
+ callback_info.context = (void*) &callback_ctx;
+ callback_info.pfn_callback = kpasswd_sendto_msg_callback;
+ callback_info.pfn_cleanup = kpasswd_sendto_msg_cleanup;
+
+ if ((code = krb5int_sendto(callback_ctx.context,
+ NULL,
+ &al,
+ &callback_info,
+ &chpw_rep,
+ NULL,
+ NULL,
+ ss2sa(&remote_addr),
+ &addrlen,
+ NULL,
+ NULL,
+ NULL
+ ))) {
+
+ /*
+ * Here we may want to switch to TCP on some errors.
+ * right?
+ */
+ break;
}
remote_kaddr.addrtype = ADDRTYPE_INET;
remote_kaddr.length = sizeof(ss2sin(&remote_addr)->sin_addr);
remote_kaddr.contents = (krb5_octet *) &ss2sin(&remote_addr)->sin_addr;
- /* mk_priv requires that the local address be set.
- getsockname is used for this. rd_priv requires that the
- remote address be set. recvfrom is used for this. If
- rd_priv is given a local address, and the message has the
- recipient addr in it, this will be checked. However, there
- is simply no way to know ahead of time what address the
- message will be delivered *to*. Therefore, it is important
- that either no recipient address is in the messages when
- mk_priv is called, or that no local address is passed to
- rd_priv. Both is a better idea, and I have done that. In
- summary, when mk_priv is called, *only* a local address is
- specified. when rd_priv is called, *only* a remote address
- is specified. Are we having fun yet? */
-
- if ((code = krb5_auth_con_setaddrs(context, auth_context,
- &local_kaddr, NULL))) {
- goto cleanup;
- }
-
- if( set_password_for )
- code = krb5int_mk_setpw_req(context, auth_context, &ap_req, set_password_for, newpw, &chpw_req);
+ if ((code = krb5_auth_con_setaddrs(callback_ctx.context,
+ callback_ctx.auth_context,
+ NULL,
+ &remote_kaddr)))
+ break;
+
+ if (set_password_for)
+ code = krb5int_rd_setpw_rep(callback_ctx.context,
+ callback_ctx.auth_context,
+ &chpw_rep,
+ &local_result_code,
+ result_string);
else
- code = krb5int_mk_chpw_req(context, auth_context, &ap_req, newpw, &chpw_req);
- if (code)
- {
- goto cleanup;
- }
-
- if ((cc = sendto(s1, chpw_req.data,
- (GETSOCKNAME_ARG3_TYPE) chpw_req.length, 0,
- al.addrs[i]->ai_addr, al.addrs[i]->ai_addrlen)) != chpw_req.length)
- {
- if ((cc < 0) && ((SOCKET_ERRNO == ECONNREFUSED) ||
- (SOCKET_ERRNO == EHOSTUNREACH)))
- continue; /* try the next addr */
-
- code = (cc < 0) ? SOCKET_ERRNO : ECONNABORTED;
- goto cleanup;
- }
-
- chpw_rep.length = 1500;
- chpw_rep.data = (char *) malloc(chpw_rep.length);
-
- /* XXX need a timeout/retry loop here */
- FD_ZERO (&fdset);
- FD_SET (s1, &fdset);
- timeout.tv_sec = 120;
- timeout.tv_usec = 0;
- switch (select (s1 + 1, &fdset, 0, 0, &timeout)) {
- case -1:
- code = SOCKET_ERRNO;
- goto cleanup;
- case 0:
- code = ETIMEDOUT;
- goto cleanup;
- default:
- /* fall through */
- ;
- }
+ code = krb5int_rd_chpw_rep(callback_ctx.context,
+ callback_ctx.auth_context,
+ &chpw_rep,
+ &local_result_code,
+ result_string);
+
+ if (code) {
+ if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !useTcp ) {
+ krb5int_free_addrlist (&al);
+ useTcp = 1;
+ continue;
+ }
- /* "recv" would be good enough here... except that Windows/NT
- commits the atrocity of returning -1 to indicate failure,
- but leaving errno set to 0.
-
- "recvfrom(...,NULL,NULL)" would seem to be a good enough
- alternative, and it works on NT, but it doesn't work on
- SunOS 4.1.4 or Irix 5.3. Thus we must actually accept the
- value and discard it. */
- tmp_len = sizeof(tmp_addr);
- if ((cc = recvfrom(s1, chpw_rep.data,
- (GETSOCKNAME_ARG3_TYPE) chpw_rep.length,
- 0, ss2sa(&tmp_addr), &tmp_len)) < 0)
- {
- code = SOCKET_ERRNO;
- goto cleanup;
+ break;
}
- closesocket(s1);
- s1 = INVALID_SOCKET;
- closesocket(s2);
- s2 = INVALID_SOCKET;
-
- chpw_rep.length = cc;
-
- if ((code = krb5_auth_con_setaddrs(context, auth_context,
- NULL, &remote_kaddr)))
- goto cleanup;
-
- if( set_password_for )
- code = krb5int_rd_setpw_rep(context, auth_context, &chpw_rep, &local_result_code, result_string);
- else
- code = krb5int_rd_chpw_rep(context, auth_context, &chpw_rep, &local_result_code, result_string);
- if (code)
- goto cleanup;
-
if (result_code)
*result_code = local_result_code;
-
+
if (result_code_string) {
- if( set_password_for )
- code = krb5int_setpw_result_code_string(context, local_result_code, (const char **)&code_string);
- else
- code = krb5_chpw_result_code_string(context, local_result_code, &code_string);
- if(code)
- goto cleanup;
+ if (set_password_for)
+ code = krb5int_setpw_result_code_string(callback_ctx.context,
+ local_result_code,
+ (const char **)&code_string);
+ else
+ code = krb5_chpw_result_code_string(callback_ctx.context,
+ local_result_code,
+ &code_string);
+ if(code)
+ goto cleanup;
result_code_string->length = strlen(code_string);
result_code_string->data = malloc(result_code_string->length);
@@ -331,34 +316,20 @@ krb5_change_set_password(
strncpy(result_code_string->data, code_string, result_code_string->length);
}
- code = 0;
- goto cleanup;
- }
-
- if (tried_one)
- /* Got some non-fatal errors, but didn't get any successes. */
- code = SOCKET_ERRNO;
- else
- /* Had some addresses, but didn't try any because they weren't
- AF_INET addresses and we don't support AF_INET6 addresses
- here yet. */
- code = EHOSTUNREACH;
+ if (code == KRB5KRB_ERR_RESPONSE_TOO_BIG && !useTcp ) {
+ krb5int_free_addrlist (&al);
+ useTcp = 1;
+ } else {
+ break;
+ }
+ } while (TRUE);
cleanup:
- if (auth_context != NULL)
- krb5_auth_con_free(context, auth_context);
+ if (callback_ctx.auth_context != NULL)
+ krb5_auth_con_free(callback_ctx.context, callback_ctx.auth_context);
krb5int_free_addrlist (&al);
-
- if (s1 != INVALID_SOCKET)
- closesocket(s1);
-
- if (s2 != INVALID_SOCKET)
- closesocket(s2);
-
- krb5_free_data_contents(context, &chpw_req);
- krb5_free_data_contents(context, &chpw_rep);
- krb5_free_data_contents(context, &ap_req);
+ krb5_free_data_contents(callback_ctx.context, &callback_ctx.ap_req);
return(code);
}
@@ -397,36 +368,33 @@ krb5_set_password_using_ccache(
int *result_code, krb5_data *result_code_string, krb5_data *result_string
)
{
- krb5_creds creds;
- krb5_creds *credsp;
- krb5_error_code code;
+ krb5_creds creds;
+ krb5_creds *credsp;
+ krb5_error_code code;
-/*
-** get the proper creds for use with krb5_set_password -
-*/
- memset( &creds, 0, sizeof(creds) );
-/*
-** first get the principal for the password service -
-*/
- code = krb5_cc_get_principal( context, ccache, &creds.client );
- if( !code )
- {
- code = krb5_build_principal( context, &creds.server,
- krb5_princ_realm(context, change_password_for)->length,
- krb5_princ_realm(context, change_password_for)->data,
- "kadmin", "changepw", NULL );
- if(!code)
- {
- code = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
- if( ! code )
- {
- code = krb5_set_password(context, credsp, newpw, change_password_for,
- result_code, result_code_string,
- result_string);
- krb5_free_creds(context, credsp);
- }
- }
- krb5_free_cred_contents(context, &creds);
+ /*
+ ** get the proper creds for use with krb5_set_password -
+ */
+ memset (&creds, 0, sizeof(creds));
+ /*
+ ** first get the principal for the password service -
+ */
+ code = krb5_cc_get_principal (context, ccache, &creds.client);
+ if (!code) {
+ code = krb5_build_principal(context, &creds.server,
+ krb5_princ_realm(context, change_password_for)->length,
+ krb5_princ_realm(context, change_password_for)->data,
+ "kadmin", "changepw", NULL);
+ if (!code) {
+ code = krb5_get_credentials(context, 0, ccache, &creds, &credsp);
+ if (!code) {
+ code = krb5_set_password(context, credsp, newpw, change_password_for,
+ result_code, result_code_string,
+ result_string);
+ krb5_free_creds(context, credsp);
+ }
}
- return code;
+ krb5_free_cred_contents(context, &creds);
+ }
+ return code;
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/def_realm.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/def_realm.c
index 8c63a4746d..c94bf33608 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/def_realm.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/def_realm.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/krb5/os/def_realm.c
*
@@ -31,11 +29,11 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include "os-proto.h"
#include <stdio.h>
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnsglue.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnsglue.c
index fec3936685..04b1d84e8a 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnsglue.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnsglue.c
@@ -3,7 +3,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/dnsglue.c
*
@@ -30,11 +29,24 @@
* or implied warranty.
*
*/
+#include "autoconf.h"
#ifdef KRB5_DNS_LOOKUP
#include "dnsglue.h"
/*
+ * Only use res_ninit() if there's also a res_ndestroy(), to avoid
+ * memory leaks (Linux & Solaris) and outright corruption (AIX 4.x,
+ * 5.x). While we're at it, make sure res_nsearch() is there too.
+ *
+ * In any case, it is probable that platforms having broken
+ * res_ninit() will have thread safety hacks for res_init() and _res.
+ */
+#if HAVE_RES_NINIT && HAVE_RES_NDESTROY && HAVE_RES_NSEARCH
+#define USE_RES_NINIT 1
+#endif
+
+/*
* Opaque handle
*/
struct krb5int_dns_state {
@@ -59,7 +71,7 @@ static int initparse(struct krb5int_dns_state *);
/*
* krb5int_dns_init()
*
- * Initialize an opaue handl. Do name lookup and initial parsing of
+ * Initialize an opaque handle. Do name lookup and initial parsing of
* reply, skipping question section. Prepare to iterate over answer
* section. Returns -1 on error, 0 on success.
*/
@@ -67,7 +79,7 @@ int
krb5int_dns_init(struct krb5int_dns_state **dsp,
char *host, int nclass, int ntype)
{
-#if HAVE_RES_NSEARCH
+#if USE_RES_NINIT
struct __res_state statbuf;
#endif
struct krb5int_dns_state *ds;
@@ -92,12 +104,14 @@ krb5int_dns_init(struct krb5int_dns_state **dsp,
ds->cur_ans = 0;
#endif
-#if HAVE_RES_NSEARCH
+#if USE_RES_NINIT
memset(&statbuf, 0, sizeof(statbuf));
ret = res_ninit(&statbuf);
+#else
+ ret = res_init();
+#endif
if (ret < 0)
return -1;
-#endif
do {
p = (ds->ansp == NULL)
@@ -110,7 +124,7 @@ krb5int_dns_init(struct krb5int_dns_state **dsp,
ds->ansp = p;
ds->ansmax = nextincr;
-#if HAVE_RES_NSEARCH
+#if USE_RES_NINIT
len = res_nsearch(&statbuf, host, ds->nclass, ds->ntype,
ds->ansp, ds->ansmax);
#else
@@ -141,12 +155,8 @@ krb5int_dns_init(struct krb5int_dns_state **dsp,
ret = 0;
errout:
-#if HAVE_RES_NSEARCH
-#if HAVE_RES_NDESTROY
+#if USE_RES_NINIT
res_ndestroy(&statbuf);
-#else
- res_nclose(&statbuf);
-#endif
#endif
if (ret < 0) {
if (ds->ansp != NULL) {
@@ -310,6 +320,11 @@ krb5int_dns_nextans(struct krb5int_dns_state *ds,
if (!INCR_OK(ds->ansp, ds->anslen, p, rdlen))
return -1;
+/* Solaris Kerberos - resync */
+#if 0
+ if (rdlen > INT_MAX)
+ return -1;
+#endif
if (nclass == ds->nclass && ntype == ds->ntype) {
*pp = p;
*lenp = rdlen;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnsglue.h b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnsglue.h
index fd4950bf42..dc36200551 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnsglue.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnsglue.h
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/dnsglue.h
*
@@ -49,9 +48,9 @@
#ifndef KRB5_DNSGLUE_H
#define KRB5_DNSGLUE_H
+#include "autoconf.h"
#ifdef KRB5_DNS_LOOKUP
-#define NEED_SOCKETS
#include "k5-int.h"
#include "os-proto.h"
#ifdef WSHELPER
@@ -86,6 +85,15 @@
#endif
+#if HAVE_NS_INITPARSE
+/*
+ * Solaris 7 has ns_rr_cl rather than ns_rr_class.
+ */
+#if !defined(ns_rr_class) && defined(ns_rr_cl)
+#define ns_rr_class ns_rr_cl
+#endif
+#endif
+
#if HAVE_RES_NSEARCH
/*
* Some BIND 8 / BIND 9 implementations disable the BIND 4 style
@@ -133,6 +141,7 @@
* failure, goto LABEL.
*/
+/* Solaris Kerberos */
#define SAFE_GETUINT16(base, max, ptr, incr, s, label) \
do { \
if (!INCR_OK(base, max, ptr, incr)) goto label; \
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnssrv.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnssrv.c
index d865522fc4..d1c96b291c 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnssrv.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/dnssrv.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/dnssrv.c
*
@@ -28,6 +27,7 @@
* do DNS SRV RR queries
*/
+#include "autoconf.h"
#ifdef KRB5_DNS_LOOKUP
#include "dnsglue.h"
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/free_hstrl.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/free_hstrl.c
index 159f371a50..4900fce9be 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/free_hstrl.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/free_hstrl.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/free_hstrl.c
*
@@ -32,7 +31,7 @@
#include <stdio.h>
/*
- Frees the storage taken by a realm list returned by krb5_get_local_realm.
+ Frees the storage taken by a realm list returned by krb5_get_host_realm.
*/
krb5_error_code KRB5_CALLCONV
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/free_krbhs.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/free_krbhs.c
index e84875666c..a10db910c9 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/free_krbhs.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/free_krbhs.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/free_krbhs.c
*
@@ -17,7 +16,10 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/full_ipadr.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/full_ipadr.c
index 73ea02f0ab..c72daa8c95 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/full_ipadr.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/full_ipadr.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/full_ipadr.c
*
@@ -28,15 +27,14 @@
* Take an IP addr & port and generate a full IP address.
*/
-#define NEED_SOCKETS
-#include <k5-int.h>
+#include "k5-int.h"
#ifdef HAVE_NETINET_IN_H
#include "os-proto.h"
krb5_error_code
-krb5_make_full_ipaddr(krb5_context context, krb5_int32 adr,
+krb5_make_full_ipaddr(krb5_context context, krb5_int32 adr,
/*krb5_int16*/int port, krb5_address **outaddr)
{
unsigned long smushaddr = (unsigned long) adr; /* already in net order */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/gen_rname.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/gen_rname.c
index df4d692e9f..28e1803818 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/gen_rname.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/gen_rname.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/gen_rname.c
*
@@ -17,7 +16,10 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
@@ -26,7 +28,6 @@
* a replay cache tag string.
*/
-#define NEED_SOCKETS
#include "k5-int.h"
#include "os-proto.h"
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/genaddrs.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/genaddrs.c
index 51469e3760..b5d6c6e746 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/genaddrs.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/genaddrs.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/genaddrs.c
@@ -29,29 +28,17 @@
* Take an IP addr & port and generate a full IP address.
*/
-#define NEED_SOCKETS
-#include <k5-int.h>
+#include "k5-int.h"
#include "os-proto.h"
-#if !defined(_WINSOCKAPI_) && !defined(HAVE_MACSOCK_H)
+#if !defined(_WINSOCKAPI_)
#include <netinet/in.h>
#endif
+
+/* Solaris Kerberos */
#include <inet/ip.h>
#include <inet/ip6.h>
-#ifndef GETPEERNAME_ARG2_TYPE
-#define GETPEERNAME_ARG2_TYPE struct sockaddr
-#endif
-#ifndef GETPEERNAME_ARG3_TYPE
-#define GETPEERNAME_ARG3_TYPE size_t
-#endif
-#ifndef GETSOCKNAME_ARG2_TYPE
-#define GETSOCKNAME_ARG2_TYPE struct sockaddr
-#endif
-#ifndef GETSOCKNAME_ARG3_TYPE
-#define GETSOCKNAME_ARG3_TYPE size_t
-#endif
-
struct addrpair {
krb5_address addr, port;
};
@@ -73,6 +60,7 @@ static void *cvtaddr (struct sockaddr_storage *a, struct addrpair *ap)
SET (ap->port, ss2sin6(a)->sin6_port, ADDRTYPE_IPPORT);
if (IN6_IS_ADDR_V4MAPPED (&ss2sin6(a)->sin6_addr)) {
ap->addr.addrtype = ADDRTYPE_INET;
+ /* Solaris Kerberos */
ap->addr.contents = (IPV6_ADDR_LEN - IPV4_ADDR_LEN) +
(krb5_octet *) &ss2sin6(a)->sin6_addr;
ap->addr.length = IPV4_ADDR_LEN;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/gmt_mktime.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/gmt_mktime.c
index b55e0946c9..65ab87349b 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/gmt_mktime.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/gmt_mktime.c
@@ -1,14 +1,7 @@
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* This code placed in the public domain by Mark W. Eichin */
#include <stdio.h>
-#include <k5-int.h>
+#include "autoconf.h"
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -43,7 +36,7 @@ static const int days_in_month[12] = {
#define hasleapday(year) (year%400?(year%100?(year%4?0:1):0):1)
-time_t gmt_mktime(struct tm *t)
+time_t krb5int_gmt_mktime(struct tm *t)
{
time_t accum;
@@ -60,6 +53,7 @@ time_t gmt_mktime(struct tm *t)
*/
assert_time(t->tm_year>=1);
assert_time(t->tm_year<=138);
+
assert_time(t->tm_mon>=0);
assert_time(t->tm_mon<=11);
assert_time(t->tm_mday>=1);
@@ -97,3 +91,37 @@ time_t gmt_mktime(struct tm *t)
return accum;
}
+
+#ifdef TEST_LEAP
+int
+main (int argc, char *argv[])
+{
+ int yr;
+ time_t t;
+ struct tm tm = {
+ .tm_mon = 0, .tm_mday = 1,
+ .tm_hour = 0, .tm_min = 0, .tm_sec = 0,
+ };
+ for (yr = 60; yr <= 104; yr++)
+ {
+ printf ("1/1/%d%c -> ", 1900 + yr, hasleapday((1900+yr)) ? '*' : ' ');
+ tm.tm_year = yr;
+ t = gmt_mktime (&tm);
+ if (t == (time_t) -1)
+ printf ("-1\n");
+ else
+ {
+ long u;
+ if (t % (24 * 60 * 60))
+ printf ("(not integral multiple of days) ");
+ u = t / (24 * 60 * 60);
+ printf ("%3ld*365%+ld\t0x%08lx\n",
+ (long) (u / 365), (long) (u % 365),
+ (long) t);
+ }
+ }
+ t = 0x80000000, printf ("time 0x%lx -> %s", t, ctime (&t));
+ t = 0x7fffffff, printf ("time 0x%lx -> %s", t, ctime (&t));
+ return 0;
+}
+#endif
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/hostaddr.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/hostaddr.c
index 48b259595c..1d11db138d 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/hostaddr.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/hostaddr.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/krb5/os/hostaddr.c
*
@@ -29,15 +27,12 @@
*
*/
-#define NEED_SOCKETS
-#include <k5-int.h>
+#include "k5-int.h"
-#include <fake-addrinfo.h>
-#include <socket-utils.h>
+#include "fake-addrinfo.h"
krb5_error_code
-krb5_os_hostaddr(krb5_context context, const char *name,
- krb5_address ***ret_addrs)
+krb5_os_hostaddr(krb5_context context, const char *name, krb5_address ***ret_addrs)
{
krb5_error_code retval;
krb5_address **addrs;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/hst_realm.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/hst_realm.c
index be1b541d07..7ef9fe6758 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/hst_realm.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/hst_realm.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/krb5/os/hst_realm.c
*
@@ -30,7 +28,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -82,7 +80,7 @@
#include <strings.h>
#endif
-#include <fake-addrinfo.h>
+#include "fake-addrinfo.h"
#ifdef KRB5_DNS_LOOKUP
@@ -309,12 +307,16 @@ krb5int_translate_gai_error (int num)
return EAFNOSUPPORT;
case EAI_MEMORY:
return ENOMEM;
-#if EAI_NODATA != EAI_NONAME
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
case EAI_NODATA:
return KRB5_EAI_NODATA;
#endif
case EAI_NONAME:
return KRB5_EAI_NONAME;
+#if defined(EAI_OVERFLOW)
+ case EAI_OVERFLOW:
+ return EINVAL; /* XXX */
+#endif
case EAI_SERVICE:
return KRB5_EAI_SERVICE;
case EAI_SOCKTYPE:
@@ -324,6 +326,7 @@ krb5int_translate_gai_error (int num)
return errno;
#endif
}
+ /* Solaris Kerberos */
/* abort (); */
return -1;
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/krbfileio.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/krbfileio.c
index bad3ee0671..e135b27aad 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/krbfileio.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/krbfileio.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include "k5-int.h"
@@ -11,12 +10,11 @@
#include <fcntl.h>
#ifndef O_BINARY
-#define O_BINARY 0
+#define O_BINARY 0
#endif
krb5_error_code
krb5_create_secure_file(krb5_context context, const char *pathname)
-
{
int fd;
int open_flag;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/ktdefname.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/ktdefname.c
index bd0628fb18..5f1dce5836 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/ktdefname.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/ktdefname.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/ktdefname.c
@@ -15,7 +14,7 @@
* 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
@@ -29,14 +28,14 @@
* 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.
- *
+ *
*
* Return default keytab file name.
*/
#define NEED_WINDOWS
-#include <k5-int.h>
+#include "k5-int.h"
extern char *krb5_defkeyname;
@@ -52,19 +51,22 @@ krb5_kt_default_name(krb5_context context, char *name, int namesize)
if (krb5_overridekeyname) {
if ((size_t) namesize < (strlen(krb5_overridekeyname)+1))
return KRB5_CONFIG_NOTENUFSPACE;
+ /* Solaris Kerberos */
strncpy(name, krb5_overridekeyname, namesize);
} else if ((context->profile_secure == FALSE) &&
(cp = getenv("KRB5_KTNAME"))) {
if ((size_t) namesize < (strlen(cp)+1))
return KRB5_CONFIG_NOTENUFSPACE;
+ /* Solaris Kerberos */
strncpy(name, cp, namesize);
} else if ((profile_get_string(context->profile,
- "libdefaults",
- "default_keytab_name", NULL,
- NULL, &retval) == 0) &&
+ "libdefaults",
+ "default_keytab_name", NULL,
+ NULL, &retval) == 0) &&
retval) {
if ((size_t) namesize < (strlen(retval)+1))
return KRB5_CONFIG_NOTENUFSPACE;
+ /* Solaris Kerberos */
strncpy(name, retval, namesize);
profile_release_string(retval);
} else {
@@ -82,8 +84,10 @@ krb5_kt_default_name(krb5_context context, char *name, int namesize)
#else
if ((size_t) namesize < (strlen(krb5_defkeyname)+1))
return KRB5_CONFIG_NOTENUFSPACE;
+ /* Solaris Kerberos */
strncpy(name, krb5_defkeyname, namesize);
#endif
}
return 0;
}
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/kuserok.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/kuserok.c
index f98ff26ca1..b9da89278f 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/kuserok.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/kuserok.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/kuserok.c
@@ -15,7 +14,7 @@
* 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
@@ -23,16 +22,19 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
- *
+ *
*
* krb5_kuserok()
*/
#include "k5-int.h"
-/* #if !defined(_WIN32) Not yet for Windows */
+#if !defined(_WIN32) /* Not yet for Windows */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
@@ -44,6 +46,23 @@
#include <gssapiP_krb5.h>
#include <syslog.h>
+#if defined(_AIX) && defined(_IBMR2)
+#include <sys/access.h>
+/* xlc has a bug with "const" */
+#define getpwnam(user) getpwnam((char *)user)
+#endif
+
+#define MAX_USERNAME 65
+#define CACHE_FILENAME_LEN 35
+
+#if defined(__APPLE__) && defined(__MACH__)
+#include <hfs/hfs_mount.h> /* XXX */
+#define FILE_OWNER_OK(UID) ((UID) == 0 || (UID) == UNKNOWNUID)
+#else
+#define FILE_OWNER_OK(UID) ((UID) == 0)
+#endif
+
+/* Solaris Kerberos */
extern void
gsscred_set_options();
@@ -55,8 +74,6 @@ safechown(const char *src, uid_t uid, gid_t gid, int mode);
extern const char *error_message(long);
-#define MAX_USERNAME 65
-#define CACHE_FILENAME_LEN 35
krb5_data tgtname = {
0,
@@ -64,6 +81,7 @@ krb5_data tgtname = {
KRB5_TGS_NAME
};
+/* Solaris Kerberos */
static krb5_error_code
krb5_move_ccache(krb5_context kcontext, krb5_principal client,
struct passwd *pwd)
@@ -182,6 +200,7 @@ krb5_move_ccache(krb5_context kcontext, krb5_principal client,
/*
+ * Solaris Kerberos:
* krb5_gsscred: Given a kerberos principal try to find the corresponding
* local uid via the gss cred table. Return TRUE if the uid was found in the
* cred table, otherwise return FALSE.
@@ -254,33 +273,20 @@ krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
char *princname;
char linebuf[BUFSIZ];
char *newline;
+ /* Solaris Kerberos */
uid_t uid;
int gobble;
/* no account => no access */
-#ifdef HAVE_GETPWNAM_R
char pwbuf[BUFSIZ];
struct passwd pwx;
-#if !defined(GETPWNAM_R_4_ARGS)
- /* POSIX */
- if (getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0)
- pwd = NULL;
-#else
- /* draft POSIX */
- pwd = getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf));
-#endif
-#else
- pwd = getpwnam(luser);
-#endif
- if (pwd == NULL)
+ if (k5_getpwnam_r(luser, &pwx, pwbuf, sizeof(pwbuf), &pwd) != 0)
return(FALSE);
-
(void) strncpy(pbuf, pwd->pw_dir, sizeof(pbuf) - 1);
pbuf[sizeof(pbuf) - 1] = '\0';
(void) strncat(pbuf, "/.k5login", sizeof(pbuf) - 1 - strlen(pbuf));
if (access(pbuf, F_OK)) { /* not accessible */
-
/*
* if he's trying to log in as himself, and there is no .k5login file,
* let him. First, have krb5 check it's rules. If no success,
@@ -290,6 +296,7 @@ krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
if (!(krb5_aname_to_localname(context, principal,
sizeof(kuser), kuser))
&& (strcmp(kuser, luser) == 0)) {
+ /* Solaris Kerberos */
if (krb5_move_ccache(context, principal, pwd))
return (FALSE);
return(TRUE);
@@ -316,6 +323,7 @@ krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
return(FALSE); /* no hope of matching */
/* open ~/.k5login */
+ /* Solaris Kerberos */
if ((fp = fopen(pbuf, "rF")) == NULL) {
free(princname);
return(FALSE);
@@ -329,7 +337,7 @@ krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
free(princname);
return(FALSE);
}
- if ((sbuf.st_uid != pwd->pw_uid) && sbuf.st_uid) {
+ if (sbuf.st_uid != pwd->pw_uid && !FILE_OWNER_OK(sbuf.st_uid)) {
fclose(fp);
free(princname);
return(FALSE);
@@ -345,6 +353,7 @@ krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
*newline = '\0';
if (!strcmp(linebuf, princname)) {
isok = TRUE;
+ /* Solaris Kerberos */
if (krb5_move_ccache(context, principal, pwd))
return (FALSE);
continue;
@@ -358,6 +367,7 @@ krb5_kuserok(krb5_context context, krb5_principal principal, const char *luser)
return(isok);
}
+/* Solaris Kerberos */
OM_uint32
krb5_gss_userok(OM_uint32 *minor,
const gss_name_t pname,
@@ -394,3 +404,27 @@ krb5_gss_userok(OM_uint32 *minor,
krb5_free_context(ctxt);
return (GSS_S_COMPLETE);
}
+
+#else /* _WIN32 */
+
+/*
+ * If the given Kerberos name "server" translates to the same name as "luser"
+ * (using * krb5_aname_to_lname()), returns TRUE.
+ */
+krb5_boolean KRB5_CALLCONV
+krb5_kuserok(context, principal, luser)
+ krb5_context context;
+ krb5_principal principal;
+ const char *luser;
+{
+ char kuser[50];
+
+ if (krb5_aname_to_localname(context, principal, sizeof(kuser), kuser))
+ return FALSE;
+
+ if (strcmp(kuser, luser) == 0)
+ return TRUE;
+
+ return FALSE;
+}
+#endif /* _WIN32 */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/localaddr.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/localaddr.c
index 189b9bb897..75953b1f36 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/localaddr.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/localaddr.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/krb5/os/localaddr.c
*
@@ -35,7 +33,6 @@
* XNS support is untested, but "Should just work". (Hah!)
*/
-#define NEED_SOCKETS
#include "k5-int.h"
#if !defined(_WIN32)
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/locate_kdc.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/locate_kdc.c
index a3f369c3b9..0d127d4eea 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/locate_kdc.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/locate_kdc.c
@@ -1,13 +1,12 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/locate_kdc.c
*
- * Copyright 1990,2000,2001,2002 by the Massachusetts Institute of Technology.
+ * Copyright 1990,2000,2001,2002,2003,2004,2006 Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -33,7 +32,6 @@
* get socket addresses for KDC.
*/
-#define NEED_SOCKETS
#include "fake-addrinfo.h"
#include "k5-int.h"
#include "os-proto.h"
@@ -63,27 +61,6 @@
#define DEFAULT_LOOKUP_KDC 1
#define DEFAULT_LOOKUP_REALM 0
-#ifdef DEBUG
-/* Solaris Kerberos: want dbg messages to syslog */
-
-#define fprintf krbint_dbg_syslog
-#include <stdarg.h>
-#include <com_err.h>
-static int
-krbint_dbg_syslog(FILE *file, const char *fmt, ...)
-{
- va_list args;
- char err_str[2048];
-
- va_start(args, fmt);
- vsnprintf(err_str, sizeof (err_str), fmt, args);
- syslog(LOG_DEBUG, err_str);
- va_end(args);
-
- return (0);
-}
-#endif
-
static int
maybe_use_dns (krb5_context context, const char *name, int defalt)
{
@@ -121,53 +98,23 @@ _krb5_use_dns_realm(krb5_context context)
#endif /* KRB5_DNS_LOOKUP */
-/*ARGSUSED*/
-static int get_port (const char *service, int stream, int defalt)
-{
-#if 0 /* Only used for "kerberos" and "kerberos-sec", and we want the
- right port numbers even on the OSes that botch the entries in
- /etc/services. So don't bother with the lookup, except maybe
- to produce a warning. */
- struct addrinfo hints = { 0 };
- struct addrinfo *ai;
- int err;
-
- hints.ai_family = PF_INET;
- hints.ai_socktype = stream ? SOCK_STREAM : SOCK_DGRAM;
- err = getaddrinfo (NULL, service, &hints, &ai);
- if (err == 0 && ai != 0) {
- if (ai->ai_addr->sa_family == AF_INET) {
- int port = ((struct sockaddr_in *)ai->ai_addr)->sin_port;
- freeaddrinfo (ai);
- return port;
- }
- freeaddrinfo (ai);
- }
-#endif
- /* Any error - don't complain, just use default. */
- return htons (defalt);
-}
-
int
krb5int_grow_addrlist (struct addrlist *lp, int nmore)
{
int i;
int newspace = lp->space + nmore;
- size_t newsize = newspace * sizeof (struct addrlist);
- struct addrinfo **newaddrs;
-
- /* NULL check a concession to SunOS4 compatibility for now; not
- required for pure ANSI support. */
- if (lp->addrs)
- newaddrs = realloc (lp->addrs, newsize);
- else
- newaddrs = malloc (newsize);
+ size_t newsize = newspace * sizeof (*lp->addrs);
+ void *newaddrs;
+ newaddrs = realloc (lp->addrs, newsize);
if (newaddrs == NULL)
return errno;
- for (i = lp->space; i < newspace; i++)
- newaddrs[i] = NULL;
lp->addrs = newaddrs;
+ for (i = lp->space; i < newspace; i++) {
+ lp->addrs[i].ai = NULL;
+ lp->addrs[i].freefn = NULL;
+ lp->addrs[i].data = NULL;
+ }
lp->space = newspace;
return 0;
}
@@ -180,7 +127,8 @@ krb5int_free_addrlist (struct addrlist *lp)
{
int i;
for (i = 0; i < lp->naddrs; i++)
- freeaddrinfo (lp->addrs[i]);
+ if (lp->addrs[i].freefn)
+ (lp->addrs[i].freefn)(lp->addrs[i].data);
free (lp->addrs);
lp->addrs = NULL;
lp->naddrs = lp->space = 0;
@@ -207,13 +155,18 @@ static int translate_ai_error (int err)
#ifdef EAI_ADDRFAMILY
case EAI_ADDRFAMILY:
#endif
-#if EAI_NODATA != EAI_NONAME
+#if defined(EAI_NODATA) && EAI_NODATA != EAI_NONAME
case EAI_NODATA:
#endif
case EAI_NONAME:
/* Name not known or no address data, but no error. Do
nothing more. */
return 0;
+#ifdef EAI_OVERFLOW
+ case EAI_OVERFLOW:
+ /* An argument buffer overflowed. */
+ return EINVAL; /* XXX */
+#endif
#ifdef EAI_SYSTEM
case EAI_SYSTEM:
/* System error, obviously. */
@@ -225,48 +178,67 @@ static int translate_ai_error (int err)
}
}
-static int add_addrinfo_to_list (struct addrlist *lp, struct addrinfo *a)
+/* Solaris Kerberos: want dbg messages to syslog */
+#include <stdarg.h>
+static inline void Tprintf(const char *fmt, ...)
{
- int err;
+#ifdef TEST
+ va_list ap;
+ char err_str[2048];
-#ifdef DEBUG
- switch (a->ai_socktype) {
- case SOCK_DGRAM:
- fprintf(stderr, "\tdgram\n");
- break;
- case SOCK_STREAM:
- fprintf(stderr, "\tstream\n");
- break;
- case SOCK_RAW:
- fprintf(stderr, "\traw\n");
- break;
- case 0:
- break;
- default:
- fprintf(stderr, "\tsocket type %d\n", a->ai_socktype);
- break;
- }
+ va_start(ap, fmt);
+ vsnprintf(err_str, sizeof (err_str), fmt, args);
+ syslog(LOG_DEBUG, err_str);
+ va_end(ap);
#endif
+}
+
+#if 0
+extern void krb5int_debug_fprint(const char *, ...);
+#define dprint krb5int_debug_fprint
+#define print_addrlist krb5int_print_addrlist
+extern void print_addrlist (const struct addrlist *a);
+#else
+static inline void dprint(const char *fmt, ...) { }
+static inline void print_addrlist(const struct addrlist *a) { }
+#endif
+
+static int add_addrinfo_to_list (struct addrlist *lp, struct addrinfo *a,
+ void (*freefn)(void *), void *data)
+{
+ int err;
+
+ dprint("\tadding %p=%A to %p (naddrs=%d space=%d)\n", a, a, lp,
+ lp->naddrs, lp->space);
if (lp->naddrs == lp->space) {
err = grow_list (lp, 1);
if (err) {
-#ifdef DEBUG
- fprintf (stderr, "grow_list failed %d\n", err);
-#endif
+ Tprintf ("grow_list failed %d\n", err);
return err;
}
}
- lp->addrs[lp->naddrs++] = a;
- a->ai_next = 0;
-#ifdef DEBUG
- fprintf (stderr, "count is now %d\n", lp->naddrs);
-#endif
+ Tprintf("setting element %d\n", lp->naddrs);
+ lp->addrs[lp->naddrs].ai = a;
+ lp->addrs[lp->naddrs].freefn = freefn;
+ lp->addrs[lp->naddrs].data = data;
+ lp->naddrs++;
+ Tprintf ("\tcount is now %d: ", lp->naddrs);
+ print_addrlist(lp);
+ Tprintf("\n");
return 0;
}
#define add_host_to_list krb5int_add_host_to_list
+static void call_freeaddrinfo(void *data)
+{
+ /* Strict interpretation of the C standard says we can't assume
+ that the ABI for f(void*) and f(struct foo *) will be
+ compatible. Use this stub just to be paranoid. */
+ freeaddrinfo(data);
+}
+
int
krb5int_add_host_to_list (struct addrlist *lp, const char *hostname,
int port, int secport,
@@ -275,24 +247,31 @@ krb5int_add_host_to_list (struct addrlist *lp, const char *hostname,
struct addrinfo *addrs, *a, *anext, hint;
int err;
char portbuf[10], secportbuf[10];
+ void (*freefn)(void *);
-#ifdef DEBUG
- fprintf (stderr, "adding hostname %s, ports %d,%d\n", hostname,
- ntohs (port), ntohs (secport));
-#endif
+ Tprintf ("adding hostname %s, ports %d,%d, family %d, socktype %d\n",
+ hostname, ntohs (port), ntohs (secport),
+ family, socktype);
memset(&hint, 0, sizeof(hint));
hint.ai_family = family;
hint.ai_socktype = socktype;
+#ifdef AI_NUMERICSERV
+ hint.ai_flags = AI_NUMERICSERV;
+#endif
sprintf(portbuf, "%d", ntohs(port));
sprintf(secportbuf, "%d", ntohs(secport));
err = getaddrinfo (hostname, portbuf, &hint, &addrs);
- if (err)
+ if (err) {
+ Tprintf ("\tgetaddrinfo(\"%s\", \"%s\", ...)\n\treturns %d: %s\n",
+ hostname, portbuf, err, gai_strerror (err));
return translate_ai_error (err);
+ }
+ freefn = call_freeaddrinfo;
anext = 0;
- for (a = addrs; a != 0 && err == 0; a = anext) {
+ for (a = addrs; a != 0 && err == 0; a = anext, freefn = 0) {
anext = a->ai_next;
- err = add_addrinfo_to_list (lp, a);
+ err = add_addrinfo_to_list (lp, a, freefn, a);
}
if (err || secport == 0)
goto egress;
@@ -306,11 +285,13 @@ krb5int_add_host_to_list (struct addrlist *lp, const char *hostname,
err = translate_ai_error (err);
goto egress;
}
- for (a = addrs; a != 0 && err == 0; a = anext) {
+ freefn = call_freeaddrinfo;
+ for (a = addrs; a != 0 && err == 0; a = anext, freefn = 0) {
anext = a->ai_next;
- err = add_addrinfo_to_list (lp, a);
+ err = add_addrinfo_to_list (lp, a, freefn, a);
}
egress:
+ /* Solaris Kerberos */
if (anext)
freeaddrinfo (anext);
return err;
@@ -333,11 +314,8 @@ krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm,
krb5_error_code code;
int i, j, count, ismaster;
-#ifdef DEBUG
- fprintf (stderr,
- "looking in krb5.conf for realm %s entry %s; ports %d,%d\n",
+ Tprintf ("looking in krb5.conf for realm %s entry %s; ports %d,%d\n",
realm->data, name, ntohs (udpport), ntohs (sec_udpport));
-#endif
if ((host = malloc(realm->length + 1)) == NULL)
return ENOMEM;
@@ -356,10 +334,8 @@ krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm,
code = profile_get_values(context->profile, realm_srv_names, &hostlist);
if (code) {
-#ifdef DEBUG
- fprintf (stderr, "config file lookup failed: %s\n",
+ Tprintf ("config file lookup failed: %s\n",
error_message(code));
-#endif
if (code == PROF_NO_SECTION || code == PROF_NO_RELATION)
code = KRB5_REALM_UNKNOWN;
krb5_xfree(host);
@@ -369,9 +345,7 @@ krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm,
count = 0;
while (hostlist && hostlist[count])
count++;
-#ifdef DEBUG
- fprintf (stderr, "found %d entries under 'kdc'\n", count);
-#endif
+ Tprintf ("found %d entries under 'kdc'\n", count);
if (count == 0) {
profile_free_list(hostlist);
@@ -426,9 +400,7 @@ krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm,
int p1, p2;
host = hostlist[i];
-#ifdef DEBUG
- fprintf (stderr, "entry %d is '%s'\n", i, host);
-#endif
+ Tprintf ("entry %d is '%s'\n", i, host);
/*
* Strip off excess whitespace
*/
@@ -487,9 +459,8 @@ krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm,
SOCK_STREAM, family);
}
if (code) {
-#ifdef DEBUG
- fprintf (stderr, "error %d returned from add_host_to_list\n", code);
-#endif
+ Tprintf ("error %d (%s) returned from add_host_to_list\n", code,
+ error_message (code));
if (hostlist)
profile_free_list (hostlist);
if (masterlist)
@@ -506,10 +477,25 @@ krb5_locate_srv_conf_1(krb5_context context, const krb5_data *realm,
return 0;
}
-#ifdef KRB5_DNS_LOOKUP
+#ifdef TEST
+static krb5_error_code
+krb5_locate_srv_conf(krb5_context context, const krb5_data *realm,
+ const char *name, struct addrlist *al, int get_masters,
+ int udpport, int sec_udpport)
+{
+ krb5_error_code ret;
-#define make_srv_query_realm krb5int_make_srv_query_realm
+ ret = krb5_locate_srv_conf_1 (context, realm, name, al,
+ get_masters, 0, udpport, sec_udpport, 0);
+ if (ret)
+ return ret;
+ if (al->naddrs == 0) /* Couldn't resolve any KDC names */
+ return KRB5_REALM_CANT_RESOLVE;
+ return 0;
+}
+#endif
+#ifdef KRB5_DNS_LOOKUP
static krb5_error_code
krb5_locate_srv_dns_1 (const krb5_data *realm,
const char *service,
@@ -521,7 +507,7 @@ krb5_locate_srv_dns_1 (const krb5_data *realm,
struct srv_dns_entry *entry = NULL, *next;
krb5_error_code code = 0;
- code = make_srv_query_realm(realm, service, protocol, &head);
+ code = krb5int_make_srv_query_realm(realm, service, protocol, &head);
if (code)
return 0;
@@ -541,20 +527,17 @@ krb5_locate_srv_dns_1 (const krb5_data *realm,
return KRB5_ERR_NO_SERVICE;
}
-#ifdef DEBUG
- fprintf (stderr, "walking answer list:\n");
-#endif
+ Tprintf ("walking answer list:\n");
for (entry = head; entry != NULL; entry = next) {
-#ifdef DEBUG
- fprintf (stderr, "\tport=%d host=%s\n", entry->port, entry->host);
-#endif
+ Tprintf ("\tport=%d host=%s\n", entry->port, entry->host);
next = entry->next;
code = add_host_to_list (addrlist, entry->host, htons (entry->port), 0,
(strcmp("_tcp", protocol)
? SOCK_DGRAM
: SOCK_STREAM), family);
- if (code)
+ if (code) {
break;
+ }
if (entry == head) {
free(entry->host);
free(entry);
@@ -562,77 +545,276 @@ krb5_locate_srv_dns_1 (const krb5_data *realm,
entry = 0;
}
}
-#ifdef DEBUG
- fprintf (stderr, "[end]\n");
-#endif
+ Tprintf ("[end]\n");
krb5int_free_srv_dns_data(head);
return code;
}
-#endif /* KRB5_DNS_LOOKUP */
+#endif
+
+#include <locate_plugin.h>
+
+#if TARGET_OS_MAC
+static const char *objdirs[] = { KRB5_PLUGIN_BUNDLE_DIR, LIBDIR "/krb5/plugins/libkrb5", NULL }; /* should be a list */
+#else
+static const char *objdirs[] = { LIBDIR "/krb5/plugins/libkrb5", NULL };
+#endif
+
+struct module_callback_data {
+ int out_of_mem;
+ struct addrlist *lp;
+};
+
+static int
+module_callback (void *cbdata, int socktype, struct sockaddr *sa)
+{
+ struct module_callback_data *d = cbdata;
+ struct {
+ struct addrinfo ai;
+ union {
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ } u;
+ } *x;
+
+ if (socktype != SOCK_STREAM && socktype != SOCK_DGRAM)
+ return 0;
+ if (sa->sa_family != AF_INET && sa->sa_family != AF_INET6)
+ return 0;
+ x = malloc (sizeof (*x));
+ if (x == 0) {
+ d->out_of_mem = 1;
+ return 1;
+ }
+ memset(x, 0, sizeof (*x));
+ x->ai.ai_addr = (struct sockaddr *) &x->u;
+ x->ai.ai_socktype = socktype;
+ x->ai.ai_family = sa->sa_family;
+ if (sa->sa_family == AF_INET) {
+ x->u.sin = *(struct sockaddr_in *)sa;
+ x->ai.ai_addrlen = sizeof(struct sockaddr_in);
+ }
+ if (sa->sa_family == AF_INET6) {
+ x->u.sin6 = *(struct sockaddr_in6 *)sa;
+ x->ai.ai_addrlen = sizeof(struct sockaddr_in6);
+ }
+ if (add_addrinfo_to_list (d->lp, &x->ai, free, x) != 0) {
+ /* Assumes only error is ENOMEM. */
+ d->out_of_mem = 1;
+ return 1;
+ }
+ return 0;
+}
+
+static krb5_error_code
+module_locate_server (krb5_context ctx, const krb5_data *realm,
+ struct addrlist *addrlist,
+ enum locate_service_type svc, int socktype, int family)
+{
+ struct krb5plugin_service_locate_result *res = NULL;
+ krb5_error_code code;
+ struct krb5plugin_service_locate_ftable *vtbl = NULL;
+ void **ptrs;
+ int i;
+ struct module_callback_data cbdata = { 0, };
+
+ Tprintf("in module_locate_server\n");
+ cbdata.lp = addrlist;
+ if (!PLUGIN_DIR_OPEN (&ctx->libkrb5_plugins)) {
+
+ code = krb5int_open_plugin_dirs (objdirs, NULL, &ctx->libkrb5_plugins,
+ &ctx->err);
+ if (code)
+ return KRB5_PLUGIN_NO_HANDLE;
+ }
+
+ code = krb5int_get_plugin_dir_data (&ctx->libkrb5_plugins,
+ "service_locator", &ptrs, &ctx->err);
+ if (code) {
+ Tprintf("error looking up plugin symbols: %s\n",
+ krb5_get_error_message(ctx, code));
+ return KRB5_PLUGIN_NO_HANDLE;
+ }
+
+ for (i = 0; ptrs[i]; i++) {
+ void *blob;
+
+ vtbl = ptrs[i];
+ Tprintf("element %d is %p\n", i, ptrs[i]);
+
+ /* For now, don't keep the plugin data alive. For long-lived
+ contexts, it may be desirable to change that later. */
+ code = vtbl->init(ctx, &blob);
+ if (code)
+ continue;
+
+ code = vtbl->lookup(blob, svc, realm->data, socktype, family,
+ module_callback, &cbdata);
+ vtbl->fini(blob);
+ if (code == KRB5_PLUGIN_NO_HANDLE) {
+ /* Module passes, keep going. */
+ /* XXX */
+ Tprintf("plugin doesn't handle this realm (KRB5_PLUGIN_NO_HANDLE)\n");
+ continue;
+ }
+ if (code != 0) {
+ /* Module encountered an actual error. */
+ Tprintf("plugin lookup routine returned error %d: %s\n",
+ code, error_message(code));
+ krb5int_free_plugin_dir_data (ptrs);
+ return code;
+ }
+ break;
+ }
+ if (ptrs[i] == NULL) {
+ Tprintf("ran off end of plugin list\n");
+ krb5int_free_plugin_dir_data (ptrs);
+ return KRB5_PLUGIN_NO_HANDLE;
+ }
+ Tprintf("stopped with plugin #%d, res=%p\n", i, res);
+
+ /* Got something back, yippee. */
+ Tprintf("now have %d addrs in list %p\n", addrlist->naddrs, addrlist);
+ print_addrlist(addrlist);
+ krb5int_free_plugin_dir_data (ptrs);
+ return 0;
+}
+
+static krb5_error_code
+prof_locate_server (krb5_context context, const krb5_data *realm,
+ struct addrlist *addrlist,
+ enum locate_service_type svc, int socktype, int family)
+{
+ const char *profname;
+ int dflport1, dflport2 = 0;
+ struct servent *serv;
+
+ switch (svc) {
+ case locate_service_kdc:
+ profname = "kdc";
+ /* We used to use /etc/services for these, but enough systems
+ have old, crufty, wrong settings that this is probably
+ better. */
+ kdc_ports:
+ dflport1 = htons(KRB5_DEFAULT_PORT);
+ dflport2 = htons(KRB5_DEFAULT_SEC_PORT);
+ break;
+ case locate_service_master_kdc:
+ profname = "master_kdc";
+ goto kdc_ports;
+ case locate_service_kadmin:
+ profname = "admin_server";
+ dflport1 = htons(DEFAULT_KADM5_PORT);
+ break;
+ case locate_service_krb524:
+ profname = "krb524_server";
+ serv = getservbyname(KRB524_SERVICE, "udp");
+ dflport1 = serv ? serv->s_port : htons (KRB524_PORT);
+ break;
+ case locate_service_kpasswd:
+ profname = "kpasswd_server";
+ dflport1 = htons(DEFAULT_KPASSWD_PORT);
+ break;
+ default:
+ return EBUSY; /* XXX */
+ }
+
+ return krb5_locate_srv_conf_1 (context, realm, profname, addrlist,
+ 0, socktype,
+ dflport1, dflport2, family);
+}
+
+static krb5_error_code
+dns_locate_server (krb5_context context, const krb5_data *realm,
+ struct addrlist *addrlist,
+ enum locate_service_type svc, int socktype, int family)
+{
+ const char *dnsname;
+ int use_dns = _krb5_use_dns_kdc(context);
+ krb5_error_code code;
+
+ if (!use_dns)
+ return KRB5_PLUGIN_NO_HANDLE;
+
+ switch (svc) {
+ case locate_service_kdc:
+ dnsname = "_kerberos";
+ break;
+ case locate_service_master_kdc:
+ dnsname = "_kerberos-master";
+ break;
+ case locate_service_kadmin:
+ dnsname = "_kerberos-adm";
+ break;
+ case locate_service_krb524:
+ dnsname = "_krb524";
+ break;
+ case locate_service_kpasswd:
+ dnsname = "_kpasswd";
+ break;
+ default:
+ return KRB5_PLUGIN_NO_HANDLE;
+ }
+
+ code = 0;
+ if (socktype == SOCK_DGRAM || socktype == 0) {
+ code = krb5_locate_srv_dns_1(realm, dnsname, "_udp", addrlist, family);
+ if (code)
+ Tprintf("dns udp lookup returned error %d\n", code);
+ }
+ if ((socktype == SOCK_STREAM || socktype == 0) && code == 0) {
+ code = krb5_locate_srv_dns_1(realm, dnsname, "_tcp", addrlist, family);
+ if (code)
+ Tprintf("dns tcp lookup returned error %d\n", code);
+ }
+ return code;
+}
/*
- * Wrapper function for the two backends
+ * Wrapper function for the various backends
*/
krb5_error_code
krb5int_locate_server (krb5_context context, const krb5_data *realm,
struct addrlist *addrlist,
- int get_masters,
- const char *profname, const char *dnsname,
- int socktype,
- /* network order port numbers! */
- int dflport1, int dflport2,
- int family)
+ enum locate_service_type svc,
+ int socktype, int family)
{
krb5_error_code code;
struct addrlist al = ADDRLIST_INIT;
*addrlist = al;
- /* Solaris Kerberos: skip local file search if profname == NULL */
- if (profname != NULL) {
+ code = module_locate_server(context, realm, &al, svc, socktype, family);
+ Tprintf("module_locate_server returns %d\n", code);
+ if (code == KRB5_PLUGIN_NO_HANDLE) {
/*
- * We always try the local file first
+ * We always try the local file before DNS. Note that there
+ * is no way to indicate "service not available" via the
+ * config file.
*/
- code = krb5_locate_srv_conf_1(context, realm, profname, &al,
- get_masters, socktype, dflport1, dflport2, family);
- }
+
+ code = prof_locate_server(context, realm, &al, svc, socktype, family);
#ifdef KRB5_DNS_LOOKUP
- if (code && dnsname != 0) {
- int use_dns = _krb5_use_dns_kdc(context);
- if (use_dns) {
- code = 0;
- if (socktype == SOCK_DGRAM || socktype == 0) {
- code = krb5_locate_srv_dns_1(realm, dnsname, "_udp",
- &al, family);
-#ifdef DEBUG
- if (code)
- fprintf(stderr, "dns udp lookup returned error %d\n",
- code);
-#endif
- }
- if ((socktype == SOCK_STREAM || socktype == 0) && code == 0) {
- code = krb5_locate_srv_dns_1(realm, dnsname, "_tcp",
- &al, family);
-#ifdef DEBUG
- if (code)
- fprintf(stderr, "dns tcp lookup returned error %d\n",
- code);
-#endif
- }
+ if (code) { /* Try DNS for all profile errors? */
+ krb5_error_code code2;
+ code2 = dns_locate_server(context, realm, &al, svc, socktype,
+ family);
+ if (code2 != KRB5_PLUGIN_NO_HANDLE)
+ code = code2;
}
- }
#endif /* KRB5_DNS_LOOKUP */
-#ifdef DEBUG
+
+ /* We could put more heuristics here, like looking up a hostname
+ of "kerberos."+REALM, etc. */
+ }
if (code == 0)
- fprintf (stderr, "krb5int_locate_server found %d addresses\n",
+ Tprintf ("krb5int_locate_server found %d addresses\n",
al.naddrs);
else
- fprintf (stderr, "krb5int_locate_server returning error code %d\n",
- code);
-#endif
+ Tprintf ("krb5int_locate_server returning error code %d/%s\n",
+ code, error_message(code));
if (code != 0) {
if (al.space)
free_list (&al);
@@ -641,6 +823,10 @@ krb5int_locate_server (krb5_context context, const krb5_data *realm,
if (al.naddrs == 0) { /* No good servers */
if (al.space)
free_list (&al);
+ krb5_set_error_message(context, KRB5_REALM_CANT_RESOLVE,
+ "Cannot resolve network address for KDC in realm %.*s",
+ realm->length, realm->data);
+
return KRB5_REALM_CANT_RESOLVE;
}
*addrlist = al;
@@ -652,25 +838,11 @@ krb5_locate_kdc(krb5_context context, const krb5_data *realm,
struct addrlist *addrlist,
int get_masters, int socktype, int family)
{
- int udpport, sec_udpport;
-
- udpport = get_port (KDC_PORTNAME, 0, KRB5_DEFAULT_PORT);
- if (socktype == SOCK_STREAM)
- sec_udpport = 0;
- else {
- sec_udpport = get_port (KDC_SECONDARY_PORTNAME, 0,
- (udpport == htons (KRB5_DEFAULT_PORT)
- ? KRB5_DEFAULT_SEC_PORT
- : KRB5_DEFAULT_PORT));
- if (sec_udpport == udpport)
- sec_udpport = 0;
- }
-
- return krb5int_locate_server(context, realm, addrlist, get_masters, "kdc",
+ return krb5int_locate_server(context, realm, addrlist,
(get_masters
- ? "_kerberos-master"
- : "_kerberos"),
- socktype, udpport, sec_udpport, family);
+ ? locate_service_master_kdc
+ : locate_service_kdc),
+ socktype, family);
}
/*
@@ -693,7 +865,7 @@ krb5_get_servername(krb5_context context,
if (use_dns) {
struct srv_dns_entry *head = NULL;
- code = make_srv_query_realm(realm, name, proto, &head);
+ code = krb5int_make_srv_query_realm(realm, name, proto, &head);
if (code)
return (code);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/lock_file.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/lock_file.c
index 3766136f07..7bbd3e9d65 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/lock_file.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/lock_file.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/lock_file.c
*
@@ -28,7 +27,7 @@
* libos: krb5_lock_file routine
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include <stdio.h>
#if !defined(_WIN32)
@@ -69,10 +68,7 @@ krb5_lock_file(krb5_context context, int fd, int mode)
krb5_error_code retval = 0;
#ifdef POSIX_FILE_LOCKS
int lock_cmd = F_SETLKW;
- static struct flock flock_zero;
struct flock lock_arg = { 0 };
-
- lock_arg = flock_zero;
#endif
switch (mode & ~KRB5_LOCKMODE_DONTBLOCK) {
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/mk_faddr.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/mk_faddr.c
index d18564100e..7caa8a8cf6 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/mk_faddr.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/mk_faddr.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/full_ipadr.c
*
@@ -28,8 +27,7 @@
* Take an IP addr & port and generate a full IP address.
*/
-#define NEED_SOCKETS
-#include <k5-int.h>
+#include "k5-int.h"
#ifdef HAVE_NETINET_IN_H
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/net_read.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/net_read.c
index cb90e81ba8..e90c6c30cb 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/net_read.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/net_read.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/net_read.c
*
@@ -26,9 +25,7 @@
*
*/
-#define NEED_LOWLEVEL_IO
-#define NEED_SOCKETS
-#include <k5-int.h>
+#include "k5-int.h"
/*
* krb5_net_read() reads from the file descriptor "fd" to the buffer
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/net_write.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/net_write.c
index 6f973b315b..5cff017619 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/net_write.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/net_write.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/net_write.c
*
@@ -26,9 +25,7 @@
*
*/
-#define NEED_LOWLEVEL_IO
-#define NEED_SOCKETS
-#include <k5-int.h>
+#include "k5-int.h"
/*
* krb5_net_write() writes "len" bytes from "buf" to the file
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/os-proto.h b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/os-proto.h
index c93da827b8..39dae84be5 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/os-proto.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/os-proto.h
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/os-proto.h
*
@@ -35,7 +34,7 @@ struct addrlist;
krb5_error_code krb5_locate_kdc
(krb5_context, const krb5_data *, struct addrlist *, int, int, int);
-/* Solaris/SUNW14resync */
+/* Solaris Kerberos */
krb5_error_code krb5_get_servername
(krb5_context,
const krb5_data *,
@@ -66,6 +65,8 @@ krb5_error_code krb5_try_realm_txt_rr(const char *, const char *,
/* Obsolete interface - leave prototype here until code removed */
krb5_error_code krb5_secure_config_files(krb5_context ctx);
+void krb5int_debug_fprint (const char *fmt, ...);
+
int _krb5_use_dns_realm (krb5_context);
int _krb5_use_dns_kdc (krb5_context);
int _krb5_conf_boolean (const char *);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/osconfig.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/osconfig.c
index a36e578d7a..dec5cac77a 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/osconfig.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/osconfig.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/osconfig.c
*
@@ -17,7 +16,10 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/port2ip.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/port2ip.c
index ad9e6ce805..037e8b1e94 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/port2ip.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/port2ip.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/port2ip.c
*
@@ -28,8 +27,7 @@
* Take an ADDRPORT address and split into IP addr & port.
*/
-#define NEED_SOCKETS
-#include <k5-int.h>
+#include "k5-int.h"
#ifdef HAVE_NETINET_IN_H
#include "os-proto.h"
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/prompter.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/prompter.c
index 24613a73b2..739c8c747d 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/prompter.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/prompter.c
@@ -1,6 +1,5 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-#include <k5-int.h>
-#if (!defined(_WIN32) || (defined(_WIN32) && defined(__CYGWIN32__))) && !defined(macintosh)
+#include "k5-int.h"
+#if !defined(_WIN32) || (defined(_WIN32) && defined(__CYGWIN32__))
#include <stdio.h>
#include <errno.h>
#include <signal.h>
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/read_msg.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/read_msg.c
index c9b86e1932..77cda8032a 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/read_msg.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/read_msg.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/read_msg.c
*
@@ -17,7 +16,10 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
@@ -25,7 +27,6 @@
* Write a message to the network
*/
-#define NEED_SOCKETS
#include "k5-int.h"
#include <errno.h>
@@ -33,7 +34,7 @@ krb5_error_code
krb5_read_message(krb5_context context, krb5_pointer fdp, krb5_data *inbuf)
{
krb5_int32 len;
- int len2, ilen;
+ int len2, ilen;
char *buf = NULL;
int fd = *( (int *) fdp);
@@ -41,15 +42,15 @@ krb5_read_message(krb5_context context, krb5_pointer fdp, krb5_data *inbuf)
return((len2 < 0) ? errno : ECONNABORTED);
len = ntohl(len);
- if ((len & VALID_UINT_BITS) != len) /* Overflow size_t??? */
- return ENOMEM;
+ if ((len & VALID_UINT_BITS) != len) /* Overflow size_t??? */
+ return ENOMEM;
inbuf->length = ilen = (int) len;
if (ilen) {
/*
* We may want to include a sanity check here someday....
*/
- if (!(buf = malloc(ilen))) {
+ if (!(buf = malloc(inbuf->length))) {
return(ENOMEM);
}
if ((len2 = krb5_net_read(context, fd, buf, ilen)) != ilen) {
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/read_pwd.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/read_pwd.c
index be00932936..6f2868da7c 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/read_pwd.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/read_pwd.c
@@ -1,10 +1,4 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-/*
* lib/krb5/os/read_pwd.c
*
* Copyright 1990,1991 by the Massachusetts Institute of Technology.
@@ -215,7 +209,7 @@ read_pwd_proc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
switch(msg) {
case WM_INITDIALOG:
dp = (pwd_params *) lParam;
- SetWindowLong(hdlg, DWL_USER, lParam);
+ SetWindowLongPtr(hdlg, DWLP_USER, lParam);
SetDlgItemText(hdlg, ID_READ_PWD_PROMPT, dp->pwd_prompt);
SetDlgItemText(hdlg, ID_READ_PWD_PROMPT2, dp->pwd_prompt2);
SetDlgItemText(hdlg, ID_READ_PWD_PWD, "");
@@ -223,7 +217,7 @@ read_pwd_proc(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
return TRUE;
case WM_COMMAND:
- dp = (pwd_params *) GetWindowLong(hdlg, DWL_USER);
+ dp = (pwd_params *) GetWindowLongPtr(hdlg, DWLP_USER);
switch (wParam) {
case IDOK:
*(dp->pwd_size_return) =
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/sendto_kdc.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/sendto_kdc.c
index 9a57749fb2..88cece63d3 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/sendto_kdc.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/sendto_kdc.c
@@ -1,12 +1,11 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/sendto_kdc.c
*
- * Copyright 1990,1991,2001,2002 by the Massachusetts Institute of Technology.
+ * Copyright 1990,1991,2001,2002,2004,2005,2007 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -33,10 +32,11 @@
* as necessary.
*/
-#define NEED_SOCKETS
-#define NEED_LOWLEVEL_IO
-#include <fake-addrinfo.h>
-#include <k5-int.h>
+#include "fake-addrinfo.h"
+#include "k5-int.h"
+
+/* Solaris Kerberos */
+#include <syslog.h>
#ifdef HAVE_SYS_TIME_H
#include <sys/time.h>
@@ -44,27 +44,46 @@
#include <time.h>
#endif
#include "os-proto.h"
+#ifdef _WIN32
+#include <sys/timeb.h>
+#endif
#ifdef _AIX
#include <sys/select.h>
#endif
+#ifndef _WIN32
/* For FIONBIO. */
#include <sys/ioctl.h>
#ifdef HAVE_SYS_FILIO_H
#include <sys/filio.h>
#endif
+#endif
#define MAX_PASS 3
/* Solaris Kerberos: moved to k5-int.h */
/* #define DEFAULT_UDP_PREF_LIMIT 1465 */
#define HARD_UDP_LIMIT 32700 /* could probably do 64K-epsilon ? */
-/* Solaris kerberos: leaving this here because other code depends on this. */
+#undef DEBUG
+
+#ifdef DEBUG
+int krb5int_debug_sendto_kdc = 0;
+#define debug krb5int_debug_sendto_kdc
+
static void default_debug_handler (const void *data, size_t len)
{
+#if 0
+ FILE *logfile;
+ logfile = fopen("/tmp/sendto_kdc.log", "a");
+ if (logfile == NULL)
+ return;
+ fwrite(data, 1, len, logfile);
+ fclose(logfile);
+#else
fwrite(data, 1, len, stderr);
/* stderr is unbuffered */
+#endif
}
void (*krb5int_sendtokdc_debug_handler) (const void *, size_t) = default_debug_handler;
@@ -73,26 +92,30 @@ void (*krb5int_sendtokdc_debug_handler) (const void *, size_t) = default_debug_h
* Solaris Kerberos: only including the debug stuff if DEBUG defined outside
* this file.
*/
-#ifdef DEBUG
-
static char global_err_str[NI_MAXHOST + NI_MAXSERV + 1024];
/* Solaris kerberos: removed put() since it isn't needed. */
+#if 0
+static void put(const void *ptr, size_t len)
+{
+ (*krb5int_sendtokdc_debug_handler)(ptr, len);
+}
+#endif
static void putstr(const char *str)
{
/* Solaris kerberos: build the string which will be passed to syslog later */
strlcat(global_err_str, str, sizeof (global_err_str));
}
+#else
+void (*krb5int_sendtokdc_debug_handler) (const void *, size_t) = 0;
+#endif
#define dprint krb5int_debug_fprint
-#define dperror dprint
-
-#include <com_err.h>
-
-static void
+ void
krb5int_debug_fprint (const char *fmt, ...)
{
+#ifdef DEBUG
va_list args;
/* Temporaries for variable arguments, etc. */
@@ -106,7 +129,10 @@ krb5int_debug_fprint (const char *fmt, ...)
const krb5_data *d;
char addrbuf[NI_MAXHOST], portbuf[NI_MAXSERV];
const char *p;
- char tmpbuf[NI_MAXHOST + NI_MAXSERV + 30];
+#ifndef max
+#define max(a,b) ((a) > (b) ? (a) : (b))
+#endif
+ char tmpbuf[max(NI_MAXHOST + NI_MAXSERV + 30, 200)];
/*
* Solaris kerberos: modified this function to create a string to pass to
@@ -131,7 +157,6 @@ krb5int_debug_fprint (const char *fmt, ...)
case 0:
default:
abort();
- break;
case 'E':
/* %E => krb5_error_code */
kerr = va_arg(args, krb5_error_code);
@@ -146,7 +171,13 @@ krb5int_debug_fprint (const char *fmt, ...)
rather than the current value. */
err = va_arg(args, int);
putf("%d/", err);
- p = strerror(err);
+ p = NULL;
+#ifdef HAVE_STRERROR_R
+ if (strerror_r(err, tmpbuf, sizeof(tmpbuf)) == 0)
+ p = tmpbuf;
+#endif
+ if (p == NULL)
+ p = strerror(err);
putstr(p);
break;
case 'F':
@@ -198,24 +229,28 @@ krb5int_debug_fprint (const char *fmt, ...)
case 'A':
/* %A => addrinfo */
ai = va_arg(args, struct addrinfo *);
+ if (ai->ai_socktype == SOCK_DGRAM)
+ strcpy(tmpbuf, "dgram");
+ else if (ai->ai_socktype == SOCK_STREAM)
+ strcpy(tmpbuf, "stream");
+ else
+ sprintf(tmpbuf, "socktype%d", ai->ai_socktype);
if (0 != getnameinfo (ai->ai_addr, ai->ai_addrlen,
addrbuf, sizeof (addrbuf),
portbuf, sizeof (portbuf),
- NI_NUMERICHOST | NI_NUMERICSERV))
- /*LINTED*/
- strcpy (addrbuf, "??"), strcpy (portbuf, "??");
- sprintf(tmpbuf, "%s %s.%s",
- (ai->ai_socktype == SOCK_DGRAM
- ? "udp"
- : ai->ai_socktype == SOCK_STREAM
- ? "tcp"
- : "???"),
- addrbuf, portbuf);
+ NI_NUMERICHOST | NI_NUMERICSERV)) {
+ if (ai->ai_addr->sa_family == AF_UNSPEC)
+ strcpy(tmpbuf + strlen(tmpbuf), " AF_UNSPEC");
+ else
+ sprintf(tmpbuf + strlen(tmpbuf), " af%d", ai->ai_addr->sa_family);
+ } else
+ sprintf(tmpbuf + strlen(tmpbuf), " %s.%s", addrbuf, portbuf);
putstr(tmpbuf);
break;
case 'D':
/* %D => krb5_data * */
d = va_arg(args, krb5_data *);
+ /* Solaris Kerberos */
p = d->data;
putstr("0x");
for (i = 0; i < d->length; i++) {
@@ -228,29 +263,39 @@ krb5int_debug_fprint (const char *fmt, ...)
/* Solaris kerberos: use syslog() for debug output */
syslog(LOG_DEBUG, global_err_str);
+#endif
}
-#else
-#define dprint (void)
-#define dperror(MSG) ((void)(MSG))
-#endif
+#define print_addrlist krb5int_print_addrlist
+static void
+print_addrlist (const struct addrlist *a)
+{
+ int i;
+ dprint("%d{", a->naddrs);
+ for (i = 0; i < a->naddrs; i++)
+ dprint("%s%p=%A", i ? "," : "", (void*)a->addrs[i].ai, a->addrs[i].ai);
+ dprint("}");
+}
static int
merge_addrlists (struct addrlist *dest, struct addrlist *src)
{
+ /* Wouldn't it be nice if we could filter out duplicates? The
+ alloc/free handling makes that pretty difficult though. */
int err, i;
+/* Solaris Kerberos */
#ifdef DEBUG
/*LINTED*/
dprint("merging addrlists:\n\tlist1: ");
for (i = 0; i < dest->naddrs; i++)
/*LINTED*/
- dprint(" %A", dest->addrs[i]);
+ dprint(" %A", dest->addrs[i].ai);
/*LINTED*/
dprint("\n\tlist2: ");
for (i = 0; i < src->naddrs; i++)
/*LINTED*/
- dprint(" %A", src->addrs[i]);
+ dprint(" %A", src->addrs[i].ai);
/*LINTED*/
dprint("\n");
#endif
@@ -260,17 +305,19 @@ merge_addrlists (struct addrlist *dest, struct addrlist *src)
return err;
for (i = 0; i < src->naddrs; i++) {
dest->addrs[dest->naddrs + i] = src->addrs[i];
- src->addrs[i] = 0;
+ src->addrs[i].ai = 0;
+ src->addrs[i].freefn = 0;
}
dest->naddrs += i;
src->naddrs = 0;
+/* Solaris Kerberos */
#ifdef DEBUG
/*LINTED*/
dprint("\tout: ");
for (i = 0; i < dest->naddrs; i++)
/*LINTED*/
- dprint(" %A", dest->addrs[i]);
+ dprint(" %A", dest->addrs[i].ai);
/*LINTED*/
dprint("\n");
#endif
@@ -278,6 +325,43 @@ merge_addrlists (struct addrlist *dest, struct addrlist *src)
return 0;
}
+static int
+in_addrlist (struct addrinfo *thisaddr, struct addrlist *list)
+{
+ int i;
+ for (i = 0; i < list->naddrs; i++) {
+ if (thisaddr->ai_addrlen == list->addrs[i].ai->ai_addrlen
+ && !memcmp(thisaddr->ai_addr, list->addrs[i].ai->ai_addr,
+ thisaddr->ai_addrlen))
+ return 1;
+ }
+ return 0;
+}
+
+static int
+check_for_svc_unavailable (krb5_context context,
+ const krb5_data *reply,
+ void *msg_handler_data)
+{
+ krb5_error_code *retval = (krb5_error_code *)msg_handler_data;
+
+ *retval = 0;
+
+ if (krb5_is_krb_error(reply)) {
+ krb5_error *err_reply;
+
+ if (decode_krb5_error(reply, &err_reply) == 0) {
+ *retval = err_reply->error;
+ krb5_free_error(context, err_reply);
+
+ /* Returning 0 means continue to next KDC */
+ return (*retval != KDC_ERR_SVC_UNAVAILABLE);
+ }
+ }
+
+ return 1;
+}
+
/*
* send the formatted request 'message' to a KDC for realm 'realm' and
* return the response (if any) in 'reply'.
@@ -294,7 +378,7 @@ krb5_sendto_kdc (krb5_context context, const krb5_data *message,
const krb5_data *realm, krb5_data *reply,
int *use_master, int tcp_only)
{
- krb5_error_code retval;
+ krb5_error_code retval, retval2;
struct addrlist addrs;
int socktype1 = 0, socktype2 = 0, addr_used;
@@ -346,50 +430,85 @@ krb5_sendto_kdc (krb5_context context, const krb5_data *message,
if (socktype2) {
struct addrlist addrs2;
- retval = krb5_locate_kdc(context, realm, &addrs2, *use_master,
- socktype2, 0);
+ retval2 = krb5_locate_kdc(context, realm, &addrs2, *use_master,
+ socktype2, 0);
+#if 0
+ if (retval2 == 0) {
+ (void) merge_addrlists(&addrs, &addrs2);
+ krb5int_free_addrlist(&addrs2);
+ retval = 0;
+ } else if (retval == KRB5_REALM_CANT_RESOLVE) {
+ retval = retval2;
+ }
+#else
+ retval = retval2;
if (retval == 0) {
(void) merge_addrlists(&addrs, &addrs2);
krb5int_free_addrlist(&addrs2);
}
+#endif
}
+
if (addrs.naddrs > 0) {
- retval = krb5int_sendto (context, message, &addrs, reply, 0, 0,
- &addr_used);
- if (retval == 0) {
+ krb5_error_code err = 0;
+
+ retval = krb5int_sendto (context, message, &addrs, 0, reply, 0, 0,
+ 0, 0, &addr_used, check_for_svc_unavailable, &err);
+ switch (retval) {
+ case 0:
/*
- * Set use_master to 1 if we ended up talking to a master when
- * didn't explicitly request to
- */
-
- if (*use_master == 0) {
- struct addrlist addrs3;
- retval = krb5_locate_kdc(context, realm, &addrs3, 1,
- addrs.addrs[addr_used]->ai_socktype,
- addrs.addrs[addr_used]->ai_family);
- if (retval == 0) {
- int i;
- for (i = 0; i < addrs3.naddrs; i++) {
- if (addrs.addrs[addr_used]->ai_addrlen ==
- addrs3.addrs[i]->ai_addrlen &&
- memcmp(addrs.addrs[addr_used]->ai_addr,
- addrs3.addrs[i]->ai_addr,
- addrs.addrs[addr_used]->ai_addrlen) == 0) {
- *use_master = 1;
- break;
- }
- }
- krb5int_free_addrlist (&addrs3);
- }
+ * Set use_master to 1 if we ended up talking to a master when
+ * we didn't explicitly request to
+ */
+ if (*use_master == 0) {
+ struct addrlist addrs3;
+ retval = krb5_locate_kdc(context, realm, &addrs3, 1,
+ addrs.addrs[addr_used].ai->ai_socktype,
+ addrs.addrs[addr_used].ai->ai_family);
+ if (retval == 0) {
+ if (in_addrlist(addrs.addrs[addr_used].ai, &addrs3))
+ *use_master = 1;
+ krb5int_free_addrlist (&addrs3);
+ }
+ }
+ krb5int_free_addrlist (&addrs);
+ return 0;
+ default:
+ break;
+ /* Cases here are for constructing useful error messages. */
+ case KRB5_KDC_UNREACH:
+ if (err == KDC_ERR_SVC_UNAVAILABLE) {
+ retval = KRB5KDC_ERR_SVC_UNAVAILABLE;
+ } else {
+ krb5_set_error_message(context, retval,
+ "Cannot contact any KDC for realm '%.*s'",
+ realm->length, realm->data);
}
- krb5int_free_addrlist (&addrs);
- return 0;
+ break;
}
- krb5int_free_addrlist (&addrs);
+ krb5int_free_addrlist (&addrs);
}
return retval;
}
+#ifdef DEBUG
+
+#ifdef _WIN32
+#define dperror(MSG) \
+ dprint("%s: an error occurred ... " \
+ "\tline=%d errno=%m socketerrno=%m\n", \
+ (MSG), __LINE__, errno, SOCKET_ERRNO)
+#else
+#define dperror(MSG) dprint("%s: %m\n", MSG, errno)
+#endif
+#define dfprintf(ARGLIST) (debug ? fprintf ARGLIST : 0)
+
+#else /* ! DEBUG */
+
+#define dperror(MSG) ((void)(MSG))
+#define dfprintf(ARGLIST) ((void)0)
+
+#endif
/*
* Notes:
@@ -411,44 +530,24 @@ krb5_sendto_kdc (krb5_context context, const krb5_data *message,
* connections already in progress
*/
-#include <cm.h>
-
-static const char *const state_strings[] = {
- "INITIALIZING", "CONNECTING", "WRITING", "READING", "FAILED"
-};
-enum conn_states { INITIALIZING, CONNECTING, WRITING, READING, FAILED };
-struct incoming_krb5_message {
- size_t bufsizebytes_read;
- size_t bufsize;
- char *buf;
- char *pos;
- unsigned char bufsizebytes[4];
- size_t n_left;
-};
-struct conn_state {
- SOCKET fd;
- krb5_error_code err;
- enum conn_states state;
- unsigned int is_udp : 1;
- int (*service)(struct conn_state *, struct select_state *, int);
- struct addrinfo *addr;
- struct {
- struct {
- sg_buf sgbuf[2];
- sg_buf *sgp;
- int sg_count;
- } out;
- struct incoming_krb5_message in;
- } x;
-};
+#include "cm.h"
static int getcurtime (struct timeval *tvp)
{
+#ifdef _WIN32
+ struct _timeb tb;
+ _ftime(&tb);
+ tvp->tv_sec = tb.time;
+ tvp->tv_usec = tb.millitm * 1000;
+ /* Can _ftime fail? */
+ return 0;
+#else
if (gettimeofday(tvp, 0)) {
dperror("gettimeofday");
return errno;
}
return 0;
+#endif
}
/*
@@ -486,10 +585,13 @@ krb5int_cm_call_select (const struct select_state *in,
/*LINTED*/
dprint("selecting on max=%d sockets [%F] timeout %t\n",
/*LINTED*/
- out->max, &out->rfds, &out->wfds, &out->xfds, out->max, timo);
+ out->max,
+ &out->rfds, &out->wfds, &out->xfds, out->max,
+ timo);
*sret = select(out->max, &out->rfds, &out->wfds, &out->xfds, timo);
e = SOCKET_ERRNO;
+/* Solaris Kerberos */
#ifdef DEBUG
/*LINTED*/
dprint("select returns %d", *sret);
@@ -514,11 +616,37 @@ static int service_tcp_fd (struct conn_state *conn,
static int service_udp_fd (struct conn_state *conn,
struct select_state *selstate, int ssflags);
+static void
+set_conn_state_msg_length (struct conn_state *state, const krb5_data *message)
+{
+ if (!message || message->length == 0)
+ return;
+
+ if (!state->is_udp) {
+
+ state->x.out.msg_len_buf[0] = (message->length >> 24) & 0xff;
+ state->x.out.msg_len_buf[1] = (message->length >> 16) & 0xff;
+ state->x.out.msg_len_buf[2] = (message->length >> 8) & 0xff;
+ state->x.out.msg_len_buf[3] = message->length & 0xff;
+
+ SG_SET(&state->x.out.sgbuf[0], state->x.out.msg_len_buf, 4);
+ SG_SET(&state->x.out.sgbuf[1], message->data, message->length);
+ state->x.out.sg_count = 2;
+
+ } else {
+
+ SG_SET(&state->x.out.sgbuf[0], message->data, message->length);
+ SG_SET(&state->x.out.sgbuf[1], 0, 0);
+ state->x.out.sg_count = 1;
+
+ }
+}
+
+
static int
setup_connection (struct conn_state *state, struct addrinfo *ai,
- const krb5_data *message, unsigned char *message_len_buf,
- char **udpbufp)
+ const krb5_data *message, char **udpbufp)
{
state->state = INITIALIZING;
state->err = 0;
@@ -527,17 +655,25 @@ setup_connection (struct conn_state *state, struct addrinfo *ai,
state->fd = INVALID_SOCKET;
SG_SET(&state->x.out.sgbuf[1], 0, 0);
if (ai->ai_socktype == SOCK_STREAM) {
+ /*
SG_SET(&state->x.out.sgbuf[0], message_len_buf, 4);
SG_SET(&state->x.out.sgbuf[1], message->data, message->length);
state->x.out.sg_count = 2;
+ */
+
state->is_udp = 0;
state->service = service_tcp_fd;
+ set_conn_state_msg_length (state, message);
} else {
+ /*
SG_SET(&state->x.out.sgbuf[0], message->data, message->length);
SG_SET(&state->x.out.sgbuf[1], 0, 0);
state->x.out.sg_count = 1;
+ */
+
state->is_udp = 1;
state->service = service_udp_fd;
+ set_conn_state_msg_length (state, message);
if (*udpbufp == 0) {
*udpbufp = malloc(krb5_max_dgram_size);
@@ -556,7 +692,10 @@ setup_connection (struct conn_state *state, struct addrinfo *ai,
}
static int
-start_connection (struct conn_state *state, struct select_state *selstate)
+start_connection (struct conn_state *state,
+ struct select_state *selstate,
+ struct sendto_callback_info* callback_info,
+ krb5_data* callback_buffer)
{
int fd, e;
struct addrinfo *ai = state->addr;
@@ -594,9 +733,11 @@ start_connection (struct conn_state *state, struct select_state *selstate)
*/
if (SOCKET_ERRNO == EINPROGRESS || SOCKET_ERRNO == EWOULDBLOCK) {
state->state = CONNECTING;
+ state->fd = fd;
} else {
/*LINTED*/
dprint("connect failed: %m\n", SOCKET_ERRNO);
+ (void) closesocket(fd);
state->err = SOCKET_ERRNO;
state->state = FAILED;
return -2;
@@ -609,11 +750,37 @@ start_connection (struct conn_state *state, struct select_state *selstate)
* stack is broken, but if they gave us a connection, use it.
*/
state->state = WRITING;
+ state->fd = fd;
}
/*LINTED*/
dprint("new state = %s\n", state_strings[state->state]);
- state->fd = fd;
+
+ /*
+ * Here's where KPASSWD callback gets the socket information it needs for
+ * a kpasswd request
+ */
+ if (callback_info) {
+
+ e = callback_info->pfn_callback(state,
+ callback_info->context,
+ callback_buffer);
+ if (e != 0) {
+ dprint("callback failed: %m\n", e);
+ (void) closesocket(fd);
+ state->err = e;
+ state->fd = INVALID_SOCKET;
+ state->state = FAILED;
+ return -3;
+ }
+
+ dprint("callback %p (message=%d@%p)\n",
+ state,
+ callback_buffer->length,
+ callback_buffer->data);
+
+ set_conn_state_msg_length( state, callback_buffer );
+ }
if (ai->ai_socktype == SOCK_DGRAM) {
/* Send it now. */
@@ -628,12 +795,26 @@ start_connection (struct conn_state *state, struct select_state *selstate)
(void) closesocket(state->fd);
state->fd = INVALID_SOCKET;
state->state = FAILED;
- return -3;
+ return -4;
} else {
state->state = READING;
}
}
-
+#ifdef DEBUG
+ if (debug) {
+ struct sockaddr_storage ss;
+ socklen_t sslen = sizeof(ss);
+ if (getsockname(state->fd, (struct sockaddr *)&ss, &sslen) == 0) {
+ struct addrinfo hack_ai;
+ memset(&hack_ai, 0, sizeof(hack_ai));
+ hack_ai.ai_addr = (struct sockaddr *) &ss;
+ hack_ai.ai_addrlen = sslen;
+ hack_ai.ai_socktype = SOCK_DGRAM;
+ hack_ai.ai_family = ai->ai_family;
+ dprint("local socket address is %A\n", &hack_ai);
+ }
+ }
+#endif
FD_SET(state->fd, &selstate->rfds);
if (state->state == CONNECTING || state->state == WRITING)
FD_SET(state->fd, &selstate->wfds);
@@ -655,16 +836,20 @@ start_connection (struct conn_state *state, struct select_state *selstate)
Otherwise, the caller should immediately move on to process the
next connection. */
static int
-maybe_send (struct conn_state *conn, struct select_state *selstate)
+maybe_send (struct conn_state *conn,
+ struct select_state *selstate,
+ struct sendto_callback_info* callback_info,
+ krb5_data* callback_buffer)
{
sg_buf *sg;
/*LINTED*/
dprint("maybe_send(@%p) state=%s type=%s\n", conn,
/*LINTED*/
- state_strings[conn->state], conn->is_udp ? "udp" : "tcp");
+ state_strings[conn->state],
+ conn->is_udp ? "udp" : "tcp");
if (conn->state == INITIALIZING)
- return start_connection(conn, selstate);
+ return start_connection(conn, selstate, callback_info, callback_buffer);
/* Did we already shut down this channel? */
if (conn->state == FAILED) {
@@ -720,6 +905,25 @@ kill_conn(struct conn_state *conn, struct select_state *selstate, int err)
selstate->nfds--;
}
+/* Check socket for error. */
+static int
+get_so_error(int fd)
+{
+ int e, sockerr;
+ socklen_t sockerrlen;
+
+ sockerr = 0;
+ sockerrlen = sizeof(sockerr);
+ e = getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &sockerrlen);
+ if (e != 0) {
+ /* What to do now? */
+ e = SOCKET_ERRNO;
+ dprint("getsockopt(SO_ERROR) on fd failed: %m\n", e);
+ return e;
+ }
+ return sockerr;
+}
+
/* Return nonzero only if we're finished and the caller should exit
its loop. This happens in two cases: We have a complete message,
or the socket has closed and no others are open. */
@@ -750,15 +954,28 @@ service_tcp_fd (struct conn_state *conn, struct select_state *selstate,
}
if (ssflags & SSF_EXCEPTION) {
handle_exception:
- e = 1; /* need only be non-zero */
+ e = get_so_error(conn->fd);
+ if (e)
+ dprint("socket error on exception fd: %m", e);
+ else
+ dprint("no socket error info available on exception fd");
goto kill_conn;
}
/*
* Connect finished -- but did it succeed or fail?
* UNIX sets can_write if failed.
- * Try writing, I guess, and find out.
+ * Call getsockopt to see if error pending.
+ *
+ * (For most UNIX systems it works to just try writing the
+ * first time and detect an error. But Bill Dodd at IBM
+ * reports that some version of AIX, SIGPIPE can result.)
*/
+ e = get_so_error(conn->fd);
+ if (e) {
+ dprint("socket error on write fd: %m", e);
+ goto kill_conn;
+ }
conn->state = WRITING;
goto try_writing;
@@ -847,6 +1064,7 @@ service_tcp_fd (struct conn_state *conn, struct select_state *selstate,
}
conn->x.in.n_left -= nread;
conn->x.in.pos += nread;
+ /* Solaris Kerberos */
if ((long)conn->x.in.n_left <= 0) {
/* We win! */
return 1;
@@ -915,15 +1133,18 @@ service_udp_fd(struct conn_state *conn, struct select_state *selstate,
}
static int
-service_fds (struct select_state *selstate,
- struct conn_state *conns, size_t n_conns, int *winning_conn)
+service_fds (krb5_context context,
+ struct select_state *selstate,
+ struct conn_state *conns, size_t n_conns, int *winning_conn,
+ struct select_state *seltemp,
+ int (*msg_handler)(krb5_context, const krb5_data *, void *),
+ void *msg_handler_data)
{
int e, selret;
- struct select_state sel_results;
e = 0;
while (selstate->nfds > 0
- && (e = krb5int_cm_call_select(selstate, &sel_results, &selret)) == 0) {
+ && (e = krb5int_cm_call_select(selstate, seltemp, &selret)) == 0) {
int i;
/*LINTED*/
@@ -940,11 +1161,11 @@ service_fds (struct select_state *selstate,
if (conns[i].fd == INVALID_SOCKET)
continue;
ssflags = 0;
- if (FD_ISSET(conns[i].fd, &sel_results.rfds))
+ if (FD_ISSET(conns[i].fd, &seltemp->rfds))
ssflags |= SSF_READ, selret--;
- if (FD_ISSET(conns[i].fd, &sel_results.wfds))
+ if (FD_ISSET(conns[i].fd, &seltemp->wfds))
ssflags |= SSF_WRITE, selret--;
- if (FD_ISSET(conns[i].fd, &sel_results.xfds))
+ if (FD_ISSET(conns[i].fd, &seltemp->xfds))
ssflags |= SSF_EXCEPTION, selret--;
if (!ssflags)
continue;
@@ -962,9 +1183,22 @@ service_fds (struct select_state *selstate,
state_strings[(int) conns[i].state]);
if (conns[i].service (&conns[i], selstate, ssflags)) {
- dprint("fd service routine says we're done\n");
- *winning_conn = i;
- return 1;
+ int stop = 1;
+
+ if (msg_handler != NULL) {
+ krb5_data reply;
+
+ reply.data = conns[i].x.in.buf;
+ reply.length = conns[i].x.in.pos - conns[i].x.in.buf;
+
+ stop = (msg_handler(context, &reply, msg_handler_data) != 0);
+ }
+
+ if (stop) {
+ dprint("fd service routine says we're done\n");
+ *winning_conn = i;
+ return 1;
+ }
}
}
}
@@ -1002,23 +1236,32 @@ service_fds (struct select_state *selstate,
krb5_error_code
/*ARGSUSED*/
krb5int_sendto (krb5_context context, const krb5_data *message,
- const struct addrlist *addrs, krb5_data *reply,
- struct sockaddr_storage *localaddr, socklen_t *localaddrlen,
- int *addr_used)
+ const struct addrlist *addrs,
+ struct sendto_callback_info* callback_info, krb5_data *reply,
+ struct sockaddr *localaddr, socklen_t *localaddrlen,
+ struct sockaddr *remoteaddr, socklen_t *remoteaddrlen,
+ int *addr_used,
+ /* return 0 -> keep going, 1 -> quit */
+ int (*msg_handler)(krb5_context, const krb5_data *, void *),
+ void *msg_handler_data)
{
int i, pass;
int delay_this_pass = 2;
krb5_error_code retval;
struct conn_state *conns;
+ krb5_data *callback_data = 0;
size_t n_conns, host;
- struct select_state select_state;
+ struct select_state *sel_state;
struct timeval now;
int winning_conn = -1, e = 0;
- unsigned char message_len_buf[4];
char *udpbuf = 0;
- /*LINTED*/
- dprint("krb5int_sendto(message=%d@%p)\n", message->length, message->data);
+ if (message)
+ dprint("krb5int_sendto(message=%d@%p, addrlist=", message->length, message->data);
+ else
+ dprint("krb5int_sendto(callback=%p, addrlist=", callback_info);
+ print_addrlist(addrs);
+ dprint(")\n");
reply->data = 0;
reply->length = 0;
@@ -1028,26 +1271,43 @@ krb5int_sendto (krb5_context context, const krb5_data *message,
if (conns == NULL) {
return ENOMEM;
}
- memset(conns, 0, n_conns * sizeof(conns[i]));
+
+ memset(conns, 0, n_conns * sizeof(struct conn_state));
+
+ if (callback_info) {
+ callback_data = malloc(n_conns * sizeof(krb5_data));
+ if (callback_data == NULL) {
+ return ENOMEM;
+ }
+
+ memset(callback_data, 0, n_conns * sizeof(krb5_data));
+ }
+
for (i = 0; i < n_conns; i++) {
conns[i].fd = INVALID_SOCKET;
}
- select_state.max = 0;
- select_state.nfds = 0;
- FD_ZERO(&select_state.rfds);
- FD_ZERO(&select_state.wfds);
- FD_ZERO(&select_state.xfds);
+ /* One for use here, listing all our fds in use, and one for
+ temporary use in service_fds, for the fds of interest. */
+ sel_state = malloc(2 * sizeof(*sel_state));
+ if (sel_state == NULL) {
+ free(conns);
+ return ENOMEM;
+ }
+ sel_state->max = 0;
+ sel_state->nfds = 0;
+ sel_state->end_time.tv_sec = sel_state->end_time.tv_usec = 0;
+ FD_ZERO(&sel_state->rfds);
+ FD_ZERO(&sel_state->wfds);
+ FD_ZERO(&sel_state->xfds);
- message_len_buf[0] = (message->length >> 24) & 0xff;
- message_len_buf[1] = (message->length >> 16) & 0xff;
- message_len_buf[2] = (message->length >> 8) & 0xff;
- message_len_buf[3] = message->length & 0xff;
/* Set up connections. */
for (host = 0; host < n_conns; host++) {
- retval = setup_connection (&conns[host], addrs->addrs[host],
- message, message_len_buf, &udpbuf);
+ retval = setup_connection(&conns[host],
+ addrs->addrs[host].ai,
+ message,
+ &udpbuf);
if (retval)
continue;
}
@@ -1061,18 +1321,22 @@ krb5int_sendto (krb5_context context, const krb5_data *message,
dprint("host %d\n", host);
/* Send to the host, wait for a response, then move on. */
- if (maybe_send(&conns[host], &select_state))
+ if (maybe_send(&conns[host],
+ sel_state,
+ callback_info,
+ (callback_info ? &callback_data[host] : NULL)))
continue;
retval = getcurtime(&now);
if (retval)
goto egress;
- select_state.end_time = now;
- select_state.end_time.tv_sec += 1;
- e = service_fds(&select_state, conns, host+1, &winning_conn);
+ sel_state->end_time = now;
+ sel_state->end_time.tv_sec += 1;
+ e = service_fds(context, sel_state, conns, host+1, &winning_conn,
+ sel_state+1, msg_handler, msg_handler_data);
if (e)
break;
- if (pass > 0 && select_state.nfds == 0)
+ if (pass > 0 && sel_state->nfds == 0)
/*
* After the first pass, if we close all fds, break
* out right away. During the first pass, it's okay,
@@ -1088,16 +1352,17 @@ krb5int_sendto (krb5_context context, const krb5_data *message,
/* Possible optimization: Find a way to integrate this select
call with the last one from the above loop, if the loop
actually calls select. */
- select_state.end_time.tv_sec += delay_this_pass;
- e = service_fds(&select_state, conns, host+1, &winning_conn);
+ sel_state->end_time.tv_sec += delay_this_pass;
+ e = service_fds(context, sel_state, conns, host+1, &winning_conn,
+ sel_state+1, msg_handler, msg_handler_data);
if (e)
break;
- if (select_state.nfds == 0)
+ if (sel_state->nfds == 0)
break;
delay_this_pass *= 2;
}
- if (select_state.nfds == 0) {
+ if (sel_state->nfds == 0) {
/* No addresses? */
retval = KRB5_KDC_UNREACH;
goto egress;
@@ -1111,26 +1376,37 @@ krb5int_sendto (krb5_context context, const krb5_data *message,
reply->length = (conns[winning_conn].x.in.pos
- conns[winning_conn].x.in.buf);
/*LINTED*/
- dprint("returning %d bytes in buffer %p (winning_conn=%d)\n",
- (int) reply->length, reply->data, winning_conn);
+ dprint("returning %d bytes in buffer %p\n",
+ (int) reply->length, reply->data);
retval = 0;
conns[winning_conn].x.in.buf = 0;
if (addr_used)
- *addr_used = winning_conn;
+ *addr_used = winning_conn;
if (localaddr != 0 && localaddrlen != 0 && *localaddrlen > 0)
- (void) getsockname(conns[winning_conn].fd, (struct sockaddr *)localaddr,
- localaddrlen);
+ (void) getsockname(conns[winning_conn].fd, localaddr, localaddrlen);
+
+ if (remoteaddr != 0 && remoteaddrlen != 0 && *remoteaddrlen > 0)
+ (void) getpeername(conns[winning_conn].fd, remoteaddr, remoteaddrlen);
+
egress:
for (i = 0; i < n_conns; i++) {
if (conns[i].fd != INVALID_SOCKET)
- close(conns[i].fd);
+ closesocket(conns[i].fd);
if (conns[i].state == READING
&& conns[i].x.in.buf != 0
&& conns[i].x.in.buf != udpbuf)
free(conns[i].x.in.buf);
+ if (callback_info) {
+ callback_info->pfn_cleanup( callback_info->context, &callback_data[i]);
+ }
}
+
+ if (callback_data)
+ free(callback_data);
+
free(conns);
if (reply->data != udpbuf)
free(udpbuf);
+ free(sel_state);
return retval;
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/sn2princ.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/sn2princ.c
index ac2fcc09aa..a865683b5e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/sn2princ.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/sn2princ.c
@@ -33,14 +33,19 @@
* form.
*/
-#include <k5-int.h>
+#include "k5-int.h"
+#include "os-proto.h"
#include "fake-addrinfo.h"
#include <ctype.h>
-#include <netdb.h>
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
+#if !defined(DEFAULT_RDNS_LOOKUP)
+/* Solaris Kerberos */
+#define DEFAULT_RDNS_LOOKUP 0
+#endif
+
/*
* Solaris Kerberos:
* The following prototypes are needed because these are
@@ -50,25 +55,41 @@ extern struct hostent *res_getipnodebyname(const char *, int, int, int *);
extern struct hostent *res_getipnodebyaddr(const void *, size_t, int, int *);
extern void res_freehostent(struct hostent *);
+static int
+maybe_use_reverse_dns (krb5_context context, int defalt)
+{
+ krb5_error_code code;
+ char * value = NULL;
+ int use_rdns = 0;
+
+ code = profile_get_string(context->profile, "libdefaults",
+ "rdns", 0, 0, &value);
+ if (code)
+ return defalt;
+
+ if (value == 0)
+ return defalt;
+
+ use_rdns = _krb5_conf_boolean(value);
+ profile_release_string(value);
+ return use_rdns;
+}
+
+
/*
+ * Solaris Kerberos:
* Note, krb5_sname_to_principal() allocates memory for ret_princ. Be sure to
* use krb5_free_principal() on ret_princ to free it when done referencing it.
*/
-krb5_error_code KRB5_CALLCONV
+krb5_error_code KRB5_CALLCONV
krb5_sname_to_principal(krb5_context context, const char *hostname, const char *sname, krb5_int32 type, krb5_principal *ret_princ)
{
char **hrealms, *realm, *remote_host;
krb5_error_code retval;
register char *cp;
char localname[MAXHOSTNAMELEN];
- /*
- * Solaris Kerberos:
- * Indicate whether or not to do a reverse lookup on a hostname for a host
- * based principal.
- */
- int rev_lookup = NO_REV_LOOKUP;
-
- KRB5_LOG0(KRB5_INFO, "krb5_sname_to_principal() start");
+ /* Solaris Kerberos */
+ KRB5_LOG0(KRB5_INFO, "krb5_sname_to_principal() start");
#ifdef DEBUG_REFERRALS
printf("krb5_sname_to_principal(host=%s, sname=%s, type=%d)\n",hostname,sname,type);
printf(" name types: 0=unknown, 3=srv_host\n");
@@ -80,6 +101,7 @@ krb5_sname_to_principal(krb5_context context, const char *hostname, const char *
/* if hostname is NULL, use local hostname */
if (! hostname) {
if (gethostname(localname, MAXHOSTNAMELEN)) {
+ /* Solaris Kerberos */
KRB5_LOG0(KRB5_ERR, "krb5_sname_to_principal()"
" gethostname failed");
return SOCKET_ERRNO;
@@ -92,19 +114,97 @@ krb5_sname_to_principal(krb5_context context, const char *hostname, const char *
sname = "host";
/* copy the hostname into non-volatile storage */
+
if (type == KRB5_NT_SRV_HST) {
- /* Solaris Kerberos: don't want to do reverse lookup at this point
- * as this will introduce a behavior change. ifdef'ing this out in
- * case we want to allow reverse lookup as a compile option.
- */
-#ifdef KRB5_SNAME_TO_PRINCIPAL_REV_LOOKUP
- rev_lookup = REV_LOOKUP;
+ /* Solaris Kerberos */
+ struct hostent *hp = NULL;
+ struct hostent *hp2 = NULL;
+ int err;
+ int addr_family;
+
+ /* Note that the old code would accept numeric addresses,
+ and if the gethostbyaddr step could convert them to
+ real hostnames, you could actually get reasonable
+ results. If the mapping failed, you'd get dotted
+ triples as realm names. *sigh*
+
+ The latter has been fixed in hst_realm.c, but we should
+ keep supporting numeric addresses if they do have
+ hostnames associated. */
+
+ /*
+ * Solaris kerberos: using res_getipnodebyname() to force dns name
+ * resolution. Note, res_getaddrinfo() isn't exported by libreolv
+ * so we use res_getipnodebyname() (MIT uses getaddrinfo()).
+ */
+ KRB5_LOG(KRB5_INFO, "krb5_sname_to_principal() hostname %s",
+ hostname);
+
+ addr_family = AF_INET;
+ try_getipnodebyname_again:
+ hp = res_getipnodebyname(hostname, addr_family, 0, &err);
+ if (!hp) {
+#ifdef DEBUG_REFERRALS
+ printf("sname_to_princ: probably punting due to bad hostname of %s\n",hostname);
#endif
- if (retval = krb5int_lookup_host(rev_lookup, hostname, &remote_host)) {
- return retval;
- }
+ if (addr_family == AF_INET) {
+ KRB5_LOG(KRB5_INFO, "krb5_sname_to_principal()"
+ " can't get AF_INET addr, err = %d", err);
+ /* Just in case it's an IPv6-only name. */
+ addr_family = AF_INET6;
+ goto try_getipnodebyname_again;
+ }
+ KRB5_LOG(KRB5_ERR, "krb5_sname_to_principal()"
+ " can't get AF_INET or AF_INET6 addr,"
+ " err = %d", err);
+ return KRB5_ERR_BAD_HOSTNAME;
+ }
+ remote_host = strdup(hp ? hp->h_name : hostname);
+ if (!remote_host) {
+ if (hp != NULL)
+ res_freehostent(hp);
+ return ENOMEM;
+ }
+
+ if (maybe_use_reverse_dns(context, DEFAULT_RDNS_LOOKUP)) {
+ /*
+ * Do a reverse resolution to get the full name, just in
+ * case there's some funny business going on. If there
+ * isn't an in-addr record, give up.
+ */
+ /* XXX: This is *so* bogus. There are several cases where
+ this won't get us the canonical name of the host, but
+ this is what we've trained people to expect. We'll
+ probably fix it at some point, but let's try to
+ preserve the current behavior and only shake things up
+ once when it comes time to fix this lossage. */
+ hp2 = res_getipnodebyaddr(hp->h_addr, hp->h_length,
+ hp->h_addrtype, &err);
+
+ if (hp2 != NULL) {
+ free(remote_host);
+ remote_host = strdup(hp2->h_name);
+ if (!remote_host) {
+ res_freehostent(hp2);
+ if (hp != NULL)
+ res_freehostent(hp);
+ return ENOMEM;
+ }
+ KRB5_LOG(KRB5_INFO, "krb5_sname_to_principal() remote_host %s",
+ remote_host);
+ }
+ }
+
+ if (hp != NULL) {
+ res_freehostent(hp);
+ }
+
+ if (hp2 != NULL) {
+ res_freehostent(hp2);
+ }
+
} else /* type == KRB5_NT_UNKNOWN */ {
- remote_host = strdup((char *) hostname);
+ remote_host = strdup(hostname);
}
if (!remote_host)
return ENOMEM;
@@ -114,8 +214,8 @@ krb5_sname_to_principal(krb5_context context, const char *hostname, const char *
if (type == KRB5_NT_SRV_HST)
for (cp = remote_host; *cp; cp++)
- if (isupper((int) *cp))
- *cp = tolower((int) *cp);
+ if (isupper((unsigned char) (*cp)))
+ *cp = tolower((unsigned char) (*cp));
/*
* Windows NT5's broken resolver gratuitously tacks on a
@@ -123,12 +223,13 @@ krb5_sname_to_principal(krb5_context context, const char *hostname, const char *
* Beta2). Find and remove it.
*/
if (remote_host[0]) {
- cp = remote_host + strlen(remote_host)-1;
- if (*cp == '.')
- *cp = 0;
+ cp = remote_host + strlen(remote_host)-1;
+ if (*cp == '.')
+ *cp = 0;
}
- if (retval = krb5_get_host_realm(context, remote_host, &hrealms)) {
+
+ if ((retval = krb5_get_host_realm(context, remote_host, &hrealms))) {
free(remote_host);
return retval;
}
@@ -166,95 +267,3 @@ krb5_sname_to_principal(krb5_context context, const char *hostname, const char *
}
}
-/*
- * Solaris Kerberos:
- * Lookup a host in DNS. If hostname cannot be resolved in DNS return
- * KRB5_ERR_BAD_HOSTNAME.
- * If "rev_lookup" is non-zero a reverse lookup will be performed.
- * "remote_host" will point to the resolved hostname.
- * Code taken from krb5_sname_to_principal().
- */
-krb5_error_code
-krb5int_lookup_host(int rev_lookup, const char *hostname, char **remote_host) {
- struct hostent *hp = NULL;
- struct hostent *hp2 = NULL;
- int addr_family;
- int err;
-
- /* Note that the old code would accept numeric addresses,
- and if the gethostbyaddr step could convert them to
- real hostnames, you could actually get reasonable
- results. If the mapping failed, you'd get dotted
- triples as realm names. *sigh*
-
- The latter has been fixed in hst_realm.c, but we should
- keep supporting numeric addresses if they do have
- hostnames associated. */
-
- /*
- * Solaris kerberos: using res_getipnodebyname() to force dns name
- * resolution. Note, res_getaddrinfo() isn't exported by libreolv
- * so we use res_getipnodebyname() (MIT uses getaddrinfo()).
- */
- KRB5_LOG(KRB5_INFO, "krb5int_lookup_host() hostname %s",
- hostname);
-
- addr_family = AF_INET;
-try_getipnodebyname_again:
- hp = res_getipnodebyname(hostname, addr_family, 0, &err);
- if (!hp) {
- if (addr_family == AF_INET) {
- KRB5_LOG(KRB5_INFO, "krb5int_lookup_host()"
- " can't get AF_INET addr, err = %d", err);
- /* Just in case it's an IPv6-only name. */
- addr_family = AF_INET6;
- goto try_getipnodebyname_again;
- }
- KRB5_LOG(KRB5_ERR, "krb5int_lookup_host()"
- " can't get AF_INET or AF_INET6 addr,"
- " err = %d", err);
- return (KRB5_ERR_BAD_HOSTNAME);
- }
- *remote_host = strdup(hp ? hp->h_name : hostname);
- if (!*remote_host) {
- if (hp != NULL)
- res_freehostent(hp);
- return ENOMEM;
- }
-
- if (rev_lookup) {
- /*
- * Do a reverse resolution to get the full name, just in
- * case there's some funny business going on. If there
- * isn't an in-addr record, give up.
- */
- /* XXX: This is *so* bogus. There are several cases where
- this won't get us the canonical name of the host, but
- this is what we've trained people to expect. We'll
- probably fix it at some point, but let's try to
- preserve the current behavior and only shake things up
- once when it comes time to fix this lossage. */
-
- hp2 = res_getipnodebyaddr(hp->h_addr, hp->h_length,
- hp->h_addrtype, &err);
- if (hp2 != NULL) {
- free(*remote_host);
- *remote_host = strdup(hp2->h_name);
- if (!*remote_host) {
- res_freehostent(hp2);
- if (hp != NULL)
- res_freehostent(hp);
- return ENOMEM;
- }
- KRB5_LOG(KRB5_INFO, "krb5int_lookup_host() remote_host %s",
- *remote_host);
- }
- }
- if (hp != NULL) {
- res_freehostent(hp);
- }
- if (hp2 != NULL) {
- res_freehostent(hp2);
- }
- return (0);
-}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/unlck_file.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/unlck_file.c
index cdfb6b2e6f..0bbf7ce316 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/unlck_file.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/unlck_file.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/unlck_file.c
*
@@ -17,7 +16,10 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/ustime.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/ustime.c
index e38005d7bc..ef923d387c 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/ustime.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/ustime.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/ustime.c
*
@@ -32,10 +31,10 @@
* this time adjustment be done.
*/
-#include <k5-int.h>
+#include "k5-int.h"
krb5_error_code KRB5_CALLCONV
-krb5_us_timeofday(krb5_context context, krb5_int32 *seconds, krb5_int32 *microseconds)
+krb5_us_timeofday(krb5_context context, krb5_timestamp *seconds, krb5_int32 *microseconds)
{
krb5_os_context os_ctx = context->os_context;
krb5_int32 sec, usec;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/write_msg.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/write_msg.c
index c767b63c0f..d75a32796d 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/os/write_msg.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/os/write_msg.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/write_msg.c
*
@@ -17,7 +16,10 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
@@ -25,7 +27,6 @@
* convenience sendauth/recvauth functions
*/
-#define NEED_SOCKETS
#include "k5-int.h"
#include <errno.h>
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/posix/daemon.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/posix/daemon.c
index a173270d33..00dde4882e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/posix/daemon.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/posix/daemon.c
@@ -1,10 +1,3 @@
-/*
- * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
@@ -38,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include <fcntl.h>
#include <sys/types.h>
#include <sys/file.h>
@@ -69,7 +62,7 @@ daemon(nochdir, noclose)
#else
{
int n;
-
+
/*
* The open below may hang on pseudo ttys if the person
* who starts named logs out before this point. Thus,
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc-int.h b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc-int.h
index 00db4e386f..ad3e343fe1 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc-int.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc-int.h
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/krb5/keytab/rc-int.h
*
@@ -73,7 +71,8 @@ typedef struct _krb5_rc_ops krb5_rc_ops;
krb5_error_code krb5_rc_register_type (krb5_context, const krb5_rc_ops *);
-extern krb5_rc_ops *krb5_rc_dfl_ops;
+/* Solaris Kerberos */
+extern krb5_rc_ops const *krb5_rc_dfl_ops;
extern const krb5_rc_ops krb5_rc_none_ops;
#endif /* __KRB5_RCACHE_INT_H__ */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_base.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_base.c
index f589e32c02..76f20be357 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_base.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_base.c
@@ -1,15 +1,15 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/rcache/rc_base.c
*
* This file of the Kerberos V5 software is derived from public-domain code
* contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
+ *
*/
@@ -21,26 +21,24 @@
#include "rc_common.h"
#include "rc_mem.h"
#include "rc_file.h"
-#include <k5-thread.h>
+#include "k5-thread.h"
+/* Solaris Kerberos */
#define FREE_RC(x) ((void) free((char *) (x)))
-struct krb5_rc_typelist
- {
- const krb5_rc_ops *ops;
- struct krb5_rc_typelist *next;
- };
-
-static struct krb5_rc_typelist rc_none_type = { &krb5_rc_none_ops, 0 };
-static struct krb5_rc_typelist rc_mem_type =
- { &krb5_rc_mem_ops, &rc_none_type };
-static struct krb5_rc_typelist krb5_rc_typelist_dfl =
- { &krb5_rc_file_ops, &rc_mem_type };
+struct krb5_rc_typelist {
+ const krb5_rc_ops *ops;
+ struct krb5_rc_typelist *next;
+};
+static struct krb5_rc_typelist none = { &krb5_rc_none_ops, 0 };
+static struct krb5_rc_typelist rc_mem_type = { &krb5_rc_mem_ops, &none };
+static struct krb5_rc_typelist krb5_rc_typelist_dfl = { &krb5_rc_file_ops, &rc_mem_type };
static struct krb5_rc_typelist *typehead = &krb5_rc_typelist_dfl;
static k5_mutex_t rc_typelist_lock = K5_MUTEX_PARTIAL_INITIALIZER;
int krb5int_rc_finish_init(void)
{
+ /* Solaris Kerberos */
int retval;
retval = k5_mutex_finish_init(&grcache.lock);
@@ -52,6 +50,7 @@ int krb5int_rc_finish_init(void)
void krb5int_rc_terminate(void)
{
struct krb5_rc_typelist *t, *t_next;
+ /* Solaris Kerberos */
struct mem_data *tgr = (struct mem_data *)grcache.data;
struct authlist *q, *qt;
int i;
@@ -84,31 +83,27 @@ void krb5int_rc_terminate(void)
krb5_error_code krb5_rc_register_type(krb5_context context,
const krb5_rc_ops *ops)
{
- struct krb5_rc_typelist *t;
- krb5_error_code err;
-
- err = k5_mutex_lock(&rc_typelist_lock);
- if (err)
+ struct krb5_rc_typelist *t;
+ krb5_error_code err;
+ err = k5_mutex_lock(&rc_typelist_lock);
+ if (err)
return err;
-
- for (t = typehead;t && strcmp(t->ops->type,ops->type);t = t->next)
- ;
- if (t) {
- k5_mutex_unlock(&rc_typelist_lock);
- return KRB5_RC_TYPE_EXISTS;
- }
-
- t = (struct krb5_rc_typelist *) malloc(sizeof(struct krb5_rc_typelist));
- if (t == NULL) {
+ for (t = typehead;t && strcmp(t->ops->type,ops->type);t = t->next)
+ ;
+ if (t) {
+ k5_mutex_unlock(&rc_typelist_lock);
+ return KRB5_RC_TYPE_EXISTS;
+ }
+ t = (struct krb5_rc_typelist *) malloc(sizeof(struct krb5_rc_typelist));
+ if (t == NULL) {
k5_mutex_unlock(&rc_typelist_lock);
return KRB5_RC_MALLOC;
- }
- t->next = typehead;
- t->ops = ops;
- typehead = t;
-
- k5_mutex_unlock(&rc_typelist_lock);
- return 0;
+ }
+ t->next = typehead;
+ t->ops = ops;
+ typehead = t;
+ k5_mutex_unlock(&rc_typelist_lock);
+ return 0;
}
/*ARGSUSED*/
@@ -135,10 +130,10 @@ krb5_error_code krb5_rc_resolve_type(krb5_context context, krb5_rcache *id,
/*ARGSUSED*/
char * krb5_rc_get_type(krb5_context context, krb5_rcache id)
{
- return id->ops->type;
+ return id->ops->type;
}
-char * krb5_rc_default_type(krb5_context context)
+char * krb5_rc_default_type(krb5_context context)
{
/*
* Solaris Kerberos/SUNW14resync
@@ -151,11 +146,11 @@ char * krb5_rc_default_type(krb5_context context)
/*ARGSUSED*/
char * krb5_rc_default_name(krb5_context context)
{
- char *s;
- if ((s = getenv("KRB5RCNAME")))
- return s;
- else
- return (char *) 0;
+ char *s;
+ if ((s = getenv("KRB5RCNAME")))
+ return s;
+ else
+ return (char *) 0;
}
krb5_error_code
@@ -166,18 +161,14 @@ krb5_rc_default(krb5_context context, krb5_rcache *id)
if (!(*id = (krb5_rcache )malloc(sizeof(**id))))
return KRB5_RC_MALLOC;
- retval = krb5_rc_resolve_type(context, id, krb5_rc_default_type(context));
- if (retval != 0) {
- /*
- * k5_mutex_destroy() is not called here, because the mutex had
- * not been successfully initialized by krb5_rc_resolve_type().
- */
+ if ((retval = krb5_rc_resolve_type(context, id,
+ krb5_rc_default_type(context)))) {
FREE_RC(*id);
- return (retval);
+ return retval;
}
- retval = krb5_rc_resolve(context, *id, krb5_rc_default_name(context));
- if (retval) {
- k5_mutex_destroy(&(*id)->lock);
+ if ((retval = krb5_rc_resolve(context, *id,
+ krb5_rc_default_name(context)))) {
+ k5_mutex_destroy(&(*id)->lock);
FREE_RC(*id);
return retval;
}
@@ -185,6 +176,7 @@ krb5_rc_default(krb5_context context, krb5_rcache *id)
return retval;
}
+
krb5_error_code krb5_rc_resolve_full(krb5_context context, krb5_rcache *id, char *string_name)
{
char *type;
@@ -194,7 +186,7 @@ krb5_error_code krb5_rc_resolve_full(krb5_context context, krb5_rcache *id, char
if (!(residual = strchr(string_name,':')))
return KRB5_RC_PARSE;
-
+
diff = residual - string_name;
if (!(type = malloc(diff + 1)))
return KRB5_RC_MALLOC;
@@ -206,23 +198,18 @@ krb5_error_code krb5_rc_resolve_full(krb5_context context, krb5_rcache *id, char
return KRB5_RC_MALLOC;
}
- retval = krb5_rc_resolve_type(context, id, type);
- if (retval != 0) {
- /*
- * k5_mutex_destroy() is not called here, because the mutex had
- * not been successfully initialized by krb5_rc_resolve_type().
- */
+ if ((retval = krb5_rc_resolve_type(context, id,type))) {
FREE_RC(type);
FREE_RC(*id);
return retval;
}
FREE_RC(type);
- retval = krb5_rc_resolve(context, *id, residual + 1);
- if (retval) {
- k5_mutex_destroy(&(*id)->lock);
+ if ((retval = krb5_rc_resolve(context, *id,residual + 1))) {
+ k5_mutex_destroy(&(*id)->lock);
FREE_RC(*id);
return retval;
}
(*id)->magic = KV5M_RCACHE;
return retval;
}
+
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_base.h b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_base.h
index 69e3411308..e2e27677ec 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_base.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_base.h
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/rcache/rc_base.h
*
@@ -9,7 +8,6 @@
#ifndef KRB5_RC_H
#define KRB5_RC_H
-#include <stdlib.h>
#include "k5-int.h"
/* all the stuff that was here is now in rcache.h, included by krb5/krb5.h */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_conv.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_conv.c
index 111cec388e..02bbf81233 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_conv.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_conv.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/rcache/rc_conv.c
*
@@ -12,6 +11,8 @@
* An implementation for the default replay cache type.
*/
+/* Solaris Kerberos - resync */
+#define FREE_RC(x) ((void) free((char *) (x)))
#include "rc_base.h"
@@ -31,7 +32,7 @@ krb5_auth_to_rep(krb5_context context, krb5_tkt_authent *auth, krb5_donot_replay
return retval; /* shouldn't happen */
if ((retval = krb5_unparse_name(context, auth->authenticator->client,
&rep->client))) {
- free(rep->server);
+ FREE_RC(rep->server);
return retval; /* shouldn't happen. */
}
return 0;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_file.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_file.c
index be81658f9f..c0ade20886 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_file.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_file.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/rcache/rc_file.c
@@ -13,9 +12,12 @@
*
*/
+
/*
* An implementation for the default replay cache type.
*/
+/* Solaris Kerberos */
+#define FREE_RC(x) ((void) free((char *) (x)))
#include "rc_common.h"
#include "rc_file.h"
@@ -27,17 +29,15 @@
/* of course, list is backwards from file */
/* hash could be forwards since we have to search on match, but naaaah */
-static int rc_store(context, id, rep)
- krb5_context context;
- krb5_rcache id;
- krb5_donot_replay *rep;
+static int
+rc_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep)
{
struct file_data *t = (struct file_data *)id->data;
int rephash;
struct authlist *ta;
krb5_int32 time;
- rephash = hash(rep,t->hsize);
+ rephash = hash(rep, t->hsize);
/* Solaris: calling krb_timeofday() here, once for better perf. */
krb5_timeofday(context, &time);
@@ -49,29 +49,32 @@ static int rc_store(context, id, rep)
return CMP_EXPIRED;
}
- for (ta = t->h[rephash]; ta; ta = ta->nh)
+ for (ta = t->h[rephash]; ta; ta = ta->nh) {
switch(cmp(&ta->rep, rep))
{
- case CMP_REPLAY: return CMP_REPLAY;
- case CMP_HOHUM: if (alive(context, &ta->rep, t->lifespan, time)
- == CMP_EXPIRED)
- t->nummisses++;
- else
- t->numhits++;
- break;
- default: ; /* wtf? */
+ case CMP_REPLAY:
+ return CMP_REPLAY;
+ case CMP_HOHUM:
+ if (alive(context, &ta->rep, t->lifespan, time) == CMP_EXPIRED)
+ t->nummisses++;
+ else
+ t->numhits++;
+ break;
+ default:
+ ; /* wtf? */
}
+ }
if (!(ta = (struct authlist *) malloc(sizeof(struct authlist))))
return CMP_MALLOC;
ta->rep = *rep;
if (!(ta->rep.client = strdup(rep->client))) {
- free(ta);
+ FREE_RC(ta);
return CMP_MALLOC;
}
if (!(ta->rep.server = strdup(rep->server))) {
- free(ta->rep.client);
- free(ta);
+ FREE_RC(ta->rep.client);
+ FREE_RC(ta);
return CMP_MALLOC;
}
ta->na = t->a; t->a = ta;
@@ -82,19 +85,15 @@ static int rc_store(context, id, rep)
/*ARGSUSED*/
char * KRB5_CALLCONV
-krb5_rc_file_get_name(context, id)
- krb5_context context;
- krb5_rcache id;
+krb5_rc_file_get_name(krb5_context context, krb5_rcache id)
{
return ((struct file_data *) (id->data))->name;
}
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
-krb5_rc_file_get_span(context, id, lifespan)
- krb5_context context;
- krb5_rcache id;
- krb5_deltat *lifespan;
+krb5_rc_file_get_span(krb5_context context, krb5_rcache id,
+ krb5_deltat *lifespan)
{
krb5_error_code err;
struct file_data *t;
@@ -108,23 +107,22 @@ krb5_rc_file_get_span(context, id, lifespan)
return 0;
}
-krb5_error_code KRB5_CALLCONV
-krb5_rc_file_init_locked(context, id, lifespan)
- krb5_context context;
- krb5_rcache id;
- krb5_deltat lifespan;
+static krb5_error_code KRB5_CALLCONV
+krb5_rc_file_init_locked(krb5_context context, krb5_rcache id, krb5_deltat lifespan)
{
struct file_data *t = (struct file_data *)id->data;
krb5_error_code retval;
t->lifespan = lifespan ? lifespan : context->clockskew;
/* default to clockskew from the context */
- if ((retval = krb5_rc_io_creat(context, &t->d, &t->name)))
+ if ((retval = krb5_rc_io_creat(context, &t->d, &t->name))) {
return retval;
+ }
if ((krb5_rc_io_write(context, &t->d,
(krb5_pointer) &t->lifespan, sizeof(t->lifespan))
- || krb5_rc_io_sync(context, &t->d)))
+ || krb5_rc_io_sync(context, &t->d))) {
return KRB5_RC_IO;
+ }
return 0;
}
@@ -141,36 +139,33 @@ krb5_rc_file_init(krb5_context context, krb5_rcache id, krb5_deltat lifespan)
return retval;
}
-krb5_error_code krb5_rc_file_close_no_free(context, id)
- krb5_context context;
- krb5_rcache id;
+/* Called with the mutex already locked. */
+krb5_error_code
+krb5_rc_file_close_no_free(krb5_context context, krb5_rcache id)
{
- struct file_data *t = (struct file_data *)id->data;
- struct authlist *q;
-
- if (t->h)
- free(t->h);
- if (t->name)
- free(t->name);
-
- while ((q = t->a) != NULL)
- {
- t->a = q->na;
- free(q->rep.client);
- free(q->rep.server);
- free(q);
- }
+ struct file_data *t = (struct file_data *)id->data;
+ struct authlist *q;
+
+ if (t->h)
+ FREE_RC(t->h);
+ if (t->name)
+ FREE_RC(t->name);
+ while ((q = t->a))
+ {
+ t->a = q->na;
+ FREE_RC(q->rep.client);
+ FREE_RC(q->rep.server);
+ FREE_RC(q);
+ }
if (t->d.fd >= 0)
(void) krb5_rc_io_close(context, &t->d);
- free(t);
- id->data = NULL;
- return 0;
+ FREE_RC(t);
+ id->data = NULL;
+ return 0;
}
krb5_error_code KRB5_CALLCONV
-krb5_rc_file_close(context, id)
- krb5_context context;
- krb5_rcache id;
+krb5_rc_file_close(krb5_context context, krb5_rcache id)
{
krb5_error_code retval;
retval = k5_mutex_lock(&id->lock);
@@ -184,9 +179,7 @@ krb5_rc_file_close(context, id)
}
krb5_error_code KRB5_CALLCONV
-krb5_rc_file_destroy(context, id)
- krb5_context context;
- krb5_rcache id;
+krb5_rc_file_destroy(krb5_context context, krb5_rcache id)
{
if (krb5_rc_io_destroy(context, &((struct file_data *) (id->data))->d))
return KRB5_RC_IO;
@@ -195,10 +188,7 @@ krb5_rc_file_destroy(context, id)
/*ARGSUSED*/
krb5_error_code KRB5_CALLCONV
-krb5_rc_file_resolve(context, id, name)
- krb5_context context;
- krb5_rcache id;
- char *name;
+krb5_rc_file_resolve(krb5_context context, krb5_rcache id, char *name)
{
struct file_data *t = 0;
krb5_error_code retval;
@@ -243,9 +233,8 @@ cleanup:
}
/*ARGSUSED*/
-void krb5_rc_free_entry (context, rep)
- krb5_context context;
- krb5_donot_replay **rep;
+void
+krb5_rc_free_entry(krb5_context context, krb5_donot_replay **rep)
{
krb5_donot_replay *rp = *rep;
@@ -263,18 +252,17 @@ void krb5_rc_free_entry (context, rep)
}
}
-static krb5_error_code krb5_rc_io_fetch(context, t, rep, maxlen)
- krb5_context context;
- struct file_data *t;
- krb5_donot_replay *rep;
- int maxlen;
+static krb5_error_code
+krb5_rc_io_fetch(krb5_context context, struct file_data *t,
+ krb5_donot_replay *rep, int maxlen)
{
- int len;
+ unsigned int len;
krb5_error_code retval;
rep->client = rep->server = 0;
- retval = krb5_rc_io_read (context, &t->d, (krb5_pointer) &len, sizeof(len));
+ retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &len,
+ sizeof(len));
if (retval)
return retval;
@@ -285,11 +273,12 @@ static krb5_error_code krb5_rc_io_fetch(context, t, rep, maxlen)
if (!rep->client)
return KRB5_RC_MALLOC;
- retval = krb5_rc_io_read (context, &t->d, (krb5_pointer) rep->client, len);
+ retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) rep->client, len);
if (retval)
goto errout;
- retval = krb5_rc_io_read (context, &t->d, (krb5_pointer) &len, sizeof(len));
+ retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &len,
+ sizeof(len));
if (retval)
goto errout;
@@ -304,15 +293,17 @@ static krb5_error_code krb5_rc_io_fetch(context, t, rep, maxlen)
goto errout;
}
- retval = krb5_rc_io_read (context, &t->d, (krb5_pointer) rep->server, len);
+ retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) rep->server, len);
if (retval)
goto errout;
- retval = krb5_rc_io_read (context, &t->d, (krb5_pointer) &rep->cusec, sizeof(rep->cusec));
+ retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &rep->cusec,
+ sizeof(rep->cusec));
if (retval)
goto errout;
- retval = krb5_rc_io_read (context, &t->d, (krb5_pointer) &rep->ctime, sizeof(rep->ctime));
+ retval = krb5_rc_io_read(context, &t->d, (krb5_pointer) &rep->ctime,
+ sizeof(rep->ctime));
if (retval)
goto errout;
@@ -327,13 +318,12 @@ errout:
return retval;
}
+
static krb5_error_code
krb5_rc_file_expunge_locked(krb5_context context, krb5_rcache id);
static krb5_error_code
-krb5_rc_file_recover_locked(context, id)
- krb5_context context;
- krb5_rcache id;
+krb5_rc_file_recover_locked(krb5_context context, krb5_rcache id)
{
struct file_data *t = (struct file_data *)id->data;
krb5_donot_replay *rep = 0;
@@ -341,15 +331,17 @@ krb5_rc_file_recover_locked(context, id)
long max_size;
int expired_entries = 0;
- if ((retval = krb5_rc_io_open(context, &t->d, t->name)))
+ if ((retval = krb5_rc_io_open(context, &t->d, t->name))) {
return retval;
+ }
t->recovering = 1;
max_size = krb5_rc_io_size(context, &t->d);
rep = NULL;
- if (krb5_rc_io_read(context, &t->d,(krb5_pointer) &t->lifespan,sizeof(t->lifespan))) {
+ if (krb5_rc_io_read(context, &t->d, (krb5_pointer) &t->lifespan,
+ sizeof(t->lifespan))) {
retval = KRB5_RC_IO;
goto io_fail;
}
@@ -388,8 +380,8 @@ krb5_rc_file_recover_locked(context, id)
/*
* free fields allocated by rc_io_fetch
*/
- free(rep->server);
- free(rep->client);
+ FREE_RC(rep->server);
+ FREE_RC(rep->client);
rep->server = 0;
rep->client = 0;
}
@@ -409,7 +401,6 @@ io_fail:
return retval;
}
-
krb5_error_code KRB5_CALLCONV
krb5_rc_file_recover(krb5_context context, krb5_rcache id)
{
@@ -438,22 +429,19 @@ krb5_rc_file_recover_or_init(krb5_context context, krb5_rcache id,
return retval;
}
-
static krb5_error_code
-krb5_rc_io_store (context, t, rep)
- krb5_context context;
- struct file_data *t;
- krb5_donot_replay *rep;
+krb5_rc_io_store(krb5_context context, struct file_data *t,
+ krb5_donot_replay *rep)
{
int clientlen, serverlen, len;
char *buf, *ptr;
krb5_error_code ret;
- clientlen = strlen (rep->client) + 1;
- serverlen = strlen (rep->server) + 1;
+ 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);
+ buf = malloc(len);
if (buf == 0)
return KRB5_RC_MALLOC;
ptr = buf;
@@ -472,10 +460,7 @@ krb5_rc_io_store (context, t, rep)
static krb5_error_code krb5_rc_file_expunge_locked(krb5_context, krb5_rcache);
krb5_error_code KRB5_CALLCONV
-krb5_rc_file_store(context, id, rep)
- krb5_context context;
- krb5_rcache id;
- krb5_donot_replay *rep;
+krb5_rc_file_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep)
{
krb5_error_code ret;
struct file_data *t;
@@ -504,8 +489,8 @@ krb5_rc_file_store(context, id, rep)
k5_mutex_unlock(&id->lock);
return ret;
}
- /* Shall we automatically expunge? */
- if (t->nummisses > t->numhits + EXCESSREPS)
+ /* Shall we automatically expunge? */
+ if (t->nummisses > t->numhits + EXCESSREPS)
{
ret = krb5_rc_file_expunge_locked(context, id);
k5_mutex_unlock(&id->lock);
@@ -518,14 +503,12 @@ krb5_rc_file_store(context, id, rep)
return KRB5_RC_IO;
}
}
- k5_mutex_unlock(&id->lock);
- return 0;
+ k5_mutex_unlock(&id->lock);
+ return 0;
}
static krb5_error_code
-krb5_rc_file_expunge_locked(context, id)
- krb5_context context;
- krb5_rcache id;
+krb5_rc_file_expunge_locked(krb5_context context, krb5_rcache id)
{
struct file_data *t = (struct file_data *)id->data;
struct authlist *q;
@@ -537,8 +520,8 @@ krb5_rc_file_expunge_locked(context, id)
if (! t->recovering) {
name = t->name;
t->name = 0; /* Clear name so it isn't freed */
- (void) krb5_rc_file_close_no_free(context, id);
- retval = krb5_rc_file_resolve(context, id, name);
+ (void) krb5_rc_file_close_no_free(context, id);
+ retval = krb5_rc_file_resolve(context, id, name);
free(name);
if (retval)
return retval;
@@ -554,8 +537,8 @@ krb5_rc_file_expunge_locked(context, id)
retval = k5_mutex_init(&tmp->lock);
if (retval) {
- free (tmp);
- return retval;
+ free(tmp);
+ return retval;
}
tmp->ops = &krb5_rc_file_ops;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_file.h b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_file.h
index 0a670f4cac..8c4991760a 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_file.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_file.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
@@ -7,6 +7,7 @@
*
* This file of the Kerberos V5 software is derived from public-domain code
* contributed by Daniel J. Bernstein, <brnstnd@acf10.nyu.edu>.
+ *
*/
/*
@@ -16,11 +17,8 @@
#ifndef _KRB5_RC_FILE_H
#define _KRB5_RC_FILE_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-#ifdef __cplusplus
-extern "C" {
-#endif
+/* Solaris Kerberos */
#include "rc_common.h"
#include "rc_io.h"
@@ -54,7 +52,7 @@ struct file_data {
char recovering;
};
-extern krb5_rc_ops krb5_rc_file_ops;
+extern const krb5_rc_ops krb5_rc_file_ops;
krb5_error_code KRB5_CALLCONV krb5_rc_file_init
(krb5_context,
@@ -62,7 +60,7 @@ krb5_error_code KRB5_CALLCONV krb5_rc_file_init
krb5_deltat);
krb5_error_code KRB5_CALLCONV krb5_rc_file_recover
(krb5_context,
- krb5_rcache);
+ krb5_rcache);
krb5_error_code KRB5_CALLCONV krb5_rc_file_recover_or_init
(krb5_context,
krb5_rcache,
@@ -97,9 +95,5 @@ krb5_error_code krb5_rc_file_close_no_free
void krb5_rc_free_entry
(krb5_context,
krb5_donot_replay **);
-
-#ifdef __cplusplus
-}
#endif
-#endif /* !_KRB5_RC_FILE_H */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_io.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_io.c
index 94d401f7a6..bf4e13a223 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_io.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_io.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/rcache/rc_io.c
@@ -13,6 +12,7 @@
*
*/
+
/*
* I/O functions for the replay cache default implementation.
*/
@@ -24,10 +24,9 @@
#endif
#define KRB5_RC_VNO 0x0501 /* krb5, rcache v 1 */
-#define NEED_SOCKETS
-#define NEED_LOWLEVEL_IO
-#include <krb5.h>
+#include "k5-int.h"
+#include <stdio.h> /* for P_tmpdir */
#include <sys/types.h>
#include <unistd.h>
#include <syslog.h> /* SUNW */
@@ -47,7 +46,8 @@
#error find some way to use net-byte-order file version numbers.
#endif
-#define free(x) ((void) free((char *) (x)))
+/* Solaris Kerberos */
+#define FREE_RC(x) ((void) free((char *) (x)))
#define UNIQUE getpid() /* hopefully unique number */
#define GETDIR (dir = getdir(), dirlen = strlen(dir) + sizeof(PATH_SEPARATOR) - 1)
@@ -55,13 +55,14 @@
static char *
getdir(void)
{
- char *dir;
+ char *dir;
#if defined(_WIN32)
- if (!(dir = getenv("TEMP")))
- if (!(dir = getenv("TMP")))
- dir = "C:";
+ if (!(dir = getenv("TEMP")))
+ if (!(dir = getenv("TMP")))
+ dir = "C:";
#else
+ /* Solaris Kerberos */
if (geteuid() == 0)
dir = "/var/krb5/rcache/root";
else
@@ -73,63 +74,67 @@ getdir(void)
krb5_error_code
krb5_rc_io_creat(krb5_context context, krb5_rc_iostuff *d, char **fn)
{
- char *c;
- krb5_int16 rc_vno = htons(KRB5_RC_VNO);
- krb5_error_code retval = 0;
- int do_not_unlink = 0;
- char *dir;
- size_t dirlen;
-
- GETDIR;
- if (fn && *fn)
- {
+ char *c;
+ krb5_int16 rc_vno = htons(KRB5_RC_VNO);
+ krb5_error_code retval = 0;
+ int do_not_unlink = 0;
+ char *dir;
+ size_t dirlen;
+
+ GETDIR;
+ if (fn && *fn)
+ {
+ /* Solaris Kerberos */
if (*fn[0] == '/') {
d->fn = strdup(*fn);
if (d->fn == NULL)
return (KRB5_RC_IO_MALLOC);
} else {
if (!(d->fn = malloc(strlen(*fn) + dirlen + 1)))
- return KRB5_RC_IO_MALLOC;
+ return KRB5_RC_IO_MALLOC;
(void) strcpy(d->fn, dir);
(void) strcat(d->fn, PATH_SEPARATOR);
(void) strcat(d->fn, *fn);
}
- d->fd = THREEPARAMOPEN(d->fn, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY, 0600);
- }
- else
- {
- /* %d is max 11 digits (-, 10 digits of 32-bit number)
- * 11 + /krb5_RC + aaa = 24, +6 for slop */
- if (!(d->fn = malloc(30 + dirlen)))
- return KRB5_RC_IO_MALLOC;
- if (fn)
- if (!(*fn = malloc(35))) {
- free(d->fn);
- return KRB5_RC_IO_MALLOC;
- }
- (void) sprintf(d->fn, "%s%skrb5_RC%d", dir, PATH_SEPARATOR, (int) UNIQUE);
- c = d->fn + strlen(d->fn);
- (void) strcpy(c, "aaa");
- while ((d->fd = THREEPARAMOPEN(d->fn, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL | O_BINARY, 0600)) == -1)
+ d->fd = THREEPARAMOPEN(d->fn, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL |
+ O_BINARY, 0600);
+ }
+ else
{
- if ((c[2]++) == 'z')
- {
- c[2] = 'a';
- if ((c[1]++) == 'z')
+ /* %d is max 11 digits (-, 10 digits of 32-bit number)
+ * 11 + /krb5_RC + aaa = 24, +6 for slop */
+ if (!(d->fn = malloc(30 + dirlen)))
+ return KRB5_RC_IO_MALLOC;
+ if (fn)
+ if (!(*fn = malloc(35))) {
+ FREE_RC(d->fn);
+ return KRB5_RC_IO_MALLOC;
+ }
+ (void) sprintf(d->fn, "%s%skrb5_RC%d", dir, PATH_SEPARATOR,
+ (int) UNIQUE);
+ c = d->fn + strlen(d->fn);
+ (void) strcpy(c, "aaa");
+ while ((d->fd = THREEPARAMOPEN(d->fn, O_WRONLY | O_CREAT | O_TRUNC |
+ O_EXCL | O_BINARY, 0600)) == -1)
{
- c[1] = 'a';
- if ((c[0]++) == 'z')
- break; /* sigh */
- }
- }
+ if ((c[2]++) == 'z')
+ {
+ c[2] = 'a';
+ if ((c[1]++) == 'z')
+ {
+ c[1] = 'a';
+ if ((c[0]++) == 'z')
+ break; /* sigh */
+ }
+ }
+ }
+ if (fn)
+ (void) strcpy(*fn, d->fn + dirlen);
}
- if (fn)
- (void) strcpy(*fn, d->fn + dirlen);
- }
- if (d->fd == -1)
- {
- switch(errno)
+ if (d->fd == -1)
{
+ switch(errno)
+ {
case EFBIG:
#ifdef EDQUOT
case EDQUOT:
@@ -137,6 +142,7 @@ krb5_rc_io_creat(krb5_context context, krb5_rc_iostuff *d, char **fn)
case ENOSPC:
retval = KRB5_RC_IO_SPACE;
goto cleanup;
+
case EIO:
retval = KRB5_RC_IO_IO;
goto cleanup;
@@ -146,15 +152,20 @@ krb5_rc_io_creat(krb5_context context, krb5_rc_iostuff *d, char **fn)
case EROFS:
case EEXIST:
retval = KRB5_RC_IO_PERM;
+ krb5_set_error_message(context, retval,
+ "Cannot create replay cache: %s",
+ strerror(errno));
do_not_unlink = 1;
goto cleanup;
default:
retval = KRB5_RC_IO_UNKNOWN;
+ krb5_set_error_message(context, retval,
+ "Cannot create replay cache: %s",
+ strerror(errno));
goto cleanup;
+ }
}
- }
-
retval = krb5_rc_io_write(context, d, (krb5_pointer)&rc_vno,
sizeof(rc_vno));
if (retval)
@@ -167,17 +178,19 @@ krb5_rc_io_creat(krb5_context context, krb5_rc_iostuff *d, char **fn)
if (d->fn) {
if (!do_not_unlink)
(void) unlink(d->fn);
- free(d->fn);
+ FREE_RC(d->fn);
d->fn = NULL;
}
- (void) close(d->fd);
+ if (d->fd != -1) {
+ (void) close(d->fd);
+ }
}
return retval;
}
static krb5_error_code
krb5_rc_io_open_internal(krb5_context context, krb5_rc_iostuff *d, char *fn,
-char* full_pathname)
+ char* full_pathname)
{
krb5_int16 rc_vno;
krb5_error_code retval = 0;
@@ -194,7 +207,7 @@ char* full_pathname)
return (KRB5_RC_IO_MALLOC);
} else {
if (!(d->fn = malloc(strlen(fn) + dirlen + 1)))
- return KRB5_RC_IO_MALLOC;
+ return KRB5_RC_IO_MALLOC;
(void) strcpy(d->fn, dir);
(void) strcat(d->fn, PATH_SEPARATOR);
(void) strcat(d->fn, fn);
@@ -223,6 +236,7 @@ char* full_pathname)
/* make sure the rcache is a regular file */
if (((fstatb.st_mode & S_IFMT) != S_IFREG)) {
retval = KRB5_RC_IO_PERM;
+
goto cleanup;
}
#endif
@@ -254,14 +268,14 @@ char* full_pathname)
do_not_unlink = 0;
retval = krb5_rc_io_read(context, d, (krb5_pointer) &rc_vno,
- sizeof(rc_vno));
+ sizeof(rc_vno));
if (retval)
goto cleanup;
if (ntohs(rc_vno) != KRB5_RC_VNO)
retval = KRB5_RCACHE_BADVNO;
-cleanup:
+ cleanup:
if (use_errno) {
switch(errno)
{
@@ -281,23 +295,28 @@ cleanup:
case EACCES:
case EROFS:
retval = KRB5_RC_IO_PERM;
+ krb5_set_error_message (context, retval,
+ "Cannot open replay cache %s: %s",
+ d->fn, strerror(errno));
break;
default:
retval = KRB5_RC_IO_UNKNOWN;
+ krb5_set_error_message (context, retval,
+ "Cannot open replay cache %s: %s",
+ d->fn, strerror(errno));
}
}
/* Solaris: END made changes to be safer and better code structure */
if (retval) {
if (d->fn) {
- if (!do_not_unlink) {
- /* unlink in case there is a bogus RC. */
+ if (!do_not_unlink)
(void) unlink(d->fn);
- }
- free(d->fn);
+ FREE_RC(d->fn);
d->fn = NULL;
}
- (void) close(d->fd);
+ if (d->fd >= 0)
+ (void) close(d->fd);
}
return retval;
}
@@ -312,7 +331,7 @@ krb5_error_code
krb5_rc_io_move(krb5_context context, krb5_rc_iostuff *new1,
krb5_rc_iostuff *old)
{
-#if defined(_WIN32)
+#if defined(_WIN32) || defined(__CYGWIN__)
char *new_fn = NULL;
char *old_fn = NULL;
off_t offset = 0;
@@ -391,14 +410,26 @@ krb5_rc_io_write(krb5_context context, krb5_rc_iostuff *d, krb5_pointer buf,
if (write(d->fd, (char *) buf, num) == -1)
switch(errno)
{
- case EBADF: return KRB5_RC_IO_UNKNOWN;
- case EFBIG: return KRB5_RC_IO_SPACE;
#ifdef EDQUOT
- case EDQUOT: return KRB5_RC_IO_SPACE;
+ case EDQUOT:
#endif
- case ENOSPC: return KRB5_RC_IO_SPACE;
- case EIO: return KRB5_RC_IO_IO;
- default: return KRB5_RC_IO_UNKNOWN;
+ case EFBIG:
+ case ENOSPC:
+ krb5_set_error_message (context, KRB5_RC_IO_SPACE,
+ "Can't write to replay cache: %s",
+ strerror(errno));
+ return KRB5_RC_IO_SPACE;
+ case EIO:
+ krb5_set_error_message (context, KRB5_RC_IO_IO,
+ "Can't write to replay cache: %s",
+ strerror(errno));
+ return KRB5_RC_IO_IO;
+ case EBADF:
+ default:
+ krb5_set_error_message (context, KRB5_RC_IO_UNKNOWN,
+ "Can't write to replay cache: %s",
+ strerror(errno));
+ return KRB5_RC_IO_UNKNOWN;
}
return 0;
}
@@ -416,7 +447,11 @@ krb5_rc_io_sync(krb5_context context, krb5_rc_iostuff *d)
{
case EBADF: return KRB5_RC_IO_UNKNOWN;
case EIO: return KRB5_RC_IO_IO;
- default: return KRB5_RC_IO_UNKNOWN;
+ default:
+ krb5_set_error_message(context, KRB5_RC_IO_UNKNOWN,
+ "Cannot sync replay cache file: %s",
+ strerror(errno));
+ return KRB5_RC_IO_UNKNOWN;
}
}
return 0;
@@ -431,9 +466,13 @@ krb5_rc_io_read(krb5_context context, krb5_rc_iostuff *d, krb5_pointer buf,
if ((count = read(d->fd, (char *) buf, num)) == -1)
switch(errno)
{
- case EBADF: return KRB5_RC_IO_UNKNOWN;
case EIO: return KRB5_RC_IO_IO;
- default: return KRB5_RC_IO_UNKNOWN;
+ case EBADF:
+ default:
+ krb5_set_error_message(context, KRB5_RC_IO_UNKNOWN,
+ "Can't read from replay cache: %s",
+ strerror(errno));
+ return KRB5_RC_IO_UNKNOWN;
}
if (count == 0)
return KRB5_RC_IO_EOF;
@@ -445,7 +484,7 @@ krb5_error_code
krb5_rc_io_close(krb5_context context, krb5_rc_iostuff *d)
{
if (d->fn != NULL) {
- free(d->fn);
+ FREE_RC(d->fn);
d->fn = NULL;
}
if (d->fd != -1) {
@@ -460,17 +499,29 @@ krb5_rc_io_close(krb5_context context, krb5_rc_iostuff *d)
krb5_error_code
krb5_rc_io_destroy(krb5_context context, krb5_rc_iostuff *d)
{
- if (unlink(d->fn) == -1)
- switch(errno)
- {
- case EBADF: return KRB5_RC_IO_UNKNOWN;
- case EIO: return KRB5_RC_IO_IO;
- case EPERM: return KRB5_RC_IO_PERM;
- case EBUSY: return KRB5_RC_IO_PERM;
- case EROFS: return KRB5_RC_IO_PERM;
- default: return KRB5_RC_IO_UNKNOWN;
- }
- return 0;
+ if (unlink(d->fn) == -1)
+ switch(errno)
+ {
+ case EIO:
+ krb5_set_error_message(context, KRB5_RC_IO_IO,
+ "Can't destroy replay cache: %s",
+ strerror(errno));
+ return KRB5_RC_IO_IO;
+ case EPERM:
+ case EBUSY:
+ case EROFS:
+ krb5_set_error_message(context, KRB5_RC_IO_PERM,
+ "Can't destroy replay cache: %s",
+ strerror(errno));
+ return KRB5_RC_IO_PERM;
+ case EBADF:
+ default:
+ krb5_set_error_message(context, KRB5_RC_IO_UNKNOWN,
+ "Can't destroy replay cache: %s",
+ strerror(errno));
+ return KRB5_RC_IO_UNKNOWN;
+ }
+ return 0;
}
/*ARGSUSED*/
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_mem.h b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_mem.h
index 1b8171858c..80e920da9d 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_mem.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_mem.h
@@ -1,12 +1,11 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _KRB5_RC_MEM_H
#define _KRB5_RC_MEM_H
-#pragma ident "%Z%%M% %I% %E% SMI"
#include "rc-int.h"
@@ -40,7 +39,7 @@ struct global_rcache {
extern struct global_rcache grcache;
-extern krb5_rc_ops krb5_rc_mem_ops;
+extern const krb5_rc_ops krb5_rc_mem_ops;
krb5_error_code KRB5_CALLCONV krb5_rc_mem_init
(krb5_context, krb5_rcache, krb5_deltat);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_none.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_none.c
index 250b8f3753..93de67f5cb 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_none.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rc_none.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/krb5/rcache/rc_none.c
*
@@ -7,9 +5,9 @@
* 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.
+ * 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
@@ -18,7 +16,7 @@
* 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
+ * 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
@@ -33,16 +31,16 @@
#include "rc-int.h"
static krb5_error_code KRB5_CALLCONV
-krb5_rc_none_init(krb5_context ctx, krb5_rcache rc, krb5_deltat lifespan)
+krb5_rc_none_init(krb5_context ctx, krb5_rcache rc, krb5_deltat d)
{
- return (0);
+ return 0;
}
#define krb5_rc_none_recover_or_init krb5_rc_none_init
static krb5_error_code KRB5_CALLCONV
krb5_rc_none_noargs(krb5_context ctx, krb5_rcache rc)
{
- return (0);
+ return 0;
}
#define krb5_rc_none_recover krb5_rc_none_noargs
#define krb5_rc_none_destroy krb5_rc_none_noargs
@@ -52,39 +50,39 @@ krb5_rc_none_noargs(krb5_context ctx, krb5_rcache rc)
static krb5_error_code KRB5_CALLCONV
krb5_rc_none_store(krb5_context ctx, krb5_rcache rc, krb5_donot_replay *r)
{
- return (0);
+ return 0;
}
static krb5_error_code KRB5_CALLCONV
krb5_rc_none_get_span(krb5_context ctx, krb5_rcache rc, krb5_deltat *d)
{
- return (0);
+ return 0;
}
static char * KRB5_CALLCONV
krb5_rc_none_get_name(krb5_context ctx, krb5_rcache rc)
{
- return ("");
+ return "";
}
static krb5_error_code KRB5_CALLCONV
krb5_rc_none_resolve(krb5_context ctx, krb5_rcache rc, char *name)
{
- rc->data = "NONE";
- return (0);
+ rc->data = "NONE";
+ return 0;
}
const krb5_rc_ops krb5_rc_none_ops = {
- (0),
- "NONE",
- krb5_rc_none_init,
- krb5_rc_none_recover,
- krb5_rc_none_recover_or_init,
- krb5_rc_none_destroy,
- krb5_rc_none_close,
- krb5_rc_none_store,
- krb5_rc_none_expunge,
- krb5_rc_none_get_span,
- krb5_rc_none_get_name,
- krb5_rc_none_resolve
+ 0,
+ "NONE",
+ krb5_rc_none_init,
+ krb5_rc_none_recover,
+ krb5_rc_none_recover_or_init,
+ krb5_rc_none_destroy,
+ krb5_rc_none_close,
+ krb5_rc_none_store,
+ krb5_rc_none_expunge,
+ krb5_rc_none_get_span,
+ krb5_rc_none_get_name,
+ krb5_rc_none_resolve
};
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rcdef.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rcdef.c
index 8dc9fd0418..570e5636c7 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rcdef.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/rcdef.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/rcache/rcdef.c
@@ -23,12 +22,15 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
*
- * replay cache default set of operation vectors.
+ * replay cache default operationvectors.
*/
#include "k5-int.h"
@@ -40,7 +42,7 @@
* Solaris Kerberos
* MIT 1.4 just has "dfl" while we now have "FILE" and "MEMORY".
*/
-krb5_rc_ops krb5_rc_file_ops = {
+const krb5_rc_ops krb5_rc_file_ops = {
0,
"FILE",
krb5_rc_file_init,
@@ -55,7 +57,7 @@ krb5_rc_ops krb5_rc_file_ops = {
krb5_rc_file_resolve
};
-krb5_rc_ops krb5_rc_mem_ops = {
+const krb5_rc_ops krb5_rc_mem_ops = {
0,
"MEMORY",
krb5_rc_mem_init,
@@ -71,4 +73,4 @@ krb5_rc_ops krb5_rc_mem_ops = {
krb5_rc_mem_resolve
};
-krb5_rc_ops *krb5_rc_dfl_ops = &krb5_rc_file_ops;
+krb5_rc_ops const *krb5_rc_dfl_ops = &krb5_rc_file_ops;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/ser_rc.c b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/ser_rc.c
index 06bb7a7831..dc58c32c99 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/ser_rc.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/krb5/rcache/ser_rc.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/rcache/ser_rc.c
@@ -35,7 +34,7 @@
/*
* ser_rcdfl.c - Serialize replay cache context.
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include "rc-int.h"
/*
@@ -73,6 +72,7 @@ krb5_rcache_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep)
size_t required;
kret = EINVAL;
+ /* Solaris Kerberos */
if ((rcache = (krb5_rcache) arg) != NULL) {
/*
* Saving FILE: variants of krb5_rcache requires at minimum:
@@ -115,6 +115,7 @@ krb5_rcache_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **bu
bp = *buffer;
remain = *lenremain;
kret = EINVAL;
+ /* Solaris Kerberos */
if ((rcache = (krb5_rcache) arg) != NULL) {
kret = ENOMEM;
if (!krb5_rcache_size(kcontext, arg, &required) &&
@@ -188,16 +189,15 @@ krb5_rcache_internalize(krb5_context kcontext, krb5_pointer *argp, krb5_octet **
&bp, &remain))) {
rcname[ibuf] = '\0';
if (!(kret = krb5_rc_resolve_full(kcontext, &rcache, rcname))) {
- (void) krb5_rc_close(kcontext, rcache);
(void) krb5_rc_recover(kcontext, rcache);
- if (!kret &&
+ if (!kret &&
!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) &&
(ibuf == KV5M_RCACHE)) {
*buffer = bp;
*lenremain = remain;
*argp = (krb5_pointer) rcache;
}
- else
+ else /* Solaris Kerberos */
(void)krb5_rc_close(kcontext, rcache);
}
free(rcname);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mapfile-vers b/usr/src/lib/gss_mechs/mech_krb5/mapfile-vers
index 69486fc940..b7793492f2 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mapfile-vers
+++ b/usr/src/lib/gss_mechs/mech_krb5/mapfile-vers
@@ -22,7 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
#
# Due to mistakes made early in the history of this library, there are
@@ -249,7 +248,6 @@ SUNWprivate_1.1 {
encode_krb5_ticket;
error_message;
ggss_error_table;
- gmt_mktime;
gss_krb5int_get_tkt_flags;
gss_krb5_ccache_name;
gss_krb5_copy_ccache;
@@ -337,10 +335,12 @@ SUNWprivate_1.1 {
krb5_c_is_coll_proof_cksum;
krb5_c_is_keyed_cksum;
krb5_c_keyed_checksum_types;
+ krb5_c_keylengths;
krb5_c_make_checksum;
krb5_c_make_random_key;
krb5_c_random_make_octets;
krb5_c_random_seed;
+ krb5_c_random_to_key;
krb5_c_string_to_key;
krb5_c_string_to_key_with_params;
krb5_c_valid_cksumtype;
@@ -487,10 +487,13 @@ SUNWprivate_1.1 {
krb5_get_host_realm;
krb5_get_init_creds;
krb5_get_init_creds_keytab;
+ krb5_get_init_creds_opt_alloc;
+ krb5_get_init_creds_opt_free;
krb5_get_init_creds_opt_init;
krb5_get_init_creds_opt_set_address_list;
krb5_get_init_creds_opt_set_etype_list;
krb5_get_init_creds_opt_set_forwardable;
+ krb5_get_init_creds_opt_set_pa;
krb5_get_init_creds_opt_set_preauth_list;
krb5_get_init_creds_opt_set_proxiable;
krb5_get_init_creds_opt_set_renew_life;
@@ -517,6 +520,7 @@ SUNWprivate_1.1 {
krb5_gss_import_name;
krb5_gss_oid_array;
krb5_gss_userok;
+ krb5_gss_register_acceptor_identity;
krb5_hmac;
krb5_init_allocated_keyblock;
krb5_init_context;
@@ -600,6 +604,7 @@ SUNWprivate_1.1 {
krb5_principal2salt_norealm;
krb5_principal_compare;
krb5_privacy_allowed;
+ krb5_process_padata;
krb5_prompter_posix;
krb5_raw_decrypt;
krb5_raw_encrypt;
@@ -730,16 +735,23 @@ SUNWprivate_1.1 {
krb5int_clear_error;
krb5int_close_plugin_dirs;
krb5int_cm_call_select;
+ krb5int_fini_fac;
krb5int_foreach_localaddr;
krb5int_free_error;
krb5int_free_plugin_dir_data;
+ krb5int_gai_strerror;
krb5int_get_error;
+ krb5int_getnameinfo;
krb5int_get_plugin_dir_data;
+ krb5int_gmt_mktime;
+ krb5int_hash_sha1;
krb5int_init_context_kdc;
+ krb5int_init_fac;
krb5int_mutex_alloc;
krb5int_mutex_free;
krb5int_open_plugin_dirs;
krb5int_pbkdf2_hmac_sha1;
+ krb5int_pthread_loaded;
krb5int_sendtokdc_debug_handler;
krb5int_vset_error;
kwarn_add_warning;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c b/usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c
index ffb57ceb52..5f773d91c2 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/accept_sec_context.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright 2000, 2004 by the Massachusetts Institute of Technology.
@@ -13,7 +12,7 @@
* 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
@@ -27,11 +26,11 @@
* 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.
- *
+ *
*/
/*
* Copyright 1993 by OpenVision Technologies, 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
@@ -41,7 +40,7 @@
* without specific, written prior permission. OpenVision makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
- *
+ *
* OPENVISION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL OPENVISION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
@@ -53,14 +52,14 @@
/*
* Copyright (C) 1998 by the FundsXpress, INC.
- *
+ *
* 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
@@ -71,24 +70,19 @@
* permission. FundsXpress makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
* or implied warranty.
- *
+ *
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-#include <k5-int.h>
-#include <auth_con.h>
-#include <gssapiP_krb5.h>
+#include "k5-int.h"
+#include "gssapiP_krb5.h"
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
#include <assert.h>
-
-/* Solaris kerberos: XXX kludgy but there is no include file for the
- * krb5_fcc_ops extern declaration.
- */
-extern krb5_cc_ops krb5_fcc_ops;
+#include "auth_con.h"
#ifdef CFX_EXERCISE
#define CFX_ACCEPTOR_SUBKEY (time(0) & 1)
@@ -104,34 +98,35 @@ extern krb5_cc_ops krb5_fcc_ops;
static krb5_error_code
rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
krb5_context context;
- krb5_auth_context auth_context;
+ krb5_auth_context auth_context;
krb5_data *inbuf;
krb5_gss_cred_id_t *out_cred;
{
- krb5_creds ** creds;
+ krb5_creds ** creds = NULL;
krb5_error_code retval;
- krb5_ccache template_ccache = NULL;
krb5_ccache ccache = NULL;
krb5_gss_cred_id_t cred = NULL;
krb5_auth_context new_auth_ctx = NULL;
- krb5_int32 flags_org;
+ krb5_int32 flags_org;
+ /* Solaris Kerberos */
KRB5_LOG0(KRB5_INFO, "rd_and_store_for_creds() start");
- if ((retval = krb5_auth_con_getflags(context, auth_context, &flags_org)))
- return retval;
- krb5_auth_con_setflags(context, auth_context, 0);
+ if ((retval = krb5_auth_con_getflags(context, auth_context, &flags_org)))
+ return retval;
+ krb5_auth_con_setflags(context, auth_context,
+ 0);
/*
- * By the time krb5_rd_cred is called here (after krb5_rd_req has been
+ * By the time krb5_rd_cred is called here (after krb5_rd_req has been
* called in krb5_gss_accept_sec_context), the "keyblock" field of
* auth_context contains a pointer to the session key, and the
- * "recv_subkey" field might contain a session subkey. Either of
+ * "recv_subkey" field might contain a session subkey. Either of
* these (the "recv_subkey" if it isn't NULL, otherwise the
* "keyblock") might have been used to encrypt the encrypted part of
* the KRB_CRED message that contains the forwarded credentials. (The
* Java Crypto and Security Implementation from the DSTC in Australia
- * always uses the session key. But apparently it never negotiates a
+ * always uses the session key. But apparently it never negotiates a
* subkey, so this code works fine against a JCSI client.) Up to the
* present, though, GSSAPI clients linked against the MIT code (which
* is almost all GSSAPI clients) don't encrypt the KRB_CRED message at
@@ -139,10 +134,11 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
* we should call it a second time with another auth context freshly
* created by krb5_auth_con_init. All of its keyblock fields will be
* NULL, so krb5_rd_cred will assume that the KRB_CRED message is
- * unencrypted. (The MIT code doesn't actually send the KRB_CRED
+ * unencrypted. (The MIT code doesn't actually send the KRB_CRED
* message in the clear -- the "authenticator" whose "checksum" ends up
* containing the KRB_CRED message does get encrypted.)
*/
+ /* Solaris Kerberos */
if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL))) {
krb5_enctype enctype = ENCTYPE_NULL;
/*
@@ -165,45 +161,32 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
}
/* Try to krb5_rd_cred() likely unencrypted KRB-CRED */
- if ((retval = krb5_auth_con_init(context, &new_auth_ctx)))
- goto cleanup;
- krb5_auth_con_setflags(context, new_auth_ctx, 0);
- if ((retval = krb5_rd_cred(context, new_auth_ctx, inbuf,
- &creds, NULL))) {
- KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
- "krb5_rd_cred() retval = %d\n", retval);
- goto cleanup;
- }
- }
-
- /* Lots of kludging going on here... Some day the ccache interface
- will be rewritten though */
-
- retval = krb5_cc_resolve(context, "MEMORY:GSSAPI", &template_ccache);
- if (retval) {
- KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
- "krb5_cc_resolve() retval = %d\n", retval);
- goto cleanup;
+ if ((retval = krb5_auth_con_init(context, &new_auth_ctx)))
+ goto cleanup;
+ krb5_auth_con_setflags(context, new_auth_ctx, 0);
+ if ((retval = krb5_rd_cred(context, new_auth_ctx, inbuf,
+ &creds, NULL))) {
+ /* Solaris Kerberos */
+ KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
+ "krb5_rd_cred() retval = %d\n", retval);
+ goto cleanup;
+ }
}
- ccache = template_ccache; /* krb5_cc_gen_new will replace so make a copy */
-
- retval = krb5_cc_gen_new(context, &ccache);
- if (retval) {
- KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
- "krb5_cc_gen_new() retval = %d\n", retval);
+ if ((retval = krb5_cc_new_unique(context, "MEMORY", NULL, &ccache))) {
+ ccache = NULL;
goto cleanup;
}
- retval = krb5_cc_initialize(context, ccache, creds[0]->client);
- if (retval != 0) {
+ if ((retval = krb5_cc_initialize(context, ccache, creds[0]->client))) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
"krb5_cc_initialize() retval = %d\n", retval);
goto cleanup;
}
- retval = krb5_cc_store_cred(context, ccache, creds[0]);
- if (retval != 0){
+ if ((retval = krb5_cc_store_cred(context, ccache, creds[0]))) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
"krb5_cc_store_cred() retval = %d\n", retval);
goto cleanup;
@@ -213,16 +196,17 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
if (out_cred) {
/* allocate memory for a cred_t... */
if (!(cred =
- (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))) {
+ (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))) {
retval = ENOMEM; /* out of memory? */
*out_cred = NULL;
goto cleanup;
}
/* zero it out... */
+ /* Solaris Kerberos */
(void) memset(cred, 0, sizeof(krb5_gss_cred_id_rec));
- retval = k5_mutex_init(&cred->lock);
+ retval = k5_mutex_init(&cred->lock);
if (retval) {
xfree(cred);
cred = NULL;
@@ -230,14 +214,15 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
}
/* copy the client principle into it... */
- if ((retval = krb5_copy_principal(context, creds[0]->client,
- &(cred->princ)))) {
+ if ((retval =
+ krb5_copy_principal(context, creds[0]->client, &(cred->princ)))) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "rd_and_store_for_creds() error "
"krb5_copy_principal() retval = %d\n", retval);
k5_mutex_destroy(&cred->lock);
retval = ENOMEM; /* out of memory? */
xfree(cred); /* clean up memory on failure */
- *out_cred = cred = NULL;
+ cred = NULL;
goto cleanup;
}
@@ -246,8 +231,7 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
cred->prerfc_mech = 1; /* this cred will work with all three mechs */
cred->rfc_mech = 1;
cred->keytab = NULL; /* no keytab associated with this... */
- /* The cred expires when the original cred was set to expire */
- cred->tgt_expire = creds[0]->times.endtime;
+ cred->tgt_expire = creds[0]->times.endtime; /* store the end time */
cred->ccache = ccache; /* the ccache containing the credential */
ccache = NULL; /* cred takes ownership so don't destroy */
}
@@ -259,19 +243,11 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
*/
cleanup:
if (creds)
- krb5_free_tgt_creds(context, creds);
+ krb5_free_tgt_creds(context, creds);
if (ccache)
(void)krb5_cc_destroy(context, ccache);
- /*
- * SUNW15resync
- * Added this cc_destroy for template_cache, w/out it causes memory
- * leak via "ssh -o gssapidelegatecredentials=yes ..."
- */
- if (template_ccache)
- (void)krb5_cc_destroy(context, template_ccache);
-
if (out_cred)
*out_cred = cred; /* return credential */
@@ -280,6 +256,7 @@ cleanup:
krb5_auth_con_setflags(context, auth_context, flags_org);
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_INFO, "rd_and_store_for_creds() end retval %d", retval);
return retval;
}
@@ -290,7 +267,7 @@ cleanup:
* does not have yet
*/
OM_uint32
-krb5_gss_accept_sec_context(minor_status, context_handle,
+krb5_gss_accept_sec_context(minor_status, context_handle,
verifier_cred_handle, input_token,
input_chan_bindings, src_name, mech_type,
output_token, ret_flags, time_rec,
@@ -364,10 +341,9 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
reqcksum.contents = 0;
ap_req.data = 0;
ap_rep.data = 0;
-
+
if (mech_type)
*mech_type = GSS_C_NULL_OID;
-
/* initialize the delegated cred handle to NO_CREDENTIAL for now */
if (delegated_cred_handle)
*delegated_cred_handle = GSS_C_NO_CREDENTIAL;
@@ -406,9 +382,9 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
mech_used = gss_mech_krb5;
} else if ((code == G_WRONG_MECH) &&
!(code = g_verify_token_header(gss_mech_krb5_old,
- (uint32_t *)&(ap_req.length),
- &ptr, KG_TOK_CTX_AP_REQ,
- input_token->length, 1))) {
+ (uint32_t *)&(ap_req.length),
+ &ptr, KG_TOK_CTX_AP_REQ,
+ input_token->length, 1))) {
/*
* Previous versions of this library used the old mech_id
* and some broken behavior (wrong IV on checksum
@@ -547,6 +523,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
if ((code = krb5_auth_con_init(context, &auth_context))) {
major_status = GSS_S_FAILURE;
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
"krb5_auth_con_init() error code %d", code);
goto fail;
@@ -558,14 +535,16 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
if (cred->rcache) {
cred_rcache = 1;
if ((code = krb5_auth_con_setrcache(context, auth_context, cred->rcache))) {
- major_status = GSS_S_FAILURE;
- KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
+ major_status = GSS_S_FAILURE;
+ /* Solaris Kerberos */
+ KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
"krb5_auth_con_setrcache() error code %d", code);
- goto fail;
+ goto fail;
}
}
if ((code = krb5_auth_con_setaddrs(context, auth_context, NULL, paddr))) {
major_status = GSS_S_FAILURE;
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
"krb5_auth_con_setaddrs() error code %d", code);
goto fail;
@@ -589,6 +568,8 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
major_status = GSS_S_FAILURE;
goto fail;
}
+ krb5_auth_con_setflags(context, auth_context,
+ KRB5_AUTH_CONTEXT_DO_SEQUENCE);
krb5_auth_con_getauthenticator(context, auth_context, &authdat);
@@ -607,8 +588,9 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
/* gss krb5 v1 */
/* stash this now, for later. */
- if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5,
- &md5len)) {
+ code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &md5len);
+ if (code) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
"krb5_c_checksum_length() error code %d", code);
major_status = GSS_S_FAILURE;
@@ -661,34 +643,38 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
/* at this point, bigend is set according to the initiator's
byte order */
- /*
+
+ /*
The following section of code attempts to implement the
- optional channel binding facility as described in RFC2743.
-
- Since this facility is optional channel binding may or may
- not have been provided by either the client or the server.
-
- If the server has specified input_chan_bindings equal to
- GSS_C_NO_CHANNEL_BINDINGS then we skip the check. If
- the server does provide channel bindings then we compute
- a checksum and compare against those provided by the
- client. If the check fails we test the clients checksum
- to see whether the client specified GSS_C_NO_CHANNEL_BINDINGS.
- If either test succeeds we continue without error.
- */
- if ((code = kg_checksum_channel_bindings(context, input_chan_bindings,
+ optional channel binding facility as described in RFC2743.
+
+ Since this facility is optional channel binding may or may
+ not have been provided by either the client or the server.
+
+ If the server has specified input_chan_bindings equal to
+ GSS_C_NO_CHANNEL_BINDINGS then we skip the check. If
+ the server does provide channel bindings then we compute
+ a checksum and compare against those provided by the
+ client. If the check fails we test the clients checksum
+ to see whether the client specified GSS_C_NO_CHANNEL_BINDINGS.
+ If either test succeeds we continue without error.
+ */
+ if ((code = kg_checksum_channel_bindings(context,
+ input_chan_bindings,
&reqcksum, bigend))) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
"kg_checksum_channel_bindings() error code %d", code);
- major_status = GSS_S_BAD_BINDINGS;
- goto fail;
+ major_status = GSS_S_BAD_BINDINGS;
+ goto fail;
}
- TREAD_STR(ptr, ptr2, reqcksum.length);
- if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) {
- if (memcmp(ptr2, reqcksum.contents, reqcksum.length) != 0) {
- xfree(reqcksum.contents);
- reqcksum.contents = 0;
+ TREAD_STR(ptr, ptr2, reqcksum.length);
+
+ if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS ) {
+ if (memcmp(ptr2, reqcksum.contents, reqcksum.length) != 0) {
+ xfree(reqcksum.contents);
+ reqcksum.contents = 0;
if ((code = kg_checksum_channel_bindings(context,
GSS_C_NO_CHANNEL_BINDINGS,
&reqcksum, bigend))) {
@@ -701,54 +687,86 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
goto fail;
}
}
+
}
TREAD_INT(ptr, gss_flags, bigend);
/* if the checksum length > 24, there are options to process */
- if (authdat->checksum->length > 24 &&
- (gss_flags & GSS_C_DELEG_FLAG)) {
+ if(authdat->checksum->length > 24 && (gss_flags & GSS_C_DELEG_FLAG)) {
+
i = authdat->checksum->length - 24;
if (i >= 4) {
+
TREAD_INT16(ptr, option_id, bigend);
TREAD_INT16(ptr, option.length, bigend);
- i -= 4;
- if (i < option.length || option.length < 0) {
- code = KG_BAD_LENGTH;
- major_status = GSS_S_FAILURE;
- goto fail;
- }
+ i -= 4;
- /* have to use ptr2, since option.data is wrong type and
+ if (i < option.length || option.length < 0) {
+ code = KG_BAD_LENGTH;
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
+
+ /* have to use ptr2, since option.data is wrong type and
macro uses ptr as both lvalue and rvalue */
- TREAD_STR(ptr, ptr2, option.length);
- option.data = (char *) ptr2;
+ TREAD_STR(ptr, ptr2, option.length);
+ option.data = (char *) ptr2;
- i -= option.length;
+ i -= option.length;
- if (option_id != KRB5_GSS_FOR_CREDS_OPTION) {
- major_status = GSS_S_FAILURE;
- goto fail;
- }
+ if (option_id != KRB5_GSS_FOR_CREDS_OPTION) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
- /* store the delegated credential */
+ /* store the delegated credential */
code = rd_and_store_for_creds(context, auth_context, &option,
- (delegated_cred_handle) ? &deleg_cred : NULL);
+ (delegated_cred_handle) ?
+ &deleg_cred : NULL);
if (code) {
major_status = GSS_S_FAILURE;
goto fail;
- }
+ }
- } /* if i >= 4 */
- /* ignore any additional trailing data, for now */
- } /* if */
- } /* krb5 gssapi v1 */
+ } /* if i >= 4 */
+ /* ignore any additional trailing data, for now */
+#ifdef CFX_EXERCISE
+ {
+ FILE *f = fopen("/tmp/gsslog", "a");
+ if (f) {
+ fprintf(f,
+ "initial context token with delegation, %d extra bytes\n",
+ i);
+ fclose(f);
+ }
+ }
+#endif
+ } else {
+#ifdef CFX_EXERCISE
+ {
+ FILE *f = fopen("/tmp/gsslog", "a");
+ if (f) {
+ if (gss_flags & GSS_C_DELEG_FLAG)
+ fprintf(f,
+ "initial context token, delegation flag but too small\n");
+ else
+ /* no deleg flag, length might still be too big */
+ fprintf(f,
+ "initial context token, %d extra bytes\n",
+ authdat->checksum->length - 24);
+ fclose(f);
+ }
+ }
+#endif
+ }
+ }
/* create the ctx struct and start filling it in */
@@ -760,14 +778,13 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
}
memset(ctx, 0, sizeof(krb5_gss_ctx_id_rec));
-
ctx->mech_used = (gss_OID) mech_used;
ctx->auth_context = auth_context;
ctx->initiate = 0;
ctx->gss_flags = (GSS_C_TRANS_FLAG |
- ((gss_flags) & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG |
- GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
- GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG)));
+ ((gss_flags) & (GSS_C_INTEG_FLAG | GSS_C_CONF_FLAG |
+ GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG |
+ GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG)));
ctx->seed_init = 0;
ctx->big_endian = bigend;
ctx->cred_rcache = cred_rcache;
@@ -777,6 +794,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
xfree(ctx);
ctx = 0;
+ /* Solaris Kerberos */
KRB5_LOG0(KRB5_ERR, "krb5_gss_accept_sec_context() "
"kg_save_ctx_id() error");
code = G_VALIDATE_FAILED;
@@ -785,6 +803,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
}
if ((code = krb5_copy_principal(context, cred->princ, &ctx->here))) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
"krb5_copy_principal() error code %d", code);
major_status = GSS_S_FAILURE;
@@ -792,6 +811,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
}
if ((code = krb5_copy_principal(context, authdat->client, &ctx->there))) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
"krb5_copy_principal() 2 error code %d", code);
major_status = GSS_S_FAILURE;
@@ -799,10 +819,11 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
}
if ((code = krb5_auth_con_getrecvsubkey(context, auth_context,
- &ctx->subkey))) {
+ &ctx->subkey))) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
"krb5_auth_con_getremotesubkey() error code %d", code);
- major_status = GSS_S_FAILURE;
+ major_status = GSS_S_FAILURE;
goto fail;
}
@@ -811,6 +832,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
if (ctx->subkey == NULL) {
if ((code = krb5_auth_con_getkey(context, auth_context,
&ctx->subkey))) {
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR, "krb5_gss_accept_sec_context() "
"krb5_auth_con_getkey() error code %d", code);
*minor_status = (OM_uint32) KRB5KDC_ERR_NULL_KEY;
@@ -827,6 +849,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
goto fail;
}
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR,"krb5_gss_accept_sec_context() "
"ctx->subkey->enctype=%d", ctx->subkey->enctype);
@@ -860,42 +883,41 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
ctx->sealalg = SEAL_ALG_DES3KD;
/* fill in the encryption descriptors */
-
copy_subkey:
if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) {
major_status = GSS_S_FAILURE;
goto fail;
}
-
copy_subkey_to_seq:
if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) {
major_status = GSS_S_FAILURE;
goto fail;
}
-
break;
+
case ENCTYPE_ARCFOUR_HMAC:
- ctx->signalg = SGN_ALG_HMAC_MD5 ;
- ctx->cksum_size = 8;
- ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
- goto copy_subkey;
+ ctx->signalg = SGN_ALG_HMAC_MD5 ;
+ ctx->cksum_size = 8;
+ ctx->sealalg = SEAL_ALG_MICROSOFT_RC4 ;
+ goto copy_subkey;
default:
- ctx->signalg = -1;
- ctx->sealalg = -1;
- ctx->proto = 1;
- code = krb5int_c_mandatory_cksumtype(context, ctx->subkey->enctype,
- &ctx->cksumtype);
- if (code)
- goto fail;
- code = krb5_c_checksum_length(context, ctx->cksumtype,
+ ctx->signalg = -1;
+ ctx->sealalg = -1;
+ ctx->proto = 1;
+ code = (*kaccess.krb5int_c_mandatory_cksumtype)(context, ctx->subkey->enctype,
+ &ctx->cksumtype);
+ if (code)
+ goto fail;
+ code = krb5_c_checksum_length(context, ctx->cksumtype,
(size_t *)&ctx->cksum_size);
- if (code)
- goto fail;
- ctx->have_acceptor_subkey = 0;
- goto copy_subkey;
+ if (code)
+ goto fail;
+ ctx->have_acceptor_subkey = 0;
+ goto copy_subkey;
}
+ /* Solaris Kerberos */
KRB5_LOG1(KRB5_ERR, "accept_sec_context: subkey enctype = %d proto = %d",
ctx->subkey->enctype, ctx->proto);
@@ -903,11 +925,12 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
ctx->krb_flags = ticket->enc_part2->flags;
krb5_free_ticket(context, ticket); /* Done with ticket */
+
{
- krb5_ui_4 seq_temp;
- krb5_auth_con_getremoteseqnumber(context, auth_context,
+ krb5_ui_4 seq_temp;
+ krb5_auth_con_getremoteseqnumber(context, auth_context,
(krb5_int32 *)&seq_temp);
- ctx->seq_recv = seq_temp;
+ ctx->seq_recv = seq_temp;
}
if ((code = krb5_timeofday(context, &now))) {
@@ -925,31 +948,31 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
(ctx->gss_flags & GSS_C_REPLAY_FLAG) != 0,
(ctx->gss_flags & GSS_C_SEQUENCE_FLAG) != 0, ctx->proto);
- /* at this point, the entire context structure is filled in,
+ /* at this point, the entire context structure is filled in,
so it can be released. */
/* generate an AP_REP if necessary */
if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) {
unsigned char * ptr3;
- krb5_ui_4 seq_temp;
- int cfx_generate_subkey;
+ krb5_ui_4 seq_temp;
+ int cfx_generate_subkey;
- if (ctx->proto == 1)
+ if (ctx->proto == 1)
cfx_generate_subkey = CFX_ACCEPTOR_SUBKEY;
- else
+ else
cfx_generate_subkey = 0;
- if (cfx_generate_subkey) {
+ if (cfx_generate_subkey) {
krb5_int32 acflags;
code = krb5_auth_con_getflags(context, auth_context, &acflags);
if (code == 0) {
- acflags |= KRB5_AUTH_CONTEXT_USE_SUBKEY;
- code = krb5_auth_con_setflags(context, auth_context, acflags);
+ acflags |= KRB5_AUTH_CONTEXT_USE_SUBKEY;
+ code = krb5_auth_con_setflags(context, auth_context, acflags);
}
- if (code) {
- major_status = GSS_S_FAILURE;
- goto fail;
+ if (code) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
}
}
@@ -962,28 +985,29 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
(krb5_int32 *)&seq_temp);
ctx->seq_send = seq_temp & 0xffffffffL;
- if (cfx_generate_subkey) {
+ if (cfx_generate_subkey) {
/* Get the new acceptor subkey. With the code above, there
- should always be one if we make it to this point. */
+ should always be one if we make it to this point. */
code = krb5_auth_con_getsendsubkey(context, auth_context,
- &ctx->acceptor_subkey);
+ &ctx->acceptor_subkey);
if (code != 0) {
- major_status = GSS_S_FAILURE;
- goto fail;
+ major_status = GSS_S_FAILURE;
+ goto fail;
}
- code = krb5int_c_mandatory_cksumtype(context,
- ctx->acceptor_subkey->enctype,
- &ctx->acceptor_subkey_cksumtype);
+ code = (*kaccess.krb5int_c_mandatory_cksumtype)(context,
+ ctx->acceptor_subkey->enctype,
+ &ctx->acceptor_subkey_cksumtype);
if (code) {
- major_status = GSS_S_FAILURE;
- goto fail;
+ major_status = GSS_S_FAILURE;
+ goto fail;
}
- ctx->have_acceptor_subkey = 1;
- }
+ ctx->have_acceptor_subkey = 1;
+ }
/* the reply token hasn't been sent yet, but that's ok. */
ctx->gss_flags |= GSS_C_PROT_READY_FLAG;
ctx->established = 1;
+
token.length = g_token_size(mech_used, ap_rep.length);
if ((token.value = (unsigned char *) xmalloc(token.length))
@@ -992,17 +1016,21 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
code = ENOMEM;
goto fail;
}
- ptr = token.value;
+ ptr3 = token.value;
g_make_token_header(mech_used, ap_rep.length,
- &ptr, KG_TOK_CTX_AP_REP);
+ &ptr3, KG_TOK_CTX_AP_REP);
+
+ TWRITE_STR(ptr3, ap_rep.data, ap_rep.length);
+
+ ctx->established = 1;
- TWRITE_STR(ptr, ap_rep.data, ap_rep.length);
} else {
token.length = 0;
token.value = NULL;
ctx->seq_send = ctx->seq_recv;
+
+ ctx->established = 1;
}
- ctx->established = 1;
/* set the return arguments */
@@ -1028,20 +1056,21 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
if (ret_flags)
*ret_flags = ctx->gss_flags;
- *context_handle = (gss_ctx_id_t) ctx;
+ *context_handle = (gss_ctx_id_t)ctx;
*output_token = token;
if (src_name)
*src_name = (gss_name_t) name;
if (delegated_cred_handle && deleg_cred) {
- if (!kg_save_cred_id((gss_cred_id_t) deleg_cred)) {
+ if (!kg_save_cred_id((gss_cred_id_t) deleg_cred)) {
+ /* Solaris Kerberos */
KRB5_LOG0(KRB5_ERR, "krb5_gss_accept_sec_context() "
"kg_save_cred_id() error");
major_status = GSS_S_FAILURE;
code = (OM_uint32) G_VALIDATE_FAILED;
- goto fail;
- }
+ goto fail;
+ }
*delegated_cred_handle = (gss_cred_id_t) deleg_cred;
}
@@ -1086,7 +1115,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
/* from here on is the real "fail" code */
if (ctx)
- (void) krb5_gss_delete_sec_context(minor_status,
+ (void) krb5_gss_delete_sec_context(minor_status,
(gss_ctx_id_t *) &ctx, NULL);
if (deleg_cred) { /* free memory associated with the deleg credential */
if (deleg_cred->ccache)
@@ -1107,8 +1136,9 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
if (saved_ap_options & AP_OPTS_MUTUAL_REQUIRED)
gss_flags |= GSS_C_MUTUAL_FLAG;
- if (cred && ((gss_flags & GSS_C_MUTUAL_FLAG) ||
- (major_status == GSS_S_CONTINUE_NEEDED))) {
+ if (cred
+ && ((gss_flags & GSS_C_MUTUAL_FLAG)
+ || (major_status == GSS_S_CONTINUE_NEEDED))) {
unsigned int tmsglen;
int toktype;
@@ -1118,7 +1148,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
*/
memset(&krb_error_data, 0, sizeof(krb_error_data));
- code -= ERROR_TABLE_BASE_krb5;
+ code -= ERROR_TABLE_BASE_krb5;
if (code < 0 || code > 128)
code = 60 /* KRB_ERR_GENERIC */;
@@ -1126,7 +1156,7 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
(void) krb5_us_timeofday(context, &krb_error_data.stime,
&krb_error_data.susec);
krb_error_data.server = cred->princ;
-
+
code = krb5_mk_error(context, &krb_error_data, &scratch);
if (code)
goto cleanup;
@@ -1150,11 +1180,11 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
cleanup:
if (!verifier_cred_handle && cred_handle) {
- krb5_gss_release_cred(minor_status, &cred_handle);
+ krb5_gss_release_cred(minor_status, &cred_handle);
}
-
krb5_free_context(context);
+ /* Solaris Kerberos */
KRB5_LOG(KRB5_ERR,"krb5_gss_accept_sec_context() end, "
"major_status = %d", major_status);
return (major_status);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/acquire_cred.c b/usr/src/lib/gss_mechs/mech_krb5/mech/acquire_cred.c
index a916cc2b0e..16fe5c0b04 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/acquire_cred.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/acquire_cred.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright 2000 by the Massachusetts Institute of Technology.
@@ -87,14 +86,14 @@
#include <strings.h>
#endif
-/* SUNW15resync - Solaris kerberos does not need this feature in this file */
-#ifdef USE_LOGIN_LIBRARY
-#undef USE_LOGIN_LIBRARY
-#endif
-
#if defined(USE_LOGIN_LIBRARY)
#include <Kerberos/KerberosLoginPrivate.h>
#elif defined(USE_LEASH)
+#ifdef _WIN64
+#define LEASH_DLL "leashw64.dll"
+#else
+#define LEASH_DLL "leashw32.dll"
+#endif
static void (*pLeash_AcquireInitialTicketsIfNeeded)(krb5_context,krb5_principal,char*,int) = NULL;
static HANDLE hLeashDLL = INVALID_HANDLE_VALUE;
#endif
@@ -237,6 +236,7 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
krb5_cc_cursor cur;
krb5_creds creds;
int got_endtime;
+ int caller_provided_ccache_name = 0;
cred->ccache = NULL;
@@ -245,36 +245,41 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
if (GSS_ERROR(kg_sync_ccache_name(context, minor_status)))
return(GSS_S_FAILURE);
+ /* check to see if the caller provided a ccache name if so
+ * we will just use that and not search the cache collection */
+ if (GSS_ERROR(kg_caller_provided_ccache_name (minor_status, &caller_provided_ccache_name))) {
+ return(GSS_S_FAILURE);
+ }
+
#if defined(USE_LOGIN_LIBRARY) || defined(USE_LEASH)
- if (desired_name != NULL) {
+ if (desired_name && !caller_provided_ccache_name) {
#if defined(USE_LOGIN_LIBRARY)
+ KLStatus err = klNoErr;
char *ccache_name = NULL;
KLPrincipal kl_desired_princ = NULL;
+
+ err = __KLCreatePrincipalFromKerberos5Principal ((krb5_principal) desired_name,
+ &kl_desired_princ);
- if ((code = __KLCreatePrincipalFromKerberos5Principal ((krb5_principal) desired_name,
- &kl_desired_princ))) {
- *minor_status = code;
- return(GSS_S_NO_CRED);
+ if (!err) {
+ err = KLAcquireInitialTickets (kl_desired_princ, NULL, NULL, &ccache_name);
}
-
- if ((code = KLAcquireInitialTickets (kl_desired_princ, NULL, NULL, &ccache_name))) {
- KLDisposePrincipal (kl_desired_princ);
- *minor_status = code;
- return(GSS_S_NO_CRED);
+
+ if (!err) {
+ err = krb5_cc_resolve (context, ccache_name, &ccache);
}
- if ((code = krb5_cc_resolve (context, ccache_name, &ccache))) {
- KLDisposeString (ccache_name);
- KLDisposePrincipal (kl_desired_princ);
- *minor_status = code;
- return(GSS_S_NO_CRED);
+ if (err) {
+ *minor_status = err;
+ return(GSS_S_CRED_UNAVAIL);
}
-
+
if (kl_desired_princ != NULL) { KLDisposePrincipal (kl_desired_princ); }
if (ccache_name != NULL) { KLDisposeString (ccache_name); }
+
#elif defined(USE_LEASH)
if ( hLeashDLL == INVALID_HANDLE_VALUE ) {
- hLeashDLL = LoadLibrary("leashw32.dll");
+ hLeashDLL = LoadLibrary(LEASH_DLL);
if ( hLeashDLL != INVALID_HANDLE_VALUE ) {
(FARPROC) pLeash_AcquireInitialTicketsIfNeeded =
GetProcAddress(hLeashDLL, "not_an_API_Leash_AcquireInitialTicketsIfNeeded");
@@ -330,6 +335,7 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
/* get out the principal name and see if it matches */
if ((code = krb5_cc_get_principal(context, ccache, &princ))) {
+ /* Solaris Kerberos */
(void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
(void)krb5_cc_close(context, ccache);
*minor_status = code;
@@ -339,6 +345,7 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
if (desired_name != (gss_name_t) NULL) {
if (! krb5_principal_compare(context, princ, (krb5_principal) desired_name)) {
(void)krb5_free_principal(context, princ);
+ /* Solaris Kerberos */
(void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
(void)krb5_cc_close(context, ccache);
*minor_status = KG_CCACHE_NOMATCH;
@@ -353,6 +360,7 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
/* iterate over the ccache, find the tgt */
if ((code = krb5_cc_start_seq_get(context, ccache, &cur))) {
+ /* Solaris Kerberos */
(void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
(void)krb5_cc_close(context, ccache);
*minor_status = code;
@@ -373,6 +381,7 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
krb5_princ_realm(context, princ)->data,
0);
if (code) {
+ /* Solaris Kerberos */
(void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
(void)krb5_cc_close(context, ccache);
*minor_status = code;
@@ -398,6 +407,7 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
if (code && code != KRB5_CC_END) {
/* this means some error occurred reading the ccache */
(void)krb5_cc_end_seq_get(context, ccache, &cur);
+ /* Solaris Kerberos */
(void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
(void)krb5_cc_close(context, ccache);
*minor_status = code;
@@ -405,6 +415,7 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
} else if (! got_endtime) {
/* this means the ccache was entirely empty */
(void)krb5_cc_end_seq_get(context, ccache, &cur);
+ /* Solaris Kerberos */
(void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
(void)krb5_cc_close(context, ccache);
*minor_status = KG_EMPTY_CCACHE;
@@ -412,6 +423,7 @@ acquire_init_cred(context, minor_status, desired_name, output_princ, cred)
} else {
/* this means that we found an endtime to use. */
if ((code = krb5_cc_end_seq_get(context, ccache, &cur))) {
+ /* Solaris Kerberos */
(void)krb5_cc_set_flags(context, ccache, KRB5_TC_OPENCLOSE);
(void)krb5_cc_close(context, ccache);
*minor_status = code;
@@ -640,11 +652,11 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
&ret_mechs)) ||
(cred->prerfc_mech &&
GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
- (const gss_OID) gss_mech_krb5_old,
+ (const gss_OID) gss_mech_krb5_old,
&ret_mechs))) ||
(cred->rfc_mech &&
GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
- (const gss_OID) gss_mech_krb5,
+ (const gss_OID) gss_mech_krb5,
&ret_mechs)))) {
if (cred->ccache)
(void)krb5_cc_close(context, cred->ccache);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/add_cred.c b/usr/src/lib/gss_mechs/mech_krb5/mech/add_cred.c
index b24d1496ca..d401785b93 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/add_cred.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/add_cred.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Copyright 2000 by the Massachusetts Institute of Technology.
* All Rights Reserved.
@@ -58,7 +56,7 @@
#endif
/*
- * $Id: add_cred.c 18015 2006-05-17 05:26:12Z raeburn $
+ * $Id: add_cred.c 18396 2006-07-25 20:29:43Z lxs $
*/
/* V2 interface */
@@ -345,7 +343,7 @@ krb5_gss_add_cred(minor_status, input_cred_handle,
/* set the outputs */
if (GSS_ERROR(major_status = krb5_gss_inquire_cred(minor_status,
- (gss_cred_id_t) cred,
+ (gss_cred_id_t)cred,
NULL, &lifetime,
NULL, actual_mechs))) {
OM_uint32 dummy;
@@ -363,7 +361,7 @@ krb5_gss_add_cred(minor_status, input_cred_handle,
*acceptor_time_rec = lifetime;
if (output_cred_handle)
- *output_cred_handle = (gss_cred_id_t) cred;
+ *output_cred_handle = (gss_cred_id_t)cred;
krb5_free_context(context);
*minor_status = 0;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/disp_com_err_status.c b/usr/src/lib/gss_mechs/mech_krb5/mech/disp_com_err_status.c
index 150f30ec20..ab49803169 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/disp_com_err_status.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/disp_com_err_status.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Copyright 1993 by OpenVision Technologies, Inc.
*
@@ -23,12 +21,12 @@
*/
/*
- * $Id: disp_com_err_status.c 16391 2004-06-02 23:40:12Z raeburn $
+ * $Id: disp_com_err_status.c 18721 2006-10-16 16:18:29Z epeisach $
*/
#include "gssapiP_generic.h"
-#include "com_err.h"
#include "gss_libinit.h"
+#include "com_err.h"
/* XXXX internationalization!! */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/export_sec_context.c b/usr/src/lib/gss_mechs/mech_krb5/mech/export_sec_context.c
index 4460c2b486..fb57b882a2 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/export_sec_context.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/export_sec_context.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/gssapi/krb5/export_sec_context.c
*
@@ -62,10 +60,6 @@ krb5_gss_export_sec_context(minor_status, context_handle, interprocess_token)
if (kret)
goto error_out;
- { gss_OID go = ctx->mech_used;
- printf("export ctx len=%lu\n", go->length);
- }
-
/* Determine size needed for externalization of context */
bufsize = 0;
if ((kret = kg_ctx_size(context, (krb5_pointer) ctx,
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/gss_libinit.c b/usr/src/lib/gss_mechs/mech_krb5/mech/gss_libinit.c
index a410640031..ee98ce3188 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/gss_libinit.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/gss_libinit.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <assert.h>
@@ -49,7 +48,7 @@ int gssint_lib_init(void)
err = k5_key_register(K5_KEY_GSS_KRB5_CCACHE_NAME, free);
if (err)
return err;
-#if 0 /* SUNW15resync - revisit when mech resynced w/1.5 */
+#ifndef _WIN32
err = k5_mutex_finish_init(&kg_kdc_flag_mutex);
if (err)
return err;
@@ -75,7 +74,7 @@ void gssint_lib_fini(void)
k5_key_delete(K5_KEY_GSS_KRB5_SET_CCACHE_OLD_NAME);
k5_key_delete(K5_KEY_GSS_KRB5_CCACHE_NAME);
k5_mutex_destroy(&kg_vdb.mutex);
-#if 0 /* SUNW15resync - revisit when mech resynced w/1.5 */
+#ifndef _WIN32
k5_mutex_destroy(&kg_kdc_flag_mutex);
#endif
k5_mutex_destroy(&gssint_krb5_keytab_lock);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/indicate_mechs.c b/usr/src/lib/gss_mechs/mech_krb5/mech/indicate_mechs.c
index 060ac76ace..f10077a77e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/indicate_mechs.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/indicate_mechs.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Copyright 1993 by OpenVision Technologies, Inc.
*
@@ -23,7 +21,7 @@
*/
/*
- * $Id: indicate_mechs.c 18131 2006-06-14 22:27:54Z tlyu $
+ * $Id: indicate_mechs.c 18330 2006-07-17 16:39:35Z tlyu $
*/
#include "gssapiP_krb5.h"
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/init_sec_context.c b/usr/src/lib/gss_mechs/mech_krb5/mech/init_sec_context.c
index 7a0015abf9..811de69cf4 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/init_sec_context.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/init_sec_context.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright 2000,2002, 2003 by the Massachusetts Institute of Technology.
@@ -78,8 +77,8 @@
*/
#include "k5-int.h"
-#include "gssapiP_krb5.h"
#include "gss_libinit.h"
+#include "gssapiP_krb5.h"
#include "mglueP.h"
#ifdef HAVE_MEMORY_H
#include <memory.h>
@@ -92,7 +91,7 @@ static OM_uint32 get_default_cred(OM_uint32 *, void *, gss_cred_id_t *);
/* Solaris Kerberos end */
/*
- * $Id: init_sec_context.c 18131 2006-06-14 22:27:54Z tlyu $
+ * $Id: init_sec_context.c 18721 2006-10-16 16:18:29Z epeisach $
*/
/* XXX This is for debugging only!!! Should become a real bitfield
@@ -232,7 +231,7 @@ make_gss_checksum (krb5_context context, krb5_auth_context auth_context,
krb5_free_data_contents(context, &credmsg);
return(ENOMEM);
}
-
+ /* Solaris Kerberos */
ptr = (uchar_t *)data->checksum_data.data; /* SUNW15resync */
TWRITE_INT(ptr, data->md5.length, 0);
@@ -370,9 +369,7 @@ setup_enc(
krb5_gss_ctx_id_rec *ctx,
krb5_context context)
{
-
krb5_error_code code;
- OM_uint32 ret = GSS_S_COMPLETE;
int i;
krb5int_access kaccess;
@@ -446,7 +443,6 @@ setup_enc(
goto fail;
goto copy_subkey;
}
-
fail:
/* SUNW15resync - (as in prev snv code) add if-code and success label fix */
if (code) {
@@ -455,7 +451,7 @@ fail:
}
success:
- return (ret);
+ return (GSS_S_COMPLETE);
}
/*
@@ -711,7 +707,7 @@ mutual_auth(
return(GSS_S_NO_CONTEXT);
}
- ctx = (krb5_gss_ctx_id_rec *)*context_handle; /* SUNW15resync */
+ ctx = (krb5_gss_ctx_id_t) *context_handle;
/* make sure the context is non-established, and that certain
arguments are unchanged */
@@ -999,7 +995,7 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
return(major_status);
}
-#if 0 /* SUNW15resync - revisit when mech resynced w/1.5 */
+#ifndef _WIN32
k5_mutex_t kg_kdc_flag_mutex = K5_MUTEX_PARTIAL_INITIALIZER;
static int kdc_flag = 0;
#endif
@@ -1008,12 +1004,14 @@ krb5_error_code
krb5_gss_init_context (krb5_context *ctxp)
{
krb5_error_code err;
+#ifndef _WIN32
int is_kdc;
+#endif
err = gssint_initialize_library();
if (err)
return err;
-#if 0 /* SUNW15resync - revisit when mech resynced w/1.5 */
+#ifndef _WIN32
err = k5_mutex_lock(&kg_kdc_flag_mutex);
if (err)
return err;
@@ -1022,14 +1020,12 @@ krb5_gss_init_context (krb5_context *ctxp)
if (is_kdc)
return krb5int_init_context_kdc(ctxp);
- else
- return krb5_init_context(ctxp);
#endif
- return krb5_init_context(ctxp);
+ return krb5_init_context(ctxp);
}
-#if 0 /* SUNW15resync - revisit when mech resynced w/1.5 */
+#ifndef _WIN32
krb5_error_code
krb5_gss_use_kdc_context()
{
@@ -1396,26 +1392,6 @@ load_root_cred_using_keytab(
*minor_status = code;
return (GSS_S_FAILURE);
}
- /*
- * Solaris Kerberos:
- * If the client's realm is empty (using a fallback method to determine
- * the realm) then make sure to set the client's realm to the default
- * realm. This ensures that the TGT is built correctly.
- */
- if (krb5_is_referral_realm(&(me->realm))) {
- char *realm;
-
- free(me->realm.data);
- code = krb5_get_default_realm(context, &realm);
- if (code) {
- (void) krb5_kt_close(context, keytab);
- *minor_status = code;
- return (GSS_S_FAILURE);
- }
-
- me->realm.data = realm;
- me->realm.length = strlen(realm);
- }
my_creds.client = me;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/inq_cred.c b/usr/src/lib/gss_mechs/mech_krb5/mech/inq_cred.c
index 9460971297..43954f7e3a 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/inq_cred.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/inq_cred.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Copyright 2000 by the Massachusetts Institute of Technology.
* All Rights Reserved.
@@ -157,15 +155,16 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
}
if (mechanisms) {
+ /* Solaris Kerberos */
if (GSS_ERROR(ret = generic_gss_create_empty_oid_set(minor_status,
&mechs)) ||
(cred->prerfc_mech &&
GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
- (const gss_OID) gss_mech_krb5_old,
+ (const gss_OID) gss_mech_krb5_old,
&mechs))) ||
(cred->rfc_mech &&
GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
- (const gss_OID) gss_mech_krb5,
+ (const gss_OID) gss_mech_krb5,
&mechs)))) {
k5_mutex_unlock(&cred->lock);
if (ret_name)
@@ -176,7 +175,7 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
}
if (name) {
- if (ret_name != NULL && ! kg_save_name((gss_name_t) ret_name)) {
+ if (ret_name != NULL && ! kg_save_name((gss_name_t) ret_name)) {
k5_mutex_unlock(&cred->lock);
if (cred_handle == GSS_C_NO_CREDENTIAL)
krb5_gss_release_cred(minor_status, (gss_cred_id_t *)&cred);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/inq_names.c b/usr/src/lib/gss_mechs/mech_krb5/mech/inq_names.c
index e5fbfa5b87..cf53719b45 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/inq_names.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/inq_names.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/gssapi/krb5/inq_names.c
*
@@ -81,12 +79,13 @@ krb5_gss_inquire_names_for_mech(minor_status, mechanism, name_types)
name_types)
) == GSS_S_COMPLETE) &&
((major = generic_gss_add_oid_set_member(minor_status,
- (const gss_OID) gss_nt_krb5_name,
+ (const gss_OID) gss_nt_krb5_name, /* Solaris Kerberos */
name_types)
) == GSS_S_COMPLETE)
) {
+ /* Solaris Kerberos */
major = generic_gss_add_oid_set_member(minor_status,
- (const gss_OID) gss_nt_krb5_principal,
+ (const gss_OID) gss_nt_krb5_principal,
name_types);
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/krb5_gss_glue.c b/usr/src/lib/gss_mechs/mech_krb5/mech/krb5_gss_glue.c
index a63be60ffd..d04f7182f5 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/krb5_gss_glue.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/krb5_gss_glue.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright 1993 by OpenVision Technologies, Inc.
@@ -28,7 +27,7 @@
*/
/*
- * $Id: krb5_gss_glue.c 18268 2006-06-29 19:44:34Z tlyu $
+ * $Id: krb5_gss_glue.c 18262 2006-06-29 04:38:48Z tlyu $
*/
#include "gssapiP_krb5.h"
@@ -42,7 +41,7 @@ static OM_uint32 k5glue_acquire_cred
gss_name_t, /* desired_name */
OM_uint32, /* time_req */
gss_OID_set, /* desired_mechs */
- gss_cred_usage_t, /* cred_usage */
+ gss_cred_usage_t, /* cred_usage */
gss_cred_id_t*, /* output_cred_handle */
gss_OID_set*, /* actual_mechs */
OM_uint32* /* time_rec */
@@ -616,7 +615,7 @@ k5glue_acquire_cred(ctx, minor_status, desired_name, time_req, desired_mechs,
gss_name_t desired_name;
OM_uint32 time_req;
gss_OID_set desired_mechs;
- gss_cred_usage_t cred_usage;
+ gss_cred_usage_t cred_usage;
gss_cred_id_t *output_cred_handle;
gss_OID_set *actual_mechs;
OM_uint32 *time_rec;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/process_context_token.c b/usr/src/lib/gss_mechs/mech_krb5/mech/process_context_token.c
index 9e312adbf5..292b3e3f08 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/process_context_token.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/process_context_token.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Copyright 1993 by OpenVision Technologies, Inc.
*
@@ -25,7 +23,7 @@
#include "gssapiP_krb5.h"
/*
- * $Id: process_context_token.c 16171 2004-03-15 17:45:01Z raeburn $
+ * $Id: process_context_token.c 18396 2006-07-25 20:29:43Z lxs $
*/
OM_uint32
@@ -54,7 +52,7 @@ krb5_gss_process_context_token(minor_status, context_handle,
/* "unseal" the token */
if (GSS_ERROR(majerr = kg_unseal(minor_status, context_handle,
- token_buffer,
+ token_buffer,
GSS_C_NO_BUFFER, NULL, NULL,
KG_TOK_DEL_CTX)))
return(majerr);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/rel_oid.c b/usr/src/lib/gss_mechs/mech_krb5/mech/rel_oid.c
index 395ba68818..5b6d9a6cdd 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/rel_oid.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/rel_oid.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/gssapi/krb5/rel_oid.c
*
@@ -31,7 +29,10 @@
* rel_oid.c - Release an OID.
*/
#include "gssapiP_krb5.h"
-#include "mglueP.h"
+
+/* Solaris Kerberos - resync 163 */
+OM_uint32 generic_gss_release_oid (OM_uint32 *, gss_OID *);
+
OM_uint32 krb5_gss_internal_release_oid (OM_uint32 *, /* minor_status */
gss_OID * /* oid */
diff --git a/usr/src/lib/gss_mechs/mech_krb5/mech/set_ccache.c b/usr/src/lib/gss_mechs/mech_krb5/mech/set_ccache.c
index e6f784c049..929749d978 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/mech/set_ccache.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/mech/set_ccache.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/gssapi/krb5/set_ccache.c
@@ -65,6 +64,7 @@ gss_krb5_ccache_name(minor_status, name, out_name)
}
if (!err) {
old_name = gss_out_name;
+ /* Solaris Kerberos */
gss_out_name = (char *)tmp_name;
}
}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/profile/prof_file.c b/usr/src/lib/gss_mechs/mech_krb5/profile/prof_file.c
index 3b33f25ccf..893cdfc6d5 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/profile/prof_file.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/profile/prof_file.c
@@ -1,8 +1,7 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* prof_file.c ---- routines that manipulate an individual profile file.
*/
@@ -55,6 +54,9 @@ MAKE_FINI_FUNCTION(profile_library_finalizer);
int profile_library_initializer(void)
{
+#ifdef SHOW_INITFINI_FUNCS
+ printf("profile_library_initializer\n");
+#endif
#if !USE_BUNDLE_ERROR_STRINGS
add_error_table(&et_prof_error_table);
#endif
@@ -62,8 +64,15 @@ int profile_library_initializer(void)
}
void profile_library_finalizer(void)
{
- if (! INITIALIZER_RAN(profile_library_initializer) || PROGRAM_EXITING())
+ if (! INITIALIZER_RAN(profile_library_initializer) || PROGRAM_EXITING()) {
+#ifdef SHOW_INITFINI_FUNCS
+ printf("profile_library_finalizer: skipping\n");
+#endif
return;
+ }
+#ifdef SHOW_INITFINI_FUNCS
+ printf("profile_library_finalizer\n");
+#endif
k5_mutex_destroy(&g_shared_trees_mutex);
#if !USE_BUNDLE_ERROR_STRINGS
remove_error_table(&et_prof_error_table);
@@ -85,6 +94,7 @@ static void profile_free_file_data(prf_data_t);
assert(d->fslen <= 1000); /* XXX */ \
assert(d->filespec[d->fslen] == 0); \
assert(d->fslen = strlen(d->filespec)); \
+ assert(d->root != NULL); \
} \
}
@@ -118,7 +128,7 @@ static int rw_access(const_profile_filespec_t filespec)
* checks the r/w permissions.
*/
FILE *f;
-
+ /* Solaris Kerberos */
f = fopen(filespec, "r+F");
if (f) {
fclose(f);
@@ -143,6 +153,7 @@ static int r_access(const_profile_filespec_t filespec)
*/
FILE *f;
+ /* Solaris Kerberos */
f = fopen(filespec, "rF");
if (f) {
fclose(f);
@@ -196,7 +207,7 @@ errcode_t profile_open_file(const_profile_filespec_t filespec,
scan_shared_trees_unlocked();
- prf = (prf_file_t) malloc(sizeof(struct _prf_file_t));
+ prf = malloc(sizeof(struct _prf_file_t));
if (!prf)
return ENOMEM;
memset(prf, 0, sizeof(struct _prf_file_t));
@@ -208,25 +219,12 @@ errcode_t profile_open_file(const_profile_filespec_t filespec,
#ifdef HAVE_PWD_H
if (home_env == NULL) {
uid_t uid;
- struct passwd *pw;
-#ifdef HAVE_GETPWUID_R
- struct passwd pwx;
+ struct passwd *pw, pwx;
char pwbuf[BUFSIZ];
-#endif
uid = getuid();
-#ifndef HAVE_GETPWUID_R
- pw = getpwuid(uid);
-#elif defined(GETPWUID_R_4_ARGS)
- /* earlier POSIX drafts */
- pw = getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf));
-#else
- /* POSIX */
- if (getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw) != 0)
- /* Probably already null, but let's make sure. */
- pw = NULL;
-#endif /* getpwuid variants */
- if (pw != NULL && pw->pw_dir[0] != 0)
+ if (!k5_getpwuid_r(uid, &pwx, pwbuf, sizeof(pwbuf), &pw)
+ && pw != NULL && pw->pw_dir[0] != 0)
home_env = pw->pw_dir;
}
#endif
@@ -257,9 +255,9 @@ errcode_t profile_open_file(const_profile_filespec_t filespec,
break;
}
if (data) {
- retval = profile_update_file_data(data);
data->refcount++;
(void) k5_mutex_unlock(&g_shared_trees_mutex);
+ retval = profile_update_file_data(data);
free(expanded_filename);
prf->data = data;
*ret_prof = prf;
@@ -311,10 +309,9 @@ errcode_t profile_update_file_data(prf_data_t data)
errcode_t retval;
#ifdef HAVE_STAT
struct stat st;
-#ifdef STAT_ONCE_PER_SECOND
+ unsigned long frac;
time_t now;
#endif
-#endif
FILE *f;
retval = k5_mutex_lock(&data->lock);
@@ -322,22 +319,29 @@ errcode_t profile_update_file_data(prf_data_t data)
return retval;
#ifdef HAVE_STAT
-#ifdef STAT_ONCE_PER_SECOND
now = time(0);
- if (now == data->last_stat) {
+ if (now == data->last_stat && data->root != NULL) {
k5_mutex_unlock(&data->lock);
return 0;
}
-#endif
if (stat(data->filespec, &st)) {
retval = errno;
k5_mutex_unlock(&data->lock);
return retval;
}
-#ifdef STAT_ONCE_PER_SECOND
data->last_stat = now;
+#if defined HAVE_STRUCT_STAT_ST_MTIMENSEC
+ frac = st.st_mtimensec;
+#elif defined HAVE_STRUCT_STAT_ST_MTIMESPEC_TV_NSEC
+ frac = st.st_mtimespec.tv_nsec;
+#elif defined HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
+ frac = st.st_mtim.tv_nsec;
+#else
+ frac = 0;
#endif
- if (st.st_mtime == data->timestamp) {
+ if (st.st_mtime == data->timestamp
+ && frac == data->frac_ts
+ && data->root != NULL) {
k5_mutex_unlock(&data->lock);
return 0;
}
@@ -361,6 +365,7 @@ errcode_t profile_update_file_data(prf_data_t data)
}
#endif
errno = 0;
+ /* Solaris Kerberos */
f = fopen(data->filespec, "rF");
if (f == NULL) {
retval = errno;
@@ -379,8 +384,10 @@ errcode_t profile_update_file_data(prf_data_t data)
k5_mutex_unlock(&data->lock);
return retval;
}
+ assert(data->root != NULL);
#ifdef HAVE_STAT
data->timestamp = st.st_mtime;
+ data->frac_ts = frac;
#endif
k5_mutex_unlock(&data->lock);
return 0;
@@ -407,10 +414,10 @@ static errcode_t write_data_to_file(prf_data_t data, const char *outfile,
retval = ENOMEM;
new_file = old_file = 0;
- new_file = (char *) malloc(strlen(outfile) + 5);
+ new_file = malloc(strlen(outfile) + 5);
if (!new_file)
goto errout;
- old_file = (char *) malloc(strlen(outfile) + 5);
+ old_file = malloc(strlen(outfile) + 5);
if (!old_file)
goto errout;
@@ -419,6 +426,7 @@ static errcode_t write_data_to_file(prf_data_t data, const char *outfile,
errno = 0;
+ /* Solaris Kerberos */
f = fopen(new_file, "wF");
if (!f) {
retval = errno;
@@ -533,19 +541,19 @@ errcode_t profile_flush_file_data_to_file(prf_data_t data, const char *outfile)
void profile_dereference_data(prf_data_t data)
{
int err;
- scan_shared_trees_unlocked();
err = k5_mutex_lock(&g_shared_trees_mutex);
if (err)
return;
profile_dereference_data_locked(data);
(void) k5_mutex_unlock(&g_shared_trees_mutex);
- scan_shared_trees_unlocked();
}
void profile_dereference_data_locked(prf_data_t data)
{
+ scan_shared_trees_locked();
data->refcount--;
if (data->refcount == 0)
profile_free_file_data(data);
+ scan_shared_trees_locked();
}
int profile_lock_global()
diff --git a/usr/src/lib/gss_mechs/mech_krb5/profile/prof_get.c b/usr/src/lib/gss_mechs/mech_krb5/profile/prof_get.c
index fdf4470087..08fac7f06f 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/profile/prof_get.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/profile/prof_get.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* prof_get.c --- routines that expose the public interfaces for
* querying items from the profile.
@@ -40,7 +39,7 @@ static errcode_t init_list(struct profile_string_list *list)
{
list->num = 0;
list->max = 10;
- list->list = (char **) malloc(list->max * sizeof(char *));
+ list->list = malloc(list->max * sizeof(char *));
if (list->list == 0)
return ENOMEM;
list->list[0] = 0;
@@ -80,13 +79,13 @@ static errcode_t add_to_list(struct profile_string_list *list, const char *str)
if (list->num+1 >= list->max) {
newmax = list->max + 10;
- newlist = (char **) realloc(list->list, newmax * sizeof(char *));
+ newlist = realloc(list->list, newmax * sizeof(char *));
if (newlist == 0)
return ENOMEM;
list->max = newmax;
list->list = newlist;
}
- newstr = (char *) malloc(strlen(str)+1);
+ newstr = malloc(strlen(str)+1);
if (newstr == 0)
return ENOMEM;
strcpy(newstr, str);
@@ -162,7 +161,7 @@ profile_get_values(profile_t profile, const char *const *names,
return 0;
cleanup:
- end_list(&values, (char ***)NULL);
+ end_list(&values, 0);
return retval;
}
@@ -218,7 +217,7 @@ profile_get_string(profile_t profile, const char *name, const char *subname,
value = def_val;
if (value) {
- *ret_string = (char *) malloc(strlen(value)+1);
+ *ret_string = malloc(strlen(value)+1);
if (*ret_string == 0)
return ENOMEM;
strcpy(*ret_string, value);
@@ -367,7 +366,7 @@ profile_get_subsection_names(profile_t profile, const char **names,
return 0;
cleanup:
- end_list(&values, (char ***)NULL);
+ end_list(&values, 0);
return retval;
}
@@ -403,7 +402,7 @@ profile_get_relation_names(profile_t profile, const char **names,
return 0;
cleanup:
- end_list(&values, (char ***)NULL);
+ end_list(&values, 0);
return retval;
}
@@ -432,7 +431,7 @@ profile_iterator(void **iter_p, char **ret_name, char **ret_value)
if (ret_name) {
if (name) {
- *ret_name = (char *) malloc(strlen(name)+1);
+ *ret_name = malloc(strlen(name)+1);
if (!*ret_name)
return ENOMEM;
strcpy(*ret_name, name);
@@ -441,7 +440,7 @@ profile_iterator(void **iter_p, char **ret_name, char **ret_value)
}
if (ret_value) {
if (value) {
- *ret_value = (char *) malloc(strlen(value)+1);
+ *ret_value = malloc(strlen(value)+1);
if (!*ret_value) {
if (ret_name) {
free(*ret_name);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/profile/prof_init.c b/usr/src/lib/gss_mechs/mech_krb5/profile/prof_init.c
index 2ee24b3aa9..3cb35924ce 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/profile/prof_init.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/profile/prof_init.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* prof_init.c --- routines that manipulate the user-visible profile_t
@@ -19,16 +18,13 @@
#endif
#include <errno.h>
-/* Find a 4-byte integer type */
-#if (SIZEOF_SHORT == 4)
-typedef short prof_int32;
-#elif (SIZEOF_INT == 4)
-typedef int prof_int32;
-#elif (SIZEOF_LONG == 4)
-typedef long prof_int32;
-#else /* SIZEOF_LONG == 4 */
-error(do not have a 4-byte integer type)
-#endif /* SIZEOF_LONG == 4 */
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+typedef int32_t prof_int32;
errcode_t KRB5_CALLCONV
profile_init(const_profile_filespec_t *files, profile_t *ret_profile)
@@ -76,6 +72,39 @@ profile_init(const_profile_filespec_t *files, profile_t *ret_profile)
return 0;
}
+#define COUNT_LINKED_LIST(COUNT, PTYPE, START, FIELD) \
+ { \
+ int cll_counter = 0; \
+ PTYPE cll_ptr = (START); \
+ while (cll_ptr != NULL) { \
+ cll_counter++; \
+ cll_ptr = cll_ptr->FIELD; \
+ } \
+ (COUNT) = cll_counter; \
+ }
+
+errcode_t KRB5_CALLCONV
+profile_copy(profile_t old_profile, profile_t *new_profile)
+{
+ size_t size, i;
+ const_profile_filespec_t *files;
+ prf_file_t file;
+ errcode_t err;
+
+ /* The fields we care about are read-only after creation, so
+ no locking is needed. */
+ COUNT_LINKED_LIST (size, prf_file_t, old_profile->first_file, next);
+ files = malloc ((size+1) * sizeof(*files));
+ if (files == NULL)
+ return errno;
+ for (i = 0, file = old_profile->first_file; i < size; i++, file = file->next)
+ files[i] = file->data->filespec;
+ files[size] = NULL;
+ err = profile_init (files, new_profile);
+ free (files);
+ return err;
+}
+
errcode_t KRB5_CALLCONV
profile_init_path(const_profile_filespec_list_t filepath,
profile_t *ret_profile)
@@ -98,6 +127,7 @@ profile_init_path(const_profile_filespec_list_t filepath,
return ENOMEM;
/* measure, copy, and skip each one */
+ /* Solaris Kerberos */
for(s = filepath, i=0; ((t = strchr(s, ':')) != NULL) ||
((t=s+strlen(s)) != NULL); s=t+1, i++) {
ent_len = t-s;
@@ -131,31 +161,31 @@ profile_init_path(const_profile_filespec_list_t filepath,
errcode_t KRB5_CALLCONV
profile_is_writable(profile_t profile, int *writable)
{
- if (!profile || profile->magic != PROF_MAGIC_PROFILE)
- return PROF_MAGIC_PROFILE;
-
- if (!writable)
- return EINVAL;
-
- if (profile->first_file)
- *writable = (profile->first_file->data->flags & PROFILE_FILE_RW);
-
- return 0;
+ if (!profile || profile->magic != PROF_MAGIC_PROFILE)
+ return PROF_MAGIC_PROFILE;
+
+ if (!writable)
+ return EINVAL;
+
+ if (profile->first_file)
+ *writable = (profile->first_file->data->flags & PROFILE_FILE_RW);
+
+ return 0;
}
errcode_t KRB5_CALLCONV
profile_is_modified(profile_t profile, int *modified)
{
- if (!profile || profile->magic != PROF_MAGIC_PROFILE)
- return PROF_MAGIC_PROFILE;
-
- if (!modified)
- return EINVAL;
-
- if (profile->first_file)
- *modified = (profile->first_file->data->flags & PROFILE_FILE_DIRTY);
-
- return 0;
+ if (!profile || profile->magic != PROF_MAGIC_PROFILE)
+ return PROF_MAGIC_PROFILE;
+
+ if (!modified)
+ return EINVAL;
+
+ if (profile->first_file)
+ *modified = (profile->first_file->data->flags & PROFILE_FILE_DIRTY);
+
+ return 0;
}
errcode_t KRB5_CALLCONV
@@ -277,7 +307,7 @@ errcode_t profile_ser_externalize(const char *unused, profile_t profile,
fcount = 0;
for (pfp = profile->first_file; pfp; pfp = pfp->next)
fcount++;
- pack_int32((prof_int32)PROF_MAGIC_PROFILE, &bp, &remain);
+ pack_int32(PROF_MAGIC_PROFILE, &bp, &remain);
pack_int32(fcount, &bp, &remain);
for (pfp = profile->first_file; pfp; pfp = pfp->next) {
slen = (prof_int32) strlen(pfp->data->filespec);
@@ -288,7 +318,7 @@ errcode_t profile_ser_externalize(const char *unused, profile_t profile,
remain -= (size_t) slen;
}
}
- pack_int32((prof_int32)PROF_MAGIC_PROFILE, &bp, &remain);
+ pack_int32(PROF_MAGIC_PROFILE, &bp, &remain);
retval = 0;
*bufpp = bp;
*remainp = remain;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/profile/prof_int.h b/usr/src/lib/gss_mechs/mech_krb5/profile/prof_int.h
index 26721834d5..eed3c8533e 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/profile/prof_int.h
+++ b/usr/src/lib/gss_mechs/mech_krb5/profile/prof_int.h
@@ -1,14 +1,14 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* prof-int.h
*/
+/* Solaris Kerberos */
#ifndef __PROF_INT_H
#include <time.h>
@@ -19,20 +19,10 @@
#define PROFILE_SUPPORTS_FOREIGN_NEWLINES
#endif
-#include <k5-thread.h>
-#include <com_err.h>
-#include <profile.h>
-#include "prof_err.h" /* SUNW14resync */
-#include "osconf.h" /* SUNW14resync */
-
-
-#define STAT_ONCE_PER_SECOND
-
-#if defined(_WIN32)
-#define SIZEOF_INT 4
-#define SIZEOF_SHORT 2
-#define SIZEOF_LONG 4
-#endif
+#include "k5-thread.h"
+#include "k5-platform.h"
+#include "com_err.h"
+#include "profile.h"
typedef long prf_magic_t;
@@ -41,28 +31,41 @@ typedef long prf_magic_t;
* particular configuration file.
*
* Locking strategy:
- * - filespec is fixed after creation
+ * - filespec, fslen are fixed after creation
* - refcount and next should only be tweaked with the global lock held
* - other fields can be tweaked after grabbing the in-struct lock
*/
struct _prf_data_t {
prf_magic_t magic;
k5_mutex_t lock;
- char *comment;
struct profile_node *root;
-#ifdef STAT_ONCE_PER_SECOND
time_t last_stat;
-#endif
time_t timestamp; /* time tree was last updated from file */
+ unsigned long frac_ts; /* fractional part of timestamp, if any */
int flags; /* r/w, dirty */
int upd_serial; /* incremented when data changes */
+ char *comment;
+
+ size_t fslen;
+
+ /* Some separation between fields controlled by different
+ mutexes. Theoretically, both could be accessed at the same
+ time from different threads on different CPUs with separate
+ caches. Don't let the threads clobber each other's
+ changes. One mutex controlling the whole thing would be
+ better, but sufficient separation might suffice.
+
+ This is icky. I just hope it's adequate.
+
+ For next major release, fix this. */
+ union { double d; void *p; UINT64_TYPE ll; k5_mutex_t m; } pad;
+
int refcount; /* prf_file_t references */
struct _prf_data_t *next;
/* Was: "profile_filespec_t filespec". Now: flexible char
array ... except, we need to work in C89, so an array
length must be specified. */
- size_t fslen;
- const char filespec[sizeof(DEFAULT_SECURE_PROFILE_PATH)];
+ const char filespec[sizeof("/etc/krb5.conf")];
};
typedef struct _prf_data_t *prf_data_t;
@@ -210,6 +213,8 @@ errcode_t profile_rename_node
/* prof_file.c */
+errcode_t KRB5_CALLCONV profile_copy (profile_t, profile_t *);
+
errcode_t profile_open_file
(const_profile_filespec_t file, prf_file_t *ret_prof);
@@ -259,5 +264,6 @@ errcode_t profile_get_value
/* prof_set.c -- included from profile.h */
+/* Solaris Kerberos */
#define __PROF_INT_H
#endif
diff --git a/usr/src/lib/gss_mechs/mech_krb5/profile/prof_parse.c b/usr/src/lib/gss_mechs/mech_krb5/profile/prof_parse.c
index 33dd13b2c0..4200bc5098 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/profile/prof_parse.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/profile/prof_parse.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include "prof_int.h"
@@ -91,10 +90,10 @@ static errcode_t parse_std_line(char *line, struct parse_state *state)
if (*line == 0)
return 0;
- if (line[0] == ';' || line[0] == '#')
- return 0;
- strip_line(line);
cp = skip_over_blanks(line);
+ if (cp[0] == ';' || cp[0] == '#')
+ return 0;
+ strip_line(cp);
ch = *cp;
if (ch == 0)
return 0;
@@ -122,7 +121,6 @@ static errcode_t parse_std_line(char *line, struct parse_state *state)
* Finish off the rest of the line.
*/
cp = p+1;
-
if (*cp == '*') {
profile_make_node_final(state->current_section);
cp++;
@@ -182,9 +180,6 @@ static errcode_t parse_std_line(char *line, struct parse_state *state)
} else if (value[0] == '{' && *(skip_over_blanks(value+1)) == 0)
do_subsection++;
else {
- /*
- * Skip over trailing whitespace characters
- */
cp = value + strlen(value) - 1;
while ((cp > value) && isspace((int) (*cp)))
*cp-- = 0;
@@ -240,7 +235,7 @@ errcode_t profile_parse_file(FILE *f, struct profile_node **root)
errcode_t retval;
struct parse_state state;
- bptr = (char *) malloc (BUF_SIZE);
+ bptr = malloc (BUF_SIZE);
if (!bptr)
return ENOMEM;
@@ -255,7 +250,7 @@ errcode_t profile_parse_file(FILE *f, struct profile_node **root)
#ifndef PROFILE_SUPPORTS_FOREIGN_NEWLINES
retval = parse_line(bptr, &state);
if (retval) {
- /* check if an unconfigured file */
+ /* Solaris Kerberos: check if an unconfigured file */
if (strstr(bptr, "___"))
retval = PROF_NO_PROFILE;
free (bptr);
@@ -322,8 +317,10 @@ errcode_t profile_parse_file(FILE *f, struct profile_node **root)
*/
static int need_double_quotes(char *str)
{
- if (!str || !*str)
- return 0;
+ if (!str)
+ return 0;
+ if (str[0] == '\0')
+ return 1;
if (isspace((int) (*str)) ||isspace((int) (*(str + strlen(str) - 1))))
return 1;
if (strchr(str, '\n') || strchr(str, '\t') || strchr(str, '\b'))
diff --git a/usr/src/lib/gss_mechs/mech_krb5/profile/prof_tree.c b/usr/src/lib/gss_mechs/mech_krb5/profile/prof_tree.c
index 398a979d89..f0ff7f56e1 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/profile/prof_tree.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/profile/prof_tree.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* prof_tree.c --- these routines maintain the parse tree of the
@@ -95,17 +94,17 @@ errcode_t profile_create_node(const char *name, const char *value,
{
struct profile_node *new;
- new = (struct profile_node *)malloc(sizeof(struct profile_node));
+ new = malloc(sizeof(struct profile_node));
if (!new)
return ENOMEM;
memset(new, 0, sizeof(struct profile_node));
- new->name = (char *) strdup(name);
+ new->name = strdup(name);
if (new->name == 0) {
profile_free_node(new);
return ENOMEM;
}
if (value) {
- new->value = (char *) strdup(value);
+ new->value = strdup(value);
if (new->value == 0) {
profile_free_node(new);
return ENOMEM;
@@ -360,6 +359,7 @@ errcode_t profile_find_node_subsection(struct profile_node *section,
struct profile_node *p;
errcode_t retval;
+ /* Solaris Kerberos */
if (section == (struct profile_node *)NULL)
return (PROF_NO_PROFILE);
@@ -422,8 +422,7 @@ errcode_t profile_node_iterator_create(profile_t profile,
done_idx = 1;
}
- if ((iter = (struct profile_iterator *)
- malloc(sizeof(struct profile_iterator))) == NULL)
+ if ((iter = malloc(sizeof(struct profile_iterator))) == NULL)
return ENOMEM;
iter->magic = PROF_MAGIC_ITERATOR;
@@ -538,6 +537,7 @@ get_new_file:
* or find the containing section if not.
*/
section = iter->file->data->root;
+ assert(section != NULL);
for (cpp = iter->names; cpp[iter->done_idx]; cpp++) {
for (p=section->first_child; p; p = p->next) {
if (!strcmp(p->name, *cpp) && !p->value)
@@ -584,6 +584,8 @@ get_new_file:
skip_num--;
continue;
}
+ if (p->deleted)
+ continue;
break;
}
iter->num++;
@@ -645,7 +647,7 @@ errcode_t profile_set_relation_value(struct profile_node *node,
if (!node->value)
return PROF_SET_SECTION_VALUE;
- cp = (char *) malloc(strlen(new_value)+1);
+ cp = malloc(strlen(new_value)+1);
if (!cp)
return ENOMEM;
@@ -674,7 +676,7 @@ errcode_t profile_rename_node(struct profile_node *node, const char *new_name)
/*
* Make sure we can allocate memory for the new name, first!
*/
- new_string = (char *) malloc(strlen(new_name)+1);
+ new_string = malloc(strlen(new_name)+1);
if (!new_string)
return ENOMEM;
strcpy(new_string, new_name);
diff --git a/usr/src/lib/gss_mechs/mech_krb5/support/fake-addrinfo.c b/usr/src/lib/gss_mechs/mech_krb5/support/fake-addrinfo.c
index d768762dfc..3254189832 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/support/fake-addrinfo.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/support/fake-addrinfo.c
@@ -1,7 +1,5 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
- * Copyright (C) 2004 by the Massachusetts Institute of Technology,
+ * Copyright (C) 2001,2002,2003,2004,2005,2006 by the Massachusetts Institute of Technology,
* Cambridge, MA, USA. All Rights Reserved.
*
* This software is being provided to you, the LICENSEE, by the
@@ -41,24 +39,1283 @@
* fashion that it might be confused with the original M.I.T. software.
*/
-#include <fake-addrinfo.h>
-#include <k5-thread.h>
+/* Approach overview:
+
+ If a system version is available but buggy, save handles to it,
+ redefine the names to refer to static functions defined here, and
+ in those functions, call the system versions and fix up the
+ returned data. Use the native data structures and flag values.
+
+ If no system version exists, use gethostby* and fake it. Define
+ the data structures and flag values locally.
+
+
+ On Mac OS X, getaddrinfo results aren't cached (though
+ gethostbyname results are), so we need to build a cache here. Now
+ things are getting really messy. Because the cache is in use, we
+ use getservbyname, and throw away thread safety. (Not that the
+ cache is thread safe, but when we get locking support, that'll be
+ dealt with.) This code needs tearing down and rebuilding, soon.
+
+
+ Note that recent Windows developers' code has an interesting hack:
+ When you include the right header files, with the right set of
+ macros indicating system versions, you'll get an inline function
+ that looks for getaddrinfo (or whatever) in the system library, and
+ calls it if it's there. If it's not there, it fakes it with
+ gethostby* calls.
+
+ We're taking a simpler approach: A system provides these routines or
+ it does not.
+
+ Someday, we may want to take into account different versions (say,
+ different revs of GNU libc) where some are broken in one way, and
+ some work or are broken in another way. Cross that bridge when we
+ come to it. */
+
+/* To do, maybe:
+
+ + For AIX 4.3.3, using the RFC 2133 definition: Implement
+ AI_NUMERICHOST. It's not defined in the header file.
+
+ For certain (old?) versions of GNU libc, AI_NUMERICHOST is
+ defined but not implemented.
+
+ + Use gethostbyname2, inet_aton and other IPv6 or thread-safe
+ functions if available. But, see
+ http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=135182 for one
+ gethostbyname2 problem on Linux. And besides, if a platform is
+ supporting IPv6 at all, they really should be doing getaddrinfo
+ by now.
+
+ + inet_ntop, inet_pton
+
+ + Conditionally export/import the function definitions, so a
+ library can have a single copy instead of multiple.
+
+ + Upgrade host requirements to include working implementations of
+ these functions, and throw all this away. Pleeease? :-) */
+
+#include "port-sockets.h"
+#include "socket-utils.h"
+#include "k5-platform.h"
+#include "k5-thread.h"
+#include "supp-int.h"
+
+#include <stdio.h> /* for sprintf */
+#include <errno.h>
+
+#define IMPLEMENT_FAKE_GETADDRINFO
+#include "fake-addrinfo.h"
+
+#ifdef S_SPLINT_S
+/*@-incondefs@*/
+extern int
+getaddrinfo (/*@in@*/ /*@null@*/ const char *,
+ /*@in@*/ /*@null@*/ const char *,
+ /*@in@*/ /*@null@*/ const struct addrinfo *,
+ /*@out@*/ struct addrinfo **)
+ ;
+extern void
+freeaddrinfo (/*@only@*/ /*@out@*/ struct addrinfo *)
+ ;
+extern int
+getnameinfo (const struct sockaddr *addr, socklen_t addrsz,
+ /*@out@*/ /*@null@*/ char *h, socklen_t hsz,
+ /*@out@*/ /*@null@*/ char *s, socklen_t ssz,
+ int flags)
+ /*@requires (maxSet(h)+1) >= hsz /\ (maxSet(s)+1) >= ssz @*/
+ /* too hard: maxRead(addr) >= (addrsz-1) */
+ /*@modifies *h, *s@*/;
+extern /*@dependent@*/ char *gai_strerror (int code) /*@*/;
+/*@=incondefs@*/
+#endif
+
+
+#include "cache-addrinfo.h"
+
+#if (defined (__linux__) && defined(HAVE_GETADDRINFO)) || defined (_AIX)
+/* See comments below. */
+# define WRAP_GETADDRINFO
+#endif
+
+#if defined (__linux__) && defined(HAVE_GETADDRINFO)
+# define COPY_FIRST_CANONNAME
+#endif
-/* Allocate the storage here. */
-struct fac krb5int_fac = { K5_MUTEX_PARTIAL_INITIALIZER, 0 };
+#ifdef _AIX
+# define NUMERIC_SERVICE_BROKEN
+# define COPY_FIRST_CANONNAME
+#endif
-int krb5int_init_fac (void)
+
+#ifdef COPY_FIRST_CANONNAME
+# include <string.h>
+#endif
+
+#ifdef NUMERIC_SERVICE_BROKEN
+# include <ctype.h> /* isdigit */
+# include <stdlib.h> /* strtoul */
+#endif
+
+
+/* Do we actually have *any* systems we care about that don't provide
+ either getaddrinfo or one of these two flavors of
+ gethostbyname_r? */
+#if !defined(HAVE_GETHOSTBYNAME_R) || defined(THREADSAFE_GETHOSTBYNAME)
+typedef struct hostent *GET_HOST_TMP;
+#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
+ { TMP = gethostbyname (NAME); (ERR) = h_errno; (HP) = TMP; }
+#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
+ { TMP = gethostbyaddr ((ADDR), (ADDRLEN), (FAMILY)); (ERR) = h_errno; (HP) = TMP; }
+#else
+#ifdef _AIX /* XXX should have a feature test! */
+typedef struct {
+ struct hostent ent;
+ struct hostent_data data;
+} GET_HOST_TMP;
+#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
+ { \
+ (HP) = (gethostbyname_r((NAME), &TMP.ent, &TMP.data) \
+ ? 0 \
+ : &TMP.ent); \
+ (ERR) = h_errno; \
+ }
+/*
+#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR) \
+ { \
+ struct hostent my_h_ent; \
+ struct hostent_data my_h_ent_data; \
+ (HP) = (gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &my_h_ent, \
+ &my_h_ent_data) \
+ ? 0 \
+ : &my_h_ent); \
+ (ERR) = my_h_err; \
+ }
+*/
+#else
+#ifdef GETHOSTBYNAME_R_RETURNS_INT
+typedef struct {
+ struct hostent ent;
+ char buf[8192];
+} GET_HOST_TMP;
+#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
+ { \
+ struct hostent *my_hp = NULL; \
+ int my_h_err, my_ret; \
+ my_ret = gethostbyname_r((NAME), &TMP.ent, \
+ TMP.buf, sizeof (TMP.buf), &my_hp, \
+ &my_h_err); \
+ (HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
+ ? 0 \
+ : &TMP.ent); \
+ (ERR) = my_h_err; \
+ }
+#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
+ { \
+ struct hostent *my_hp; \
+ int my_h_err, my_ret; \
+ my_ret = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
+ TMP.buf, sizeof (TMP.buf), &my_hp, \
+ &my_h_err); \
+ (HP) = (((my_ret != 0) || (my_hp != &TMP.ent)) \
+ ? 0 \
+ : &TMP.ent); \
+ (ERR) = my_h_err; \
+ }
+#else
+typedef struct {
+ struct hostent ent;
+ char buf[8192];
+} GET_HOST_TMP;
+#define GET_HOST_BY_NAME(NAME, HP, ERR, TMP) \
+ { \
+ int my_h_err; \
+ (HP) = gethostbyname_r((NAME), &TMP.ent, \
+ TMP.buf, sizeof (TMP.buf), &my_h_err); \
+ (ERR) = my_h_err; \
+ }
+#define GET_HOST_BY_ADDR(ADDR, ADDRLEN, FAMILY, HP, ERR, TMP) \
+ { \
+ int my_h_err; \
+ (HP) = gethostbyaddr_r((ADDR), (ADDRLEN), (FAMILY), &TMP.ent, \
+ TMP.buf, sizeof (TMP.buf), &my_h_err); \
+ (ERR) = my_h_err; \
+ }
+#endif /* returns int? */
+#endif /* _AIX */
+#endif
+
+/* Now do the same for getservby* functions. */
+#ifndef HAVE_GETSERVBYNAME_R
+typedef struct servent *GET_SERV_TMP;
+#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
+ (TMP = getservbyname (NAME, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1)
+#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
+ (TMP = getservbyport (PORT, PROTO), (SP) = TMP, (ERR) = (SP) ? 0 : -1)
+#else
+#ifdef GETSERVBYNAME_R_RETURNS_INT
+typedef struct {
+ struct servent ent;
+ char buf[8192];
+} GET_SERV_TMP;
+#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
+ { \
+ struct servent *my_sp; \
+ int my_s_err; \
+ (SP) = (getservbyname_r((NAME), (PROTO), &TMP.ent, \
+ TMP.buf, sizeof (TMP.buf), &my_sp, \
+ &my_s_err) \
+ ? 0 \
+ : &TMP.ent); \
+ (ERR) = my_s_err; \
+ }
+#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
+ { \
+ struct servent *my_sp; \
+ int my_s_err; \
+ (SP) = (getservbyport_r((PORT), (PROTO), &TMP.ent, \
+ TMP.buf, sizeof (TMP.buf), &my_sp, \
+ &my_s_err) \
+ ? 0 \
+ : &TMP.ent); \
+ (ERR) = my_s_err; \
+ }
+#else
+/* returns ptr -- IRIX? */
+typedef struct {
+ struct servent ent;
+ char buf[8192];
+} GET_SERV_TMP;
+#define GET_SERV_BY_NAME(NAME, PROTO, SP, ERR, TMP) \
+ { \
+ (SP) = getservbyname_r((NAME), (PROTO), &TMP.ent, \
+ TMP.buf, sizeof (TMP.buf)); \
+ (ERR) = (SP) == NULL; \
+ }
+
+#define GET_SERV_BY_PORT(PORT, PROTO, SP, ERR, TMP) \
+ { \
+ struct servent *my_sp; \
+ my_sp = getservbyport_r((PORT), (PROTO), &TMP.ent, \
+ TMP.buf, sizeof (TMP.buf)); \
+ (SP) = my_sp; \
+ (ERR) = my_sp == 0; \
+ (ERR) = (ERR); /* avoid "unused" warning */ \
+ }
+#endif
+#endif
+
+#if defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
+static inline int
+system_getaddrinfo (const char *name, const char *serv,
+ const struct addrinfo *hint,
+ struct addrinfo **res)
{
- return k5_mutex_finish_init(&krb5int_fac.lock);
+ return getaddrinfo(name, serv, hint, res);
}
-void krb5int_fini_fac (void)
+static inline void
+system_freeaddrinfo (struct addrinfo *ai)
{
- k5_mutex_destroy(&krb5int_fac.lock);
+ freeaddrinfo(ai);
}
-extern int krb5int_call_thread_support_init(void);
-int krb5int_lock_fac (void)
+/* Note: Implementations written to RFC 2133 use size_t, while RFC
+ 2553 implementations use socklen_t, for the second parameter.
+
+ Mac OS X (10.2) and AIX 4.3.3 appear to be in the RFC 2133 camp,
+ but we don't have an autoconf test for that right now. */
+static inline int
+system_getnameinfo (const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen, char *serv, size_t servlen,
+ int flags)
+{
+ return getnameinfo(sa, salen, host, hostlen, serv, servlen, flags);
+}
+#endif
+
+#if !defined (HAVE_GETADDRINFO) || defined(WRAP_GETADDRINFO) || defined(FAI_CACHE)
+
+#undef getaddrinfo
+#define getaddrinfo my_fake_getaddrinfo
+#undef freeaddrinfo
+#define freeaddrinfo my_fake_freeaddrinfo
+
+#endif
+
+#if !defined (HAVE_GETADDRINFO)
+
+#undef gai_strerror
+#define gai_strerror my_fake_gai_strerror
+
+#endif /* ! HAVE_GETADDRINFO */
+
+#if (!defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)) && defined(DEBUG_ADDRINFO)
+/* Some debug routines. */
+
+static const char *protoname (int p, char *buf) {
+#define X(N) if (p == IPPROTO_ ## N) return #N
+
+ X(TCP);
+ X(UDP);
+ X(ICMP);
+ X(IPV6);
+#ifdef IPPROTO_GRE
+ X(GRE);
+#endif
+ X(NONE);
+ X(RAW);
+#ifdef IPPROTO_COMP
+ X(COMP);
+#endif
+#ifdef IPPROTO_IGMP
+ X(IGMP);
+#endif
+
+ sprintf(buf, " %-2d", p);
+ return buf;
+}
+
+static const char *socktypename (int t, char *buf) {
+ switch (t) {
+ case SOCK_DGRAM: return "DGRAM";
+ case SOCK_STREAM: return "STREAM";
+ case SOCK_RAW: return "RAW";
+ case SOCK_RDM: return "RDM";
+ case SOCK_SEQPACKET: return "SEQPACKET";
+ }
+ sprintf(buf, " %-2d", t);
+ return buf;
+}
+
+static const char *familyname (int f, char *buf) {
+ switch (f) {
+ default:
+ sprintf(buf, "AF %d", f);
+ return buf;
+ case AF_INET: return "AF_INET";
+ case AF_INET6: return "AF_INET6";
+#ifdef AF_UNIX
+ case AF_UNIX: return "AF_UNIX";
+#endif
+ }
+}
+
+static void debug_dump_getaddrinfo_args (const char *name, const char *serv,
+ const struct addrinfo *hint)
+{
+ const char *sep;
+ fprintf(stderr,
+ "getaddrinfo(hostname %s, service %s,\n"
+ " hints { ",
+ name ? name : "(null)", serv ? serv : "(null)");
+ if (hint) {
+ char buf[30];
+ sep = "";
+#define Z(FLAG) if (hint->ai_flags & AI_##FLAG) fprintf(stderr, "%s%s", sep, #FLAG), sep = "|"
+ Z(CANONNAME);
+ Z(PASSIVE);
+#ifdef AI_NUMERICHOST
+ Z(NUMERICHOST);
+#endif
+ if (sep[0] == 0)
+ fprintf(stderr, "no-flags");
+ if (hint->ai_family)
+ fprintf(stderr, " %s", familyname(hint->ai_family, buf));
+ if (hint->ai_socktype)
+ fprintf(stderr, " SOCK_%s", socktypename(hint->ai_socktype, buf));
+ if (hint->ai_protocol)
+ fprintf(stderr, " IPPROTO_%s", protoname(hint->ai_protocol, buf));
+ } else
+ fprintf(stderr, "(null)");
+ fprintf(stderr, " }):\n");
+}
+
+static void debug_dump_error (int err)
+{
+ fprintf(stderr, "error %d: %s\n", err, gai_strerror(err));
+}
+
+static void debug_dump_addrinfos (const struct addrinfo *ai)
+{
+ int count = 0;
+ char buf[10];
+ fprintf(stderr, "addrinfos returned:\n");
+ while (ai) {
+ fprintf(stderr, "%p...", ai);
+ fprintf(stderr, " socktype=%s", socktypename(ai->ai_socktype, buf));
+ fprintf(stderr, " ai_family=%s", familyname(ai->ai_family, buf));
+ if (ai->ai_family != ai->ai_addr->sa_family)
+ fprintf(stderr, " sa_family=%s",
+ familyname(ai->ai_addr->sa_family, buf));
+ fprintf(stderr, "\n");
+ ai = ai->ai_next;
+ count++;
+ }
+ fprintf(stderr, "end addrinfos returned (%d)\n");
+}
+
+#endif
+
+#if !defined (HAVE_GETADDRINFO) || defined (WRAP_GETADDRINFO)
+
+static
+int getaddrinfo (const char *name, const char *serv,
+ const struct addrinfo *hint, struct addrinfo **result);
+
+static
+void freeaddrinfo (struct addrinfo *ai);
+
+#endif
+
+#if !defined (HAVE_GETADDRINFO)
+
+#define HAVE_FAKE_GETADDRINFO /* was not originally HAVE_GETADDRINFO */
+#define HAVE_GETADDRINFO
+#define NEED_FAKE_GETNAMEINFO
+#undef HAVE_GETNAMEINFO
+#define HAVE_GETNAMEINFO 1
+
+#undef getnameinfo
+#define getnameinfo my_fake_getnameinfo
+
+static
+char *gai_strerror (int code);
+
+#endif
+
+#if !defined (HAVE_GETADDRINFO)
+static
+int getnameinfo (const struct sockaddr *addr, socklen_t len,
+ char *host, socklen_t hostlen,
+ char *service, socklen_t servicelen,
+ int flags);
+#endif
+
+/* Fudge things on older gai implementations. */
+/* AIX 4.3.3 is based on RFC 2133; no AI_NUMERICHOST. */
+#ifndef AI_NUMERICHOST
+# define AI_NUMERICHOST 0
+#endif
+/* Partial RFC 2553 implementations may not have AI_ADDRCONFIG and
+ friends, which RFC 3493 says are now part of the getaddrinfo
+ interface, and we'll want to use. */
+#ifndef AI_ADDRCONFIG
+# define AI_ADDRCONFIG 0
+#endif
+#ifndef AI_V4MAPPED
+# define AI_V4MAPPED 0
+#endif
+#ifndef AI_ALL
+# define AI_ALL 0
+#endif
+#ifndef AI_DEFAULT
+# define AI_DEFAULT (AI_ADDRCONFIG|AI_V4MAPPED)
+#endif
+
+#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
+#define NEED_FAKE_GETADDRINFO
+#endif
+
+#if defined(NEED_FAKE_GETADDRINFO) || defined(WRAP_GETADDRINFO)
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_FAKE_GETADDRINFO
+#include <string.h> /* for strspn */
+
+static inline int translate_h_errno (int h);
+
+static inline int fai_add_entry (struct addrinfo **result, void *addr,
+ int port, const struct addrinfo *template)
+{
+ struct addrinfo *n = malloc (sizeof (struct addrinfo));
+ if (n == 0)
+ return EAI_MEMORY;
+ if (template->ai_family != AF_INET
+#ifdef KRB5_USE_INET6
+ && template->ai_family != AF_INET6
+#endif
+ )
+ return EAI_FAMILY;
+ *n = *template;
+ if (template->ai_family == AF_INET) {
+ struct sockaddr_in *sin4;
+ sin4 = malloc (sizeof (struct sockaddr_in));
+ if (sin4 == 0)
+ return EAI_MEMORY;
+ memset (sin4, 0, sizeof (struct sockaddr_in)); /* for sin_zero */
+ n->ai_addr = (struct sockaddr *) sin4;
+ sin4->sin_family = AF_INET;
+ sin4->sin_addr = *(struct in_addr *)addr;
+ sin4->sin_port = port;
+#ifdef HAVE_SA_LEN
+ sin4->sin_len = sizeof (struct sockaddr_in);
+#endif
+ }
+#ifdef KRB5_USE_INET6
+ if (template->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sin6;
+ sin6 = malloc (sizeof (struct sockaddr_in6));
+ if (sin6 == 0)
+ return EAI_MEMORY;
+ memset (sin6, 0, sizeof (struct sockaddr_in6)); /* for sin_zero */
+ n->ai_addr = (struct sockaddr *) sin6;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_addr = *(struct in6_addr *)addr;
+ sin6->sin6_port = port;
+#ifdef HAVE_SA_LEN
+ sin6->sin6_len = sizeof (struct sockaddr_in6);
+#endif
+ }
+#endif
+ n->ai_next = *result;
+ *result = n;
+ return 0;
+}
+
+#ifdef FAI_CACHE
+/* fake addrinfo cache entries */
+#define CACHE_ENTRY_LIFETIME 15 /* seconds */
+
+static void plant_face (const char *name, struct face *entry)
+{
+ entry->name = strdup(name);
+ if (entry->name == NULL)
+ /* @@ Wastes memory. */
+ return;
+ k5_mutex_assert_locked(&krb5int_fac.lock);
+ entry->next = krb5int_fac.data;
+ entry->expiration = time(0) + CACHE_ENTRY_LIFETIME;
+ krb5int_fac.data = entry;
+#ifdef DEBUG_ADDRINFO
+ printf("added cache entry '%s' at %p: %d ipv4, %d ipv6; expire %d\n",
+ name, entry, entry->naddrs4, entry->naddrs6, entry->expiration);
+#endif
+}
+
+static int find_face (const char *name, struct face **entry)
+{
+ struct face *fp, **fpp;
+ time_t now = time(0);
+
+ /* First, scan for expired entries and free them.
+ (Future improvement: Integrate these two loops.) */
+#ifdef DEBUG_ADDRINFO
+ printf("scanning cache at %d for '%s'...\n", now, name);
+#endif
+ k5_mutex_assert_locked(&krb5int_fac.lock);
+ for (fpp = &krb5int_fac.data; *fpp; ) {
+ fp = *fpp;
+#ifdef DEBUG_ADDRINFO
+ printf(" checking expiration time of @%p: %d\n",
+ fp, fp->expiration);
+#endif
+ if (fp->expiration < now) {
+#ifdef DEBUG_ADDRINFO
+ printf("\texpiring cache entry\n");
+#endif
+ free(fp->name);
+ free(fp->canonname);
+ free(fp->addrs4);
+ free(fp->addrs6);
+ *fpp = fp->next;
+ free(fp);
+ /* Stay at this point in the list, and check again. */
+ } else
+ /* Move forward. */
+ fpp = &(*fpp)->next;
+ }
+
+ for (fp = krb5int_fac.data; fp; fp = fp->next) {
+#ifdef DEBUG_ADDRINFO
+ printf(" comparing entry @%p\n", fp);
+#endif
+ if (!strcasecmp(fp->name, name)) {
+#ifdef DEBUG_ADDRINFO
+ printf("\tMATCH!\n");
+#endif
+ *entry = fp;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#endif
+
+static int krb5int_lock_fac(void), krb5int_unlock_fac(void);
+
+static inline int fai_add_hosts_by_name (const char *name,
+ struct addrinfo *template,
+ int portnum, int flags,
+ struct addrinfo **result)
+{
+#ifdef FAI_CACHE
+
+ struct face *ce;
+ int i, r, err;
+
+ err = krb5int_lock_fac();
+ if (err) {
+ errno = err;
+ return EAI_SYSTEM;
+ }
+ if (!find_face(name, &ce)) {
+ struct addrinfo myhints = { 0 }, *ai, *ai2;
+ int i4, i6, aierr;
+
+#ifdef DEBUG_ADDRINFO
+ printf("looking up new data for '%s'...\n", name);
+#endif
+ myhints.ai_socktype = SOCK_STREAM;
+ myhints.ai_flags = AI_CANONNAME;
+ /* Don't set ai_family -- we want to cache all address types,
+ because the next lookup may not use the same constraints as
+ the current one. We *could* cache them separately, so that
+ we never have to look up an IPv6 address if we are always
+ asked for IPv4 only, but let's deal with that later, if we
+ have to. */
+ /* Try NULL for the service for now.
+
+ It would be nice to use the requested service name, and not
+ have to patch things up, but then we'd be doing multiple
+ queries for the same host when we get different services.
+ We were using "telnet" for a little more confidence that
+ getaddrinfo would heed the hints to only give us stream
+ socket types (with no socket type and null service name, we
+ might get stream *and* dgram *and* raw, for each address,
+ or only raw). The RFC 3493 description of ai_socktype
+ sometimes associates it with the specified service,
+ sometimes not.
+
+ But on Mac OS X (10.3, 10.4) they've "extended" getaddrinfo
+ to make SRV RR queries. (Please, somebody, show me
+ something in the specs that actually supports this? RFC
+ 3493 says nothing about it, but it does say getaddrinfo is
+ the new way to look up hostnames. RFC 2782 says SRV
+ records should *not* be used unless the application
+ protocol spec says to do so. The Telnet spec does not say
+ to do it.) And then they complain when our code
+ "unexpectedly" seems to use this "extension" in cases where
+ they don't want it to be used.
+
+ Fortunately, it appears that if we specify ai_socktype as
+ SOCK_STREAM and use a null service name, we only get one
+ copy of each address on all the platforms I've tried,
+ although it may not have ai_socktype filled in properly.
+ So, we'll fudge it with that for now. */
+ aierr = system_getaddrinfo(name, NULL, &myhints, &ai);
+ if (aierr) {
+ krb5int_unlock_fac();
+ return aierr;
+ }
+ ce = malloc(sizeof(struct face));
+ memset(ce, 0, sizeof(*ce));
+ ce->expiration = time(0) + 30;
+ for (ai2 = ai; ai2; ai2 = ai2->ai_next) {
+#ifdef DEBUG_ADDRINFO
+ printf(" found an address in family %d...\n", ai2->ai_family);
+#endif
+ switch (ai2->ai_family) {
+ case AF_INET:
+ ce->naddrs4++;
+ break;
+ case AF_INET6:
+ ce->naddrs6++;
+ break;
+ default:
+ break;
+ }
+ }
+ ce->addrs4 = calloc(ce->naddrs4, sizeof(*ce->addrs4));
+ if (ce->addrs4 == NULL && ce->naddrs4 != 0) {
+ krb5int_unlock_fac();
+ system_freeaddrinfo(ai);
+ return EAI_MEMORY;
+ }
+ ce->addrs6 = calloc(ce->naddrs6, sizeof(*ce->addrs6));
+ if (ce->addrs6 == NULL && ce->naddrs6 != 0) {
+ krb5int_unlock_fac();
+ free(ce->addrs4);
+ system_freeaddrinfo(ai);
+ return EAI_MEMORY;
+ }
+ for (ai2 = ai, i4 = i6 = 0; ai2; ai2 = ai2->ai_next) {
+ switch (ai2->ai_family) {
+ case AF_INET:
+ ce->addrs4[i4++] = ((struct sockaddr_in *)ai2->ai_addr)->sin_addr;
+ break;
+ case AF_INET6:
+ ce->addrs6[i6++] = ((struct sockaddr_in6 *)ai2->ai_addr)->sin6_addr;
+ break;
+ default:
+ break;
+ }
+ }
+ ce->canonname = ai->ai_canonname ? strdup(ai->ai_canonname) : 0;
+ system_freeaddrinfo(ai);
+ plant_face(name, ce);
+ }
+ template->ai_family = AF_INET6;
+ template->ai_addrlen = sizeof(struct sockaddr_in6);
+ for (i = 0; i < ce->naddrs6; i++) {
+ r = fai_add_entry (result, &ce->addrs6[i], portnum, template);
+ if (r) {
+ krb5int_unlock_fac();
+ return r;
+ }
+ }
+ template->ai_family = AF_INET;
+ template->ai_addrlen = sizeof(struct sockaddr_in);
+ for (i = 0; i < ce->naddrs4; i++) {
+ r = fai_add_entry (result, &ce->addrs4[i], portnum, template);
+ if (r) {
+ krb5int_unlock_fac();
+ return r;
+ }
+ }
+ if (*result && (flags & AI_CANONNAME))
+ (*result)->ai_canonname = (ce->canonname
+ ? strdup(ce->canonname)
+ : NULL);
+ krb5int_unlock_fac();
+ return 0;
+
+#else
+
+ struct hostent *hp;
+ int i, r;
+ int herr;
+ GET_HOST_TMP htmp;
+
+ GET_HOST_BY_NAME (name, hp, herr, htmp);
+ if (hp == 0)
+ return translate_h_errno (herr);
+ for (i = 0; hp->h_addr_list[i]; i++) {
+ r = fai_add_entry (result, hp->h_addr_list[i], portnum, template);
+ if (r)
+ return r;
+ }
+ if (*result && (flags & AI_CANONNAME))
+ (*result)->ai_canonname = strdup (hp->h_name);
+ return 0;
+
+#endif
+}
+
+static inline void
+fake_freeaddrinfo (struct addrinfo *ai)
+{
+ struct addrinfo *next;
+ while (ai) {
+ next = ai->ai_next;
+ if (ai->ai_canonname)
+ free (ai->ai_canonname);
+ if (ai->ai_addr)
+ free (ai->ai_addr);
+ free (ai);
+ ai = next;
+ }
+}
+
+static inline int
+fake_getaddrinfo (const char *name, const char *serv,
+ const struct addrinfo *hint, struct addrinfo **result)
+{
+ struct addrinfo *res = 0;
+ int ret;
+ int port = 0, socktype;
+ int flags;
+ struct addrinfo template;
+
+#ifdef DEBUG_ADDRINFO
+ debug_dump_getaddrinfo_args(name, serv, hint);
+#endif
+
+ if (hint != 0) {
+ if (hint->ai_family != 0 && hint->ai_family != AF_INET)
+ return EAI_NODATA;
+ socktype = hint->ai_socktype;
+ flags = hint->ai_flags;
+ } else {
+ socktype = 0;
+ flags = 0;
+ }
+
+ if (serv) {
+ size_t numlen = strspn (serv, "0123456789");
+ if (serv[numlen] == '\0') {
+ /* pure numeric */
+ unsigned long p = strtoul (serv, 0, 10);
+ if (p == 0 || p > 65535)
+ return EAI_NONAME;
+ port = htons (p);
+ } else {
+ struct servent *sp;
+ int try_dgram_too = 0, s_err;
+ GET_SERV_TMP stmp;
+
+ if (socktype == 0) {
+ try_dgram_too = 1;
+ socktype = SOCK_STREAM;
+ }
+ try_service_lookup:
+ GET_SERV_BY_NAME(serv, socktype == SOCK_STREAM ? "tcp" : "udp",
+ sp, s_err, stmp);
+ if (sp == 0) {
+ if (try_dgram_too) {
+ socktype = SOCK_DGRAM;
+ goto try_service_lookup;
+ }
+ return EAI_SERVICE;
+ }
+ port = sp->s_port;
+ }
+ }
+
+ if (name == 0) {
+ name = (flags & AI_PASSIVE) ? "0.0.0.0" : "127.0.0.1";
+ flags |= AI_NUMERICHOST;
+ }
+
+ template.ai_family = AF_INET;
+ template.ai_addrlen = sizeof (struct sockaddr_in);
+ template.ai_socktype = socktype;
+ template.ai_protocol = 0;
+ template.ai_flags = 0;
+ template.ai_canonname = 0;
+ template.ai_next = 0;
+ template.ai_addr = 0;
+
+ /* If NUMERICHOST is set, parse a numeric address.
+ If it's not set, don't accept such names. */
+ if (flags & AI_NUMERICHOST) {
+ struct in_addr addr4;
+#if 0
+ ret = inet_aton (name, &addr4);
+ if (ret)
+ return EAI_NONAME;
+#else
+ addr4.s_addr = inet_addr (name);
+ if (addr4.s_addr == 0xffffffff || addr4.s_addr == -1)
+ /* 255.255.255.255 or parse error, both bad */
+ return EAI_NONAME;
+#endif
+ ret = fai_add_entry (&res, &addr4, port, &template);
+ } else {
+ ret = fai_add_hosts_by_name (name, &template, port, flags,
+ &res);
+ }
+
+ if (ret && ret != NO_ADDRESS) {
+ fake_freeaddrinfo (res);
+ return ret;
+ }
+ if (res == 0)
+ return NO_ADDRESS;
+ *result = res;
+ return 0;
+}
+
+#ifdef NEED_FAKE_GETNAMEINFO
+static inline int
+fake_getnameinfo (const struct sockaddr *sa, socklen_t len,
+ char *host, socklen_t hostlen,
+ char *service, socklen_t servicelen,
+ int flags)
+{
+ struct hostent *hp;
+ const struct sockaddr_in *sinp;
+ struct servent *sp;
+ size_t hlen, slen;
+
+ if (sa->sa_family != AF_INET) {
+ return EAI_FAMILY;
+ }
+ sinp = (const struct sockaddr_in *) sa;
+
+ hlen = hostlen;
+ if (hostlen < 0 || hlen != hostlen) {
+ errno = EINVAL;
+ return EAI_SYSTEM;
+ }
+ slen = servicelen;
+ if (servicelen < 0 || slen != servicelen) {
+ errno = EINVAL;
+ return EAI_SYSTEM;
+ }
+
+ if (host) {
+ if (flags & NI_NUMERICHOST) {
+#if (defined(__GNUC__) && defined(__mips__)) || 1 /* thread safety always */
+ /* The inet_ntoa call, passing a struct, fails on IRIX 6.5
+ using gcc 2.95; we get back "0.0.0.0". Since this in a
+ configuration still important at Athena, here's the
+ workaround, which also happens to be thread-safe.... */
+ const unsigned char *uc;
+ char tmpbuf[20];
+ numeric_host:
+ uc = (const unsigned char *) &sinp->sin_addr;
+ sprintf(tmpbuf, "%d.%d.%d.%d", uc[0], uc[1], uc[2], uc[3]);
+ strncpy(host, tmpbuf, hlen);
+#else
+ char *p;
+ numeric_host:
+ p = inet_ntoa (sinp->sin_addr);
+ strncpy (host, p, hlen);
+#endif
+ } else {
+ int herr;
+ GET_HOST_TMP htmp;
+
+ GET_HOST_BY_ADDR((const char *) &sinp->sin_addr,
+ sizeof (struct in_addr),
+ sa->sa_family, hp, herr, htmp);
+ if (hp == 0) {
+ if (herr == NO_ADDRESS && !(flags & NI_NAMEREQD)) /* ??? */
+ goto numeric_host;
+ return translate_h_errno (herr);
+ }
+ /* According to the Open Group spec, getnameinfo can
+ silently truncate, but must still return a
+ null-terminated string. */
+ strncpy (host, hp->h_name, hlen);
+ }
+ host[hostlen-1] = 0;
+ }
+
+ if (service) {
+ if (flags & NI_NUMERICSERV) {
+ char numbuf[10];
+ int port;
+ numeric_service:
+ port = ntohs (sinp->sin_port);
+ if (port < 0 || port > 65535)
+ return EAI_FAIL;
+ sprintf (numbuf, "%d", port);
+ strncpy (service, numbuf, slen);
+ } else {
+ int serr;
+ GET_SERV_TMP stmp;
+
+ GET_SERV_BY_PORT(sinp->sin_port,
+ (flags & NI_DGRAM) ? "udp" : "tcp",
+ sp, serr, stmp);
+ if (sp == 0)
+ goto numeric_service;
+ strncpy (service, sp->s_name, slen);
+ }
+ service[servicelen-1] = 0;
+ }
+
+ return 0;
+}
+#endif
+
+#if defined(HAVE_FAKE_GETADDRINFO) || defined(NEED_FAKE_GETNAMEINFO)
+
+static inline
+char *gai_strerror (int code)
+{
+ switch (code) {
+ case EAI_ADDRFAMILY: return "address family for nodename not supported";
+ case EAI_AGAIN: return "temporary failure in name resolution";
+ case EAI_BADFLAGS: return "bad flags to getaddrinfo/getnameinfo";
+ case EAI_FAIL: return "non-recoverable failure in name resolution";
+ case EAI_FAMILY: return "ai_family not supported";
+ case EAI_MEMORY: return "out of memory";
+ case EAI_NODATA: return "no address associated with hostname";
+ case EAI_NONAME: return "name does not exist";
+ case EAI_SERVICE: return "service name not supported for specified socket type";
+ case EAI_SOCKTYPE: return "ai_socktype not supported";
+ case EAI_SYSTEM: return strerror (errno);
+ default: return "bogus getaddrinfo error?";
+ }
+}
+#endif
+
+static inline int translate_h_errno (int h)
+{
+ switch (h) {
+ case 0:
+ return 0;
+#ifdef NETDB_INTERNAL
+ case NETDB_INTERNAL:
+ if (errno == ENOMEM)
+ return EAI_MEMORY;
+ return EAI_SYSTEM;
+#endif
+ case HOST_NOT_FOUND:
+ return EAI_NONAME;
+ case TRY_AGAIN:
+ return EAI_AGAIN;
+ case NO_RECOVERY:
+ return EAI_FAIL;
+ case NO_DATA:
+#if NO_DATA != NO_ADDRESS
+ case NO_ADDRESS:
+#endif
+ return EAI_NODATA;
+ default:
+ return EAI_SYSTEM;
+ }
+}
+
+#if defined(HAVE_FAKE_GETADDRINFO) || defined(FAI_CACHE)
+static inline
+int getaddrinfo (const char *name, const char *serv,
+ const struct addrinfo *hint, struct addrinfo **result)
+{
+ return fake_getaddrinfo(name, serv, hint, result);
+}
+
+static inline
+void freeaddrinfo (struct addrinfo *ai)
+{
+ fake_freeaddrinfo(ai);
+}
+
+#ifdef NEED_FAKE_GETNAMEINFO
+static inline
+int getnameinfo (const struct sockaddr *sa, socklen_t len,
+ char *host, socklen_t hostlen,
+ char *service, socklen_t servicelen,
+ int flags)
+{
+ return fake_getnameinfo(sa, len, host, hostlen, service, servicelen,
+ flags);
+}
+#endif /* NEED_FAKE_GETNAMEINFO */
+#endif /* HAVE_FAKE_GETADDRINFO */
+#endif /* NEED_FAKE_GETADDRINFO */
+
+
+#ifdef WRAP_GETADDRINFO
+
+static inline
+int
+getaddrinfo (const char *name, const char *serv, const struct addrinfo *hint,
+ struct addrinfo **result)
+{
+ int aierr;
+#if defined(_AIX) || defined(COPY_FIRST_CANONNAME)
+ struct addrinfo *ai;
+#endif
+#ifdef NUMERIC_SERVICE_BROKEN
+ int service_is_numeric = 0;
+ int service_port = 0;
+ int socket_type = 0;
+#endif
+
+#ifdef DEBUG_ADDRINFO
+ debug_dump_getaddrinfo_args(name, serv, hint);
+#endif
+
+#ifdef NUMERIC_SERVICE_BROKEN
+ /* AIX 4.3.3 is broken. (Or perhaps out of date?)
+
+ If a numeric service is provided, and it doesn't correspond to
+ a known service name for tcp or udp (as appropriate), an error
+ code (for "host not found") is returned. If the port maps to a
+ known service for both udp and tcp, all is well. */
+ if (serv && serv[0] && isdigit(serv[0])) {
+ unsigned long lport;
+ char *end;
+ lport = strtoul(serv, &end, 10);
+ if (!*end) {
+ if (lport > 65535)
+ return EAI_SOCKTYPE;
+ service_is_numeric = 1;
+ service_port = htons(lport);
+#ifdef AI_NUMERICSERV
+ if (hint && hint->ai_flags & AI_NUMERICSERV)
+ serv = "9";
+ else
+#endif
+ serv = "discard"; /* defined for both udp and tcp */
+ if (hint)
+ socket_type = hint->ai_socktype;
+ }
+ }
+#endif
+
+ aierr = system_getaddrinfo (name, serv, hint, result);
+ if (aierr || *result == 0) {
+#ifdef DEBUG_ADDRINFO
+ debug_dump_error(aierr);
+#endif
+ return aierr;
+ }
+
+ /* Linux libc version 6 (libc-2.2.4.so on Debian) is broken.
+
+ RFC 2553 says that when AI_CANONNAME is set, the ai_canonname
+ flag of the first returned structure has the canonical name of
+ the host. Instead, GNU libc sets ai_canonname in each returned
+ structure to the name that the corresponding address maps to,
+ if any, or a printable numeric form.
+
+ RFC 2553 bis and the new Open Group spec say that field will be
+ the canonical name if it can be determined, otherwise, the
+ provided hostname or a copy of it.
+
+ IMNSHO, "canonical name" means CNAME processing and not PTR
+ processing, but I can see arguing it. Using the numeric form
+ when that's not the form provided is just wrong. So, let's fix
+ it.
+
+ The glibc 2.2.5 sources indicate that the canonical name is
+ *not* allocated separately, it's just some extra storage tacked
+ on the end of the addrinfo structure. So, let's try this
+ approach: If getaddrinfo sets ai_canonname, we'll replace the
+ *first* one with allocated storage, and free up that pointer in
+ freeaddrinfo if it's set; the other ai_canonname fields will be
+ left untouched. And we'll just pray that the application code
+ won't mess around with the list structure; if we start doing
+ that, we'll have to start replacing and freeing all of the
+ ai_canonname fields.
+
+ Ref: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=133668 .
+
+ Since it's dependent on the target hostname, it's hard to check
+ for at configure time. Always do it on Linux for now. When
+ they get around to fixing it, add a compile-time or run-time
+ check for the glibc version in use.
+
+ Some Windows documentation says that even when AI_CANONNAME is
+ set, the returned ai_canonname field can be null. The NetBSD
+ 1.5 implementation also does this, if the input hostname is a
+ numeric host address string. That case isn't handled well at
+ the moment.
+
+ Libc version 5 didn't have getaddrinfo at all. */
+
+#ifdef COPY_FIRST_CANONNAME
+ /*
+ * This code must *always* return an error, return a null
+ * ai_canonname, or return an ai_canonname allocated here using
+ * malloc, so that freeaddrinfo can always free a non-null
+ * ai_canonname. Note that it really doesn't matter if the
+ * AI_CANONNAME flag was set.
+ */
+ ai = *result;
+ if (ai->ai_canonname) {
+ struct hostent *hp;
+ const char *name2 = 0;
+ int i, herr;
+ GET_HOST_TMP htmp;
+
+ /*
+ * Current versions of GET_HOST_BY_NAME will fail if the
+ * target hostname has IPv6 addresses only. Make sure it
+ * fails fairly cleanly.
+ */
+ GET_HOST_BY_NAME (name, hp, herr, htmp);
+ if (hp == 0) {
+ /*
+ * This case probably means it's an IPv6-only name. If
+ * ai_canonname is a numeric address, get rid of it.
+ */
+ if (ai->ai_canonname && strchr(ai->ai_canonname, ':'))
+ ai->ai_canonname = 0;
+ name2 = ai->ai_canonname ? ai->ai_canonname : name;
+ } else {
+ /* Sometimes gethostbyname will be directed to /etc/hosts
+ first, and sometimes that file will have entries with
+ the unqualified name first. So take the first entry
+ that looks like it could be a FQDN. */
+ for (i = 0; hp->h_aliases[i]; i++) {
+ if (strchr(hp->h_aliases[i], '.') != 0) {
+ name2 = hp->h_aliases[i];
+ break;
+ }
+ }
+ /* Give up, just use the first name (h_name ==
+ h_aliases[0] on all systems I've seen). */
+ if (hp->h_aliases[i] == 0)
+ name2 = hp->h_name;
+ }
+
+ ai->ai_canonname = strdup(name2);
+ if (name2 != 0 && ai->ai_canonname == 0) {
+ system_freeaddrinfo(ai);
+ *result = 0;
+#ifdef DEBUG_ADDRINFO
+ debug_dump_error(EAI_MEMORY);
+#endif
+ return EAI_MEMORY;
+ }
+ /* Zap the remaining ai_canonname fields glibc fills in, in
+ case the application messes around with the list
+ structure. */
+ while ((ai = ai->ai_next) != NULL)
+ ai->ai_canonname = 0;
+ }
+#endif
+
+#ifdef NUMERIC_SERVICE_BROKEN
+ if (service_port != 0) {
+ for (ai = *result; ai; ai = ai->ai_next) {
+ if (socket_type != 0 && ai->ai_socktype == 0)
+ /* Is this check actually needed? */
+ ai->ai_socktype = socket_type;
+ switch (ai->ai_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)ai->ai_addr)->sin_port = service_port;
+ break;
+ case AF_INET6:
+ ((struct sockaddr_in6 *)ai->ai_addr)->sin6_port = service_port;
+ break;
+ }
+ }
+ }
+#endif
+
+#ifdef _AIX
+ for (ai = *result; ai; ai = ai->ai_next) {
+ /* AIX 4.3.3 libc is broken. It doesn't set the family or len
+ fields of the sockaddr structures. Usually, sa_family is
+ zero, but I've seen it set to 1 in some cases also (maybe
+ just leftover from previous contents of the memory
+ block?). So, always override what libc returned. */
+ ai->ai_addr->sa_family = ai->ai_family;
+#ifdef HAVE_SA_LEN /* always true on AIX, actually */
+ ai->ai_addr->sa_len = ai->ai_addrlen;
+#endif
+ }
+#endif
+
+ /* Not dealt with currently:
+
+ - Some versions of GNU libc can lose some IPv4 addresses in
+ certain cases when multiple IPv4 and IPv6 addresses are
+ available. */
+
+#ifdef DEBUG_ADDRINFO
+ debug_dump_addrinfos(*result);
+#endif
+
+ return 0;
+}
+
+static inline
+void freeaddrinfo (struct addrinfo *ai)
+{
+#ifdef COPY_FIRST_CANONNAME
+ if (ai) {
+ free(ai->ai_canonname);
+ ai->ai_canonname = 0;
+ system_freeaddrinfo(ai);
+ }
+#else
+ system_freeaddrinfo(ai);
+#endif
+}
+#endif /* WRAP_GETADDRINFO */
+
+static int krb5int_lock_fac (void)
{
int err;
err = krb5int_call_thread_support_init();
@@ -67,7 +1324,35 @@ int krb5int_lock_fac (void)
return k5_mutex_lock(&krb5int_fac.lock);
}
-int krb5int_unlock_fac (void)
+static int krb5int_unlock_fac (void)
{
return k5_mutex_unlock(&krb5int_fac.lock);
}
+
+/* Some systems don't define in6addr_any. */
+const struct in6_addr krb5int_in6addr_any = IN6ADDR_ANY_INIT;
+
+int krb5int_getaddrinfo (const char *node, const char *service,
+ const struct addrinfo *hints,
+ struct addrinfo **aip)
+{
+ return getaddrinfo(node, service, hints, aip);
+}
+
+void krb5int_freeaddrinfo (struct addrinfo *ai)
+{
+ freeaddrinfo(ai);
+}
+
+const char *krb5int_gai_strerror(int err)
+{
+ return gai_strerror(err);
+}
+
+int krb5int_getnameinfo (const struct sockaddr *sa, socklen_t salen,
+ char *hbuf, size_t hbuflen,
+ char *sbuf, size_t sbuflen,
+ int flags)
+{
+ return getnameinfo(sa, salen, hbuf, hbuflen, sbuf, sbuflen, flags);
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/support/init-addrinfo.c b/usr/src/lib/gss_mechs/mech_krb5/support/init-addrinfo.c
new file mode 100644
index 0000000000..4c94dc7434
--- /dev/null
+++ b/usr/src/lib/gss_mechs/mech_krb5/support/init-addrinfo.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2004 by the Massachusetts Institute of Technology,
+ * Cambridge, MA, USA. All Rights Reserved.
+ *
+ * This software is being provided to you, the LICENSEE, by the
+ * Massachusetts Institute of Technology (M.I.T.) under the following
+ * license. By obtaining, using and/or copying this software, you agree
+ * that you have read, understood, and will comply with these terms and
+ * conditions:
+ *
+ * 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 or
+ * royalty is hereby granted, provided that you agree to comply with the
+ * following copyright notice and statements, including the disclaimer, and
+ * that the same appear on ALL copies of the software and documentation,
+ * including modifications that you make for internal use or for
+ * distribution:
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS", AND M.I.T. MAKES NO REPRESENTATIONS
+ * OR WARRANTIES, EXPRESS OR IMPLIED. By way of example, but not
+ * limitation, M.I.T. MAKES NO REPRESENTATIONS OR WARRANTIES OF
+ * MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF
+ * THE LICENSED SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY THIRD PARTY
+ * PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.
+ *
+ * The name of the Massachusetts Institute of Technology or M.I.T. may NOT
+ * be used in advertising or publicity pertaining to distribution of the
+ * software. Title to copyright in this software and any associated
+ * documentation shall at all times remain with M.I.T., and USER agrees to
+ * preserve same.
+ *
+ * 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.
+ */
+
+/* Stuff that needs initialization for fake-addrinfo.c.
+
+ Separated out, so that static linking against this library doesn't
+ require pulling in socket/nsl/whatever libraries for code not using
+ getaddrinfo. */
+
+#include "port-sockets.h"
+#include "socket-utils.h"
+#include "k5-platform.h"
+#include "k5-thread.h"
+
+#include <stdio.h> /* for sprintf */
+#include <errno.h>
+
+#define IMPLEMENT_FAKE_GETADDRINFO
+#include "fake-addrinfo.h"
+#include "cache-addrinfo.h"
+
+struct fac krb5int_fac = { K5_MUTEX_PARTIAL_INITIALIZER, 0 };
+
+int krb5int_init_fac (void)
+{
+ return k5_mutex_finish_init(&krb5int_fac.lock);
+}
+
+void krb5int_fini_fac (void)
+{
+ k5_mutex_destroy(&krb5int_fac.lock);
+}
diff --git a/usr/src/lib/gss_mechs/mech_krb5/support/plugins.c b/usr/src/lib/gss_mechs/mech_krb5/support/plugins.c
index ec7b116407..4a3a41d23b 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/support/plugins.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/support/plugins.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* util/support/plugins.c
*
@@ -29,6 +27,12 @@
* Plugin module support, and shims around dlopen/whatever.
*/
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
#include "k5-plugin.h"
#if USE_DLOPEN
#include <dlfcn.h>
@@ -462,20 +466,13 @@ krb5int_open_plugin_dirs (const char * const *dirnames,
} else {
/* load all plugins in each directory */
#ifndef _WIN32
- DIR *dir = NULL;
+ DIR *dir = opendir (dirnames[i]);
- if (!err) {
- dir = opendir(dirnames[i]);
- if (dir == NULL) {
- err = errno;
- Tprintf ("-> error %d/%s\n", err, strerror (err));
- }
- }
-
- while (!err) {
+ while (dir != NULL && !err) {
struct dirent *d = NULL;
char *filepath = NULL;
struct plugin_file_handle *handle = NULL;
+ int len;
d = readdir (dir);
if (d == NULL) { break; }
@@ -484,9 +481,13 @@ krb5int_open_plugin_dirs (const char * const *dirnames,
(strcmp (d->d_name, "..") == 0)) {
continue;
}
-
+
+ /* Solaris Kerberos: Only open files with a .so extension */
+ len = NAMELEN (d);
+ if (len < 3 || strcmp(".so", d->d_name + len - 3 ) != 0)
+ continue;
+
if (!err) {
- int len = NAMELEN (d);
filepath = malloc (dirnamelen + len + 1); /* NULL */
if (filepath == NULL) {
err = errno;
diff --git a/usr/src/lib/gss_mechs/mech_krb5/support/threads.c b/usr/src/lib/gss_mechs/mech_krb5/support/threads.c
index b03f4e6253..f81af831e4 100644
--- a/usr/src/lib/gss_mechs/mech_krb5/support/threads.c
+++ b/usr/src/lib/gss_mechs/mech_krb5/support/threads.c
@@ -1,9 +1,7 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* util/support/threads.c
*
- * Copyright 2004 by the Massachusetts Institute of Technology.
+ * Copyright 2004,2005,2006 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
* Export of this software from the United States of America may
@@ -32,8 +30,9 @@
#include <assert.h>
#include <stdlib.h>
#include <errno.h>
-#include <k5-thread.h>
-#include <k5-platform.h>
+#include "k5-thread.h"
+#include "k5-platform.h"
+#include "supp-int.h"
MAKE_INIT_FUNCTION(krb5int_thread_support_init);
MAKE_FINI_FUNCTION(krb5int_thread_support_fini);
@@ -45,6 +44,11 @@ struct tsd_block { void *values[K5_KEY_MAX]; };
static struct tsd_block tsd_no_threads;
static unsigned char destructors_set[K5_KEY_MAX];
+int krb5int_pthread_loaded (void)
+{
+ return 0;
+}
+
#elif defined(_WIN32)
static DWORD tls_idx;
@@ -78,6 +82,11 @@ void krb5int_thread_detach_hook (void)
}
}
+/* Stub function not used on Windows. */
+int krb5int_pthread_loaded (void)
+{
+ return 0;
+}
#else /* POSIX threads */
/* Must support register/delete/register sequence, e.g., if krb5 is
@@ -108,6 +117,56 @@ struct tsd_block {
# pragma weak pthread_setspecific
# pragma weak pthread_key_create
# pragma weak pthread_key_delete
+# pragma weak pthread_create
+# pragma weak pthread_join
+static volatile int flag_pthread_loaded = -1;
+static void loaded_test_aux(void)
+{
+ if (flag_pthread_loaded == -1)
+ flag_pthread_loaded = 1;
+ else
+ /* Could we have been called twice? */
+ flag_pthread_loaded = 0;
+}
+static pthread_once_t loaded_test_once = PTHREAD_ONCE_INIT;
+int krb5int_pthread_loaded (void)
+{
+ int x = flag_pthread_loaded;
+ if (x != -1)
+ return x;
+ if (&pthread_getspecific == 0
+ || &pthread_setspecific == 0
+ || &pthread_key_create == 0
+ || &pthread_key_delete == 0
+ || &pthread_once == 0
+ || &pthread_mutex_lock == 0
+ || &pthread_mutex_unlock == 0
+ || &pthread_mutex_destroy == 0
+ || &pthread_mutex_init == 0
+ || &pthread_self == 0
+ || &pthread_equal == 0
+ /* Any program that's really multithreaded will have to be
+ able to create threads. */
+ || &pthread_create == 0
+ || &pthread_join == 0
+ /* Okay, all the interesting functions -- or stubs for them --
+ seem to be present. If we call pthread_once, does it
+ actually seem to cause the indicated function to get called
+ exactly one time? */
+ || pthread_once(&loaded_test_once, loaded_test_aux) != 0
+ || pthread_once(&loaded_test_once, loaded_test_aux) != 0
+ /* This catches cases where pthread_once does nothing, and
+ never causes the function to get called. That's a pretty
+ clear violation of the POSIX spec, but hey, it happens. */
+ || flag_pthread_loaded < 0) {
+ flag_pthread_loaded = 0;
+ return 0;
+ }
+ /* If we wanted to be super-paranoid, we could try testing whether
+ pthread_get/setspecific work, too. I don't know -- so far --
+ of any system with non-functional stubs for those. */
+ return flag_pthread_loaded;
+}
static struct tsd_block tsd_if_single;
# define GET_NO_PTHREAD_TSD() (&tsd_if_single)
#else
@@ -119,30 +178,36 @@ static void thread_termination(void *);
static void thread_termination (void *tptr)
{
- int i, pass, none_found;
- struct tsd_block *t = tptr;
-
- /* Make multiple passes in case, for example, a libkrb5 cleanup
- function wants to print out an error message, which causes
- com_err to allocate a thread-specific buffer, after we just
- freed up the old one.
-
- Shouldn't actually happen, if we're careful, but check just in
- case. */
-
- pass = 0;
- none_found = 0;
- while (pass < 4 && !none_found) {
- none_found = 1;
- for (i = 0; i < K5_KEY_MAX; i++) {
- if (destructors_set[i] && destructors[i] && t->values[i]) {
- void *v = t->values[i];
- t->values[i] = 0;
- (*destructors[i])(v);
- none_found = 0;
- }
- }
- }
+ int err = k5_mutex_lock(&key_lock);
+ if (err == 0) {
+ int i, pass, none_found;
+ struct tsd_block *t = tptr;
+
+ /* Make multiple passes in case, for example, a libkrb5 cleanup
+ function wants to print out an error message, which causes
+ com_err to allocate a thread-specific buffer, after we just
+ freed up the old one.
+
+ Shouldn't actually happen, if we're careful, but check just in
+ case. */
+
+ pass = 0;
+ none_found = 0;
+ while (pass < 4 && !none_found) {
+ none_found = 1;
+ for (i = 0; i < K5_KEY_MAX; i++) {
+ if (destructors_set[i] && destructors[i] && t->values[i]) {
+ void *v = t->values[i];
+ t->values[i] = 0;
+ (*destructors[i])(v);
+ none_found = 0;
+ }
+ }
+ }
+ free (t);
+ err = k5_mutex_unlock(&key_lock);
+ }
+
/* remove thread from global linked list */
}
@@ -211,9 +276,9 @@ int k5_setspecific (k5_key_t keynum, void *value)
/* add to global linked list */
/* t->next = 0; */
err = TlsSetValue(tls_idx, t);
- if (err) {
+ if (!err) {
free(t);
- return err;
+ return GetLastError();
}
}
@@ -307,12 +372,28 @@ int k5_key_delete (k5_key_t keynum)
/* XXX Memory leak here!
Need to destroy the associated data for all threads.
But watch for race conditions in case threads are going away too. */
+ assert(destructors_set[keynum] == 1);
+ destructors_set[keynum] = 0;
+ destructors[keynum] = 0;
LeaveCriticalSection(&key_lock);
#else /* POSIX */
- /* Not written yet. */
- abort();
+ {
+ int err;
+
+ /* XXX RESOURCE LEAK:
+
+ Need to destroy the allocated objects first! */
+
+ err = k5_mutex_lock(&key_lock);
+ if (err == 0) {
+ assert(destructors_set[keynum] == 1);
+ destructors_set[keynum] = 0;
+ destructors[keynum] = NULL;
+ k5_mutex_unlock(&key_lock);
+ }
+ }
#endif
@@ -324,13 +405,28 @@ int krb5int_call_thread_support_init (void)
return CALL_INIT_FUNCTION(krb5int_thread_support_init);
}
-extern int krb5int_init_fac(void);
-extern void krb5int_fini_fac(void);
+#include "cache-addrinfo.h"
+
+#ifdef DEBUG_THREADS_STATS
+#include <stdio.h>
+static FILE *stats_logfile;
+#endif
int krb5int_thread_support_init (void)
{
int err;
+#ifdef SHOW_INITFINI_FUNCS
+ printf("krb5int_thread_support_init\n");
+#endif
+
+#ifdef DEBUG_THREADS_STATS
+ /* stats_logfile = stderr; */
+ stats_logfile = fopen("/dev/tty", "w+");
+ if (stats_logfile == NULL)
+ stats_logfile = stderr;
+#endif
+
#ifndef ENABLE_THREADS
/* Nothing to do for TLS initialization. */
@@ -358,6 +454,10 @@ int krb5int_thread_support_init (void)
if (err)
return err;
+ err = krb5int_err_init();
+ if (err)
+ return err;
+
return 0;
}
@@ -366,6 +466,10 @@ void krb5int_thread_support_fini (void)
if (! INITIALIZER_RAN (krb5int_thread_support_init))
return;
+#ifdef SHOW_INITFINI_FUNCS
+ printf("krb5int_thread_support_fini\n");
+#endif
+
#ifndef ENABLE_THREADS
/* Do nothing. */
@@ -387,8 +491,127 @@ void krb5int_thread_support_fini (void)
#endif
+#ifdef DEBUG_THREADS_STATS
+ fflush(stats_logfile);
+ /* XXX Should close if not stderr, in case unloading library but
+ not exiting. */
+#endif
+
krb5int_fini_fac();
}
+
+#ifdef DEBUG_THREADS_STATS
+void KRB5_CALLCONV
+k5_mutex_lock_update_stats(k5_debug_mutex_stats *m,
+ k5_mutex_stats_tmp startwait)
+{
+ k5_debug_time_t now;
+ k5_debug_timediff_t tdiff, tdiff2;
+
+ now = get_current_time();
+ (void) krb5int_call_thread_support_init();
+ m->count++;
+ m->time_acquired = now;
+ tdiff = timediff(now, startwait);
+ tdiff2 = tdiff * tdiff;
+ if (m->count == 1 || m->lockwait.valmin > tdiff)
+ m->lockwait.valmin = tdiff;
+ if (m->count == 1 || m->lockwait.valmax < tdiff)
+ m->lockwait.valmax = tdiff;
+ m->lockwait.valsum += tdiff;
+ m->lockwait.valsqsum += tdiff2;
+}
+
+void KRB5_CALLCONV
+krb5int_mutex_unlock_update_stats(k5_debug_mutex_stats *m)
+{
+ k5_debug_time_t now = get_current_time();
+ k5_debug_timediff_t tdiff, tdiff2;
+ tdiff = timediff(now, m->time_acquired);
+ tdiff2 = tdiff * tdiff;
+ if (m->count == 1 || m->lockheld.valmin > tdiff)
+ m->lockheld.valmin = tdiff;
+ if (m->count == 1 || m->lockheld.valmax < tdiff)
+ m->lockheld.valmax = tdiff;
+ m->lockheld.valsum += tdiff;
+ m->lockheld.valsqsum += tdiff2;
+}
+
+#include <math.h>
+static double
+get_stddev(struct k5_timediff_stats sp, int count)
+{
+ long double mu, mu_squared, rho_squared;
+ mu = (long double) sp.valsum / count;
+ mu_squared = mu * mu;
+ /* SUM((x_i - mu)^2)
+ = SUM(x_i^2 - 2*mu*x_i + mu^2)
+ = SUM(x_i^2) - 2*mu*SUM(x_i) + N*mu^2
+
+ Standard deviation rho^2 = SUM(...) / N. */
+ rho_squared = (sp.valsqsum - 2 * mu * sp.valsum + count * mu_squared) / count;
+ return sqrt(rho_squared);
+}
+
+void KRB5_CALLCONV
+krb5int_mutex_report_stats(k5_mutex_t *m)
+{
+ char *p;
+
+ /* Tweak this to only record data on "interesting" locks. */
+ if (m->stats.count < 10)
+ return;
+ if (m->stats.lockwait.valsum < 10 * m->stats.count)
+ return;
+
+ p = strrchr(m->loc_created.filename, '/');
+ if (p == NULL)
+ p = m->loc_created.filename;
+ else
+ p++;
+ fprintf(stats_logfile, "mutex @%p: created at line %d of %s\n",
+ (void *) m, m->loc_created.lineno, p);
+ if (m->stats.count == 0)
+ fprintf(stats_logfile, "\tnever locked\n");
+ else {
+ double sd_wait, sd_hold;
+ sd_wait = get_stddev(m->stats.lockwait, m->stats.count);
+ sd_hold = get_stddev(m->stats.lockheld, m->stats.count);
+ fprintf(stats_logfile,
+ "\tlocked %d time%s; wait %lu/%f/%lu/%fus, hold %lu/%f/%lu/%fus\n",
+ m->stats.count, m->stats.count == 1 ? "" : "s",
+ (unsigned long) m->stats.lockwait.valmin,
+ (double) m->stats.lockwait.valsum / m->stats.count,
+ (unsigned long) m->stats.lockwait.valmax,
+ sd_wait,
+ (unsigned long) m->stats.lockheld.valmin,
+ (double) m->stats.lockheld.valsum / m->stats.count,
+ (unsigned long) m->stats.lockheld.valmax,
+ sd_hold);
+ }
+}
+#else
+/* On Windows, everything defined in the export list must be defined.
+ The UNIX systems where we're using the export list don't seem to
+ care. */
+#undef krb5int_mutex_lock_update_stats
+void KRB5_CALLCONV
+krb5int_mutex_lock_update_stats(k5_debug_mutex_stats *m,
+ k5_mutex_stats_tmp startwait)
+{
+}
+#undef krb5int_mutex_unlock_update_stats
+void KRB5_CALLCONV
+krb5int_mutex_unlock_update_stats(k5_debug_mutex_stats *m)
+{
+}
+#undef krb5int_mutex_report_stats
+void KRB5_CALLCONV
+krb5int_mutex_report_stats(k5_mutex_t *m)
+{
+}
+#endif
+
/* Mutex allocation functions, for use in plugins that may not know
what options a given set of libraries was compiled with. */
int KRB5_CALLCONV
diff --git a/usr/src/lib/krb5/kadm5/adb.h b/usr/src/lib/krb5/kadm5/adb.h
index de5650eb89..95a042c55e 100644
--- a/usr/src/lib/krb5/kadm5/adb.h
+++ b/usr/src/lib/krb5/kadm5/adb.h
@@ -1,33 +1,14 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
- * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ * Data Types for policy and principal information that
+ * exists in the respective databases.
*
- * Openvision retains the copyright to derivative works of
- * this source code. Do *NOT* create a derivative of this
- * source code before consulting with your legal department.
- * Do *NOT* integrate *ANY* of this source code into another
- * product before consulting with your legal department.
- *
- * For further information, read the top-level Openvision
- * copyright which is contained in the top-level MIT Kerberos
- * copyright.
- *
- * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
- *
- */
-
-
-/*
- * Data Types for policys, and principal information that
- * exist in the respective databases.
- *
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/adb.h,v 1.21 1998/02/14 02:34:09 tlyu Exp $
+ * $Header$
*
* This file was originally created with rpcgen.
* It has been hacked up since then.
@@ -104,6 +85,7 @@ typedef struct _osa_policy_ent_t {
typedef void (*osa_adb_iter_princ_func) (void *, osa_princ_ent_t);
typedef void (*osa_adb_iter_policy_func) (void *, osa_policy_ent_t);
+
/*
* Return Code (the rest are in adb_err.h)
diff --git a/usr/src/lib/krb5/kadm5/admin.h b/usr/src/lib/krb5/kadm5/admin.h
index 1494a6a1f6..90f582e843 100644
--- a/usr/src/lib/krb5/kadm5/admin.h
+++ b/usr/src/lib/krb5/kadm5/admin.h
@@ -6,7 +6,6 @@
#ifndef __KADM5_ADMIN_H__
#define __KADM5_ADMIN_H__
-#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __cplusplus
extern "C" {
@@ -63,8 +62,8 @@ extern "C" {
#include <sys/types.h>
#include <rpc/types.h>
#include <rpc/rpc.h>
-#include <krb5.h>
#include <k5-int.h>
+#include <krb5.h>
#include <krb5/kdb.h>
#include <com_err.h>
#include <kadm5/kadm_err.h>
@@ -274,13 +273,6 @@ typedef struct _kadm5_policy_ent_t {
long policy_refcnt;
} kadm5_policy_ent_rec, *kadm5_policy_ent_t;
-#if 0 /************** Begin IFDEF'ed OUT *******************************/
-typedef struct __krb5_key_salt_tuple {
- krb5_enctype ks_enctype;
- krb5_int32 ks_salttype;
-} krb5_key_salt_tuple;
-#endif /**************** END IFDEF'ed OUT *******************************/
-
/*
* New types to indicate which protocol to use when sending
* password change requests
@@ -296,7 +288,6 @@ typedef enum {
typedef struct _kadm5_config_params {
long mask;
char * realm;
- char * profile;
int kadmind_port;
int kpasswd_port;
@@ -379,7 +370,7 @@ kadm5_get_cpw_host_srv_name(krb5_context context,
#if USE_KADM5_API_VERSION > 1
krb5_error_code kadm5_get_config_params(krb5_context context,
- char *kdcprofile, char *kdcenv,
+ int use_kdc_config,
kadm5_config_params *params_in,
kadm5_config_params *params_out);
@@ -404,7 +395,6 @@ kadm5_ret_t kadm5_init(char *client_name, char *pass,
krb5_ui_4 api_version,
char **db_args,
void **server_handle);
-
kadm5_ret_t kadm5_init_with_password(char *client_name,
char *pass,
char *service_name,
diff --git a/usr/src/lib/krb5/kadm5/admin_xdr.h b/usr/src/lib/krb5/kadm5/admin_xdr.h
index 8eff0ca9f1..d3af4727e6 100644
--- a/usr/src/lib/krb5/kadm5/admin_xdr.h
+++ b/usr/src/lib/krb5/kadm5/admin_xdr.h
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
*
@@ -21,12 +19,13 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/admin_xdr.h,v 1.7 2001/07/25 19:02:29 epeisach Exp $
+ * $Header$
*
*/
#include <kadm5/admin.h>
#include "kadm_rpc.h"
+#include "server_internal.h"
bool_t xdr_ui_4(XDR *xdrs, krb5_ui_4 *objp);
bool_t xdr_nullstring(XDR *xdrs, char **objp);
@@ -79,3 +78,5 @@ bool_t xdr_krb5_int32(XDR *xdrs, krb5_int32 *objp);
bool_t xdr_krb5_enctype(XDR *xdrs, krb5_enctype *objp);
bool_t xdr_krb5_salttype(XDR *xdrs, krb5_int32 *objp);
bool_t xdr_krb5_keyblock(XDR *xdrs, krb5_keyblock *objp);
+bool_t xdr_krb5_key_data(XDR *xdrs, krb5_key_data *objp);
+bool_t xdr_osa_pw_hist_ent(XDR *xdrs, osa_pw_hist_ent *objp);
diff --git a/usr/src/lib/krb5/kadm5/alt_prof.c b/usr/src/lib/krb5/kadm5/alt_prof.c
index b76339b7a5..2469fe4562 100644
--- a/usr/src/lib/krb5/kadm5/alt_prof.c
+++ b/usr/src/lib/krb5/kadm5/alt_prof.c
@@ -3,7 +3,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -53,9 +52,9 @@
/*
* alt_prof.c - Implement alternate profile file handling.
*/
-#include <k5-int.h>
+#include "k5-int.h"
#include <kadm5/admin.h>
-#include <adm_proto.h>
+#include "adm_proto.h"
#include <stdio.h>
#include <ctype.h>
#include <os-proto.h>
@@ -104,30 +103,50 @@ krb5_aprof_init(fname, envname, acontextp)
krb5_pointer *acontextp;
{
krb5_error_code kret;
- const_profile_filespec_t namelist[2];
profile_t profile;
-
- namelist[1] = (profile_filespec_t) NULL;
- profile = (profile_t) NULL;
- if (envname) {
- if ((namelist[0] = getenv(envname))) {
- kret = profile_init(namelist, &profile);
- if (kret)
- return kret;
- *acontextp = (krb5_pointer) profile;
- return 0;
- }
+ const char *kdc_config;
+ size_t krb5_config_len, kdc_config_len;
+ char *profile_path;
+ char **filenames;
+ int i;
+
+ kret = krb5_get_default_config_files (&filenames);
+ if (kret)
+ return kret;
+ krb5_config_len = 0;
+ for (i = 0; filenames[i] != NULL; i++)
+ krb5_config_len += strlen(filenames[i]) + 1;
+ if (i > 0)
+ krb5_config_len--;
+ if (envname == NULL
+ || (kdc_config = getenv(envname)) == NULL)
+ kdc_config = fname;
+ if (kdc_config == NULL)
+ kdc_config_len = 0;
+ else
+ kdc_config_len = strlen(kdc_config);
+ profile_path = malloc(2 + krb5_config_len + kdc_config_len);
+ if (profile_path == NULL) {
+ krb5_free_config_files(filenames);
+ return errno;
}
+ if (kdc_config_len)
+ strcpy(profile_path, kdc_config);
+ else
+ profile_path[0] = 0;
+ if (krb5_config_len)
+ for (i = 0; filenames[i] != NULL; i++) {
+ if (kdc_config_len || i)
+ strcat(profile_path, ":");
+ strcat(profile_path, filenames[i]);
+ }
+ krb5_free_config_files(filenames);
profile = (profile_t) NULL;
- if (fname) {
- kret = profile_init_path(fname, &profile);
- if (kret == ENOENT) {
- profile = 0;
- } else if (kret)
- return kret;
- *acontextp = (krb5_pointer) profile;
- return 0;
- }
+ kret = profile_init_path(profile_path, &profile);
+ free(profile_path);
+ if (kret)
+ return kret;
+ *acontextp = profile;
return 0;
}
@@ -387,11 +406,10 @@ krb5_aprof_finish(acontext)
* in params_in for which the mask is set will be re-assigned to newly copied
* versions, overwriting the old pointer value.
*/
-krb5_error_code kadm5_get_config_params(context, kdcprofile, kdcenv,
+krb5_error_code kadm5_get_config_params(context, use_kdc_config,
params_in, params_out)
krb5_context context;
- char *kdcprofile;
- char *kdcenv;
+ int use_kdc_config;
kadm5_config_params *params_in, *params_out;
{
char *filename;
@@ -404,7 +422,7 @@ krb5_error_code kadm5_get_config_params(context, kdcprofile, kdcenv,
kadm5_config_params params, empty_params;
krb5_error_code kret = 0;
- krb5_error_code dnsret = 1;
+ krb5_error_code dnsret = 1;
#ifdef KRB5_DNS_LOOKUP
char dns_host[MAX_DNS_NAMELEN];
@@ -429,22 +447,20 @@ krb5_error_code kadm5_get_config_params(context, kdcprofile, kdcenv,
params.realm = lrealm;
params.mask |= KADM5_CONFIG_REALM;
}
- if (params_in->mask & KADM5_CONFIG_PROFILE) {
- filename = params.profile = strdup(params_in->profile);
- if (params.profile)
- params.mask |= KADM5_CONFIG_PROFILE;
- envname = NULL;
+ /*
+ * XXX These defaults should to work on both client and
+ * server. kadm5_get_config_params can be implemented as a
+ * wrapper function in each library that provides correct
+ * defaults for NULL values.
+ */
+ if (use_kdc_config) {
+ filename = DEFAULT_KDC_PROFILE;
+ envname = KDC_PROFILE_ENV;
} else {
- /*
- * XXX These defaults should to work on both client and
- * server. kadm5_get_config_params can be implemented as a
- * wrapper function in each library that provides correct
- * defaults for NULL values.
- */
- filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE;
- envname = (kdcenv) ? kdcenv : KDC_PROFILE_ENV;
- if (context->profile_secure == TRUE) envname = 0;
+ filename = DEFAULT_PROFILE_PATH;
+ envname = "KRB5_CONFIG";
}
+ if (context->profile_secure == TRUE) envname = 0;
kret = krb5_aprof_init(filename, envname, &aprofile);
if (kret)
@@ -671,7 +687,8 @@ krb5_error_code kadm5_get_config_params(context, kdcprofile, kdcenv,
params.stash_file = svalue;
}
- /*
+ /*
+ * Solaris Kerberos
* Get the value for maximum ticket lifetime.
* See SEAM documentation or the Bug ID 4184504
* We have changed the logic so that the entries are
@@ -1001,63 +1018,59 @@ kadm5_free_config_params(context, params)
kadm5_config_params *params;
{
if (params) {
- if (params->profile) {
- krb5_xfree(params->profile);
- params->profile = NULL;
- }
- if (params->dbname) {
- krb5_xfree(params->dbname);
- params->dbname = NULL;
- }
- if (params->mkey_name) {
- krb5_xfree(params->mkey_name);
- params->mkey_name = NULL;
- }
- if (params->stash_file) {
- krb5_xfree(params->stash_file);
- params->stash_file = NULL;
- }
- if (params->keysalts) {
- krb5_xfree(params->keysalts);
- params->keysalts = NULL;
- params->num_keysalts = 0;
- }
- if (params->admin_keytab) {
- free(params->admin_keytab);
- params->admin_keytab = NULL;
- }
- if (params->dict_file) {
- free(params->dict_file);
- params->dict_file = NULL;
- }
- if (params->acl_file) {
- free(params->acl_file);
- params->acl_file = NULL;
- }
- if (params->realm) {
- free(params->realm);
- params->realm = NULL;
- }
- if (params->admin_dbname) {
- free(params->admin_dbname);
- params->admin_dbname = NULL;
- }
- if (params->admin_lockfile) {
- free(params->admin_lockfile);
- params->admin_lockfile = NULL;
- }
- if (params->admin_server) {
- free(params->admin_server);
- params->admin_server = NULL;
- }
- if (params->kpasswd_server) {
- free(params->kpasswd_server);
- params->kpasswd_server = NULL;
- }
- if (params->iprop_polltime) {
- free(params->iprop_polltime);
- params->iprop_polltime = NULL;
- }
+ if (params->dbname) {
+ krb5_xfree(params->dbname);
+ params->dbname = NULL;
+ }
+ if (params->mkey_name) {
+ krb5_xfree(params->mkey_name);
+ params->mkey_name = NULL;
+ }
+ if (params->stash_file) {
+ krb5_xfree(params->stash_file);
+ params->stash_file = NULL;
+ }
+ if (params->keysalts) {
+ krb5_xfree(params->keysalts);
+ params->keysalts = NULL;
+ params->num_keysalts = 0;
+ }
+ if (params->admin_keytab) {
+ free(params->admin_keytab);
+ params->admin_keytab = NULL;
+ }
+ if (params->dict_file) {
+ free(params->dict_file);
+ params->dict_file = NULL;
+ }
+ if (params->acl_file) {
+ free(params->acl_file);
+ params->acl_file = NULL;
+ }
+ if (params->realm) {
+ free(params->realm);
+ params->realm = NULL;
+ }
+ if (params->admin_dbname) {
+ free(params->admin_dbname);
+ params->admin_dbname = NULL;
+ }
+ if (params->admin_lockfile) {
+ free(params->admin_lockfile);
+ params->admin_lockfile = NULL;
+ }
+ if (params->admin_server) {
+ free(params->admin_server);
+ params->admin_server = NULL;
+ }
+ if (params->kpasswd_server) {
+ free(params->kpasswd_server);
+ params->kpasswd_server = NULL;
+ }
+ if (params->iprop_polltime) {
+ free(params->iprop_polltime);
+ params->iprop_polltime = NULL;
+ }
}
return (0);
}
@@ -1077,8 +1090,7 @@ kadm5_get_admin_service_name(krb5_context ctx,
params_in.mask |= KADM5_CONFIG_REALM;
params_in.realm = realm_in;
- ret = kadm5_get_config_params(ctx, DEFAULT_PROFILE_PATH,
- "KRB5_CONFIG", &params_in, &params_out);
+ ret = kadm5_get_config_params(ctx, 0, &params_in, &params_out);
if (ret)
return ret;
@@ -1114,11 +1126,9 @@ err_params:
* alternate profile.
*/
krb5_error_code
-krb5_read_realm_params(kcontext, realm, kdcprofile, kdcenv, rparamp)
+krb5_read_realm_params(kcontext, realm, rparamp)
krb5_context kcontext;
char *realm;
- char *kdcprofile;
- char *kdcenv;
krb5_realm_params **rparamp;
{
char *filename;
@@ -1132,6 +1142,9 @@ krb5_read_realm_params(kcontext, realm, kdcprofile, kdcenv, rparamp)
krb5_boolean bvalue;
krb5_deltat dtvalue;
+ char *kdcprofile = 0;
+ char *kdcenv = 0;
+
krb5_error_code kret;
filename = (kdcprofile) ? kdcprofile : DEFAULT_KDC_PROFILE;
diff --git a/usr/src/lib/krb5/kadm5/chpass_util.c b/usr/src/lib/krb5/kadm5/chpass_util.c
index 18422e0924..d1c7039ddc 100644
--- a/usr/src/lib/krb5/kadm5/chpass_util.c
+++ b/usr/src/lib/krb5/kadm5/chpass_util.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -25,10 +24,6 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
- *
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/chpass_util.c,v 1.18.18.1 2000/05/19 22:24:14 raeburn Exp $
- *
- *
*/
@@ -43,6 +38,7 @@
#include "admin_internal.h"
#include <krb5.h>
+#include <strings.h>
#define string_text error_message
@@ -112,7 +108,7 @@ kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle,
} else { /* read the password */
krb5_context context;
- if ((code = (int) krb5_init_context(&context)) == 0) {
+ if ((code = (int) kadm5_init_krb5_context(&context)) == 0) {
pwsize = sizeof(buffer);
code = krb5_read_password(context, KADM5_PW_FIRST_PROMPT,
KADM5_PW_SECOND_PROMPT,
@@ -127,16 +123,16 @@ kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle,
memset(buffer, 0, sizeof(buffer));
#endif
if (code == KRB5_LIBOS_BADPWDMATCH) {
- strncpy(msg_ret, string_text(CHPASS_UTIL_NEW_PASSWORD_MISMATCH),
+ (void) strncpy(msg_ret, string_text(CHPASS_UTIL_NEW_PASSWORD_MISMATCH),
msg_len - 1);
msg_ret[msg_len - 1] = '\0';
return(code);
} else {
- strncpy(msg_ret, error_message(code), msg_len - 1);
- strncat(msg_ret, " ", msg_len - 1);
- strncat(msg_ret, string_text(CHPASS_UTIL_WHILE_READING_PASSWORD),
+ (void) strncpy(msg_ret, error_message(code), msg_len - 1);
+ (void) strncat(msg_ret, " ", msg_len - 1);
+ (void) strncat(msg_ret, string_text(CHPASS_UTIL_WHILE_READING_PASSWORD),
msg_len - 1);
- strncat(msg_ret, string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
+ (void) strncat(msg_ret, string_text(CHPASS_UTIL_PASSWORD_NOT_CHANGED),
msg_len - 1);
msg_ret[msg_len - 1] = '\0';
return(code);
@@ -298,7 +294,7 @@ kadm5_ret_t _kadm5_chpass_principal_util(void *server_handle,
(void) kadm5_free_principal_ent(lhandle, &princ_ent);
(void) kadm5_free_policy_ent(lhandle, &policy_ent);
return(code);
- } else {
+ } else {
/* We should never get here, but just in case ... */
sprintf(buffer, "%s %s", error_message(code),
diff --git a/usr/src/lib/krb5/kadm5/clnt/changepw.c b/usr/src/lib/krb5/kadm5/clnt/changepw.c
index 48d4d130aa..7d79d4ccba 100644
--- a/usr/src/lib/krb5/kadm5/clnt/changepw.c
+++ b/usr/src/lib/krb5/kadm5/clnt/changepw.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/krb5/os/changepw.c
@@ -33,24 +32,24 @@
*/
#define NEED_SOCKETS
-#include <krb5.h>
#include <k5-int.h>
#include <kadm5/admin.h>
#include <client_internal.h>
#include <gssapi/gssapi.h>
#include <gssapi_krb5.h>
#include <gssapiP_krb5.h>
+#include <krb5.h>
/* #include "adm_err.h" */
#include <stdio.h>
#include <errno.h>
-extern krb5_error_code krb5_mk_chpw_req(krb5_context context,
+extern krb5_error_code krb5int_mk_chpw_req(krb5_context context,
krb5_auth_context auth_context,
krb5_data *ap_req, char *passwd,
krb5_data *packet);
-extern krb5_error_code krb5_rd_chpw_rep(krb5_context context,
+extern krb5_error_code krb5int_rd_chpw_rep(krb5_context context,
krb5_auth_context auth_context,
krb5_data *packet, int *result_code,
krb5_data *result_data);
@@ -268,7 +267,7 @@ krb5_data *srvr_msg;
goto cleanup;
}
- if (code = krb5_mk_chpw_req(context, auth_context,
+ if (code = krb5int_mk_chpw_req(context, auth_context,
&ap_req, newpw, &chpw_req))
{
code = errno;
@@ -326,7 +325,7 @@ krb5_data *srvr_msg;
NULL, &remote_kaddr))
goto cleanup;
- if (code = krb5_rd_chpw_rep(context, auth_context, &chpw_rep,
+ if (code = krb5int_rd_chpw_rep(context, auth_context, &chpw_rep,
&local_result_code, srvr_msg))
goto cleanup;
diff --git a/usr/src/lib/krb5/kadm5/clnt/chpw.c b/usr/src/lib/krb5/kadm5/clnt/chpw.c
index 246dfc8dc9..543f6a51ab 100644
--- a/usr/src/lib/krb5/kadm5/clnt/chpw.c
+++ b/usr/src/lib/krb5/kadm5/clnt/chpw.c
@@ -1,140 +1,144 @@
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
#include <string.h>
-#include <k5-int.h>
+#include "k5-int.h"
#include <kadm5/admin.h>
#include <client_internal.h>
-#include <auth_con.h>
+#include "auth_con.h"
#include <locale.h>
-/*
- * krb5_mk_chpw_req
- *
- * Generate a CHANGEPW request packet to send to a
- * password server.
- * The format of the packet used here is defined in the
- * Marc Horowitz Password change protocol document (1998)
- * (expired).
- * It is also defined in the latest kerberos passwd set/change
- * protocol IETF draft document by UMich, Cisco, and MS.
- */
-krb5_error_code KRB5_CALLCONV
-krb5_mk_chpw_req(context, auth_context, ap_req, passwd, packet)
-krb5_context context;
-krb5_auth_context auth_context;
-krb5_data *ap_req;
-char *passwd;
-krb5_data *packet;
+
+krb5_error_code
+krb5int_mk_chpw_req(
+ krb5_context context,
+ krb5_auth_context auth_context,
+ krb5_data *ap_req,
+ char *passwd,
+ krb5_data *packet)
{
- krb5_error_code ret = 0;
- krb5_data clearpw;
- krb5_data cipherpw;
- krb5_replay_data replay;
- char *ptr;
+ krb5_error_code ret = 0;
+ krb5_data clearpw;
+ krb5_data cipherpw;
+ krb5_replay_data replay;
+ char *ptr;
- cipherpw.data = NULL;
+ cipherpw.data = NULL;
- if (ret = krb5_auth_con_setflags(context, auth_context,
- KRB5_AUTH_CONTEXT_DO_SEQUENCE))
- goto cleanup;
+ if ((ret = krb5_auth_con_setflags(context, auth_context,
+ KRB5_AUTH_CONTEXT_DO_SEQUENCE)))
+ goto cleanup;
- clearpw.length = strlen(passwd);
- clearpw.data = passwd;
+ clearpw.length = strlen(passwd);
+ clearpw.data = passwd;
- if (ret = krb5_mk_priv(context, auth_context,
- &clearpw, &cipherpw, &replay))
- goto cleanup;
+ if ((ret = krb5_mk_priv(context, auth_context,
+ &clearpw, &cipherpw, &replay)))
+ goto cleanup;
- packet->length = 6 + ap_req->length + cipherpw.length;
- packet->data = (char *)malloc(packet->length);
- if (packet->data == NULL)
+ packet->length = 6 + ap_req->length + cipherpw.length;
+ packet->data = (char *) malloc(packet->length);
+ if (packet->data == NULL)
{
- ret = ENOMEM;
- goto cleanup;
+ ret = ENOMEM;
+ goto cleanup;
}
- ptr = packet->data;
+ ptr = packet->data;
- /* length */
- *ptr++ = (packet->length>>8) & 0xff;
- *ptr++ = packet->length & 0xff;
+ /* length */
- /*
- * version == 0x0001 big-endian
- * NOTE: when MS and MIT start supporting the latest
- * version of the passwd change protocol (v2),
- * this value will change to 2.
- */
- *ptr++ = 0;
- *ptr++ = 1;
+ *ptr++ = (packet->length>> 8) & 0xff;
+ *ptr++ = packet->length & 0xff;
- /* ap_req length, big-endian */
- *ptr++ = (ap_req->length>>8) & 0xff;
- *ptr++ = ap_req->length & 0xff;
+ /* version == 0x0001 big-endian
+ * NOTE: when MS and MIT start supporting the latest
+ * version of the passwd change protocol (v2),
+ * this value will change to 2.
+ */
+ *ptr++ = 0;
+ *ptr++ = 1;
- /* ap-req data */
- memcpy(ptr, ap_req->data, ap_req->length);
- ptr += ap_req->length;
+ /* ap_req length, big-endian */
- /* krb-priv of password */
- memcpy(ptr, cipherpw.data, cipherpw.length);
+ *ptr++ = (ap_req->length>>8) & 0xff;
+ *ptr++ = ap_req->length & 0xff;
-cleanup:
- if (cipherpw.data != NULL) /* allocated by krb5_mk_priv */
- free(cipherpw.data);
+ /* ap-req data */
+
+ memcpy(ptr, ap_req->data, ap_req->length);
+ ptr += ap_req->length;
+
+ /* krb-priv of password */
- return (ret);
+ memcpy(ptr, cipherpw.data, cipherpw.length);
+
+cleanup:
+ if(cipherpw.data != NULL) /* allocated by krb5_mk_priv */
+ free(cipherpw.data);
+
+ return(ret);
}
-/*
- * krb5_rd_chpw_rep
- *
- * Decode and parse the reply from the CHANGEPW request.
- */
-krb5_error_code KRB5_CALLCONV
-krb5_rd_chpw_rep(context, auth_context, packet, result_code, result_data)
-krb5_context context;
-krb5_auth_context auth_context;
-krb5_data *packet;
-int *result_code;
-krb5_data *result_data;
+krb5_error_code
+krb5int_rd_chpw_rep(krb5_context context, krb5_auth_context auth_context, krb5_data *packet, int *result_code, krb5_data *result_data)
{
- char *ptr;
- int plen, vno;
- krb5_data ap_rep;
- krb5_ap_rep_enc_part *ap_rep_enc;
- krb5_error_code ret;
- krb5_data cipherresult;
- krb5_data clearresult;
- krb5_error *krberror;
- krb5_replay_data replay;
- krb5_keyblock *tmp;
- int local_result_code;
-
- if (packet->length < 4)
+ char *ptr;
+ int plen, vno;
+ krb5_data ap_rep;
+ krb5_ap_rep_enc_part *ap_rep_enc;
+ krb5_error_code ret;
+ krb5_data cipherresult;
+ krb5_data clearresult;
+ krb5_error *krberror;
+ krb5_replay_data replay;
+ krb5_keyblock *tmp;
+ int local_result_code;
+
+ if (packet->length < 4)
+ /* either this, or the server is printing bad messages,
+ or the caller passed in garbage */
+ return(KRB5KRB_AP_ERR_MODIFIED);
+
+ ptr = packet->data;
+
+ /* verify length */
+
+ plen = (*ptr++ & 0xff);
+ plen = (plen<<8) | (*ptr++ & 0xff);
+
+ if (plen != packet->length)
+ {
/*
- * either this, or the server is printing bad messages,
- * or the caller passed in garbage
+ * MS KDCs *may* send back a KRB_ERROR. Although
+ * not 100% correct via RFC3244, it's something
+ * we can workaround here.
*/
- return (KRB5KRB_AP_ERR_MODIFIED);
+ if (krb5_is_krb_error(packet)) {
- ptr = packet->data;
+ if ((ret = krb5_rd_error(context, packet, &krberror)))
+ return(ret);
- /* verify length */
- plen = (*ptr++ & 0xff);
- plen = (plen<<8) | (*ptr++ & 0xff);
+ if (krberror->e_data.data == NULL) {
+ ret = ERROR_TABLE_BASE_krb5 + (krb5_error_code) krberror->error;
+ krb5_free_error(context, krberror);
+ return (ret);
+ }
+ }
+ else
+ {
+ return(KRB5KRB_AP_ERR_MODIFIED);
+ }
+ }
+
- if (plen != packet->length)
- return (KRB5KRB_AP_ERR_MODIFIED);
+ /* verify version number */
- /* verify version number */
- vno = (*ptr++ & 0xff);
- vno = (vno<<8) | (*ptr++ & 0xff);
+ vno = (*ptr++ & 0xff);
+ vno = (vno<<8) | (*ptr++ & 0xff);
/*
* when the servers update to v2 of the protocol,
@@ -143,69 +147,71 @@ krb5_data *result_data;
if (vno != 1 && vno != 2)
return (KRB5KDC_ERR_BAD_PVNO);
- /* read, check ap-rep length */
- ap_rep.length = (*ptr++ & 0xff);
- ap_rep.length = (ap_rep.length<<8) | (*ptr++ & 0xff);
+ /* read, check ap-rep length */
- if (ptr + ap_rep.length >= packet->data + packet->length)
- return (KRB5KRB_AP_ERR_MODIFIED);
+ ap_rep.length = (*ptr++ & 0xff);
+ ap_rep.length = (ap_rep.length<<8) | (*ptr++ & 0xff);
- if (ap_rep.length) {
- /* verify ap_rep */
- ap_rep.data = ptr;
- ptr += ap_rep.length;
+ if (ptr + ap_rep.length >= packet->data + packet->length)
+ return(KRB5KRB_AP_ERR_MODIFIED);
- /*
- * Save send_subkey to later smash recv_subkey.
- */
- ret = krb5_auth_con_getsendsubkey(context, auth_context, &tmp);
- if (ret)
- return (ret);
-
- if (ret = krb5_rd_rep(context, auth_context, &ap_rep,
- &ap_rep_enc)) {
- krb5_free_keyblock(context, tmp);
- return (ret);
- }
+ if (ap_rep.length) {
+ /* verify ap_rep */
+ ap_rep.data = ptr;
+ ptr += ap_rep.length;
- krb5_free_ap_rep_enc_part(context, ap_rep_enc);
+ /*
+ * Save send_subkey to later smash recv_subkey.
+ */
+ ret = krb5_auth_con_getsendsubkey(context, auth_context, &tmp);
+ if (ret)
+ return ret;
+
+ ret = krb5_rd_rep(context, auth_context, &ap_rep, &ap_rep_enc);
+ if (ret) {
+ krb5_free_keyblock(context, tmp);
+ return(ret);
+ }
- /* extract and decrypt the result */
- cipherresult.data = ptr;
- cipherresult.length = (packet->data + packet->length) - ptr;
+ krb5_free_ap_rep_enc_part(context, ap_rep_enc);
- /*
- * Smash recv_subkey to be send_subkey, per spec.
- */
- ret = krb5_auth_con_setrecvsubkey(context, auth_context, tmp);
- krb5_free_keyblock(context, tmp);
- if (ret)
- return (ret);
+ /* extract and decrypt the result */
- ret = krb5_rd_priv(context, auth_context, &cipherresult,
- &clearresult, &replay);
+ cipherresult.data = ptr;
+ cipherresult.length = (packet->data + packet->length) - ptr;
- if (ret)
- return (ret);
- } else {
- cipherresult.data = ptr;
- cipherresult.length = (packet->data + packet->length) - ptr;
+ /*
+ * Smash recv_subkey to be send_subkey, per spec.
+ */
+ ret = krb5_auth_con_setrecvsubkey(context, auth_context, tmp);
+ krb5_free_keyblock(context, tmp);
+ if (ret)
+ return ret;
- if (ret = krb5_rd_error(context, &cipherresult, &krberror))
- return (ret);
+ ret = krb5_rd_priv(context, auth_context, &cipherresult, &clearresult,
+ &replay);
- clearresult = krberror->e_data;
- }
+ if (ret)
+ return(ret);
+ } else {
+ cipherresult.data = ptr;
+ cipherresult.length = (packet->data + packet->length) - ptr;
- if (clearresult.length < 2) {
- ret = KRB5KRB_AP_ERR_MODIFIED;
- goto cleanup;
- }
+ if ((ret = krb5_rd_error(context, &cipherresult, &krberror)))
+ return(ret);
+
+ clearresult = krberror->e_data;
+ }
- ptr = clearresult.data;
+ if (clearresult.length < 2) {
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ goto cleanup;
+ }
- local_result_code = (*ptr++ & 0xff);
- local_result_code = (local_result_code<<8) | (*ptr++ & 0xff);
+ ptr = clearresult.data;
+
+ local_result_code = (*ptr++ & 0xff);
+ local_result_code = (local_result_code<<8) | (*ptr++ & 0xff);
if (result_code)
*result_code = local_result_code;
@@ -214,41 +220,40 @@ krb5_data *result_data;
* Make sure the result code is in range for this
* protocol.
*/
- if ((local_result_code < KRB5_KPASSWD_SUCCESS) ||
- (local_result_code > KRB5_KPASSWD_ETYPE_NOSUPP)) {
- ret = KRB5KRB_AP_ERR_MODIFIED;
- goto cleanup;
+ if ((local_result_code < KRB5_KPASSWD_SUCCESS) ||
+ (local_result_code > KRB5_KPASSWD_ETYPE_NOSUPP)) {
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ goto cleanup;
+ }
+
+ /* all success replies should be authenticated/encrypted */
+
+ if ((ap_rep.length == 0) && (local_result_code == KRB5_KPASSWD_SUCCESS)) {
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ goto cleanup;
+ }
+
+ result_data->length = (clearresult.data + clearresult.length) - ptr;
+
+ if (result_data->length) {
+ result_data->data = (char *) malloc(result_data->length);
+ if (result_data->data == NULL) {
+ ret = ENOMEM;
+ goto cleanup;
}
+ memcpy(result_data->data, ptr, result_data->length);
+ } else {
+ result_data->data = NULL;
+ }
-
- /* all success replies should be authenticated/encrypted */
- if ((ap_rep.length == 0) &&
- (local_result_code == KRB5_KPASSWD_SUCCESS)) {
- ret = KRB5KRB_AP_ERR_MODIFIED;
- goto cleanup;
- }
-
- result_data->length = (clearresult.data + clearresult.length) - ptr;
-
- if (result_data->length) {
- result_data->data = (char *)malloc(result_data->length);
- if (result_data->data == NULL) {
- ret = ENOMEM;
- goto cleanup;
- }
- memcpy(result_data->data, ptr, result_data->length);
- } else {
- result_data->data = NULL;
- }
-
- ret = 0;
+ ret = 0;
cleanup:
- if (ap_rep.length) {
- krb5_xfree(clearresult.data);
- } else {
- krb5_free_error(context, krberror);
- }
+ if (ap_rep.length) {
+ krb5_xfree(clearresult.data);
+ } else {
+ krb5_free_error(context, krberror);
+ }
- return (ret);
+ return(ret);
}
diff --git a/usr/src/lib/krb5/kadm5/clnt/client_init.c b/usr/src/lib/krb5/kadm5/clnt/client_init.c
index b7d186701e..15fdbebea8 100644
--- a/usr/src/lib/krb5/kadm5/clnt/client_init.c
+++ b/usr/src/lib/krb5/kadm5/clnt/client_init.c
@@ -1,11 +1,13 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- *
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/client_init.c,v 1.13.2.2 2000/05/09 13:17:14 raeburn Exp $
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
+
+
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
+ */
/*
* Copyright (C) 1998 by the FundsXpress, INC.
@@ -33,13 +35,6 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
-
-/*
- * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
- *
- * $Header: /afs/athena.mit.edu/astaff/project/krbdev/.cvsroot/src/lib/kadm5/clnt/client_init.c,v 1.6 1996/11/07 17:13:44 tytso Exp $
- */
-
#include <stdio.h>
#include <netdb.h>
#include "autoconf.h"
@@ -545,27 +540,15 @@ _kadm5_initialize_rpcsec_gss_handle(kadm5_server_handle_t handle,
goto cleanup;
}
- r = init_1(&handle->api_version, handle->clnt, &rpc_err_code);
+ r = init_2(&handle->api_version, handle->clnt);
+ /* Solaris Kerberos: 163 resync */
if (r == NULL) {
ADMIN_LOGO(LOG_ERR, dgettext(TEXT_DOMAIN,
"error during admin api initialization\n"));
-
- if (rpc_err_code == RPC_CANTENCODEARGS) {
- ADMIN_LOGO(LOG_ERR, dgettext(TEXT_DOMAIN,
- "encryption needed to encode RPC data may not be "
- "installed/configured on this system"));
- code = KADM5_RPC_ERROR_CANTENCODEARGS;
- } else if (rpc_err_code == RPC_CANTDECODEARGS) {
- ADMIN_LOGO(LOG_ERR, dgettext(TEXT_DOMAIN,
- "encryption needed to decode RPC data may not be "
- "installed/configured on the server"));
- code = KADM5_RPC_ERROR_CANTDECODEARGS;
- } else
- code = KADM5_RPC_ERROR;
-
+ code = KADM5_RPC_ERROR;
goto error;
-
}
+
if (r->code) {
code = r->code;
ADMIN_LOG(LOG_ERR,
@@ -701,11 +684,8 @@ static kadm5_ret_t _kadm5_init_any(char *client_name,
return KADM5_BAD_CLIENT_PARAMS;
}
- if ((code = kadm5_get_config_params(handle->context,
- DEFAULT_PROFILE_PATH,
- "KRB5_CONFIG",
- params_in,
- &handle->params))) {
+ if ((code = kadm5_get_config_params(handle->context, 0,
+ params_in, &handle->params))) {
krb5_free_context(handle->context);
free(handle->lhandle);
free(handle);
@@ -959,8 +939,10 @@ static kadm5_ret_t _kadm5_init_any(char *client_name,
* to prevent a double free in the "error" code.
*/
if (code != 0) {
- if (init_type != INIT_CREDS)
+ if (init_type != INIT_CREDS) {
krb5_cc_close(handle->context, ccache);
+ ccache = NULL;
+ }
goto error;
}
}
diff --git a/usr/src/lib/krb5/kadm5/clnt/client_internal.h b/usr/src/lib/krb5/kadm5/clnt/client_internal.h
index ff739b4b91..d8e9f885da 100644
--- a/usr/src/lib/krb5/kadm5/clnt/client_internal.h
+++ b/usr/src/lib/krb5/kadm5/clnt/client_internal.h
@@ -1,12 +1,11 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef __KADM5_CLIENT_INTERNAL_H__
#define __KADM5_CLIENT_INTERNAL_H__
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -29,9 +28,9 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/client_internal.h,v 1.1 1996/07/24 22:22:43 tlyu Exp $
+ * $Header$
*
- * $Log: client_internal.h,v $
+ * $Log$
* Revision 1.1 1996/07/24 22:22:43 tlyu
* * Makefile.in, configure.in: break out client lib into a
* subdirectory
@@ -91,6 +90,7 @@
extern "C" {
#endif
+
#include "admin_internal.h"
typedef struct _kadm5_server_handle_t {
@@ -101,6 +101,7 @@ typedef struct _kadm5_server_handle_t {
int destroy_cache;
CLIENT * clnt;
krb5_context context;
+ /* Solaris Kerberos */
gss_cred_id_t my_cred;
kadm5_config_params params;
struct _kadm5_server_handle_t *lhandle;
diff --git a/usr/src/lib/krb5/kadm5/clnt/client_principal.c b/usr/src/lib/krb5/kadm5/clnt/client_principal.c
index dc06bc5fe7..9aea25ff56 100644
--- a/usr/src/lib/krb5/kadm5/clnt/client_principal.c
+++ b/usr/src/lib/krb5/kadm5/clnt/client_principal.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -26,11 +25,11 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/client_principal.c,v 1.11 2004/06/16 03:11:53 tlyu Exp $
+ * $Header$
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/client_principal.c,v 1.11 2004/06/16 03:11:53 tlyu Exp $";
+static char *rcsid = "$Header$";
#endif
#include <rpc/rpc.h> /* SUNWresync121 XXX */
@@ -39,6 +38,7 @@ static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/client_princi
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
+#include <errno.h>
#include "client_internal.h"
#ifdef DEBUG /* SUNWresync14 XXX */
@@ -95,7 +95,7 @@ kadm5_create_principal(void *server_handle,
arg.rec.tl_data = NULL;
}
- r = create_principal_1(&arg, handle->clnt);
+ r = create_principal_2(&arg, handle->clnt);
if (handle->api_version == KADM5_API_VERSION_1)
krb5_free_principal(handle->context, arg.rec.mod_name);
@@ -156,7 +156,7 @@ kadm5_create_principal_3(void *server_handle,
arg.rec.tl_data = NULL;
}
- r = create_principal3_1(&arg, handle->clnt);
+ r = create_principal3_2(&arg, handle->clnt);
if (handle->api_version == KADM5_API_VERSION_1)
krb5_free_principal(handle->context, arg.rec.mod_name);
@@ -179,7 +179,7 @@ kadm5_delete_principal(void *server_handle, krb5_principal principal)
return EINVAL;
arg.princ = principal;
arg.api_version = handle->api_version;
- r = delete_principal_1(&arg, handle->clnt);
+ r = delete_principal_2(&arg, handle->clnt);
if(r == NULL)
eret();
return r->code;
@@ -228,7 +228,7 @@ kadm5_modify_principal(void *server_handle,
} else
arg.rec.mod_name = NULL;
- r = modify_principal_1(&arg, handle->clnt);
+ r = modify_principal_2(&arg, handle->clnt);
if (handle->api_version == KADM5_API_VERSION_1)
krb5_free_principal(handle->context, arg.rec.mod_name);
@@ -257,7 +257,7 @@ kadm5_get_principal(void *server_handle,
else
arg.mask = mask;
arg.api_version = handle->api_version;
- r = get_principal_1(&arg, handle->clnt);
+ r = get_principal_2(&arg, handle->clnt);
if(r == NULL)
eret();
if (handle->api_version == KADM5_API_VERSION_1) {
@@ -297,7 +297,7 @@ kadm5_get_principals(void *server_handle,
return EINVAL;
arg.exp = exp;
arg.api_version = handle->api_version;
- r = get_princs_1(&arg, handle->clnt);
+ r = get_princs_2(&arg, handle->clnt);
if(r == NULL)
eret();
if(r->code == 0) {
@@ -326,7 +326,7 @@ kadm5_rename_principal(void *server_handle,
arg.api_version = handle->api_version;
if (source == NULL || dest == NULL)
return EINVAL;
- r = rename_principal_1(&arg, handle->clnt);
+ r = rename_principal_2(&arg, handle->clnt);
if(r == NULL)
eret();
return r->code;
@@ -348,7 +348,7 @@ kadm5_chpass_principal(void *server_handle,
if(princ == NULL)
return EINVAL;
- r = chpass_principal_1(&arg, handle->clnt);
+ r = chpass_principal_2(&arg, handle->clnt);
if(r == NULL)
eret();
return r->code;
@@ -375,7 +375,7 @@ kadm5_chpass_principal_3(void *server_handle,
if(princ == NULL)
return EINVAL;
- r = chpass_principal3_1(&arg, handle->clnt);
+ r = chpass_principal3_2(&arg, handle->clnt);
if(r == NULL)
eret();
return r->code;
@@ -398,7 +398,7 @@ kadm5_setv4key_principal(void *server_handle,
if(princ == NULL || keyblock == NULL)
return EINVAL;
- r = setv4key_principal_1(&arg, handle->clnt);
+ r = setv4key_principal_2(&arg, handle->clnt);
if(r == NULL)
eret();
return r->code;
@@ -423,7 +423,7 @@ kadm5_setkey_principal(void *server_handle,
if(princ == NULL || keyblocks == NULL)
return EINVAL;
- r = setkey_principal_1(&arg, handle->clnt);
+ r = setkey_principal_2(&arg, handle->clnt);
if(r == NULL)
eret();
return r->code;
@@ -453,7 +453,7 @@ kadm5_setkey_principal_3(void *server_handle,
if(princ == NULL || keyblocks == NULL)
return EINVAL;
- r = setkey_principal3_1(&arg, handle->clnt);
+ r = setkey_principal3_2(&arg, handle->clnt);
if(r == NULL)
eret();
return r->code;
@@ -497,7 +497,7 @@ kadm5_randkey_principal_old(void *server_handle,
if(princ == NULL)
return EINVAL;
- r = chrand_principal_1(&arg, handle->clnt);
+ r = chrand_principal_2(&arg, handle->clnt);
if (r == NULL)
return KADM5_RPC_ERROR;
if (handle->api_version == KADM5_API_VERSION_1) {
@@ -537,7 +537,7 @@ kadm5_randkey_principal_3(void *server_handle,
kadm5_server_handle_t handle = server_handle;
int i, ret;
- /* For safety */
+ /* Solaris Kerberos - For safety */
if (n_keys)
*n_keys = 0;
if (key)
@@ -553,7 +553,7 @@ kadm5_randkey_principal_3(void *server_handle,
if(princ == NULL)
return EINVAL;
- r = chrand_principal3_1(&arg, handle->clnt);
+ r = chrand_principal3_2(&arg, handle->clnt);
if(r == NULL)
eret();
if (handle->api_version == KADM5_API_VERSION_1) {
@@ -589,7 +589,7 @@ kadm5_randkey_principal(void *server_handle,
krb5_principal princ,
krb5_keyblock **key, int *n_keys)
{
-
+ /* Solaris Kerberos */
kadm5_ret_t kret;
/*
diff --git a/usr/src/lib/krb5/kadm5/clnt/client_rpc.c b/usr/src/lib/krb5/kadm5/clnt/client_rpc.c
index 1e029e1bf7..407c85b4cd 100644
--- a/usr/src/lib/krb5/kadm5/clnt/client_rpc.c
+++ b/usr/src/lib/krb5/kadm5/clnt/client_rpc.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -35,375 +34,380 @@
static struct timeval TIMEOUT = { 25, 0 };
generic_ret *
-create_principal_1(argp, clnt)
- cprinc_arg *argp;
- CLIENT *clnt;
+create_principal_2(cprinc_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, CREATE_PRINCIPAL, (xdrproc_t) xdr_cprinc_arg,
- (caddr_t) argp, (xdrproc_t) xdr_generic_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, CREATE_PRINCIPAL,
+ (xdrproc_t) xdr_cprinc_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-create_principal3_1(argp, clnt)
- cprinc3_arg *argp;
- CLIENT *clnt;
+create_principal3_2(cprinc3_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, CREATE_PRINCIPAL3, xdr_cprinc3_arg,
- (caddr_t) argp, /* SUNWresync121 XXX */
- xdr_generic_ret,
- (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, CREATE_PRINCIPAL3,
+ (xdrproc_t) xdr_cprinc3_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-delete_principal_1(argp, clnt)
- dprinc_arg *argp;
- CLIENT *clnt;
+delete_principal_2(dprinc_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, DELETE_PRINCIPAL, xdr_dprinc_arg, (caddr_t) argp,
- xdr_generic_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, DELETE_PRINCIPAL,
+ (xdrproc_t) xdr_dprinc_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-modify_principal_1(argp, clnt)
- mprinc_arg *argp;
- CLIENT *clnt;
+modify_principal_2(mprinc_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, MODIFY_PRINCIPAL, xdr_mprinc_arg, (caddr_t) argp,
- xdr_generic_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MODIFY_PRINCIPAL,
+ (xdrproc_t) xdr_mprinc_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-rename_principal_1(argp, clnt)
- rprinc_arg *argp;
- CLIENT *clnt;
+rename_principal_2(rprinc_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, RENAME_PRINCIPAL, xdr_rprinc_arg, (caddr_t) argp,
- xdr_generic_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, RENAME_PRINCIPAL,
+ (xdrproc_t) xdr_rprinc_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
gprinc_ret *
-get_principal_1(argp, clnt)
- gprinc_arg *argp;
- CLIENT *clnt;
+get_principal_2(gprinc_arg *argp, CLIENT *clnt)
{
- static gprinc_ret res;
+ static gprinc_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, GET_PRINCIPAL, xdr_gprinc_arg, (caddr_t) argp,
- xdr_gprinc_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, GET_PRINCIPAL,
+ (xdrproc_t) xdr_gprinc_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_gprinc_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
gprincs_ret *
-get_princs_1(argp, clnt)
- gprincs_arg *argp;
- CLIENT *clnt;
+get_princs_2(gprincs_arg *argp, CLIENT *clnt)
{
- static gprincs_ret res;
+ static gprincs_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, GET_PRINCS, xdr_gprincs_arg, (caddr_t) argp,
- xdr_gprincs_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, GET_PRINCS,
+ (xdrproc_t) xdr_gprincs_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_gprincs_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-chpass_principal_1(argp, clnt)
- chpass_arg *argp;
- CLIENT *clnt;
+chpass_principal_2(chpass_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, CHPASS_PRINCIPAL, xdr_chpass_arg, (caddr_t) argp,
- xdr_generic_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, CHPASS_PRINCIPAL,
+ (xdrproc_t) xdr_chpass_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-chpass_principal3_1(argp, clnt)
- chpass3_arg *argp;
- CLIENT *clnt;
+chpass_principal3_2(chpass3_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, CHPASS_PRINCIPAL3, xdr_chpass3_arg,
- (caddr_t) argp, /* SUNWresync 121 XXX */
- xdr_generic_ret, (caddr_t) &res,
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, CHPASS_PRINCIPAL3,
+ (xdrproc_t) xdr_chpass3_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-setv4key_principal_1(argp, clnt)
- setv4key_arg *argp;
- CLIENT *clnt;
+setv4key_principal_2(setv4key_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, SETV4KEY_PRINCIPAL, xdr_setv4key_arg,
- (caddr_t) argp, /* SUNWresync121 XXX */
- xdr_generic_ret, (caddr_t) &res,
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, SETV4KEY_PRINCIPAL,
+ (xdrproc_t) xdr_setv4key_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-setkey_principal_1(argp, clnt)
- setkey_arg *argp;
- CLIENT *clnt;
+setkey_principal_2(setkey_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, SETKEY_PRINCIPAL, xdr_setkey_arg,
- (caddr_t) argp, /* SUNWresync121 XXX */
- xdr_generic_ret, (caddr_t) &res,
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, SETKEY_PRINCIPAL,
+ (xdrproc_t) xdr_setkey_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-setkey_principal3_1(argp, clnt)
- setkey3_arg *argp;
- CLIENT *clnt;
+setkey_principal3_2(setkey3_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, SETKEY_PRINCIPAL3, xdr_setkey3_arg,
- (caddr_t) argp, /* SUNWresync121 XXX */
- xdr_generic_ret, (caddr_t) &res,
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, SETKEY_PRINCIPAL3,
+ (xdrproc_t) xdr_setkey3_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
chrand_ret *
-chrand_principal_1(argp, clnt)
- chrand_arg *argp;
- CLIENT *clnt;
+chrand_principal_2(chrand_arg *argp, CLIENT *clnt)
{
- static chrand_ret res;
+ static chrand_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, CHRAND_PRINCIPAL, xdr_chrand_arg, (caddr_t) argp,
- xdr_chrand_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, CHRAND_PRINCIPAL,
+ (xdrproc_t) xdr_chrand_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_chrand_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
chrand_ret *
-chrand_principal3_1(argp, clnt)
- chrand3_arg *argp;
- CLIENT *clnt;
+chrand_principal3_2(chrand3_arg *argp, CLIENT *clnt)
{
- static chrand_ret res;
+ static chrand_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, CHRAND_PRINCIPAL3, xdr_chrand3_arg,
- (caddr_t) argp, /* SUNWresync121 XXX */
- xdr_chrand_ret, (caddr_t) &res,
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, CHRAND_PRINCIPAL3,
+ (xdrproc_t) xdr_chrand3_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_chrand_ret, (caddr_t) &clnt_res,
TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-create_policy_1(argp, clnt)
- cpol_arg *argp;
- CLIENT *clnt;
+create_policy_2(cpol_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, CREATE_POLICY, xdr_cpol_arg, (caddr_t) argp,
- xdr_generic_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, CREATE_POLICY,
+ (xdrproc_t) xdr_cpol_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-delete_policy_1(argp, clnt)
- dpol_arg *argp;
- CLIENT *clnt;
+delete_policy_2(dpol_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, DELETE_POLICY, xdr_dpol_arg, (caddr_t) argp,
- xdr_generic_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, DELETE_POLICY,
+ (xdrproc_t) xdr_dpol_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-modify_policy_1(argp, clnt)
- mpol_arg *argp;
- CLIENT *clnt;
+modify_policy_2(mpol_arg *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, MODIFY_POLICY, xdr_mpol_arg, (caddr_t) argp,
- xdr_generic_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MODIFY_POLICY,
+ (xdrproc_t) xdr_mpol_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
gpol_ret *
-get_policy_1(argp, clnt)
- gpol_arg *argp;
- CLIENT *clnt;
+get_policy_2(gpol_arg *argp, CLIENT *clnt)
{
- static gpol_ret res;
+ static gpol_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, GET_POLICY, xdr_gpol_arg, (caddr_t) argp,
- xdr_gpol_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, GET_POLICY,
+ (xdrproc_t) xdr_gpol_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_gpol_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
gpols_ret *
-get_pols_1(argp, clnt)
- gpols_arg *argp;
- CLIENT *clnt;
+get_pols_2(gpols_arg *argp, CLIENT *clnt)
{
- static gpols_ret res;
+ static gpols_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, GET_POLS, xdr_gpols_arg, (caddr_t) argp,
- xdr_gpols_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, GET_POLS,
+ (xdrproc_t) xdr_gpols_arg, (caddr_t) argp,
+ (xdrproc_t) xdr_gpols_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
-getprivs_ret *get_privs_1(argp, clnt)
- void *argp;
- CLIENT *clnt;
+getprivs_ret *
+get_privs_2(void *argp, CLIENT *clnt)
{
- static getprivs_ret res;
+ static getprivs_ret clnt_res;
+ /* Solaris Kerberos */
if (clnt == NULL)
return (NULL);
- memset((char *)&res, 0, sizeof(res));
- if (clnt_call(clnt, GET_PRIVS, xdr_u_int, (caddr_t) argp,
- xdr_getprivs_ret, (caddr_t) &res, TIMEOUT) != RPC_SUCCESS) {
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, GET_PRIVS,
+ (xdrproc_t) xdr_u_int, (caddr_t) argp,
+ (xdrproc_t) xdr_getprivs_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
generic_ret *
-init_1(argp, clnt, rpc_err_code)
- void *argp;
- CLIENT *clnt;
- enum clnt_stat *rpc_err_code;
+init_2(void *argp, CLIENT *clnt)
{
- static generic_ret res;
+ static generic_ret clnt_res;
- enum clnt_stat retval;
-
- if (clnt == NULL)
- return (NULL);
- memset((char *)&res, 0, sizeof(res));
- retval = clnt_call(clnt, INIT, xdr_u_int, (caddr_t) argp,
- xdr_generic_ret, (caddr_t) &res, TIMEOUT);
+ /* Solaris Kerberos */
+ if (clnt == NULL)
+ return (NULL);
- if (retval != RPC_SUCCESS) {
- *rpc_err_code = retval;
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, INIT,
+ (xdrproc_t) xdr_u_int, (caddr_t) argp,
+ (xdrproc_t) xdr_generic_ret, (caddr_t) &clnt_res,
+ TIMEOUT) != RPC_SUCCESS) {
return (NULL);
}
- return (&res);
+ return (&clnt_res);
}
diff --git a/usr/src/lib/krb5/kadm5/clnt/clnt_policy.c b/usr/src/lib/krb5/kadm5/clnt/clnt_policy.c
index 15ee88ef8a..2c97b16723 100644
--- a/usr/src/lib/krb5/kadm5/clnt/clnt_policy.c
+++ b/usr/src/lib/krb5/kadm5/clnt/clnt_policy.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -26,11 +25,11 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/clnt_policy.c,v 1.4 2004/02/19 01:22:26 raeburn Exp $
+ * $Header$
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/clnt_policy.c,v 1.2 1998/02/14 02:32:57 tlyu Exp $";
+static char *rcsid = "$Header$";
#endif
#include <rpc/rpc.h> /* SUNWresync121 XXX */
@@ -39,6 +38,7 @@ static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/clnt_policy.c
#include "client_internal.h"
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
kadm5_ret_t
kadm5_create_policy(void *server_handle,
@@ -56,9 +56,10 @@ kadm5_create_policy(void *server_handle,
arg.mask = mask;
arg.api_version = handle->api_version;
memcpy(&arg.rec, policy, sizeof(kadm5_policy_ent_rec));
- r = create_policy_1(&arg, handle->clnt);
+ r = create_policy_2(&arg, handle->clnt);
if(r == NULL)
return KADM5_RPC_ERROR;
+
return r->code;
}
@@ -77,9 +78,10 @@ kadm5_delete_policy(void *server_handle, char *name)
arg.name = name;
arg.api_version = handle->api_version;
- r = delete_policy_1(&arg, handle->clnt);
+ r = delete_policy_2(&arg, handle->clnt);
if(r == NULL)
return KADM5_RPC_ERROR;
+
return r->code;
}
@@ -100,9 +102,10 @@ kadm5_modify_policy(void *server_handle,
arg.api_version = handle->api_version;
memcpy(&arg.rec, policy, sizeof(kadm5_policy_ent_rec));
- r = modify_policy_1(&arg, handle->clnt);
+ r = modify_policy_2(&arg, handle->clnt);
if(r == NULL)
return KADM5_RPC_ERROR;
+
return r->code;
}
@@ -121,7 +124,7 @@ kadm5_get_policy(void *server_handle, char *name, kadm5_policy_ent_t ent)
if(name == NULL)
return EINVAL;
- r = get_policy_1(&arg, handle->clnt);
+ r = get_policy_2(&arg, handle->clnt);
if(r == NULL)
return KADM5_RPC_ERROR;
if (handle->api_version == KADM5_API_VERSION_1) {
@@ -158,7 +161,7 @@ kadm5_get_policies(void *server_handle,
return EINVAL;
arg.exp = exp;
arg.api_version = handle->api_version;
- r = get_pols_1(&arg, handle->clnt);
+ r = get_pols_2(&arg, handle->clnt);
if(r == NULL)
return KADM5_RPC_ERROR;
if(r->code == 0) {
diff --git a/usr/src/lib/krb5/kadm5/clnt/clnt_privs.c b/usr/src/lib/krb5/kadm5/clnt/clnt_privs.c
index 0552198f4a..9fab0e48bd 100644
--- a/usr/src/lib/krb5/kadm5/clnt/clnt_privs.c
+++ b/usr/src/lib/krb5/kadm5/clnt/clnt_privs.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -26,64 +25,13 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
*
- * $Id: clnt_privs.c,v 1.2 1998/02/14 02:32:58 tlyu Exp $
- * $Source: /cvs/krbdev/krb5/src/lib/kadm5/clnt/clnt_privs.c,v $
+ * $Id: clnt_privs.c 18130 2006-06-14 21:42:02Z raeburn $
+ * $Source$
*
- * $Log: clnt_privs.c,v $
- * Revision 1.2 1998/02/14 02:32:58 tlyu
- * * client_init.c:
- * * client_principal.c:
- * * client_rpc.c:
- * * clnt_policy.c:
- * * clnt_privs.c: Update header locations.
- *
- * * Makefile.in (LIBMAJOR): Bump major version to reflect change in
- * rpc library.
- *
- * Revision 1.1 1996/07/24 22:22:48 tlyu
- * * Makefile.in, configure.in: break out client lib into a
- * subdirectory
- *
- * Revision 1.6 1996/07/22 20:35:57 marc
- * this commit includes all the changes on the OV_9510_INTEGRATION and
- * OV_MERGE branches. This includes, but is not limited to, the new openvision
- * admin system, and major changes to gssapi to add functionality, and bring
- * the implementation in line with rfc1964. before committing, the
- * code was built and tested for netbsd and solaris.
- *
- * Revision 1.5.4.1 1996/07/18 03:08:45 marc
- * merged in changes from OV_9510_BP to OV_9510_FINAL1
- *
- * Revision 1.5.2.1 1996/06/20 02:16:53 marc
- * File added to the repository on a branch
- *
- * Revision 1.5 1996/05/17 21:36:50 bjaspan
- * rename to kadm5, begin implementing version 2
- *
- * Revision 1.4 1996/05/16 21:45:51 bjaspan
- * u_int32 -> long, add krb5_context
- *
- * Revision 1.3 1994/09/20 16:25:05 bjaspan
- * [secure-admin/2436: API versioning fixes to various admin files]
- * [secure-releng/2502: audit secure-admin/2436: random API versioning fixes]
- *
- * Sandbox:
- *
- * Unnecessary variable initialization removed.
- *
- * Revision 1.3 1994/09/12 20:26:39 jik
- * Unnecessary variable initialization removed.
- *
- * Revision 1.2 1994/08/16 18:52:02 jik
- * Versioning changes.
- *
- * Revision 1.1 1993/11/10 23:10:39 bjaspan
- * Initial revision
- *
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/clnt/clnt_privs.c,v 1.2 1998/02/14 02:32:58 tlyu Exp $";
+static char *rcsid = "$Header$";
#endif
#include <rpc/rpc.h> /* SUNWresync121 XXX */
@@ -96,10 +44,11 @@ kadm5_ret_t kadm5_get_privs(void *server_handle, long *privs)
getprivs_ret *r;
kadm5_server_handle_t handle = server_handle;
- r = get_privs_1(&handle->api_version, handle->clnt);
+ r = get_privs_2(&handle->api_version, handle->clnt);
if (r == NULL)
return KADM5_RPC_ERROR;
else if (r->code == KADM5_OK)
*privs = r->privs;
+
return r->code;
}
diff --git a/usr/src/lib/krb5/kadm5/clnt/logger.c b/usr/src/lib/krb5/kadm5/clnt/logger.c
index 8dcc0326bd..db4325f699 100644
--- a/usr/src/lib/krb5/kadm5/clnt/logger.c
+++ b/usr/src/lib/krb5/kadm5/clnt/logger.c
@@ -1,4 +1,9 @@
/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
* lib/kadm/logger.c
*
* Copyright 1995 by the Massachusetts Institute of Technology.
@@ -16,20 +21,15 @@
* 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. M.I.T. makes no representations about the suitability of
+ * 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.
*
*/
-/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-
/* KADM5 wants non-syslog log files to contain syslog-like entries */
#define VERBOSE_LOGS
@@ -41,9 +41,18 @@
#include "com_err.h"
#include <stdio.h>
#include <ctype.h>
+#include <ctype.h>
+#ifdef HAVE_SYSLOG_H
#include <syslog.h>
+#endif /* HAVE_SYSLOG_H */
+#ifdef HAVE_STDARG_H
#include <stdarg.h>
+#else /* HAVE_STDARG_H */
+#include <varargs.h>
+#endif /* HAVE_STDARG_H */
#include <libintl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
#define KRB5_KLOG_MAX_ERRMSG_SIZE 2048
#ifndef MAXHOSTNAMELEN
@@ -196,7 +205,6 @@ struct log_control {
char *log_whoami;
char *log_hostname;
krb5_boolean log_opened;
-
};
static struct log_control log_control = {
@@ -214,8 +222,8 @@ static struct log_entry def_log_entry;
*/
#define DEVICE_OPEN(d, m) fopen(d, m)
#define CONSOLE_OPEN(m) fopen("/dev/console", m)
-#define DEVICE_PRINT(f, m) ((fprintf(f, m) >= 0) ? \
- (fprintf(f, "\r\n"), fflush(f), 0) : \
+#define DEVICE_PRINT(f, m) ((fprintf(f, "%s\r\n", m) >= 0) ? \
+ (fflush(f), 0) : \
-1)
#define DEVICE_CLOSE(d) fclose(d)
@@ -236,6 +244,8 @@ klog_rotate(struct log_entry *le)
char *tmp;
FILE *fp;
int num_vers;
+ mode_t old_umask;
+
/*
* By default we don't rotate.
@@ -304,17 +314,18 @@ klog_rotate(struct log_entry *le)
*/
le->lfu_last_rotated = t;
+ /*
+ * Default log file creation mode should be read-only
+ * by owner(root), but the admin can override with
+ * chmod(1) if desired.
+ */
+
+ old_umask = umask(077);
fp = fopen(old_name, le->lfu_fopen_mode);
- if (fp != NULL) {
+ umask(old_umask);
- /* Set the permissions to 644 */
- if (fchmod(fileno(fp),
- S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) {
- fprintf(stderr,
-gettext("During rotate, couldn't set permissions for log file %s: %s\n"),
- old_name, error_message(errno));
- }
+ if (fp != NULL) {
(void) fclose(le->lfu_filep);
le->lfu_filep = fp;
@@ -347,17 +358,16 @@ gettext("During rotate, couldn't set permissions for log file %s: %s\n"),
* klog_com_err_proc() - Handle com_err(3) messages as specified by the
* profile.
*/
+static krb5_context err_context;
static void
-klog_com_err_proc(whoami, code, format, ap)
- const char *whoami;
- long code;
- const char *format;
- va_list ap;
+klog_com_err_proc(const char *whoami, long code, const char *format, va_list ap)
{
char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
int lindex;
- char *actual_format;
+ const char *actual_format;
+#ifdef HAVE_SYSLOG
int log_pri = -1;
+#endif /* HAVE_SYSLOG */
char *cp;
char *syslogp;
@@ -371,15 +381,18 @@ klog_com_err_proc(whoami, code, format, ap)
/* If reporting an error message, separate it. */
if (code) {
- outbuf[sizeof(outbuf) - 1] = '\0';
+ const char *emsg;
+ outbuf[sizeof(outbuf) - 1] = '\0';
- strncat(outbuf, error_message(code),
- sizeof(outbuf) - 1 - strlen(outbuf));
+ emsg = krb5_get_error_message (err_context, code);
+ strncat(outbuf, emsg, sizeof(outbuf) - 1 - strlen(outbuf));
strncat(outbuf, " - ", sizeof(outbuf) - 1 - strlen(outbuf));
+ krb5_free_error_message(err_context, emsg);
}
cp = &outbuf[strlen(outbuf)];
- actual_format = (char *) format;
+ actual_format = format;
+#ifdef HAVE_SYSLOG
/*
* This is an unpleasant hack. If the first character is less than
* 8, then we assume that it is a priority.
@@ -389,38 +402,61 @@ klog_com_err_proc(whoami, code, format, ap)
* intermediate representation.
*/
if ((((unsigned char) *format) > 0) && (((unsigned char) *format) <= 8)) {
- actual_format = (char *) (format + 1);
+ actual_format = (format + 1);
switch ((unsigned char) *format) {
+#ifdef LOG_EMERG
case 1:
log_pri = LOG_EMERG;
break;
+#endif /* LOG_EMERG */
+#ifdef LOG_ALERT
case 2:
log_pri = LOG_ALERT;
break;
+#endif /* LOG_ALERT */
+#ifdef LOG_CRIT
case 3:
log_pri = LOG_CRIT;
break;
+#endif /* LOG_CRIT */
default:
case 4:
log_pri = LOG_ERR;
break;
+#ifdef LOG_WARNING
case 5:
log_pri = LOG_WARNING;
break;
+#endif /* LOG_WARNING */
+#ifdef LOG_NOTICE
case 6:
log_pri = LOG_NOTICE;
break;
+#endif /* LOG_NOTICE */
+#ifdef LOG_INFO
case 7:
log_pri = LOG_INFO;
break;
+#endif /* LOG_INFO */
+#ifdef LOG_DEBUG
case 8:
log_pri = LOG_DEBUG;
break;
+#endif /* LOG_DEBUG */
}
}
+#endif /* HAVE_SYSLOG */
/* Now format the actual message */
- vsnprintf(cp, sizeof (outbuf) - (cp - outbuf), actual_format, ap);
+#if HAVE_VSNPRINTF
+ vsnprintf(cp, sizeof(outbuf) - (cp - outbuf), actual_format, ap);
+#elif HAVE_VSPRINTF
+ vsprintf(cp, actual_format, ap);
+#else /* HAVE_VSPRINTF */
+ sprintf(cp, actual_format, ((int *) ap)[0], ((int *) ap)[1],
+ ((int *) ap)[2], ((int *) ap)[3],
+ ((int *) ap)[4], ((int *) ap)[5]);
+#endif /* HAVE_VSPRINTF */
/*
* Now that we have the message formatted, perform the output to each
@@ -436,14 +472,13 @@ klog_com_err_proc(whoami, code, format, ap)
/*
* Files/standard error.
*/
- if (fprintf(log_control.log_entries[lindex].lfu_filep,
+ if (fprintf(log_control.log_entries[lindex].lfu_filep, "%s\n",
outbuf) < 0) {
/* Attempt to report error */
fprintf(stderr, krb5_log_error_table(LOG_FILE_ERR), whoami,
log_control.log_entries[lindex].lfu_fname);
}
else {
- fprintf(log_control.log_entries[lindex].lfu_filep, "\n");
fflush(log_control.log_entries[lindex].lfu_filep);
}
break;
@@ -459,6 +494,7 @@ klog_com_err_proc(whoami, code, format, ap)
log_control.log_entries[lindex].ldu_devname);
}
break;
+#ifdef HAVE_SYSLOG
case K_LOG_SYSLOG:
/*
* System log.
@@ -476,6 +512,7 @@ klog_com_err_proc(whoami, code, format, ap)
/* Log the message with our header trimmed off */
syslog(log_pri, syslogp);
break;
+#endif /* HAVE_SYSLOG */
default:
break;
}
@@ -504,26 +541,25 @@ klog_com_err_proc(whoami, code, format, ap)
* where/how to send output.
*/
krb5_error_code
-krb5_klog_init(kcontext, ename, whoami, do_com_err)
- krb5_context kcontext;
- char *ename;
- char *whoami;
- krb5_boolean do_com_err;
+krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do_com_err)
{
const char *logging_profent[3];
const char *logging_defent[3];
char **logging_specs;
int i, ngood;
char *cp, *cp2;
- char savec;
+ char savec = '\0';
int error;
int do_openlog, log_facility;
FILE *f;
+ mode_t old_umask;
/* Initialize */
do_openlog = 0;
log_facility = 0;
+ err_context = kcontext;
+
/*
* Look up [logging]-><ename> in the profile. If that doesn't
* succeed, then look for [logging]->default.
@@ -567,9 +603,9 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
* <whitespace><data><whitespace>
* so, trim off the leading and trailing whitespace here.
*/
- for (cp = logging_specs[i]; isspace(*cp); cp++);
+ for (cp = logging_specs[i]; isspace((int) *cp); cp++);
for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1];
- isspace(*cp2); cp2--);
+ isspace((int) *cp2); cp2--);
cp2++;
*cp2 = '\0';
/*
@@ -582,16 +618,13 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
if (cp[4] == ':' || cp[4] == '=') {
log_control.log_entries[i].lfu_fopen_mode =
(cp[4] == ':') ? "a+F" : "wF";
+ old_umask = umask(077);
f = fopen(&cp[5],
log_control.log_entries[i].lfu_fopen_mode);
+ umask(old_umask);
if (f) {
- char rotate_kw[128];
- /* Set the permissions to 644 */
- if (fchmod(fileno(f),
- S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) == -1) {
- fprintf(stderr,gettext("Couldn't set permissions for log file %s: %s\n"),
- &cp[5], error_message(errno));
- }
+ char rotate_kw[128];
+
log_control.log_entries[i].lfu_filep = f;
log_control.log_entries[i].log_type = K_LOG_FILE;
log_control.log_entries[i].lfu_fname = &cp[5];
@@ -642,12 +675,13 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
}
} else {
- fprintf(stderr,gettext("Couldn't open log file %s: %s\n"),
+ fprintf(stderr, gettext("Couldn't open log file %s: %s\n"),
&cp[5], error_message(errno));
continue;
}
}
}
+#ifdef HAVE_SYSLOG
/*
* Is this a syslog?
*/
@@ -662,7 +696,8 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
/*
* Find the end of the severity.
*/
- if (cp2 = strchr(&cp[7], ':')) {
+ cp2 = strchr(&cp[7], ':');
+ if (cp2) {
savec = *cp2;
*cp2 = '\0';
cp2++;
@@ -674,32 +709,46 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
if (!strcasecmp(&cp[7], "ERR")) {
log_control.log_entries[i].lsu_severity = LOG_ERR;
}
+#ifdef LOG_EMERG
else if (!strcasecmp(&cp[7], "EMERG")) {
log_control.log_entries[i].lsu_severity =
LOG_EMERG;
}
+#endif /* LOG_EMERG */
+#ifdef LOG_ALERT
else if (!strcasecmp(&cp[7], "ALERT")) {
log_control.log_entries[i].lsu_severity =
LOG_ALERT;
}
+#endif /* LOG_ALERT */
+#ifdef LOG_CRIT
else if (!strcasecmp(&cp[7], "CRIT")) {
log_control.log_entries[i].lsu_severity = LOG_CRIT;
}
+#endif /* LOG_CRIT */
+#ifdef LOG_WARNING
else if (!strcasecmp(&cp[7], "WARNING")) {
log_control.log_entries[i].lsu_severity =
LOG_WARNING;
}
+#endif /* LOG_WARNING */
+#ifdef LOG_NOTICE
else if (!strcasecmp(&cp[7], "NOTICE")) {
log_control.log_entries[i].lsu_severity =
LOG_NOTICE;
}
+#endif /* LOG_NOTICE */
+#ifdef LOG_INFO
else if (!strcasecmp(&cp[7], "INFO")) {
log_control.log_entries[i].lsu_severity = LOG_INFO;
}
+#endif /* LOG_INFO */
+#ifdef LOG_DEBUG
else if (!strcasecmp(&cp[7], "DEBUG")) {
log_control.log_entries[i].lsu_severity =
LOG_DEBUG;
}
+#endif /* LOG_DEBUG */
else
error = 1;
@@ -771,12 +820,14 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
log_facility = log_control.log_entries[i].lsu_facility;
}
}
+#endif /* HAVE_SYSLOG */
/*
* Is this a standard error specification?
*/
else if (!strcasecmp(cp, "STDERR")) {
- if (log_control.log_entries[i].lfu_filep =
- fdopen(fileno(stderr), "a+F")) {
+ log_control.log_entries[i].lfu_filep =
+ fdopen(fileno(stderr), "a+F");
+ if (log_control.log_entries[i].lfu_filep) {
log_control.log_entries[i].log_type = K_LOG_STDERR;
log_control.log_entries[i].lfu_fname =
"standard error";
@@ -786,8 +837,9 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
* Is this a specification of the console?
*/
else if (!strcasecmp(cp, "CONSOLE")) {
- if (log_control.log_entries[i].ldu_filep =
- CONSOLE_OPEN("a+F")) {
+ log_control.log_entries[i].ldu_filep =
+ CONSOLE_OPEN("a+F");
+ if (log_control.log_entries[i].ldu_filep) {
log_control.log_entries[i].log_type = K_LOG_CONSOLE;
log_control.log_entries[i].ldu_devname = "console";
}
@@ -800,8 +852,9 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
* We handle devices very similarly to files.
*/
if (cp[6] == '=') {
- if (log_control.log_entries[i].ldu_filep =
- DEVICE_OPEN(&cp[7], "wF")) {
+ log_control.log_entries[i].ldu_filep =
+ DEVICE_OPEN(&cp[7], "wF");
+ if (log_control.log_entries[i].ldu_filep) {
log_control.log_entries[i].log_type = K_LOG_DEVICE;
log_control.log_entries[i].ldu_devname = &cp[7];
}
@@ -843,14 +896,21 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
log_control.log_nentries = 1;
}
if (log_control.log_nentries) {
- if (log_control.log_whoami = (char *) malloc(strlen(whoami)+1))
+ log_control.log_whoami = (char *) malloc(strlen(whoami)+1);
+ if (log_control.log_whoami)
strcpy(log_control.log_whoami, whoami);
- if (log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN))
+
+ log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN + 1);
+ if (log_control.log_hostname) {
gethostname(log_control.log_hostname, MAXHOSTNAMELEN);
+ log_control.log_hostname[MAXHOSTNAMELEN] = '\0';
+ }
+#ifdef HAVE_OPENLOG
if (do_openlog) {
openlog(whoami, LOG_NDELAY|LOG_PID, log_facility);
log_control.log_opened = 1;
}
+#endif /* HAVE_OPENLOG */
if (do_com_err)
(void) set_com_err_hook(klog_com_err_proc);
}
@@ -861,8 +921,7 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
* krb5_klog_close() - Close the logging context and free all data.
*/
void
-krb5_klog_close(kcontext)
- krb5_context kcontext;
+krb5_klog_close(krb5_context kcontext)
{
int lindex;
(void) reset_com_err_hook();
@@ -882,11 +941,13 @@ krb5_klog_close(kcontext)
*/
DEVICE_CLOSE(log_control.log_entries[lindex].ldu_filep);
break;
+#ifdef HAVE_SYSLOG
case K_LOG_SYSLOG:
/*
* System log.
*/
break;
+#endif /* HAVE_SYSLOG */
default:
break;
}
@@ -903,16 +964,17 @@ krb5_klog_close(kcontext)
if (log_control.log_hostname)
free(log_control.log_hostname);
log_control.log_hostname = (char *) NULL;
+#ifdef HAVE_CLOSELOG
if (log_control.log_opened)
closelog();
+#endif /* HAVE_CLOSELOG */
}
/*
* severity2string() - Convert a severity to a string.
*/
-static char *
-severity2string(severity)
- int severity;
+static const char *
+severity2string(int severity)
{
int s;
const char *ss;
@@ -920,30 +982,44 @@ severity2string(severity)
s = severity & LOG_PRIMASK;
ss = krb5_log_error_table(LOG_UFO_STRING);
switch (s) {
+#ifdef LOG_EMERG
case LOG_EMERG:
ss = krb5_log_error_table(LOG_EMERG_STRING);
break;
+#endif /* LOG_EMERG */
+#ifdef LOG_ALERT
case LOG_ALERT:
ss = krb5_log_error_table(LOG_ALERT_STRING);
break;
+#endif /* LOG_ALERT */
+#ifdef LOG_CRIT
case LOG_CRIT:
ss = krb5_log_error_table(LOG_CRIT_STRING);
break;
+#endif /* LOG_CRIT */
case LOG_ERR:
ss = krb5_log_error_table(LOG_ERR_STRING);
break;
+#ifdef LOG_WARNING
case LOG_WARNING:
ss = krb5_log_error_table(LOG_WARNING_STRING);
break;
+#endif /* LOG_WARNING */
+#ifdef LOG_NOTICE
case LOG_NOTICE:
ss = krb5_log_error_table(LOG_NOTICE_STRING);
break;
+#endif /* LOG_NOTICE */
+#ifdef LOG_INFO
case LOG_INFO:
ss = krb5_log_error_table(LOG_INFO_STRING);
break;
+#endif /* LOG_INFO */
+#ifdef LOG_DEBUG
case LOG_DEBUG:
ss = krb5_log_error_table(LOG_DEBUG_STRING);
break;
+#endif /* LOG_DEBUG */
}
return((char *) ss);
}
@@ -954,17 +1030,16 @@ severity2string(severity)
* by krb5_klog_init().
*/
static int
-klog_vsyslog(priority, format, arglist)
- int priority;
- const char *format;
- va_list arglist;
+klog_vsyslog(int priority, const char *format, va_list arglist)
{
char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
int lindex;
char *syslogp;
char *cp;
time_t now;
+#ifdef HAVE_STRFTIME
size_t soff;
+#endif /* HAVE_STRFTIME */
/*
* Format a syslog-esque message of the format:
@@ -977,6 +1052,7 @@ klog_vsyslog(priority, format, arglist)
*/
cp = outbuf;
(void) time(&now);
+#ifdef HAVE_STRFTIME
/*
* Format the date: mon dd hh:mm:ss
*/
@@ -985,9 +1061,19 @@ klog_vsyslog(priority, format, arglist)
cp += soff;
else
return(-1);
+#else /* HAVE_STRFTIME */
+ /*
+ * Format the date:
+ * We ASSUME here that the output of ctime is of the format:
+ * dow mon dd hh:mm:ss tzs yyyy\n
+ * 012345678901234567890123456789
+ */
+ strncpy(outbuf, ctime(&now) + 4, 15);
+ cp += 15;
+#endif /* HAVE_STRFTIME */
#ifdef VERBOSE_LOGS
- sprintf(cp, " %s %s[%d](%s): ",
- log_control.log_hostname, log_control.log_whoami, getpid(),
+ sprintf(cp, " %s %s[%ld](%s): ",
+ log_control.log_hostname, log_control.log_whoami, (long) getpid(),
severity2string(priority));
#else
sprintf(cp, " ");
@@ -995,7 +1081,26 @@ klog_vsyslog(priority, format, arglist)
syslogp = &outbuf[strlen(outbuf)];
/* Now format the actual message */
- vsnprintf(syslogp, sizeof (outbuf) - (syslogp - outbuf), format, arglist);
+#ifdef HAVE_VSNPRINTF
+ vsnprintf(syslogp, sizeof(outbuf) - (syslogp - outbuf), format, arglist);
+#elif HAVE_VSPRINTF
+ vsprintf(syslogp, format, arglist);
+#else /* HAVE_VSPRINTF */
+ sprintf(syslogp, format, ((int *) arglist)[0], ((int *) arglist)[1],
+ ((int *) arglist)[2], ((int *) arglist)[3],
+ ((int *) arglist)[4], ((int *) arglist)[5]);
+#endif /* HAVE_VSPRINTF */
+
+ /*
+ * If the user did not use krb5_klog_init() instead of dropping
+ * the request on the floor, syslog it - if it exists
+ */
+#ifdef HAVE_SYSLOG
+ if (log_control.log_nentries == 0) {
+ /* Log the message with our header trimmed off */
+ syslog(priority, "%s", syslogp);
+ }
+#endif
/*
* Now that we have the message formatted, perform the output to each
@@ -1011,14 +1116,14 @@ klog_vsyslog(priority, format, arglist)
/*
* Files/standard error.
*/
- if (fprintf(log_control.log_entries[lindex].lfu_filep,
+ if (fprintf(log_control.log_entries[lindex].lfu_filep, "%s\n",
outbuf) < 0) {
/* Attempt to report error */
fprintf(stderr, krb5_log_error_table(LOG_FILE_ERR),
+ log_control.log_whoami,
log_control.log_entries[lindex].lfu_fname);
}
else {
- fprintf(log_control.log_entries[lindex].lfu_filep, "\n");
fflush(log_control.log_entries[lindex].lfu_filep);
}
break;
@@ -1031,17 +1136,20 @@ klog_vsyslog(priority, format, arglist)
outbuf) < 0) {
/* Attempt to report error */
fprintf(stderr, krb5_log_error_table(LOG_DEVICE_ERR),
+ log_control.log_whoami,
log_control.log_entries[lindex].ldu_devname);
}
break;
+#ifdef HAVE_SYSLOG
case K_LOG_SYSLOG:
/*
* System log.
*/
/* Log the message with our header trimmed off */
- syslog(priority, syslogp);
+ syslog(priority, "%s", syslogp);
break;
+#endif /* HAVE_SYSLOG */
default:
break;
}
diff --git a/usr/src/lib/krb5/kadm5/clnt/mapfile-vers b/usr/src/lib/krb5/kadm5/clnt/mapfile-vers
index 4ee6d71f5c..a796ee01ab 100644
--- a/usr/src/lib/krb5/kadm5/clnt/mapfile-vers
+++ b/usr/src/lib/krb5/kadm5/clnt/mapfile-vers
@@ -22,29 +22,28 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
#
SUNWprivate_1.1 {
global:
_kadm5_get_kpasswd_protocol;
- chpass_principal3_1;
- chpass_principal_1;
+ chpass_principal3_2;
+ chpass_principal_2;
chpw_error_message;
- chrand_principal3_1;
- chrand_principal_1;
- create_policy_1;
- create_principal3_1;
- create_principal_1;
- delete_policy_1;
- delete_principal_1;
+ chrand_principal3_2;
+ chrand_principal_2;
+ create_policy_2;
+ create_principal3_2;
+ create_principal_2;
+ delete_policy_2;
+ delete_principal_2;
display_status;
- get_policy_1;
- get_pols_1;
- get_principal_1;
- get_princs_1;
- get_privs_1;
- init_1;
+ get_policy_2;
+ get_pols_2;
+ get_principal_2;
+ get_princs_2;
+ get_privs_2;
+ init_2;
kadm5_chpass_principal;
kadm5_chpass_principal_3;
kadm5_chpass_principal_util;
@@ -106,16 +105,16 @@ SUNWprivate_1.1 {
krb5_klog_init;
krb5_klog_syslog;
krb5_log_error_table;
- krb5_mk_chpw_req;
- krb5_rd_chpw_rep;
+ krb5int_mk_chpw_req;
+ krb5int_rd_chpw_rep;
krb5_read_realm_params;
krb5_string_to_flags;
krb5_string_to_keysalts;
- modify_policy_1;
- modify_principal_1;
- rename_principal_1;
- setkey_principal3_1;
- setkey_principal_1;
+ modify_policy_2;
+ modify_principal_2;
+ rename_principal_2;
+ setkey_principal3_2;
+ setkey_principal_2;
xdr_chpass3_arg;
xdr_chpass_arg;
xdr_chrand3_arg;
diff --git a/usr/src/lib/krb5/kadm5/get_admhst.c b/usr/src/lib/krb5/kadm5/get_admhst.c
deleted file mode 100644
index 577abd2b8d..0000000000
--- a/usr/src/lib/krb5/kadm5/get_admhst.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
- *
- * Openvision retains the copyright to derivative works of
- * this source code. Do *NOT* create a derivative of this
- * source code before consulting with your legal department.
- * Do *NOT* integrate *ANY* of this source code into another
- * product before consulting with your legal department.
- *
- * For further information, read the top-level Openvision
- * copyright which is contained in the top-level MIT Kerberos
- * copyright.
- *
- * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
- *
- */
-
-
-/*
- * $Source: /afs/athena.mit.edu/astaff/project/krbdev/.cvsroot/src/lib/kadm5/get_admhst.c,v $
- * $Author: marc $
- *
- * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
- * of Technology.
- *
- * For copying and distribution information, please see the file
- * <mit-copyright.h>.
- */
-
-#ifndef lint
-static char *rcsid =
-"$Header: /cvs/krbdev/krb5/src/lib/kadm5/get_admhst.c,v 1.8 1996/07/22 20:36:00 marc Exp $";
-#endif /* lint */
-
-#include <stdio.h>
-#include <krb5/osconf.h>
-#include <string.h>
-
-/*
- * Given a Kerberos realm, find a host on which the Kerberos database
- * administration server can be found.
- *
- * krb5_get_admhst takes a pointer to be filled in, a pointer to the name
- * of the realm for which a server is desired, and an integer n, and
- * returns (in h) the nth administrative host entry from the configuration
- * file DEFAULT_CONFIG_FILENAME.
- *
- * If the realm is NULL, the default realm is used.
- *
- * On error, get_admhst returns 0. If all goes well, the routine
- * returns 1.
- *
- * This is a temporary hack to allow us to find the nearest system running
- * a Kerberos admin server. In the long run, this functionality will be
- * provided by a nameserver.
- */
-int
-krb5_get_admhst(char *h, char *r, int n)
-{
- FILE *cnffile;
- char *realm = NULL;
- char tr[BUFSIZ];
- char linebuf[BUFSIZ];
- char scratch[64];
- register int i;
- int ret;
-
- if(r == NULL) {
- if((ret = krb5_get_default_realm(&realm)) != 0)
- return ret;
- r = realm;
- }
- if ((cnffile = fopen(DEFAULT_CONFIG_FILENAME, "rF")) == NULL) {
- return(0);
- }
- if (fgets(linebuf, BUFSIZ, cnffile) == NULL) {
- /* error reading */
- (void) fclose(cnffile);
- return(0);
- }
- if (!strchr(linebuf, '\n')) {
- /* didn't all fit into buffer, punt */
- (void) fclose(cnffile);
- if(realm)
- free(realm);
- return(0);
- }
- for (i = 0; i < n; ) {
- /* run through the file, looking for admin host */
- if (fgets(linebuf, BUFSIZ, cnffile) == NULL) {
- (void) fclose(cnffile);
- if(realm)
- free(realm);
- return(0);
- }
- /* need to scan for a token after 'admin' to make sure that
- admin matched correctly */
- if (sscanf(linebuf, "%s %s admin %s", tr, h, scratch) != 3)
- continue;
- if (!strcmp(tr,r))
- i++;
- }
- (void) fclose(cnffile);
- if(realm)
- free(realm);
- return(1);
-}
diff --git a/usr/src/lib/krb5/kadm5/kadm_host_srv_names.c b/usr/src/lib/krb5/kadm5/kadm_host_srv_names.c
index 9abe0fe842..a6c15849fc 100644
--- a/usr/src/lib/krb5/kadm5/kadm_host_srv_names.c
+++ b/usr/src/lib/krb5/kadm5/kadm_host_srv_names.c
@@ -3,16 +3,17 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/kad5/kadm_host_srv_names.c
*/
+#include <k5-int.h>
#include "admin.h"
#include <stdio.h>
#include <os-proto.h>
+
#define KADM5_MASTER "admin_server"
#define KADM5_KPASSWD "kpasswd_server"
diff --git a/usr/src/lib/krb5/kadm5/kadm_rpc.h b/usr/src/lib/krb5/kadm5/kadm_rpc.h
index 9521c9f923..c204c8f6db 100644
--- a/usr/src/lib/krb5/kadm5/kadm_rpc.h
+++ b/usr/src/lib/krb5/kadm5/kadm_rpc.h
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
*
@@ -22,8 +20,8 @@
#include <rpc/types.h>
-#include <krb5.h>
#include <kadm5/admin.h>
+#include <krb5.h>
struct cprinc_arg {
krb5_ui_4 api_version;
@@ -32,7 +30,6 @@ struct cprinc_arg {
char *passwd;
};
typedef struct cprinc_arg cprinc_arg;
-bool_t xdr_cprinc_arg();
struct cprinc3_arg {
krb5_ui_4 api_version;
@@ -43,21 +40,18 @@ struct cprinc3_arg {
char *passwd;
};
typedef struct cprinc3_arg cprinc3_arg;
-bool_t xdr_cprinc3_arg();
struct generic_ret {
krb5_ui_4 api_version;
kadm5_ret_t code;
};
typedef struct generic_ret generic_ret;
-bool_t xdr_generic_ret();
struct dprinc_arg {
krb5_ui_4 api_version;
krb5_principal princ;
};
typedef struct dprinc_arg dprinc_arg;
-bool_t xdr_dprinc_arg();
struct mprinc_arg {
krb5_ui_4 api_version;
@@ -65,7 +59,6 @@ struct mprinc_arg {
long mask;
};
typedef struct mprinc_arg mprinc_arg;
-bool_t xdr_mprinc_arg();
struct rprinc_arg {
krb5_ui_4 api_version;
@@ -73,14 +66,12 @@ struct rprinc_arg {
krb5_principal dest;
};
typedef struct rprinc_arg rprinc_arg;
-bool_t xdr_rprinc_arg();
struct gprincs_arg {
krb5_ui_4 api_version;
char *exp;
};
typedef struct gprincs_arg gprincs_arg;
-bool_t xdr_gprincs_arg();
struct gprincs_ret {
krb5_ui_4 api_version;
@@ -89,7 +80,6 @@ struct gprincs_ret {
int count;
};
typedef struct gprincs_ret gprincs_ret;
-bool_t xdr_gprincs_ret();
struct chpass_arg {
krb5_ui_4 api_version;
@@ -97,7 +87,6 @@ struct chpass_arg {
char *pass;
};
typedef struct chpass_arg chpass_arg;
-bool_t xdr_chpass_arg();
struct chpass3_arg {
krb5_ui_4 api_version;
@@ -108,7 +97,6 @@ struct chpass3_arg {
char *pass;
};
typedef struct chpass3_arg chpass3_arg;
-bool_t xdr_chpass3_arg();
struct setv4key_arg {
krb5_ui_4 api_version;
@@ -116,7 +104,6 @@ struct setv4key_arg {
krb5_keyblock *keyblock;
};
typedef struct setv4key_arg setv4key_arg;
-bool_t xdr_setv4key_arg();
struct setkey_arg {
krb5_ui_4 api_version;
@@ -125,7 +112,6 @@ struct setkey_arg {
int n_keys;
};
typedef struct setkey_arg setkey_arg;
-bool_t xdr_setkey_arg();
struct setkey3_arg {
krb5_ui_4 api_version;
@@ -137,14 +123,12 @@ struct setkey3_arg {
int n_keys;
};
typedef struct setkey3_arg setkey3_arg;
-bool_t xdr_setkey3_arg();
struct chrand_arg {
krb5_ui_4 api_version;
krb5_principal princ;
};
typedef struct chrand_arg chrand_arg;
-bool_t xdr_chrand_arg();
struct chrand3_arg {
krb5_ui_4 api_version;
@@ -154,7 +138,6 @@ struct chrand3_arg {
krb5_key_salt_tuple *ks_tuple;
};
typedef struct chrand3_arg chrand3_arg;
-bool_t xdr_chrand3_arg();
struct chrand_ret {
krb5_ui_4 api_version;
@@ -164,7 +147,6 @@ struct chrand_ret {
int n_keys;
};
typedef struct chrand_ret chrand_ret;
-bool_t xdr_chrand_ret();
struct gprinc_arg {
krb5_ui_4 api_version;
@@ -172,7 +154,6 @@ struct gprinc_arg {
long mask;
};
typedef struct gprinc_arg gprinc_arg;
-bool_t xdr_gprinc_arg();
struct gprinc_ret {
krb5_ui_4 api_version;
@@ -180,16 +161,6 @@ struct gprinc_ret {
kadm5_principal_ent_rec rec;
};
typedef struct gprinc_ret gprinc_ret;
-bool_t xdr_gprinc_ret();
-bool_t xdr_kadm5_ret_t();
-bool_t xdr_kadm5_principal_ent_rec();
-bool_t xdr_kadm5_policy_ent_rec();
-bool_t xdr_krb5_keyblock();
-bool_t xdr_krb5_principal();
-bool_t xdr_krb5_enctype();
-bool_t xdr_krb5_octet();
-bool_t xdr_krb5_int32();
-bool_t xdr_u_int32();
struct cpol_arg {
krb5_ui_4 api_version;
@@ -197,14 +168,12 @@ struct cpol_arg {
long mask;
};
typedef struct cpol_arg cpol_arg;
-bool_t xdr_cpol_arg();
struct dpol_arg {
krb5_ui_4 api_version;
char *name;
};
typedef struct dpol_arg dpol_arg;
-bool_t xdr_dpol_arg();
struct mpol_arg {
krb5_ui_4 api_version;
@@ -212,14 +181,12 @@ struct mpol_arg {
long mask;
};
typedef struct mpol_arg mpol_arg;
-bool_t xdr_mpol_arg();
struct gpol_arg {
krb5_ui_4 api_version;
char *name;
};
typedef struct gpol_arg gpol_arg;
-bool_t xdr_gpol_arg();
struct gpol_ret {
krb5_ui_4 api_version;
@@ -227,14 +194,12 @@ struct gpol_ret {
kadm5_policy_ent_rec rec;
};
typedef struct gpol_ret gpol_ret;
-bool_t xdr_gpol_ret();
struct gpols_arg {
krb5_ui_4 api_version;
char *exp;
};
typedef struct gpols_arg gpols_arg;
-bool_t xdr_gpols_arg();
struct gpols_ret {
krb5_ui_4 api_version;
@@ -243,7 +208,6 @@ struct gpols_ret {
int count;
};
typedef struct gpols_ret gpols_ret;
-bool_t xdr_gpols_ret();
struct getprivs_ret {
krb5_ui_4 api_version;
@@ -251,104 +215,108 @@ struct getprivs_ret {
long privs;
};
typedef struct getprivs_ret getprivs_ret;
-bool_t xdr_getprivs_ret();
-
-#define KADM ((krb5_ui_4)2112)
-#define KADMVERS ((krb5_ui_4)2)
-#define CREATE_PRINCIPAL ((krb5_ui_4)1)
-extern generic_ret *create_principal_1_svc(cprinc_arg *arg,
- struct svc_req *rqstp);
-extern generic_ret *create_principal_1(cprinc_arg *argp, CLIENT *clnt);
-
-#define DELETE_PRINCIPAL ((krb5_ui_4)2)
-extern generic_ret *delete_principal_1_svc(dprinc_arg *arg,
- struct svc_req *rqstp);
-extern generic_ret *delete_principal_1(dprinc_arg *argp, CLIENT *clnt);
-
-#define MODIFY_PRINCIPAL ((krb5_ui_4)3)
-extern generic_ret *modify_principal_1_svc(mprinc_arg *arg,
- struct svc_req *rqstp);
-extern generic_ret *modify_principal_1(mprinc_arg *argp, CLIENT *clnt);
-
-#define RENAME_PRINCIPAL ((krb5_ui_4)4)
-extern generic_ret *rename_principal_1_svc(rprinc_arg *arg,
- struct svc_req *rqstp);
-extern generic_ret *rename_principal_1(rprinc_arg *argp, CLIENT *clnt);
-
-#define GET_PRINCIPAL ((krb5_ui_4)5)
-extern gprinc_ret *get_principal_1_svc(gprinc_arg *arg, struct svc_req *rqstp);
-extern gprinc_ret *get_principal_1(gprinc_arg *argp, CLIENT *clnt);
-
-#define CHPASS_PRINCIPAL ((krb5_ui_4)6)
-extern generic_ret *chpass_principal_1_svc(chpass_arg *arg,
- struct svc_req *rqstp);
-extern generic_ret *chpass_principal_1(chpass_arg *argp, CLIENT *clnt);
-
-#define CHRAND_PRINCIPAL ((krb5_ui_4)7)
-extern chrand_ret *chrand_principal_1_svc(chrand_arg *arg,
- struct svc_req *rqstp);
-extern chrand_ret *chrand_principal_1(chrand_arg *argp, CLIENT *clnt);
-
-#define CREATE_POLICY ((krb5_ui_4)8)
-extern generic_ret *create_policy_1_svc(cpol_arg *arg, struct svc_req *rqstp);
-extern generic_ret *create_policy_1(cpol_arg *argp, CLIENT *clnt);
-
-#define DELETE_POLICY ((krb5_ui_4)9)
-extern generic_ret *delete_policy_1_svc(dpol_arg *arg, struct svc_req *rqstp);
-extern generic_ret *delete_policy_1(dpol_arg *argp, CLIENT *clnt);
-
-#define MODIFY_POLICY ((krb5_ui_4)10)
-extern generic_ret *modify_policy_1_svc(mpol_arg *arg, struct svc_req *rqstp);
-extern generic_ret *modify_policy_1(mpol_arg *argp, CLIENT *clnt);
-
-#define GET_POLICY ((krb5_ui_4)11)
-extern gpol_ret *get_policy_1_svc(gpol_arg *arg, struct svc_req *rqstp);
-extern gpol_ret *get_policy_1(gpol_arg *argp, CLIENT *clnt);
-
-#define GET_PRIVS ((krb5_ui_4)12)
-extern getprivs_ret *get_privs_1_svc(krb5_ui_4 *arg, struct svc_req *rqstp);
-extern getprivs_ret *get_privs_1(void *argp, CLIENT *clnt);
-
-#define INIT ((krb5_ui_4)13)
-extern generic_ret *init_1_svc(krb5_ui_4 *arg, struct svc_req *rqstp);
-extern generic_ret *init_1();
-
-#define GET_PRINCS ((krb5_ui_4) 14)
-extern gprincs_ret *get_princs_1_svc(gprincs_arg *arg, struct svc_req *rqstp);
-extern gprincs_ret *get_princs_1(gprincs_arg *argp, CLIENT *clnt);
-
-#define GET_POLS ((krb5_ui_4) 15)
-extern gpols_ret *get_pols_1_svc(gpols_arg *arg, struct svc_req *rqstp);
-extern gpols_ret *get_pols_1(gpols_arg *argp, CLIENT *clnt);
-
-#define SETKEY_PRINCIPAL ((krb5_ui_4) 16)
-extern generic_ret *setkey_principal_1_svc(setkey_arg *arg,
- struct svc_req *rqstp);
-extern generic_ret *setkey_principal_1(setkey_arg *argp, CLIENT *clnt);
-
-#define SETV4KEY_PRINCIPAL ((krb5_ui_4) 17)
-extern generic_ret *setv4key_principal_1_svc(setv4key_arg *arg,
- struct svc_req *rqstp);
-extern generic_ret *setv4key_principal_1(setv4key_arg *argp, CLIENT *clnt);
-
-#define CREATE_PRINCIPAL3 ((krb5_ui_4) 18)
-extern generic_ret *create_principal3_1_svc(cprinc3_arg *arg,
- struct svc_req *rqstp);
-extern generic_ret *create_principal3_1(cprinc3_arg *argp, CLIENT *clnt);
-
-#define CHPASS_PRINCIPAL3 ((krb5_ui_4) 19)
-extern generic_ret *chpass_principal3_1_svc(chpass3_arg *arg,
- struct svc_req *rqstp);
-extern generic_ret *chpass_principal3_1(chpass3_arg *argp, CLIENT *clnt);
-
-#define CHRAND_PRINCIPAL3 ((krb5_ui_4) 20)
-extern chrand_ret *chrand_principal3_1_svc(chrand3_arg *arg,
- struct svc_req *rqstp);
-extern chrand_ret *chrand_principal3_1(chrand3_arg *argp, CLIENT *clnt);
-
-#define SETKEY_PRINCIPAL3 ((krb5_ui_4) 21)
-extern generic_ret *setkey_principal3_1_svc(setkey3_arg *arg,
- struct svc_req *rqstp);
-extern generic_ret *setkey_principal3_1(setkey3_arg *argp, CLIENT *clnt);
+
+#define KADM 2112
+#define KADMVERS 2
+#define CREATE_PRINCIPAL 1
+extern generic_ret * create_principal_2(cprinc_arg *, CLIENT *);
+extern generic_ret * create_principal_2_svc(cprinc_arg *, struct svc_req *);
+#define DELETE_PRINCIPAL 2
+extern generic_ret * delete_principal_2(dprinc_arg *, CLIENT *);
+extern generic_ret * delete_principal_2_svc(dprinc_arg *, struct svc_req *);
+#define MODIFY_PRINCIPAL 3
+extern generic_ret * modify_principal_2(mprinc_arg *, CLIENT *);
+extern generic_ret * modify_principal_2_svc(mprinc_arg *, struct svc_req *);
+#define RENAME_PRINCIPAL 4
+extern generic_ret * rename_principal_2(rprinc_arg *, CLIENT *);
+extern generic_ret * rename_principal_2_svc(rprinc_arg *, struct svc_req *);
+#define GET_PRINCIPAL 5
+extern gprinc_ret * get_principal_2(gprinc_arg *, CLIENT *);
+extern gprinc_ret * get_principal_2_svc(gprinc_arg *, struct svc_req *);
+#define CHPASS_PRINCIPAL 6
+extern generic_ret * chpass_principal_2(chpass_arg *, CLIENT *);
+extern generic_ret * chpass_principal_2_svc(chpass_arg *, struct svc_req *);
+#define CHRAND_PRINCIPAL 7
+extern chrand_ret * chrand_principal_2(chrand_arg *, CLIENT *);
+extern chrand_ret * chrand_principal_2_svc(chrand_arg *, struct svc_req *);
+#define CREATE_POLICY 8
+extern generic_ret * create_policy_2(cpol_arg *, CLIENT *);
+extern generic_ret * create_policy_2_svc(cpol_arg *, struct svc_req *);
+#define DELETE_POLICY 9
+extern generic_ret * delete_policy_2(dpol_arg *, CLIENT *);
+extern generic_ret * delete_policy_2_svc(dpol_arg *, struct svc_req *);
+#define MODIFY_POLICY 10
+extern generic_ret * modify_policy_2(mpol_arg *, CLIENT *);
+extern generic_ret * modify_policy_2_svc(mpol_arg *, struct svc_req *);
+#define GET_POLICY 11
+extern gpol_ret * get_policy_2(gpol_arg *, CLIENT *);
+extern gpol_ret * get_policy_2_svc(gpol_arg *, struct svc_req *);
+#define GET_PRIVS 12
+extern getprivs_ret * get_privs_2(void *, CLIENT *);
+extern getprivs_ret * get_privs_2_svc(krb5_ui_4 *, struct svc_req *);
+#define INIT 13
+extern generic_ret * init_2(void *, CLIENT *);
+extern generic_ret * init_2_svc(krb5_ui_4 *, struct svc_req *);
+#define GET_PRINCS 14
+extern gprincs_ret * get_princs_2(gprincs_arg *, CLIENT *);
+extern gprincs_ret * get_princs_2_svc(gprincs_arg *, struct svc_req *);
+#define GET_POLS 15
+extern gpols_ret * get_pols_2(gpols_arg *, CLIENT *);
+extern gpols_ret * get_pols_2_svc(gpols_arg *, struct svc_req *);
+#define SETKEY_PRINCIPAL 16
+extern generic_ret * setkey_principal_2(setkey_arg *, CLIENT *);
+extern generic_ret * setkey_principal_2_svc(setkey_arg *, struct svc_req *);
+#define SETV4KEY_PRINCIPAL 17
+extern generic_ret * setv4key_principal_2(setv4key_arg *, CLIENT *);
+extern generic_ret * setv4key_principal_2_svc(setv4key_arg *, struct svc_req *);
+#define CREATE_PRINCIPAL3 18
+extern generic_ret * create_principal3_2(cprinc3_arg *, CLIENT *);
+extern generic_ret * create_principal3_2_svc(cprinc3_arg *, struct svc_req *);
+#define CHPASS_PRINCIPAL3 19
+extern generic_ret * chpass_principal3_2(chpass3_arg *, CLIENT *);
+extern generic_ret * chpass_principal3_2_svc(chpass3_arg *, struct svc_req *);
+#define CHRAND_PRINCIPAL3 20
+extern chrand_ret * chrand_principal3_2(chrand3_arg *, CLIENT *);
+extern chrand_ret * chrand_principal3_2_svc(chrand3_arg *, struct svc_req *);
+#define SETKEY_PRINCIPAL3 21
+extern generic_ret * setkey_principal3_2(setkey3_arg *, CLIENT *);
+extern generic_ret * setkey_principal3_2_svc(setkey3_arg *, struct svc_req *);
+
+extern bool_t xdr_cprinc_arg ();
+extern bool_t xdr_cprinc3_arg ();
+extern bool_t xdr_generic_ret ();
+extern bool_t xdr_dprinc_arg ();
+extern bool_t xdr_mprinc_arg ();
+extern bool_t xdr_rprinc_arg ();
+extern bool_t xdr_gprincs_arg ();
+extern bool_t xdr_gprincs_ret ();
+extern bool_t xdr_chpass_arg ();
+extern bool_t xdr_chpass3_arg ();
+extern bool_t xdr_setv4key_arg ();
+extern bool_t xdr_setkey_arg ();
+extern bool_t xdr_setkey3_arg ();
+extern bool_t xdr_chrand_arg ();
+extern bool_t xdr_chrand3_arg ();
+extern bool_t xdr_chrand_ret ();
+extern bool_t xdr_gprinc_arg ();
+extern bool_t xdr_gprinc_ret ();
+extern bool_t xdr_kadm5_ret_t ();
+extern bool_t xdr_kadm5_principal_ent_rec ();
+extern bool_t xdr_kadm5_policy_ent_rec ();
+extern bool_t xdr_krb5_keyblock ();
+extern bool_t xdr_krb5_principal ();
+extern bool_t xdr_krb5_enctype ();
+extern bool_t xdr_krb5_octet ();
+extern bool_t xdr_krb5_int32 ();
+extern bool_t xdr_u_int32 ();
+extern bool_t xdr_cpol_arg ();
+extern bool_t xdr_dpol_arg ();
+extern bool_t xdr_mpol_arg ();
+extern bool_t xdr_gpol_arg ();
+extern bool_t xdr_gpol_ret ();
+extern bool_t xdr_gpols_arg ();
+extern bool_t xdr_gpols_ret ();
+extern bool_t xdr_getprivs_ret ();
+
#endif /* __KADM_RPC_H__ */
diff --git a/usr/src/lib/krb5/kadm5/kadm_rpc_xdr.c b/usr/src/lib/krb5/kadm5/kadm_rpc_xdr.c
index d9d5697458..c4600dbee6 100644
--- a/usr/src/lib/krb5/kadm5/kadm_rpc_xdr.c
+++ b/usr/src/lib/krb5/kadm5/kadm_rpc_xdr.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -28,10 +27,10 @@
*/
#include <rpc/rpc.h>
-#include <krb5.h>
-#include <k5-int.h>
+#include <errno.h>
#include <kadm5/admin.h>
#include <kadm5/kadm_rpc.h>
+#include <krb5.h>
#include <stdlib.h>
#include <string.h>
@@ -571,6 +570,7 @@ xdr_generic_ret(XDR *xdrs, generic_ret *objp)
if (!xdr_kadm5_ret_t(xdrs, &objp->code)) {
return (FALSE);
}
+
return(TRUE);
}
@@ -653,6 +653,7 @@ xdr_gprincs_ret(XDR *xdrs, gprincs_ret *objp)
return (FALSE);
}
}
+
return (TRUE);
}
@@ -812,7 +813,7 @@ xdr_chrand_ret(XDR *xdrs, chrand_ret *objp)
return FALSE;
}
}
-
+
return (TRUE);
}
@@ -853,6 +854,7 @@ xdr_gprinc_ret(XDR *xdrs, gprinc_ret *objp)
}
}
}
+
return (TRUE);
}
@@ -923,6 +925,7 @@ xdr_gpol_ret(XDR *xdrs, gpol_ret *objp)
if (!xdr_kadm5_policy_ent_rec(xdrs, &objp->rec))
return (FALSE);
}
+
return (TRUE);
}
@@ -957,6 +960,7 @@ xdr_gpols_ret(XDR *xdrs, gpols_ret *objp)
return (FALSE);
}
}
+
return (TRUE);
}
@@ -968,6 +972,7 @@ bool_t xdr_getprivs_ret(XDR *xdrs, getprivs_ret *objp)
if (! xdr_kadm5_ret_t(xdrs, &objp->code) ||
! xdr_long(xdrs, &objp->privs))
return FALSE;
+
return TRUE;
}
@@ -983,7 +988,7 @@ xdr_krb5_principal(XDR *xdrs, krb5_principal *objp)
ok, and the other solutions are even uglier */
if (!context &&
- krb5_init_context(&context))
+ kadm5_init_krb5_context(&context))
return(FALSE);
switch(xdrs->x_op) {
@@ -1045,7 +1050,7 @@ xdr_krb5_enctype(XDR *xdrs, krb5_enctype *objp)
bool_t
xdr_krb5_salttype(XDR *xdrs, krb5_int32 *objp)
{
- if (!xdr_int(xdrs, (int32_t *) objp)) /* SUNWresync121 XXX */
+ if (!xdr_int(xdrs, (int32_t *) objp))
return FALSE;
return TRUE;
}
diff --git a/usr/src/lib/krb5/kadm5/misc_free.c b/usr/src/lib/krb5/kadm5/misc_free.c
index 53c5ae5562..0a064b6872 100644
--- a/usr/src/lib/krb5/kadm5/misc_free.c
+++ b/usr/src/lib/krb5/kadm5/misc_free.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
*
@@ -21,15 +19,15 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/misc_free.c,v 1.18 1997/05/28 17:35:05 bjaspan Exp $
+ * $Header$
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/misc_free.c,v 1.18 1997/05/28 17:35:05 bjaspan Exp $";
+static char *rcsid = "$Header$";
#endif
+#include "server_internal.h"
#include <kadm5/admin.h>
#include <stdlib.h>
-#include "server_internal.h"
kadm5_ret_t
kadm5_free_policy_ent(void *server_handle, kadm5_policy_ent_t val)
diff --git a/usr/src/lib/krb5/kadm5/server_internal.h b/usr/src/lib/krb5/kadm5/server_internal.h
index 3a0303e2ce..e87268aa0c 100644
--- a/usr/src/lib/krb5/kadm5/server_internal.h
+++ b/usr/src/lib/krb5/kadm5/server_internal.h
@@ -1,8 +1,7 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -25,7 +24,7 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/server_internal.h,v 1.31 2001/07/08 12:24:56 epeisach Exp $
+ * $Header$
*/
/*
@@ -41,6 +40,7 @@
#include <memory.h>
#endif
#include <stdlib.h>
+#include <errno.h>
#include "k5-int.h"
#include <krb5/kdb.h>
#include <kadm5/admin.h>
@@ -55,7 +55,7 @@ typedef struct _kadm5_server_handle_t {
krb5_principal current_caller;
kadm5_config_params params;
struct _kadm5_server_handle_t *lhandle;
- char **db_args;
+ char **db_args;
krb5_keyblock master_keyblock;
} kadm5_server_handle_rec, *kadm5_server_handle_t;
@@ -76,6 +76,7 @@ typedef struct _osa_princ_ent_t {
osa_pw_hist_ent *old_keys;
} osa_princ_ent_rec, *osa_princ_ent_t;
+
kadm5_ret_t adb_policy_init(kadm5_server_handle_t handle);
kadm5_ret_t adb_policy_close(kadm5_server_handle_t handle);
kadm5_ret_t passwd_check(kadm5_server_handle_t handle,
@@ -96,7 +97,8 @@ krb5_error_code kdb_put_entry(kadm5_server_handle_t handle,
krb5_db_entry *kdb, osa_princ_ent_rec *adb);
krb5_error_code kdb_delete_entry(kadm5_server_handle_t handle,
krb5_principal name);
-krb5_error_code kdb_iter_entry(kadm5_server_handle_t handle, char *,
+krb5_error_code kdb_iter_entry(kadm5_server_handle_t handle,
+ char *match_entry,
void (*iter_fct)(void *, krb5_principal),
void *data);
@@ -161,4 +163,5 @@ bool_t xdr_osa_princ_ent_rec(XDR *xdrs, osa_princ_ent_t objp);
void
osa_free_princ_ent(osa_princ_ent_t val);
+
#endif /* __KADM5_SERVER_INTERNAL_H__ */
diff --git a/usr/src/lib/krb5/kadm5/srv/adb_xdr.c b/usr/src/lib/krb5/kadm5/srv/adb_xdr.c
index 7b554d72f1..cb5e4e705f 100644
--- a/usr/src/lib/krb5/kadm5/srv/adb_xdr.c
+++ b/usr/src/lib/krb5/kadm5/srv/adb_xdr.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -26,17 +25,17 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/adb_xdr.c,v 1.4 2001/07/25 19:03:35 epeisach Exp $
+ * $Header$
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/adb_xdr.c,v 1.2 1998/02/14 02:31:34 tlyu Exp $";
+static char *rcsid = "$Header$";
#endif
#include <sys/types.h>
+#include "server_internal.h"
#include <krb5.h>
#include <rpc/rpc.h> /* SUNWresync121 XXX */
-#include "server_internal.h"
#include "admin_xdr.h"
#ifdef HAVE_MEMORY_H
#include <memory.h>
@@ -133,3 +132,4 @@ osa_free_princ_ent(osa_princ_ent_t val)
xdr_osa_princ_ent_rec(&xdrs, val);
free(val);
}
+
diff --git a/usr/src/lib/krb5/kadm5/srv/logger.c b/usr/src/lib/krb5/kadm5/srv/logger.c
index 1887746824..8722275935 100644
--- a/usr/src/lib/krb5/kadm5/srv/logger.c
+++ b/usr/src/lib/krb5/kadm5/srv/logger.c
@@ -3,7 +3,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/kadm/logger.c
*
@@ -31,7 +30,6 @@
*
*/
-
/* KADM5 wants non-syslog log files to contain syslog-like entries */
#define VERBOSE_LOGS
@@ -44,8 +42,14 @@
#include <stdio.h>
#include <ctype.h>
#include <ctype.h>
+#ifdef HAVE_SYSLOG_H
#include <syslog.h>
+#endif /* HAVE_SYSLOG_H */
+#ifdef HAVE_STDARG_H
#include <stdarg.h>
+#else /* HAVE_STDARG_H */
+#include <varargs.h>
+#endif /* HAVE_STDARG_H */
#include <libintl.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -201,7 +205,6 @@ struct log_control {
char *log_whoami;
char *log_hostname;
krb5_boolean log_opened;
-
};
static struct log_control log_control = {
@@ -357,16 +360,14 @@ klog_rotate(struct log_entry *le)
*/
static krb5_context err_context;
static void
-klog_com_err_proc(whoami, code, format, ap)
- const char *whoami;
- long code;
- const char *format;
- va_list ap;
+klog_com_err_proc(const char *whoami, long code, const char *format, va_list ap)
{
char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
int lindex;
- char *actual_format;
+ const char *actual_format;
+#ifdef HAVE_SYSLOG
int log_pri = -1;
+#endif /* HAVE_SYSLOG */
char *cp;
char *syslogp;
@@ -380,17 +381,19 @@ klog_com_err_proc(whoami, code, format, ap)
/* If reporting an error message, separate it. */
if (code) {
+ /* Solaris Kerberos */
const char *emsg;
outbuf[sizeof(outbuf) - 1] = '\0';
emsg = krb5_get_error_message (err_context, code);
strncat(outbuf, emsg, sizeof(outbuf) - 1 - strlen(outbuf));
- strncat(outbuf, " ", sizeof(outbuf) - 1 - strlen(outbuf));
+ strncat(outbuf, " - ", sizeof(outbuf) - 1 - strlen(outbuf));
krb5_free_error_message(err_context, emsg);
}
cp = &outbuf[strlen(outbuf)];
- actual_format = (char *) format;
+ actual_format = format;
+#ifdef HAVE_SYSLOG
/*
* This is an unpleasant hack. If the first character is less than
* 8, then we assume that it is a priority.
@@ -400,38 +403,61 @@ klog_com_err_proc(whoami, code, format, ap)
* intermediate representation.
*/
if ((((unsigned char) *format) > 0) && (((unsigned char) *format) <= 8)) {
- actual_format = (char *) (format + 1);
+ actual_format = (format + 1);
switch ((unsigned char) *format) {
+#ifdef LOG_EMERG
case 1:
log_pri = LOG_EMERG;
break;
+#endif /* LOG_EMERG */
+#ifdef LOG_ALERT
case 2:
log_pri = LOG_ALERT;
break;
+#endif /* LOG_ALERT */
+#ifdef LOG_CRIT
case 3:
log_pri = LOG_CRIT;
break;
+#endif /* LOG_CRIT */
default:
case 4:
log_pri = LOG_ERR;
break;
+#ifdef LOG_WARNING
case 5:
log_pri = LOG_WARNING;
break;
+#endif /* LOG_WARNING */
+#ifdef LOG_NOTICE
case 6:
log_pri = LOG_NOTICE;
break;
+#endif /* LOG_NOTICE */
+#ifdef LOG_INFO
case 7:
log_pri = LOG_INFO;
break;
+#endif /* LOG_INFO */
+#ifdef LOG_DEBUG
case 8:
log_pri = LOG_DEBUG;
break;
+#endif /* LOG_DEBUG */
}
}
+#endif /* HAVE_SYSLOG */
/* Now format the actual message */
- vsnprintf(cp, sizeof (outbuf) - (cp - outbuf), actual_format, ap);
+#if HAVE_VSNPRINTF
+ vsnprintf(cp, sizeof(outbuf) - (cp - outbuf), actual_format, ap);
+#elif HAVE_VSPRINTF
+ vsprintf(cp, actual_format, ap);
+#else /* HAVE_VSPRINTF */
+ sprintf(cp, actual_format, ((int *) ap)[0], ((int *) ap)[1],
+ ((int *) ap)[2], ((int *) ap)[3],
+ ((int *) ap)[4], ((int *) ap)[5]);
+#endif /* HAVE_VSPRINTF */
/*
* Now that we have the message formatted, perform the output to each
@@ -469,6 +495,7 @@ klog_com_err_proc(whoami, code, format, ap)
log_control.log_entries[lindex].ldu_devname);
}
break;
+#ifdef HAVE_SYSLOG
case K_LOG_SYSLOG:
/*
* System log.
@@ -486,6 +513,7 @@ klog_com_err_proc(whoami, code, format, ap)
/* Log the message with our header trimmed off */
syslog(log_pri, "%s", syslogp);
break;
+#endif /* HAVE_SYSLOG */
default:
break;
}
@@ -514,18 +542,14 @@ klog_com_err_proc(whoami, code, format, ap)
* where/how to send output.
*/
krb5_error_code
-krb5_klog_init(kcontext, ename, whoami, do_com_err)
- krb5_context kcontext;
- char *ename;
- char *whoami;
- krb5_boolean do_com_err;
+krb5_klog_init(krb5_context kcontext, char *ename, char *whoami, krb5_boolean do_com_err)
{
const char *logging_profent[3];
const char *logging_defent[3];
char **logging_specs;
int i, ngood;
char *cp, *cp2;
- char savec;
+ char savec = '\0';
int error;
int do_openlog, log_facility;
FILE *f;
@@ -580,9 +604,9 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
* <whitespace><data><whitespace>
* so, trim off the leading and trailing whitespace here.
*/
- for (cp = logging_specs[i]; isspace(*cp); cp++);
+ for (cp = logging_specs[i]; isspace((int) *cp); cp++);
for (cp2 = &logging_specs[i][strlen(logging_specs[i])-1];
- isspace(*cp2); cp2--);
+ isspace((int) *cp2); cp2--);
cp2++;
*cp2 = '\0';
/*
@@ -652,12 +676,13 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
}
} else {
- fprintf(stderr,gettext("Couldn't open log file %s: %s\n"),
+ fprintf(stderr, gettext("Couldn't open log file %s: %s\n"),
&cp[5], error_message(errno));
continue;
}
}
}
+#ifdef HAVE_SYSLOG
/*
* Is this a syslog?
*/
@@ -672,7 +697,8 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
/*
* Find the end of the severity.
*/
- if (cp2 = strchr(&cp[7], ':')) {
+ cp2 = strchr(&cp[7], ':');
+ if (cp2) {
savec = *cp2;
*cp2 = '\0';
cp2++;
@@ -684,32 +710,46 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
if (!strcasecmp(&cp[7], "ERR")) {
log_control.log_entries[i].lsu_severity = LOG_ERR;
}
+#ifdef LOG_EMERG
else if (!strcasecmp(&cp[7], "EMERG")) {
log_control.log_entries[i].lsu_severity =
LOG_EMERG;
}
+#endif /* LOG_EMERG */
+#ifdef LOG_ALERT
else if (!strcasecmp(&cp[7], "ALERT")) {
log_control.log_entries[i].lsu_severity =
LOG_ALERT;
}
+#endif /* LOG_ALERT */
+#ifdef LOG_CRIT
else if (!strcasecmp(&cp[7], "CRIT")) {
log_control.log_entries[i].lsu_severity = LOG_CRIT;
}
+#endif /* LOG_CRIT */
+#ifdef LOG_WARNING
else if (!strcasecmp(&cp[7], "WARNING")) {
log_control.log_entries[i].lsu_severity =
LOG_WARNING;
}
+#endif /* LOG_WARNING */
+#ifdef LOG_NOTICE
else if (!strcasecmp(&cp[7], "NOTICE")) {
log_control.log_entries[i].lsu_severity =
LOG_NOTICE;
}
+#endif /* LOG_NOTICE */
+#ifdef LOG_INFO
else if (!strcasecmp(&cp[7], "INFO")) {
log_control.log_entries[i].lsu_severity = LOG_INFO;
}
+#endif /* LOG_INFO */
+#ifdef LOG_DEBUG
else if (!strcasecmp(&cp[7], "DEBUG")) {
log_control.log_entries[i].lsu_severity =
LOG_DEBUG;
}
+#endif /* LOG_DEBUG */
else
error = 1;
@@ -778,12 +818,14 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
log_facility = log_control.log_entries[i].lsu_facility;
}
}
+#endif /* HAVE_SYSLOG */
/*
* Is this a standard error specification?
*/
else if (!strcasecmp(cp, "STDERR")) {
- if (log_control.log_entries[i].lfu_filep =
- fdopen(fileno(stderr), "a+F")) {
+ log_control.log_entries[i].lfu_filep =
+ fdopen(fileno(stderr), "a+F");
+ if (log_control.log_entries[i].lfu_filep) {
log_control.log_entries[i].log_type = K_LOG_STDERR;
log_control.log_entries[i].lfu_fname =
"standard error";
@@ -793,8 +835,9 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
* Is this a specification of the console?
*/
else if (!strcasecmp(cp, "CONSOLE")) {
- if (log_control.log_entries[i].ldu_filep =
- CONSOLE_OPEN("a+F")) {
+ log_control.log_entries[i].ldu_filep =
+ CONSOLE_OPEN("a+F");
+ if (log_control.log_entries[i].ldu_filep) {
log_control.log_entries[i].log_type = K_LOG_CONSOLE;
log_control.log_entries[i].ldu_devname = "console";
}
@@ -807,8 +850,9 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
* We handle devices very similarly to files.
*/
if (cp[6] == '=') {
- if (log_control.log_entries[i].ldu_filep =
- DEVICE_OPEN(&cp[7], "wF")) {
+ log_control.log_entries[i].ldu_filep =
+ DEVICE_OPEN(&cp[7], "wF");
+ if (log_control.log_entries[i].ldu_filep) {
log_control.log_entries[i].log_type = K_LOG_DEVICE;
log_control.log_entries[i].ldu_devname = &cp[7];
}
@@ -850,14 +894,21 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
log_control.log_nentries = 1;
}
if (log_control.log_nentries) {
- if (log_control.log_whoami = (char *) malloc(strlen(whoami)+1))
+ log_control.log_whoami = (char *) malloc(strlen(whoami)+1);
+ if (log_control.log_whoami)
strcpy(log_control.log_whoami, whoami);
- if (log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN))
+
+ log_control.log_hostname = (char *) malloc(MAXHOSTNAMELEN + 1);
+ if (log_control.log_hostname) {
gethostname(log_control.log_hostname, MAXHOSTNAMELEN);
+ log_control.log_hostname[MAXHOSTNAMELEN] = '\0';
+ }
+#ifdef HAVE_OPENLOG
if (do_openlog) {
openlog(whoami, LOG_NDELAY|LOG_PID, log_facility);
log_control.log_opened = 1;
}
+#endif /* HAVE_OPENLOG */
if (do_com_err)
(void) set_com_err_hook(klog_com_err_proc);
}
@@ -868,8 +919,7 @@ krb5_klog_init(kcontext, ename, whoami, do_com_err)
* krb5_klog_close() - Close the logging context and free all data.
*/
void
-krb5_klog_close(kcontext)
- krb5_context kcontext;
+krb5_klog_close(krb5_context kcontext)
{
int lindex;
(void) reset_com_err_hook();
@@ -889,11 +939,13 @@ krb5_klog_close(kcontext)
*/
DEVICE_CLOSE(log_control.log_entries[lindex].ldu_filep);
break;
+#ifdef HAVE_SYSLOG
case K_LOG_SYSLOG:
/*
* System log.
*/
break;
+#endif /* HAVE_SYSLOG */
default:
break;
}
@@ -910,16 +962,17 @@ krb5_klog_close(kcontext)
if (log_control.log_hostname)
free(log_control.log_hostname);
log_control.log_hostname = (char *) NULL;
+#ifdef HAVE_CLOSELOG
if (log_control.log_opened)
closelog();
+#endif /* HAVE_CLOSELOG */
}
/*
* severity2string() - Convert a severity to a string.
*/
-static char *
-severity2string(severity)
- int severity;
+static const char *
+severity2string(int severity)
{
int s;
const char *ss;
@@ -927,30 +980,44 @@ severity2string(severity)
s = severity & LOG_PRIMASK;
ss = krb5_log_error_table(LOG_UFO_STRING);
switch (s) {
+#ifdef LOG_EMERG
case LOG_EMERG:
ss = krb5_log_error_table(LOG_EMERG_STRING);
break;
+#endif /* LOG_EMERG */
+#ifdef LOG_ALERT
case LOG_ALERT:
ss = krb5_log_error_table(LOG_ALERT_STRING);
break;
+#endif /* LOG_ALERT */
+#ifdef LOG_CRIT
case LOG_CRIT:
ss = krb5_log_error_table(LOG_CRIT_STRING);
break;
+#endif /* LOG_CRIT */
case LOG_ERR:
ss = krb5_log_error_table(LOG_ERR_STRING);
break;
+#ifdef LOG_WARNING
case LOG_WARNING:
ss = krb5_log_error_table(LOG_WARNING_STRING);
break;
+#endif /* LOG_WARNING */
+#ifdef LOG_NOTICE
case LOG_NOTICE:
ss = krb5_log_error_table(LOG_NOTICE_STRING);
break;
+#endif /* LOG_NOTICE */
+#ifdef LOG_INFO
case LOG_INFO:
ss = krb5_log_error_table(LOG_INFO_STRING);
break;
+#endif /* LOG_INFO */
+#ifdef LOG_DEBUG
case LOG_DEBUG:
ss = krb5_log_error_table(LOG_DEBUG_STRING);
break;
+#endif /* LOG_DEBUG */
}
return((char *) ss);
}
@@ -961,17 +1028,16 @@ severity2string(severity)
* by krb5_klog_init().
*/
static int
-klog_vsyslog(priority, format, arglist)
- int priority;
- const char *format;
- va_list arglist;
+klog_vsyslog(int priority, const char *format, va_list arglist)
{
char outbuf[KRB5_KLOG_MAX_ERRMSG_SIZE];
int lindex;
char *syslogp;
char *cp;
time_t now;
+#ifdef HAVE_STRFTIME
size_t soff;
+#endif /* HAVE_STRFTIME */
/*
* Format a syslog-esque message of the format:
@@ -984,6 +1050,7 @@ klog_vsyslog(priority, format, arglist)
*/
cp = outbuf;
(void) time(&now);
+#ifdef HAVE_STRFTIME
/*
* Format the date: mon dd hh:mm:ss
*/
@@ -992,6 +1059,16 @@ klog_vsyslog(priority, format, arglist)
cp += soff;
else
return(-1);
+#else /* HAVE_STRFTIME */
+ /*
+ * Format the date:
+ * We ASSUME here that the output of ctime is of the format:
+ * dow mon dd hh:mm:ss tzs yyyy\n
+ * 012345678901234567890123456789
+ */
+ strncpy(outbuf, ctime(&now) + 4, 15);
+ cp += 15;
+#endif /* HAVE_STRFTIME */
#ifdef VERBOSE_LOGS
sprintf(cp, " %s %s[%ld](%s): ",
log_control.log_hostname, log_control.log_whoami, (long) getpid(),
@@ -1002,7 +1079,26 @@ klog_vsyslog(priority, format, arglist)
syslogp = &outbuf[strlen(outbuf)];
/* Now format the actual message */
- vsnprintf(syslogp, sizeof (outbuf) - (syslogp - outbuf), format, arglist);
+#ifdef HAVE_VSNPRINTF
+ vsnprintf(syslogp, sizeof(outbuf) - (syslogp - outbuf), format, arglist);
+#elif HAVE_VSPRINTF
+ vsprintf(syslogp, format, arglist);
+#else /* HAVE_VSPRINTF */
+ sprintf(syslogp, format, ((int *) arglist)[0], ((int *) arglist)[1],
+ ((int *) arglist)[2], ((int *) arglist)[3],
+ ((int *) arglist)[4], ((int *) arglist)[5]);
+#endif /* HAVE_VSPRINTF */
+
+ /*
+ * If the user did not use krb5_klog_init() instead of dropping
+ * the request on the floor, syslog it - if it exists
+ */
+#ifdef HAVE_SYSLOG
+ if (log_control.log_nentries == 0) {
+ /* Log the message with our header trimmed off */
+ syslog(priority, "%s", syslogp);
+ }
+#endif
/*
* Now that we have the message formatted, perform the output to each
@@ -1042,6 +1138,7 @@ klog_vsyslog(priority, format, arglist)
log_control.log_entries[lindex].ldu_devname);
}
break;
+#ifdef HAVE_SYSLOG
case K_LOG_SYSLOG:
/*
* System log.
@@ -1050,6 +1147,7 @@ klog_vsyslog(priority, format, arglist)
/* Log the message with our header trimmed off */
syslog(priority, "%s", syslogp);
break;
+#endif /* HAVE_SYSLOG */
default:
break;
}
@@ -1077,8 +1175,7 @@ krb5_klog_syslog(int priority, const char *format, ...)
* a new file descriptor for the give filename.
*/
void
-krb5_klog_reopen(kcontext)
-krb5_context kcontext;
+krb5_klog_reopen(krb5_context kcontext)
{
int lindex;
FILE *f;
diff --git a/usr/src/lib/krb5/kadm5/srv/server_acl.c b/usr/src/lib/krb5/kadm5/srv/server_acl.c
index df25e8ad65..513a65dacb 100644
--- a/usr/src/lib/krb5/kadm5/srv/server_acl.c
+++ b/usr/src/lib/krb5/kadm5/srv/server_acl.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -56,8 +55,8 @@
#include <stdio.h>
#include <syslog.h>
#include <sys/param.h>
-#include <gssapi_krb5.h>
#include "k5-int.h"
+#include <gssapi_krb5.h>
#include <kadm5/server_internal.h>
#include <kadm5/admin.h>
#include <adm_proto.h> /* SUNWresync121 XXX */
@@ -118,6 +117,7 @@ static int acl_debug_level = 0;
*/
static const char *acl_catchall_entry = NULL;
+/* Solaris Kerberos */
#define ACL_LINE2LONG_MSG dgettext(TEXT_DOMAIN, \
"%s: line %d too long, truncated\n")
#define ACL_OP_BAD_MSG dgettext(TEXT_DOMAIN, \
@@ -229,7 +229,7 @@ kadm5int_acl_parse_line(lp)
for (op=acle_ops; *op; op++) {
char rop;
- rop = (isupper((int) *op)) ? tolower((int) *op) : *op;
+ rop = (isupper((unsigned char) *op)) ? tolower((unsigned char) *op) : *op;
found = 0;
for (t=0; acl_op_table[t].ao_op; t++) {
if (rop == acl_op_table[t].ao_op) {
@@ -514,7 +514,7 @@ kadm5int_acl_load_acl_file()
DPRINT(DEBUG_CALLS, acl_debug_level, ("* kadm5int_acl_load_acl_file()\n"));
/* Open the ACL file for read */
- afp = fopen(acl_acl_file, "rF");
+ afp = fopen(acl_acl_file, "rF"); /* Solaris Kerberos */
if (afp) {
alineno = 1;
aentpp = &acl_list_head;
@@ -592,6 +592,7 @@ kadm5int_acl_match_data(e1, e2, targetflag, ws)
retval = 1;
if (ws && !targetflag) {
if (ws->nwild >= 9) {
+ /* Solaris Kerberos */
DPRINT(DEBUG_ACL, acl_debug_level,
("Too many wildcards in ACL entry %s\n", e1->data));
}
@@ -603,6 +604,7 @@ kadm5int_acl_match_data(e1, e2, targetflag, ws)
(e1->data[1] >= '1') && (e1->data[1] <= '9')) {
int n = e1->data[1] - '1';
if (n >= ws->nwild) {
+ /* Solaris Kerberos */
DPRINT(DEBUG_ACL, acl_debug_level,
("Too many backrefs in ACL entry %s\n", e1->data));
}
@@ -790,6 +792,7 @@ kadm5int_acl_check(kcontext, caller, opmask, principal, restrictions)
DPRINT(DEBUG_CALLS, acl_debug_level, ("* acl_op_permitted()\n"));
+ /* Solaris Kerberos */
if (restrictions)
*restrictions = NULL;
diff --git a/usr/src/lib/krb5/kadm5/srv/server_acl.h b/usr/src/lib/krb5/kadm5/srv/server_acl.h
index ffe618c82c..5676328c96 100644
--- a/usr/src/lib/krb5/kadm5/srv/server_acl.h
+++ b/usr/src/lib/krb5/kadm5/srv/server_acl.h
@@ -1,12 +1,9 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#ifndef _SERVER_ACL_H
-#define _SERVER_ACL_H
-#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __cplusplus
extern "C" {
@@ -58,6 +55,9 @@ extern "C" {
*
*/
+#ifndef SERVER_ACL_H__
+#define SERVER_ACL_H__
+
#include <admin.h> /* SUNWresync121 XXX */
/*
@@ -136,8 +136,8 @@ krb5_error_code kadm5int_acl_impose_restrictions
kadm5_principal_ent_rec *,
long *,
restriction_t *);
+#endif /* SERVER_ACL_H__ */
#ifdef __cplusplus
}
#endif
-#endif /* !_SERVER_ACL_H */
diff --git a/usr/src/lib/krb5/kadm5/srv/server_dict.c b/usr/src/lib/krb5/kadm5/srv/server_dict.c
index f79262da8c..23567e361d 100644
--- a/usr/src/lib/krb5/kadm5/srv/server_dict.c
+++ b/usr/src/lib/krb5/kadm5/srv/server_dict.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -21,11 +20,11 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_dict.c,v 1.7 2003/01/05 23:27:59 hartmans Exp $
+ * $Header$
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_dict.c,v 1.7 2003/01/05 23:27:59 hartmans Exp $";
+static char *rcsid = "$Header$";
#endif
#include <sys/types.h>
@@ -34,6 +33,7 @@ static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_dict.c,
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
+#include "server_internal.h"
#include <kadm5/admin.h>
#include <stdlib.h>
#include <stdio.h>
@@ -44,7 +44,6 @@ static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_dict.c,
#include "adm_proto.h"
#include <syslog.h>
#include <libintl.h>
-#include "server_internal.h"
static char **word_list = NULL; /* list of word pointers */
static char *word_block = NULL; /* actual word data */
@@ -110,6 +109,7 @@ int init_dict(kadm5_config_params *params)
if(word_list != NULL && word_block != NULL)
return KADM5_OK;
if (! (params->mask & KADM5_CONFIG_DICT_FILE)) {
+ /* Solaris Kerberos */
krb5_klog_syslog(LOG_INFO,
dgettext(TEXT_DOMAIN,
"No dictionary file specified, continuing "
@@ -118,6 +118,7 @@ int init_dict(kadm5_config_params *params)
}
if ((fd = open(params->dict_file, O_RDONLY)) == -1) {
if (errno == ENOENT) {
+ /* Solaris Kerberos */
krb5_klog_syslog(LOG_ERR,
dgettext(TEXT_DOMAIN,
"WARNING! Cannot find dictionary file %s, "
diff --git a/usr/src/lib/krb5/kadm5/srv/server_init.c b/usr/src/lib/krb5/kadm5/srv/server_init.c
index 5cb20542fe..45a7c95bf0 100644
--- a/usr/src/lib/krb5/kadm5/srv/server_init.c
+++ b/usr/src/lib/krb5/kadm5/srv/server_init.c
@@ -3,7 +3,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -26,8 +25,8 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
*
- * $Id: server_init.c,v 1.8 2002/10/15 15:40:49 epeisach Exp $
- * $Source: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_init.c,v $
+ * $Id: server_init.c 18584 2006-09-13 20:30:23Z raeburn $
+ * $Source$
*/
#if !defined(lint) && !defined(__CODECENTER__)
@@ -36,7 +35,9 @@ static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_init.c,
#include <stdio.h>
#include <stdlib.h>
+#include <errno.h>
#include <com_err.h>
+#include "k5-int.h" /* needed for gssapiP_krb5.h */
#include <kadm5/admin.h>
#include <krb5.h>
#include "server_internal.h"
@@ -251,10 +252,8 @@ kadm5_ret_t kadm5_init2(char *client_name, char *pass,
}
#endif
- ret = kadm5_get_config_params(handle->context, (char *) NULL,
- (char *) NULL, params_in,
+ ret = kadm5_get_config_params(handle->context, 1, params_in,
&handle->params);
-
if (ret) {
krb5_free_context(handle->context);
free_db_args(handle);
diff --git a/usr/src/lib/krb5/kadm5/srv/server_kdb.c b/usr/src/lib/krb5/kadm5/srv/server_kdb.c
index 2ad4f184b4..f32b432ccb 100644
--- a/usr/src/lib/krb5/kadm5/srv/server_kdb.c
+++ b/usr/src/lib/krb5/kadm5/srv/server_kdb.c
@@ -2,7 +2,6 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -25,11 +24,11 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_kdb.c,v 1.4 2003/06/13 22:30:59 tlyu Exp $
+ * $Header$
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_kdb.c,v 1.4 2003/06/13 22:30:59 tlyu Exp $";
+static char *rcsid = "$Header$";
#endif
#include <stdio.h>
@@ -73,8 +72,12 @@ krb5_error_code kdb_init_master(kadm5_server_handle_t handle,
handle->params.mkey_name,
realm, NULL, &master_princ)))
goto done;
+/* Solaris Kerberos */
+#if 0
+ master_keyblock.enctype = handle->params.enctype;
+#endif
-
+ /* Solaris Kerberos */
ret = krb5_db_fetch_mkey(handle->context, master_princ,
handle->params.enctype, from_kbd,
FALSE /* only prompt once */,
@@ -85,6 +88,7 @@ krb5_error_code kdb_init_master(kadm5_server_handle_t handle,
if (ret)
goto done;
+ /* Solaris Kerberos */
if ((ret = krb5_db_verify_master_key(handle->context, master_princ,
&handle->master_keyblock))) {
krb5_db_fini(handle->context);
@@ -202,6 +206,7 @@ krb5_error_code kdb_init_hist(kadm5_server_handle_t handle, char *r)
if (ret)
goto done;
+ /* Solaris Kerberos */
ret = krb5_dbekd_decrypt_key_data(handle->context,
&handle->master_keyblock, key_data, &hist_key, NULL);
if (ret)
@@ -281,6 +286,7 @@ kdb_get_entry(kadm5_server_handle_t handle,
return(ret);
}
+ /* Solaris Kerberos */
xdrmem_create(&xdrs, (caddr_t)tl_data.tl_data_contents,
tl_data.tl_data_length, XDR_DECODE);
if (! xdr_osa_princ_ent_rec(&xdrs, adb)) {
@@ -372,6 +378,7 @@ kdb_put_entry(kadm5_server_handle_t handle,
}
tl_data.tl_data_type = KRB5_TL_KADM_DATA;
tl_data.tl_data_length = xdr_getpos(&xdrs);
+ /* Solaris Kerberos */
tl_data.tl_data_contents = (unsigned char *) xdralloc_getdata(&xdrs);
ret = krb5_dbe_update_tl_data(handle->context, kdb, &tl_data);
diff --git a/usr/src/lib/krb5/kadm5/srv/server_misc.c b/usr/src/lib/krb5/kadm5/srv/server_misc.c
index cbe227e89b..06cf637dcc 100644
--- a/usr/src/lib/krb5/kadm5/srv/server_misc.c
+++ b/usr/src/lib/krb5/kadm5/srv/server_misc.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -21,11 +20,11 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_misc.c,v 1.4 2001/06/18 18:58:00 epeisach Exp $
+ * $Header$
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/server_misc.c,v 1.4 2001/06/18 18:58:00 epeisach Exp $";
+static char *rcsid = "$Header$";
#endif
#include "k5-int.h"
diff --git a/usr/src/lib/krb5/kadm5/srv/svr_chpass_util.c b/usr/src/lib/krb5/kadm5/srv/svr_chpass_util.c
index e010d27f68..0fe0d016a1 100644
--- a/usr/src/lib/krb5/kadm5/srv/svr_chpass_util.c
+++ b/usr/src/lib/krb5/kadm5/srv/svr_chpass_util.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -22,9 +21,8 @@
*
*/
-
-#include <kadm5/admin.h>
#include "server_internal.h"
+#include <kadm5/admin.h>
kadm5_ret_t kadm5_chpass_principal_util(void *server_handle,
krb5_principal princ,
diff --git a/usr/src/lib/krb5/kadm5/srv/svr_iters.c b/usr/src/lib/krb5/kadm5/srv/svr_iters.c
index 722a695272..87f5094bed 100644
--- a/usr/src/lib/krb5/kadm5/srv/svr_iters.c
+++ b/usr/src/lib/krb5/kadm5/srv/svr_iters.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -21,11 +20,11 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/svr_iters.c,v 1.6 2003/01/12 18:17:02 epeisach Exp $
+ * $Header$
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/svr_iters.c,v 1.6 2003/01/12 18:17:02 epeisach Exp $";
+static char *rcsid = "$Header$";
#endif
#include "autoconf.h"
@@ -41,6 +40,7 @@ static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/svr_iters.c,v
#include <sys/types.h>
#include <string.h>
+#include "server_internal.h"
#include <kadm5/admin.h>
#ifdef SOLARIS_REGEXPS
#include <regexpr.h>
@@ -50,7 +50,6 @@ static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/svr_iters.c,v
#endif
#include <stdlib.h>
-#include "server_internal.h"
struct iter_data {
krb5_context context;
diff --git a/usr/src/lib/krb5/kadm5/srv/svr_misc_free.c b/usr/src/lib/krb5/kadm5/srv/svr_misc_free.c
index a552c4e2b4..645eaa2854 100644
--- a/usr/src/lib/krb5/kadm5/srv/svr_misc_free.c
+++ b/usr/src/lib/krb5/kadm5/srv/svr_misc_free.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
*
@@ -21,12 +19,12 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/svr_misc_free.c,v 1.2 1996/10/18 19:45:53 bjaspan Exp $
+ * $Header$
*
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/svr_misc_free.c,v 1.2 1996/10/18 19:45:53 bjaspan Exp $";
+static char *rcsid = "$Header$";
#endif
#include <kadm5/admin.h>
#include <stdlib.h>
diff --git a/usr/src/lib/krb5/kadm5/srv/svr_policy.c b/usr/src/lib/krb5/kadm5/srv/svr_policy.c
index 8aa9604b98..d6c739b2a2 100644
--- a/usr/src/lib/krb5/kadm5/srv/svr_policy.c
+++ b/usr/src/lib/krb5/kadm5/srv/svr_policy.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
*
@@ -21,17 +19,18 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/svr_policy.c,v 1.2 2001/06/20 05:01:37 mitchb Exp $
+ * $Header$
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/svr_policy.c,v 1.2 2001/06/20 05:01:37 mitchb Exp $";
+static char *rcsid = "$Header$";
#endif
+#include "server_internal.h"
#include <sys/types.h>
#include <kadm5/admin.h>
-#include "server_internal.h"
#include <stdlib.h>
+#include <errno.h>
#define MAX_PW_HISTORY 10
#define MIN_PW_HISTORY 1
@@ -182,7 +181,7 @@ kadm5_delete_policy(void *server_handle, kadm5_policy_t name)
return EINVAL;
if(strlen(name) == 0)
return KADM5_BAD_POLICY;
- if((ret = krb5_db_get_policy(handle->context, name, &entry, &cnt)))
+ if((ret = krb5_db_get_policy(handle->context, name, &entry,&cnt)))
return ret;
if( cnt != 1 )
return KADM5_UNK_POLICY;
@@ -230,9 +229,9 @@ kadm5_modify_policy_internal(void *server_handle,
if((mask & KADM5_POLICY))
return KADM5_BAD_MASK;
- if((ret = krb5_db_get_policy(handle->context, entry->policy, &p, &cnt)))
+ if ((ret = krb5_db_get_policy(handle->context, entry->policy, &p, &cnt)))
return ret;
- if( cnt != 1 )
+ if (cnt != 1)
return KADM5_UNK_POLICY;
if ((mask & KADM5_PW_MAX_LIFE))
diff --git a/usr/src/lib/krb5/kadm5/srv/svr_principal.c b/usr/src/lib/krb5/kadm5/srv/svr_principal.c
index f4faf5e17f..f02deb362b 100644
--- a/usr/src/lib/krb5/kadm5/srv/svr_principal.c
+++ b/usr/src/lib/krb5/kadm5/srv/svr_principal.c
@@ -3,7 +3,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -26,20 +25,21 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/svr_principal.c,v 1.30.8.1 2004/12/20 21:16:20 tlyu Exp $
+ * $Header$
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/svr_principal.c,v 1.30.8.1 2004/12/20 21:16:20 tlyu Exp $";
+static char *rcsid = "$Header$";
#endif
#include <sys/types.h>
#include <sys/time.h>
+#include <errno.h>
+#include "server_internal.h"
#include <kadm5/admin.h>
#include <kdb.h>
#include <stdio.h>
#include <string.h>
-#include "server_internal.h"
#include <stdarg.h>
#include <stdlib.h>
#ifdef USE_PASSWORD_SERVER
@@ -202,10 +202,6 @@ kadm5_create_principal(void *server_handle,
kadm5_principal_ent_t entry, long mask,
char *password)
{
- /*
- * Default to using the new API with the default set of
- * key/salt combinations.
- */
return
kadm5_create_principal_3(server_handle, entry, mask,
0, NULL, password);
@@ -250,6 +246,7 @@ kadm5_create_principal_3(void *server_handle,
switch(ret) {
case KADM5_UNK_PRINC:
+ /* Solaris Kerberos */
memset(&kdb, 0, sizeof(krb5_db_entry));
memset(&adb, 0, sizeof(osa_princ_ent_rec));
break;
@@ -311,6 +308,7 @@ kadm5_create_principal_3(void *server_handle,
kdb.len = KRB5_KDB_V1_BASE_LENGTH; /* gag me with a chainsaw */
/*
+ * Solaris Kerberos:
* If KADM5_ATTRIBUTES is set, we want to rope in not only
* entry->attributes, but also the generic params.flags
* obtained previously via kadm5_get_config_params.
@@ -1122,106 +1120,214 @@ static kadm5_ret_t add_to_history(krb5_context context,
osa_pw_hist_ent *pw)
{
osa_pw_hist_ent *histp;
- int i;
+ uint32_t nhist;
+ unsigned int i, knext, nkeys;
+
+ nhist = pol->pw_history_num;
+ /* A history of 1 means just check the current password */
+ if (nhist <= 1)
+ return 0;
+
+ nkeys = adb->old_key_len;
+ knext = adb->old_key_next;
+ /* resize the adb->old_keys array if necessary */
+ if (nkeys + 1 < nhist) {
+ if (adb->old_keys == NULL) {
+ adb->old_keys = (osa_pw_hist_ent *)
+ malloc((nkeys + 1) * sizeof (osa_pw_hist_ent));
+ } else {
+ adb->old_keys = (osa_pw_hist_ent *)
+ realloc(adb->old_keys,
+ (nkeys + 1) * sizeof (osa_pw_hist_ent));
+ }
+ if (adb->old_keys == NULL)
+ return(ENOMEM);
+
+ memset(&adb->old_keys[nkeys], 0, sizeof(osa_pw_hist_ent));
+ nkeys = ++adb->old_key_len;
+ /*
+ * To avoid losing old keys, shift forward each entry after
+ * knext.
+ */
+ for (i = nkeys - 1; i > knext; i--) {
+ adb->old_keys[i] = adb->old_keys[i - 1];
+ }
+ memset(&adb->old_keys[knext], 0, sizeof(osa_pw_hist_ent));
+ } else if (nkeys + 1 > nhist) {
+ /*
+ * The policy must have changed! Shrink the array.
+ * Can't simply realloc() down, since it might be wrapped.
+ * To understand the arithmetic below, note that we are
+ * copying into new positions 0 .. N-1 from old positions
+ * old_key_next-N .. old_key_next-1, modulo old_key_len,
+ * where N = pw_history_num - 1 is the length of the
+ * shortened list. Matt Crawford, FNAL
+ */
+ /*
+ * M = adb->old_key_len, N = pol->pw_history_num - 1
+ *
+ * tmp[0] .. tmp[N-1] = old[(knext-N)%M] .. old[(knext-1)%M]
+ */
+ int j;
+ osa_pw_hist_t tmp;
+
+ tmp = (osa_pw_hist_ent *)
+ malloc((nhist - 1) * sizeof (osa_pw_hist_ent));
+ if (tmp == NULL)
+ return ENOMEM;
+ for (i = 0; i < nhist - 1; i++) {
+ /*
+ * Add nkeys once before taking remainder to avoid
+ * negative values.
+ */
+ j = (i + nkeys + knext - (nhist - 1)) % nkeys;
+ tmp[i] = adb->old_keys[j];
+ }
+ /* Now free the ones we don't keep (the oldest ones) */
+ for (i = 0; i < nkeys - (nhist - 1); i++) {
+ j = (i + nkeys + knext) % nkeys;
+ histp = &adb->old_keys[j];
+ for (j = 0; j < histp->n_key_data; j++) {
+ krb5_free_key_data_contents(context, &histp->key_data[j]);
+ }
+ free(histp->key_data);
+ }
+ free((void *)adb->old_keys);
+ adb->old_keys = tmp;
+ nkeys = adb->old_key_len = nhist - 1;
+ knext = adb->old_key_next = 0;
+ }
- /* A history of 1 means just check the current password */
- if (pol->pw_history_num == 1)
- return (0);
-
- /* resize the adb->old_keys array if necessary */
- if (adb->old_key_len < pol->pw_history_num-1) {
- if (adb->old_keys == NULL) {
- adb->old_keys = (osa_pw_hist_ent *)
- malloc((adb->old_key_len + 1) *
- sizeof (osa_pw_hist_ent));
- } else {
- adb->old_keys = (osa_pw_hist_ent *)
- realloc(adb->old_keys,
- (adb->old_key_len + 1) *
- sizeof (osa_pw_hist_ent));
- }
- if (adb->old_keys == NULL)
- return (ENOMEM);
-
- memset(&adb->old_keys[adb->old_key_len], 0,
- sizeof (osa_pw_hist_ent));
- adb->old_key_len++;
- for (i = adb->old_key_len - 1; i > adb->old_key_next; i--)
- adb->old_keys[i] = adb->old_keys[i - 1];
- memset(&adb->old_keys[adb->old_key_next], 0,
- sizeof (osa_pw_hist_ent));
- } else if (adb->old_key_len > pol->pw_history_num-1) {
- /*
- * The policy must have changed! Shrink the array.
- * Can't simply realloc() down, since it might be wrapped.
- * To understand the arithmetic below, note that we are
- * copying into new positions 0 .. N-1 from old positions
- * old_key_next-N .. old_key_next-1, modulo old_key_len,
- * where N = pw_history_num - 1 is the length of the
- * shortened list. Matt Crawford, FNAL
- */
- int j;
- histp = (osa_pw_hist_ent *)
- malloc((pol->pw_history_num - 1) * sizeof (osa_pw_hist_ent));
- if (histp) {
- for (i = 0; i < pol->pw_history_num - 1; i++) {
- /*
- * We need the number we use the modulus
- * operator on to be positive, so after
- * subtracting pol->pw_history_num-1, we
- * add back adb->old_key_len.
- */
- j = KADM_MOD(i - (pol->pw_history_num - 1) +
- adb->old_key_len);
- histp[i] = adb->old_keys[j];
- }
- /* Now free the ones we don't keep (the oldest ones) */
- for (i = 0; i < adb->old_key_len - \
- (pol->pw_history_num-1); i++) {
- for (j = 0; j < \
- adb->old_keys[KADM_MOD(i)].n_key_data; j++)
- krb5_free_key_data_contents(context,
- &adb->old_keys[KADM_MOD(i)].
- key_data[j]);
- free(adb->old_keys[KADM_MOD(i)].key_data);
- }
- free((void *)adb->old_keys);
- adb->old_keys = histp;
- adb->old_key_len = pol->pw_history_num - 1;
- adb->old_key_next = 0;
- } else {
- return (ENOMEM);
- }
- }
+ /*
+ * If nhist decreased since the last password change, and nkeys+1
+ * is less than the previous nhist, it is possible for knext to
+ * index into unallocated space. This condition would not be
+ * caught by the resizing code above.
+ */
+ if (knext + 1 > nkeys)
+ knext = adb->old_key_next = 0;
+ /* free the old pw history entry if it contains data */
+ histp = &adb->old_keys[knext];
+ for (i = 0; i < histp->n_key_data; i++)
+ krb5_free_key_data_contents(context, &histp->key_data[i]);
+ free(histp->key_data);
+
+ /* store the new entry */
+ adb->old_keys[knext] = *pw;
+
+ /* update the next pointer */
+ if (++adb->old_key_next == nhist - 1)
+ adb->old_key_next = 0;
+
+ return(0);
+}
+#undef KADM_MOD
+
+#ifdef USE_PASSWORD_SERVER
+/* FIXME: don't use global variable for this */
+krb5_boolean use_password_server = 0;
- if (adb->old_key_next + 1 > adb->old_key_len)
- adb->old_key_next = 0;
+static krb5_boolean
+kadm5_use_password_server (void)
+{
+ return use_password_server;
+}
- /* free the old pw history entry if it contains data */
- histp = &adb->old_keys[adb->old_key_next];
- for (i = 0; i < histp->n_key_data; i++)
- krb5_free_key_data_contents(context, &histp->key_data[i]);
- free(histp->key_data);
+void
+kadm5_set_use_password_server (void)
+{
+ use_password_server = 1;
+}
+#endif
- /* store the new entry */
- adb->old_keys[adb->old_key_next] = *pw;
+#ifdef USE_PASSWORD_SERVER
- /* update the next pointer */
- if (++adb->old_key_next == pol->pw_history_num-1)
- adb->old_key_next = 0;
+/*
+ * 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).
+ *
+ * Because a failure to communicate with the tool results in the
+ * password server falling out of sync with the database,
+ * kadm5_launch_task() always fails if it can't talk to the tool.
+ */
- return (0);
+static kadm5_ret_t
+kadm5_launch_task (krb5_context context,
+ const char *task_path, char * const task_argv[],
+ const char *data_buffer)
+{
+ kadm5_ret_t ret = 0;
+ int data_pipe[2];
+
+ if (data_buffer != NULL) {
+ ret = pipe (data_pipe);
+ if (ret) { ret = errno; }
+ }
+
+ if (!ret) {
+ pid_t pid = fork ();
+ if (pid == -1) {
+ ret = errno;
+ } else if (pid == 0) {
+ /* The child: */
+
+ if (data_buffer != NULL) {
+ if (dup2 (data_pipe[0], STDIN_FILENO) == -1) {
+ _exit (1);
+ }
+ } else {
+ close (data_pipe[0]);
+ }
+
+ close (data_pipe[1]);
+
+ execv (task_path, task_argv);
+
+ _exit (1); /* Fail if execv fails */
+ } else {
+ /* The parent: */
+ int status;
+
+ if (data_buffer != NULL) {
+ /* Write out the buffer to the child */
+ if (krb5_net_write (context, data_pipe[1],
+ data_buffer, strlen (data_buffer)) < 0) {
+ /* kill the child to make sure waitpid() won't hang later */
+ ret = errno;
+ kill (pid, SIGKILL);
+ }
+ }
+
+ close (data_buffer[0]);
+ close (data_buffer[1]);
+
+ waitpid (pid, &status, 0);
+
+ if (!ret) {
+ if (WIFEXITED (status)) {
+ /* child read password and exited. Check the return value. */
+ if ((WEXITSTATUS (status) != 0) && (WEXITSTATUS (status) != 252)) {
+ ret = KRB5KDC_ERR_POLICY; /* password change rejected */
+ }
+ } else {
+ /* child read password but crashed or was killed */
+ ret = KRB5KRB_ERR_GENERIC; /* FIXME: better error */
+ }
+ }
+ }
+ }
+
+ return ret;
}
-#undef KADM_MOD
+
+#endif
kadm5_ret_t
kadm5_chpass_principal(void *server_handle,
krb5_principal principal, char *password)
{
- /*
- * Default to using the new API with the default set of
- * key/salt combinations.
- */
return
kadm5_chpass_principal_3(server_handle, principal, FALSE,
0, NULL, password);
@@ -1352,6 +1458,42 @@ kadm5_chpass_principal_3(void *server_handle,
kdb.pw_expiration = 0;
}
+#ifdef USE_PASSWORD_SERVER
+ if (kadm5_use_password_server () &&
+ (krb5_princ_size (handle->context, principal) == 1)) {
+ krb5_data *princ = krb5_princ_component (handle->context, principal, 0);
+ const char *path = "/usr/sbin/mkpassdb";
+ char *argv[] = { "mkpassdb", "-setpassword", NULL, NULL };
+ char *pstring = NULL;
+ char pwbuf[256];
+ int pwlen = strlen (password);
+
+ if (pwlen > 254) pwlen = 254;
+ strncpy (pwbuf, password, pwlen);
+ pwbuf[pwlen] = '\n';
+ pwbuf[pwlen + 1] = '\0';
+
+ if (!ret) {
+ pstring = malloc ((princ->length + 1) * sizeof (char));
+ if (pstring == NULL) { ret = errno; }
+ }
+
+ if (!ret) {
+ memcpy (pstring, princ->data, princ->length);
+ pstring [princ->length] = '\0';
+ argv[2] = pstring;
+
+ ret = kadm5_launch_task (handle->context, path, argv, pwbuf);
+ }
+
+ if (pstring != NULL)
+ free (pstring);
+
+ if (ret)
+ goto done;
+ }
+#endif
+
ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now);
if (ret)
goto done;
@@ -1388,6 +1530,7 @@ kadm5_randkey_principal(void *server_handle,
krb5_keyblock **keyblocks,
int *n_keys)
{
+ /* Solaris Kerberos: */
krb5_key_salt_tuple keysalts[2];
/*
@@ -1406,7 +1549,6 @@ kadm5_randkey_principal(void *server_handle,
return (kadm5_randkey_principal_3(server_handle, principal,
FALSE, 2, keysalts, keyblocks, n_keys));
}
-
kadm5_ret_t
kadm5_randkey_principal_3(void *server_handle,
krb5_principal principal,
@@ -1544,6 +1686,175 @@ done:
return ret;
}
+#if 0 /* Solaris Kerberos */
+/*
+ * kadm5_setv4key_principal:
+ *
+ * Set only ONE key of the principal, removing all others. This key
+ * must have the DES_CBC_CRC enctype and is entered as having the
+ * krb4 salttype. This is to enable things like kadmind4 to work.
+ */
+kadm5_ret_t
+kadm5_setv4key_principal(void *server_handle,
+ krb5_principal principal,
+ krb5_keyblock *keyblock)
+{
+ krb5_db_entry kdb;
+ osa_princ_ent_rec adb;
+ krb5_int32 now;
+ kadm5_policy_ent_rec pol;
+ krb5_keysalt keysalt;
+ int i, k, kvno, ret, have_pol = 0;
+#if 0
+ int last_pwd;
+#endif
+ kadm5_server_handle_t handle = server_handle;
+ krb5_key_data tmp_key_data;
+
+ memset( &tmp_key_data, 0, sizeof(tmp_key_data));
+
+ CHECK_HANDLE(server_handle);
+
+ krb5_clear_error_message(handle->context);
+
+ if (principal == NULL || keyblock == NULL)
+ return EINVAL;
+ if (hist_princ && /* this will be NULL when initializing the databse */
+ ((krb5_principal_compare(handle->context,
+ principal, hist_princ)) == TRUE))
+ return KADM5_PROTECT_PRINCIPAL;
+
+ if (keyblock->enctype != ENCTYPE_DES_CBC_CRC)
+ return KADM5_SETV4KEY_INVAL_ENCTYPE;
+
+ if ((ret = kdb_get_entry(handle, principal, &kdb, &adb)))
+ return(ret);
+
+ for (kvno = 0, i=0; i<kdb.n_key_data; i++)
+ if (kdb.key_data[i].key_data_kvno > kvno)
+ kvno = kdb.key_data[i].key_data_kvno;
+
+ 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;
+ memset(kdb.key_data, 0, sizeof(krb5_key_data));
+ kdb.n_key_data = 1;
+ keysalt.type = KRB5_KDB_SALTTYPE_V4;
+ /* XXX data.magic? */
+ keysalt.data.length = 0;
+ keysalt.data.data = NULL;
+
+ /* use tmp_key_data as temporary location and reallocate later */
+ ret = krb5_dbekd_encrypt_key_data(handle->context, &master_keyblock,
+ keyblock, &keysalt, kvno + 1,
+ &tmp_key_data);
+ if (ret) {
+ goto done;
+ }
+
+ for (k = 0; k < tmp_key_data.key_data_ver; k++) {
+ kdb.key_data->key_data_type[k] = tmp_key_data.key_data_type[k];
+ kdb.key_data->key_data_length[k] = tmp_key_data.key_data_length[k];
+ if (tmp_key_data.key_data_contents[k]) {
+ kdb.key_data->key_data_contents[k] = krb5_db_alloc(handle->context, NULL, tmp_key_data.key_data_length[k]);
+ if (kdb.key_data->key_data_contents[k] == NULL) {
+ cleanup_key_data(handle->context, kdb.n_key_data, kdb.key_data);
+ kdb.key_data = NULL;
+ kdb.n_key_data = 0;
+ ret = ENOMEM;
+ goto done;
+ }
+ memcpy (kdb.key_data->key_data_contents[k], tmp_key_data.key_data_contents[k], tmp_key_data.key_data_length[k]);
+
+ memset (tmp_key_data.key_data_contents[k], 0, tmp_key_data.key_data_length[k]);
+ free (tmp_key_data.key_data_contents[k]);
+ tmp_key_data.key_data_contents[k] = NULL;
+ }
+ }
+
+
+
+ kdb.attributes &= ~KRB5_KDB_REQUIRES_PWCHANGE;
+
+ ret = krb5_timeofday(handle->context, &now);
+ if (ret)
+ goto done;
+
+ if ((adb.aux_attributes & KADM5_POLICY)) {
+ if ((ret = kadm5_get_policy(handle->lhandle, adb.policy,
+ &pol)) != KADM5_OK)
+ goto done;
+ have_pol = 1;
+
+#if 0
+ /*
+ * The spec says this check is overridden if the caller has
+ * modify privilege. The admin server therefore makes this
+ * check itself (in chpass_principal_wrapper, misc.c). A
+ * local caller implicitly has all authorization bits.
+ */
+ if (ret = krb5_dbe_lookup_last_pwd_change(handle->context,
+ &kdb, &last_pwd))
+ goto done;
+ if((now - last_pwd) < pol.pw_min_life &&
+ !(kdb.attributes & KRB5_KDB_REQUIRES_PWCHANGE)) {
+ ret = KADM5_PASS_TOOSOON;
+ goto done;
+ }
+#endif
+#if 0
+ /*
+ * Should we be checking/updating pw history here?
+ */
+ if(pol.pw_history_num > 1) {
+ if(adb.admin_history_kvno != hist_kvno) {
+ ret = KADM5_BAD_HIST_KEY;
+ goto done;
+ }
+
+ if (ret = check_pw_reuse(handle->context,
+ &hist_key,
+ kdb.n_key_data, kdb.key_data,
+ adb.old_key_len, adb.old_keys))
+ goto done;
+ }
+#endif
+
+ if (pol.pw_max_life)
+ kdb.pw_expiration = now + pol.pw_max_life;
+ else
+ kdb.pw_expiration = 0;
+ } else {
+ kdb.pw_expiration = 0;
+ }
+
+ ret = krb5_dbe_update_last_pwd_change(handle->context, &kdb, now);
+ if (ret)
+ goto done;
+
+ if ((ret = kdb_put_entry(handle, &kdb, &adb)))
+ goto done;
+
+ ret = KADM5_OK;
+done:
+ for (i = 0; i < tmp_key_data.key_data_ver; i++) {
+ if (tmp_key_data.key_data_contents[i]) {
+ memset (tmp_key_data.key_data_contents[i], 0, tmp_key_data.key_data_length[i]);
+ free (tmp_key_data.key_data_contents[i]);
+ }
+ }
+
+ kdb_free_entry(handle, &kdb, &adb);
+ if (have_pol)
+ kadm5_free_policy_ent(handle->lhandle, &pol);
+
+ return ret;
+}
+#endif
+
kadm5_ret_t
kadm5_setkey_principal(void *server_handle,
krb5_principal principal,
@@ -1870,6 +2181,13 @@ kadm5_ret_t kadm5_decrypt_key(void *server_handle,
keyblock, keysalt)))
return ret;
+ /*
+ * Coerce the enctype of the output keyblock in case we got an
+ * inexact match on the enctype; this behavior will go away when
+ * the key storage architecture gets redesigned for 1.3.
+ */
+ keyblock->enctype = ktype;
+
if (kvnop)
*kvnop = key_data->key_data_kvno;
diff --git a/usr/src/lib/krb5/kadm5/srv/xdr_alloc.c b/usr/src/lib/krb5/kadm5/srv/xdr_alloc.c
index 9bc36b9e37..db3aa953af 100644
--- a/usr/src/lib/krb5/kadm5/srv/xdr_alloc.c
+++ b/usr/src/lib/krb5/kadm5/srv/xdr_alloc.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -54,65 +53,29 @@ static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
*
- * $Header: /afs/athena.mit.edu/astaff/project/krbdev/.cvsroot/src/lib/rpc/xdr_alloc.c,v 1.6 1996/07/22 20:41:21 marc Exp $
- *
- * $Log: xdr_alloc.c,v $
- * Revision 1.6 1996/07/22 20:41:21 marc
- * this commit includes all the changes on the OV_9510_INTEGRATION and
- * OV_MERGE branches. This includes, but is not limited to, the new openvision
- * admin system, and major changes to gssapi to add functionality, and bring
- * the implementation in line with rfc1964. before committing, the
- * code was built and tested for netbsd and solaris.
- *
- * Revision 1.5.4.1 1996/07/18 04:19:49 marc
- * merged in changes from OV_9510_BP to OV_9510_FINAL1
- *
- * Revision 1.5.2.1 1996/06/20 23:40:30 marc
- * File added to the repository on a branch
- *
- * Revision 1.5 1996/05/12 06:19:25 marc
- * renamed lots of types: u_foo to unsigned foo, and foo32 to rpc_foo32. This is to make autoconfiscation less painful.
- *
- * Revision 1.4 1995/12/13 14:03:14 grier
- * Longs to ints for Alpha
- *
- * Revision 1.3 1993/12/09 18:57:25 bjaspan
- * [secure-releng/833] misc bugfixes to admin library
- *
- * Revision 1.3 1993/12/06 21:23:08 bjaspan
- * add xdralloc_release
- *
- * Revision 1.2 1993/10/26 21:13:19 bjaspan
- * add casts for correctness
- *
- * Revision 1.1 1993/10/19 03:11:39 bjaspan
- * Initial revision
- *
*/
-#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /afs/athena.mit.edu/astaff/project/krbdev/.cvsroot/src/lib/rpc/xdr_alloc.c,v 1.6 1996/07/22 20:41:21 marc Exp $";
-#endif
-
#include "admin.h"
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <dyn/dyn.h>
+/* Solaris Kerberos - 116 resync */
static bool_t xdralloc_putlong();
static bool_t xdralloc_putbytes();
static unsigned int xdralloc_getpos();
static rpc_inline_t * xdralloc_inline();
static void xdralloc_destroy();
-static bool_t xdralloc_notsup();
-
+static bool_t xdralloc_notsup_getlong();
+static bool_t xdralloc_notsup_getbytes();
+static bool_t xdralloc_notsup_setpos();
static struct xdr_ops xdralloc_ops = {
- xdralloc_notsup,
+ xdralloc_notsup_getlong,
xdralloc_putlong,
- xdralloc_notsup,
+ xdralloc_notsup_getbytes,
xdralloc_putbytes,
xdralloc_getpos,
- xdralloc_notsup,
+ xdralloc_notsup_setpos,
xdralloc_inline,
xdralloc_destroy,
};
@@ -121,9 +84,7 @@ static struct xdr_ops xdralloc_ops = {
* The procedure xdralloc_create initializes a stream descriptor for a
* memory buffer.
*/
-void xdralloc_create(xdrs, op)
- register XDR *xdrs;
- enum xdr_op op;
+void xdralloc_create(XDR *xdrs, enum xdr_op op)
{
xdrs->x_op = op;
xdrs->x_ops = &xdralloc_ops;
@@ -131,35 +92,35 @@ void xdralloc_create(xdrs, op)
/* not allowed to fail */
}
-caddr_t xdralloc_getdata(xdrs)
- XDR *xdrs;
+caddr_t xdralloc_getdata(XDR *xdrs)
{
return (caddr_t) DynGet((DynObject) xdrs->x_private, 0);
}
-void xdralloc_release(xdrs)
- XDR *xdrs;
+void xdralloc_release(XDR *xdrs)
{
DynRelease((DynObject) xdrs->x_private);
}
-static void xdralloc_destroy(xdrs)
- XDR *xdrs;
+static void xdralloc_destroy(XDR *xdrs)
{
DynDestroy((DynObject) xdrs->x_private);
}
-static bool_t xdralloc_notsup()
+static bool_t xdralloc_notsup_getlong(
+ register XDR *xdrs,
+ long *lp)
{
return FALSE;
}
-static bool_t xdralloc_putlong(xdrs, lp)
- register XDR *xdrs;
- rpc_int32 *lp;
+static bool_t xdralloc_putlong(
+ register XDR *xdrs,
+ long *lp)
{
- int l = htonl((rpc_u_int32) *(int *)lp);
-
+ int l = htonl((uint32_t) *lp); /* XXX need bounds checking */
+
+ /* XXX assumes sizeof(int)==4 */
if (DynInsert((DynObject) xdrs->x_private,
DynSize((DynObject) xdrs->x_private), &l,
sizeof(int)) != DYN_OK)
@@ -167,28 +128,45 @@ static bool_t xdralloc_putlong(xdrs, lp)
return (TRUE);
}
-static bool_t xdralloc_putbytes(xdrs, addr, len)
- register XDR *xdrs;
- caddr_t addr;
- register unsigned int len;
+
+static bool_t xdralloc_notsup_getbytes(
+ register XDR *xdrs,
+ caddr_t addr,
+ register unsigned int len)
+{
+ return FALSE;
+}
+
+
+static bool_t xdralloc_putbytes(
+ register XDR *xdrs,
+ caddr_t addr,
+ register unsigned int len)
{
if (DynInsert((DynObject) xdrs->x_private,
DynSize((DynObject) xdrs->x_private),
- addr, len) != DYN_OK)
+ addr, (int) len) != DYN_OK)
return FALSE;
return TRUE;
}
-static unsigned int xdralloc_getpos(xdrs)
- register XDR *xdrs;
+static unsigned int xdralloc_getpos(XDR *xdrs)
{
return DynSize((DynObject) xdrs->x_private);
}
+static bool_t xdralloc_notsup_setpos(
+ register XDR *xdrs,
+ unsigned int lp)
+{
+ return FALSE;
+}
+
+
-static rpc_inline_t *xdralloc_inline(xdrs, len)
- register XDR *xdrs;
- int len;
+static rpc_inline_t *xdralloc_inline(
+ register XDR *xdrs,
+ int len)
{
return (rpc_inline_t *) 0;
}
diff --git a/usr/src/lib/krb5/kadm5/str_conv.c b/usr/src/lib/krb5/kadm5/str_conv.c
index 62cb897d49..5d003cf7c8 100644
--- a/usr/src/lib/krb5/kadm5/str_conv.c
+++ b/usr/src/lib/krb5/kadm5/str_conv.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -335,7 +334,7 @@ krb5_string_to_keysalts(string, tupleseps, ksaltseps, dups, ksaltp, nksaltp)
septmp = ksseplist;
for (sp = strchr(kp, (int) *septmp);
*(++septmp) && !sp;
- sp = strchr(kp, (int)*septmp));
+ sp = strchr(kp, (int)*septmp)); /* Solaris Kerberos */
if (sp) {
/* Separate enctype from salttype */
diff --git a/usr/src/lib/krb5/kdb/decrypt_key.c b/usr/src/lib/krb5/kdb/decrypt_key.c
index 73b748c53c..1a04a4a906 100644
--- a/usr/src/lib/krb5/kdb/decrypt_key.c
+++ b/usr/src/lib/krb5/kdb/decrypt_key.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/kdb/decrypt_key.c
@@ -70,12 +69,11 @@
*/
krb5_error_code
-krb5_dbekd_decrypt_key_data(context, mkey, key_data, dbkey, keysalt)
- krb5_context context;
- const krb5_keyblock * mkey;
- const krb5_key_data * key_data;
- krb5_keyblock * dbkey;
- krb5_keysalt * keysalt;
+krb5_dbekd_decrypt_key_data( krb5_context context,
+ const krb5_keyblock * mkey,
+ const krb5_key_data * key_data,
+ krb5_keyblock * dbkey,
+ krb5_keysalt * keysalt)
{
krb5_error_code retval = 0;
krb5_int16 tmplen;
diff --git a/usr/src/lib/krb5/kdb/encrypt_key.c b/usr/src/lib/krb5/kdb/encrypt_key.c
index e5751dc98c..0f69baddec 100644
--- a/usr/src/lib/krb5/kdb/encrypt_key.c
+++ b/usr/src/lib/krb5/kdb/encrypt_key.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/kdb/encrypt_key.c
@@ -70,13 +69,12 @@
*/
krb5_error_code
-krb5_dbekd_encrypt_key_data(context, mkey, dbkey, keysalt, keyver, key_data)
- krb5_context context;
- const krb5_keyblock * mkey;
- const krb5_keyblock * dbkey;
- const krb5_keysalt * keysalt;
- int keyver;
- krb5_key_data * key_data;
+krb5_dbekd_encrypt_key_data( krb5_context context,
+ const krb5_keyblock * mkey,
+ const krb5_keyblock * dbkey,
+ const krb5_keysalt * keysalt,
+ int keyver,
+ krb5_key_data * key_data)
{
krb5_error_code retval;
krb5_octet * ptr;
diff --git a/usr/src/lib/krb5/kdb/kdb_cpw.c b/usr/src/lib/krb5/kdb/kdb_cpw.c
index f44cd9c21d..1e0d781cef 100644
--- a/usr/src/lib/krb5/kdb/kdb_cpw.c
+++ b/usr/src/lib/krb5/kdb/kdb_cpw.c
@@ -1,8 +1,7 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/kdb/kdb_cpw.c
@@ -58,7 +57,7 @@
*/
#include "k5-int.h"
-#include <kdb.h>
+#include "kdb.h"
#include <stdio.h>
#include <errno.h>
@@ -92,11 +91,11 @@ cleanup_key_data(context, count, data)
for (i = 0; i < count; i++) {
for (j = 0; j < data[i].key_data_ver; j++) {
if (data[i].key_data_length[j]) {
- free(data[i].key_data_contents[j]);
+ krb5_db_free(context, data[i].key_data_contents[j]);
}
}
}
- free(data);
+ krb5_db_free(context, data);
}
static krb5_error_code
@@ -112,8 +111,13 @@ add_key_rnd(context, master_key, ks_tuple, ks_tuple_count, db_entry, kvno)
krb5_keyblock key;
krb5_db_entry krbtgt_entry;
krb5_boolean more;
- int max_kvno, one, i, j;
+ int max_kvno, one, i, j, k;
krb5_error_code retval;
+ krb5_key_data tmp_key_data;
+ krb5_key_data *tptr;
+
+ memset( &tmp_key_data, 0, sizeof(tmp_key_data));
+
retval = krb5_build_principal_ext(context, &krbtgt_princ,
db_entry->princ->realm.length,
@@ -182,19 +186,59 @@ add_key_rnd(context, master_key, ks_tuple, ks_tuple_count, db_entry, kvno)
&key)))
goto add_key_rnd_err;
+
+ /* db library will free this. Since, its a so, it could actually be using different memory management
+ function. So, its better if the memory is allocated by the db's malloc. So, a temporary memory is used
+ here which will later be copied to the db_entry */
retval = krb5_dbekd_encrypt_key_data(context, master_key,
&key, NULL, kvno,
- &db_entry->key_data[db_entry->n_key_data-1]);
+ &tmp_key_data);
krb5_free_keyblock_contents(context, &key);
-
- if (retval)
+ if( retval )
goto add_key_rnd_err;
+
+ tptr = &db_entry->key_data[db_entry->n_key_data-1];
+
+ tptr->key_data_ver = tmp_key_data.key_data_ver;
+ tptr->key_data_kvno = tmp_key_data.key_data_kvno;
+
+ for( k = 0; k < tmp_key_data.key_data_ver; k++ )
+ {
+ tptr->key_data_type[k] = tmp_key_data.key_data_type[k];
+ tptr->key_data_length[k] = tmp_key_data.key_data_length[k];
+ if( tmp_key_data.key_data_contents[k] )
+ {
+ tptr->key_data_contents[k] = krb5_db_alloc(context, NULL, tmp_key_data.key_data_length[k]);
+ if( tptr->key_data_contents[k] == NULL )
+ {
+ cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
+ db_entry->key_data = NULL;
+ db_entry->n_key_data = 0;
+ retval = ENOMEM;
+ goto add_key_rnd_err;
+ }
+ memcpy( tptr->key_data_contents[k], tmp_key_data.key_data_contents[k], tmp_key_data.key_data_length[k]);
+
+ memset( tmp_key_data.key_data_contents[k], 0, tmp_key_data.key_data_length[k]);
+ free( tmp_key_data.key_data_contents[k] );
+ tmp_key_data.key_data_contents[k] = NULL;
+ }
+ }
+
}
add_key_rnd_err:
krb5_db_free_principal(context, &krbtgt_entry, one);
+ for( i = 0; i < tmp_key_data.key_data_ver; i++ )
+ {
+ if( tmp_key_data.key_data_contents[i] )
+ {
+ memset( tmp_key_data.key_data_contents[i], 0, tmp_key_data.key_data_length[i]);
+ free( tmp_key_data.key_data_contents[i] );
+ }
+ }
return(retval);
}
@@ -248,6 +292,7 @@ krb5_dbe_crk(context, master_key, ks_tuple, ks_tuple_count, keepold, db_entry)
db_entry->key_data[i+n_new_key_data] = key_data[i];
memset(&key_data[i], 0, sizeof(krb5_key_data));
}
+ krb5_db_free(context, key_data); /* we moved the cotents to new memory. But, the original block which contained the data */
} else {
cleanup_key_data(context, key_data_count, key_data);
}
@@ -327,7 +372,11 @@ add_key_pwd(context, master_key, ks_tuple, ks_tuple_count, passwd,
krb5_keysalt key_salt;
krb5_keyblock key;
krb5_data pwd;
- int i, j;
+ int i, j, k;
+ krb5_key_data tmp_key_data;
+ krb5_key_data *tptr;
+
+ memset( &tmp_key_data, 0, sizeof(tmp_key_data));
retval = 0;
@@ -418,8 +467,10 @@ add_key_pwd(context, master_key, ks_tuple, ks_tuple_count, passwd,
pwd.data = passwd;
pwd.length = strlen(passwd);
+ /* Solaris Kerberos */
memset(&key, 0, sizeof (krb5_keyblock));
-
+
+ /* AFS string to key will happen here */
if ((retval = krb5_c_string_to_key(context, ks_tuple[i].ks_enctype,
&pwd, &key_salt.data, &key))) {
if (key_salt.data.data)
@@ -431,20 +482,58 @@ add_key_pwd(context, master_key, ks_tuple, ks_tuple_count, passwd,
key_salt.data.length =
krb5_princ_realm(context, db_entry->princ)->length;
- if ((retval = krb5_dbekd_encrypt_key_data(context, master_key, &key,
- (const krb5_keysalt *)&key_salt,
- kvno, &db_entry->key_data[db_entry->n_key_data-1]))) {
- if (key_salt.data.data)
- free(key_salt.data.data);
-
- krb5_free_keyblock_contents(context, &key);
- return(retval);
- }
+ /* memory allocation to be done by db. So, use temporary block and later copy
+ it to the memory allocated by db */
+ retval = krb5_dbekd_encrypt_key_data(context, master_key, &key,
+ (const krb5_keysalt *)&key_salt,
+ kvno, &tmp_key_data);
if (key_salt.data.data)
- free(key_salt.data.data);
+ free(key_salt.data.data);
+ /* Solaris Kerberos */
krb5_free_keyblock_contents(context, &key);
+
+ if( retval )
+ return retval;
+
+ tptr = &db_entry->key_data[db_entry->n_key_data-1];
+
+ tptr->key_data_ver = tmp_key_data.key_data_ver;
+ tptr->key_data_kvno = tmp_key_data.key_data_kvno;
+
+ for( k = 0; k < tmp_key_data.key_data_ver; k++ )
+ {
+ tptr->key_data_type[k] = tmp_key_data.key_data_type[k];
+ tptr->key_data_length[k] = tmp_key_data.key_data_length[k];
+ if( tmp_key_data.key_data_contents[k] )
+ {
+ tptr->key_data_contents[k] = krb5_db_alloc(context, NULL, tmp_key_data.key_data_length[k]);
+ if( tptr->key_data_contents[k] == NULL )
+ {
+ cleanup_key_data(context, db_entry->n_key_data, db_entry->key_data);
+ db_entry->key_data = NULL;
+ db_entry->n_key_data = 0;
+ retval = ENOMEM;
+ goto add_key_pwd_err;
+ }
+ memcpy( tptr->key_data_contents[k], tmp_key_data.key_data_contents[k], tmp_key_data.key_data_length[k]);
+
+ memset( tmp_key_data.key_data_contents[k], 0, tmp_key_data.key_data_length[k]);
+ free( tmp_key_data.key_data_contents[k] );
+ tmp_key_data.key_data_contents[k] = NULL;
+ }
+ }
+ }
+ add_key_pwd_err:
+ for( i = 0; i < tmp_key_data.key_data_ver; i++ )
+ {
+ if( tmp_key_data.key_data_contents[i] )
+ {
+ memset( tmp_key_data.key_data_contents[i], 0, tmp_key_data.key_data_length[i]);
+ free( tmp_key_data.key_data_contents[i] );
+ }
}
+
return(retval);
}
@@ -566,3 +655,5 @@ krb5_dbe_apw(context, master_key, ks_tuple, ks_tuple_count, passwd, db_entry)
}
return(retval);
}
+
+
diff --git a/usr/src/lib/krb5/kdb/keytab.c b/usr/src/lib/krb5/kdb/keytab.c
index fbf259a80c..08fb55cfdf 100644
--- a/usr/src/lib/krb5/kdb/keytab.c
+++ b/usr/src/lib/krb5/kdb/keytab.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* kadmin/v5server/keytab.c
*
@@ -150,11 +149,11 @@ krb5_ktkdb_get_entry(in_context, id, principal, kvno, enctype, entry)
kerror = krb5_db_get_principal(context, principal, &
db_entry, &n, &more);
if (kerror) {
- /* krb5_db_close_database(context); */
+ /* krb5_db_close_database(context); */
return(kerror);
}
if (n != 1) {
- /* krb5_db_close_database(context); */
+ /* krb5_db_close_database(context); */
return KRB5_KT_NOTFOUND;
}
@@ -209,7 +208,7 @@ krb5_ktkdb_get_entry(in_context, id, principal, kvno, enctype, entry)
/* Close database */
error:
krb5_db_free_principal(context, &db_entry, 1);
- /* krb5_db_close_database(context); */
+ /* krb5_db_close_database(context); */
return(kerror);
}
diff --git a/usr/src/lib/krb5/plugins/Makefile b/usr/src/lib/krb5/plugins/Makefile
index fcd16e242b..baeda9e18e 100644
--- a/usr/src/lib/krb5/plugins/Makefile
+++ b/usr/src/lib/krb5/plugins/Makefile
@@ -18,10 +18,9 @@
#
# CDDL HEADER END
#
-# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
#
# include global definitions
include ../../../Makefile.master
@@ -31,7 +30,8 @@ include ../../../Makefile.master
.PARALLEL:
SUBDIRS= \
- kdb
+ kdb \
+ preauth
all := TARGET= all
install := TARGET= install
diff --git a/usr/src/lib/krb5/plugins/kdb/db2/adb_policy.c b/usr/src/lib/krb5/plugins/kdb/db2/adb_policy.c
index 2d473e0b98..9b503f3f95 100644
--- a/usr/src/lib/krb5/plugins/kdb/db2/adb_policy.c
+++ b/usr/src/lib/krb5/plugins/kdb/db2/adb_policy.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
@@ -21,11 +20,11 @@
/*
* Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved
*
- * $Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/adb_policy.c,v 1.7 2003/01/05 23:27:59 hartmans Exp $
+ * $Header$
*/
#if !defined(lint) && !defined(__CODECENTER__)
-static char *rcsid = "$Header: /cvs/krbdev/krb5/src/lib/kadm5/srv/adb_policy.c,v 1.7 2003/01/05 23:27:59 hartmans Exp $";
+static char *rcsid = "$Header$";
#endif
#include <sys/file.h>
diff --git a/usr/src/lib/krb5/plugins/kdb/db2/db2_exp.c b/usr/src/lib/krb5/plugins/kdb/db2/db2_exp.c
index df7b42b51f..653e70f8d4 100644
--- a/usr/src/lib/krb5/plugins/kdb/db2/db2_exp.c
+++ b/usr/src/lib/krb5/plugins/kdb/db2/db2_exp.c
@@ -3,7 +3,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Copyright 2006 by the Massachusetts Institute of Technology.
@@ -264,6 +263,6 @@ kdb_vftabl kdb_function_table = {
/* db_free */ wrap_krb5_db2_free,
/* set_master_key */ wrap_krb5_db2_set_master_key_ext,
/* get_master_key */ wrap_krb5_db2_db_get_mkey,
- /* blah blah blah */ 0,0,0,0,0,0,
+ /* blah blah blah */ 0,0,0,0,0,0,
/* promote_db */ wrap_krb5_db2_promote_db,
};
diff --git a/usr/src/lib/krb5/plugins/kdb/db2/kdb_db2.c b/usr/src/lib/krb5/plugins/kdb/db2/kdb_db2.c
index 75676df92e..536b31ee4f 100644
--- a/usr/src/lib/krb5/plugins/kdb/db2/kdb_db2.c
+++ b/usr/src/lib/krb5/plugins/kdb/db2/kdb_db2.c
@@ -3,7 +3,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/kdb/kdb_db2.c
@@ -69,7 +68,7 @@
#include <stdio.h>
#include <errno.h>
#include <utime.h>
-#include <kdb5.h>
+#include "kdb5.h"
#include "kdb_db2.h"
#include "kdb_xdr.h"
#include "policy_db.h"
@@ -938,7 +937,6 @@ krb5_db2_db_destroy(krb5_context context, char *dbname)
if (retval1 || retval2)
return (retval1 ? retval1 : retval2);
-
assert (strlen(dbname) + strlen("%s.kadm5") < sizeof(policy_db_name));
sprintf(policy_db_name, "%s.kadm5", dbname);
/* XXX finish this */
diff --git a/usr/src/lib/krb5/plugins/kdb/db2/libdb2/hash/dbm.c b/usr/src/lib/krb5/plugins/kdb/db2/libdb2/hash/dbm.c
index cdae51c0a3..9d6c7012a5 100644
--- a/usr/src/lib/krb5/plugins/kdb/db2/libdb2/hash/dbm.c
+++ b/usr/src/lib/krb5/plugins/kdb/db2/libdb2/hash/dbm.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*-
* Copyright (c) 1990, 1993
@@ -52,6 +51,7 @@ static char sccsid[] = "@(#)dbm.c 8.6 (Berkeley) 11/7/95";
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
+
#include <libintl.h>
#include "db-ndbm.h"
#include "hash.h"
@@ -96,6 +96,7 @@ kdb2_fetch(key)
if (__cur_db == NULL) {
no_open_db();
item.dptr = 0;
+ item.dsize = 0;
return (item);
}
return (kdb2_dbm_fetch(__cur_db, key));
@@ -109,6 +110,7 @@ kdb2_firstkey()
if (__cur_db == NULL) {
no_open_db();
item.dptr = 0;
+ item.dsize = 0;
return (item);
}
return (kdb2_dbm_firstkey(__cur_db));
@@ -123,6 +125,7 @@ kdb2_nextkey(key)
if (__cur_db == NULL) {
no_open_db();
item.dptr = 0;
+ item.dsize = 0;
return (item);
}
return (kdb2_dbm_nextkey(__cur_db));
diff --git a/usr/src/lib/krb5/plugins/kdb/db2/libdb2/hash/hash.c b/usr/src/lib/krb5/plugins/kdb/db2/libdb2/hash/hash.c
index 87fdffae7b..7df1c536e9 100644
--- a/usr/src/lib/krb5/plugins/kdb/db2/libdb2/hash/hash.c
+++ b/usr/src/lib/krb5/plugins/kdb/db2/libdb2/hash/hash.c
@@ -1,6 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
@@ -114,10 +111,8 @@ __kdb2_hash_open(file, flags, mode, info, dflags)
errno = EINVAL;
return (NULL);
}
- if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB)))) {
- errno = ENOMEM;
+ if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB))))
return (NULL);
- }
hashp->fp = -1;
/* set this now, before file goes away... */
@@ -276,6 +271,7 @@ __kdb2_hash_open(file, flags, mode, info, dflags)
return (dbp);
error2:
+ save_errno = errno;
hdestroy(hashp);
errno = save_errno;
return (NULL);
diff --git a/usr/src/lib/krb5/plugins/kdb/db2/libdb2/include/db-int.h b/usr/src/lib/krb5/plugins/kdb/db2/libdb2/include/db-int.h
index c5c43a481a..694f1c0a41 100644
--- a/usr/src/lib/krb5/plugins/kdb/db2/libdb2/include/db-int.h
+++ b/usr/src/lib/krb5/plugins/kdb/db2/libdb2/include/db-int.h
@@ -1,12 +1,11 @@
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _KRB5_DB2_MISC_H
#define _KRB5_DB2_MISC_H
-#pragma ident "%Z%%M% %I% %E% SMI"
#ifdef __cplusplus
extern "C" {
@@ -50,7 +49,7 @@ extern "C" {
#ifndef _DB_INT_H_
#define _DB_INT_H_
-#include <db.h>
+#include "db.h"
/* deal with autoconf-based stuff */
diff --git a/usr/src/lib/krb5/plugins/kdb/db2/libdb2/include/db-ndbm.h b/usr/src/lib/krb5/plugins/kdb/db2/libdb2/include/db-ndbm.h
index b1ff3e38e1..e99f46fdc9 100644
--- a/usr/src/lib/krb5/plugins/kdb/db2/libdb2/include/db-ndbm.h
+++ b/usr/src/lib/krb5/plugins/kdb/db2/libdb2/include/db-ndbm.h
@@ -1,6 +1,3 @@
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -73,7 +70,7 @@ typedef DB DBM;
#define dbm_nextkey kdb2_dbm_nextkey
#define dbm_open kdb2_dbm_open
#define dbm_store kdb2_dbm_store
-#define dbm_dirinfo kdb2_dbm_dirinfo
+#define dbm_dirfno kdb2_dbm_dirfno
#define dbm_error kdb2_dbm_error
#define dbm_clearerr kdb2_dbm_clearerr
diff --git a/usr/src/lib/krb5/plugins/kdb/db2/libdb2/mpool/mpool.c b/usr/src/lib/krb5/plugins/kdb/db2/libdb2/mpool/mpool.c
index 2881fb813a..56f2749a92 100644
--- a/usr/src/lib/krb5/plugins/kdb/db2/libdb2/mpool/mpool.c
+++ b/usr/src/lib/krb5/plugins/kdb/db2/libdb2/mpool/mpool.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
@@ -395,7 +393,7 @@ new: if ((bp = (BKT *)malloc(sizeof(BKT) + mp->pagesize)) == NULL)
#ifdef STATISTICS
++mp->pagealloc;
#endif
-#if defined(DEBUG) || defined(PURIFY)
+#if defined(DEBUG) || defined(PURIFY) || 1
memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
#endif
bp->page = (char *)bp + sizeof(BKT);
@@ -453,8 +451,7 @@ mpool_look(mp, pgno)
head = &mp->hqh[HASHKEY(pgno)];
for (bp = head->cqh_first; bp != (void *)head; bp = bp->hq.cqe_next)
- if ((bp->pgno == pgno) &&
- (bp->flags & MPOOL_INUSE == MPOOL_INUSE)) {
+ if ((bp->pgno == pgno) && (bp->flags & MPOOL_INUSE)) {
#ifdef STATISTICS
++mp->cachehit;
#endif
diff --git a/usr/src/lib/krb5/plugins/kdb/db2/pol_xdr.c b/usr/src/lib/krb5/plugins/kdb/db2/pol_xdr.c
index 83991cd27a..c174490702 100644
--- a/usr/src/lib/krb5/plugins/kdb/db2/pol_xdr.c
+++ b/usr/src/lib/krb5/plugins/kdb/db2/pol_xdr.c
@@ -1,7 +1,4 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
-#include <krb5.h>
/* Solaris Kerberos: gssrpc not supported */
#if 0 /************** Begin IFDEF'ed OUT *******************************/
#include <gssrpc/rpc.h>
@@ -14,6 +11,7 @@
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
+#include <krb5.h>
#include <strings.h>
/* Solaris Kerberos: this function taken from MIT's src/lib/rpc/xdr.c */
diff --git a/usr/src/lib/krb5/plugins/kdb/ldap/Makefile.com b/usr/src/lib/krb5/plugins/kdb/ldap/Makefile.com
index 6d7d551406..b92f19520a 100644
--- a/usr/src/lib/krb5/plugins/kdb/ldap/Makefile.com
+++ b/usr/src/lib/krb5/plugins/kdb/ldap/Makefile.com
@@ -22,7 +22,6 @@
# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-# ident "%Z%%M% %I% %E% SMI"
#
LIBRARY= kldap.a
@@ -64,7 +63,8 @@ CFLAGS += $(CCVERBOSE)
DYNFLAGS += $(KERBRUNPATH)
# setting -L $(ROOT)/usr/lib/gss because libkdb_ldap needs mech_krb5
-LDLIBS += -L $(ROOT)/usr/lib/gss -L $(ROOTLIBDIR) -lkdb_ldap -lc
+LDLIBS += -L $(ROOT)/usr/lib/gss -L $(ROOTLIBDIR) -lkdb_ldap \
+ -lc
.KEEP_STATE:
diff --git a/usr/src/lib/krb5/plugins/kdb/ldap/ldap_exp.c b/usr/src/lib/krb5/plugins/kdb/ldap/ldap_exp.c
index 9cf8b6fcdb..0245e05268 100644
--- a/usr/src/lib/krb5/plugins/kdb/ldap/ldap_exp.c
+++ b/usr/src/lib/krb5/plugins/kdb/ldap/ldap_exp.c
@@ -1,9 +1,8 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/kdb/kdb_ldap/ldap_exp.c
@@ -94,6 +93,6 @@ kdb_vftabl kdb_function_table = {
/* fetch_master_key */ NULL /* krb5_ldap_fetch_mkey */,
/* verify_master_key */ NULL /* krb5_ldap_verify_master_key */,
/* Search enc type */ NULL,
- /* db_change_pwd */ NULL
+ /* Change pwd */ NULL
};
diff --git a/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c b/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
index 546a6455c5..017b1706bf 100644
--- a/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
+++ b/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.c
@@ -3,7 +3,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/kdb/kdb_ldap/kdb_ldap.c
@@ -133,12 +132,7 @@ krb5_ldap_read_startup_information(krb5_context context)
memset((char *) &params_in, 0, sizeof(params_in));
memset((char *) &params_out, 0, sizeof(params_out));
- /* Solaris Kerberos: not supported yet */
-#if 0 /************** Begin IFDEF'ed OUT *******************************/
retval = kadm5_get_config_params(context, 1, &params_in, &params_out);
-#else
- retval = kadm5_get_config_params(context, NULL, NULL, &params_in, &params_out);
-#endif /**************** END IFDEF'ed OUT *******************************/
if (retval) {
if ((mask & LDAP_REALM_MAXTICKETLIFE) == 0) {
ldap_context->lrparams->max_life = 24 * 60 * 60; /* 1 day */
diff --git a/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h b/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
index 9fc00f6a87..1d6ffdfc2f 100644
--- a/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
+++ b/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -37,8 +37,6 @@
#ifndef _KDB_LDAP_H
#define _KDB_LDAP_H 1
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/* We want the interfaces marked "deprecated" in OpenLDAP. */
#define LDAP_DEPRECATED 1
#include <ldap.h>
@@ -60,6 +58,11 @@
#include <k5-thread.h>
#include <k5-platform.h> /* Solaris Kerberos */
+#include <k5-platform-store_16.h>
+#include <k5-platform-store_32.h>
+#include <k5-platform-load_16.h>
+#include <k5-platform-load_32.h>
+
#include <kdb5.h>
#include "k5-int.h"
#include "ldap_krbcontainer.h"
diff --git a/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c b/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
index bbdff731e1..c7f871ec3a 100644
--- a/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
+++ b/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/kdb_ldap_conn.c
@@ -3,7 +3,6 @@
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/kdb/kdb_ldap/kdb_ldap_conn.c
@@ -65,10 +64,8 @@ krb5_validate_ldap_context(krb5_context context, krb5_ldap_context *ldap_context
goto err_out;
}
- if (ldap_context->bind_pwd == NULL &&
- ldap_context->service_password_file != NULL &&
- ldap_context->service_cert_path == NULL) {
-
+ if (ldap_context->bind_pwd == NULL && ldap_context->service_password_file !=
+ NULL && ldap_context->service_cert_path == NULL) {
if ((st=krb5_ldap_readpassword(context, ldap_context, &password)) != 0) {
prepend_err_str(context, gettext("Error reading password from stash: "), st, st);
goto err_out;
@@ -169,6 +166,7 @@ krb5_ldap_initialize(ldap_context, server_info)
krb5_ldap_server_handle *ldap_server_handle=NULL;
char *errstr = NULL;
+
ldap_server_handle = calloc(1, sizeof(krb5_ldap_server_handle));
if (ldap_server_handle == NULL) {
st = ENOMEM;
diff --git a/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c b/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
index a5ab9834ca..6e498a62ac 100644
--- a/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
+++ b/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c
@@ -1,4 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
/*
* lib/kdb/kdb_ldap/ldap_misc.c
*
@@ -1267,12 +1266,9 @@ getepochtime(strtime, epochtime)
*epochtime = 0;
return EINVAL;
}
- /* Solaris kerberos: don't have krb5int_gmt_mktime at this point */
-#if 0 /************** Begin IFDEF'ed OUT *******************************/
+
*epochtime = krb5int_gmt_mktime(&tme);
-#else
- *epochtime = gmt_mktime(&tme);
-#endif /**************** END IFDEF'ed OUT *******************************/
+
return 0;
}
diff --git a/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c b/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
index 9355fd9d2b..6f22fe2e56 100644
--- a/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
+++ b/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_principal.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/kdb/kdb_ldap/ldap_principal.c
*
@@ -30,7 +28,7 @@
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -140,13 +138,13 @@ krb5_ldap_free_principal(kcontext , entries, nentries)
}
krb5_error_code
-krb5_ldap_iterate(
- krb5_context context,
- char *match_expr,
- krb5_error_code (*func) (krb5_pointer, krb5_db_entry *),
- krb5_pointer func_arg,
+krb5_ldap_iterate(context, match_expr, func, func_arg, db_args)
+ krb5_context context;
+ char *match_expr;
+ krb5_error_code (*func) (krb5_pointer, krb5_db_entry *);
+ krb5_pointer func_arg;
/* Solaris Kerberos: adding support for -rev/recurse flags */
- char **db_args)
+ char **db_args;
{
krb5_db_entry entry;
krb5_principal principal;
diff --git a/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c b/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c
index abe747a5ee..4bfd0ffef5 100644
--- a/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c
+++ b/usr/src/lib/krb5/plugins/kdb/ldap/libkdb_ldap/ldap_tkt_policy.c
@@ -1,5 +1,3 @@
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* lib/kdb/kdb_ldap/ldap_tkt_policy.c
*
@@ -303,7 +301,7 @@ krb5_ldap_delete_policy(context, policyname)
krb5_ldap_context *ldap_context=NULL;
krb5_ldap_server_handle *ldap_server_handle=NULL;
- if (policyname == NULL) {
+ if (policyname == NULL) {
st = EINVAL;
prepend_err_str (context, gettext("Ticket Policy Object DN missing"),st,st);
goto cleanup;
diff --git a/usr/src/lib/krb5/plugins/preauth/Makefile b/usr/src/lib/krb5/plugins/preauth/Makefile
new file mode 100644
index 0000000000..884a2af6ff
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/Makefile
@@ -0,0 +1,49 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+# include global definitions
+include ../../../../Makefile.master
+
+#
+# Build everything in parallel; use .WAIT for dependencies
+.PARALLEL:
+
+SUBDIRS= \
+ pkinit
+
+all := TARGET= all
+install := TARGET= install
+clean := TARGET= clean
+clobber := TARGET= clobber
+lint := TARGET= lint
+_msg := TARGET= _msg
+
+.KEEP_STATE:
+
+all install clean clobber lint _msg: $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/Makefile b/usr/src/lib/krb5/plugins/preauth/pkinit/Makefile
new file mode 100644
index 0000000000..84965753db
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/Makefile
@@ -0,0 +1,55 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+include $(SRC)/lib/krb5/Makefile.lib
+
+include $(SRC)/lib/gss_mechs/mech_krb5/Makefile.mech_krb5
+
+SUBDIRS= $(MACH)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+_msg := TARGET= _msg
+
+.KEEP_STATE:
+
+all clean clobber lint _msg: $(SUBDIRS)
+
+$(ROOTLIBDIR):
+ $(INS.dir)
+
+$(ROOTLIBDIR)/%: %
+ $(INS.file)
+
+install: $(ROOTLIBDIR) $(SUBDIRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/Makefile.com b/usr/src/lib/krb5/plugins/preauth/pkinit/Makefile.com
new file mode 100644
index 0000000000..cc5516bf7c
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/Makefile.com
@@ -0,0 +1,94 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+LIBRARY= pkinit.a
+VERS= .1
+
+PKINIT_OBJS= \
+ pkinit_accessor.o \
+ pkinit_clnt.o \
+ pkinit_crypto_openssl.o \
+ pkinit_identity.o \
+ pkinit_lib.o \
+ pkinit_matching.o \
+ pkinit_profile.o \
+ pkinit_srv.o
+
+
+OBJECTS= $(PKINIT_OBJS)
+
+# include library definitions
+include $(SRC)/lib/krb5/Makefile.lib
+
+SRCS= $(PKINIT_OBJS:%.o=../%.c)
+
+LIBS= $(DYNLIB)
+
+include $(SRC)/lib/gss_mechs/mech_krb5/Makefile.mech_krb5
+
+POFILE = $(LIBRARY:%.a=%.po)
+POFILES = generic.po
+
+#override liblink
+INS.liblink= -$(RM) $@; $(SYMLINK) $(LIBLINKS)$(VERS) $@
+
+include $(SRC)/lib/openssl/Makefile.openssl
+
+CPPFLAGS += $(OPENSSL_CPPFLAGS) \
+ -I$(SRC)/lib/krb5 \
+ -I$(SRC)/lib/krb5/kdb \
+ -I$(SRC)/lib/gss_mechs/mech_krb5/include \
+ -I$(SRC)/lib/gss_mechs/mech_krb5/krb5/os \
+ -I$(SRC)/lib/gss_mechs/mech_krb5/include/krb5 \
+ -I$(SRC)/uts/common/gssapi/include/ \
+ -I$(SRC)/uts/common/gssapi/mechs/krb5/include \
+ -I$(SRC)
+
+CFLAGS += $(CCVERBOSE) -I..
+DYNFLAGS += $(KRUNPATH) $(KMECHLIB) $(OPENSSL_DYNFLAGS)
+LDLIBS += -L $(ROOTLIBDIR) $(OPENSSL_LDFLAGS) -lcrypto -lc
+
+ROOTLIBDIR= $(ROOT)/usr/lib/krb5/plugins/preauth
+
+$(ROOTLIBDIR):
+ $(INS.dir)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+# include library targets
+include $(SRC)/lib/krb5/Makefile.targ
+
+FRC:
+
+generic.po: FRC
+ $(RM) messages.po
+ $(XGETTEXT) $(XGETFLAGS) `$(GREP) -l gettext ../*.[ch]`
+ $(SED) "/^domain/d" messages.po > $@
+ $(RM) messages.po
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/i386/Makefile b/usr/src/lib/krb5/plugins/preauth/pkinit/i386/Makefile
new file mode 100644
index 0000000000..8bc3adb7c7
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/i386/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBDIR) $(ROOTLIBS) $(ROOTLINKS)
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/mapfile-vers b/usr/src/lib/krb5/plugins/preauth/pkinit/mapfile-vers
new file mode 100644
index 0000000000..5e2c0307bd
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/mapfile-vers
@@ -0,0 +1,37 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+# Due to mistakes made early in the history of this library, there are
+# no SUNW_1.1 symbols, but the version is now kept as a placeholder.
+# Don't add any symbols to this version.
+
+SUNWprivate_1.1 {
+ global:
+ preauthentication_client_1;
+ preauthentication_server_1;
+ local:
+ *;
+};
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h
new file mode 100644
index 0000000000..9ae77a2a5f
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit.h
@@ -0,0 +1,364 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifndef _PKINIT_H
+#define _PKINIT_H
+
+/* Solaris Kerberos */
+#include <preauth_plugin.h>
+#include <k5-int-pkinit.h>
+#include <profile.h>
+#include "pkinit_accessor.h"
+
+/*
+ * It is anticipated that all the special checks currently
+ * required when talking to a Longhorn server will go away
+ * by the time it is officially released and all references
+ * to the longhorn global can be removed and any code
+ * #ifdef'd with LONGHORN_BETA_COMPAT can be removed.
+ * And this #define!
+ */
+#define LONGHORN_BETA_COMPAT 1
+#ifdef LONGHORN_BETA_COMPAT
+extern int longhorn; /* XXX Talking to a Longhorn server? */
+#endif
+
+
+#ifndef WITHOUT_PKCS11
+/* Solaris Kerberos */
+#include <security/cryptoki.h>
+#include <security/pkcs11.h>
+
+/* Solaris Kerberos */
+#define PKCS11_MODNAME "/usr/lib/libpkcs11.so"
+
+#define PK_SIGLEN_GUESS 1000
+#define PK_NOSLOT 999999
+#endif
+
+#define DH_PROTOCOL 1
+#define RSA_PROTOCOL 2
+
+#define TD_TRUSTED_CERTIFIERS 104
+#define TD_INVALID_CERTIFICATES 105
+#define TD_DH_PARAMETERS 109
+
+#define PKINIT_CTX_MAGIC 0x05551212
+#define PKINIT_REQ_CTX_MAGIC 0xdeadbeef
+
+#define PKINIT_DEFAULT_DH_MIN_BITS 2048
+
+/* Make pkiDebug(fmt,...) print, or not. */
+#ifdef DEBUG
+#define pkiDebug printf
+#else
+/* Still evaluates for side effects. */
+/* ARGSUSED */
+static void pkiDebug (const char *fmt, ...) { }
+/* This is better if the compiler doesn't inline variadic functions
+ well, but gcc will warn about "left-hand operand of comma
+ expression has no effect". Still evaluates for side effects. */
+/* #define pkiDebug (void) */
+#endif
+
+/* Solaris Kerberos */
+#if (__STDC_VERSION__ >= 199901L) || \
+ (defined(__SUNPRO_C) && defined(__C99FEATURES__))
+#define __FUNCTION__ __func__
+#else
+#define __FUNCTION__ ""
+#endif
+
+
+/* Macros to deal with converting between various data types... */
+#define PADATA_TO_KRB5DATA(pad, k5d) \
+ (k5d)->length = (pad)->length; (k5d)->data = (char *)(pad)->contents;
+#define OCTETDATA_TO_KRB5DATA(octd, k5d) \
+ (k5d)->length = (octd)->length; (k5d)->data = (char *)(octd)->data;
+
+extern const krb5_octet_data dh_oid;
+
+/*
+ * notes about crypto contexts:
+ *
+ * the basic idea is that there are crypto contexts that live at
+ * both the plugin level and request level. the identity context (that
+ * keeps info about your own certs and such) is separate because
+ * it is needed at different levels for the kdc and and the client.
+ * (the kdc's identity is at the plugin level, the client's identity
+ * information could change per-request.)
+ * the identity context is meant to have the entity's cert,
+ * a list of trusted and intermediate cas, a list of crls, and any
+ * pkcs11 information. the req context is meant to have the
+ * received certificate and the DH related information. the plugin
+ * context is meant to have global crypto information, i.e., OIDs
+ * and constant DH parameter information.
+ */
+
+/*
+ * plugin crypto context should keep plugin common information,
+ * eg., OIDs, known DHparams
+ */
+typedef struct _pkinit_plg_crypto_context *pkinit_plg_crypto_context;
+
+/*
+ * request crypto context should keep reqyest common information,
+ * eg., received credentials, DH parameters of this request
+ */
+typedef struct _pkinit_req_crypto_context *pkinit_req_crypto_context;
+
+/*
+ * identity context should keep information about credentials
+ * for the request, eg., my credentials, trusted ca certs,
+ * intermediate ca certs, crls, pkcs11 info
+ */
+typedef struct _pkinit_identity_crypto_context *pkinit_identity_crypto_context;
+
+/*
+ * this structure keeps information about the config options
+ */
+typedef struct _pkinit_plg_opts {
+ int require_eku; /* require EKU checking (default is true) */
+ int accept_secondary_eku;/* accept secondary EKU (default is false) */
+ int allow_upn; /* allow UPN-SAN instead of pkinit-SAN */
+ int dh_or_rsa; /* selects DH or RSA based pkinit */
+ int require_crl_checking; /* require CRL for a CA (default is false) */
+ int dh_min_bits; /* minimum DH modulus size allowed */
+} pkinit_plg_opts;
+
+/*
+ * this structure keeps options used for a given request
+ */
+typedef struct _pkinit_req_opts {
+ int require_eku;
+ int accept_secondary_eku;
+ int allow_upn;
+ int dh_or_rsa;
+ int require_crl_checking;
+ int dh_size; /* initial request DH modulus size (default=1024) */
+ int require_hostname_match;
+ int win2k_target;
+ int win2k_require_cksum;
+} pkinit_req_opts;
+
+/*
+ * information about identity from config file or command line
+ */
+
+#define PKINIT_ID_OPT_USER_IDENTITY 1
+#define PKINIT_ID_OPT_ANCHOR_CAS 2
+#define PKINIT_ID_OPT_INTERMEDIATE_CAS 3
+#define PKINIT_ID_OPT_CRLS 4
+#define PKINIT_ID_OPT_OCSP 5
+#define PKINIT_ID_OPT_DN_MAPPING 6 /* XXX ? */
+
+typedef struct _pkinit_identity_opts {
+ char *identity;
+ char **identity_alt;
+ char **anchors;
+ char **intermediates;
+ char **crls;
+ char *ocsp;
+ char *dn_mapping_file;
+ int idtype;
+ char *cert_filename;
+ char *key_filename;
+#ifndef WITHOUT_PKCS11
+ char *p11_module_name;
+ CK_SLOT_ID slotid;
+ char *token_label;
+ char *cert_id_string;
+ char *cert_label;
+#endif
+} pkinit_identity_opts;
+
+
+/*
+ * Client's plugin context
+ */
+struct _pkinit_context {
+ int magic;
+ pkinit_plg_crypto_context cryptoctx;
+ pkinit_plg_opts *opts;
+ pkinit_identity_opts *idopts;
+};
+typedef struct _pkinit_context *pkinit_context;
+
+/*
+ * Client's per-request context
+ */
+struct _pkinit_req_context {
+ int magic;
+ pkinit_req_crypto_context cryptoctx;
+ pkinit_req_opts *opts;
+ pkinit_identity_crypto_context idctx;
+ pkinit_identity_opts *idopts;
+ krb5_preauthtype pa_type;
+};
+typedef struct _pkinit_kdc_context *pkinit_kdc_context;
+
+/*
+ * KDC's (per-realm) plugin context
+ */
+struct _pkinit_kdc_context {
+ int magic;
+ pkinit_plg_crypto_context cryptoctx;
+ pkinit_plg_opts *opts;
+ pkinit_identity_crypto_context idctx;
+ pkinit_identity_opts *idopts;
+ char *realmname;
+ unsigned int realmname_len;
+};
+typedef struct _pkinit_req_context *pkinit_req_context;
+
+/*
+ * KDC's per-request context
+ */
+struct _pkinit_kdc_req_context {
+ int magic;
+ pkinit_req_crypto_context cryptoctx;
+ krb5_auth_pack *rcv_auth_pack;
+ krb5_auth_pack_draft9 *rcv_auth_pack9;
+ krb5_preauthtype pa_type;
+};
+typedef struct _pkinit_kdc_req_context *pkinit_kdc_req_context;
+
+/*
+ * Functions in pkinit_lib.c
+ */
+
+krb5_error_code pkinit_init_req_opts(pkinit_req_opts **);
+void pkinit_fini_req_opts(pkinit_req_opts *);
+
+krb5_error_code pkinit_init_plg_opts(pkinit_plg_opts **);
+void pkinit_fini_plg_opts(pkinit_plg_opts *);
+
+krb5_error_code pkinit_init_identity_opts(pkinit_identity_opts **idopts);
+void pkinit_fini_identity_opts(pkinit_identity_opts *idopts);
+krb5_error_code pkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
+ pkinit_identity_opts **dest_opts);
+
+/*
+ * Functions in pkinit_identity.c
+ */
+char * idtype2string(int idtype);
+char * catype2string(int catype);
+
+krb5_error_code pkinit_identity_initialize
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_opts *idopts, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */
+ int do_matching, /* IN */
+ krb5_principal princ); /* IN (optional) */
+
+krb5_error_code pkinit_cert_matching
+ (krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_principal princ);
+
+/*
+ * initialization and free functions
+ */
+void init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in);
+void init_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in);
+void init_krb5_reply_key_pack(krb5_reply_key_pack **in);
+void init_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in);
+
+void init_krb5_auth_pack(krb5_auth_pack **in);
+void init_krb5_auth_pack_draft9(krb5_auth_pack_draft9 **in);
+void init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in);
+void init_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in);
+void init_krb5_typed_data(krb5_typed_data **in);
+void init_krb5_subject_pk_info(krb5_subject_pk_info **in);
+
+void free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in);
+void free_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in);
+void free_krb5_reply_key_pack(krb5_reply_key_pack **in);
+void free_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in);
+void free_krb5_auth_pack(krb5_auth_pack **in);
+void free_krb5_auth_pack_draft9(krb5_context, krb5_auth_pack_draft9 **in);
+void free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in);
+void free_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in);
+void free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in);
+void free_krb5_trusted_ca(krb5_trusted_ca ***in);
+void free_krb5_typed_data(krb5_typed_data ***in);
+void free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in);
+void free_krb5_algorithm_identifier(krb5_algorithm_identifier *in);
+void free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in);
+void free_krb5_subject_pk_info(krb5_subject_pk_info **in);
+krb5_error_code pkinit_copy_krb5_octet_data(krb5_octet_data *dst, const krb5_octet_data *src);
+
+
+/*
+ * Functions in pkinit_profile.c
+ */
+krb5_error_code pkinit_kdcdefault_strings
+ (krb5_context context, const char *realmname, const char *option,
+ char ***ret_value);
+krb5_error_code pkinit_kdcdefault_string
+ (krb5_context context, const char *realmname, const char *option,
+ char **ret_value);
+krb5_error_code pkinit_kdcdefault_boolean
+ (krb5_context context, const char *realmname, const char *option,
+ int default_value, int *ret_value);
+krb5_error_code pkinit_kdcdefault_integer
+ (krb5_context context, const char *realmname, const char *option,
+ int default_value, int *ret_value);
+
+
+krb5_error_code pkinit_libdefault_strings
+ (krb5_context context, const krb5_data *realm,
+ const char *option, char ***ret_value);
+krb5_error_code pkinit_libdefault_string
+ (krb5_context context, const krb5_data *realm,
+ const char *option, char **ret_value);
+krb5_error_code pkinit_libdefault_boolean
+ (krb5_context context, const krb5_data *realm, const char *option,
+ int default_value, int *ret_value);
+krb5_error_code pkinit_libdefault_integer
+ (krb5_context context, const krb5_data *realm, const char *option,
+ int default_value, int *ret_value);
+
+/*
+ * debugging functions
+ */
+void print_buffer(unsigned char *, unsigned int);
+void print_buffer_bin(unsigned char *, unsigned int, char *);
+
+/*
+ * Now get crypto function declarations
+ */
+#include "pkinit_crypto.h"
+
+#endif /* _PKINIT_H */
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_accessor.c b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_accessor.c
new file mode 100644
index 0000000000..e954ca361c
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_accessor.c
@@ -0,0 +1,118 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <k5-int.h>
+#include "pkinit_accessor.h"
+
+#define DEF_FUNC_PTRS(type) \
+krb5_error_code (*k5int_encode_##type)(const type *, krb5_data **); \
+krb5_error_code (*k5int_decode_##type)(const krb5_data *, type **)
+
+#define DEF_FUNC_PTRS_ARRAY(type) \
+krb5_error_code (*k5int_encode_##type)(const type **, krb5_data **); \
+krb5_error_code (*k5int_decode_##type)(const krb5_data *, type ***)
+
+DEF_FUNC_PTRS(krb5_auth_pack);
+DEF_FUNC_PTRS(krb5_auth_pack_draft9);
+DEF_FUNC_PTRS(krb5_kdc_dh_key_info);
+DEF_FUNC_PTRS(krb5_pa_pk_as_rep);
+DEF_FUNC_PTRS(krb5_pa_pk_as_rep_draft9);
+DEF_FUNC_PTRS(krb5_pa_pk_as_req);
+DEF_FUNC_PTRS(krb5_pa_pk_as_req_draft9);
+DEF_FUNC_PTRS(krb5_reply_key_pack);
+DEF_FUNC_PTRS(krb5_reply_key_pack_draft9);
+DEF_FUNC_PTRS_ARRAY(krb5_typed_data);
+
+/* special cases... */
+krb5_error_code (*k5int_decode_krb5_principal_name)
+ (const krb5_data *, krb5_principal_data **);
+
+krb5_error_code (*k5int_encode_krb5_td_dh_parameters)
+ (const krb5_algorithm_identifier **, krb5_data **code);
+krb5_error_code (*k5int_decode_krb5_td_dh_parameters)
+ (const krb5_data *, krb5_algorithm_identifier ***);
+
+krb5_error_code (*k5int_encode_krb5_td_trusted_certifiers)
+ (const krb5_external_principal_identifier **, krb5_data **code);
+krb5_error_code (*k5int_decode_krb5_td_trusted_certifiers)
+ (const krb5_data *, krb5_external_principal_identifier ***);
+
+krb5_error_code (*k5int_decode_krb5_as_req)
+ (const krb5_data *output, krb5_kdc_req **rep);
+krb5_error_code (*k5int_encode_krb5_kdc_req_body)
+ (const krb5_kdc_req *rep, krb5_data **code);
+void KRB5_CALLCONV (*k5int_krb5_free_kdc_req)
+ (krb5_context, krb5_kdc_req * );
+void (*k5int_set_prompt_types)
+ (krb5_context, krb5_prompt_type *);
+krb5_error_code (*k5int_encode_krb5_authdata_elt)
+ (const krb5_authdata *rep, krb5_data **code);
+
+
+
+/*
+ * Grab internal function pointers from the krb5int_accessor
+ * structure and make them available
+ */
+krb5_error_code
+pkinit_accessor_init(void)
+{
+ krb5_error_code retval;
+ krb5int_access k5int;
+
+ retval = krb5int_accessor(&k5int, KRB5INT_ACCESS_VERSION);
+ if (retval)
+ return retval;
+#define SET_PTRS(type) \
+k5int_encode_##type = k5int.encode_##type; \
+k5int_decode_##type = k5int.decode_##type;
+
+ SET_PTRS(krb5_auth_pack);
+ SET_PTRS(krb5_auth_pack_draft9);
+ SET_PTRS(krb5_kdc_dh_key_info);
+ SET_PTRS(krb5_pa_pk_as_rep);
+ SET_PTRS(krb5_pa_pk_as_rep_draft9);
+ SET_PTRS(krb5_pa_pk_as_req);
+ SET_PTRS(krb5_pa_pk_as_req_draft9);
+ SET_PTRS(krb5_reply_key_pack);
+ SET_PTRS(krb5_reply_key_pack_draft9);
+ SET_PTRS(krb5_td_dh_parameters);
+ SET_PTRS(krb5_td_trusted_certifiers);
+ SET_PTRS(krb5_typed_data);
+
+ /* special cases... */
+ k5int_decode_krb5_principal_name = k5int.decode_krb5_principal_name;
+ k5int_decode_krb5_as_req = k5int.decode_krb5_as_req;
+ k5int_encode_krb5_kdc_req_body = k5int.encode_krb5_kdc_req_body;
+ k5int_krb5_free_kdc_req = k5int.krb5_free_kdc_req;
+ k5int_set_prompt_types = k5int.krb5int_set_prompt_types;
+ k5int_encode_krb5_authdata_elt = k5int.encode_krb5_authdata_elt;
+ return 0;
+}
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_accessor.h b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_accessor.h
new file mode 100644
index 0000000000..ba82533c8c
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_accessor.h
@@ -0,0 +1,83 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifndef _PKINIT_ACCESSOR_H
+#define _PKINIT_ACCESSOR_H
+
+/*
+ * Function prototypes
+ */
+krb5_error_code pkinit_accessor_init(void);
+
+#define DEF_EXT_FUNC_PTRS(type) \
+extern krb5_error_code (*k5int_encode_##type)(const type *, krb5_data **); \
+extern krb5_error_code (*k5int_decode_##type)(const krb5_data *, type **)
+
+#define DEF_EXT_FUNC_PTRS_ARRAY(type) \
+extern krb5_error_code (*k5int_encode_##type)(const type **, krb5_data **); \
+extern krb5_error_code (*k5int_decode_##type)(const krb5_data *, type ***)
+
+DEF_EXT_FUNC_PTRS(krb5_auth_pack);
+DEF_EXT_FUNC_PTRS(krb5_auth_pack_draft9);
+DEF_EXT_FUNC_PTRS(krb5_kdc_dh_key_info);
+DEF_EXT_FUNC_PTRS(krb5_pa_pk_as_rep);
+DEF_EXT_FUNC_PTRS(krb5_pa_pk_as_rep_draft9);
+DEF_EXT_FUNC_PTRS(krb5_pa_pk_as_req);
+DEF_EXT_FUNC_PTRS(krb5_pa_pk_as_req_draft9);
+DEF_EXT_FUNC_PTRS(krb5_reply_key_pack);
+DEF_EXT_FUNC_PTRS(krb5_reply_key_pack_draft9);
+DEF_EXT_FUNC_PTRS_ARRAY(krb5_typed_data);
+
+/* special cases... */
+extern krb5_error_code (*k5int_decode_krb5_principal_name)
+ (const krb5_data *, krb5_principal_data **);
+
+extern krb5_error_code (*k5int_encode_krb5_td_dh_parameters)
+ (const krb5_algorithm_identifier **, krb5_data **code);
+extern krb5_error_code (*k5int_decode_krb5_td_dh_parameters)
+ (const krb5_data *, krb5_algorithm_identifier ***);
+
+extern krb5_error_code (*k5int_encode_krb5_td_trusted_certifiers)
+ (const krb5_external_principal_identifier **, krb5_data **code);
+extern krb5_error_code (*k5int_decode_krb5_td_trusted_certifiers)
+ (const krb5_data *, krb5_external_principal_identifier ***);
+
+extern krb5_error_code (*k5int_decode_krb5_as_req)
+ (const krb5_data *output, krb5_kdc_req **rep);
+extern krb5_error_code (*k5int_encode_krb5_kdc_req_body)
+ (const krb5_kdc_req *rep, krb5_data **code);
+extern void KRB5_CALLCONV (*k5int_krb5_free_kdc_req)
+ (krb5_context, krb5_kdc_req * );
+extern void (*k5int_set_prompt_types)
+ (krb5_context, krb5_prompt_type *);
+extern krb5_error_code (*k5int_encode_krb5_authdata_elt)
+ (const krb5_authdata *rep, krb5_data **code);
+
+#endif /* _PKINIT_ACCESSOR_H */
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c
new file mode 100644
index 0000000000..296d051708
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_clnt.c
@@ -0,0 +1,1510 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <dlfcn.h>
+#include <sys/stat.h>
+
+#include "pkinit.h"
+
+#ifdef LONGHORN_BETA_COMPAT
+/*
+ * It is anticipated that all the special checks currently
+ * required when talking to a Longhorn server will go away
+ * by the time it is officially released and all references
+ * to the longhorn global can be removed and any code
+ * #ifdef'd with LONGHORN_BETA_COMPAT can be removed.
+ *
+ * Current testing (20070620) is against a patched Beta 3
+ * version of Longhorn. Most, if not all, problems should
+ * be fixed in SP1 of Longhorn.
+ */
+int longhorn = 0; /* Talking to a Longhorn server? */
+#endif
+
+krb5_error_code pkinit_client_process
+ (krb5_context context, void *plugin_context, void *request_context,
+ krb5_get_init_creds_opt *gic_opt,
+ preauth_get_client_data_proc get_data_proc,
+ struct _krb5_preauth_client_rock *rock,
+ krb5_kdc_req * request, krb5_data *encoded_request_body,
+ krb5_data *encoded_previous_request, krb5_pa_data *in_padata,
+ krb5_prompter_fct prompter, void *prompter_data,
+ preauth_get_as_key_proc gak_fct, void *gak_data,
+ krb5_data * salt, krb5_data * s2kparams,
+ krb5_keyblock * as_key, krb5_pa_data *** out_padata);
+
+krb5_error_code pkinit_client_tryagain
+ (krb5_context context, void *plugin_context, void *request_context,
+ krb5_get_init_creds_opt *gic_opt,
+ preauth_get_client_data_proc get_data_proc,
+ struct _krb5_preauth_client_rock *rock,
+ krb5_kdc_req * request, krb5_data *encoded_request_body,
+ krb5_data *encoded_previous_request,
+ krb5_pa_data *in_padata, krb5_error *err_reply,
+ krb5_prompter_fct prompter, void *prompter_data,
+ preauth_get_as_key_proc gak_fct, void *gak_data,
+ krb5_data * salt, krb5_data * s2kparams,
+ krb5_keyblock * as_key, krb5_pa_data *** out_padata);
+
+void pkinit_client_req_init
+ (krb5_context contex, void *plugin_context, void **request_context);
+
+void pkinit_client_req_fini
+ (krb5_context context, void *plugin_context, void *request_context);
+
+krb5_error_code pa_pkinit_gen_req
+ (krb5_context context, pkinit_context plgctx,
+ pkinit_req_context reqctx, krb5_kdc_req * request,
+ krb5_pa_data * in_padata, krb5_pa_data *** out_padata,
+ krb5_prompter_fct prompter, void *prompter_data,
+ krb5_get_init_creds_opt *gic_opt);
+
+krb5_error_code pkinit_as_req_create
+ (krb5_context context, pkinit_context plgctx,
+ pkinit_req_context reqctx, krb5_timestamp ctsec,
+ krb5_int32 cusec, krb5_ui_4 nonce,
+ const krb5_checksum * cksum, krb5_principal server,
+ krb5_data ** as_req);
+
+krb5_error_code pkinit_as_rep_parse
+ (krb5_context context, pkinit_context plgctx,
+ pkinit_req_context reqctx, krb5_preauthtype pa_type,
+ krb5_kdc_req * request, const krb5_data * as_rep,
+ krb5_keyblock * key_block, krb5_enctype etype, krb5_data *);
+
+krb5_error_code pa_pkinit_parse_rep
+ (krb5_context context, pkinit_context plgctx,
+ pkinit_req_context reqcxt, krb5_kdc_req * request,
+ krb5_pa_data * in_padata, krb5_enctype etype,
+ krb5_keyblock * as_key, krb5_data *);
+
+static int pkinit_client_plugin_init(krb5_context context, void **blob);
+static void pkinit_client_plugin_fini(krb5_context context, void *blob);
+
+/* ARGSUSED */
+krb5_error_code
+pa_pkinit_gen_req(krb5_context context,
+ pkinit_context plgctx,
+ pkinit_req_context reqctx,
+ krb5_kdc_req * request,
+ krb5_pa_data * in_padata,
+ krb5_pa_data *** out_padata,
+ krb5_prompter_fct prompter,
+ void *prompter_data,
+ krb5_get_init_creds_opt *gic_opt)
+{
+
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_data *out_data = NULL;
+ krb5_timestamp ctsec = 0;
+ krb5_int32 cusec = 0;
+ krb5_ui_4 nonce = 0;
+ krb5_checksum cksum;
+ krb5_data *der_req = NULL;
+ krb5_pa_data **return_pa_data = NULL;
+
+ cksum.contents = NULL;
+ reqctx->pa_type = in_padata->pa_type;
+
+ pkiDebug("kdc_options = 0x%x till = %d\n",
+ request->kdc_options, request->till);
+ /* If we don't have a client, we're done */
+ if (request->client == NULL) {
+ pkiDebug("No request->client; aborting PKINIT\n");
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ retval = pkinit_get_kdc_cert(context, plgctx->cryptoctx, reqctx->cryptoctx,
+ reqctx->idctx, request->server);
+ if (retval) {
+ pkiDebug("pkinit_get_kdc_cert returned %d\n", retval);
+ goto cleanup;
+ }
+
+ /* checksum of the encoded KDC-REQ-BODY */
+ retval = k5int_encode_krb5_kdc_req_body(request, &der_req);
+ if (retval) {
+ pkiDebug("encode_krb5_kdc_req_body returned %d\n", (int) retval);
+ goto cleanup;
+ }
+
+ retval = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL, 0,
+ der_req, &cksum);
+ if (retval)
+ goto cleanup;
+#ifdef DEBUG_CKSUM
+ pkiDebug("calculating checksum on buf size (%d)\n", der_req->length);
+ print_buffer(der_req->data, der_req->length);
+#endif
+
+ retval = krb5_us_timeofday(context, &ctsec, &cusec);
+ if (retval)
+ goto cleanup;
+
+ /* XXX PKINIT RFC says that nonce in PKAuthenticator doesn't have be the
+ * same as in the AS_REQ. However, if we pick a different nonce, then we
+ * need to remember that info when AS_REP is returned. I'm choosing to
+ * reuse the AS_REQ nonce.
+ */
+ nonce = request->nonce;
+
+ retval = pkinit_as_req_create(context, plgctx, reqctx, ctsec, cusec,
+ nonce, &cksum, request->server, &out_data);
+ if (retval || !out_data->length) {
+ pkiDebug("error %d on pkinit_as_req_create; aborting PKINIT\n",
+ (int) retval);
+ goto cleanup;
+ }
+ retval = ENOMEM;
+ /*
+ * The most we'll return is two pa_data, normally just one.
+ * We need to make room for the NULL terminator.
+ */
+ return_pa_data = (krb5_pa_data **) malloc(3 * sizeof(krb5_pa_data *));
+ if (return_pa_data == NULL)
+ goto cleanup;
+
+ return_pa_data[1] = NULL; /* in case of an early trip to cleanup */
+ return_pa_data[2] = NULL; /* Terminate the list */
+
+ return_pa_data[0] = (krb5_pa_data *) malloc(sizeof(krb5_pa_data));
+ if (return_pa_data[0] == NULL)
+ goto cleanup;
+
+ return_pa_data[1] = (krb5_pa_data *) malloc(sizeof(krb5_pa_data));
+ if (return_pa_data[1] == NULL)
+ goto cleanup;
+
+ return_pa_data[0]->magic = KV5M_PA_DATA;
+
+ if (in_padata->pa_type == KRB5_PADATA_PK_AS_REQ_OLD)
+ return_pa_data[0]->pa_type = KRB5_PADATA_PK_AS_REP_OLD;
+ else
+ return_pa_data[0]->pa_type = in_padata->pa_type;
+ return_pa_data[0]->length = out_data->length;
+ return_pa_data[0]->contents = (krb5_octet *) out_data->data;
+
+#ifdef LONGHORN_BETA_COMPAT
+ /*
+ * LH Beta 3 requires the extra pa-data, even for RFC requests,
+ * in order to get the Checksum rather than a Nonce in the reply.
+ * This can be removed when LH SP1 is released.
+ */
+ if ((return_pa_data[0]->pa_type == KRB5_PADATA_PK_AS_REP_OLD
+ && reqctx->opts->win2k_require_cksum) || (longhorn == 1)) {
+#else
+ if ((return_pa_data[0]->pa_type == KRB5_PADATA_PK_AS_REP_OLD
+ && reqctx->opts->win2k_require_cksum)) {
+#endif
+ return_pa_data[1]->pa_type = 132;
+ return_pa_data[1]->length = 0;
+ return_pa_data[1]->contents = NULL;
+ } else {
+ free(return_pa_data[1]);
+ return_pa_data[1] = NULL; /* Move the list terminator */
+ }
+ *out_padata = return_pa_data;
+ retval = 0;
+
+ cleanup:
+ if (der_req != NULL)
+ krb5_free_data(context, der_req);
+
+ if (out_data != NULL)
+ free(out_data);
+
+ if (retval) {
+ if (return_pa_data) {
+ if (return_pa_data[0] != NULL)
+ free(return_pa_data[0]);
+ if (return_pa_data[1] != NULL)
+ free(return_pa_data[1]);
+ free(return_pa_data);
+ }
+ if (out_data) {
+ free(out_data->data);
+ free(out_data);
+ }
+ }
+ return retval;
+}
+
+krb5_error_code
+pkinit_as_req_create(krb5_context context,
+ pkinit_context plgctx,
+ pkinit_req_context reqctx,
+ krb5_timestamp ctsec,
+ krb5_int32 cusec,
+ krb5_ui_4 nonce,
+ const krb5_checksum * cksum,
+ krb5_principal server,
+ krb5_data ** as_req)
+{
+ krb5_error_code retval = ENOMEM;
+ krb5_subject_pk_info *info = NULL;
+ krb5_data *coded_auth_pack = NULL;
+ krb5_auth_pack *auth_pack = NULL;
+ krb5_pa_pk_as_req *req = NULL;
+ krb5_auth_pack_draft9 *auth_pack9 = NULL;
+ krb5_pa_pk_as_req_draft9 *req9 = NULL;
+ int protocol = reqctx->opts->dh_or_rsa;
+
+ pkiDebug("pkinit_as_req_create pa_type = %d\n", reqctx->pa_type);
+
+ /* Create the authpack */
+ switch((int)reqctx->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ protocol = RSA_PROTOCOL;
+ init_krb5_auth_pack_draft9(&auth_pack9);
+ if (auth_pack9 == NULL)
+ goto cleanup;
+ auth_pack9->pkAuthenticator.ctime = ctsec;
+ auth_pack9->pkAuthenticator.cusec = cusec;
+ auth_pack9->pkAuthenticator.nonce = nonce;
+ auth_pack9->pkAuthenticator.kdcName = server;
+ auth_pack9->pkAuthenticator.kdcRealm.magic = 0;
+ auth_pack9->pkAuthenticator.kdcRealm.data =
+ (unsigned char *)server->realm.data;
+ auth_pack9->pkAuthenticator.kdcRealm.length = server->realm.length;
+ free(cksum->contents);
+ break;
+ case KRB5_PADATA_PK_AS_REQ:
+ init_krb5_subject_pk_info(&info);
+ if (info == NULL)
+ goto cleanup;
+ init_krb5_auth_pack(&auth_pack);
+ if (auth_pack == NULL)
+ goto cleanup;
+ auth_pack->pkAuthenticator.ctime = ctsec;
+ auth_pack->pkAuthenticator.cusec = cusec;
+ auth_pack->pkAuthenticator.nonce = nonce;
+ auth_pack->pkAuthenticator.paChecksum = *cksum;
+ auth_pack->clientDHNonce.length = 0;
+ auth_pack->clientPublicValue = info;
+
+ /* add List of CMS algorithms */
+ retval = create_krb5_supportedCMSTypes(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx,
+ &auth_pack->supportedCMSTypes);
+ if (retval)
+ goto cleanup;
+ break;
+ default:
+ pkiDebug("as_req: unrecognized pa_type = %d\n",
+ (int)reqctx->pa_type);
+ retval = -1;
+ goto cleanup;
+ }
+
+ switch(protocol) {
+ case DH_PROTOCOL:
+ pkiDebug("as_req: DH key transport algorithm\n");
+ retval = pkinit_copy_krb5_octet_data(&info->algorithm.algorithm, &dh_oid);
+ if (retval) {
+ pkiDebug("failed to copy dh_oid\n");
+ goto cleanup;
+ }
+
+ /* create client-side DH keys */
+ if ((retval = client_create_dh(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx, reqctx->opts->dh_size,
+ &info->algorithm.parameters.data,
+ &info->algorithm.parameters.length,
+ &info->subjectPublicKey.data,
+ &info->subjectPublicKey.length)) != 0) {
+ pkiDebug("failed to create dh parameters\n");
+ goto cleanup;
+ }
+ break;
+ case RSA_PROTOCOL:
+ pkiDebug("as_req: RSA key transport algorithm\n");
+ switch((int)reqctx->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ auth_pack9->clientPublicValue = NULL;
+ break;
+ case KRB5_PADATA_PK_AS_REQ:
+ free_krb5_subject_pk_info(&info);
+ auth_pack->clientPublicValue = NULL;
+ break;
+ }
+ break;
+ default:
+ pkiDebug("as_req: unknown key transport protocol %d\n",
+ protocol);
+ retval = -1;
+ goto cleanup;
+ }
+
+ /* Encode the authpack */
+ switch((int)reqctx->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ retval = k5int_encode_krb5_auth_pack(auth_pack, &coded_auth_pack);
+ break;
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ retval = k5int_encode_krb5_auth_pack_draft9(auth_pack9,
+ &coded_auth_pack);
+ break;
+ }
+ if (retval) {
+ pkiDebug("failed to encode the AuthPack %d\n", retval);
+ goto cleanup;
+ }
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)coded_auth_pack->data,
+ coded_auth_pack->length,
+ "/tmp/client_auth_pack");
+#endif
+
+ /* create PKCS7 object from authpack */
+ switch((int)reqctx->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ init_krb5_pa_pk_as_req(&req);
+ if (req == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ retval = cms_signeddata_create(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx, CMS_SIGN_CLIENT, 1,
+ (unsigned char *)coded_auth_pack->data, coded_auth_pack->length,
+ &req->signedAuthPack.data, &req->signedAuthPack.length);
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)req->signedAuthPack.data,
+ req->signedAuthPack.length,
+ "/tmp/client_signed_data");
+#endif
+ break;
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ init_krb5_pa_pk_as_req_draft9(&req9);
+ if (req9 == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ retval = cms_signeddata_create(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx, CMS_SIGN_DRAFT9, 1,
+ (unsigned char *)coded_auth_pack->data, coded_auth_pack->length,
+ &req9->signedAuthPack.data, &req9->signedAuthPack.length);
+ break;
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)req9->signedAuthPack.data,
+ req9->signedAuthPack.length,
+ "/tmp/client_signed_data_draft9");
+#endif
+ }
+ krb5_free_data(context, coded_auth_pack);
+ if (retval) {
+ pkiDebug("failed to create pkcs7 signed data\n");
+ goto cleanup;
+ }
+
+ /* create a list of trusted CAs */
+ switch((int)reqctx->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ retval = create_krb5_trustedCertifiers(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx, &req->trustedCertifiers);
+ if (retval)
+ goto cleanup;
+ retval = create_issuerAndSerial(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx, &req->kdcPkId.data,
+ &req->kdcPkId.length);
+ if (retval)
+ goto cleanup;
+
+ /* Encode the as-req */
+ retval = k5int_encode_krb5_pa_pk_as_req(req, as_req);
+ break;
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+#if 0
+ /* W2K3 KDC doesn't like this */
+ retval = create_krb5_trustedCas(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx, 1, &req9->trustedCertifiers);
+ if (retval)
+ goto cleanup;
+
+#endif
+ retval = create_issuerAndSerial(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx, &req9->kdcCert.data,
+ &req9->kdcCert.length);
+ if (retval)
+ goto cleanup;
+ /* Encode the as-req */
+ retval = k5int_encode_krb5_pa_pk_as_req_draft9(req9, as_req);
+ break;
+ }
+#ifdef DEBUG_ASN1
+ if (!retval)
+ print_buffer_bin((unsigned char *)(*as_req)->data, (*as_req)->length,
+ "/tmp/client_as_req");
+#endif
+
+cleanup:
+ switch((int)reqctx->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ free_krb5_auth_pack(&auth_pack);
+ free_krb5_pa_pk_as_req(&req);
+ break;
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ free_krb5_pa_pk_as_req_draft9(&req9);
+ free(auth_pack9);
+ break;
+ }
+
+
+ pkiDebug("pkinit_as_req_create retval=%d\n", (int) retval);
+
+ return retval;
+}
+
+krb5_error_code
+pa_pkinit_parse_rep(krb5_context context,
+ pkinit_context plgctx,
+ pkinit_req_context reqctx,
+ krb5_kdc_req * request,
+ krb5_pa_data * in_padata,
+ krb5_enctype etype,
+ krb5_keyblock * as_key,
+ krb5_data *encoded_request)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_data asRep = { 0, 0, NULL};
+
+ /*
+ * One way or the other - success or failure - no other PA systems can
+ * work if the server sent us a PKINIT reply, since only we know how to
+ * decrypt the key.
+ */
+ if ((in_padata == NULL) || (in_padata->length == 0)) {
+ pkiDebug("pa_pkinit_parse_rep: no in_padata\n");
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ asRep.data = (char *) in_padata->contents;
+ asRep.length = in_padata->length;
+
+ retval =
+ pkinit_as_rep_parse(context, plgctx, reqctx, in_padata->pa_type,
+ request, &asRep, as_key, etype, encoded_request);
+ if (retval) {
+ pkiDebug("pkinit_as_rep_parse returned %d (%s)\n",
+ retval, error_message(retval));
+ goto cleanup;
+ }
+
+ retval = 0;
+
+cleanup:
+
+ return retval;
+}
+
+static krb5_error_code
+verify_kdc_san(krb5_context context,
+ pkinit_context plgctx,
+ pkinit_req_context reqctx,
+ krb5_principal kdcprinc,
+ int *valid_san,
+ int *need_eku_checking)
+{
+ krb5_error_code retval;
+ char **certhosts = NULL, **cfghosts = NULL;
+ krb5_principal *princs = NULL;
+ unsigned char ***get_dns;
+ int i, j;
+
+ *valid_san = 0;
+ *need_eku_checking = 1;
+
+ retval = pkinit_libdefault_strings(context,
+ krb5_princ_realm(context, kdcprinc),
+ "pkinit_kdc_hostname",
+ &cfghosts);
+ if (retval || cfghosts == NULL) {
+ pkiDebug("%s: No pkinit_kdc_hostname values found in config file\n",
+ __FUNCTION__);
+ get_dns = NULL;
+ } else {
+ pkiDebug("%s: pkinit_kdc_hostname values found in config file\n",
+ __FUNCTION__);
+ get_dns = (unsigned char ***)&certhosts;
+ }
+
+ retval = crypto_retrieve_cert_sans(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx,
+ &princs, NULL, get_dns);
+ if (retval) {
+ pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__);
+ retval = KRB5KDC_ERR_KDC_NAME_MISMATCH;
+ goto out;
+ }
+#if 0
+ retval = call_san_checking_plugins(context, plgctx, reqctx, idctx,
+ princs, hosts, &plugin_decision,
+ need_eku_checking);
+ pkiDebug("%s: call_san_checking_plugins() returned retval %d\n",
+ __FUNCTION__);
+ if (retval) {
+ retval = KRB5KDC_ERR_KDC_NAME_MISMATCH;
+ goto out;
+ }
+ pkiDebug("%s: call_san_checking_plugins() returned decision %d and "
+ "need_eku_checking %d\n",
+ __FUNCTION__, plugin_decision, *need_eku_checking);
+ if (plugin_decision != NO_DECISION) {
+ retval = plugin_decision;
+ goto out;
+ }
+#endif
+
+ pkiDebug("%s: Checking pkinit sans\n", __FUNCTION__);
+ for (i = 0; princs != NULL && princs[i] != NULL; i++) {
+ if (krb5_principal_compare(context, princs[i], kdcprinc)) {
+ pkiDebug("%s: pkinit san match found\n", __FUNCTION__);
+ *valid_san = 1;
+ *need_eku_checking = 0;
+ retval = 0;
+ goto out;
+ }
+ }
+ pkiDebug("%s: no pkinit san match found\n", __FUNCTION__);
+
+ if (certhosts == NULL) {
+ pkiDebug("%s: no certhosts (or we wouldn't accept them anyway)\n",
+ __FUNCTION__);
+ retval = KRB5KDC_ERR_KDC_NAME_MISMATCH;
+ goto out;
+ }
+
+ for (i = 0; certhosts[i] != NULL; i++) {
+ for (j = 0; cfghosts != NULL && cfghosts[j] != NULL; j++) {
+ pkiDebug("%s: comparing cert name '%s' with config name '%s'\n",
+ __FUNCTION__, certhosts[i], cfghosts[j]);
+ if (strcmp(certhosts[i], cfghosts[j]) == 0) {
+ pkiDebug("%s: we have a dnsName match\n", __FUNCTION__);
+ *valid_san = 1;
+ retval = 0;
+ goto out;
+ }
+ }
+ }
+ pkiDebug("%s: no dnsName san match found\n", __FUNCTION__);
+
+ /* We found no match */
+ retval = 0;
+
+out:
+ if (princs != NULL) {
+ for (i = 0; princs[i] != NULL; i++)
+ krb5_free_principal(context, princs[i]);
+ free(princs);
+ }
+ if (certhosts != NULL) {
+ for (i = 0; certhosts[i] != NULL; i++)
+ free(certhosts[i]);
+ free(certhosts);
+ }
+ if (cfghosts != NULL)
+ profile_free_list(cfghosts);
+
+ pkiDebug("%s: returning retval %d, valid_san %d, need_eku_checking %d\n",
+ __FUNCTION__, retval, *valid_san, *need_eku_checking);
+ return retval;
+}
+
+static krb5_error_code
+verify_kdc_eku(krb5_context context,
+ pkinit_context plgctx,
+ pkinit_req_context reqctx,
+ int *eku_accepted)
+{
+ krb5_error_code retval;
+
+ *eku_accepted = 0;
+
+ if (reqctx->opts->require_eku == 0) {
+ pkiDebug("%s: configuration requests no EKU checking\n", __FUNCTION__);
+ *eku_accepted = 1;
+ retval = 0;
+ goto out;
+ }
+ retval = crypto_check_cert_eku(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx,
+ 1, /* kdc cert */
+ reqctx->opts->accept_secondary_eku,
+ eku_accepted);
+ if (retval) {
+ pkiDebug("%s: Error from crypto_check_cert_eku %d (%s)\n",
+ __FUNCTION__, retval, error_message(retval));
+ goto out;
+ }
+
+out:
+ pkiDebug("%s: returning retval %d, eku_accepted %d\n",
+ __FUNCTION__, retval, *eku_accepted);
+ return retval;
+}
+
+/*
+ * Parse PA-PK-AS-REP message. Optionally evaluates the message's
+ * certificate chain.
+ * Optionally returns various components.
+ */
+krb5_error_code
+pkinit_as_rep_parse(krb5_context context,
+ pkinit_context plgctx,
+ pkinit_req_context reqctx,
+ krb5_preauthtype pa_type,
+ krb5_kdc_req *request,
+ const krb5_data *as_rep,
+ krb5_keyblock *key_block,
+ krb5_enctype etype,
+ krb5_data *encoded_request)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_pa_pk_as_rep *kdc_reply = NULL;
+ krb5_kdc_dh_key_info *kdc_dh = NULL;
+ krb5_reply_key_pack *key_pack = NULL;
+ krb5_reply_key_pack_draft9 *key_pack9 = NULL;
+ krb5_octet_data dh_data = { 0, 0, NULL };
+ unsigned char *client_key = NULL, *kdc_hostname = NULL;
+ unsigned int client_key_len = 0;
+ krb5_checksum cksum = {0, 0, 0, NULL};
+ krb5_data k5data;
+ int valid_san = 0;
+ int valid_eku = 0;
+ int need_eku_checking = 1;
+
+ assert((as_rep != NULL) && (key_block != NULL));
+
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)as_rep->data, as_rep->length,
+ "/tmp/client_as_rep");
+#endif
+
+ if ((retval = k5int_decode_krb5_pa_pk_as_rep(as_rep, &kdc_reply))) {
+ pkiDebug("decode_krb5_as_rep failed %d\n", retval);
+ return retval;
+ }
+
+ switch(kdc_reply->choice) {
+ case choice_pa_pk_as_rep_dhInfo:
+ pkiDebug("as_rep: DH key transport algorithm\n");
+#ifdef DEBUG_ASN1
+ print_buffer_bin(kdc_reply->u.dh_Info.dhSignedData.data,
+ kdc_reply->u.dh_Info.dhSignedData.length, "/tmp/client_kdc_signeddata");
+#endif
+ if ((retval = cms_signeddata_verify(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx, CMS_SIGN_SERVER,
+ reqctx->opts->require_crl_checking,
+ kdc_reply->u.dh_Info.dhSignedData.data,
+ kdc_reply->u.dh_Info.dhSignedData.length,
+ &dh_data.data, &dh_data.length, NULL, NULL)) != 0) {
+ pkiDebug("failed to verify pkcs7 signed data\n");
+ goto cleanup;
+ }
+
+ break;
+ case choice_pa_pk_as_rep_encKeyPack:
+ pkiDebug("as_rep: RSA key transport algorithm\n");
+ if ((retval = cms_envelopeddata_verify(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx, pa_type,
+ reqctx->opts->require_crl_checking,
+ kdc_reply->u.encKeyPack.data,
+ kdc_reply->u.encKeyPack.length,
+ &dh_data.data, &dh_data.length)) != 0) {
+ pkiDebug("failed to verify pkcs7 enveloped data\n");
+ goto cleanup;
+ }
+ break;
+ default:
+ pkiDebug("unknown as_rep type %d\n", kdc_reply->choice);
+ retval = -1;
+ goto cleanup;
+ }
+
+ retval = verify_kdc_san(context, plgctx, reqctx, request->server,
+ &valid_san, &need_eku_checking);
+ if (retval)
+ goto cleanup;
+ if (!valid_san) {
+ pkiDebug("%s: did not find an acceptable SAN in KDC certificate\n",
+ __FUNCTION__);
+ retval = KRB5KDC_ERR_KDC_NAME_MISMATCH;
+ goto cleanup;
+ }
+
+ if (need_eku_checking) {
+ retval = verify_kdc_eku(context, plgctx, reqctx,
+ &valid_eku);
+ if (retval)
+ goto cleanup;
+ if (!valid_eku) {
+ pkiDebug("%s: did not find an acceptable EKU in KDC certificate\n",
+ __FUNCTION__);
+ retval = KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
+ goto cleanup;
+ }
+ } else
+ pkiDebug("%s: skipping EKU check\n", __FUNCTION__);
+
+ OCTETDATA_TO_KRB5DATA(&dh_data, &k5data);
+
+ switch(kdc_reply->choice) {
+ case choice_pa_pk_as_rep_dhInfo:
+#ifdef DEBUG_ASN1
+ print_buffer_bin(dh_data.data, dh_data.length,
+ "/tmp/client_dh_key");
+#endif
+ if ((retval = k5int_decode_krb5_kdc_dh_key_info(&k5data,
+ &kdc_dh)) != 0) {
+ pkiDebug("failed to decode kdc_dh_key_info\n");
+ goto cleanup;
+ }
+
+ /* client after KDC reply */
+ if ((retval = client_process_dh(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx,
+ kdc_dh->subjectPublicKey.data,
+ kdc_dh->subjectPublicKey.length,
+ &client_key, &client_key_len)) != 0) {
+ pkiDebug("failed to process dh params\n");
+ goto cleanup;
+ }
+
+ retval = pkinit_octetstring2key(context, etype, client_key,
+ client_key_len, key_block);
+ if (retval) {
+ pkiDebug("failed to create key pkinit_octetstring2key %s\n",
+ error_message(retval));
+ goto cleanup;
+ }
+
+ break;
+ case choice_pa_pk_as_rep_encKeyPack:
+#ifdef DEBUG_ASN1
+ print_buffer_bin(dh_data.data, dh_data.length,
+ "/tmp/client_key_pack");
+#endif
+ if ((retval = k5int_decode_krb5_reply_key_pack(&k5data,
+ &key_pack)) != 0) {
+ pkiDebug("failed to decode reply_key_pack\n");
+#ifdef LONGHORN_BETA_COMPAT
+ /*
+ * LH Beta 3 requires the extra pa-data, even for RFC requests,
+ * in order to get the Checksum rather than a Nonce in the reply.
+ * This can be removed when LH SP1 is released.
+ */
+ if (pa_type == KRB5_PADATA_PK_AS_REP && longhorn == 0)
+#else
+ if (pa_type == KRB5_PADATA_PK_AS_REP)
+#endif
+ goto cleanup;
+ else {
+ if ((retval =
+ k5int_decode_krb5_reply_key_pack_draft9(&k5data,
+ &key_pack9)) != 0) {
+ pkiDebug("failed to decode reply_key_pack_draft9\n");
+ goto cleanup;
+ }
+ pkiDebug("decode reply_key_pack_draft9\n");
+ if (key_pack9->nonce != request->nonce) {
+ pkiDebug("nonce in AS_REP=%d doesn't match AS_REQ=%d\n", key_pack9->nonce, request->nonce);
+ retval = -1;
+ goto cleanup;
+ }
+ krb5_copy_keyblock_contents(context, &key_pack9->replyKey,
+ key_block);
+ break;
+ }
+ }
+ /*
+ * This is hack but Windows sends back SHA1 checksum
+ * with checksum type of 14. There is currently no
+ * checksum type of 14 defined.
+ */
+ if (key_pack->asChecksum.checksum_type == 14)
+ key_pack->asChecksum.checksum_type = CKSUMTYPE_NIST_SHA;
+ retval = krb5_c_make_checksum(context,
+ key_pack->asChecksum.checksum_type,
+ &key_pack->replyKey,
+ KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
+ encoded_request, &cksum);
+ if (retval) {
+ pkiDebug("failed to make a checksum\n");
+ goto cleanup;
+ }
+
+ if ((cksum.length != key_pack->asChecksum.length) ||
+ memcmp(cksum.contents, key_pack->asChecksum.contents,
+ cksum.length)) {
+ pkiDebug("failed to match the checksums\n");
+#ifdef DEBUG_CKSUM
+ pkiDebug("calculating checksum on buf size (%d)\n",
+ encoded_request->length);
+ print_buffer(encoded_request->data, encoded_request->length);
+ pkiDebug("encrypting key (%d)\n", key_pack->replyKey.length);
+ print_buffer(key_pack->replyKey.contents,
+ key_pack->replyKey.length);
+ pkiDebug("received checksum type=%d size=%d ",
+ key_pack->asChecksum.checksum_type,
+ key_pack->asChecksum.length);
+ print_buffer(key_pack->asChecksum.contents,
+ key_pack->asChecksum.length);
+ pkiDebug("expected checksum type=%d size=%d ",
+ cksum.checksum_type, cksum.length);
+ print_buffer(cksum.contents, cksum.length);
+#endif
+ goto cleanup;
+ } else
+ pkiDebug("checksums match\n");
+
+ krb5_copy_keyblock_contents(context, &key_pack->replyKey,
+ key_block);
+
+ break;
+ default:
+ pkiDebug("unknow as_rep type %d\n", kdc_reply->choice);
+ goto cleanup;
+ }
+
+ retval = 0;
+
+cleanup:
+ if (dh_data.data != NULL)
+ free(dh_data.data);
+ if (client_key != NULL)
+ free(client_key);
+ free_krb5_kdc_dh_key_info(&kdc_dh);
+ free_krb5_pa_pk_as_rep(&kdc_reply);
+
+ if (key_pack != NULL) {
+ free_krb5_reply_key_pack(&key_pack);
+ if (cksum.contents != NULL)
+ free(cksum.contents);
+ }
+ if (key_pack9 != NULL)
+ free_krb5_reply_key_pack_draft9(&key_pack9);
+
+ if (kdc_hostname != NULL)
+ free(kdc_hostname);
+
+ pkiDebug("pkinit_as_rep_parse returning %d (%s)\n",
+ retval, error_message(retval));
+ return retval;
+}
+
+static void
+pkinit_client_profile(krb5_context context,
+ pkinit_context plgctx,
+ pkinit_req_context reqctx,
+ krb5_kdc_req *request)
+{
+ char *eku_string = NULL;
+
+ pkiDebug("pkinit_client_profile %p %p %p %p\n",
+ context, plgctx, reqctx, request);
+
+ (void) pkinit_libdefault_boolean(context, &request->server->realm,
+ "pkinit_win2k",
+ reqctx->opts->win2k_target,
+ &reqctx->opts->win2k_target);
+ (void) pkinit_libdefault_boolean(context, &request->server->realm,
+ "pkinit_win2k_require_binding",
+ reqctx->opts->win2k_require_cksum,
+ &reqctx->opts->win2k_require_cksum);
+ (void) pkinit_libdefault_boolean(context, &request->server->realm,
+ "pkinit_require_crl_checking",
+ reqctx->opts->require_crl_checking,
+ &reqctx->opts->require_crl_checking);
+ (void) pkinit_libdefault_integer(context, &request->server->realm,
+ "pkinit_dh_min_bits",
+ reqctx->opts->dh_size,
+ &reqctx->opts->dh_size);
+ if (reqctx->opts->dh_size != 1024 && reqctx->opts->dh_size != 2048
+ && reqctx->opts->dh_size != 4096) {
+ pkiDebug("%s: invalid value (%d) for pkinit_dh_min_bits, "
+ "using default value (%d) instead\n", __FUNCTION__,
+ reqctx->opts->dh_size, PKINIT_DEFAULT_DH_MIN_BITS);
+ reqctx->opts->dh_size = PKINIT_DEFAULT_DH_MIN_BITS;
+ }
+ (void) pkinit_libdefault_string(context, &request->server->realm,
+ "pkinit_eku_checking",
+ &eku_string);
+ if (eku_string != NULL) {
+ if (strcasecmp(eku_string, "kpKDC") == 0) {
+ reqctx->opts->require_eku = 1;
+ reqctx->opts->accept_secondary_eku = 0;
+ } else if (strcasecmp(eku_string, "kpServerAuth") == 0) {
+ reqctx->opts->require_eku = 1;
+ reqctx->opts->accept_secondary_eku = 1;
+ } else if (strcasecmp(eku_string, "none") == 0) {
+ reqctx->opts->require_eku = 0;
+ reqctx->opts->accept_secondary_eku = 0;
+ } else {
+ pkiDebug("%s: Invalid value for pkinit_eku_checking: '%s'\n",
+ __FUNCTION__, eku_string);
+ }
+ free(eku_string);
+ }
+#ifdef LONGHORN_BETA_COMPAT
+ /* Temporarily just set global flag from config file */
+ (void) pkinit_libdefault_boolean(context, &request->server->realm,
+ "pkinit_longhorn",
+ 0,
+ &longhorn);
+#endif
+
+ /* Only process anchors here if they were not specified on command line */
+ if (reqctx->idopts->anchors == NULL)
+ (void) pkinit_libdefault_strings(context, &request->server->realm,
+ "pkinit_anchors",
+ &reqctx->idopts->anchors);
+ /* Solaris Kerberos */
+ (void) pkinit_libdefault_strings(context, &request->server->realm,
+ "pkinit_pool",
+ &reqctx->idopts->intermediates);
+ (void) pkinit_libdefault_strings(context, &request->server->realm,
+ "pkinit_revoke",
+ &reqctx->idopts->crls);
+ (void) pkinit_libdefault_strings(context, &request->server->realm,
+ "pkinit_identities",
+ &reqctx->idopts->identity_alt);
+}
+
+/* ARGSUSED */
+krb5_error_code
+pkinit_client_process(krb5_context context,
+ void *plugin_context,
+ void *request_context,
+ krb5_get_init_creds_opt *gic_opt,
+ preauth_get_client_data_proc get_data_proc,
+ struct _krb5_preauth_client_rock *rock,
+ krb5_kdc_req *request,
+ krb5_data *encoded_request_body,
+ krb5_data *encoded_previous_request,
+ krb5_pa_data *in_padata,
+ krb5_prompter_fct prompter,
+ void *prompter_data,
+ preauth_get_as_key_proc gak_fct,
+ void *gak_data,
+ krb5_data *salt,
+ krb5_data *s2kparams,
+ krb5_keyblock *as_key,
+ krb5_pa_data ***out_padata)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_enctype enctype = -1;
+ krb5_data *cdata = NULL;
+ int processing_request = 0;
+ pkinit_context plgctx = (pkinit_context)plugin_context;
+ pkinit_req_context reqctx = (pkinit_req_context)request_context;
+
+ pkiDebug("pkinit_client_process %p %p %p %p\n",
+ context, plgctx, reqctx, request);
+
+ if (plgctx == NULL || reqctx == NULL)
+ return EINVAL;
+
+ switch ((int) in_padata->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ pkiDebug("processing KRB5_PADATA_PK_AS_REQ\n");
+ processing_request = 1;
+ break;
+
+ case KRB5_PADATA_PK_AS_REP:
+ pkiDebug("processing KRB5_PADATA_PK_AS_REP\n");
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ if (in_padata->length == 0) {
+ pkiDebug("processing KRB5_PADATA_PK_AS_REQ_OLD\n");
+ in_padata->pa_type = KRB5_PADATA_PK_AS_REQ_OLD;
+ processing_request = 1;
+ } else {
+ pkiDebug("processing KRB5_PADATA_PK_AS_REP_OLD\n");
+ in_padata->pa_type = KRB5_PADATA_PK_AS_REP_OLD;
+ }
+ break;
+ default:
+ pkiDebug("unrecognized patype = %d for PKINIT\n",
+ in_padata->pa_type);
+ return EINVAL;
+ }
+
+ if (processing_request) {
+ pkinit_client_profile(context, plgctx, reqctx, request);
+ /* Solaris Kerberos */
+ retval = pkinit_identity_set_prompter(reqctx->idctx, prompter, prompter_data);
+ if (retval) {
+ pkiDebug("pkinit_identity_set_prompter returned %d (%s)\n",
+ retval, error_message(retval));
+ return retval;
+ }
+
+ retval = pkinit_identity_initialize(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idopts,
+ reqctx->idctx, 1, request->client);
+ if (retval) {
+ pkiDebug("pkinit_identity_initialize returned %d (%s)\n",
+ retval, error_message(retval));
+ return retval;
+ }
+ retval = pa_pkinit_gen_req(context, plgctx, reqctx, request,
+ in_padata, out_padata, prompter,
+ prompter_data, gic_opt);
+ } else {
+ /*
+ * Get the enctype of the reply.
+ */
+ retval = (*get_data_proc)(context, rock,
+ krb5plugin_preauth_client_get_etype, &cdata);
+ if (retval) {
+ pkiDebug("get_data_proc returned %d (%s)\n",
+ retval, error_message(retval));
+ return retval;
+ }
+ enctype = *((krb5_enctype *)cdata->data);
+ (*get_data_proc)(context, rock,
+ krb5plugin_preauth_client_free_etype, &cdata);
+ retval = pa_pkinit_parse_rep(context, plgctx, reqctx, request,
+ in_padata, enctype, as_key,
+ encoded_previous_request);
+ }
+
+ pkiDebug("pkinit_client_process: returning %d (%s)\n",
+ retval, error_message(retval));
+ return retval;
+}
+
+/* ARGSUSED */
+krb5_error_code
+pkinit_client_tryagain(krb5_context context,
+ void *plugin_context,
+ void *request_context,
+ krb5_get_init_creds_opt *gic_opt,
+ preauth_get_client_data_proc get_data_proc,
+ struct _krb5_preauth_client_rock *rock,
+ krb5_kdc_req *request,
+ krb5_data *encoded_request_body,
+ krb5_data *encoded_previous_request,
+ krb5_pa_data *in_padata,
+ krb5_error *err_reply,
+ krb5_prompter_fct prompter,
+ void *prompter_data,
+ preauth_get_as_key_proc gak_fct,
+ void *gak_data,
+ krb5_data *salt,
+ krb5_data *s2kparams,
+ krb5_keyblock *as_key,
+ krb5_pa_data ***out_padata)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ pkinit_context plgctx = (pkinit_context)plugin_context;
+ pkinit_req_context reqctx = (pkinit_req_context)request_context;
+ krb5_typed_data **typed_data = NULL;
+ krb5_data scratch;
+ krb5_external_principal_identifier **krb5_trusted_certifiers = NULL;
+ krb5_algorithm_identifier **algId = NULL;
+ int do_again = 0;
+
+ pkiDebug("pkinit_client_tryagain %p %p %p %p\n",
+ context, plgctx, reqctx, request);
+
+ if (reqctx->pa_type != in_padata->pa_type)
+ return retval;
+
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)err_reply->e_data.data,
+ err_reply->e_data.length, "/tmp/client_edata");
+#endif
+ retval = k5int_decode_krb5_typed_data(&err_reply->e_data, &typed_data);
+ if (retval) {
+ pkiDebug("decode_krb5_typed_data failed\n");
+ goto cleanup;
+ }
+#ifdef DEBUG_ASN1
+ print_buffer_bin(typed_data[0]->data, typed_data[0]->length,
+ "/tmp/client_typed_data");
+#endif
+ OCTETDATA_TO_KRB5DATA(typed_data[0], &scratch);
+
+ switch(typed_data[0]->type) {
+ case TD_TRUSTED_CERTIFIERS:
+ case TD_INVALID_CERTIFICATES:
+ retval = k5int_decode_krb5_td_trusted_certifiers(&scratch,
+ &krb5_trusted_certifiers);
+ if (retval) {
+ pkiDebug("failed to decode sequence of trusted certifiers\n");
+ goto cleanup;
+ }
+ retval = pkinit_process_td_trusted_certifiers(context,
+ plgctx->cryptoctx, reqctx->cryptoctx, reqctx->idctx,
+ krb5_trusted_certifiers, typed_data[0]->type);
+ if (!retval)
+ do_again = 1;
+ break;
+ case TD_DH_PARAMETERS:
+ retval = k5int_decode_krb5_td_dh_parameters(&scratch, &algId);
+ if (retval) {
+ pkiDebug("failed to decode td_dh_parameters\n");
+ goto cleanup;
+ }
+ retval = pkinit_process_td_dh_params(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, reqctx->idctx, algId,
+ &reqctx->opts->dh_size);
+ if (!retval)
+ do_again = 1;
+ break;
+ default:
+ break;
+ }
+
+ if (do_again) {
+ retval = pa_pkinit_gen_req(context, plgctx, reqctx, request, in_padata,
+ out_padata, prompter, prompter_data, gic_opt);
+ if (retval)
+ goto cleanup;
+ }
+
+ retval = 0;
+cleanup:
+ if (krb5_trusted_certifiers != NULL)
+ free_krb5_external_principal_identifier(&krb5_trusted_certifiers);
+
+ if (typed_data != NULL)
+ free_krb5_typed_data(&typed_data);
+
+ if (algId != NULL)
+ free_krb5_algorithm_identifiers(&algId);
+
+ pkiDebug("pkinit_client_tryagain: returning %d (%s)\n",
+ retval, error_message(retval));
+ return retval;
+}
+
+/* ARGSUSED */
+static int
+pkinit_client_get_flags(krb5_context kcontext, krb5_preauthtype patype)
+{
+ return PA_REAL;
+}
+
+static krb5_preauthtype supported_client_pa_types[] = {
+ KRB5_PADATA_PK_AS_REP,
+ KRB5_PADATA_PK_AS_REQ,
+ KRB5_PADATA_PK_AS_REP_OLD,
+ KRB5_PADATA_PK_AS_REQ_OLD,
+ 0
+};
+
+/* ARGSUSED */
+void
+pkinit_client_req_init(krb5_context context,
+ void *plugin_context,
+ void **request_context)
+{
+ krb5_error_code retval = ENOMEM;
+ struct _pkinit_req_context *reqctx = NULL;
+ struct _pkinit_context *plgctx = (struct _pkinit_context *)plugin_context;
+
+ *request_context = NULL;
+
+ reqctx = (struct _pkinit_req_context *) malloc(sizeof(*reqctx));
+ if (reqctx == NULL)
+ return;
+ (void) memset(reqctx, 0, sizeof(*reqctx));
+
+ reqctx->magic = PKINIT_REQ_CTX_MAGIC;
+ reqctx->cryptoctx = NULL;
+ reqctx->opts = NULL;
+ reqctx->idctx = NULL;
+ reqctx->idopts = NULL;
+
+ retval = pkinit_init_req_opts(&reqctx->opts);
+ if (retval)
+ goto cleanup;
+
+ reqctx->opts->require_eku = plgctx->opts->require_eku;
+ reqctx->opts->accept_secondary_eku = plgctx->opts->accept_secondary_eku;
+ reqctx->opts->dh_or_rsa = plgctx->opts->dh_or_rsa;
+ reqctx->opts->allow_upn = plgctx->opts->allow_upn;
+ reqctx->opts->require_crl_checking = plgctx->opts->require_crl_checking;
+
+ retval = pkinit_init_req_crypto(&reqctx->cryptoctx);
+ if (retval)
+ goto cleanup;
+
+ retval = pkinit_init_identity_crypto(&reqctx->idctx);
+ if (retval)
+ goto cleanup;
+
+ retval = pkinit_dup_identity_opts(plgctx->idopts, &reqctx->idopts);
+ if (retval)
+ goto cleanup;
+
+ *request_context = (void *) reqctx;
+ pkiDebug("%s: returning reqctx at %p\n", __FUNCTION__, reqctx);
+
+cleanup:
+ if (retval) {
+ if (reqctx->idctx != NULL)
+ pkinit_fini_identity_crypto(reqctx->idctx);
+ if (reqctx->cryptoctx != NULL)
+ pkinit_fini_req_crypto(reqctx->cryptoctx);
+ if (reqctx->opts != NULL)
+ pkinit_fini_req_opts(reqctx->opts);
+ if (reqctx->idopts != NULL)
+ pkinit_fini_identity_opts(reqctx->idopts);
+ free(reqctx);
+ }
+
+ return;
+}
+
+/* ARGSUSED */
+void
+pkinit_client_req_fini(krb5_context context,
+ void *plugin_context,
+ void *request_context)
+{
+ struct _pkinit_req_context *reqctx =
+ (struct _pkinit_req_context *)request_context;
+
+ pkiDebug("%s: received reqctx at %p\n", __FUNCTION__, reqctx);
+ if (reqctx == NULL)
+ return;
+ if (reqctx->magic != PKINIT_REQ_CTX_MAGIC) {
+ pkiDebug("%s: Bad magic value (%x) in req ctx\n",
+ __FUNCTION__, reqctx->magic);
+ return;
+ }
+ if (reqctx->opts != NULL)
+ pkinit_fini_req_opts(reqctx->opts);
+
+ if (reqctx->cryptoctx != NULL)
+ pkinit_fini_req_crypto(reqctx->cryptoctx);
+
+ if (reqctx->idctx != NULL)
+ pkinit_fini_identity_crypto(reqctx->idctx);
+
+ if (reqctx->idopts != NULL)
+ pkinit_fini_identity_opts(reqctx->idopts);
+
+ free(reqctx);
+ return;
+}
+
+/* ARGSUSED */
+static void
+pkinit_fini_client_profile(krb5_context context, pkinit_context plgctx)
+{
+ /* This should clean up anything allocated in pkinit_init_client_profile */
+}
+
+/* ARGSUSED */
+static krb5_error_code
+pkinit_init_client_profile(krb5_context context, pkinit_context plgctx)
+{
+ return 0;
+}
+
+static int
+pkinit_client_plugin_init(krb5_context context, void **blob)
+{
+ krb5_error_code retval = ENOMEM;
+ struct _pkinit_context *ctx = NULL;
+
+ ctx = (struct _pkinit_context *)calloc(1, sizeof(*ctx));
+ if (ctx == NULL)
+ return ENOMEM;
+ (void) memset(ctx, 0, sizeof(*ctx));
+ ctx->magic = PKINIT_CTX_MAGIC;
+ ctx->opts = NULL;
+ ctx->cryptoctx = NULL;
+ ctx->idopts = NULL;
+
+ retval = pkinit_accessor_init();
+ if (retval)
+ goto errout;
+
+ retval = pkinit_init_plg_opts(&ctx->opts);
+ if (retval)
+ goto errout;
+
+ retval = pkinit_init_plg_crypto(&ctx->cryptoctx);
+ if (retval)
+ goto errout;
+
+ retval = pkinit_init_identity_opts(&ctx->idopts);
+ if (retval)
+ goto errout;
+
+ retval = pkinit_init_client_profile(context, ctx);
+ if (retval)
+ goto errout;
+
+ *blob = ctx;
+
+ pkiDebug("%s: returning plgctx at %p\n", __FUNCTION__, ctx);
+
+errout:
+ if (retval)
+ pkinit_client_plugin_fini(context, ctx);
+
+ return retval;
+}
+
+static void
+pkinit_client_plugin_fini(krb5_context context, void *blob)
+{
+ struct _pkinit_context *ctx = (struct _pkinit_context *)blob;
+
+ if (ctx == NULL || ctx->magic != PKINIT_CTX_MAGIC) {
+ pkiDebug("pkinit_lib_fini: got bad plgctx (%p)!\n", ctx);
+ return;
+ }
+ pkiDebug("%s: got plgctx at %p\n", __FUNCTION__, ctx);
+
+ pkinit_fini_client_profile(context, ctx);
+ pkinit_fini_identity_opts(ctx->idopts);
+ pkinit_fini_plg_crypto(ctx->cryptoctx);
+ pkinit_fini_plg_opts(ctx->opts);
+ free(ctx);
+
+}
+
+/* ARGSUSED */
+static krb5_error_code
+add_string_to_array(krb5_context context, char ***array, const char *addition)
+{
+ char **out = NULL;
+
+ if (*array == NULL) {
+ out = malloc(2 * sizeof(char *));
+ if (out == NULL)
+ return ENOMEM;
+ out[1] = NULL;
+ out[0] = strdup(addition);
+ if (out[0] == NULL) {
+ free(out);
+ return ENOMEM;
+ }
+ } else {
+ int i;
+ char **a = *array;
+ for (i = 0; a[i] != NULL; i++);
+ out = malloc( (i + 2) * sizeof(char *));
+ if (out == NULL)
+ return ENOMEM;
+ for (i = 0; a[i] != NULL; i++) {
+ out[i] = a[i];
+ }
+ out[i++] = strdup(addition);
+ if (out == NULL) {
+ free(out);
+ return ENOMEM;
+ }
+ out[i] = NULL;
+ free(*array);
+ }
+ *array = out;
+
+ return 0;
+}
+static krb5_error_code
+handle_gic_opt(krb5_context context,
+ struct _pkinit_context *plgctx,
+ const char *attr,
+ const char *value)
+{
+ krb5_error_code retval;
+
+ if (strcmp(attr, "X509_user_identity") == 0) {
+ if (plgctx->idopts->identity != NULL) {
+ krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
+ "X509_user_identity can not be given twice\n");
+ return KRB5_PREAUTH_FAILED;
+ }
+ plgctx->idopts->identity = strdup(value);
+ if (plgctx->idopts->identity == NULL) {
+ krb5_set_error_message(context, ENOMEM,
+ "Could not duplicate X509_user_identity value\n");
+ return ENOMEM;
+ }
+ } else if (strcmp(attr, "X509_anchors") == 0) {
+ retval = add_string_to_array(context, &plgctx->idopts->anchors, value);
+ if (retval)
+ return retval;
+ } else if (strcmp(attr, "flag_RSA_PROTOCOL") == 0) {
+ if (strcmp(value, "yes") == 0) {
+ pkiDebug("Setting flag to use RSA_PROTOCOL\n");
+ plgctx->opts->dh_or_rsa = RSA_PROTOCOL;
+ }
+ }
+ return 0;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+pkinit_client_gic_opt(krb5_context context,
+ void *plugin_context,
+ krb5_get_init_creds_opt *gic_opt,
+ const char *attr,
+ const char *value)
+{
+ krb5_error_code retval;
+ struct _pkinit_context *plgctx = (struct _pkinit_context *)plugin_context;
+
+ pkiDebug("(pkinit) received '%s' = '%s'\n", attr, value);
+ retval = handle_gic_opt(context, plgctx, attr, value);
+ if (retval)
+ return retval;
+
+ return 0;
+}
+
+struct krb5plugin_preauth_client_ftable_v1 preauthentication_client_1 = {
+ "pkinit", /* name */
+ supported_client_pa_types, /* pa_type_list */
+ NULL, /* enctype_list */
+ pkinit_client_plugin_init, /* (*init) */
+ pkinit_client_plugin_fini, /* (*fini) */
+ pkinit_client_get_flags, /* (*flags) */
+ pkinit_client_req_init, /* (*client_req_init) */
+ pkinit_client_req_fini, /* (*client_req_fini) */
+ pkinit_client_process, /* (*process) */
+ pkinit_client_tryagain, /* (*tryagain) */
+ pkinit_client_gic_opt /* (*gic_opt) */
+};
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto.h b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto.h
new file mode 100644
index 0000000000..292325b7eb
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto.h
@@ -0,0 +1,624 @@
+/*
+ * COPYRIGHT (C) 2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+/*
+ * This header defines the cryptographic interface
+ */
+
+#ifndef _PKINIT_CRYPTO_H
+#define _PKINIT_CRYPTO_H
+
+/* Solaris Kerberos */
+#include <krb5.h>
+#include <preauth_plugin.h>
+#include <k5-int-pkinit.h>
+#include <profile.h>
+#include "pkinit_accessor.h"
+
+/*
+ * these describe the CMS message types
+ */
+enum cms_msg_types {
+ CMS_SIGN_CLIENT,
+ CMS_SIGN_DRAFT9,
+ CMS_SIGN_SERVER,
+ CMS_ENVEL_SERVER
+};
+
+/*
+ * storage types for identity information
+ */
+#define IDTYPE_FILE 1
+#define IDTYPE_DIR 2
+#define IDTYPE_PKCS11 3
+#define IDTYPE_ENVVAR 4
+#define IDTYPE_PKCS12 5
+
+/*
+ * ca/crl types
+ */
+#define CATYPE_ANCHORS 1
+#define CATYPE_INTERMEDIATES 2
+#define CATYPE_CRLS 3
+
+/*
+ * The following represent Key Usage values that we
+ * may care about in a certificate
+ */
+#define PKINIT_KU_DIGITALSIGNATURE 0x80000000
+#define PKINIT_KU_KEYENCIPHERMENT 0x40000000
+
+/*
+ * The following represent Extended Key Usage oid values
+ * that we may care about in a certificate
+ */
+#define PKINIT_EKU_PKINIT 0x80000000
+#define PKINIT_EKU_MSSCLOGIN 0x40000000
+#define PKINIT_EKU_CLIENTAUTH 0x20000000
+#define PKINIT_EKU_EMAILPROTECTION 0x10000000
+
+
+/* Handle to cert, opaque above crypto interface */
+typedef struct _pkinit_cert_info *pkinit_cert_handle;
+
+/* Handle to cert iteration information, opaque above crypto interface */
+typedef struct _pkinit_cert_iter_info *pkinit_cert_iter_handle;
+
+#define PKINIT_ITER_NO_MORE 0x11111111 /* XXX */
+
+typedef struct _pkinit_cert_matching_data {
+ pkinit_cert_handle ch; /* cert handle for this certificate */
+ char *subject_dn; /* rfc2253-style subject name string */
+ char *issuer_dn; /* rfc2253-style issuer name string */
+ unsigned int ku_bits; /* key usage information */
+ unsigned int eku_bits; /* extended key usage information */
+ krb5_principal *sans; /* Null-terminated array of subject alternative
+ name info (pkinit and ms-upn) */
+} pkinit_cert_matching_data;
+
+/*
+ * Functions to initialize and cleanup crypto contexts
+ */
+krb5_error_code pkinit_init_plg_crypto(pkinit_plg_crypto_context *);
+void pkinit_fini_plg_crypto(pkinit_plg_crypto_context);
+
+krb5_error_code pkinit_init_req_crypto(pkinit_req_crypto_context *);
+void pkinit_fini_req_crypto(pkinit_req_crypto_context);
+
+krb5_error_code pkinit_init_identity_crypto(pkinit_identity_crypto_context *);
+void pkinit_fini_identity_crypto(pkinit_identity_crypto_context);
+
+/*
+ * this function creates a CMS message where eContentType is SignedData
+ */
+krb5_error_code cms_signeddata_create
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ int cms_msg_type, /* IN
+ specifies CMS_SIGN_CLIENT for client-side CMS message
+ and CMS_SIGN_SERVER for kdc-side */
+ int include_certchain, /* IN
+ specifies where certificates field in SignedData
+ should contain certificate path */
+ unsigned char *auth_pack, /* IN
+ contains DER encoded AuthPack (CMS_SIGN_CLIENT)
+ or DER encoded DHRepInfo (CMS_SIGN_SERVER) */
+ unsigned int auth_pack_len, /* IN
+ contains length of auth_pack */
+ unsigned char **signed_data, /* OUT
+ for CMS_SIGN_CLIENT receives DER encoded
+ SignedAuthPack (CMS_SIGN_CLIENT) or DER
+ encoded DHInfo (CMS_SIGN_SERVER) */
+ unsigned int *signed_data_len); /* OUT
+ receives length of signed_data */
+
+/*
+ * this function verifies a CMS message where eContentType is SignedData
+ */
+krb5_error_code cms_signeddata_verify
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ int cms_msg_type, /* IN
+ specifies CMS_SIGN_CLIENT for client-side
+ CMS message and CMS_SIGN_SERVER for kdc-side */
+ int require_crl_checking, /* IN
+ specifies whether CRL checking should be
+ strictly enforced, i.e. if no CRLs available
+ for the CA then fail verification.
+ note, if the value is 0, crls are still
+ checked if present */
+ unsigned char *signed_data, /* IN
+ contains DER encoded SignedAuthPack (CMS_SIGN_CLIENT)
+ or DER encoded DHInfo (CMS_SIGN_SERVER) */
+ unsigned int signed_data_len, /* IN
+ contains length of signed_data*/
+ unsigned char **auth_pack, /* OUT
+ receives DER encoded AuthPack (CMS_SIGN_CLIENT)
+ or DER encoded DHRepInfo (CMS_SIGN_SERVER)*/
+ unsigned int *auth_pack_len, /* OUT
+ receives length of auth_pack */
+ unsigned char **authz_data, /* OUT
+ receives required authorization data that
+ contains the verified certificate chain
+ (only used by the KDC) */
+ unsigned int *authz_data_len); /* OUT
+ receives length of authz_data */
+
+/*
+ * this function creates a CMS message where eContentType is EnvelopedData
+ */
+krb5_error_code cms_envelopeddata_create
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ krb5_preauthtype pa_type, /* IN */
+ int include_certchain, /* IN
+ specifies whether the certificates field in
+ SignedData should contain certificate path */
+ unsigned char *key_pack, /* IN
+ contains DER encoded ReplyKeyPack */
+ unsigned int key_pack_len, /* IN
+ contains length of key_pack */
+ unsigned char **envel_data, /* OUT
+ receives DER encoded encKeyPack */
+ unsigned int *envel_data_len); /* OUT
+ receives length of envel_data */
+
+/*
+ * this function creates a CMS message where eContentType is EnvelopedData
+ */
+krb5_error_code cms_envelopeddata_verify
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ krb5_preauthtype pa_type, /* IN */
+ int require_crl_checking, /* IN
+ specifies whether CRL checking should be
+ strictly enforced */
+ unsigned char *envel_data, /* IN
+ contains DER encoded encKeyPack */
+ unsigned int envel_data_len, /* IN
+ contains length of envel_data */
+ unsigned char **signed_data, /* OUT
+ receives ReplyKeyPack */
+ unsigned int *signed_data_len); /* OUT
+ receives length of signed_data */
+
+/*
+ * this function returns SAN information found in the
+ * received certificate. at least one of pkinit_sans,
+ * upn_sans, or kdc_hostnames must be non-NULL.
+ */
+krb5_error_code crypto_retrieve_cert_sans
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ krb5_principal **pkinit_sans, /* OUT
+ if non-NULL, a null-terminated array of
+ id-pkinit-san values found in the certificate
+ are returned */
+ krb5_principal **upn_sans, /* OUT
+ if non-NULL, a null-terminated array of
+ id-ms-upn-san values found in the certificate
+ are returned */
+ unsigned char ***kdc_hostname); /* OUT
+ if non-NULL, a null-terminated array of
+ dNSName (hostname) SAN values found in the
+ certificate are returned */
+
+/*
+ * this function checks for acceptable key usage values
+ * in the received certificate.
+ *
+ * when checking a received kdc certificate, it looks for
+ * the kpKdc key usage. if allow_secondary_usage is
+ * non-zero, it will also accept kpServerAuth.
+ *
+ * when checking a received user certificate, it looks for
+ * kpClientAuth key usage. if allow_secondary_usage is
+ * non-zero, it will also accept id-ms-sc-logon EKU.
+ *
+ * this function must also assert that the digitalSignature
+ * key usage is consistent.
+ */
+krb5_error_code crypto_check_cert_eku
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ int checking_kdc_cert, /* IN
+ specifies if the received certificate is
+ a KDC certificate (non-zero),
+ or a user certificate (zero) */
+ int allow_secondary_usage, /* IN
+ specifies if the secondary key usage
+ should be accepted or not (see above) */
+ int *eku_valid); /* OUT
+ receives non-zero if an acceptable EKU was found */
+
+/*
+ * this functions takes in generated DH secret key and converts
+ * it in to a kerberos session key. it takes into the account the
+ * enc type and then follows the procedure specified in the RFC p 22.
+ */
+krb5_error_code pkinit_octetstring2key
+ (krb5_context context, /* IN */
+ krb5_enctype etype, /* IN
+ specifies the enc type */
+ unsigned char *key, /* IN
+ contains the DH secret key */
+ unsigned int key_len, /* IN
+ contains length of key */
+ krb5_keyblock * krb5key); /* OUT
+ receives kerberos session key */
+
+/*
+ * this function implements clients first part of the DH protocol.
+ * client selects its DH parameters and pub key
+ */
+krb5_error_code client_create_dh
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ int dh_size, /* IN
+ specifies the DH modulous, eg 1024, 2048, or 4096 */
+ unsigned char **dh_paramas, /* OUT
+ contains DER encoded DH params */
+ unsigned int *dh_params_len, /* OUT
+ contains length of dh_parmas */
+ unsigned char **dh_pubkey, /* OUT
+ receives DER encoded DH pub key */
+ unsigned int *dh_pubkey_len); /* OUT
+ receives length of dh_pubkey */
+
+/*
+ * this function completes client's the DH protocol. client
+ * processes received DH pub key from the KDC and computes
+ * the DH secret key
+ */
+krb5_error_code client_process_dh
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ unsigned char *dh_pubkey, /* IN
+ contains client's DER encoded DH pub key */
+ unsigned int dh_pubkey_len, /* IN
+ contains length of dh_pubkey */
+ unsigned char **dh_session_key, /* OUT
+ receives DH secret key */
+ unsigned int *dh_session_key_len); /* OUT
+ receives length of dh_session_key */
+
+/*
+ * this function implements the KDC first part of the DH protocol.
+ * it decodes the client's DH parameters and pub key and checks
+ * if they are acceptable.
+ */
+krb5_error_code server_check_dh
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ krb5_octet_data *dh_params, /* IN
+ ???? */
+ int minbits); /* IN
+ the mininum number of key bits acceptable */
+
+/*
+ * this function completes the KDC's DH protocol. The KDC generates
+ * its DH pub key and computes the DH secret key
+ */
+krb5_error_code server_process_dh
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ unsigned char *received_pubkey, /* IN
+ contains client's DER encoded DH pub key */
+ unsigned int received_pub_len, /* IN
+ contains length of received_pubkey */
+ unsigned char **dh_pubkey, /* OUT
+ receives KDC's DER encoded DH pub key */
+ unsigned int *dh_pubkey_len, /* OUT
+ receives length of dh_pubkey */
+ unsigned char **server_key, /* OUT
+ receives DH secret key */
+ unsigned int *server_key_len); /* OUT
+ receives length of server_key */
+
+/*
+ * this functions takes in crypto specific representation of
+ * supportedCMSTypes and creates a list of
+ * krb5_algorithm_identifier
+ */
+krb5_error_code create_krb5_supportedCMSTypes
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ krb5_algorithm_identifier ***supportedCMSTypes); /* OUT */
+
+/*
+ * this functions takes in crypto specific representation of
+ * trustedCertifiers and creates a list of
+ * krb5_external_principal_identifier
+ */
+krb5_error_code create_krb5_trustedCertifiers
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ krb5_external_principal_identifier ***trustedCertifiers); /* OUT */
+
+/*
+ * this functions takes in crypto specific representation of
+ * trustedCas (draft9) and creates a list of krb5_trusted_ca (draft9).
+ * draft9 trustedCAs is a CHOICE. we only support choices for
+ * [1] caName and [2] issuerAndSerial. there is no config
+ * option available to select the choice yet. default = 1.
+ */
+krb5_error_code create_krb5_trustedCas
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ int flag, /* IN
+ specifies the tag of the CHOICE */
+ krb5_trusted_ca ***trustedCas); /* OUT */
+
+/*
+ * this functions takes in crypto specific representation of the
+ * KDC's certificate and creates a DER encoded kdcPKId
+ */
+krb5_error_code create_issuerAndSerial
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ unsigned char **kdcId_buf, /* OUT
+ receives DER encoded kdcPKId */
+ unsigned int *kdcId_len); /* OUT
+ receives length of encoded kdcPKId */
+
+/*
+ * process the values from idopts and obtain the cert(s)
+ * specified by those options, populating the id_cryptoctx.
+ */
+krb5_error_code crypto_load_certs
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_opts *idopts, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */
+ krb5_principal princ); /* IN */
+
+/*
+ * Free up information held from crypto_load_certs()
+ */
+krb5_error_code crypto_free_cert_info
+ (krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx);
+
+
+/*
+ * Get number of certificates available after crypto_load_certs()
+ */
+krb5_error_code crypto_cert_get_count
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ int *cert_count); /* OUT */
+
+/*
+ * Begin iteration over the certs loaded in crypto_load_certs()
+ */
+krb5_error_code crypto_cert_iteration_begin
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ pkinit_cert_iter_handle *iter_handle); /* OUT */
+
+/*
+ * End iteration over the certs loaded in crypto_load_certs()
+ */
+krb5_error_code crypto_cert_iteration_end
+ (krb5_context context, /* IN */
+ pkinit_cert_iter_handle iter_handle); /* IN */
+
+/*
+ * Get next certificate handle
+ */
+krb5_error_code crypto_cert_iteration_next
+ (krb5_context context, /* IN */
+ pkinit_cert_iter_handle iter_handle, /* IN */
+ pkinit_cert_handle *cert_handle); /* OUT */
+
+/*
+ * Release cert handle
+ */
+krb5_error_code crypto_cert_release
+ (krb5_context context, /* IN */
+ pkinit_cert_handle cert_handle); /* IN */
+
+/*
+ * Get certificate matching information
+ */
+krb5_error_code crypto_cert_get_matching_data
+ (krb5_context context, /* IN */
+ pkinit_cert_handle cert_handle, /* IN */
+ pkinit_cert_matching_data **ret_data); /* OUT */
+
+/*
+ * Free certificate information
+ */
+krb5_error_code crypto_cert_free_matching_data
+ (krb5_context context, /* IN */
+ pkinit_cert_matching_data *data); /* IN */
+
+/*
+ * Make the given certificate "the chosen one"
+ */
+krb5_error_code crypto_cert_select
+ (krb5_context context, /* IN */
+ pkinit_cert_matching_data *data); /* IN */
+
+/*
+ * Select the default certificate as "the chosen one"
+ */
+krb5_error_code crypto_cert_select_default
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx); /* IN */
+
+/*
+ * process the values from idopts and obtain the anchor or
+ * intermediate certificates, or crls specified by idtype,
+ * catype, and id
+ */
+krb5_error_code crypto_load_cas_and_crls
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_opts *idopts, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */
+ int idtype, /* IN
+ defines the storage type (file, directory, etc) */
+ int catype, /* IN
+ defines the ca type (anchor, intermediate, crls) */
+ char *id); /* IN
+ defines the location (filename, directory name, etc) */
+
+/*
+ * on the client, obtain the kdc's certificate to include
+ * in a request
+ */
+krb5_error_code pkinit_get_kdc_cert
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN/OUT */
+ krb5_principal princ); /* IN */
+
+/*
+ * this function creates edata that contains TD-DH-PARAMETERS
+ */
+krb5_error_code pkinit_create_td_dh_parameters
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ pkinit_plg_opts *opts, /* IN */
+ krb5_data **edata); /* OUT */
+
+/*
+ * this function processes edata that contains TD-DH-PARAMETERS.
+ * the client processes the received acceptable by KDC DH
+ * parameters and picks the first acceptable to it. it matches
+ * them against the known DH parameters.
+ */
+krb5_error_code pkinit_process_td_dh_params
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ krb5_algorithm_identifier **algId, /* IN */
+ int *new_dh_size); /* OUT
+ receives the new DH modulus to use in the new AS-REQ */
+
+/*
+ * this function creates edata that contains TD-INVALID-CERTIFICATES
+ */
+krb5_error_code pkinit_create_td_invalid_certificate
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ krb5_data **edata); /* OUT */
+
+/*
+ * this function creates edata that contains TD-TRUSTED-CERTIFIERS
+ */
+krb5_error_code pkinit_create_td_trusted_certifiers
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ krb5_data **edata); /* OUT */
+
+/*
+ * this function processes edata that contains either
+ * TD-TRUSTED-CERTIFICATES or TD-INVALID-CERTIFICATES.
+ * current implementation only decodes the received message
+ * but does not act on it
+ */
+krb5_error_code pkinit_process_td_trusted_certifiers
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ krb5_external_principal_identifier **trustedCertifiers, /* IN */
+ int td_type); /* IN */
+
+/*
+ * this function checks if the received kdcPKId matches
+ * the KDC's certificate
+ */
+krb5_error_code pkinit_check_kdc_pkid
+ (krb5_context context, /* IN */
+ pkinit_plg_crypto_context plg_cryptoctx, /* IN */
+ pkinit_req_crypto_context req_cryptoctx, /* IN */
+ pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ unsigned char *pdid_buf, /* IN
+ contains DER encoded kdcPKId */
+ unsigned int pkid_len, /* IN
+ contains length of pdid_buf */
+ int *valid_kdcPkId); /* OUT
+ 1 if kdcPKId matches, otherwise 0 */
+
+krb5_error_code pkinit_identity_set_prompter
+ (pkinit_identity_crypto_context id_cryptoctx, /* IN */
+ krb5_prompter_fct prompter, /* IN */
+ void *prompter_data); /* IN */
+
+#endif /* _PKINIT_CRYPTO_H */
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c
new file mode 100644
index 0000000000..25bd44acc3
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.c
@@ -0,0 +1,5982 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <dirent.h>
+
+/* Solaris Kerberos */
+#include <libintl.h>
+
+/*
+ * Q: What is this SILLYDECRYPT stuff about?
+ * A: When using the ActivCard Linux pkcs11 library (v2.0.1),
+ * the decrypt function fails. By inserting an extra
+ * function call, which serves nothing but to change the
+ * stack, we were able to work around the issue. If the
+ * ActivCard library is fixed in the future, this
+ * definition and related code can be removed.
+ */
+#define SILLYDECRYPT
+
+#include "pkinit_crypto_openssl.h"
+
+/*
+ * Solaris Kerberos:
+ * Changed to a switch statement so gettext() can be used
+ * for internationization.
+ * Use defined constants rather than raw numbers for error codes.
+ */
+static char *
+pkcs11_error_table(short code) {
+ switch (code) {
+ case CKR_OK:
+ return (gettext("ok"));
+ case CKR_CANCEL:
+ return (gettext("cancel"));
+ case CKR_HOST_MEMORY:
+ return (gettext("host memory"));
+ case CKR_SLOT_ID_INVALID:
+ return (gettext("slot id invalid"));
+ case CKR_GENERAL_ERROR:
+ return (gettext("general error"));
+ case CKR_FUNCTION_FAILED:
+ return (gettext("function failed"));
+ case CKR_ARGUMENTS_BAD:
+ return (gettext("arguments bad"));
+ case CKR_NO_EVENT:
+ return (gettext("no event"));
+ case CKR_NEED_TO_CREATE_THREADS:
+ return (gettext("need to create threads"));
+ case CKR_CANT_LOCK:
+ return (gettext("cant lock"));
+ case CKR_ATTRIBUTE_READ_ONLY:
+ return (gettext("attribute read only"));
+ case CKR_ATTRIBUTE_SENSITIVE:
+ return (gettext("attribute sensitive"));
+ case CKR_ATTRIBUTE_TYPE_INVALID:
+ return (gettext("attribute type invalid"));
+ case CKR_ATTRIBUTE_VALUE_INVALID:
+ return (gettext("attribute value invalid"));
+ case CKR_DATA_INVALID:
+ return (gettext("data invalid"));
+ case CKR_DATA_LEN_RANGE:
+ return (gettext("data len range"));
+ case CKR_DEVICE_ERROR:
+ return (gettext("device error"));
+ case CKR_DEVICE_MEMORY:
+ return (gettext("device memory"));
+ case CKR_DEVICE_REMOVED:
+ return (gettext("device removed"));
+ case CKR_ENCRYPTED_DATA_INVALID:
+ return (gettext("encrypted data invalid"));
+ case CKR_ENCRYPTED_DATA_LEN_RANGE:
+ return (gettext("encrypted data len range"));
+ case CKR_FUNCTION_CANCELED:
+ return (gettext("function canceled"));
+ case CKR_FUNCTION_NOT_PARALLEL:
+ return (gettext("function not parallel"));
+ case CKR_FUNCTION_NOT_SUPPORTED:
+ return (gettext("function not supported"));
+ case CKR_KEY_HANDLE_INVALID:
+ return (gettext("key handle invalid"));
+ case CKR_KEY_SIZE_RANGE:
+ return (gettext("key size range"));
+ case CKR_KEY_TYPE_INCONSISTENT:
+ return (gettext("key type inconsistent"));
+ case CKR_KEY_NOT_NEEDED:
+ return (gettext("key not needed"));
+ case CKR_KEY_CHANGED:
+ return (gettext("key changed"));
+ case CKR_KEY_NEEDED:
+ return (gettext("key needed"));
+ case CKR_KEY_INDIGESTIBLE:
+ return (gettext("key indigestible"));
+ case CKR_KEY_FUNCTION_NOT_PERMITTED:
+ return (gettext("key function not permitted"));
+ case CKR_KEY_NOT_WRAPPABLE:
+ return (gettext("key not wrappable"));
+ case CKR_KEY_UNEXTRACTABLE:
+ return (gettext("key unextractable"));
+ case CKR_MECHANISM_INVALID:
+ return (gettext("mechanism invalid"));
+ case CKR_MECHANISM_PARAM_INVALID:
+ return (gettext("mechanism param invalid"));
+ case CKR_OBJECT_HANDLE_INVALID:
+ return (gettext("object handle invalid"));
+ case CKR_OPERATION_ACTIVE:
+ return (gettext("operation active"));
+ case CKR_OPERATION_NOT_INITIALIZED:
+ return (gettext("operation not initialized"));
+ case CKR_PIN_INCORRECT:
+ return (gettext("pin incorrect"));
+ case CKR_PIN_INVALID:
+ return (gettext("pin invalid"));
+ case CKR_PIN_LEN_RANGE:
+ return (gettext("pin len range"));
+ case CKR_PIN_EXPIRED:
+ return (gettext("pin expired"));
+ case CKR_PIN_LOCKED:
+ return (gettext("pin locked"));
+ case CKR_SESSION_CLOSED:
+ return (gettext("session closed"));
+ case CKR_SESSION_COUNT:
+ return (gettext("session count"));
+ case CKR_SESSION_HANDLE_INVALID:
+ return (gettext("session handle invalid"));
+ case CKR_SESSION_PARALLEL_NOT_SUPPORTED:
+ return (gettext("session parallel not supported"));
+ case CKR_SESSION_READ_ONLY:
+ return (gettext("session read only"));
+ case CKR_SESSION_EXISTS:
+ return (gettext("session exists"));
+ case CKR_SESSION_READ_ONLY_EXISTS:
+ return (gettext("session read only exists"));
+ case CKR_SESSION_READ_WRITE_SO_EXISTS:
+ return (gettext("session read write so exists"));
+ case CKR_SIGNATURE_INVALID:
+ return (gettext("signature invalid"));
+ case CKR_SIGNATURE_LEN_RANGE:
+ return (gettext("signature len range"));
+ case CKR_TEMPLATE_INCOMPLETE:
+ return (gettext("template incomplete"));
+ case CKR_TEMPLATE_INCONSISTENT:
+ return (gettext("template inconsistent"));
+ case CKR_TOKEN_NOT_PRESENT:
+ return (gettext("token not present"));
+ case CKR_TOKEN_NOT_RECOGNIZED:
+ return (gettext("token not recognized"));
+ case CKR_TOKEN_WRITE_PROTECTED:
+ return (gettext("token write protected"));
+ case CKR_UNWRAPPING_KEY_HANDLE_INVALID:
+ return (gettext("unwrapping key handle invalid"));
+ case CKR_UNWRAPPING_KEY_SIZE_RANGE:
+ return (gettext("unwrapping key size range"));
+ case CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT:
+ return (gettext("unwrapping key type inconsistent"));
+ case CKR_USER_ALREADY_LOGGED_IN:
+ return (gettext("user already logged in"));
+ case CKR_USER_NOT_LOGGED_IN:
+ return (gettext("user not logged in"));
+ case CKR_USER_PIN_NOT_INITIALIZED:
+ return (gettext("user pin not initialized"));
+ case CKR_USER_TYPE_INVALID:
+ return (gettext("user type invalid"));
+ case CKR_USER_ANOTHER_ALREADY_LOGGED_IN:
+ return (gettext("user another already logged in"));
+ case CKR_USER_TOO_MANY_TYPES:
+ return (gettext("user too many types"));
+ case CKR_WRAPPED_KEY_INVALID:
+ return (gettext("wrapped key invalid"));
+ case CKR_WRAPPED_KEY_LEN_RANGE:
+ return (gettext("wrapped key len range"));
+ case CKR_WRAPPING_KEY_HANDLE_INVALID:
+ return (gettext("wrapping key handle invalid"));
+ case CKR_WRAPPING_KEY_SIZE_RANGE:
+ return (gettext("wrapping key size range"));
+ case CKR_WRAPPING_KEY_TYPE_INCONSISTENT:
+ return (gettext("wrapping key type inconsistent"));
+ case CKR_RANDOM_SEED_NOT_SUPPORTED:
+ return (gettext("random seed not supported"));
+ case CKR_RANDOM_NO_RNG:
+ return (gettext("random no rng"));
+ case CKR_DOMAIN_PARAMS_INVALID:
+ return (gettext("domain params invalid"));
+ case CKR_BUFFER_TOO_SMALL:
+ return (gettext("buffer too small"));
+ case CKR_SAVED_STATE_INVALID:
+ return (gettext("saved state invalid"));
+ case CKR_INFORMATION_SENSITIVE:
+ return (gettext("information sensitive"));
+ case CKR_STATE_UNSAVEABLE:
+ return (gettext("state unsaveable"));
+ case CKR_CRYPTOKI_NOT_INITIALIZED:
+ return (gettext("cryptoki not initialized"));
+ case CKR_CRYPTOKI_ALREADY_INITIALIZED:
+ return (gettext("cryptoki already initialized"));
+ case CKR_MUTEX_BAD:
+ return (gettext("mutex bad"));
+ case CKR_MUTEX_NOT_LOCKED:
+ return (gettext("mutex not locked"));
+ case CKR_FUNCTION_REJECTED:
+ return (gettext("function rejected"));
+ default:
+ return (gettext("unknown error"));
+ }
+}
+
+/* DH parameters */
+unsigned char pkinit_1024_dhprime[128] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+unsigned char pkinit_2048_dhprime[2048/8] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+unsigned char pkinit_4096_dhprime[4096/8] = {
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+ 0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+ 0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+ 0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+ 0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+ 0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+ 0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+ 0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+ 0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+ 0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+ 0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+ 0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+ 0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+ 0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+ 0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+ 0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+ 0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+ 0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+ 0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+ 0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+ 0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+ 0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+ 0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+ 0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+ 0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+ 0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+ 0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+ 0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+ 0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+ 0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
+ 0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
+ 0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+ 0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
+ 0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
+ 0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+ 0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
+ 0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
+ 0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+ 0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
+ 0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
+ 0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+ 0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
+ 0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
+ 0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+ 0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
+ 0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
+ 0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+ 0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
+ 0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
+ 0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+ 0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
+ 0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
+ 0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+ 0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
+ 0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
+ 0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+ 0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
+ 0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
+ 0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+ 0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
+ 0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
+ 0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* Solaris Kerberos: May not be thread safe! */
+static int pkinit_oids_refs = 0;
+
+krb5_error_code
+pkinit_init_plg_crypto(pkinit_plg_crypto_context *cryptoctx) {
+
+ krb5_error_code retval = ENOMEM;
+ pkinit_plg_crypto_context ctx = NULL;
+
+ /* initialize openssl routines */
+ openssl_init();
+
+ ctx = (pkinit_plg_crypto_context)malloc(sizeof(*ctx));
+ if (ctx == NULL)
+ goto out;
+ (void) memset(ctx, 0, sizeof(*ctx));
+
+ pkiDebug("%s: initializing openssl crypto context at %p\n",
+ __FUNCTION__, ctx);
+ retval = pkinit_init_pkinit_oids(ctx);
+ if (retval)
+ goto out;
+
+ retval = pkinit_init_dh_params(ctx);
+ if (retval)
+ goto out;
+
+ *cryptoctx = ctx;
+
+out:
+ if (retval && ctx != NULL)
+ pkinit_fini_plg_crypto(ctx);
+
+ return retval;
+}
+
+void
+pkinit_fini_plg_crypto(pkinit_plg_crypto_context cryptoctx)
+{
+ pkiDebug("%s: freeing context at %p\n", __FUNCTION__, cryptoctx);
+
+ if (cryptoctx == NULL)
+ return;
+ pkinit_fini_pkinit_oids(cryptoctx);
+ pkinit_fini_dh_params(cryptoctx);
+ free(cryptoctx);
+}
+
+krb5_error_code
+pkinit_init_identity_crypto(pkinit_identity_crypto_context *idctx)
+{
+ krb5_error_code retval = ENOMEM;
+ pkinit_identity_crypto_context ctx = NULL;
+
+ ctx = (pkinit_identity_crypto_context)malloc(sizeof(*ctx));
+ if (ctx == NULL)
+ goto out;
+ (void) memset(ctx, 0, sizeof(*ctx));
+
+ retval = pkinit_init_certs(ctx);
+ if (retval)
+ goto out;
+
+ retval = pkinit_init_pkcs11(ctx);
+ if (retval)
+ goto out;
+
+ pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
+ *idctx = ctx;
+
+out:
+ if (retval) {
+ if (ctx)
+ pkinit_fini_identity_crypto(ctx);
+ }
+
+ return retval;
+}
+
+void
+pkinit_fini_identity_crypto(pkinit_identity_crypto_context idctx)
+{
+ if (idctx == NULL)
+ return;
+
+ pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, idctx);
+ pkinit_fini_certs(idctx);
+ pkinit_fini_pkcs11(idctx);
+ free(idctx);
+}
+
+krb5_error_code
+pkinit_init_req_crypto(pkinit_req_crypto_context *cryptoctx)
+{
+
+ pkinit_req_crypto_context ctx = NULL;
+
+ /* Solaris Kerberos */
+ if (cryptoctx == NULL)
+ return EINVAL;
+
+ ctx = (pkinit_req_crypto_context)malloc(sizeof(*ctx));
+ if (ctx == NULL)
+ return ENOMEM;
+ (void) memset(ctx, 0, sizeof(*ctx));
+
+ ctx->dh = NULL;
+ ctx->received_cert = NULL;
+
+ *cryptoctx = ctx;
+
+ pkiDebug("%s: returning ctx at %p\n", __FUNCTION__, ctx);
+
+ return 0;
+}
+
+void
+pkinit_fini_req_crypto(pkinit_req_crypto_context req_cryptoctx)
+{
+ if (req_cryptoctx == NULL)
+ return;
+
+ pkiDebug("%s: freeing ctx at %p\n", __FUNCTION__, req_cryptoctx);
+ if (req_cryptoctx->dh != NULL)
+ DH_free(req_cryptoctx->dh);
+ if (req_cryptoctx->received_cert != NULL)
+ X509_free(req_cryptoctx->received_cert);
+
+ free(req_cryptoctx);
+}
+
+static krb5_error_code
+pkinit_init_pkinit_oids(pkinit_plg_crypto_context ctx)
+{
+ krb5_error_code retval = ENOMEM;
+ int nid = 0;
+
+ /*
+ * If OpenSSL already knows about the OID, use the
+ * existing definition. Otherwise, create an OID object.
+ */
+ #define CREATE_OBJ_IF_NEEDED(oid, vn, sn, ln) \
+ nid = OBJ_txt2nid(oid); \
+ if (nid == NID_undef) { \
+ nid = OBJ_create(oid, sn, ln); \
+ if (nid == NID_undef) { \
+ pkiDebug("Error creating oid object for '%s'\n", oid); \
+ goto out; \
+ } \
+ } \
+ ctx->vn = OBJ_nid2obj(nid);
+
+ CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.2", id_pkinit_san,
+ "id-pkinit-san", "KRB5PrincipalName");
+
+ CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.1", id_pkinit_authData,
+ "id-pkinit-authdata", "PKINIT signedAuthPack");
+
+ CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.2", id_pkinit_DHKeyData,
+ "id-pkinit-DHKeyData", "PKINIT dhSignedData");
+
+ CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.3", id_pkinit_rkeyData,
+ "id-pkinit-rkeyData", "PKINIT encKeyPack");
+
+ CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.4", id_pkinit_KPClientAuth,
+ "id-pkinit-KPClientAuth", "PKINIT Client EKU");
+
+ CREATE_OBJ_IF_NEEDED("1.3.6.1.5.2.3.5", id_pkinit_KPKdc,
+ "id-pkinit-KPKdc", "KDC EKU");
+
+#if 0
+ CREATE_OBJ_IF_NEEDED("1.2.840.113549.1.7.1", id_pkinit_authData9,
+ "id-pkcs7-data", "PKCS7 data");
+#else
+ /* See note in pkinit_pkcs7type2oid() */
+ ctx->id_pkinit_authData9 = NULL;
+#endif
+
+ CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.2", id_ms_kp_sc_logon,
+ "id-ms-kp-sc-logon EKU", "Microsoft SmartCard Login EKU");
+
+ CREATE_OBJ_IF_NEEDED("1.3.6.1.4.1.311.20.2.3", id_ms_san_upn,
+ "id-ms-san-upn", "Microsoft Universal Principal Name");
+
+ CREATE_OBJ_IF_NEEDED("1.3.6.1.5.5.7.3.1", id_kp_serverAuth,
+ "id-kp-serverAuth EKU", "Server Authentication EKU");
+
+ /* Success */
+ retval = 0;
+
+ /* Solaris Kerberos: May not be thread safe! */
+ pkinit_oids_refs++;
+
+out:
+ return retval;
+}
+
+static krb5_error_code
+get_cert(char *filename, X509 **retcert)
+{
+ X509 *cert = NULL;
+ BIO *tmp = NULL;
+ int code;
+ krb5_error_code retval;
+
+ if (filename == NULL || retcert == NULL)
+ return EINVAL;
+
+ *retcert = NULL;
+
+ tmp = BIO_new(BIO_s_file());
+ if (tmp == NULL)
+ return ENOMEM;
+
+ code = BIO_read_filename(tmp, filename);
+ if (code == 0) {
+ retval = errno;
+ goto cleanup;
+ }
+
+ cert = (X509 *) PEM_read_bio_X509(tmp, NULL, NULL, NULL);
+ if (cert == NULL) {
+ retval = EIO;
+ pkiDebug("failed to read certificate from %s\n", filename);
+ goto cleanup;
+ }
+ *retcert = cert;
+ retval = 0;
+cleanup:
+ if (tmp != NULL)
+ BIO_free(tmp);
+ return retval;
+}
+
+static krb5_error_code
+get_key(char *filename, EVP_PKEY **retkey)
+{
+ EVP_PKEY *pkey = NULL;
+ BIO *tmp = NULL;
+ int code;
+ krb5_error_code retval;
+
+ if (filename == NULL || retkey == NULL)
+ return EINVAL;
+
+ tmp = BIO_new(BIO_s_file());
+ if (tmp == NULL)
+ return ENOMEM;
+
+ code = BIO_read_filename(tmp, filename);
+ if (code == 0) {
+ retval = errno;
+ goto cleanup;
+ }
+ pkey = (EVP_PKEY *) PEM_read_bio_PrivateKey(tmp, NULL, NULL, NULL);
+ if (pkey == NULL) {
+ retval = EIO;
+ pkiDebug("failed to read private key from %s\n", filename);
+ goto cleanup;
+ }
+ *retkey = pkey;
+ retval = 0;
+cleanup:
+ if (tmp != NULL)
+ BIO_free(tmp);
+ return retval;
+}
+
+static void
+pkinit_fini_pkinit_oids(pkinit_plg_crypto_context ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ /* Only call OBJ_cleanup once! */
+ if (--pkinit_oids_refs == 0) /* Solaris Kerberos: May not be thread safe! */
+ OBJ_cleanup();
+}
+
+static krb5_error_code
+pkinit_init_dh_params(pkinit_plg_crypto_context plgctx)
+{
+ krb5_error_code retval = ENOMEM;
+
+ plgctx->dh_1024 = DH_new();
+ if (plgctx->dh_1024 == NULL)
+ goto cleanup;
+ plgctx->dh_1024->p = BN_bin2bn(pkinit_1024_dhprime,
+ sizeof(pkinit_1024_dhprime), NULL);
+ if ((plgctx->dh_1024->g = BN_new()) == NULL ||
+ (plgctx->dh_1024->q = BN_new()) == NULL)
+ goto cleanup;
+ BN_set_word(plgctx->dh_1024->g, DH_GENERATOR_2);
+ BN_rshift1(plgctx->dh_1024->q, plgctx->dh_1024->p);
+
+ plgctx->dh_2048 = DH_new();
+ if (plgctx->dh_2048 == NULL)
+ goto cleanup;
+ plgctx->dh_2048->p = BN_bin2bn(pkinit_2048_dhprime,
+ sizeof(pkinit_2048_dhprime), NULL);
+ if ((plgctx->dh_2048->g = BN_new()) == NULL ||
+ (plgctx->dh_2048->q = BN_new()) == NULL)
+ goto cleanup;
+ BN_set_word(plgctx->dh_2048->g, DH_GENERATOR_2);
+ BN_rshift1(plgctx->dh_2048->q, plgctx->dh_2048->p);
+
+ plgctx->dh_4096 = DH_new();
+ if (plgctx->dh_4096 == NULL)
+ goto cleanup;
+ plgctx->dh_4096->p = BN_bin2bn(pkinit_4096_dhprime,
+ sizeof(pkinit_4096_dhprime), NULL);
+ if ((plgctx->dh_4096->g = BN_new()) == NULL ||
+ (plgctx->dh_4096->q = BN_new()) == NULL)
+ goto cleanup;
+ BN_set_word(plgctx->dh_4096->g, DH_GENERATOR_2);
+ BN_rshift1(plgctx->dh_4096->q, plgctx->dh_4096->p);
+
+ retval = 0;
+
+cleanup:
+ if (retval)
+ pkinit_fini_dh_params(plgctx);
+
+ return retval;
+}
+
+static void
+pkinit_fini_dh_params(pkinit_plg_crypto_context plgctx)
+{
+ if (plgctx->dh_1024 != NULL)
+ DH_free(plgctx->dh_1024);
+ if (plgctx->dh_2048 != NULL)
+ DH_free(plgctx->dh_2048);
+ if (plgctx->dh_4096 != NULL)
+ DH_free(plgctx->dh_4096);
+
+ plgctx->dh_1024 = plgctx->dh_2048 = plgctx->dh_4096 = NULL;
+}
+
+static krb5_error_code
+pkinit_init_certs(pkinit_identity_crypto_context ctx)
+{
+ /* Solaris Kerberos */
+ int i;
+
+ for (i = 0; i < MAX_CREDS_ALLOWED; i++)
+ ctx->creds[i] = NULL;
+ ctx->my_certs = NULL;
+ ctx->cert_index = 0;
+ ctx->my_key = NULL;
+ ctx->trustedCAs = NULL;
+ ctx->intermediateCAs = NULL;
+ ctx->revoked = NULL;
+
+ return 0;
+}
+
+static void
+pkinit_fini_certs(pkinit_identity_crypto_context ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ if (ctx->my_certs != NULL)
+ sk_X509_pop_free(ctx->my_certs, X509_free);
+
+ if (ctx->my_key != NULL)
+ EVP_PKEY_free(ctx->my_key);
+
+ if (ctx->trustedCAs != NULL)
+ sk_X509_pop_free(ctx->trustedCAs, X509_free);
+
+ if (ctx->intermediateCAs != NULL)
+ sk_X509_pop_free(ctx->intermediateCAs, X509_free);
+
+ if (ctx->revoked != NULL)
+ sk_X509_CRL_pop_free(ctx->revoked, X509_CRL_free);
+}
+
+static krb5_error_code
+pkinit_init_pkcs11(pkinit_identity_crypto_context ctx)
+{
+ /* Solaris Kerberos */
+
+#ifndef WITHOUT_PKCS11
+ ctx->p11_module_name = strdup(PKCS11_MODNAME);
+ if (ctx->p11_module_name == NULL)
+ return ENOMEM;
+ ctx->p11_module = NULL;
+ ctx->slotid = PK_NOSLOT;
+ ctx->token_label = NULL;
+ ctx->cert_label = NULL;
+ ctx->session = CK_INVALID_HANDLE;
+ ctx->p11 = NULL;
+#endif
+ ctx->pkcs11_method = 0;
+
+ return 0;
+}
+
+static void
+pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx)
+{
+#ifndef WITHOUT_PKCS11
+ if (ctx == NULL)
+ return;
+
+ if (ctx->p11 != NULL) {
+ if (ctx->session) {
+ ctx->p11->C_CloseSession(ctx->session);
+ ctx->session = CK_INVALID_HANDLE;
+ }
+ /*
+ * Solaris Kerberos:
+ * Only call C_Finalize if the process was not already using pkcs11.
+ */
+ if (ctx->finalize_pkcs11 == TRUE)
+ ctx->p11->C_Finalize(NULL_PTR);
+
+ ctx->p11 = NULL;
+ }
+ if (ctx->p11_module != NULL) {
+ pkinit_C_UnloadModule(ctx->p11_module);
+ ctx->p11_module = NULL;
+ }
+ if (ctx->p11_module_name != NULL)
+ free(ctx->p11_module_name);
+ if (ctx->token_label != NULL)
+ free(ctx->token_label);
+ if (ctx->cert_id != NULL)
+ free(ctx->cert_id);
+ if (ctx->cert_label != NULL)
+ free(ctx->cert_label);
+#endif
+}
+
+krb5_error_code
+pkinit_identity_set_prompter(pkinit_identity_crypto_context id_cryptoctx,
+ krb5_prompter_fct prompter,
+ void *prompter_data)
+{
+ id_cryptoctx->prompter = prompter;
+ id_cryptoctx->prompter_data = prompter_data;
+
+ return 0;
+}
+
+/* ARGSUSED */
+krb5_error_code
+cms_signeddata_create(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ int cms_msg_type,
+ int include_certchain,
+ unsigned char *data,
+ unsigned int data_len,
+ unsigned char **signed_data,
+ unsigned int *signed_data_len)
+{
+ /* Solaris Kerberos */
+ krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+ PKCS7 *p7 = NULL, *inner_p7 = NULL;
+ PKCS7_SIGNED *p7s = NULL;
+ PKCS7_SIGNER_INFO *p7si = NULL;
+ unsigned char *p;
+ ASN1_TYPE *pkinit_data = NULL;
+ STACK_OF(X509) * cert_stack = NULL;
+ ASN1_OCTET_STRING *digest_attr = NULL;
+ EVP_MD_CTX ctx, ctx2;
+ const EVP_MD *md_tmp = NULL;
+ unsigned char md_data[EVP_MAX_MD_SIZE], md_data2[EVP_MAX_MD_SIZE];
+ unsigned char *digestInfo_buf = NULL, *abuf = NULL;
+ unsigned int md_len, md_len2, alen, digestInfo_len;
+ STACK_OF(X509_ATTRIBUTE) * sk;
+ unsigned char *sig = NULL;
+ unsigned int sig_len = 0;
+ X509_ALGOR *alg = NULL;
+ ASN1_OCTET_STRING *digest = NULL;
+ unsigned int alg_len = 0, digest_len = 0;
+ unsigned char *y = NULL, *alg_buf = NULL, *digest_buf = NULL;
+ X509 *cert = NULL;
+ ASN1_OBJECT *oid = NULL;
+
+ /* Solaris Kerberos */
+ if (signed_data == NULL)
+ return EINVAL;
+
+ if (signed_data_len == NULL)
+ return EINVAL;
+
+ /* start creating PKCS7 data */
+ if ((p7 = PKCS7_new()) == NULL)
+ goto cleanup;
+ p7->type = OBJ_nid2obj(NID_pkcs7_signed);
+
+ if ((p7s = PKCS7_SIGNED_new()) == NULL)
+ goto cleanup;
+ p7->d.sign = p7s;
+ if (!ASN1_INTEGER_set(p7s->version, 3))
+ goto cleanup;
+
+ /* create a cert chain that has at least the signer's certificate */
+ if ((cert_stack = sk_X509_new_null()) == NULL)
+ goto cleanup;
+
+ cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
+ if (!include_certchain) {
+ pkiDebug("only including signer's certificate\n");
+ sk_X509_push(cert_stack, X509_dup(cert));
+ } else {
+ /* create a cert chain */
+ X509_STORE *certstore = NULL;
+ X509_STORE_CTX certctx;
+ STACK_OF(X509) *certstack = NULL;
+ char buf[DN_BUF_LEN];
+ int i = 0, size = 0;
+
+ if ((certstore = X509_STORE_new()) == NULL)
+ goto cleanup;
+ pkiDebug("building certificate chain\n");
+ X509_STORE_set_verify_cb_func(certstore, openssl_callback);
+ X509_STORE_CTX_init(&certctx, certstore, cert,
+ id_cryptoctx->intermediateCAs);
+ X509_STORE_CTX_trusted_stack(&certctx, id_cryptoctx->trustedCAs);
+ if (!X509_verify_cert(&certctx)) {
+ pkiDebug("failed to create a certificate chain: %s\n",
+ X509_verify_cert_error_string(X509_STORE_CTX_get_error(&certctx)));
+ if (!sk_X509_num(id_cryptoctx->trustedCAs))
+ pkiDebug("No trusted CAs found. Check your X509_anchors\n");
+ goto cleanup;
+ }
+ certstack = X509_STORE_CTX_get1_chain(&certctx);
+ size = sk_X509_num(certstack);
+ pkiDebug("size of certificate chain = %d\n", size);
+ for(i = 0; i < size - 1; i++) {
+ X509 *x = sk_X509_value(certstack, i);
+ X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
+ pkiDebug("cert #%d: %s\n", i, buf);
+ sk_X509_push(cert_stack, X509_dup(x));
+ }
+ X509_STORE_CTX_cleanup(&certctx);
+ X509_STORE_free(certstore);
+ sk_X509_pop_free(certstack, X509_free);
+ }
+ p7s->cert = cert_stack;
+
+ /* fill-in PKCS7_SIGNER_INFO */
+ if ((p7si = PKCS7_SIGNER_INFO_new()) == NULL)
+ goto cleanup;
+ if (!ASN1_INTEGER_set(p7si->version, 1))
+ goto cleanup;
+ if (!X509_NAME_set(&p7si->issuer_and_serial->issuer,
+ X509_get_issuer_name(cert)))
+ goto cleanup;
+ /* because ASN1_INTEGER_set is used to set a 'long' we will do
+ * things the ugly way. */
+ M_ASN1_INTEGER_free(p7si->issuer_and_serial->serial);
+ if (!(p7si->issuer_and_serial->serial =
+ M_ASN1_INTEGER_dup(X509_get_serialNumber(cert))))
+ goto cleanup;
+
+ /* will not fill-out EVP_PKEY because it's on the smartcard */
+
+ /* Set digest algs */
+ p7si->digest_alg->algorithm = OBJ_nid2obj(NID_sha1);
+
+ if (p7si->digest_alg->parameter != NULL)
+ ASN1_TYPE_free(p7si->digest_alg->parameter);
+ if ((p7si->digest_alg->parameter = ASN1_TYPE_new()) == NULL)
+ goto cleanup;
+ p7si->digest_alg->parameter->type = V_ASN1_NULL;
+
+ /* Set sig algs */
+ if (p7si->digest_enc_alg->parameter != NULL)
+ ASN1_TYPE_free(p7si->digest_enc_alg->parameter);
+ p7si->digest_enc_alg->algorithm = OBJ_nid2obj(NID_sha1WithRSAEncryption);
+ if (!(p7si->digest_enc_alg->parameter = ASN1_TYPE_new()))
+ goto cleanup;
+ p7si->digest_enc_alg->parameter->type = V_ASN1_NULL;
+
+ /* pick the correct oid for the eContentInfo */
+ oid = pkinit_pkcs7type2oid(plg_cryptoctx, cms_msg_type);
+ if (oid == NULL)
+ goto cleanup;
+
+ if (cms_msg_type == CMS_SIGN_DRAFT9) {
+ /* don't include signed attributes for pa-type 15 request */
+ abuf = data;
+ alen = data_len;
+ } else {
+ /* add signed attributes */
+ /* compute sha1 digest over the EncapsulatedContentInfo */
+ EVP_MD_CTX_init(&ctx);
+ EVP_DigestInit_ex(&ctx, EVP_sha1(), NULL);
+ EVP_DigestUpdate(&ctx, data, data_len);
+ md_tmp = EVP_MD_CTX_md(&ctx);
+ EVP_DigestFinal_ex(&ctx, md_data, &md_len);
+
+ /* create a message digest attr */
+ digest_attr = ASN1_OCTET_STRING_new();
+ ASN1_OCTET_STRING_set(digest_attr, md_data, (int)md_len);
+ PKCS7_add_signed_attribute(p7si, NID_pkcs9_messageDigest,
+ V_ASN1_OCTET_STRING, (char *) digest_attr);
+
+ /* create a content-type attr */
+ PKCS7_add_signed_attribute(p7si, NID_pkcs9_contentType,
+ V_ASN1_OBJECT, oid);
+
+ /* create the signature over signed attributes. get DER encoded value */
+ /* This is the place where smartcard signature needs to be calculated */
+ sk = p7si->auth_attr;
+ alen = ASN1_item_i2d((ASN1_VALUE *) sk, &abuf,
+ ASN1_ITEM_rptr(PKCS7_ATTR_SIGN));
+ if (abuf == NULL)
+ goto cleanup2;
+ }
+
+#ifndef WITHOUT_PKCS11
+ /* Some tokens can only do RSAEncryption without sha1 hash */
+ /* to compute sha1WithRSAEncryption, encode the algorithm ID for the hash
+ * function and the hash value into an ASN.1 value of type DigestInfo
+ * DigestInfo::=SEQUENCE {
+ * digestAlgorithm AlgorithmIdentifier,
+ * digest OCTET STRING }
+ */
+ if (id_cryptoctx->pkcs11_method == 1 &&
+ id_cryptoctx->mech == CKM_RSA_PKCS) {
+ pkiDebug("mech = CKM_RSA_PKCS\n");
+ EVP_MD_CTX_init(&ctx2);
+ /* if this is not draft9 request, include digest signed attribute */
+ if (cms_msg_type != CMS_SIGN_DRAFT9)
+ EVP_DigestInit_ex(&ctx2, md_tmp, NULL);
+ else
+ EVP_DigestInit_ex(&ctx2, EVP_sha1(), NULL);
+ EVP_DigestUpdate(&ctx2, abuf, alen);
+ EVP_DigestFinal_ex(&ctx2, md_data2, &md_len2);
+
+ alg = X509_ALGOR_new();
+ if (alg == NULL)
+ goto cleanup2;
+ alg->algorithm = OBJ_nid2obj(NID_sha1);
+ alg->parameter = NULL;
+ alg_len = i2d_X509_ALGOR(alg, NULL);
+ alg_buf = (unsigned char *)malloc(alg_len);
+ if (alg_buf == NULL)
+ goto cleanup2;
+
+ digest = ASN1_OCTET_STRING_new();
+ if (digest == NULL)
+ goto cleanup2;
+ ASN1_OCTET_STRING_set(digest, md_data2, (int)md_len2);
+ digest_len = i2d_ASN1_OCTET_STRING(digest, NULL);
+ digest_buf = (unsigned char *)malloc(digest_len);
+ if (digest_buf == NULL)
+ goto cleanup2;
+
+ digestInfo_len = ASN1_object_size(1, (int)(alg_len + digest_len),
+ V_ASN1_SEQUENCE);
+ y = digestInfo_buf = (unsigned char *)malloc(digestInfo_len);
+ if (digestInfo_buf == NULL)
+ goto cleanup2;
+ ASN1_put_object(&y, 1, (int)(alg_len + digest_len), V_ASN1_SEQUENCE,
+ V_ASN1_UNIVERSAL);
+ i2d_X509_ALGOR(alg, &y);
+ i2d_ASN1_OCTET_STRING(digest, &y);
+#ifdef DEBUG_SIG
+ pkiDebug("signing buffer\n");
+ print_buffer(digestInfo_buf, digestInfo_len);
+ print_buffer_bin(digestInfo_buf, digestInfo_len, "/tmp/pkcs7_tosign");
+#endif
+ retval = pkinit_sign_data(context, id_cryptoctx, digestInfo_buf,
+ digestInfo_len, &sig, &sig_len);
+ } else
+#endif
+ {
+ pkiDebug("mech = %s\n",
+ id_cryptoctx->pkcs11_method == 1 ? "CKM_SHA1_RSA_PKCS" : "FS");
+ retval = pkinit_sign_data(context, id_cryptoctx, abuf, alen,
+ &sig, &sig_len);
+ }
+#ifdef DEBUG_SIG
+ print_buffer(sig, sig_len);
+#endif
+ if (cms_msg_type != CMS_SIGN_DRAFT9)
+ free(abuf);
+ if (retval)
+ goto cleanup2;
+
+ /* Add signature */
+ if (!ASN1_STRING_set(p7si->enc_digest, (unsigned char *) sig,
+ (int)sig_len)) {
+ unsigned long err = ERR_peek_error();
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, retval, "%s\n",
+ ERR_error_string(err, NULL));
+ pkiDebug("failed to add a signed digest attribute\n");
+ goto cleanup2;
+ }
+ /* adder signer_info to pkcs7 signed */
+ if (!PKCS7_add_signer(p7, p7si))
+ goto cleanup2;
+
+ /* start on adding data to the pkcs7 signed */
+ if ((inner_p7 = PKCS7_new()) == NULL)
+ goto cleanup2;
+ if ((pkinit_data = ASN1_TYPE_new()) == NULL)
+ goto cleanup2;
+ pkinit_data->type = V_ASN1_OCTET_STRING;
+ if ((pkinit_data->value.octet_string = ASN1_OCTET_STRING_new()) == NULL)
+ goto cleanup2;
+ if (!ASN1_OCTET_STRING_set(pkinit_data->value.octet_string, data,
+ (int)data_len)) {
+ unsigned long err = ERR_peek_error();
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, retval, "%s\n",
+ ERR_error_string(err, NULL));
+ pkiDebug("failed to add pkcs7 data\n");
+ goto cleanup2;
+ }
+
+ if (!PKCS7_set0_type_other(inner_p7, OBJ_obj2nid(oid), pkinit_data))
+ goto cleanup2;
+
+ if (p7s->contents != NULL)
+ PKCS7_free(p7s->contents);
+ p7s->contents = inner_p7;
+
+ *signed_data_len = i2d_PKCS7(p7, NULL);
+ if (!(*signed_data_len)) {
+ unsigned long err = ERR_peek_error();
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, retval, "%s\n",
+ ERR_error_string(err, NULL));
+ pkiDebug("failed to der encode pkcs7\n");
+ goto cleanup2;
+ }
+ if ((p = *signed_data =
+ (unsigned char *) malloc((size_t)*signed_data_len)) == NULL)
+ goto cleanup2;
+
+ /* DER encode PKCS7 data */
+ retval = i2d_PKCS7(p7, &p);
+ if (!retval) {
+ unsigned long err = ERR_peek_error();
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, retval, "%s\n",
+ ERR_error_string(err, NULL));
+ pkiDebug("failed to der encode pkcs7\n");
+ goto cleanup2;
+ }
+ retval = 0;
+
+#ifdef DEBUG_ASN1
+ if (cms_msg_type == CMS_SIGN_CLIENT) {
+ print_buffer_bin(*signed_data, *signed_data_len,
+ "/tmp/client_pkcs7_signeddata");
+ } else {
+ if (cms_msg_type == CMS_SIGN_SERVER) {
+ print_buffer_bin(*signed_data, *signed_data_len,
+ "/tmp/kdc_pkcs7_signeddata");
+ } else {
+ print_buffer_bin(*signed_data, *signed_data_len,
+ "/tmp/draft9_pkcs7_signeddata");
+ }
+ }
+#endif
+
+ cleanup2:
+ if (cms_msg_type != CMS_SIGN_DRAFT9)
+ EVP_MD_CTX_cleanup(&ctx);
+#ifndef WITHOUT_PKCS11
+ if (id_cryptoctx->pkcs11_method == 1 &&
+ id_cryptoctx->mech == CKM_RSA_PKCS) {
+ EVP_MD_CTX_cleanup(&ctx2);
+ if (digest_buf != NULL)
+ free(digest_buf);
+ if (digestInfo_buf != NULL)
+ free(digestInfo_buf);
+ if (alg_buf != NULL)
+ free(alg_buf);
+ if (digest != NULL)
+ ASN1_OCTET_STRING_free(digest);
+ }
+#endif
+ if (alg != NULL)
+ X509_ALGOR_free(alg);
+ cleanup:
+ if (p7 != NULL)
+ PKCS7_free(p7);
+ if (sig != NULL)
+ free(sig);
+
+ return retval;
+}
+
+krb5_error_code
+cms_signeddata_verify(krb5_context context,
+ pkinit_plg_crypto_context plgctx,
+ pkinit_req_crypto_context reqctx,
+ pkinit_identity_crypto_context idctx,
+ int cms_msg_type,
+ int require_crl_checking,
+ unsigned char *signed_data,
+ unsigned int signed_data_len,
+ unsigned char **data,
+ unsigned int *data_len,
+ unsigned char **authz_data,
+ unsigned int *authz_data_len)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ PKCS7 *p7 = NULL;
+ BIO *out = NULL;
+ int flags = PKCS7_NOVERIFY, i = 0;
+ unsigned int vflags = 0, size = 0;
+ const unsigned char *p = signed_data;
+ STACK_OF(PKCS7_SIGNER_INFO) *si_sk = NULL;
+ PKCS7_SIGNER_INFO *si = NULL;
+ X509 *x = NULL;
+ X509_STORE *store = NULL;
+ X509_STORE_CTX cert_ctx;
+ STACK_OF(X509) *intermediateCAs = NULL;
+ STACK_OF(X509_CRL) *revoked = NULL;
+ STACK_OF(X509) *verified_chain = NULL;
+ ASN1_OBJECT *oid = NULL;
+ krb5_external_principal_identifier **krb5_verified_chain = NULL;
+ krb5_data *authz = NULL;
+ char buf[DN_BUF_LEN];
+
+#ifdef DEBUG_ASN1
+ print_buffer_bin(signed_data, signed_data_len,
+ "/tmp/client_received_pkcs7_signeddata");
+#endif
+
+ /* Do this early enough to create the shadow OID for pkcs7-data if needed */
+ oid = pkinit_pkcs7type2oid(plgctx, cms_msg_type);
+ if (oid == NULL)
+ goto cleanup;
+
+ /* decode received PKCS7 message */
+ if ((p7 = d2i_PKCS7(NULL, &p, (int)signed_data_len)) == NULL) {
+ unsigned long err = ERR_peek_error();
+ krb5_set_error_message(context, retval, "%s\n",
+ ERR_error_string(err, NULL));
+ pkiDebug("%s: failed to decode message: %s\n",
+ __FUNCTION__, ERR_error_string(err, NULL));
+ goto cleanup;
+ }
+
+ /* verify that the received message is PKCS7 SignedData message */
+ if (OBJ_obj2nid(p7->type) != NID_pkcs7_signed) {
+ pkiDebug("Expected id-signedData PKCS7 msg (received type = %d)\n",
+ OBJ_obj2nid(p7->type));
+ krb5_set_error_message(context, retval, "wrong oid\n");
+ goto cleanup;
+ }
+
+ /* setup to verify X509 certificate used to sign PKCS7 message */
+ if (!(store = X509_STORE_new()))
+ goto cleanup;
+
+ /* check if we are inforcing CRL checking */
+ vflags = X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL;
+ if (require_crl_checking)
+ X509_STORE_set_verify_cb_func(store, openssl_callback);
+ else
+ X509_STORE_set_verify_cb_func(store, openssl_callback_ignore_crls);
+ X509_STORE_set_flags(store, vflags);
+
+ /* get the signer's information from the PKCS7 message */
+ if ((si_sk = PKCS7_get_signer_info(p7)) == NULL)
+ goto cleanup;
+ if ((si = sk_PKCS7_SIGNER_INFO_value(si_sk, 0)) == NULL)
+ goto cleanup;
+ if ((x = PKCS7_cert_from_signer_info(p7, si)) == NULL)
+ goto cleanup;
+
+ /* create available CRL information (get local CRLs and include CRLs
+ * received in the PKCS7 message
+ */
+ if (idctx->revoked == NULL)
+ revoked = p7->d.sign->crl;
+ else if (p7->d.sign->crl == NULL)
+ revoked = idctx->revoked;
+ else {
+ size = sk_X509_CRL_num(idctx->revoked);
+ revoked = sk_X509_CRL_new_null();
+ for (i = 0; i < size; i++)
+ sk_X509_CRL_push(revoked, sk_X509_CRL_value(idctx->revoked, i));
+ size = sk_X509_num(p7->d.sign->crl);
+ for (i = 0; i < size; i++)
+ sk_X509_CRL_push(revoked, sk_X509_CRL_value(p7->d.sign->crl, i));
+ }
+
+ /* create available intermediate CAs chains (get local intermediateCAs and
+ * include the CA chain received in the PKCS7 message
+ */
+ if (idctx->intermediateCAs == NULL)
+ intermediateCAs = p7->d.sign->cert;
+ else if (p7->d.sign->cert == NULL)
+ intermediateCAs = idctx->intermediateCAs;
+ else {
+ size = sk_X509_num(idctx->intermediateCAs);
+ intermediateCAs = sk_X509_new_null();
+ for (i = 0; i < size; i++) {
+ sk_X509_push(intermediateCAs,
+ sk_X509_value(idctx->intermediateCAs, i));
+ }
+ size = sk_X509_num(p7->d.sign->cert);
+ for (i = 0; i < size; i++) {
+ sk_X509_push(intermediateCAs, sk_X509_value(p7->d.sign->cert, i));
+ }
+ }
+
+ /* initialize x509 context with the received certificate and
+ * trusted and intermediate CA chains and CRLs
+ */
+ if (!X509_STORE_CTX_init(&cert_ctx, store, x, intermediateCAs))
+ goto cleanup;
+
+ X509_STORE_CTX_set0_crls(&cert_ctx, revoked);
+
+ /* add trusted CAs certificates for cert verification */
+ if (idctx->trustedCAs != NULL)
+ X509_STORE_CTX_trusted_stack(&cert_ctx, idctx->trustedCAs);
+ else {
+ pkiDebug("unable to find any trusted CAs\n");
+ goto cleanup;
+ }
+#ifdef DEBUG_CERTCHAIN
+ if (intermediateCAs != NULL) {
+ size = sk_X509_num(intermediateCAs);
+ pkiDebug("untrusted cert chain of size %d\n", size);
+ for (i = 0; i < size; i++) {
+ X509_NAME_oneline(X509_get_subject_name(
+ sk_X509_value(intermediateCAs, i)), buf, sizeof(buf));
+ pkiDebug("cert #%d: %s\n", i, buf);
+ }
+ }
+ if (idctx->trustedCAs != NULL) {
+ size = sk_X509_num(idctx->trustedCAs);
+ pkiDebug("trusted cert chain of size %d\n", size);
+ for (i = 0; i < size; i++) {
+ X509_NAME_oneline(X509_get_subject_name(
+ sk_X509_value(idctx->trustedCAs, i)), buf, sizeof(buf));
+ pkiDebug("cert #%d: %s\n", i, buf);
+ }
+ }
+ if (revoked != NULL) {
+ size = sk_X509_CRL_num(revoked);
+ pkiDebug("CRL chain of size %d\n", size);
+ for (i = 0; i < size; i++) {
+ X509_CRL *crl = sk_X509_CRL_value(revoked, i);
+ X509_NAME_oneline(X509_CRL_get_issuer(crl), buf, sizeof(buf));
+ pkiDebug("crls by CA #%d: %s\n", i , buf);
+ }
+ }
+#endif
+
+ i = X509_verify_cert(&cert_ctx);
+ if (i <= 0) {
+ int j = X509_STORE_CTX_get_error(&cert_ctx);
+
+ reqctx->received_cert = X509_dup(cert_ctx.current_cert);
+ switch(j) {
+ case X509_V_ERR_CERT_REVOKED:
+ retval = KRB5KDC_ERR_REVOKED_CERTIFICATE;
+ break;
+ case X509_V_ERR_UNABLE_TO_GET_CRL:
+ retval = KRB5KDC_ERR_REVOCATION_STATUS_UNKNOWN;
+ break;
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
+ case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+ retval = KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE;
+ break;
+ default:
+ retval = KRB5KDC_ERR_INVALID_CERTIFICATE;
+ }
+ X509_NAME_oneline(X509_get_subject_name(
+ reqctx->received_cert), buf, sizeof(buf));
+ pkiDebug("problem with cert DN = %s (error=%d) %s\n", buf, j,
+ X509_verify_cert_error_string(j));
+ krb5_set_error_message(context, retval, "%s\n",
+ X509_verify_cert_error_string(j));
+#ifdef DEBUG_CERTCHAIN
+ size = sk_X509_num(p7->d.sign->cert);
+ pkiDebug("received cert chain of size %d\n", size);
+ for (j = 0; j < size; j++) {
+ X509 *tmp_cert = sk_X509_value(p7->d.sign->cert, j);
+ X509_NAME_oneline(X509_get_subject_name(tmp_cert), buf, sizeof(buf));
+ pkiDebug("cert #%d: %s\n", j, buf);
+ }
+#endif
+ } else {
+ /* retrieve verified certificate chain */
+ if (cms_msg_type == CMS_SIGN_CLIENT || cms_msg_type == CMS_SIGN_DRAFT9)
+ verified_chain = X509_STORE_CTX_get1_chain(&cert_ctx);
+ }
+ X509_STORE_CTX_cleanup(&cert_ctx);
+ if (i <= 0)
+ goto cleanup;
+
+ out = BIO_new(BIO_s_mem());
+ if (cms_msg_type == CMS_SIGN_DRAFT9)
+ flags |= PKCS7_NOATTR;
+ if (PKCS7_verify(p7, NULL, store, NULL, out, flags)) {
+ int valid_oid = 0;
+
+ if (!OBJ_cmp(p7->d.sign->contents->type, oid))
+ valid_oid = 1;
+ else if (cms_msg_type == CMS_SIGN_DRAFT9) {
+ /*
+ * Various implementations of the pa-type 15 request use
+ * different OIDS. We check that the returned object
+ * has any of the acceptable OIDs
+ */
+ ASN1_OBJECT *client_oid = NULL, *server_oid = NULL, *rsa_oid = NULL;
+ client_oid = pkinit_pkcs7type2oid(plgctx, CMS_SIGN_CLIENT);
+ server_oid = pkinit_pkcs7type2oid(plgctx, CMS_SIGN_SERVER);
+ rsa_oid = pkinit_pkcs7type2oid(plgctx, CMS_ENVEL_SERVER);
+ if (!OBJ_cmp(p7->d.sign->contents->type, client_oid) ||
+ !OBJ_cmp(p7->d.sign->contents->type, server_oid) ||
+ !OBJ_cmp(p7->d.sign->contents->type, rsa_oid))
+ valid_oid = 1;
+ }
+
+ if (valid_oid)
+ pkiDebug("PKCS7 Verification successful\n");
+ else {
+ pkiDebug("wrong oid in eContentType\n");
+ print_buffer(p7->d.sign->contents->type->data,
+ (unsigned int)p7->d.sign->contents->type->length);
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ krb5_set_error_message(context, retval, "wrong oid\n");
+ goto cleanup;
+ }
+ }
+ else {
+ unsigned long err = ERR_peek_error();
+ switch(ERR_GET_REASON(err)) {
+ case PKCS7_R_DIGEST_FAILURE:
+ retval = KRB5KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED;
+ break;
+ case PKCS7_R_SIGNATURE_FAILURE:
+ default:
+ retval = KRB5KDC_ERR_INVALID_SIG;
+ }
+ pkiDebug("PKCS7 Verification failure\n");
+ krb5_set_error_message(context, retval, "%s\n",
+ ERR_error_string(err, NULL));
+ goto cleanup;
+ }
+
+ /* transfer the data from PKCS7 message into return buffer */
+ for (size = 0;;) {
+ if ((*data = realloc(*data, size + 1024 * 10)) == NULL)
+ goto cleanup;
+ i = BIO_read(out, &((*data)[size]), 1024 * 10);
+ if (i <= 0)
+ break;
+ else
+ size += i;
+ }
+ *data_len = size;
+
+ reqctx->received_cert = X509_dup(x);
+
+ /* generate authorization data */
+ if (cms_msg_type == CMS_SIGN_CLIENT || cms_msg_type == CMS_SIGN_DRAFT9) {
+
+ if (authz_data == NULL || authz_data_len == NULL)
+ goto out;
+
+ *authz_data = NULL;
+ retval = create_identifiers_from_stack(verified_chain,
+ &krb5_verified_chain);
+ if (retval) {
+ pkiDebug("create_identifiers_from_stack failed\n");
+ goto cleanup;
+ }
+
+ retval = k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier **)krb5_verified_chain, &authz);
+ if (retval) {
+ pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
+ goto cleanup;
+ }
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)authz->data, authz->length,
+ "/tmp/kdc_ad_initial_verified_cas");
+#endif
+ *authz_data = (unsigned char *)malloc(authz->length);
+ if (*authz_data == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ (void) memcpy(*authz_data, authz->data, authz->length);
+ *authz_data_len = authz->length;
+ }
+ out:
+ retval = 0;
+
+ cleanup:
+ if (out != NULL)
+ BIO_free(out);
+ if (store != NULL)
+ X509_STORE_free(store);
+ if (p7 != NULL) {
+ if (idctx->intermediateCAs != NULL && p7->d.sign->cert)
+ sk_X509_free(intermediateCAs);
+ if (idctx->revoked != NULL && p7->d.sign->crl)
+ sk_X509_CRL_free(revoked);
+ PKCS7_free(p7);
+ }
+ if (verified_chain != NULL)
+ sk_X509_pop_free(verified_chain, X509_free);
+ if (krb5_verified_chain != NULL)
+ free_krb5_external_principal_identifier(&krb5_verified_chain);
+ if (authz != NULL)
+ krb5_free_data(context, authz);
+
+ return retval;
+}
+
+krb5_error_code
+cms_envelopeddata_create(krb5_context context,
+ pkinit_plg_crypto_context plgctx,
+ pkinit_req_crypto_context reqctx,
+ pkinit_identity_crypto_context idctx,
+ krb5_preauthtype pa_type,
+ int include_certchain,
+ unsigned char *key_pack,
+ unsigned int key_pack_len,
+ unsigned char **out,
+ unsigned int *out_len)
+{
+
+ /* Solaris Kerberos */
+ krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+ PKCS7 *p7 = NULL;
+ BIO *in = NULL;
+ unsigned char *p = NULL, *signed_data = NULL, *enc_data = NULL;
+ int signed_data_len = 0, enc_data_len = 0, flags = PKCS7_BINARY;
+ STACK_OF(X509) *encerts = NULL;
+ const EVP_CIPHER *cipher = NULL;
+ int cms_msg_type;
+
+ /* create the PKCS7 SignedData portion of the PKCS7 EnvelopedData */
+ switch ((int)pa_type) {
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ cms_msg_type = CMS_SIGN_DRAFT9;
+ break;
+ case KRB5_PADATA_PK_AS_REQ:
+ cms_msg_type = CMS_ENVEL_SERVER;
+ break;
+ default:
+ /* Solaris Kerberos */
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ retval = cms_signeddata_create(context, plgctx, reqctx, idctx,
+ cms_msg_type, include_certchain, key_pack, key_pack_len,
+ &signed_data, (unsigned int *)&signed_data_len);
+ if (retval) {
+ pkiDebug("failed to create pkcs7 signed data\n");
+ goto cleanup;
+ }
+
+ /* check we have client's certificate */
+ if (reqctx->received_cert == NULL) {
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto cleanup;
+ }
+ encerts = sk_X509_new_null();
+ sk_X509_push(encerts, reqctx->received_cert);
+
+ cipher = EVP_des_ede3_cbc();
+ in = BIO_new(BIO_s_mem());
+ switch (pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ prepare_enc_data(signed_data, signed_data_len, &enc_data,
+ &enc_data_len);
+ retval = BIO_write(in, enc_data, enc_data_len);
+ if (retval != enc_data_len) {
+ pkiDebug("BIO_write only wrote %d\n", retval);
+ goto cleanup;
+ }
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ retval = BIO_write(in, signed_data, signed_data_len);
+ if (retval != signed_data_len) {
+ pkiDebug("BIO_write only wrote %d\n", retval);
+ /* Solaris Kerberos */
+ retval = KRB5KRB_ERR_GENERIC;
+ goto cleanup;
+ }
+ break;
+ default:
+ retval = -1;
+ goto cleanup;
+ }
+
+ p7 = PKCS7_encrypt(encerts, in, cipher, flags);
+ if (p7 == NULL) {
+ pkiDebug("failed to encrypt PKCS7 object\n");
+ retval = -1;
+ goto cleanup;
+ }
+ switch (pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ p7->d.enveloped->enc_data->content_type =
+ OBJ_nid2obj(NID_pkcs7_signed);
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ p7->d.enveloped->enc_data->content_type =
+ OBJ_nid2obj(NID_pkcs7_data);
+ break;
+ }
+
+ *out_len = i2d_PKCS7(p7, NULL);
+ if (!*out_len || (p = *out = (unsigned char *)malloc(*out_len)) == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ retval = i2d_PKCS7(p7, &p);
+ if (!retval) {
+ pkiDebug("unable to write pkcs7 object\n");
+ goto cleanup;
+ }
+ retval = 0;
+
+#ifdef DEBUG_ASN1
+ print_buffer_bin(*out, *out_len, "/tmp/kdc_enveloped_data");
+#endif
+
+cleanup:
+ if (p7 != NULL)
+ PKCS7_free(p7);
+ if (in != NULL)
+ BIO_free(in);
+ if (signed_data != NULL)
+ free(signed_data);
+ if (enc_data != NULL)
+ free(enc_data);
+ if (encerts != NULL)
+ sk_X509_free(encerts);
+
+ return retval;
+}
+
+krb5_error_code
+cms_envelopeddata_verify(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_preauthtype pa_type,
+ int require_crl_checking,
+ unsigned char *enveloped_data,
+ unsigned int enveloped_data_len,
+ unsigned char **data,
+ unsigned int *data_len)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ PKCS7 *p7 = NULL;
+ BIO *out = NULL;
+ int i = 0;
+ unsigned int size = 0;
+ const unsigned char *p = enveloped_data;
+ unsigned int tmp_buf_len = 0, tmp_buf2_len = 0, vfy_buf_len = 0;
+ unsigned char *tmp_buf = NULL, *tmp_buf2 = NULL, *vfy_buf = NULL;
+ int msg_type = 0;
+
+#ifdef DEBUG_ASN1
+ print_buffer_bin(enveloped_data, enveloped_data_len,
+ "/tmp/client_envelopeddata");
+#endif
+ /* decode received PKCS7 message */
+ if ((p7 = d2i_PKCS7(NULL, &p, (int)enveloped_data_len)) == NULL) {
+ unsigned long err = ERR_peek_error();
+ pkiDebug("failed to decode pkcs7\n");
+ krb5_set_error_message(context, retval, "%s\n",
+ ERR_error_string(err, NULL));
+ goto cleanup;
+ }
+
+ /* verify that the received message is PKCS7 EnvelopedData message */
+ if (OBJ_obj2nid(p7->type) != NID_pkcs7_enveloped) {
+ pkiDebug("Expected id-enveloped PKCS7 msg (received type = %d)\n",
+ OBJ_obj2nid(p7->type));
+ krb5_set_error_message(context, retval, "wrong oid\n");
+ goto cleanup;
+ }
+
+ /* decrypt received PKCS7 message */
+ out = BIO_new(BIO_s_mem());
+ if (pkcs7_decrypt(context, id_cryptoctx, p7, out)) {
+ pkiDebug("PKCS7 decryption successful\n");
+ } else {
+ unsigned long err = ERR_peek_error();
+ if (err != 0)
+ krb5_set_error_message(context, retval, "%s\n",
+ ERR_error_string(err, NULL));
+ pkiDebug("PKCS7 decryption failed\n");
+ goto cleanup;
+ }
+
+ /* transfer the decoded PKCS7 SignedData message into a separate buffer */
+ for (;;) {
+ if ((tmp_buf = realloc(tmp_buf, size + 1024 * 10)) == NULL)
+ goto cleanup;
+ i = BIO_read(out, &(tmp_buf[size]), 1024 * 10);
+ if (i <= 0)
+ break;
+ else
+ size += i;
+ }
+ tmp_buf_len = size;
+
+#ifdef DEBUG_ASN1
+ print_buffer_bin(tmp_buf, tmp_buf_len, "/tmp/client_enc_keypack");
+#endif
+ /* verify PKCS7 SignedData message */
+ switch (pa_type) {
+ case KRB5_PADATA_PK_AS_REP:
+ msg_type = CMS_ENVEL_SERVER;
+
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ msg_type = CMS_SIGN_DRAFT9;
+ break;
+ default:
+ pkiDebug("%s: unrecognized pa_type = %d\n", __FUNCTION__, pa_type);
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto cleanup;
+ }
+ /*
+ * If this is the RFC style, wrap the signed data to make
+ * decoding easier in the verify routine.
+ * For draft9-compatible, we don't do anything because it
+ * is already wrapped.
+ */
+#ifdef LONGHORN_BETA_COMPAT
+ /*
+ * The Longhorn server returns the expected RFC-style data, but
+ * it is missing the sequence tag and length, so it requires
+ * special processing when wrapping.
+ * This will hopefully be fixed before the final release and
+ * this can all be removed.
+ */
+ if (msg_type == CMS_ENVEL_SERVER || longhorn == 1) {
+ retval = wrap_signeddata(tmp_buf, tmp_buf_len,
+ &tmp_buf2, &tmp_buf2_len, longhorn);
+ if (retval) {
+ pkiDebug("failed to encode signeddata\n");
+ goto cleanup;
+ }
+ vfy_buf = tmp_buf2;
+ vfy_buf_len = tmp_buf2_len;
+
+ } else {
+ vfy_buf = tmp_buf;
+ vfy_buf_len = tmp_buf_len;
+ }
+#else
+ if (msg_type == CMS_ENVEL_SERVER) {
+ retval = wrap_signeddata(tmp_buf, tmp_buf_len,
+ &tmp_buf2, &tmp_buf2_len);
+ if (retval) {
+ pkiDebug("failed to encode signeddata\n");
+ goto cleanup;
+ }
+ vfy_buf = tmp_buf2;
+ vfy_buf_len = tmp_buf2_len;
+
+ } else {
+ vfy_buf = tmp_buf;
+ vfy_buf_len = tmp_buf_len;
+ }
+#endif
+
+#ifdef DEBUG_ASN1
+ print_buffer_bin(vfy_buf, vfy_buf_len, "/tmp/client_enc_keypack2");
+#endif
+
+ retval = cms_signeddata_verify(context, plg_cryptoctx, req_cryptoctx,
+ id_cryptoctx, msg_type,
+ require_crl_checking,
+ vfy_buf, vfy_buf_len,
+ data, data_len, NULL, NULL);
+
+ if (!retval)
+ pkiDebug("PKCS7 Verification Success\n");
+ else {
+ pkiDebug("PKCS7 Verification Failure\n");
+ goto cleanup;
+ }
+
+ retval = 0;
+
+ cleanup:
+
+ if (p7 != NULL)
+ PKCS7_free(p7);
+ if (out != NULL)
+ BIO_free(out);
+ if (tmp_buf != NULL)
+ free(tmp_buf);
+ if (tmp_buf2 != NULL)
+ free(tmp_buf2);
+
+ return retval;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+crypto_retrieve_X509_sans(krb5_context context,
+ pkinit_plg_crypto_context plgctx,
+ pkinit_req_crypto_context reqctx,
+ X509 *cert,
+ krb5_principal **princs_ret,
+ krb5_principal **upn_ret,
+ unsigned char ***dns_ret)
+{
+ krb5_error_code retval = EINVAL;
+ char buf[DN_BUF_LEN];
+ int p = 0, u = 0, d = 0;
+ krb5_principal *princs = NULL;
+ krb5_principal *upns = NULL;
+ unsigned char **dnss = NULL;
+ int i, num_found = 0;
+
+ if (princs_ret == NULL && upn_ret == NULL && dns_ret == NULL) {
+ pkiDebug("%s: nowhere to return any values!\n", __FUNCTION__);
+ return retval;
+ }
+
+ if (cert == NULL) {
+ pkiDebug("%s: no certificate!\n", __FUNCTION__);
+ return retval;
+ }
+
+ X509_NAME_oneline(X509_get_subject_name(cert),
+ buf, sizeof(buf));
+ pkiDebug("%s: looking for SANs in cert = %s\n", __FUNCTION__, buf);
+
+ if ((i = X509_get_ext_by_NID(cert, NID_subject_alt_name, -1)) >= 0) {
+ X509_EXTENSION *ext = NULL;
+ GENERAL_NAMES *ialt = NULL;
+ GENERAL_NAME *gen = NULL;
+ int ret = 0;
+ unsigned int num_sans = 0;
+
+ if (!(ext = X509_get_ext(cert, i)) || !(ialt = X509V3_EXT_d2i(ext))) {
+ pkiDebug("%s: found no subject alt name extensions\n",
+ __FUNCTION__);
+ goto cleanup;
+ }
+ num_sans = sk_GENERAL_NAME_num(ialt);
+
+ pkiDebug("%s: found %d subject alt name extension(s)\n",
+ __FUNCTION__, num_sans);
+
+ /* OK, we're likely returning something. Allocate return values */
+ if (princs_ret != NULL) {
+ princs = calloc(num_sans + 1, sizeof(krb5_principal));
+ if (princs == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ if (upn_ret != NULL) {
+ upns = calloc(num_sans + 1, sizeof(krb5_principal));
+ if (upns == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+ if (dns_ret != NULL) {
+ dnss = calloc(num_sans + 1, sizeof(*dnss));
+ if (dnss == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ }
+
+ for (i = 0; i < num_sans; i++) {
+ krb5_data name = { 0, 0, NULL };
+
+ gen = sk_GENERAL_NAME_value(ialt, i);
+ switch (gen->type) {
+ case GEN_OTHERNAME:
+ name.length = gen->d.otherName->value->value.sequence->length;
+ name.data = (char *)gen->d.otherName->value->value.sequence->data;
+ if (princs != NULL
+ && OBJ_cmp(plgctx->id_pkinit_san,
+ gen->d.otherName->type_id) == 0) {
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)name.data, name.length,
+ "/tmp/pkinit_san");
+#endif
+ ret = k5int_decode_krb5_principal_name(&name, &princs[p]);
+ if (ret) {
+ pkiDebug("%s: failed decoding pkinit san value\n",
+ __FUNCTION__);
+ } else {
+ p++;
+ num_found++;
+ }
+ } else if (upns != NULL
+ && OBJ_cmp(plgctx->id_ms_san_upn,
+ gen->d.otherName->type_id) == 0) {
+ ret = krb5_parse_name(context, name.data, &upns[u]);
+ if (ret) {
+ pkiDebug("%s: failed parsing ms-upn san value\n",
+ __FUNCTION__);
+ } else {
+ u++;
+ num_found++;
+ }
+ } else {
+ pkiDebug("%s: unrecognized othername oid in SAN\n",
+ __FUNCTION__);
+ continue;
+ }
+
+ break;
+ case GEN_DNS:
+ if (dnss != NULL) {
+ pkiDebug("%s: found dns name = %s\n",
+ __FUNCTION__, gen->d.dNSName->data);
+ dnss[d] = (unsigned char *)
+ strdup((char *)gen->d.dNSName->data);
+ if (dnss[d] == NULL) {
+ pkiDebug("%s: failed to duplicate dns name\n",
+ __FUNCTION__);
+ } else {
+ d++;
+ num_found++;
+ }
+ }
+ break;
+ default:
+ pkiDebug("%s: SAN type = %d expecting %d\n",
+ __FUNCTION__, gen->type, GEN_OTHERNAME);
+ }
+ }
+ sk_GENERAL_NAME_pop_free(ialt, GENERAL_NAME_free);
+ }
+
+ retval = 0;
+ if (princs)
+ *princs_ret = princs;
+ if (upns)
+ *upn_ret = upns;
+ if (dnss)
+ *dns_ret = dnss;
+
+ cleanup:
+ if (retval) {
+ if (princs != NULL) {
+ for (i = 0; princs[i] != NULL; i++)
+ krb5_free_principal(context, princs[i]);
+ free(princs);
+ }
+ if (upns != NULL) {
+ for (i = 0; upns[i] != NULL; i++)
+ krb5_free_principal(context, upns[i]);
+ free(upns);
+ }
+ if (dnss != NULL) {
+ for (i = 0; dnss[i] != NULL; i++)
+ free(dnss[i]);
+ free(dnss);
+ }
+ }
+ return retval;
+}
+
+/* ARGSUSED */
+krb5_error_code
+crypto_retrieve_cert_sans(krb5_context context,
+ pkinit_plg_crypto_context plgctx,
+ pkinit_req_crypto_context reqctx,
+ pkinit_identity_crypto_context idctx,
+ krb5_principal **princs_ret,
+ krb5_principal **upn_ret,
+ unsigned char ***dns_ret)
+{
+ krb5_error_code retval = EINVAL;
+
+ if (reqctx->received_cert == NULL) {
+ pkiDebug("%s: No certificate!\n", __FUNCTION__);
+ return retval;
+ }
+
+ return crypto_retrieve_X509_sans(context, plgctx, reqctx,
+ reqctx->received_cert, princs_ret,
+ upn_ret, dns_ret);
+}
+
+/* ARGSUSED */
+krb5_error_code
+crypto_check_cert_eku(krb5_context context,
+ pkinit_plg_crypto_context plgctx,
+ pkinit_req_crypto_context reqctx,
+ pkinit_identity_crypto_context idctx,
+ int checking_kdc_cert,
+ int allow_secondary_usage,
+ int *valid_eku)
+{
+ char buf[DN_BUF_LEN];
+ int found_eku = 0;
+ krb5_error_code retval = EINVAL;
+ int i;
+
+ /* Solaris Kerberos */
+ if (valid_eku == NULL)
+ return retval;
+
+ *valid_eku = 0;
+ if (reqctx->received_cert == NULL)
+ goto cleanup;
+
+ X509_NAME_oneline(X509_get_subject_name(reqctx->received_cert),
+ buf, sizeof(buf));
+ pkiDebug("%s: looking for EKUs in cert = %s\n", __FUNCTION__, buf);
+
+ if ((i = X509_get_ext_by_NID(reqctx->received_cert,
+ NID_ext_key_usage, -1)) >= 0) {
+ EXTENDED_KEY_USAGE *extusage;
+
+ extusage = X509_get_ext_d2i(reqctx->received_cert, NID_ext_key_usage,
+ NULL, NULL);
+ if (extusage) {
+ pkiDebug("%s: found eku info in the cert\n", __FUNCTION__);
+ for (i = 0; found_eku == 0 && i < sk_ASN1_OBJECT_num(extusage); i++) {
+ ASN1_OBJECT *tmp_oid;
+
+ tmp_oid = sk_ASN1_OBJECT_value(extusage, i);
+ pkiDebug("%s: checking eku %d of %d, allow_secondary = %d\n",
+ __FUNCTION__, i+1, sk_ASN1_OBJECT_num(extusage),
+ allow_secondary_usage);
+ if (checking_kdc_cert) {
+ if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPKdc) == 0)
+ || (allow_secondary_usage
+ && OBJ_cmp(tmp_oid, plgctx->id_kp_serverAuth) == 0))
+ found_eku = 1;
+ } else {
+ if ((OBJ_cmp(tmp_oid, plgctx->id_pkinit_KPClientAuth) == 0)
+ || (allow_secondary_usage
+ && OBJ_cmp(tmp_oid, plgctx->id_ms_kp_sc_logon) == 0))
+ found_eku = 1;
+ }
+ }
+ }
+ EXTENDED_KEY_USAGE_free(extusage);
+
+ if (found_eku) {
+ ASN1_BIT_STRING *usage = NULL;
+ pkiDebug("%s: found acceptable EKU, checking for digitalSignature\n", __FUNCTION__);
+
+ /* check that digitalSignature KeyUsage is present */
+ if ((usage = X509_get_ext_d2i(reqctx->received_cert,
+ NID_key_usage, NULL, NULL))) {
+
+ if (!ku_reject(reqctx->received_cert,
+ X509v3_KU_DIGITAL_SIGNATURE)) {
+ pkiDebug("%s: found digitalSignature KU\n",
+ __FUNCTION__);
+ *valid_eku = 1;
+ } else
+ pkiDebug("%s: didn't find digitalSignature KU\n",
+ __FUNCTION__);
+ }
+ ASN1_BIT_STRING_free(usage);
+ }
+ }
+ retval = 0;
+cleanup:
+ pkiDebug("%s: returning retval %d, valid_eku %d\n",
+ __FUNCTION__, retval, *valid_eku);
+ return retval;
+}
+
+krb5_error_code
+pkinit_octetstring2key(krb5_context context,
+ krb5_enctype etype,
+ unsigned char *key,
+ unsigned int dh_key_len,
+ krb5_keyblock * key_block)
+{
+ krb5_error_code retval;
+ unsigned char *buf = NULL;
+ unsigned char md[SHA_DIGEST_LENGTH];
+ unsigned char counter;
+ size_t keybytes, keylength, offset;
+ krb5_data random_data;
+
+
+ if ((buf = (unsigned char *) malloc(dh_key_len)) == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ (void) memset(buf, 0, dh_key_len);
+
+ counter = 0;
+ offset = 0;
+ do {
+ SHA_CTX c;
+
+ SHA1_Init(&c);
+ SHA1_Update(&c, &counter, 1);
+ SHA1_Update(&c, key, dh_key_len);
+ SHA1_Final(md, &c);
+
+ if (dh_key_len - offset < sizeof(md))
+ (void) memcpy(buf + offset, md, dh_key_len - offset);
+ else
+ (void) memcpy(buf + offset, md, sizeof(md));
+
+ offset += sizeof(md);
+ counter++;
+ } while (offset < dh_key_len);
+
+ /* Solaris Kerberos */
+ key_block->magic = KV5M_KEYBLOCK;
+ key_block->enctype = etype;
+
+ retval = krb5_c_keylengths(context, etype, &keybytes, &keylength);
+ if (retval)
+ goto cleanup;
+
+ key_block->length = keylength;
+ key_block->contents = calloc(keylength, sizeof(unsigned char *));
+ if (key_block->contents == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ random_data.length = keybytes;
+ random_data.data = (char *)buf;
+
+ retval = krb5_c_random_to_key(context, etype, &random_data, key_block);
+
+ cleanup:
+ if (buf != NULL)
+ free(buf);
+ if (retval && key_block->contents != NULL && key_block->length != 0) {
+ (void) memset(key_block->contents, 0, key_block->length);
+ key_block->length = 0;
+ }
+
+ return retval;
+}
+
+/* ARGSUSED */
+krb5_error_code
+client_create_dh(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ int dh_size,
+ unsigned char **dh_params,
+ unsigned int *dh_params_len,
+ unsigned char **dh_pubkey,
+ unsigned int *dh_pubkey_len)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ unsigned char *buf = NULL;
+ int dh_err = 0;
+ ASN1_INTEGER *pub_key = NULL;
+
+ if (cryptoctx->dh == NULL) {
+ if ((cryptoctx->dh = DH_new()) == NULL)
+ goto cleanup;
+ if ((cryptoctx->dh->g = BN_new()) == NULL ||
+ (cryptoctx->dh->q = BN_new()) == NULL)
+ goto cleanup;
+
+ switch(dh_size) {
+ case 1024:
+ pkiDebug("client uses 1024 DH keys\n");
+ cryptoctx->dh->p = get_rfc2409_prime_1024(NULL);
+ break;
+ case 2048:
+ pkiDebug("client uses 2048 DH keys\n");
+ cryptoctx->dh->p = BN_bin2bn(pkinit_2048_dhprime,
+ sizeof(pkinit_2048_dhprime), NULL);
+ break;
+ case 4096:
+ pkiDebug("client uses 4096 DH keys\n");
+ cryptoctx->dh->p = BN_bin2bn(pkinit_4096_dhprime,
+ sizeof(pkinit_4096_dhprime), NULL);
+ break;
+ default:
+ goto cleanup;
+ }
+
+ BN_set_word((cryptoctx->dh->g), DH_GENERATOR_2);
+ BN_rshift1(cryptoctx->dh->q, cryptoctx->dh->p);
+ }
+
+ DH_generate_key(cryptoctx->dh);
+/* Solaris Kerberos */
+#ifdef DEBUG
+ DH_check(cryptoctx->dh, &dh_err);
+ if (dh_err != 0) {
+ pkiDebug("Warning: dh_check failed with %d\n", dh_err);
+ if (dh_err & DH_CHECK_P_NOT_PRIME)
+ pkiDebug("p value is not prime\n");
+ if (dh_err & DH_CHECK_P_NOT_SAFE_PRIME)
+ pkiDebug("p value is not a safe prime\n");
+ if (dh_err & DH_UNABLE_TO_CHECK_GENERATOR)
+ pkiDebug("unable to check the generator value\n");
+ if (dh_err & DH_NOT_SUITABLE_GENERATOR)
+ pkiDebug("the g value is not a generator\n");
+ }
+#endif
+#ifdef DEBUG_DH
+ print_dh(cryptoctx->dh, "client's DH params\n");
+ print_pubkey(cryptoctx->dh->pub_key, "client's pub_key=");
+#endif
+
+ DH_check_pub_key(cryptoctx->dh, cryptoctx->dh->pub_key, &dh_err);
+ if (dh_err != 0) {
+ pkiDebug("dh_check_pub_key failed with %d\n", dh_err);
+ goto cleanup;
+ }
+
+ /* pack DHparams */
+ /* aglo: usually we could just call i2d_DHparams to encode DH params
+ * however, PKINIT requires RFC3279 encoding and openssl does pkcs#3.
+ */
+ retval = pkinit_encode_dh_params(cryptoctx->dh->p, cryptoctx->dh->g,
+ cryptoctx->dh->q, dh_params, dh_params_len);
+ if (retval)
+ goto cleanup;
+
+ /* pack DH public key */
+ /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
+ * encoding shall be used as the contents (the value) of the
+ * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
+ * data element
+ */
+ if ((pub_key = BN_to_ASN1_INTEGER(cryptoctx->dh->pub_key, NULL)) == NULL)
+ goto cleanup;
+ *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL);
+ if ((buf = *dh_pubkey = (unsigned char *)
+ malloc((size_t) *dh_pubkey_len)) == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ i2d_ASN1_INTEGER(pub_key, &buf);
+
+ if (pub_key != NULL)
+ ASN1_INTEGER_free(pub_key);
+
+ retval = 0;
+ return retval;
+
+ cleanup:
+ if (cryptoctx->dh != NULL)
+ DH_free(cryptoctx->dh);
+ cryptoctx->dh = NULL;
+ if (*dh_params != NULL)
+ free(*dh_params);
+ *dh_params = NULL;
+ if (*dh_pubkey != NULL)
+ free(*dh_pubkey);
+ *dh_pubkey = NULL;
+ if (pub_key != NULL)
+ ASN1_INTEGER_free(pub_key);
+
+ return retval;
+}
+
+/* ARGSUSED */
+krb5_error_code
+client_process_dh(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *subjectPublicKey_data,
+ unsigned int subjectPublicKey_length,
+ unsigned char **client_key,
+ unsigned int *client_key_len)
+{
+ /* Solaris Kerberos */
+ krb5_error_code retval = KRB5_PREAUTH_FAILED;
+ BIGNUM *server_pub_key = NULL;
+ ASN1_INTEGER *pub_key = NULL;
+ const unsigned char *p = NULL;
+ unsigned char *data = NULL;
+ long data_len;
+
+ /* decode subjectPublicKey (retrieve INTEGER from OCTET_STRING) */
+
+ if (der_decode_data(subjectPublicKey_data, (long)subjectPublicKey_length,
+ &data, &data_len) != 0) {
+ pkiDebug("failed to decode subjectPublicKey\n");
+ /* Solaris Kerberos */
+ retval = KRB5_PREAUTH_FAILED;
+ goto cleanup;
+ }
+
+ *client_key_len = DH_size(cryptoctx->dh);
+ if ((*client_key = (unsigned char *)
+ malloc((size_t) *client_key_len)) == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ p = data;
+ if ((pub_key = d2i_ASN1_INTEGER(NULL, &p, data_len)) == NULL)
+ goto cleanup;
+ if ((server_pub_key = ASN1_INTEGER_to_BN(pub_key, NULL)) == NULL)
+ goto cleanup;
+
+ DH_compute_key(*client_key, server_pub_key, cryptoctx->dh);
+#ifdef DEBUG_DH
+ print_pubkey(server_pub_key, "server's pub_key=");
+ pkiDebug("client secret key (%d)= ", *client_key_len);
+ print_buffer(*client_key, *client_key_len);
+#endif
+
+ retval = 0;
+ if (server_pub_key != NULL)
+ BN_free(server_pub_key);
+ if (pub_key != NULL)
+ ASN1_INTEGER_free(pub_key);
+ if (data != NULL)
+ free (data);
+
+ return retval;
+
+ cleanup:
+ if (*client_key != NULL)
+ free(*client_key);
+ *client_key = NULL;
+ if (pub_key != NULL)
+ ASN1_INTEGER_free(pub_key);
+ if (data != NULL)
+ free (data);
+
+ return retval;
+}
+
+/* ARGSUSED */
+krb5_error_code
+server_check_dh(krb5_context context,
+ pkinit_plg_crypto_context cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_octet_data *dh_params,
+ int minbits)
+{
+ DH *dh = NULL;
+ unsigned char *tmp = NULL;
+ int dh_prime_bits;
+ krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
+
+ tmp = dh_params->data;
+ dh = DH_new();
+ dh = pkinit_decode_dh_params(&dh, &tmp, dh_params->length);
+ if (dh == NULL) {
+ pkiDebug("failed to decode dhparams\n");
+ goto cleanup;
+ }
+
+ /* KDC SHOULD check to see if the key parameters satisfy its policy */
+ dh_prime_bits = BN_num_bits(dh->p);
+ if (minbits && dh_prime_bits < minbits) {
+ pkiDebug("client sent dh params with %d bits, we require %d\n",
+ dh_prime_bits, minbits);
+ goto cleanup;
+ }
+
+ /* check dhparams is group 2 */
+ if (pkinit_check_dh_params(cryptoctx->dh_1024->p,
+ dh->p, dh->g, dh->q) == 0) {
+ retval = 0;
+ goto cleanup;
+ }
+
+ /* check dhparams is group 14 */
+ if (pkinit_check_dh_params(cryptoctx->dh_2048->p,
+ dh->p, dh->g, dh->q) == 0) {
+ retval = 0;
+ goto cleanup;
+ }
+
+ /* check dhparams is group 16 */
+ if (pkinit_check_dh_params(cryptoctx->dh_4096->p,
+ dh->p, dh->g, dh->q) == 0) {
+ retval = 0;
+ goto cleanup;
+ }
+
+ cleanup:
+ if (retval == 0)
+ req_cryptoctx->dh = dh;
+ else
+ DH_free(dh);
+
+ return retval;
+}
+
+/* kdc's dh function */
+/* ARGSUSED */
+krb5_error_code
+server_process_dh(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *data,
+ unsigned int data_len,
+ unsigned char **dh_pubkey,
+ unsigned int *dh_pubkey_len,
+ unsigned char **server_key,
+ unsigned int *server_key_len)
+{
+ /* Solaris Kerberos */
+ krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+ DH *dh = NULL, *dh_server = NULL;
+ unsigned char *p = NULL;
+ ASN1_INTEGER *pub_key = NULL;
+
+ /* get client's received DH parameters that we saved in server_check_dh */
+ dh = cryptoctx->dh;
+
+ dh_server = DH_new();
+ if (dh_server == NULL)
+ goto cleanup;
+ dh_server->p = BN_dup(dh->p);
+ dh_server->g = BN_dup(dh->g);
+ dh_server->q = BN_dup(dh->q);
+
+ /* decode client's public key */
+ p = data;
+ pub_key = d2i_ASN1_INTEGER(NULL, (const unsigned char **)&p, (int)data_len);
+ if (pub_key == NULL)
+ goto cleanup;
+ dh->pub_key = ASN1_INTEGER_to_BN(pub_key, NULL);
+ if (dh->pub_key == NULL)
+ goto cleanup;
+ ASN1_INTEGER_free(pub_key);
+
+ if (!DH_generate_key(dh_server))
+ goto cleanup;
+
+ /* generate DH session key */
+ *server_key_len = DH_size(dh_server);
+ if ((*server_key = (unsigned char *) malloc((size_t)*server_key_len)) == NULL)
+ goto cleanup;
+ DH_compute_key(*server_key, dh->pub_key, dh_server);
+
+#ifdef DEBUG_DH
+ print_dh(dh_server, "client&server's DH params\n");
+ print_pubkey(dh->pub_key, "client's pub_key=");
+ print_pubkey(dh_server->pub_key, "server's pub_key=");
+ pkiDebug("server secret key=");
+ print_buffer(*server_key, *server_key_len);
+#endif
+
+ /* KDC reply */
+ /* pack DH public key */
+ /* Diffie-Hellman public key must be ASN1 encoded as an INTEGER; this
+ * encoding shall be used as the contents (the value) of the
+ * subjectPublicKey component (a BIT STRING) of the SubjectPublicKeyInfo
+ * data element
+ */
+ if ((pub_key = BN_to_ASN1_INTEGER(dh_server->pub_key, NULL)) == NULL)
+ goto cleanup;
+ *dh_pubkey_len = i2d_ASN1_INTEGER(pub_key, NULL);
+ if ((p = *dh_pubkey = (unsigned char *) malloc((size_t)*dh_pubkey_len)) == NULL)
+ goto cleanup;
+ i2d_ASN1_INTEGER(pub_key, &p);
+ if (pub_key != NULL)
+ ASN1_INTEGER_free(pub_key);
+
+ retval = 0;
+
+ if (dh_server != NULL)
+ DH_free(dh_server);
+ return retval;
+
+ cleanup:
+ if (dh_server != NULL)
+ DH_free(dh_server);
+ if (*dh_pubkey != NULL)
+ free(*dh_pubkey);
+ if (*server_key != NULL)
+ free(*server_key);
+
+ return retval;
+}
+
+static void
+openssl_init()
+{
+ static int did_init = 0;
+
+ if (!did_init) {
+ /* initialize openssl routines */
+ CRYPTO_malloc_init();
+ ERR_load_crypto_strings();
+ OpenSSL_add_all_algorithms();
+ did_init++;
+ }
+}
+
+static krb5_error_code
+pkinit_encode_dh_params(BIGNUM *p, BIGNUM *g, BIGNUM *q,
+ unsigned char **buf, unsigned int *buf_len)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ int bufsize = 0, r = 0;
+ unsigned char *tmp = NULL;
+ ASN1_INTEGER *ap = NULL, *ag = NULL, *aq = NULL;
+
+ if ((ap = BN_to_ASN1_INTEGER(p, NULL)) == NULL)
+ goto cleanup;
+ if ((ag = BN_to_ASN1_INTEGER(g, NULL)) == NULL)
+ goto cleanup;
+ if ((aq = BN_to_ASN1_INTEGER(q, NULL)) == NULL)
+ goto cleanup;
+ bufsize = i2d_ASN1_INTEGER(ap, NULL);
+ bufsize += i2d_ASN1_INTEGER(ag, NULL);
+ bufsize += i2d_ASN1_INTEGER(aq, NULL);
+
+ r = ASN1_object_size(1, bufsize, V_ASN1_SEQUENCE);
+
+ tmp = *buf = (unsigned char *)malloc((size_t) r);
+ if (tmp == NULL)
+ goto cleanup;
+
+ ASN1_put_object(&tmp, 1, bufsize, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
+
+ i2d_ASN1_INTEGER(ap, &tmp);
+ i2d_ASN1_INTEGER(ag, &tmp);
+ i2d_ASN1_INTEGER(aq, &tmp);
+
+ *buf_len = r;
+
+ retval = 0;
+
+cleanup:
+ if (ap != NULL)
+ ASN1_INTEGER_free(ap);
+ if (ag != NULL)
+ ASN1_INTEGER_free(ag);
+ if (aq != NULL)
+ ASN1_INTEGER_free(aq);
+
+ return retval;
+}
+
+static DH *
+pkinit_decode_dh_params(DH ** a, unsigned char **pp, unsigned int len)
+{
+ ASN1_INTEGER ai, *aip = NULL;
+ long length = (long) len;
+
+ M_ASN1_D2I_vars(a, DH *, DH_new);
+
+ M_ASN1_D2I_Init();
+ M_ASN1_D2I_start_sequence();
+ aip = &ai;
+ ai.data = NULL;
+ ai.length = 0;
+ M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
+ if (aip == NULL)
+ return NULL;
+ else {
+ (*a)->p = ASN1_INTEGER_to_BN(aip, NULL);
+ if ((*a)->p == NULL)
+ return NULL;
+ if (ai.data != NULL) {
+ OPENSSL_free(ai.data);
+ ai.data = NULL;
+ ai.length = 0;
+ }
+ }
+ M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
+ if (aip == NULL)
+ return NULL;
+ else {
+ (*a)->g = ASN1_INTEGER_to_BN(aip, NULL);
+ if ((*a)->g == NULL)
+ return NULL;
+ if (ai.data != NULL) {
+ OPENSSL_free(ai.data);
+ ai.data = NULL;
+ ai.length = 0;
+ }
+
+ }
+ M_ASN1_D2I_get_x(ASN1_INTEGER, aip, d2i_ASN1_INTEGER);
+ if (aip == NULL)
+ return NULL;
+ else {
+ (*a)->q = ASN1_INTEGER_to_BN(aip, NULL);
+ if ((*a)->q == NULL)
+ return NULL;
+ if (ai.data != NULL) {
+ OPENSSL_free(ai.data);
+ ai.data = NULL;
+ ai.length = 0;
+ }
+
+ }
+ M_ASN1_D2I_end_sequence();
+ M_ASN1_D2I_Finish(a, DH_free, 0);
+
+}
+
+static krb5_error_code
+pkinit_create_sequence_of_principal_identifiers(
+ krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ int type,
+ krb5_data **out_data)
+{
+ krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+ krb5_external_principal_identifier **krb5_trusted_certifiers = NULL;
+ krb5_data *td_certifiers = NULL, *data = NULL;
+ krb5_typed_data **typed_data = NULL;
+
+ switch(type) {
+ case TD_TRUSTED_CERTIFIERS:
+ retval = create_krb5_trustedCertifiers(context, plg_cryptoctx,
+ req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
+ if (retval) {
+ pkiDebug("create_krb5_trustedCertifiers failed\n");
+ goto cleanup;
+ }
+ break;
+ case TD_INVALID_CERTIFICATES:
+ retval = create_krb5_invalidCertificates(context, plg_cryptoctx,
+ req_cryptoctx, id_cryptoctx, &krb5_trusted_certifiers);
+ if (retval) {
+ pkiDebug("create_krb5_invalidCertificates failed\n");
+ goto cleanup;
+ }
+ break;
+ default:
+ retval = -1;
+ goto cleanup;
+ }
+
+ retval = k5int_encode_krb5_td_trusted_certifiers((const krb5_external_principal_identifier **)krb5_trusted_certifiers, &td_certifiers);
+ if (retval) {
+ pkiDebug("encode_krb5_td_trusted_certifiers failed\n");
+ goto cleanup;
+ }
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)td_certifiers->data,
+ td_certifiers->length, "/tmp/kdc_td_certifiers");
+#endif
+ typed_data = malloc (2 * sizeof(krb5_typed_data *));
+ if (typed_data == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ typed_data[1] = NULL;
+ init_krb5_typed_data(&typed_data[0]);
+ if (typed_data[0] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ typed_data[0]->type = type;
+ typed_data[0]->length = td_certifiers->length;
+ typed_data[0]->data = (unsigned char *)td_certifiers->data;
+ retval = k5int_encode_krb5_typed_data((const krb5_typed_data **)typed_data,
+ &data);
+ if (retval) {
+ pkiDebug("encode_krb5_typed_data failed\n");
+ goto cleanup;
+ }
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)data->data, data->length,
+ "/tmp/kdc_edata");
+#endif
+ *out_data = (krb5_data *)malloc(sizeof(krb5_data));
+ (*out_data)->length = data->length;
+ (*out_data)->data = (char *)malloc(data->length);
+ (void) memcpy((*out_data)->data, data->data, data->length);
+
+ retval = 0;
+
+cleanup:
+ if (krb5_trusted_certifiers != NULL)
+ free_krb5_external_principal_identifier(&krb5_trusted_certifiers);
+
+ if (data != NULL) {
+ if (data->data != NULL)
+ free(data->data);
+ free(data);
+ }
+
+ if (td_certifiers != NULL)
+ free(td_certifiers);
+
+ if (typed_data != NULL)
+ free_krb5_typed_data(&typed_data);
+
+ return retval;
+}
+
+krb5_error_code
+pkinit_create_td_trusted_certifiers(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_data **out_data)
+{
+ krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+
+ retval = pkinit_create_sequence_of_principal_identifiers(context,
+ plg_cryptoctx, req_cryptoctx, id_cryptoctx,
+ TD_TRUSTED_CERTIFIERS, out_data);
+
+ return retval;
+}
+
+krb5_error_code
+pkinit_create_td_invalid_certificate(
+ krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_data **out_data)
+{
+ krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+
+ retval = pkinit_create_sequence_of_principal_identifiers(context,
+ plg_cryptoctx, req_cryptoctx, id_cryptoctx,
+ TD_INVALID_CERTIFICATES, out_data);
+
+ return retval;
+}
+
+/* ARGSUSED */
+krb5_error_code
+pkinit_create_td_dh_parameters(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ pkinit_plg_opts *opts,
+ krb5_data **out_data)
+{
+ /* Solaris Kerberos */
+ krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+ unsigned int buf1_len = 0, buf2_len = 0, buf3_len = 0, i = 0;
+ unsigned char *buf1 = NULL, *buf2 = NULL, *buf3 = NULL;
+ krb5_typed_data **typed_data = NULL;
+ krb5_data *data = NULL, *encoded_algId = NULL;
+ krb5_algorithm_identifier **algId = NULL;
+
+ /* Solaris Kerberos */
+ if (opts->dh_min_bits > 4096) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+
+ if (opts->dh_min_bits <= 1024) {
+ retval = pkinit_encode_dh_params(plg_cryptoctx->dh_1024->p,
+ plg_cryptoctx->dh_1024->g, plg_cryptoctx->dh_1024->q,
+ &buf1, &buf1_len);
+ if (retval)
+ goto cleanup;
+ }
+ if (opts->dh_min_bits <= 2048) {
+ retval = pkinit_encode_dh_params(plg_cryptoctx->dh_2048->p,
+ plg_cryptoctx->dh_2048->g, plg_cryptoctx->dh_2048->q,
+ &buf2, &buf2_len);
+ if (retval)
+ goto cleanup;
+ }
+ retval = pkinit_encode_dh_params(plg_cryptoctx->dh_4096->p,
+ plg_cryptoctx->dh_4096->g, plg_cryptoctx->dh_4096->q,
+ &buf3, &buf3_len);
+ if (retval)
+ goto cleanup;
+
+ if (opts->dh_min_bits <= 1024) {
+ algId = malloc(4 * sizeof(krb5_algorithm_identifier *));
+ if (algId == NULL)
+ goto cleanup;
+ algId[3] = NULL;
+ algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+ if (algId[0] == NULL)
+ goto cleanup;
+ algId[0]->parameters.data = (unsigned char *)malloc(buf2_len);
+ if (algId[0]->parameters.data == NULL)
+ goto cleanup;
+ (void) memcpy(algId[0]->parameters.data, buf2, buf2_len);
+ algId[0]->parameters.length = buf2_len;
+ algId[0]->algorithm = dh_oid;
+
+ algId[1] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+ if (algId[1] == NULL)
+ goto cleanup;
+ algId[1]->parameters.data = (unsigned char *)malloc(buf3_len);
+ if (algId[1]->parameters.data == NULL)
+ goto cleanup;
+ (void) memcpy(algId[1]->parameters.data, buf3, buf3_len);
+ algId[1]->parameters.length = buf3_len;
+ algId[1]->algorithm = dh_oid;
+
+ algId[2] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+ if (algId[2] == NULL)
+ goto cleanup;
+ algId[2]->parameters.data = (unsigned char *)malloc(buf1_len);
+ if (algId[2]->parameters.data == NULL)
+ goto cleanup;
+ (void) memcpy(algId[2]->parameters.data, buf1, buf1_len);
+ algId[2]->parameters.length = buf1_len;
+ algId[2]->algorithm = dh_oid;
+
+ } else if (opts->dh_min_bits <= 2048) {
+ algId = malloc(3 * sizeof(krb5_algorithm_identifier *));
+ if (algId == NULL)
+ goto cleanup;
+ algId[2] = NULL;
+ algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+ if (algId[0] == NULL)
+ goto cleanup;
+ algId[0]->parameters.data = (unsigned char *)malloc(buf2_len);
+ if (algId[0]->parameters.data == NULL)
+ goto cleanup;
+ (void) memcpy(algId[0]->parameters.data, buf2, buf2_len);
+ algId[0]->parameters.length = buf2_len;
+ algId[0]->algorithm = dh_oid;
+
+ algId[1] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+ if (algId[1] == NULL)
+ goto cleanup;
+ algId[1]->parameters.data = (unsigned char *)malloc(buf3_len);
+ if (algId[1]->parameters.data == NULL)
+ goto cleanup;
+ (void) memcpy(algId[1]->parameters.data, buf3, buf3_len);
+ algId[1]->parameters.length = buf3_len;
+ algId[1]->algorithm = dh_oid;
+
+ } else if (opts->dh_min_bits <= 4096) {
+ algId = malloc(2 * sizeof(krb5_algorithm_identifier *));
+ if (algId == NULL)
+ goto cleanup;
+ algId[1] = NULL;
+ algId[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+ if (algId[0] == NULL)
+ goto cleanup;
+ algId[0]->parameters.data = (unsigned char *)malloc(buf3_len);
+ if (algId[0]->parameters.data == NULL)
+ goto cleanup;
+ (void) memcpy(algId[0]->parameters.data, buf3, buf3_len);
+ algId[0]->parameters.length = buf3_len;
+ algId[0]->algorithm = dh_oid;
+
+ }
+ retval = k5int_encode_krb5_td_dh_parameters((const krb5_algorithm_identifier **)algId, &encoded_algId);
+ if (retval)
+ goto cleanup;
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)encoded_algId->data,
+ encoded_algId->length, "/tmp/kdc_td_dh_params");
+#endif
+ typed_data = malloc (2 * sizeof(krb5_typed_data *));
+ if (typed_data == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ typed_data[1] = NULL;
+ init_krb5_typed_data(&typed_data[0]);
+ if (typed_data == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ typed_data[0]->type = TD_DH_PARAMETERS;
+ typed_data[0]->length = encoded_algId->length;
+ typed_data[0]->data = (unsigned char *)encoded_algId->data;
+ retval = k5int_encode_krb5_typed_data((const krb5_typed_data**)typed_data,
+ &data);
+ if (retval) {
+ pkiDebug("encode_krb5_typed_data failed\n");
+ goto cleanup;
+ }
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)data->data, data->length,
+ "/tmp/kdc_edata");
+#endif
+ *out_data = (krb5_data *)malloc(sizeof(krb5_data));
+ if (*out_data == NULL)
+ goto cleanup;
+ (*out_data)->length = data->length;
+ (*out_data)->data = (char *)malloc(data->length);
+ if ((*out_data)->data == NULL) {
+ free(*out_data);
+ *out_data = NULL;
+ goto cleanup;
+ }
+ (void) memcpy((*out_data)->data, data->data, data->length);
+
+ retval = 0;
+cleanup:
+
+ if (buf1 != NULL)
+ free(buf1);
+ if (buf2 != NULL)
+ free(buf2);
+ if (buf3 != NULL)
+ free(buf3);
+ if (data != NULL) {
+ if (data->data != NULL)
+ free(data->data);
+ free(data);
+ }
+ if (typed_data != NULL)
+ free_krb5_typed_data(&typed_data);
+ if (encoded_algId != NULL)
+ free(encoded_algId);
+
+ if (algId != NULL) {
+ while(algId[i] != NULL) {
+ if (algId[i]->parameters.data != NULL)
+ free(algId[i]->parameters.data);
+ free(algId[i]);
+ i++;
+ }
+ free(algId);
+ }
+
+ return retval;
+}
+
+/* ARGSUSED */
+krb5_error_code
+pkinit_check_kdc_pkid(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *pdid_buf,
+ unsigned int pkid_len,
+ int *valid_kdcPkId)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ PKCS7_ISSUER_AND_SERIAL *is = NULL;
+ const unsigned char *p = pdid_buf;
+ int status = 1;
+ X509 *kdc_cert = sk_X509_value(id_cryptoctx->my_certs, id_cryptoctx->cert_index);
+
+ *valid_kdcPkId = 0;
+ pkiDebug("found kdcPkId in AS REQ\n");
+ is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p, (int)pkid_len);
+ if (is == NULL)
+ goto cleanup;
+
+ status = X509_NAME_cmp(X509_get_issuer_name(kdc_cert), is->issuer);
+ if (!status) {
+ status = ASN1_INTEGER_cmp(X509_get_serialNumber(kdc_cert), is->serial);
+ if (!status)
+ *valid_kdcPkId = 1;
+ }
+
+ retval = 0;
+cleanup:
+ X509_NAME_free(is->issuer);
+ ASN1_INTEGER_free(is->serial);
+ free(is);
+
+ return retval;
+}
+
+static int
+pkinit_check_dh_params(BIGNUM * p1, BIGNUM * p2, BIGNUM * g1, BIGNUM * q1)
+{
+ BIGNUM *g2 = NULL, *q2 = NULL;
+ /* Solaris Kerberos */
+ int retval = EINVAL;
+
+ if (!BN_cmp(p1, p2)) {
+ g2 = BN_new();
+ BN_set_word(g2, DH_GENERATOR_2);
+ if (!BN_cmp(g1, g2)) {
+ q2 = BN_new();
+ BN_rshift1(q2, p1);
+ if (!BN_cmp(q1, q2)) {
+ pkiDebug("good %d dhparams\n", BN_num_bits(p1));
+ retval = 0;
+ } else
+ pkiDebug("bad group 2 q dhparameter\n");
+ BN_free(q2);
+ } else
+ pkiDebug("bad g dhparameter\n");
+ BN_free(g2);
+ } else
+ pkiDebug("p is not well-known group 2 dhparameter\n");
+
+ return retval;
+}
+
+/* ARGSUSED */
+krb5_error_code
+pkinit_process_td_dh_params(krb5_context context,
+ pkinit_plg_crypto_context cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_algorithm_identifier **algId,
+ int *new_dh_size)
+{
+ krb5_error_code retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
+ int i = 0, use_sent_dh = 0, ok = 0;
+
+ pkiDebug("dh parameters\n");
+
+ while (algId[i] != NULL) {
+ DH *dh = NULL;
+ unsigned char *tmp = NULL;
+ int dh_prime_bits = 0;
+
+ if (algId[i]->algorithm.length != dh_oid.length ||
+ memcmp(algId[i]->algorithm.data, dh_oid.data, dh_oid.length))
+ goto cleanup;
+
+ tmp = algId[i]->parameters.data;
+ dh = DH_new();
+ dh = pkinit_decode_dh_params(&dh, &tmp, algId[i]->parameters.length);
+ dh_prime_bits = BN_num_bits(dh->p);
+ pkiDebug("client sent %d DH bits server prefers %d DH bits\n",
+ *new_dh_size, dh_prime_bits);
+ switch(dh_prime_bits) {
+ case 1024:
+ if (pkinit_check_dh_params(cryptoctx->dh_1024->p, dh->p,
+ dh->g, dh->q) == 0) {
+ *new_dh_size = 1024;
+ ok = 1;
+ }
+ break;
+ case 2048:
+ if (pkinit_check_dh_params(cryptoctx->dh_2048->p, dh->p,
+ dh->g, dh->q) == 0) {
+ *new_dh_size = 2048;
+ ok = 1;
+ }
+ break;
+ case 4096:
+ if (pkinit_check_dh_params(cryptoctx->dh_4096->p, dh->p,
+ dh->g, dh->q) == 0) {
+ *new_dh_size = 4096;
+ ok = 1;
+ }
+ break;
+ default:
+ break;
+ }
+ if (!ok) {
+ DH_check(dh, &retval);
+ if (retval != 0) {
+ pkiDebug("DH parameters provided by server are unacceptable\n");
+ retval = KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED;
+ }
+ else {
+ use_sent_dh = 1;
+ ok = 1;
+ }
+ }
+ if (!use_sent_dh)
+ DH_free(dh);
+ if (ok) {
+ if (req_cryptoctx->dh != NULL) {
+ DH_free(req_cryptoctx->dh);
+ req_cryptoctx->dh = NULL;
+ }
+ if (use_sent_dh)
+ req_cryptoctx->dh = dh;
+ break;
+ }
+ i++;
+ }
+
+ if (ok)
+ retval = 0;
+
+cleanup:
+ return retval;
+}
+
+/* ARGSUSED */
+static int
+openssl_callback(int ok, X509_STORE_CTX * ctx)
+{
+#ifdef DEBUG
+ if (!ok) {
+ char buf[DN_BUF_LEN];
+
+ X509_NAME_oneline(X509_get_subject_name(ctx->current_cert), buf, sizeof(buf));
+ pkiDebug("cert = %s\n", buf);
+ pkiDebug("callback function: %d (%s)\n", ctx->error,
+ X509_verify_cert_error_string(ctx->error));
+ }
+#endif
+ return ok;
+}
+
+static int
+openssl_callback_ignore_crls(int ok, X509_STORE_CTX * ctx)
+{
+ if (!ok) {
+ switch (ctx->error) {
+ case X509_V_ERR_UNABLE_TO_GET_CRL:
+ return 1;
+ default:
+ return 0;
+ }
+ }
+ return ok;
+}
+
+static ASN1_OBJECT *
+pkinit_pkcs7type2oid(pkinit_plg_crypto_context cryptoctx, int pkcs7_type)
+{
+ int nid;
+
+ switch (pkcs7_type) {
+ case CMS_SIGN_CLIENT:
+ return cryptoctx->id_pkinit_authData;
+ case CMS_SIGN_DRAFT9:
+ /*
+ * Delay creating this OID until we know we need it.
+ * It shadows an existing OpenSSL oid. If it
+ * is created too early, it breaks things like
+ * the use of pkcs12 (which uses pkcs7 structures).
+ * We need this shadow version because our code
+ * depends on the "other" type to be unknown to the
+ * OpenSSL code.
+ */
+ if (cryptoctx->id_pkinit_authData9 == NULL) {
+ pkiDebug("%s: Creating shadow instance of pkcs7-data oid\n",
+ __FUNCTION__);
+ nid = OBJ_create("1.2.840.113549.1.7.1", "id-pkcs7-data",
+ "PKCS7 data");
+ if (nid == NID_undef)
+ return NULL;
+ cryptoctx->id_pkinit_authData9 = OBJ_nid2obj(nid);
+ }
+ return cryptoctx->id_pkinit_authData9;
+ case CMS_SIGN_SERVER:
+ return cryptoctx->id_pkinit_DHKeyData;
+ case CMS_ENVEL_SERVER:
+ return cryptoctx->id_pkinit_rkeyData;
+ default:
+ return NULL;
+ }
+
+}
+
+#ifdef LONGHORN_BETA_COMPAT
+#if 0
+/*
+ * This is a version that worked with Longhorn Beta 3.
+ */
+static int
+wrap_signeddata(unsigned char *data, unsigned int data_len,
+ unsigned char **out, unsigned int *out_len,
+ int is_longhorn_server)
+{
+
+ unsigned int orig_len = 0, oid_len = 0, tot_len = 0;
+ ASN1_OBJECT *oid = NULL;
+ unsigned char *p = NULL;
+
+ pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n",
+ __FUNCTION__, is_longhorn_server);
+
+ /* Get length to wrap the original data with SEQUENCE tag */
+ tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE);
+
+ if (is_longhorn_server == 0) {
+ /* Add the signedData OID and adjust lengths */
+ oid = OBJ_nid2obj(NID_pkcs7_signed);
+ oid_len = i2d_ASN1_OBJECT(oid, NULL);
+
+ tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE);
+ }
+
+ p = *out = (unsigned char *)malloc(tot_len);
+ if (p == NULL) return -1;
+
+ if (is_longhorn_server == 0) {
+ ASN1_put_object(&p, 1, (int)(orig_len+oid_len),
+ V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
+
+ i2d_ASN1_OBJECT(oid, &p);
+
+ ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC);
+ } else {
+ ASN1_put_object(&p, 1, (int)data_len, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
+ }
+ memcpy(p, data, data_len);
+
+ *out_len = tot_len;
+
+ return 0;
+}
+#else
+/*
+ * This is a version that works with a patched Longhorn KDC.
+ * (Which should match SP1 ??).
+ */
+static int
+wrap_signeddata(unsigned char *data, unsigned int data_len,
+ unsigned char **out, unsigned int *out_len,
+ int is_longhorn_server)
+{
+
+ unsigned int oid_len = 0, tot_len = 0, wrap_len = 0, tag_len = 0;
+ ASN1_OBJECT *oid = NULL;
+ unsigned char *p = NULL;
+
+ pkiDebug("%s: This is the Longhorn version and is_longhorn_server = %d\n",
+ __FUNCTION__, is_longhorn_server);
+
+ /* New longhorn is missing another sequence */
+ if (is_longhorn_server == 1)
+ wrap_len = ASN1_object_size(1, (int)(data_len), V_ASN1_SEQUENCE);
+ else
+ wrap_len = data_len;
+
+ /* Get length to wrap the original data with SEQUENCE tag */
+ tag_len = ASN1_object_size(1, (int)wrap_len, V_ASN1_SEQUENCE);
+
+ /* Always add oid */
+ oid = OBJ_nid2obj(NID_pkcs7_signed);
+ oid_len = i2d_ASN1_OBJECT(oid, NULL);
+ oid_len += tag_len;
+
+ tot_len = ASN1_object_size(1, (int)(oid_len), V_ASN1_SEQUENCE);
+
+ p = *out = (unsigned char *)malloc(tot_len);
+ if (p == NULL)
+ return -1;
+
+ ASN1_put_object(&p, 1, (int)(oid_len),
+ V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
+
+ i2d_ASN1_OBJECT(oid, &p);
+
+ ASN1_put_object(&p, 1, (int)wrap_len, 0, V_ASN1_CONTEXT_SPECIFIC);
+
+ /* Wrap in extra seq tag */
+ if (is_longhorn_server == 1) {
+ ASN1_put_object(&p, 1, (int)data_len, V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
+ }
+ (void) memcpy(p, data, data_len);
+
+ *out_len = tot_len;
+
+ return 0;
+}
+
+#endif
+#else
+static int
+wrap_signeddata(unsigned char *data, unsigned int data_len,
+ unsigned char **out, unsigned int *out_len)
+{
+
+ unsigned int orig_len = 0, oid_len = 0, tot_len = 0;
+ ASN1_OBJECT *oid = NULL;
+ unsigned char *p = NULL;
+
+ /* Get length to wrap the original data with SEQUENCE tag */
+ tot_len = orig_len = ASN1_object_size(1, (int)data_len, V_ASN1_SEQUENCE);
+
+ /* Add the signedData OID and adjust lengths */
+ oid = OBJ_nid2obj(NID_pkcs7_signed);
+ oid_len = i2d_ASN1_OBJECT(oid, NULL);
+
+ tot_len = ASN1_object_size(1, (int)(orig_len+oid_len), V_ASN1_SEQUENCE);
+
+ p = *out = (unsigned char *)malloc(tot_len);
+ if (p == NULL) return -1;
+
+ ASN1_put_object(&p, 1, (int)(orig_len+oid_len),
+ V_ASN1_SEQUENCE, V_ASN1_UNIVERSAL);
+
+ i2d_ASN1_OBJECT(oid, &p);
+
+ ASN1_put_object(&p, 1, (int)data_len, 0, V_ASN1_CONTEXT_SPECIFIC);
+ (void) memcpy(p, data, data_len);
+
+ *out_len = tot_len;
+
+ return 0;
+}
+#endif
+
+static int
+prepare_enc_data(unsigned char *indata,
+ int indata_len,
+ unsigned char **outdata,
+ int *outdata_len)
+{
+ /* Solaris Kerberos */
+ ASN1_const_CTX c;
+ long length = indata_len;
+ int Ttag, Tclass;
+ long Tlen;
+
+ c.pp = (const unsigned char **)&indata;
+ c.q = *(const unsigned char **)&indata;
+ c.error = ERR_R_NESTED_ASN1_ERROR;
+ c.p= *(const unsigned char **)&indata;
+ c.max = (length == 0)?0:(c.p+length);
+
+ asn1_GetSequence(&c,&length);
+
+ ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen);
+ c.p += Tlen;
+ ASN1_get_object(&c.p,&Tlen,&Ttag,&Tclass,c.slen);
+
+ asn1_const_Finish(&c);
+
+ *outdata = (unsigned char *)malloc((size_t)Tlen);
+ /* Solaris Kerberos */
+ if (outdata == NULL)
+ return ENOMEM;
+
+ (void) memcpy(*outdata, c.p, (size_t)Tlen);
+ *outdata_len = Tlen;
+
+ return 0;
+}
+
+#ifndef WITHOUT_PKCS11
+static void *
+pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p)
+{
+ void *handle;
+ CK_RV (*getflist)(CK_FUNCTION_LIST_PTR_PTR);
+
+ pkiDebug("loading module \"%s\"... ", modname);
+ /* Solaris Kerberos */
+ handle = dlopen(modname, RTLD_NOW | RTLD_GROUP);
+ if (handle == NULL) {
+ pkiDebug("not found\n");
+ return NULL;
+ }
+ getflist = (CK_RV (*)(CK_FUNCTION_LIST_PTR_PTR)) dlsym(handle, "C_GetFunctionList");
+ if (getflist == NULL || (*getflist)(p11p) != CKR_OK) {
+ (void) dlclose(handle);
+ pkiDebug("failed\n");
+ return NULL;
+ }
+ pkiDebug("ok\n");
+ return handle;
+}
+
+static CK_RV
+pkinit_C_UnloadModule(void *handle)
+{
+ /* Solaris Kerberos */
+ if (dlclose(handle) != 0)
+ return CKR_GENERAL_ERROR;
+
+ return CKR_OK;
+}
+
+static krb5_error_code
+pkinit_login(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ CK_TOKEN_INFO *tip)
+{
+ krb5_data rdat;
+ char *prompt;
+ int prompt_len;
+ krb5_prompt kprompt;
+ krb5_prompt_type prompt_type;
+ int r = 0;
+
+ if (tip->flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
+ rdat.data = NULL;
+ rdat.length = 0;
+ } else {
+ /* Solaris Kerberos - Changes for gettext() */
+ prompt_len = sizeof (tip->label) + 256;
+ if ((prompt = (char *) malloc(prompt_len)) == NULL)
+ return ENOMEM;
+ (void) snprintf(prompt, prompt_len, gettext("%.*s PIN"), sizeof (tip->label), tip->label);
+ /* Solaris Kerberos */
+ if (tip->flags & CKF_USER_PIN_LOCKED)
+ (void) strlcat(prompt, gettext(" (Warning: PIN locked)"), prompt_len);
+ else if (tip->flags & CKF_USER_PIN_FINAL_TRY)
+ (void) strlcat(prompt, gettext(" (Warning: PIN final try)"), prompt_len);
+ else if (tip->flags & CKF_USER_PIN_COUNT_LOW)
+ (void) strlcat(prompt, gettext(" (Warning: PIN count low)"), prompt_len);
+ rdat.data = (char *)malloc(tip->ulMaxPinLen + 2);
+ rdat.length = tip->ulMaxPinLen + 1;
+
+ kprompt.prompt = prompt;
+ kprompt.hidden = 1;
+ kprompt.reply = &rdat;
+ prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
+
+ /* PROMPTER_INVOCATION */
+ k5int_set_prompt_types(context, &prompt_type);
+ r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
+ NULL, NULL, 1, &kprompt);
+ k5int_set_prompt_types(context, 0);
+ free(prompt);
+ }
+
+ if (r == 0) {
+ r = id_cryptoctx->p11->C_Login(id_cryptoctx->session, CKU_USER,
+ (u_char *) rdat.data, rdat.length);
+
+ if (r != CKR_OK) {
+ pkiDebug("C_Login: %s\n", pkinit_pkcs11_code_to_text(r));
+ /* Solaris Kerberos: Improved error messages */
+ krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
+ gettext("failed to log into token: %s"),
+ pkinit_pkcs11_code_to_text(r));
+ r = KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ }
+ if (rdat.data)
+ free(rdat.data);
+
+ return r;
+}
+
+static krb5_error_code
+pkinit_open_session(krb5_context context,
+ pkinit_identity_crypto_context cctx)
+{
+ int i, r;
+ unsigned char *cp;
+ CK_ULONG count = 0;
+ CK_SLOT_ID_PTR slotlist;
+ CK_TOKEN_INFO tinfo;
+
+ if (cctx->p11_module != NULL)
+ return 0; /* session already open */
+
+ /* Load module */
+ cctx->p11_module =
+ pkinit_C_LoadModule(cctx->p11_module_name, &cctx->p11);
+ if (cctx->p11_module == NULL)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+
+ /* Init */
+ /* Solaris Kerberos: Don't fail if cryptoki is already initialized */
+ r = cctx->p11->C_Initialize(NULL);
+ if (r != CKR_OK && r != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
+ pkiDebug("C_Initialize: %s\n", pkinit_pkcs11_code_to_text(r));
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ /*
+ * Solaris Kerberos:
+ * If C_Initialize was already called by the process before the pkinit
+ * module was loaded then record that fact.
+ * "finalize_pkcs11" is used by pkinit_fini_pkcs11 to determine whether
+ * or not C_Finalize() should be called.
+ */
+ cctx->finalize_pkcs11 =
+ (r == CKR_CRYPTOKI_ALREADY_INITIALIZED ? FALSE : TRUE);
+
+ /* Get the list of available slots */
+ if (cctx->slotid != PK_NOSLOT) {
+ /* A slot was specified, so that's the only one in the list */
+ count = 1;
+ slotlist = (CK_SLOT_ID_PTR) malloc(sizeof (CK_SLOT_ID));
+ slotlist[0] = cctx->slotid;
+ } else {
+ if (cctx->p11->C_GetSlotList(TRUE, NULL, &count) != CKR_OK)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ if (count == 0)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ slotlist = (CK_SLOT_ID_PTR) malloc(count * sizeof (CK_SLOT_ID));
+ if (cctx->p11->C_GetSlotList(TRUE, slotlist, &count) != CKR_OK)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ /* Look for the given token label, or if none given take the first one */
+ for (i = 0; i < count; i++) {
+ /* Open session */
+ if ((r = cctx->p11->C_OpenSession(slotlist[i], CKF_SERIAL_SESSION,
+ NULL, NULL, &cctx->session)) != CKR_OK) {
+ pkiDebug("C_OpenSession: %s\n", pkinit_pkcs11_code_to_text(r));
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ /* Get token info */
+ if ((r = cctx->p11->C_GetTokenInfo(slotlist[i], &tinfo)) != CKR_OK) {
+ pkiDebug("C_GetTokenInfo: %s\n", pkinit_pkcs11_code_to_text(r));
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ for (cp = tinfo.label + sizeof (tinfo.label) - 1;
+ *cp == '\0' || *cp == ' '; cp--)
+ *cp = '\0';
+ pkiDebug("open_session: slotid %d token \"%s\"\n",
+ (int) slotlist[i], tinfo.label);
+ if (cctx->token_label == NULL ||
+ !strcmp((char *) cctx->token_label, (char *) tinfo.label))
+ break;
+ cctx->p11->C_CloseSession(cctx->session);
+ }
+ if (i >= count) {
+ free(slotlist);
+ pkiDebug("open_session: no matching token found\n");
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ cctx->slotid = slotlist[i];
+ free(slotlist);
+ pkiDebug("open_session: slotid %d (%d of %d)\n", (int) cctx->slotid,
+ i + 1, (int) count);
+
+ /* Login if needed */
+ if (tinfo.flags & CKF_LOGIN_REQUIRED)
+ r = pkinit_login(context, cctx, &tinfo);
+
+ return r;
+}
+
+/*
+ * Look for a key that's:
+ * 1. private
+ * 2. capable of the specified operation (usually signing or decrypting)
+ * 3. RSA (this may be wrong but it's all we can do for now)
+ * 4. matches the id of the cert we chose
+ *
+ * You must call pkinit_get_certs before calling pkinit_find_private_key
+ * (that's because we need the ID of the private key)
+ *
+ * pkcs11 says the id of the key doesn't have to match that of the cert, but
+ * I can't figure out any other way to decide which key to use.
+ *
+ * We should only find one key that fits all the requirements.
+ * If there are more than one, we just take the first one.
+ */
+
+/* ARGSUSED */
+krb5_error_code
+pkinit_find_private_key(pkinit_identity_crypto_context id_cryptoctx,
+ CK_ATTRIBUTE_TYPE usage,
+ CK_OBJECT_HANDLE *objp)
+{
+ CK_OBJECT_CLASS cls;
+ CK_ATTRIBUTE attrs[4];
+ CK_ULONG count;
+ CK_KEY_TYPE keytype;
+ unsigned int nattrs = 0;
+ int r;
+#ifdef PKINIT_USE_KEY_USAGE
+ CK_BBOOL true_false;
+#endif
+
+ cls = CKO_PRIVATE_KEY;
+ attrs[nattrs].type = CKA_CLASS;
+ attrs[nattrs].pValue = &cls;
+ attrs[nattrs].ulValueLen = sizeof cls;
+ nattrs++;
+
+#ifdef PKINIT_USE_KEY_USAGE
+ /*
+ * Some cards get confused if you try to specify a key usage,
+ * so don't, and hope for the best. This will fail if you have
+ * several keys with the same id and different usages but I have
+ * not seen this on real cards.
+ */
+ true_false = TRUE;
+ attrs[nattrs].type = usage;
+ attrs[nattrs].pValue = &true_false;
+ attrs[nattrs].ulValueLen = sizeof true_false;
+ nattrs++;
+#endif
+
+ keytype = CKK_RSA;
+ attrs[nattrs].type = CKA_KEY_TYPE;
+ attrs[nattrs].pValue = &keytype;
+ attrs[nattrs].ulValueLen = sizeof keytype;
+ nattrs++;
+
+ attrs[nattrs].type = CKA_ID;
+ attrs[nattrs].pValue = id_cryptoctx->cert_id;
+ attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
+ nattrs++;
+
+ r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
+ if (r != CKR_OK) {
+ pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
+ pkinit_pkcs11_code_to_text(r));
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count);
+ id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
+ pkiDebug("found %d private keys (%s)\n", (int) count, pkinit_pkcs11_code_to_text(r));
+
+ /*
+ * Solaris Kerberos:
+ * The CKA_ID may not be correctly set for the private key. For e.g. when
+ * storing a private key in softtoken pktool(1) doesn't generate or store
+ * a CKA_ID for the private key. Another way to identify the private key is
+ * to look for a private key with the same RSA modulus as the public key
+ * in the certificate.
+ */
+ if (r == CKR_OK && count != 1) {
+
+ EVP_PKEY *priv;
+ X509 *cert;
+ unsigned int n_len;
+ unsigned char *n_bytes;
+
+ cert = sk_X509_value(id_cryptoctx->my_certs, 0);
+ priv = X509_get_pubkey(cert);
+ if (priv == NULL) {
+ pkiDebug("Failed to extract pub key from cert\n");
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ nattrs = 0;
+ cls = CKO_PRIVATE_KEY;
+ attrs[nattrs].type = CKA_CLASS;
+ attrs[nattrs].pValue = &cls;
+ attrs[nattrs].ulValueLen = sizeof cls;
+ nattrs++;
+
+#ifdef PKINIT_USE_KEY_USAGE
+ true_false = TRUE;
+ attrs[nattrs].type = usage;
+ attrs[nattrs].pValue = &true_false;
+ attrs[nattrs].ulValueLen = sizeof true_false;
+ nattrs++;
+#endif
+
+ keytype = CKK_RSA;
+ attrs[nattrs].type = CKA_KEY_TYPE;
+ attrs[nattrs].pValue = &keytype;
+ attrs[nattrs].ulValueLen = sizeof keytype;
+ nattrs++;
+
+ n_len = BN_num_bytes(priv->pkey.rsa->n);
+ n_bytes = (unsigned char *) malloc((size_t) n_len);
+ if (n_bytes == NULL) {
+ return (ENOMEM);
+ }
+
+ if (BN_bn2bin(priv->pkey.rsa->n, n_bytes) == 0) {
+ free (n_bytes);
+ pkiDebug("zero-byte key modulus\n");
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ attrs[nattrs].type = CKA_MODULUS;
+ attrs[nattrs].ulValueLen = n_len;
+ attrs[nattrs].pValue = n_bytes;
+
+ nattrs++;
+
+ r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
+ free (n_bytes);
+ if (r != CKR_OK) {
+ pkiDebug("krb5_pkinit_sign_data: C_FindObjectsInit: %s\n",
+ pkinit_pkcs11_code_to_text(r));
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session, objp, 1, &count);
+ id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
+ pkiDebug("found %d private keys (%s)\n", (int) count, pkinit_pkcs11_code_to_text(r));
+
+ }
+
+ if (r != CKR_OK || count < 1)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ return 0;
+}
+#endif
+
+/* ARGSUSED */
+static krb5_error_code
+pkinit_decode_data_fs(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *data,
+ unsigned int data_len,
+ unsigned char **decoded_data,
+ unsigned int *decoded_data_len)
+{
+ if (decode_data(decoded_data, decoded_data_len, data, data_len,
+ id_cryptoctx->my_key, sk_X509_value(id_cryptoctx->my_certs,
+ id_cryptoctx->cert_index)) <= 0) {
+ pkiDebug("failed to decode data\n");
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ return 0;
+}
+
+#ifndef WITHOUT_PKCS11
+#ifdef SILLYDECRYPT
+CK_RV
+pkinit_C_Decrypt(pkinit_identity_crypto_context id_cryptoctx,
+ CK_BYTE_PTR pEncryptedData,
+ CK_ULONG ulEncryptedDataLen,
+ CK_BYTE_PTR pData,
+ CK_ULONG_PTR pulDataLen)
+{
+ CK_RV rv = CKR_OK;
+
+ rv = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, pEncryptedData,
+ ulEncryptedDataLen, pData, pulDataLen);
+ if (rv == CKR_OK) {
+ pkiDebug("pData %x *pulDataLen %d\n", (int) pData, (int) *pulDataLen);
+ }
+ return rv;
+}
+#endif
+
+static krb5_error_code
+pkinit_decode_data_pkcs11(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *data,
+ unsigned int data_len,
+ unsigned char **decoded_data,
+ unsigned int *decoded_data_len)
+{
+ CK_OBJECT_HANDLE obj;
+ CK_ULONG len;
+ CK_MECHANISM mech;
+ unsigned char *cp;
+ int r;
+
+ if (pkinit_open_session(context, id_cryptoctx)) {
+ pkiDebug("can't open pkcs11 session\n");
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ /* Solaris Kerberos */
+ r = pkinit_find_private_key(id_cryptoctx, CKA_DECRYPT, &obj);
+ if (r != 0)
+ return r;
+
+ mech.mechanism = CKM_RSA_PKCS;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ if ((r = id_cryptoctx->p11->C_DecryptInit(id_cryptoctx->session, &mech,
+ obj)) != CKR_OK) {
+ pkiDebug("C_DecryptInit: 0x%x\n", (int) r);
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ pkiDebug("data_len = %d\n", data_len);
+ cp = (unsigned char *)malloc((size_t) data_len);
+ if (cp == NULL)
+ return ENOMEM;
+ len = data_len;
+#ifdef SILLYDECRYPT
+ pkiDebug("session %x edata %x edata_len %d data %x datalen @%x %d\n",
+ (int) id_cryptoctx->session, (int) data, (int) data_len, (int) cp,
+ (int) &len, (int) len);
+ if ((r = pkinit_C_Decrypt(id_cryptoctx, data, (CK_ULONG) data_len,
+ cp, &len)) != CKR_OK) {
+#else
+ if ((r = id_cryptoctx->p11->C_Decrypt(id_cryptoctx->session, data,
+ (CK_ULONG) data_len, cp, &len)) != CKR_OK) {
+#endif
+ pkiDebug("C_Decrypt: %s\n", pkinit_pkcs11_code_to_text(r));
+ if (r == CKR_BUFFER_TOO_SMALL)
+ pkiDebug("decrypt %d needs %d\n", (int) data_len, (int) len);
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ pkiDebug("decrypt %d -> %d\n", (int) data_len, (int) len);
+ *decoded_data_len = len;
+ *decoded_data = cp;
+
+ return 0;
+}
+#endif
+
+krb5_error_code
+pkinit_decode_data(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *data,
+ unsigned int data_len,
+ unsigned char **decoded_data,
+ unsigned int *decoded_data_len)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+
+ if (id_cryptoctx->pkcs11_method != 1)
+ retval = pkinit_decode_data_fs(context, id_cryptoctx, data, data_len,
+ decoded_data, decoded_data_len);
+#ifndef WITHOUT_PKCS11
+ else
+ retval = pkinit_decode_data_pkcs11(context, id_cryptoctx, data,
+ data_len, decoded_data, decoded_data_len);
+#endif
+
+ return retval;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+pkinit_sign_data_fs(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *data,
+ unsigned int data_len,
+ unsigned char **sig,
+ unsigned int *sig_len)
+{
+ if (create_signature(sig, sig_len, data, data_len,
+ id_cryptoctx->my_key) != 0) {
+ pkiDebug("failed to create the signature\n");
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ return 0;
+}
+
+#ifndef WITHOUT_PKCS11
+static krb5_error_code
+pkinit_sign_data_pkcs11(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *data,
+ unsigned int data_len,
+ unsigned char **sig,
+ unsigned int *sig_len)
+{
+ CK_OBJECT_HANDLE obj;
+ CK_ULONG len;
+ CK_MECHANISM mech;
+ unsigned char *cp;
+ int r;
+
+ if (pkinit_open_session(context, id_cryptoctx)) {
+ pkiDebug("can't open pkcs11 session\n");
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ /* Solaris Kerberos */
+ r = pkinit_find_private_key(id_cryptoctx, CKA_SIGN, &obj);
+ if (r != 0 )
+ return r;
+
+ mech.mechanism = id_cryptoctx->mech;
+ mech.pParameter = NULL;
+ mech.ulParameterLen = 0;
+
+ if ((r = id_cryptoctx->p11->C_SignInit(id_cryptoctx->session, &mech,
+ obj)) != CKR_OK) {
+ pkiDebug("C_SignInit: %s\n", pkinit_pkcs11_code_to_text(r));
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ /*
+ * Key len would give an upper bound on sig size, but there's no way to
+ * get that. So guess, and if it's too small, re-malloc.
+ */
+ len = PK_SIGLEN_GUESS;
+ cp = (unsigned char *)malloc((size_t) len);
+ if (cp == NULL)
+ return ENOMEM;
+
+ r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data,
+ (CK_ULONG) data_len, cp, &len);
+ if (r == CKR_BUFFER_TOO_SMALL || (r == CKR_OK && len >= PK_SIGLEN_GUESS)) {
+ free(cp);
+ pkiDebug("C_Sign realloc %d\n", (int) len);
+ cp = (unsigned char *)malloc((size_t) len);
+ r = id_cryptoctx->p11->C_Sign(id_cryptoctx->session, data,
+ (CK_ULONG) data_len, cp, &len);
+ }
+ if (r != CKR_OK) {
+ pkiDebug("C_Sign: %s\n", pkinit_pkcs11_code_to_text(r));
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ pkiDebug("sign %d -> %d\n", (int) data_len, (int) len);
+ *sig_len = len;
+ *sig = cp;
+
+ return 0;
+}
+#endif
+
+krb5_error_code
+pkinit_sign_data(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *data,
+ unsigned int data_len,
+ unsigned char **sig,
+ unsigned int *sig_len)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+
+ if (id_cryptoctx == NULL || id_cryptoctx->pkcs11_method != 1)
+ retval = pkinit_sign_data_fs(context, id_cryptoctx, data, data_len,
+ sig, sig_len);
+#ifndef WITHOUT_PKCS11
+ else
+ retval = pkinit_sign_data_pkcs11(context, id_cryptoctx, data, data_len,
+ sig, sig_len);
+#endif
+
+ return retval;
+}
+
+
+static krb5_error_code
+decode_data(unsigned char **out_data, unsigned int *out_data_len,
+ unsigned char *data, unsigned int data_len,
+ EVP_PKEY *pkey, X509 *cert)
+{
+ /* Solaris Kerberos */
+ int len;
+ unsigned char *buf = NULL;
+ int buf_len = 0;
+
+ /* Solaris Kerberos */
+ if (out_data == NULL || out_data_len == NULL)
+ return EINVAL;
+
+ if (cert && !X509_check_private_key(cert, pkey)) {
+ pkiDebug("private key does not match certificate\n");
+ /* Solaris Kerberos */
+ return EINVAL;
+ }
+
+ buf_len = EVP_PKEY_size(pkey);
+ buf = (unsigned char *)malloc((size_t) buf_len + 10);
+ if (buf == NULL)
+ return ENOMEM;
+
+ len = EVP_PKEY_decrypt(buf, data, (int)data_len, pkey);
+ if (len <= 0) {
+ pkiDebug("unable to decrypt received data (len=%d)\n", data_len);
+ /* Solaris Kerberos */
+ free(buf);
+ return KRB5KRB_ERR_GENERIC;
+ }
+ *out_data = buf;
+ *out_data_len = len;
+
+ return 0;
+}
+
+static krb5_error_code
+create_signature(unsigned char **sig, unsigned int *sig_len,
+ unsigned char *data, unsigned int data_len, EVP_PKEY *pkey)
+{
+ krb5_error_code retval = ENOMEM;
+ EVP_MD_CTX md_ctx;
+
+ if (pkey == NULL)
+ /* Solaris Kerberos */
+ return EINVAL;
+
+ EVP_VerifyInit(&md_ctx, EVP_sha1());
+ EVP_SignUpdate(&md_ctx, data, data_len);
+ *sig_len = EVP_PKEY_size(pkey);
+ if ((*sig = (unsigned char *) malloc((size_t) *sig_len)) == NULL)
+ goto cleanup;
+ EVP_SignFinal(&md_ctx, *sig, sig_len, pkey);
+
+ retval = 0;
+
+ cleanup:
+ EVP_MD_CTX_cleanup(&md_ctx);
+
+ return retval;
+}
+
+/*
+ * Note:
+ * This is not the routine the KDC uses to get its certificate.
+ * This routine is intended to be called by the client
+ * to obtain the KDC's certificate from some local storage
+ * to be sent as a hint in its request to the KDC.
+ */
+/* ARGSUSED */
+krb5_error_code
+pkinit_get_kdc_cert(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_principal princ)
+{
+ /* Solaris Kerberos */
+ if (req_cryptoctx == NULL)
+ return EINVAL;
+
+ req_cryptoctx->received_cert = NULL;
+ return 0;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+pkinit_get_certs_pkcs12(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_opts *idopts,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_principal princ)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ X509 *x = NULL;
+ PKCS12 *p12 = NULL;
+ int ret;
+ FILE *fp;
+ EVP_PKEY *y = NULL;
+
+ if (idopts->cert_filename == NULL) {
+ /* Solaris Kerberos: Improved error messages */
+ krb5_set_error_message(context, retval,
+ gettext("failed to get certificate location"));
+ pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
+ goto cleanup;
+ }
+
+ if (idopts->key_filename == NULL) {
+ /* Solaris Kerberos: Improved error messages */
+ krb5_set_error_message(context, retval,
+ gettext("failed to get private key location"));
+ pkiDebug("%s: failed to get user's private key location\n", __FUNCTION__);
+ goto cleanup;
+ }
+
+ fp = fopen(idopts->cert_filename, "rb");
+ if (fp == NULL) {
+ /* Solaris Kerberos: Improved error messages */
+ krb5_set_error_message(context, retval,
+ gettext("failed to open PKCS12 file '%s': %s"),
+ idopts->cert_filename, error_message(errno));
+ pkiDebug("Failed to open PKCS12 file '%s', error %d\n",
+ idopts->cert_filename, errno);
+ goto cleanup;
+ }
+
+ p12 = d2i_PKCS12_fp(fp, NULL);
+ (void) fclose(fp);
+ if (p12 == NULL) {
+ krb5_set_error_message(context, retval,
+ gettext("failed to decode PKCS12 file '%s' contents"),
+ idopts->cert_filename);
+ pkiDebug("Failed to decode PKCS12 file '%s' contents\n",
+ idopts->cert_filename);
+ goto cleanup;
+ }
+ /*
+ * Try parsing with no pass phrase first. If that fails,
+ * prompt for the pass phrase and try again.
+ */
+ ret = PKCS12_parse(p12, NULL, &y, &x, NULL);
+ if (ret == 0) {
+ krb5_data rdat;
+ krb5_prompt kprompt;
+ krb5_prompt_type prompt_type;
+ int r = 0;
+ char prompt_string[128];
+ char prompt_reply[128];
+ /* Solaris Kerberos */
+ char *prompt_prefix = gettext("Pass phrase for");
+
+ pkiDebug("Initial PKCS12_parse with no password failed\n");
+
+ (void) memset(prompt_reply, '\0', sizeof(prompt_reply));
+ rdat.data = prompt_reply;
+ rdat.length = sizeof(prompt_reply);
+
+ r = snprintf(prompt_string, sizeof(prompt_string), "%s %s",
+ prompt_prefix, idopts->cert_filename);
+ if (r >= sizeof(prompt_string)) {
+ pkiDebug("Prompt string, '%s %s', is too long!\n",
+ prompt_prefix, idopts->cert_filename);
+ goto cleanup;
+ }
+ kprompt.prompt = prompt_string;
+ kprompt.hidden = 1;
+ kprompt.reply = &rdat;
+ prompt_type = KRB5_PROMPT_TYPE_PREAUTH;
+
+ /* PROMPTER_INVOCATION */
+ k5int_set_prompt_types(context, &prompt_type);
+ r = (*id_cryptoctx->prompter)(context, id_cryptoctx->prompter_data,
+ NULL, NULL, 1, &kprompt);
+ k5int_set_prompt_types(context, 0);
+
+ ret = PKCS12_parse(p12, rdat.data, &y, &x, NULL);
+ if (ret == 0) {
+ /* Solaris Kerberos: Improved error messages */
+ krb5_set_error_message(context, retval,
+ gettext("failed to parse PKCS12 file '%s' with password"),
+ idopts->cert_filename);
+ pkiDebug("Seconde PKCS12_parse with password failed\n");
+ goto cleanup;
+ }
+ }
+ id_cryptoctx->creds[0] = malloc(sizeof(struct _pkinit_cred_info));
+ if (id_cryptoctx->creds[0] == NULL)
+ goto cleanup;
+ id_cryptoctx->creds[0]->cert = x;
+#ifndef WITHOUT_PKCS11
+ id_cryptoctx->creds[0]->cert_id = NULL;
+ id_cryptoctx->creds[0]->cert_id_len = 0;
+#endif
+ id_cryptoctx->creds[0]->key = y;
+ id_cryptoctx->creds[1] = NULL;
+
+ retval = 0;
+
+cleanup:
+ if (p12)
+ PKCS12_free(p12);
+ if (retval) {
+ if (x != NULL)
+ X509_free(x);
+ if (y != NULL)
+ EVP_PKEY_free(y);
+ }
+ return retval;
+}
+
+static krb5_error_code
+pkinit_load_fs_cert_and_key(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ char *certname,
+ char *keyname,
+ int cindex)
+{
+ krb5_error_code retval;
+ X509 *x = NULL;
+ EVP_PKEY *y = NULL;
+
+ /* load the certificate */
+ retval = get_cert(certname, &x);
+ if (retval != 0 || x == NULL) {
+ /* Solaris Kerberos: Improved error messages */
+ krb5_set_error_message(context, retval,
+ gettext("failed to load user's certificate from %s: %s"),
+ certname, error_message(retval));
+ pkiDebug("failed to load user's certificate from '%s'\n", certname);
+ goto cleanup;
+ }
+ retval = get_key(keyname, &y);
+ if (retval != 0 || y == NULL) {
+ /* Solaris Kerberos: Improved error messages */
+ krb5_set_error_message(context, retval,
+ gettext("failed to load user's private key from %s: %s"),
+ keyname, error_message(retval));
+ pkiDebug("failed to load user's private key from '%s'\n", keyname);
+ goto cleanup;
+ }
+
+ id_cryptoctx->creds[cindex] = malloc(sizeof(struct _pkinit_cred_info));
+ if (id_cryptoctx->creds[cindex] == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ id_cryptoctx->creds[cindex]->cert = x;
+#ifndef WITHOUT_PKCS11
+ id_cryptoctx->creds[cindex]->cert_id = NULL;
+ id_cryptoctx->creds[cindex]->cert_id_len = 0;
+#endif
+ id_cryptoctx->creds[cindex]->key = y;
+ id_cryptoctx->creds[cindex+1] = NULL;
+
+ retval = 0;
+
+cleanup:
+ if (retval) {
+ if (x != NULL)
+ X509_free(x);
+ if (y != NULL)
+ EVP_PKEY_free(y);
+ }
+ return retval;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+pkinit_get_certs_fs(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_opts *idopts,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_principal princ)
+{
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+
+ if (idopts->cert_filename == NULL) {
+ pkiDebug("%s: failed to get user's cert location\n", __FUNCTION__);
+ goto cleanup;
+ }
+
+ if (idopts->key_filename == NULL) {
+ pkiDebug("%s: failed to get user's private key location\n",
+ __FUNCTION__);
+ goto cleanup;
+ }
+
+ retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
+ idopts->cert_filename,
+ idopts->key_filename, 0);
+cleanup:
+ return retval;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+pkinit_get_certs_dir(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_opts *idopts,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_principal princ)
+{
+ /* Solaris Kerberos */
+ krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+ DIR *d = NULL;
+ struct dirent *dentry = NULL;
+ char certname[1024];
+ char keyname[1024];
+ int i = 0, len;
+ char *dirname, *suf;
+
+ /* Solaris Kerberos */
+ if (idopts == NULL)
+ return EINVAL;
+
+ if (idopts->cert_filename == NULL) {
+ pkiDebug("%s: failed to get user's certificate directory location\n",
+ __FUNCTION__);
+ return ENOENT;
+ }
+
+ dirname = idopts->cert_filename;
+ d = opendir(dirname);
+ if (d == NULL) {
+ /* Solaris Kerberos: Improved error messages */
+ krb5_set_error_message(context, errno,
+ gettext("failed to open directory \"%s\": %s"),
+ dirname, error_message(errno));
+ return errno;
+ }
+
+ /*
+ * We'll assume that certs are named XXX.crt and the corresponding
+ * key is named XXX.key
+ */
+ while ((i < MAX_CREDS_ALLOWED) && (dentry = readdir(d)) != NULL) {
+ /* Ignore subdirectories and anything starting with a dot */
+#ifdef DT_DIR
+ if (dentry->d_type == DT_DIR)
+ continue;
+#endif
+ if (dentry->d_name[0] == '.')
+ continue;
+ len = strlen(dentry->d_name);
+ if (len < 5)
+ continue;
+ suf = dentry->d_name + (len - 4);
+ if (strncmp(suf, ".crt", 4) != 0)
+ continue;
+
+ /* Checked length */
+ if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(certname)) {
+ pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
+ __FUNCTION__, dirname, dentry->d_name);
+ continue;
+ }
+ (void) snprintf(certname, sizeof(certname), "%s/%s", dirname, dentry->d_name);
+ (void) snprintf(keyname, sizeof(keyname), "%s/%s", dirname, dentry->d_name);
+ len = strlen(keyname);
+ keyname[len - 3] = 'k';
+ keyname[len - 2] = 'e';
+ keyname[len - 1] = 'y';
+
+ retval = pkinit_load_fs_cert_and_key(context, id_cryptoctx,
+ certname, keyname, i);
+ if (retval == 0) {
+ pkiDebug("%s: Successfully loaded cert (and key) for %s\n",
+ __FUNCTION__, dentry->d_name);
+ i++;
+ }
+ else
+ continue;
+ }
+
+ if (i == 0) {
+ /* Solaris Kerberos: Improved error messages */
+ krb5_set_error_message(context, ENOENT,
+ gettext("No suitable cert/key pairs found in directory '%s'"),
+ idopts->cert_filename);
+ pkiDebug("%s: No cert/key pairs found in directory '%s'\n",
+ __FUNCTION__, idopts->cert_filename);
+ retval = ENOENT;
+ goto cleanup;
+ }
+
+ retval = 0;
+
+ cleanup:
+ if (d)
+ (void) closedir(d);
+
+ return retval;
+}
+
+#ifndef WITHOUT_PKCS11
+/* ARGSUSED */
+static krb5_error_code
+pkinit_get_certs_pkcs11(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_opts *idopts,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_principal princ)
+{
+#ifdef PKINIT_USE_MECH_LIST
+ CK_MECHANISM_TYPE_PTR mechp;
+ CK_MECHANISM_INFO info;
+#endif
+ CK_OBJECT_CLASS cls;
+ CK_OBJECT_HANDLE obj;
+ CK_ATTRIBUTE attrs[4];
+ CK_ULONG count;
+ CK_CERTIFICATE_TYPE certtype;
+ CK_BYTE_PTR cert = NULL, cert_id;
+ const unsigned char *cp;
+ int i, r;
+ unsigned int nattrs;
+ X509 *x = NULL;
+
+ /* Copy stuff from idopts -> id_cryptoctx */
+ if (idopts->p11_module_name != NULL) {
+ id_cryptoctx->p11_module_name = strdup(idopts->p11_module_name);
+ if (id_cryptoctx->p11_module_name == NULL)
+ return ENOMEM;
+ }
+ if (idopts->token_label != NULL) {
+ id_cryptoctx->token_label = strdup(idopts->token_label);
+ if (id_cryptoctx->token_label == NULL)
+ return ENOMEM;
+ }
+ if (idopts->cert_label != NULL) {
+ id_cryptoctx->cert_label = strdup(idopts->cert_label);
+ if (id_cryptoctx->cert_label == NULL)
+ return ENOMEM;
+ }
+ /* Convert the ascii cert_id string into a binary blob */
+ /*
+ * Solaris Kerberos:
+ * If the cert_id_string is empty then behave in a similar way to how
+ * an empty certlabel is treated - i.e. don't fail now but rather continue
+ * as though the certid wasn't specified.
+ */
+ if (idopts->cert_id_string != NULL && strlen(idopts->cert_id_string) != 0) {
+ BIGNUM *bn = NULL;
+ BN_hex2bn(&bn, idopts->cert_id_string);
+ if (bn == NULL)
+ return ENOMEM;
+ id_cryptoctx->cert_id_len = BN_num_bytes(bn);
+ id_cryptoctx->cert_id = malloc((size_t) id_cryptoctx->cert_id_len);
+ if (id_cryptoctx->cert_id == NULL) {
+ BN_free(bn);
+ return ENOMEM;
+ }
+ BN_bn2bin(bn, id_cryptoctx->cert_id);
+ BN_free(bn);
+ }
+ id_cryptoctx->slotid = idopts->slotid;
+ id_cryptoctx->pkcs11_method = 1;
+
+
+
+ if (pkinit_open_session(context, id_cryptoctx)) {
+ pkiDebug("can't open pkcs11 session\n");
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+#ifndef PKINIT_USE_MECH_LIST
+ /*
+ * We'd like to use CKM_SHA1_RSA_PKCS for signing if it's available, but
+ * many cards seems to be confused about whether they are capable of
+ * this or not. The safe thing seems to be to ignore the mechanism list,
+ * always use CKM_RSA_PKCS and calculate the sha1 digest ourselves.
+ */
+
+ id_cryptoctx->mech = CKM_RSA_PKCS;
+#else
+ if ((r = id_cryptoctx->p11->C_GetMechanismList(id_cryptoctx->slotid, NULL,
+ &count)) != CKR_OK || count <= 0) {
+ pkiDebug("C_GetMechanismList: %s\n", pkinit_pkcs11_code_to_text(r));
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ mechp = (CK_MECHANISM_TYPE_PTR) malloc(count * sizeof (CK_MECHANISM_TYPE));
+ if (mechp == NULL)
+ return ENOMEM;
+ if ((r = id_cryptoctx->p11->C_GetMechanismList(id_cryptoctx->slotid,
+ mechp, &count)) != CKR_OK)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ for (i = 0; i < count; i++) {
+ if ((r = id_cryptoctx->p11->C_GetMechanismInfo(id_cryptoctx->slotid,
+ mechp[i], &info)) != CKR_OK)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+#ifdef DEBUG_MECHINFO
+ pkiDebug("mech %x flags %x\n", (int) mechp[i], (int) info.flags);
+ if ((info.flags & (CKF_SIGN|CKF_DECRYPT)) == (CKF_SIGN|CKF_DECRYPT))
+ pkiDebug(" this mech is good for sign & decrypt\n");
+#endif
+ if (mechp[i] == CKM_RSA_PKCS) {
+ /* This seems backwards... */
+ id_cryptoctx->mech =
+ (info.flags & CKF_SIGN) ? CKM_SHA1_RSA_PKCS : CKM_RSA_PKCS;
+ }
+ }
+ free(mechp);
+
+ pkiDebug("got %d mechs from card\n", (int) count);
+#endif
+
+ cls = CKO_CERTIFICATE;
+ attrs[0].type = CKA_CLASS;
+ attrs[0].pValue = &cls;
+ attrs[0].ulValueLen = sizeof cls;
+
+ certtype = CKC_X_509;
+ attrs[1].type = CKA_CERTIFICATE_TYPE;
+ attrs[1].pValue = &certtype;
+ attrs[1].ulValueLen = sizeof certtype;
+
+ nattrs = 2;
+
+ /* If a cert id and/or label were given, use them too */
+ if (id_cryptoctx->cert_id_len > 0) {
+ attrs[nattrs].type = CKA_ID;
+ attrs[nattrs].pValue = id_cryptoctx->cert_id;
+ attrs[nattrs].ulValueLen = id_cryptoctx->cert_id_len;
+ nattrs++;
+ }
+ if (id_cryptoctx->cert_label != NULL) {
+ attrs[nattrs].type = CKA_LABEL;
+ attrs[nattrs].pValue = id_cryptoctx->cert_label;
+ attrs[nattrs].ulValueLen = strlen(id_cryptoctx->cert_label);
+ nattrs++;
+ }
+
+ r = id_cryptoctx->p11->C_FindObjectsInit(id_cryptoctx->session, attrs, nattrs);
+ if (r != CKR_OK) {
+ pkiDebug("C_FindObjectsInit: %s\n", pkinit_pkcs11_code_to_text(r));
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ for (i = 0; ; i++) {
+ if (i >= MAX_CREDS_ALLOWED)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+
+ /* Look for x.509 cert */
+ /* Solaris Kerberos */
+ if ((r = id_cryptoctx->p11->C_FindObjects(id_cryptoctx->session,
+ &obj, 1, &count)) != CKR_OK || count == 0) {
+ id_cryptoctx->creds[i] = NULL;
+ break;
+ }
+
+ /* Get cert and id len */
+ attrs[0].type = CKA_VALUE;
+ attrs[0].pValue = NULL;
+ attrs[0].ulValueLen = 0;
+
+ attrs[1].type = CKA_ID;
+ attrs[1].pValue = NULL;
+ attrs[1].ulValueLen = 0;
+
+ if ((r = id_cryptoctx->p11->C_GetAttributeValue(id_cryptoctx->session,
+ obj, attrs, 2)) != CKR_OK && r != CKR_BUFFER_TOO_SMALL) {
+ pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r));
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ cert = (CK_BYTE_PTR) malloc((size_t) attrs[0].ulValueLen + 1);
+ cert_id = (CK_BYTE_PTR) malloc((size_t) attrs[1].ulValueLen + 1);
+ if (cert == NULL || cert_id == NULL)
+ return ENOMEM;
+
+ /* Read the cert and id off the card */
+
+ attrs[0].type = CKA_VALUE;
+ attrs[0].pValue = cert;
+
+ attrs[1].type = CKA_ID;
+ attrs[1].pValue = cert_id;
+
+ if ((r = id_cryptoctx->p11->C_GetAttributeValue(id_cryptoctx->session,
+ obj, attrs, 2)) != CKR_OK) {
+ pkiDebug("C_GetAttributeValue: %s\n", pkinit_pkcs11_code_to_text(r));
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+
+ pkiDebug("cert %d size %d id %d idlen %d\n", i,
+ (int) attrs[0].ulValueLen, (int) cert_id[0],
+ (int) attrs[1].ulValueLen);
+
+ cp = (unsigned char *) cert;
+ x = d2i_X509(NULL, &cp, (int) attrs[0].ulValueLen);
+ if (x == NULL)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ id_cryptoctx->creds[i] = malloc(sizeof(struct _pkinit_cred_info));
+ if (id_cryptoctx->creds[i] == NULL)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ id_cryptoctx->creds[i]->cert = x;
+ id_cryptoctx->creds[i]->key = NULL;
+ id_cryptoctx->creds[i]->cert_id = cert_id;
+ id_cryptoctx->creds[i]->cert_id_len = attrs[1].ulValueLen;
+ free(cert);
+ }
+ id_cryptoctx->p11->C_FindObjectsFinal(id_cryptoctx->session);
+ /* Solaris Kerberos: Improved error messages */
+ if (cert == NULL) {
+ if (r != CKR_OK) {
+ krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
+ gettext("pkcs11 error while searching for certificates: %s"),
+ pkinit_pkcs11_code_to_text(r));
+ } else {
+ BIGNUM *cid = BN_bin2bn(id_cryptoctx->cert_id,
+ id_cryptoctx->cert_id_len, NULL);
+ char *cidstr = BN_bn2hex(cid);
+ char *printstr = id_cryptoctx->cert_id_len ? cidstr : "<none>";
+
+ krb5_set_error_message(context, KRB5KDC_ERR_PREAUTH_FAILED,
+ gettext("failed to find any suitable certificates "
+ "(certlabel: %s, certid: %s)"),
+ id_cryptoctx->cert_label ? id_cryptoctx->cert_label : "<none>",
+ cidstr ? printstr : "<unknown>");
+
+ if (cidstr != NULL)
+ OPENSSL_free(cidstr);
+ BN_free(cid);
+ }
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+ }
+ return 0;
+}
+#endif
+
+/* ARGSUSED */
+static void
+free_cred_info(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ struct _pkinit_cred_info *cred)
+{
+ if (cred != NULL) {
+ if (cred->cert != NULL)
+ X509_free(cred->cert);
+ if (cred->key != NULL)
+ EVP_PKEY_free(cred->key);
+#ifndef WITHOUT_PKCS11
+ if (cred->cert_id != NULL)
+ free(cred->cert_id);
+#endif
+ free(cred);
+ }
+}
+
+/* ARGSUSED */
+krb5_error_code
+crypto_free_cert_info(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx)
+{
+ int i;
+
+ if (id_cryptoctx == NULL)
+ return EINVAL;
+
+ for (i = 0; i < MAX_CREDS_ALLOWED; i++) {
+ if (id_cryptoctx->creds[i] != NULL) {
+ free_cred_info(context, id_cryptoctx, id_cryptoctx->creds[i]);
+ id_cryptoctx->creds[i] = NULL;
+ }
+ }
+ return 0;
+}
+
+krb5_error_code
+crypto_load_certs(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_opts *idopts,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_principal princ)
+{
+ krb5_error_code retval;
+
+ switch(idopts->idtype) {
+ case IDTYPE_FILE:
+ retval = pkinit_get_certs_fs(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx, princ);
+ break;
+ case IDTYPE_DIR:
+ retval = pkinit_get_certs_dir(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx, princ);
+ break;
+#ifndef WITHOUT_PKCS11
+ case IDTYPE_PKCS11:
+ retval = pkinit_get_certs_pkcs11(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx, princ);
+ break;
+#endif
+ case IDTYPE_PKCS12:
+ retval = pkinit_get_certs_pkcs12(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx, princ);
+ break;
+ default:
+ retval = EINVAL;
+ }
+/* Solaris Kerberos */
+
+ return retval;
+}
+
+/*
+ * Get number of certificates available after crypto_load_certs()
+ */
+/* ARGSUSED */
+krb5_error_code
+crypto_cert_get_count(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ int *cert_count)
+{
+ int count;
+
+ if (id_cryptoctx == NULL || id_cryptoctx->creds[0] == NULL)
+ return EINVAL;
+
+ for (count = 0;
+ count <= MAX_CREDS_ALLOWED && id_cryptoctx->creds[count] != NULL;
+ count++);
+ *cert_count = count;
+ return 0;
+}
+
+
+/*
+ * Begin iteration over the certs loaded in crypto_load_certs()
+ */
+/* ARGSUSED */
+krb5_error_code
+crypto_cert_iteration_begin(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ pkinit_cert_iter_handle *ih_ret)
+{
+ struct _pkinit_cert_iter_data *id;
+
+ if (id_cryptoctx == NULL || ih_ret == NULL)
+ return EINVAL;
+ if (id_cryptoctx->creds[0] == NULL) /* No cred info available */
+ return ENOENT;
+
+ id = calloc(1, sizeof(*id));
+ if (id == NULL)
+ return ENOMEM;
+ id->magic = ITER_MAGIC;
+ id->plgctx = plg_cryptoctx,
+ id->reqctx = req_cryptoctx,
+ id->idctx = id_cryptoctx;
+ id->index = 0;
+ *ih_ret = (pkinit_cert_iter_handle) id;
+ return 0;
+}
+
+/*
+ * End iteration over the certs loaded in crypto_load_certs()
+ */
+/* ARGSUSED */
+krb5_error_code
+crypto_cert_iteration_end(krb5_context context,
+ pkinit_cert_iter_handle ih)
+{
+ struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih;
+
+ if (id == NULL || id->magic != ITER_MAGIC)
+ return EINVAL;
+ free(ih);
+ return 0;
+}
+
+/*
+ * Get next certificate handle
+ */
+/* ARGSUSED */
+krb5_error_code
+crypto_cert_iteration_next(krb5_context context,
+ pkinit_cert_iter_handle ih,
+ pkinit_cert_handle *ch_ret)
+{
+ struct _pkinit_cert_iter_data *id = (struct _pkinit_cert_iter_data *)ih;
+ struct _pkinit_cert_data *cd;
+ pkinit_identity_crypto_context id_cryptoctx;
+
+ if (id == NULL || id->magic != ITER_MAGIC)
+ return EINVAL;
+
+ if (ch_ret == NULL)
+ return EINVAL;
+
+ id_cryptoctx = id->idctx;
+ if (id_cryptoctx == NULL)
+ return EINVAL;
+
+ if (id_cryptoctx->creds[id->index] == NULL)
+ return PKINIT_ITER_NO_MORE;
+
+ cd = calloc(1, sizeof(*cd));
+ if (cd == NULL)
+ return ENOMEM;
+
+ cd->magic = CERT_MAGIC;
+ cd->plgctx = id->plgctx;
+ cd->reqctx = id->reqctx;
+ cd->idctx = id->idctx;
+ cd->index = id->index;
+ cd->cred = id_cryptoctx->creds[id->index++];
+ *ch_ret = (pkinit_cert_handle)cd;
+ return 0;
+}
+
+/*
+ * Release cert handle
+ */
+/* ARGSUSED */
+krb5_error_code
+crypto_cert_release(krb5_context context,
+ pkinit_cert_handle ch)
+{
+ struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch;
+ if (cd == NULL || cd->magic != CERT_MAGIC)
+ return EINVAL;
+ free(cd);
+ return 0;
+}
+
+/*
+ * Get certificate Key Usage and Extended Key Usage
+ */
+/* ARGSUSED */
+static krb5_error_code
+crypto_retieve_X509_key_usage(krb5_context context,
+ pkinit_plg_crypto_context plgcctx,
+ pkinit_req_crypto_context reqcctx,
+ X509 *x,
+ unsigned int *ret_ku_bits,
+ unsigned int *ret_eku_bits)
+{
+ /* Solaris Kerberos */
+ int i;
+ unsigned int eku_bits = 0, ku_bits = 0;
+ ASN1_BIT_STRING *usage = NULL;
+
+ if (ret_ku_bits == NULL && ret_eku_bits == NULL)
+ return EINVAL;
+
+ if (ret_eku_bits)
+ *ret_eku_bits = 0;
+ else {
+ pkiDebug("%s: EKUs not requested, not checking\n", __FUNCTION__);
+ goto check_kus;
+ }
+
+ /* Start with Extended Key usage */
+ i = X509_get_ext_by_NID(x, NID_ext_key_usage, -1);
+ if (i >= 0) {
+ EXTENDED_KEY_USAGE *eku;
+
+ eku = X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL);
+ if (eku) {
+ for (i = 0; i < sk_ASN1_OBJECT_num(eku); i++) {
+ ASN1_OBJECT *certoid;
+ certoid = sk_ASN1_OBJECT_value(eku, i);
+ if ((OBJ_cmp(certoid, plgcctx->id_pkinit_KPClientAuth)) == 0)
+ eku_bits |= PKINIT_EKU_PKINIT;
+ else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_ms_smartcard_login))) == 0)
+ eku_bits |= PKINIT_EKU_MSSCLOGIN;
+ else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_client_auth))) == 0)
+ eku_bits |= PKINIT_EKU_CLIENTAUTH;
+ else if ((OBJ_cmp(certoid, OBJ_nid2obj(NID_email_protect))) == 0)
+ eku_bits |= PKINIT_EKU_EMAILPROTECTION;
+ }
+ EXTENDED_KEY_USAGE_free(eku);
+ }
+ }
+ pkiDebug("%s: returning eku 0x%08x\n", __FUNCTION__, eku_bits);
+ *ret_eku_bits = eku_bits;
+
+check_kus:
+ /* Now the Key Usage bits */
+ if (ret_ku_bits)
+ *ret_ku_bits = 0;
+ else {
+ pkiDebug("%s: KUs not requested, not checking\n", __FUNCTION__);
+ goto out;
+ }
+
+ /* Make sure usage exists before checking bits */
+ usage = X509_get_ext_d2i(x, NID_key_usage, NULL, NULL);
+ if (usage) {
+ if (!ku_reject(x, X509v3_KU_DIGITAL_SIGNATURE))
+ ku_bits |= PKINIT_KU_DIGITALSIGNATURE;
+ if (!ku_reject(x, X509v3_KU_KEY_ENCIPHERMENT))
+ ku_bits |= PKINIT_KU_KEYENCIPHERMENT;
+ ASN1_BIT_STRING_free(usage);
+ }
+
+ pkiDebug("%s: returning ku 0x%08x\n", __FUNCTION__, ku_bits);
+ *ret_ku_bits = ku_bits;
+
+out:
+ return 0;
+}
+
+/*
+ * Return a string format of an X509_NAME in buf where
+ * size is an in/out parameter. On input it is the size
+ * of the buffer, and on output it is the actual length
+ * of the name.
+ * If buf is NULL, returns the length req'd to hold name
+ */
+static char *
+X509_NAME_oneline_ex(X509_NAME * a,
+ char *buf,
+ unsigned int *size,
+ unsigned long flag)
+{
+ BIO *out = NULL;
+
+ out = BIO_new(BIO_s_mem ());
+ if (X509_NAME_print_ex(out, a, 0, flag) > 0) {
+ if (buf != NULL && *size > (int) BIO_number_written(out)) {
+ (void) memset(buf, 0, *size);
+ BIO_read(out, buf, (int) BIO_number_written(out));
+ }
+ else {
+ *size = BIO_number_written(out);
+ }
+ }
+ BIO_free(out);
+ return (buf);
+}
+
+/*
+ * Get certificate information
+ */
+krb5_error_code
+crypto_cert_get_matching_data(krb5_context context,
+ pkinit_cert_handle ch,
+ pkinit_cert_matching_data **ret_md)
+{
+ krb5_error_code retval;
+ pkinit_cert_matching_data *md;
+ krb5_principal *pkinit_sans =NULL, *upn_sans = NULL;
+ struct _pkinit_cert_data *cd = (struct _pkinit_cert_data *)ch;
+ int i, j;
+ char buf[DN_BUF_LEN];
+ unsigned int bufsize = sizeof(buf);
+
+ if (cd == NULL || cd->magic != CERT_MAGIC)
+ return EINVAL;
+ if (ret_md == NULL)
+ return EINVAL;
+
+ md = calloc(1, sizeof(*md));
+ if (md == NULL)
+ return ENOMEM;
+
+ md->ch = ch;
+
+ /* get the subject name (in rfc2253 format) */
+ X509_NAME_oneline_ex(X509_get_subject_name(cd->cred->cert),
+ buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS);
+ md->subject_dn = strdup(buf);
+ if (md->subject_dn == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ /* get the issuer name (in rfc2253 format) */
+ X509_NAME_oneline_ex(X509_get_issuer_name(cd->cred->cert),
+ buf, &bufsize, XN_FLAG_SEP_COMMA_PLUS);
+ md->issuer_dn = strdup(buf);
+ if (md->issuer_dn == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ /* get the san data */
+ retval = crypto_retrieve_X509_sans(context, cd->plgctx, cd->reqctx,
+ cd->cred->cert, &pkinit_sans,
+ &upn_sans, NULL);
+ if (retval)
+ goto cleanup;
+
+ j = 0;
+ if (pkinit_sans != NULL) {
+ for (i = 0; pkinit_sans[i] != NULL; i++)
+ j++;
+ }
+ if (upn_sans != NULL) {
+ for (i = 0; upn_sans[i] != NULL; i++)
+ j++;
+ }
+ if (j != 0) {
+ md->sans = calloc((size_t)j+1, sizeof(*md->sans));
+ if (md->sans == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ j = 0;
+ if (pkinit_sans != NULL) {
+ for (i = 0; pkinit_sans[i] != NULL; i++)
+ md->sans[j++] = pkinit_sans[i];
+ free(pkinit_sans);
+ }
+ if (upn_sans != NULL) {
+ for (i = 0; upn_sans[i] != NULL; i++)
+ md->sans[j++] = upn_sans[i];
+ free(upn_sans);
+ }
+ md->sans[j] = NULL;
+ } else
+ md->sans = NULL;
+
+ /* get the KU and EKU data */
+
+ retval = crypto_retieve_X509_key_usage(context, cd->plgctx, cd->reqctx,
+ cd->cred->cert,
+ &md->ku_bits, &md->eku_bits);
+ if (retval)
+ goto cleanup;
+
+ *ret_md = md;
+ retval = 0;
+cleanup:
+ if (retval) {
+ if (md)
+ crypto_cert_free_matching_data(context, md);
+ }
+ return retval;
+}
+
+/*
+ * Free certificate information
+ */
+krb5_error_code
+crypto_cert_free_matching_data(krb5_context context,
+ pkinit_cert_matching_data *md)
+{
+ krb5_principal p;
+ int i;
+
+ if (md == NULL)
+ return EINVAL;
+ if (md->subject_dn)
+ free(md->subject_dn);
+ if (md->issuer_dn)
+ free(md->issuer_dn);
+ if (md->sans) {
+ for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i])
+ krb5_free_principal(context, p);
+ free(md->sans);
+ }
+ free(md);
+ return 0;
+}
+
+/*
+ * Make this matching certificate "the chosen one"
+ */
+/* ARGSUSED */
+krb5_error_code
+crypto_cert_select(krb5_context context,
+ pkinit_cert_matching_data *md)
+{
+ struct _pkinit_cert_data *cd;
+ if (md == NULL)
+ return EINVAL;
+
+ cd = (struct _pkinit_cert_data *)md->ch;
+ if (cd == NULL || cd->magic != CERT_MAGIC)
+ return EINVAL;
+
+ /* copy the selected cert into our id_cryptoctx */
+ if (cd->idctx->my_certs != NULL) {
+ sk_X509_pop_free(cd->idctx->my_certs, X509_free);
+ }
+ cd->idctx->my_certs = sk_X509_new_null();
+ sk_X509_push(cd->idctx->my_certs, cd->cred->cert);
+ cd->idctx->creds[cd->index]->cert = NULL; /* Don't free it twice */
+ cd->idctx->cert_index = 0;
+
+ if (cd->idctx->pkcs11_method != 1) {
+ cd->idctx->my_key = cd->cred->key;
+ cd->idctx->creds[cd->index]->key = NULL; /* Don't free it twice */
+ }
+#ifndef WITHOUT_PKCS11
+ else {
+ cd->idctx->cert_id = cd->cred->cert_id;
+ cd->idctx->creds[cd->index]->cert_id = NULL; /* Don't free it twice */
+ cd->idctx->cert_id_len = cd->cred->cert_id_len;
+ }
+#endif
+ return 0;
+}
+
+/*
+ * Choose the default certificate as "the chosen one"
+ */
+krb5_error_code
+crypto_cert_select_default(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx)
+{
+ krb5_error_code retval;
+ int cert_count = 0;
+
+ retval = crypto_cert_get_count(context, plg_cryptoctx, req_cryptoctx,
+ id_cryptoctx, &cert_count);
+ if (retval) {
+ pkiDebug("%s: crypto_cert_get_count error %d, %s\n",
+ __FUNCTION__, retval, error_message(retval));
+ goto errout;
+ }
+ if (cert_count != 1) {
+ /* Solaris Kerberos: Improved error messages */
+ retval = EINVAL;
+ krb5_set_error_message(context, retval,
+ gettext("failed to select default certificate: "
+ "found %d certs to choose from but there must be exactly one"),
+ cert_count);
+ pkiDebug("%s: ERROR: There are %d certs to choose from, "
+ "but there must be exactly one.\n",
+ __FUNCTION__, cert_count);
+ goto errout;
+ }
+ /* copy the selected cert into our id_cryptoctx */
+ if (id_cryptoctx->my_certs != NULL) {
+ sk_X509_pop_free(id_cryptoctx->my_certs, X509_free);
+ }
+ id_cryptoctx->my_certs = sk_X509_new_null();
+ sk_X509_push(id_cryptoctx->my_certs, id_cryptoctx->creds[0]->cert);
+ id_cryptoctx->creds[0]->cert = NULL; /* Don't free it twice */
+ id_cryptoctx->cert_index = 0;
+
+ if (id_cryptoctx->pkcs11_method != 1) {
+ id_cryptoctx->my_key = id_cryptoctx->creds[0]->key;
+ id_cryptoctx->creds[0]->key = NULL; /* Don't free it twice */
+ }
+#ifndef WITHOUT_PKCS11
+ else {
+ id_cryptoctx->cert_id = id_cryptoctx->creds[0]->cert_id;
+ id_cryptoctx->creds[0]->cert_id = NULL; /* Don't free it twice */
+ id_cryptoctx->cert_id_len = id_cryptoctx->creds[0]->cert_id_len;
+ }
+#endif
+ retval = 0;
+errout:
+ return retval;
+}
+
+
+/* ARGSUSED */
+static krb5_error_code
+load_cas_and_crls(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ int catype,
+ char *filename)
+{
+ STACK_OF(X509_INFO) *sk = NULL;
+ STACK_OF(X509) *ca_certs = NULL;
+ STACK_OF(X509_CRL) *ca_crls = NULL;
+ BIO *in = NULL;
+ /* Solaris Kerberos */
+ krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+ int i = 0;
+
+ /* If there isn't already a stack in the context,
+ * create a temporary one now */
+ switch(catype) {
+ case CATYPE_ANCHORS:
+ if (id_cryptoctx->trustedCAs != NULL)
+ ca_certs = id_cryptoctx->trustedCAs;
+ else {
+ ca_certs = sk_X509_new_null();
+ if (ca_certs == NULL)
+ return ENOMEM;
+ }
+ break;
+ case CATYPE_INTERMEDIATES:
+ if (id_cryptoctx->intermediateCAs != NULL)
+ ca_certs = id_cryptoctx->intermediateCAs;
+ else {
+ ca_certs = sk_X509_new_null();
+ if (ca_certs == NULL)
+ return ENOMEM;
+ }
+ break;
+ case CATYPE_CRLS:
+ if (id_cryptoctx->revoked != NULL)
+ ca_crls = id_cryptoctx->revoked;
+ else {
+ ca_crls = sk_X509_CRL_new_null();
+ if (ca_crls == NULL)
+ return ENOMEM;
+ }
+ break;
+ default:
+ return ENOTSUP;
+ }
+
+ if (!(in = BIO_new_file(filename, "r"))) {
+ retval = errno;
+ pkiDebug("%s: error opening file '%s': %s\n", __FUNCTION__,
+ filename, error_message(errno));
+ goto cleanup;
+ }
+
+ /* This loads from a file, a stack of x509/crl/pkey sets */
+ if ((sk = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL)) == NULL) {
+ pkiDebug("%s: error reading file '%s'\n", __FUNCTION__, filename);
+ retval = EIO;
+ goto cleanup;
+ }
+
+ /* scan over the stack created from loading the file contents,
+ * weed out duplicates, and push new ones onto the return stack
+ */
+ for (i = 0; i < sk_X509_INFO_num(sk); i++) {
+ X509_INFO *xi = sk_X509_INFO_value(sk, i);
+ if (xi != NULL && xi->x509 != NULL && catype != CATYPE_CRLS) {
+ int j = 0, size = sk_X509_num(ca_certs), flag = 0;
+
+ if (!size) {
+ sk_X509_push(ca_certs, xi->x509);
+ xi->x509 = NULL;
+ continue;
+ }
+ for (j = 0; j < size; j++) {
+ X509 *x = sk_X509_value(ca_certs, j);
+ flag = X509_cmp(x, xi->x509);
+ if (flag == 0)
+ break;
+ else
+ continue;
+ }
+ if (flag != 0) {
+ sk_X509_push(ca_certs, X509_dup(xi->x509));
+ }
+ } else if (xi != NULL && xi->crl != NULL && catype == CATYPE_CRLS) {
+ int j = 0, size = sk_X509_CRL_num(ca_crls), flag = 0;
+ if (!size) {
+ sk_X509_CRL_push(ca_crls, xi->crl);
+ xi->crl = NULL;
+ continue;
+ }
+ for (j = 0; j < size; j++) {
+ X509_CRL *x = sk_X509_CRL_value(ca_crls, j);
+ flag = X509_CRL_cmp(x, xi->crl);
+ if (flag == 0)
+ break;
+ else
+ continue;
+ }
+ if (flag != 0) {
+ sk_X509_push(ca_crls, X509_CRL_dup(xi->crl));
+ }
+ }
+ }
+
+ /* If we added something and there wasn't a stack in the
+ * context before, add the temporary stack to the context.
+ */
+ switch(catype) {
+ case CATYPE_ANCHORS:
+ if (sk_X509_num(ca_certs) == 0) {
+ pkiDebug("no anchors in file, %s\n", filename);
+ if (id_cryptoctx->trustedCAs == NULL)
+ sk_X509_free(ca_certs);
+ } else {
+ if (id_cryptoctx->trustedCAs == NULL)
+ id_cryptoctx->trustedCAs = ca_certs;
+ }
+ break;
+ case CATYPE_INTERMEDIATES:
+ if (sk_X509_num(ca_certs) == 0) {
+ pkiDebug("no intermediates in file, %s\n", filename);
+ if (id_cryptoctx->intermediateCAs == NULL)
+ sk_X509_free(ca_certs);
+ } else {
+ if (id_cryptoctx->intermediateCAs == NULL)
+ id_cryptoctx->intermediateCAs = ca_certs;
+ }
+ break;
+ case CATYPE_CRLS:
+ if (sk_X509_num(ca_crls) == 0) {
+ pkiDebug("no crls in file, %s\n", filename);
+ if (id_cryptoctx->revoked == NULL)
+ sk_X509_CRL_free(ca_crls);
+ } else {
+ if (id_cryptoctx->revoked == NULL)
+ id_cryptoctx->revoked = ca_crls;
+ }
+ break;
+ default:
+ /* Should have been caught above! */
+ retval = EINVAL;
+ goto cleanup;
+ /* Solaris Kerberos: removed "break" as it's never reached */
+ }
+
+ retval = 0;
+
+ cleanup:
+ if (in != NULL)
+ BIO_free(in);
+ if (sk != NULL)
+ sk_X509_INFO_pop_free(sk, X509_INFO_free);
+
+ return retval;
+}
+
+static krb5_error_code
+load_cas_and_crls_dir(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ int catype,
+ char *dirname)
+{
+ krb5_error_code retval = EINVAL;
+ DIR *d = NULL;
+ struct dirent *dentry = NULL;
+ char filename[1024];
+
+ if (dirname == NULL)
+ return EINVAL;
+
+ d = opendir(dirname);
+ if (d == NULL)
+ return ENOENT;
+
+ while ((dentry = readdir(d))) {
+ if (strlen(dirname) + strlen(dentry->d_name) + 2 > sizeof(filename)) {
+ pkiDebug("%s: Path too long -- directory '%s' and file '%s'\n",
+ __FUNCTION__, dirname, dentry->d_name);
+ goto cleanup;
+ }
+ /* Ignore subdirectories and anything starting with a dot */
+#ifdef DT_DIR
+ if (dentry->d_type == DT_DIR)
+ continue;
+#endif
+ if (dentry->d_name[0] == '.')
+ continue;
+ (void) snprintf(filename, sizeof(filename), "%s/%s", dirname, dentry->d_name);
+
+ retval = load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
+ id_cryptoctx, catype, filename);
+ if (retval)
+ goto cleanup;
+ }
+
+ retval = 0;
+
+ cleanup:
+ if (d != NULL)
+ (void) closedir(d);
+
+ return retval;
+}
+
+/* ARGSUSED */
+krb5_error_code
+crypto_load_cas_and_crls(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_opts *idopts,
+ pkinit_identity_crypto_context id_cryptoctx,
+ int idtype,
+ int catype,
+ char *id)
+{
+ pkiDebug("%s: called with idtype %s and catype %s\n",
+ __FUNCTION__, idtype2string(idtype), catype2string(catype));
+ /* Solaris Kerberos: Removed "break"'s as they are never reached */
+ switch (idtype) {
+ case IDTYPE_FILE:
+ return load_cas_and_crls(context, plg_cryptoctx, req_cryptoctx,
+ id_cryptoctx, catype, id);
+ case IDTYPE_DIR:
+ return load_cas_and_crls_dir(context, plg_cryptoctx, req_cryptoctx,
+ id_cryptoctx, catype, id);
+ default:
+ return ENOTSUP;
+ }
+}
+
+static krb5_error_code
+create_identifiers_from_stack(STACK_OF(X509) *sk,
+ krb5_external_principal_identifier *** ids)
+{
+ krb5_error_code retval = ENOMEM;
+ int i = 0, sk_size = sk_X509_num(sk);
+ krb5_external_principal_identifier **krb5_cas = NULL;
+ X509 *x = NULL;
+ X509_NAME *xn = NULL;
+ unsigned char *p = NULL;
+ int len = 0;
+ PKCS7_ISSUER_AND_SERIAL *is = NULL;
+ char buf[DN_BUF_LEN];
+
+ *ids = NULL;
+
+ krb5_cas =
+ malloc((sk_size + 1) * sizeof(krb5_external_principal_identifier *));
+ if (krb5_cas == NULL)
+ return ENOMEM;
+ krb5_cas[sk_size] = NULL;
+
+ for (i = 0; i < sk_size; i++) {
+ krb5_cas[i] = (krb5_external_principal_identifier *)malloc(sizeof(krb5_external_principal_identifier));
+
+ x = sk_X509_value(sk, i);
+
+ X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
+ pkiDebug("#%d cert= %s\n", i, buf);
+
+ /* fill-in subjectName */
+ krb5_cas[i]->subjectName.magic = 0;
+ krb5_cas[i]->subjectName.length = 0;
+ krb5_cas[i]->subjectName.data = NULL;
+
+ xn = X509_get_subject_name(x);
+ len = i2d_X509_NAME(xn, NULL);
+ if ((p = krb5_cas[i]->subjectName.data = (unsigned char *)malloc((size_t) len)) == NULL)
+ goto cleanup;
+ i2d_X509_NAME(xn, &p);
+ krb5_cas[i]->subjectName.length = len;
+
+ /* fill-in issuerAndSerialNumber */
+ krb5_cas[i]->issuerAndSerialNumber.length = 0;
+ krb5_cas[i]->issuerAndSerialNumber.magic = 0;
+ krb5_cas[i]->issuerAndSerialNumber.data = NULL;
+
+#ifdef LONGHORN_BETA_COMPAT
+if (longhorn == 0) { /* XXX Longhorn doesn't like this */
+#endif
+ is = PKCS7_ISSUER_AND_SERIAL_new();
+ X509_NAME_set(&is->issuer, X509_get_issuer_name(x));
+ M_ASN1_INTEGER_free(is->serial);
+ is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(x));
+ len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
+ if ((p = krb5_cas[i]->issuerAndSerialNumber.data =
+ (unsigned char *)malloc((size_t) len)) == NULL)
+ goto cleanup;
+ i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
+ krb5_cas[i]->issuerAndSerialNumber.length = len;
+#ifdef LONGHORN_BETA_COMPAT
+}
+#endif
+
+ /* fill-in subjectKeyIdentifier */
+ krb5_cas[i]->subjectKeyIdentifier.length = 0;
+ krb5_cas[i]->subjectKeyIdentifier.magic = 0;
+ krb5_cas[i]->subjectKeyIdentifier.data = NULL;
+
+
+#ifdef LONGHORN_BETA_COMPAT
+if (longhorn == 0) { /* XXX Longhorn doesn't like this */
+#endif
+ if (X509_get_ext_by_NID(x, NID_subject_key_identifier, -1) >= 0) {
+ ASN1_OCTET_STRING *ikeyid = NULL;
+
+ if ((ikeyid = X509_get_ext_d2i(x, NID_subject_key_identifier, NULL,
+ NULL))) {
+ len = i2d_ASN1_OCTET_STRING(ikeyid, NULL);
+ if ((p = krb5_cas[i]->subjectKeyIdentifier.data =
+ (unsigned char *)malloc((size_t) len)) == NULL)
+ goto cleanup;
+ i2d_ASN1_OCTET_STRING(ikeyid, &p);
+ krb5_cas[i]->subjectKeyIdentifier.length = len;
+ }
+ if (ikeyid != NULL)
+ ASN1_OCTET_STRING_free(ikeyid);
+ }
+#ifdef LONGHORN_BETA_COMPAT
+}
+#endif
+ if (is != NULL) {
+ if (is->issuer != NULL)
+ X509_NAME_free(is->issuer);
+ if (is->serial != NULL)
+ ASN1_INTEGER_free(is->serial);
+ free(is);
+ }
+ }
+
+ *ids = krb5_cas;
+
+ retval = 0;
+ cleanup:
+ if (retval)
+ free_krb5_external_principal_identifier(&krb5_cas);
+
+ return retval;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+create_krb5_invalidCertificates(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_external_principal_identifier *** ids)
+{
+
+ krb5_error_code retval = ENOMEM;
+ STACK_OF(X509) *sk = NULL;
+
+ *ids = NULL;
+ if (req_cryptoctx->received_cert == NULL)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+
+ sk = sk_X509_new_null();
+ if (sk == NULL)
+ goto cleanup;
+ sk_X509_push(sk, req_cryptoctx->received_cert);
+
+ retval = create_identifiers_from_stack(sk, ids);
+
+ sk_X509_free(sk);
+cleanup:
+
+ return retval;
+}
+
+/* ARGSUSED */
+krb5_error_code
+create_krb5_supportedCMSTypes(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_algorithm_identifier ***oids)
+{
+
+ krb5_error_code retval = ENOMEM;
+ krb5_algorithm_identifier **loids = NULL;
+ krb5_octet_data des3oid = {0, 8, (unsigned char *)"\x2A\x86\x48\x86\xF7\x0D\x03\x07" };
+
+ *oids = NULL;
+ loids = malloc(2 * sizeof(krb5_algorithm_identifier *));
+ if (loids == NULL)
+ goto cleanup;
+ loids[1] = NULL;
+ loids[0] = (krb5_algorithm_identifier *)malloc(sizeof(krb5_algorithm_identifier));
+ if (loids[0] == NULL) {
+ free(loids);
+ goto cleanup;
+ }
+ retval = pkinit_copy_krb5_octet_data(&loids[0]->algorithm, &des3oid);
+ if (retval) {
+ free(loids[0]);
+ free(loids);
+ goto cleanup;
+ }
+ loids[0]->parameters.length = 0;
+ loids[0]->parameters.data = NULL;
+
+ *oids = loids;
+ retval = 0;
+cleanup:
+
+ return retval;
+}
+
+/* ARGSUSED */
+krb5_error_code
+create_krb5_trustedCertifiers(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_external_principal_identifier *** ids)
+{
+
+ /* Solaris Kerberos */
+ STACK_OF(X509) *sk = id_cryptoctx->trustedCAs;
+
+ *ids = NULL;
+ if (id_cryptoctx->trustedCAs == NULL)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+
+ return create_identifiers_from_stack(sk, ids);
+
+}
+
+/* ARGSUSED */
+krb5_error_code
+create_krb5_trustedCas(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ int flag,
+ krb5_trusted_ca *** ids)
+{
+ krb5_error_code retval = ENOMEM;
+ STACK_OF(X509) *sk = id_cryptoctx->trustedCAs;
+ int i = 0, len = 0, sk_size = sk_X509_num(sk);
+ krb5_trusted_ca **krb5_cas = NULL;
+ X509 *x = NULL;
+ char buf[DN_BUF_LEN];
+ X509_NAME *xn = NULL;
+ unsigned char *p = NULL;
+ PKCS7_ISSUER_AND_SERIAL *is = NULL;
+
+ *ids = NULL;
+ if (id_cryptoctx->trustedCAs == NULL)
+ return KRB5KDC_ERR_PREAUTH_FAILED;
+
+ krb5_cas = malloc((sk_size + 1) * sizeof(krb5_trusted_ca *));
+ if (krb5_cas == NULL)
+ return ENOMEM;
+ krb5_cas[sk_size] = NULL;
+
+ for (i = 0; i < sk_size; i++) {
+ krb5_cas[i] = (krb5_trusted_ca *)malloc(sizeof(krb5_trusted_ca));
+ if (krb5_cas[i] == NULL)
+ goto cleanup;
+ x = sk_X509_value(sk, i);
+
+ X509_NAME_oneline(X509_get_subject_name(x), buf, sizeof(buf));
+ pkiDebug("#%d cert= %s\n", i, buf);
+
+ switch (flag) {
+ case choice_trusted_cas_principalName:
+ krb5_cas[i]->choice = choice_trusted_cas_principalName;
+ break;
+ case choice_trusted_cas_caName:
+ krb5_cas[i]->choice = choice_trusted_cas_caName;
+ krb5_cas[i]->u.caName.data = NULL;
+ krb5_cas[i]->u.caName.length = 0;
+ xn = X509_get_subject_name(x);
+ len = i2d_X509_NAME(xn, NULL);
+ if ((p = krb5_cas[i]->u.caName.data =
+ (unsigned char *)malloc((size_t) len)) == NULL)
+ goto cleanup;
+ i2d_X509_NAME(xn, &p);
+ krb5_cas[i]->u.caName.length = len;
+ break;
+ case choice_trusted_cas_issuerAndSerial:
+ krb5_cas[i]->choice = choice_trusted_cas_issuerAndSerial;
+ krb5_cas[i]->u.issuerAndSerial.data = NULL;
+ krb5_cas[i]->u.issuerAndSerial.length = 0;
+ is = PKCS7_ISSUER_AND_SERIAL_new();
+ X509_NAME_set(&is->issuer, X509_get_issuer_name(x));
+ M_ASN1_INTEGER_free(is->serial);
+ is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(x));
+ len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
+ if ((p = krb5_cas[i]->u.issuerAndSerial.data =
+ (unsigned char *)malloc((size_t) len)) == NULL)
+ goto cleanup;
+ i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
+ krb5_cas[i]->u.issuerAndSerial.length = len;
+ if (is != NULL) {
+ if (is->issuer != NULL)
+ X509_NAME_free(is->issuer);
+ if (is->serial != NULL)
+ ASN1_INTEGER_free(is->serial);
+ free(is);
+ }
+ break;
+ default: break;
+ }
+ }
+ retval = 0;
+ *ids = krb5_cas;
+cleanup:
+ if (retval)
+ free_krb5_trusted_ca(&krb5_cas);
+
+ return retval;
+}
+
+/* ARGSUSED */
+krb5_error_code
+create_issuerAndSerial(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char **out,
+ unsigned int *out_len)
+{
+ unsigned char *p = NULL;
+ PKCS7_ISSUER_AND_SERIAL *is = NULL;
+ int len = 0;
+ krb5_error_code retval = ENOMEM;
+ X509 *cert = req_cryptoctx->received_cert;
+
+ *out = NULL;
+ *out_len = 0;
+ if (req_cryptoctx->received_cert == NULL)
+ return 0;
+
+ is = PKCS7_ISSUER_AND_SERIAL_new();
+ X509_NAME_set(&is->issuer, X509_get_issuer_name(cert));
+ M_ASN1_INTEGER_free(is->serial);
+ is->serial = M_ASN1_INTEGER_dup(X509_get_serialNumber(cert));
+ len = i2d_PKCS7_ISSUER_AND_SERIAL(is, NULL);
+ if ((p = *out = (unsigned char *)malloc((size_t) len)) == NULL)
+ goto cleanup;
+ i2d_PKCS7_ISSUER_AND_SERIAL(is, &p);
+ *out_len = len;
+ retval = 0;
+
+cleanup:
+ X509_NAME_free(is->issuer);
+ ASN1_INTEGER_free(is->serial);
+ free(is);
+
+ return retval;
+}
+
+static int
+pkcs7_decrypt(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ PKCS7 *p7,
+ BIO *data)
+{
+ BIO *tmpmem = NULL;
+ /* Solaris Kerberos */
+ int i = 0;
+ char buf[4096];
+
+ if(p7 == NULL)
+ return 0;
+
+ if(!PKCS7_type_is_enveloped(p7)) {
+ pkiDebug("wrong pkcs7 content type\n");
+ return 0;
+ }
+
+ if(!(tmpmem = pkcs7_dataDecode(context, id_cryptoctx, p7))) {
+ pkiDebug("unable to decrypt pkcs7 object\n");
+ return 0;
+ }
+/* Solaris Kerberos: Suppress sun studio compiler warning */
+#pragma error_messages (off, E_END_OF_LOOP_CODE_NOT_REACHED)
+ for(;;) {
+ i = BIO_read(tmpmem, buf, sizeof(buf));
+ if (i <= 0) break;
+ BIO_write(data, buf, i);
+ BIO_free_all(tmpmem);
+ return 1;
+ }
+#pragma error_messages (default, E_END_OF_LOOP_CODE_NOT_REACHED)
+
+ return 0;
+}
+
+krb5_error_code
+pkinit_process_td_trusted_certifiers(
+ krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_external_principal_identifier **krb5_trusted_certifiers,
+ int td_type)
+{
+ krb5_error_code retval = ENOMEM;
+ STACK_OF(X509_NAME) *sk_xn = NULL;
+ X509_NAME *xn = NULL;
+ PKCS7_ISSUER_AND_SERIAL *is = NULL;
+ ASN1_OCTET_STRING *id = NULL;
+ const unsigned char *p = NULL;
+ char buf[DN_BUF_LEN];
+ int i = 0;
+
+ if (td_type == TD_TRUSTED_CERTIFIERS)
+ pkiDebug("received trusted certifiers\n");
+ else
+ pkiDebug("received invalid certificate\n");
+
+ sk_xn = sk_X509_NAME_new_null();
+ while(krb5_trusted_certifiers[i] != NULL) {
+ if (krb5_trusted_certifiers[i]->subjectName.data != NULL) {
+ p = krb5_trusted_certifiers[i]->subjectName.data;
+ xn = d2i_X509_NAME(NULL, &p,
+ (int)krb5_trusted_certifiers[i]->subjectName.length);
+ if (xn == NULL)
+ goto cleanup;
+ X509_NAME_oneline(xn, buf, sizeof(buf));
+ if (td_type == TD_TRUSTED_CERTIFIERS)
+ pkiDebug("#%d cert = %s is trusted by kdc\n", i, buf);
+ else
+ pkiDebug("#%d cert = %s is invalid\n", i, buf);
+ sk_X509_NAME_push(sk_xn, xn);
+ }
+
+ if (krb5_trusted_certifiers[i]->issuerAndSerialNumber.data != NULL) {
+ p = krb5_trusted_certifiers[i]->issuerAndSerialNumber.data;
+ is = d2i_PKCS7_ISSUER_AND_SERIAL(NULL, &p,
+ (int)krb5_trusted_certifiers[i]->issuerAndSerialNumber.length);
+ if (is == NULL)
+ goto cleanup;
+ X509_NAME_oneline(is->issuer, buf, sizeof(buf));
+ if (td_type == TD_TRUSTED_CERTIFIERS)
+ pkiDebug("#%d issuer = %s serial = %ld is trusted bu kdc\n", i,
+ buf, ASN1_INTEGER_get(is->serial));
+ else
+ pkiDebug("#%d issuer = %s serial = %ld is invalid\n", i, buf,
+ ASN1_INTEGER_get(is->serial));
+ PKCS7_ISSUER_AND_SERIAL_free(is);
+ }
+
+ if (krb5_trusted_certifiers[i]->subjectKeyIdentifier.data != NULL) {
+ p = krb5_trusted_certifiers[i]->subjectKeyIdentifier.data;
+ id = d2i_ASN1_OCTET_STRING(NULL, &p,
+ (int)krb5_trusted_certifiers[i]->subjectKeyIdentifier.length);
+ if (id == NULL)
+ goto cleanup;
+ /* XXX */
+ ASN1_OCTET_STRING_free(id);
+ }
+ i++;
+ }
+ /* XXX Since we not doing anything with received trusted certifiers
+ * return an error. this is the place where we can pick a different
+ * client certificate based on the information in td_trusted_certifiers
+ */
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+cleanup:
+ if (sk_xn != NULL)
+ sk_X509_NAME_pop_free(sk_xn, X509_NAME_free);
+
+ return retval;
+}
+
+static BIO *
+pkcs7_dataDecode(krb5_context context,
+ pkinit_identity_crypto_context id_cryptoctx,
+ PKCS7 *p7)
+{
+ int i = 0;
+ unsigned int jj = 0, tmp_len = 0;
+ BIO *out=NULL,*etmp=NULL,*bio=NULL;
+ unsigned char *tmp=NULL;
+ ASN1_OCTET_STRING *data_body=NULL;
+ const EVP_CIPHER *evp_cipher=NULL;
+ EVP_CIPHER_CTX *evp_ctx=NULL;
+ X509_ALGOR *enc_alg=NULL;
+ STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL;
+/* Solaris Kerberos: Not used */
+#if 0
+ X509_ALGOR *xalg=NULL;
+#endif
+ PKCS7_RECIP_INFO *ri=NULL;
+ X509 *cert = sk_X509_value(id_cryptoctx->my_certs,
+ id_cryptoctx->cert_index);
+
+ p7->state=PKCS7_S_HEADER;
+
+ rsk=p7->d.enveloped->recipientinfo;
+ enc_alg=p7->d.enveloped->enc_data->algorithm;
+ data_body=p7->d.enveloped->enc_data->enc_data;
+ evp_cipher=EVP_get_cipherbyobj(enc_alg->algorithm);
+ if (evp_cipher == NULL) {
+ PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE);
+ goto cleanup;
+ }
+/* Solaris Kerberos: Not used */
+#if 0
+ xalg=p7->d.enveloped->enc_data->algorithm;
+#endif
+
+ if ((etmp=BIO_new(BIO_f_cipher())) == NULL) {
+ PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB);
+ goto cleanup;
+ }
+
+ /* It was encrypted, we need to decrypt the secret key
+ * with the private key */
+
+ /* Find the recipientInfo which matches the passed certificate
+ * (if any)
+ */
+
+ if (cert) {
+ for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
+ int tmp_ret = 0;
+ ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
+ tmp_ret = X509_NAME_cmp(ri->issuer_and_serial->issuer,
+ cert->cert_info->issuer);
+ if (!tmp_ret) {
+ tmp_ret = M_ASN1_INTEGER_cmp(cert->cert_info->serialNumber,
+ ri->issuer_and_serial->serial);
+ if (!tmp_ret)
+ break;
+ }
+ ri=NULL;
+ }
+ if (ri == NULL) {
+ PKCS7err(PKCS7_F_PKCS7_DATADECODE,
+ PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE);
+ goto cleanup;
+ }
+
+ }
+
+ /* If we haven't got a certificate try each ri in turn */
+
+ if (cert == NULL) {
+ for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) {
+ ri=sk_PKCS7_RECIP_INFO_value(rsk,i);
+ jj = pkinit_decode_data(context, id_cryptoctx,
+ M_ASN1_STRING_data(ri->enc_key),
+ (unsigned int) M_ASN1_STRING_length(ri->enc_key),
+ &tmp, &tmp_len);
+ if (jj) {
+ PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB);
+ goto cleanup;
+ }
+
+ if (!jj && tmp_len > 0) {
+ jj = tmp_len;
+ break;
+ }
+
+ ERR_clear_error();
+ ri = NULL;
+ }
+
+ if (ri == NULL) {
+ PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_RECIPIENT_MATCHES_KEY);
+ goto cleanup;
+ }
+ }
+ else {
+ jj = pkinit_decode_data(context, id_cryptoctx,
+ M_ASN1_STRING_data(ri->enc_key),
+ (unsigned int) M_ASN1_STRING_length(ri->enc_key),
+ &tmp, &tmp_len);
+ /* Solaris Kerberos: tmp_len is unsigned. Cannot be < 0 */
+ if (jj || tmp_len == 0) {
+ PKCS7err(PKCS7_F_PKCS7_DATADECODE, ERR_R_EVP_LIB);
+ goto cleanup;
+ }
+ jj = tmp_len;
+ }
+
+ evp_ctx=NULL;
+ BIO_get_cipher_ctx(etmp,&evp_ctx);
+ if (EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0) <= 0)
+ goto cleanup;
+ if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0)
+ goto cleanup;
+
+ if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) {
+ /* Some S/MIME clients don't use the same key
+ * and effective key length. The key length is
+ * determined by the size of the decrypted RSA key.
+ */
+ if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, (int)jj)) {
+ PKCS7err(PKCS7_F_PKCS7_DATADECODE,
+ PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH);
+ goto cleanup;
+ }
+ }
+ if (EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0) <= 0)
+ goto cleanup;
+
+ OPENSSL_cleanse(tmp,jj);
+
+ if (out == NULL)
+ out=etmp;
+ else
+ BIO_push(out,etmp);
+ etmp=NULL;
+
+ if (data_body->length > 0)
+ bio = BIO_new_mem_buf(data_body->data, data_body->length);
+ else {
+ bio=BIO_new(BIO_s_mem());
+ BIO_set_mem_eof_return(bio,0);
+ }
+ BIO_push(out,bio);
+ bio=NULL;
+
+ /* Solaris Kerberos */
+ goto out;
+
+cleanup:
+ if (out != NULL) BIO_free_all(out);
+ if (etmp != NULL) BIO_free_all(etmp);
+ if (bio != NULL) BIO_free_all(bio);
+ out=NULL;
+
+out:
+ if (tmp != NULL)
+ free(tmp);
+
+ return(out);
+}
+
+static krb5_error_code
+der_decode_data(unsigned char *data, long data_len,
+ unsigned char **out, long *out_len)
+{
+ /* Solaris Kerberos */
+ krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+ ASN1_OCTET_STRING *s = NULL;
+ const unsigned char *p = data;
+
+ if ((s = d2i_ASN1_BIT_STRING(NULL, &p, data_len)) == NULL)
+ goto cleanup;
+ *out_len = s->length;
+ if ((*out = (unsigned char *) malloc((size_t) *out_len + 1)) == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ (void) memcpy(*out, s->data, (size_t) s->length);
+ (*out)[s->length] = '\0';
+
+ retval = 0;
+ cleanup:
+ if (s != NULL)
+ ASN1_OCTET_STRING_free(s);
+
+ return retval;
+}
+
+
+#ifdef DEBUG_DH
+static void
+print_dh(DH * dh, char *msg)
+{
+ BIO *bio_err = NULL;
+
+ bio_err = BIO_new(BIO_s_file());
+ BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+
+ if (msg)
+ BIO_puts(bio_err, (const char *)msg);
+ if (dh)
+ DHparams_print(bio_err, dh);
+
+ BN_print(bio_err, dh->q);
+ BIO_puts(bio_err, (const char *)"\n");
+ BIO_free(bio_err);
+
+}
+
+static void
+print_pubkey(BIGNUM * key, char *msg)
+{
+ BIO *bio_err = NULL;
+
+ bio_err = BIO_new(BIO_s_file());
+ BIO_set_fp(bio_err, stderr, BIO_NOCLOSE | BIO_FP_TEXT);
+
+ if (msg)
+ BIO_puts(bio_err, (const char *)msg);
+ if (key)
+ BN_print(bio_err, key);
+ BIO_puts(bio_err, "\n");
+
+ BIO_free(bio_err);
+
+}
+#endif
+
+/*
+ * Solaris Kerberos:
+ * Error message generation has changed so gettext() can be used
+ */
+#if 0
+static char *
+pkinit_pkcs11_code_to_text(int err)
+{
+ int i;
+ static char uc[64];
+
+ for (i = 0; pkcs11_errstrings[i].text != NULL; i++)
+ if (pkcs11_errstrings[i].code == err)
+ break;
+ if (pkcs11_errstrings[i].text != NULL)
+ return (pkcs11_errstrings[i].text);
+ snprintf(uc, 64, gettext("unknown code 0x%x"), err);
+ return (uc);
+}
+#endif
+
+static char *
+pkinit_pkcs11_code_to_text(int err) {
+ return pkcs11_error_table(err);
+}
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.h b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.h
new file mode 100644
index 0000000000..236ad91363
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_crypto_openssl.h
@@ -0,0 +1,273 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#ifndef _PKINIT_CRYPTO_OPENSSL_H
+#define _PKINIT_CRYPTO_OPENSSL_H
+
+#include <openssl/bn.h>
+#include <openssl/dh.h>
+#include <openssl/x509.h>
+#include <openssl/pkcs7.h>
+#include <openssl/pkcs12.h>
+#include <openssl/obj_mac.h>
+#include <openssl/x509v3.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/asn1_mac.h>
+#include <openssl/sha.h>
+#include <openssl/asn1.h>
+#include <openssl/pem.h>
+
+#include "pkinit.h"
+
+#define DN_BUF_LEN 256
+#define MAX_CREDS_ALLOWED 20
+
+struct _pkinit_cred_info {
+ X509 *cert;
+ EVP_PKEY *key;
+#ifndef WITHOUT_PKCS11
+ CK_BYTE_PTR cert_id;
+ int cert_id_len;
+#endif
+};
+typedef struct _pkinit_cred_info * pkinit_cred_info;
+
+struct _pkinit_identity_crypto_context {
+ pkinit_cred_info creds[MAX_CREDS_ALLOWED+1];
+ STACK_OF(X509) *my_certs; /* available user certs */
+ int cert_index; /* cert to use out of available certs*/
+ EVP_PKEY *my_key; /* available user keys if in filesystem */
+ STACK_OF(X509) *trustedCAs; /* available trusted ca certs */
+ STACK_OF(X509) *intermediateCAs; /* available intermediate ca certs */
+ STACK_OF(X509_CRL) *revoked; /* available crls */
+ int pkcs11_method;
+ krb5_prompter_fct prompter;
+ void *prompter_data;
+#ifndef WITHOUT_PKCS11
+ char *p11_module_name;
+ CK_SLOT_ID slotid;
+ char *token_label;
+ char *cert_label;
+ /* These are crypto-specific */
+ void *p11_module;
+ CK_SESSION_HANDLE session;
+ CK_FUNCTION_LIST_PTR p11;
+ CK_BYTE_PTR cert_id;
+ int cert_id_len;
+ CK_MECHANISM_TYPE mech;
+ /*
+ * Solaris Kerberos:
+ * If PKCS#11 is already being used by the process then C_Finalize should
+ * not be called by pkinit as it would invalidate any PKCS#11 sessions the
+ * process was using prior to loading the pkinit plugin. "finalize_pkcs11"
+ * indicates whether or not C_Finalize should be called by pkinit.
+ */
+ krb5_boolean finalize_pkcs11;
+#endif
+};
+
+struct _pkinit_plg_crypto_context {
+ DH *dh_1024;
+ DH *dh_2048;
+ DH *dh_4096;
+ ASN1_OBJECT *id_pkinit_authData;
+ ASN1_OBJECT *id_pkinit_authData9;
+ ASN1_OBJECT *id_pkinit_DHKeyData;
+ ASN1_OBJECT *id_pkinit_rkeyData;
+ ASN1_OBJECT *id_pkinit_san;
+ ASN1_OBJECT *id_ms_san_upn;
+ ASN1_OBJECT *id_pkinit_KPClientAuth;
+ ASN1_OBJECT *id_pkinit_KPKdc;
+ ASN1_OBJECT *id_ms_kp_sc_logon;
+ ASN1_OBJECT *id_kp_serverAuth;
+};
+
+struct _pkinit_req_crypto_context {
+ X509 *received_cert;
+ DH *dh;
+};
+
+#define CERT_MAGIC 0x53534c43
+struct _pkinit_cert_data {
+ unsigned int magic;
+ pkinit_plg_crypto_context plgctx;
+ pkinit_req_crypto_context reqctx;
+ pkinit_identity_crypto_context idctx;
+ pkinit_cred_info cred;
+ unsigned int index; /* Index of this cred in the creds[] array */
+};
+
+#define ITER_MAGIC 0x53534c49
+struct _pkinit_cert_iter_data {
+ unsigned int magic;
+ pkinit_plg_crypto_context plgctx;
+ pkinit_req_crypto_context reqctx;
+ pkinit_identity_crypto_context idctx;
+ unsigned int index;
+};
+
+static void openssl_init(void);
+
+static krb5_error_code pkinit_init_pkinit_oids(pkinit_plg_crypto_context );
+static void pkinit_fini_pkinit_oids(pkinit_plg_crypto_context );
+
+static krb5_error_code pkinit_init_dh_params(pkinit_plg_crypto_context );
+static void pkinit_fini_dh_params(pkinit_plg_crypto_context );
+
+static krb5_error_code pkinit_init_certs(pkinit_identity_crypto_context ctx);
+static void pkinit_fini_certs(pkinit_identity_crypto_context ctx);
+
+static krb5_error_code pkinit_init_pkcs11(pkinit_identity_crypto_context ctx);
+static void pkinit_fini_pkcs11(pkinit_identity_crypto_context ctx);
+
+static krb5_error_code pkinit_encode_dh_params
+ (BIGNUM *, BIGNUM *, BIGNUM *, unsigned char **, unsigned int *);
+static DH *pkinit_decode_dh_params
+ (DH **, unsigned char **, unsigned int );
+static int pkinit_check_dh_params
+ (BIGNUM * p1, BIGNUM * p2, BIGNUM * g1, BIGNUM * q1);
+
+static krb5_error_code pkinit_sign_data
+ (krb5_context context, pkinit_identity_crypto_context cryptoctx,
+ unsigned char *data, unsigned int data_len,
+ unsigned char **sig, unsigned int *sig_len);
+
+static krb5_error_code create_signature
+ (unsigned char **, unsigned int *, unsigned char *, unsigned int,
+ EVP_PKEY *pkey);
+
+static krb5_error_code pkinit_decode_data
+ (krb5_context context, pkinit_identity_crypto_context cryptoctx,
+ unsigned char *data, unsigned int data_len,
+ unsigned char **decoded, unsigned int *decoded_len);
+
+static krb5_error_code decode_data
+ (unsigned char **, unsigned int *, unsigned char *, unsigned int,
+ EVP_PKEY *pkey, X509 *cert);
+
+#ifdef DEBUG_DH
+static void print_dh(DH *, char *);
+static void print_pubkey(BIGNUM *, char *);
+#endif
+
+static int prepare_enc_data
+ (unsigned char *indata, int indata_len, unsigned char **outdata,
+ int *outdata_len);
+
+static int openssl_callback (int, X509_STORE_CTX *);
+static int openssl_callback_ignore_crls (int, X509_STORE_CTX *);
+
+static int pkcs7_decrypt
+ (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+ PKCS7 *p7, BIO *bio);
+
+static BIO * pkcs7_dataDecode
+ (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+ PKCS7 *p7);
+
+static ASN1_OBJECT * pkinit_pkcs7type2oid
+ (pkinit_plg_crypto_context plg_cryptoctx, int pkcs7_type);
+
+static krb5_error_code pkinit_create_sequence_of_principal_identifiers
+ (krb5_context context, pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ int type, krb5_data **out_data);
+
+#ifndef WITHOUT_PKCS11
+static krb5_error_code pkinit_find_private_key
+ (pkinit_identity_crypto_context, CK_ATTRIBUTE_TYPE usage,
+ CK_OBJECT_HANDLE *objp);
+static krb5_error_code pkinit_login
+ (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+ CK_TOKEN_INFO *tip);
+static krb5_error_code pkinit_open_session
+ (krb5_context context, pkinit_identity_crypto_context id_cryptoctx);
+static void * pkinit_C_LoadModule(const char *modname, CK_FUNCTION_LIST_PTR_PTR p11p);
+static CK_RV pkinit_C_UnloadModule(void *handle);
+#ifdef SILLYDECRYPT
+CK_RV pkinit_C_Decrypt
+ (pkinit_identity_crypto_context id_cryptoctx,
+ CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen,
+ CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen);
+#endif
+
+static krb5_error_code pkinit_sign_data_pkcs11
+ (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *data, unsigned int data_len,
+ unsigned char **sig, unsigned int *sig_len);
+static krb5_error_code pkinit_decode_data_pkcs11
+ (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *data, unsigned int data_len,
+ unsigned char **decoded_data, unsigned int *decoded_data_len);
+#endif /* WITHOUT_PKCS11 */
+
+static krb5_error_code pkinit_sign_data_fs
+ (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *data, unsigned int data_len,
+ unsigned char **sig, unsigned int *sig_len);
+static krb5_error_code pkinit_decode_data_fs
+ (krb5_context context, pkinit_identity_crypto_context id_cryptoctx,
+ unsigned char *data, unsigned int data_len,
+ unsigned char **decoded_data, unsigned int *decoded_data_len);
+
+static krb5_error_code der_decode_data
+ (unsigned char *, long, unsigned char **, long *);
+
+static krb5_error_code
+create_krb5_invalidCertificates(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_external_principal_identifier *** ids);
+
+static krb5_error_code
+create_identifiers_from_stack(STACK_OF(X509) *sk,
+ krb5_external_principal_identifier *** ids);
+#ifdef LONGHORN_BETA_COMPAT
+static int
+wrap_signeddata(unsigned char *data, unsigned int data_len,
+ unsigned char **out, unsigned int *out_len,
+ int is_longhorn_server);
+#else
+static int
+wrap_signeddata(unsigned char *data, unsigned int data_len,
+ unsigned char **out, unsigned int *out_len);
+#endif
+
+/* This handy macro borrowed from crypto/x509v3/v3_purp.c */
+#define ku_reject(x, usage) \
+ (((x)->ex_flags & EXFLAG_KUSAGE) && !((x)->ex_kusage & (usage)))
+
+static char *
+pkinit_pkcs11_code_to_text(int err);
+
+#endif /* _PKINIT_CRYPTO_OPENSSL_H */
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c
new file mode 100644
index 0000000000..e4a6470523
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_identity.c
@@ -0,0 +1,685 @@
+/*
+ * COPYRIGHT (C) 2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include <dirent.h>
+
+#include <libintl.h>
+
+#include "pkinit.h"
+
+static void
+free_list(char **list)
+{
+ int i;
+
+ if (list == NULL)
+ return;
+
+ for (i = 0; list[i] != NULL; i++)
+ free(list[i]);
+ free(list);
+}
+
+static krb5_error_code
+copy_list(char ***dst, char **src)
+{
+ int i;
+ char **newlist;
+
+ if (dst == NULL)
+ return EINVAL;
+ *dst = NULL;
+
+ if (src == NULL)
+ return 0;
+
+ for (i = 0; src[i] != NULL; i++);
+
+ newlist = calloc(1, (i + 1) * sizeof(*newlist));
+ if (newlist == NULL)
+ return ENOMEM;
+
+ for (i = 0; src[i] != NULL; i++) {
+ newlist[i] = strdup(src[i]);
+ if (newlist[i] == NULL)
+ goto cleanup;
+ }
+ newlist[i] = NULL;
+ *dst = newlist;
+ return 0;
+cleanup:
+ free_list(newlist);
+ return ENOMEM;
+}
+
+char *
+idtype2string(int idtype)
+{
+/* Solaris Kerberos: Removed "break"s (lint) */
+ switch(idtype) {
+ case IDTYPE_FILE: return "FILE";
+ case IDTYPE_DIR: return "DIR";
+ case IDTYPE_PKCS11: return "PKCS11";
+ case IDTYPE_PKCS12: return "PKCS12";
+ case IDTYPE_ENVVAR: return "ENV";
+ default: return "INVALID";
+ }
+}
+
+char *
+catype2string(int catype)
+{
+/* Solaris Kerberos: Removed "break"s (lint) */
+ switch(catype) {
+ case CATYPE_ANCHORS: return "ANCHORS";
+ case CATYPE_INTERMEDIATES: return "INTERMEDIATES";
+ case CATYPE_CRLS: return "CRLS";
+ default: return "INVALID";
+ }
+}
+
+krb5_error_code
+pkinit_init_identity_opts(pkinit_identity_opts **idopts)
+{
+ pkinit_identity_opts *opts = NULL;
+
+ *idopts = NULL;
+ opts = (pkinit_identity_opts *) calloc(1, sizeof(pkinit_identity_opts));
+ if (opts == NULL)
+ return ENOMEM;
+
+ opts->identity = NULL;
+ opts->anchors = NULL;
+ opts->intermediates = NULL;
+ opts->crls = NULL;
+ opts->ocsp = NULL;
+ opts->dn_mapping_file = NULL;
+
+ opts->cert_filename = NULL;
+ opts->key_filename = NULL;
+#ifndef WITHOUT_PKCS11
+ opts->p11_module_name = NULL;
+ opts->slotid = PK_NOSLOT;
+ opts->token_label = NULL;
+ opts->cert_id_string = NULL;
+ opts->cert_label = NULL;
+#endif
+
+ *idopts = opts;
+
+ return 0;
+}
+
+krb5_error_code
+pkinit_dup_identity_opts(pkinit_identity_opts *src_opts,
+ pkinit_identity_opts **dest_opts)
+{
+ pkinit_identity_opts *newopts;
+ krb5_error_code retval;
+
+ *dest_opts = NULL;
+ retval = pkinit_init_identity_opts(&newopts);
+ if (retval)
+ return retval;
+
+ retval = ENOMEM;
+
+ if (src_opts->identity != NULL) {
+ newopts->identity = strdup(src_opts->identity);
+ if (newopts->identity == NULL)
+ goto cleanup;
+ }
+
+ retval = copy_list(&newopts->anchors, src_opts->anchors);
+ if (retval)
+ goto cleanup;
+
+ retval = copy_list(&newopts->intermediates,src_opts->intermediates);
+ if (retval)
+ goto cleanup;
+
+ retval = copy_list(&newopts->crls, src_opts->crls);
+ if (retval)
+ goto cleanup;
+
+ if (src_opts->ocsp != NULL) {
+ newopts->ocsp = strdup(src_opts->ocsp);
+ if (newopts->ocsp == NULL)
+ goto cleanup;
+ }
+
+ if (src_opts->cert_filename != NULL) {
+ newopts->cert_filename = strdup(src_opts->cert_filename);
+ if (newopts->cert_filename == NULL)
+ goto cleanup;
+ }
+
+ if (src_opts->key_filename != NULL) {
+ newopts->key_filename = strdup(src_opts->key_filename);
+ if (newopts->key_filename == NULL)
+ goto cleanup;
+ }
+
+#ifndef WITHOUT_PKCS11
+ if (src_opts->p11_module_name != NULL) {
+ newopts->p11_module_name = strdup(src_opts->p11_module_name);
+ if (newopts->p11_module_name == NULL)
+ goto cleanup;
+ }
+
+ newopts->slotid = src_opts->slotid;
+
+ if (src_opts->token_label != NULL) {
+ newopts->token_label = strdup(src_opts->token_label);
+ if (newopts->token_label == NULL)
+ goto cleanup;
+ }
+
+ if (src_opts->cert_id_string != NULL) {
+ newopts->cert_id_string = strdup(src_opts->cert_id_string);
+ if (newopts->cert_id_string == NULL)
+ goto cleanup;
+ }
+
+ if (src_opts->cert_label != NULL) {
+ newopts->cert_label = strdup(src_opts->cert_label);
+ if (newopts->cert_label == NULL)
+ goto cleanup;
+ }
+#endif
+
+
+ *dest_opts = newopts;
+ return 0;
+cleanup:
+ pkinit_fini_identity_opts(newopts);
+ return retval;
+}
+
+void
+pkinit_fini_identity_opts(pkinit_identity_opts *idopts)
+{
+ if (idopts == NULL)
+ return;
+
+ if (idopts->identity != NULL)
+ free(idopts->identity);
+ free_list(idopts->anchors);
+ free_list(idopts->intermediates);
+ free_list(idopts->crls);
+ free_list(idopts->identity_alt);
+
+ if (idopts->cert_filename != NULL)
+ free(idopts->cert_filename);
+ if (idopts->key_filename != NULL)
+ free(idopts->key_filename);
+#ifndef WITHOUT_PKCS11
+ if (idopts->p11_module_name != NULL)
+ free(idopts->p11_module_name);
+ if (idopts->token_label != NULL)
+ free(idopts->token_label);
+ if (idopts->cert_id_string != NULL)
+ free(idopts->cert_id_string);
+ if (idopts->cert_label != NULL)
+ free(idopts->cert_label);
+#endif
+ free(idopts);
+}
+
+#ifndef WITHOUT_PKCS11
+/* ARGSUSED */
+static krb5_error_code
+parse_pkcs11_options(krb5_context context,
+ pkinit_identity_opts *idopts,
+ const char *residual)
+{
+ char *s, *cp, *vp;
+ krb5_error_code retval = ENOMEM;
+
+ if (residual == NULL || residual[0] == '\0')
+ return 0;
+
+ /* Split string into attr=value substrings */
+ s = strdup(residual);
+ if (s == NULL)
+ return retval;
+
+ for ((cp = strtok(s, ":")); cp; (cp = strtok(NULL, ":"))) {
+ vp = strchr(cp, '=');
+
+ /* If there is no "=", this is a pkcs11 module name */
+ if (vp == NULL) {
+ if (idopts->p11_module_name != NULL)
+ free(idopts->p11_module_name);
+ idopts->p11_module_name = strdup(cp);
+ if (idopts->p11_module_name == NULL)
+ goto cleanup;
+ continue;
+ }
+ *vp++ = '\0';
+ if (!strcmp(cp, "module_name")) {
+ if (idopts->p11_module_name != NULL)
+ free(idopts->p11_module_name);
+ idopts->p11_module_name = strdup(vp);
+ if (idopts->p11_module_name == NULL)
+ goto cleanup;
+ } else if (!strcmp(cp, "slotid")) {
+ long slotid = strtol(vp, NULL, 10);
+ if ((slotid == LONG_MIN || slotid == LONG_MAX) && errno != 0) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+ if ((long) (int) slotid != slotid) {
+ retval = EINVAL;
+ goto cleanup;
+ }
+ idopts->slotid = slotid;
+ } else if (!strcmp(cp, "token")) {
+ if (idopts->token_label != NULL)
+ free(idopts->token_label);
+ idopts->token_label = strdup(vp);
+ if (idopts->token_label == NULL)
+ goto cleanup;
+ } else if (!strcmp(cp, "certid")) {
+ if (idopts->cert_id_string != NULL)
+ free(idopts->cert_id_string);
+ idopts->cert_id_string = strdup(vp);
+ if (idopts->cert_id_string == NULL)
+ goto cleanup;
+ } else if (!strcmp(cp, "certlabel")) {
+ if (idopts->cert_label != NULL)
+ free(idopts->cert_label);
+ idopts->cert_label = strdup(vp);
+ if (idopts->cert_label == NULL)
+ goto cleanup;
+ }
+ }
+ retval = 0;
+cleanup:
+ free(s);
+ return retval;
+}
+#endif
+
+/* ARGSUSED */
+static krb5_error_code
+parse_fs_options(krb5_context context,
+ pkinit_identity_opts *idopts,
+ const char *residual)
+{
+ char *certname, *keyname;
+ krb5_error_code retval = ENOMEM;
+
+ if (residual == NULL || residual[0] == '\0')
+ return 0;
+
+ certname = strdup(residual);
+ if (certname == NULL)
+ goto cleanup;
+
+ certname = strtok(certname, ",");
+ keyname = strtok(NULL, ",");
+
+ idopts->cert_filename = strdup(certname);
+ if (idopts->cert_filename == NULL)
+ goto cleanup;
+
+ idopts->key_filename = strdup(keyname ? keyname : certname);
+ if (idopts->key_filename == NULL)
+ goto cleanup;
+
+ retval = 0;
+cleanup:
+ if (certname != NULL)
+ free(certname);
+ return retval;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+parse_pkcs12_options(krb5_context context,
+ pkinit_identity_opts *idopts,
+ const char *residual)
+{
+ krb5_error_code retval = ENOMEM;
+
+ if (residual == NULL || residual[0] == '\0')
+ return 0;
+
+ idopts->cert_filename = strdup(residual);
+ if (idopts->cert_filename == NULL)
+ goto cleanup;
+
+ idopts->key_filename = strdup(residual);
+ if (idopts->key_filename == NULL)
+ goto cleanup;
+
+ pkiDebug("%s: cert_filename '%s' key_filename '%s'\n",
+ __FUNCTION__, idopts->cert_filename,
+ idopts->key_filename);
+ retval = 0;
+cleanup:
+ return retval;
+}
+
+static krb5_error_code
+process_option_identity(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_opts *idopts,
+ pkinit_identity_crypto_context id_cryptoctx,
+ const char *value)
+{
+ const char *residual;
+ int idtype;
+ krb5_error_code retval = 0;
+
+ pkiDebug("%s: processing value '%s'\n",
+ __FUNCTION__, value ? value : "NULL");
+ if (value == NULL)
+ return EINVAL;
+
+ residual = strchr(value, ':');
+ if (residual != NULL) {
+ unsigned int typelen;
+ residual++; /* skip past colon */
+ typelen = residual - value;
+ if (strncmp(value, "FILE:", typelen) == 0) {
+ idtype = IDTYPE_FILE;
+#ifndef WITHOUT_PKCS11
+ } else if (strncmp(value, "PKCS11:", typelen) == 0) {
+ idtype = IDTYPE_PKCS11;
+#endif
+ } else if (strncmp(value, "PKCS12:", typelen) == 0) {
+ idtype = IDTYPE_PKCS12;
+ } else if (strncmp(value, "DIR:", typelen) == 0) {
+ idtype = IDTYPE_DIR;
+ } else if (strncmp(value, "ENV:", typelen) == 0) {
+ idtype = IDTYPE_ENVVAR;
+ } else {
+ pkiDebug("%s: Unsupported type while processing '%s'\n",
+ __FUNCTION__, value);
+ krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
+ "Unsupported type while processing '%s'\n",
+ value);
+ return KRB5_PREAUTH_FAILED;
+ }
+ } else {
+ idtype = IDTYPE_FILE;
+ residual = value;
+ }
+
+ idopts->idtype = idtype;
+ pkiDebug("%s: idtype is %s\n", __FUNCTION__, idtype2string(idopts->idtype));
+ switch (idtype) {
+ case IDTYPE_ENVVAR: {
+ /* Solaris Kerberos: Improved error messages */
+ char *envvar = getenv(residual);
+ if (envvar == NULL) {
+ krb5_set_error_message(context, EINVAL,
+ gettext("failed to find environmental variable \'%s\'"),
+ residual);
+ return EINVAL;
+ }
+ return process_option_identity(context, plg_cryptoctx,
+ req_cryptoctx, idopts, id_cryptoctx,
+ envvar);
+ /* Solaris Kerberos: not reached */
+ }
+ case IDTYPE_FILE:
+ retval = parse_fs_options(context, idopts, residual);
+ break;
+ case IDTYPE_PKCS12:
+ retval = parse_pkcs12_options(context, idopts, residual);
+ break;
+#ifndef WITHOUT_PKCS11
+ case IDTYPE_PKCS11:
+ retval = parse_pkcs11_options(context, idopts, residual);
+ break;
+#endif
+ case IDTYPE_DIR:
+ idopts->cert_filename = strdup(residual);
+ if (idopts->cert_filename == NULL)
+ retval = ENOMEM;
+ break;
+ default:
+ krb5_set_error_message(context, KRB5_PREAUTH_FAILED,
+ "Internal error parsing X509_user_identity\n");
+ retval = EINVAL;
+ break;
+ }
+ return retval;
+}
+
+static krb5_error_code
+process_option_ca_crl(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_opts *idopts,
+ pkinit_identity_crypto_context id_cryptoctx,
+ const char *value,
+ int catype)
+{
+ char *residual;
+ unsigned int typelen;
+ int idtype;
+
+ pkiDebug("%s: processing catype %s, value '%s'\n",
+ __FUNCTION__, catype2string(catype), value);
+ residual = strchr(value, ':');
+ if (residual == NULL) {
+ pkiDebug("No type given for '%s'\n", value);
+ return EINVAL;
+ }
+ residual++; /* skip past colon */
+ typelen = residual - value;
+ if (strncmp(value, "FILE:", typelen) == 0) {
+ idtype = IDTYPE_FILE;
+ } else if (strncmp(value, "DIR:", typelen) == 0) {
+ idtype = IDTYPE_DIR;
+ } else {
+ return ENOTSUP;
+ }
+ return crypto_load_cas_and_crls(context,
+ plg_cryptoctx,
+ req_cryptoctx,
+ idopts, id_cryptoctx,
+ idtype, catype, residual);
+}
+
+static krb5_error_code
+pkinit_identity_process_option(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_opts *idopts,
+ pkinit_identity_crypto_context id_cryptoctx,
+ int attr,
+ const char *value)
+{
+ krb5_error_code retval = 0;
+
+ switch (attr) {
+ case PKINIT_ID_OPT_USER_IDENTITY:
+ retval = process_option_identity(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx, value);
+ break;
+ case PKINIT_ID_OPT_ANCHOR_CAS:
+ retval = process_option_ca_crl(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx, value,
+ CATYPE_ANCHORS);
+ break;
+ case PKINIT_ID_OPT_INTERMEDIATE_CAS:
+ retval = process_option_ca_crl(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx,
+ value, CATYPE_INTERMEDIATES);
+ break;
+ case PKINIT_ID_OPT_CRLS:
+ retval = process_option_ca_crl(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx,
+ value, CATYPE_CRLS);
+ break;
+ case PKINIT_ID_OPT_OCSP:
+ retval = ENOTSUP;
+ break;
+ default:
+ retval = EINVAL;
+ break;
+ }
+ return retval;
+}
+
+krb5_error_code
+pkinit_identity_initialize(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_opts *idopts,
+ pkinit_identity_crypto_context id_cryptoctx,
+ int do_matching,
+ krb5_principal princ)
+{
+ krb5_error_code retval = EINVAL;
+ int i;
+
+ pkiDebug("%s: %p %p %p\n", __FUNCTION__, context, idopts, id_cryptoctx);
+ if (idopts == NULL || id_cryptoctx == NULL)
+ goto errout;
+
+ /*
+ * If identity was specified, use that. (For the kdc, this
+ * is specified as pkinit_identity in the kdc.conf. For users,
+ * this is specified on the command line via X509_user_identity.)
+ * If a user did not specify identity on the command line,
+ * then we will try alternatives which may have been specified
+ * in the config file.
+ */
+ if (idopts->identity != NULL) {
+ retval = pkinit_identity_process_option(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx,
+ PKINIT_ID_OPT_USER_IDENTITY,
+ idopts->identity);
+ } else if (idopts->identity_alt != NULL) {
+ for (i = 0; retval != 0 && idopts->identity_alt[i] != NULL; i++)
+ retval = pkinit_identity_process_option(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx,
+ PKINIT_ID_OPT_USER_IDENTITY,
+ idopts->identity_alt[i]);
+ } else {
+ pkiDebug("%s: no user identity options specified\n", __FUNCTION__);
+ goto errout;
+ }
+ if (retval)
+ goto errout;
+
+ retval = crypto_load_certs(context, plg_cryptoctx, req_cryptoctx,
+ idopts, id_cryptoctx, princ);
+ if (retval)
+ goto errout;
+
+ if (do_matching) {
+ retval = pkinit_cert_matching(context, plg_cryptoctx, req_cryptoctx,
+ id_cryptoctx, princ);
+ if (retval) {
+ pkiDebug("%s: No matching certificate found\n", __FUNCTION__);
+ (void) crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
+ id_cryptoctx);
+ goto errout;
+ }
+ } else {
+ /* Tell crypto code to use the "default" */
+ retval = crypto_cert_select_default(context, plg_cryptoctx,
+ req_cryptoctx, id_cryptoctx);
+ if (retval) {
+ pkiDebug("%s: Failed while selecting default certificate\n",
+ __FUNCTION__);
+ (void) crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
+ id_cryptoctx);
+ goto errout;
+ }
+ }
+
+ retval = crypto_free_cert_info(context, plg_cryptoctx, req_cryptoctx,
+ id_cryptoctx);
+ if (retval)
+ goto errout;
+
+ for (i = 0; idopts->anchors != NULL && idopts->anchors[i] != NULL; i++) {
+ retval = pkinit_identity_process_option(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx,
+ PKINIT_ID_OPT_ANCHOR_CAS,
+ idopts->anchors[i]);
+ if (retval)
+ goto errout;
+ }
+ for (i = 0; idopts->intermediates != NULL
+ && idopts->intermediates[i] != NULL; i++) {
+ retval = pkinit_identity_process_option(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx,
+ PKINIT_ID_OPT_INTERMEDIATE_CAS,
+ idopts->intermediates[i]);
+ if (retval)
+ goto errout;
+ }
+ for (i = 0; idopts->crls != NULL && idopts->crls[i] != NULL; i++) {
+ retval = pkinit_identity_process_option(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx,
+ PKINIT_ID_OPT_CRLS,
+ idopts->crls[i]);
+ if (retval)
+ goto errout;
+ }
+ if (idopts->ocsp != NULL) {
+ retval = pkinit_identity_process_option(context, plg_cryptoctx,
+ req_cryptoctx, idopts,
+ id_cryptoctx,
+ PKINIT_ID_OPT_OCSP,
+ idopts->ocsp);
+ if (retval)
+ goto errout;
+ }
+
+errout:
+ return retval;
+}
+
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_lib.c b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_lib.c
new file mode 100644
index 0000000000..fb6e4feada
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_lib.c
@@ -0,0 +1,479 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "pkinit.h"
+
+#define FAKECERT
+
+const krb5_octet_data
+ dh_oid = { 0, 7, (unsigned char *)"\x2A\x86\x48\xce\x3e\x02\x01" };
+
+
+krb5_error_code
+pkinit_init_req_opts(pkinit_req_opts **reqopts)
+{
+ krb5_error_code retval = ENOMEM;
+ pkinit_req_opts *opts = NULL;
+
+ *reqopts = NULL;
+ opts = (pkinit_req_opts *) calloc(1, sizeof(pkinit_req_opts));
+ if (opts == NULL)
+ return retval;
+
+ opts->require_eku = 1;
+ opts->accept_secondary_eku = 0;
+ opts->allow_upn = 0;
+ opts->dh_or_rsa = DH_PROTOCOL;
+ opts->require_crl_checking = 0;
+ opts->dh_size = PKINIT_DEFAULT_DH_MIN_BITS;
+ opts->win2k_target = 0;
+ opts->win2k_require_cksum = 0;
+
+ *reqopts = opts;
+
+ return 0;
+}
+
+void
+pkinit_fini_req_opts(pkinit_req_opts *opts)
+{
+ if (opts != NULL)
+ free(opts);
+ return;
+}
+
+krb5_error_code
+pkinit_init_plg_opts(pkinit_plg_opts **plgopts)
+{
+ krb5_error_code retval = ENOMEM;
+ pkinit_plg_opts *opts = NULL;
+
+ *plgopts = NULL;
+ opts = (pkinit_plg_opts *) calloc(1, sizeof(pkinit_plg_opts));
+ if (opts == NULL)
+ return retval;
+
+ opts->require_eku = 1;
+ opts->accept_secondary_eku = 0;
+ opts->dh_or_rsa = DH_PROTOCOL;
+ opts->allow_upn = 0;
+ opts->require_crl_checking = 0;
+
+ opts->dh_min_bits = PKINIT_DEFAULT_DH_MIN_BITS;
+
+ *plgopts = opts;
+
+ return 0;
+}
+
+void
+pkinit_fini_plg_opts(pkinit_plg_opts *opts)
+{
+ if (opts != NULL)
+ free(opts);
+ return;
+}
+
+void
+free_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in)
+{
+ if (*in == NULL) return;
+ if ((*in)->signedAuthPack.data != NULL)
+ free((*in)->signedAuthPack.data);
+ if ((*in)->trustedCertifiers != NULL)
+ free_krb5_external_principal_identifier(&(*in)->trustedCertifiers);
+ if ((*in)->kdcPkId.data != NULL)
+ free((*in)->kdcPkId.data);
+ free(*in);
+}
+
+void
+free_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in)
+{
+ if (*in == NULL) return;
+ if ((*in)->signedAuthPack.data != NULL)
+ free((*in)->signedAuthPack.data);
+ if ((*in)->kdcCert.data != NULL)
+ free((*in)->kdcCert.data);
+ if ((*in)->encryptionCert.data != NULL)
+ free((*in)->encryptionCert.data);
+ if ((*in)->trustedCertifiers != NULL)
+ free_krb5_trusted_ca(&(*in)->trustedCertifiers);
+ free(*in);
+}
+
+void
+free_krb5_reply_key_pack(krb5_reply_key_pack **in)
+{
+ if (*in == NULL) return;
+ if ((*in)->replyKey.contents != NULL)
+ free((*in)->replyKey.contents);
+ if ((*in)->asChecksum.contents != NULL)
+ free((*in)->asChecksum.contents);
+ free(*in);
+}
+
+void
+free_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in)
+{
+ if (*in == NULL) return;
+ if ((*in)->replyKey.contents != NULL)
+ free((*in)->replyKey.contents);
+ free(*in);
+}
+
+void
+free_krb5_auth_pack(krb5_auth_pack **in)
+{
+ if ((*in) == NULL) return;
+ if ((*in)->clientPublicValue != NULL) {
+ if ((*in)->clientPublicValue->algorithm.algorithm.data != NULL)
+ free((*in)->clientPublicValue->algorithm.algorithm.data);
+ if ((*in)->clientPublicValue->algorithm.parameters.data != NULL)
+ free((*in)->clientPublicValue->algorithm.parameters.data);
+ if ((*in)->clientPublicValue->subjectPublicKey.data != NULL)
+ free((*in)->clientPublicValue->subjectPublicKey.data);
+ free((*in)->clientPublicValue);
+ }
+ if ((*in)->pkAuthenticator.paChecksum.contents != NULL)
+ free((*in)->pkAuthenticator.paChecksum.contents);
+ if ((*in)->supportedCMSTypes != NULL)
+ free_krb5_algorithm_identifiers(&((*in)->supportedCMSTypes));
+ free(*in);
+}
+
+void
+free_krb5_auth_pack_draft9(krb5_context context,
+ krb5_auth_pack_draft9 **in)
+{
+ if ((*in) == NULL) return;
+ krb5_free_principal(context, (*in)->pkAuthenticator.kdcName);
+ free(*in);
+}
+
+void
+free_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in)
+{
+ if (*in == NULL) return;
+ switch ((*in)->choice) {
+ case choice_pa_pk_as_rep_dhInfo:
+ if ((*in)->u.dh_Info.dhSignedData.data != NULL)
+ free((*in)->u.dh_Info.dhSignedData.data);
+ break;
+ case choice_pa_pk_as_rep_encKeyPack:
+ if ((*in)->u.encKeyPack.data != NULL)
+ free((*in)->u.encKeyPack.data);
+ break;
+ default:
+ break;
+ }
+ free(*in);
+}
+
+void
+free_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in)
+{
+ if (*in == NULL) return;
+ if ((*in)->u.encKeyPack.data != NULL)
+ free((*in)->u.encKeyPack.data);
+ free(*in);
+}
+
+void
+free_krb5_external_principal_identifier(krb5_external_principal_identifier ***in)
+{
+ int i = 0;
+ if (*in == NULL) return;
+ while ((*in)[i] != NULL) {
+ if ((*in)[i]->subjectName.data != NULL)
+ free((*in)[i]->subjectName.data);
+ if ((*in)[i]->issuerAndSerialNumber.data != NULL)
+ free((*in)[i]->issuerAndSerialNumber.data);
+ if ((*in)[i]->subjectKeyIdentifier.data != NULL)
+ free((*in)[i]->subjectKeyIdentifier.data);
+ free((*in)[i]);
+ i++;
+ }
+ free(*in);
+}
+
+void
+free_krb5_trusted_ca(krb5_trusted_ca ***in)
+{
+ int i = 0;
+ if (*in == NULL) return;
+ while ((*in)[i] != NULL) {
+ switch((*in)[i]->choice) {
+ case choice_trusted_cas_principalName:
+ break;
+ case choice_trusted_cas_caName:
+ if ((*in)[i]->u.caName.data != NULL)
+ free((*in)[i]->u.caName.data);
+ break;
+ case choice_trusted_cas_issuerAndSerial:
+ if ((*in)[i]->u.issuerAndSerial.data != NULL)
+ free((*in)[i]->u.issuerAndSerial.data);
+ break;
+ case choice_trusted_cas_UNKNOWN:
+ break;
+ }
+ free((*in)[i]);
+ i++;
+ }
+ free(*in);
+}
+
+void
+free_krb5_typed_data(krb5_typed_data ***in)
+{
+ int i = 0;
+ if (*in == NULL) return;
+ while ((*in)[i] != NULL) {
+ if ((*in)[i]->data != NULL)
+ free((*in)[i]->data);
+ free((*in)[i]);
+ i++;
+ }
+ free(*in);
+}
+
+void
+free_krb5_algorithm_identifier(krb5_algorithm_identifier *in)
+{
+ if (in == NULL)
+ return;
+ if (in->algorithm.data != NULL)
+ free(in->algorithm.data);
+ if (in->parameters.data != NULL)
+ free(in->parameters.data);
+ free(in);
+}
+
+void
+free_krb5_algorithm_identifiers(krb5_algorithm_identifier ***in)
+{
+ int i;
+ if (in == NULL || *in == NULL)
+ return;
+ for (i = 0; (*in)[i] != NULL; i++) {
+ free_krb5_algorithm_identifier((*in)[i]);
+ }
+ free(*in);
+}
+
+void
+free_krb5_subject_pk_info(krb5_subject_pk_info **in)
+{
+ if ((*in) == NULL) return;
+ if ((*in)->algorithm.parameters.data != NULL)
+ free((*in)->algorithm.parameters.data);
+ if ((*in)->subjectPublicKey.data != NULL)
+ free((*in)->subjectPublicKey.data);
+ free(*in);
+}
+
+void
+free_krb5_kdc_dh_key_info(krb5_kdc_dh_key_info **in)
+{
+ if (*in == NULL) return;
+ if ((*in)->subjectPublicKey.data != NULL)
+ free((*in)->subjectPublicKey.data);
+ free(*in);
+}
+
+void
+init_krb5_pa_pk_as_req(krb5_pa_pk_as_req **in)
+{
+ (*in) = malloc(sizeof(krb5_pa_pk_as_req));
+ if ((*in) == NULL) return;
+ (*in)->signedAuthPack.data = NULL;
+ (*in)->signedAuthPack.length = 0;
+ (*in)->trustedCertifiers = NULL;
+ (*in)->kdcPkId.data = NULL;
+ (*in)->kdcPkId.length = 0;
+}
+
+void
+init_krb5_pa_pk_as_req_draft9(krb5_pa_pk_as_req_draft9 **in)
+{
+ (*in) = malloc(sizeof(krb5_pa_pk_as_req_draft9));
+ if ((*in) == NULL) return;
+ (*in)->signedAuthPack.data = NULL;
+ (*in)->signedAuthPack.length = 0;
+ (*in)->trustedCertifiers = NULL;
+ (*in)->kdcCert.data = NULL;
+ (*in)->kdcCert.length = 0;
+ (*in)->encryptionCert.data = NULL;
+ (*in)->encryptionCert.length = 0;
+}
+
+void
+init_krb5_reply_key_pack(krb5_reply_key_pack **in)
+{
+ (*in) = malloc(sizeof(krb5_reply_key_pack));
+ if ((*in) == NULL) return;
+ (*in)->replyKey.contents = NULL;
+ (*in)->replyKey.length = 0;
+ (*in)->asChecksum.contents = NULL;
+ (*in)->asChecksum.length = 0;
+}
+
+void
+init_krb5_reply_key_pack_draft9(krb5_reply_key_pack_draft9 **in)
+{
+ (*in) = malloc(sizeof(krb5_reply_key_pack_draft9));
+ if ((*in) == NULL) return;
+ (*in)->replyKey.contents = NULL;
+ (*in)->replyKey.length = 0;
+}
+
+void
+init_krb5_auth_pack(krb5_auth_pack **in)
+{
+ (*in) = malloc(sizeof(krb5_auth_pack));
+ if ((*in) == NULL) return;
+ (*in)->clientPublicValue = NULL;
+ (*in)->supportedCMSTypes = NULL;
+ (*in)->clientDHNonce.length = 0;
+ (*in)->clientDHNonce.data = NULL;
+ (*in)->pkAuthenticator.paChecksum.contents = NULL;
+}
+
+void
+init_krb5_auth_pack_draft9(krb5_auth_pack_draft9 **in)
+{
+ (*in) = malloc(sizeof(krb5_auth_pack_draft9));
+ if ((*in) == NULL) return;
+ (*in)->clientPublicValue = NULL;
+}
+
+void
+init_krb5_pa_pk_as_rep(krb5_pa_pk_as_rep **in)
+{
+ (*in) = malloc(sizeof(krb5_pa_pk_as_rep));
+ if ((*in) == NULL) return;
+ (*in)->u.dh_Info.serverDHNonce.length = 0;
+ (*in)->u.dh_Info.serverDHNonce.data = NULL;
+ (*in)->u.dh_Info.dhSignedData.length = 0;
+ (*in)->u.dh_Info.dhSignedData.data = NULL;
+ (*in)->u.encKeyPack.length = 0;
+ (*in)->u.encKeyPack.data = NULL;
+}
+
+void
+init_krb5_pa_pk_as_rep_draft9(krb5_pa_pk_as_rep_draft9 **in)
+{
+ (*in) = malloc(sizeof(krb5_pa_pk_as_rep_draft9));
+ if ((*in) == NULL) return;
+ (*in)->u.dhSignedData.length = 0;
+ (*in)->u.dhSignedData.data = NULL;
+ (*in)->u.encKeyPack.length = 0;
+ (*in)->u.encKeyPack.data = NULL;
+}
+
+void
+init_krb5_typed_data(krb5_typed_data **in)
+{
+ (*in) = malloc(sizeof(krb5_typed_data));
+ if ((*in) == NULL) return;
+ (*in)->type = 0;
+ (*in)->length = 0;
+ (*in)->data = NULL;
+}
+
+void
+init_krb5_subject_pk_info(krb5_subject_pk_info **in)
+{
+ (*in) = malloc(sizeof(krb5_subject_pk_info));
+ if ((*in) == NULL) return;
+ (*in)->algorithm.parameters.data = NULL;
+ (*in)->algorithm.parameters.length = 0;
+ (*in)->subjectPublicKey.data = NULL;
+ (*in)->subjectPublicKey.length = 0;
+}
+
+krb5_error_code
+pkinit_copy_krb5_octet_data(krb5_octet_data *dst, const krb5_octet_data *src)
+{
+ if (dst == NULL || src == NULL)
+ return EINVAL;
+ if (src->data == NULL) {
+ dst->data = NULL;
+ dst->length = 0;
+ return 0;
+ }
+ dst->data = malloc(src->length);
+ if (dst->data == NULL)
+ return ENOMEM;
+ (void) memcpy(dst->data, src->data, src->length);
+ dst->length = src->length;
+ return 0;
+}
+
+/* debugging functions */
+void
+print_buffer(unsigned char *buf, unsigned int len)
+{
+ int i = 0;
+ /* Solaris Kerberos: len is unsigned (lint) */
+ if (len == 0)
+ return;
+
+ for (i = 0; i < len; i++)
+ pkiDebug("%02x ", buf[i]);
+ pkiDebug("\n");
+}
+
+void
+print_buffer_bin(unsigned char *buf, unsigned int len, char *filename)
+{
+ FILE *f = NULL;
+ int i = 0;
+
+ /* Solaris Kerberos: len is unsigned (lint) */
+ if (len == 0 || filename == NULL)
+ return;
+
+ if ((f = fopen(filename, "w")) == NULL)
+ return;
+
+ for (i = 0; i < len; i++)
+ (void) fputc(buf[i], f);
+
+ (void) fclose(f);
+}
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_matching.c b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_matching.c
new file mode 100644
index 0000000000..781e42cc34
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_matching.c
@@ -0,0 +1,843 @@
+/*
+ * COPYRIGHT (C) 2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <regex.h>
+#include <krb5.h>
+#include "pkinit.h"
+
+typedef struct _pkinit_cert_info pkinit_cert_info;
+
+typedef enum {
+ kw_undefined = 0,
+ kw_subject = 1,
+ kw_issuer = 2,
+ kw_san = 3,
+ kw_eku = 4,
+ kw_ku = 5
+} keyword_type;
+
+static char *
+keyword2string(unsigned int kw)
+{
+ /* Solaris Kerberos: removed "break"s (lint) */
+ switch(kw) {
+ case kw_undefined: return "NONE";
+ case kw_subject: return "SUBJECT";
+ case kw_issuer: return "ISSUER";
+ case kw_san: return "SAN";
+ case kw_eku: return "EKU";
+ case kw_ku: return "KU";
+ default: return "INVALID";
+ }
+}
+typedef enum {
+ relation_none = 0,
+ relation_and = 1,
+ relation_or = 2
+} relation_type;
+
+static char *
+relation2string(unsigned int rel)
+{
+ /* Solaris Kerberos: removed "break"s (lint) */
+ switch(rel) {
+ case relation_none: return "NONE";
+ case relation_and: return "AND";
+ case relation_or: return "OR";
+ default: return "INVALID";
+ }
+}
+
+typedef enum {
+ kwvaltype_undefined = 0,
+ kwvaltype_regexp = 1,
+ kwvaltype_list = 2
+} kw_value_type;
+
+static char *
+kwval2string(unsigned int kwval)
+{
+ /* Solaris Kerberos: removed "break"s (lint) */
+ switch(kwval) {
+ case kwvaltype_undefined: return "NONE";
+ case kwvaltype_regexp: return "REGEXP";
+ case kwvaltype_list: return "LIST";
+ default: return "INVALID";
+ }
+}
+
+struct keyword_desc {
+ const char *value;
+ size_t length;
+ keyword_type kwtype;
+ kw_value_type kwvaltype;
+} matching_keywords[] = {
+ { "<KU>", 4, kw_ku, kwvaltype_list },
+ { "<EKU>", 5, kw_eku, kwvaltype_list },
+ { "<SAN>", 5, kw_san, kwvaltype_regexp },
+ { "<ISSUER>", 8, kw_issuer, kwvaltype_regexp },
+ { "<SUBJECT>", 9, kw_subject, kwvaltype_regexp },
+ { NULL, 0, kw_undefined, kwvaltype_undefined},
+};
+
+struct ku_desc {
+ const char *value;
+ size_t length;
+ unsigned int bitval;
+};
+
+struct ku_desc ku_keywords[] = {
+ { "digitalSignature", 16, PKINIT_KU_DIGITALSIGNATURE },
+ { "keyEncipherment", 15, PKINIT_KU_KEYENCIPHERMENT },
+ { NULL, 0, 0 },
+};
+
+struct ku_desc eku_keywords[] = {
+ { "pkinit", 6, PKINIT_EKU_PKINIT },
+ { "msScLogin", 9, PKINIT_EKU_MSSCLOGIN },
+ { "clientAuth", 10, PKINIT_EKU_CLIENTAUTH },
+ { "emailProtection", 15, PKINIT_EKU_EMAILPROTECTION },
+ { NULL, 0, 0 },
+};
+
+/* Rule component */
+typedef struct _rule_component {
+ struct _rule_component *next;
+ keyword_type kw_type;
+ kw_value_type kwval_type;
+ regex_t regexp; /* Compiled regular expression */
+ char *regsrc; /* The regular expression source (for debugging) */
+ unsigned int ku_bits;
+ unsigned int eku_bits;
+} rule_component;
+
+/* Set rule components */
+typedef struct _rule_set {
+ relation_type relation;
+ int num_crs;
+ rule_component *crs;
+} rule_set;
+
+/* ARGSUSED */
+static krb5_error_code
+free_rule_component(krb5_context context,
+ rule_component *rc)
+{
+ if (rc == NULL)
+ return 0;
+
+ if (rc->kwval_type == kwvaltype_regexp) {
+ if (rc->regsrc)
+ free(rc->regsrc);
+ regfree(&rc->regexp);
+ }
+ free(rc);
+ return 0;
+}
+
+static krb5_error_code
+free_rule_set(krb5_context context,
+ rule_set *rs)
+{
+ rule_component *rc, *trc;
+
+ if (rs == NULL)
+ return 0;
+ for (rc = rs->crs; rc != NULL;) {
+ trc = rc->next;
+ /* Solaris Kerberos */
+ (void) free_rule_component(context, rc);
+ rc = trc;
+ }
+ free(rs);
+ return 0;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+parse_list_value(krb5_context context,
+ keyword_type type,
+ char *value,
+ rule_component *rc)
+{
+ krb5_error_code retval;
+ char *comma;
+ struct ku_desc *ku = NULL;
+ int found;
+ size_t len;
+ unsigned int *bitptr;
+
+
+ if (value == NULL || value[0] == '\0') {
+ pkiDebug("%s: Missing or empty value for list keyword type %d\n",
+ __FUNCTION__, type);
+ retval = EINVAL;
+ goto out;
+ }
+
+ if (type == kw_eku) {
+ bitptr = &rc->eku_bits;
+ } else if (type == kw_ku) {
+ bitptr = &rc->ku_bits;
+ } else {
+ pkiDebug("%s: Unknown list keyword type %d\n", __FUNCTION__, type);
+ retval = EINVAL;
+ goto out;
+ }
+
+ do {
+ found = 0;
+ comma = strchr(value, ',');
+ if (comma != NULL)
+ len = comma - value;
+ else
+ len = strlen(value);
+
+ if (type == kw_eku) {
+ ku = eku_keywords;
+ } else if (type == kw_ku) {
+ ku = ku_keywords;
+ }
+
+ for (; ku->value != NULL; ku++) {
+ if (strncasecmp(value, ku->value, len) == 0) {
+ *bitptr |= ku->bitval;
+ found = 1;
+ pkiDebug("%s: Found value '%s', bitfield is now 0x%x\n",
+ __FUNCTION__, ku->value, *bitptr);
+ break;
+ }
+ }
+ if (found) {
+ value += ku->length;
+ if (*value == ',')
+ value += 1;
+ } else {
+ pkiDebug("%s: Urecognized value '%s'\n", __FUNCTION__, value);
+ retval = EINVAL;
+ goto out;
+ }
+ } while (found && *value != '\0');
+
+ retval = 0;
+out:
+ pkiDebug("%s: returning %d\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static krb5_error_code
+parse_rule_component(krb5_context context,
+ const char **rule,
+ int *remaining,
+ rule_component **ret_rule)
+{
+ krb5_error_code retval;
+ rule_component *rc = NULL;
+ keyword_type kw_type;
+ kw_value_type kwval_type;
+ char err_buf[128];
+ int ret;
+ struct keyword_desc *kw, *nextkw;
+ char *nk;
+ int found_next_kw = 0;
+ char *value = NULL;
+ size_t len;
+
+ for (kw = matching_keywords; kw->value != NULL; kw++) {
+ if (strncmp(*rule, kw->value, kw->length) == 0) {
+ kw_type = kw->kwtype;
+ kwval_type = kw->kwvaltype;
+ *rule += kw->length;
+ *remaining -= kw->length;
+ break;
+ }
+ }
+ if (kw->value == NULL) {
+ pkiDebug("%s: Missing or invalid keyword in rule '%s'\n",
+ __FUNCTION__, *rule);
+ retval = ENOENT;
+ goto out;
+ }
+
+ pkiDebug("%s: found keyword '%s'\n", __FUNCTION__, kw->value);
+
+ rc = calloc(1, sizeof(*rc));
+ if (rc == NULL) {
+ retval = ENOMEM;
+ goto out;
+ }
+ rc->next = NULL;
+ rc->kw_type = kw_type;
+ rc->kwval_type = kwval_type;
+
+ /*
+ * Before procesing the value for this keyword,
+ * (compiling the regular expression or processing the list)
+ * we need to find the end of it. That means parsing for the
+ * beginning of the next keyword (or the end of the rule).
+ */
+ nk = strchr(*rule, '<');
+ while (nk != NULL) {
+ /* Possibly another keyword, check it out */
+ for (nextkw = matching_keywords; nextkw->value != NULL; nextkw++) {
+ if (strncmp(nk, nextkw->value, nextkw->length) == 0) {
+ /* Found a keyword, nk points to the beginning */
+ found_next_kw = 1;
+ break; /* Need to break out of the while! */
+ }
+ }
+ if (!found_next_kw)
+ nk = strchr(nk+1, '<'); /* keep looking */
+ else
+ break;
+ }
+
+ if (nk != NULL && found_next_kw)
+ len = (nk - *rule);
+ else
+ len = (*remaining);
+
+ if (len == 0) {
+ pkiDebug("%s: Missing value for keyword '%s'\n",
+ __FUNCTION__, kw->value);
+ retval = EINVAL;
+ goto out;
+ }
+
+ value = calloc(1, len+1);
+ if (value == NULL) {
+ retval = ENOMEM;
+ goto out;
+ }
+ (void) memcpy(value, *rule, len);
+ *remaining -= len;
+ *rule += len;
+ pkiDebug("%s: found value '%s'\n", __FUNCTION__, value);
+
+ if (kw->kwvaltype == kwvaltype_regexp) {
+ ret = regcomp(&rc->regexp, value, REG_EXTENDED);
+ if (ret) {
+ (void) regerror(ret, &rc->regexp, err_buf, sizeof(err_buf));
+ pkiDebug("%s: Error compiling reg-exp '%s': %s\n",
+ __FUNCTION__, value, err_buf);
+ retval = ret;
+ goto out;
+ }
+ rc->regsrc = strdup(value);
+ if (rc->regsrc == NULL) {
+ retval = ENOMEM;
+ goto out;
+ }
+ } else if (kw->kwvaltype == kwvaltype_list) {
+ retval = parse_list_value(context, rc->kw_type, value, rc);
+ if (retval) {
+ pkiDebug("%s: Error %d, parsing list values for keyword %s\n",
+ __FUNCTION__, retval, kw->value);
+ goto out;
+ }
+ }
+
+ *ret_rule = rc;
+ retval = 0;
+out:
+ if (value != NULL)
+ free(value);
+ if (retval && rc != NULL)
+ (void) free_rule_component(context, rc);
+ pkiDebug("%s: returning %d\n", __FUNCTION__, retval);
+ return retval;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+parse_rule_set(krb5_context context,
+ const char *rule_in,
+ rule_set **out_rs)
+{
+ const char *rule;
+ /* Solaris Kerberos */
+ int remaining;
+ krb5_error_code ret, retval;
+ rule_component *rc = NULL, *trc;
+ rule_set *rs;
+
+
+ if (rule_in == NULL)
+ return EINVAL;
+ rule = rule_in;
+ /* Solaris Kerberos */
+ remaining = strlen(rule);
+
+ rs = calloc(1, sizeof(*rs));
+ if (rs == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+
+ rs->relation = relation_none;
+ if (remaining > 1) {
+ if (rule[0] == '&' && rule[1] == '&') {
+ rs->relation = relation_and;
+ rule += 2;
+ remaining -= 2;
+ } else if (rule_in[0] == '|' && rule_in[1] == '|') {
+ rs->relation = relation_or;
+ rule +=2;
+ remaining -= 2;
+ }
+ }
+ rs->num_crs = 0;
+ while (remaining > 0) {
+ if (rs->relation == relation_none && rs->num_crs > 1) {
+ pkiDebug("%s: Assuming AND relation for multiple components in rule '%s'\n",
+ __FUNCTION__, rule_in);
+ rs->relation = relation_and;
+ }
+ ret = parse_rule_component(context, &rule, &remaining, &rc);
+ if (ret) {
+ retval = ret;
+ goto cleanup;
+ }
+ pkiDebug("%s: After parse_rule_component, remaining %d, rule '%s'\n",
+ __FUNCTION__, remaining, rule);
+ rs->num_crs++;
+
+ /*
+ * Chain the new component on the end (order matters since
+ * we can short-circuit an OR or an AND relation if an
+ * earlier check passes
+ */
+ for (trc = rs->crs; trc != NULL && trc->next != NULL; trc = trc->next);
+ if (trc == NULL)
+ rs->crs = rc;
+ else {
+ trc->next = rc;
+ }
+ }
+
+ *out_rs = rs;
+
+ retval = 0;
+cleanup:
+ if (retval && rs != NULL) {
+ (void) free_rule_set(context, rs);
+ }
+ pkiDebug("%s: returning %d\n", __FUNCTION__, retval);
+ return retval;
+}
+
+/* ARGSUSED */
+static int
+regexp_match(krb5_context context, rule_component *rc, char *value)
+{
+ int code;
+
+ pkiDebug("%s: checking %s rule '%s' with value '%s'\n",
+ __FUNCTION__, keyword2string(rc->kw_type), rc->regsrc, value);
+
+ code = regexec(&rc->regexp, value, 0, NULL, 0);
+
+ pkiDebug("%s: the result is%s a match\n", __FUNCTION__,
+ code == REG_NOMATCH ? " NOT" : "");
+
+ return (code == 0 ? 1: 0);
+}
+
+static int
+component_match(krb5_context context,
+ rule_component *rc,
+ pkinit_cert_matching_data *md)
+{
+ int match = 0;
+ int i;
+ krb5_principal p;
+ char *princ_string;
+
+ switch (rc->kwval_type) {
+ case kwvaltype_regexp:
+ switch (rc->kw_type) {
+ case kw_subject:
+ match = regexp_match(context, rc, md->subject_dn);
+ break;
+ case kw_issuer:
+ match = regexp_match(context, rc, md->issuer_dn);
+ break;
+ case kw_san:
+ if (md->sans == NULL)
+ break;
+ for (i = 0, p = md->sans[i]; p != NULL; p = md->sans[++i]) {
+ krb5_unparse_name(context, p, &princ_string);
+ match = regexp_match(context, rc, princ_string);
+ krb5_free_unparsed_name(context, princ_string);
+ if (match)
+ break;
+ }
+ break;
+ default:
+ pkiDebug("%s: keyword %s, keyword value %s mismatch\n",
+ __FUNCTION__, keyword2string(rc->kw_type),
+ kwval2string(kwvaltype_regexp));
+ break;
+ }
+ break;
+ case kwvaltype_list:
+ switch(rc->kw_type) {
+ case kw_eku:
+ pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n",
+ __FUNCTION__, keyword2string(rc->kw_type),
+ rc->eku_bits, md->eku_bits);
+ if ((rc->eku_bits & md->eku_bits) == rc->eku_bits)
+ match = 1;
+ break;
+ case kw_ku:
+ pkiDebug("%s: checking %s: rule 0x%08x, cert 0x%08x\n",
+ __FUNCTION__, keyword2string(rc->kw_type),
+ rc->ku_bits, md->ku_bits);
+ if ((rc->ku_bits & md->ku_bits) == rc->ku_bits)
+ match = 1;
+ break;
+ default:
+ pkiDebug("%s: keyword %s, keyword value %s mismatch\n",
+ __FUNCTION__, keyword2string(rc->kw_type),
+ kwval2string(kwvaltype_regexp));
+ break;
+ }
+ break;
+ default:
+ pkiDebug("%s: unknown keyword value type %d\n",
+ __FUNCTION__, rc->kwval_type);
+ break;
+ }
+ pkiDebug("%s: returning match = %d\n", __FUNCTION__, match);
+ return match;
+}
+/*
+ * Returns match_found == 1 only if exactly one certificate matches
+ * the given rule
+ */
+/* ARGSUSED */
+static krb5_error_code
+check_all_certs(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_principal princ,
+ rule_set *rs, /* rule to check */
+ pkinit_cert_matching_data **matchdata,
+ int *match_found,
+ pkinit_cert_matching_data **matching_cert)
+{
+ krb5_error_code retval;
+ pkinit_cert_matching_data *md;
+ int i;
+ int comp_match = 0;
+ int total_cert_matches = 0;
+ rule_component *rc;
+ int certs_checked = 0;
+ pkinit_cert_matching_data *save_match = NULL;
+
+ if (match_found == NULL || matching_cert == NULL)
+ return EINVAL;
+
+ *matching_cert = NULL;
+ *match_found = 0;
+
+ pkiDebug("%s: matching rule relation is %s with %d components\n",
+ __FUNCTION__, relation2string(rs->relation), rs->num_crs);
+
+ /*
+ * Loop through all the certs available and count
+ * how many match the rule
+ */
+ for (i = 0, md = matchdata[i]; md != NULL; md = matchdata[++i]) {
+ pkiDebug("%s: subject: '%s'\n", __FUNCTION__, md->subject_dn);
+#if 0
+ pkiDebug("%s: issuer: '%s'\n", __FUNCTION__, md->subject_dn);
+ for (j = 0, p = md->sans[j]; p != NULL; p = md->sans[++j]) {
+ char *san_string;
+ krb5_unparse_name(context, p, &san_string);
+ pkiDebug("%s: san: '%s'\n", __FUNCTION__, san_string);
+ krb5_free_unparsed_name(context, san_string);
+ }
+#endif
+ certs_checked++;
+ for (rc = rs->crs; rc != NULL; rc = rc->next) {
+ comp_match = component_match(context, rc, md);
+ if (comp_match) {
+ pkiDebug("%s: match for keyword type %s\n",
+ __FUNCTION__, keyword2string(rc->kw_type));
+ }
+ if (comp_match && rs->relation == relation_or) {
+ pkiDebug("%s: cert matches rule (OR relation)\n",
+ __FUNCTION__);
+ total_cert_matches++;
+ save_match = md;
+ goto nextcert;
+ }
+ if (!comp_match && rs->relation == relation_and) {
+ pkiDebug("%s: cert does not match rule (AND relation)\n",
+ __FUNCTION__);
+ goto nextcert;
+ }
+ }
+ if (rc == NULL && comp_match) {
+ pkiDebug("%s: cert matches rule (AND relation)\n", __FUNCTION__);
+ total_cert_matches++;
+ save_match = md;
+ }
+nextcert:
+ continue;
+ }
+ pkiDebug("%s: After checking %d certs, we found %d matches\n",
+ __FUNCTION__, certs_checked, total_cert_matches);
+ if (total_cert_matches == 1) {
+ *match_found = 1;
+ *matching_cert = save_match;
+ }
+
+ retval = 0;
+
+ pkiDebug("%s: returning %d, match_found %d\n",
+ __FUNCTION__, retval, *match_found);
+ return retval;
+}
+
+static krb5_error_code
+free_all_cert_matching_data(krb5_context context,
+ pkinit_cert_matching_data **matchdata)
+{
+ krb5_error_code retval;
+ pkinit_cert_matching_data *md;
+ int i;
+
+ if (matchdata == NULL)
+ return EINVAL;
+
+ for (i = 0, md = matchdata[i]; md != NULL; md = matchdata[++i]) {
+ pkinit_cert_handle ch = md->ch;
+ retval = crypto_cert_free_matching_data(context, md);
+ if (retval) {
+ pkiDebug("%s: crypto_cert_free_matching_data error %d, %s\n",
+ __FUNCTION__, retval, error_message(retval));
+ goto cleanup;
+ }
+ retval = crypto_cert_release(context, ch);
+ if (retval) {
+ pkiDebug("%s: crypto_cert_release error %d, %s\n",
+ __FUNCTION__, retval, error_message(retval));
+ goto cleanup;
+ }
+ }
+ free(matchdata);
+ retval = 0;
+
+cleanup:
+ return retval;
+}
+
+static krb5_error_code
+obtain_all_cert_matching_data(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ pkinit_cert_matching_data ***all_matching_data)
+{
+ krb5_error_code retval;
+ int i, cert_count;
+ pkinit_cert_iter_handle ih = NULL;
+ pkinit_cert_handle ch;
+ pkinit_cert_matching_data **matchdata = NULL;
+
+ retval = crypto_cert_get_count(context, plg_cryptoctx, req_cryptoctx,
+ id_cryptoctx, &cert_count);
+ if (retval) {
+ pkiDebug("%s: crypto_cert_get_count error %d, %s\n",
+ __FUNCTION__, retval, error_message(retval));
+ goto cleanup;
+ }
+
+ pkiDebug("%s: crypto_cert_get_count says there are %d certs\n",
+ __FUNCTION__, cert_count);
+
+ matchdata = calloc((size_t)cert_count + 1, sizeof(*matchdata));
+ if (matchdata == NULL)
+ return ENOMEM;
+
+ retval = crypto_cert_iteration_begin(context, plg_cryptoctx, req_cryptoctx,
+ id_cryptoctx, &ih);
+ if (retval) {
+ pkiDebug("%s: crypto_cert_iteration_begin returned %d, %s\n",
+ __FUNCTION__, retval, error_message(retval));
+ goto cleanup;
+ }
+
+ for (i = 0; i < cert_count; i++) {
+ retval = crypto_cert_iteration_next(context, ih, &ch);
+ if (retval) {
+ if (retval == PKINIT_ITER_NO_MORE)
+ pkiDebug("%s: We thought there were %d certs, but "
+ "crypto_cert_iteration_next stopped after %d?\n",
+ __FUNCTION__, cert_count, i);
+ else
+ pkiDebug("%s: crypto_cert_iteration_next error %d, %s\n",
+ __FUNCTION__, retval, error_message(retval));
+ goto cleanup;
+ }
+
+ retval = crypto_cert_get_matching_data(context, ch, &matchdata[i]);
+ if (retval) {
+ pkiDebug("%s: crypto_cert_get_matching_data error %d, %s\n",
+ __FUNCTION__, retval, error_message(retval));
+ goto cleanup;
+ }
+
+ }
+
+ *all_matching_data = matchdata;
+ retval = 0;
+cleanup:
+ if (ih != NULL)
+ /* Solaris Kerberos */
+ (void) crypto_cert_iteration_end(context, ih);
+ if (retval) {
+ if (matchdata != NULL)
+ (void) free_all_cert_matching_data(context, matchdata);
+ }
+ pkiDebug("%s: returning %d, certinfo %p\n",
+ __FUNCTION__, retval, *all_matching_data);
+ return retval;
+}
+
+krb5_error_code
+pkinit_cert_matching(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ krb5_principal princ)
+{
+
+ krb5_error_code retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ int x;
+ char **rules = NULL;
+ rule_set *rs = NULL;
+ int match_found = 0;
+ pkinit_cert_matching_data **matchdata = NULL;
+ pkinit_cert_matching_data *the_matching_cert = NULL;
+
+ /* If no matching rules, select the default cert and we're done */
+ (void) pkinit_libdefault_strings(context, krb5_princ_realm(context, princ),
+ "pkinit_cert_match", &rules);
+ if (rules == NULL) {
+ pkiDebug("%s: no matching rules found in config file\n", __FUNCTION__);
+ retval = crypto_cert_select_default(context, plg_cryptoctx,
+ req_cryptoctx, id_cryptoctx);
+ goto cleanup;
+ }
+
+ /* parse each rule line one at a time and check all the certs against it */
+ for (x = 0; rules[x] != NULL; x++) {
+ pkiDebug("%s: Processing rule '%s'\n", __FUNCTION__, rules[x]);
+
+ /* Free rules from previous time through... */
+ if (rs != NULL) {
+ (void) free_rule_set(context, rs);
+ rs = NULL;
+ }
+ retval = parse_rule_set(context, rules[x], &rs);
+ if (retval) {
+ if (retval == EINVAL) {
+ pkiDebug("%s: Ignoring invalid rule pkinit_cert_match = '%s'\n",
+ __FUNCTION__, rules[x]);
+ continue;
+ }
+ goto cleanup;
+ }
+
+ /*
+ * Optimize so that we do not get cert info unless we have
+ * valid rules to check. Once obtained, keep it around
+ * until we are done.
+ */
+ if (matchdata == NULL) {
+ retval = obtain_all_cert_matching_data(context, plg_cryptoctx,
+ req_cryptoctx, id_cryptoctx,
+ &matchdata);
+ if (retval || matchdata == NULL) {
+ pkiDebug("%s: Error %d obtaining certificate information\n",
+ __FUNCTION__, retval);
+ retval = ENOENT;
+ goto cleanup;
+ }
+ }
+
+ retval = check_all_certs(context, plg_cryptoctx, req_cryptoctx,
+ id_cryptoctx, princ, rs, matchdata,
+ &match_found, &the_matching_cert);
+ if (retval) {
+ pkiDebug("%s: Error %d, checking certs against rule '%s'\n",
+ __FUNCTION__, retval, rules[x]);
+ goto cleanup;
+ }
+ if (match_found) {
+ pkiDebug("%s: We have an exact match with rule '%s'\n",
+ __FUNCTION__, rules[x]);
+ break;
+ }
+ }
+
+ if (match_found && the_matching_cert != NULL) {
+ pkiDebug("%s: Selecting the matching cert!\n", __FUNCTION__);
+ retval = crypto_cert_select(context, the_matching_cert);
+ if (retval) {
+ pkiDebug("%s: crypto_cert_select error %d, %s\n",
+ __FUNCTION__, retval, error_message(retval));
+ goto cleanup;
+ }
+ } else {
+ retval = ENOENT; /* XXX */
+ goto cleanup;
+ }
+
+ retval = 0;
+cleanup:
+ if (rules != NULL)
+ profile_free_list(rules);
+ if (rs != NULL)
+ /* Solaris Kerberos */
+ (void) free_rule_set(context, rs);
+ if (matchdata != NULL)
+ (void) free_all_cert_matching_data(context, matchdata);
+ return retval;
+}
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_profile.c b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_profile.c
new file mode 100644
index 0000000000..d11bb36f12
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_profile.c
@@ -0,0 +1,380 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "k5-int.h"
+#include "pkinit.h"
+
+/*
+ * Routines for handling profile [config file] options
+ */
+
+/* Forward prototypes */
+static int _krb5_conf_boolean(const char *s);
+
+/*
+ * XXX
+ * The following is duplicated verbatim from src/lib/krb5/krb/get_in_tkt.c,
+ * which is duplicated from somewhere else. :-/
+ * XXX
+ */
+static const char *const conf_yes[] = {
+ "y", "yes", "true", "t", "1", "on",
+ 0,
+};
+
+static const char *const conf_no[] = {
+ "n", "no", "false", "nil", "0", "off",
+ 0,
+};
+
+static int
+_krb5_conf_boolean(const char *s)
+{
+ const char *const *p;
+
+ for(p=conf_yes; *p; p++) {
+ if (strcasecmp(*p,s) == 0)
+ return 1;
+ }
+
+ for(p=conf_no; *p; p++) {
+ if (strcasecmp(*p,s) == 0)
+ return 0;
+ }
+
+ /* Default to "no" */
+ return 0;
+}
+
+/*
+ * XXX
+ * End duplicated code from src/lib/krb5/krb/get_in_tkt.c
+ * XXX
+ */
+
+/*
+ * The following are based on krb5_libdefault_* functions in
+ * src/lib/krb5/krb/get_in_tkt.c
+ * N.B. This assumes that context->default_realm has
+ * already been established.
+ */
+krb5_error_code
+pkinit_kdcdefault_strings(krb5_context context, const char *realmname,
+ const char *option, char ***ret_value)
+{
+ profile_t profile = NULL;
+ const char *names[5];
+ char **values = NULL;
+ krb5_error_code retval;
+
+ if (context == NULL)
+ return KV5M_CONTEXT;
+
+ profile = context->profile;
+
+ if (realmname != NULL) {
+ /*
+ * Try number one:
+ *
+ * [realms]
+ * REALM = {
+ * option = <value>
+ * }
+ */
+
+ names[0] = "realms";
+ names[1] = realmname;
+ names[2] = option;
+ names[3] = 0;
+ retval = profile_get_values(profile, names, &values);
+ if (retval == 0 && values != NULL)
+ goto goodbye;
+ }
+
+ /*
+ * Try number two:
+ *
+ * [kdcdefaults]
+ * option = <value>
+ */
+
+ names[0] = "kdcdefaults";
+ names[1] = option;
+ names[2] = 0;
+ retval = profile_get_values(profile, names, &values);
+ if (retval == 0 && values != NULL)
+ goto goodbye;
+
+goodbye:
+ if (values == NULL)
+ retval = ENOENT;
+
+ *ret_value = values;
+
+ return retval;
+
+}
+
+krb5_error_code
+pkinit_kdcdefault_string(krb5_context context, const char *realmname,
+ const char *option, char **ret_value)
+{
+ krb5_error_code retval;
+ char **values = NULL;
+
+ retval = pkinit_kdcdefault_strings(context, realmname, option, &values);
+ if (retval)
+ return retval;
+
+ if (values[0] == NULL) {
+ retval = ENOENT;
+ } else {
+ *ret_value = malloc(strlen(values[0]) + 1);
+ /* Solaris Kerberos */
+ if (*ret_value == NULL) {
+ pkiDebug(error_message(ENOMEM));
+ retval = ENOMEM;
+ }
+ else /* Solaris Kerberos */
+ (void) strlcpy(*ret_value, values[0], strlen(values[0]) + 1);
+ }
+
+ profile_free_list(values);
+ return retval;
+}
+
+krb5_error_code
+pkinit_kdcdefault_boolean(krb5_context context, const char *realmname,
+ const char *option, int default_value, int *ret_value)
+{
+ char *string = NULL;
+ krb5_error_code retval;
+
+ retval = pkinit_kdcdefault_string(context, realmname, option, &string);
+
+ if (retval == 0) {
+ *ret_value = _krb5_conf_boolean(string);
+ free(string);
+ } else
+ *ret_value = default_value;
+
+ return 0;
+}
+
+krb5_error_code
+pkinit_kdcdefault_integer(krb5_context context, const char *realmname,
+ const char *option, int default_value, int *ret_value)
+{
+ char *string = NULL;
+ krb5_error_code retval;
+
+ retval = pkinit_kdcdefault_string(context, realmname, option, &string);
+
+ if (retval == 0) {
+ char *endptr;
+ long l;
+ l = strtol(string, &endptr, 0);
+ if (endptr == string)
+ *ret_value = default_value;
+ else
+ *ret_value = l;
+ free(string);
+ } else
+ *ret_value = default_value;
+
+ return 0;
+}
+
+
+/*
+ * krb5_libdefault_string() is defined as static in
+ * src/lib/krb5/krb/get_in_tkt.c. Create local versions of
+ * krb5_libdefault_* functions here. We need a libdefaults_strings()
+ * function which is not currently supported there anyway. Also,
+ * add the ability to supply a default value for the boolean and
+ * integer functions.
+ */
+
+krb5_error_code
+pkinit_libdefault_strings(krb5_context context, const krb5_data *realm,
+ const char *option, char ***ret_value)
+{
+ profile_t profile;
+ const char *names[5];
+ char **values = NULL;
+ krb5_error_code retval;
+ char realmstr[1024];
+
+ if (realm != NULL && realm->length > sizeof(realmstr)-1)
+ return EINVAL;
+
+ if (realm != NULL) {
+ /* Solaris Kerberos */
+ (void) strlcpy(realmstr, realm->data, realm->length + 1);
+ realmstr[realm->length] = '\0';
+ }
+
+ if (!context || (context->magic != KV5M_CONTEXT))
+ return KV5M_CONTEXT;
+
+ profile = context->profile;
+
+
+ if (realm != NULL) {
+ /*
+ * Try number one:
+ *
+ * [libdefaults]
+ * REALM = {
+ * option = <value>
+ * }
+ */
+
+ names[0] = "libdefaults";
+ names[1] = realmstr;
+ names[2] = option;
+ names[3] = 0;
+ retval = profile_get_values(profile, names, &values);
+ if (retval == 0 && values != NULL && values[0] != NULL)
+ goto goodbye;
+
+ /*
+ * Try number two:
+ *
+ * [realms]
+ * REALM = {
+ * option = <value>
+ * }
+ */
+
+ names[0] = "realms";
+ names[1] = realmstr;
+ names[2] = option;
+ names[3] = 0;
+ retval = profile_get_values(profile, names, &values);
+ if (retval == 0 && values != NULL && values[0] != NULL)
+ goto goodbye;
+ }
+
+ /*
+ * Try number three:
+ *
+ * [libdefaults]
+ * option = <value>
+ */
+
+ names[0] = "libdefaults";
+ names[1] = option;
+ names[2] = 0;
+ retval = profile_get_values(profile, names, &values);
+ if (retval == 0 && values != NULL && values[0] != NULL)
+ goto goodbye;
+
+goodbye:
+ if (values == NULL)
+ return ENOENT;
+
+ *ret_value = values;
+
+ return retval;
+}
+
+krb5_error_code
+pkinit_libdefault_string(krb5_context context, const krb5_data *realm,
+ const char *option, char **ret_value)
+{
+ krb5_error_code retval;
+ char **values = NULL;
+
+ retval = pkinit_libdefault_strings(context, realm, option, &values);
+ if (retval)
+ return retval;
+
+ if (values[0] == NULL) {
+ retval = ENOENT;
+ } else {
+ *ret_value = malloc(strlen(values[0]) + 1);
+ if (*ret_value == NULL)
+ retval = ENOMEM;
+ else /* Solaris Kerberos */
+ (void) strlcpy(*ret_value, values[0], strlen(values[0]) + 1);
+ }
+
+ profile_free_list(values);
+ return retval;
+}
+
+krb5_error_code
+pkinit_libdefault_boolean(krb5_context context, const krb5_data *realm,
+ const char *option, int default_value,
+ int *ret_value)
+{
+ char *string = NULL;
+ krb5_error_code retval;
+
+ retval = pkinit_libdefault_string(context, realm, option, &string);
+
+ if (retval == 0) {
+ *ret_value = _krb5_conf_boolean(string);
+ free(string);
+ } else
+ *ret_value = default_value;
+
+ return 0;
+}
+
+krb5_error_code
+pkinit_libdefault_integer(krb5_context context, const krb5_data *realm,
+ const char *option, int default_value,
+ int *ret_value)
+{
+ char *string = NULL;
+ krb5_error_code retval;
+
+ retval = pkinit_libdefault_string(context, realm, option, &string);
+
+ if (retval == 0) {
+ char *endptr;
+ long l;
+ l = strtol(string, &endptr, 0);
+ if (endptr == string)
+ *ret_value = default_value;
+ else
+ *ret_value = l;
+ free(string);
+ }
+
+ return retval;
+}
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_srv.c b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_srv.c
new file mode 100644
index 0000000000..04f45828e5
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/pkinit_srv.c
@@ -0,0 +1,1426 @@
+/*
+ * COPYRIGHT (C) 2006,2007
+ * THE REGENTS OF THE UNIVERSITY OF MICHIGAN
+ * ALL RIGHTS RESERVED
+ *
+ * Permission is granted to use, copy, create derivative works
+ * and redistribute this software and such derivative works
+ * for any purpose, so long as the name of The University of
+ * Michigan is not used in any advertising or publicity
+ * pertaining to the use of distribution of this software
+ * without specific, written prior authorization. If the
+ * above copyright notice or any other identification of the
+ * University of Michigan is included in any copy of any
+ * portion of this software, then the disclaimer below must
+ * also be included.
+ *
+ * THIS SOFTWARE IS PROVIDED AS IS, WITHOUT REPRESENTATION
+ * FROM THE UNIVERSITY OF MICHIGAN AS TO ITS FITNESS FOR ANY
+ * PURPOSE, AND WITHOUT WARRANTY BY THE UNIVERSITY OF
+ * MICHIGAN OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING
+ * WITHOUT LIMITATION THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
+ * REGENTS OF THE UNIVERSITY OF MICHIGAN SHALL NOT BE LIABLE
+ * FOR ANY DAMAGES, INCLUDING SPECIAL, INDIRECT, INCIDENTAL, OR
+ * CONSEQUENTIAL DAMAGES, WITH RESPECT TO ANY CLAIM ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OF THE SOFTWARE, EVEN
+ * IF IT HAS BEEN OR IS HEREAFTER ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGES.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+
+#include "pkinit.h"
+
+static krb5_error_code
+pkinit_server_get_edata(krb5_context context,
+ krb5_kdc_req * request,
+ struct _krb5_db_entry_new * client,
+ struct _krb5_db_entry_new * server,
+ preauth_get_entry_data_proc server_get_entry_data,
+ void *pa_plugin_context,
+ krb5_pa_data * data);
+
+static krb5_error_code
+pkinit_server_verify_padata(krb5_context context,
+ struct _krb5_db_entry_new * client,
+ krb5_data *req_pkt,
+ krb5_kdc_req * request,
+ krb5_enc_tkt_part * enc_tkt_reply,
+ krb5_pa_data * data,
+ preauth_get_entry_data_proc server_get_entry_data,
+ void *pa_plugin_context,
+ void **pa_request_context,
+ krb5_data **e_data,
+ krb5_authdata ***authz_data);
+
+static krb5_error_code
+pkinit_server_return_padata(krb5_context context,
+ krb5_pa_data * padata,
+ struct _krb5_db_entry_new * client,
+ krb5_data *req_pkt,
+ krb5_kdc_req * request,
+ krb5_kdc_rep * reply,
+ struct _krb5_key_data * client_key,
+ krb5_keyblock * encrypting_key,
+ krb5_pa_data ** send_pa,
+ preauth_get_entry_data_proc server_get_entry_data,
+ void *pa_plugin_context,
+ void **pa_request_context);
+
+static int pkinit_server_get_flags
+ (krb5_context kcontext, krb5_preauthtype patype);
+
+static krb5_error_code pkinit_init_kdc_req_context
+ (krb5_context, void **blob);
+
+static void pkinit_fini_kdc_req_context
+ (krb5_context context, void *blob);
+
+static int pkinit_server_plugin_init_realm
+ (krb5_context context, const char *realmname,
+ pkinit_kdc_context *pplgctx);
+
+static void pkinit_server_plugin_fini_realm
+ (krb5_context context, pkinit_kdc_context plgctx);
+
+static int pkinit_server_plugin_init
+ (krb5_context context, void **blob, const char **realmnames);
+
+static void pkinit_server_plugin_fini
+ (krb5_context context, void *blob);
+
+static pkinit_kdc_context pkinit_find_realm_context
+ (krb5_context context, void *pa_plugin_context, krb5_principal princ);
+
+static krb5_error_code
+pkinit_create_edata(krb5_context context,
+ pkinit_plg_crypto_context plg_cryptoctx,
+ pkinit_req_crypto_context req_cryptoctx,
+ pkinit_identity_crypto_context id_cryptoctx,
+ pkinit_plg_opts *opts,
+ krb5_error_code err_code,
+ krb5_data **e_data)
+{
+ krb5_error_code retval = KRB5KRB_ERR_GENERIC;
+
+ pkiDebug("pkinit_create_edata: creating edata for error %d (%s)\n",
+ err_code, error_message(err_code));
+ switch(err_code) {
+ case KRB5KDC_ERR_CANT_VERIFY_CERTIFICATE:
+ retval = pkinit_create_td_trusted_certifiers(context,
+ plg_cryptoctx, req_cryptoctx, id_cryptoctx, e_data);
+ break;
+ case KRB5KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED:
+ retval = pkinit_create_td_dh_parameters(context, plg_cryptoctx,
+ req_cryptoctx, id_cryptoctx, opts, e_data);
+ break;
+ case KRB5KDC_ERR_INVALID_CERTIFICATE:
+ case KRB5KDC_ERR_REVOKED_CERTIFICATE:
+ retval = pkinit_create_td_invalid_certificate(context,
+ plg_cryptoctx, req_cryptoctx, id_cryptoctx, e_data);
+ break;
+ default:
+ pkiDebug("no edata needed for error %d (%s)\n",
+ err_code, error_message(err_code));
+ retval = 0;
+ goto cleanup;
+ }
+
+cleanup:
+
+ return retval;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+pkinit_server_get_edata(krb5_context context,
+ krb5_kdc_req * request,
+ struct _krb5_db_entry_new * client,
+ struct _krb5_db_entry_new * server,
+ preauth_get_entry_data_proc server_get_entry_data,
+ void *pa_plugin_context,
+ krb5_pa_data * data)
+{
+ krb5_error_code retval = 0;
+ pkinit_kdc_context plgctx = NULL;
+
+ pkiDebug("pkinit_server_get_edata: entered!\n");
+
+ /*
+ * If we don't have a realm context for the given realm,
+ * don't tell the client that we support pkinit!
+ */
+ plgctx = pkinit_find_realm_context(context, pa_plugin_context,
+ request->server);
+ if (plgctx == NULL)
+ retval = EINVAL;
+
+ return retval;
+}
+
+static krb5_error_code
+verify_client_san(krb5_context context,
+ pkinit_kdc_context plgctx,
+ pkinit_kdc_req_context reqctx,
+ krb5_principal client,
+ int *valid_san)
+{
+ krb5_error_code retval;
+ krb5_principal *princs = NULL;
+ krb5_principal *upns = NULL;
+ int i;
+#ifdef DEBUG_SAN_INFO
+ char *client_string = NULL, *san_string;
+#endif
+
+ retval = crypto_retrieve_cert_sans(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, plgctx->idctx,
+ &princs,
+ plgctx->opts->allow_upn ? &upns : NULL,
+ NULL);
+ if (retval) {
+ pkiDebug("%s: error from retrieve_certificate_sans()\n", __FUNCTION__);
+ retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+ goto out;
+ }
+ /* XXX Verify this is consistent with client side XXX */
+#if 0
+ retval = call_san_checking_plugins(context, plgctx, reqctx, princs,
+ upns, NULL, &plugin_decision, &ignore);
+ pkiDebug("%s: call_san_checking_plugins() returned retval %d\n",
+ __FUNCTION__);
+ if (retval) {
+ retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+ goto cleanup;
+ }
+ pkiDebug("%s: call_san_checking_plugins() returned decision %d\n",
+ __FUNCTION__, plugin_decision);
+ if (plugin_decision != NO_DECISION) {
+ retval = plugin_decision;
+ goto out;
+ }
+#endif
+
+#ifdef DEBUG_SAN_INFO
+ krb5_unparse_name(context, client, &client_string);
+#endif
+ pkiDebug("%s: Checking pkinit sans\n", __FUNCTION__);
+ for (i = 0; princs != NULL && princs[i] != NULL; i++) {
+#ifdef DEBUG_SAN_INFO
+ krb5_unparse_name(context, princs[i], &san_string);
+ pkiDebug("%s: Comparing client '%s' to pkinit san value '%s'\n",
+ __FUNCTION__, client_string, san_string);
+ krb5_free_unparsed_name(context, san_string);
+#endif
+ if (krb5_principal_compare(context, princs[i], client)) {
+ pkiDebug("%s: pkinit san match found\n", __FUNCTION__);
+ *valid_san = 1;
+ retval = 0;
+ goto out;
+ }
+ }
+ pkiDebug("%s: no pkinit san match found\n", __FUNCTION__);
+ /*
+ * XXX if cert has names but none match, should we
+ * be returning KRB5KDC_ERR_CLIENT_NAME_MISMATCH here?
+ */
+
+ if (upns == NULL) {
+ pkiDebug("%s: no upn sans (or we wouldn't accept them anyway)\n",
+ __FUNCTION__);
+ retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+ goto out;
+ }
+
+ pkiDebug("%s: Checking upn sans\n", __FUNCTION__);
+ for (i = 0; upns[i] != NULL; i++) {
+#ifdef DEBUG_SAN_INFO
+ krb5_unparse_name(context, upns[i], &san_string);
+ pkiDebug("%s: Comparing client '%s' to upn san value '%s'\n",
+ __FUNCTION__, client_string, san_string);
+ krb5_free_unparsed_name(context, san_string);
+#endif
+ if (krb5_principal_compare(context, upns[i], client)) {
+ pkiDebug("%s: upn san match found\n", __FUNCTION__);
+ *valid_san = 1;
+ retval = 0;
+ goto out;
+ }
+ }
+ pkiDebug("%s: no upn san match found\n", __FUNCTION__);
+
+ /* We found no match */
+ if (princs != NULL || upns != NULL) {
+ *valid_san = 0;
+ /* XXX ??? If there was one or more name in the cert, but
+ * none matched the client name, then return mismatch? */
+ retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+ }
+ retval = 0;
+
+out:
+ if (princs != NULL) {
+ for (i = 0; princs[i] != NULL; i++)
+ krb5_free_principal(context, princs[i]);
+ free(princs);
+ }
+ if (upns != NULL) {
+ for (i = 0; upns[i] != NULL; i++)
+ krb5_free_principal(context, upns[i]);
+ free(upns);
+ }
+#ifdef DEBUG_SAN_INFO
+ if (client_string != NULL)
+ krb5_free_unparsed_name(context, client_string);
+#endif
+ pkiDebug("%s: returning retval %d, valid_san %d\n",
+ __FUNCTION__, retval, *valid_san);
+ return retval;
+}
+
+static krb5_error_code
+verify_client_eku(krb5_context context,
+ pkinit_kdc_context plgctx,
+ pkinit_kdc_req_context reqctx,
+ int *eku_accepted)
+{
+ krb5_error_code retval;
+
+ *eku_accepted = 0;
+
+ if (plgctx->opts->require_eku == 0) {
+ pkiDebug("%s: configuration requests no EKU checking\n", __FUNCTION__);
+ *eku_accepted = 1;
+ retval = 0;
+ goto out;
+ }
+
+ retval = crypto_check_cert_eku(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, plgctx->idctx,
+ 0, /* kdc cert */
+ plgctx->opts->accept_secondary_eku,
+ eku_accepted);
+ if (retval) {
+ pkiDebug("%s: Error from crypto_check_cert_eku %d (%s)\n",
+ __FUNCTION__, retval, error_message(retval));
+ goto out;
+ }
+
+out:
+ pkiDebug("%s: returning retval %d, eku_accepted %d\n",
+ __FUNCTION__, retval, *eku_accepted);
+ return retval;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+pkinit_server_verify_padata(krb5_context context,
+ struct _krb5_db_entry_new * client,
+ krb5_data *req_pkt,
+ krb5_kdc_req * request,
+ krb5_enc_tkt_part * enc_tkt_reply,
+ krb5_pa_data * data,
+ preauth_get_entry_data_proc server_get_entry_data,
+ void *pa_plugin_context,
+ void **pa_request_context,
+ krb5_data **e_data,
+ krb5_authdata ***authz_data)
+{
+ krb5_error_code retval = 0;
+ krb5_octet_data authp_data = {0, 0, NULL}, krb5_authz = {0, 0, NULL};
+ krb5_data *encoded_pkinit_authz_data = NULL;
+ krb5_pa_pk_as_req *reqp = NULL;
+ krb5_pa_pk_as_req_draft9 *reqp9 = NULL;
+ krb5_auth_pack *auth_pack = NULL;
+ krb5_auth_pack_draft9 *auth_pack9 = NULL;
+ pkinit_kdc_context plgctx = NULL;
+ pkinit_kdc_req_context reqctx;
+/* Solaris Kerberos: set but not used */
+#if 0
+ krb5_preauthtype pa_type;
+#endif
+ krb5_checksum cksum = {0, 0, 0, NULL};
+ krb5_data *der_req = NULL;
+ int valid_eku = 0, valid_san = 0;
+ krb5_authdata **my_authz_data = NULL, *pkinit_authz_data = NULL;
+ krb5_kdc_req *tmp_as_req = NULL;
+ krb5_data k5data;
+
+ pkiDebug("pkinit_verify_padata: entered!\n");
+ /* Solaris Kerberos */
+ if (data == NULL || data->length == 0 || data->contents == NULL)
+ return 0;
+
+ if (pa_plugin_context == NULL || e_data == NULL)
+ return EINVAL;
+
+ plgctx = pkinit_find_realm_context(context, pa_plugin_context,
+ request->server);
+ if (plgctx == NULL)
+ return 0;
+
+#ifdef DEBUG_ASN1
+ print_buffer_bin(data->contents, data->length, "/tmp/kdc_as_req");
+#endif
+ /* create a per-request context */
+ retval = pkinit_init_kdc_req_context(context, (void **)&reqctx);
+ if (retval)
+ goto cleanup;
+ reqctx->pa_type = data->pa_type;
+
+ PADATA_TO_KRB5DATA(data, &k5data);
+
+ switch ((int)data->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ pkiDebug("processing KRB5_PADATA_PK_AS_REQ\n");
+ retval = k5int_decode_krb5_pa_pk_as_req(&k5data, &reqp);
+ if (retval) {
+ pkiDebug("decode_krb5_pa_pk_as_req failed\n");
+ goto cleanup;
+ }
+#ifdef DEBUG_ASN1
+ print_buffer_bin(reqp->signedAuthPack.data,
+ reqp->signedAuthPack.length,
+ "/tmp/kdc_signed_data");
+#endif
+ retval = cms_signeddata_verify(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, plgctx->idctx, CMS_SIGN_CLIENT,
+ plgctx->opts->require_crl_checking,
+ reqp->signedAuthPack.data, reqp->signedAuthPack.length,
+ &authp_data.data, &authp_data.length, &krb5_authz.data,
+ &krb5_authz.length);
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ pkiDebug("processing KRB5_PADATA_PK_AS_REQ_OLD\n");
+ retval = k5int_decode_krb5_pa_pk_as_req_draft9(&k5data, &reqp9);
+ if (retval) {
+ pkiDebug("decode_krb5_pa_pk_as_req_draft9 failed\n");
+ goto cleanup;
+ }
+#ifdef DEBUG_ASN1
+ print_buffer_bin(reqp9->signedAuthPack.data,
+ reqp9->signedAuthPack.length,
+ "/tmp/kdc_signed_data_draft9");
+#endif
+
+ retval = cms_signeddata_verify(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, plgctx->idctx, CMS_SIGN_DRAFT9,
+ plgctx->opts->require_crl_checking,
+ reqp9->signedAuthPack.data, reqp9->signedAuthPack.length,
+ &authp_data.data, &authp_data.length, &krb5_authz.data,
+ &krb5_authz.length);
+ break;
+ default:
+ pkiDebug("unrecognized pa_type = %d\n", data->pa_type);
+ retval = EINVAL;
+ goto cleanup;
+ }
+ if (retval) {
+ pkiDebug("pkcs7_signeddata_verify failed\n");
+ goto cleanup;
+ }
+
+ retval = verify_client_san(context, plgctx, reqctx, request->client,
+ &valid_san);
+ if (retval)
+ goto cleanup;
+ if (!valid_san) {
+ pkiDebug("%s: did not find an acceptable SAN in user certificate\n",
+ __FUNCTION__);
+ retval = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
+ goto cleanup;
+ }
+ retval = verify_client_eku(context, plgctx, reqctx, &valid_eku);
+ if (retval)
+ goto cleanup;
+
+ if (!valid_eku) {
+ pkiDebug("%s: did not find an acceptable EKU in user certificate\n",
+ __FUNCTION__);
+ retval = KRB5KDC_ERR_INCONSISTENT_KEY_PURPOSE;
+ goto cleanup;
+ }
+
+#ifdef DEBUG_ASN1
+ print_buffer_bin(authp_data.data, authp_data.length, "/tmp/kdc_auth_pack");
+#endif
+
+ OCTETDATA_TO_KRB5DATA(&authp_data, &k5data);
+ switch ((int)data->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ retval = k5int_decode_krb5_auth_pack(&k5data, &auth_pack);
+ if (retval) {
+ pkiDebug("failed to decode krb5_auth_pack\n");
+ goto cleanup;
+ }
+
+ /* check dh parameters */
+ if (auth_pack->clientPublicValue != NULL) {
+ retval = server_check_dh(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, plgctx->idctx,
+ &auth_pack->clientPublicValue->algorithm.parameters,
+ plgctx->opts->dh_min_bits);
+
+ if (retval) {
+ pkiDebug("bad dh parameters\n");
+ goto cleanup;
+ }
+ }
+ /*
+ * The KDC may have modified the request after decoding it.
+ * We need to compute the checksum on the data that
+ * came from the client. Therefore, we use the original
+ * packet contents.
+ */
+ retval = k5int_decode_krb5_as_req(req_pkt, &tmp_as_req);
+ if (retval) {
+ pkiDebug("decode_krb5_as_req returned %d\n", (int)retval);
+ goto cleanup;
+ }
+
+ retval = k5int_encode_krb5_kdc_req_body(tmp_as_req, &der_req);
+ if (retval) {
+ pkiDebug("encode_krb5_kdc_req_body returned %d\n", (int) retval);
+ goto cleanup;
+ }
+ retval = krb5_c_make_checksum(context, CKSUMTYPE_NIST_SHA, NULL,
+ 0, der_req, &cksum);
+ if (retval) {
+ pkiDebug("unable to calculate AS REQ checksum\n");
+ goto cleanup;
+ }
+ if (cksum.length != auth_pack->pkAuthenticator.paChecksum.length ||
+ memcmp(cksum.contents,
+ auth_pack->pkAuthenticator.paChecksum.contents,
+ cksum.length)) {
+ pkiDebug("failed to match the checksum\n");
+#ifdef DEBUG_CKSUM
+ pkiDebug("calculating checksum on buf size (%d)\n",
+ req_pkt->length);
+ print_buffer(req_pkt->data, req_pkt->length);
+ pkiDebug("received checksum type=%d size=%d ",
+ auth_pack->pkAuthenticator.paChecksum.checksum_type,
+ auth_pack->pkAuthenticator.paChecksum.length);
+ print_buffer(auth_pack->pkAuthenticator.paChecksum.contents,
+ auth_pack->pkAuthenticator.paChecksum.length);
+ pkiDebug("expected checksum type=%d size=%d ",
+ cksum.checksum_type, cksum.length);
+ print_buffer(cksum.contents, cksum.length);
+#endif
+
+ retval = KRB5KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED;
+ goto cleanup;
+ }
+
+ /* check if kdcPkId present and match KDC's subjectIdentifier */
+ if (reqp->kdcPkId.data != NULL) {
+ int valid_kdcPkId = 0;
+ retval = pkinit_check_kdc_pkid(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, plgctx->idctx,
+ reqp->kdcPkId.data, reqp->kdcPkId.length, &valid_kdcPkId);
+ if (retval)
+ goto cleanup;
+ if (!valid_kdcPkId)
+ pkiDebug("kdcPkId in AS_REQ does not match KDC's cert"
+ "RFC says to ignore and proceed\n");
+
+ }
+ /* remember the decoded auth_pack for verify_padata routine */
+ reqctx->rcv_auth_pack = auth_pack;
+ auth_pack = NULL;
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ retval = k5int_decode_krb5_auth_pack_draft9(&k5data, &auth_pack9);
+ if (retval) {
+ pkiDebug("failed to decode krb5_auth_pack_draft9\n");
+ goto cleanup;
+ }
+ if (auth_pack9->clientPublicValue != NULL) {
+ retval = server_check_dh(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, plgctx->idctx,
+ &auth_pack9->clientPublicValue->algorithm.parameters,
+ plgctx->opts->dh_min_bits);
+
+ if (retval) {
+ pkiDebug("bad dh parameters\n");
+ goto cleanup;
+ }
+ }
+ /* remember the decoded auth_pack for verify_padata routine */
+ reqctx->rcv_auth_pack9 = auth_pack9;
+ auth_pack9 = NULL;
+ break;
+ }
+
+ /* return authorization data to be included in the ticket */
+ switch ((int)data->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ my_authz_data = malloc(2 * sizeof(*my_authz_data));
+ if (my_authz_data == NULL) {
+ retval = ENOMEM;
+ pkiDebug("Couldn't allocate krb5_authdata ptr array\n");
+ goto cleanup;
+ }
+ my_authz_data[1] = NULL;
+ my_authz_data[0] = malloc(sizeof(krb5_authdata));
+ if (my_authz_data[0] == NULL) {
+ retval = ENOMEM;
+ pkiDebug("Couldn't allocate krb5_authdata\n");
+ free(my_authz_data);
+ goto cleanup;
+ }
+ /* AD-INITIAL-VERIFIED-CAS must be wrapped in AD-IF-RELEVANT */
+ my_authz_data[0]->magic = KV5M_AUTHDATA;
+ my_authz_data[0]->ad_type = KRB5_AUTHDATA_IF_RELEVANT;
+
+ /* create an internal AD-INITIAL-VERIFIED-CAS data */
+ pkinit_authz_data = malloc(sizeof(krb5_authdata));
+ if (pkinit_authz_data == NULL) {
+ retval = ENOMEM;
+ pkiDebug("Couldn't allocate krb5_authdata\n");
+ free(my_authz_data[0]);
+ free(my_authz_data);
+ goto cleanup;
+ }
+ pkinit_authz_data->ad_type = KRB5_AUTHDATA_INITIAL_VERIFIED_CAS;
+ /* content of this ad-type contains the certification
+ path with which the client certificate was validated
+ */
+ pkinit_authz_data->contents = krb5_authz.data;
+ pkinit_authz_data->length = krb5_authz.length;
+ retval = k5int_encode_krb5_authdata_elt(pkinit_authz_data,
+ &encoded_pkinit_authz_data);
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)encoded_pkinit_authz_data->data,
+ encoded_pkinit_authz_data->length,
+ "/tmp/kdc_pkinit_authz_data");
+#endif
+ free(pkinit_authz_data);
+ if (retval) {
+ pkiDebug("k5int_encode_krb5_authdata_elt failed\n");
+ free(my_authz_data[0]);
+ free(my_authz_data);
+ goto cleanup;
+ }
+
+ my_authz_data[0]->contents =
+ (krb5_octet *) encoded_pkinit_authz_data->data;
+ my_authz_data[0]->length = encoded_pkinit_authz_data->length;
+ *authz_data = my_authz_data;
+ pkiDebug("Returning %d bytes of authorization data\n",
+ krb5_authz.length);
+ encoded_pkinit_authz_data->data = NULL; /* Don't free during cleanup*/
+ free(encoded_pkinit_authz_data);
+ break;
+ default:
+ *authz_data = NULL;
+ }
+ /* remember to set the PREAUTH flag in the reply */
+ enc_tkt_reply->flags |= TKT_FLG_PRE_AUTH;
+ *pa_request_context = reqctx;
+ reqctx = NULL;
+
+ cleanup:
+ if (retval && data->pa_type == KRB5_PADATA_PK_AS_REQ) {
+ pkiDebug("pkinit_verify_padata failed: creating e-data\n");
+ if (pkinit_create_edata(context, plgctx->cryptoctx, reqctx->cryptoctx,
+ plgctx->idctx, plgctx->opts, retval, e_data))
+ pkiDebug("pkinit_create_edata failed\n");
+ }
+
+ switch ((int)data->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ free_krb5_pa_pk_as_req(&reqp);
+ if (cksum.contents != NULL)
+ free(cksum.contents);
+ if (der_req != NULL)
+ krb5_free_data(context, der_req);
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ free_krb5_pa_pk_as_req_draft9(&reqp9);
+ }
+ if (tmp_as_req != NULL)
+ k5int_krb5_free_kdc_req(context, tmp_as_req);
+ if (authp_data.data != NULL)
+ free(authp_data.data);
+ if (krb5_authz.data != NULL)
+ free(krb5_authz.data);
+ if (reqctx != NULL)
+ pkinit_fini_kdc_req_context(context, reqctx);
+ if (auth_pack != NULL)
+ free_krb5_auth_pack(&auth_pack);
+ if (auth_pack9 != NULL)
+ free_krb5_auth_pack_draft9(context, &auth_pack9);
+
+ return retval;
+}
+
+/* ARGSUSED */
+static krb5_error_code
+pkinit_server_return_padata(krb5_context context,
+ krb5_pa_data * padata,
+ struct _krb5_db_entry_new * client,
+ krb5_data *req_pkt,
+ krb5_kdc_req * request,
+ krb5_kdc_rep * reply,
+ struct _krb5_key_data * client_key,
+ krb5_keyblock * encrypting_key,
+ krb5_pa_data ** send_pa,
+ preauth_get_entry_data_proc server_get_entry_data,
+ void *pa_plugin_context,
+ void **pa_request_context)
+{
+ krb5_error_code retval = 0;
+ krb5_data scratch = {0, 0, NULL};
+ krb5_pa_pk_as_req *reqp = NULL;
+ krb5_pa_pk_as_req_draft9 *reqp9 = NULL;
+ int i = 0;
+
+ unsigned char *subjectPublicKey = NULL;
+ unsigned char *dh_pubkey = NULL, *server_key = NULL;
+ unsigned int subjectPublicKey_len = 0;
+ unsigned int server_key_len = 0, dh_pubkey_len = 0;
+
+ krb5_kdc_dh_key_info dhkey_info;
+ krb5_data *encoded_dhkey_info = NULL;
+ krb5_pa_pk_as_rep *rep = NULL;
+ krb5_pa_pk_as_rep_draft9 *rep9 = NULL;
+ krb5_data *out_data = NULL;
+
+ krb5_enctype enctype = -1;
+
+ krb5_reply_key_pack *key_pack = NULL;
+ krb5_reply_key_pack_draft9 *key_pack9 = NULL;
+ krb5_data *encoded_key_pack = NULL;
+ unsigned int num_types;
+ krb5_cksumtype *cksum_types = NULL;
+
+ pkinit_kdc_context plgctx;
+ pkinit_kdc_req_context reqctx;
+
+ int fixed_keypack = 0;
+
+ *send_pa = NULL;
+ /* Solaris Kerberos */
+ if (padata == NULL || padata->length == 0 || padata->contents == NULL)
+ return 0;
+
+ if (pa_request_context == NULL || *pa_request_context == NULL) {
+ pkiDebug("missing request context \n");
+ return EINVAL;
+ }
+
+ plgctx = pkinit_find_realm_context(context, pa_plugin_context,
+ request->server);
+ if (plgctx == NULL) {
+ pkiDebug("Unable to locate correct realm context\n");
+ return ENOENT;
+ }
+
+ pkiDebug("pkinit_return_padata: entered!\n");
+ reqctx = (pkinit_kdc_req_context)*pa_request_context;
+
+ if (encrypting_key->contents) {
+ free(encrypting_key->contents);
+ encrypting_key->length = 0;
+ encrypting_key->contents = NULL;
+ }
+
+ for(i = 0; i < request->nktypes; i++) {
+ enctype = request->ktype[i];
+ if (!krb5_c_valid_enctype(enctype))
+ continue;
+ else {
+ pkiDebug("KDC picked etype = %d\n", enctype);
+ break;
+ }
+ }
+
+ if (i == request->nktypes) {
+ retval = KRB5KDC_ERR_ETYPE_NOSUPP;
+ goto cleanup;
+ }
+
+ switch((int)reqctx->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ init_krb5_pa_pk_as_rep(&rep);
+ if (rep == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ /* let's assume it's RSA. we'll reset it to DH if needed */
+ rep->choice = choice_pa_pk_as_rep_encKeyPack;
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ init_krb5_pa_pk_as_rep_draft9(&rep9);
+ if (rep9 == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ rep9->choice = choice_pa_pk_as_rep_draft9_encKeyPack;
+ break;
+ default:
+ retval = KRB5KDC_ERR_PREAUTH_FAILED;
+ goto cleanup;
+ }
+
+ if (reqctx->rcv_auth_pack != NULL &&
+ reqctx->rcv_auth_pack->clientPublicValue != NULL) {
+ subjectPublicKey =
+ reqctx->rcv_auth_pack->clientPublicValue->subjectPublicKey.data;
+ subjectPublicKey_len =
+ reqctx->rcv_auth_pack->clientPublicValue->subjectPublicKey.length;
+ rep->choice = choice_pa_pk_as_rep_dhInfo;
+ } else if (reqctx->rcv_auth_pack9 != NULL &&
+ reqctx->rcv_auth_pack9->clientPublicValue != NULL) {
+ subjectPublicKey =
+ reqctx->rcv_auth_pack9->clientPublicValue->subjectPublicKey.data;
+ subjectPublicKey_len =
+ reqctx->rcv_auth_pack9->clientPublicValue->subjectPublicKey.length;
+ rep9->choice = choice_pa_pk_as_rep_draft9_dhSignedData;
+ }
+
+ /* if this DH, then process finish computing DH key */
+ if (rep != NULL && (rep->choice == choice_pa_pk_as_rep_dhInfo ||
+ rep->choice == choice_pa_pk_as_rep_draft9_dhSignedData)) {
+ pkiDebug("received DH key delivery AS REQ\n");
+ retval = server_process_dh(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, plgctx->idctx, subjectPublicKey,
+ subjectPublicKey_len, &dh_pubkey, &dh_pubkey_len,
+ &server_key, &server_key_len);
+ if (retval) {
+ pkiDebug("failed to process/create dh paramters\n");
+ goto cleanup;
+ }
+ }
+
+ if ((rep9 != NULL &&
+ rep9->choice == choice_pa_pk_as_rep_draft9_dhSignedData) ||
+ (rep != NULL && rep->choice == choice_pa_pk_as_rep_dhInfo)) {
+ retval = pkinit_octetstring2key(context, enctype, server_key,
+ server_key_len, encrypting_key);
+ if (retval) {
+ pkiDebug("pkinit_octetstring2key failed: %s\n",
+ error_message(retval));
+ goto cleanup;
+ }
+
+ dhkey_info.subjectPublicKey.length = dh_pubkey_len;
+ dhkey_info.subjectPublicKey.data = dh_pubkey;
+ dhkey_info.nonce = request->nonce;
+ dhkey_info.dhKeyExpiration = 0;
+
+ retval = k5int_encode_krb5_kdc_dh_key_info(&dhkey_info,
+ &encoded_dhkey_info);
+ if (retval) {
+ pkiDebug("encode_krb5_kdc_dh_key_info failed\n");
+ goto cleanup;
+ }
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)encoded_dhkey_info->data,
+ encoded_dhkey_info->length,
+ "/tmp/kdc_dh_key_info");
+#endif
+
+ switch ((int)padata->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ retval = cms_signeddata_create(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, plgctx->idctx, CMS_SIGN_SERVER, 1,
+ (unsigned char *)encoded_dhkey_info->data,
+ encoded_dhkey_info->length,
+ &rep->u.dh_Info.dhSignedData.data,
+ &rep->u.dh_Info.dhSignedData.length);
+ if (retval) {
+ pkiDebug("failed to create pkcs7 signed data\n");
+ goto cleanup;
+ }
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ retval = cms_signeddata_create(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, plgctx->idctx, CMS_SIGN_DRAFT9, 1,
+ (unsigned char *)encoded_dhkey_info->data,
+ encoded_dhkey_info->length,
+ &rep9->u.dhSignedData.data,
+ &rep9->u.dhSignedData.length);
+ if (retval) {
+ pkiDebug("failed to create pkcs7 signed data\n");
+ goto cleanup;
+ }
+ break;
+ }
+ } else {
+ pkiDebug("received RSA key delivery AS REQ\n");
+
+ retval = krb5_c_make_random_key(context, enctype, encrypting_key);
+ if (retval) {
+ pkiDebug("unable to make a session key\n");
+ goto cleanup;
+ }
+
+ /* check if PA_TYPE of 132 is present which means the client is
+ * requesting that a checksum is send back instead of the nonce
+ */
+ for (i = 0; request->padata[i] != NULL; i++) {
+ pkiDebug("%s: Checking pa_type 0x%08x\n",
+ __FUNCTION__, request->padata[i]->pa_type);
+ if (request->padata[i]->pa_type == 132)
+ fixed_keypack = 1;
+ }
+ pkiDebug("%s: return checksum instead of nonce = %d\n",
+ __FUNCTION__, fixed_keypack);
+
+ /* if this is an RFC reply or draft9 client requested a checksum
+ * in the reply instead of the nonce, create an RFC-style keypack
+ */
+ if ((int)padata->pa_type == KRB5_PADATA_PK_AS_REQ || fixed_keypack) {
+ init_krb5_reply_key_pack(&key_pack);
+ if (key_pack == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ /* retrieve checksums for a given enctype of the reply key */
+ retval = krb5_c_keyed_checksum_types(context,
+ encrypting_key->enctype, &num_types, &cksum_types);
+ if (retval)
+ goto cleanup;
+
+ /* pick the first of acceptable enctypes for the checksum */
+ retval = krb5_c_make_checksum(context, cksum_types[0],
+ encrypting_key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
+ req_pkt, &key_pack->asChecksum);
+ if (retval) {
+ pkiDebug("unable to calculate AS REQ checksum\n");
+ goto cleanup;
+ }
+#ifdef DEBUG_CKSUM
+ pkiDebug("calculating checksum on buf size = %d\n", req_pkt->length);
+ print_buffer(req_pkt->data, req_pkt->length);
+ pkiDebug("checksum size = %d\n", key_pack->asChecksum.length);
+ print_buffer(key_pack->asChecksum.contents,
+ key_pack->asChecksum.length);
+ pkiDebug("encrypting key (%d)\n", encrypting_key->length);
+ print_buffer(encrypting_key->contents, encrypting_key->length);
+#endif
+
+ krb5_copy_keyblock_contents(context, encrypting_key,
+ &key_pack->replyKey);
+
+ retval = k5int_encode_krb5_reply_key_pack(key_pack,
+ &encoded_key_pack);
+ if (retval) {
+ pkiDebug("failed to encode reply_key_pack\n");
+ goto cleanup;
+ }
+ }
+
+ switch ((int)padata->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ rep->choice = choice_pa_pk_as_rep_encKeyPack;
+ retval = cms_envelopeddata_create(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, plgctx->idctx, padata->pa_type, 1,
+ (unsigned char *)encoded_key_pack->data,
+ encoded_key_pack->length,
+ &rep->u.encKeyPack.data, &rep->u.encKeyPack.length);
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ /* if the request is from the broken draft9 client that
+ * expects back a nonce, create it now
+ */
+ if (!fixed_keypack) {
+ init_krb5_reply_key_pack_draft9(&key_pack9);
+ if (key_pack9 == NULL) {
+ retval = ENOMEM;
+ goto cleanup;
+ }
+ key_pack9->nonce = reqctx->rcv_auth_pack9->pkAuthenticator.nonce;
+ krb5_copy_keyblock_contents(context, encrypting_key,
+ &key_pack9->replyKey);
+
+ retval = k5int_encode_krb5_reply_key_pack_draft9(key_pack9,
+ &encoded_key_pack);
+ if (retval) {
+ pkiDebug("failed to encode reply_key_pack\n");
+ goto cleanup;
+ }
+ }
+
+ rep9->choice = choice_pa_pk_as_rep_draft9_encKeyPack;
+ retval = cms_envelopeddata_create(context, plgctx->cryptoctx,
+ reqctx->cryptoctx, plgctx->idctx, padata->pa_type, 1,
+ (unsigned char *)encoded_key_pack->data,
+ encoded_key_pack->length,
+ &rep9->u.encKeyPack.data, &rep9->u.encKeyPack.length);
+ break;
+ }
+ if (retval) {
+ pkiDebug("failed to create pkcs7 enveloped data: %s\n",
+ error_message(retval));
+ goto cleanup;
+ }
+#ifdef DEBUG_ASN1
+ print_buffer_bin((unsigned char *)encoded_key_pack->data,
+ encoded_key_pack->length,
+ "/tmp/kdc_key_pack");
+ switch ((int)padata->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ print_buffer_bin(rep->u.encKeyPack.data,
+ rep->u.encKeyPack.length,
+ "/tmp/kdc_enc_key_pack");
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ print_buffer_bin(rep9->u.encKeyPack.data,
+ rep9->u.encKeyPack.length,
+ "/tmp/kdc_enc_key_pack");
+ break;
+ }
+#endif
+ }
+
+ switch ((int)padata->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ retval = k5int_encode_krb5_pa_pk_as_rep(rep, &out_data);
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ retval = k5int_encode_krb5_pa_pk_as_rep_draft9(rep9, &out_data);
+ break;
+ }
+ if (retval) {
+ pkiDebug("failed to encode AS_REP\n");
+ goto cleanup;
+ }
+#ifdef DEBUG_ASN1
+ if (out_data != NULL)
+ print_buffer_bin((unsigned char *)out_data->data, out_data->length,
+ "/tmp/kdc_as_rep");
+#endif
+
+ *send_pa = (krb5_pa_data *) malloc(sizeof(krb5_pa_data));
+ if (*send_pa == NULL) {
+ retval = ENOMEM;
+ free(out_data->data);
+ free(out_data);
+ out_data = NULL;
+ goto cleanup;
+ }
+ (*send_pa)->magic = KV5M_PA_DATA;
+ switch ((int)padata->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ (*send_pa)->pa_type = KRB5_PADATA_PK_AS_REP;
+ break;
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ (*send_pa)->pa_type = KRB5_PADATA_PK_AS_REP_OLD;
+ break;
+ }
+ (*send_pa)->length = out_data->length;
+ (*send_pa)->contents = (krb5_octet *) out_data->data;
+
+
+ cleanup:
+ pkinit_fini_kdc_req_context(context, reqctx);
+ if (scratch.data != NULL)
+ free(scratch.data);
+ if (out_data != NULL)
+ free(out_data);
+ if (encoded_dhkey_info != NULL)
+ krb5_free_data(context, encoded_dhkey_info);
+ if (encoded_key_pack != NULL)
+ krb5_free_data(context, encoded_key_pack);
+ if (dh_pubkey != NULL)
+ free(dh_pubkey);
+ if (server_key != NULL)
+ free(server_key);
+ if (cksum_types != NULL)
+ free(cksum_types);
+
+ switch ((int)padata->pa_type) {
+ case KRB5_PADATA_PK_AS_REQ:
+ free_krb5_pa_pk_as_req(&reqp);
+ free_krb5_pa_pk_as_rep(&rep);
+ free_krb5_reply_key_pack(&key_pack);
+ break;
+ case KRB5_PADATA_PK_AS_REP_OLD:
+ case KRB5_PADATA_PK_AS_REQ_OLD:
+ free_krb5_pa_pk_as_req_draft9(&reqp9);
+ free_krb5_pa_pk_as_rep_draft9(&rep9);
+ if (!fixed_keypack)
+ free_krb5_reply_key_pack_draft9(&key_pack9);
+ else
+ free_krb5_reply_key_pack(&key_pack);
+ break;
+ }
+
+ if (retval)
+ pkiDebug("pkinit_verify_padata failure");
+
+ return retval;
+}
+
+/* ARGSUSED */
+static int
+pkinit_server_get_flags(krb5_context kcontext, krb5_preauthtype patype)
+{
+ return PA_SUFFICIENT | PA_REPLACES_KEY;
+}
+
+static krb5_preauthtype supported_server_pa_types[] = {
+ KRB5_PADATA_PK_AS_REQ,
+ KRB5_PADATA_PK_AS_REQ_OLD,
+ KRB5_PADATA_PK_AS_REP_OLD,
+ 0
+};
+
+/* ARGSUSED */
+static void
+pkinit_fini_kdc_profile(krb5_context context, pkinit_kdc_context plgctx)
+{
+ /*
+ * There is nothing currently allocated by pkinit_init_kdc_profile()
+ * which needs to be freed here.
+ */
+}
+
+static krb5_error_code
+pkinit_init_kdc_profile(krb5_context context, pkinit_kdc_context plgctx)
+{
+ krb5_error_code retval;
+ char *eku_string = NULL;
+
+ pkiDebug("%s: entered for realm %s\n", __FUNCTION__, plgctx->realmname);
+ retval = pkinit_kdcdefault_string(context, plgctx->realmname,
+ "pkinit_identity",
+ &plgctx->idopts->identity);
+ if (retval != 0 || NULL == plgctx->idopts->identity) {
+ retval = EINVAL;
+ krb5_set_error_message(context, retval,
+ "No pkinit_identity supplied for realm %s",
+ plgctx->realmname);
+ goto errout;
+ }
+
+ retval = pkinit_kdcdefault_strings(context, plgctx->realmname,
+ "pkinit_anchors",
+ &plgctx->idopts->anchors);
+ if (retval != 0 || NULL == plgctx->idopts->anchors) {
+ retval = EINVAL;
+ krb5_set_error_message(context, retval,
+ "No pkinit_anchors supplied for realm %s",
+ plgctx->realmname);
+ goto errout;
+ }
+
+ /* Solaris Kerberos */
+ (void) pkinit_kdcdefault_strings(context, plgctx->realmname,
+ "pkinit_pool",
+ &plgctx->idopts->intermediates);
+
+ (void) pkinit_kdcdefault_strings(context, plgctx->realmname,
+ "pkinit_revoke",
+ &plgctx->idopts->crls);
+
+ (void) pkinit_kdcdefault_string(context, plgctx->realmname,
+ "pkinit_kdc_ocsp",
+ &plgctx->idopts->ocsp);
+
+ (void) pkinit_kdcdefault_string(context, plgctx->realmname,
+ "pkinit_mappings_file",
+ &plgctx->idopts->dn_mapping_file);
+
+ (void) pkinit_kdcdefault_integer(context, plgctx->realmname,
+ "pkinit_dh_min_bits",
+ PKINIT_DEFAULT_DH_MIN_BITS,
+ &plgctx->opts->dh_min_bits);
+ if (plgctx->opts->dh_min_bits < 1024) {
+ pkiDebug("%s: invalid value (%d) for pkinit_dh_min_bits, "
+ "using default value (%d) instead\n", __FUNCTION__,
+ plgctx->opts->dh_min_bits, PKINIT_DEFAULT_DH_MIN_BITS);
+ plgctx->opts->dh_min_bits = PKINIT_DEFAULT_DH_MIN_BITS;
+ }
+
+ (void) pkinit_kdcdefault_boolean(context, plgctx->realmname,
+ "pkinit_allow_upn",
+ 0, &plgctx->opts->allow_upn);
+
+ (void) pkinit_kdcdefault_boolean(context, plgctx->realmname,
+ "pkinit_require_crl_checking",
+ 0, &plgctx->opts->require_crl_checking);
+
+ (void) pkinit_kdcdefault_string(context, plgctx->realmname,
+ "pkinit_eku_checking",
+ &eku_string);
+ if (eku_string != NULL) {
+ if (strcasecmp(eku_string, "kpClientAuth") == 0) {
+ plgctx->opts->require_eku = 1;
+ plgctx->opts->accept_secondary_eku = 0;
+ } else if (strcasecmp(eku_string, "scLogin") == 0) {
+ plgctx->opts->require_eku = 1;
+ plgctx->opts->accept_secondary_eku = 1;
+ } else if (strcasecmp(eku_string, "none") == 0) {
+ plgctx->opts->require_eku = 0;
+ plgctx->opts->accept_secondary_eku = 0;
+ } else {
+ pkiDebug("%s: Invalid value for pkinit_eku_checking: '%s'\n",
+ __FUNCTION__, eku_string);
+ }
+ free(eku_string);
+ }
+
+
+ return 0;
+errout:
+ pkinit_fini_kdc_profile(context, plgctx);
+ return retval;
+}
+
+/* ARGSUSED */
+static pkinit_kdc_context
+pkinit_find_realm_context(krb5_context context, void *pa_plugin_context,
+ krb5_principal princ)
+{
+ int i;
+ pkinit_kdc_context *realm_contexts = pa_plugin_context;
+
+ if (pa_plugin_context == NULL)
+ return NULL;
+
+ for (i = 0; realm_contexts[i] != NULL; i++) {
+ pkinit_kdc_context p = realm_contexts[i];
+
+ if ((p->realmname_len == princ->realm.length) &&
+ (strncmp(p->realmname, princ->realm.data, p->realmname_len) == 0)) {
+ pkiDebug("%s: returning context at %p for realm '%s'\n",
+ __FUNCTION__, p, p->realmname);
+ return p;
+ }
+ }
+ pkiDebug("%s: unable to find realm context for realm '%.*s'\n",
+ __FUNCTION__, princ->realm.length, princ->realm.data);
+ return NULL;
+}
+
+static int
+pkinit_server_plugin_init_realm(krb5_context context, const char *realmname,
+ pkinit_kdc_context *pplgctx)
+{
+ krb5_error_code retval = ENOMEM;
+ pkinit_kdc_context plgctx = NULL;
+
+ *pplgctx = NULL;
+
+ plgctx = (pkinit_kdc_context) calloc(1, sizeof(*plgctx));
+ if (plgctx == NULL)
+ goto errout;
+
+ pkiDebug("%s: initializing context at %p for realm '%s'\n",
+ __FUNCTION__, plgctx, realmname);
+ (void) memset(plgctx, 0, sizeof(*plgctx));
+ plgctx->magic = PKINIT_CTX_MAGIC;
+
+ plgctx->realmname = strdup(realmname);
+ if (plgctx->realmname == NULL)
+ goto errout;
+ plgctx->realmname_len = strlen(plgctx->realmname);
+
+ retval = pkinit_init_plg_crypto(&plgctx->cryptoctx);
+ if (retval)
+ goto errout;
+
+ retval = pkinit_init_plg_opts(&plgctx->opts);
+ if (retval)
+ goto errout;
+
+ retval = pkinit_init_identity_crypto(&plgctx->idctx);
+ if (retval)
+ goto errout;
+
+ retval = pkinit_init_identity_opts(&plgctx->idopts);
+ if (retval)
+ goto errout;
+
+ retval = pkinit_init_kdc_profile(context, plgctx);
+ if (retval)
+ goto errout;
+
+ /*
+ * Solaris Kerberos:
+ * Some methods of storing key information (PKCS11, PKCS12,...) may
+ * require interactive prompting.
+ */
+ retval = pkinit_identity_set_prompter(plgctx->idctx, krb5_prompter_posix,
+ NULL);
+ if (retval)
+ goto errout;
+
+ retval = pkinit_identity_initialize(context, plgctx->cryptoctx, NULL,
+ plgctx->idopts, plgctx->idctx, 0, NULL);
+ if (retval)
+ goto errout;
+
+ pkiDebug("%s: returning context at %p for realm '%s'\n",
+ __FUNCTION__, plgctx, realmname);
+ *pplgctx = plgctx;
+ retval = 0;
+
+errout:
+ if (retval)
+ pkinit_server_plugin_fini_realm(context, plgctx);
+
+ return retval;
+}
+
+static int
+pkinit_server_plugin_init(krb5_context context, void **blob,
+ const char **realmnames)
+{
+ krb5_error_code retval = ENOMEM;
+ pkinit_kdc_context plgctx, *realm_contexts = NULL;
+ int i, j;
+ size_t numrealms;
+
+ retval = pkinit_accessor_init();
+ if (retval)
+ return retval;
+
+ /* Determine how many realms we may need to support */
+ for (i = 0; realmnames[i] != NULL; i++) {};
+ numrealms = i;
+
+ realm_contexts = (pkinit_kdc_context *)
+ calloc(numrealms+1, sizeof(pkinit_kdc_context));
+ if (realm_contexts == NULL)
+ return ENOMEM;
+
+ for (i = 0, j = 0; i < numrealms; i++) {
+ pkiDebug("%s: processing realm '%s'\n", __FUNCTION__, realmnames[i]);
+ retval = pkinit_server_plugin_init_realm(context, realmnames[i], &plgctx);
+ if (retval == 0 && plgctx != NULL)
+ realm_contexts[j++] = plgctx;
+ }
+
+ if (j == 0) {
+ /*
+ * Solaris Kerberos
+ * Improve error messages for the common case of a single realm
+ */
+ if (numrealms != 1) {
+ retval = EINVAL;
+ krb5_set_error_message(context, retval, "No realms configured "
+ "correctly for pkinit support");
+ }
+
+ goto errout;
+ }
+
+ *blob = realm_contexts;
+ retval = 0;
+ pkiDebug("%s: returning context at %p\n", __FUNCTION__, realm_contexts);
+
+errout:
+ if (retval)
+ pkinit_server_plugin_fini(context, realm_contexts);
+
+ return retval;
+}
+
+static void
+pkinit_server_plugin_fini_realm(krb5_context context, pkinit_kdc_context plgctx)
+{
+ if (plgctx == NULL)
+ return;
+
+ pkinit_fini_kdc_profile(context, plgctx);
+ pkinit_fini_identity_opts(plgctx->idopts);
+ pkinit_fini_identity_crypto(plgctx->idctx);
+ pkinit_fini_plg_crypto(plgctx->cryptoctx);
+ pkinit_fini_plg_opts(plgctx->opts);
+ free(plgctx->realmname);
+ free(plgctx);
+}
+
+static void
+pkinit_server_plugin_fini(krb5_context context, void *blob)
+{
+ pkinit_kdc_context *realm_contexts = blob;
+ int i;
+
+ if (realm_contexts == NULL)
+ return;
+
+ for (i = 0; realm_contexts[i] != NULL; i++) {
+ pkinit_server_plugin_fini_realm(context, realm_contexts[i]);
+ }
+ pkiDebug("%s: freeing context at %p\n", __FUNCTION__, realm_contexts);
+ free(realm_contexts);
+}
+
+static krb5_error_code
+pkinit_init_kdc_req_context(krb5_context context, void **ctx)
+{
+ krb5_error_code retval = ENOMEM;
+ pkinit_kdc_req_context reqctx = NULL;
+
+ reqctx = (pkinit_kdc_req_context)malloc(sizeof(*reqctx));
+ if (reqctx == NULL)
+ return retval;
+ (void) memset(reqctx, 0, sizeof(*reqctx));
+ reqctx->magic = PKINIT_CTX_MAGIC;
+
+ retval = pkinit_init_req_crypto(&reqctx->cryptoctx);
+ if (retval)
+ goto cleanup;
+ reqctx->rcv_auth_pack = NULL;
+ reqctx->rcv_auth_pack9 = NULL;
+
+ pkiDebug("%s: returning reqctx at %p\n", __FUNCTION__, reqctx);
+ *ctx = reqctx;
+ retval = 0;
+cleanup:
+ if (retval)
+ pkinit_fini_kdc_req_context(context, reqctx);
+
+ return retval;
+}
+
+static void
+pkinit_fini_kdc_req_context(krb5_context context, void *ctx)
+{
+ pkinit_kdc_req_context reqctx = (pkinit_kdc_req_context)ctx;
+
+ if (reqctx == NULL || reqctx->magic != PKINIT_CTX_MAGIC) {
+ pkiDebug("pkinit_fini_kdc_req_context: got bad reqctx (%p)!\n", reqctx);
+ return;
+ }
+ pkiDebug("%s: freeing reqctx at %p\n", __FUNCTION__, reqctx);
+
+ pkinit_fini_req_crypto(reqctx->cryptoctx);
+ if (reqctx->rcv_auth_pack != NULL)
+ free_krb5_auth_pack(&reqctx->rcv_auth_pack);
+ if (reqctx->rcv_auth_pack9 != NULL)
+ free_krb5_auth_pack_draft9(context, &reqctx->rcv_auth_pack9);
+
+ free(reqctx);
+}
+
+struct krb5plugin_preauth_server_ftable_v1 preauthentication_server_1 = {
+ "pkinit", /* name */
+ supported_server_pa_types, /* pa_type_list */
+ pkinit_server_plugin_init, /* (*init_proc) */
+ pkinit_server_plugin_fini, /* (*fini_proc) */
+ pkinit_server_get_flags, /* (*flags_proc) */
+ pkinit_server_get_edata, /* (*edata_proc) */
+ pkinit_server_verify_padata,/* (*verify_proc) */
+ pkinit_server_return_padata,/* (*return_proc) */
+ NULL, /* (*freepa_reqcontext_proc) */
+};
diff --git a/usr/src/lib/krb5/plugins/preauth/pkinit/sparc/Makefile b/usr/src/lib/krb5/plugins/preauth/pkinit/sparc/Makefile
new file mode 100644
index 0000000000..a0889a1a81
--- /dev/null
+++ b/usr/src/lib/krb5/plugins/preauth/pkinit/sparc/Makefile
@@ -0,0 +1,29 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBDIR) $(PLUGINDIR) $(PREAUTHDIR) $(ROOTLIBS) $(ROOTLINKS)