summaryrefslogtreecommitdiff
path: root/source4/heimdal
diff options
context:
space:
mode:
Diffstat (limited to 'source4/heimdal')
-rw-r--r--source4/heimdal/README1
-rw-r--r--source4/heimdal/cf/make-proto.pl17
-rw-r--r--source4/heimdal/cf/resolv.m411
-rw-r--r--source4/heimdal/include/heim_threads.h (renamed from source4/heimdal/lib/krb5/heim_threads.h)0
-rw-r--r--source4/heimdal/kdc/524.c400
-rw-r--r--source4/heimdal/kdc/default_config.c24
-rw-r--r--source4/heimdal/kdc/digest.c17
-rw-r--r--source4/heimdal/kdc/headers.h6
-rw-r--r--source4/heimdal/kdc/kaserver.c4
-rw-r--r--source4/heimdal/kdc/kdc.h16
-rw-r--r--source4/heimdal/kdc/kdc_locl.h5
-rw-r--r--source4/heimdal/kdc/kerberos4.c794
-rw-r--r--source4/heimdal/kdc/kerberos5.c378
-rw-r--r--source4/heimdal/kdc/krb5tgs.c62
-rw-r--r--source4/heimdal/kdc/kx509.c25
-rw-r--r--source4/heimdal/kdc/pkinit.c809
-rw-r--r--source4/heimdal/kdc/process.c293
-rw-r--r--source4/heimdal/kpasswd/kpasswd.c4
-rw-r--r--source4/heimdal/kuser/kinit.c106
-rw-r--r--source4/heimdal/kuser/kuser_locl.h4
-rw-r--r--source4/heimdal/lib/asn1/asn1_err.et2
-rw-r--r--source4/heimdal/lib/asn1/asn1_gen.c12
-rw-r--r--source4/heimdal/lib/asn1/canthandle.asn12
-rw-r--r--source4/heimdal/lib/asn1/cms.asn1 (renamed from source4/heimdal/lib/asn1/CMS.asn1)12
-rw-r--r--source4/heimdal/lib/asn1/cms.opt1
-rw-r--r--source4/heimdal/lib/asn1/der.h2
-rw-r--r--source4/heimdal/lib/asn1/der_get.c112
-rw-r--r--source4/heimdal/lib/asn1/der_locl.h4
-rw-r--r--source4/heimdal/lib/asn1/der_put.c2
-rw-r--r--source4/heimdal/lib/asn1/digest.asn12
-rw-r--r--source4/heimdal/lib/asn1/extra.c14
-rw-r--r--source4/heimdal/lib/asn1/gen.c44
-rw-r--r--source4/heimdal/lib/asn1/gen_copy.c2
-rw-r--r--source4/heimdal/lib/asn1/gen_decode.c87
-rw-r--r--source4/heimdal/lib/asn1/gen_encode.c4
-rw-r--r--source4/heimdal/lib/asn1/gen_free.c2
-rw-r--r--source4/heimdal/lib/asn1/gen_length.c2
-rw-r--r--source4/heimdal/lib/asn1/gen_locl.h10
-rw-r--r--source4/heimdal/lib/asn1/krb5.asn1 (renamed from source4/heimdal/lib/asn1/k5.asn1)101
-rw-r--r--source4/heimdal/lib/asn1/krb5.opt6
-rw-r--r--source4/heimdal/lib/asn1/kx509.asn111
-rw-r--r--source4/heimdal/lib/asn1/lex.l6
-rw-r--r--source4/heimdal/lib/asn1/main.c72
-rw-r--r--source4/heimdal/lib/asn1/parse.y1015
-rw-r--r--source4/heimdal/lib/asn1/pkcs12.asn12
-rw-r--r--source4/heimdal/lib/asn1/pkcs8.asn12
-rw-r--r--source4/heimdal/lib/asn1/pkinit.asn133
-rw-r--r--source4/heimdal/lib/asn1/rfc2459.asn174
-rw-r--r--source4/heimdal/lib/asn1/test.asn114
-rw-r--r--source4/heimdal/lib/com_err/com_err.c5
-rw-r--r--source4/heimdal/lib/com_err/compile_et.c2
-rw-r--r--source4/heimdal/lib/com_err/compile_et.h2
-rw-r--r--source4/heimdal/lib/com_err/error.c5
-rw-r--r--source4/heimdal/lib/com_err/lex.l2
-rw-r--r--source4/heimdal/lib/com_err/parse.y2
-rw-r--r--source4/heimdal/lib/gssapi/gssapi/gssapi.h117
-rw-r--r--source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h2
-rw-r--r--source4/heimdal/lib/gssapi/gssapi_mech.h44
-rw-r--r--source4/heimdal/lib/gssapi/krb5/8003.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/accept_sec_context.c25
-rw-r--r--source4/heimdal/lib/gssapi/krb5/acquire_cred.c5
-rw-r--r--source4/heimdal/lib/gssapi/krb5/add_cred.c6
-rw-r--r--source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/aeap.c271
-rw-r--r--source4/heimdal/lib/gssapi/krb5/arcfour.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/canonicalize_name.c2
-rwxr-xr-xsource4/heimdal/lib/gssapi/krb5/cfx.c228
-rw-r--r--source4/heimdal/lib/gssapi/krb5/compare_name.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/compat.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/context_time.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/copy_ccache.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/decapsulate.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/delete_sec_context.c4
-rw-r--r--source4/heimdal/lib/gssapi/krb5/display_name.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/display_status.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/duplicate_name.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/encapsulate.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/export_name.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/export_sec_context.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/external.c7
-rw-r--r--source4/heimdal/lib/gssapi/krb5/get_mic.c9
-rw-r--r--source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h11
-rw-r--r--source4/heimdal/lib/gssapi/krb5/import_name.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/import_sec_context.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/indicate_mechs.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/init.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/init_sec_context.c23
-rw-r--r--source4/heimdal/lib/gssapi/krb5/inquire_context.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/inquire_cred.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c7
-rw-r--r--source4/heimdal/lib/gssapi/krb5/prf.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/process_context_token.c5
-rw-r--r--source4/heimdal/lib/gssapi/krb5/release_buffer.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/release_cred.c4
-rw-r--r--source4/heimdal/lib/gssapi/krb5/release_name.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/sequence.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/set_cred_option.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c2
-rw-r--r--source4/heimdal/lib/gssapi/krb5/unwrap.c15
-rw-r--r--source4/heimdal/lib/gssapi/krb5/verify_mic.c27
-rw-r--r--source4/heimdal/lib/gssapi/krb5/wrap.c23
-rw-r--r--source4/heimdal/lib/gssapi/mech/context.c2
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c3
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c2
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_aeap.c184
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c24
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_get_mic.c4
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_import_name.c85
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_krb5.c4
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_mech_switch.c14
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_pseudo_random.c4
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_verify_mic.c4
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_wrap.c4
-rw-r--r--source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c4
-rw-r--r--source4/heimdal/lib/gssapi/mech/mech_locl.h1
-rw-r--r--source4/heimdal/lib/gssapi/mech/mech_switch.h1
-rw-r--r--source4/heimdal/lib/gssapi/spnego/accept_sec_context.c6
-rw-r--r--source4/heimdal/lib/gssapi/spnego/compat.c2
-rw-r--r--source4/heimdal/lib/gssapi/spnego/context_stubs.c127
-rw-r--r--source4/heimdal/lib/gssapi/spnego/cred_stubs.c2
-rw-r--r--source4/heimdal/lib/gssapi/spnego/external.c4
-rw-r--r--source4/heimdal/lib/gssapi/spnego/init_sec_context.c73
-rw-r--r--source4/heimdal/lib/gssapi/spnego/spnego_locl.h9
-rw-r--r--source4/heimdal/lib/hcrypto/bn.c88
-rw-r--r--source4/heimdal/lib/hcrypto/bn.h19
-rw-r--r--source4/heimdal/lib/hcrypto/evp-aes-cts.c4
-rw-r--r--source4/heimdal/lib/hcrypto/evp.c16
-rw-r--r--source4/heimdal/lib/hcrypto/rand-unix.c40
-rw-r--r--source4/heimdal/lib/hcrypto/rand.c4
-rw-r--r--source4/heimdal/lib/hdb/dbinfo.c6
-rw-r--r--source4/heimdal/lib/hdb/ext.c14
-rw-r--r--source4/heimdal/lib/hdb/hdb.asn112
-rw-r--r--source4/heimdal/lib/hdb/hdb.c55
-rw-r--r--source4/heimdal/lib/hdb/hdb.h157
-rw-r--r--source4/heimdal/lib/hdb/keys.c13
-rw-r--r--source4/heimdal/lib/hdb/keytab.c7
-rw-r--r--source4/heimdal/lib/hdb/mkey.c29
-rw-r--r--source4/heimdal/lib/hdb/ndbm.c4
-rw-r--r--source4/heimdal/lib/hx509/ca.c32
-rw-r--r--source4/heimdal/lib/hx509/cert.c169
-rw-r--r--source4/heimdal/lib/hx509/cms.c478
-rw-r--r--source4/heimdal/lib/hx509/collector.c5
-rw-r--r--source4/heimdal/lib/hx509/crypto.c995
-rw-r--r--source4/heimdal/lib/hx509/env.c1
-rw-r--r--source4/heimdal/lib/hx509/error.c1
-rw-r--r--source4/heimdal/lib/hx509/file.c1
-rw-r--r--source4/heimdal/lib/hx509/hx509.h19
-rw-r--r--source4/heimdal/lib/hx509/hx509_err.et5
-rw-r--r--source4/heimdal/lib/hx509/hx_locl.h4
-rw-r--r--source4/heimdal/lib/hx509/keyset.c76
-rw-r--r--source4/heimdal/lib/hx509/ks_dir.c3
-rw-r--r--source4/heimdal/lib/hx509/ks_file.c100
-rw-r--r--source4/heimdal/lib/hx509/ks_keychain.c63
-rw-r--r--source4/heimdal/lib/hx509/ks_mem.c1
-rw-r--r--source4/heimdal/lib/hx509/ks_null.c1
-rw-r--r--source4/heimdal/lib/hx509/ks_p11.c11
-rw-r--r--source4/heimdal/lib/hx509/ks_p12.c45
-rw-r--r--source4/heimdal/lib/hx509/lock.c1
-rw-r--r--source4/heimdal/lib/hx509/name.c63
-rw-r--r--source4/heimdal/lib/hx509/peer.c34
-rw-r--r--source4/heimdal/lib/hx509/print.c37
-rw-r--r--source4/heimdal/lib/hx509/req.c1
-rw-r--r--source4/heimdal/lib/hx509/revoke.c8
-rw-r--r--source4/heimdal/lib/hx509/sel-gram.y1
-rw-r--r--source4/heimdal/lib/hx509/test_name.c1
-rw-r--r--source4/heimdal/lib/krb5/acache.c25
-rw-r--r--source4/heimdal/lib/krb5/add_et_list.c2
-rw-r--r--source4/heimdal/lib/krb5/addr_families.c12
-rw-r--r--source4/heimdal/lib/krb5/appdefault.c2
-rw-r--r--source4/heimdal/lib/krb5/asn1_glue.c18
-rw-r--r--source4/heimdal/lib/krb5/auth_context.c2
-rw-r--r--source4/heimdal/lib/krb5/build_ap_req.c2
-rw-r--r--source4/heimdal/lib/krb5/build_auth.c4
-rw-r--r--source4/heimdal/lib/krb5/cache.c328
-rw-r--r--source4/heimdal/lib/krb5/changepw.c28
-rw-r--r--source4/heimdal/lib/krb5/codec.c39
-rw-r--r--source4/heimdal/lib/krb5/config_file.c53
-rw-r--r--source4/heimdal/lib/krb5/config_file_netinfo.c180
-rw-r--r--source4/heimdal/lib/krb5/constants.c9
-rw-r--r--source4/heimdal/lib/krb5/context.c135
-rw-r--r--source4/heimdal/lib/krb5/convert_creds.c6
-rw-r--r--source4/heimdal/lib/krb5/copy_host_realm.c2
-rw-r--r--source4/heimdal/lib/krb5/crc.c2
-rw-r--r--source4/heimdal/lib/krb5/creds.c21
-rw-r--r--source4/heimdal/lib/krb5/crypto.c492
-rw-r--r--source4/heimdal/lib/krb5/data.c21
-rw-r--r--source4/heimdal/lib/krb5/eai_to_heim_errno.c2
-rw-r--r--source4/heimdal/lib/krb5/error_string.c84
-rw-r--r--source4/heimdal/lib/krb5/expand_hostname.c37
-rw-r--r--source4/heimdal/lib/krb5/fcache.c52
-rw-r--r--source4/heimdal/lib/krb5/free.c2
-rw-r--r--source4/heimdal/lib/krb5/free_host_realm.c11
-rw-r--r--source4/heimdal/lib/krb5/generate_seq_number.c2
-rw-r--r--source4/heimdal/lib/krb5/generate_subkey.c2
-rw-r--r--source4/heimdal/lib/krb5/get_addrs.c11
-rw-r--r--source4/heimdal/lib/krb5/get_cred.c25
-rw-r--r--source4/heimdal/lib/krb5/get_default_principal.c2
-rw-r--r--source4/heimdal/lib/krb5/get_default_realm.c2
-rw-r--r--source4/heimdal/lib/krb5/get_for_creds.c2
-rw-r--r--source4/heimdal/lib/krb5/get_host_realm.c16
-rw-r--r--source4/heimdal/lib/krb5/get_in_tkt.c539
-rw-r--r--source4/heimdal/lib/krb5/get_port.c2
-rw-r--r--source4/heimdal/lib/krb5/heim_err.et2
-rw-r--r--source4/heimdal/lib/krb5/init_creds.c166
-rw-r--r--source4/heimdal/lib/krb5/init_creds_pw.c1184
-rw-r--r--source4/heimdal/lib/krb5/kcm.c121
-rw-r--r--source4/heimdal/lib/krb5/keyblock.c79
-rw-r--r--source4/heimdal/lib/krb5/keytab.c439
-rw-r--r--source4/heimdal/lib/krb5/keytab_any.c3
-rw-r--r--source4/heimdal/lib/krb5/keytab_file.c40
-rw-r--r--source4/heimdal/lib/krb5/keytab_keyfile.c5
-rw-r--r--source4/heimdal/lib/krb5/keytab_memory.c3
-rw-r--r--source4/heimdal/lib/krb5/krb5.h75
-rw-r--r--source4/heimdal/lib/krb5/krb5_ccapi.h11
-rw-r--r--source4/heimdal/lib/krb5/krb5_err.et8
-rw-r--r--source4/heimdal/lib/krb5/krb5_locl.h9
-rw-r--r--source4/heimdal/lib/krb5/krbhst.c22
-rw-r--r--source4/heimdal/lib/krb5/locate_plugin.h4
-rw-r--r--source4/heimdal/lib/krb5/log.c2
-rw-r--r--source4/heimdal/lib/krb5/mcache.c2
-rw-r--r--source4/heimdal/lib/krb5/misc.c2
-rw-r--r--source4/heimdal/lib/krb5/mit_glue.c20
-rw-r--r--source4/heimdal/lib/krb5/mk_error.c2
-rw-r--r--source4/heimdal/lib/krb5/mk_priv.c3
-rw-r--r--source4/heimdal/lib/krb5/mk_rep.c2
-rw-r--r--source4/heimdal/lib/krb5/mk_req.c2
-rw-r--r--source4/heimdal/lib/krb5/mk_req_ext.c2
-rw-r--r--source4/heimdal/lib/krb5/n-fold.c20
-rw-r--r--source4/heimdal/lib/krb5/pac.c3
-rw-r--r--source4/heimdal/lib/krb5/padata.c2
-rw-r--r--source4/heimdal/lib/krb5/pkinit.c814
-rw-r--r--source4/heimdal/lib/krb5/plugin.c44
-rw-r--r--source4/heimdal/lib/krb5/principal.c123
-rw-r--r--source4/heimdal/lib/krb5/prog_setup.c2
-rw-r--r--source4/heimdal/lib/krb5/prompter_posix.c2
-rw-r--r--source4/heimdal/lib/krb5/rd_cred.c17
-rw-r--r--source4/heimdal/lib/krb5/rd_error.c2
-rw-r--r--source4/heimdal/lib/krb5/rd_priv.c2
-rw-r--r--source4/heimdal/lib/krb5/rd_rep.c13
-rw-r--r--source4/heimdal/lib/krb5/rd_req.c301
-rw-r--r--source4/heimdal/lib/krb5/replay.c2
-rw-r--r--source4/heimdal/lib/krb5/send_to_kdc.c6
-rw-r--r--source4/heimdal/lib/krb5/set_default_realm.c2
-rw-r--r--source4/heimdal/lib/krb5/store-int.h1
-rw-r--r--source4/heimdal/lib/krb5/store.c281
-rw-r--r--source4/heimdal/lib/krb5/store_emem.c48
-rw-r--r--source4/heimdal/lib/krb5/store_fd.c24
-rw-r--r--source4/heimdal/lib/krb5/store_mem.c61
-rw-r--r--source4/heimdal/lib/krb5/ticket.c484
-rw-r--r--source4/heimdal/lib/krb5/time.c2
-rw-r--r--source4/heimdal/lib/krb5/transited.c2
-rw-r--r--source4/heimdal/lib/krb5/v4_glue.c7
-rw-r--r--source4/heimdal/lib/krb5/version.c2
-rw-r--r--source4/heimdal/lib/krb5/warn.c137
-rw-r--r--source4/heimdal/lib/ntlm/ntlm.c26
-rw-r--r--source4/heimdal/lib/roken/base64.c8
-rw-r--r--source4/heimdal/lib/roken/bswap.c4
-rw-r--r--source4/heimdal/lib/roken/cloexec.c3
-rw-r--r--source4/heimdal/lib/roken/closefrom.c3
-rw-r--r--source4/heimdal/lib/roken/copyhostent.c3
-rw-r--r--source4/heimdal/lib/roken/dumpdata.c3
-rw-r--r--source4/heimdal/lib/roken/ecalloc.c3
-rw-r--r--source4/heimdal/lib/roken/emalloc.c3
-rw-r--r--source4/heimdal/lib/roken/erealloc.c3
-rw-r--r--source4/heimdal/lib/roken/estrdup.c3
-rw-r--r--source4/heimdal/lib/roken/freeaddrinfo.c3
-rw-r--r--source4/heimdal/lib/roken/freehostent.c3
-rw-r--r--source4/heimdal/lib/roken/gai_strerror.c3
-rw-r--r--source4/heimdal/lib/roken/get_window_size.c3
-rw-r--r--source4/heimdal/lib/roken/getaddrinfo.c3
-rw-r--r--source4/heimdal/lib/roken/getarg.c3
-rw-r--r--source4/heimdal/lib/roken/getdtablesize.c (renamed from source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c)114
-rw-r--r--source4/heimdal/lib/roken/getipnodebyaddr.c3
-rw-r--r--source4/heimdal/lib/roken/getipnodebyname.c3
-rw-r--r--source4/heimdal/lib/roken/getnameinfo.c3
-rw-r--r--source4/heimdal/lib/roken/getprogname.c3
-rw-r--r--source4/heimdal/lib/roken/h_errno.c3
-rw-r--r--source4/heimdal/lib/roken/hex.c12
-rw-r--r--source4/heimdal/lib/roken/hostent_find_fqdn.c3
-rw-r--r--source4/heimdal/lib/roken/inet_aton.c3
-rw-r--r--source4/heimdal/lib/roken/inet_ntop.c3
-rw-r--r--source4/heimdal/lib/roken/inet_pton.c3
-rw-r--r--source4/heimdal/lib/roken/issuid.c3
-rw-r--r--source4/heimdal/lib/roken/net_read.c3
-rw-r--r--source4/heimdal/lib/roken/net_write.c3
-rw-r--r--source4/heimdal/lib/roken/parse_time.c3
-rw-r--r--source4/heimdal/lib/roken/parse_units.c3
-rw-r--r--source4/heimdal/lib/roken/resolve.c139
-rw-r--r--source4/heimdal/lib/roken/resolve.h135
-rw-r--r--source4/heimdal/lib/roken/rkpty.c38
-rw-r--r--source4/heimdal/lib/roken/roken-common.h45
-rw-r--r--source4/heimdal/lib/roken/roken.h.in148
-rw-r--r--source4/heimdal/lib/roken/roken_gethostby.c3
-rw-r--r--source4/heimdal/lib/roken/rtbl.c4
-rw-r--r--source4/heimdal/lib/roken/setprogname.c3
-rw-r--r--source4/heimdal/lib/roken/signal.c3
-rw-r--r--source4/heimdal/lib/roken/simple_exec.c24
-rw-r--r--source4/heimdal/lib/roken/socket.c13
-rw-r--r--source4/heimdal/lib/roken/strcollect.c3
-rw-r--r--source4/heimdal/lib/roken/strlwr.c3
-rw-r--r--source4/heimdal/lib/roken/strpool.c3
-rw-r--r--source4/heimdal/lib/roken/strsep.c3
-rw-r--r--source4/heimdal/lib/roken/strsep_copy.c3
-rw-r--r--source4/heimdal/lib/roken/strupr.c3
-rw-r--r--source4/heimdal/lib/roken/vis.c3
-rw-r--r--source4/heimdal/lib/roken/xfree.c3
-rw-r--r--source4/heimdal/lib/vers/print_version.c11
-rw-r--r--source4/heimdal/lib/wind/normalize.c4
-rw-r--r--source4/heimdal/lib/wind/stringprep.c2
-rw-r--r--source4/heimdal/lib/wind/utf8.c2
-rw-r--r--source4/heimdal/lib/wind/wind_err.et4
315 files changed, 9362 insertions, 7002 deletions
diff --git a/source4/heimdal/README b/source4/heimdal/README
index 3b938248fc..f130698597 100644
--- a/source4/heimdal/README
+++ b/source4/heimdal/README
@@ -1,4 +1,3 @@
-$Id$
Heimdal is a Kerberos 5 implementation.
diff --git a/source4/heimdal/cf/make-proto.pl b/source4/heimdal/cf/make-proto.pl
index b89ef79067..04733e1281 100644
--- a/source4/heimdal/cf/make-proto.pl
+++ b/source4/heimdal/cf/make-proto.pl
@@ -100,13 +100,16 @@ while(<>) {
s/^\s*//;
s/\s*$//;
s/\s+/ /g;
- if($_ =~ /\)$/){
+ if($_ =~ /\)$/ or $_ =~ /DEPRECATED$/){
if(!/^static/ && !/^PRIVATE/){
- if(/(.*)(__attribute__\s?\(.*\))/) {
- $attr = $2;
+ $attr = "";
+ if(m/(.*)(__attribute__\s?\(.*\))/) {
+ $attr .= " $2";
+ $_ = $1;
+ }
+ if(m/(.*)\s(\w+DEPRECATED)/) {
+ $attr .= " $2";
$_ = $1;
- } else {
- $attr = "";
}
# remove outer ()
s/\s*\(/</;
@@ -308,7 +311,7 @@ extern \"C\" {
if ($opt_E) {
$public_h_header .= "#ifndef $opt_E
#if defined(_WIN32)
-#define ${opt_E}_FUNCTION _stdcall __declspec(dllimport)
+#define ${opt_E}_FUNCTION __stdcall __declspec(dllimport)
#define ${opt_E}_VARIABLE __declspec(dllimport)
#else
#define ${opt_E}_FUNCTION
@@ -320,7 +323,7 @@ if ($opt_E) {
$private_h_header .= "#ifndef $opt_E
#if defined(_WIN32)
-#define ${opt_E}_FUNCTION _stdcall __declspec(dllimport)
+#define ${opt_E}_FUNCTION __stdcall __declspec(dllimport)
#define ${opt_E}_VARIABLE __declspec(dllimport)
#else
#define ${opt_E}_FUNCTION
diff --git a/source4/heimdal/cf/resolv.m4 b/source4/heimdal/cf/resolv.m4
index b4045094d8..49c868ab0e 100644
--- a/source4/heimdal/cf/resolv.m4
+++ b/source4/heimdal/cf/resolv.m4
@@ -5,7 +5,7 @@ dnl
AC_DEFUN([rk_RESOLV],[
-AC_CHECK_HEADERS([arpa/nameser.h])
+AC_CHECK_HEADERS([arpa/nameser.h dns.h])
AC_CHECK_HEADERS(resolv.h, , , [AC_INCLUDES_DEFAULT
#ifdef HAVE_SYS_TYPES_H
@@ -73,6 +73,15 @@ AC_FIND_FUNC(res_ndestroy, resolv,
],
[0])
+AC_FIND_FUNC_NO_LIBS(dns_search,,
+[
+#ifdef HAVE_DNS_H
+#include <dns.h>
+#endif
+],
+[0,0,0,0,0,0,0,0])
+
+
AC_FIND_FUNC(dn_expand, resolv,
[
#include <stdio.h>
diff --git a/source4/heimdal/lib/krb5/heim_threads.h b/source4/heimdal/include/heim_threads.h
index c4f841fb61..c4f841fb61 100644
--- a/source4/heimdal/lib/krb5/heim_threads.h
+++ b/source4/heimdal/include/heim_threads.h
diff --git a/source4/heimdal/kdc/524.c b/source4/heimdal/kdc/524.c
deleted file mode 100644
index d15310384a..0000000000
--- a/source4/heimdal/kdc/524.c
+++ /dev/null
@@ -1,400 +0,0 @@
-/*
- * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "kdc_locl.h"
-
-RCSID("$Id$");
-
-#include <krb5-v4compat.h>
-
-/*
- * fetch the server from `t', returning the name in malloced memory in
- * `spn' and the entry itself in `server'
- */
-
-static krb5_error_code
-fetch_server (krb5_context context,
- krb5_kdc_configuration *config,
- const Ticket *t,
- char **spn,
- hdb_entry_ex **server,
- const char *from)
-{
- krb5_error_code ret;
- krb5_principal sprinc;
-
- ret = _krb5_principalname2krb5_principal(context, &sprinc,
- t->sname, t->realm);
- if (ret) {
- kdc_log(context, config, 0, "_krb5_principalname2krb5_principal: %s",
- krb5_get_err_text(context, ret));
- return ret;
- }
- ret = krb5_unparse_name(context, sprinc, spn);
- if (ret) {
- krb5_free_principal(context, sprinc);
- kdc_log(context, config, 0, "krb5_unparse_name: %s",
- krb5_get_err_text(context, ret));
- return ret;
- }
- ret = _kdc_db_fetch(context, config, sprinc, HDB_F_GET_SERVER,
- NULL, server);
- krb5_free_principal(context, sprinc);
- if (ret) {
- kdc_log(context, config, 0,
- "Request to convert ticket from %s for unknown principal %s: %s",
- from, *spn, krb5_get_err_text(context, ret));
- if (ret == HDB_ERR_NOENTRY)
- ret = KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN;
- return ret;
- }
- return 0;
-}
-
-static krb5_error_code
-log_524 (krb5_context context,
- krb5_kdc_configuration *config,
- const EncTicketPart *et,
- const char *from,
- const char *spn)
-{
- krb5_principal client;
- char *cpn;
- krb5_error_code ret;
-
- ret = _krb5_principalname2krb5_principal(context, &client,
- et->cname, et->crealm);
- if (ret) {
- kdc_log(context, config, 0, "_krb5_principalname2krb5_principal: %s",
- krb5_get_err_text (context, ret));
- return ret;
- }
- ret = krb5_unparse_name(context, client, &cpn);
- if (ret) {
- krb5_free_principal(context, client);
- kdc_log(context, config, 0, "krb5_unparse_name: %s",
- krb5_get_err_text (context, ret));
- return ret;
- }
- kdc_log(context, config, 1, "524-REQ %s from %s for %s", cpn, from, spn);
- free(cpn);
- krb5_free_principal(context, client);
- return 0;
-}
-
-static krb5_error_code
-verify_flags (krb5_context context,
- krb5_kdc_configuration *config,
- const EncTicketPart *et,
- const char *spn)
-{
- if(et->endtime < kdc_time){
- kdc_log(context, config, 0, "Ticket expired (%s)", spn);
- return KRB5KRB_AP_ERR_TKT_EXPIRED;
- }
- if(et->flags.invalid){
- kdc_log(context, config, 0, "Ticket not valid (%s)", spn);
- return KRB5KRB_AP_ERR_TKT_NYV;
- }
- return 0;
-}
-
-/*
- * set the `et->caddr' to the most appropriate address to use, where
- * `addr' is the address the request was received from.
- */
-
-static krb5_error_code
-set_address (krb5_context context,
- krb5_kdc_configuration *config,
- EncTicketPart *et,
- struct sockaddr *addr,
- const char *from)
-{
- krb5_error_code ret;
- krb5_address *v4_addr;
-
- v4_addr = malloc (sizeof(*v4_addr));
- if (v4_addr == NULL)
- return ENOMEM;
-
- ret = krb5_sockaddr2address(context, addr, v4_addr);
- if(ret) {
- free (v4_addr);
- kdc_log(context, config, 0, "Failed to convert address (%s)", from);
- return ret;
- }
-
- if (et->caddr && !krb5_address_search (context, v4_addr, et->caddr)) {
- kdc_log(context, config, 0, "Incorrect network address (%s)", from);
- krb5_free_address(context, v4_addr);
- free (v4_addr);
- return KRB5KRB_AP_ERR_BADADDR;
- }
- if(v4_addr->addr_type == KRB5_ADDRESS_INET) {
- /* we need to collapse the addresses in the ticket to a
- single address; best guess is to use the address the
- connection came from */
-
- if (et->caddr != NULL) {
- free_HostAddresses(et->caddr);
- } else {
- et->caddr = malloc (sizeof (*et->caddr));
- if (et->caddr == NULL) {
- krb5_free_address(context, v4_addr);
- free(v4_addr);
- return ENOMEM;
- }
- }
- et->caddr->val = v4_addr;
- et->caddr->len = 1;
- } else {
- krb5_free_address(context, v4_addr);
- free(v4_addr);
- }
- return 0;
-}
-
-
-static krb5_error_code
-encrypt_v4_ticket(krb5_context context,
- krb5_kdc_configuration *config,
- void *buf,
- size_t len,
- krb5_keyblock *skey,
- EncryptedData *reply)
-{
- krb5_crypto crypto;
- krb5_error_code ret;
- ret = krb5_crypto_init(context, skey, ETYPE_DES_PCBC_NONE, &crypto);
- if (ret) {
- free(buf);
- kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
- krb5_get_err_text(context, ret));
- return ret;
- }
-
- ret = krb5_encrypt_EncryptedData(context,
- crypto,
- KRB5_KU_TICKET,
- buf,
- len,
- 0,
- reply);
- krb5_crypto_destroy(context, crypto);
- if(ret) {
- kdc_log(context, config, 0, "Failed to encrypt data: %s",
- krb5_get_err_text(context, ret));
- return ret;
- }
- return 0;
-}
-
-static krb5_error_code
-encode_524_response(krb5_context context,
- krb5_kdc_configuration *config,
- const char *spn, const EncTicketPart et,
- const Ticket *t, hdb_entry_ex *server,
- EncryptedData *ticket, int *kvno)
-{
- krb5_error_code ret;
- int use_2b;
- size_t len;
-
- use_2b = krb5_config_get_bool(context, NULL, "kdc", "use_2b", spn, NULL);
- if(use_2b) {
- ASN1_MALLOC_ENCODE(EncryptedData,
- ticket->cipher.data, ticket->cipher.length,
- &t->enc_part, &len, ret);
-
- if (ret) {
- kdc_log(context, config, 0,
- "Failed to encode v4 (2b) ticket (%s)", spn);
- return ret;
- }
-
- ticket->etype = 0;
- ticket->kvno = NULL;
- *kvno = 213; /* 2b's use this magic kvno */
- } else {
- unsigned char buf[MAX_KTXT_LEN + 4 * 4];
- Key *skey;
-
- if (!config->enable_v4_cross_realm && strcmp (et.crealm, t->realm) != 0) {
- kdc_log(context, config, 0, "524 cross-realm %s -> %s disabled", et.crealm,
- t->realm);
- return KRB5KDC_ERR_POLICY;
- }
-
- ret = _kdc_encode_v4_ticket(context, config,
- buf + sizeof(buf) - 1, sizeof(buf),
- &et, &t->sname, &len);
- if(ret){
- kdc_log(context, config, 0,
- "Failed to encode v4 ticket (%s)", spn);
- return ret;
- }
- ret = _kdc_get_des_key(context, server, TRUE, FALSE, &skey);
- if(ret){
- kdc_log(context, config, 0,
- "no suitable DES key for server (%s)", spn);
- return ret;
- }
- ret = encrypt_v4_ticket(context, config, buf + sizeof(buf) - len, len,
- &skey->key, ticket);
- if(ret){
- kdc_log(context, config, 0,
- "Failed to encrypt v4 ticket (%s)", spn);
- return ret;
- }
- *kvno = server->entry.kvno;
- }
-
- return 0;
-}
-
-/*
- * process a 5->4 request, based on `t', and received `from, addr',
- * returning the reply in `reply'
- */
-
-krb5_error_code
-_kdc_do_524(krb5_context context,
- krb5_kdc_configuration *config,
- const Ticket *t, krb5_data *reply,
- const char *from, struct sockaddr *addr)
-{
- krb5_error_code ret = 0;
- krb5_crypto crypto;
- hdb_entry_ex *server = NULL;
- Key *skey;
- krb5_data et_data;
- EncTicketPart et;
- EncryptedData ticket;
- krb5_storage *sp;
- char *spn = NULL;
- unsigned char buf[MAX_KTXT_LEN + 4 * 4];
- size_t len;
- int kvno = 0;
-
- if(!config->enable_524) {
- ret = KRB5KDC_ERR_POLICY;
- kdc_log(context, config, 0,
- "Rejected ticket conversion request from %s", from);
- goto out;
- }
-
- ret = fetch_server (context, config, t, &spn, &server, from);
- if (ret) {
- goto out;
- }
-
- ret = hdb_enctype2key(context, &server->entry, t->enc_part.etype, &skey);
- if(ret){
- kdc_log(context, config, 0,
- "No suitable key found for server (%s) from %s", spn, from);
- goto out;
- }
- ret = krb5_crypto_init(context, &skey->key, 0, &crypto);
- if (ret) {
- kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
- krb5_get_err_text(context, ret));
- goto out;
- }
- ret = krb5_decrypt_EncryptedData (context,
- crypto,
- KRB5_KU_TICKET,
- &t->enc_part,
- &et_data);
- krb5_crypto_destroy(context, crypto);
- if(ret){
- kdc_log(context, config, 0,
- "Failed to decrypt ticket from %s for %s", from, spn);
- goto out;
- }
- ret = krb5_decode_EncTicketPart(context, et_data.data, et_data.length,
- &et, &len);
- krb5_data_free(&et_data);
- if(ret){
- kdc_log(context, config, 0,
- "Failed to decode ticket from %s for %s", from, spn);
- goto out;
- }
-
- ret = log_524 (context, config, &et, from, spn);
- if (ret) {
- free_EncTicketPart(&et);
- goto out;
- }
-
- ret = verify_flags (context, config, &et, spn);
- if (ret) {
- free_EncTicketPart(&et);
- goto out;
- }
-
- ret = set_address (context, config, &et, addr, from);
- if (ret) {
- free_EncTicketPart(&et);
- goto out;
- }
-
- ret = encode_524_response(context, config, spn, et, t,
- server, &ticket, &kvno);
- free_EncTicketPart(&et);
-
- out:
- /* make reply */
- memset(buf, 0, sizeof(buf));
- sp = krb5_storage_from_mem(buf, sizeof(buf));
- if (sp) {
- krb5_store_int32(sp, ret);
- if(ret == 0){
- krb5_store_int32(sp, kvno);
- krb5_store_data(sp, ticket.cipher);
- /* Aargh! This is coded as a KTEXT_ST. */
- krb5_storage_seek(sp, MAX_KTXT_LEN - ticket.cipher.length, SEEK_CUR);
- krb5_store_int32(sp, 0); /* mbz */
- free_EncryptedData(&ticket);
- }
- ret = krb5_storage_to_data(sp, reply);
- reply->length = krb5_storage_seek(sp, 0, SEEK_CUR);
- krb5_storage_free(sp);
- } else
- krb5_data_zero(reply);
- if(spn)
- free(spn);
- if(server)
- _kdc_free_ent (context, server);
- return ret;
-}
diff --git a/source4/heimdal/kdc/default_config.c b/source4/heimdal/kdc/default_config.c
index 60fbc92903..bf65af3cb9 100644
--- a/source4/heimdal/kdc/default_config.c
+++ b/source4/heimdal/kdc/default_config.c
@@ -84,6 +84,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
krb5_config_get_bool_default(context, NULL,
c->enable_v4,
"kdc", "enable-524", NULL);
+#ifdef DIGEST
c->enable_digest =
krb5_config_get_bool_default(context, NULL,
FALSE,
@@ -110,7 +111,9 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
c->enable_digest = 0;
}
}
+#endif
+#ifdef KX509
c->enable_kx509 =
krb5_config_get_bool_default(context, NULL,
FALSE,
@@ -129,6 +132,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
c->enable_kx509 = FALSE;
}
}
+#endif
c->check_ticket_addresses =
krb5_config_get_bool_default(context, NULL,
@@ -220,7 +224,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
"enable-pkinit",
NULL);
if (c->enable_pkinit) {
- const char *user_id, *anchors, *ocsp_file;
+ const char *user_id, *anchors, *file;
char **pool_list, **revoke_list;
user_id =
@@ -242,15 +246,23 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
krb5_config_get_strings(context, NULL,
"kdc", "pkinit_revoke", NULL);
- ocsp_file =
- krb5_config_get_string(context, NULL,
- "kdc", "pkinit_kdc_ocsp", NULL);
- if (ocsp_file) {
- c->pkinit_kdc_ocsp_file = strdup(ocsp_file);
+ file = krb5_config_get_string(context, NULL,
+ "kdc", "pkinit_kdc_ocsp", NULL);
+ if (file) {
+ c->pkinit_kdc_ocsp_file = strdup(file);
if (c->pkinit_kdc_ocsp_file == NULL)
krb5_errx(context, 1, "out of memory");
}
+ file = krb5_config_get_string(context, NULL,
+ "kdc", "pkinit_kdc_friendly_name", NULL);
+ if (file) {
+ c->pkinit_kdc_friendly_name = strdup(file);
+ if (c->pkinit_kdc_friendly_name == NULL)
+ krb5_errx(context, 1, "out of memory");
+ }
+
+
_kdc_pk_initialize(context, c, user_id, anchors,
pool_list, revoke_list);
diff --git a/source4/heimdal/kdc/digest.c b/source4/heimdal/kdc/digest.c
index 96986c1a87..d13507fc1f 100644
--- a/source4/heimdal/kdc/digest.c
+++ b/source4/heimdal/kdc/digest.c
@@ -34,7 +34,7 @@
#include "kdc_locl.h"
#include <hex.h>
-RCSID("$Id$");
+#ifdef DIGEST
#define MS_CHAP_V2 0x20
#define CHAP_MD5 0x10
@@ -201,7 +201,7 @@ get_password_entry(krb5_context context,
krb5_error_code
_kdc_do_digest(krb5_context context,
krb5_kdc_configuration *config,
- const DigestREQ *req, krb5_data *reply,
+ const struct DigestREQ *req, krb5_data *reply,
const char *from, struct sockaddr *addr)
{
krb5_error_code ret = 0;
@@ -234,6 +234,7 @@ _kdc_do_digest(krb5_context context,
memset(&ireq, 0, sizeof(ireq));
memset(&r, 0, sizeof(r));
memset(&rep, 0, sizeof(rep));
+ memset(&res, 0, sizeof(res));
kdc_log(context, config, 0, "Digest request from %s", from);
@@ -487,6 +488,7 @@ _kdc_do_digest(krb5_context context,
hex_encode(buf.data, buf.length, &r.u.initReply.opaque);
free(buf.data);
+ krb5_data_zero(&buf);
if (r.u.initReply.opaque == NULL) {
krb5_clear_error_message(context);
ret = ENOMEM;
@@ -539,8 +541,10 @@ _kdc_do_digest(krb5_context context,
ret = decode_Checksum(buf.data, buf.length, &res, NULL);
free(buf.data);
+ krb5_data_zero(&buf);
if (ret) {
- krb5_set_error_message(context, ret, "Failed to decode digest Checksum");
+ krb5_set_error_message(context, ret,
+ "Failed to decode digest Checksum");
goto out;
}
@@ -582,6 +586,8 @@ _kdc_do_digest(krb5_context context,
ret = krb5_verify_checksum(context, crypto,
KRB5_KU_DIGEST_OPAQUE,
buf.data, buf.length, &res);
+ free_Checksum(&res);
+ krb5_data_free(&buf);
krb5_crypto_destroy(context, crypto);
crypto = NULL;
if (ret)
@@ -1165,6 +1171,8 @@ _kdc_do_digest(krb5_context context,
krb5_set_error_message(context, ret, "NTLM storage read flags");
goto out;
}
+ krb5_storage_free(sp);
+ sp = NULL;
krb5_data_free(&buf);
if ((flags & NTLM_NEG_NTLM) == 0) {
@@ -1450,9 +1458,12 @@ _kdc_do_digest(krb5_context context,
free (client_name);
krb5_data_free(&buf);
krb5_data_free(&serverNonce);
+ free_Checksum(&res);
free_DigestREP(&rep);
free_DigestRepInner(&r);
free_DigestReqInner(&ireq);
return ret;
}
+
+#endif /* DIGEST */
diff --git a/source4/heimdal/kdc/headers.h b/source4/heimdal/kdc/headers.h
index 3635d3c56a..2240336e31 100644
--- a/source4/heimdal/kdc/headers.h
+++ b/source4/heimdal/kdc/headers.h
@@ -91,13 +91,19 @@
#include <parse_units.h>
#include <krb5.h>
#include <krb5_locl.h>
+#ifdef DIGEST
#include <digest_asn1.h>
+#endif
+#ifdef KX509
#include <kx509_asn1.h>
+#endif
#include <hdb.h>
#include <hdb_err.h>
#include <der.h>
+#ifndef NO_NTLM
#include <heimntlm.h>
+#endif
#include <windc_plugin.h>
#undef ALLOC
diff --git a/source4/heimdal/kdc/kaserver.c b/source4/heimdal/kdc/kaserver.c
index 9226ae115d..3702ab9281 100644
--- a/source4/heimdal/kdc/kaserver.c
+++ b/source4/heimdal/kdc/kaserver.c
@@ -33,7 +33,7 @@
#include "kdc_locl.h"
-RCSID("$Id$");
+#ifdef KRB4
#include <krb5-v4compat.h>
#include <rx.h>
@@ -949,3 +949,5 @@ out:
krb5_storage_free (sp);
return ret;
}
+
+#endif /* KRB4 */
diff --git a/source4/heimdal/kdc/kdc.h b/source4/heimdal/kdc/kdc.h
index 843bd5fa56..285a33af14 100644
--- a/source4/heimdal/kdc/kdc.h
+++ b/source4/heimdal/kdc/kdc.h
@@ -75,8 +75,10 @@ typedef struct krb5_kdc_configuration {
krb5_boolean enable_pkinit;
krb5_boolean pkinit_princ_in_cert;
char *pkinit_kdc_ocsp_file;
+ char *pkinit_kdc_friendly_name;
int pkinit_dh_min_bits;
int pkinit_require_binding;
+ int pkinit_allow_proxy_certs;
krb5_log_facility *logf;
@@ -91,6 +93,20 @@ typedef struct krb5_kdc_configuration {
} krb5_kdc_configuration;
+struct krb5_kdc_service {
+ unsigned int flags;
+#define KS_KRB5 1
+#define KS_NO_LENGTH 2
+ krb5_error_code (*process)(krb5_context context,
+ krb5_kdc_configuration *config,
+ krb5_data *req_buffer,
+ krb5_data *reply,
+ const char *from,
+ struct sockaddr *addr,
+ int datagram_reply,
+ int *claim);
+};
+
#include <kdc-protos.h>
#endif
diff --git a/source4/heimdal/kdc/kdc_locl.h b/source4/heimdal/kdc/kdc_locl.h
index 8e34c50049..9b291ac896 100644
--- a/source4/heimdal/kdc/kdc_locl.h
+++ b/source4/heimdal/kdc/kdc_locl.h
@@ -42,6 +42,8 @@
#include "kdc.h"
typedef struct pk_client_params pk_client_params;
+struct DigestREQ;
+struct Kx509Request;
#include <kdc-private.h>
extern sig_atomic_t exit_flag;
@@ -52,9 +54,12 @@ extern krb5_addresses explicit_addresses;
extern int enable_http;
+#ifdef SUPPORT_DETACH
+
#define DETACH_IS_DEFAULT FALSE
extern int detach_from_console;
+#endif
extern const struct units _kdc_digestunits[];
diff --git a/source4/heimdal/kdc/kerberos4.c b/source4/heimdal/kdc/kerberos4.c
deleted file mode 100644
index 2bd2383940..0000000000
--- a/source4/heimdal/kdc/kerberos4.c
+++ /dev/null
@@ -1,794 +0,0 @@
-/*
- * Copyright (c) 1997 - 2006 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "kdc_locl.h"
-
-#include <krb5-v4compat.h>
-
-RCSID("$Id$");
-
-#ifndef swap32
-static uint32_t
-swap32(uint32_t x)
-{
- return ((x << 24) & 0xff000000) |
- ((x << 8) & 0xff0000) |
- ((x >> 8) & 0xff00) |
- ((x >> 24) & 0xff);
-}
-#endif /* swap32 */
-
-int
-_kdc_maybe_version4(unsigned char *buf, int len)
-{
- return len > 0 && *buf == 4;
-}
-
-static void
-make_err_reply(krb5_context context, krb5_data *reply,
- int code, const char *msg)
-{
- _krb5_krb_cr_err_reply(context, "", "", "",
- kdc_time, code, msg, reply);
-}
-
-struct valid_princ_ctx {
- krb5_kdc_configuration *config;
- unsigned flags;
-};
-
-static krb5_boolean
-valid_princ(krb5_context context,
- void *funcctx,
- krb5_principal princ)
-{
- struct valid_princ_ctx *ctx = funcctx;
- krb5_error_code ret;
- char *s;
- hdb_entry_ex *ent;
-
- ret = krb5_unparse_name(context, princ, &s);
- if (ret)
- return FALSE;
- ret = _kdc_db_fetch(context, ctx->config, princ, ctx->flags, NULL, &ent);
- if (ret) {
- kdc_log(context, ctx->config, 7, "Lookup %s failed: %s", s,
- krb5_get_err_text (context, ret));
- free(s);
- return FALSE;
- }
- kdc_log(context, ctx->config, 7, "Lookup %s succeeded", s);
- free(s);
- _kdc_free_ent(context, ent);
- return TRUE;
-}
-
-krb5_error_code
-_kdc_db_fetch4(krb5_context context,
- krb5_kdc_configuration *config,
- const char *name, const char *instance, const char *realm,
- unsigned flags,
- hdb_entry_ex **ent)
-{
- krb5_principal p;
- krb5_error_code ret;
- struct valid_princ_ctx ctx;
-
- ctx.config = config;
- ctx.flags = flags;
-
- ret = krb5_425_conv_principal_ext2(context, name, instance, realm,
- valid_princ, &ctx, 0, &p);
- if(ret)
- return ret;
- ret = _kdc_db_fetch(context, config, p, flags, NULL, ent);
- krb5_free_principal(context, p);
- return ret;
-}
-
-#define RCHECK(X, L) if(X){make_err_reply(context, reply, KFAILURE, "Packet too short"); goto L;}
-
-/*
- * Process the v4 request in `buf, len' (received from `addr'
- * (with string `from').
- * Return an error code and a reply in `reply'.
- */
-
-krb5_error_code
-_kdc_do_version4(krb5_context context,
- krb5_kdc_configuration *config,
- unsigned char *buf,
- size_t len,
- krb5_data *reply,
- const char *from,
- struct sockaddr_in *addr)
-{
- krb5_storage *sp;
- krb5_error_code ret = EINVAL;
- hdb_entry_ex *client = NULL, *server = NULL;
- Key *ckey, *skey;
- int8_t pvno;
- int8_t msg_type;
- int lsb;
- char *name = NULL, *inst = NULL, *realm = NULL;
- char *sname = NULL, *sinst = NULL;
- int32_t req_time;
- time_t max_life;
- uint8_t life;
- char client_name[256];
- char server_name[256];
-
- if(!config->enable_v4) {
- kdc_log(context, config, 0,
- "Rejected version 4 request from %s", from);
- make_err_reply(context, reply, KRB4ET_KDC_GEN_ERR,
- "Function not enabled");
- return 0;
- }
-
- sp = krb5_storage_from_mem(buf, len);
- RCHECK(krb5_ret_int8(sp, &pvno), out);
- if(pvno != 4){
- kdc_log(context, config, 0,
- "Protocol version mismatch (krb4) (%d)", pvno);
- make_err_reply(context, reply, KRB4ET_KDC_PKT_VER, "protocol mismatch");
- ret = KRB4ET_KDC_PKT_VER;
- goto out;
- }
- RCHECK(krb5_ret_int8(sp, &msg_type), out);
- lsb = msg_type & 1;
- msg_type &= ~1;
- switch(msg_type){
- case AUTH_MSG_KDC_REQUEST: {
- krb5_data ticket, cipher;
- krb5_keyblock session;
-
- krb5_data_zero(&ticket);
- krb5_data_zero(&cipher);
-
- RCHECK(krb5_ret_stringz(sp, &name), out1);
- RCHECK(krb5_ret_stringz(sp, &inst), out1);
- RCHECK(krb5_ret_stringz(sp, &realm), out1);
- RCHECK(krb5_ret_int32(sp, &req_time), out1);
- if(lsb)
- req_time = swap32(req_time);
- RCHECK(krb5_ret_uint8(sp, &life), out1);
- RCHECK(krb5_ret_stringz(sp, &sname), out1);
- RCHECK(krb5_ret_stringz(sp, &sinst), out1);
- snprintf (client_name, sizeof(client_name),
- "%s.%s@%s", name, inst, realm);
- snprintf (server_name, sizeof(server_name),
- "%s.%s@%s", sname, sinst, config->v4_realm);
-
- kdc_log(context, config, 0, "AS-REQ (krb4) %s from %s for %s",
- client_name, from, server_name);
-
- ret = _kdc_db_fetch4(context, config, name, inst, realm,
- HDB_F_GET_CLIENT, &client);
- if(ret) {
- kdc_log(context, config, 0, "Client not found in database: %s: %s",
- client_name, krb5_get_err_text(context, ret));
- make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN,
- "principal unknown");
- goto out1;
- }
- ret = _kdc_db_fetch4(context, config, sname, sinst, config->v4_realm,
- HDB_F_GET_SERVER, &server);
- if(ret){
- kdc_log(context, config, 0, "Server not found in database: %s: %s",
- server_name, krb5_get_err_text(context, ret));
- make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN,
- "principal unknown");
- goto out1;
- }
-
- ret = _kdc_check_flags (context, config,
- client, client_name,
- server, server_name,
- TRUE);
- if (ret) {
- /* good error code? */
- make_err_reply(context, reply, KRB4ET_KDC_NAME_EXP,
- "operation not allowed");
- goto out1;
- }
-
- if (config->enable_v4_per_principal &&
- client->entry.flags.allow_kerberos4 == 0)
- {
- kdc_log(context, config, 0,
- "Per principal Kerberos 4 flag not turned on for %s",
- client_name);
- make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY,
- "allow kerberos4 flag required");
- goto out1;
- }
-
- /*
- * There's no way to do pre-authentication in v4 and thus no
- * good error code to return if preauthentication is required.
- */
-
- if (config->require_preauth
- || client->entry.flags.require_preauth
- || server->entry.flags.require_preauth) {
- kdc_log(context, config, 0,
- "Pre-authentication required for v4-request: "
- "%s for %s",
- client_name, server_name);
- make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY,
- "preauth required");
- goto out1;
- }
-
- ret = _kdc_get_des_key(context, client, FALSE, FALSE, &ckey);
- if(ret){
- kdc_log(context, config, 0, "no suitable DES key for client");
- make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY,
- "no suitable DES key for client");
- goto out1;
- }
-
- ret = _kdc_get_des_key(context, server, TRUE, FALSE, &skey);
- if(ret){
- kdc_log(context, config, 0, "no suitable DES key for server");
- make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY,
- "no suitable DES key for server");
- goto out1;
- }
-
- max_life = _krb5_krb_life_to_time(0, life);
- if(client->entry.max_life)
- max_life = min(max_life, *client->entry.max_life);
- if(server->entry.max_life)
- max_life = min(max_life, *server->entry.max_life);
-
- life = krb_time_to_life(kdc_time, kdc_time + max_life);
-
- ret = krb5_generate_random_keyblock(context,
- ETYPE_DES_PCBC_NONE,
- &session);
- if (ret) {
- make_err_reply(context, reply, KFAILURE,
- "Not enough random i KDC");
- goto out1;
- }
-
- ret = _krb5_krb_create_ticket(context,
- 0,
- name,
- inst,
- config->v4_realm,
- addr->sin_addr.s_addr,
- &session,
- life,
- kdc_time,
- sname,
- sinst,
- &skey->key,
- &ticket);
- if (ret) {
- krb5_free_keyblock_contents(context, &session);
- make_err_reply(context, reply, KFAILURE,
- "failed to create v4 ticket");
- goto out1;
- }
-
- ret = _krb5_krb_create_ciph(context,
- &session,
- sname,
- sinst,
- config->v4_realm,
- life,
- server->entry.kvno % 255,
- &ticket,
- kdc_time,
- &ckey->key,
- &cipher);
- krb5_free_keyblock_contents(context, &session);
- krb5_data_free(&ticket);
- if (ret) {
- make_err_reply(context, reply, KFAILURE,
- "Failed to create v4 cipher");
- goto out1;
- }
-
- ret = _krb5_krb_create_auth_reply(context,
- name,
- inst,
- realm,
- req_time,
- 0,
- client->entry.pw_end ? *client->entry.pw_end : 0,
- client->entry.kvno % 256,
- &cipher,
- reply);
- krb5_data_free(&cipher);
-
- out1:
- break;
- }
- case AUTH_MSG_APPL_REQUEST: {
- struct _krb5_krb_auth_data ad;
- int8_t kvno;
- int8_t ticket_len;
- int8_t req_len;
- krb5_data auth;
- int32_t address;
- size_t pos;
- krb5_principal tgt_princ = NULL;
- hdb_entry_ex *tgt = NULL;
- Key *tkey;
- time_t max_end, actual_end, issue_time;
-
- memset(&ad, 0, sizeof(ad));
- krb5_data_zero(&auth);
-
- RCHECK(krb5_ret_int8(sp, &kvno), out2);
- RCHECK(krb5_ret_stringz(sp, &realm), out2);
-
- ret = krb5_425_conv_principal(context, "krbtgt", realm,
- config->v4_realm,
- &tgt_princ);
- if(ret){
- kdc_log(context, config, 0,
- "Converting krbtgt principal (krb4): %s",
- krb5_get_err_text(context, ret));
- make_err_reply(context, reply, KFAILURE,
- "Failed to convert v4 principal (krbtgt)");
- goto out2;
- }
-
- ret = _kdc_db_fetch(context, config, tgt_princ,
- HDB_F_GET_KRBTGT, NULL, &tgt);
- if(ret){
- char *s;
- s = kdc_log_msg(context, config, 0, "Ticket-granting ticket not "
- "found in database (krb4): krbtgt.%s@%s: %s",
- realm, config->v4_realm,
- krb5_get_err_text(context, ret));
- make_err_reply(context, reply, KFAILURE, s);
- free(s);
- goto out2;
- }
-
- if(tgt->entry.kvno % 256 != kvno){
- kdc_log(context, config, 0,
- "tgs-req (krb4) with old kvno %d (current %d) for "
- "krbtgt.%s@%s", kvno, tgt->entry.kvno % 256,
- realm, config->v4_realm);
- make_err_reply(context, reply, KRB4ET_KDC_AUTH_EXP,
- "old krbtgt kvno used");
- goto out2;
- }
-
- ret = _kdc_get_des_key(context, tgt, TRUE, FALSE, &tkey);
- if(ret){
- kdc_log(context, config, 0,
- "no suitable DES key for krbtgt (krb4)");
- make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY,
- "no suitable DES key for krbtgt");
- goto out2;
- }
-
- RCHECK(krb5_ret_int8(sp, &ticket_len), out2);
- RCHECK(krb5_ret_int8(sp, &req_len), out2);
-
- pos = krb5_storage_seek(sp, ticket_len + req_len, SEEK_CUR);
-
- auth.data = buf;
- auth.length = pos;
-
- if (config->check_ticket_addresses)
- address = addr->sin_addr.s_addr;
- else
- address = 0;
-
- ret = _krb5_krb_rd_req(context, &auth, "krbtgt", realm,
- config->v4_realm,
- address, &tkey->key, &ad);
- if(ret){
- kdc_log(context, config, 0, "krb_rd_req: %d", ret);
- make_err_reply(context, reply, ret, "failed to parse request");
- goto out2;
- }
-
- RCHECK(krb5_ret_int32(sp, &req_time), out2);
- if(lsb)
- req_time = swap32(req_time);
- RCHECK(krb5_ret_uint8(sp, &life), out2);
- RCHECK(krb5_ret_stringz(sp, &sname), out2);
- RCHECK(krb5_ret_stringz(sp, &sinst), out2);
- snprintf (server_name, sizeof(server_name),
- "%s.%s@%s",
- sname, sinst, config->v4_realm);
- snprintf (client_name, sizeof(client_name),
- "%s.%s@%s",
- ad.pname, ad.pinst, ad.prealm);
-
- kdc_log(context, config, 0, "TGS-REQ (krb4) %s from %s for %s",
- client_name, from, server_name);
-
- if(strcmp(ad.prealm, realm)){
- kdc_log(context, config, 0,
- "Can't hop realms (krb4) %s -> %s", realm, ad.prealm);
- make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN,
- "Can't hop realms");
- goto out2;
- }
-
- if (!config->enable_v4_cross_realm && strcmp(realm, config->v4_realm) != 0) {
- kdc_log(context, config, 0,
- "krb4 Cross-realm %s -> %s disabled",
- realm, config->v4_realm);
- make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN,
- "Can't hop realms");
- goto out2;
- }
-
- if(strcmp(sname, "changepw") == 0){
- kdc_log(context, config, 0,
- "Bad request for changepw ticket (krb4)");
- make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN,
- "Can't authorize password change based on TGT");
- goto out2;
- }
-
- ret = _kdc_db_fetch4(context, config, ad.pname, ad.pinst, ad.prealm,
- HDB_F_GET_CLIENT, &client);
- if(ret && ret != HDB_ERR_NOENTRY) {
- char *s;
- s = kdc_log_msg(context, config, 0,
- "Client not found in database: (krb4) %s: %s",
- client_name, krb5_get_err_text(context, ret));
- make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN, s);
- free(s);
- goto out2;
- }
- if (client == NULL && strcmp(ad.prealm, config->v4_realm) == 0) {
- char *s;
- s = kdc_log_msg(context, config, 0,
- "Local client not found in database: (krb4) "
- "%s", client_name);
- make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN, s);
- free(s);
- goto out2;
- }
-
- ret = _kdc_db_fetch4(context, config, sname, sinst, config->v4_realm,
- HDB_F_GET_SERVER, &server);
- if(ret){
- char *s;
- s = kdc_log_msg(context, config, 0,
- "Server not found in database (krb4): %s: %s",
- server_name, krb5_get_err_text(context, ret));
- make_err_reply(context, reply, KRB4ET_KDC_PR_UNKNOWN, s);
- free(s);
- goto out2;
- }
-
- ret = _kdc_check_flags (context, config,
- client, client_name,
- server, server_name,
- FALSE);
- if (ret) {
- make_err_reply(context, reply, KRB4ET_KDC_NAME_EXP,
- "operation not allowed");
- goto out2;
- }
-
- ret = _kdc_get_des_key(context, server, TRUE, FALSE, &skey);
- if(ret){
- kdc_log(context, config, 0,
- "no suitable DES key for server (krb4)");
- make_err_reply(context, reply, KRB4ET_KDC_NULL_KEY,
- "no suitable DES key for server");
- goto out2;
- }
-
- max_end = _krb5_krb_life_to_time(ad.time_sec, ad.life);
- max_end = min(max_end, _krb5_krb_life_to_time(kdc_time, life));
- if(server->entry.max_life)
- max_end = min(max_end, kdc_time + *server->entry.max_life);
- if(client && client->entry.max_life)
- max_end = min(max_end, kdc_time + *client->entry.max_life);
- life = min(life, krb_time_to_life(kdc_time, max_end));
-
- issue_time = kdc_time;
- actual_end = _krb5_krb_life_to_time(issue_time, life);
- while (actual_end > max_end && life > 1) {
- /* move them into the next earlier lifetime bracket */
- life--;
- actual_end = _krb5_krb_life_to_time(issue_time, life);
- }
- if (actual_end > max_end) {
- /* if life <= 1 and it's still too long, backdate the ticket */
- issue_time -= actual_end - max_end;
- }
-
- {
- krb5_data ticket, cipher;
- krb5_keyblock session;
-
- krb5_data_zero(&ticket);
- krb5_data_zero(&cipher);
-
- ret = krb5_generate_random_keyblock(context,
- ETYPE_DES_PCBC_NONE,
- &session);
- if (ret) {
- make_err_reply(context, reply, KFAILURE,
- "Not enough random i KDC");
- goto out2;
- }
-
- ret = _krb5_krb_create_ticket(context,
- 0,
- ad.pname,
- ad.pinst,
- ad.prealm,
- addr->sin_addr.s_addr,
- &session,
- life,
- issue_time,
- sname,
- sinst,
- &skey->key,
- &ticket);
- if (ret) {
- krb5_free_keyblock_contents(context, &session);
- make_err_reply(context, reply, KFAILURE,
- "failed to create v4 ticket");
- goto out2;
- }
-
- ret = _krb5_krb_create_ciph(context,
- &session,
- sname,
- sinst,
- config->v4_realm,
- life,
- server->entry.kvno % 255,
- &ticket,
- issue_time,
- &ad.session,
- &cipher);
- krb5_free_keyblock_contents(context, &session);
- if (ret) {
- make_err_reply(context, reply, KFAILURE,
- "failed to create v4 cipher");
- goto out2;
- }
-
- ret = _krb5_krb_create_auth_reply(context,
- ad.pname,
- ad.pinst,
- ad.prealm,
- req_time,
- 0,
- 0,
- 0,
- &cipher,
- reply);
- krb5_data_free(&cipher);
- }
- out2:
- _krb5_krb_free_auth_data(context, &ad);
- if(tgt_princ)
- krb5_free_principal(context, tgt_princ);
- if(tgt)
- _kdc_free_ent(context, tgt);
- break;
- }
- case AUTH_MSG_ERR_REPLY:
- ret = EINVAL;
- break;
- default:
- kdc_log(context, config, 0, "Unknown message type (krb4): %d from %s",
- msg_type, from);
-
- make_err_reply(context, reply, KFAILURE, "Unknown message type");
- ret = EINVAL;
- }
- out:
- if(name)
- free(name);
- if(inst)
- free(inst);
- if(realm)
- free(realm);
- if(sname)
- free(sname);
- if(sinst)
- free(sinst);
- if(client)
- _kdc_free_ent(context, client);
- if(server)
- _kdc_free_ent(context, server);
- krb5_storage_free(sp);
- return ret;
-}
-
-krb5_error_code
-_kdc_encode_v4_ticket(krb5_context context,
- krb5_kdc_configuration *config,
- void *buf, size_t len, const EncTicketPart *et,
- const PrincipalName *service, size_t *size)
-{
- krb5_storage *sp;
- krb5_error_code ret;
- char name[40], inst[40], realm[40];
- char sname[40], sinst[40];
-
- {
- krb5_principal princ;
- _krb5_principalname2krb5_principal(context,
- &princ,
- *service,
- et->crealm);
- ret = krb5_524_conv_principal(context,
- princ,
- sname,
- sinst,
- realm);
- krb5_free_principal(context, princ);
- if(ret)
- return ret;
-
- _krb5_principalname2krb5_principal(context,
- &princ,
- et->cname,
- et->crealm);
-
- ret = krb5_524_conv_principal(context,
- princ,
- name,
- inst,
- realm);
- krb5_free_principal(context, princ);
- }
- if(ret)
- return ret;
-
- sp = krb5_storage_emem();
-
- krb5_store_int8(sp, 0); /* flags */
- krb5_store_stringz(sp, name);
- krb5_store_stringz(sp, inst);
- krb5_store_stringz(sp, realm);
- {
- unsigned char tmp[4] = { 0, 0, 0, 0 };
- int i;
- if(et->caddr){
- for(i = 0; i < et->caddr->len; i++)
- if(et->caddr->val[i].addr_type == AF_INET &&
- et->caddr->val[i].address.length == 4){
- memcpy(tmp, et->caddr->val[i].address.data, 4);
- break;
- }
- }
- krb5_storage_write(sp, tmp, sizeof(tmp));
- }
-
- if((et->key.keytype != ETYPE_DES_CBC_MD5 &&
- et->key.keytype != ETYPE_DES_CBC_MD4 &&
- et->key.keytype != ETYPE_DES_CBC_CRC) ||
- et->key.keyvalue.length != 8)
- return -1;
- krb5_storage_write(sp, et->key.keyvalue.data, 8);
-
- {
- time_t start = et->starttime ? *et->starttime : et->authtime;
- krb5_store_int8(sp, krb_time_to_life(start, et->endtime));
- krb5_store_int32(sp, start);
- }
-
- krb5_store_stringz(sp, sname);
- krb5_store_stringz(sp, sinst);
-
- {
- krb5_data data;
- krb5_storage_to_data(sp, &data);
- krb5_storage_free(sp);
- *size = (data.length + 7) & ~7; /* pad to 8 bytes */
- if(*size > len)
- return -1;
- memset((unsigned char*)buf - *size + 1, 0, *size);
- memcpy((unsigned char*)buf - *size + 1, data.data, data.length);
- krb5_data_free(&data);
- }
- return 0;
-}
-
-krb5_error_code
-_kdc_get_des_key(krb5_context context,
- hdb_entry_ex *principal, krb5_boolean is_server,
- krb5_boolean prefer_afs_key, Key **ret_key)
-{
- Key *v5_key = NULL, *v4_key = NULL, *afs_key = NULL, *server_key = NULL;
- int i;
- krb5_enctype etypes[] = { ETYPE_DES_CBC_MD5,
- ETYPE_DES_CBC_MD4,
- ETYPE_DES_CBC_CRC };
-
- for(i = 0;
- i < sizeof(etypes)/sizeof(etypes[0])
- && (v5_key == NULL || v4_key == NULL ||
- afs_key == NULL || server_key == NULL);
- ++i) {
- Key *key = NULL;
- while(hdb_next_enctype2key(context, &principal->entry, etypes[i], &key) == 0) {
- if(key->salt == NULL) {
- if(v5_key == NULL)
- v5_key = key;
- } else if(key->salt->type == hdb_pw_salt &&
- key->salt->salt.length == 0) {
- if(v4_key == NULL)
- v4_key = key;
- } else if(key->salt->type == hdb_afs3_salt) {
- if(afs_key == NULL)
- afs_key = key;
- } else if(server_key == NULL)
- server_key = key;
- }
- }
-
- if(prefer_afs_key) {
- if(afs_key)
- *ret_key = afs_key;
- else if(v4_key)
- *ret_key = v4_key;
- else if(v5_key)
- *ret_key = v5_key;
- else if(is_server && server_key)
- *ret_key = server_key;
- else
- return KRB4ET_KDC_NULL_KEY;
- } else {
- if(v4_key)
- *ret_key = v4_key;
- else if(afs_key)
- *ret_key = afs_key;
- else if(v5_key)
- *ret_key = v5_key;
- else if(is_server && server_key)
- *ret_key = server_key;
- else
- return KRB4ET_KDC_NULL_KEY;
- }
-
- if((*ret_key)->key.keyvalue.length == 0)
- return KRB4ET_KDC_NULL_KEY;
- return 0;
-}
-
diff --git a/source4/heimdal/kdc/kerberos5.c b/source4/heimdal/kdc/kerberos5.c
index c715e0812f..941a2e0572 100644
--- a/source4/heimdal/kdc/kerberos5.c
+++ b/source4/heimdal/kdc/kerberos5.c
@@ -90,7 +90,7 @@ _kdc_find_padata(const KDC_REQ *req, int *start, int type)
*/
krb5_boolean
-_kdc_is_weak_expection(krb5_principal principal, krb5_enctype etype)
+_kdc_is_weak_exception(krb5_principal principal, krb5_enctype etype)
{
if (principal->name.name_string.len > 0 &&
strcmp(principal->name.name_string.val[0], "afs") == 0 &&
@@ -139,7 +139,7 @@ _kdc_find_etype(krb5_context context, const hdb_entry_ex *princ,
Key *key = NULL;
if (krb5_enctype_valid(context, etypes[i]) != 0 &&
- !_kdc_is_weak_expection(princ->entry.principal, etypes[i]))
+ !_kdc_is_weak_exception(princ->entry.principal, etypes[i]))
continue;
while (hdb_next_enctype2key(context, &princ->entry, etypes[i], &key) == 0) {
@@ -260,7 +260,7 @@ _kdc_encode_reply(krb5_context context,
KDC_REP *rep, const EncTicketPart *et, EncKDCRepPart *ek,
krb5_enctype etype,
int skvno, const EncryptionKey *skey,
- int ckvno, const EncryptionKey *ckey,
+ int ckvno, const EncryptionKey *reply_key,
const char **e_text,
krb5_data *reply)
{
@@ -321,7 +321,7 @@ _kdc_encode_reply(krb5_context context,
*e_text = "KDC internal error";
return KRB5KRB_ERR_GENERIC;
}
- ret = krb5_crypto_init(context, ckey, 0, &crypto);
+ ret = krb5_crypto_init(context, reply_key, 0, &crypto);
if (ret) {
free(buf);
kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
@@ -394,18 +394,6 @@ older_enctype(krb5_enctype enctype)
}
}
-static int
-only_older_enctype_p(const KDC_REQ *req)
-{
- int i;
-
- for(i = 0; i < req->req_body.etype.len; i++) {
- if (!older_enctype(req->req_body.etype.val[i]))
- return 0;
- }
- return 1;
-}
-
/*
*
*/
@@ -461,72 +449,23 @@ make_etype_info_entry(krb5_context context, ETYPE_INFO_ENTRY *ent, Key *key)
static krb5_error_code
get_pa_etype_info(krb5_context context,
krb5_kdc_configuration *config,
- METHOD_DATA *md, hdb_entry *client,
- ENCTYPE *etypes, unsigned int etypes_len)
+ METHOD_DATA *md, Key *ckey)
{
krb5_error_code ret = 0;
- int i, j;
- unsigned int n = 0;
ETYPE_INFO pa;
unsigned char *buf;
size_t len;
- pa.len = client->keys.len;
- if(pa.len > UINT_MAX/sizeof(*pa.val))
- return ERANGE;
- pa.val = malloc(pa.len * sizeof(*pa.val));
+ pa.len = 1;
+ pa.val = calloc(1, sizeof(pa.val[0]));
if(pa.val == NULL)
return ENOMEM;
- memset(pa.val, 0, pa.len * sizeof(*pa.val));
-
- for(i = 0; i < client->keys.len; i++) {
- for (j = 0; j < n; j++)
- if (pa.val[j].etype == client->keys.val[i].key.keytype)
- goto skip1;
- for(j = 0; j < etypes_len; j++) {
- if(client->keys.val[i].key.keytype == etypes[j]) {
- if (krb5_enctype_valid(context, etypes[j]) != 0)
- continue;
- if (!older_enctype(etypes[j]))
- continue;
- if (n >= pa.len)
- krb5_abortx(context, "internal error: n >= p.len");
- if((ret = make_etype_info_entry(context,
- &pa.val[n++],
- &client->keys.val[i])) != 0) {
- free_ETYPE_INFO(&pa);
- return ret;
- }
- break;
- }
- }
- skip1:;
- }
- for(i = 0; i < client->keys.len; i++) {
- /* already added? */
- for(j = 0; j < etypes_len; j++) {
- if(client->keys.val[i].key.keytype == etypes[j])
- goto skip2;
- }
- if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
- continue;
- if (!older_enctype(etypes[j]))
- continue;
- if (n >= pa.len)
- krb5_abortx(context, "internal error: n >= p.len");
- if((ret = make_etype_info_entry(context,
- &pa.val[n++],
- &client->keys.val[i])) != 0) {
- free_ETYPE_INFO(&pa);
- return ret;
- }
- skip2:;
- }
- if(n < pa.len) {
- /* stripped out dups, newer enctypes, and not valid enctypes */
- pa.len = n;
+ ret = make_etype_info_entry(context, &pa.val[0], ckey);
+ if (ret) {
+ free_ETYPE_INFO(&pa);
+ return ret;
}
ASN1_MALLOC_ENCODE(ETYPE_INFO, buf, len, &pa, &len, ret);
@@ -623,66 +562,22 @@ make_etype_info2_entry(ETYPE_INFO2_ENTRY *ent, Key *key)
static krb5_error_code
get_pa_etype_info2(krb5_context context,
krb5_kdc_configuration *config,
- METHOD_DATA *md, hdb_entry *client,
- ENCTYPE *etypes, unsigned int etypes_len)
+ METHOD_DATA *md, Key *ckey)
{
krb5_error_code ret = 0;
- int i, j;
- unsigned int n = 0;
ETYPE_INFO2 pa;
unsigned char *buf;
size_t len;
- pa.len = client->keys.len;
- if(pa.len > UINT_MAX/sizeof(*pa.val))
- return ERANGE;
- pa.val = malloc(pa.len * sizeof(*pa.val));
+ pa.len = 1;
+ pa.val = calloc(1, sizeof(pa.val[0]));
if(pa.val == NULL)
return ENOMEM;
- memset(pa.val, 0, pa.len * sizeof(*pa.val));
-
- for(i = 0; i < client->keys.len; i++) {
- for (j = 0; j < n; j++)
- if (pa.val[j].etype == client->keys.val[i].key.keytype)
- goto skip1;
- for(j = 0; j < etypes_len; j++) {
- if(client->keys.val[i].key.keytype == etypes[j]) {
- if (krb5_enctype_valid(context, etypes[j]) != 0)
- continue;
- if (n >= pa.len)
- krb5_abortx(context, "internal error: n >= p.len");
- if((ret = make_etype_info2_entry(&pa.val[n++],
- &client->keys.val[i])) != 0) {
- free_ETYPE_INFO2(&pa);
- return ret;
- }
- break;
- }
- }
- skip1:;
- }
- /* send enctypes that the client doesn't know about too */
- for(i = 0; i < client->keys.len; i++) {
- /* already added? */
- for(j = 0; j < etypes_len; j++) {
- if(client->keys.val[i].key.keytype == etypes[j])
- goto skip2;
- }
- if (krb5_enctype_valid(context, client->keys.val[i].key.keytype) != 0)
- continue;
- if (n >= pa.len)
- krb5_abortx(context, "internal error: n >= p.len");
- if((ret = make_etype_info2_entry(&pa.val[n++],
- &client->keys.val[i])) != 0) {
- free_ETYPE_INFO2(&pa);
- return ret;
- }
- skip2:;
- }
- if(n < pa.len) {
- /* stripped out dups, and not valid enctypes */
- pa.len = n;
+ ret = make_etype_info2_entry(&pa.val[0], ckey);
+ if (ret) {
+ free_ETYPE_INFO2(&pa);
+ return ret;
}
ASN1_MALLOC_ENCODE(ETYPE_INFO2, buf, len, &pa, &len, ret);
@@ -712,10 +607,12 @@ log_as_req(krb5_context context,
const KDC_REQ_BODY *b)
{
krb5_error_code ret;
- struct rk_strpool *p = NULL;
+ struct rk_strpool *p;
char *str;
int i;
+ p = rk_strpoolprintf(NULL, "%s", "Client supported enctypes: ");
+
for (i = 0; i < b->etype.len; i++) {
ret = krb5_enctype_to_string(context, b->etype.val[i], &str);
if (ret == 0) {
@@ -733,10 +630,6 @@ log_as_req(krb5_context context,
if (p == NULL)
p = rk_strpoolprintf(p, "no encryption types");
- str = rk_strpoolcollect(p);
- kdc_log(context, config, 0, "Client supported enctypes: %s", str);
- free(str);
-
{
char *cet;
char *set;
@@ -745,21 +638,26 @@ log_as_req(krb5_context context,
if(ret == 0) {
ret = krb5_enctype_to_string(context, setype, &set);
if (ret == 0) {
- kdc_log(context, config, 5, "Using %s/%s", cet, set);
+ p = rk_strpoolprintf(p, ", using %s/%s", cet, set);
free(set);
}
free(cet);
}
if (ret != 0)
- kdc_log(context, config, 5, "Using e-types %d/%d", cetype, setype);
+ p = rk_strpoolprintf(p, ", using enctypes %d/%d",
+ cetype, setype);
}
+ str = rk_strpoolcollect(p);
+ kdc_log(context, config, 0, "%s", str);
+ free(str);
+
{
char fixedstr[128];
unparse_flags(KDCOptions2int(b->kdc_options), asn1_KDCOptions_units(),
fixedstr, sizeof(fixedstr));
if(*fixedstr)
- kdc_log(context, config, 2, "Requested flags: %s", fixedstr);
+ kdc_log(context, config, 0, "Requested flags: %s", fixedstr);
}
}
@@ -956,6 +854,17 @@ send_pac_p(krb5_context context, KDC_REQ *req)
return TRUE;
}
+krb5_boolean
+_kdc_is_anonymous(krb5_context context, krb5_principal principal)
+{
+ if (principal->name.name_type != KRB5_NT_WELLKNOWN ||
+ principal->name.name_string.len != 2 ||
+ strcmp(principal->name.name_string.val[0], KRB5_WELLKNOWN_NAME) != 0 ||
+ strcmp(principal->name.name_string.val[1], KRB5_ANON_NAME) != 0)
+ return 0;
+ return 1;
+}
+
/*
*
*/
@@ -1039,6 +948,7 @@ _kdc_as_rep(krb5_context context,
if (ret)
goto out;
}
+
ret = krb5_unparse_name(context, client_princ, &client_name);
}
if (ret) {
@@ -1050,6 +960,28 @@ _kdc_as_rep(krb5_context context,
kdc_log(context, config, 0, "AS-REQ %s from %s for %s",
client_name, from, server_name);
+ /*
+ *
+ */
+
+ if (_kdc_is_anonymous(context, client_princ)) {
+ if (!b->kdc_options.request_anonymous) {
+ kdc_log(context, config, 0, "Anonymous ticket w/o anonymous flag");
+ ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+ goto out;
+ }
+ } else if (b->kdc_options.request_anonymous) {
+ kdc_log(context, config, 0,
+ "Request for a anonymous ticket with non "
+ "anonymous client name: %s", client_name);
+ ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+ goto out;
+ }
+
+ /*
+ *
+ */
+
ret = _kdc_db_fetch(context, config, client_princ,
HDB_F_GET_CLIENT | flags, NULL, &client);
if(ret){
@@ -1069,19 +1001,27 @@ _kdc_as_rep(krb5_context context,
goto out;
}
- ret = _kdc_windc_client_access(context, client, req, &e_data);
- if(ret)
- goto out;
+ memset(&et, 0, sizeof(et));
+ memset(&ek, 0, sizeof(ek));
- ret = _kdc_check_flags(context, config,
- client, client_name,
- server, server_name,
- TRUE);
- if(ret)
+ /*
+ * Find the client key for reply encryption and pa-type salt, Pick
+ * the client key upfront before the other keys because that is
+ * going to affect what enctypes we are going to use in
+ * ETYPE-INFO{,2}.
+ */
+
+ ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len,
+ &ckey, &cetype);
+ if (ret) {
+ kdc_log(context, config, 0,
+ "Client (%s) has no support for etypes", client_name);
goto out;
+ }
- memset(&et, 0, sizeof(et));
- memset(&ek, 0, sizeof(ek));
+ /*
+ * Pre-auth processing
+ */
if(req->padata){
int i;
@@ -1097,17 +1037,15 @@ _kdc_as_rep(krb5_context context,
e_text = "No PKINIT PA found";
i = 0;
- if ((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ)))
- ;
+ pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ);
if (pa == NULL) {
i = 0;
- if((pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN)))
- ;
+ pa = _kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_REQ_WIN);
}
if (pa) {
char *client_cert = NULL;
- ret = _kdc_pk_rd_padata(context, config, req, pa, &pkp);
+ ret = _kdc_pk_rd_padata(context, config, req, pa, client, &pkp);
if (ret) {
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
kdc_log(context, config, 5,
@@ -1127,11 +1065,12 @@ _kdc_as_rep(krb5_context context,
e_text = "PKINIT certificate not allowed to "
"impersonate principal";
_kdc_pk_free_client_param(context, pkp);
-
+
kdc_log(context, config, 0, "%s", e_text);
pkp = NULL;
goto out;
}
+
found_pa = 1;
et.flags.pre_authent = 1;
kdc_log(context, config, 0,
@@ -1158,6 +1097,12 @@ _kdc_as_rep(krb5_context context,
found_pa = 1;
+ if (b->kdc_options.request_anonymous) {
+ ret = KRB5KRB_AP_ERR_BAD_INTEGRITY;
+ kdc_log(context, config, 0, "ENC-TS doesn't support anon");
+ goto out;
+ }
+
ret = decode_EncryptedData(pa->padata_value.data,
pa->padata_value.length,
&enc_data,
@@ -1206,6 +1151,11 @@ _kdc_as_rep(krb5_context context,
&enc_data,
&ts_data);
krb5_crypto_destroy(context, crypto);
+ /*
+ * Since the user might have several keys with the same
+ * enctype but with diffrent salting, we need to try all
+ * the keys with the same enctype.
+ */
if(ret){
krb5_error_code ret2;
ret2 = krb5_enctype_to_string(context,
@@ -1298,6 +1248,7 @@ _kdc_as_rep(krb5_context context,
goto out;
}
}else if (config->require_preauth
+ || b->kdc_options.request_anonymous /* hack to force anon */
|| client->entry.flags.require_preauth
|| server->entry.flags.require_preauth) {
METHOD_DATA method_data;
@@ -1310,6 +1261,10 @@ _kdc_as_rep(krb5_context context,
method_data.val = NULL;
ret = realloc_method_data(&method_data);
+ if (ret) {
+ free_METHOD_DATA(&method_data);
+ goto out;
+ }
pa = &method_data.val[method_data.len-1];
pa->padata_type = KRB5_PADATA_ENC_TIMESTAMP;
pa->padata_value.length = 0;
@@ -1317,12 +1272,20 @@ _kdc_as_rep(krb5_context context,
#ifdef PKINIT
ret = realloc_method_data(&method_data);
+ if (ret) {
+ free_METHOD_DATA(&method_data);
+ goto out;
+ }
pa = &method_data.val[method_data.len-1];
pa->padata_type = KRB5_PADATA_PK_AS_REQ;
pa->padata_value.length = 0;
pa->padata_value.data = NULL;
ret = realloc_method_data(&method_data);
+ if (ret) {
+ free_METHOD_DATA(&method_data);
+ goto out;
+ }
pa = &method_data.val[method_data.len-1];
pa->padata_type = KRB5_PADATA_PK_AS_REQ_WIN;
pa->padata_value.length = 0;
@@ -1330,22 +1293,37 @@ _kdc_as_rep(krb5_context context,
#endif
/*
- * RFC4120 requires:
- * - If the client only knows about old enctypes, then send
- * both info replies (we send 'info' first in the list).
- * - If the client is 'modern', because it knows about 'new'
- * enctype types, then only send the 'info2' reply.
+ * If there is a client key, send ETYPE_INFO{,2}
*/
-
- /* XXX check ret */
- if (only_older_enctype_p(req))
- ret = get_pa_etype_info(context, config,
- &method_data, &client->entry,
- b->etype.val, b->etype.len);
- /* XXX check ret */
- ret = get_pa_etype_info2(context, config, &method_data,
- &client->entry, b->etype.val, b->etype.len);
-
+ if (ckey) {
+
+ /*
+ * RFC4120 requires:
+ * - If the client only knows about old enctypes, then send
+ * both info replies (we send 'info' first in the list).
+ * - If the client is 'modern', because it knows about 'new'
+ * enctype types, then only send the 'info2' reply.
+ *
+ * Before we send the full list of etype-info data, we pick
+ * the client key we would have used anyway below, just pick
+ * that instead.
+ */
+
+ if (older_enctype(ckey->key.keytype)) {
+ ret = get_pa_etype_info(context, config,
+ &method_data, ckey);
+ if (ret) {
+ free_METHOD_DATA(&method_data);
+ goto out;
+ }
+ }
+ ret = get_pa_etype_info2(context, config,
+ &method_data, ckey);
+ if (ret) {
+ free_METHOD_DATA(&method_data);
+ goto out;
+ }
+ }
ASN1_MALLOC_ENCODE(METHOD_DATA, buf, len, &method_data, &len, ret);
free_METHOD_DATA(&method_data);
@@ -1363,20 +1341,26 @@ _kdc_as_rep(krb5_context context,
}
/*
- * Find the client key (for preauth ENC-TS verification and reply
- * encryption). Then the best encryption type for the KDC and
- * last the best session key that shared between the client and
- * KDC runtime enctypes.
+ * Verify flags after the user been required to prove its identity
+ * with in a preauth mech.
*/
- ret = _kdc_find_etype(context, client, b->etype.val, b->etype.len,
- &ckey, &cetype);
- if (ret) {
- kdc_log(context, config, 0,
- "Client (%s) has no support for etypes", client_name);
+ ret = _kdc_check_flags(context, config,
+ client, client_name,
+ server, server_name,
+ TRUE);
+ if(ret)
goto out;
- }
-
+
+ ret = _kdc_windc_client_access(context, client, req, &e_data);
+ if(ret)
+ goto out;
+
+ /*
+ * Selelct the best encryption type for the KDC with out regard to
+ * the client since the client never needs to read that data.
+ */
+
ret = _kdc_get_preferred_key(context, config,
server, server_name,
&setype, &skey);
@@ -1449,12 +1433,14 @@ _kdc_as_rep(krb5_context context,
rep.pvno = 5;
rep.msg_type = krb_as_rep;
- copy_Realm(&client->entry.principal->realm, &rep.crealm);
- if (f.request_anonymous)
- _kdc_make_anonymous_principalname (&rep.cname);
- else
- _krb5_principal2principalname(&rep.cname,
- client->entry.principal);
+
+ ret = copy_Realm(&client->entry.principal->realm, &rep.crealm);
+ if (ret)
+ goto out;
+ ret = _krb5_principal2principalname(&rep.cname, client->entry.principal);
+ if (ret)
+ goto out;
+
rep.ticket.tkt_vno = 5;
copy_Realm(&server->entry.principal->realm, &rep.ticket.realm);
_krb5_principal2principalname(&rep.ticket.sname,
@@ -1500,11 +1486,12 @@ _kdc_as_rep(krb5_context context,
goto out;
}
- ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);
+ ret = copy_PrincipalName(&rep.cname, &et.cname);
+ if (ret)
+ goto out;
+ ret = copy_Realm(&rep.crealm, &et.crealm);
if (ret)
goto out;
- copy_PrincipalName(&rep.cname, &et.cname);
- copy_Realm(&rep.crealm, &et.crealm);
{
time_t start;
@@ -1568,8 +1555,6 @@ _kdc_as_rep(krb5_context context,
et.transited.tr_type = DOMAIN_X500_COMPRESS;
krb5_data_zero(&et.transited.contents);
- copy_EncryptionKey(&et.key, &ek.key);
-
/* The MIT ASN.1 library (obviously) doesn't tell lengths encoded
* as 0 and as 0x80 (meaning indefinite length) apart, and is thus
* incapable of correctly decoding SEQUENCE OF's of zero length.
@@ -1637,12 +1622,12 @@ _kdc_as_rep(krb5_context context,
rep.padata->len = 0;
rep.padata->val = NULL;
- reply_key = &ckey->key;
#if PKINIT
if (pkp) {
+ e_text = "Failed to build PK-INIT reply";
ret = _kdc_pk_mk_pa_reply(context, config, pkp, client,
- req, req_buffer,
- &reply_key, rep.padata);
+ sessionetype, req, req_buffer,
+ &reply_key, &et.key, rep.padata);
if (ret)
goto out;
ret = _kdc_add_inital_verified_cas(context,
@@ -1651,10 +1636,25 @@ _kdc_as_rep(krb5_context context,
&et);
if (ret)
goto out;
- }
+ } else
#endif
+ if (ckey) {
+ reply_key = &ckey->key;
+ ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);
+ if (ret)
+ goto out;
+ } else {
+ e_text = "Client have no reply key";
+ ret = KRB5KDC_ERR_CLIENT_NOTYET;
+ goto out;
+ }
+
+ ret = copy_EncryptionKey(&et.key, &ek.key);
+ if (ret)
+ goto out;
- set_salt_padata (rep.padata, ckey->salt);
+ if (ckey)
+ set_salt_padata (rep.padata, ckey->salt);
/* Add signing of alias referral */
if (f.canonicalize) {
diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c
index 4cf93e5a54..3abdb18ae4 100644
--- a/source4/heimdal/kdc/krb5tgs.c
+++ b/source4/heimdal/kdc/krb5tgs.c
@@ -107,7 +107,7 @@ _kdc_add_KRB5SignedPath(krb5_context context,
hdb_entry_ex *krbtgt,
krb5_enctype enctype,
krb5_const_principal server,
- KRB5SignedPathPrincipals *principals,
+ krb5_principals principals,
EncTicketPart *tkt)
{
krb5_error_code ret;
@@ -117,7 +117,7 @@ _kdc_add_KRB5SignedPath(krb5_context context,
size_t size;
if (server && principals) {
- ret = add_KRB5SignedPathPrincipals(principals, server);
+ ret = add_Principals(principals, server);
if (ret)
return ret;
}
@@ -186,7 +186,7 @@ check_KRB5SignedPath(krb5_context context,
krb5_kdc_configuration *config,
hdb_entry_ex *krbtgt,
EncTicketPart *tkt,
- KRB5SignedPathPrincipals **delegated,
+ krb5_principals *delegated,
int *signedpath)
{
krb5_error_code ret;
@@ -255,7 +255,7 @@ check_KRB5SignedPath(krb5_context context,
return ENOMEM;
}
- ret = copy_KRB5SignedPathPrincipals(*delegated, sp.delegated);
+ ret = copy_Principals(*delegated, sp.delegated);
if (ret) {
free_KRB5SignedPath(&sp);
free(*delegated);
@@ -668,7 +668,7 @@ tgs_make_reply(krb5_context context,
krb5_principal client_principal,
hdb_entry_ex *krbtgt,
krb5_enctype krbtgt_etype,
- KRB5SignedPathPrincipals *spp,
+ krb5_principals spp,
const krb5_data *rspac,
const METHOD_DATA *enc_pa_data,
const char **e_text,
@@ -725,14 +725,13 @@ tgs_make_reply(krb5_context context,
PRINCIPAL_ALLOW_DISABLE_TRANSITED_CHECK(server)) ||
GLOBAL_ALLOW_DISABLE_TRANSITED_CHECK),
&tgt->transited, &et,
- *krb5_princ_realm(context, client_principal),
- *krb5_princ_realm(context, server->entry.principal),
- *krb5_princ_realm(context, krbtgt->entry.principal));
+ krb5_principal_get_realm(context, client_principal),
+ krb5_principal_get_realm(context, server->entry.principal),
+ krb5_principal_get_realm(context, krbtgt->entry.principal));
if(ret)
goto out;
- copy_Realm(krb5_princ_realm(context, server_principal),
- &rep.ticket.realm);
+ copy_Realm(&server_principal->realm, &rep.ticket.realm);
_krb5_principal2principalname(&rep.ticket.sname, server_principal);
copy_Realm(&tgt_name->realm, &rep.crealm);
/*
@@ -888,7 +887,7 @@ tgs_make_reply(krb5_context context,
}
if (krb5_enctype_valid(context, et.key.keytype) != 0
- && _kdc_is_weak_expection(server->entry.principal, et.key.keytype))
+ && _kdc_is_weak_exception(server->entry.principal, et.key.keytype))
{
krb5_enctype_enable(context, et.key.keytype);
is_weak = 1;
@@ -1035,7 +1034,7 @@ need_referral(krb5_context context, krb5_kdc_configuration *config,
if (server->name.name_string.len == 1)
name = server->name.name_string.val[0];
- if (server->name.name_string.len > 1)
+ else if (server->name.name_string.len > 1)
name = server->name.name_string.val[1];
else
return FALSE;
@@ -1205,9 +1204,7 @@ tgs_parse_request(krb5_context context,
krb5_keyblock *subkey;
krb5_data ad;
- ret = krb5_auth_con_getremotesubkey(context,
- ac,
- &subkey);
+ ret = krb5_auth_con_getremotesubkey(context, ac, &subkey);
if(ret){
krb5_auth_con_free(context, ac);
kdc_log(context, config, 0, "Failed to get remote subkey: %s",
@@ -1232,6 +1229,7 @@ tgs_parse_request(krb5_context context,
goto out;
}
ret = krb5_crypto_init(context, subkey, 0, &crypto);
+ krb5_free_keyblock(context, subkey);
if (ret) {
krb5_auth_con_free(context, ac);
kdc_log(context, config, 0, "krb5_crypto_init failed: %s",
@@ -1251,7 +1249,6 @@ tgs_parse_request(krb5_context context,
ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; /* ? */
goto out;
}
- krb5_free_keyblock(context, subkey);
ALLOC(*auth_data);
if (*auth_data == NULL) {
krb5_auth_con_free(context, ac);
@@ -1365,8 +1362,7 @@ tgs_build_reply(krb5_context context,
const char *from,
const char **e_text,
AuthorizationData **auth_data,
- const struct sockaddr *from_addr,
- int datagram_reply)
+ const struct sockaddr *from_addr)
{
krb5_error_code ret;
krb5_principal cp = NULL, sp = NULL;
@@ -1375,13 +1371,11 @@ tgs_build_reply(krb5_context context,
hdb_entry_ex *server = NULL, *client = NULL;
krb5_realm ref_realm = NULL;
EncTicketPart *tgt = &ticket->ticket;
- KRB5SignedPathPrincipals *spp = NULL;
- Key *tkey;
+ krb5_principals spp = NULL;
const EncryptionKey *ekey;
krb5_keyblock sessionkey;
krb5_kvno kvno;
krb5_data rspac;
- int cross_realm = 0;
METHOD_DATA enc_pa_data;
@@ -1392,6 +1386,8 @@ tgs_build_reply(krb5_context context,
char opt_str[128];
int signedpath = 0;
+ Key *tkey;
+
memset(&sessionkey, 0, sizeof(sessionkey));
memset(&adtkt, 0, sizeof(adtkt));
krb5_data_zero(&rspac);
@@ -1559,8 +1555,6 @@ server_lookup:
kdc_log(context, config, 1, "Client not found in database: %s: %s",
cpn, krb5_get_err_text(context, ret));
-
- cross_realm = 1;
}
/*
@@ -1578,9 +1572,10 @@ server_lookup:
break;
if(i == b->etype.len) {
kdc_log(context, config, 0,
- "Addition ticket have not matching etypes", spp);
+ "Addition ticket have not matching etypes");
krb5_clear_error_message(context);
- return KRB5KDC_ERR_ETYPE_NOSUPP;
+ ret = KRB5KDC_ERR_ETYPE_NOSUPP;
+ goto out;
}
etype = b->etype.val[i];
kvno = 0;
@@ -1592,7 +1587,7 @@ server_lookup:
if(ret) {
kdc_log(context, config, 0,
"Server (%s) has no support for etypes", spn);
- return ret;
+ goto out;
}
ekey = &skey->key;
kvno = server->entry.kvno;
@@ -1604,10 +1599,6 @@ server_lookup:
}
/*
- * Validate authoriation data
- */
-
- /*
* Check that service is in the same realm as the krbtgt. If it's
* not the same, it's someone that is using a uni-directional trust
* backward.
@@ -1628,13 +1619,15 @@ server_lookup:
goto out;
}
- /* check PAC if there is one */
+ /*
+ * Validate authoriation data
+ */
ret = hdb_enctype2key(context, &krbtgt->entry,
krbtgt_etype, &tkey);
if(ret) {
kdc_log(context, config, 0,
- "Failed to find key for krbtgt PAC check");
+ "Failed to find key for krbtgt PAC check");
goto out;
}
@@ -1672,7 +1665,7 @@ server_lookup:
const PA_DATA *sdata;
int i = 0;
- sdata = _kdc_find_padata(req, &i, KRB5_PADATA_S4U2SELF);
+ sdata = _kdc_find_padata(req, &i, KRB5_PADATA_FOR_USER);
if (sdata) {
krb5_crypto crypto;
krb5_data datack;
@@ -2044,8 +2037,7 @@ _kdc_tgs_rep(krb5_context context,
from,
&e_text,
&auth_data,
- from_addr,
- datagram_reply);
+ from_addr);
if (ret) {
kdc_log(context, config, 0,
"Failed building TGS-REP to %s", from);
diff --git a/source4/heimdal/kdc/kx509.c b/source4/heimdal/kdc/kx509.c
index 83e05b81c5..8f7f3a27fb 100644
--- a/source4/heimdal/kdc/kx509.c
+++ b/source4/heimdal/kdc/kx509.c
@@ -36,14 +36,14 @@
#include <rfc2459_asn1.h>
#include <hx509.h>
-RCSID("$Id$");
+#ifdef KX509
/*
*
*/
krb5_error_code
-_kdc_try_kx509_request(void *ptr, size_t len, Kx509Request *req, size_t *size)
+_kdc_try_kx509_request(void *ptr, size_t len, struct Kx509Request *req, size_t *size)
{
if (len < 4)
return -1;
@@ -97,16 +97,15 @@ calculate_reply_hash(krb5_context context,
krb5_keyblock *key,
Kx509Response *rep)
{
+ krb5_error_code ret;
HMAC_CTX ctx;
HMAC_CTX_init(&ctx);
- HMAC_Init_ex(&ctx,
- key->keyvalue.data, key->keyvalue.length,
+ HMAC_Init_ex(&ctx, key->keyvalue.data, key->keyvalue.length,
EVP_sha1(), NULL);
- rep->hash->length = HMAC_size(&ctx);
- rep->hash->data = malloc(rep->hash->length);
- if (rep->hash->data == NULL) {
+ ret = krb5_data_alloc(rep->hash, HMAC_size(&ctx));
+ if (ret) {
HMAC_CTX_cleanup(&ctx);
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
@@ -208,7 +207,7 @@ build_certificate(krb5_context context,
spki.subjectPublicKey.data = key->data;
spki.subjectPublicKey.length = key->length * 8;
- ret = der_copy_oid(oid_id_pkcs1_rsaEncryption(),
+ ret = der_copy_oid(&asn1_oid_id_pkcs1_rsaEncryption,
&spki.algorithm.algorithm);
any.data = "\x05\x00";
@@ -289,7 +288,7 @@ out:
krb5_error_code
_kdc_do_kx509(krb5_context context,
krb5_kdc_configuration *config,
- const Kx509Request *req, krb5_data *reply,
+ const struct Kx509Request *req, krb5_data *reply,
const char *from, struct sockaddr *addr)
{
krb5_error_code ret;
@@ -385,8 +384,10 @@ _kdc_do_kx509(krb5_context context,
if (ret)
goto out;
free_RSAPublicKey(&key);
- if (size != req->pk_key.length)
- ;
+ if (size != req->pk_key.length) {
+ ret = ASN1_EXTRA_DATA;
+ goto out;
+ }
}
ALLOC(rep.certificate);
@@ -458,3 +459,5 @@ out:
return 0;
}
+
+#endif /* KX509 */
diff --git a/source4/heimdal/kdc/pkinit.c b/source4/heimdal/kdc/pkinit.c
index 82358682d8..22734be811 100644
--- a/source4/heimdal/kdc/pkinit.c
+++ b/source4/heimdal/kdc/pkinit.c
@@ -47,14 +47,26 @@ RCSID("$Id$");
struct pk_client_params {
enum krb5_pk_type type;
- BIGNUM *dh_public_key;
+ enum { USE_RSA, USE_DH, USE_ECDH } keyex;
+ union {
+ struct {
+ BIGNUM *public_key;
+ DH *key;
+ } dh;
+#ifdef HAVE_OPENSSL
+ struct {
+ EC_KEY *public_key;
+ EC_KEY *key;
+ } ecdh;
+#endif
+ } u;
hx509_cert cert;
unsigned nonce;
- DH *dh;
EncryptionKey reply_key;
char *dh_group_name;
hx509_peer_info peer;
hx509_certs client_anchors;
+ hx509_verify_ctx verify_ctx;
};
struct pk_principal_mapping {
@@ -155,29 +167,43 @@ out:
}
void
-_kdc_pk_free_client_param(krb5_context context,
- pk_client_params *client_params)
+_kdc_pk_free_client_param(krb5_context context, pk_client_params *cp)
{
- if (client_params->cert)
- hx509_cert_free(client_params->cert);
- if (client_params->dh)
- DH_free(client_params->dh);
- if (client_params->dh_public_key)
- BN_free(client_params->dh_public_key);
- krb5_free_keyblock_contents(context, &client_params->reply_key);
- if (client_params->dh_group_name)
- free(client_params->dh_group_name);
- if (client_params->peer)
- hx509_peer_info_free(client_params->peer);
- if (client_params->client_anchors)
- hx509_certs_free(&client_params->client_anchors);
- memset(client_params, 0, sizeof(*client_params));
- free(client_params);
+ if (cp == NULL)
+ return;
+ if (cp->cert)
+ hx509_cert_free(cp->cert);
+ if (cp->verify_ctx)
+ hx509_verify_destroy_ctx(cp->verify_ctx);
+ if (cp->keyex == USE_DH) {
+ if (cp->u.dh.key)
+ DH_free(cp->u.dh.key);
+ if (cp->u.dh.public_key)
+ BN_free(cp->u.dh.public_key);
+ }
+#ifdef HAVE_OPENSSL
+ if (cp->keyex == USE_ECDH) {
+ if (cp->u.ecdh.key)
+ EC_KEY_free(cp->u.ecdh.key);
+ if (cp->u.ecdh.public_key)
+ EC_KEY_free(cp->u.ecdh.public_key);
+ }
+#endif
+ krb5_free_keyblock_contents(context, &cp->reply_key);
+ if (cp->dh_group_name)
+ free(cp->dh_group_name);
+ if (cp->peer)
+ hx509_peer_info_free(cp->peer);
+ if (cp->client_anchors)
+ hx509_certs_free(&cp->client_anchors);
+ memset(cp, 0, sizeof(*cp));
+ free(cp);
}
static krb5_error_code
-generate_dh_keyblock(krb5_context context, pk_client_params *client_params,
- krb5_enctype enctype, krb5_keyblock *reply_key)
+generate_dh_keyblock(krb5_context context,
+ pk_client_params *client_params,
+ krb5_enctype enctype)
{
unsigned char *dh_gen_key = NULL;
krb5_keyblock key;
@@ -186,36 +212,84 @@ generate_dh_keyblock(krb5_context context, pk_client_params *client_params,
memset(&key, 0, sizeof(key));
- if (!DH_generate_key(client_params->dh)) {
- ret = KRB5KRB_ERR_GENERIC;
- krb5_set_error_message(context, ret, "Can't generate Diffie-Hellman keys");
- goto out;
- }
- if (client_params->dh_public_key == NULL) {
- ret = KRB5KRB_ERR_GENERIC;
- krb5_set_error_message(context, ret, "dh_public_key");
- goto out;
- }
+ if (client_params->keyex == USE_DH) {
- dh_gen_keylen = DH_size(client_params->dh);
- size = BN_num_bytes(client_params->dh->p);
- if (size < dh_gen_keylen)
- size = dh_gen_keylen;
+ if (client_params->u.dh.public_key == NULL) {
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret, "public_key");
+ goto out;
+ }
- dh_gen_key = malloc(size);
- if (dh_gen_key == NULL) {
- ret = ENOMEM;
- krb5_set_error_message(context, ret, "malloc: out of memory");
- goto out;
- }
- memset(dh_gen_key, 0, size - dh_gen_keylen);
+ if (!DH_generate_key(client_params->u.dh.key)) {
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret,
+ "Can't generate Diffie-Hellman keys");
+ goto out;
+ }
+
+ dh_gen_keylen = DH_size(client_params->u.dh.key);
+ size = BN_num_bytes(client_params->u.dh.key->p);
+ if (size < dh_gen_keylen)
+ size = dh_gen_keylen;
+
+ dh_gen_key = malloc(size);
+ if (dh_gen_key == NULL) {
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, "malloc: out of memory");
+ goto out;
+ }
+ memset(dh_gen_key, 0, size - dh_gen_keylen);
+
+ dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen),
+ client_params->u.dh.public_key,
+ client_params->u.dh.key);
+ if (dh_gen_keylen == -1) {
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret,
+ "Can't compute Diffie-Hellman key");
+ goto out;
+ }
+ ret = 0;
+#ifdef HAVE_OPENSSL
+ } else if (client_params->keyex == USE_ECDH) {
+
+ if (client_params->u.ecdh.public_key == NULL) {
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret, "public_key");
+ goto out;
+ }
+
+ client_params->u.ecdh.key = EC_KEY_new();
+ if (client_params->u.ecdh.key == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+ EC_KEY_set_group(client_params->u.ecdh.key,
+ EC_KEY_get0_group(client_params->u.ecdh.public_key));
- dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen),
- client_params->dh_public_key,
- client_params->dh);
- if (dh_gen_keylen == -1) {
+ if (EC_KEY_generate_key(client_params->u.ecdh.key) != 1) {
+ ret = ENOMEM;
+ goto out;
+ }
+
+ size = (EC_GROUP_get_degree(EC_KEY_get0_group(client_params->u.ecdh.key)) + 7) / 8;
+ dh_gen_key = malloc(size);
+ if (dh_gen_key == NULL) {
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret,
+ N_("malloc: out of memory", ""));
+ goto out;
+ }
+
+ dh_gen_keylen = ECDH_compute_key(dh_gen_key, size,
+ EC_KEY_get0_public_key(client_params->u.ecdh.public_key),
+ client_params->u.ecdh.key, NULL);
+ ret = 0;
+#endif /* HAVE_OPENSSL */
+ } else {
ret = KRB5KRB_ERR_GENERIC;
- krb5_set_error_message(context, ret, "Can't compute Diffie-Hellman key");
+ krb5_set_error_message(context, ret,
+ "Diffie-Hellman not selected keys");
goto out;
}
@@ -223,7 +297,7 @@ generate_dh_keyblock(krb5_context context, pk_client_params *client_params,
enctype,
dh_gen_key, dh_gen_keylen,
NULL, NULL,
- reply_key);
+ &client_params->reply_key);
out:
if (dh_gen_key)
@@ -261,10 +335,12 @@ get_dh_param(krb5_context context,
memset(&dhparam, 0, sizeof(dhparam));
- if (der_heim_oid_cmp(&dh_key_info->algorithm.algorithm, oid_id_dhpublicnumber())) {
- krb5_set_error_message(context, KRB5_BADMSGTYPE,
- "PKINIT invalid oid in clientPublicValue");
- return KRB5_BADMSGTYPE;
+ if ((dh_key_info->subjectPublicKey.length % 8) != 0) {
+ ret = KRB5_BADMSGTYPE;
+ krb5_set_error_message(context, ret,
+ "PKINIT: subjectPublicKey not aligned "
+ "to 8 bit boundary");
+ goto out;
}
if (dh_key_info->algorithm.parameters == NULL) {
@@ -284,15 +360,6 @@ get_dh_param(krb5_context context,
goto out;
}
- if ((dh_key_info->subjectPublicKey.length % 8) != 0) {
- ret = KRB5_BADMSGTYPE;
- krb5_set_error_message(context, ret,
- "PKINIT: subjectPublicKey not aligned "
- "to 8 bit boundary");
- goto out;
- }
-
-
ret = _krb5_dh_group_ok(context, config->pkinit_dh_min_bits,
&dhparam.p, &dhparam.g, &dhparam.q, moduli,
&client_params->dh_group_name);
@@ -331,17 +398,17 @@ get_dh_param(krb5_context context,
return ret;
}
- client_params->dh_public_key = integer_to_BN(context,
- "subjectPublicKey",
- &glue);
+ client_params->u.dh.public_key = integer_to_BN(context,
+ "subjectPublicKey",
+ &glue);
der_free_heim_integer(&glue);
- if (client_params->dh_public_key == NULL) {
+ if (client_params->u.dh.public_key == NULL) {
ret = KRB5_BADMSGTYPE;
goto out;
}
}
- client_params->dh = dh;
+ client_params->u.dh.key = dh;
dh = NULL;
ret = 0;
@@ -352,20 +419,88 @@ get_dh_param(krb5_context context,
return ret;
}
+#ifdef HAVE_OPENSSL
+
+static krb5_error_code
+get_ecdh_param(krb5_context context,
+ krb5_kdc_configuration *config,
+ SubjectPublicKeyInfo *dh_key_info,
+ pk_client_params *client_params)
+{
+ ECParameters ecp;
+ EC_KEY *public = NULL;
+ krb5_error_code ret;
+ const unsigned char *p;
+ size_t len;
+ int nid;
+
+ if (dh_key_info->algorithm.parameters == NULL) {
+ krb5_set_error_message(context, KRB5_BADMSGTYPE,
+ "PKINIT missing algorithm parameter "
+ "in clientPublicValue");
+ return KRB5_BADMSGTYPE;
+ }
+
+ memset(&ecp, 0, sizeof(ecp));
+
+ ret = decode_ECParameters(dh_key_info->algorithm.parameters->data,
+ dh_key_info->algorithm.parameters->length, &ecp, &len);
+ if (ret)
+ goto out;
+
+ if (ecp.element != choice_ECParameters_namedCurve) {
+ ret = KRB5_BADMSGTYPE;
+ goto out;
+ }
+
+ if (der_heim_oid_cmp(&ecp.u.namedCurve, &asn1_oid_id_ec_group_secp256r1) == 0)
+ nid = NID_X9_62_prime256v1;
+ else {
+ ret = KRB5_BADMSGTYPE;
+ goto out;
+ }
+
+ /* XXX verify group is ok */
+
+ public = EC_KEY_new_by_curve_name(nid);
+
+ p = dh_key_info->subjectPublicKey.data;
+ len = dh_key_info->subjectPublicKey.length / 8;
+ if (o2i_ECPublicKey(&public, &p, len) == NULL) {
+ ret = KRB5_BADMSGTYPE;
+ krb5_set_error_message(context, ret,
+ "PKINIT failed to decode ECDH key");
+ goto out;
+ }
+ client_params->u.ecdh.public_key = public;
+ public = NULL;
+
+ out:
+ if (public)
+ EC_KEY_free(public);
+ free_ECParameters(&ecp);
+ return ret;
+}
+
+#endif /* HAVE_OPENSSL */
+
krb5_error_code
_kdc_pk_rd_padata(krb5_context context,
krb5_kdc_configuration *config,
const KDC_REQ *req,
const PA_DATA *pa,
+ hdb_entry_ex *client,
pk_client_params **ret_params)
{
- pk_client_params *client_params;
+ pk_client_params *cp;
krb5_error_code ret;
heim_oid eContentType = { 0, NULL }, contentInfoOid = { 0, NULL };
krb5_data eContent = { 0, NULL };
krb5_data signed_content = { 0, NULL };
const char *type = "unknown type";
+ hx509_certs trust_anchors;
int have_data = 0;
+ const HDB_Ext_PKINIT_cert *pc;
*ret_params = NULL;
@@ -375,20 +510,73 @@ _kdc_pk_rd_padata(krb5_context context,
return 0;
}
- hx509_verify_set_time(kdc_identity->verify_ctx, kdc_time);
-
- client_params = calloc(1, sizeof(*client_params));
- if (client_params == NULL) {
+ cp = calloc(1, sizeof(*cp));
+ if (cp == NULL) {
krb5_clear_error_message(context);
ret = ENOMEM;
goto out;
}
+ ret = hx509_certs_init(kdc_identity->hx509ctx,
+ "MEMORY:trust-anchors",
+ 0, NULL, &trust_anchors);
+ if (ret) {
+ krb5_set_error_message(context, ret, "failed to create trust anchors");
+ goto out;
+ }
+
+ ret = hx509_certs_merge(kdc_identity->hx509ctx, trust_anchors,
+ kdc_identity->anchors);
+ if (ret) {
+ hx509_certs_free(&trust_anchors);
+ krb5_set_error_message(context, ret, "failed to create verify context");
+ goto out;
+ }
+
+ /* Add any registered certificates for this client as trust anchors */
+ ret = hdb_entry_get_pkinit_cert(&client->entry, &pc);
+ if (ret == 0 && pc != NULL) {
+ hx509_cert cert;
+ unsigned int i;
+
+ for (i = 0; i < pc->len; i++) {
+ ret = hx509_cert_init_data(kdc_identity->hx509ctx,
+ pc->val[i].cert.data,
+ pc->val[i].cert.length,
+ &cert);
+ if (ret)
+ continue;
+ hx509_certs_add(kdc_identity->hx509ctx, trust_anchors, cert);
+ hx509_cert_free(cert);
+ }
+ }
+
+ ret = hx509_verify_init_ctx(kdc_identity->hx509ctx, &cp->verify_ctx);
+ if (ret) {
+ hx509_certs_free(&trust_anchors);
+ krb5_set_error_message(context, ret, "failed to create verify context");
+ goto out;
+ }
+
+ hx509_verify_set_time(cp->verify_ctx, kdc_time);
+ hx509_verify_attach_anchors(cp->verify_ctx, trust_anchors);
+ hx509_certs_free(&trust_anchors);
+
+ if (config->pkinit_allow_proxy_certs)
+ hx509_verify_set_proxy_certificate(cp->verify_ctx, 1);
+
if (pa->padata_type == KRB5_PADATA_PK_AS_REQ_WIN) {
PA_PK_AS_REQ_Win2k r;
type = "PK-INIT-Win2k";
+ if (req->req_body.kdc_options.request_anonymous) {
+ ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED;
+ krb5_set_error_message(context, ret,
+ "Anon not supported in RSA mode");
+ goto out;
+ }
+
ret = decode_PA_PK_AS_REQ_Win2k(pa->padata_value.data,
pa->padata_value.length,
&r,
@@ -406,7 +594,7 @@ _kdc_pk_rd_padata(krb5_context context,
free_PA_PK_AS_REQ_Win2k(&r);
if (ret) {
krb5_set_error_message(context, ret,
- "Can't decode PK-AS-REQ: %d", ret);
+ "Can't unwrap ContentInfo(win): %d", ret);
goto out;
}
@@ -420,25 +608,35 @@ _kdc_pk_rd_padata(krb5_context context,
&r,
NULL);
if (ret) {
- krb5_set_error_message(context, ret, "Can't decode PK-AS-REQ: %d", ret);
+ krb5_set_error_message(context, ret,
+ "Can't decode PK-AS-REQ: %d", ret);
goto out;
}
/* XXX look at r.kdcPkId */
if (r.trustedCertifiers) {
ExternalPrincipalIdentifiers *edi = r.trustedCertifiers;
- unsigned int i;
+ unsigned int i, maxedi;
ret = hx509_certs_init(kdc_identity->hx509ctx,
"MEMORY:client-anchors",
0, NULL,
- &client_params->client_anchors);
+ &cp->client_anchors);
if (ret) {
- krb5_set_error_message(context, ret, "Can't allocate client anchors: %d", ret);
+ krb5_set_error_message(context, ret,
+ "Can't allocate client anchors: %d",
+ ret);
goto out;
}
- for (i = 0; i < edi->len; i++) {
+ /*
+ * If the client sent more then 10 EDI, don't bother
+ * looking more then 10 of performance reasons.
+ */
+ maxedi = edi->len;
+ if (maxedi > 10)
+ maxedi = 10;
+ for (i = 0; i < maxedi; i++) {
IssuerAndSerialNumber iasn;
hx509_query *q;
hx509_cert cert;
@@ -464,8 +662,10 @@ _kdc_pk_rd_padata(krb5_context context,
}
ret = hx509_query_match_issuer_serial(q, &iasn.issuer, &iasn.serialNumber);
free_IssuerAndSerialNumber(&iasn);
- if (ret)
+ if (ret) {
+ hx509_query_free(kdc_identity->hx509ctx, q);
continue;
+ }
ret = hx509_certs_find(kdc_identity->hx509ctx,
kdc_identity->certs,
@@ -475,7 +675,7 @@ _kdc_pk_rd_padata(krb5_context context,
if (ret)
continue;
hx509_certs_add(kdc_identity->hx509ctx,
- client_params->client_anchors, cert);
+ cp->client_anchors, cert);
hx509_cert_free(cert);
}
}
@@ -497,7 +697,7 @@ _kdc_pk_rd_padata(krb5_context context,
goto out;
}
- ret = der_heim_oid_cmp(&contentInfoOid, oid_id_pkcs7_signedData());
+ ret = der_heim_oid_cmp(&contentInfoOid, &asn1_oid_id_pkcs7_signedData);
if (ret != 0) {
ret = KRB5KRB_ERR_GENERIC;
krb5_set_error_message(context, ret,
@@ -514,9 +714,14 @@ _kdc_pk_rd_padata(krb5_context context,
{
hx509_certs signer_certs;
+ int flags = HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH; /* BTMM */
+
+ if (req->req_body.kdc_options.request_anonymous)
+ flags |= HX509_CMS_VS_ALLOW_ZERO_SIGNER;
ret = hx509_cms_verify_signed(kdc_identity->hx509ctx,
- kdc_identity->verify_ctx,
+ cp->verify_ctx,
+ flags,
signed_content.data,
signed_content.length,
NULL,
@@ -532,16 +737,18 @@ _kdc_pk_rd_padata(krb5_context context,
goto out;
}
- ret = hx509_get_one_cert(kdc_identity->hx509ctx, signer_certs,
- &client_params->cert);
- hx509_certs_free(&signer_certs);
+ if (signer_certs) {
+ ret = hx509_get_one_cert(kdc_identity->hx509ctx, signer_certs,
+ &cp->cert);
+ hx509_certs_free(&signer_certs);
+ }
if (ret)
goto out;
}
/* Signature is correct, now verify the signed message */
- if (der_heim_oid_cmp(&eContentType, oid_id_pkcs7_data()) != 0 &&
- der_heim_oid_cmp(&eContentType, oid_id_pkauthdata()) != 0)
+ if (der_heim_oid_cmp(&eContentType, &asn1_oid_id_pkcs7_data) != 0 &&
+ der_heim_oid_cmp(&eContentType, &asn1_oid_id_pkauthdata) != 0)
{
ret = KRB5_BADMSGTYPE;
krb5_set_error_message(context, ret, "got wrong oid for pkauthdata");
@@ -556,7 +763,8 @@ _kdc_pk_rd_padata(krb5_context context,
&ap,
NULL);
if (ret) {
- krb5_set_error_message(context, ret, "can't decode AuthPack: %d", ret);
+ krb5_set_error_message(context, ret,
+ "Can't decode AuthPack: %d", ret);
goto out;
}
@@ -568,12 +776,13 @@ _kdc_pk_rd_padata(krb5_context context,
goto out;
}
- client_params->type = PKINIT_WIN2K;
- client_params->nonce = ap.pkAuthenticator.nonce;
+ cp->type = PKINIT_WIN2K;
+ cp->nonce = ap.pkAuthenticator.nonce;
if (ap.clientPublicValue) {
ret = KRB5KRB_ERR_GENERIC;
- krb5_set_error_message(context, ret, "DH not supported for windows");
+ krb5_set_error_message(context, ret,
+ "DH not supported for windows");
goto out;
}
free_AuthPack_Win2k(&ap);
@@ -586,11 +795,21 @@ _kdc_pk_rd_padata(krb5_context context,
&ap,
NULL);
if (ret) {
- krb5_set_error_message(context, ret, "can't decode AuthPack: %d", ret);
+ krb5_set_error_message(context, ret,
+ "Can't decode AuthPack: %d", ret);
free_AuthPack(&ap);
goto out;
}
+ if (req->req_body.kdc_options.request_anonymous &&
+ ap.clientPublicValue == NULL) {
+ free_AuthPack(&ap);
+ ret = KRB5_KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED;
+ krb5_set_error_message(context, ret,
+ "Anon not supported in RSA mode");
+ goto out;
+ }
+
ret = pk_check_pkauthenticator(context,
&ap.pkAuthenticator,
req);
@@ -599,33 +818,55 @@ _kdc_pk_rd_padata(krb5_context context,
goto out;
}
- client_params->type = PKINIT_27;
- client_params->nonce = ap.pkAuthenticator.nonce;
+ cp->type = PKINIT_27;
+ cp->nonce = ap.pkAuthenticator.nonce;
if (ap.clientPublicValue) {
- ret = get_dh_param(context, config,
- ap.clientPublicValue, client_params);
+ if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_dhpublicnumber) == 0) {
+ cp->keyex = USE_DH;
+ ret = get_dh_param(context, config,
+ ap.clientPublicValue, cp);
+#ifdef HAVE_OPENSSL
+ } else if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_ecPublicKey) == 0) {
+ cp->keyex = USE_ECDH;
+ ret = get_ecdh_param(context, config,
+ ap.clientPublicValue, cp);
+#endif /* HAVE_OPENSSL */
+ } else {
+ ret = KRB5_BADMSGTYPE;
+ krb5_set_error_message(context, ret, "PKINIT unknown DH mechanism");
+ }
if (ret) {
free_AuthPack(&ap);
goto out;
}
- }
+ } else
+ cp->keyex = USE_RSA;
+ ret = hx509_peer_info_alloc(kdc_identity->hx509ctx,
+ &cp->peer);
+ if (ret) {
+ free_AuthPack(&ap);
+ goto out;
+ }
+
if (ap.supportedCMSTypes) {
- ret = hx509_peer_info_alloc(kdc_identity->hx509ctx,
- &client_params->peer);
- if (ret) {
- free_AuthPack(&ap);
- goto out;
- }
ret = hx509_peer_info_set_cms_algs(kdc_identity->hx509ctx,
- client_params->peer,
+ cp->peer,
ap.supportedCMSTypes->val,
ap.supportedCMSTypes->len);
if (ret) {
free_AuthPack(&ap);
goto out;
}
+ } else {
+ /* assume old client */
+ hx509_peer_info_add_cms_alg(kdc_identity->hx509ctx, cp->peer,
+ hx509_crypto_des_rsdi_ede3_cbc());
+ hx509_peer_info_add_cms_alg(kdc_identity->hx509ctx, cp->peer,
+ hx509_signature_rsa_with_sha1());
+ hx509_peer_info_add_cms_alg(kdc_identity->hx509ctx, cp->peer,
+ hx509_signature_sha1());
}
free_AuthPack(&ap);
} else
@@ -642,10 +883,10 @@ out:
krb5_data_free(&eContent);
der_free_oid(&eContentType);
der_free_oid(&contentInfoOid);
- if (ret)
- _kdc_pk_free_client_param(context, client_params);
- else
- *ret_params = client_params;
+ if (ret) {
+ _kdc_pk_free_client_param(context, cp);
+ } else
+ *ret_params = cp;
return ret;
}
@@ -670,11 +911,12 @@ BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer)
static krb5_error_code
pk_mk_pa_reply_enckey(krb5_context context,
krb5_kdc_configuration *config,
- pk_client_params *client_params,
+ pk_client_params *cp,
const KDC_REQ *req,
const krb5_data *req_buffer,
krb5_keyblock *reply_key,
- ContentInfo *content_info)
+ ContentInfo *content_info,
+ hx509_cert *kdc_cert)
{
const heim_oid *envelopedAlg = NULL, *sdAlg = NULL, *evAlg = NULL;
krb5_error_code ret;
@@ -685,13 +927,15 @@ pk_mk_pa_reply_enckey(krb5_context context,
krb5_data_zero(&buf);
krb5_data_zero(&signed_data);
+ *kdc_cert = NULL;
+
/*
* If the message client is a win2k-type but it send pa data
* 09-binding it expects a IETF (checksum) reply so there can be
* no replay attacks.
*/
- switch (client_params->type) {
+ switch (cp->type) {
case PKINIT_WIN2K: {
int i = 0;
if (_kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_09_BINDING) == NULL
@@ -699,14 +943,14 @@ pk_mk_pa_reply_enckey(krb5_context context,
{
do_win2k = 1;
}
- sdAlg = oid_id_pkcs7_data();
- evAlg = oid_id_pkcs7_data();
- envelopedAlg = oid_id_rsadsi_des_ede3_cbc();
+ sdAlg = &asn1_oid_id_pkcs7_data;
+ evAlg = &asn1_oid_id_pkcs7_data;
+ envelopedAlg = &asn1_oid_id_rsadsi_des_ede3_cbc;
break;
}
case PKINIT_27:
- sdAlg = oid_id_pkrkeydata();
- evAlg = oid_id_pkcs7_signedData();
+ sdAlg = &asn1_oid_id_pkrkeydata;
+ evAlg = &asn1_oid_id_pkcs7_signedData;
break;
default:
krb5_abortx(context, "internal pkinit error");
@@ -721,7 +965,7 @@ pk_mk_pa_reply_enckey(krb5_context context,
krb5_clear_error_message(context);
goto out;
}
- kp.nonce = client_params->nonce;
+ kp.nonce = cp->nonce;
ASN1_MALLOC_ENCODE(ReplyKeyPack_Win2k,
buf.data, buf.length,
@@ -777,7 +1021,8 @@ pk_mk_pa_reply_enckey(krb5_context context,
goto out;
hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
- hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
+ if (config->pkinit_kdc_friendly_name)
+ hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name);
ret = hx509_certs_find(kdc_identity->hx509ctx,
kdc_identity->certs,
@@ -794,19 +1039,19 @@ pk_mk_pa_reply_enckey(krb5_context context,
buf.length,
NULL,
cert,
- client_params->peer,
- client_params->client_anchors,
+ cp->peer,
+ cp->client_anchors,
kdc_identity->certpool,
&signed_data);
- hx509_cert_free(cert);
+ *kdc_cert = cert;
}
krb5_data_free(&buf);
if (ret)
goto out;
- if (client_params->type == PKINIT_WIN2K) {
- ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(),
+ if (cp->type == PKINIT_WIN2K) {
+ ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_signedData,
&signed_data,
&buf);
if (ret)
@@ -816,8 +1061,8 @@ pk_mk_pa_reply_enckey(krb5_context context,
}
ret = hx509_cms_envelope_1(kdc_identity->hx509ctx,
- 0,
- client_params->cert,
+ HX509_CMS_EV_NO_KU_CHECK,
+ cp->cert,
signed_data.data, signed_data.length,
envelopedAlg,
evAlg, &buf);
@@ -826,9 +1071,14 @@ pk_mk_pa_reply_enckey(krb5_context context,
ret = _krb5_pk_mk_ContentInfo(context,
&buf,
- oid_id_pkcs7_envelopedData(),
+ &asn1_oid_id_pkcs7_envelopedData,
content_info);
out:
+ if (ret && *kdc_cert) {
+ hx509_cert_free(*kdc_cert);
+ *kdc_cert = NULL;
+ }
+
krb5_data_free(&buf);
krb5_data_free(&signed_data);
return ret;
@@ -840,9 +1090,8 @@ out:
static krb5_error_code
pk_mk_pa_reply_dh(krb5_context context,
- DH *kdc_dh,
- pk_client_params *client_params,
- krb5_keyblock *reply_key,
+ krb5_kdc_configuration *config,
+ pk_client_params *cp,
ContentInfo *content_info,
hx509_cert *kdc_cert)
{
@@ -850,33 +1099,63 @@ pk_mk_pa_reply_dh(krb5_context context,
krb5_data signed_data, buf;
ContentInfo contentinfo;
krb5_error_code ret;
+ hx509_cert cert;
+ hx509_query *q;
size_t size;
- heim_integer i;
memset(&contentinfo, 0, sizeof(contentinfo));
memset(&dh_info, 0, sizeof(dh_info));
- krb5_data_zero(&buf);
krb5_data_zero(&signed_data);
+ krb5_data_zero(&buf);
*kdc_cert = NULL;
- ret = BN_to_integer(context, kdc_dh->pub_key, &i);
- if (ret)
- return ret;
+ if (cp->keyex == USE_DH) {
+ DH *kdc_dh = cp->u.dh.key;
+ heim_integer i;
- ASN1_MALLOC_ENCODE(DHPublicKey, buf.data, buf.length, &i, &size, ret);
- if (ret) {
- krb5_set_error_message(context, ret, "ASN.1 encoding of "
- "DHPublicKey failed (%d)", ret);
- return ret;
- }
- if (buf.length != size)
- krb5_abortx(context, "Internal ASN.1 encoder error");
-
- dh_info.subjectPublicKey.length = buf.length * 8;
- dh_info.subjectPublicKey.data = buf.data;
+ ret = BN_to_integer(context, kdc_dh->pub_key, &i);
+ if (ret)
+ return ret;
+
+ ASN1_MALLOC_ENCODE(DHPublicKey, buf.data, buf.length, &i, &size, ret);
+ der_free_heim_integer(&i);
+ if (ret) {
+ krb5_set_error_message(context, ret, "ASN.1 encoding of "
+ "DHPublicKey failed (%d)", ret);
+ return ret;
+ }
+ if (buf.length != size)
+ krb5_abortx(context, "Internal ASN.1 encoder error");
+
+ dh_info.subjectPublicKey.length = buf.length * 8;
+ dh_info.subjectPublicKey.data = buf.data;
+ krb5_data_zero(&buf);
+#ifdef HAVE_OPENSSL
+ } else if (cp->keyex == USE_ECDH) {
+ unsigned char *p;
+ int len;
+
+ len = i2o_ECPublicKey(cp->u.ecdh.key, NULL);
+ if (len <= 0)
+ abort();
+
+ p = malloc(len);
+ if (p == NULL)
+ abort();
+
+ dh_info.subjectPublicKey.length = len * 8;
+ dh_info.subjectPublicKey.data = p;
+
+ len = i2o_ECPublicKey(cp->u.ecdh.key, &p);
+ if (len <= 0)
+ abort();
+#endif
+ } else
+ krb5_abortx(context, "no keyex selected ?");
- dh_info.nonce = client_params->nonce;
+
+ dh_info.nonce = cp->nonce;
ASN1_MALLOC_ENCODE(KDCDHKeyInfo, buf.data, buf.length, &dh_info, &size,
ret);
@@ -893,44 +1172,42 @@ pk_mk_pa_reply_dh(krb5_context context,
* filled in above
*/
- {
- hx509_query *q;
- hx509_cert cert;
-
- ret = hx509_query_alloc(kdc_identity->hx509ctx, &q);
- if (ret)
- goto out;
-
- hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
- hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
-
- ret = hx509_certs_find(kdc_identity->hx509ctx,
- kdc_identity->certs,
- q,
- &cert);
- hx509_query_free(kdc_identity->hx509ctx, q);
- if (ret)
- goto out;
-
- ret = hx509_cms_create_signed_1(kdc_identity->hx509ctx,
- 0,
- oid_id_pkdhkeydata(),
- buf.data,
- buf.length,
- NULL,
- cert,
- client_params->peer,
- client_params->client_anchors,
- kdc_identity->certpool,
- &signed_data);
- *kdc_cert = cert;
- }
+ ret = hx509_query_alloc(kdc_identity->hx509ctx, &q);
+ if (ret)
+ goto out;
+
+ hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
+ if (config->pkinit_kdc_friendly_name)
+ hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name);
+
+ ret = hx509_certs_find(kdc_identity->hx509ctx,
+ kdc_identity->certs,
+ q,
+ &cert);
+ hx509_query_free(kdc_identity->hx509ctx, q);
if (ret)
goto out;
+
+ ret = hx509_cms_create_signed_1(kdc_identity->hx509ctx,
+ 0,
+ &asn1_oid_id_pkdhkeydata,
+ buf.data,
+ buf.length,
+ NULL,
+ cert,
+ cp->peer,
+ cp->client_anchors,
+ kdc_identity->certpool,
+ &signed_data);
+ if (ret) {
+ kdc_log(context, config, 0, "Failed signing the DH* reply: %d", ret);
+ goto out;
+ }
+ *kdc_cert = cert;
ret = _krb5_pk_mk_ContentInfo(context,
&signed_data,
- oid_id_pkcs7_signedData(),
+ &asn1_oid_id_pkcs7_signedData,
content_info);
if (ret)
goto out;
@@ -955,11 +1232,13 @@ pk_mk_pa_reply_dh(krb5_context context,
krb5_error_code
_kdc_pk_mk_pa_reply(krb5_context context,
krb5_kdc_configuration *config,
- pk_client_params *client_params,
+ pk_client_params *cp,
const hdb_entry_ex *client,
+ krb5_enctype sessionetype,
const KDC_REQ *req,
const krb5_data *req_buffer,
krb5_keyblock **reply_key,
+ krb5_keyblock *sessionkey,
METHOD_DATA *md)
{
krb5_error_code ret;
@@ -989,7 +1268,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
} else
enctype = ETYPE_DES3_CBC_SHA1;
- if (client_params->type == PKINIT_27) {
+ if (cp->type == PKINIT_27) {
PA_PK_AS_REP rep;
const char *type, *other = "";
@@ -997,7 +1276,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
pa_type = KRB5_PADATA_PK_AS_REP;
- if (client_params->dh == NULL) {
+ if (cp->keyex == USE_RSA) {
ContentInfo info;
type = "enckey";
@@ -1005,18 +1284,19 @@ _kdc_pk_mk_pa_reply(krb5_context context,
rep.element = choice_PA_PK_AS_REP_encKeyPack;
ret = krb5_generate_random_keyblock(context, enctype,
- &client_params->reply_key);
+ &cp->reply_key);
if (ret) {
free_PA_PK_AS_REP(&rep);
goto out;
}
ret = pk_mk_pa_reply_enckey(context,
config,
- client_params,
+ cp,
req,
req_buffer,
- &client_params->reply_key,
- &info);
+ &cp->reply_key,
+ &info,
+ &kdc_cert);
if (ret) {
free_PA_PK_AS_REP(&rep);
goto out;
@@ -1034,32 +1314,52 @@ _kdc_pk_mk_pa_reply(krb5_context context,
if (rep.u.encKeyPack.length != size)
krb5_abortx(context, "Internal ASN.1 encoder error");
+ ret = krb5_generate_random_keyblock(context, sessionetype,
+ sessionkey);
+ if (ret) {
+ free_PA_PK_AS_REP(&rep);
+ goto out;
+ }
+
} else {
ContentInfo info;
- type = "dh";
- if (client_params->dh_group_name)
- other = client_params->dh_group_name;
+ switch (cp->keyex) {
+ case USE_DH: type = "dh"; break;
+#ifdef HAVE_OPENSSL
+ case USE_ECDH: type = "ecdh"; break;
+#endif
+ default: krb5_abortx(context, "unknown keyex"); break;
+ }
+
+ if (cp->dh_group_name)
+ other = cp->dh_group_name;
rep.element = choice_PA_PK_AS_REP_dhInfo;
- ret = generate_dh_keyblock(context, client_params, enctype,
- &client_params->reply_key);
+ ret = generate_dh_keyblock(context, cp, enctype);
if (ret)
return ret;
- ret = pk_mk_pa_reply_dh(context, client_params->dh,
- client_params,
- &client_params->reply_key,
+ ret = pk_mk_pa_reply_dh(context, config,
+ cp,
&info,
&kdc_cert);
+ if (ret) {
+ free_PA_PK_AS_REP(&rep);
+ krb5_set_error_message(context, ret,
+ "create pa-reply-dh "
+ "failed %d", ret);
+ goto out;
+ }
ASN1_MALLOC_ENCODE(ContentInfo, rep.u.dhInfo.dhSignedData.data,
rep.u.dhInfo.dhSignedData.length, &info, &size,
ret);
free_ContentInfo(&info);
if (ret) {
- krb5_set_error_message(context, ret, "encoding of Key ContentInfo "
+ krb5_set_error_message(context, ret,
+ "encoding of Key ContentInfo "
"failed %d", ret);
free_PA_PK_AS_REP(&rep);
goto out;
@@ -1067,17 +1367,23 @@ _kdc_pk_mk_pa_reply(krb5_context context,
if (rep.u.encKeyPack.length != size)
krb5_abortx(context, "Internal ASN.1 encoder error");
- }
- if (ret) {
- free_PA_PK_AS_REP(&rep);
- goto out;
+ /* XXX KRB-FX-CF2 */
+ ret = krb5_generate_random_keyblock(context, sessionetype,
+ sessionkey);
+ if (ret) {
+ free_PA_PK_AS_REP(&rep);
+ goto out;
+ }
+
+ /* XXX Add PA-PKINIT-KX */
+
}
ASN1_MALLOC_ENCODE(PA_PK_AS_REP, buf, len, &rep, &size, ret);
free_PA_PK_AS_REP(&rep);
if (ret) {
- krb5_set_error_message(context, ret, "encode PA-PK-AS-REP failed %d",
- ret);
+ krb5_set_error_message(context, ret,
+ "encode PA-PK-AS-REP failed %d", ret);
goto out;
}
if (len != size)
@@ -1085,13 +1391,14 @@ _kdc_pk_mk_pa_reply(krb5_context context,
kdc_log(context, config, 0, "PK-INIT using %s %s", type, other);
- } else if (client_params->type == PKINIT_WIN2K) {
+ } else if (cp->type == PKINIT_WIN2K) {
PA_PK_AS_REP_Win2k rep;
ContentInfo info;
- if (client_params->dh) {
+ if (cp->keyex != USE_RSA) {
ret = KRB5KRB_ERR_GENERIC;
- krb5_set_error_message(context, ret, "Windows PK-INIT doesn't support DH");
+ krb5_set_error_message(context, ret,
+ "Windows PK-INIT doesn't support DH");
goto out;
}
@@ -1101,18 +1408,19 @@ _kdc_pk_mk_pa_reply(krb5_context context,
rep.element = choice_PA_PK_AS_REP_encKeyPack;
ret = krb5_generate_random_keyblock(context, enctype,
- &client_params->reply_key);
+ &cp->reply_key);
if (ret) {
free_PA_PK_AS_REP_Win2k(&rep);
goto out;
}
ret = pk_mk_pa_reply_enckey(context,
config,
- client_params,
+ cp,
req,
req_buffer,
- &client_params->reply_key,
- &info);
+ &cp->reply_key,
+ &info,
+ &kdc_cert);
if (ret) {
free_PA_PK_AS_REP_Win2k(&rep);
goto out;
@@ -1140,13 +1448,19 @@ _kdc_pk_mk_pa_reply(krb5_context context,
if (len != size)
krb5_abortx(context, "Internal ASN.1 encoder error");
+ ret = krb5_generate_random_keyblock(context, sessionetype,
+ sessionkey);
+ if (ret)
+ goto out;
+
} else
krb5_abortx(context, "PK-INIT internal error");
ret = krb5_padata_add(context, md, pa_type, buf, len);
if (ret) {
- krb5_set_error_message(context, ret, "failed adding PA-PK-AS-REP %d", ret);
+ krb5_set_error_message(context, ret,
+ "Failed adding PA-PK-AS-REP %d", ret);
free(buf);
goto out;
}
@@ -1232,7 +1546,7 @@ out:
hx509_cert_free(kdc_cert);
if (ret == 0)
- *reply_key = &client_params->reply_key;
+ *reply_key = &cp->reply_key;
return ret;
}
@@ -1250,7 +1564,7 @@ match_rfc_san(krb5_context context,
ret = hx509_cert_find_subjectAltName_otherName(hx509ctx,
client_cert,
- oid_id_pkinit_san(),
+ &asn1_oid_id_pkinit_san,
&list);
if (ret)
goto out;
@@ -1311,7 +1625,7 @@ match_ms_upn_san(krb5_context context,
ret = hx509_cert_find_subjectAltName_otherName(hx509ctx,
client_cert,
- oid_id_pkinit_ms_san(),
+ &asn1_oid_id_pkinit_ms_san,
&list);
if (ret)
goto out;
@@ -1363,16 +1677,25 @@ krb5_error_code
_kdc_pk_check_client(krb5_context context,
krb5_kdc_configuration *config,
const hdb_entry_ex *client,
- pk_client_params *client_params,
+ pk_client_params *cp,
char **subject_name)
{
const HDB_Ext_PKINIT_acl *acl;
+ const HDB_Ext_PKINIT_cert *pc;
krb5_error_code ret;
hx509_name name;
int i;
+ if (cp->cert == NULL) {
+
+ *subject_name = strdup("anonymous client client");
+ if (*subject_name == NULL)
+ return ENOMEM;
+ return 0;
+ }
+
ret = hx509_cert_get_base_subject(kdc_identity->hx509ctx,
- client_params->cert,
+ cp->cert,
&name);
if (ret)
return ret;
@@ -1386,10 +1709,33 @@ _kdc_pk_check_client(krb5_context context,
"Trying to authorize PK-INIT subject DN %s",
*subject_name);
+ ret = hdb_entry_get_pkinit_cert(&client->entry, &pc);
+ if (ret == 0 && pc) {
+ hx509_cert cert;
+ unsigned int i;
+
+ for (i = 0; i < pc->len; i++) {
+ ret = hx509_cert_init_data(kdc_identity->hx509ctx,
+ pc->val[i].cert.data,
+ pc->val[i].cert.length,
+ &cert);
+ if (ret)
+ continue;
+ ret = hx509_cert_cmp(cert, cp->cert);
+ hx509_cert_free(cert);
+ if (ret == 0) {
+ kdc_log(context, config, 5,
+ "Found matching PK-INIT cert in hdb");
+ return 0;
+ }
+ }
+ }
+
+
if (config->pkinit_princ_in_cert) {
ret = match_rfc_san(context, config,
kdc_identity->hx509ctx,
- client_params->cert,
+ cp->cert,
client->entry.principal);
if (ret == 0) {
kdc_log(context, config, 5,
@@ -1398,7 +1744,7 @@ _kdc_pk_check_client(krb5_context context,
}
ret = match_ms_upn_san(context, config,
kdc_identity->hx509ctx,
- client_params->cert,
+ cp->cert,
client->entry.principal);
if (ret == 0) {
kdc_log(context, config, 5,
@@ -1493,7 +1839,7 @@ add_principal_mapping(krb5_context context,
krb5_error_code
_kdc_add_inital_verified_cas(krb5_context context,
krb5_kdc_configuration *config,
- pk_client_params *params,
+ pk_client_params *cp,
EncTicketPart *tkt)
{
AD_INITIAL_VERIFIED_CAS cas;
@@ -1594,6 +1940,7 @@ _kdc_pk_initialize(krb5_context context,
ret = _krb5_pk_load_id(context,
&kdc_identity,
+ 0,
user_id,
anchors,
pool,
@@ -1618,7 +1965,8 @@ _kdc_pk_initialize(krb5_context context,
}
hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
- hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
+ if (config->pkinit_kdc_friendly_name)
+ hx509_query_match_friendly_name(q, config->pkinit_kdc_friendly_name);
ret = hx509_certs_find(kdc_identity->hx509ctx,
kdc_identity->certs,
@@ -1627,23 +1975,30 @@ _kdc_pk_initialize(krb5_context context,
hx509_query_free(kdc_identity->hx509ctx, q);
if (ret == 0) {
if (hx509_cert_check_eku(kdc_identity->hx509ctx, cert,
- oid_id_pkkdcekuoid(), 0))
- krb5_warnx(context, "WARNING Found KDC certificate "
+ &asn1_oid_id_pkkdcekuoid, 0)) {
+ hx509_name name;
+ char *str;
+ ret = hx509_cert_get_subject(cert, &name);
+ hx509_name_to_string(name, &str);
+ krb5_warnx(context, "WARNING Found KDC certificate (%s)"
"is missing the PK-INIT KDC EKU, this is bad for "
- "interoperability.");
+ "interoperability.", str);
+ hx509_name_free(&name);
+ free(str);
+ }
hx509_cert_free(cert);
} else
krb5_warnx(context, "PKINIT: failed to find a signing "
"certifiate with a public key");
}
- ret = krb5_config_get_bool_default(context,
- NULL,
- FALSE,
- "kdc",
- "pkinit_allow_proxy_certificate",
- NULL);
- _krb5_pk_allow_proxy_certificate(kdc_identity, ret);
+ if (krb5_config_get_bool_default(context,
+ NULL,
+ FALSE,
+ "kdc",
+ "pkinit_allow_proxy_certificate",
+ NULL))
+ config->pkinit_allow_proxy_certs = 1;
file = krb5_config_get_string(context,
NULL,
diff --git a/source4/heimdal/kdc/process.c b/source4/heimdal/kdc/process.c
index a27911914b..d3557ee6c9 100644
--- a/source4/heimdal/kdc/process.c
+++ b/source4/heimdal/kdc/process.c
@@ -34,8 +34,6 @@
#include "kdc_locl.h"
-RCSID("$Id$");
-
/*
*
*/
@@ -49,6 +47,209 @@ krb5_kdc_update_time(struct timeval *tv)
_kdc_now = *tv;
}
+static krb5_error_code
+kdc_as_req(krb5_context context,
+ krb5_kdc_configuration *config,
+ krb5_data *req_buffer,
+ krb5_data *reply,
+ const char *from,
+ struct sockaddr *addr,
+ int datagram_reply,
+ int *claim)
+{
+ krb5_error_code ret;
+ KDC_REQ req;
+ size_t len;
+
+ ret = decode_AS_REQ(req_buffer->data, req_buffer->length, &req, &len);
+ if (ret)
+ return ret;
+
+ *claim = 1;
+
+ ret = _kdc_as_rep(context, config, &req, req_buffer,
+ reply, from, addr, datagram_reply);
+ free_AS_REQ(&req);
+ return ret;
+}
+
+
+static krb5_error_code
+kdc_tgs_req(krb5_context context,
+ krb5_kdc_configuration *config,
+ krb5_data *req_buffer,
+ krb5_data *reply,
+ const char *from,
+ struct sockaddr *addr,
+ int datagram_reply,
+ int *claim)
+{
+ krb5_error_code ret;
+ KDC_REQ req;
+ size_t len;
+
+ ret = decode_TGS_REQ(req_buffer->data, req_buffer->length, &req, &len);
+ if (ret)
+ return ret;
+
+ *claim = 1;
+
+ ret = _kdc_tgs_rep(context, config, &req, reply,
+ from, addr, datagram_reply);
+ free_TGS_REQ(&req);
+ return ret;
+}
+
+#ifdef DIGEST
+
+static krb5_error_code
+kdc_digest(krb5_context context,
+ krb5_kdc_configuration *config,
+ krb5_data *req_buffer,
+ krb5_data *reply,
+ const char *from,
+ struct sockaddr *addr,
+ int datagram_reply,
+ int *claim)
+{
+ DigestREQ digestreq;
+ krb5_error_code ret;
+ size_t len;
+
+ ret = decode_DigestREQ(req_buffer->data, req_buffer->length,
+ &digestreq, &len);
+ if (ret)
+ return ret;
+
+ *claim = 1;
+
+ ret = _kdc_do_digest(context, config, &digestreq, reply, from, addr);
+ free_DigestREQ(&digestreq);
+ return ret;
+}
+
+#endif
+
+#ifdef KX509
+
+static krb5_error_code
+kdc_kx509(krb5_context context,
+ krb5_kdc_configuration *config,
+ krb5_data *req_buffer,
+ krb5_data *reply,
+ const char *from,
+ struct sockaddr *addr,
+ int datagram_reply,
+ int *claim)
+{
+ Kx509Request kx509req;
+ krb5_error_code ret;
+ size_t len;
+
+ ret = _kdc_try_kx509_request(req_buffer->data, req_buffer->length,
+ &kx509req, &len);
+ if (ret)
+ return ret;
+
+ *claim = 1;
+
+ ret = _kdc_do_kx509(context, config, &kx509req, reply, from, addr);
+ free_Kx509Request(&kx509req);
+ return ret;
+}
+
+#endif
+
+
+#ifdef KRB4
+
+static krb5_error_code
+kdc_524(krb5_context context,
+ krb5_kdc_configuration *config,
+ krb5_data *req_buffer,
+ krb5_data *reply,
+ const char *from,
+ struct sockaddr *addr,
+ int datagram_reply,
+ int *claim)
+{
+ krb5_error_code ret;
+ Ticket ticket;
+ size_t len;
+
+ ret = decode_Ticket(req_buffer->data, req_buffer->length, &ticket, &len);
+ if (ret)
+ return ret;
+
+ *claim = 1;
+
+ ret = _kdc_do_524(context, config, &ticket, reply, from, addr);
+ free_Ticket(&ticket);
+ return ret;
+}
+
+static krb5_error_code
+kdc_krb4(krb5_context context,
+ krb5_kdc_configuration *config,
+ krb5_data *req_buffer,
+ krb5_data *reply,
+ const char *from,
+ struct sockaddr *addr,
+ int datagram_reply,
+ int *claim)
+{
+ if (_kdc_maybe_version4(req_buffer->data, req_buffer->length) == 0)
+ return -1;
+
+ *claim = 1;
+
+ return _kdc_do_version4(context, config,
+ req_buffer->data, req_buffer->length,
+ reply, from,
+ (struct sockaddr_in*)addr);
+}
+
+static krb5_error_code
+kdc_kaserver(krb5_context context,
+ krb5_kdc_configuration *config,
+ krb5_data *req_buffer,
+ krb5_data *reply,
+ const char *from,
+ struct sockaddr *addr,
+ int datagram_reply,
+ int *claim)
+{
+ if (config->enable_kaserver == 0)
+ return -1;
+
+ *claim = 1;
+
+ return _kdc_do_kaserver(context, config,
+ req_buffer->data, req_buffer->length,
+ reply, from,
+ (struct sockaddr_in*)addr);
+}
+
+#endif /* KRB4 */
+
+
+static struct krb5_kdc_service services[] = {
+ { KS_KRB5, kdc_as_req },
+ { KS_KRB5, kdc_tgs_req },
+#ifdef DIGEST
+ { 0, kdc_digest },
+#endif
+#ifdef KX509
+ { 0, kdc_kx509 },
+#endif
+#ifdef KRB4
+ { 0, kdc_524 },
+ { KS_NO_LENGTH, kdc_krb4 },
+ { 0, kdc_kaserver },
+#endif
+ { 0, NULL }
+};
+
/*
* handle the request in `buf, len', from `addr' (or `from' as a string),
* sending a reply in `reply'.
@@ -65,50 +266,25 @@ krb5_kdc_process_request(krb5_context context,
struct sockaddr *addr,
int datagram_reply)
{
- KDC_REQ req;
- Ticket ticket;
- DigestREQ digestreq;
- Kx509Request kx509req;
krb5_error_code ret;
- size_t i;
-
- if(decode_AS_REQ(buf, len, &req, &i) == 0){
- krb5_data req_buffer;
+ unsigned int i;
+ krb5_data req_buffer;
+ int claim = 0;
+
+ req_buffer.data = buf;
+ req_buffer.length = len;
- req_buffer.data = buf;
- req_buffer.length = len;
-
- ret = _kdc_as_rep(context, config, &req, &req_buffer,
- reply, from, addr, datagram_reply);
- free_AS_REQ(&req);
- return ret;
- }else if(decode_TGS_REQ(buf, len, &req, &i) == 0){
- ret = _kdc_tgs_rep(context, config, &req, reply, from, addr, datagram_reply);
- free_TGS_REQ(&req);
- return ret;
- }else if(decode_Ticket(buf, len, &ticket, &i) == 0){
- ret = _kdc_do_524(context, config, &ticket, reply, from, addr);
- free_Ticket(&ticket);
- return ret;
- }else if(decode_DigestREQ(buf, len, &digestreq, &i) == 0){
- ret = _kdc_do_digest(context, config, &digestreq, reply, from, addr);
- free_DigestREQ(&digestreq);
- return ret;
- } else if (_kdc_try_kx509_request(buf, len, &kx509req, &i) == 0) {
- ret = _kdc_do_kx509(context, config, &kx509req, reply, from, addr);
- free_Kx509Request(&kx509req);
- return ret;
- } else if(_kdc_maybe_version4(buf, len)){
- *prependlength = FALSE; /* elbitapmoc sdrawkcab XXX */
- ret = _kdc_do_version4(context, config, buf, len, reply, from,
- (struct sockaddr_in*)addr);
- return ret;
- } else if (config->enable_kaserver) {
- ret = _kdc_do_kaserver(context, config, buf, len, reply, from,
- (struct sockaddr_in*)addr);
- return ret;
+ for (i = 0; services[i].process != NULL; i++) {
+ ret = (*services[i].process)(context, config, &req_buffer,
+ reply, from, addr, datagram_reply,
+ &claim);
+ if (claim) {
+ if (services[i].flags & KS_NO_LENGTH)
+ *prependlength = 0;
+ return ret;
+ }
}
-
+
return -1;
}
@@ -129,25 +305,24 @@ krb5_kdc_process_krb5_request(krb5_context context,
struct sockaddr *addr,
int datagram_reply)
{
- KDC_REQ req;
krb5_error_code ret;
- size_t i;
+ unsigned int i;
+ krb5_data req_buffer;
+ int claim = 0;
+
+ req_buffer.data = buf;
+ req_buffer.length = len;
- if(decode_AS_REQ(buf, len, &req, &i) == 0){
- krb5_data req_buffer;
-
- req_buffer.data = buf;
- req_buffer.length = len;
-
- ret = _kdc_as_rep(context, config, &req, &req_buffer,
- reply, from, addr, datagram_reply);
- free_AS_REQ(&req);
- return ret;
- }else if(decode_TGS_REQ(buf, len, &req, &i) == 0){
- ret = _kdc_tgs_rep(context, config, &req, reply, from, addr, datagram_reply);
- free_TGS_REQ(&req);
- return ret;
+ for (i = 0; services[i].process != NULL; i++) {
+ if ((services[i].flags & KS_KRB5) == 0)
+ continue;
+ ret = (*services[i].process)(context, config, &req_buffer,
+ reply, from, addr, datagram_reply,
+ &claim);
+ if (claim)
+ return ret;
}
+
return -1;
}
diff --git a/source4/heimdal/kpasswd/kpasswd.c b/source4/heimdal/kpasswd/kpasswd.c
index f67130a052..c2f980b25f 100644
--- a/source4/heimdal/kpasswd/kpasswd.c
+++ b/source4/heimdal/kpasswd/kpasswd.c
@@ -153,9 +153,9 @@ main (int argc, char **argv)
if (ret)
krb5_err (context, 1, ret, "krb5_cc_resolve");
} else {
- ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &id);
+ ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &id);
if (ret)
- krb5_err (context, 1, ret, "krb5_cc_gen_new");
+ krb5_err (context, 1, ret, "krb5_cc_new_unique");
}
if (cred_cache_str == NULL) {
diff --git a/source4/heimdal/kuser/kinit.c b/source4/heimdal/kuser/kinit.c
index fbb2d2287b..350988dbac 100644
--- a/source4/heimdal/kuser/kinit.c
+++ b/source4/heimdal/kuser/kinit.c
@@ -32,11 +32,19 @@
*/
#include "kuser_locl.h"
-RCSID("$Id$");
+#ifndef HEIMDAL_SMALLER
#include "krb5-v4compat.h"
+#endif
+
+struct krb5_dh_moduli;
+struct AlgorithmIdentifier;
+struct _krb5_krb_auth_data;
+#include <krb5-private.h>
+#ifndef NO_NTLM
#include "heimntlm.h"
+#endif
int forwardable_flag = -1;
int proxiable_flag = -1;
@@ -54,6 +62,7 @@ char *renew_life = NULL;
char *server_str = NULL;
char *cred_cache = NULL;
char *start_str = NULL;
+static int switch_cache_flags = 1;
struct getarg_strings etype_str;
int use_keytab = 0;
char *keytab_str = NULL;
@@ -66,13 +75,17 @@ static char *krb4_cc_name;
int fcache_version;
char *password_file = NULL;
char *pk_user_id = NULL;
+int pk_enterprise_flag = 0;
char *pk_x509_anchors = NULL;
int pk_use_enckey = 0;
static int canonicalize_flag = 0;
+static int enterprise_flag = 0;
static int ok_as_delegate_flag = 0;
static int use_referrals_flag = 0;
static int windows_flag = 0;
+#ifndef NO_NTLM
static char *ntlm_domain;
+#endif
static struct getargs args[] = {
@@ -154,7 +167,13 @@ static struct getargs args[] = {
{ "canonicalize",0, arg_flag, &canonicalize_flag,
NP_("canonicalize client principal", "") },
+
+ { "enterprise",0, arg_flag, &enterprise_flag,
+ NP_("parse principal as a KRB5-NT-ENTERPRISE name", "") },
#ifdef PKINIT
+ { "pk-enterprise", 0, arg_flag, &pk_enterprise_flag,
+ NP_("use enterprise name from certificate", "") },
+
{ "pk-user", 'C', arg_string, &pk_user_id,
NP_("principal's public/private/certificate identifier", ""), "id" },
@@ -164,8 +183,13 @@ static struct getargs args[] = {
{ "pk-use-enckey", 0, arg_flag, &pk_use_enckey,
NP_("Use RSA encrypted reply (instead of DH)", "") },
#endif
+#ifndef NO_NTLM
{ "ntlm-domain", 0, arg_string, &ntlm_domain,
NP_("NTLM domain", ""), "domain" },
+#endif
+
+ { "change-default", 0, arg_negative_flag, &switch_cache_flags,
+ NP_("switch the default cache to the new credentials cache", "") },
{ "ok-as-delegate", 0, arg_flag, &ok_as_delegate_flag,
NP_("honor ok-as-delegate on tickets", "") },
@@ -198,13 +222,13 @@ get_server(krb5_context context,
const char *server,
krb5_principal *princ)
{
- krb5_realm *client_realm;
+ krb5_const_realm realm;
if(server)
return krb5_parse_name(context, server, princ);
- client_realm = krb5_princ_realm (context, client);
- return krb5_make_principal(context, princ, *client_realm,
- KRB5_TGS_NAME, *client_realm, NULL);
+ realm = krb5_principal_get_realm(context, client);
+ return krb5_make_principal(context, princ, realm,
+ KRB5_TGS_NAME, realm, NULL);
}
#ifndef HEIMDAL_SMALLER
@@ -301,7 +325,7 @@ renew_validate(krb5_context context,
else if (out)
flags.b.proxiable = out->flags.b.proxiable;
- if (anonymous_flag != -1)
+ if (anonymous_flag)
flags.b.request_anonymous = anonymous_flag;
if(life)
in.times.endtime = time(NULL) + life;
@@ -337,8 +361,10 @@ renew_validate(krb5_context context,
if(get_v4_tgt)
do_524init(context, cache, out, NULL);
#endif
+#ifndef NO_AFS
if(do_afslog && k_hasafs())
krb5_afslog(context, cache, NULL, NULL);
+#endif
}
krb5_free_creds (context, out);
@@ -351,6 +377,8 @@ out:
return ret;
}
+#ifndef NO_NTLM
+
static krb5_error_code
store_ntlmkey(krb5_context context, krb5_ccache id,
const char *domain, struct ntlm_buf *buf)
@@ -372,6 +400,7 @@ store_ntlmkey(krb5_context context, krb5_ccache id,
free(name);
return ret;
}
+#endif
static krb5_error_code
get_new_tickets(krb5_context context,
@@ -388,10 +417,11 @@ get_new_tickets(krb5_context context,
krb5_deltat renew = 0;
char *renewstr = NULL;
krb5_enctype *enctype = NULL;
- struct ntlm_buf ntlmkey;
krb5_ccache tempccache;
-
+#ifndef NO_NTLM
+ struct ntlm_buf ntlmkey;
memset(&ntlmkey, 0, sizeof(ntlmkey));
+#endif
passwd[0] = '\0';
if (password_file) {
@@ -428,21 +458,24 @@ get_new_tickets(krb5_context context,
krb5_get_init_creds_opt_set_forwardable (opt, forwardable_flag);
if(proxiable_flag != -1)
krb5_get_init_creds_opt_set_proxiable (opt, proxiable_flag);
- if(anonymous_flag != -1)
+ if(anonymous_flag)
krb5_get_init_creds_opt_set_anonymous (opt, anonymous_flag);
if (pac_flag != -1)
krb5_get_init_creds_opt_set_pac_request(context, opt,
pac_flag ? TRUE : FALSE);
if (canonicalize_flag)
krb5_get_init_creds_opt_set_canonicalize(context, opt, TRUE);
- if (pk_user_id) {
+ if (pk_enterprise_flag && windows_flag)
+ krb5_get_init_creds_opt_set_win2k(context, opt, TRUE);
+ if (pk_user_id || anonymous_flag) {
ret = krb5_get_init_creds_opt_set_pkinit(context, opt,
principal,
pk_user_id,
pk_x509_anchors,
NULL,
NULL,
- pk_use_enckey ? 2 : 0,
+ pk_use_enckey ? 2 : 0 |
+ anonymous_flag ? 4 : 0,
krb5_prompter_posix,
NULL,
passwd);
@@ -510,7 +543,7 @@ get_new_tickets(krb5_context context,
server_str,
opt);
krb5_kt_close(context, kt);
- } else if (pk_user_id) {
+ } else if (pk_user_id || anonymous_flag) {
ret = krb5_get_init_creds_password (context,
&cred,
principal,
@@ -552,8 +585,10 @@ get_new_tickets(krb5_context context,
opt);
}
krb5_get_init_creds_opt_free(context, opt);
+#ifndef NO_NTLM
if (ntlm_domain && passwd[0])
heim_ntlm_nt_key(passwd, &ntlmkey);
+#endif
memset(passwd, 0, sizeof(passwd));
switch(ret){
@@ -611,8 +646,13 @@ get_new_tickets(krb5_context context,
if (ret)
krb5_err (context, 1, ret, "krb5_cc_move");
+ if (switch_cache_flags)
+ krb5_cc_switch(context, ccache);
+
+#ifndef NO_NTLM
if (ntlm_domain && ntlmkey.data)
store_ntlmkey(context, ccache, ntlm_domain, &ntlmkey);
+#endif
if (ok_as_delegate_flag || windows_flag || use_referrals_flag) {
unsigned char d = 0;
@@ -704,8 +744,10 @@ renew_func(void *ptr)
if(get_v4_tgt || convert_524)
do_524init(ctx->context, ctx->ccache, NULL, server_str);
#endif
+#ifndef NO_AFS
if(do_afslog && k_hasafs())
krb5_afslog(ctx->context, ctx->ccache, NULL, NULL);
+#endif
expire = ticket_lifetime(ctx->context, ctx->ccache, ctx->principal,
server_str) / 2;
@@ -751,17 +793,35 @@ main (int argc, char **argv)
argc -= optidx;
argv += optidx;
- if (canonicalize_flag)
+ if (canonicalize_flag || enterprise_flag)
parseflags |= KRB5_PRINCIPAL_PARSE_ENTERPRISE;
- if (argv[0]) {
- ret = krb5_parse_name_flags (context, argv[0], parseflags, &principal);
+ if (pk_enterprise_flag) {
+ ret = _krb5_pk_enterprise_cert(context, pk_user_id,
+ argv[0], &principal);
if (ret)
- krb5_err (context, 1, ret, "krb5_parse_name");
- } else {
- ret = krb5_get_default_principal (context, &principal);
+ krb5_err(context, 1, ret, "krb5_pk_enterprise_certs");
+
+ } else if (anonymous_flag) {
+
+ ret = krb5_make_principal(context, &principal, argv[0],
+ KRB5_WELLKNOWN_NAME, KRB5_ANON_NAME,
+ NULL);
if (ret)
- krb5_err (context, 1, ret, "krb5_get_default_principal");
+ krb5_err(context, 1, ret, "krb5_build_principal");
+ krb5_principal_set_type(context, principal, KRB5_NT_WELLKNOWN);
+
+ } else {
+ if (argv[0]) {
+ ret = krb5_parse_name_flags (context, argv[0], parseflags,
+ &principal);
+ if (ret)
+ krb5_err (context, 1, ret, "krb5_parse_name");
+ } else {
+ ret = krb5_get_default_principal (context, &principal);
+ if (ret)
+ krb5_err (context, 1, ret, "krb5_get_default_principal");
+ }
}
if(fcache_version)
@@ -788,7 +848,7 @@ main (int argc, char **argv)
else {
if(argc > 1) {
char s[1024];
- ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &ccache);
+ ret = krb5_cc_new_unique(context, NULL, NULL, &ccache);
if(ret)
krb5_err(context, 1, ret, "creating cred cache");
snprintf(s, sizeof(s), "%s:%s",
@@ -818,8 +878,10 @@ main (int argc, char **argv)
if (ret)
krb5_err (context, 1, ret, N_("resolving credentials cache", ""));
+#ifndef NO_AFS
if(argc > 1 && k_hasafs ())
k_setpag();
+#endif
if (lifetime) {
int tmp = parse_time (lifetime, "s");
@@ -863,8 +925,10 @@ main (int argc, char **argv)
if(get_v4_tgt || convert_524)
do_524init(context, ccache, NULL, server_str);
#endif
+#ifndef NO_AFS
if(do_afslog && k_hasafs())
krb5_afslog(context, ccache, NULL, NULL);
+#endif
if(argc > 1) {
struct renew_ctx ctx;
time_t timeout;
@@ -889,8 +953,10 @@ main (int argc, char **argv)
#ifndef HEIMDAL_SMALLER
_krb5_krb_dest_tkt(context, krb4_cc_name);
#endif
+#ifndef NO_AFS
if(k_hasafs())
k_unlog();
+#endif
} else {
krb5_cc_close (context, ccache);
ret = 0;
diff --git a/source4/heimdal/kuser/kuser_locl.h b/source4/heimdal/kuser/kuser_locl.h
index eed9e00af6..eafffe9bff 100644
--- a/source4/heimdal/kuser/kuser_locl.h
+++ b/source4/heimdal/kuser/kuser_locl.h
@@ -36,9 +36,7 @@
#ifndef __KUSER_LOCL_H__
#define __KUSER_LOCL_H__
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <stdio.h>
#include <stdlib.h>
@@ -81,7 +79,9 @@
#ifdef HAVE_SYS_IOCCOM_H
#include <sys/ioccom.h>
#endif
+#ifndef NO_AFS
#include <kafs.h>
+#endif
#include "crypto-headers.h" /* for UI_UTIL_read_pw_string */
#ifdef HAVE_LOCALE_H
diff --git a/source4/heimdal/lib/asn1/asn1_err.et b/source4/heimdal/lib/asn1/asn1_err.et
index 26bda55c19..f1a653b1f9 100644
--- a/source4/heimdal/lib/asn1/asn1_err.et
+++ b/source4/heimdal/lib/asn1/asn1_err.et
@@ -22,4 +22,6 @@ error_code BAD_CHARACTER, "ASN.1 invalid character in string"
error_code MIN_CONSTRAINT, "ASN.1 too few elements"
error_code MAX_CONSTRAINT, "ASN.1 too many elements"
error_code EXACT_CONSTRAINT, "ASN.1 wrong number of elements"
+error_code INDEF_OVERRUN, "ASN.1 BER indefinte encoding overrun"
+error_code INDEF_UNDERRUN, "ASN.1 BER indefinte encoding underun"
end
diff --git a/source4/heimdal/lib/asn1/asn1_gen.c b/source4/heimdal/lib/asn1/asn1_gen.c
index e25f6d919e..925cc72cb4 100644
--- a/source4/heimdal/lib/asn1/asn1_gen.c
+++ b/source4/heimdal/lib/asn1/asn1_gen.c
@@ -119,24 +119,24 @@ doit(const char *fn)
&sz);
if (ret)
errx(1, "der_put_length_and_tag: %d", ret);
-
+
if (fwrite(p + sizeof(p) - sz , sz, 1, fout) != 1)
err(1, "fwrite length/tag failed");
offset += sz;
-
+
if (data) {
size_t datalen;
-
+
datalen = strlen(data) / 2;
pdata = emalloc(sz);
-
+
if (hex_decode(data, pdata, datalen) != datalen)
errx(1, "failed to decode data");
-
+
if (fwrite(pdata, datalen, 1, fout) != 1)
err(1, "fwrite data failed");
offset += datalen;
-
+
free(pdata);
}
}
diff --git a/source4/heimdal/lib/asn1/canthandle.asn1 b/source4/heimdal/lib/asn1/canthandle.asn1
index 5c2690f9b6..a335ee89e3 100644
--- a/source4/heimdal/lib/asn1/canthandle.asn1
+++ b/source4/heimdal/lib/asn1/canthandle.asn1
@@ -7,7 +7,7 @@ CANTHANDLE DEFINITIONS ::= BEGIN
-- Code the tag [2] but it should be primitive since KAKA3 is
-- Workaround: use the INTEGER type directly
-Kaka2 ::= SEQUENCE {
+Kaka2 ::= SEQUENCE {
kaka2-1 [0] INTEGER
}
diff --git a/source4/heimdal/lib/asn1/CMS.asn1 b/source4/heimdal/lib/asn1/cms.asn1
index 65a467521d..1c13d5f387 100644
--- a/source4/heimdal/lib/asn1/CMS.asn1
+++ b/source4/heimdal/lib/asn1/cms.asn1
@@ -18,8 +18,8 @@ id-pkcs7-digestedData OBJECT IDENTIFIER ::= { id-pkcs7 5 }
id-pkcs7-encryptedData OBJECT IDENTIFIER ::= { id-pkcs7 6 }
CMSVersion ::= INTEGER {
- CMSVersion_v0(0),
- CMSVersion_v1(1),
+ CMSVersion_v0(0),
+ CMSVersion_v1(1),
CMSVersion_v2(2),
CMSVersion_v3(3),
CMSVersion_v4(4)
@@ -34,7 +34,7 @@ MessageDigest ::= OCTET STRING
ContentInfo ::= SEQUENCE {
contentType ContentType,
- content [0] EXPLICIT heim_any OPTIONAL -- DEFINED BY contentType
+ content [0] EXPLICIT heim_any OPTIONAL -- DEFINED BY contentType
}
EncapsulatedContentInfo ::= SEQUENCE {
@@ -53,7 +53,7 @@ IssuerAndSerialNumber ::= SEQUENCE {
serialNumber CertificateSerialNumber
}
--- RecipientIdentifier is same as SignerIdentifier,
+-- RecipientIdentifier is same as SignerIdentifier,
-- lets glue them togheter and save some bytes and share code for them
CMSIdentifier ::= CHOICE {
@@ -67,7 +67,7 @@ RecipientIdentifier ::= CMSIdentifier
--- CMSAttributes are the combined UnsignedAttributes and SignedAttributes
--- to store space and share code
-CMSAttributes ::= SET OF Attribute -- SIZE (1..MAX)
+CMSAttributes ::= SET OF Attribute -- SIZE (1..MAX)
SignatureValue ::= OCTET STRING
@@ -79,7 +79,7 @@ SignerInfo ::= SEQUENCE {
SET OF Attribute OPTIONAL,
signatureAlgorithm SignatureAlgorithmIdentifier,
signature SignatureValue,
- unsignedAttrs [1] IMPLICIT -- CMSAttributes --
+ unsignedAttrs [1] IMPLICIT -- CMSAttributes --
SET OF Attribute OPTIONAL
}
diff --git a/source4/heimdal/lib/asn1/cms.opt b/source4/heimdal/lib/asn1/cms.opt
new file mode 100644
index 0000000000..bf7d396529
--- /dev/null
+++ b/source4/heimdal/lib/asn1/cms.opt
@@ -0,0 +1 @@
+--decode-dce-ber
diff --git a/source4/heimdal/lib/asn1/der.h b/source4/heimdal/lib/asn1/der.h
index 3b6f30887c..5b24b917d8 100644
--- a/source4/heimdal/lib/asn1/der.h
+++ b/source4/heimdal/lib/asn1/der.h
@@ -52,7 +52,7 @@ typedef enum {PRIM = 0, CONS = 1} Der_type;
enum {
UT_EndOfContent = 0,
UT_Boolean = 1,
- UT_Integer = 2,
+ UT_Integer = 2,
UT_BitString = 3,
UT_OctetString = 4,
UT_Null = 5,
diff --git a/source4/heimdal/lib/asn1/der_get.c b/source4/heimdal/lib/asn1/der_get.c
index 8a70966413..8144639b9a 100644
--- a/source4/heimdal/lib/asn1/der_get.c
+++ b/source4/heimdal/lib/asn1/der_get.c
@@ -33,10 +33,6 @@
#include "der_locl.h"
-RCSID("$Id$");
-
-#include <version.h>
-
/*
* All decoding functions take a pointer `p' to first position in
* which to read, from the left, `len' which means the maximum number
@@ -252,6 +248,75 @@ der_get_octet_string (const unsigned char *p, size_t len,
}
int
+der_get_octet_string_ber (const unsigned char *p, size_t len,
+ heim_octet_string *data, size_t *size)
+{
+ int e;
+ Der_type type;
+ Der_class class;
+ unsigned int tag, depth = 0;
+ size_t l, datalen, oldlen = len;
+
+ data->length = 0;
+ data->data = NULL;
+
+ while (len) {
+ e = der_get_tag (p, len, &class, &type, &tag, &l);
+ if (e) goto out;
+ if (class != ASN1_C_UNIV) {
+ e = ASN1_BAD_ID;
+ goto out;
+ }
+ if (type == PRIM && tag == UT_EndOfContent) {
+ if (depth == 0)
+ break;
+ depth--;
+ }
+ if (tag != UT_OctetString) {
+ e = ASN1_BAD_ID;
+ goto out;
+ }
+
+ p += l;
+ len -= l;
+ e = der_get_length (p, len, &datalen, &l);
+ if (e) goto out;
+ p += l;
+ len -= l;
+
+ if (datalen > len)
+ return ASN1_OVERRUN;
+
+ if (type == PRIM) {
+ void *ptr;
+
+ ptr = realloc(data->data, data->length + datalen);
+ if (ptr == NULL) {
+ e = ENOMEM;
+ goto out;
+ }
+ data->data = ptr;
+ memcpy(((unsigned char *)data->data) + data->length, p, datalen);
+ data->length += datalen;
+ } else
+ depth++;
+
+ p += datalen;
+ len -= datalen;
+ }
+ if (depth != 0)
+ return ASN1_INDEF_OVERRUN;
+ if(size) *size = oldlen - len;
+ return 0;
+ out:
+ free(data->data);
+ data->data = NULL;
+ data->length = 0;
+ return e;
+}
+
+
+int
der_get_heim_integer (const unsigned char *p, size_t len,
heim_integer *data, size_t *size)
{
@@ -397,7 +462,7 @@ der_get_oid (const unsigned char *p, size_t len,
++p;
for (n = 2; len > 0; ++n) {
unsigned u = 0, u1;
-
+
do {
--len;
u1 = u * 128 + (*p++ % 128);
@@ -457,15 +522,28 @@ der_match_tag (const unsigned char *p, size_t len,
Der_class class, Der_type type,
unsigned int tag, size_t *size)
{
+ Der_type thistype;
+ int e;
+
+ e = der_match_tag2(p, len, class, &thistype, tag, size);
+ if (e) return e;
+ if (thistype != type) return ASN1_BAD_ID;
+ return 0;
+}
+
+int
+der_match_tag2 (const unsigned char *p, size_t len,
+ Der_class class, Der_type *type,
+ unsigned int tag, size_t *size)
+{
size_t l;
Der_class thisclass;
- Der_type thistype;
unsigned int thistag;
int e;
- e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l);
+ e = der_get_tag (p, len, &thisclass, type, &thistag, &l);
if (e) return e;
- if (class != thisclass || type != thistype)
+ if (class != thisclass)
return ASN1_BAD_ID;
if(tag > thistag)
return ASN1_MISPLACED_FIELD;
@@ -477,26 +555,25 @@ der_match_tag (const unsigned char *p, size_t len,
int
der_match_tag_and_length (const unsigned char *p, size_t len,
- Der_class class, Der_type type, unsigned int tag,
+ Der_class class, Der_type *type, unsigned int tag,
size_t *length_ret, size_t *size)
{
size_t l, ret = 0;
int e;
- e = der_match_tag (p, len, class, type, tag, &l);
+ e = der_match_tag2 (p, len, class, type, tag, &l);
if (e) return e;
p += l;
len -= l;
ret += l;
e = der_get_length (p, len, length_ret, &l);
if (e) return e;
- p += l;
- len -= l;
- ret += l;
- if(size) *size = ret;
+ if(size) *size = ret + l;
return 0;
}
+
+
/*
* Old versions of DCE was based on a very early beta of the MIT code,
* which used MAVROS for ASN.1 encoding. MAVROS had the interesting
@@ -539,8 +616,11 @@ der_get_bit_string (const unsigned char *p, size_t len,
data->data = malloc(len - 1);
if (data->data == NULL && (len - 1) != 0)
return ENOMEM;
- memcpy (data->data, p + 1, len - 1);
- data->length -= p[0];
+ /* copy data is there is data to copy */
+ if (len - 1 != 0) {
+ memcpy (data->data, p + 1, len - 1);
+ data->length -= p[0];
+ }
if(size) *size = len;
return 0;
}
diff --git a/source4/heimdal/lib/asn1/der_locl.h b/source4/heimdal/lib/asn1/der_locl.h
index f8a21de71c..1f27e72903 100644
--- a/source4/heimdal/lib/asn1/der_locl.h
+++ b/source4/heimdal/lib/asn1/der_locl.h
@@ -36,9 +36,9 @@
#ifndef __DER_LOCL_H__
#define __DER_LOCL_H__
-#ifdef HAVE_CONFIG_H
+
#include <config.h>
-#endif
+
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/source4/heimdal/lib/asn1/der_put.c b/source4/heimdal/lib/asn1/der_put.c
index 5afddb1d05..7e71443da5 100644
--- a/source4/heimdal/lib/asn1/der_put.c
+++ b/source4/heimdal/lib/asn1/der_put.c
@@ -384,7 +384,7 @@ der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type,
} else {
size_t ret = 0;
unsigned int continuation = 0;
-
+
do {
if (len < 1)
return ASN1_OVERFLOW;
diff --git a/source4/heimdal/lib/asn1/digest.asn1 b/source4/heimdal/lib/asn1/digest.asn1
index 1cf58b4638..5ee5bd4a99 100644
--- a/source4/heimdal/lib/asn1/digest.asn1
+++ b/source4/heimdal/lib/asn1/digest.asn1
@@ -139,7 +139,7 @@ DigestREP ::= [APPLICATION 129] SEQUENCE {
-- qop == auth
-- A2 = Method ":" digest-uri-value
-- qop == auth-int
--- A2 = Method ":" digest-uri-value ":" H(entity-body)
+-- A2 = Method ":" digest-uri-value ":" H(entity-body)
-- request-digest = HEX(KD(HEX(H(A1)),
-- unq(nonce-value) ":" nc-value ":" unq(cnonce-value) ":" unq(qop-value) ":" HEX(H(A2))))
diff --git a/source4/heimdal/lib/asn1/extra.c b/source4/heimdal/lib/asn1/extra.c
index 49240605c8..b244dbb52a 100644
--- a/source4/heimdal/lib/asn1/extra.c
+++ b/source4/heimdal/lib/asn1/extra.c
@@ -67,15 +67,21 @@ decode_heim_any(const unsigned char *p, size_t len,
return ASN1_OVERFLOW;
e = der_get_length(p + l, len - l, &length, &len_len);
if (e) return e;
- if (length + len_len + l > len)
- return ASN1_OVERFLOW;
-
+ if (length == ASN1_INDEFINITE) {
+ if (len < len_len + l)
+ return ASN1_OVERFLOW;
+ length = len - (len_len + l);
+ } else {
+ if (len < length + len_len + l)
+ return ASN1_OVERFLOW;
+ }
+
data->data = malloc(length + len_len + l);
if (data->data == NULL)
return ENOMEM;
data->length = length + len_len + l;
memcpy(data->data, p, length + len_len + l);
-
+
if (size)
*size = length + len_len + l;
diff --git a/source4/heimdal/lib/asn1/gen.c b/source4/heimdal/lib/asn1/gen.c
index 52fd0d393b..e156c7cefb 100644
--- a/source4/heimdal/lib/asn1/gen.c
+++ b/source4/heimdal/lib/asn1/gen.c
@@ -83,12 +83,19 @@ init_generate (const char *filename, const char *base)
if (headerbase == NULL)
errx(1, "strdup");
}
+
+ /* public header file */
asprintf(&header, "%s.h", headerbase);
if (header == NULL)
errx(1, "malloc");
- headerfile = fopen (header, "w");
+ asprintf(&fn, "%s.hx", headerbase);
+ if (fn == NULL)
+ errx(1, "malloc");
+ headerfile = fopen (fn, "w");
if (headerfile == NULL)
- err (1, "open %s", header);
+ err (1, "open %s", fn);
+ free(fn);
+
fprintf (headerfile,
"/* Generated from %s */\n"
"/* Do not edit */\n\n",
@@ -229,7 +236,7 @@ gen_compare_defval(const char *var, struct value *val)
}
}
-static void
+void
generate_header_of_codefile(const char *name)
{
char *filename;
@@ -267,7 +274,7 @@ generate_header_of_codefile(const char *name)
}
-static void
+void
close_codefile(void)
{
if (codefile == NULL)
@@ -296,7 +303,8 @@ generate_constant (const Symbol *s)
struct objid *o, **list;
unsigned int i, len;
- generate_header_of_codefile(s->gen_name);
+ if (!one_code_file)
+ generate_header_of_codefile(s->gen_name);
len = 0;
for (o = s->value->u.objectidentifiervalue; o != NULL; o = o->next)
@@ -320,9 +328,13 @@ generate_constant (const Symbol *s)
}
fprintf (headerfile, "} */\n");
- fprintf (headerfile, "const heim_oid *oid_%s(void);\n\n",
+ fprintf (headerfile, "const heim_oid *oid_%s(void);\n",
+ s->gen_name);
+ fprintf (headerfile,
+ "extern const heim_oid asn1_oid_%s;\n\n",
s->gen_name);
+
fprintf (codefile, "static unsigned oid_%s_variable_num[%d] = {",
s->gen_name, len);
for (i = len ; i > 0; i--) {
@@ -330,17 +342,20 @@ generate_constant (const Symbol *s)
}
fprintf(codefile, "};\n");
- fprintf (codefile, "static const heim_oid oid_%s_variable = "
+ fprintf (codefile, "const heim_oid asn1_oid_%s = "
"{ %d, oid_%s_variable_num };\n\n",
s->gen_name, len, s->gen_name);
fprintf (codefile, "const heim_oid *oid_%s(void)\n"
"{\n"
- "return &oid_%s_variable;\n"
+ "return &asn1_oid_%s;\n"
"}\n\n",
s->gen_name, s->gen_name);
- close_codefile();
+ free(list);
+
+ if (!one_code_file)
+ close_codefile();
break;
}
@@ -587,7 +602,7 @@ define_type (int level, const char *name, Type *t, int typedefp, int preservep)
fprintf (headerfile, "struct %s {\n", typedefp ? name : "");
ASN1_TAILQ_FOREACH(m, t->members, members) {
char *n;
-
+
asprintf (&n, "%s:1", m->gen_name);
if (n == NULL)
errx(1, "malloc");
@@ -787,7 +802,8 @@ generate_type_header (const Symbol *s)
void
generate_type (const Symbol *s)
{
- generate_header_of_codefile(s->gen_name);
+ if (!one_code_file)
+ generate_header_of_codefile(s->gen_name);
generate_type_header (s);
generate_type_encode (s);
@@ -798,5 +814,9 @@ generate_type (const Symbol *s)
generate_type_seq (s);
generate_glue (s->type, s->gen_name);
fprintf(headerfile, "\n\n");
- close_codefile();
+
+ if (!one_code_file) {
+ fprintf(codefile, "\n\n");
+ close_codefile();
+ }
}
diff --git a/source4/heimdal/lib/asn1/gen_copy.c b/source4/heimdal/lib/asn1/gen_copy.c
index 37c9304779..5042ed64ed 100644
--- a/source4/heimdal/lib/asn1/gen_copy.c
+++ b/source4/heimdal/lib/asn1/gen_copy.c
@@ -149,7 +149,7 @@ copy_type (const char *from, const char *to, const Type *t, int preserve)
to, have_ellipsis->gen_name);
used_fail++;
}
- fprintf(codefile, "}\n");
+ fprintf(codefile, "}\n");
}
break;
}
diff --git a/source4/heimdal/lib/asn1/gen_decode.c b/source4/heimdal/lib/asn1/gen_decode.c
index 2bd5acb47e..cf7f0b05dc 100644
--- a/source4/heimdal/lib/asn1/gen_decode.c
+++ b/source4/heimdal/lib/asn1/gen_decode.c
@@ -230,7 +230,7 @@ range_check(const char *name,
static int
decode_type (const char *name, const Type *t, int optional,
- const char *forwstr, const char *tmpstr)
+ const char *forwstr, const char *tmpstr, const char *dertype)
{
switch (t->type) {
case TType: {
@@ -289,7 +289,17 @@ decode_type (const char *name, const Type *t, int optional,
decode_primitive ("enumerated", name, forwstr);
break;
case TOctetString:
+ if (dertype) {
+ fprintf(codefile,
+ "if (%s == CONS) {\n",
+ dertype);
+ decode_primitive("octet_string_ber", name, forwstr);
+ fprintf(codefile,
+ "} else {\n");
+ }
decode_primitive ("octet_string", name, forwstr);
+ if (dertype)
+ fprintf(codefile, "}\n");
if (t->range)
range_check(name, "length", forwstr, t->range);
break;
@@ -340,10 +350,10 @@ decode_type (const char *name, const Type *t, int optional,
name, m->gen_name);
if (s == NULL)
errx(1, "malloc");
- decode_type (s, m->type, m->optional, forwstr, m->gen_name);
+ decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL);
free (s);
}
-
+
break;
}
case TSet: {
@@ -382,7 +392,7 @@ decode_type (const char *name, const Type *t, int optional,
"%s = calloc(1, sizeof(*%s));\n"
"if (%s == NULL) { e = ENOMEM; %s; }\n",
s, s, s, forwstr);
- decode_type (s, m->type, 0, forwstr, m->gen_name);
+ decode_type (s, m->type, 0, forwstr, m->gen_name, NULL);
free (s);
fprintf(codefile, "members |= (1 << %d);\n", memno);
@@ -458,7 +468,7 @@ decode_type (const char *name, const Type *t, int optional,
asprintf (&sname, "%s_s_of", tmpstr);
if (sname == NULL)
errx(1, "malloc");
- decode_type (n, t->subtype, 0, forwstr, sname);
+ decode_type (n, t->subtype, 0, forwstr, sname, NULL);
fprintf (codefile,
"(%s)->len++;\n"
"len = %s_origlen - ret;\n"
@@ -480,21 +490,37 @@ decode_type (const char *name, const Type *t, int optional,
decode_primitive ("general_string", name, forwstr);
break;
case TTag:{
- char *tname;
+ char *tname, *typestring;
+ char *ide = NULL;
+
+ asprintf(&typestring, "%s_type", tmpstr);
fprintf(codefile,
"{\n"
- "size_t %s_datalen, %s_oldlen;\n",
- tmpstr, tmpstr);
- if(dce_fix)
+ "size_t %s_datalen, %s_oldlen;\n"
+ "Der_type %s;\n",
+ tmpstr, tmpstr, typestring);
+ if(support_ber)
fprintf(codefile,
- "int dce_fix;\n");
- fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, %s, %s, "
+ "int is_indefinite;\n");
+
+ fprintf(codefile, "e = der_match_tag_and_length(p, len, %s, &%s, %s, "
"&%s_datalen, &l);\n",
classname(t->tag.tagclass),
- is_primitive_type(t->subtype->type) ? "PRIM" : "CONS",
+ typestring,
valuename(t->tag.tagclass, t->tag.tagvalue),
tmpstr);
+
+ /* XXX hardcode for now */
+ if (support_ber && t->subtype->type == TOctetString) {
+ ide = typestring;
+ } else {
+ fprintf(codefile,
+ "if (e == 0 && %s != %s) { e = ASN1_BAD_ID; }\n",
+ typestring,
+ is_primitive_type(t->subtype->type) ? "PRIM" : "CONS");
+ }
+
if(optional) {
fprintf(codefile,
"if(e) {\n"
@@ -510,11 +536,12 @@ decode_type (const char *name, const Type *t, int optional,
"p += l; len -= l; ret += l;\n"
"%s_oldlen = len;\n",
tmpstr);
- if(dce_fix)
+ if(support_ber)
fprintf (codefile,
- "if((dce_fix = _heim_fix_dce(%s_datalen, &len)) < 0)\n"
- "{ e = ASN1_BAD_FORMAT; %s; }\n",
- tmpstr, forwstr);
+ "if((is_indefinite = _heim_fix_dce(%s_datalen, &len)) < 0)\n"
+ "{ e = ASN1_BAD_FORMAT; %s; }\n"
+ "if (is_indefinite) { if (len < 2) { e = ASN1_OVERRUN; %s; } len -= 2; }",
+ tmpstr, forwstr, forwstr);
else
fprintf(codefile,
"if (%s_datalen > len) { e = ASN1_OVERRUN; %s; }\n"
@@ -522,15 +549,22 @@ decode_type (const char *name, const Type *t, int optional,
asprintf (&tname, "%s_Tag", tmpstr);
if (tname == NULL)
errx(1, "malloc");
- decode_type (name, t->subtype, 0, forwstr, tname);
- if(dce_fix)
+ decode_type (name, t->subtype, 0, forwstr, tname, ide);
+ if(support_ber)
fprintf(codefile,
- "if(dce_fix){\n"
- "e = der_match_tag_and_length (p, len, "
- "(Der_class)0,(Der_type)0, UT_EndOfContent, "
+ "if(is_indefinite){\n"
+ "len += 2;\n"
+ "e = der_match_tag_and_length(p, len, "
+ "(Der_class)0, &%s, UT_EndOfContent, "
"&%s_datalen, &l);\n"
- "if(e) %s;\np += l; len -= l; ret += l;\n"
- "} else \n", tmpstr, forwstr);
+ "if(e) %s;\n"
+ "p += l; len -= l; ret += l;\n"
+ "if (%s != (Der_type)0) { e = ASN1_BAD_ID; %s; }\n"
+ "} else \n",
+ typestring,
+ tmpstr,
+ forwstr,
+ typestring, forwstr);
fprintf(codefile,
"len = %s_oldlen - %s_datalen;\n",
tmpstr, tmpstr);
@@ -540,6 +574,7 @@ decode_type (const char *name, const Type *t, int optional,
fprintf(codefile,
"}\n");
free(tname);
+ free(typestring);
break;
}
case TChoice: {
@@ -555,7 +590,7 @@ decode_type (const char *name, const Type *t, int optional,
Der_class cl;
Der_type ty;
unsigned tag;
-
+
if (m->ellipsis) {
have_ellipsis = m;
continue;
@@ -573,7 +608,7 @@ decode_type (const char *name, const Type *t, int optional,
name, m->gen_name);
if (s == NULL)
errx(1, "malloc");
- decode_type (s, m->type, m->optional, forwstr, m->gen_name);
+ decode_type (s, m->type, m->optional, forwstr, m->gen_name, NULL);
fprintf(codefile,
"(%s)->element = %s;\n",
name, m->label);
@@ -695,7 +730,7 @@ generate_type_decode (const Symbol *s)
fprintf (codefile, "\n");
fprintf (codefile, "memset(data, 0, sizeof(*data));\n"); /* hack to avoid `unused variable' */
- decode_type ("data", s->type, 0, "goto fail", "Top");
+ decode_type ("data", s->type, 0, "goto fail", "Top", NULL);
if (preserve)
fprintf (codefile,
"data->_save.data = calloc(1, ret);\n"
diff --git a/source4/heimdal/lib/asn1/gen_encode.c b/source4/heimdal/lib/asn1/gen_encode.c
index d80a2f8d1f..1f8078a0ee 100644
--- a/source4/heimdal/lib/asn1/gen_encode.c
+++ b/source4/heimdal/lib/asn1/gen_encode.c
@@ -257,7 +257,7 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
if (t->members == NULL)
break;
-
+
ASN1_TAILQ_FOREACH_REVERSE(m, t->members, memhead, members) {
char *s;
@@ -388,7 +388,7 @@ encode_type (const char *name, const Type *t, const char *tmpstr)
int c;
asprintf (&tname, "%s_tag", tmpstr);
if (tname == NULL)
- errx(1, "malloc");
+ errx(1, "malloc");
c = encode_type (name, t->subtype, tname);
fprintf (codefile,
"e = der_put_length_and_tag (p, len, ret, %s, %s, %s, &l);\n"
diff --git a/source4/heimdal/lib/asn1/gen_free.c b/source4/heimdal/lib/asn1/gen_free.c
index 305d7de247..fac1f6da5d 100644
--- a/source4/heimdal/lib/asn1/gen_free.c
+++ b/source4/heimdal/lib/asn1/gen_free.c
@@ -110,7 +110,7 @@ free_type (const char *name, const Type *t, int preserve)
if(t->type == TChoice)
fprintf(codefile, "break;\n");
}
-
+
if(t->type == TChoice) {
if (have_ellipsis)
fprintf(codefile,
diff --git a/source4/heimdal/lib/asn1/gen_length.c b/source4/heimdal/lib/asn1/gen_length.c
index a1df4eef6b..7f9755e2da 100644
--- a/source4/heimdal/lib/asn1/gen_length.c
+++ b/source4/heimdal/lib/asn1/gen_length.c
@@ -139,7 +139,7 @@ length_type (const char *name, const Type *t,
ASN1_TAILQ_FOREACH(m, t->members, members) {
char *s;
-
+
if (m->ellipsis) {
have_ellipsis = m;
continue;
diff --git a/source4/heimdal/lib/asn1/gen_locl.h b/source4/heimdal/lib/asn1/gen_locl.h
index c8b3896314..2bb64b5a38 100644
--- a/source4/heimdal/lib/asn1/gen_locl.h
+++ b/source4/heimdal/lib/asn1/gen_locl.h
@@ -36,9 +36,8 @@
#ifndef __GEN_LOCL_H__
#define __GEN_LOCL_H__
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
+
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
@@ -80,9 +79,14 @@ int yyparse(void);
int preserve_type(const char *);
int seq_type(const char *);
+void generate_header_of_codefile(const char *);
+void close_codefile(void);
+
+
extern FILE *headerfile, *codefile, *logfile;
-extern int dce_fix;
+extern int support_ber;
extern int rfc1510_bitstring;
+extern int one_code_file;
extern int error_flag;
diff --git a/source4/heimdal/lib/asn1/k5.asn1 b/source4/heimdal/lib/asn1/krb5.asn1
index 9b36498161..8edb0fde69 100644
--- a/source4/heimdal/lib/asn1/k5.asn1
+++ b/source4/heimdal/lib/asn1/krb5.asn1
@@ -13,6 +13,7 @@ NAME-TYPE ::= INTEGER {
KRB5_NT_X500_PRINCIPAL(6), -- PKINIT
KRB5_NT_SMTP_NAME(7), -- Name in form of SMTP email name
KRB5_NT_ENTERPRISE_PRINCIPAL(10), -- Windows 2000 UPN
+ KRB5_NT_WELLKNOWN(11), -- Wellknown
KRB5_NT_ENT_PRINCIPAL_AND_ID(-130), -- Windows 2000 UPN and SID
KRB5_NT_MS_PRINCIPAL(-128), -- NT 4 style name
KRB5_NT_MS_PRINCIPAL_AND_ID(-129) -- NT style name and SID
@@ -64,6 +65,10 @@ PADATA-TYPE ::= INTEGER {
KRB5-PADATA-GET-FROM-TYPED-DATA(22),
KRB5-PADATA-SAM-ETYPE-INFO(23),
KRB5-PADATA-SERVER-REFERRAL(25),
+ KRB5-PADATA-ALT-PRINC(24), -- (crawdad@fnal.gov)
+ KRB5-PADATA-SAM-CHALLENGE2(30), -- (kenh@pobox.com)
+ KRB5-PADATA-SAM-RESPONSE2(31), -- (kenh@pobox.com)
+ KRB5-PA-EXTRA-TGT(41), -- Reserved extra TGT
KRB5-PADATA-TD-KRB-PRINCIPAL(102), -- PrincipalName
KRB5-PADATA-PK-TD-TRUSTED-CERTIFIERS(104), -- PKINIT
KRB5-PADATA-PK-TD-CERTIFICATE-INDEX(105), -- PKINIT
@@ -71,13 +76,30 @@ PADATA-TYPE ::= INTEGER {
KRB5-PADATA-TD-REQ-NONCE(107), -- INTEGER
KRB5-PADATA-TD-REQ-SEQ(108), -- INTEGER
KRB5-PADATA-PA-PAC-REQUEST(128), -- jbrezak@exchange.microsoft.com
- KRB5-PADATA-S4U2SELF(129),
- KRB5-PADATA-EPAC(130), -- EPAK
- KRB5-PADATA-PK-AS-09-BINDING(132), -- client send this to
- -- tell KDC that is supports
+ KRB5-PADATA-FOR-USER(129), -- MS-KILE
+ KRB5-PADATA-FOR-X509-USER(130), -- MS-KILE
+ KRB5-PADATA-FOR-CHECK-DUPS(131), -- MS-KILE
+ KRB5-PADATA-AS-CHECKSUM(132), -- MS-KILE
+ KRB5-PADATA-PK-AS-09-BINDING(132), -- client send this to
+ -- tell KDC that is supports
-- the asCheckSum in the
-- PK-AS-REP
- KRB5-PADATA-CLIENT-CANONICALIZED(133) --
+ KRB5-PADATA-CLIENT-CANONICALIZED(133), -- referals
+ KRB5-PADATA-FX-COOKIE(133), -- krb-wg-preauth-framework
+ KRB5-PADATA-AUTHENTICATION-SET(134), -- krb-wg-preauth-framework
+ KRB5-PADATA-AUTH-SET-SELECTED(135), -- krb-wg-preauth-framework
+ KRB5-PADATA-FX-FAST(136), -- krb-wg-preauth-framework
+ KRB5-PADATA-FX-ERROR(137), -- krb-wg-preauth-framework
+ KRB5-PADATA-ENCRYPTED-CHALLENGE(138), -- krb-wg-preauth-framework
+ KRB5-PADATA-OTP-CHALLENGE(141), -- (gareth.richards@rsa.com)
+ KRB5-PADATA-OTP-REQUEST(142), -- (gareth.richards@rsa.com)
+ KBB5-PADATA-OTP-CONFIRM(143), -- (gareth.richards@rsa.com)
+ KRB5-PADATA-OTP-PIN-CHANGE(144), -- (gareth.richards@rsa.com)
+ KRB5-PADATA-EPAK-AS-REQ(145),
+ KRB5-PADATA-EPAK-AS-REP(146),
+ KRB5-PADATA-PKINIT-KX(147), -- krb-wg-anon
+ KRB5-PADATA-PKU2U-NAME(148), -- zhu-pku2u
+ KRB5-PADATA-SUPPORTED-ETYPES(165) -- MS-KILE
}
AUTHDATA-TYPE ::= INTEGER {
@@ -174,6 +196,8 @@ Principal ::= SEQUENCE {
realm[1] Realm
}
+Principals ::= SEQUENCE OF Principal
+
HostAddress ::= SEQUENCE {
addr-type[0] krb5int32,
address[1] OCTET STRING
@@ -387,7 +411,7 @@ PA-ENC-TS-ENC ::= SEQUENCE {
-- draft-brezak-win2k-krb-authz-01
PA-PAC-REQUEST ::= SEQUENCE {
- include-pac[0] BOOLEAN -- Indicates whether a PAC
+ include-pac[0] BOOLEAN -- Indicates whether a PAC
-- should be included or not
}
@@ -618,21 +642,19 @@ PA-S4U2Self ::= SEQUENCE {
auth[3] GeneralString
}
-KRB5SignedPathPrincipals ::= SEQUENCE OF Principal
-
-- never encoded on the wire, just used to checksum over
KRB5SignedPathData ::= SEQUENCE {
encticket[0] EncTicketPart,
- delegated[1] KRB5SignedPathPrincipals OPTIONAL
+ delegated[1] Principals OPTIONAL
}
KRB5SignedPath ::= SEQUENCE {
-- DERcoded KRB5SignedPathData
- -- krbtgt key (etype), KeyUsage = XXX
+ -- krbtgt key (etype), KeyUsage = XXX
etype[0] ENCTYPE,
cksum[1] Checksum,
-- srvs delegated though
- delegated[2] KRB5SignedPathPrincipals OPTIONAL
+ delegated[2] Principals OPTIONAL
}
PA-ClientCanonicalizedNames ::= SEQUENCE{
@@ -666,6 +688,63 @@ PA-ServerReferralData ::= SEQUENCE {
...
}
+FastOptions ::= BIT STRING {
+ reserved(0),
+ hide-client-names(1),
+ kdc-follow--referrals(16)
+}
+
+KrbFastReq ::= SEQUENCE {
+ fast-options [0] FastOptions,
+ padata [1] SEQUENCE OF PA-DATA,
+ req-body [2] KDC-REQ-BODY,
+ ...
+}
+
+KrbFastArmor ::= SEQUENCE {
+ armor-type [0] krb5int32,
+ armor-value [1] OCTET STRING,
+ ...
+}
+
+KrbFastArmoredReq ::= SEQUENCE {
+ armor [0] KrbFastArmor OPTIONAL,
+ req-checksum [1] Checksum,
+ enc-fast-req [2] EncryptedData -- KrbFastReq --
+}
+
+PA-FX-FAST-REQUEST ::= CHOICE {
+ armored-data [0] KrbFastArmoredReq,
+ ...
+}
+
+KrbFastFinished ::= SEQUENCE {
+ timestamp [0] KerberosTime,
+ usec [1] krb5int32,
+ crealm [2] Realm,
+ cname [3] PrincipalName,
+ checksum [4] Checksum,
+ ticket-checksum [5] Checksum,
+ ...
+}
+
+KrbFastResponse ::= SEQUENCE {
+ padata [0] SEQUENCE OF PA-DATA,
+ rep-key [1] EncryptionKey OPTIONAL,
+ finished [2] KrbFastFinished OPTIONAL,
+ ...
+}
+
+KrbFastArmoredRep ::= SEQUENCE {
+ enc-fast-rep [0] EncryptedData, -- KrbFastResponse --
+ ...
+}
+
+PA-FX-FAST-REPLY ::= CHOICE {
+ armored-data [0] KrbFastArmoredRep,
+ ...
+}
+
END
-- etags -r '/\([A-Za-z][-A-Za-z0-9]*\).*::=/\1/' k5.asn1
diff --git a/source4/heimdal/lib/asn1/krb5.opt b/source4/heimdal/lib/asn1/krb5.opt
new file mode 100644
index 0000000000..1d6d5e8989
--- /dev/null
+++ b/source4/heimdal/lib/asn1/krb5.opt
@@ -0,0 +1,6 @@
+--encode-rfc1510-bit-string
+--sequence=Principals
+--sequence=AuthorizationData
+--sequence=METHOD-DATA
+--sequence=ETYPE-INFO
+--sequence=ETYPE-INFO2
diff --git a/source4/heimdal/lib/asn1/kx509.asn1 b/source4/heimdal/lib/asn1/kx509.asn1
index 820abc8106..14ebf50ecd 100644
--- a/source4/heimdal/lib/asn1/kx509.asn1
+++ b/source4/heimdal/lib/asn1/kx509.asn1
@@ -3,6 +3,17 @@
KX509 DEFINITIONS ::=
BEGIN
+KX509-ERROR-CODE ::= INTEGER {
+ KX509-STATUS-GOOD(0),
+ KX509-STATUS-CLIENT-BAD(1),
+ KX509-STATUS-CLIENT-FIX(2),
+ KX509-STATUS-CLIENT-TEMP(3),
+ KX509-STATUS-SERVER-BAD(4),
+ KX509-STATUS-SERVER-TEMP(5),
+ -- 6 is used internally in the umich client, avoid that
+ KX509-STATUS-SERVER-KEY(7)
+}
+
Kx509Request ::= SEQUENCE {
authenticator OCTET STRING,
pk-hash OCTET STRING,
diff --git a/source4/heimdal/lib/asn1/lex.l b/source4/heimdal/lib/asn1/lex.l
index 1198ef16a6..7bd442bc50 100644
--- a/source4/heimdal/lib/asn1/lex.l
+++ b/source4/heimdal/lib/asn1/lex.l
@@ -46,7 +46,7 @@
#endif
#undef ECHO
#include "symbol.h"
-#include "parse.h"
+#include "asn1parse.h"
#include "lex.h"
#include "gen_locl.h"
@@ -216,7 +216,7 @@ WITH { return kw_WITH; }
char *p = buf;
int f = 0;
int skip_ws = 0;
-
+
while((c = input()) != EOF) {
if(isspace(c) && skip_ws) {
if(c == '\n')
@@ -224,7 +224,7 @@ WITH { return kw_WITH; }
continue;
}
skip_ws = 0;
-
+
if(c == '"') {
if(f) {
*p++ = '"';
diff --git a/source4/heimdal/lib/asn1/main.c b/source4/heimdal/lib/asn1/main.c
index 6a97634310..115c82a9c7 100644
--- a/source4/heimdal/lib/asn1/main.c
+++ b/source4/heimdal/lib/asn1/main.c
@@ -62,15 +62,20 @@ seq_type(const char *p)
return 0;
}
-int dce_fix;
+int support_ber;
int rfc1510_bitstring;
+int one_code_file;
+char *option_file;
int version_flag;
int help_flag;
struct getargs args[] = {
{ "encode-rfc1510-bit-string", 0, arg_flag, &rfc1510_bitstring },
- { "decode-dce-ber", 0, arg_flag, &dce_fix },
+ { "decode-dce-ber", 0, arg_flag, &support_ber },
+ { "support-ber", 0, arg_flag, &support_ber },
{ "preserve-binary", 0, arg_strings, &preserve },
{ "sequence", 0, arg_strings, &seq },
+ { "one-code-file", 0, arg_flag, &one_code_file },
+ { "option-file", 0, arg_string, &option_file },
{ "version", 0, arg_flag, &version_flag },
{ "help", 0, arg_flag, &help_flag }
};
@@ -92,6 +97,8 @@ main(int argc, char **argv)
const char *file;
const char *name = NULL;
int optidx = 0;
+ char **arg = NULL;
+ size_t len = 0, i;
setprogname(argv[0]);
if(getarg(args, num_args, argc, argv, &optidx))
@@ -121,7 +128,58 @@ main(int argc, char **argv)
name = argv[optidx + 1];
}
+ /*
+ * Parse extra options file
+ */
+ if (option_file) {
+ char buf[1024];
+ FILE *opt;
+
+ opt = fopen(option_file, "r");
+ if (opt == NULL) {
+ perror("open");
+ exit(1);
+ }
+
+ arg = calloc(2, sizeof(arg[0]));
+ arg[0] = option_file;
+ arg[1] = NULL;
+ len = 1;
+
+ while (fgets(buf, sizeof(buf), opt) != NULL) {
+ buf[strcspn(buf, "\n\r")] = '\0';
+
+ arg = realloc(arg, (len + 2) * sizeof(arg[0]));
+ if (argv == NULL) {
+ perror("malloc");
+ exit(1);
+ }
+ arg[len] = strdup(buf);
+ if (arg[len] == NULL) {
+ perror("strdup");
+ exit(1);
+ }
+ arg[len + 1] = NULL;
+ len++;
+ }
+ fclose(opt);
+
+ optidx = 0;
+ if(getarg(args, num_args, len, arg, &optidx))
+ usage(1);
+
+ if (len != optidx) {
+ fprintf(stderr, "extra args");
+ exit(1);
+ }
+ }
+
+
init_generate (file, name);
+
+ if (one_code_file)
+ generate_header_of_codefile(name);
+
initsym ();
ret = yyparse ();
if(ret != 0 || error_flag != 0)
@@ -129,5 +187,15 @@ main(int argc, char **argv)
close_generate ();
if (argc != optidx)
fclose(yyin);
+
+ if (one_code_file)
+ close_codefile();
+
+ if (arg) {
+ for (i = 1; i < len; i++)
+ free(arg[i]);
+ free(arg);
+ }
+
return 0;
}
diff --git a/source4/heimdal/lib/asn1/parse.y b/source4/heimdal/lib/asn1/parse.y
deleted file mode 100644
index aca4a062b8..0000000000
--- a/source4/heimdal/lib/asn1/parse.y
+++ /dev/null
@@ -1,1015 +0,0 @@
-/*
- * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/* $Id$ */
-
-%{
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "symbol.h"
-#include "lex.h"
-#include "gen_locl.h"
-#include "der.h"
-
-RCSID("$Id$");
-
-static Type *new_type (Typetype t);
-static struct constraint_spec *new_constraint_spec(enum ctype);
-static Type *new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype);
-void yyerror (const char *);
-static struct objid *new_objid(const char *label, int value);
-static void add_oid_to_tail(struct objid *, struct objid *);
-static void fix_labels(Symbol *s);
-
-struct string_list {
- char *string;
- struct string_list *next;
-};
-
-%}
-
-%union {
- int constant;
- struct value *value;
- struct range *range;
- char *name;
- Type *type;
- Member *member;
- struct objid *objid;
- char *defval;
- struct string_list *sl;
- struct tagtype tag;
- struct memhead *members;
- struct constraint_spec *constraint_spec;
-}
-
-%token kw_ABSENT
-%token kw_ABSTRACT_SYNTAX
-%token kw_ALL
-%token kw_APPLICATION
-%token kw_AUTOMATIC
-%token kw_BEGIN
-%token kw_BIT
-%token kw_BMPString
-%token kw_BOOLEAN
-%token kw_BY
-%token kw_CHARACTER
-%token kw_CHOICE
-%token kw_CLASS
-%token kw_COMPONENT
-%token kw_COMPONENTS
-%token kw_CONSTRAINED
-%token kw_CONTAINING
-%token kw_DEFAULT
-%token kw_DEFINITIONS
-%token kw_EMBEDDED
-%token kw_ENCODED
-%token kw_END
-%token kw_ENUMERATED
-%token kw_EXCEPT
-%token kw_EXPLICIT
-%token kw_EXPORTS
-%token kw_EXTENSIBILITY
-%token kw_EXTERNAL
-%token kw_FALSE
-%token kw_FROM
-%token kw_GeneralString
-%token kw_GeneralizedTime
-%token kw_GraphicString
-%token kw_IA5String
-%token kw_IDENTIFIER
-%token kw_IMPLICIT
-%token kw_IMPLIED
-%token kw_IMPORTS
-%token kw_INCLUDES
-%token kw_INSTANCE
-%token kw_INTEGER
-%token kw_INTERSECTION
-%token kw_ISO646String
-%token kw_MAX
-%token kw_MIN
-%token kw_MINUS_INFINITY
-%token kw_NULL
-%token kw_NumericString
-%token kw_OBJECT
-%token kw_OCTET
-%token kw_OF
-%token kw_OPTIONAL
-%token kw_ObjectDescriptor
-%token kw_PATTERN
-%token kw_PDV
-%token kw_PLUS_INFINITY
-%token kw_PRESENT
-%token kw_PRIVATE
-%token kw_PrintableString
-%token kw_REAL
-%token kw_RELATIVE_OID
-%token kw_SEQUENCE
-%token kw_SET
-%token kw_SIZE
-%token kw_STRING
-%token kw_SYNTAX
-%token kw_T61String
-%token kw_TAGS
-%token kw_TRUE
-%token kw_TYPE_IDENTIFIER
-%token kw_TeletexString
-%token kw_UNION
-%token kw_UNIQUE
-%token kw_UNIVERSAL
-%token kw_UTCTime
-%token kw_UTF8String
-%token kw_UniversalString
-%token kw_VideotexString
-%token kw_VisibleString
-%token kw_WITH
-
-%token RANGE
-%token EEQUAL
-%token ELLIPSIS
-
-%token <name> IDENTIFIER referencename
-%token <name> STRING
-
-%token <constant> NUMBER
-%type <constant> SignedNumber
-%type <constant> Class tagenv
-
-%type <value> Value
-%type <value> BuiltinValue
-%type <value> IntegerValue
-%type <value> BooleanValue
-%type <value> ObjectIdentifierValue
-%type <value> CharacterStringValue
-%type <value> NullValue
-%type <value> DefinedValue
-%type <value> ReferencedValue
-%type <value> Valuereference
-
-%type <type> Type
-%type <type> BuiltinType
-%type <type> BitStringType
-%type <type> BooleanType
-%type <type> ChoiceType
-%type <type> ConstrainedType
-%type <type> EnumeratedType
-%type <type> IntegerType
-%type <type> NullType
-%type <type> OctetStringType
-%type <type> SequenceType
-%type <type> SequenceOfType
-%type <type> SetType
-%type <type> SetOfType
-%type <type> TaggedType
-%type <type> ReferencedType
-%type <type> DefinedType
-%type <type> UsefulType
-%type <type> ObjectIdentifierType
-%type <type> CharacterStringType
-%type <type> RestrictedCharactedStringType
-
-%type <tag> Tag
-
-%type <member> ComponentType
-%type <member> NamedBit
-%type <member> NamedNumber
-%type <member> NamedType
-%type <members> ComponentTypeList
-%type <members> Enumerations
-%type <members> NamedBitList
-%type <members> NamedNumberList
-
-%type <objid> objid objid_list objid_element objid_opt
-%type <range> range size
-
-%type <sl> referencenames
-
-%type <constraint_spec> Constraint
-%type <constraint_spec> ConstraintSpec
-%type <constraint_spec> GeneralConstraint
-%type <constraint_spec> ContentsConstraint
-%type <constraint_spec> UserDefinedConstraint
-
-
-
-%start ModuleDefinition
-
-%%
-
-ModuleDefinition: IDENTIFIER objid_opt kw_DEFINITIONS TagDefault ExtensionDefault
- EEQUAL kw_BEGIN ModuleBody kw_END
- {
- checkundefined();
- }
- ;
-
-TagDefault : kw_EXPLICIT kw_TAGS
- | kw_IMPLICIT kw_TAGS
- { error_message("implicit tagging is not supported"); }
- | kw_AUTOMATIC kw_TAGS
- { error_message("automatic tagging is not supported"); }
- | /* empty */
- ;
-
-ExtensionDefault: kw_EXTENSIBILITY kw_IMPLIED
- { error_message("no extensibility options supported"); }
- | /* empty */
- ;
-
-ModuleBody : /* Exports */ Imports AssignmentList
- | /* empty */
- ;
-
-Imports : kw_IMPORTS SymbolsImported ';'
- | /* empty */
- ;
-
-SymbolsImported : SymbolsFromModuleList
- | /* empty */
- ;
-
-SymbolsFromModuleList: SymbolsFromModule
- | SymbolsFromModuleList SymbolsFromModule
- ;
-
-SymbolsFromModule: referencenames kw_FROM IDENTIFIER objid_opt
- {
- struct string_list *sl;
- for(sl = $1; sl != NULL; sl = sl->next) {
- Symbol *s = addsym(sl->string);
- s->stype = Stype;
- }
- add_import($3);
- }
- ;
-
-AssignmentList : Assignment
- | Assignment AssignmentList
- ;
-
-Assignment : TypeAssignment
- | ValueAssignment
- ;
-
-referencenames : IDENTIFIER ',' referencenames
- {
- $$ = emalloc(sizeof(*$$));
- $$->string = $1;
- $$->next = $3;
- }
- | IDENTIFIER
- {
- $$ = emalloc(sizeof(*$$));
- $$->string = $1;
- $$->next = NULL;
- }
- ;
-
-TypeAssignment : IDENTIFIER EEQUAL Type
- {
- Symbol *s = addsym ($1);
- s->stype = Stype;
- s->type = $3;
- fix_labels(s);
- generate_type (s);
- }
- ;
-
-Type : BuiltinType
- | ReferencedType
- | ConstrainedType
- ;
-
-BuiltinType : BitStringType
- | BooleanType
- | CharacterStringType
- | ChoiceType
- | EnumeratedType
- | IntegerType
- | NullType
- | ObjectIdentifierType
- | OctetStringType
- | SequenceType
- | SequenceOfType
- | SetType
- | SetOfType
- | TaggedType
- ;
-
-BooleanType : kw_BOOLEAN
- {
- $$ = new_tag(ASN1_C_UNIV, UT_Boolean,
- TE_EXPLICIT, new_type(TBoolean));
- }
- ;
-
-range : '(' Value RANGE Value ')'
- {
- if($2->type != integervalue)
- error_message("Non-integer used in first part of range");
- if($2->type != integervalue)
- error_message("Non-integer in second part of range");
- $$ = ecalloc(1, sizeof(*$$));
- $$->min = $2->u.integervalue;
- $$->max = $4->u.integervalue;
- }
- | '(' Value RANGE kw_MAX ')'
- {
- if($2->type != integervalue)
- error_message("Non-integer in first part of range");
- $$ = ecalloc(1, sizeof(*$$));
- $$->min = $2->u.integervalue;
- $$->max = $2->u.integervalue - 1;
- }
- | '(' kw_MIN RANGE Value ')'
- {
- if($4->type != integervalue)
- error_message("Non-integer in second part of range");
- $$ = ecalloc(1, sizeof(*$$));
- $$->min = $4->u.integervalue + 2;
- $$->max = $4->u.integervalue;
- }
- | '(' Value ')'
- {
- if($2->type != integervalue)
- error_message("Non-integer used in limit");
- $$ = ecalloc(1, sizeof(*$$));
- $$->min = $2->u.integervalue;
- $$->max = $2->u.integervalue;
- }
- ;
-
-
-IntegerType : kw_INTEGER
- {
- $$ = new_tag(ASN1_C_UNIV, UT_Integer,
- TE_EXPLICIT, new_type(TInteger));
- }
- | kw_INTEGER range
- {
- $$ = new_type(TInteger);
- $$->range = $2;
- $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$);
- }
- | kw_INTEGER '{' NamedNumberList '}'
- {
- $$ = new_type(TInteger);
- $$->members = $3;
- $$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$);
- }
- ;
-
-NamedNumberList : NamedNumber
- {
- $$ = emalloc(sizeof(*$$));
- ASN1_TAILQ_INIT($$);
- ASN1_TAILQ_INSERT_HEAD($$, $1, members);
- }
- | NamedNumberList ',' NamedNumber
- {
- ASN1_TAILQ_INSERT_TAIL($1, $3, members);
- $$ = $1;
- }
- | NamedNumberList ',' ELLIPSIS
- { $$ = $1; } /* XXX used for Enumerations */
- ;
-
-NamedNumber : IDENTIFIER '(' SignedNumber ')'
- {
- $$ = emalloc(sizeof(*$$));
- $$->name = $1;
- $$->gen_name = estrdup($1);
- output_name ($$->gen_name);
- $$->val = $3;
- $$->optional = 0;
- $$->ellipsis = 0;
- $$->type = NULL;
- }
- ;
-
-EnumeratedType : kw_ENUMERATED '{' Enumerations '}'
- {
- $$ = new_type(TInteger);
- $$->members = $3;
- $$ = new_tag(ASN1_C_UNIV, UT_Enumerated, TE_EXPLICIT, $$);
- }
- ;
-
-Enumerations : NamedNumberList /* XXX */
- ;
-
-BitStringType : kw_BIT kw_STRING
- {
- $$ = new_type(TBitString);
- $$->members = emalloc(sizeof(*$$->members));
- ASN1_TAILQ_INIT($$->members);
- $$ = new_tag(ASN1_C_UNIV, UT_BitString, TE_EXPLICIT, $$);
- }
- | kw_BIT kw_STRING '{' NamedBitList '}'
- {
- $$ = new_type(TBitString);
- $$->members = $4;
- $$ = new_tag(ASN1_C_UNIV, UT_BitString, TE_EXPLICIT, $$);
- }
- ;
-
-ObjectIdentifierType: kw_OBJECT kw_IDENTIFIER
- {
- $$ = new_tag(ASN1_C_UNIV, UT_OID,
- TE_EXPLICIT, new_type(TOID));
- }
- ;
-OctetStringType : kw_OCTET kw_STRING size
- {
- Type *t = new_type(TOctetString);
- t->range = $3;
- $$ = new_tag(ASN1_C_UNIV, UT_OctetString,
- TE_EXPLICIT, t);
- }
- ;
-
-NullType : kw_NULL
- {
- $$ = new_tag(ASN1_C_UNIV, UT_Null,
- TE_EXPLICIT, new_type(TNull));
- }
- ;
-
-size :
- { $$ = NULL; }
- | kw_SIZE range
- { $$ = $2; }
- ;
-
-
-SequenceType : kw_SEQUENCE '{' /* ComponentTypeLists */ ComponentTypeList '}'
- {
- $$ = new_type(TSequence);
- $$->members = $3;
- $$ = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, $$);
- }
- | kw_SEQUENCE '{' '}'
- {
- $$ = new_type(TSequence);
- $$->members = NULL;
- $$ = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, $$);
- }
- ;
-
-SequenceOfType : kw_SEQUENCE size kw_OF Type
- {
- $$ = new_type(TSequenceOf);
- $$->range = $2;
- $$->subtype = $4;
- $$ = new_tag(ASN1_C_UNIV, UT_Sequence, TE_EXPLICIT, $$);
- }
- ;
-
-SetType : kw_SET '{' /* ComponentTypeLists */ ComponentTypeList '}'
- {
- $$ = new_type(TSet);
- $$->members = $3;
- $$ = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, $$);
- }
- | kw_SET '{' '}'
- {
- $$ = new_type(TSet);
- $$->members = NULL;
- $$ = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, $$);
- }
- ;
-
-SetOfType : kw_SET kw_OF Type
- {
- $$ = new_type(TSetOf);
- $$->subtype = $3;
- $$ = new_tag(ASN1_C_UNIV, UT_Set, TE_EXPLICIT, $$);
- }
- ;
-
-ChoiceType : kw_CHOICE '{' /* AlternativeTypeLists */ ComponentTypeList '}'
- {
- $$ = new_type(TChoice);
- $$->members = $3;
- }
- ;
-
-ReferencedType : DefinedType
- | UsefulType
- ;
-
-DefinedType : IDENTIFIER
- {
- Symbol *s = addsym($1);
- $$ = new_type(TType);
- if(s->stype != Stype && s->stype != SUndefined)
- error_message ("%s is not a type\n", $1);
- else
- $$->symbol = s;
- }
- ;
-
-UsefulType : kw_GeneralizedTime
- {
- $$ = new_tag(ASN1_C_UNIV, UT_GeneralizedTime,
- TE_EXPLICIT, new_type(TGeneralizedTime));
- }
- | kw_UTCTime
- {
- $$ = new_tag(ASN1_C_UNIV, UT_UTCTime,
- TE_EXPLICIT, new_type(TUTCTime));
- }
- ;
-
-ConstrainedType : Type Constraint
- {
- /* if (Constraint.type == contentConstrant) {
- assert(Constraint.u.constraint.type == octetstring|bitstring-w/o-NamedBitList); // remember to check type reference too
- if (Constraint.u.constraint.type) {
- assert((Constraint.u.constraint.type.length % 8) == 0);
- }
- }
- if (Constraint.u.constraint.encoding) {
- type == der-oid|ber-oid
- }
- */
- }
- ;
-
-
-Constraint : '(' ConstraintSpec ')'
- {
- $$ = $2;
- }
- ;
-
-ConstraintSpec : GeneralConstraint
- ;
-
-GeneralConstraint: ContentsConstraint
- | UserDefinedConstraint
- ;
-
-ContentsConstraint: kw_CONTAINING Type
- {
- $$ = new_constraint_spec(CT_CONTENTS);
- $$->u.content.type = $2;
- $$->u.content.encoding = NULL;
- }
- | kw_ENCODED kw_BY Value
- {
- if ($3->type != objectidentifiervalue)
- error_message("Non-OID used in ENCODED BY constraint");
- $$ = new_constraint_spec(CT_CONTENTS);
- $$->u.content.type = NULL;
- $$->u.content.encoding = $3;
- }
- | kw_CONTAINING Type kw_ENCODED kw_BY Value
- {
- if ($5->type != objectidentifiervalue)
- error_message("Non-OID used in ENCODED BY constraint");
- $$ = new_constraint_spec(CT_CONTENTS);
- $$->u.content.type = $2;
- $$->u.content.encoding = $5;
- }
- ;
-
-UserDefinedConstraint: kw_CONSTRAINED kw_BY '{' '}'
- {
- $$ = new_constraint_spec(CT_USER);
- }
- ;
-
-TaggedType : Tag tagenv Type
- {
- $$ = new_type(TTag);
- $$->tag = $1;
- $$->tag.tagenv = $2;
- if($3->type == TTag && $2 == TE_IMPLICIT) {
- $$->subtype = $3->subtype;
- free($3);
- } else
- $$->subtype = $3;
- }
- ;
-
-Tag : '[' Class NUMBER ']'
- {
- $$.tagclass = $2;
- $$.tagvalue = $3;
- $$.tagenv = TE_EXPLICIT;
- }
- ;
-
-Class : /* */
- {
- $$ = ASN1_C_CONTEXT;
- }
- | kw_UNIVERSAL
- {
- $$ = ASN1_C_UNIV;
- }
- | kw_APPLICATION
- {
- $$ = ASN1_C_APPL;
- }
- | kw_PRIVATE
- {
- $$ = ASN1_C_PRIVATE;
- }
- ;
-
-tagenv : /* */
- {
- $$ = TE_EXPLICIT;
- }
- | kw_EXPLICIT
- {
- $$ = TE_EXPLICIT;
- }
- | kw_IMPLICIT
- {
- $$ = TE_IMPLICIT;
- }
- ;
-
-
-ValueAssignment : IDENTIFIER Type EEQUAL Value
- {
- Symbol *s;
- s = addsym ($1);
-
- s->stype = SValue;
- s->value = $4;
- generate_constant (s);
- }
- ;
-
-CharacterStringType: RestrictedCharactedStringType
- ;
-
-RestrictedCharactedStringType: kw_GeneralString
- {
- $$ = new_tag(ASN1_C_UNIV, UT_GeneralString,
- TE_EXPLICIT, new_type(TGeneralString));
- }
- | kw_UTF8String
- {
- $$ = new_tag(ASN1_C_UNIV, UT_UTF8String,
- TE_EXPLICIT, new_type(TUTF8String));
- }
- | kw_PrintableString
- {
- $$ = new_tag(ASN1_C_UNIV, UT_PrintableString,
- TE_EXPLICIT, new_type(TPrintableString));
- }
- | kw_VisibleString
- {
- $$ = new_tag(ASN1_C_UNIV, UT_VisibleString,
- TE_EXPLICIT, new_type(TVisibleString));
- }
- | kw_IA5String
- {
- $$ = new_tag(ASN1_C_UNIV, UT_IA5String,
- TE_EXPLICIT, new_type(TIA5String));
- }
- | kw_BMPString
- {
- $$ = new_tag(ASN1_C_UNIV, UT_BMPString,
- TE_EXPLICIT, new_type(TBMPString));
- }
- | kw_UniversalString
- {
- $$ = new_tag(ASN1_C_UNIV, UT_UniversalString,
- TE_EXPLICIT, new_type(TUniversalString));
- }
-
- ;
-
-ComponentTypeList: ComponentType
- {
- $$ = emalloc(sizeof(*$$));
- ASN1_TAILQ_INIT($$);
- ASN1_TAILQ_INSERT_HEAD($$, $1, members);
- }
- | ComponentTypeList ',' ComponentType
- {
- ASN1_TAILQ_INSERT_TAIL($1, $3, members);
- $$ = $1;
- }
- | ComponentTypeList ',' ELLIPSIS
- {
- struct member *m = ecalloc(1, sizeof(*m));
- m->name = estrdup("...");
- m->gen_name = estrdup("asn1_ellipsis");
- m->ellipsis = 1;
- ASN1_TAILQ_INSERT_TAIL($1, m, members);
- $$ = $1;
- }
- ;
-
-NamedType : IDENTIFIER Type
- {
- $$ = emalloc(sizeof(*$$));
- $$->name = $1;
- $$->gen_name = estrdup($1);
- output_name ($$->gen_name);
- $$->type = $2;
- $$->ellipsis = 0;
- }
- ;
-
-ComponentType : NamedType
- {
- $$ = $1;
- $$->optional = 0;
- $$->defval = NULL;
- }
- | NamedType kw_OPTIONAL
- {
- $$ = $1;
- $$->optional = 1;
- $$->defval = NULL;
- }
- | NamedType kw_DEFAULT Value
- {
- $$ = $1;
- $$->optional = 0;
- $$->defval = $3;
- }
- ;
-
-NamedBitList : NamedBit
- {
- $$ = emalloc(sizeof(*$$));
- ASN1_TAILQ_INIT($$);
- ASN1_TAILQ_INSERT_HEAD($$, $1, members);
- }
- | NamedBitList ',' NamedBit
- {
- ASN1_TAILQ_INSERT_TAIL($1, $3, members);
- $$ = $1;
- }
- ;
-
-NamedBit : IDENTIFIER '(' NUMBER ')'
- {
- $$ = emalloc(sizeof(*$$));
- $$->name = $1;
- $$->gen_name = estrdup($1);
- output_name ($$->gen_name);
- $$->val = $3;
- $$->optional = 0;
- $$->ellipsis = 0;
- $$->type = NULL;
- }
- ;
-
-objid_opt : objid
- | /* empty */ { $$ = NULL; }
- ;
-
-objid : '{' objid_list '}'
- {
- $$ = $2;
- }
- ;
-
-objid_list : /* empty */
- {
- $$ = NULL;
- }
- | objid_element objid_list
- {
- if ($2) {
- $$ = $2;
- add_oid_to_tail($2, $1);
- } else {
- $$ = $1;
- }
- }
- ;
-
-objid_element : IDENTIFIER '(' NUMBER ')'
- {
- $$ = new_objid($1, $3);
- }
- | IDENTIFIER
- {
- Symbol *s = addsym($1);
- if(s->stype != SValue ||
- s->value->type != objectidentifiervalue) {
- error_message("%s is not an object identifier\n",
- s->name);
- exit(1);
- }
- $$ = s->value->u.objectidentifiervalue;
- }
- | NUMBER
- {
- $$ = new_objid(NULL, $1);
- }
- ;
-
-Value : BuiltinValue
- | ReferencedValue
- ;
-
-BuiltinValue : BooleanValue
- | CharacterStringValue
- | IntegerValue
- | ObjectIdentifierValue
- | NullValue
- ;
-
-ReferencedValue : DefinedValue
- ;
-
-DefinedValue : Valuereference
- ;
-
-Valuereference : IDENTIFIER
- {
- Symbol *s = addsym($1);
- if(s->stype != SValue)
- error_message ("%s is not a value\n",
- s->name);
- else
- $$ = s->value;
- }
- ;
-
-CharacterStringValue: STRING
- {
- $$ = emalloc(sizeof(*$$));
- $$->type = stringvalue;
- $$->u.stringvalue = $1;
- }
- ;
-
-BooleanValue : kw_TRUE
- {
- $$ = emalloc(sizeof(*$$));
- $$->type = booleanvalue;
- $$->u.booleanvalue = 0;
- }
- | kw_FALSE
- {
- $$ = emalloc(sizeof(*$$));
- $$->type = booleanvalue;
- $$->u.booleanvalue = 0;
- }
- ;
-
-IntegerValue : SignedNumber
- {
- $$ = emalloc(sizeof(*$$));
- $$->type = integervalue;
- $$->u.integervalue = $1;
- }
- ;
-
-SignedNumber : NUMBER
- ;
-
-NullValue : kw_NULL
- {
- }
- ;
-
-ObjectIdentifierValue: objid
- {
- $$ = emalloc(sizeof(*$$));
- $$->type = objectidentifiervalue;
- $$->u.objectidentifiervalue = $1;
- }
- ;
-
-%%
-
-void
-yyerror (const char *s)
-{
- error_message ("%s\n", s);
-}
-
-static Type *
-new_tag(int tagclass, int tagvalue, int tagenv, Type *oldtype)
-{
- Type *t;
- if(oldtype->type == TTag && oldtype->tag.tagenv == TE_IMPLICIT) {
- t = oldtype;
- oldtype = oldtype->subtype; /* XXX */
- } else
- t = new_type (TTag);
-
- t->tag.tagclass = tagclass;
- t->tag.tagvalue = tagvalue;
- t->tag.tagenv = tagenv;
- t->subtype = oldtype;
- return t;
-}
-
-static struct objid *
-new_objid(const char *label, int value)
-{
- struct objid *s;
- s = emalloc(sizeof(*s));
- s->label = label;
- s->value = value;
- s->next = NULL;
- return s;
-}
-
-static void
-add_oid_to_tail(struct objid *head, struct objid *tail)
-{
- struct objid *o;
- o = head;
- while (o->next)
- o = o->next;
- o->next = tail;
-}
-
-static Type *
-new_type (Typetype tt)
-{
- Type *t = ecalloc(1, sizeof(*t));
- t->type = tt;
- return t;
-}
-
-static struct constraint_spec *
-new_constraint_spec(enum ctype ct)
-{
- struct constraint_spec *c = ecalloc(1, sizeof(*c));
- c->ctype = ct;
- return c;
-}
-
-static void fix_labels2(Type *t, const char *prefix);
-static void fix_labels1(struct memhead *members, const char *prefix)
-{
- Member *m;
-
- if(members == NULL)
- return;
- ASN1_TAILQ_FOREACH(m, members, members) {
- asprintf(&m->label, "%s_%s", prefix, m->gen_name);
- if (m->label == NULL)
- errx(1, "malloc");
- if(m->type != NULL)
- fix_labels2(m->type, m->label);
- }
-}
-
-static void fix_labels2(Type *t, const char *prefix)
-{
- for(; t; t = t->subtype)
- fix_labels1(t->members, prefix);
-}
-
-static void
-fix_labels(Symbol *s)
-{
- char *p;
- asprintf(&p, "choice_%s", s->gen_name);
- if (p == NULL)
- errx(1, "malloc");
- fix_labels2(s->type, p);
- free(p);
-}
diff --git a/source4/heimdal/lib/asn1/pkcs12.asn1 b/source4/heimdal/lib/asn1/pkcs12.asn1
index 4d6454a08f..8b604c68d7 100644
--- a/source4/heimdal/lib/asn1/pkcs12.asn1
+++ b/source4/heimdal/lib/asn1/pkcs12.asn1
@@ -50,7 +50,7 @@ PKCS12-AuthenticatedSafe ::= SEQUENCE OF ContentInfo
PKCS12-Attribute ::= SEQUENCE {
attrId OBJECT IDENTIFIER,
- attrValues -- SET OF -- heim_any_set
+ attrValues -- SET OF -- heim_any_set
}
PKCS12-Attributes ::= SET OF PKCS12-Attribute
diff --git a/source4/heimdal/lib/asn1/pkcs8.asn1 b/source4/heimdal/lib/asn1/pkcs8.asn1
index 203d91eef8..45a7d715df 100644
--- a/source4/heimdal/lib/asn1/pkcs8.asn1
+++ b/source4/heimdal/lib/asn1/pkcs8.asn1
@@ -24,7 +24,7 @@ PKCS8EncryptedData ::= OCTET STRING
PKCS8EncryptedPrivateKeyInfo ::= SEQUENCE {
encryptionAlgorithm AlgorithmIdentifier,
- encryptedData PKCS8EncryptedData
+ encryptedData PKCS8EncryptedData
}
END
diff --git a/source4/heimdal/lib/asn1/pkinit.asn1 b/source4/heimdal/lib/asn1/pkinit.asn1
index 758af6f86e..f36ebf0b32 100644
--- a/source4/heimdal/lib/asn1/pkinit.asn1
+++ b/source4/heimdal/lib/asn1/pkinit.asn1
@@ -27,11 +27,11 @@ id-pkinit-san OBJECT IDENTIFIER ::=
x509-sanan(2) }
id-pkinit-ms-eku OBJECT IDENTIFIER ::=
- { iso(1) org(3) dod(6) internet(1) private(4)
+ { iso(1) org(3) dod(6) internet(1) private(4)
enterprise(1) microsoft(311) 20 2 2 }
id-pkinit-ms-san OBJECT IDENTIFIER ::=
- { iso(1) org(3) dod(6) internet(1) private(4)
+ { iso(1) org(3) dod(6) internet(1) private(4)
enterprise(1) microsoft(311) 20 2 3 }
MS-UPN-SAN ::= UTF8String
@@ -152,19 +152,18 @@ TrustedCA-Win2k ::= CHOICE {
issuerAndSerial [2] IssuerAndSerialNumber
}
-PA-PK-AS-REQ-Win2k ::= SEQUENCE {
- signed-auth-pack [0] IMPLICIT OCTET STRING,
- trusted-certifiers [2] SEQUENCE OF TrustedCA-Win2k OPTIONAL,
- kdc-cert [3] IMPLICIT OCTET STRING OPTIONAL,
+PA-PK-AS-REQ-Win2k ::= SEQUENCE {
+ signed-auth-pack [0] IMPLICIT OCTET STRING,
+ trusted-certifiers [2] SEQUENCE OF TrustedCA-Win2k OPTIONAL,
+ kdc-cert [3] IMPLICIT OCTET STRING OPTIONAL,
encryption-cert [4] IMPLICIT OCTET STRING OPTIONAL
}
PA-PK-AS-REP-Win2k ::= CHOICE {
- dhSignedData [0] IMPLICIT OCTET STRING,
+ dhSignedData [0] IMPLICIT OCTET STRING,
encKeyPack [1] IMPLICIT OCTET STRING
}
-
KDCDHKeyInfo-Win2k ::= SEQUENCE {
nonce [0] INTEGER (-2147483648..2147483647),
subjectPublicKey [2] BIT STRING
@@ -176,12 +175,18 @@ ReplyKeyPack-Win2k ::= SEQUENCE {
...
}
-PkinitSP80056AOtherInfo ::= SEQUENCE {
- algorithmID AlgorithmIdentifier,
- partyUInfo [0] OCTET STRING,
- partyVInfo [1] OCTET STRING,
- suppPubInfo [2] OCTET STRING OPTIONAL,
- suppPrivInfo [3] OCTET STRING OPTIONAL
+PA-PK-AS-REP-BTMM ::= SEQUENCE {
+ dhSignedData [0] heim_any OPTIONAL,
+ encKeyPack [1] heim_any OPTIONAL
+}
+
+
+PkinitSP80056AOtherInfo ::= SEQUENCE {
+ algorithmID AlgorithmIdentifier,
+ partyUInfo [0] OCTET STRING,
+ partyVInfo [1] OCTET STRING,
+ suppPubInfo [2] OCTET STRING OPTIONAL,
+ suppPrivInfo [3] OCTET STRING OPTIONAL
}
PkinitSuppPubInfo ::= SEQUENCE {
diff --git a/source4/heimdal/lib/asn1/rfc2459.asn1 b/source4/heimdal/lib/asn1/rfc2459.asn1
index 8e24f0740b..51cac55cc0 100644
--- a/source4/heimdal/lib/asn1/rfc2459.asn1
+++ b/source4/heimdal/lib/asn1/rfc2459.asn1
@@ -6,7 +6,7 @@ RFC2459 DEFINITIONS ::= BEGIN
IMPORTS heim_any FROM heim;
Version ::= INTEGER {
- rfc3280_version_1(0),
+ rfc3280_version_1(0),
rfc3280_version_2(1),
rfc3280_version_3(2)
}
@@ -29,7 +29,7 @@ id-pkcs2-md2 OBJECT IDENTIFIER ::= { id-pkcs-2 2 }
id-pkcs2-md4 OBJECT IDENTIFIER ::= { id-pkcs-2 4 }
id-pkcs2-md5 OBJECT IDENTIFIER ::= { id-pkcs-2 5 }
-id-rsa-digestAlgorithm OBJECT IDENTIFIER ::=
+id-rsa-digestAlgorithm OBJECT IDENTIFIER ::=
{ iso(1) member-body(2) us(840) rsadsi(113549) 2 }
id-rsa-digest-md2 OBJECT IDENTIFIER ::= { id-rsa-digestAlgorithm 2 }
@@ -54,7 +54,7 @@ id-secsig-sha-1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3)
id-nistAlgorithm OBJECT IDENTIFIER ::= {
joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) 4 }
-
+
id-nist-aes-algs OBJECT IDENTIFIER ::= { id-nistAlgorithm 1 }
id-aes-128-cbc OBJECT IDENTIFIER ::= { id-nist-aes-algs 2 }
@@ -72,9 +72,42 @@ id-dhpublicnumber OBJECT IDENTIFIER ::= {
iso(1) member-body(2) us(840) ansi-x942(10046)
number-type(2) 1 }
+-- ECC
+
+id-ecPublicKey OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 }
+
+id-ecDH OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) certicom(132) schemes(1)
+ ecdh(12) }
+
+id-ecMQV OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) certicom(132) schemes(1)
+ ecmqv(13) }
+
+id-ecdsa-with-SHA256 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4)
+ ecdsa-with-SHA2(3) 2 }
+
+id-ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 }
+
+-- some EC group ids
+
+id-ec-group-secp256r1 OBJECT IDENTIFIER ::= {
+ iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3)
+ prime(1) 7 }
+
+id-ec-group-secp160r1 OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) certicom(132) 0 8 }
+
+id-ec-group-secp160r2 OBJECT IDENTIFIER ::= {
+ iso(1) identified-organization(3) certicom(132) 0 30 }
+
+-- DSA
+
id-x9-57 OBJECT IDENTIFIER ::= {
- iso(1) member-body(2) us(840) ansi-x942(10046)
- 4 }
+ iso(1) member-body(2) us(840) ansi-x942(10046) 4 }
id-dsa OBJECT IDENTIFIER ::= { id-x9-57 1 }
id-dsa-with-sha1 OBJECT IDENTIFIER ::= { id-x9-57 3 }
@@ -256,8 +289,8 @@ KeyIdentifier ::= OCTET STRING
AuthorityKeyIdentifier ::= SEQUENCE {
keyIdentifier [0] IMPLICIT OCTET STRING OPTIONAL,
- authorityCertIssuer [1] IMPLICIT -- GeneralName --
- SEQUENCE -- SIZE (1..MAX) -- OF GeneralName OPTIONAL,
+ authorityCertIssuer [1] IMPLICIT -- GeneralName --
+ SEQUENCE -- SIZE (1..MAX) -- OF GeneralName OPTIONAL,
authorityCertSerialNumber [2] IMPLICIT INTEGER OPTIONAL
}
@@ -269,7 +302,7 @@ id-x509-ce-basicConstraints OBJECT IDENTIFIER ::= { id-x509-ce 19 }
BasicConstraints ::= SEQUENCE {
cA BOOLEAN OPTIONAL -- DEFAULT FALSE --,
- pathLenConstraint INTEGER (0..4294967295) OPTIONAL
+ pathLenConstraint INTEGER (0..4294967295) OPTIONAL
}
id-x509-ce-nameConstraints OBJECT IDENTIFIER ::= { id-x509-ce 30 }
@@ -350,6 +383,21 @@ DSAParams ::= SEQUENCE {
g INTEGER
}
+-- draft-ietf-pkix-ecc-subpubkeyinfo-11
+
+ECPoint ::= OCTET STRING
+
+ECParameters ::= CHOICE {
+ namedCurve OBJECT IDENTIFIER
+ -- implicitCurve NULL
+ -- specifiedCurve SpecifiedECDomain
+}
+
+ECDSA-Sig-Value ::= SEQUENCE {
+ r INTEGER,
+ s INTEGER
+}
+
-- really pkcs1
RSAPublicKey ::= SEQUENCE {
@@ -382,7 +430,7 @@ DigestInfo ::= SEQUENCE {
-- szOID_CERTIFICATE_TEMPLATE "1.3.6.1.4.1.311.21.7" is Encoded as:
--- TemplateVersion ::= INTEGER (0..4294967295)
+-- TemplateVersion ::= INTEGER (0..4294967295)
-- CertificateTemplate ::= SEQUENCE {
-- templateID OBJECT IDENTIFIER,
@@ -393,7 +441,7 @@ DigestInfo ::= SEQUENCE {
--
-- CRL
---
+--
TBSCRLCertList ::= SEQUENCE {
version Version OPTIONAL, -- if present, MUST be v2
@@ -489,16 +537,16 @@ id-uspkicommon-piv-interim OBJECT IDENTIFIER ::= { 2 16 840 1 101 3 6 9 1 }
--- Netscape extentions
-id-netscape OBJECT IDENTIFIER ::=
+id-netscape OBJECT IDENTIFIER ::=
{ joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730) }
id-netscape-cert-comment OBJECT IDENTIFIER ::= { id-netscape 1 13 }
--- MS extentions
-id-ms-cert-enroll-domaincontroller OBJECT IDENTIFIER ::=
+id-ms-cert-enroll-domaincontroller OBJECT IDENTIFIER ::=
{ 1 3 6 1 4 1 311 20 2 }
-id-ms-client-authentication OBJECT IDENTIFIER ::=
+id-ms-client-authentication OBJECT IDENTIFIER ::=
{ 1 3 6 1 5 5 7 3 2 }
-- DER:1e:20:00:44:00:6f:00:6d:00:61:00:69:00:6e:00:43:00:6f:00:6e:00:74:00:72:00:6f:00:6c:00:6c:00:65:00:72
diff --git a/source4/heimdal/lib/asn1/test.asn1 b/source4/heimdal/lib/asn1/test.asn1
index d07bba6185..f6237b85b8 100644
--- a/source4/heimdal/lib/asn1/test.asn1
+++ b/source4/heimdal/lib/asn1/test.asn1
@@ -20,12 +20,12 @@ TESTSeq ::= SEQUENCE {
TESTChoice1 ::= CHOICE {
i1[1] INTEGER (-2147483648..2147483647),
i2[2] INTEGER (-2147483648..2147483647),
- ...
+ ...
}
TESTChoice2 ::= CHOICE {
i1[1] INTEGER (-2147483648..2147483647),
- ...
+ ...
}
TESTInteger ::= INTEGER (-2147483648..2147483647)
@@ -35,7 +35,7 @@ TESTInteger3 ::= [5] IMPLICIT TESTInteger2
TESTImplicit ::= SEQUENCE {
ti1[0] IMPLICIT INTEGER (-2147483648..2147483647),
- ti2[1] IMPLICIT SEQUENCE {
+ ti2[1] IMPLICIT SEQUENCE {
foo[127] INTEGER (-2147483648..2147483647)
},
ti3[2] IMPLICIT [5] IMPLICIT [4] IMPLICIT INTEGER (-2147483648..2147483647)
@@ -59,19 +59,19 @@ TESTAlloc ::= SEQUENCE {
TESTCONTAINING ::= OCTET STRING ( CONTAINING INTEGER )
-TESTENCODEDBY ::= OCTET STRING ( ENCODED BY
+TESTENCODEDBY ::= OCTET STRING ( ENCODED BY
{ joint-iso-itu-t(2) asn(1) ber-derived(2) distinguished-encoding(1) }
)
-TESTDer OBJECT IDENTIFIER ::= {
+TESTDer OBJECT IDENTIFIER ::= {
joint-iso-itu-t(2) asn(1) ber-derived(2) distinguished-encoding(1)
}
-TESTCONTAININGENCODEDBY ::= OCTET STRING ( CONTAINING INTEGER ENCODED BY
+TESTCONTAININGENCODEDBY ::= OCTET STRING ( CONTAINING INTEGER ENCODED BY
{ joint-iso-itu-t(2) asn(1) ber-derived(2) distinguished-encoding(1) }
)
-TESTCONTAININGENCODEDBY2 ::= OCTET STRING (
+TESTCONTAININGENCODEDBY2 ::= OCTET STRING (
CONTAINING INTEGER ENCODED BY TESTDer
)
diff --git a/source4/heimdal/lib/com_err/com_err.c b/source4/heimdal/lib/com_err/com_err.c
index 89c8ab2c89..a43d1e3e6c 100644
--- a/source4/heimdal/lib/com_err/com_err.c
+++ b/source4/heimdal/lib/com_err/com_err.c
@@ -31,10 +31,9 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
+
#include <config.h>
-RCSID("$Id$");
-#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/source4/heimdal/lib/com_err/compile_et.c b/source4/heimdal/lib/com_err/compile_et.c
index 239617d1de..a28e51f8da 100644
--- a/source4/heimdal/lib/com_err/compile_et.c
+++ b/source4/heimdal/lib/com_err/compile_et.c
@@ -35,8 +35,6 @@
#include "compile_et.h"
#include <getarg.h>
-RCSID("$Id$");
-
#include <roken.h>
#include <err.h>
#include "parse.h"
diff --git a/source4/heimdal/lib/com_err/compile_et.h b/source4/heimdal/lib/com_err/compile_et.h
index 430405d9d5..b0b8e21da1 100644
--- a/source4/heimdal/lib/com_err/compile_et.h
+++ b/source4/heimdal/lib/com_err/compile_et.h
@@ -36,9 +36,7 @@
#ifndef __COMPILE_ET_H__
#define __COMPILE_ET_H__
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <err.h>
#include <stdio.h>
diff --git a/source4/heimdal/lib/com_err/error.c b/source4/heimdal/lib/com_err/error.c
index d64225a758..6b12c00c7a 100644
--- a/source4/heimdal/lib/com_err/error.c
+++ b/source4/heimdal/lib/com_err/error.c
@@ -31,10 +31,9 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
+
#include <config.h>
-RCSID("$Id$");
-#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/source4/heimdal/lib/com_err/lex.l b/source4/heimdal/lib/com_err/lex.l
index 84356405dd..b68814b21c 100644
--- a/source4/heimdal/lib/com_err/lex.l
+++ b/source4/heimdal/lib/com_err/lex.l
@@ -44,8 +44,6 @@
#include "parse.h"
#include "lex.h"
-RCSID("$Id$");
-
static unsigned lineno = 1;
static int getstring(void);
diff --git a/source4/heimdal/lib/com_err/parse.y b/source4/heimdal/lib/com_err/parse.y
index 99dddbe1e1..d64681d902 100644
--- a/source4/heimdal/lib/com_err/parse.y
+++ b/source4/heimdal/lib/com_err/parse.y
@@ -35,8 +35,6 @@
#include "compile_et.h"
#include "lex.h"
-RCSID("$Id$");
-
void yyerror (char *s);
static long name2number(const char *str);
diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi.h b/source4/heimdal/lib/gssapi/gssapi/gssapi.h
index f8b599a664..9fe2bb8b46 100644
--- a/source4/heimdal/lib/gssapi/gssapi/gssapi.h
+++ b/source4/heimdal/lib/gssapi/gssapi/gssapi.h
@@ -53,6 +53,10 @@
#endif
#endif
+#ifndef GSSAPI_DEPRECATED
+#define GSSAPI_DEPRECATED __attribute__((deprecated))
+#endif
+
/*
* Now define the three implementation-dependent types.
*/
@@ -102,6 +106,11 @@ typedef struct gss_buffer_set_desc_struct {
gss_buffer_desc *elements;
} gss_buffer_set_desc, *gss_buffer_set_t;
+typedef struct gss_iov_buffer_desc_struct {
+ OM_uint32 type;
+ gss_buffer_desc buffer;
+} gss_iov_buffer_desc, *gss_iov_buffer_t;
+
/*
* For now, define a QOP-type as an OM_uint32
*/
@@ -178,6 +187,7 @@ typedef OM_uint32 gss_qop_t;
#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0)
#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0)
#define GSS_C_EMPTY_BUFFER {0, NULL}
+#define GSS_C_NO_IOV_BUFFER ((gss_iov_buffer_t)0)
/*
* Some alternate names for a couple of the above
@@ -206,6 +216,27 @@ typedef OM_uint32 gss_qop_t;
*/
#define GSS_C_INDEFINITE 0xfffffffful
+/*
+ * Type of gss_wrap_iov()/gss_unwrap_iov().
+ */
+
+#define GSS_IOV_BUFFER_TYPE_EMPTY 0
+#define GSS_IOV_BUFFER_TYPE_DATA 1
+#define GSS_IOV_BUFFER_TYPE_HEADER 2
+#define GSS_IOV_BUFFER_TYPE_MECH_PARAMS 3
+
+#define GSS_IOV_BUFFER_TYPE_TRAILER 7
+#define GSS_IOV_BUFFER_TYPE_PADDING 9
+#define GSS_IOV_BUFFER_TYPE_STREAM 10
+#define GSS_IOV_BUFFER_TYPE_SIGN_ONLY 11
+
+#define GSS_IOV_BUFFER_TYPE_FLAG_MASK 0xffff0000
+#define GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE 0x00010000
+#define GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED 0x00020000
+
+#define GSS_IOV_BUFFER_TYPE(_t) ((_t) & ~GSS_IOV_BUFFER_TYPE_FLAG_MASK)
+#define GSS_IOV_BUFFER_FLAGS(_t) ((_t) & GSS_IOV_BUFFER_TYPE_FLAG_MASK)
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -311,12 +342,6 @@ extern GSSAPI_LIB_VARIABLE gss_OID GSS_C_NT_EXPORT_NAME;
extern GSSAPI_LIB_VARIABLE gss_OID GSS_SASL_DIGEST_MD5_MECHANISM;
-/*
- * NTLM mechanism
- */
-
-extern GSSAPI_LIB_VARIABLE gss_OID GSS_NTLM_MECHANISM;
-
/* Major status codes */
#define GSS_S_COMPLETE 0
@@ -744,6 +769,75 @@ gss_pseudo_random
);
/*
+ * AEAD support
+ */
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_wrap_iov(OM_uint32 * /* minor_status */,
+ gss_ctx_id_t /* context_handle */,
+ int /* conf_req_flag */,
+ gss_qop_t /* qop_req */,
+ int * /* conf_state */,
+ gss_iov_buffer_desc * /*iov */,
+ int /* iov_count */);
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_unwrap_iov(OM_uint32 * /* minor_status */,
+ gss_ctx_id_t /* context_handle */,
+ int * /* conf_state */,
+ gss_qop_t * /* qop_state */,
+ gss_iov_buffer_desc * /* iov */,
+ int /* iov_count */);
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_wrap_iov_length(OM_uint32 * /* minor_status */,
+ gss_ctx_id_t /* context_handle */,
+ int /* conf_req_flag */,
+ gss_qop_t /* qop_req */,
+ int * /* conf_state */,
+ gss_iov_buffer_desc * /* iov */,
+ int /* iov_count */);
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_release_iov_buffer(OM_uint32 * /* minor_status */,
+ gss_iov_buffer_desc * /* iov */,
+ int /* iov_count */);
+
+
+OM_uint32
+gss_store_cred(OM_uint32 * /* minor_status */,
+ gss_cred_id_t /* input_cred_handle */,
+ gss_cred_usage_t /* cred_usage */,
+ const gss_OID /* desired_mech */,
+ OM_uint32 /* overwrite_cred */,
+ OM_uint32 /* default_cred */,
+ gss_OID_set * /* elements_stored */,
+ gss_cred_usage_t * /* cred_usage_stored */);
+
+
+/*
+ * Query functions
+ */
+
+typedef struct {
+ size_t header; /**< size of header */
+ size_t trailer; /**< size of trailer */
+ size_t max_msg_size; /**< maximum message size */
+ size_t buffers; /**< extra GSS_IOV_BUFFER_TYPE_EMPTY buffer to pass */
+ size_t blocksize; /**< Specificed optimal size of messages, also
+ is the maximum padding size
+ (GSS_IOV_BUFFER_TYPE_PADDING) */
+} gss_context_stream_sizes;
+
+extern gss_OID GSSAPI_LIB_VARIABLE GSS_C_ATTR_STREAM_SIZES;
+
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_context_query_attributes(OM_uint32 * /* minor_status */,
+ gss_OID /* attribute */,
+ void * /*data*/,
+ size_t /* len */);
+/*
* The following routines are obsolete variants of gss_get_mic,
* gss_verify_mic, gss_wrap and gss_unwrap. They should be
* provided by GSSAPI V2 implementations for backwards
@@ -754,7 +848,7 @@ gss_pseudo_random
* obsolete versions of these routines and their current forms.
*/
-OM_uint32 GSSAPI_LIB_FUNCTION gss_sign
+OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_sign
(OM_uint32 * /*minor_status*/,
gss_ctx_id_t /*context_handle*/,
int /*qop_req*/,
@@ -762,7 +856,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_sign
gss_buffer_t /*message_token*/
);
-OM_uint32 GSSAPI_LIB_FUNCTION gss_verify
+OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_verify
(OM_uint32 * /*minor_status*/,
gss_ctx_id_t /*context_handle*/,
gss_buffer_t /*message_buffer*/,
@@ -770,7 +864,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_verify
int * /*qop_state*/
);
-OM_uint32 GSSAPI_LIB_FUNCTION gss_seal
+OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_seal
(OM_uint32 * /*minor_status*/,
gss_ctx_id_t /*context_handle*/,
int /*conf_req_flag*/,
@@ -780,7 +874,7 @@ OM_uint32 GSSAPI_LIB_FUNCTION gss_seal
gss_buffer_t /*output_message_buffer*/
);
-OM_uint32 GSSAPI_LIB_FUNCTION gss_unseal
+OM_uint32 GSSAPI_LIB_FUNCTION GSSAPI_DEPRECATED gss_unseal
(OM_uint32 * /*minor_status*/,
gss_ctx_id_t /*context_handle*/,
gss_buffer_t /*input_message_buffer*/,
@@ -809,7 +903,4 @@ gss_decapsulate_token(gss_buffer_t /* input_token */,
}
#endif
-#include <gssapi/gssapi_krb5.h>
-#include <gssapi/gssapi_spnego.h>
-
#endif /* GSSAPI_GSSAPI_H_ */
diff --git a/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h b/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h
index a821f73d2a..0baccf5098 100644
--- a/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h
+++ b/source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h
@@ -36,7 +36,7 @@
#ifndef GSSAPI_KRB5_H_
#define GSSAPI_KRB5_H_
-#include <gssapi/gssapi.h>
+#include <gssapi.h>
#ifdef __cplusplus
extern "C" {
diff --git a/source4/heimdal/lib/gssapi/gssapi_mech.h b/source4/heimdal/lib/gssapi/gssapi_mech.h
index b360de13fc..6470df30a0 100644
--- a/source4/heimdal/lib/gssapi/gssapi_mech.h
+++ b/source4/heimdal/lib/gssapi/gssapi_mech.h
@@ -307,7 +307,45 @@ typedef OM_uint32 _gss_pseudo_random(
gss_buffer_t prf_out
);
-#define GMI_VERSION 1
+typedef OM_uint32
+_gss_wrap_iov_t(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ int * conf_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count);
+
+typedef OM_uint32
+_gss_unwrap_iov_t(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ int *conf_state,
+ gss_qop_t *qop_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count);
+
+typedef OM_uint32
+_gss_wrap_iov_length_t(OM_uint32 * minor_status,
+ gss_ctx_id_t context_handle,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ int *conf_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count);
+
+typedef OM_uint32
+_gss_store_cred_t(OM_uint32 *minor_status,
+ gss_cred_id_t input_cred_handle,
+ gss_cred_usage_t cred_usage,
+ const gss_OID desired_mech,
+ OM_uint32 overwrite_cred,
+ OM_uint32 default_cred,
+ gss_OID_set *elements_stored,
+ gss_cred_usage_t *cred_usage_stored);
+
+
+
+#define GMI_VERSION 2
typedef struct gssapi_mech_interface_desc {
unsigned gm_version;
@@ -347,6 +385,10 @@ typedef struct gssapi_mech_interface_desc {
_gss_set_sec_context_option *gm_set_sec_context_option;
_gss_set_cred_option *gm_set_cred_option;
_gss_pseudo_random *gm_pseudo_random;
+ _gss_wrap_iov_t *gm_wrap_iov;
+ _gss_unwrap_iov_t *gm_unwrap_iov;
+ _gss_wrap_iov_length_t *gm_wrap_iov_length;
+ _gss_store_cred_t *gm_store_cred;
} gssapi_mech_interface_desc, *gssapi_mech_interface;
gssapi_mech_interface
diff --git a/source4/heimdal/lib/gssapi/krb5/8003.c b/source4/heimdal/lib/gssapi/krb5/8003.c
index 119d49a0c5..f5181cc311 100644
--- a/source4/heimdal/lib/gssapi/krb5/8003.c
+++ b/source4/heimdal/lib/gssapi/krb5/8003.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
index 626afa9384..e0944852a7 100644
--- a/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
+++ b/source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -74,12 +74,10 @@ _gsskrb5_register_acceptor_identity (const char *identity)
}
void
-_gsskrb5i_is_cfx(gsskrb5_ctx ctx, int *is_cfx)
+_gsskrb5i_is_cfx(krb5_context context, gsskrb5_ctx ctx, int acceptor)
{
+ krb5_error_code ret;
krb5_keyblock *key;
- int acceptor = (ctx->more_flags & LOCAL) == 0;
-
- *is_cfx = 0;
if (acceptor) {
if (ctx->auth_context->local_subkey)
@@ -108,12 +106,16 @@ _gsskrb5i_is_cfx(gsskrb5_ctx ctx, int *is_cfx)
case ETYPE_ARCFOUR_HMAC_MD5_56:
break;
default :
- *is_cfx = 1;
+ ctx->more_flags |= IS_CFX;
+
if ((acceptor && ctx->auth_context->local_subkey) ||
(!acceptor && ctx->auth_context->remote_subkey))
ctx->more_flags |= ACCEPTOR_SUBKEY;
break;
}
+ if (ctx->crypto)
+ krb5_crypto_destroy(context, ctx->crypto);
+ ret = krb5_crypto_init(context, key, 0, &ctx->crypto);
}
@@ -136,7 +138,8 @@ gsskrb5_accept_delegated_token
kret = krb5_cc_default (context, &ccache);
} else {
*delegated_cred_handle = NULL;
- kret = krb5_cc_gen_new (context, &krb5_mcc_ops, &ccache);
+ kret = krb5_cc_new_unique (context, krb5_cc_type_memory,
+ NULL, &ccache);
}
if (kret) {
ctx->flags &= ~GSS_C_DELEG_FLAG;
@@ -210,7 +213,8 @@ gsskrb5_acceptor_ready(OM_uint32 * minor_status,
ctx->auth_context,
&seq_number);
- _gsskrb5i_is_cfx(ctx, &is_cfx);
+ _gsskrb5i_is_cfx(context, ctx, 1);
+ is_cfx = (ctx->more_flags & IS_CFX);
ret = _gssapi_msg_order_create(minor_status,
&ctx->order,
@@ -381,7 +385,7 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
server,
in, &out);
krb5_rd_req_in_ctx_free(context, in);
- if (kret == KRB5KRB_AP_ERR_SKEW) {
+ if (kret == KRB5KRB_AP_ERR_SKEW || kret == KRB5KRB_AP_ERR_TKT_NYV) {
/*
* No reply in non-MUTUAL mode, but we don't know that its
* non-MUTUAL mode yet, thats inside the 8003 checksum, so
@@ -526,7 +530,8 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
krb5_data outbuf;
int use_subkey = 0;
- _gsskrb5i_is_cfx(ctx, &is_cfx);
+ _gsskrb5i_is_cfx(context, ctx, 1);
+ is_cfx = (ctx->more_flags & IS_CFX);
if (is_cfx || (ap_options & AP_OPTS_USE_SUBKEY)) {
use_subkey = 1;
diff --git a/source4/heimdal/lib/gssapi/krb5/acquire_cred.c b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c
index be680840f5..bfab5667be 100644
--- a/source4/heimdal/lib/gssapi/krb5/acquire_cred.c
+++ b/source4/heimdal/lib/gssapi/krb5/acquire_cred.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -187,7 +187,8 @@ static OM_uint32 acquire_initiator_cred
krb5_get_init_creds_opt_free(context, opt);
if (kret)
goto end;
- kret = krb5_cc_gen_new(context, &krb5_mcc_ops, &ccache);
+ kret = krb5_cc_new_unique(context, krb5_cc_type_memory,
+ NULL, &ccache);
if (kret)
goto end;
kret = krb5_cc_initialize(context, ccache, cred.client);
diff --git a/source4/heimdal/lib/gssapi/krb5/add_cred.c b/source4/heimdal/lib/gssapi/krb5/add_cred.c
index d6fd8f6f15..aa96a45e45 100644
--- a/source4/heimdal/lib/gssapi/krb5/add_cred.c
+++ b/source4/heimdal/lib/gssapi/krb5/add_cred.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -168,8 +168,8 @@ OM_uint32 _gsskrb5_add_cred (
}
if (strcmp(type, "MEMORY") == 0) {
- ret = krb5_cc_gen_new(context, &krb5_mcc_ops,
- &handle->ccache);
+ ret = krb5_cc_new_unique(context, type,
+ NULL, &handle->ccache);
if (ret) {
*minor_status = ret;
goto failure;
diff --git a/source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c b/source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c
index ff0afdc059..fa115d964a 100644
--- a/source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c
+++ b/source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
#include <roken.h>
diff --git a/source4/heimdal/lib/gssapi/krb5/aeap.c b/source4/heimdal/lib/gssapi/krb5/aeap.c
new file mode 100644
index 0000000000..7dab7877d7
--- /dev/null
+++ b/source4/heimdal/lib/gssapi/krb5/aeap.c
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2008 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden).
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "gsskrb5_locl.h"
+
+#include <roken.h>
+
+static OM_uint32
+iov_allocate(OM_uint32 *minor_status, gss_iov_buffer_desc *iov, int iov_count)
+{
+ unsigned int i;
+
+ for (i = 0; i < iov_count; i++) {
+ if (GSS_IOV_BUFFER_FLAGS(iov[i].type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE){
+ void *ptr = malloc(iov[i].buffer.length);
+ if (ptr == NULL)
+ abort();
+ if (iov[i].buffer.value)
+ memcpy(ptr, iov[i].buffer.value, iov[i].buffer.length);
+ iov[i].buffer.value = ptr;
+ iov[i].type |= GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED;
+ }
+ }
+ return GSS_S_COMPLETE;
+}
+
+static OM_uint32
+iov_map(OM_uint32 *minor_status,
+ const gss_iov_buffer_desc *iov,
+ int iov_count,
+ krb5_crypto_iov *data)
+{
+ unsigned int i;
+
+ for (i = 0; i < iov_count; i++) {
+ switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) {
+ case GSS_IOV_BUFFER_TYPE_EMPTY:
+ data[i].flags = KRB5_CRYPTO_TYPE_EMPTY;
+ break;
+ case GSS_IOV_BUFFER_TYPE_DATA:
+ data[i].flags = KRB5_CRYPTO_TYPE_DATA;
+ break;
+ case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
+ data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+ break;
+ case GSS_IOV_BUFFER_TYPE_HEADER:
+ data[i].flags = KRB5_CRYPTO_TYPE_HEADER;
+ break;
+ case GSS_IOV_BUFFER_TYPE_TRAILER:
+ data[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
+ break;
+ case GSS_IOV_BUFFER_TYPE_PADDING:
+ data[i].flags = KRB5_CRYPTO_TYPE_PADDING;
+ break;
+ case GSS_IOV_BUFFER_TYPE_STREAM:
+ abort();
+ break;
+ default:
+ *minor_status = EINVAL;
+ return GSS_S_FAILURE;
+ }
+ data[i].data.data = iov[i].buffer.value;
+ data[i].data.length = iov[i].buffer.length;
+ }
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+_gk_wrap_iov(OM_uint32 * minor_status,
+ gss_ctx_id_t context_handle,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ int * conf_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count)
+{
+ gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
+ krb5_context context;
+ OM_uint32 major_status, junk;
+ krb5_crypto_iov *data;
+ krb5_error_code ret;
+ unsigned usage;
+
+ GSSAPI_KRB5_INIT (&context);
+
+ major_status = iov_allocate(minor_status, iov, iov_count);
+ if (major_status != GSS_S_COMPLETE)
+ return major_status;
+
+ data = calloc(iov_count, sizeof(data[0]));
+ if (data == NULL) {
+ gss_release_iov_buffer(&junk, iov, iov_count);
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+
+ major_status = iov_map(minor_status, iov, iov_count, data);
+ if (major_status != GSS_S_COMPLETE) {
+ gss_release_iov_buffer(&junk, iov, iov_count);
+ free(data);
+ return major_status;
+ }
+
+ if (ctx->more_flags & LOCAL) {
+ usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;
+ } else {
+ usage = KRB5_KU_USAGE_INITIATOR_SIGN;
+ }
+
+ ret = krb5_encrypt_iov_ivec(context, ctx->crypto, usage,
+ data, iov_count, NULL);
+ free(data);
+ if (ret) {
+ gss_release_iov_buffer(&junk, iov, iov_count);
+ *minor_status = ret;
+ return GSS_S_FAILURE;
+ }
+
+ *minor_status = 0;
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+_gk_unwrap_iov(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ int *conf_state,
+ gss_qop_t *qop_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count)
+{
+ gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
+ krb5_context context;
+ krb5_error_code ret;
+ OM_uint32 major_status, junk;
+ krb5_crypto_iov *data;
+ unsigned usage;
+
+ GSSAPI_KRB5_INIT (&context);
+
+ major_status = iov_allocate(minor_status, iov, iov_count);
+ if (major_status != GSS_S_COMPLETE)
+ return major_status;
+
+ data = calloc(iov_count, sizeof(data[0]));
+ if (data == NULL) {
+ gss_release_iov_buffer(&junk, iov, iov_count);
+ *minor_status = ENOMEM;
+ return GSS_S_FAILURE;
+ }
+
+ major_status = iov_map(minor_status, iov, iov_count, data);
+ if (major_status != GSS_S_COMPLETE) {
+ gss_release_iov_buffer(&junk, iov, iov_count);
+ free(data);
+ return major_status;
+ }
+
+ if (ctx->more_flags & LOCAL) {
+ usage = KRB5_KU_USAGE_INITIATOR_SIGN;
+ } else {
+ usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;
+ }
+
+ ret = krb5_decrypt_iov_ivec(context, ctx->crypto, usage,
+ data, iov_count, NULL);
+ free(data);
+ if (ret) {
+ *minor_status = ret;
+ gss_release_iov_buffer(&junk, iov, iov_count);
+ return GSS_S_FAILURE;
+ }
+
+ *minor_status = 0;
+ return GSS_S_COMPLETE;
+}
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+_gk_wrap_iov_length(OM_uint32 * minor_status,
+ gss_ctx_id_t context_handle,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ int *conf_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count)
+{
+ gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
+ krb5_context context;
+ unsigned int i;
+ size_t size;
+ size_t *padding = NULL;
+
+ GSSAPI_KRB5_INIT (&context);
+ *minor_status = 0;
+
+ for (size = 0, i = 0; i < iov_count; i++) {
+ switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) {
+ case GSS_IOV_BUFFER_TYPE_EMPTY:
+ break;
+ case GSS_IOV_BUFFER_TYPE_DATA:
+ size += iov[i].buffer.length;
+ break;
+ case GSS_IOV_BUFFER_TYPE_HEADER:
+ iov[i].buffer.length =
+ krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER);
+ size += iov[i].buffer.length;
+ break;
+ case GSS_IOV_BUFFER_TYPE_TRAILER:
+ iov[i].buffer.length =
+ krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER);
+ size += iov[i].buffer.length;
+ break;
+ case GSS_IOV_BUFFER_TYPE_PADDING:
+ if (padding != NULL) {
+ *minor_status = 0;
+ return GSS_S_FAILURE;
+ }
+ padding = &iov[i].buffer.length;
+ break;
+ case GSS_IOV_BUFFER_TYPE_STREAM:
+ size += iov[i].buffer.length;
+ break;
+ case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
+ break;
+ default:
+ *minor_status = EINVAL;
+ return GSS_S_FAILURE;
+ }
+ }
+ if (padding) {
+ size_t pad = krb5_crypto_length(context, ctx->crypto,
+ KRB5_CRYPTO_TYPE_PADDING);
+ if (pad > 1) {
+ *padding = pad - (size % pad);
+ if (*padding == pad)
+ *padding = 0;
+ } else
+ *padding = 0;
+ }
+
+ return GSS_S_COMPLETE;
+}
diff --git a/source4/heimdal/lib/gssapi/krb5/arcfour.c b/source4/heimdal/lib/gssapi/krb5/arcfour.c
index 7288b58493..b48cfebcf1 100644
--- a/source4/heimdal/lib/gssapi/krb5/arcfour.c
+++ b/source4/heimdal/lib/gssapi/krb5/arcfour.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c b/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c
index fa2258ce82..3a206b1be1 100644
--- a/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c
+++ b/source4/heimdal/lib/gssapi/krb5/canonicalize_name.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/cfx.c b/source4/heimdal/lib/gssapi/krb5/cfx.c
index d029f55ce4..7ae26e2e7a 100755
--- a/source4/heimdal/lib/gssapi/krb5/cfx.c
+++ b/source4/heimdal/lib/gssapi/krb5/cfx.c
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -101,49 +101,47 @@ _gsskrb5cfx_wrap_length_cfx(const gsskrb5_ctx context_handle,
return 0;
}
-krb5_error_code
-_gsskrb5cfx_max_wrap_length_cfx(krb5_context context,
- krb5_crypto crypto,
+OM_uint32 _gssapi_wrap_size_cfx(OM_uint32 *minor_status,
+ const gsskrb5_ctx ctx,
+ krb5_context context,
int conf_req_flag,
- size_t input_length,
- OM_uint32 *output_length)
+ gss_qop_t qop_req,
+ OM_uint32 req_output_size,
+ OM_uint32 *max_input_size)
{
krb5_error_code ret;
- *output_length = 0;
+ *max_input_size = 0;
/* 16-byte header is always first */
- if (input_length < 16)
+ if (req_output_size < 16)
return 0;
- input_length -= 16;
+ req_output_size -= 16;
if (conf_req_flag) {
size_t wrapped_size, sz;
- wrapped_size = input_length + 1;
+ wrapped_size = req_output_size + 1;
do {
wrapped_size--;
sz = krb5_get_wrapped_length(context,
- crypto, wrapped_size);
- } while (wrapped_size && sz > input_length);
- if (wrapped_size == 0) {
- *output_length = 0;
+ ctx->crypto, wrapped_size);
+ } while (wrapped_size && sz > req_output_size);
+ if (wrapped_size == 0)
return 0;
- }
/* inner header */
- if (wrapped_size < 16) {
- *output_length = 0;
+ if (wrapped_size < 16)
return 0;
- }
+
wrapped_size -= 16;
- *output_length = wrapped_size;
+ *max_input_size = wrapped_size;
} else {
krb5_cksumtype type;
size_t cksumsize;
- ret = krb5_crypto_get_checksum_type(context, crypto, &type);
+ ret = krb5_crypto_get_checksum_type(context, ctx->crypto, &type);
if (ret)
return ret;
@@ -151,48 +149,16 @@ _gsskrb5cfx_max_wrap_length_cfx(krb5_context context,
if (ret)
return ret;
- if (input_length < cksumsize)
+ if (req_output_size < cksumsize)
return 0;
/* Checksum is concatenated with data */
- *output_length = input_length - cksumsize;
+ *max_input_size = req_output_size - cksumsize;
}
return 0;
}
-
-OM_uint32 _gssapi_wrap_size_cfx(OM_uint32 *minor_status,
- const gsskrb5_ctx context_handle,
- krb5_context context,
- int conf_req_flag,
- gss_qop_t qop_req,
- OM_uint32 req_output_size,
- OM_uint32 *max_input_size,
- krb5_keyblock *key)
-{
- krb5_error_code ret;
- krb5_crypto crypto;
-
- ret = krb5_crypto_init(context, key, 0, &crypto);
- if (ret != 0) {
- *minor_status = ret;
- return GSS_S_FAILURE;
- }
-
- ret = _gsskrb5cfx_max_wrap_length_cfx(context, crypto, conf_req_flag,
- req_output_size, max_input_size);
- if (ret != 0) {
- *minor_status = ret;
- krb5_crypto_destroy(context, crypto);
- return GSS_S_FAILURE;
- }
-
- krb5_crypto_destroy(context, crypto);
-
- return GSS_S_COMPLETE;
-}
-
/*
* Rotate "rrc" bytes to the front or back
*/
@@ -238,16 +204,14 @@ rrc_rotate(void *data, size_t len, uint16_t rrc, krb5_boolean unrotate)
}
OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
- const gsskrb5_ctx context_handle,
+ const gsskrb5_ctx ctx,
krb5_context context,
int conf_req_flag,
gss_qop_t qop_req,
const gss_buffer_t input_message_buffer,
int *conf_state,
- gss_buffer_t output_message_buffer,
- krb5_keyblock *key)
+ gss_buffer_t output_message_buffer)
{
- krb5_crypto crypto;
gss_cfx_wrap_token token;
krb5_error_code ret;
unsigned usage;
@@ -257,19 +221,12 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
int32_t seq_number;
u_char *p;
- ret = krb5_crypto_init(context, key, 0, &crypto);
- if (ret != 0) {
- *minor_status = ret;
- return GSS_S_FAILURE;
- }
-
- ret = _gsskrb5cfx_wrap_length_cfx(context_handle, context,
- crypto, conf_req_flag,
+ ret = _gsskrb5cfx_wrap_length_cfx(ctx, context,
+ ctx->crypto, conf_req_flag,
input_message_buffer->length,
&wrapped_len, &cksumsize, &padlength);
if (ret != 0) {
*minor_status = ret;
- krb5_crypto_destroy(context, crypto);
return GSS_S_FAILURE;
}
@@ -280,7 +237,6 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
output_message_buffer->value = malloc(output_message_buffer->length);
if (output_message_buffer->value == NULL) {
*minor_status = ENOMEM;
- krb5_crypto_destroy(context, crypto);
return GSS_S_FAILURE;
}
@@ -290,9 +246,9 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
token->TOK_ID[1] = 0x04;
token->Flags = 0;
token->Filler = 0xFF;
- if ((context_handle->more_flags & LOCAL) == 0)
+ if ((ctx->more_flags & LOCAL) == 0)
token->Flags |= CFXSentByAcceptor;
- if (context_handle->more_flags & ACCEPTOR_SUBKEY)
+ if (ctx->more_flags & ACCEPTOR_SUBKEY)
token->Flags |= CFXAcceptorSubkey;
if (conf_req_flag) {
/*
@@ -329,16 +285,16 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
token->RRC[0] = 0;
token->RRC[1] = 0;
- HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+ HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
krb5_auth_con_getlocalseqnumber(context,
- context_handle->auth_context,
+ ctx->auth_context,
&seq_number);
_gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]);
_gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]);
krb5_auth_con_setlocalseqnumber(context,
- context_handle->auth_context,
+ ctx->auth_context,
++seq_number);
- HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+ HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
/*
* If confidentiality is requested, the token header is
@@ -349,7 +305,7 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
* calculated over the plaintext concatenated with the
* token header.
*/
- if (context_handle->more_flags & LOCAL) {
+ if (ctx->more_flags & LOCAL) {
usage = KRB5_KU_USAGE_INITIATOR_SEAL;
} else {
usage = KRB5_KU_USAGE_ACCEPTOR_SEAL;
@@ -370,14 +326,13 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
memcpy(p + input_message_buffer->length + padlength,
token, sizeof(*token));
- ret = krb5_encrypt(context, crypto,
+ ret = krb5_encrypt(context, ctx->crypto,
usage, p,
input_message_buffer->length + padlength +
sizeof(*token),
&cipher);
if (ret != 0) {
*minor_status = ret;
- krb5_crypto_destroy(context, crypto);
_gsskrb5_release_buffer(minor_status, output_message_buffer);
return GSS_S_FAILURE;
}
@@ -389,14 +344,13 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
* this is really ugly, but needed against windows
* for DCERPC, as windows rotates by EC+RRC.
*/
- if (IS_DCE_STYLE(context_handle)) {
+ if (IS_DCE_STYLE(ctx)) {
ret = rrc_rotate(cipher.data, cipher.length, rrc+padlength, FALSE);
} else {
ret = rrc_rotate(cipher.data, cipher.length, rrc, FALSE);
}
if (ret != 0) {
*minor_status = ret;
- krb5_crypto_destroy(context, crypto);
_gsskrb5_release_buffer(minor_status, output_message_buffer);
return GSS_S_FAILURE;
}
@@ -409,21 +363,19 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
buf = malloc(input_message_buffer->length + sizeof(*token));
if (buf == NULL) {
*minor_status = ENOMEM;
- krb5_crypto_destroy(context, crypto);
_gsskrb5_release_buffer(minor_status, output_message_buffer);
return GSS_S_FAILURE;
}
memcpy(buf, input_message_buffer->value, input_message_buffer->length);
memcpy(buf + input_message_buffer->length, token, sizeof(*token));
- ret = krb5_create_checksum(context, crypto,
+ ret = krb5_create_checksum(context, ctx->crypto,
usage, 0, buf,
input_message_buffer->length +
sizeof(*token),
&cksum);
if (ret != 0) {
*minor_status = ret;
- krb5_crypto_destroy(context, crypto);
_gsskrb5_release_buffer(minor_status, output_message_buffer);
free(buf);
return GSS_S_FAILURE;
@@ -446,7 +398,6 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
input_message_buffer->length + cksum.checksum.length, rrc, FALSE);
if (ret != 0) {
*minor_status = ret;
- krb5_crypto_destroy(context, crypto);
_gsskrb5_release_buffer(minor_status, output_message_buffer);
free_Checksum(&cksum);
return GSS_S_FAILURE;
@@ -454,8 +405,6 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
free_Checksum(&cksum);
}
- krb5_crypto_destroy(context, crypto);
-
if (conf_state != NULL) {
*conf_state = conf_req_flag;
}
@@ -465,15 +414,13 @@ OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
}
OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
- const gsskrb5_ctx context_handle,
+ const gsskrb5_ctx ctx,
krb5_context context,
const gss_buffer_t input_message_buffer,
gss_buffer_t output_message_buffer,
int *conf_state,
- gss_qop_t *qop_state,
- krb5_keyblock *key)
+ gss_qop_t *qop_state)
{
- krb5_crypto crypto;
gss_cfx_wrap_token token;
u_char token_flags;
krb5_error_code ret;
@@ -503,11 +450,11 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
(CFXSentByAcceptor | CFXSealed | CFXAcceptorSubkey);
if (token_flags & CFXSentByAcceptor) {
- if ((context_handle->more_flags & LOCAL) == 0)
+ if ((ctx->more_flags & LOCAL) == 0)
return GSS_S_DEFECTIVE_TOKEN;
}
- if (context_handle->more_flags & ACCEPTOR_SUBKEY) {
+ if (ctx->more_flags & ACCEPTOR_SUBKEY) {
if ((token_flags & CFXAcceptorSubkey) == 0)
return GSS_S_DEFECTIVE_TOKEN;
} else {
@@ -537,26 +484,21 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
return GSS_S_UNSEQ_TOKEN;
}
- HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
- ret = _gssapi_msg_order_check(context_handle->order, seq_number_lo);
+ HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
+ ret = _gssapi_msg_order_check(ctx->order, seq_number_lo);
if (ret != 0) {
*minor_status = 0;
- HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+ HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
_gsskrb5_release_buffer(minor_status, output_message_buffer);
return ret;
}
- HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+ HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
/*
* Decrypt and/or verify checksum
*/
- ret = krb5_crypto_init(context, key, 0, &crypto);
- if (ret != 0) {
- *minor_status = ret;
- return GSS_S_FAILURE;
- }
- if (context_handle->more_flags & LOCAL) {
+ if (ctx->more_flags & LOCAL) {
usage = KRB5_KU_USAGE_ACCEPTOR_SEAL;
} else {
usage = KRB5_KU_USAGE_INITIATOR_SEAL;
@@ -571,27 +513,24 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
* this is really ugly, but needed against windows
* for DCERPC, as windows rotates by EC+RRC.
*/
- if (IS_DCE_STYLE(context_handle)) {
+ if (IS_DCE_STYLE(ctx)) {
*minor_status = rrc_rotate(p, len, rrc+ec, TRUE);
} else {
*minor_status = rrc_rotate(p, len, rrc, TRUE);
}
if (*minor_status != 0) {
- krb5_crypto_destroy(context, crypto);
return GSS_S_FAILURE;
}
- ret = krb5_decrypt(context, crypto, usage,
+ ret = krb5_decrypt(context, ctx->crypto, usage,
p, len, &data);
if (ret != 0) {
*minor_status = ret;
- krb5_crypto_destroy(context, crypto);
return GSS_S_BAD_MIC;
}
/* Check that there is room for the pad and token header */
if (data.length < ec + sizeof(*token)) {
- krb5_crypto_destroy(context, crypto);
krb5_data_free(&data);
return GSS_S_DEFECTIVE_TOKEN;
}
@@ -604,7 +543,6 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
/* Check the integrity of the header */
if (memcmp(p, token, sizeof(*token)) != 0) {
- krb5_crypto_destroy(context, crypto);
krb5_data_free(&data);
return GSS_S_BAD_MIC;
}
@@ -617,16 +555,15 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
/* Rotate by RRC; bogus to do this in-place XXX */
*minor_status = rrc_rotate(p, len, rrc, TRUE);
if (*minor_status != 0) {
- krb5_crypto_destroy(context, crypto);
return GSS_S_FAILURE;
}
/* Determine checksum type */
ret = krb5_crypto_get_checksum_type(context,
- crypto, &cksum.cksumtype);
+ ctx->crypto,
+ &cksum.cksumtype);
if (ret != 0) {
*minor_status = ret;
- krb5_crypto_destroy(context, crypto);
return GSS_S_FAILURE;
}
@@ -635,7 +572,6 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
/* Check we have at least as much data as the checksum */
if (len < cksum.checksum.length) {
*minor_status = ERANGE;
- krb5_crypto_destroy(context, crypto);
return GSS_S_BAD_MIC;
}
@@ -647,7 +583,6 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
output_message_buffer->value = malloc(len + sizeof(*token));
if (output_message_buffer->value == NULL) {
*minor_status = ENOMEM;
- krb5_crypto_destroy(context, crypto);
return GSS_S_FAILURE;
}
@@ -664,21 +599,18 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
token->RRC[0] = 0;
token->RRC[1] = 0;
- ret = krb5_verify_checksum(context, crypto,
+ ret = krb5_verify_checksum(context, ctx->crypto,
usage,
output_message_buffer->value,
len + sizeof(*token),
&cksum);
if (ret != 0) {
*minor_status = ret;
- krb5_crypto_destroy(context, crypto);
_gsskrb5_release_buffer(minor_status, output_message_buffer);
return GSS_S_BAD_MIC;
}
}
- krb5_crypto_destroy(context, crypto);
-
if (qop_state != NULL) {
*qop_state = GSS_C_QOP_DEFAULT;
}
@@ -688,14 +620,12 @@ OM_uint32 _gssapi_unwrap_cfx(OM_uint32 *minor_status,
}
OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status,
- const gsskrb5_ctx context_handle,
+ const gsskrb5_ctx ctx,
krb5_context context,
gss_qop_t qop_req,
const gss_buffer_t message_buffer,
- gss_buffer_t message_token,
- krb5_keyblock *key)
+ gss_buffer_t message_token)
{
- krb5_crypto crypto;
gss_cfx_mic_token token;
krb5_error_code ret;
unsigned usage;
@@ -704,17 +634,10 @@ OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status,
size_t len;
int32_t seq_number;
- ret = krb5_crypto_init(context, key, 0, &crypto);
- if (ret != 0) {
- *minor_status = ret;
- return GSS_S_FAILURE;
- }
-
len = message_buffer->length + sizeof(*token);
buf = malloc(len);
if (buf == NULL) {
*minor_status = ENOMEM;
- krb5_crypto_destroy(context, crypto);
return GSS_S_FAILURE;
}
@@ -724,38 +647,36 @@ OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status,
token->TOK_ID[0] = 0x04;
token->TOK_ID[1] = 0x04;
token->Flags = 0;
- if ((context_handle->more_flags & LOCAL) == 0)
+ if ((ctx->more_flags & LOCAL) == 0)
token->Flags |= CFXSentByAcceptor;
- if (context_handle->more_flags & ACCEPTOR_SUBKEY)
+ if (ctx->more_flags & ACCEPTOR_SUBKEY)
token->Flags |= CFXAcceptorSubkey;
memset(token->Filler, 0xFF, 5);
- HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
+ HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
krb5_auth_con_getlocalseqnumber(context,
- context_handle->auth_context,
+ ctx->auth_context,
&seq_number);
_gsskrb5_encode_be_om_uint32(0, &token->SND_SEQ[0]);
_gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]);
krb5_auth_con_setlocalseqnumber(context,
- context_handle->auth_context,
+ ctx->auth_context,
++seq_number);
- HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+ HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
- if (context_handle->more_flags & LOCAL) {
+ if (ctx->more_flags & LOCAL) {
usage = KRB5_KU_USAGE_INITIATOR_SIGN;
} else {
usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;
}
- ret = krb5_create_checksum(context, crypto,
+ ret = krb5_create_checksum(context, ctx->crypto,
usage, 0, buf, len, &cksum);
if (ret != 0) {
*minor_status = ret;
- krb5_crypto_destroy(context, crypto);
free(buf);
return GSS_S_FAILURE;
}
- krb5_crypto_destroy(context, crypto);
/* Determine MIC length */
message_token->length = sizeof(*token) + cksum.checksum.length;
@@ -780,14 +701,12 @@ OM_uint32 _gssapi_mic_cfx(OM_uint32 *minor_status,
}
OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status,
- const gsskrb5_ctx context_handle,
+ const gsskrb5_ctx ctx,
krb5_context context,
const gss_buffer_t message_buffer,
const gss_buffer_t token_buffer,
- gss_qop_t *qop_state,
- krb5_keyblock *key)
+ gss_qop_t *qop_state)
{
- krb5_crypto crypto;
gss_cfx_mic_token token;
u_char token_flags;
krb5_error_code ret;
@@ -814,10 +733,10 @@ OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status,
token_flags = token->Flags & (CFXSentByAcceptor | CFXAcceptorSubkey);
if (token_flags & CFXSentByAcceptor) {
- if ((context_handle->more_flags & LOCAL) == 0)
+ if ((ctx->more_flags & LOCAL) == 0)
return GSS_S_DEFECTIVE_TOKEN;
}
- if (context_handle->more_flags & ACCEPTOR_SUBKEY) {
+ if (ctx->more_flags & ACCEPTOR_SUBKEY) {
if ((token_flags & CFXAcceptorSubkey) == 0)
return GSS_S_DEFECTIVE_TOKEN;
} else {
@@ -839,36 +758,29 @@ OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status,
return GSS_S_UNSEQ_TOKEN;
}
- HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
- ret = _gssapi_msg_order_check(context_handle->order, seq_number_lo);
+ HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
+ ret = _gssapi_msg_order_check(ctx->order, seq_number_lo);
if (ret != 0) {
*minor_status = 0;
- HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+ HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
return ret;
}
- HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+ HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
/*
* Verify checksum
*/
- ret = krb5_crypto_init(context, key, 0, &crypto);
- if (ret != 0) {
- *minor_status = ret;
- return GSS_S_FAILURE;
- }
-
- ret = krb5_crypto_get_checksum_type(context, crypto,
+ ret = krb5_crypto_get_checksum_type(context, ctx->crypto,
&cksum.cksumtype);
if (ret != 0) {
*minor_status = ret;
- krb5_crypto_destroy(context, crypto);
return GSS_S_FAILURE;
}
cksum.checksum.data = p + sizeof(*token);
cksum.checksum.length = token_buffer->length - sizeof(*token);
- if (context_handle->more_flags & LOCAL) {
+ if (ctx->more_flags & LOCAL) {
usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;
} else {
usage = KRB5_KU_USAGE_INITIATOR_SIGN;
@@ -877,18 +789,16 @@ OM_uint32 _gssapi_verify_mic_cfx(OM_uint32 *minor_status,
buf = malloc(message_buffer->length + sizeof(*token));
if (buf == NULL) {
*minor_status = ENOMEM;
- krb5_crypto_destroy(context, crypto);
return GSS_S_FAILURE;
}
memcpy(buf, message_buffer->value, message_buffer->length);
memcpy(buf + message_buffer->length, token, sizeof(*token));
- ret = krb5_verify_checksum(context, crypto,
+ ret = krb5_verify_checksum(context, ctx->crypto,
usage,
buf,
sizeof(*token) + message_buffer->length,
&cksum);
- krb5_crypto_destroy(context, crypto);
if (ret != 0) {
*minor_status = ret;
free(buf);
diff --git a/source4/heimdal/lib/gssapi/krb5/compare_name.c b/source4/heimdal/lib/gssapi/krb5/compare_name.c
index d92f3ef405..fbb0f0218e 100644
--- a/source4/heimdal/lib/gssapi/krb5/compare_name.c
+++ b/source4/heimdal/lib/gssapi/krb5/compare_name.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/compat.c b/source4/heimdal/lib/gssapi/krb5/compat.c
index ee0d07d983..012602c074 100644
--- a/source4/heimdal/lib/gssapi/krb5/compat.c
+++ b/source4/heimdal/lib/gssapi/krb5/compat.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/context_time.c b/source4/heimdal/lib/gssapi/krb5/context_time.c
index 3854b68782..3230389938 100644
--- a/source4/heimdal/lib/gssapi/krb5/context_time.c
+++ b/source4/heimdal/lib/gssapi/krb5/context_time.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/copy_ccache.c b/source4/heimdal/lib/gssapi/krb5/copy_ccache.c
index 8961642671..40a8fab1b7 100644
--- a/source4/heimdal/lib/gssapi/krb5/copy_ccache.c
+++ b/source4/heimdal/lib/gssapi/krb5/copy_ccache.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/decapsulate.c b/source4/heimdal/lib/gssapi/krb5/decapsulate.c
index 22386fa737..a2a5de9fe7 100644
--- a/source4/heimdal/lib/gssapi/krb5/decapsulate.c
+++ b/source4/heimdal/lib/gssapi/krb5/decapsulate.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c b/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c
index 5ccfe9d015..ea0831815a 100644
--- a/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c
+++ b/source4/heimdal/lib/gssapi/krb5/delete_sec_context.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -74,6 +74,8 @@ _gsskrb5_delete_sec_context(OM_uint32 * minor_status,
if (ctx->service_keyblock)
krb5_free_keyblock (context, ctx->service_keyblock);
krb5_data_free(&ctx->fwd_data);
+ if (ctx->crypto)
+ krb5_crypto_destroy(context, ctx->crypto);
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
HEIMDAL_MUTEX_destroy(&ctx->ctx_id_mutex);
diff --git a/source4/heimdal/lib/gssapi/krb5/display_name.c b/source4/heimdal/lib/gssapi/krb5/display_name.c
index d1834ebaf8..0b37731510 100644
--- a/source4/heimdal/lib/gssapi/krb5/display_name.c
+++ b/source4/heimdal/lib/gssapi/krb5/display_name.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/display_status.c b/source4/heimdal/lib/gssapi/krb5/display_status.c
index 18622610d5..4136c25e53 100644
--- a/source4/heimdal/lib/gssapi/krb5/display_status.c
+++ b/source4/heimdal/lib/gssapi/krb5/display_status.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/duplicate_name.c b/source4/heimdal/lib/gssapi/krb5/duplicate_name.c
index 6c281f43de..2b5e5c0ef4 100644
--- a/source4/heimdal/lib/gssapi/krb5/duplicate_name.c
+++ b/source4/heimdal/lib/gssapi/krb5/duplicate_name.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/encapsulate.c b/source4/heimdal/lib/gssapi/krb5/encapsulate.c
index 19c6ec8ca7..838a34d7db 100644
--- a/source4/heimdal/lib/gssapi/krb5/encapsulate.c
+++ b/source4/heimdal/lib/gssapi/krb5/encapsulate.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/export_name.c b/source4/heimdal/lib/gssapi/krb5/export_name.c
index b28777ea2e..bad73611dc 100644
--- a/source4/heimdal/lib/gssapi/krb5/export_name.c
+++ b/source4/heimdal/lib/gssapi/krb5/export_name.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/export_sec_context.c b/source4/heimdal/lib/gssapi/krb5/export_sec_context.c
index 842921fe50..305d5c334e 100644
--- a/source4/heimdal/lib/gssapi/krb5/export_sec_context.c
+++ b/source4/heimdal/lib/gssapi/krb5/export_sec_context.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/external.c b/source4/heimdal/lib/gssapi/krb5/external.c
index 4efa61fd70..1c28f7c141 100644
--- a/source4/heimdal/lib/gssapi/krb5/external.c
+++ b/source4/heimdal/lib/gssapi/krb5/external.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
#include <gssapi_mech.h>
RCSID("$Id$");
@@ -469,7 +469,10 @@ static gssapi_mech_interface_desc krb5_mech = {
_gsskrb5_inquire_cred_by_oid,
_gsskrb5_set_sec_context_option,
_gsskrb5_set_cred_option,
- _gsskrb5_pseudo_random
+ _gsskrb5_pseudo_random,
+ _gk_wrap_iov,
+ _gk_unwrap_iov,
+ _gk_wrap_iov_length
};
gssapi_mech_interface
diff --git a/source4/heimdal/lib/gssapi/krb5/get_mic.c b/source4/heimdal/lib/gssapi/krb5/get_mic.c
index 199c414ef4..66aaba44d6 100644
--- a/source4/heimdal/lib/gssapi/krb5/get_mic.c
+++ b/source4/heimdal/lib/gssapi/krb5/get_mic.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -284,6 +284,10 @@ OM_uint32 _gsskrb5_get_mic
GSSAPI_KRB5_INIT (&context);
+ if (ctx->more_flags & IS_CFX)
+ return _gssapi_mic_cfx (minor_status, ctx, context, qop_req,
+ message_buffer, message_token);
+
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
ret = _gsskrb5i_get_token_key(ctx, context, &key);
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
@@ -308,8 +312,7 @@ OM_uint32 _gsskrb5_get_mic
message_buffer, message_token, key);
break;
default :
- ret = _gssapi_mic_cfx (minor_status, ctx, context, qop_req,
- message_buffer, message_token, key);
+ abort();
break;
}
krb5_free_keyblock (context, key);
diff --git a/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h
index 6db842395f..aadb80db0d 100644
--- a/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h
+++ b/source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h
@@ -36,14 +36,13 @@
#ifndef GSSKRB5_LOCL_H
#define GSSKRB5_LOCL_H
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <krb5_locl.h>
#include <gkrb5_err.h>
#include <gssapi.h>
#include <gssapi_mech.h>
+#include <gssapi_krb5.h>
#include <assert.h>
#include "cfx.h"
@@ -54,7 +53,7 @@
struct gss_msg_order;
-typedef struct {
+typedef struct gsskrb5_ctx {
struct krb5_auth_context_data *auth_context;
krb5_principal source, target;
#define IS_DCE_STYLE(ctx) (((ctx)->flags & GSS_C_DCE_STYLE) != 0)
@@ -64,7 +63,8 @@ typedef struct {
COMPAT_OLD_DES3_SELECTED = 8,
ACCEPTOR_SUBKEY = 16,
RETRIED = 32,
- CLOSE_CCACHE = 64
+ CLOSE_CCACHE = 64,
+ IS_CFX = 128
} more_flags;
enum gss_ctx_id_t_state {
/* initiator states */
@@ -85,6 +85,7 @@ typedef struct {
struct gss_msg_order *order;
krb5_keyblock *service_keyblock;
krb5_data fwd_data;
+ krb5_crypto crypto;
} *gsskrb5_ctx;
typedef struct {
@@ -119,7 +120,7 @@ struct gssapi_thr_context {
* Prototypes
*/
-#include <krb5/gsskrb5-private.h>
+#include <gsskrb5-private.h>
#define GSSAPI_KRB5_INIT(ctx) do { \
krb5_error_code kret_gss_init; \
diff --git a/source4/heimdal/lib/gssapi/krb5/import_name.c b/source4/heimdal/lib/gssapi/krb5/import_name.c
index 2f6b002f30..8f5387fe2b 100644
--- a/source4/heimdal/lib/gssapi/krb5/import_name.c
+++ b/source4/heimdal/lib/gssapi/krb5/import_name.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/import_sec_context.c b/source4/heimdal/lib/gssapi/krb5/import_sec_context.c
index e1e8e551b4..ba1a977d2d 100644
--- a/source4/heimdal/lib/gssapi/krb5/import_sec_context.c
+++ b/source4/heimdal/lib/gssapi/krb5/import_sec_context.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c b/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c
index 05b9447746..3702106e79 100644
--- a/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c
+++ b/source4/heimdal/lib/gssapi/krb5/indicate_mechs.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/init.c b/source4/heimdal/lib/gssapi/krb5/init.c
index 6c1c5949e0..b28e6a4c12 100644
--- a/source4/heimdal/lib/gssapi/krb5/init.c
+++ b/source4/heimdal/lib/gssapi/krb5/init.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c
index dfa0e935e6..4b632bd95a 100644
--- a/source4/heimdal/lib/gssapi/krb5/init_sec_context.c
+++ b/source4/heimdal/lib/gssapi/krb5/init_sec_context.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -131,6 +131,7 @@ _gsskrb5_create_ctx(
krb5_data_zero(&ctx->fwd_data);
ctx->lifetime = GSS_C_INDEFINITE;
ctx->order = NULL;
+ ctx->crypto = NULL;
HEIMDAL_MUTEX_init(&ctx->ctx_id_mutex);
kret = krb5_auth_con_init (context, &ctx->auth_context);
@@ -257,7 +258,8 @@ gsskrb5_initiator_ready(
krb5_auth_getremoteseqnumber (context, ctx->auth_context, &seq_number);
- _gsskrb5i_is_cfx(ctx, &is_cfx);
+ _gsskrb5i_is_cfx(context, ctx, 0);
+ is_cfx = (ctx->more_flags & IS_CFX);
ret = _gssapi_msg_order_create(minor_status,
&ctx->order,
@@ -552,8 +554,10 @@ init_auth_restart
flags |= GSS_C_REPLAY_FLAG;
if (req_flags & GSS_C_SEQUENCE_FLAG)
flags |= GSS_C_SEQUENCE_FLAG;
+#if 0
if (req_flags & GSS_C_ANON_FLAG)
; /* XXX */
+#endif
if (req_flags & GSS_C_DCE_STYLE) {
/* GSS_C_DCE_STYLE implies GSS_C_MUTUAL_FLAG */
flags |= GSS_C_DCE_STYLE | GSS_C_MUTUAL_FLAG;
@@ -686,7 +690,6 @@ repl_mutual
krb5_error_code kret;
krb5_data indata;
krb5_ap_rep_enc_part *repl;
- int is_cfx = 0;
output_token->length = 0;
output_token->value = NULL;
@@ -759,20 +762,6 @@ repl_mutual
krb5_free_ap_rep_enc_part (context,
repl);
- _gsskrb5i_is_cfx(ctx, &is_cfx);
- if (is_cfx) {
- krb5_keyblock *key = NULL;
-
- kret = krb5_auth_con_getremotesubkey(context,
- ctx->auth_context,
- &key);
- if (kret == 0 && key != NULL) {
- ctx->more_flags |= ACCEPTOR_SUBKEY;
- krb5_free_keyblock (context, key);
- }
- }
-
-
*minor_status = 0;
if (time_rec) {
ret = _gsskrb5_lifetime_left(minor_status,
diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_context.c b/source4/heimdal/lib/gssapi/krb5/inquire_context.c
index e0aeb032ce..188a6135a4 100644
--- a/source4/heimdal/lib/gssapi/krb5/inquire_context.c
+++ b/source4/heimdal/lib/gssapi/krb5/inquire_context.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred.c
index bb75978adb..27e3014923 100644
--- a/source4/heimdal/lib/gssapi/krb5/inquire_cred.c
+++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c
index cdf05d7934..1fd9733940 100644
--- a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c
+++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c
index 2bcc17683b..5a35202a6a 100644
--- a/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c
+++ b/source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c b/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c
index 4fd730deab..5d54bd6508 100644
--- a/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c
+++ b/source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c b/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c
index a9d6495c7b..9eba7b7f4d 100644
--- a/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c
+++ b/source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c b/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c
index 8d40706294..f8ef2a3aa4 100644
--- a/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c
+++ b/source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -242,7 +242,7 @@ static OM_uint32 inquire_sec_context_has_updated_spnego
* mechanism.
*/
HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
- _gsskrb5i_is_cfx(context_handle, &is_updated);
+ is_updated = (context_handle->more_flags & IS_CFX);
if (is_updated == 0) {
krb5_keyblock *acceptor_subkey;
@@ -282,7 +282,7 @@ export_lucid_sec_context_v1(OM_uint32 *minor_status,
HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
- _gsskrb5i_is_cfx(context_handle, &is_cfx);
+ is_cfx = (context_handle->more_flags & IS_CFX);
sp = krb5_storage_emem();
if (sp == NULL) {
@@ -445,6 +445,7 @@ get_service_keyblock
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
if (ctx->service_keyblock == NULL) {
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
+ krb5_storage_free(sp);
_gsskrb5_set_status(EINVAL, "No service keyblock on gssapi context");
*minor_status = EINVAL;
return GSS_S_FAILURE;
diff --git a/source4/heimdal/lib/gssapi/krb5/prf.c b/source4/heimdal/lib/gssapi/krb5/prf.c
index 9cbe603435..9fd13f51bd 100644
--- a/source4/heimdal/lib/gssapi/krb5/prf.c
+++ b/source4/heimdal/lib/gssapi/krb5/prf.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/process_context_token.c b/source4/heimdal/lib/gssapi/krb5/process_context_token.c
index 6892d3ca60..3229b36292 100644
--- a/source4/heimdal/lib/gssapi/krb5/process_context_token.c
+++ b/source4/heimdal/lib/gssapi/krb5/process_context_token.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -44,15 +44,12 @@ OM_uint32 _gsskrb5_process_context_token (
krb5_context context;
OM_uint32 ret = GSS_S_FAILURE;
gss_buffer_desc empty_buffer;
- gss_qop_t qop_state;
empty_buffer.length = 0;
empty_buffer.value = NULL;
GSSAPI_KRB5_INIT (&context);
- qop_state = GSS_C_QOP_DEFAULT;
-
ret = _gsskrb5_verify_mic_internal(minor_status,
(gsskrb5_ctx)context_handle,
context,
diff --git a/source4/heimdal/lib/gssapi/krb5/release_buffer.c b/source4/heimdal/lib/gssapi/krb5/release_buffer.c
index a0f37c06f4..18e0279939 100644
--- a/source4/heimdal/lib/gssapi/krb5/release_buffer.c
+++ b/source4/heimdal/lib/gssapi/krb5/release_buffer.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/release_cred.c b/source4/heimdal/lib/gssapi/krb5/release_cred.c
index 5a0ec829d2..62674a1d53 100644
--- a/source4/heimdal/lib/gssapi/krb5/release_cred.c
+++ b/source4/heimdal/lib/gssapi/krb5/release_cred.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -61,8 +61,6 @@ OM_uint32 _gsskrb5_release_cred
if (cred->keytab != NULL)
krb5_kt_close(context, cred->keytab);
if (cred->ccache != NULL) {
- const krb5_cc_ops *ops;
- ops = krb5_cc_get_ops(context, cred->ccache);
if (cred->cred_flags & GSS_CF_DESTROY_CRED_ON_RELEASE)
krb5_cc_destroy(context, cred->ccache);
else
diff --git a/source4/heimdal/lib/gssapi/krb5/release_name.c b/source4/heimdal/lib/gssapi/krb5/release_name.c
index d39c705433..5491052c59 100644
--- a/source4/heimdal/lib/gssapi/krb5/release_name.c
+++ b/source4/heimdal/lib/gssapi/krb5/release_name.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/sequence.c b/source4/heimdal/lib/gssapi/krb5/sequence.c
index 61164ffec1..6391d44429 100644
--- a/source4/heimdal/lib/gssapi/krb5/sequence.c
+++ b/source4/heimdal/lib/gssapi/krb5/sequence.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c
index e47e6fdb6c..2a2390f8d1 100644
--- a/source4/heimdal/lib/gssapi/krb5/set_cred_option.c
+++ b/source4/heimdal/lib/gssapi/krb5/set_cred_option.c
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c b/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c
index 6591ab04dd..460cfe942a 100644
--- a/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c
+++ b/source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c
@@ -34,7 +34,7 @@
* glue routine for _gsskrb5_inquire_sec_context_by_oid
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/krb5/unwrap.c b/source4/heimdal/lib/gssapi/krb5/unwrap.c
index f34f72542e..0e87cb88b7 100644
--- a/source4/heimdal/lib/gssapi/krb5/unwrap.c
+++ b/source4/heimdal/lib/gssapi/krb5/unwrap.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -393,11 +393,16 @@ OM_uint32 _gsskrb5_unwrap
output_message_buffer->value = NULL;
output_message_buffer->length = 0;
+ if (qop_state != NULL)
+ *qop_state = GSS_C_QOP_DEFAULT;
GSSAPI_KRB5_INIT (&context);
- if (qop_state != NULL)
- *qop_state = GSS_C_QOP_DEFAULT;
+ if (ctx->more_flags & IS_CFX)
+ return _gssapi_unwrap_cfx (minor_status, ctx, context,
+ input_message_buffer, output_message_buffer,
+ conf_state, qop_state);
+
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
ret = _gsskrb5i_get_token_key(ctx, context, &key);
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
@@ -427,9 +432,7 @@ OM_uint32 _gsskrb5_unwrap
conf_state, qop_state, key);
break;
default :
- ret = _gssapi_unwrap_cfx (minor_status, ctx, context,
- input_message_buffer, output_message_buffer,
- conf_state, qop_state, key);
+ abort();
break;
}
krb5_free_keyblock (context, key);
diff --git a/source4/heimdal/lib/gssapi/krb5/verify_mic.c b/source4/heimdal/lib/gssapi/krb5/verify_mic.c
index 1832d35b5a..6eb7ae4b08 100644
--- a/source4/heimdal/lib/gssapi/krb5/verify_mic.c
+++ b/source4/heimdal/lib/gssapi/krb5/verify_mic.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -266,7 +266,7 @@ retry:
OM_uint32
_gsskrb5_verify_mic_internal
(OM_uint32 * minor_status,
- const gsskrb5_ctx context_handle,
+ const gsskrb5_ctx ctx,
krb5_context context,
const gss_buffer_t message_buffer,
const gss_buffer_t token_buffer,
@@ -278,9 +278,14 @@ _gsskrb5_verify_mic_internal
OM_uint32 ret;
krb5_keytype keytype;
- HEIMDAL_MUTEX_lock(&context_handle->ctx_id_mutex);
- ret = _gsskrb5i_get_token_key(context_handle, context, &key);
- HEIMDAL_MUTEX_unlock(&context_handle->ctx_id_mutex);
+ if (ctx->more_flags & IS_CFX)
+ return _gssapi_verify_mic_cfx (minor_status, ctx,
+ context, message_buffer, token_buffer,
+ qop_state);
+
+ HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
+ ret = _gsskrb5i_get_token_key(ctx, context, &key);
+ HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
if (ret) {
*minor_status = ret;
return GSS_S_FAILURE;
@@ -289,28 +294,24 @@ _gsskrb5_verify_mic_internal
krb5_enctype_to_keytype (context, key->keytype, &keytype);
switch (keytype) {
case KEYTYPE_DES :
- ret = verify_mic_des (minor_status, context_handle, context,
+ ret = verify_mic_des (minor_status, ctx, context,
message_buffer, token_buffer, qop_state, key,
type);
break;
case KEYTYPE_DES3 :
- ret = verify_mic_des3 (minor_status, context_handle, context,
+ ret = verify_mic_des3 (minor_status, ctx, context,
message_buffer, token_buffer, qop_state, key,
type);
break;
case KEYTYPE_ARCFOUR :
case KEYTYPE_ARCFOUR_56 :
- ret = _gssapi_verify_mic_arcfour (minor_status, context_handle,
+ ret = _gssapi_verify_mic_arcfour (minor_status, ctx,
context,
message_buffer, token_buffer,
qop_state, key, type);
break;
default :
- ret = _gssapi_verify_mic_cfx (minor_status, context_handle,
- context,
- message_buffer, token_buffer, qop_state,
- key);
- break;
+ abort();
}
krb5_free_keyblock (context, key);
diff --git a/source4/heimdal/lib/gssapi/krb5/wrap.c b/source4/heimdal/lib/gssapi/krb5/wrap.c
index ad21bcb57b..b9f4c237c7 100644
--- a/source4/heimdal/lib/gssapi/krb5/wrap.c
+++ b/source4/heimdal/lib/gssapi/krb5/wrap.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
RCSID("$Id$");
@@ -154,6 +154,11 @@ _gsskrb5_wrap_size_limit (
GSSAPI_KRB5_INIT (&context);
+ if (ctx->more_flags & IS_CFX)
+ return _gssapi_wrap_size_cfx(minor_status, ctx, context,
+ conf_req_flag, qop_req,
+ req_output_size, max_input_size);
+
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
ret = _gsskrb5i_get_token_key(ctx, context, &key);
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
@@ -177,9 +182,7 @@ _gsskrb5_wrap_size_limit (
ret = sub_wrap_size(req_output_size, max_input_size, 8, 34);
break;
default :
- ret = _gssapi_wrap_size_cfx(minor_status, ctx, context,
- conf_req_flag, qop_req,
- req_output_size, max_input_size, key);
+ abort();
break;
}
krb5_free_keyblock (context, key);
@@ -530,8 +533,16 @@ OM_uint32 _gsskrb5_wrap
krb5_keytype keytype;
const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
+ output_message_buffer->value = NULL;
+ output_message_buffer->length = 0;
+
GSSAPI_KRB5_INIT (&context);
+ if (ctx->more_flags & IS_CFX)
+ return _gssapi_wrap_cfx (minor_status, ctx, context, conf_req_flag,
+ qop_req, input_message_buffer, conf_state,
+ output_message_buffer);
+
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
ret = _gsskrb5i_get_token_key(ctx, context, &key);
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
@@ -559,9 +570,7 @@ OM_uint32 _gsskrb5_wrap
output_message_buffer, key);
break;
default :
- ret = _gssapi_wrap_cfx (minor_status, ctx, context, conf_req_flag,
- qop_req, input_message_buffer, conf_state,
- output_message_buffer, key);
+ abort();
break;
}
krb5_free_keyblock (context, key);
diff --git a/source4/heimdal/lib/gssapi/mech/context.c b/source4/heimdal/lib/gssapi/mech/context.c
index a06a1e9e37..b032d8aa0e 100644
--- a/source4/heimdal/lib/gssapi/mech/context.c
+++ b/source4/heimdal/lib/gssapi/mech/context.c
@@ -1,4 +1,4 @@
-#include "mech/mech_locl.h"
+#include "mech_locl.h"
#include "heim_threads.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c b/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c
index 50011a9b0d..134511f34b 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c
@@ -260,7 +260,8 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status,
if (mech_ret_flags & GSS_C_DELEG_FLAG) {
if (!delegated_cred_handle) {
m->gm_release_cred(minor_status, &delegated_mc);
- *ret_flags &= ~GSS_C_DELEG_FLAG;
+ if (ret_flags)
+ *ret_flags &= ~GSS_C_DELEG_FLAG;
} else if (delegated_mc) {
struct _gss_cred *dcred;
struct _gss_mechanism_cred *dmc;
diff --git a/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c b/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c
index b21b3f62e8..a8ebe644ab 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c
@@ -51,7 +51,7 @@ gss_acquire_cred(OM_uint32 *minor_status,
*minor_status = 0;
if (output_cred_handle)
- *output_cred_handle = GSS_C_NO_CREDENTIAL;
+ return GSS_S_CALL_INACCESSIBLE_READ;
if (actual_mechs)
*actual_mechs = GSS_C_NO_OID_SET;
if (time_rec)
diff --git a/source4/heimdal/lib/gssapi/mech/gss_aeap.c b/source4/heimdal/lib/gssapi/mech/gss_aeap.c
new file mode 100644
index 0000000000..cbe0cd1460
--- /dev/null
+++ b/source4/heimdal/lib/gssapi/mech/gss_aeap.c
@@ -0,0 +1,184 @@
+/*
+ * AEAD support
+ */
+
+#include "mech_locl.h"
+RCSID("$Id$");
+
+/**
+ * Encrypts or sign the data.
+ *
+ * The maximum packet size is gss_context_stream_sizes.max_msg_size.
+ *
+ * The caller needs provide the folloing buffers:
+ *
+ * - HEADER (of size gss_context_stream_sizes.header)
+ * SIGN_ONLY (optional, zero or more)
+ * DATA
+ * SIGN_ONLY (optional, zero or more)
+ * PADDING (of size gss_context_stream_sizes.blocksize)
+ * TRAILER (of size gss_context_stream_sizes.trailer)
+ *
+ * - on DCE-RPC mode, the caller can skip PADDING and TRAILER if the
+ * DATA elements is padded to a block bountry.
+ *
+ * To generate gss_wrap() compatible packets, use: HEADER | DATA | PADDING | TRAILER
+ *
+ * The input sizes of HEADER, PADDING and TRAILER can be fetched using gss_wrap_iov_length() or
+ * gss_context_query_attributes().
+ *
+ * @ingroup gssapi
+ */
+
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_wrap_iov(OM_uint32 * minor_status,
+ gss_ctx_id_t context_handle,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ int * conf_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count)
+{
+ struct _gss_context *ctx = (struct _gss_context *) context_handle;
+ gssapi_mech_interface m;
+
+ if (minor_status)
+ *minor_status = 0;
+ if (conf_state)
+ *conf_state = 0;
+ if (ctx == NULL)
+ return GSS_S_NO_CONTEXT;
+ if (iov == NULL && iov_count != 0)
+ return GSS_S_CALL_INACCESSIBLE_READ;
+
+ m = ctx->gc_mech;
+
+ if (m->gm_wrap_iov == NULL) {
+ if (minor_status)
+ *minor_status = 0;
+ return GSS_S_UNAVAILABLE;
+ }
+
+ return (m->gm_wrap_iov)(minor_status, ctx->gc_ctx,
+ conf_req_flag, qop_req, conf_state,
+ iov, iov_count);
+}
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_unwrap_iov(OM_uint32 *minor_status,
+ gss_ctx_id_t context_handle,
+ int *conf_state,
+ gss_qop_t *qop_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count)
+{
+ struct _gss_context *ctx = (struct _gss_context *) context_handle;
+ gssapi_mech_interface m;
+
+ if (minor_status)
+ *minor_status = 0;
+ if (conf_state)
+ *conf_state = 0;
+ if (qop_state)
+ *qop_state = 0;
+ if (ctx == NULL)
+ return GSS_S_NO_CONTEXT;
+ if (iov == NULL && iov_count != 0)
+ return GSS_S_CALL_INACCESSIBLE_READ;
+
+ m = ctx->gc_mech;
+
+ if (m->gm_unwrap_iov == NULL) {
+ *minor_status = 0;
+ return GSS_S_UNAVAILABLE;
+ }
+
+ return (m->gm_unwrap_iov)(minor_status, ctx->gc_ctx,
+ conf_state, qop_state,
+ iov, iov_count);
+}
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_wrap_iov_length(OM_uint32 * minor_status,
+ gss_ctx_id_t context_handle,
+ int conf_req_flag,
+ gss_qop_t qop_req,
+ int *conf_state,
+ gss_iov_buffer_desc *iov,
+ int iov_count)
+{
+ struct _gss_context *ctx = (struct _gss_context *) context_handle;
+ gssapi_mech_interface m;
+
+ if (minor_status)
+ *minor_status = 0;
+ if (conf_state)
+ *conf_state = 0;
+ if (ctx == NULL)
+ return GSS_S_NO_CONTEXT;
+ if (iov == NULL && iov_count != 0)
+ return GSS_S_CALL_INACCESSIBLE_READ;
+
+ m = ctx->gc_mech;
+
+ if (m->gm_wrap_iov_length == NULL) {
+ *minor_status = 0;
+ return GSS_S_UNAVAILABLE;
+ }
+
+ return (m->gm_wrap_iov_length)(minor_status, ctx->gc_ctx,
+ conf_req_flag, qop_req, conf_state,
+ iov, iov_count);
+}
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_release_iov_buffer(OM_uint32 *minor_status,
+ gss_iov_buffer_desc *iov,
+ int iov_count)
+{
+ OM_uint32 junk;
+ size_t i;
+
+ if (minor_status)
+ *minor_status = 0;
+ if (iov == NULL && iov_count != 0)
+ return GSS_S_CALL_INACCESSIBLE_READ;
+
+ for (i = 0; i < iov_count; i++) {
+ if (iov[i].type & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED)
+ continue;
+ gss_release_buffer(&junk, &iov[i].buffer);
+ }
+ return GSS_S_COMPLETE;
+}
+
+/**
+ * Query the context for parameters.
+ *
+ * SSPI equivalent if this function is QueryContextAttributes.
+ *
+ * - GSS_C_ATTR_STREAM_SIZES data is a gss_context_stream_sizes.
+ */
+
+static gss_OID_desc gss_c_attr_stream_sizes_desc =
+ {10, rk_UNCONST("\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03")};
+
+gss_OID GSSAPI_LIB_VARIABLE GSS_C_ATTR_STREAM_SIZES =
+ &gss_c_attr_stream_sizes_desc;
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_context_query_attributes(OM_uint32 *minor_status,
+ gss_OID attribute,
+ void *data,
+ size_t len)
+{
+ *minor_status = 0;
+
+ if (gss_oid_equal(GSS_C_ATTR_STREAM_SIZES, attribute)) {
+ memset(data, 0, len);
+ return GSS_S_COMPLETE;
+ }
+
+ return GSS_S_FAILURE;
+}
diff --git a/source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c b/source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c
index 91a08fb2bc..db976f2453 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c
@@ -29,6 +29,30 @@
#include "mech_locl.h"
RCSID("$Id$");
+/**
+ * gss_canonicalize_name takes a Internal Name (IN) and converts in into a
+ * mechanism specific Mechanism Name (MN).
+ *
+ * The input name may multiple name, or generic name types.
+ *
+ * If the input_name if of the GSS_C_NT_USER_NAME, and the Kerberos
+ * mechanism is specified, the resulting MN type is a
+ * GSS_KRB5_NT_PRINCIPAL_NAME.
+ *
+ * For more information about @ref internalVSmechname.
+ *
+ * @param minor_status minor status code.
+ * @param input_name name to covert, unchanged by gss_canonicalize_name().
+ * @param mech_type the type to convert Name too.
+ * @param output_name the resulting type, release with
+ * gss_release_name(), independent of input_name.
+ *
+ * @returns a gss_error code, see gss_display_status() about printing
+ * the error code.
+ *
+ * @ingroup gssapi
+ */
+
OM_uint32 GSSAPI_LIB_FUNCTION
gss_canonicalize_name(OM_uint32 *minor_status,
const gss_name_t input_name,
diff --git a/source4/heimdal/lib/gssapi/mech/gss_get_mic.c b/source4/heimdal/lib/gssapi/mech/gss_get_mic.c
index 9cd5060fc9..3a0f3fb757 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_get_mic.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_get_mic.c
@@ -37,7 +37,7 @@ gss_get_mic(OM_uint32 *minor_status,
gss_buffer_t message_token)
{
struct _gss_context *ctx = (struct _gss_context *) context_handle;
- gssapi_mech_interface m = ctx->gc_mech;
+ gssapi_mech_interface m;
_mg_buffer_zero(message_token);
if (ctx == NULL) {
@@ -45,6 +45,8 @@ gss_get_mic(OM_uint32 *minor_status,
return GSS_S_NO_CONTEXT;
}
+ m = ctx->gc_mech;
+
return (m->gm_get_mic(minor_status, ctx->gc_ctx, qop_req,
message_buffer, message_token));
}
diff --git a/source4/heimdal/lib/gssapi/mech/gss_import_name.c b/source4/heimdal/lib/gssapi/mech/gss_import_name.c
index 040e228410..c1dffdc614 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_import_name.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_import_name.c
@@ -145,9 +145,12 @@ gss_import_name(OM_uint32 *minor_status,
const gss_OID input_name_type,
gss_name_t *output_name)
{
+ struct _gss_mechanism_name *mn;
gss_OID name_type = input_name_type;
- OM_uint32 major_status;
+ OM_uint32 major_status, ms;
struct _gss_name *name;
+ struct _gss_mech_switch *m;
+ gss_name_t rname;
*output_name = GSS_C_NO_NAME;
@@ -156,6 +159,8 @@ gss_import_name(OM_uint32 *minor_status,
return (GSS_S_BAD_NAME);
}
+ _gss_load_mech();
+
/*
* Use GSS_NT_USER_NAME as default name type.
*/
@@ -172,29 +177,15 @@ gss_import_name(OM_uint32 *minor_status,
input_name_buffer, output_name);
}
- /*
- * Only allow certain name types. This is pretty bogus - we
- * should figure out the list of supported name types using
- * gss_inquire_names_for_mech.
- */
- if (!gss_oid_equal(name_type, GSS_C_NT_USER_NAME)
- && !gss_oid_equal(name_type, GSS_C_NT_MACHINE_UID_NAME)
- && !gss_oid_equal(name_type, GSS_C_NT_STRING_UID_NAME)
- && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE_X)
- && !gss_oid_equal(name_type, GSS_C_NT_HOSTBASED_SERVICE)
- && !gss_oid_equal(name_type, GSS_C_NT_ANONYMOUS)
- && !gss_oid_equal(name_type, GSS_KRB5_NT_PRINCIPAL_NAME)) {
- *minor_status = 0;
- return (GSS_S_BAD_NAMETYPE);
- }
*minor_status = 0;
- name = malloc(sizeof(struct _gss_name));
+ name = calloc(1, sizeof(struct _gss_name));
if (!name) {
*minor_status = ENOMEM;
return (GSS_S_FAILURE);
}
- memset(name, 0, sizeof(struct _gss_name));
+
+ SLIST_INIT(&name->gn_mn);
major_status = _gss_copy_oid(minor_status,
name_type, &name->gn_type);
@@ -205,14 +196,62 @@ gss_import_name(OM_uint32 *minor_status,
major_status = _gss_copy_buffer(minor_status,
input_name_buffer, &name->gn_value);
- if (major_status) {
- gss_name_t rname = (gss_name_t)name;
- gss_release_name(minor_status, &rname);
- return (GSS_S_FAILURE);
+ if (major_status)
+ goto out;
+
+ /*
+ * Walk over the mechs and import the name into a mech name
+ * for those supported this nametype.
+ */
+
+ SLIST_FOREACH(m, &_gss_mechs, gm_link) {
+ int present = 0;
+
+ major_status = gss_test_oid_set_member(minor_status,
+ name_type, m->gm_name_types, &present);
+
+ if (major_status || present == 0)
+ continue;
+
+ mn = malloc(sizeof(struct _gss_mechanism_name));
+ if (!mn) {
+ *minor_status = ENOMEM;
+ major_status = GSS_S_FAILURE;
+ goto out;
+ }
+
+ major_status = (*m->gm_mech.gm_import_name)(minor_status,
+ &name->gn_value,
+ (name->gn_type.elements
+ ? &name->gn_type : GSS_C_NO_OID),
+ &mn->gmn_name);
+ if (major_status != GSS_S_COMPLETE) {
+ _gss_mg_error(&m->gm_mech, major_status, *minor_status);
+ free(mn);
+ goto out;
+ }
+
+ mn->gmn_mech = &m->gm_mech;
+ mn->gmn_mech_oid = &m->gm_mech_oid;
+ SLIST_INSERT_HEAD(&name->gn_mn, mn, gmn_link);
}
- SLIST_INIT(&name->gn_mn);
+ /*
+ * If we can't find a mn for the name, bail out already here.
+ */
+
+ mn = SLIST_FIRST(&name->gn_mn);
+ if (!mn) {
+ *minor_status = 0;
+ major_status = GSS_S_NAME_NOT_MN;
+ goto out;
+ }
*output_name = (gss_name_t) name;
return (GSS_S_COMPLETE);
+
+ out:
+ rname = (gss_name_t)name;
+ gss_release_name(&ms, &rname);
+ return major_status;
}
diff --git a/source4/heimdal/lib/gssapi/mech/gss_krb5.c b/source4/heimdal/lib/gssapi/mech/gss_krb5.c
index 5318f6cdba..5d883c45c2 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_krb5.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_krb5.c
@@ -278,7 +278,7 @@ gss_krb5_export_lucid_sec_context(OM_uint32 *minor_status,
|| *context_handle == GSS_C_NO_CONTEXT
|| version != 1)
{
- ret = EINVAL;
+ *minor_status = EINVAL;
return GSS_S_FAILURE;
}
@@ -715,7 +715,7 @@ gsskrb5_extract_key(OM_uint32 *minor_status,
krb5_storage *sp = NULL;
if (context_handle == GSS_C_NO_CONTEXT) {
- ret = EINVAL;
+ *minor_status = EINVAL;
return GSS_S_FAILURE;
}
diff --git a/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c b/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c
index fc2e8816c5..3321819d28 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_mech_switch.c
@@ -186,6 +186,15 @@ add_builtin(gssapi_mech_interface mech)
gss_add_oid_set_member(&minor_status,
&m->gm_mech.gm_mech_oid, &_gss_mech_oids);
+ /* pick up the oid sets of names */
+
+ if (m->gm_mech.gm_inquire_names_for_mech) {
+ (*m->gm_mech.gm_inquire_names_for_mech)(&minor_status,
+ &m->gm_mech.gm_mech_oid, &m->gm_name_types);
+ } else {
+ gss_create_empty_oid_set(&minor_status, &m->gm_name_types);
+ }
+
SLIST_INSERT_HEAD(&_gss_mechs, m, gm_link);
return 0;
}
@@ -221,9 +230,7 @@ _gss_load_mech(void)
add_builtin(__gss_krb5_initialize());
add_builtin(__gss_spnego_initialize());
-#ifndef HEIMDAL_SMALLER
add_builtin(__gss_ntlm_initialize());
-#endif
#ifdef HAVE_DLOPEN
fp = fopen(_PATH_GSS_MECH, "r");
@@ -308,6 +315,9 @@ _gss_load_mech(void)
OPTSYM(set_sec_context_option);
OPTSYM(set_cred_option);
OPTSYM(pseudo_random);
+ OPTSYM(wrap_iov);
+ OPTSYM(unwrap_iov);
+ OPTSYM(wrap_iov_length);
SLIST_INSERT_HEAD(&_gss_mechs, m, gm_link);
continue;
diff --git a/source4/heimdal/lib/gssapi/mech/gss_pseudo_random.c b/source4/heimdal/lib/gssapi/mech/gss_pseudo_random.c
index b907f94038..771efcb434 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_pseudo_random.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_pseudo_random.c
@@ -45,7 +45,7 @@ gss_pseudo_random(OM_uint32 *minor_status,
gss_buffer_t prf_out)
{
struct _gss_context *ctx = (struct _gss_context *) context;
- gssapi_mech_interface m = ctx->gc_mech;
+ gssapi_mech_interface m;
OM_uint32 major_status;
_mg_buffer_zero(prf_out);
@@ -56,6 +56,8 @@ gss_pseudo_random(OM_uint32 *minor_status,
return GSS_S_NO_CONTEXT;
}
+ m = ctx->gc_mech;
+
if (m->gm_pseudo_random == NULL)
return GSS_S_UNAVAILABLE;
diff --git a/source4/heimdal/lib/gssapi/mech/gss_verify_mic.c b/source4/heimdal/lib/gssapi/mech/gss_verify_mic.c
index 1a411729c6..60ef3bff85 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_verify_mic.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_verify_mic.c
@@ -37,7 +37,7 @@ gss_verify_mic(OM_uint32 *minor_status,
gss_qop_t *qop_state)
{
struct _gss_context *ctx = (struct _gss_context *) context_handle;
- gssapi_mech_interface m = ctx->gc_mech;
+ gssapi_mech_interface m;
if (qop_state)
*qop_state = 0;
@@ -46,6 +46,8 @@ gss_verify_mic(OM_uint32 *minor_status,
return GSS_S_NO_CONTEXT;
}
+ m = ctx->gc_mech;
+
return (m->gm_verify_mic(minor_status, ctx->gc_ctx,
message_buffer, token_buffer, qop_state));
}
diff --git a/source4/heimdal/lib/gssapi/mech/gss_wrap.c b/source4/heimdal/lib/gssapi/mech/gss_wrap.c
index b3363d3f20..9476d01ddd 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_wrap.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_wrap.c
@@ -39,7 +39,7 @@ gss_wrap(OM_uint32 *minor_status,
gss_buffer_t output_message_buffer)
{
struct _gss_context *ctx = (struct _gss_context *) context_handle;
- gssapi_mech_interface m = ctx->gc_mech;
+ gssapi_mech_interface m;
if (conf_state)
*conf_state = 0;
@@ -49,6 +49,8 @@ gss_wrap(OM_uint32 *minor_status,
return GSS_S_NO_CONTEXT;
}
+ m = ctx->gc_mech;
+
return (m->gm_wrap(minor_status, ctx->gc_ctx,
conf_req_flag, qop_req, input_message_buffer,
conf_state, output_message_buffer));
diff --git a/source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c b/source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c
index 15b86a9367..a5a80b21d7 100644
--- a/source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c
+++ b/source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c
@@ -38,7 +38,7 @@ gss_wrap_size_limit(OM_uint32 *minor_status,
OM_uint32 *max_input_size)
{
struct _gss_context *ctx = (struct _gss_context *) context_handle;
- gssapi_mech_interface m = ctx->gc_mech;
+ gssapi_mech_interface m;
*max_input_size = 0;
if (ctx == NULL) {
@@ -46,6 +46,8 @@ gss_wrap_size_limit(OM_uint32 *minor_status,
return GSS_S_NO_CONTEXT;
}
+ m = ctx->gc_mech;
+
return (m->gm_wrap_size_limit(minor_status, ctx->gc_ctx,
conf_req_flag, qop_req, req_output_size, max_input_size));
}
diff --git a/source4/heimdal/lib/gssapi/mech/mech_locl.h b/source4/heimdal/lib/gssapi/mech/mech_locl.h
index 42c069eb2d..17721fd3ce 100644
--- a/source4/heimdal/lib/gssapi/mech/mech_locl.h
+++ b/source4/heimdal/lib/gssapi/mech/mech_locl.h
@@ -53,6 +53,7 @@
#include <gssapi.h>
#include <gssapi_mech.h>
+#include <gssapi_krb5.h>
#include "mechqueue.h"
diff --git a/source4/heimdal/lib/gssapi/mech/mech_switch.h b/source4/heimdal/lib/gssapi/mech/mech_switch.h
index e83a4c8a5a..56e3b7dea7 100644
--- a/source4/heimdal/lib/gssapi/mech/mech_switch.h
+++ b/source4/heimdal/lib/gssapi/mech/mech_switch.h
@@ -32,6 +32,7 @@
struct _gss_mech_switch {
SLIST_ENTRY(_gss_mech_switch) gm_link;
gss_OID_desc gm_mech_oid;
+ gss_OID_set gm_name_types;
void *gm_so;
gssapi_mech_interface_desc gm_mech;
};
diff --git a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c
index cabd806fbf..158126d99f 100644
--- a/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c
+++ b/source4/heimdal/lib/gssapi/spnego/accept_sec_context.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "spnego/spnego_locl.h"
+#include "spnego_locl.h"
RCSID("$Id$");
@@ -494,7 +494,7 @@ acceptor_complete(OM_uint32 * minor_status,
*get_mic = 1;
}
- if (verify_mic || get_mic) {
+ if (verify_mic || *get_mic) {
int eret;
size_t buf_len;
@@ -512,7 +512,7 @@ acceptor_complete(OM_uint32 * minor_status,
if (verify_mic) {
ret = verify_mechlist_mic(minor_status, ctx, mech_buf, mic);
if (ret) {
- if (get_mic)
+ if (*get_mic)
send_reject (minor_status, output_token);
if (buf.value)
free(buf.value);
diff --git a/source4/heimdal/lib/gssapi/spnego/compat.c b/source4/heimdal/lib/gssapi/spnego/compat.c
index 67d9b202a7..ee25b59435 100644
--- a/source4/heimdal/lib/gssapi/spnego/compat.c
+++ b/source4/heimdal/lib/gssapi/spnego/compat.c
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*/
-#include "spnego/spnego_locl.h"
+#include "spnego_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/spnego/context_stubs.c b/source4/heimdal/lib/gssapi/spnego/context_stubs.c
index 5bc1a48656..1998c44edf 100644
--- a/source4/heimdal/lib/gssapi/spnego/context_stubs.c
+++ b/source4/heimdal/lib/gssapi/spnego/context_stubs.c
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*/
-#include "spnego/spnego_locl.h"
+#include "spnego_locl.h"
RCSID("$Id$");
@@ -62,6 +62,7 @@ spnego_supported_mechs(OM_uint32 *minor_status, gss_OID_set *mechs)
return ret;
}
}
+ gss_release_oid_set(&junk, &m);
return ret;
}
@@ -598,7 +599,7 @@ out:
gss_release_oid_set(&junk, &mechs);
- return GSS_S_COMPLETE;
+ return ret;
}
OM_uint32 _gss_spnego_inquire_mechs_for_name (
@@ -642,128 +643,6 @@ OM_uint32 _gss_spnego_duplicate_name (
return gss_duplicate_name(minor_status, src_name, dest_name);
}
-OM_uint32 _gss_spnego_sign
- (OM_uint32 * minor_status,
- gss_ctx_id_t context_handle,
- int qop_req,
- gss_buffer_t message_buffer,
- gss_buffer_t message_token
- )
-{
- gssspnego_ctx ctx;
-
- *minor_status = 0;
-
- if (context_handle == GSS_C_NO_CONTEXT) {
- return GSS_S_NO_CONTEXT;
- }
-
- ctx = (gssspnego_ctx)context_handle;
-
- if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
- return GSS_S_NO_CONTEXT;
- }
-
- return gss_sign(minor_status,
- ctx->negotiated_ctx_id,
- qop_req,
- message_buffer,
- message_token);
-}
-
-OM_uint32 _gss_spnego_verify
- (OM_uint32 * minor_status,
- gss_ctx_id_t context_handle,
- gss_buffer_t message_buffer,
- gss_buffer_t token_buffer,
- int * qop_state
- )
-{
- gssspnego_ctx ctx;
-
- *minor_status = 0;
-
- if (context_handle == GSS_C_NO_CONTEXT) {
- return GSS_S_NO_CONTEXT;
- }
-
- ctx = (gssspnego_ctx)context_handle;
-
- if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
- return GSS_S_NO_CONTEXT;
- }
-
- return gss_verify(minor_status,
- ctx->negotiated_ctx_id,
- message_buffer,
- token_buffer,
- qop_state);
-}
-
-OM_uint32 _gss_spnego_seal
- (OM_uint32 * minor_status,
- gss_ctx_id_t context_handle,
- int conf_req_flag,
- int qop_req,
- gss_buffer_t input_message_buffer,
- int * conf_state,
- gss_buffer_t output_message_buffer
- )
-{
- gssspnego_ctx ctx;
-
- *minor_status = 0;
-
- if (context_handle == GSS_C_NO_CONTEXT) {
- return GSS_S_NO_CONTEXT;
- }
-
- ctx = (gssspnego_ctx)context_handle;
-
- if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
- return GSS_S_NO_CONTEXT;
- }
-
- return gss_seal(minor_status,
- ctx->negotiated_ctx_id,
- conf_req_flag,
- qop_req,
- input_message_buffer,
- conf_state,
- output_message_buffer);
-}
-
-OM_uint32 _gss_spnego_unseal
- (OM_uint32 * minor_status,
- gss_ctx_id_t context_handle,
- gss_buffer_t input_message_buffer,
- gss_buffer_t output_message_buffer,
- int * conf_state,
- int * qop_state
- )
-{
- gssspnego_ctx ctx;
-
- *minor_status = 0;
-
- if (context_handle == GSS_C_NO_CONTEXT) {
- return GSS_S_NO_CONTEXT;
- }
-
- ctx = (gssspnego_ctx)context_handle;
-
- if (ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
- return GSS_S_NO_CONTEXT;
- }
-
- return gss_unseal(minor_status,
- ctx->negotiated_ctx_id,
- input_message_buffer,
- output_message_buffer,
- conf_state,
- qop_state);
-}
-
#if 0
OM_uint32 _gss_spnego_unwrap_ex
(OM_uint32 * minor_status,
diff --git a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c
index f6b3fecaa0..a3a984e22c 100644
--- a/source4/heimdal/lib/gssapi/spnego/cred_stubs.c
+++ b/source4/heimdal/lib/gssapi/spnego/cred_stubs.c
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*/
-#include "spnego/spnego_locl.h"
+#include "spnego_locl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/gssapi/spnego/external.c b/source4/heimdal/lib/gssapi/spnego/external.c
index 02404237a7..2dc809bbba 100644
--- a/source4/heimdal/lib/gssapi/spnego/external.c
+++ b/source4/heimdal/lib/gssapi/spnego/external.c
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*/
-#include "spnego/spnego_locl.h"
+#include "spnego_locl.h"
#include <gssapi_mech.h>
RCSID("$Id$");
@@ -71,7 +71,7 @@ static gssapi_mech_interface_desc spnego_mech = {
_gss_spnego_inquire_cred_by_mech,
_gss_spnego_export_sec_context,
_gss_spnego_import_sec_context,
- _gss_spnego_inquire_names_for_mech,
+ NULL /* _gss_spnego_inquire_names_for_mech */,
_gss_spnego_inquire_mechs_for_name,
_gss_spnego_canonicalize_name,
_gss_spnego_duplicate_name,
diff --git a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c
index 7a5814413b..ac32432d55 100644
--- a/source4/heimdal/lib/gssapi/spnego/init_sec_context.c
+++ b/source4/heimdal/lib/gssapi/spnego/init_sec_context.c
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*/
-#include "spnego/spnego_locl.h"
+#include "spnego_locl.h"
RCSID("$Id$");
@@ -392,8 +392,7 @@ spnego_reply
)
{
OM_uint32 ret, minor;
- NegTokenResp resp;
- size_t len, taglen;
+ NegotiationToken resp;
gss_OID_desc mech;
int require_mic;
size_t buf_len;
@@ -414,27 +413,23 @@ spnego_reply
mech_buf.value = NULL;
mech_buf.length = 0;
- ret = der_match_tag_and_length(input_token->value, input_token->length,
- ASN1_C_CONTEXT, CONS, 1, &len, &taglen);
+ ret = decode_NegotiationToken(input_token->value, input_token->length,
+ &resp, NULL);
if (ret)
- return ret;
+ return ret;
- if (len > input_token->length - taglen)
- return ASN1_OVERRUN;
-
- ret = decode_NegTokenResp((const unsigned char *)input_token->value+taglen,
- len, &resp, NULL);
- if (ret) {
- *minor_status = ENOMEM;
- return GSS_S_FAILURE;
+ if (resp.element != choice_NegotiationToken_negTokenResp) {
+ free_NegotiationToken(&resp);
+ *minor_status = 0;
+ return GSS_S_BAD_MECH;
}
- if (resp.negResult == NULL
- || *(resp.negResult) == reject
- /* || resp.supportedMech == NULL */
+ if (resp.u.negTokenResp.negResult == NULL
+ || *(resp.u.negTokenResp.negResult) == reject
+ /* || resp.u.negTokenResp.supportedMech == NULL */
)
{
- free_NegTokenResp(&resp);
+ free_NegotiationToken(&resp);
return GSS_S_BAD_MECH;
}
@@ -445,16 +440,16 @@ spnego_reply
HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
- if (resp.supportedMech) {
+ if (resp.u.negTokenResp.supportedMech) {
if (ctx->oidlen) {
- free_NegTokenResp(&resp);
+ free_NegotiationToken(&resp);
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
return GSS_S_BAD_MECH;
}
ret = der_put_oid(ctx->oidbuf + sizeof(ctx->oidbuf) - 1,
sizeof(ctx->oidbuf),
- resp.supportedMech,
+ resp.u.negTokenResp.supportedMech,
&ctx->oidlen);
/* Avoid recursively embedded SPNEGO */
if (ret || (ctx->oidlen == GSS_SPNEGO_MECHANISM->length &&
@@ -462,7 +457,7 @@ spnego_reply
GSS_SPNEGO_MECHANISM->elements,
ctx->oidlen) == 0))
{
- free_NegTokenResp(&resp);
+ free_NegotiationToken(&resp);
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
return GSS_S_BAD_MECH;
}
@@ -478,19 +473,19 @@ spnego_reply
ctx->negotiated_ctx_id = GSS_C_NO_CONTEXT;
}
} else if (ctx->oidlen == 0) {
- free_NegTokenResp(&resp);
+ free_NegotiationToken(&resp);
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
return GSS_S_BAD_MECH;
}
/* if a token (of non zero length), or no context, pass to underlaying mech */
- if ((resp.responseToken != NULL && resp.responseToken->length) ||
+ if ((resp.u.negTokenResp.responseToken != NULL && resp.u.negTokenResp.responseToken->length) ||
ctx->negotiated_ctx_id == GSS_C_NO_CONTEXT) {
gss_buffer_desc mech_input_token;
- if (resp.responseToken) {
- mech_input_token.length = resp.responseToken->length;
- mech_input_token.value = resp.responseToken->data;
+ if (resp.u.negTokenResp.responseToken) {
+ mech_input_token.length = resp.u.negTokenResp.responseToken->length;
+ mech_input_token.value = resp.u.negTokenResp.responseToken->data;
} else {
mech_input_token.length = 0;
mech_input_token.value = NULL;
@@ -518,7 +513,7 @@ spnego_reply
&ctx->mech_time_rec);
if (GSS_ERROR(ret)) {
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
- free_NegTokenResp(&resp);
+ free_NegotiationToken(&resp);
gss_mg_collect_error(&mech, ret, minor);
*minor_status = minor;
return ret;
@@ -526,12 +521,12 @@ spnego_reply
if (ret == GSS_S_COMPLETE) {
ctx->open = 1;
}
- } else if (*(resp.negResult) == accept_completed) {
+ } else if (*(resp.u.negTokenResp.negResult) == accept_completed) {
if (ctx->maybe_open)
ctx->open = 1;
}
- if (*(resp.negResult) == request_mic) {
+ if (*(resp.u.negTokenResp.negResult) == request_mic) {
ctx->require_mic = 1;
}
@@ -540,14 +535,14 @@ spnego_reply
* Verify the mechListMIC if one was provided or CFX was
* used and a non-preferred mechanism was selected
*/
- if (resp.mechListMIC != NULL) {
+ if (resp.u.negTokenResp.mechListMIC != NULL) {
require_mic = 1;
} else {
ret = _gss_spnego_require_mechlist_mic(minor_status, ctx,
&require_mic);
if (ret) {
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
- free_NegTokenResp(&resp);
+ free_NegotiationToken(&resp);
gss_release_buffer(&minor, &mech_output_token);
return ret;
}
@@ -561,7 +556,7 @@ spnego_reply
&ctx->initiator_mech_types, &buf_len, ret);
if (ret) {
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
- free_NegTokenResp(&resp);
+ free_NegotiationToken(&resp);
gss_release_buffer(&minor, &mech_output_token);
*minor_status = ret;
return GSS_S_FAILURE;
@@ -569,15 +564,15 @@ spnego_reply
if (mech_buf.length != buf_len)
abort();
- if (resp.mechListMIC == NULL) {
+ if (resp.u.negTokenResp.mechListMIC == NULL) {
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
free(mech_buf.value);
- free_NegTokenResp(&resp);
+ free_NegotiationToken(&resp);
*minor_status = 0;
return GSS_S_DEFECTIVE_TOKEN;
}
- mic_buf.length = resp.mechListMIC->length;
- mic_buf.value = resp.mechListMIC->data;
+ mic_buf.length = resp.u.negTokenResp.mechListMIC->length;
+ mic_buf.value = resp.u.negTokenResp.mechListMIC->data;
if (mech_output_token.length == 0) {
ret = gss_verify_mic(minor_status,
@@ -589,7 +584,7 @@ spnego_reply
HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
free(mech_buf.value);
gss_release_buffer(&minor, &mech_output_token);
- free_NegTokenResp(&resp);
+ free_NegotiationToken(&resp);
return GSS_S_DEFECTIVE_TOKEN;
}
ctx->verified_mic = 1;
@@ -604,7 +599,7 @@ spnego_reply
if (mech_buf.value != NULL)
free(mech_buf.value);
- free_NegTokenResp(&resp);
+ free_NegotiationToken(&resp);
gss_release_buffer(&minor, &mech_output_token);
if (actual_mech_type)
diff --git a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h
index 8344e750ae..44fa8b117d 100644
--- a/source4/heimdal/lib/gssapi/spnego/spnego_locl.h
+++ b/source4/heimdal/lib/gssapi/spnego/spnego_locl.h
@@ -35,9 +35,7 @@
#ifndef SPNEGO_LOCL_H
#define SPNEGO_LOCL_H
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
@@ -50,8 +48,9 @@
#include <pthread.h>
#endif
-#include <gssapi/gssapi_spnego.h>
#include <gssapi.h>
+#include <gssapi_krb5.h>
+#include <gssapi_spnego.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
@@ -67,7 +66,7 @@
#include <gssapi_mech.h>
#include "spnego_asn1.h"
-#include "mech/utils.h"
+#include "utils.h"
#include <der.h>
#include <roken.h>
@@ -109,6 +108,6 @@ typedef struct {
extern gss_OID_desc _gss_spnego_mskrb_mechanism_oid_desc;
extern gss_OID_desc _gss_spnego_krb5_mechanism_oid_desc;
-#include <spnego/spnego-private.h>
+#include <spnego-private.h>
#endif /* SPNEGO_LOCL_H */
diff --git a/source4/heimdal/lib/hcrypto/bn.c b/source4/heimdal/lib/hcrypto/bn.c
index b91a65a7bf..179595ae5c 100644
--- a/source4/heimdal/lib/hcrypto/bn.c
+++ b/source4/heimdal/lib/hcrypto/bn.c
@@ -443,3 +443,91 @@ BN_GENCB_call(BN_GENCB *cb, int a, int b)
return 1;
return cb->cb.cb_2(a, b, cb);
}
+
+/*
+ *
+ */
+
+struct BN_CTX {
+ struct {
+ BIGNUM **val;
+ size_t used;
+ size_t len;
+ } bn;
+ struct {
+ size_t *val;
+ size_t used;
+ size_t len;
+ } stack;
+};
+
+BN_CTX *
+BN_CTX_new(void)
+{
+ struct BN_CTX *c;
+ c = calloc(1, sizeof(*c));
+ return c;
+}
+
+void
+BN_CTX_free(BN_CTX *c)
+{
+ size_t i;
+ for (i = 0; i < c->bn.len; i++)
+ BN_free(c->bn.val[i]);
+ free(c->bn.val);
+ free(c->stack.val);
+}
+
+BIGNUM *
+BN_CTX_get(BN_CTX *c)
+{
+ if (c->bn.used == c->bn.len) {
+ void *ptr;
+ size_t i;
+ c->bn.len += 16;
+ ptr = realloc(c->bn.val, c->bn.len * sizeof(c->bn.val[0]));
+ if (ptr == NULL)
+ return NULL;
+ c->bn.val = ptr;
+ for (i = c->bn.used; i < c->bn.len; i++) {
+ c->bn.val[i] = BN_new();
+ if (c->bn.val[i] == NULL) {
+ c->bn.len = i;
+ return NULL;
+ }
+ }
+ }
+ return c->bn.val[c->bn.used++];
+}
+
+void
+BN_CTX_start(BN_CTX *c)
+{
+ if (c->stack.used == c->stack.len) {
+ void *ptr;
+ c->stack.len += 16;
+ ptr = realloc(c->stack.val, c->stack.len * sizeof(c->stack.val[0]));
+ if (ptr == NULL)
+ abort();
+ c->stack.val = ptr;
+ }
+ c->stack.val[c->stack.used++] = c->bn.used;
+}
+
+void
+BN_CTX_end(BN_CTX *c)
+{
+ const size_t prev = c->stack.val[c->stack.used - 1];
+ size_t i;
+
+ if (c->stack.used == 0)
+ abort();
+
+ for (i = prev; i < c->bn.used; i++)
+ BN_clear(c->bn.val[i]);
+
+ c->stack.used--;
+ c->bn.used = prev;
+}
+
diff --git a/source4/heimdal/lib/hcrypto/bn.h b/source4/heimdal/lib/hcrypto/bn.h
index aac770b5a8..2fa25ac1a0 100644
--- a/source4/heimdal/lib/hcrypto/bn.h
+++ b/source4/heimdal/lib/hcrypto/bn.h
@@ -62,16 +62,21 @@
#define BN_set_negative hc_BN_set_negative
#define BN_set_word hc_BN_set_word
#define BN_uadd hc_BN_uadd
+#define BN_CTX_new hc_BN_CTX_new
+#define BN_CTX_free hc_BN_CTX_free
+#define BN_CTX_get hc_BN_CTX_get
+#define BN_CTX_start hc_BN_CTX_start
+#define BN_CTX_end hc_BN_CTX_end
/*
*
*/
-typedef void BIGNUM;
+typedef struct BIGNUM BIGNUM;
typedef struct BN_GENCB BN_GENCB;
-typedef void BN_CTX;
-typedef void BN_MONT_CTX;
-typedef void BN_BLINDING;
+typedef struct BN_CTX BN_CTX;
+typedef struct BN_MONT_CTX BN_MONT_CTX;
+typedef struct BN_BLINDING BN_BLINDING;
struct BN_GENCB {
unsigned int ver;
@@ -118,4 +123,10 @@ int BN_rand(BIGNUM *, int, int, int);
void BN_GENCB_set(BN_GENCB *, int (*)(int, int, BN_GENCB *), void *);
int BN_GENCB_call(BN_GENCB *, int, int);
+BN_CTX *BN_CTX_new(void);
+void BN_CTX_free(BN_CTX *);
+BIGNUM *BN_CTX_get(BN_CTX *);
+void BN_CTX_start(BN_CTX *);
+void BN_CTX_end(BN_CTX *);
+
#endif
diff --git a/source4/heimdal/lib/hcrypto/evp-aes-cts.c b/source4/heimdal/lib/hcrypto/evp-aes-cts.c
index 685dcac18b..66f87982c0 100644
--- a/source4/heimdal/lib/hcrypto/evp-aes-cts.c
+++ b/source4/heimdal/lib/hcrypto/evp-aes-cts.c
@@ -31,11 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
-
-RCSID("$Id$");
#define HC_DEPRECATED
diff --git a/source4/heimdal/lib/hcrypto/evp.c b/source4/heimdal/lib/hcrypto/evp.c
index 517ca2a2bc..ac6cac972a 100644
--- a/source4/heimdal/lib/hcrypto/evp.c
+++ b/source4/heimdal/lib/hcrypto/evp.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006 - 2008 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -35,8 +35,6 @@
#include <config.h>
#endif
-RCSID("$Id$");
-
#define HC_DEPRECATED
#define HC_DEPRECATED_CRYPTO
@@ -512,13 +510,6 @@ EVP_md_null(void)
return &null;
}
-#if 0
-int EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type);
-int EVP_DigestFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s);
-int EVP_SignFinal(EVP_MD_CTX *, void *, size_t *, EVP_PKEY *);
-int EVP_VerifyFinal(EVP_MD_CTX *, const void *, size_t, EVP_PKEY *);
-#endif
-
/**
* Return the block size of the cipher.
*
@@ -1650,6 +1641,11 @@ EVP_CIPHER_CTX_rand_key(EVP_CIPHER_CTX *ctx, void *key)
/**
* Perform a operation on a ctx
*
+ * @param ctx context to perform operation on.
+ * @param type type of operation.
+ * @param arg argument to operation.
+ * @param data addition data to operation.
+
* @return 1 for success, 0 for failure.
*
* @ingroup hcrypto_core
diff --git a/source4/heimdal/lib/hcrypto/rand-unix.c b/source4/heimdal/lib/hcrypto/rand-unix.c
index 0c2185776c..07d81eb620 100644
--- a/source4/heimdal/lib/hcrypto/rand-unix.c
+++ b/source4/heimdal/lib/hcrypto/rand-unix.c
@@ -40,11 +40,15 @@ RCSID("$Id$");
#include <stdio.h>
#include <stdlib.h>
#include <rand.h>
+#include <heim_threads.h>
#include <roken.h>
#include "randi.h"
+static int random_fd = -1;
+static HEIMDAL_MUTEX random_mutex = HEIMDAL_MUTEX_INITIALIZER;
+
/*
* Unix /dev/random
*/
@@ -88,31 +92,47 @@ unix_seed(const void *indata, int size)
}
+
static int
unix_bytes(unsigned char *outdata, int size)
{
ssize_t count;
- int fd;
+ int once = 0;
if (size <= 0)
return 0;
- fd = get_device_fd(O_RDONLY);
- if (fd < 0)
- return 0;
+ HEIMDAL_MUTEX_lock(&random_mutex);
+ if (random_fd == -1) {
+ retry:
+ random_fd = get_device_fd(O_RDONLY);
+ if (random_fd < 0) {
+ HEIMDAL_MUTEX_unlock(&random_mutex);
+ return 0;
+ }
+ }
while (size > 0) {
- count = read (fd, outdata, size);
- if (count < 0 && errno == EINTR)
- continue;
- else if (count <= 0) {
- close(fd);
+ HEIMDAL_MUTEX_unlock(&random_mutex);
+ count = read (random_fd, outdata, size);
+ HEIMDAL_MUTEX_lock(&random_mutex);
+ if (random_fd < 0) {
+ if (errno == EINTR)
+ continue;
+ else if (errno == EBADF && once++ == 0) {
+ close(random_fd);
+ random_fd = -1;
+ goto retry;
+ }
+ return 0;
+ } else if (count <= 0) {
+ HEIMDAL_MUTEX_unlock(&random_mutex);
return 0;
}
outdata += count;
size -= count;
}
- close(fd);
+ HEIMDAL_MUTEX_unlock(&random_mutex);
return 1;
}
diff --git a/source4/heimdal/lib/hcrypto/rand.c b/source4/heimdal/lib/hcrypto/rand.c
index b8ac2155d1..a61c9cdfb2 100644
--- a/source4/heimdal/lib/hcrypto/rand.c
+++ b/source4/heimdal/lib/hcrypto/rand.c
@@ -62,7 +62,11 @@ init_method(void)
{
if (selected_meth != NULL)
return;
+#ifdef __APPLE__
+ selected_meth = &hc_rand_unix_method;
+#else
selected_meth = &hc_rand_fortuna_method;
+#endif
}
/**
diff --git a/source4/heimdal/lib/hdb/dbinfo.c b/source4/heimdal/lib/hdb/dbinfo.c
index 2121577bb1..7e2961c614 100644
--- a/source4/heimdal/lib/hdb/dbinfo.c
+++ b/source4/heimdal/lib/hdb/dbinfo.c
@@ -228,10 +228,12 @@ hdb_free_dbinfo(krb5_context context, struct hdb_dbinfo **dbp)
for(di = *dbp; di != NULL; di = ndi) {
ndi = di->next;
+ free (di->label);
free (di->realm);
free (di->dbname);
- if (di->mkey_file)
- free (di->mkey_file);
+ free (di->mkey_file);
+ free (di->acl_file);
+ free (di->log_file);
free(di);
}
*dbp = NULL;
diff --git a/source4/heimdal/lib/hdb/ext.c b/source4/heimdal/lib/hdb/ext.c
index f792b85c09..9053fd6633 100644
--- a/source4/heimdal/lib/hdb/ext.c
+++ b/source4/heimdal/lib/hdb/ext.c
@@ -235,6 +235,20 @@ hdb_entry_get_pkinit_hash(const hdb_entry *entry, const HDB_Ext_PKINIT_hash **a)
}
krb5_error_code
+hdb_entry_get_pkinit_cert(const hdb_entry *entry, const HDB_Ext_PKINIT_cert **a)
+{
+ const HDB_extension *ext;
+
+ ext = hdb_find_extension(entry, choice_HDB_extension_data_pkinit_cert);
+ if (ext)
+ *a = &ext->data.u.pkinit_cert;
+ else
+ *a = NULL;
+
+ return 0;
+}
+
+krb5_error_code
hdb_entry_get_pw_change_time(const hdb_entry *entry, time_t *t)
{
const HDB_extension *ext;
diff --git a/source4/heimdal/lib/hdb/hdb.asn1 b/source4/heimdal/lib/hdb/hdb.asn1
index 5cddf8f1d0..c2abd4af73 100644
--- a/source4/heimdal/lib/hdb/hdb.asn1
+++ b/source4/heimdal/lib/hdb/hdb.asn1
@@ -13,7 +13,8 @@ hdb-afs3-salt INTEGER ::= 10
Salt ::= SEQUENCE {
type[0] INTEGER (0..4294967295),
- salt[1] OCTET STRING
+ salt[1] OCTET STRING,
+ opaque[2] OCTET STRING OPTIONAL
}
Key ::= SEQUENCE {
@@ -64,6 +65,10 @@ HDB-Ext-PKINIT-hash ::= SEQUENCE OF SEQUENCE {
digest[1] OCTET STRING
}
+HDB-Ext-PKINIT-cert ::= SEQUENCE OF SEQUENCE {
+ cert[0] OCTET STRING
+}
+
HDB-Ext-Constrained-delegation-acl ::= SEQUENCE OF Principal
-- hdb-ext-referrals ::= PA-SERVER-REFERRAL-DATA
@@ -94,6 +99,7 @@ HDB-extension ::= SEQUENCE {
password[5] HDB-Ext-Password,
aliases[6] HDB-Ext-Aliases,
last-pw-change[7] KerberosTime,
+ pkinit-cert[8] HDB-Ext-PKINIT-cert,
...
},
...
@@ -101,6 +107,10 @@ HDB-extension ::= SEQUENCE {
HDB-extensions ::= SEQUENCE OF HDB-extension
+hdb_keyset ::= SEQUENCE {
+ kvno[1] INTEGER (0..4294967295),
+ keys[0] SEQUENCE OF Key
+}
hdb_entry ::= SEQUENCE {
principal[0] Principal OPTIONAL, -- this is optional only
diff --git a/source4/heimdal/lib/hdb/hdb.c b/source4/heimdal/lib/hdb/hdb.c
index ad2c35a43a..e55b0bed03 100644
--- a/source4/heimdal/lib/hdb/hdb.c
+++ b/source4/heimdal/lib/hdb/hdb.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -31,11 +31,6 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "krb5.h"
#include "krb5_locl.h"
#include "hdb_locl.h"
RCSID("$Id$");
@@ -44,24 +39,49 @@ RCSID("$Id$");
#include <dlfcn.h>
#endif
+/*! @mainpage Heimdal database backend library
+ *
+ * @section intro Introduction
+ *
+ * Heimdal libhdb library provides the backend support for Heimdal kdc
+ * and kadmind. Its here where plugins for diffrent database engines
+ * can be pluged in and extend support for here Heimdal get the
+ * principal and policy data from.
+ *
+ * Example of Heimdal backend are:
+ * - Berkeley DB 1.85
+ * - Berkeley DB 3.0
+ * - Berkeley DB 4.0
+ * - New Berkeley DB
+ * - LDAP
+ *
+ *
+ * The project web page: http://www.h5l.org/
+ *
+ */
+
+
+
static struct hdb_method methods[] = {
#if HAVE_DB1 || HAVE_DB3
- {HDB_INTERFACE_VERSION, "db:", hdb_db_create},
+ { HDB_INTERFACE_VERSION, "db:", hdb_db_create},
#endif
#if HAVE_NDBM
- {HDB_INTERFACE_VERSION, "ndbm:", hdb_ndbm_create},
+ { HDB_INTERFACE_VERSION, "ndbm:", hdb_ndbm_create},
#endif
#if defined(OPENLDAP) && !defined(OPENLDAP_MODULE)
- {HDB_INTERFACE_VERSION, "ldap:", hdb_ldap_create},
- {HDB_INTERFACE_VERSION, "ldapi:", hdb_ldapi_create},
+ { HDB_INTERFACE_VERSION, "ldap:", hdb_ldap_create},
+ { HDB_INTERFACE_VERSION, "ldapi:", hdb_ldapi_create},
#endif
{0, NULL, NULL}
};
#if HAVE_DB1 || HAVE_DB3
-static struct hdb_method dbmetod = {"", hdb_db_create };
+static struct hdb_method dbmetod =
+ { HDB_INTERFACE_VERSION, "", hdb_db_create };
#elif defined(HAVE_NDBM)
-static struct hdb_method dbmetod = {"", hdb_ndbm_create };
+static struct hdb_method dbmetod =
+ { HDB_INTERFACE_VERSION, "", hdb_ndbm_create };
#endif
@@ -265,9 +285,10 @@ find_dynamic_method (krb5_context context,
len = p - filename;
*rest = filename + len + 1;
- prefix = strndup(filename, len);
+ prefix = malloc(len + 1);
if (prefix == NULL)
krb5_errx(context, 1, "out of memory");
+ strlcpy(prefix, filename, len + 1);
if (asprintf(&path, LIBDIR "/hdb_%s.so", prefix) == -1)
krb5_errx(context, 1, "out of memory");
@@ -390,6 +411,14 @@ hdb_list_builtin(krb5_context context, char **list)
return 0;
}
+/**
+ * Create a handle for a Kerberos database
+ *
+ * Create a handle for a Kerberos database backend specified by a
+ * filename. Doesn't create a file if its doesn't exists, you have to
+ * use O_CREAT to tell the backend to create the file.
+ */
+
krb5_error_code
hdb_create(krb5_context context, HDB **db, const char *filename)
{
diff --git a/source4/heimdal/lib/hdb/hdb.h b/source4/heimdal/lib/hdb/hdb.h
index 53b1defc96..ce219153b3 100644
--- a/source4/heimdal/lib/hdb/hdb.h
+++ b/source4/heimdal/lib/hdb/hdb.h
@@ -66,65 +66,122 @@ typedef struct hdb_entry_ex {
} hdb_entry_ex;
+/**
+ * HDB backend function pointer structure
+ *
+ * The HDB structure is what the KDC and kadmind framework uses to
+ * query the backend database when talking about principals.
+ */
+
typedef struct HDB{
void *hdb_db;
- void *hdb_dbc;
+ void *hdb_dbc; /** don't use, only for DB3 */
char *hdb_name;
int hdb_master_key_set;
hdb_master_key hdb_master_key;
int hdb_openp;
- krb5_error_code (*hdb_open)(krb5_context,
- struct HDB*,
- int,
- mode_t);
- krb5_error_code (*hdb_close)(krb5_context,
- struct HDB*);
- void (*hdb_free)(krb5_context,
- struct HDB*,
- hdb_entry_ex*);
- krb5_error_code (*hdb_fetch)(krb5_context,
- struct HDB*,
- krb5_const_principal,
- unsigned,
- hdb_entry_ex*);
- krb5_error_code (*hdb_store)(krb5_context,
- struct HDB*,
- unsigned,
+ /**
+ * Open (or create) the a Kerberos database.
+ *
+ * Open (or create) the a Kerberos database that was resolved with
+ * hdb_create(). The third and fourth flag to the function are the
+ * same as open(), thus passing O_CREAT will create the data base
+ * if it doesn't exists.
+ *
+ * Then done the caller should call hdb_close(), and to release
+ * all resources hdb_destroy().
+ */
+ krb5_error_code (*hdb_open)(krb5_context, struct HDB*, int, mode_t);
+ /**
+ * Close the database for transaction
+ *
+ * Closes the database for further transactions, wont release any
+ * permanant resources. the database can be ->hdb_open-ed again.
+ */
+ krb5_error_code (*hdb_close)(krb5_context, struct HDB*);
+ /**
+ * Free an entry after use.
+ */
+ void (*hdb_free)(krb5_context, struct HDB*, hdb_entry_ex*);
+ /**
+ * Fetch an entry from the backend
+ *
+ * Fetch an entry from the backend, flags are what type of entry
+ * should be fetch: client, server, krbtgt.
+ */
+ krb5_error_code (*hdb_fetch)(krb5_context, struct HDB*,
+ krb5_const_principal, unsigned,
hdb_entry_ex*);
- krb5_error_code (*hdb_remove)(krb5_context,
- struct HDB*,
+ /**
+ * Store an entry to database
+ */
+ krb5_error_code (*hdb_store)(krb5_context, struct HDB*,
+ unsigned, hdb_entry_ex*);
+ /**
+ * Remove an entry from the database.
+ */
+ krb5_error_code (*hdb_remove)(krb5_context, struct HDB*,
krb5_const_principal);
- krb5_error_code (*hdb_firstkey)(krb5_context,
- struct HDB*,
- unsigned,
- hdb_entry_ex*);
- krb5_error_code (*hdb_nextkey)(krb5_context,
- struct HDB*,
- unsigned,
- hdb_entry_ex*);
- krb5_error_code (*hdb_lock)(krb5_context,
- struct HDB*,
- int operation);
- krb5_error_code (*hdb_unlock)(krb5_context,
- struct HDB*);
- krb5_error_code (*hdb_rename)(krb5_context,
- struct HDB*,
- const char*);
- krb5_error_code (*hdb__get)(krb5_context,
- struct HDB*,
- krb5_data,
- krb5_data*);
- krb5_error_code (*hdb__put)(krb5_context,
- struct HDB*,
- int,
- krb5_data,
- krb5_data);
- krb5_error_code (*hdb__del)(krb5_context,
- struct HDB*,
- krb5_data);
- krb5_error_code (*hdb_destroy)(krb5_context,
- struct HDB*);
+ /**
+ * As part of iteration, fetch one entry
+ */
+ krb5_error_code (*hdb_firstkey)(krb5_context, struct HDB*,
+ unsigned, hdb_entry_ex*);
+ /**
+ * As part of iteration, fetch next entry
+ */
+ krb5_error_code (*hdb_nextkey)(krb5_context, struct HDB*,
+ unsigned, hdb_entry_ex*);
+ /**
+ * Lock database
+ *
+ * A lock can only be held by one consumers. Transaction can still
+ * happen on the database while the lock is held, so the entry is
+ * only useful for syncroning creation of the database and renaming of the database.
+ */
+ krb5_error_code (*hdb_lock)(krb5_context, struct HDB*, int);
+ /**
+ * Unlock database
+ */
+ krb5_error_code (*hdb_unlock)(krb5_context, struct HDB*);
+ /**
+ * Rename the data base.
+ */
+ krb5_error_code (*hdb_rename)(krb5_context, struct HDB*, const char*);
+ /**
+ * Get an hdb_entry from a classical DB backend
+ *
+ * If the database is a classical DB (ie BDB, NDBM, GDBM, etc)
+ * backend, this function will take a principal key (krb5_data)
+ * and return all data related to principal in the return
+ * krb5_data. The returned encoded entry is of type hdb_entry or
+ * hdb_entry_alias.
+ */
+ krb5_error_code (*hdb__get)(krb5_context, struct HDB*,
+ krb5_data, krb5_data*);
+ /**
+ * Store an hdb_entry from a classical DB backend
+ *
+ * Same discussion as in @ref HDB::hdb__get
+ */
+ krb5_error_code (*hdb__put)(krb5_context, struct HDB*, int,
+ krb5_data, krb5_data);
+ /**
+ * Delete and hdb_entry from a classical DB backend
+ *
+ * Same discussion as in @ref HDB::hdb__get
+ */
+ krb5_error_code (*hdb__del)(krb5_context, struct HDB*, krb5_data);
+ /**
+ * Destroy the handle to the database.
+ *
+ * Destroy the handle to the database, deallocate all memory and
+ * related resources. Does not remove any permanent data. Its the
+ * logical reverse of hdb_create() function that is the entry
+ * point for the module.
+ */
+ krb5_error_code (*hdb_destroy)(krb5_context, struct HDB*);
}HDB;
#define HDB_INTERFACE_VERSION 4
diff --git a/source4/heimdal/lib/hdb/keys.c b/source4/heimdal/lib/hdb/keys.c
index b9f294e2eb..50fe7d7fda 100644
--- a/source4/heimdal/lib/hdb/keys.c
+++ b/source4/heimdal/lib/hdb/keys.c
@@ -1,3 +1,4 @@
+
/*
* Copyright (c) 1997 - 2001, 2003 - 2004 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
@@ -172,8 +173,8 @@ parse_key_set(krb5_context context, const char *key,
if(salt->salttype == KRB5_PW_SALT)
ret = krb5_get_pw_salt(context, principal, salt);
else if(salt->salttype == KRB5_AFS3_SALT) {
- krb5_realm *realm = krb5_princ_realm(context, principal);
- salt->saltvalue.data = strdup(*realm);
+ krb5_const_realm realm = krb5_principal_get_realm(context, principal);
+ salt->saltvalue.data = strdup(realm);
if(salt->saltvalue.data == NULL) {
krb5_set_error_message(context, ENOMEM,
"out of memory while "
@@ -181,7 +182,7 @@ parse_key_set(krb5_context context, const char *key,
return ENOMEM;
}
strlwr(salt->saltvalue.data);
- salt->saltvalue.length = strlen(*realm);
+ salt->saltvalue.length = strlen(realm);
}
}
@@ -217,7 +218,7 @@ add_enctype_to_key_set(Key **key_set, size_t *nkeyset,
key.key.keyvalue.data = NULL;
if (salt) {
- key.salt = malloc(sizeof(*key.salt));
+ key.salt = calloc(1, sizeof(*key.salt));
if (key.salt == NULL) {
free_Key(&key);
return ENOMEM;
@@ -259,7 +260,6 @@ hdb_generate_key_set(krb5_context context, krb5_principal principal,
Key *k, *key_set;
int i, j;
char *default_keytypes[] = {
- "des:pw-salt",
"aes256-cts-hmac-sha1-96:pw-salt",
"des3-cbc-sha1:pw-salt",
"arcfour-hmac-md5:pw-salt",
@@ -271,9 +271,6 @@ hdb_generate_key_set(krb5_context context, krb5_principal principal,
if (ktypes == NULL)
ktypes = default_keytypes;
- if (ktypes == NULL)
- abort();
-
*ret_key_set = key_set = NULL;
*nkeyset = 0;
diff --git a/source4/heimdal/lib/hdb/keytab.c b/source4/heimdal/lib/hdb/keytab.c
index a890ba62cd..97989a9764 100644
--- a/source4/heimdal/lib/hdb/keytab.c
+++ b/source4/heimdal/lib/hdb/keytab.c
@@ -59,7 +59,7 @@ hdb_resolve(krb5_context context, const char *name, krb5_keytab id)
return ENOMEM;
}
db = name;
- mkey = strrchr(name, ':');
+ mkey = strchr(name, ':');
if(mkey == NULL || mkey[1] == '\0') {
if(*name == '\0')
d->dbname = NULL;
@@ -147,7 +147,7 @@ find_db (krb5_context context,
const krb5_config_binding *top_bind = NULL;
const krb5_config_binding *default_binding = NULL;
const krb5_config_binding *db;
- krb5_realm *prealm = krb5_princ_realm(context, rk_UNCONST(principal));
+ krb5_const_realm realm = krb5_principal_get_realm(context, principal);
*dbname = *mkey = NULL;
@@ -169,7 +169,7 @@ find_db (krb5_context context,
krb5_warnx(context, "WARNING: using the first encountered");
} else
default_binding = db;
- } else if (strcmp (*prealm, p) == 0) {
+ } else if (strcmp (realm, p) == 0) {
set_config (context, db, dbname, mkey);
break;
}
@@ -263,6 +263,7 @@ krb5_kt_ops hdb_kt_ops = {
hdb_resolve,
hdb_get_name,
hdb_close,
+ NULL, /* destroy */
hdb_get_entry,
NULL, /* start_seq_get */
NULL, /* next_entry */
diff --git a/source4/heimdal/lib/hdb/mkey.c b/source4/heimdal/lib/hdb/mkey.c
index ce1aa9aff1..1520c4f7e9 100644
--- a/source4/heimdal/lib/hdb/mkey.c
+++ b/source4/heimdal/lib/hdb/mkey.c
@@ -169,23 +169,24 @@ read_master_mit(krb5_context context, const char *filename,
return errno;
}
krb5_storage_set_flags(sp, KRB5_STORAGE_HOST_BYTEORDER);
-#if 0
/* could possibly use ret_keyblock here, but do it with more
checks for now */
- ret = krb5_ret_keyblock(sp, &key);
-#else
- ret = krb5_ret_int16(sp, &enctype);
- if((htons(enctype) & 0xff00) == 0x3000) {
- ret = HEIM_ERR_BAD_MKEY;
- krb5_set_error_message(context, ret, "unknown keytype in %s: %#x, expected %#x",
- filename, htons(enctype), 0x3000);
- goto out;
+ {
+ ret = krb5_ret_int16(sp, &enctype);
+ if (ret)
+ goto out;
+ if((htons(enctype) & 0xff00) == 0x3000) {
+ ret = HEIM_ERR_BAD_MKEY;
+ krb5_set_error_message(context, ret, "unknown keytype in %s: "
+ "%#x, expected %#x",
+ filename, htons(enctype), 0x3000);
+ goto out;
+ }
+ key.keytype = enctype;
+ ret = krb5_ret_data(sp, &key.keyvalue);
+ if(ret)
+ goto out;
}
- key.keytype = enctype;
- ret = krb5_ret_data(sp, &key.keyvalue);
- if(ret)
- goto out;
-#endif
ret = hdb_process_master_key(context, 0, &key, 0, mkey);
krb5_free_keyblock_contents(context, &key);
out:
diff --git a/source4/heimdal/lib/hdb/ndbm.c b/source4/heimdal/lib/hdb/ndbm.c
index e71125c61f..1e9df81652 100644
--- a/source4/heimdal/lib/hdb/ndbm.c
+++ b/source4/heimdal/lib/hdb/ndbm.c
@@ -53,9 +53,7 @@ struct ndbm_db {
static krb5_error_code
NDBM_destroy(krb5_context context, HDB *db)
{
- krb5_error_code ret;
-
- ret = hdb_clear_master_key (context, db);
+ hdb_clear_master_key (context, db);
free(db->hdb_name);
free(db);
return 0;
diff --git a/source4/heimdal/lib/hx509/ca.c b/source4/heimdal/lib/hx509/ca.c
index cbd58ebd01..624d74289d 100644
--- a/source4/heimdal/lib/hx509/ca.c
+++ b/source4/heimdal/lib/hx509/ca.c
@@ -33,7 +33,6 @@
#include "hx_locl.h"
#include <pkinit_asn1.h>
-RCSID("$Id$");
/**
* @page page_ca Hx509 CA functions
@@ -672,7 +671,7 @@ hx509_ca_tbs_add_san_pkinit(hx509_context context,
ret = hx509_ca_tbs_add_san_otherName(context,
tbs,
- oid_id_pkinit_san(),
+ &asn1_oid_id_pkinit_san,
&os);
free(os.data);
out:
@@ -736,7 +735,7 @@ hx509_ca_tbs_add_san_ms_upn(hx509_context context,
hx509_ca_tbs tbs,
const char *principal)
{
- return add_utf8_san(context, tbs, oid_id_pkinit_ms_san(), principal);
+ return add_utf8_san(context, tbs, &asn1_oid_id_pkinit_ms_san, principal);
}
/**
@@ -757,7 +756,7 @@ hx509_ca_tbs_add_san_jid(hx509_context context,
hx509_ca_tbs tbs,
const char *jid)
{
- return add_utf8_san(context, tbs, oid_id_pkix_on_xmppAddr(), jid);
+ return add_utf8_san(context, tbs, &asn1_oid_id_pkix_on_xmppAddr, jid);
}
@@ -926,7 +925,7 @@ build_proxy_prefix(hx509_context context, const Name *issuer, Name *subject)
return ENOMEM;
}
/* prefix with CN=<ts>,...*/
- ret = _hx509_name_modify(context, subject, 1, oid_id_at_commonName(), tstr);
+ ret = _hx509_name_modify(context, subject, 1, &asn1_oid_id_at_commonName, tstr);
free(tstr);
if (ret)
free_Name(subject);
@@ -1110,7 +1109,7 @@ ca_sign(hx509_context context,
data.length = 34;
ret = add_extension(context, tbsc, 0,
- oid_id_ms_cert_enroll_domaincontroller(),
+ &asn1_oid_id_ms_cert_enroll_domaincontroller,
&data);
if (ret)
goto out;
@@ -1129,7 +1128,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, 1,
- oid_id_x509_ce_keyUsage(), &data);
+ &asn1_oid_id_x509_ce_keyUsage, &data);
free(data.data);
if (ret)
goto out;
@@ -1146,7 +1145,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, 0,
- oid_id_x509_ce_extKeyUsage(), &data);
+ &asn1_oid_id_x509_ce_extKeyUsage, &data);
free(data.data);
if (ret)
goto out;
@@ -1163,7 +1162,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, 0,
- oid_id_x509_ce_subjectAltName(),
+ &asn1_oid_id_x509_ce_subjectAltName,
&data);
free(data.data);
if (ret)
@@ -1181,7 +1180,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, 0,
- oid_id_x509_ce_authorityKeyIdentifier(),
+ &asn1_oid_id_x509_ce_authorityKeyIdentifier,
&data);
free(data.data);
if (ret)
@@ -1214,7 +1213,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, 0,
- oid_id_x509_ce_subjectKeyIdentifier(),
+ &asn1_oid_id_x509_ce_subjectKeyIdentifier,
&data);
free(data.data);
if (ret)
@@ -1247,7 +1246,7 @@ ca_sign(hx509_context context,
_hx509_abort("internal ASN.1 encoder error");
/* Critical if this is a CA */
ret = add_extension(context, tbsc, tbs->flags.ca,
- oid_id_x509_ce_basicConstraints(),
+ &asn1_oid_id_x509_ce_basicConstraints,
&data);
free(data.data);
if (ret)
@@ -1271,7 +1270,7 @@ ca_sign(hx509_context context,
*info.pCPathLenConstraint = tbs->pathLenConstraint;
}
- ret = der_copy_oid(oid_id_pkix_ppl_inheritAll(),
+ ret = der_copy_oid(&asn1_oid_id_pkix_ppl_inheritAll,
&info.proxyPolicy.policyLanguage);
if (ret) {
free_ProxyCertInfo(&info);
@@ -1289,7 +1288,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, 0,
- oid_id_pkix_pe_proxyCertInfo(),
+ &asn1_oid_id_pkix_pe_proxyCertInfo,
&data);
free(data.data);
if (ret)
@@ -1307,7 +1306,7 @@ ca_sign(hx509_context context,
if (size != data.length)
_hx509_abort("internal ASN.1 encoder error");
ret = add_extension(context, tbsc, FALSE,
- oid_id_x509_ce_cRLDistributionPoints(),
+ &asn1_oid_id_x509_ce_cRLDistributionPoints,
&data);
free(data.data);
if (ret)
@@ -1399,8 +1398,7 @@ get_AuthorityKeyIdentifier(hx509_context context,
*/
ret = copy_Name(&certificate->tbsCertificate.subject, &name);
- if (ai->authorityCertSerialNumber == NULL) {
- ret = ENOMEM;
+ if (ret) {
hx509_set_error_string(context, 0, ret, "Out of memory");
goto out;
}
diff --git a/source4/heimdal/lib/hx509/cert.c b/source4/heimdal/lib/hx509/cert.c
index 121847faaa..cd9ae01fac 100644
--- a/source4/heimdal/lib/hx509/cert.c
+++ b/source4/heimdal/lib/hx509/cert.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
#include "crypto-headers.h"
#include <rtbl.h>
@@ -59,6 +58,7 @@ struct hx509_verify_ctx_data {
#define HX509_VERIFY_CTX_F_REQUIRE_RFC3280 4
#define HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS 8
#define HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS 16
+#define HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK 32
time_t time_now;
unsigned int max_depth;
#define HX509_VERIFY_MAX_DEPTH 30
@@ -432,6 +432,7 @@ hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
* Set the trust anchors in the verification context, makes an
* reference to the keyset, so the consumer can free the keyset
* independent of the destruction of the verification context (ctx).
+ * If there already is a keyset attached, it's released.
*
* @param ctx a verification context
* @param set a keyset containing the trust anchors.
@@ -442,6 +443,8 @@ hx509_verify_destroy_ctx(hx509_verify_ctx ctx)
void
hx509_verify_attach_anchors(hx509_verify_ctx ctx, hx509_certs set)
{
+ if (ctx->trust_anchors)
+ hx509_certs_free(&ctx->trust_anchors);
ctx->trust_anchors = _hx509_certs_ref(set);
}
@@ -569,6 +572,16 @@ hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean)
ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
}
+void
+hx509_verify_ctx_f_allow_best_before_signature_algs(hx509_context ctx,
+ int boolean)
+{
+ if (boolean)
+ ctx->flags &= ~HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
+ else
+ ctx->flags |= HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK;
+}
+
static const Extension *
find_extension(const Certificate *cert, const heim_oid *oid, int *idx)
{
@@ -594,7 +607,7 @@ find_extension_auth_key_id(const Certificate *subject,
memset(ai, 0, sizeof(*ai));
- e = find_extension(subject, oid_id_x509_ce_authorityKeyIdentifier(), &i);
+ e = find_extension(subject, &asn1_oid_id_x509_ce_authorityKeyIdentifier, &i);
if (e == NULL)
return HX509_EXTENSION_NOT_FOUND;
@@ -613,7 +626,7 @@ _hx509_find_extension_subject_key_id(const Certificate *issuer,
memset(si, 0, sizeof(*si));
- e = find_extension(issuer, oid_id_x509_ce_subjectKeyIdentifier(), &i);
+ e = find_extension(issuer, &asn1_oid_id_x509_ce_subjectKeyIdentifier, &i);
if (e == NULL)
return HX509_EXTENSION_NOT_FOUND;
@@ -632,7 +645,7 @@ find_extension_name_constraints(const Certificate *subject,
memset(nc, 0, sizeof(*nc));
- e = find_extension(subject, oid_id_x509_ce_nameConstraints(), &i);
+ e = find_extension(subject, &asn1_oid_id_x509_ce_nameConstraints, &i);
if (e == NULL)
return HX509_EXTENSION_NOT_FOUND;
@@ -650,7 +663,7 @@ find_extension_subject_alt_name(const Certificate *cert, int *i,
memset(sa, 0, sizeof(*sa));
- e = find_extension(cert, oid_id_x509_ce_subjectAltName(), i);
+ e = find_extension(cert, &asn1_oid_id_x509_ce_subjectAltName, i);
if (e == NULL)
return HX509_EXTENSION_NOT_FOUND;
@@ -668,7 +681,7 @@ find_extension_eku(const Certificate *cert, ExtKeyUsage *eku)
memset(eku, 0, sizeof(*eku));
- e = find_extension(cert, oid_id_x509_ce_extKeyUsage(), &i);
+ e = find_extension(cert, &asn1_oid_id_x509_ce_extKeyUsage, &i);
if (e == NULL)
return HX509_EXTENSION_NOT_FOUND;
@@ -748,8 +761,7 @@ hx509_cert_find_subjectAltName_otherName(hx509_context context,
ret = find_extension_subject_alt_name(_hx509_get_cert(cert), &i, &sa);
i++;
if (ret == HX509_EXTENSION_NOT_FOUND) {
- ret = 0;
- break;
+ return 0;
} else if (ret != 0) {
hx509_set_error_string(context, 0, ret, "Error searching for SAN");
hx509_free_octet_string_list(list);
@@ -773,7 +785,6 @@ hx509_cert_find_subjectAltName_otherName(hx509_context context,
}
free_GeneralNames(&sa);
}
- return 0;
}
@@ -790,7 +801,7 @@ check_key_usage(hx509_context context, const Certificate *cert,
if (_hx509_cert_get_version(cert) < 3)
return 0;
- e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
+ e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i);
if (e == NULL) {
if (req_present) {
hx509_set_error_string(context, 0, HX509_KU_CERT_MISSING,
@@ -847,7 +858,7 @@ check_basic_constraints(hx509_context context, const Certificate *cert,
if (_hx509_cert_get_version(cert) < 3)
return 0;
- e = find_extension(cert, oid_id_x509_ce_basicConstraints(), &i);
+ e = find_extension(cert, &asn1_oid_id_x509_ce_basicConstraints, &i);
if (e == NULL) {
switch(type) {
case PROXY_CERT:
@@ -1134,7 +1145,7 @@ is_proxy_cert(hx509_context context,
if (rinfo)
memset(rinfo, 0, sizeof(*rinfo));
- e = find_extension(cert, oid_id_pkix_pe_proxyCertInfo(), &i);
+ e = find_extension(cert, &asn1_oid_id_pkix_pe_proxyCertInfo, &i);
if (e == NULL) {
hx509_clear_error_string(context);
return HX509_EXTENSION_NOT_FOUND;
@@ -1472,7 +1483,9 @@ hx509_cert_get_SPKI(hx509_context context, hx509_cert p, SubjectPublicKeyInfo *s
* @param context a hx509 context.
* @param p a hx509 certificate object.
* @param alg AlgorithmIdentifier, should be freed with
- * free_AlgorithmIdentifier().
+ * free_AlgorithmIdentifier(). The algorithmidentifier is
+ * typicly rsaEncryption, or id-ecPublicKey, or some other
+ * public key mechanism.
*
* @return An hx509 error code, see hx509_get_error_string().
*
@@ -2003,7 +2016,7 @@ hx509_verify_path(hx509_context context,
free_ProxyCertInfo(&info);
j = 0;
- if (find_extension(c, oid_id_x509_ce_subjectAltName(), &j)) {
+ if (find_extension(c, &asn1_oid_id_x509_ce_subjectAltName, &j)) {
ret = HX509_PROXY_CERT_INVALID;
hx509_set_error_string(context, 0, ret,
"Proxy certificate have explicity "
@@ -2012,7 +2025,7 @@ hx509_verify_path(hx509_context context,
}
j = 0;
- if (find_extension(c, oid_id_x509_ce_issuerAltName(), &j)) {
+ if (find_extension(c, &asn1_oid_id_x509_ce_issuerAltName, &j)) {
ret = HX509_PROXY_CERT_INVALID;
hx509_set_error_string(context, 0, ret,
"Proxy certificate have explicity "
@@ -2053,7 +2066,7 @@ hx509_verify_path(hx509_context context,
if (proxy_issuer.u.rdnSequence.len < 2
|| proxy_issuer.u.rdnSequence.val[j - 1].len > 1
|| der_heim_oid_cmp(&proxy_issuer.u.rdnSequence.val[j - 1].val[0].type,
- oid_id_at_commonName()))
+ &asn1_oid_id_at_commonName))
{
ret = HX509_PROXY_CERT_NAME_WRONG;
hx509_set_error_string(context, 0, ret,
@@ -2263,6 +2276,24 @@ hx509_verify_path(hx509_context context,
"Failed to verify signature of certificate");
goto out;
}
+ /*
+ * Verify that the sigature algorithm "best-before" date is
+ * before the creation date of the certificate, do this for
+ * trust anchors too, since any trust anchor that is created
+ * after a algorithm is known to be bad deserved to be invalid.
+ *
+ * Skip the leaf certificate for now...
+ */
+
+ if (i != 0 && (ctx->flags & HX509_VERIFY_CTX_F_NO_BEST_BEFORE_CHECK) == 0) {
+ time_t notBefore =
+ _hx509_Time2time_t(&c->tbsCertificate.validity.notBefore);
+ ret = _hx509_signature_best_before(context,
+ &c->signatureAlgorithm,
+ notBefore);
+ if (ret)
+ goto out;
+ }
}
out:
@@ -2329,6 +2360,7 @@ hx509_verify_hostname(hx509_context context,
/* XXX krb5_socklen_t */ int sa_size)
{
GeneralNames san;
+ const Name *name;
int ret, i, j;
if (sa && sa_size <= 0)
@@ -2339,11 +2371,10 @@ hx509_verify_hostname(hx509_context context,
i = 0;
do {
ret = find_extension_subject_alt_name(cert->data, &i, &san);
- if (ret == HX509_EXTENSION_NOT_FOUND) {
- ret = 0;
- break;
- } else if (ret != 0)
+ if (ret == HX509_EXTENSION_NOT_FOUND)
break;
+ else if (ret != 0)
+ return HX509_PARSING_NAME_FAILED;
for (j = 0; j < san.len; j++) {
switch (san.val[j].element) {
@@ -2360,31 +2391,31 @@ hx509_verify_hostname(hx509_context context,
free_GeneralNames(&san);
} while (1);
- {
- const Name *name = &cert->data->tbsCertificate.subject;
-
- /* match if first component is a CN= */
- if (name->u.rdnSequence.len > 0
- && name->u.rdnSequence.val[0].len == 1
- && der_heim_oid_cmp(&name->u.rdnSequence.val[0].val[0].type,
- oid_id_at_commonName()) == 0)
- {
- DirectoryString *ds = &name->u.rdnSequence.val[0].val[0].value;
-
- switch (ds->element) {
- case choice_DirectoryString_printableString:
- if (strcasecmp(ds->u.printableString, hostname) == 0)
- return 0;
- break;
- case choice_DirectoryString_ia5String:
- if (strcasecmp(ds->u.ia5String, hostname) == 0)
+ name = &cert->data->tbsCertificate.subject;
+
+ /* Find first CN= in the name, and try to match the hostname on that */
+ for (ret = 0, i = name->u.rdnSequence.len - 1; ret == 0 && i >= 0; i--) {
+ for (j = 0; ret == 0 && j < name->u.rdnSequence.val[i].len; j++) {
+ AttributeTypeAndValue *n = &name->u.rdnSequence.val[i].val[j];
+
+ if (der_heim_oid_cmp(&n->type, &asn1_oid_id_at_commonName) == 0) {
+ DirectoryString *ds = &n->value;
+ switch (ds->element) {
+ case choice_DirectoryString_printableString:
+ if (strcasecmp(ds->u.printableString, hostname) == 0)
+ return 0;
+ break;
+ case choice_DirectoryString_ia5String:
+ if (strcasecmp(ds->u.ia5String, hostname) == 0)
return 0;
- break;
- case choice_DirectoryString_utf8String:
- if (strcasecmp(ds->u.utf8String, hostname) == 0)
- return 0;
- default:
- break;
+ break;
+ case choice_DirectoryString_utf8String:
+ if (strcasecmp(ds->u.utf8String, hostname) == 0)
+ return 0;
+ default:
+ break;
+ }
+ ret = HX509_NAME_CONSTRAINT_ERROR;
}
}
}
@@ -2495,7 +2526,7 @@ hx509_cert_get_friendly_name(hx509_cert cert)
if (cert->friendlyname)
return cert->friendlyname;
- a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_friendlyName());
+ a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_friendlyName);
if (a == NULL) {
hx509_name name;
@@ -2746,7 +2777,7 @@ hx509_query_match_expr(hx509_context context, hx509_query *q, const char *expr)
int
hx509_query_match_cmp_func(hx509_query *q,
- int (*func)(void *, hx509_cert),
+ int (*func)(hx509_context, hx509_cert, void *),
void *ctx)
{
if (func)
@@ -2869,7 +2900,7 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert
if (q->match & HX509_QUERY_MATCH_LOCAL_KEY_ID) {
hx509_cert_attribute a;
- a = hx509_cert_get_attribute(cert, oid_id_pkcs_9_at_localKeyId());
+ a = hx509_cert_get_attribute(cert, &asn1_oid_id_pkcs_9_at_localKeyId);
if (a == NULL)
return 0;
if (der_heim_octet_string_cmp(&a->data, q->local_key_id) != 0)
@@ -2891,7 +2922,7 @@ _hx509_query_match_cert(hx509_context context, const hx509_query *q, hx509_cert
return 0;
}
if (q->match & HX509_QUERY_MATCH_FUNCTION) {
- ret = (*q->cmp_func)(q->cmp_func_ctx, cert);
+ ret = (*q->cmp_func)(context, cert, q->cmp_func_ctx);
if (ret != 0)
return 0;
}
@@ -3163,7 +3194,7 @@ _hx509_cert_get_keyusage(hx509_context context,
if (_hx509_cert_get_version(cert) < 3)
return 0;
- e = find_extension(cert, oid_id_x509_ce_keyUsage(), &i);
+ e = find_extension(cert, &asn1_oid_id_x509_ce_keyUsage, &i);
if (e == NULL)
return HX509_KU_CERT_MISSING;
@@ -3348,6 +3379,46 @@ _hx509_cert_to_env(hx509_context context, hx509_cert cert, hx509_env *env)
}
}
+ {
+ Certificate *c = _hx509_get_cert(cert);
+ heim_octet_string os, sig;
+ hx509_env envhash = NULL;
+ char *buf;
+
+ os.data = c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.data;
+ os.length =
+ c->tbsCertificate.subjectPublicKeyInfo.subjectPublicKey.length / 8;
+
+ ret = _hx509_create_signature(context,
+ NULL,
+ hx509_signature_sha1(),
+ &os,
+ NULL,
+ &sig);
+ if (ret != 0)
+ goto out;
+
+ ret = hex_encode(sig.data, sig.length, &buf);
+ der_free_octet_string(&sig);
+ if (ret < 0) {
+ ret = ENOMEM;
+ hx509_set_error_string(context, 0, ret,
+ "Out of memory");
+ goto out;
+ }
+
+ ret = hx509_env_add(context, &envhash, "sha1", buf);
+ free(buf);
+ if (ret)
+ goto out;
+
+ ret = hx509_env_add_binding(context, &envcert, "hash", envhash);
+ if (ret) {
+ hx509_env_free(&envhash);
+ goto out;
+ }
+ }
+
ret = hx509_env_add_binding(context, env, "certificate", envcert);
if (ret)
goto out;
diff --git a/source4/heimdal/lib/hx509/cms.c b/source4/heimdal/lib/hx509/cms.c
index ba1800ddf2..4766c34655 100644
--- a/source4/heimdal/lib/hx509/cms.c
+++ b/source4/heimdal/lib/hx509/cms.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_cms CMS/PKCS7 message functions.
@@ -474,6 +473,9 @@ hx509_cms_unenvelope(hx509_context context,
if (ret)
goto out;
+ if (flags & HX509_CMS_UE_ALLOW_WEAK)
+ hx509_crypto_allow_weak(crypto);
+
if (params) {
ret = hx509_crypto_set_params(context, crypto, params, &ivec);
if (ret) {
@@ -527,7 +529,9 @@ out:
* used to RSA.
*
* @param context A hx509 context.
- * @param flags flags to control the behavior, no flags today
+ * @param flags flags to control the behavior.
+ * - HX509_CMS_EV_NO_KU_CHECK - Dont check KU on certificate
+ * - HX509_CMS_EV_ALLOW_WEAK - Allow weak crytpo
* @param cert Certificate to encrypt the EnvelopedData encryption key
* with.
* @param data pointer the data to encrypt.
@@ -565,16 +569,21 @@ hx509_cms_envelope_1(hx509_context context,
memset(content, 0, sizeof(*content));
if (encryption_type == NULL)
- encryption_type = oid_id_aes_256_cbc();
+ encryption_type = &asn1_oid_id_aes_256_cbc;
- ret = _hx509_check_key_usage(context, cert, 1 << 2, TRUE);
- if (ret)
- goto out;
+ if ((flags & HX509_CMS_EV_NO_KU_CHECK) == 0) {
+ ret = _hx509_check_key_usage(context, cert, 1 << 2, TRUE);
+ if (ret)
+ goto out;
+ }
ret = hx509_crypto_init(context, NULL, encryption_type, &crypto);
if (ret)
goto out;
+ if (flags & HX509_CMS_EV_ALLOW_WEAK)
+ hx509_crypto_allow_weak(crypto);
+
ret = hx509_crypto_set_random_key(crypto, &key);
if (ret) {
hx509_set_error_string(context, 0, ret,
@@ -738,12 +747,16 @@ find_attribute(const CMSAttributes *attr, const heim_oid *oid)
* Decode SignedData and verify that the signature is correct.
*
* @param context A hx509 context.
- * @param ctx a hx509 version context
- * @param data
+ * @param ctx a hx509 verify context.
+ * @param flags to control the behaivor of the function.
+ * - HX509_CMS_VS_NO_KU_CHECK - Don't check KeyUsage
+ * - HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH - allow oid mismatch
+ * - HX509_CMS_VS_ALLOW_ZERO_SIGNER - no signer, see below.
+ * @param data pointer to CMS SignedData encoded data.
* @param length length of the data that data point to.
- * @param signedContent
+ * @param signedContent external data used for signature.
* @param pool certificate pool to build certificates paths.
- * @param contentType free with der_free_oid()
+ * @param contentType free with der_free_oid().
* @param content the output of the function, free with
* der_free_octet_string().
* @param signer_certs list of the cerficates used to sign this
@@ -755,6 +768,7 @@ find_attribute(const CMSAttributes *attr, const heim_oid *oid)
int
hx509_cms_verify_signed(hx509_context context,
hx509_verify_ctx ctx,
+ unsigned int flags,
const void *data,
size_t length,
const heim_octet_string *signedContent,
@@ -797,8 +811,15 @@ hx509_cms_verify_signed(hx509_context context,
"Both external and internal SignedData");
goto out;
}
+
if (sd.encapContentInfo.eContent)
- signedContent = sd.encapContentInfo.eContent;
+ ret = der_copy_octet_string(sd.encapContentInfo.eContent, content);
+ else
+ ret = der_copy_octet_string(signedContent, content);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret, "malloc: out of memory");
+ goto out;
+ }
ret = hx509_certs_init(context, "MEMORY:cms-cert-buffer",
0, NULL, &certs);
@@ -823,7 +844,7 @@ hx509_cms_verify_signed(hx509_context context,
}
for (found_valid_sig = 0, i = 0; i < sd.signerInfos.len; i++) {
- heim_octet_string *signed_data;
+ heim_octet_string signed_data;
const heim_oid *match_oid;
heim_oid decode_oid;
@@ -841,8 +862,22 @@ hx509_cms_verify_signed(hx509_context context,
ret = find_CMSIdentifier(context, &signer_info->sid, certs,
_hx509_verify_get_time(ctx), &cert,
HX509_QUERY_KU_DIGITALSIGNATURE);
- if (ret)
- continue;
+ if (ret) {
+ /**
+ * If HX509_CMS_VS_NO_KU_CHECK is set, allow more liberal
+ * search for matching certificates by not considering
+ * KeyUsage bits on the certificates.
+ */
+ if ((flags & HX509_CMS_VS_NO_KU_CHECK) == 0)
+ continue;
+
+ ret = find_CMSIdentifier(context, &signer_info->sid, certs,
+ _hx509_verify_get_time(ctx), &cert,
+ 0);
+ if (ret)
+ continue;
+
+ }
if (signer_info->signedAttrs) {
const Attribute *attr;
@@ -854,7 +889,7 @@ hx509_cms_verify_signed(hx509_context context,
sa.len = signer_info->signedAttrs->len;
/* verify that sigature exists */
- attr = find_attribute(&sa, oid_id_pkcs9_messageDigest());
+ attr = find_attribute(&sa, &asn1_oid_id_pkcs9_messageDigest);
if (attr == NULL) {
ret = HX509_CRYPTO_SIGNATURE_MISSING;
hx509_set_error_string(context, 0, ret,
@@ -885,7 +920,7 @@ hx509_cms_verify_signed(hx509_context context,
ret = _hx509_verify_signature(context,
NULL,
&signer_info->digestAlgorithm,
- signedContent,
+ content,
&os);
der_free_octet_string(&os);
if (ret) {
@@ -898,9 +933,9 @@ hx509_cms_verify_signed(hx509_context context,
* Fetch content oid inside signedAttrs or set it to
* id-pkcs7-data.
*/
- attr = find_attribute(&sa, oid_id_pkcs9_contentType());
+ attr = find_attribute(&sa, &asn1_oid_id_pkcs9_contentType);
if (attr == NULL) {
- match_oid = oid_id_pkcs7_data();
+ match_oid = &asn1_oid_id_pkcs7_data;
} else {
if (attr->value.len != 1) {
ret = HX509_CMS_DATA_OID_MISMATCH;
@@ -922,36 +957,36 @@ hx509_cms_verify_signed(hx509_context context,
match_oid = &decode_oid;
}
- ALLOC(signed_data, 1);
- if (signed_data == NULL) {
- if (match_oid == &decode_oid)
- der_free_oid(&decode_oid);
- ret = ENOMEM;
- hx509_clear_error_string(context);
- goto next_sigature;
- }
-
ASN1_MALLOC_ENCODE(CMSAttributes,
- signed_data->data,
- signed_data->length,
+ signed_data.data,
+ signed_data.length,
&sa,
&size, ret);
if (ret) {
if (match_oid == &decode_oid)
der_free_oid(&decode_oid);
- free(signed_data);
hx509_clear_error_string(context);
goto next_sigature;
}
- if (size != signed_data->length)
+ if (size != signed_data.length)
_hx509_abort("internal ASN.1 encoder error");
} else {
- signed_data = rk_UNCONST(signedContent);
- match_oid = oid_id_pkcs7_data();
+ signed_data.data = content->data;
+ signed_data.length = content->length;
+ match_oid = &asn1_oid_id_pkcs7_data;
}
- if (der_heim_oid_cmp(match_oid, &sd.encapContentInfo.eContentType)) {
+ /**
+ * If HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH, allow
+ * encapContentInfo mismatch with the oid in signedAttributes
+ * (or if no signedAttributes where use, pkcs7-data oid).
+ * This is only needed to work with broken CMS implementations
+ * that doesn't follow CMS signedAttributes rules.
+ */
+
+ if (der_heim_oid_cmp(match_oid, &sd.encapContentInfo.eContentType) &&
+ (flags & HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH) == 0) {
ret = HX509_CMS_DATA_OID_MISMATCH;
hx509_set_error_string(context, 0, ret,
"Oid in message mismatch from the expected");
@@ -963,23 +998,28 @@ hx509_cms_verify_signed(hx509_context context,
ret = hx509_verify_signature(context,
cert,
&signer_info->signatureAlgorithm,
- signed_data,
+ &signed_data,
&signer_info->signature);
if (ret)
hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
- "Failed to verify sigature in "
+ "Failed to verify signature in "
"CMS SignedData");
}
- if (signed_data != signedContent) {
- der_free_octet_string(signed_data);
- free(signed_data);
- }
+ if (signer_info->signedAttrs)
+ free(signed_data.data);
if (ret)
goto next_sigature;
- ret = hx509_verify_path(context, ctx, cert, certs);
- if (ret)
- goto next_sigature;
+ /**
+ * If HX509_CMS_VS_NO_VALIDATE flags is set, do not verify the
+ * signing certificates and leave that up to the caller.
+ */
+
+ if ((flags & HX509_CMS_VS_NO_VALIDATE) == 0) {
+ ret = hx509_verify_path(context, ctx, cert, certs);
+ if (ret)
+ goto next_sigature;
+ }
ret = hx509_certs_add(context, *signer_certs, cert);
if (ret)
@@ -992,7 +1032,18 @@ hx509_cms_verify_signed(hx509_context context,
hx509_cert_free(cert);
cert = NULL;
}
- if (found_valid_sig == 0) {
+ /**
+ * If HX509_CMS_VS_ALLOW_ZERO_SIGNER is set, allow empty
+ * SignerInfo (no signatures). If SignedData have no signatures,
+ * the function will return 0 with signer_certs set to NULL. Zero
+ * signers is allowed by the standard, but since its only useful
+ * in corner cases, it make into a flag that the caller have to
+ * turn on.
+ */
+ if (sd.signerInfos.len == 0 && (flags & HX509_CMS_VS_ALLOW_ZERO_SIGNER)) {
+ if (*signer_certs)
+ hx509_certs_free(signer_certs);
+ } else if (found_valid_sig == 0) {
if (ret == 0) {
ret = HX509_CMS_SIGNER_NOT_FOUND;
hx509_set_error_string(context, 0, ret,
@@ -1007,20 +1058,13 @@ hx509_cms_verify_signed(hx509_context context,
goto out;
}
- content->data = malloc(signedContent->length);
- if (content->data == NULL) {
- hx509_clear_error_string(context);
- ret = ENOMEM;
- goto out;
- }
- content->length = signedContent->length;
- memcpy(content->data, signedContent->data, content->length);
-
out:
free_SignedData(&sd);
if (certs)
hx509_certs_free(&certs);
if (ret) {
+ if (content->data)
+ der_free_octet_string(content);
if (*signer_certs)
hx509_certs_free(signer_certs);
der_free_oid(contentType);
@@ -1097,26 +1141,55 @@ hx509_cms_create_signed_1(hx509_context context,
hx509_certs pool,
heim_octet_string *signed_data)
{
- AlgorithmIdentifier digest;
- hx509_name name;
- SignerInfo *signer_info;
- heim_octet_string buf, content, sigdata = { 0, NULL };
+ hx509_certs certs;
+ int ret = 0;
+
+ signed_data->data = NULL;
+ signed_data->length = 0;
+
+ ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &certs);
+ if (ret)
+ return ret;
+ ret = hx509_certs_add(context, certs, cert);
+ if (ret)
+ goto out;
+
+ ret = hx509_cms_create_signed(context, flags, eContentType, data, length,
+ digest_alg, certs, peer, anchors, pool,
+ signed_data);
+
+ out:
+ hx509_certs_free(&certs);
+ return ret;
+}
+
+struct sigctx {
SignedData sd;
- int ret;
+ const AlgorithmIdentifier *digest_alg;
+ const heim_oid *eContentType;
+ heim_octet_string content;
+ hx509_peer_info peer;
+ int cmsidflag;
+ hx509_certs certs;
+ hx509_certs anchors;
+ hx509_certs pool;
+};
+
+static int
+sig_process(hx509_context context, void *ctx, hx509_cert cert)
+{
+ struct sigctx *sigctx = ctx;
+ heim_octet_string buf, sigdata = { 0, NULL };
+ SignerInfo *signer_info = NULL;
+ AlgorithmIdentifier digest;
size_t size;
+ void *ptr;
+ int ret;
+ SignedData *sd = &sigctx->sd;
hx509_path path;
- int cmsidflag = CMS_ID_SKI;
- memset(&sd, 0, sizeof(sd));
- memset(&name, 0, sizeof(name));
- memset(&path, 0, sizeof(path));
memset(&digest, 0, sizeof(digest));
-
- content.data = rk_UNCONST(data);
- content.length = length;
-
- if (flags & HX509_CMS_SIGATURE_ID_NAME)
- cmsidflag = CMS_ID_NAME;
+ memset(&path, 0, sizeof(path));
if (_hx509_cert_private_key(cert) == NULL) {
hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
@@ -1124,55 +1197,37 @@ hx509_cms_create_signed_1(hx509_context context,
return HX509_PRIVATE_KEY_MISSING;
}
- if (digest_alg == NULL) {
- ret = hx509_crypto_select(context, HX509_SELECT_DIGEST,
- _hx509_cert_private_key(cert), peer, &digest);
- } else {
- ret = copy_AlgorithmIdentifier(digest_alg, &digest);
+ if (sigctx->digest_alg) {
+ ret = copy_AlgorithmIdentifier(sigctx->digest_alg, &digest);
if (ret)
hx509_clear_error_string(context);
+ } else {
+ ret = hx509_crypto_select(context, HX509_SELECT_DIGEST,
+ _hx509_cert_private_key(cert),
+ sigctx->peer, &digest);
}
if (ret)
goto out;
- sd.version = CMSVersion_v3;
-
- if (eContentType == NULL)
- eContentType = oid_id_pkcs7_data();
-
- der_copy_oid(eContentType, &sd.encapContentInfo.eContentType);
-
- /* */
- if ((flags & HX509_CMS_SIGATURE_DETACHED) == 0) {
- ALLOC(sd.encapContentInfo.eContent, 1);
- if (sd.encapContentInfo.eContent == NULL) {
- hx509_clear_error_string(context);
- ret = ENOMEM;
- goto out;
- }
-
- sd.encapContentInfo.eContent->data = malloc(length);
- if (sd.encapContentInfo.eContent->data == NULL) {
- hx509_clear_error_string(context);
- ret = ENOMEM;
- goto out;
- }
- memcpy(sd.encapContentInfo.eContent->data, data, length);
- sd.encapContentInfo.eContent->length = length;
- }
+ /*
+ * Allocate on more signerInfo and do the signature processing
+ */
- ALLOC_SEQ(&sd.signerInfos, 1);
- if (sd.signerInfos.val == NULL) {
- hx509_clear_error_string(context);
+ ptr = realloc(sd->signerInfos.val,
+ (sd->signerInfos.len + 1) * sizeof(sd->signerInfos.val[0]));
+ if (ptr == NULL) {
ret = ENOMEM;
goto out;
}
+ sd->signerInfos.val = ptr;
- signer_info = &sd.signerInfos.val[0];
+ signer_info = &sd->signerInfos.val[sd->signerInfos.len];
+
+ memset(signer_info, 0, sizeof(*signer_info));
signer_info->version = 1;
- ret = fill_CMSIdentifier(cert, cmsidflag, &signer_info->sid);
+ ret = fill_CMSIdentifier(cert, sigctx->cmsidflag, &signer_info->sid);
if (ret) {
hx509_clear_error_string(context);
goto out;
@@ -1181,7 +1236,6 @@ hx509_cms_create_signed_1(hx509_context context,
signer_info->signedAttrs = NULL;
signer_info->unsignedAttrs = NULL;
-
ret = copy_AlgorithmIdentifier(&digest, &signer_info->digestAlgorithm);
if (ret) {
hx509_clear_error_string(context);
@@ -1192,7 +1246,7 @@ hx509_cms_create_signed_1(hx509_context context,
* If it isn't pkcs7-data send signedAttributes
*/
- if (der_heim_oid_cmp(eContentType, oid_id_pkcs7_data()) != 0) {
+ if (der_heim_oid_cmp(sigctx->eContentType, &asn1_oid_id_pkcs7_data) != 0) {
CMSAttributes sa;
heim_octet_string sig;
@@ -1205,7 +1259,7 @@ hx509_cms_create_signed_1(hx509_context context,
ret = _hx509_create_signature(context,
NULL,
&digest,
- &content,
+ &sigctx->content,
NULL,
&sig);
if (ret)
@@ -1227,9 +1281,10 @@ hx509_cms_create_signed_1(hx509_context context,
ret = add_one_attribute(&signer_info->signedAttrs->val,
&signer_info->signedAttrs->len,
- oid_id_pkcs9_messageDigest(),
+ &asn1_oid_id_pkcs9_messageDigest,
&buf);
if (ret) {
+ free(buf.data);
hx509_clear_error_string(context);
goto out;
}
@@ -1238,7 +1293,7 @@ hx509_cms_create_signed_1(hx509_context context,
ASN1_MALLOC_ENCODE(ContentType,
buf.data,
buf.length,
- eContentType,
+ sigctx->eContentType,
&size,
ret);
if (ret)
@@ -1248,9 +1303,10 @@ hx509_cms_create_signed_1(hx509_context context,
ret = add_one_attribute(&signer_info->signedAttrs->val,
&signer_info->signedAttrs->len,
- oid_id_pkcs9_contentType(),
+ &asn1_oid_id_pkcs9_contentType,
&buf);
if (ret) {
+ free(buf.data);
hx509_clear_error_string(context);
goto out;
}
@@ -1271,16 +1327,15 @@ hx509_cms_create_signed_1(hx509_context context,
if (size != sigdata.length)
_hx509_abort("internal ASN.1 encoder error");
} else {
- sigdata.data = content.data;
- sigdata.length = content.length;
+ sigdata.data = sigctx->content.data;
+ sigdata.length = sigctx->content.length;
}
-
{
AlgorithmIdentifier sigalg;
ret = hx509_crypto_select(context, HX509_SELECT_PUBLIC_SIG,
- _hx509_cert_private_key(cert), peer,
+ _hx509_cert_private_key(cert), sigctx->peer,
&sigalg);
if (ret)
goto out;
@@ -1296,54 +1351,165 @@ hx509_cms_create_signed_1(hx509_context context,
goto out;
}
- ALLOC_SEQ(&sd.digestAlgorithms, 1);
- if (sd.digestAlgorithms.val == NULL) {
- ret = ENOMEM;
- hx509_clear_error_string(context);
- goto out;
- }
-
- ret = copy_AlgorithmIdentifier(&digest, &sd.digestAlgorithms.val[0]);
- if (ret) {
- hx509_clear_error_string(context);
- goto out;
- }
+ sigctx->sd.signerInfos.len++;
+ signer_info = NULL;
/*
* Provide best effort path
*/
- if (pool) {
- _hx509_calculate_path(context,
- HX509_CALCULATE_PATH_NO_ANCHOR,
- time(NULL),
- anchors,
- 0,
- cert,
- pool,
- &path);
- } else
- _hx509_path_append(context, &path, cert);
+ if (sigctx->certs) {
+ unsigned int i;
+
+ if (sigctx->pool) {
+ _hx509_calculate_path(context,
+ HX509_CALCULATE_PATH_NO_ANCHOR,
+ time(NULL),
+ sigctx->anchors,
+ 0,
+ cert,
+ sigctx->pool,
+ &path);
+ } else
+ _hx509_path_append(context, &path, cert);
+
+ for (i = 0; i < path.len; i++) {
+ /* XXX remove dups */
+ ret = hx509_certs_add(context, sigctx->certs, path.val[i]);
+ if (ret) {
+ hx509_clear_error_string(context);
+ goto out;
+ }
+ }
+ }
+
+ out:
+ if (signer_info)
+ free_SignerInfo(signer_info);
+ if (sigdata.data != sigctx->content.data)
+ der_free_octet_string(&sigdata);
+ _hx509_path_free(&path);
+ free_AlgorithmIdentifier(&digest);
+
+ return ret;
+}
+
+static int
+cert_process(hx509_context context, void *ctx, hx509_cert cert)
+{
+ struct sigctx *sigctx = ctx;
+ const unsigned int i = sigctx->sd.certificates->len;
+ void *ptr;
+ int ret;
+
+ ptr = realloc(sigctx->sd.certificates->val,
+ (i + 1) * sizeof(sigctx->sd.certificates->val[0]));
+ if (ptr == NULL)
+ return ENOMEM;
+ sigctx->sd.certificates->val = ptr;
+
+ ret = hx509_cert_binary(context, cert,
+ &sigctx->sd.certificates->val[i]);
+ if (ret == 0)
+ sigctx->sd.certificates->len++;
+
+ return ret;
+}
+
+int
+hx509_cms_create_signed(hx509_context context,
+ int flags,
+ const heim_oid *eContentType,
+ const void *data, size_t length,
+ const AlgorithmIdentifier *digest_alg,
+ hx509_certs certs,
+ hx509_peer_info peer,
+ hx509_certs anchors,
+ hx509_certs pool,
+ heim_octet_string *signed_data)
+{
+ unsigned int i;
+ hx509_name name;
+ int ret;
+ size_t size;
+ struct sigctx sigctx;
+
+ memset(&sigctx, 0, sizeof(sigctx));
+ memset(&name, 0, sizeof(name));
+
+ if (eContentType == NULL)
+ eContentType = &asn1_oid_id_pkcs7_data;
+
+ sigctx.digest_alg = digest_alg;
+ sigctx.content.data = rk_UNCONST(data);
+ sigctx.content.length = length;
+ sigctx.eContentType = eContentType;
+ sigctx.peer = peer;
+ /**
+ * Use HX509_CMS_SIGNATURE_ID_NAME to preferred use of issuer name
+ * and serial number if possible. Otherwise subject key identifier
+ * will preferred.
+ */
+ if (flags & HX509_CMS_SIGNATURE_ID_NAME)
+ sigctx.cmsidflag = CMS_ID_NAME;
+ else
+ sigctx.cmsidflag = CMS_ID_SKI;
+
+ ret = hx509_certs_init(context, "MEMORY:certs", 0, NULL, &sigctx.certs);
+ if (ret)
+ return ret;
+
+ sigctx.anchors = anchors;
+ sigctx.pool = pool;
+ sigctx.sd.version = CMSVersion_v3;
- if (path.len) {
- int i;
+ der_copy_oid(eContentType, &sigctx.sd.encapContentInfo.eContentType);
- ALLOC(sd.certificates, 1);
- if (sd.certificates == NULL) {
+ /**
+ * Use HX509_CMS_SIGNATURE_DETACHED to create detached signatures.
+ */
+ if ((flags & HX509_CMS_SIGNATURE_DETACHED) == 0) {
+ ALLOC(sigctx.sd.encapContentInfo.eContent, 1);
+ if (sigctx.sd.encapContentInfo.eContent == NULL) {
hx509_clear_error_string(context);
ret = ENOMEM;
goto out;
}
- ALLOC_SEQ(sd.certificates, path.len);
- if (sd.certificates->val == NULL) {
+
+ sigctx.sd.encapContentInfo.eContent->data = malloc(length);
+ if (sigctx.sd.encapContentInfo.eContent->data == NULL) {
hx509_clear_error_string(context);
ret = ENOMEM;
goto out;
}
+ memcpy(sigctx.sd.encapContentInfo.eContent->data, data, length);
+ sigctx.sd.encapContentInfo.eContent->length = length;
+ }
- for (i = 0; i < path.len; i++) {
- ret = hx509_cert_binary(context, path.val[i],
- &sd.certificates->val[i]);
+ /**
+ * Use HX509_CMS_SIGNATURE_NO_SIGNER to create no sigInfo (no
+ * signatures).
+ */
+ if ((flags & HX509_CMS_SIGNATURE_NO_SIGNER) == 0) {
+ ret = hx509_certs_iter(context, certs, sig_process, &sigctx);
+ if (ret)
+ goto out;
+ }
+
+ if (sigctx.sd.signerInfos.len) {
+ ALLOC_SEQ(&sigctx.sd.digestAlgorithms, sigctx.sd.signerInfos.len);
+ if (sigctx.sd.digestAlgorithms.val == NULL) {
+ ret = ENOMEM;
+ hx509_clear_error_string(context);
+ goto out;
+ }
+
+ /* XXX remove dups */
+ for (i = 0; i < sigctx.sd.signerInfos.len; i++) {
+ AlgorithmIdentifier *di =
+ &sigctx.sd.signerInfos.val[i].digestAlgorithm;
+ ret = copy_AlgorithmIdentifier(di,
+ &sigctx.sd.digestAlgorithms.val[i]);
if (ret) {
hx509_clear_error_string(context);
goto out;
@@ -1351,9 +1517,22 @@ hx509_cms_create_signed_1(hx509_context context,
}
}
+ if (sigctx.certs) {
+ ALLOC(sigctx.sd.certificates, 1);
+ if (sigctx.sd.certificates == NULL) {
+ hx509_clear_error_string(context);
+ ret = ENOMEM;
+ goto out;
+ }
+
+ ret = hx509_certs_iter(context, sigctx.certs, cert_process, &sigctx);
+ if (ret)
+ goto out;
+ }
+
ASN1_MALLOC_ENCODE(SignedData,
signed_data->data, signed_data->length,
- &sd, &size, ret);
+ &sigctx.sd, &size, ret);
if (ret) {
hx509_clear_error_string(context);
goto out;
@@ -1362,11 +1541,8 @@ hx509_cms_create_signed_1(hx509_context context,
_hx509_abort("internal ASN.1 encoder error");
out:
- if (sigdata.data != content.data)
- der_free_octet_string(&sigdata);
- free_AlgorithmIdentifier(&digest);
- _hx509_path_free(&path);
- free_SignedData(&sd);
+ hx509_certs_free(&sigctx.certs);
+ free_SignedData(&sigctx.sd);
return ret;
}
diff --git a/source4/heimdal/lib/hx509/collector.c b/source4/heimdal/lib/hx509/collector.c
index b59052bb4e..ab36fe2dc8 100644
--- a/source4/heimdal/lib/hx509/collector.c
+++ b/source4/heimdal/lib/hx509/collector.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
struct private_key {
AlgorithmIdentifier alg;
@@ -144,7 +143,7 @@ _hx509_collector_private_key_add(hx509_context context,
if (private_key) {
key->private_key = private_key;
} else {
- ret = _hx509_parse_private_key(context, &alg->algorithm,
+ ret = _hx509_parse_private_key(context, alg,
key_data->data, key_data->length,
&key->private_key);
if (ret)
@@ -306,7 +305,7 @@ _hx509_collector_collect_private_keys(hx509_context context,
c->val.data[i]->private_key = NULL;
}
}
- (*keys)[nkeys++] = NULL;
+ (*keys)[nkeys] = NULL;
return 0;
}
diff --git a/source4/heimdal/lib/hx509/crypto.c b/source4/heimdal/lib/hx509/crypto.c
index 4a8ec8f756..8063100717 100644
--- a/source4/heimdal/lib/hx509/crypto.c
+++ b/source4/heimdal/lib/hx509/crypto.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
struct hx509_crypto;
@@ -50,40 +49,21 @@ struct hx509_generate_private_context {
struct hx509_private_key_ops {
const char *pemtype;
- const heim_oid *(*key_oid)(void);
+ const heim_oid *key_oid;
+ int (*available)(const hx509_private_key,
+ const AlgorithmIdentifier *);
int (*get_spki)(hx509_context,
const hx509_private_key,
SubjectPublicKeyInfo *);
int (*export)(hx509_context context,
const hx509_private_key,
heim_octet_string *);
- int (*import)(hx509_context,
- const void *data,
- size_t len,
- hx509_private_key private_key);
+ int (*import)(hx509_context, const AlgorithmIdentifier *,
+ const void *, size_t, hx509_private_key);
int (*generate_private_key)(hx509_context,
struct hx509_generate_private_context *,
hx509_private_key);
BIGNUM *(*get_internal)(hx509_context, hx509_private_key, const char *);
- int (*handle_alg)(const hx509_private_key,
- const AlgorithmIdentifier *,
- enum crypto_op_type);
- int (*sign)(hx509_context context,
- const hx509_private_key,
- const AlgorithmIdentifier *,
- const heim_octet_string *,
- AlgorithmIdentifier *,
- heim_octet_string *);
-#if 0
- const AlgorithmIdentifier *(*preferred_sig_alg)
- (const hx509_private_key,
- const hx509_peer_info);
- int (*unwrap)(hx509_context context,
- const hx509_private_key,
- const AlgorithmIdentifier *,
- const heim_octet_string *,
- heim_octet_string *);
-#endif
};
struct hx509_private_key {
@@ -93,8 +73,10 @@ struct hx509_private_key {
union {
RSA *rsa;
void *keydata;
+#ifdef HAVE_OPENSSL
+ EC_KEY *ecdsa;
+#endif
} private_key;
- /* new crypto layer */
hx509_private_key_ops *ops;
};
@@ -104,10 +86,10 @@ struct hx509_private_key {
struct signature_alg {
const char *name;
- const heim_oid *(*sig_oid)(void);
- const AlgorithmIdentifier *(*sig_alg)(void);
- const heim_oid *(*key_oid)(void);
- const heim_oid *(*digest_oid)(void);
+ const heim_oid *sig_oid;
+ const AlgorithmIdentifier *sig_alg;
+ const heim_oid *key_oid;
+ const AlgorithmIdentifier *digest_alg;
int flags;
#define PROVIDE_CONF 1
#define REQUIRE_SIGNER 2
@@ -118,7 +100,7 @@ struct signature_alg {
#define RA_RSA_USES_DIGEST_INFO 0x1000000
-
+ time_t best_before; /* refuse signature made after best before date */
int (*verify_signature)(hx509_context context,
const struct signature_alg *,
const Certificate *,
@@ -132,6 +114,116 @@ struct signature_alg {
const heim_octet_string *,
AlgorithmIdentifier *,
heim_octet_string *);
+ int digest_size;
+};
+
+static const struct signature_alg *
+find_sig_alg(const heim_oid *oid);
+
+/*
+ *
+ */
+
+static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") };
+
+static const unsigned sha512_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };
+const AlgorithmIdentifier _hx509_signature_sha512_data = {
+ { 9, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+static const unsigned sha384_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };
+const AlgorithmIdentifier _hx509_signature_sha384_data = {
+ { 9, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
+const AlgorithmIdentifier _hx509_signature_sha256_data = {
+ { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };
+const AlgorithmIdentifier _hx509_signature_sha1_data = {
+ { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+static const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 };
+const AlgorithmIdentifier _hx509_signature_md5_data = {
+ { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+static const unsigned md2_oid_tree[] = { 1, 2, 840, 113549, 2, 2 };
+const AlgorithmIdentifier _hx509_signature_md2_data = {
+ { 6, rk_UNCONST(md2_oid_tree) }, rk_UNCONST(&null_entry_oid)
+};
+
+static const unsigned ecPublicKey[] ={ 1, 2, 840, 10045, 2, 1 };
+const AlgorithmIdentifier _hx509_signature_ecPublicKey = {
+ { 6, rk_UNCONST(ecPublicKey) }, NULL
+};
+
+static const unsigned ecdsa_with_sha256_oid[] ={ 1, 2, 840, 10045, 4, 3, 2 };
+const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha256_data = {
+ { 7, rk_UNCONST(ecdsa_with_sha256_oid) }, NULL
+};
+
+static const unsigned ecdsa_with_sha1_oid[] ={ 1, 2, 840, 10045, 4, 1 };
+const AlgorithmIdentifier _hx509_signature_ecdsa_with_sha1_data = {
+ { 6, rk_UNCONST(ecdsa_with_sha1_oid) }, NULL
+};
+
+static const unsigned rsa_with_sha512_oid[] ={ 1, 2, 840, 113549, 1, 1, 13 };
+const AlgorithmIdentifier _hx509_signature_rsa_with_sha512_data = {
+ { 7, rk_UNCONST(rsa_with_sha512_oid) }, NULL
+};
+
+static const unsigned rsa_with_sha384_oid[] ={ 1, 2, 840, 113549, 1, 1, 12 };
+const AlgorithmIdentifier _hx509_signature_rsa_with_sha384_data = {
+ { 7, rk_UNCONST(rsa_with_sha384_oid) }, NULL
+};
+
+static const unsigned rsa_with_sha256_oid[] ={ 1, 2, 840, 113549, 1, 1, 11 };
+const AlgorithmIdentifier _hx509_signature_rsa_with_sha256_data = {
+ { 7, rk_UNCONST(rsa_with_sha256_oid) }, NULL
+};
+
+static const unsigned rsa_with_sha1_oid[] ={ 1, 2, 840, 113549, 1, 1, 5 };
+const AlgorithmIdentifier _hx509_signature_rsa_with_sha1_data = {
+ { 7, rk_UNCONST(rsa_with_sha1_oid) }, NULL
+};
+
+static const unsigned rsa_with_md5_oid[] ={ 1, 2, 840, 113549, 1, 1, 4 };
+const AlgorithmIdentifier _hx509_signature_rsa_with_md5_data = {
+ { 7, rk_UNCONST(rsa_with_md5_oid) }, NULL
+};
+
+static const unsigned rsa_with_md2_oid[] ={ 1, 2, 840, 113549, 1, 1, 2 };
+const AlgorithmIdentifier _hx509_signature_rsa_with_md2_data = {
+ { 7, rk_UNCONST(rsa_with_md2_oid) }, NULL
+};
+
+static const unsigned rsa_oid[] ={ 1, 2, 840, 113549, 1, 1, 1 };
+const AlgorithmIdentifier _hx509_signature_rsa_data = {
+ { 7, rk_UNCONST(rsa_oid) }, NULL
+};
+
+static const unsigned rsa_pkcs1_x509_oid[] ={ 1, 2, 752, 43, 16, 1 };
+const AlgorithmIdentifier _hx509_signature_rsa_pkcs1_x509_data = {
+ { 6, rk_UNCONST(rsa_pkcs1_x509_oid) }, NULL
+};
+
+static const unsigned des_rsdi_ede3_cbc_oid[] ={ 1, 2, 840, 113549, 3, 7 };
+const AlgorithmIdentifier _hx509_des_rsdi_ede3_cbc_oid = {
+ { 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL
+};
+
+static const unsigned aes128_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 2 };
+const AlgorithmIdentifier _hx509_crypto_aes128_cbc_data = {
+ { 9, rk_UNCONST(aes128_cbc_oid) }, NULL
+};
+
+static const unsigned aes256_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 42 };
+const AlgorithmIdentifier _hx509_crypto_aes256_cbc_data = {
+ { 9, rk_UNCONST(aes256_cbc_oid) }, NULL
};
/*
@@ -184,6 +276,265 @@ set_digest_alg(DigestAlgorithmIdentifier *id,
return 0;
}
+#ifdef HAVE_OPENSSL
+
+static int
+heim_oid2ecnid(heim_oid *oid)
+{
+ /*
+ * Now map to openssl OID fun
+ */
+
+ if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp256r1) == 0)
+ return NID_X9_62_prime256v1;
+ else if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp160r1) == 0)
+ return NID_secp160r1;
+ else if (der_heim_oid_cmp(oid, &asn1_oid_id_ec_group_secp160r2) == 0)
+ return NID_secp160r2;
+
+ return -1;
+}
+
+static int
+parse_ECParameters(hx509_context context,
+ heim_octet_string *parameters, int *nid)
+{
+ ECParameters ecparam;
+ size_t size;
+ int ret;
+
+ if (parameters == NULL) {
+ ret = HX509_PARSING_KEY_FAILED;
+ hx509_set_error_string(context, 0, ret,
+ "EC parameters missing");
+ return ret;
+ }
+
+ ret = decode_ECParameters(parameters->data, parameters->length,
+ &ecparam, &size);
+ if (ret) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to decode EC parameters");
+ return ret;
+ }
+
+ if (ecparam.element != choice_ECParameters_namedCurve) {
+ free_ECParameters(&ecparam);
+ hx509_set_error_string(context, 0, ret,
+ "EC parameters is not a named curve");
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
+ }
+
+ *nid = heim_oid2ecnid(&ecparam.u.namedCurve);
+ free_ECParameters(&ecparam);
+ if (*nid == -1) {
+ hx509_set_error_string(context, 0, ret,
+ "Failed to find matcing NID for EC curve");
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
+ }
+ return 0;
+}
+
+
+/*
+ *
+ */
+
+static int
+ecdsa_verify_signature(hx509_context context,
+ const struct signature_alg *sig_alg,
+ const Certificate *signer,
+ const AlgorithmIdentifier *alg,
+ const heim_octet_string *data,
+ const heim_octet_string *sig)
+{
+ const AlgorithmIdentifier *digest_alg;
+ const SubjectPublicKeyInfo *spi;
+ heim_octet_string digest;
+ int ret;
+ EC_KEY *key = NULL;
+ int groupnid;
+ EC_GROUP *group;
+ const unsigned char *p;
+ long len;
+
+ digest_alg = sig_alg->digest_alg;
+
+ ret = _hx509_create_signature(context,
+ NULL,
+ digest_alg,
+ data,
+ NULL,
+ &digest);
+ if (ret)
+ return ret;
+
+ /* set up EC KEY */
+ spi = &signer->tbsCertificate.subjectPublicKeyInfo;
+
+ if (der_heim_oid_cmp(&spi->algorithm.algorithm, &asn1_oid_id_ecPublicKey) != 0)
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
+
+#ifdef HAVE_OPENSSL
+ /*
+ * Find the group id
+ */
+
+ ret = parse_ECParameters(context, spi->algorithm.parameters, &groupnid);
+ if (ret) {
+ der_free_octet_string(&digest);
+ return ret;
+ }
+
+ /*
+ * Create group, key, parse key
+ */
+
+ key = EC_KEY_new();
+ group = EC_GROUP_new_by_curve_name(groupnid);
+ EC_KEY_set_group(key, group);
+ EC_GROUP_free(group);
+
+ p = spi->subjectPublicKey.data;
+ len = spi->subjectPublicKey.length / 8;
+
+ if (o2i_ECPublicKey(&key, &p, len) == NULL) {
+ EC_KEY_free(key);
+ return HX509_CRYPTO_SIG_INVALID_FORMAT;
+ }
+#else
+ key = SubjectPublicKeyInfo2EC_KEY(spi);
+#endif
+
+ ret = ECDSA_verify(-1, digest.data, digest.length,
+ sig->data, sig->length, key);
+ der_free_octet_string(&digest);
+ EC_KEY_free(key);
+ if (ret != 1) {
+ ret = HX509_CRYPTO_SIG_INVALID_FORMAT;
+ return ret;
+ }
+
+ return 0;
+}
+
+static int
+ecdsa_create_signature(hx509_context context,
+ const struct signature_alg *sig_alg,
+ const hx509_private_key signer,
+ const AlgorithmIdentifier *alg,
+ const heim_octet_string *data,
+ AlgorithmIdentifier *signatureAlgorithm,
+ heim_octet_string *sig)
+{
+ const AlgorithmIdentifier *digest_alg;
+ heim_octet_string indata;
+ const heim_oid *sig_oid;
+ unsigned int siglen;
+ int ret;
+
+ if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
+ _hx509_abort("internal error passing private key to wrong ops");
+
+ sig_oid = sig_alg->sig_oid;
+ digest_alg = sig_alg->digest_alg;
+
+ if (signatureAlgorithm) {
+ ret = set_digest_alg(signatureAlgorithm, sig_oid, "\x05\x00", 2);
+ if (ret) {
+ hx509_clear_error_string(context);
+ goto error;
+ }
+ }
+
+ ret = _hx509_create_signature(context,
+ NULL,
+ digest_alg,
+ data,
+ NULL,
+ &indata);
+ if (ret) {
+ if (signatureAlgorithm)
+ free_AlgorithmIdentifier(signatureAlgorithm);
+ goto error;
+ }
+
+ sig->length = ECDSA_size(signer->private_key.ecdsa);
+ sig->data = malloc(sig->length);
+ if (sig->data == NULL) {
+ der_free_octet_string(&indata);
+ ret = ENOMEM;
+ hx509_set_error_string(context, 0, ret, "out of memory");
+ goto error;
+ }
+
+ siglen = sig->length;
+
+ ret = ECDSA_sign(-1, indata.data, indata.length,
+ sig->data, &siglen, signer->private_key.ecdsa);
+ der_free_octet_string(&indata);
+ if (ret != 1) {
+ ret = HX509_CMS_FAILED_CREATE_SIGATURE;
+ hx509_set_error_string(context, 0, ret,
+ "ECDSA sign failed: %d", ret);
+ goto error;
+ }
+ if (siglen > sig->length)
+ _hx509_abort("ECDSA signature prelen longer the output len");
+
+ sig->length = siglen;
+
+ return 0;
+ error:
+ if (signatureAlgorithm)
+ free_AlgorithmIdentifier(signatureAlgorithm);
+ return ret;
+}
+
+static int
+ecdsa_available(const hx509_private_key signer,
+ const AlgorithmIdentifier *sig_alg)
+{
+ const struct signature_alg *sig;
+ const EC_GROUP *group;
+ BN_CTX *bnctx = NULL;
+ BIGNUM *order = NULL;
+ int ret = 0;
+
+ if (der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_ecPublicKey) != 0)
+ _hx509_abort("internal error passing private key to wrong ops");
+
+ sig = find_sig_alg(&sig_alg->algorithm);
+
+ if (sig == NULL || sig->digest_size == 0)
+ return 0;
+
+ group = EC_KEY_get0_group(signer->private_key.ecdsa);
+ if (group == NULL)
+ return 0;
+
+ bnctx = BN_CTX_new();
+ order = BN_new();
+ if (order == NULL)
+ goto err;
+
+ if (EC_GROUP_get_order(group, order, bnctx) != 1)
+ goto err;
+
+ if (BN_num_bytes(order) > sig->digest_size)
+ ret = 1;
+ err:
+ if (bnctx)
+ BN_CTX_free(bnctx);
+ if (order)
+ BN_clear_free(order);
+
+ return ret;
+}
+
+
+#endif /* HAVE_OPENSSL */
+
/*
*
*/
@@ -268,9 +619,9 @@ rsa_verify_signature(hx509_context context,
goto out;
}
- if (sig_alg->digest_oid &&
+ if (sig_alg->digest_alg &&
der_heim_oid_cmp(&di.digestAlgorithm.algorithm,
- (*sig_alg->digest_oid)()) != 0)
+ &sig_alg->digest_alg->algorithm) != 0)
{
ret = HX509_CRYPTO_OID_MISMATCH;
hx509_set_error_string(context, 0, ret, "object identifier in RSA sig mismatch");
@@ -324,24 +675,27 @@ rsa_create_signature(hx509_context context,
size_t size;
int ret;
+ if (signer->ops && der_heim_oid_cmp(signer->ops->key_oid, &asn1_oid_id_pkcs1_rsaEncryption) != 0)
+ return HX509_ALG_NOT_SUPP;
+
if (alg)
sig_oid = &alg->algorithm;
else
sig_oid = signer->signature_alg;
- if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_sha256WithRSAEncryption()) == 0) {
+ if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_sha256WithRSAEncryption) == 0) {
digest_alg = hx509_signature_sha256();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_sha1WithRSAEncryption()) == 0) {
+ } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_sha1WithRSAEncryption) == 0) {
digest_alg = hx509_signature_sha1();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_md5WithRSAEncryption()) == 0) {
+ } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_md5WithRSAEncryption) == 0) {
digest_alg = hx509_signature_md5();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_md5WithRSAEncryption()) == 0) {
+ } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_md5WithRSAEncryption) == 0) {
digest_alg = hx509_signature_md5();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_dsa_with_sha1()) == 0) {
+ } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_dsa_with_sha1) == 0) {
digest_alg = hx509_signature_sha1();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_pkcs1_rsaEncryption()) == 0) {
+ } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_pkcs1_rsaEncryption) == 0) {
digest_alg = hx509_signature_sha1();
- } else if (der_heim_oid_cmp(sig_oid, oid_id_heim_rsa_pkcs1_x509()) == 0) {
+ } else if (der_heim_oid_cmp(sig_oid, &asn1_oid_id_heim_rsa_pkcs1_x509) == 0) {
digest_alg = NULL;
} else
return HX509_ALG_NOT_SUPP;
@@ -413,6 +767,7 @@ rsa_create_signature(hx509_context context,
static int
rsa_private_key_import(hx509_context context,
+ const AlgorithmIdentifier *keyai,
const void *data,
size_t len,
hx509_private_key private_key)
@@ -426,7 +781,7 @@ rsa_private_key_import(hx509_context context,
"Failed to parse RSA key");
return HX509_PARSING_KEY_FAILED;
}
- private_key->signature_alg = oid_id_pkcs1_sha1WithRSAEncryption();
+ private_key->signature_alg = &asn1_oid_id_pkcs1_sha1WithRSAEncryption;
return 0;
}
@@ -449,7 +804,7 @@ rsa_private_key2SPKI(hx509_context context,
}
spki->subjectPublicKey.length = len * 8;
- ret = set_digest_alg(&spki->algorithm,oid_id_pkcs1_rsaEncryption(),
+ ret = set_digest_alg(&spki->algorithm, &asn1_oid_id_pkcs1_rsaEncryption,
"\x05\x00", 2);
if (ret) {
hx509_set_error_string(context, 0, ret, "malloc - out of memory");
@@ -503,7 +858,7 @@ rsa_generate_private_key(hx509_context context,
"Failed to generate RSA key");
return HX509_PARSING_KEY_FAILED;
}
- private_key->signature_alg = oid_id_pkcs1_sha1WithRSAEncryption();
+ private_key->signature_alg = &asn1_oid_id_pkcs1_sha1WithRSAEncryption;
return 0;
}
@@ -543,7 +898,9 @@ rsa_private_key_export(hx509_context context,
}
static BIGNUM *
-rsa_get_internal(hx509_context context, hx509_private_key key, const char *type)
+rsa_get_internal(hx509_context context,
+ hx509_private_key key,
+ const char *type)
{
if (strcasecmp(type, "rsa-modulus") == 0) {
return BN_dup(key->private_key.rsa->n);
@@ -557,7 +914,8 @@ rsa_get_internal(hx509_context context, hx509_private_key key, const char *type)
static hx509_private_key_ops rsa_private_key_ops = {
"RSA PRIVATE KEY",
- oid_id_pkcs1_rsaEncryption,
+ &asn1_oid_id_pkcs1_rsaEncryption,
+ NULL,
rsa_private_key2SPKI,
rsa_private_key_export,
rsa_private_key_import,
@@ -565,6 +923,104 @@ static hx509_private_key_ops rsa_private_key_ops = {
rsa_get_internal
};
+#ifdef HAVE_OPENSSL
+
+static int
+ecdsa_private_key2SPKI(hx509_context context,
+ hx509_private_key private_key,
+ SubjectPublicKeyInfo *spki)
+{
+ memset(spki, 0, sizeof(*spki));
+ return ENOMEM;
+}
+
+static int
+ecdsa_private_key_export(hx509_context context,
+ const hx509_private_key key,
+ heim_octet_string *data)
+{
+ return ENOMEM;
+}
+
+static int
+ecdsa_private_key_import(hx509_context context,
+ const AlgorithmIdentifier *keyai,
+ const void *data,
+ size_t len,
+ hx509_private_key private_key)
+{
+ const unsigned char *p = data;
+ EC_KEY **pkey = NULL;
+
+ if (keyai->parameters) {
+ EC_GROUP *group;
+ int groupnid;
+ EC_KEY *key;
+ int ret;
+
+ ret = parse_ECParameters(context, keyai->parameters, &groupnid);
+ if (ret)
+ return ret;
+
+ key = EC_KEY_new();
+ if (key == NULL)
+ return ENOMEM;
+
+ group = EC_GROUP_new_by_curve_name(groupnid);
+ if (group == NULL) {
+ EC_KEY_free(key);
+ return ENOMEM;
+ }
+ EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
+ if (EC_KEY_set_group(key, group) == 0) {
+ EC_KEY_free(key);
+ EC_GROUP_free(group);
+ return ENOMEM;
+ }
+ EC_GROUP_free(group);
+ pkey = &key;
+ }
+
+ private_key->private_key.ecdsa = d2i_ECPrivateKey(pkey, &p, len);
+ if (private_key->private_key.ecdsa == NULL) {
+ hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
+ "Failed to parse EC private key");
+ return HX509_PARSING_KEY_FAILED;
+ }
+ private_key->signature_alg = &asn1_oid_id_ecdsa_with_SHA256;
+
+ return 0;
+}
+
+static int
+ecdsa_generate_private_key(hx509_context context,
+ struct hx509_generate_private_context *ctx,
+ hx509_private_key private_key)
+{
+ return ENOMEM;
+}
+
+static BIGNUM *
+ecdsa_get_internal(hx509_context context,
+ hx509_private_key key,
+ const char *type)
+{
+ return NULL;
+}
+
+
+static hx509_private_key_ops ecdsa_private_key_ops = {
+ "EC PRIVATE KEY",
+ &asn1_oid_id_ecPublicKey,
+ ecdsa_available,
+ ecdsa_private_key2SPKI,
+ ecdsa_private_key_export,
+ ecdsa_private_key_import,
+ ecdsa_generate_private_key,
+ ecdsa_get_internal
+};
+
+#endif /* HAVE_OPENSSL */
/*
*
@@ -668,7 +1124,7 @@ dsa_parse_private_key(hx509_context context,
d2i_DSAPrivateKey(NULL, &p, len);
if (private_key->private_key.dsa == NULL)
return EINVAL;
- private_key->signature_alg = oid_id_dsa_with_sha1();
+ private_key->signature_alg = &asn1_oid_id_dsa_with_sha1;
return 0;
/* else */
@@ -724,7 +1180,7 @@ sha256_create_signature(hx509_context context,
if (signatureAlgorithm) {
int ret;
- ret = set_digest_alg(signatureAlgorithm, (*sig_alg->sig_oid)(),
+ ret = set_digest_alg(signatureAlgorithm, sig_alg->sig_oid,
"\x05\x00", 2);
if (ret)
return ret;
@@ -790,7 +1246,7 @@ sha1_create_signature(hx509_context context,
if (signatureAlgorithm) {
int ret;
- ret = set_digest_alg(signatureAlgorithm, (*sig_alg->sig_oid)(),
+ ret = set_digest_alg(signatureAlgorithm, sig_alg->sig_oid,
"\x05\x00", 2);
if (ret)
return ret;
@@ -871,131 +1327,176 @@ md2_verify_signature(hx509_context context,
return 0;
}
+#ifdef HAVE_OPENSSL
+
+static const struct signature_alg ecdsa_with_sha256_alg = {
+ "ecdsa-with-sha256",
+ &asn1_oid_id_ecdsa_with_SHA256,
+ &_hx509_signature_ecdsa_with_sha256_data,
+ &asn1_oid_id_ecPublicKey,
+ &_hx509_signature_sha256_data,
+ PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 0,
+ ecdsa_verify_signature,
+ ecdsa_create_signature,
+ 32
+};
+
+static const struct signature_alg ecdsa_with_sha1_alg = {
+ "ecdsa-with-sha1",
+ &asn1_oid_id_ecdsa_with_SHA1,
+ &_hx509_signature_ecdsa_with_sha1_data,
+ &asn1_oid_id_ecPublicKey,
+ &_hx509_signature_sha1_data,
+ PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 0,
+ ecdsa_verify_signature,
+ ecdsa_create_signature,
+ 20
+};
+
+#endif
+
static const struct signature_alg heim_rsa_pkcs1_x509 = {
"rsa-pkcs1-x509",
- oid_id_heim_rsa_pkcs1_x509,
- hx509_signature_rsa_pkcs1_x509,
- oid_id_pkcs1_rsaEncryption,
+ &asn1_oid_id_heim_rsa_pkcs1_x509,
+ &_hx509_signature_rsa_pkcs1_x509_data,
+ &asn1_oid_id_pkcs1_rsaEncryption,
NULL,
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
+ 0,
rsa_verify_signature,
rsa_create_signature
};
static const struct signature_alg pkcs1_rsa_sha1_alg = {
"rsa",
- oid_id_pkcs1_rsaEncryption,
- hx509_signature_rsa_with_sha1,
- oid_id_pkcs1_rsaEncryption,
+ &asn1_oid_id_pkcs1_rsaEncryption,
+ &_hx509_signature_rsa_with_sha1_data,
+ &asn1_oid_id_pkcs1_rsaEncryption,
NULL,
PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 0,
rsa_verify_signature,
rsa_create_signature
};
static const struct signature_alg rsa_with_sha256_alg = {
"rsa-with-sha256",
- oid_id_pkcs1_sha256WithRSAEncryption,
- hx509_signature_rsa_with_sha256,
- oid_id_pkcs1_rsaEncryption,
- oid_id_sha256,
+ &asn1_oid_id_pkcs1_sha256WithRSAEncryption,
+ &_hx509_signature_rsa_with_sha256_data,
+ &asn1_oid_id_pkcs1_rsaEncryption,
+ &_hx509_signature_sha256_data,
PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 0,
rsa_verify_signature,
rsa_create_signature
};
static const struct signature_alg rsa_with_sha1_alg = {
"rsa-with-sha1",
- oid_id_pkcs1_sha1WithRSAEncryption,
- hx509_signature_rsa_with_sha1,
- oid_id_pkcs1_rsaEncryption,
- oid_id_secsig_sha_1,
+ &asn1_oid_id_pkcs1_sha1WithRSAEncryption,
+ &_hx509_signature_rsa_with_sha1_data,
+ &asn1_oid_id_pkcs1_rsaEncryption,
+ &_hx509_signature_sha1_data,
PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 0,
rsa_verify_signature,
rsa_create_signature
};
static const struct signature_alg rsa_with_md5_alg = {
"rsa-with-md5",
- oid_id_pkcs1_md5WithRSAEncryption,
- hx509_signature_rsa_with_md5,
- oid_id_pkcs1_rsaEncryption,
- oid_id_rsa_digest_md5,
+ &asn1_oid_id_pkcs1_md5WithRSAEncryption,
+ &_hx509_signature_rsa_with_md5_data,
+ &asn1_oid_id_pkcs1_rsaEncryption,
+ &_hx509_signature_md5_data,
PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 1230739889,
rsa_verify_signature,
rsa_create_signature
};
static const struct signature_alg rsa_with_md2_alg = {
"rsa-with-md2",
- oid_id_pkcs1_md2WithRSAEncryption,
- hx509_signature_rsa_with_md2,
- oid_id_pkcs1_rsaEncryption,
- oid_id_rsa_digest_md2,
+ &asn1_oid_id_pkcs1_md2WithRSAEncryption,
+ &_hx509_signature_rsa_with_md2_data,
+ &asn1_oid_id_pkcs1_rsaEncryption,
+ &_hx509_signature_md2_data,
PROVIDE_CONF|REQUIRE_SIGNER|RA_RSA_USES_DIGEST_INFO|SIG_PUBLIC_SIG,
+ 1230739889,
rsa_verify_signature,
rsa_create_signature
};
static const struct signature_alg dsa_sha1_alg = {
"dsa-with-sha1",
- oid_id_dsa_with_sha1,
+ &asn1_oid_id_dsa_with_sha1,
NULL,
- oid_id_dsa,
- oid_id_secsig_sha_1,
+ &asn1_oid_id_dsa,
+ &_hx509_signature_sha1_data,
PROVIDE_CONF|REQUIRE_SIGNER|SIG_PUBLIC_SIG,
+ 0,
dsa_verify_signature,
/* create_signature */ NULL,
};
static const struct signature_alg sha256_alg = {
"sha-256",
- oid_id_sha256,
- hx509_signature_sha256,
+ &asn1_oid_id_sha256,
+ &_hx509_signature_sha256_data,
NULL,
NULL,
SIG_DIGEST,
+ 0,
sha256_verify_signature,
sha256_create_signature
};
static const struct signature_alg sha1_alg = {
"sha1",
- oid_id_secsig_sha_1,
- hx509_signature_sha1,
+ &asn1_oid_id_secsig_sha_1,
+ &_hx509_signature_sha1_data,
NULL,
NULL,
SIG_DIGEST,
+ 0,
sha1_verify_signature,
sha1_create_signature
};
static const struct signature_alg md5_alg = {
"rsa-md5",
- oid_id_rsa_digest_md5,
- hx509_signature_md5,
+ &asn1_oid_id_rsa_digest_md5,
+ &_hx509_signature_md5_data,
NULL,
NULL,
SIG_DIGEST,
+ 0,
md5_verify_signature
};
static const struct signature_alg md2_alg = {
"rsa-md2",
- oid_id_rsa_digest_md2,
- hx509_signature_md2,
+ &asn1_oid_id_rsa_digest_md2,
+ &_hx509_signature_md2_data,
NULL,
NULL,
SIG_DIGEST,
+ 0,
md2_verify_signature
};
/*
* Order matter in this structure, "best" first for each "key
- * compatible" type (type is RSA, DSA, none, etc)
+ * compatible" type (type is ECDSA, RSA, DSA, none, etc)
*/
static const struct signature_alg *sig_algs[] = {
+#ifdef HAVE_OPENSSL
+ &ecdsa_with_sha256_alg,
+ &ecdsa_with_sha1_alg,
+#endif
&rsa_with_sha256_alg,
&rsa_with_sha1_alg,
&pkcs1_rsa_sha1_alg,
@@ -1013,19 +1514,51 @@ static const struct signature_alg *sig_algs[] = {
static const struct signature_alg *
find_sig_alg(const heim_oid *oid)
{
- int i;
+ unsigned int i;
for (i = 0; sig_algs[i]; i++)
- if (der_heim_oid_cmp((*sig_algs[i]->sig_oid)(), oid) == 0)
+ if (der_heim_oid_cmp(sig_algs[i]->sig_oid, oid) == 0)
return sig_algs[i];
return NULL;
}
+static const AlgorithmIdentifier *
+alg_for_privatekey(const hx509_private_key pk, int type)
+{
+ const heim_oid *keytype;
+ unsigned int i;
+
+ if (pk->ops == NULL)
+ return NULL;
+
+ keytype = pk->ops->key_oid;
+
+ for (i = 0; sig_algs[i]; i++) {
+ if (sig_algs[i]->key_oid == NULL)
+ continue;
+ if (der_heim_oid_cmp(sig_algs[i]->key_oid, keytype) != 0)
+ continue;
+ if (pk->ops->available &&
+ pk->ops->available(pk, sig_algs[i]->sig_alg) == 0)
+ continue;
+ if (type == HX509_SELECT_PUBLIC_SIG)
+ return sig_algs[i]->sig_alg;
+ if (type == HX509_SELECT_DIGEST)
+ return sig_algs[i]->digest_alg;
+
+ return NULL;
+ }
+ return NULL;
+}
+
/*
*
*/
static struct hx509_private_key_ops *private_algs[] = {
&rsa_private_key_ops,
+#ifdef HAVE_OPENSSL
+ &ecdsa_private_key_ops,
+#endif
NULL
};
@@ -1036,12 +1569,37 @@ find_private_alg(const heim_oid *oid)
for (i = 0; private_algs[i]; i++) {
if (private_algs[i]->key_oid == NULL)
continue;
- if (der_heim_oid_cmp((*private_algs[i]->key_oid)(), oid) == 0)
+ if (der_heim_oid_cmp(private_algs[i]->key_oid, oid) == 0)
return private_algs[i];
}
return NULL;
}
+/*
+ * Check if the algorithm `alg' have a best before date, and if it
+ * des, make sure the its before the time `t'.
+ */
+
+int
+_hx509_signature_best_before(hx509_context context,
+ const AlgorithmIdentifier *alg,
+ time_t t)
+{
+ const struct signature_alg *md;
+
+ md = find_sig_alg(&alg->algorithm);
+ if (md == NULL) {
+ hx509_clear_error_string(context);
+ return HX509_SIG_ALG_NO_SUPPORTED;
+ }
+ if (md->best_before && md->best_before < t) {
+ hx509_set_error_string(context, 0, HX509_CRYPTO_ALGORITHM_BEST_BEFORE,
+ "Algorithm %s has passed it best before date",
+ md->name);
+ return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
+ }
+ return 0;
+}
int
_hx509_verify_signature(hx509_context context,
@@ -1069,7 +1627,7 @@ _hx509_verify_signature(hx509_context context,
const SubjectPublicKeyInfo *spi;
spi = &signer->tbsCertificate.subjectPublicKeyInfo;
- if (der_heim_oid_cmp(&spi->algorithm.algorithm, (*md->key_oid)()) != 0) {
+ if (der_heim_oid_cmp(&spi->algorithm.algorithm, md->key_oid) != 0) {
hx509_clear_error_string(context);
return HX509_SIG_ALG_DONT_MATCH_KEY_ALG;
}
@@ -1108,13 +1666,6 @@ _hx509_create_signature(hx509_context context,
{
const struct signature_alg *md;
- if (signer && signer->ops && signer->ops->handle_alg &&
- (*signer->ops->handle_alg)(signer, alg, COT_SIGN))
- {
- return (*signer->ops->sign)(context, signer, alg, data,
- signatureAlgorithm, sig);
- }
-
md = find_sig_alg(&alg->algorithm);
if (md == NULL) {
hx509_set_error_string(context, 0, HX509_SIG_ALG_NO_SUPPORTED,
@@ -1221,7 +1772,7 @@ _hx509_public_encrypt(hx509_context context,
ciphertext->length = ret;
ciphertext->data = to;
- ret = der_copy_oid(oid_id_pkcs1_rsaEncryption(), encryption_oid);
+ ret = der_copy_oid(&asn1_oid_id_pkcs1_rsaEncryption, encryption_oid);
if (ret) {
der_free_octet_string(ciphertext);
hx509_set_error_string(context, 0, ENOMEM, "out of memory");
@@ -1276,7 +1827,7 @@ _hx509_private_key_private_decrypt(hx509_context context,
int
_hx509_parse_private_key(hx509_context context,
- const heim_oid *key_oid,
+ const AlgorithmIdentifier *keyai,
const void *data,
size_t len,
hx509_private_key *private_key)
@@ -1286,7 +1837,7 @@ _hx509_parse_private_key(hx509_context context,
*private_key = NULL;
- ops = find_private_alg(key_oid);
+ ops = find_private_alg(&keyai->algorithm);
if (ops == NULL) {
hx509_clear_error_string(context);
return HX509_SIG_ALG_NO_SUPPORTED;
@@ -1298,7 +1849,7 @@ _hx509_parse_private_key(hx509_context context,
return ret;
}
- ret = (*ops->import)(context, data, len, *private_key);
+ ret = (*ops->import)(context, keyai, data, len, *private_key);
if (ret)
_hx509_private_key_free(private_key);
@@ -1330,7 +1881,7 @@ _hx509_generate_private_key_init(hx509_context context,
{
*ctx = NULL;
- if (der_heim_oid_cmp(oid, oid_id_pkcs1_rsaEncryption()) != 0) {
+ if (der_heim_oid_cmp(oid, &asn1_oid_id_pkcs1_rsaEncryption) != 0) {
hx509_set_error_string(context, 0, EINVAL,
"private key not an RSA key");
return EINVAL;
@@ -1400,98 +1951,10 @@ _hx509_generate_private_key(hx509_context context,
return ret;
}
-
/*
*
*/
-static const heim_octet_string null_entry_oid = { 2, rk_UNCONST("\x05\x00") };
-
-static const unsigned sha512_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };
-const AlgorithmIdentifier _hx509_signature_sha512_data = {
- { 9, rk_UNCONST(sha512_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
-static const unsigned sha384_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };
-const AlgorithmIdentifier _hx509_signature_sha384_data = {
- { 9, rk_UNCONST(sha384_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
-static const unsigned sha256_oid_tree[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
-const AlgorithmIdentifier _hx509_signature_sha256_data = {
- { 9, rk_UNCONST(sha256_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
-static const unsigned sha1_oid_tree[] = { 1, 3, 14, 3, 2, 26 };
-const AlgorithmIdentifier _hx509_signature_sha1_data = {
- { 6, rk_UNCONST(sha1_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
-static const unsigned md5_oid_tree[] = { 1, 2, 840, 113549, 2, 5 };
-const AlgorithmIdentifier _hx509_signature_md5_data = {
- { 6, rk_UNCONST(md5_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
-static const unsigned md2_oid_tree[] = { 1, 2, 840, 113549, 2, 2 };
-const AlgorithmIdentifier _hx509_signature_md2_data = {
- { 6, rk_UNCONST(md2_oid_tree) }, rk_UNCONST(&null_entry_oid)
-};
-
-static const unsigned rsa_with_sha512_oid[] ={ 1, 2, 840, 113549, 1, 1, 13 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_sha512_data = {
- { 7, rk_UNCONST(rsa_with_sha512_oid) }, NULL
-};
-
-static const unsigned rsa_with_sha384_oid[] ={ 1, 2, 840, 113549, 1, 1, 12 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_sha384_data = {
- { 7, rk_UNCONST(rsa_with_sha384_oid) }, NULL
-};
-
-static const unsigned rsa_with_sha256_oid[] ={ 1, 2, 840, 113549, 1, 1, 11 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_sha256_data = {
- { 7, rk_UNCONST(rsa_with_sha256_oid) }, NULL
-};
-
-static const unsigned rsa_with_sha1_oid[] ={ 1, 2, 840, 113549, 1, 1, 5 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_sha1_data = {
- { 7, rk_UNCONST(rsa_with_sha1_oid) }, NULL
-};
-
-static const unsigned rsa_with_md5_oid[] ={ 1, 2, 840, 113549, 1, 1, 4 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_md5_data = {
- { 7, rk_UNCONST(rsa_with_md5_oid) }, NULL
-};
-
-static const unsigned rsa_with_md2_oid[] ={ 1, 2, 840, 113549, 1, 1, 2 };
-const AlgorithmIdentifier _hx509_signature_rsa_with_md2_data = {
- { 7, rk_UNCONST(rsa_with_md2_oid) }, NULL
-};
-
-static const unsigned rsa_oid[] ={ 1, 2, 840, 113549, 1, 1, 1 };
-const AlgorithmIdentifier _hx509_signature_rsa_data = {
- { 7, rk_UNCONST(rsa_oid) }, NULL
-};
-
-static const unsigned rsa_pkcs1_x509_oid[] ={ 1, 2, 752, 43, 16, 1 };
-const AlgorithmIdentifier _hx509_signature_rsa_pkcs1_x509_data = {
- { 6, rk_UNCONST(rsa_pkcs1_x509_oid) }, NULL
-};
-
-static const unsigned des_rsdi_ede3_cbc_oid[] ={ 1, 2, 840, 113549, 3, 7 };
-const AlgorithmIdentifier _hx509_des_rsdi_ede3_cbc_oid = {
- { 6, rk_UNCONST(des_rsdi_ede3_cbc_oid) }, NULL
-};
-
-static const unsigned aes128_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 2 };
-const AlgorithmIdentifier _hx509_crypto_aes128_cbc_data = {
- { 9, rk_UNCONST(aes128_cbc_oid) }, NULL
-};
-
-static const unsigned aes256_cbc_oid[] ={ 2, 16, 840, 1, 101, 3, 4, 1, 42 };
-const AlgorithmIdentifier _hx509_crypto_aes256_cbc_data = {
- { 9, rk_UNCONST(aes256_cbc_oid) }, NULL
-};
-
const AlgorithmIdentifier *
hx509_signature_sha512(void)
{ return &_hx509_signature_sha512_data; }
@@ -1517,6 +1980,18 @@ hx509_signature_md2(void)
{ return &_hx509_signature_md2_data; }
const AlgorithmIdentifier *
+hx509_signature_ecPublicKey(void)
+{ return &_hx509_signature_ecPublicKey; }
+
+const AlgorithmIdentifier *
+hx509_signature_ecdsa_with_sha256(void)
+{ return &_hx509_signature_ecdsa_with_sha256_data; }
+
+const AlgorithmIdentifier *
+hx509_signature_ecdsa_with_sha1(void)
+{ return &_hx509_signature_ecdsa_with_sha1_data; }
+
+const AlgorithmIdentifier *
hx509_signature_rsa_with_sha512(void)
{ return &_hx509_signature_rsa_with_sha512_data; }
@@ -1565,9 +2040,9 @@ hx509_crypto_aes256_cbc(void)
*/
const AlgorithmIdentifier * _hx509_crypto_default_sig_alg =
- &_hx509_signature_rsa_with_sha1_data;
+ &_hx509_signature_rsa_with_sha256_data;
const AlgorithmIdentifier * _hx509_crypto_default_digest_alg =
- &_hx509_signature_sha1_data;
+ &_hx509_signature_sha256_data;
const AlgorithmIdentifier * _hx509_crypto_default_secret_alg =
&_hx509_crypto_aes128_cbc_data;
@@ -1617,8 +2092,15 @@ _hx509_private_key_free(hx509_private_key *key)
if (--(*key)->ref > 0)
return 0;
- if ((*key)->private_key.rsa)
- RSA_free((*key)->private_key.rsa);
+ if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, &asn1_oid_id_pkcs1_rsaEncryption) == 0) {
+ if ((*key)->private_key.rsa)
+ RSA_free((*key)->private_key.rsa);
+#ifdef HAVE_OPENSSL
+ } else if ((*key)->ops && der_heim_oid_cmp((*key)->ops->key_oid, &asn1_oid_id_ecPublicKey) == 0) {
+ if ((*key)->private_key.ecdsa)
+ EC_KEY_free((*key)->private_key.ecdsa);
+#endif
+ }
(*key)->private_key.rsa = NULL;
free(*key);
*key = NULL;
@@ -1631,7 +2113,7 @@ _hx509_private_key_assign_rsa(hx509_private_key key, void *ptr)
if (key->private_key.rsa)
RSA_free(key->private_key.rsa);
key->private_key.rsa = ptr;
- key->signature_alg = oid_id_pkcs1_sha1WithRSAEncryption();
+ key->signature_alg = &asn1_oid_id_pkcs1_sha1WithRSAEncryption;
key->md = &pkcs1_rsa_sha1_alg;
}
@@ -1641,7 +2123,7 @@ _hx509_private_key_oid(hx509_context context,
heim_oid *data)
{
int ret;
- ret = der_copy_oid((*key->ops->key_oid)(), data);
+ ret = der_copy_oid(key->ops->key_oid, data);
if (ret)
hx509_set_error_string(context, 0, ret, "malloc out of memory");
return ret;
@@ -1683,7 +2165,9 @@ _hx509_private_key_export(hx509_context context,
struct hx509cipher {
const char *name;
- const heim_oid *(*oid_func)(void);
+ int flags;
+#define CIPHER_WEAK 1
+ const heim_oid *oid;
const AlgorithmIdentifier *(*ai_func)(void);
const EVP_CIPHER *(*evp_func)(void);
int (*get_params)(hx509_context, const hx509_crypto,
@@ -1694,6 +2178,8 @@ struct hx509cipher {
struct hx509_crypto_data {
char *name;
+ int flags;
+#define ALLOW_WEAK 1
const struct hx509cipher *cipher;
const EVP_CIPHER *c;
heim_octet_string key;
@@ -1705,15 +2191,10 @@ struct hx509_crypto_data {
*
*/
-static const heim_oid *
-oid_private_rc2_40(void)
-{
- static unsigned oid_data[] = { 127, 1 };
- static const heim_oid oid = { 2, oid_data };
-
- return &oid;
-}
+static unsigned private_rc2_40_oid_data[] = { 127, 1 };
+static heim_oid asn1_oid_private_rc2_40 =
+ { 2, private_rc2_40_oid_data };
/*
*
@@ -1853,7 +2334,8 @@ CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param,
static const struct hx509cipher ciphers[] = {
{
"rc2-cbc",
- oid_id_pkcs3_rc2_cbc,
+ CIPHER_WEAK,
+ &asn1_oid_id_pkcs3_rc2_cbc,
NULL,
EVP_rc2_cbc,
CMSRC2CBCParam_get,
@@ -1861,7 +2343,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"rc2-cbc",
- oid_id_rsadsi_rc2_cbc,
+ CIPHER_WEAK,
+ &asn1_oid_id_rsadsi_rc2_cbc,
NULL,
EVP_rc2_cbc,
CMSRC2CBCParam_get,
@@ -1869,7 +2352,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"rc2-40-cbc",
- oid_private_rc2_40,
+ CIPHER_WEAK,
+ &asn1_oid_private_rc2_40,
NULL,
EVP_rc2_40_cbc,
CMSRC2CBCParam_get,
@@ -1877,7 +2361,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"des-ede3-cbc",
- oid_id_pkcs3_des_ede3_cbc,
+ 0,
+ &asn1_oid_id_pkcs3_des_ede3_cbc,
NULL,
EVP_des_ede3_cbc,
CMSCBCParam_get,
@@ -1885,7 +2370,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"des-ede3-cbc",
- oid_id_rsadsi_des_ede3_cbc,
+ 0,
+ &asn1_oid_id_rsadsi_des_ede3_cbc,
hx509_crypto_des_rsdi_ede3_cbc,
EVP_des_ede3_cbc,
CMSCBCParam_get,
@@ -1893,7 +2379,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"aes-128-cbc",
- oid_id_aes_128_cbc,
+ 0,
+ &asn1_oid_id_aes_128_cbc,
hx509_crypto_aes128_cbc,
EVP_aes_128_cbc,
CMSCBCParam_get,
@@ -1901,7 +2388,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"aes-192-cbc",
- oid_id_aes_192_cbc,
+ 0,
+ &asn1_oid_id_aes_192_cbc,
NULL,
EVP_aes_192_cbc,
CMSCBCParam_get,
@@ -1909,7 +2397,8 @@ static const struct hx509cipher ciphers[] = {
},
{
"aes-256-cbc",
- oid_id_aes_256_cbc,
+ 0,
+ &asn1_oid_id_aes_256_cbc,
hx509_crypto_aes256_cbc,
EVP_aes_256_cbc,
CMSCBCParam_get,
@@ -1923,7 +2412,7 @@ find_cipher_by_oid(const heim_oid *oid)
int i;
for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++)
- if (der_heim_oid_cmp(oid, (*ciphers[i].oid_func)()) == 0)
+ if (der_heim_oid_cmp(oid, ciphers[i].oid) == 0)
return &ciphers[i];
return NULL;
@@ -1950,7 +2439,7 @@ hx509_crypto_enctype_by_name(const char *name)
cipher = find_cipher_by_name(name);
if (cipher == NULL)
return NULL;
- return (*cipher->oid_func)();
+ return cipher->oid;
}
int
@@ -2015,6 +2504,12 @@ hx509_crypto_set_key_name(hx509_crypto crypto, const char *name)
return 0;
}
+void
+hx509_crypto_allow_weak(hx509_crypto crypto)
+{
+ crypto->flags |= ALLOW_WEAK;
+}
+
int
hx509_crypto_set_key_data(hx509_crypto crypto, const void *data, size_t length)
{
@@ -2111,6 +2606,10 @@ hx509_crypto_encrypt(hx509_crypto crypto,
*ciphertext = NULL;
+ if ((crypto->cipher->flags & CIPHER_WEAK) &&
+ (crypto->flags & ALLOW_WEAK) == 0)
+ return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
+
assert(EVP_CIPHER_iv_length(crypto->c) == ivec->length);
EVP_CIPHER_CTX_init(&evp);
@@ -2189,6 +2688,10 @@ hx509_crypto_decrypt(hx509_crypto crypto,
clear->data = NULL;
clear->length = 0;
+ if ((crypto->cipher->flags & CIPHER_WEAK) &&
+ (crypto->flags & ALLOW_WEAK) == 0)
+ return HX509_CRYPTO_ALGORITHM_BEST_BEFORE;
+
if (ivec && EVP_CIPHER_iv_length(crypto->c) < ivec->length)
return HX509_CRYPTO_INTERNAL_ERROR;
@@ -2312,6 +2815,8 @@ PBE_string2key(hx509_context context,
if (ret)
goto out;
+ hx509_crypto_allow_weak(c);
+
ret = hx509_crypto_set_key_data(c, key->data, key->length);
if (ret) {
hx509_crypto_destroy(c);
@@ -2330,33 +2835,33 @@ find_string2key(const heim_oid *oid,
const EVP_MD **md,
PBE_string2key_func *s2k)
{
- if (der_heim_oid_cmp(oid, oid_id_pbewithSHAAnd40BitRC2_CBC()) == 0) {
+ if (der_heim_oid_cmp(oid, &asn1_oid_id_pbewithSHAAnd40BitRC2_CBC) == 0) {
*c = EVP_rc2_40_cbc();
*md = EVP_sha1();
*s2k = PBE_string2key;
- return oid_private_rc2_40();
- } else if (der_heim_oid_cmp(oid, oid_id_pbeWithSHAAnd128BitRC2_CBC()) == 0) {
+ return &asn1_oid_private_rc2_40;
+ } else if (der_heim_oid_cmp(oid, &asn1_oid_id_pbeWithSHAAnd128BitRC2_CBC) == 0) {
*c = EVP_rc2_cbc();
*md = EVP_sha1();
*s2k = PBE_string2key;
- return oid_id_pkcs3_rc2_cbc();
+ return &asn1_oid_id_pkcs3_rc2_cbc;
#if 0
- } else if (der_heim_oid_cmp(oid, oid_id_pbeWithSHAAnd40BitRC4()) == 0) {
+ } else if (der_heim_oid_cmp(oid, &asn1_oid_id_pbeWithSHAAnd40BitRC4) == 0) {
*c = EVP_rc4_40();
*md = EVP_sha1();
*s2k = PBE_string2key;
return NULL;
- } else if (der_heim_oid_cmp(oid, oid_id_pbeWithSHAAnd128BitRC4()) == 0) {
+ } else if (der_heim_oid_cmp(oid, &asn1_oid_id_pbeWithSHAAnd128BitRC4) == 0) {
*c = EVP_rc4();
*md = EVP_sha1();
*s2k = PBE_string2key;
- return oid_id_pkcs3_rc4();
+ return &asn1_oid_id_pkcs3_rc4;
#endif
- } else if (der_heim_oid_cmp(oid, oid_id_pbeWithSHAAnd3_KeyTripleDES_CBC()) == 0) {
+ } else if (der_heim_oid_cmp(oid, &asn1_oid_id_pbeWithSHAAnd3_KeyTripleDES_CBC) == 0) {
*c = EVP_des_ede3_cbc();
*md = EVP_sha1();
*s2k = PBE_string2key;
- return oid_id_pkcs3_des_ede3_cbc();
+ return &asn1_oid_id_pkcs3_des_ede3_cbc;
}
return NULL;
@@ -2467,8 +2972,8 @@ out:
*/
-int
-_hx509_match_keys(hx509_cert c, hx509_private_key private_key)
+static int
+match_keys_rsa(hx509_cert c, hx509_private_key private_key)
{
const Certificate *cert;
const SubjectPublicKeyInfo *spi;
@@ -2523,6 +3028,25 @@ _hx509_match_keys(hx509_cert c, hx509_private_key private_key)
return ret == 1;
}
+static int
+match_keys_ec(hx509_cert c, hx509_private_key private_key)
+{
+ return 1; /* XXX use EC_KEY_check_key */
+}
+
+
+int
+_hx509_match_keys(hx509_cert c, hx509_private_key key)
+{
+ if (der_heim_oid_cmp(key->ops->key_oid, &asn1_oid_id_pkcs1_rsaEncryption) == 0)
+ return match_keys_rsa(c, key);
+ if (der_heim_oid_cmp(key->ops->key_oid, &asn1_oid_id_ecPublicKey) == 0)
+ return match_keys_ec(c, key);
+ return 0;
+
+}
+
+
static const heim_oid *
find_keytype(const hx509_private_key key)
{
@@ -2534,10 +3058,9 @@ find_keytype(const hx509_private_key key)
md = find_sig_alg(key->signature_alg);
if (md == NULL)
return NULL;
- return (*md->key_oid)();
+ return md->key_oid;
}
-
int
hx509_crypto_select(const hx509_context context,
int type,
@@ -2545,7 +3068,7 @@ hx509_crypto_select(const hx509_context context,
hx509_peer_info peer,
AlgorithmIdentifier *selected)
{
- const AlgorithmIdentifier *def;
+ const AlgorithmIdentifier *def = NULL;
size_t i, j;
int ret, bits;
@@ -2553,11 +3076,17 @@ hx509_crypto_select(const hx509_context context,
if (type == HX509_SELECT_DIGEST) {
bits = SIG_DIGEST;
- def = _hx509_crypto_default_digest_alg;
+ if (source)
+ def = alg_for_privatekey(source, type);
+ if (def == NULL)
+ def = _hx509_crypto_default_digest_alg;
} else if (type == HX509_SELECT_PUBLIC_SIG) {
bits = SIG_PUBLIC_SIG;
/* XXX depend on `source´ and `peer´ */
- def = _hx509_crypto_default_sig_alg;
+ if (source)
+ def = alg_for_privatekey(source, type);
+ if (def == NULL)
+ def = _hx509_crypto_default_sig_alg;
} else if (type == HX509_SELECT_SECRET_ENC) {
bits = SIG_SECRET;
def = _hx509_crypto_default_secret_alg;
@@ -2576,11 +3105,11 @@ hx509_crypto_select(const hx509_context context,
for (j = 0; sig_algs[j]; j++) {
if ((sig_algs[j]->flags & bits) != bits)
continue;
- if (der_heim_oid_cmp((*sig_algs[j]->sig_oid)(),
+ if (der_heim_oid_cmp(sig_algs[j]->sig_oid,
&peer->val[i].algorithm) != 0)
continue;
if (keytype && sig_algs[j]->key_oid &&
- der_heim_oid_cmp(keytype, (*sig_algs[j]->key_oid)()))
+ der_heim_oid_cmp(keytype, sig_algs[j]->key_oid))
continue;
/* found one, use that */
@@ -2648,7 +3177,7 @@ hx509_crypto_available(hx509_context context,
if (sig_algs[i]->sig_alg == NULL)
continue;
if (keytype && sig_algs[i]->key_oid &&
- der_heim_oid_cmp((*sig_algs[i]->key_oid)(), keytype))
+ der_heim_oid_cmp(sig_algs[i]->key_oid, keytype))
continue;
/* found one, add that to the list */
@@ -2657,7 +3186,7 @@ hx509_crypto_available(hx509_context context,
goto out;
*val = ptr;
- ret = copy_AlgorithmIdentifier((*sig_algs[i]->sig_alg)(), &(*val)[len]);
+ ret = copy_AlgorithmIdentifier(sig_algs[i]->sig_alg, &(*val)[len]);
if (ret)
goto out;
len++;
@@ -2667,7 +3196,9 @@ hx509_crypto_available(hx509_context context,
if (bits & SIG_SECRET) {
for (i = 0; i < sizeof(ciphers)/sizeof(ciphers[0]); i++) {
-
+
+ if (ciphers[i].flags & CIPHER_WEAK)
+ continue;
if (ciphers[i].ai_func == NULL)
continue;
diff --git a/source4/heimdal/lib/hx509/env.c b/source4/heimdal/lib/hx509/env.c
index 0b0a68ceae..7598aebaae 100644
--- a/source4/heimdal/lib/hx509/env.c
+++ b/source4/heimdal/lib/hx509/env.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_env Hx509 enviroment functions
diff --git a/source4/heimdal/lib/hx509/error.c b/source4/heimdal/lib/hx509/error.c
index 6f25404145..45813efb38 100644
--- a/source4/heimdal/lib/hx509/error.c
+++ b/source4/heimdal/lib/hx509/error.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_error Hx509 error reporting functions
diff --git a/source4/heimdal/lib/hx509/file.c b/source4/heimdal/lib/hx509/file.c
index a364dd2179..ba7a23f471 100644
--- a/source4/heimdal/lib/hx509/file.c
+++ b/source4/heimdal/lib/hx509/file.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$ID$");
int
_hx509_map_file_os(const char *fn, heim_octet_string *os)
diff --git a/source4/heimdal/lib/hx509/hx509.h b/source4/heimdal/lib/hx509/hx509.h
index 5e5a2f811b..86aad7ec9c 100644
--- a/source4/heimdal/lib/hx509/hx509.h
+++ b/source4/heimdal/lib/hx509/hx509.h
@@ -36,8 +36,9 @@
#ifndef HEIMDAL_HX509_H
#define HEIMDAL_HX509_H 1
-#include <heim_asn1.h>
#include <rfc2459_asn1.h>
+#include <stdarg.h>
+#include <stdio.h>
typedef struct hx509_cert_attribute_data *hx509_cert_attribute;
typedef struct hx509_cert_data *hx509_cert;
@@ -124,6 +125,17 @@ typedef enum {
/* flags to hx509_cms_unenvelope */
#define HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT 0x01
+#define HX509_CMS_UE_ALLOW_WEAK 0x02
+
+/* flags to hx509_cms_envelope_1 */
+#define HX509_CMS_EV_NO_KU_CHECK 0x01
+#define HX509_CMS_EV_ALLOW_WEAK 0x02
+
+/* flags to hx509_cms_verify_signed */
+#define HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH 0x01
+#define HX509_CMS_VS_NO_KU_CHECK 0x02
+#define HX509_CMS_VS_ALLOW_ZERO_SIGNER 0x04
+#define HX509_CMS_VS_NO_VALIDATE 0x08
/* selectors passed to hx509_crypto_select and hx509_crypto_available */
#define HX509_SELECT_ALL 0
@@ -142,8 +154,9 @@ typedef enum {
#define HX509_CA_TEMPLATE_EKU 64
/* flags hx509_cms_create_signed* */
-#define HX509_CMS_SIGATURE_DETACHED 1
-#define HX509_CMS_SIGATURE_ID_NAME 2
+#define HX509_CMS_SIGNATURE_DETACHED 0x01
+#define HX509_CMS_SIGNATURE_ID_NAME 0x02
+#define HX509_CMS_SIGNATURE_NO_SIGNER 0x04
/* hx509_verify_hostname nametype */
typedef enum {
diff --git a/source4/heimdal/lib/hx509/hx509_err.et b/source4/heimdal/lib/hx509/hx509_err.et
index c1dfaf587e..76bbfaeaba 100644
--- a/source4/heimdal/lib/hx509/hx509_err.et
+++ b/source4/heimdal/lib/hx509/hx509_err.et
@@ -62,9 +62,10 @@ error_code OID_MISMATCH, "Mismatch bewteen oids"
error_code NO_PROMPTER, "No prompter function defined"
error_code SIGNATURE_WITHOUT_SIGNER, "Signature require signer, but non available"
error_code RSA_PUBLIC_ENCRYPT, "RSA public encyption failed"
-error_code RSA_PRIVATE_ENCRYPT, "RSA public encyption failed"
-error_code RSA_PUBLIC_DECRYPT, "RSA private decryption failed"
+error_code RSA_PRIVATE_ENCRYPT, "RSA private encyption failed"
+error_code RSA_PUBLIC_DECRYPT, "RSA public decryption failed"
error_code RSA_PRIVATE_DECRYPT, "RSA private decryption failed"
+error_code ALGORITHM_BEST_BEFORE, "Algorithm has passed its best before date"
# revoke related errors
index 96
diff --git a/source4/heimdal/lib/hx509/hx_locl.h b/source4/heimdal/lib/hx509/hx_locl.h
index 8de2353f15..2d1c036d53 100644
--- a/source4/heimdal/lib/hx509/hx_locl.h
+++ b/source4/heimdal/lib/hx509/hx_locl.h
@@ -33,9 +33,7 @@
/* $Id$ */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <stdio.h>
#include <stdlib.h>
@@ -145,7 +143,7 @@ struct hx509_query_data {
Name *subject_name;
hx509_path *path;
char *friendlyname;
- int (*cmp_func)(void *, hx509_cert);
+ int (*cmp_func)(hx509_context, hx509_cert, void *);
void *cmp_func_ctx;
heim_octet_string *keyhash_sha1;
time_t timenow;
diff --git a/source4/heimdal/lib/hx509/keyset.c b/source4/heimdal/lib/hx509/keyset.c
index b68064b512..c4f035ab87 100644
--- a/source4/heimdal/lib/hx509/keyset.c
+++ b/source4/heimdal/lib/hx509/keyset.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_keyset Certificate store operations
@@ -481,6 +480,10 @@ hx509_certs_find(hx509_context context,
hx509_certs_end_seq(context, certs, cursor);
if (ret)
return ret;
+ /**
+ * Return HX509_CERT_NOT_FOUND if no certificate in certs matched
+ * the query.
+ */
if (c == NULL) {
hx509_clear_error_string(context);
return HX509_CERT_NOT_FOUND;
@@ -489,6 +492,77 @@ hx509_certs_find(hx509_context context,
return 0;
}
+/**
+ * Filter certificate matching the query.
+ *
+ * @param context a hx509 context.
+ * @param certs certificate store to search.
+ * @param q query allocated with @ref hx509_query functions.
+ * @param result the filtered certificate store, caller must free with
+ * hx509_certs_free().
+ *
+ * @return Returns an hx509 error code.
+ *
+ * @ingroup hx509_keyset
+ */
+
+int
+hx509_certs_filter(hx509_context context,
+ hx509_certs certs,
+ const hx509_query *q,
+ hx509_certs *result)
+{
+ hx509_cursor cursor;
+ hx509_cert c;
+ int ret, found = 0;
+
+ _hx509_query_statistic(context, 0, q);
+
+ ret = hx509_certs_init(context, "MEMORY:filter-certs", 0,
+ NULL, result);
+ if (ret)
+ return ret;
+
+ ret = hx509_certs_start_seq(context, certs, &cursor);
+ if (ret) {
+ hx509_certs_free(result);
+ return ret;
+ }
+
+ c = NULL;
+ while (1) {
+ ret = hx509_certs_next_cert(context, certs, cursor, &c);
+ if (ret)
+ break;
+ if (c == NULL)
+ break;
+ if (_hx509_query_match_cert(context, q, c)) {
+ hx509_certs_add(context, *result, c);
+ found = 1;
+ }
+ hx509_cert_free(c);
+ }
+
+ hx509_certs_end_seq(context, certs, cursor);
+ if (ret) {
+ hx509_certs_free(result);
+ return ret;
+ }
+
+ /**
+ * Return HX509_CERT_NOT_FOUND if no certificate in certs matched
+ * the query.
+ */
+ if (!found) {
+ hx509_certs_free(result);
+ hx509_clear_error_string(context);
+ return HX509_CERT_NOT_FOUND;
+ }
+
+ return 0;
+}
+
+
static int
certs_merge_func(hx509_context context, void *ctx, hx509_cert c)
{
diff --git a/source4/heimdal/lib/hx509/ks_dir.c b/source4/heimdal/lib/hx509/ks_dir.c
index 76c0c42633..a627fc65a2 100644
--- a/source4/heimdal/lib/hx509/ks_dir.c
+++ b/source4/heimdal/lib/hx509/ks_dir.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
#include <dirent.h>
/*
@@ -71,7 +70,7 @@ dir_init(hx509_context context,
return ENOENT;
}
- if ((sb.st_mode & S_IFDIR) == 0) {
+ if (!S_ISDIR(sb.st_mode)) {
hx509_set_error_string(context, 0, ENOTDIR,
"%s is not a directory", residue);
return ENOTDIR;
diff --git a/source4/heimdal/lib/hx509/ks_file.c b/source4/heimdal/lib/hx509/ks_file.c
index ca0171f8b9..74808f7607 100644
--- a/source4/heimdal/lib/hx509/ks_file.c
+++ b/source4/heimdal/lib/hx509/ks_file.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
typedef enum { USE_PEM, USE_DER } outformat;
@@ -50,7 +49,8 @@ static int
parse_certificate(hx509_context context, const char *fn,
struct hx509_collector *c,
const hx509_pem_header *headers,
- const void *data, size_t len)
+ const void *data, size_t len,
+ const AlgorithmIdentifier *ai)
{
hx509_cert cert;
int ret;
@@ -130,10 +130,40 @@ out:
}
static int
-parse_rsa_private_key(hx509_context context, const char *fn,
+parse_pkcs8_private_key(hx509_context context, const char *fn,
+ struct hx509_collector *c,
+ const hx509_pem_header *headers,
+ const void *data, size_t length,
+ const AlgorithmIdentifier *ai)
+{
+ PKCS8PrivateKeyInfo ki;
+ heim_octet_string keydata;
+
+ int ret;
+
+ ret = decode_PKCS8PrivateKeyInfo(data, length, &ki, NULL);
+ if (ret)
+ return ret;
+
+ keydata.data = rk_UNCONST(data);
+ keydata.length = length;
+
+ ret = _hx509_collector_private_key_add(context,
+ c,
+ &ki.privateKeyAlgorithm,
+ NULL,
+ &ki.privateKey,
+ &keydata);
+ free_PKCS8PrivateKeyInfo(&ki);
+ return ret;
+}
+
+static int
+parse_pem_private_key(hx509_context context, const char *fn,
struct hx509_collector *c,
const hx509_pem_header *headers,
- const void *data, size_t len)
+ const void *data, size_t len,
+ const AlgorithmIdentifier *ai)
{
int ret = 0;
const char *enc;
@@ -159,7 +189,7 @@ parse_rsa_private_key(hx509_context context, const char *fn,
if (strcmp(enc, "4,ENCRYPTED") != 0) {
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "RSA key encrypted in unknown method %s "
+ "Private key encrypted in unknown method %s "
"in file",
enc, fn);
hx509_clear_error_string(context);
@@ -169,7 +199,7 @@ parse_rsa_private_key(hx509_context context, const char *fn,
dek = hx509_pem_find_header(headers, "DEK-Info");
if (dek == NULL) {
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "Encrypted RSA missing DEK-Info");
+ "Encrypted private key missing DEK-Info");
return HX509_PARSING_KEY_FAILED;
}
@@ -201,7 +231,7 @@ parse_rsa_private_key(hx509_context context, const char *fn,
if (cipher == NULL) {
free(ivdata);
hx509_set_error_string(context, 0, HX509_ALG_NOT_SUPP,
- "RSA key encrypted with "
+ "Private key encrypted with "
"unsupported cipher: %s",
type);
free(type);
@@ -218,7 +248,8 @@ parse_rsa_private_key(hx509_context context, const char *fn,
if (ssize < 0 || ssize < PKCS5_SALT_LEN || ssize < EVP_CIPHER_iv_length(cipher)) {
free(ivdata);
hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
- "Salt have wrong length in RSA key file");
+ "Salt have wrong length in "
+ "private key file");
return HX509_PARSING_KEY_FAILED;
}
@@ -231,9 +262,8 @@ parse_rsa_private_key(hx509_context context, const char *fn,
password = pw->val[i];
passwordlen = strlen(password);
- ret = try_decrypt(context, c, hx509_signature_rsa(),
- cipher, ivdata, password, passwordlen,
- data, len);
+ ret = try_decrypt(context, c, ai, cipher, ivdata,
+ password, passwordlen, data, len);
if (ret == 0) {
decrypted = 1;
break;
@@ -253,9 +283,8 @@ parse_rsa_private_key(hx509_context context, const char *fn,
ret = hx509_lock_prompt(lock, &prompt);
if (ret == 0)
- ret = try_decrypt(context, c, hx509_signature_rsa(),
- cipher, ivdata, password, strlen(password),
- data, len);
+ ret = try_decrypt(context, c, ai, cipher, ivdata, password,
+ strlen(password), data, len);
/* XXX add password to lock password collection ? */
memset(password, 0, sizeof(password));
}
@@ -267,12 +296,8 @@ parse_rsa_private_key(hx509_context context, const char *fn,
keydata.data = rk_UNCONST(data);
keydata.length = len;
- ret = _hx509_collector_private_key_add(context,
- c,
- hx509_signature_rsa(),
- NULL,
- &keydata,
- NULL);
+ ret = _hx509_collector_private_key_add(context, c, ai, NULL,
+ &keydata, NULL);
}
return ret;
@@ -282,10 +307,14 @@ parse_rsa_private_key(hx509_context context, const char *fn,
struct pem_formats {
const char *name;
int (*func)(hx509_context, const char *, struct hx509_collector *,
- const hx509_pem_header *, const void *, size_t);
+ const hx509_pem_header *, const void *, size_t,
+ const AlgorithmIdentifier *);
+ const AlgorithmIdentifier *(*ai)(void);
} formats[] = {
- { "CERTIFICATE", parse_certificate },
- { "RSA PRIVATE KEY", parse_rsa_private_key }
+ { "CERTIFICATE", parse_certificate, NULL },
+ { "PRIVATE KEY", parse_pkcs8_private_key, NULL },
+ { "RSA PRIVATE KEY", parse_pem_private_key, hx509_signature_rsa },
+ { "EC PRIVATE KEY", parse_pem_private_key, hx509_signature_ecPublicKey }
};
@@ -305,9 +334,18 @@ pem_func(hx509_context context, const char *type,
for (j = 0; j < sizeof(formats)/sizeof(formats[0]); j++) {
const char *q = formats[j].name;
if (strcasecmp(type, q) == 0) {
- ret = (*formats[j].func)(context, NULL, pem_ctx->c, header, data, len);
- if (ret == 0)
- break;
+ const AlgorithmIdentifier *ai = NULL;
+ if (formats[j].ai != NULL)
+ ai = (*formats[j].ai)();
+
+ ret = (*formats[j].func)(context, NULL, pem_ctx->c,
+ header, data, len, ai);
+ if (ret) {
+ hx509_set_error_string(context, HX509_ERROR_APPEND, ret,
+ "Failed parseing PEM format %s", type);
+ return ret;
+ }
+ break;
}
}
if (j == sizeof(formats)/sizeof(formats[0])) {
@@ -409,13 +447,19 @@ file_init_common(hx509_context context,
}
for (i = 0; i < sizeof(formats)/sizeof(formats[0]); i++) {
- ret = (*formats[i].func)(context, p, pem_ctx.c, NULL, ptr, length);
+ const AlgorithmIdentifier *ai = NULL;
+ if (formats[i].ai != NULL)
+ ai = (*formats[i].ai)();
+
+ ret = (*formats[i].func)(context, p, pem_ctx.c, NULL, ptr, length, ai);
if (ret == 0)
break;
}
rk_xfree(ptr);
- if (ret)
+ if (ret) {
+ hx509_clear_error_string(context);
goto out;
+ }
}
}
diff --git a/source4/heimdal/lib/hx509/ks_keychain.c b/source4/heimdal/lib/hx509/ks_keychain.c
index 2dc0721563..01d0c55d1c 100644
--- a/source4/heimdal/lib/hx509/ks_keychain.c
+++ b/source4/heimdal/lib/hx509/ks_keychain.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
#ifdef HAVE_FRAMEWORK_SECURITY
@@ -119,6 +118,8 @@ kc_rsa_private_encrypt(int flen,
CSSM_DATA sig, in;
int fret = 0;
+ if (padding != RSA_PKCS1_PADDING)
+ return -1;
cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey);
if(cret) abort();
@@ -157,7 +158,62 @@ static int
kc_rsa_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
RSA * rsa, int padding)
{
- return -1;
+ struct kc_rsa *kc = RSA_get_app_data(rsa);
+
+ CSSM_RETURN cret;
+ OSStatus ret;
+ const CSSM_ACCESS_CREDENTIALS *creds;
+ SecKeyRef privKeyRef = (SecKeyRef)kc->item;
+ CSSM_CSP_HANDLE cspHandle;
+ const CSSM_KEY *cssmKey;
+ CSSM_CC_HANDLE handle = 0;
+ CSSM_DATA out, in, rem;
+ int fret = 0;
+ CSSM_SIZE outlen = 0;
+ char remdata[1024];
+
+ if (padding != RSA_PKCS1_PADDING)
+ return -1;
+
+ cret = SecKeyGetCSSMKey(privKeyRef, &cssmKey);
+ if(cret) abort();
+
+ cret = SecKeyGetCSPHandle(privKeyRef, &cspHandle);
+ if(cret) abort();
+
+ ret = SecKeyGetCredentials(privKeyRef, CSSM_ACL_AUTHORIZATION_DECRYPT,
+ kSecCredentialTypeDefault, &creds);
+ if(ret) abort();
+
+
+ ret = CSSM_CSP_CreateAsymmetricContext (cspHandle,
+ CSSM_ALGID_RSA,
+ creds,
+ cssmKey,
+ CSSM_PADDING_PKCS1,
+ &handle);
+ if(ret) abort();
+
+ in.Data = (uint8 *)from;
+ in.Length = flen;
+
+ out.Data = (uint8 *)to;
+ out.Length = kc->keysize;
+
+ rem.Data = (uint8 *)remdata;
+ rem.Length = sizeof(remdata);
+
+ cret = CSSM_DecryptData(handle, &in, 1, &out, 1, &outlen, &rem);
+ if(cret) {
+ /* cssmErrorString(cret); */
+ fret = -1;
+ } else
+ fret = out.Length;
+
+ if(handle)
+ CSSM_DeleteContext(handle);
+
+ return fret;
}
static int
@@ -504,8 +560,7 @@ keychain_iter_end(hx509_context context,
struct iter *iter = cursor;
if (iter->certs) {
- int ret;
- ret = hx509_certs_end_seq(context, iter->certs, iter->cursor);
+ hx509_certs_end_seq(context, iter->certs, iter->cursor);
hx509_certs_free(&iter->certs);
} else {
CFRelease(iter->searchRef);
diff --git a/source4/heimdal/lib/hx509/ks_mem.c b/source4/heimdal/lib/hx509/ks_mem.c
index bf952fbeee..299a3932c9 100644
--- a/source4/heimdal/lib/hx509/ks_mem.c
+++ b/source4/heimdal/lib/hx509/ks_mem.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("Id$");
/*
* Should use two hash/tree certificates intead of a array. Criteria
diff --git a/source4/heimdal/lib/hx509/ks_null.c b/source4/heimdal/lib/hx509/ks_null.c
index fae631fb3f..136d2d4345 100644
--- a/source4/heimdal/lib/hx509/ks_null.c
+++ b/source4/heimdal/lib/hx509/ks_null.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
static int
diff --git a/source4/heimdal/lib/hx509/ks_p11.c b/source4/heimdal/lib/hx509/ks_p11.c
index 652cdc2210..52697f834b 100644
--- a/source4/heimdal/lib/hx509/ks_p11.c
+++ b/source4/heimdal/lib/hx509/ks_p11.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
@@ -332,7 +331,7 @@ p11_init_slot(hx509_context context,
}
asprintf(&slot->name, "%.*s",
- i, slot_info.slotDescription);
+ (int)i, slot_info.slotDescription);
if ((slot_info.flags & CKF_TOKEN_PRESENT) == 0)
return 0;
@@ -711,7 +710,7 @@ collect_cert(hx509_context context,
_hx509_set_cert_attribute(context,
cert,
- oid_id_pkcs_9_at_localKeyId(),
+ &asn1_oid_id_pkcs_9_at_localKeyId,
&data);
}
@@ -945,11 +944,7 @@ p11_release_module(struct p11_module *p)
if (p->slot[i].flags & P11_SESSION_IN_USE)
_hx509_abort("pkcs11 module release while session in use");
if (p->slot[i].flags & P11_SESSION) {
- int ret;
-
- ret = P11FUNC(p, CloseSession, (p->slot[i].session));
- if (ret != CKR_OK)
- ;
+ P11FUNC(p, CloseSession, (p->slot[i].session));
}
if (p->slot[i].name)
diff --git a/source4/heimdal/lib/hx509/ks_p12.c b/source4/heimdal/lib/hx509/ks_p12.c
index b59bd215f0..c17ce3f6ac 100644
--- a/source4/heimdal/lib/hx509/ks_p12.c
+++ b/source4/heimdal/lib/hx509/ks_p12.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
struct ks_pkcs12 {
hx509_certs certs;
@@ -45,7 +44,7 @@ typedef int (*collector_func)(hx509_context,
const PKCS12_Attributes *);
struct type {
- const heim_oid * (*oid)(void);
+ const heim_oid *oid;
collector_func func;
};
@@ -77,7 +76,7 @@ keyBag_parser(hx509_context context,
const heim_octet_string *os = NULL;
int ret;
- attr = find_attribute(attrs, oid_id_pkcs_9_at_localKeyId());
+ attr = find_attribute(attrs, &asn1_oid_id_pkcs_9_at_localKeyId);
if (attr)
os = &attr->attrValues;
@@ -140,7 +139,7 @@ certBag_parser(hx509_context context,
if (ret)
return ret;
- if (der_heim_oid_cmp(oid_id_pkcs_9_at_certTypes_x509(), &cb.certType)) {
+ if (der_heim_oid_cmp(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType)) {
free_PKCS12_CertBag(&cb);
return 0;
}
@@ -166,13 +165,13 @@ certBag_parser(hx509_context context,
{
const PKCS12_Attribute *attr;
- const heim_oid * (*oids[])(void) = {
- oid_id_pkcs_9_at_localKeyId, oid_id_pkcs_9_at_friendlyName
+ const heim_oid *oids[] = {
+ &asn1_oid_id_pkcs_9_at_localKeyId, &asn1_oid_id_pkcs_9_at_friendlyName
};
int i;
- for (i = 0; i < sizeof(oids)/sizeof(oids[0]); i++) {
- const heim_oid *oid = (*(oids[i]))();
+ for (i = 0; i < sizeof(oids)/sizeof(oids[0]); i++) {
+ const heim_oid *oid = oids[i];
attr = find_attribute(attrs, oid);
if (attr)
_hx509_set_cert_attribute(context, cert, oid,
@@ -248,7 +247,7 @@ encryptedData_parser(hx509_context context,
if (ret)
return ret;
- if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) == 0)
+ if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0)
ret = parse_safe_content(context, c, content.data, content.length);
der_free_octet_string(&content);
@@ -285,7 +284,7 @@ envelopedData_parser(hx509_context context,
return ret;
}
- if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) == 0)
+ if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) == 0)
ret = parse_safe_content(context, c, content.data, content.length);
der_free_octet_string(&content);
@@ -296,12 +295,12 @@ envelopedData_parser(hx509_context context,
struct type bagtypes[] = {
- { oid_id_pkcs12_keyBag, keyBag_parser },
- { oid_id_pkcs12_pkcs8ShroudedKeyBag, ShroudedKeyBag_parser },
- { oid_id_pkcs12_certBag, certBag_parser },
- { oid_id_pkcs7_data, safeContent_parser },
- { oid_id_pkcs7_encryptedData, encryptedData_parser },
- { oid_id_pkcs7_envelopedData, envelopedData_parser }
+ { &asn1_oid_id_pkcs12_keyBag, keyBag_parser },
+ { &asn1_oid_id_pkcs12_pkcs8ShroudedKeyBag, ShroudedKeyBag_parser },
+ { &asn1_oid_id_pkcs12_certBag, certBag_parser },
+ { &asn1_oid_id_pkcs7_data, safeContent_parser },
+ { &asn1_oid_id_pkcs7_encryptedData, encryptedData_parser },
+ { &asn1_oid_id_pkcs7_envelopedData, envelopedData_parser }
};
static void
@@ -314,7 +313,7 @@ parse_pkcs12_type(hx509_context context,
int i;
for (i = 0; i < sizeof(bagtypes)/sizeof(bagtypes[0]); i++)
- if (der_heim_oid_cmp((*bagtypes[i].oid)(), oid) == 0)
+ if (der_heim_oid_cmp(bagtypes[i].oid, oid) == 0)
(*bagtypes[i].func)(context, c, data, length, attrs);
}
@@ -376,7 +375,7 @@ p12_init(hx509_context context,
goto out;
}
- if (der_heim_oid_cmp(&pfx.authSafe.contentType, oid_id_pkcs7_data()) != 0) {
+ if (der_heim_oid_cmp(&pfx.authSafe.contentType, &asn1_oid_id_pkcs7_data) != 0) {
free_PKCS12_PFX(&pfx);
ret = EINVAL;
hx509_set_error_string(context, 0, ret,
@@ -506,7 +505,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
free(os.data);
if (ret)
goto out;
- ret = der_copy_oid(oid_id_pkcs_9_at_certTypes_x509(), &cb.certType);
+ ret = der_copy_oid(&asn1_oid_id_pkcs_9_at_certTypes_x509, &cb.certType);
if (ret) {
free_PKCS12_CertBag(&cb);
goto out;
@@ -517,7 +516,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
if (ret)
goto out;
- ret = addBag(context, as, oid_id_pkcs12_certBag(), os.data, os.length);
+ ret = addBag(context, as, &asn1_oid_id_pkcs12_certBag, os.data, os.length);
if (_hx509_cert_private_key_exportable(c)) {
hx509_private_key key = _hx509_cert_private_key(c);
@@ -541,7 +540,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
free_PKCS8PrivateKeyInfo(&pki);
return ret;
}
- /* set attribute, oid_id_pkcs_9_at_localKeyId() */
+ /* set attribute, asn1_oid_id_pkcs_9_at_localKeyId */
ASN1_MALLOC_ENCODE(PKCS8PrivateKeyInfo, os.data, os.length,
&pki, &size, ret);
@@ -549,7 +548,7 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
if (ret)
return ret;
- ret = addBag(context, as, oid_id_pkcs12_keyBag(), os.data, os.length);
+ ret = addBag(context, as, &asn1_oid_id_pkcs12_keyBag, os.data, os.length);
if (ret)
return ret;
}
@@ -598,7 +597,7 @@ p12_store(hx509_context context,
if (ret)
goto out;
- ret = der_copy_oid(oid_id_pkcs7_data(), &pfx.authSafe.contentType);
+ ret = der_copy_oid(&asn1_oid_id_pkcs7_data, &pfx.authSafe.contentType);
if (ret)
goto out;
diff --git a/source4/heimdal/lib/hx509/lock.c b/source4/heimdal/lib/hx509/lock.c
index e2ceedecb8..219a301928 100644
--- a/source4/heimdal/lib/hx509/lock.c
+++ b/source4/heimdal/lib/hx509/lock.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_lock Locking and unlocking certificates and encrypted data.
diff --git a/source4/heimdal/lib/hx509/name.c b/source4/heimdal/lib/hx509/name.c
index 069eed6062..b8f48d5236 100644
--- a/source4/heimdal/lib/hx509/name.c
+++ b/source4/heimdal/lib/hx509/name.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2004 - 2007 Kungliga Tekniska Högskolan
+ * Copyright (c) 2004 - 2009 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,6 @@
#include "hx_locl.h"
#include <wind.h>
-RCSID("$Id$");
/**
* @page page_name PKIX/X.509 Names
@@ -63,20 +62,20 @@ RCSID("$Id$");
static const struct {
const char *n;
- const heim_oid *(*o)(void);
+ const heim_oid *o;
wind_profile_flags flags;
} no[] = {
- { "C", oid_id_at_countryName },
- { "CN", oid_id_at_commonName },
- { "DC", oid_id_domainComponent },
- { "L", oid_id_at_localityName },
- { "O", oid_id_at_organizationName },
- { "OU", oid_id_at_organizationalUnitName },
- { "S", oid_id_at_stateOrProvinceName },
- { "STREET", oid_id_at_streetAddress },
- { "UID", oid_id_Userid },
- { "emailAddress", oid_id_pkcs9_emailAddress },
- { "serialNumber", oid_id_at_serialNumber }
+ { "C", &asn1_oid_id_at_countryName },
+ { "CN", &asn1_oid_id_at_commonName },
+ { "DC", &asn1_oid_id_domainComponent },
+ { "L", &asn1_oid_id_at_localityName },
+ { "O", &asn1_oid_id_at_organizationName },
+ { "OU", &asn1_oid_id_at_organizationalUnitName },
+ { "S", &asn1_oid_id_at_stateOrProvinceName },
+ { "STREET", &asn1_oid_id_at_streetAddress },
+ { "UID", &asn1_oid_id_Userid },
+ { "emailAddress", &asn1_oid_id_pkcs9_emailAddress },
+ { "serialNumber", &asn1_oid_id_at_serialNumber }
};
static char *
@@ -145,7 +144,7 @@ oidtostring(const heim_oid *type)
size_t i;
for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) {
- if (der_heim_oid_cmp((*no[i].o)(), type) == 0)
+ if (der_heim_oid_cmp(no[i].o, type) == 0)
return strdup(no[i].n);
}
if (der_print_heim_oid(type, '.', &s) != 0)
@@ -163,7 +162,7 @@ stringtooid(const char *name, size_t len, heim_oid *oid)
for (i = 0; i < sizeof(no)/sizeof(no[0]); i++) {
if (strncasecmp(no[i].n, name, len) == 0)
- return der_copy_oid((*no[i].o)(), oid);
+ return der_copy_oid(no[i].o, oid);
}
s = malloc(len + 1);
if (s == NULL)
@@ -197,7 +196,7 @@ int
_hx509_Name_to_string(const Name *n, char **str)
{
size_t total_len = 0;
- int i, j;
+ int i, j, ret;
*str = strdup("");
if (*str == NULL)
@@ -224,15 +223,20 @@ _hx509_Name_to_string(const Name *n, char **str)
ss = ds->u.utf8String;
break;
case choice_DirectoryString_bmpString: {
- uint16_t *bmp = ds->u.bmpString.data;
+ const uint16_t *bmp = ds->u.bmpString.data;
size_t bmplen = ds->u.bmpString.length;
size_t k;
- ss = malloc(bmplen + 1);
+ ret = wind_ucs2utf8_length(bmp, bmplen, &k);
+ if (ret)
+ return ret;
+
+ ss = malloc(k + 1);
if (ss == NULL)
_hx509_abort("allocation failure"); /* XXX */
- for (k = 0; k < bmplen; k++)
- ss[k] = bmp[k] & 0xff; /* XXX */
+ ret = wind_ucs2utf8(bmp, bmplen, ss, NULL);
+ if (ret)
+ return ret;
ss[k] = '\0';
break;
}
@@ -244,15 +248,20 @@ _hx509_Name_to_string(const Name *n, char **str)
ss[ds->u.teletexString.length] = '\0';
break;
case choice_DirectoryString_universalString: {
- uint32_t *uni = ds->u.universalString.data;
+ const uint32_t *uni = ds->u.universalString.data;
size_t unilen = ds->u.universalString.length;
size_t k;
- ss = malloc(unilen + 1);
+ ret = wind_ucs4utf8_length(uni, unilen, &k);
+ if (ret)
+ return ret;
+
+ ss = malloc(k + 1);
if (ss == NULL)
_hx509_abort("allocation failure"); /* XXX */
- for (k = 0; k < unilen; k++)
- ss[k] = uni[k] & 0xff; /* XXX */
+ ret = wind_ucs4utf8(uni, unilen, ss, NULL);
+ if (ret)
+ return ret;
ss[k] = '\0';
break;
}
@@ -344,8 +353,10 @@ dsstringprep(const DirectoryString *ds, uint32_t **rname, size_t *rlen)
if (name == NULL)
return ENOMEM;
ret = wind_utf8ucs4(ds->u.utf8String, name, &len);
- if (ret)
+ if (ret) {
+ free(name);
return ret;
+ }
break;
default:
_hx509_abort("unknown directory type: %d", ds->element);
diff --git a/source4/heimdal/lib/hx509/peer.c b/source4/heimdal/lib/hx509/peer.c
index f5841e497b..c796e19173 100644
--- a/source4/heimdal/lib/hx509/peer.c
+++ b/source4/heimdal/lib/hx509/peer.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_peer Hx509 crypto selecting functions
@@ -121,6 +120,39 @@ hx509_peer_info_set_cert(hx509_peer_info peer,
}
/**
+ * Add an additional algorithm that the peer supports.
+ *
+ * @param context A hx509 context.
+ * @param peer the peer to set the new algorithms for
+ * @param val an AlgorithmsIdentier to add
+ *
+ * @return An hx509 error code, see hx509_get_error_string().
+ *
+ * @ingroup hx509_peer
+ */
+
+int
+hx509_peer_info_add_cms_alg(hx509_context context,
+ hx509_peer_info peer,
+ const AlgorithmIdentifier *val)
+{
+ void *ptr;
+ int ret;
+
+ ptr = realloc(peer->val, sizeof(peer->val[0]) * (peer->len + 1));
+ if (ptr == NULL) {
+ hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+ return ENOMEM;
+ }
+ ret = copy_AlgorithmIdentifier(val, &peer->val[peer->len]);
+ if (ret == 0)
+ peer->len += 1;
+ else
+ hx509_set_error_string(context, 0, ret, "out of memory");
+ return ret;
+}
+
+/**
* Set the algorithms that the peer supports.
*
* @param context A hx509 context.
diff --git a/source4/heimdal/lib/hx509/print.c b/source4/heimdal/lib/hx509/print.c
index 38d103905f..ddafb7f46e 100644
--- a/source4/heimdal/lib/hx509/print.c
+++ b/source4/heimdal/lib/hx509/print.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
/**
* @page page_print Hx509 printing functions
@@ -547,14 +546,14 @@ check_CRLDistributionPoints(hx509_validate_ctx ctx,
struct {
const char *name;
- const heim_oid *(*oid)(void);
+ const heim_oid *oid;
int (*func)(hx509_validate_ctx, heim_any *);
-} check_altname[] = {
- { "pk-init", oid_id_pkinit_san, check_pkinit_san },
- { "jabber", oid_id_pkix_on_xmppAddr, check_utf8_string_san },
- { "dns-srv", oid_id_pkix_on_dnsSRV, check_altnull },
- { "card-id", oid_id_uspkicommon_card_id, check_altnull },
- { "Microsoft NT-PRINCIPAL-NAME", oid_id_pkinit_ms_san, check_utf8_string_san }
+} altname_types[] = {
+ { "pk-init", &asn1_oid_id_pkinit_san, check_pkinit_san },
+ { "jabber", &asn1_oid_id_pkix_on_xmppAddr, check_utf8_string_san },
+ { "dns-srv", &asn1_oid_id_pkix_on_dnsSRV, check_altnull },
+ { "card-id", &asn1_oid_id_uspkicommon_card_id, check_altnull },
+ { "Microsoft NT-PRINCIPAL-NAME", &asn1_oid_id_pkinit_ms_san, check_utf8_string_san }
};
static int
@@ -597,17 +596,17 @@ check_altName(hx509_validate_ctx ctx,
validate_print(ctx, HX509_VALIDATE_F_VERBOSE,
"%sAltName otherName ", name);
- for (j = 0; j < sizeof(check_altname)/sizeof(check_altname[0]); j++) {
- if (der_heim_oid_cmp((*check_altname[j].oid)(),
+ for (j = 0; j < sizeof(altname_types)/sizeof(altname_types[0]); j++) {
+ if (der_heim_oid_cmp(altname_types[j].oid,
&gn.val[i].u.otherName.type_id) != 0)
continue;
validate_print(ctx, HX509_VALIDATE_F_VERBOSE, "%s: ",
- check_altname[j].name);
- (*check_altname[j].func)(ctx, &gn.val[i].u.otherName.value);
+ altname_types[j].name);
+ (*altname_types[j].func)(ctx, &gn.val[i].u.otherName.value);
break;
}
- if (j == sizeof(check_altname)/sizeof(check_altname[0])) {
+ if (j == sizeof(altname_types)/sizeof(altname_types[0])) {
hx509_oid_print(&gn.val[i].u.otherName.type_id,
validate_vprint, ctx);
validate_print(ctx, HX509_VALIDATE_F_VERBOSE, " unknown");
@@ -751,14 +750,14 @@ check_authorityInfoAccess(hx509_validate_ctx ctx,
struct {
const char *name;
- const heim_oid *(*oid)(void);
+ const heim_oid *oid;
int (*func)(hx509_validate_ctx ctx,
struct cert_status *status,
enum critical_flag cf,
const Extension *);
enum critical_flag cf;
} check_extension[] = {
-#define ext(name, checkname) #name, &oid_id_x509_ce_##name, check_##checkname
+#define ext(name, checkname) #name, &asn1_oid_id_x509_ce_##name, check_##checkname
{ ext(subjectDirectoryAttributes, Null), M_N_C },
{ ext(subjectKeyIdentifier, subjectKeyIdentifier), M_N_C },
{ ext(keyUsage, Null), S_C },
@@ -782,13 +781,13 @@ struct {
{ ext(freshestCRL, Null), M_N_C },
{ ext(inhibitAnyPolicy, Null), M_C },
#undef ext
-#define ext(name, checkname) #name, &oid_id_pkix_pe_##name, check_##checkname
+#define ext(name, checkname) #name, &asn1_oid_id_pkix_pe_##name, check_##checkname
{ ext(proxyCertInfo, proxyCertInfo), M_C },
{ ext(authorityInfoAccess, authorityInfoAccess), M_C },
#undef ext
- { "US Fed PKI - PIV Interim", oid_id_uspkicommon_piv_interim,
+ { "US Fed PKI - PIV Interim", &asn1_oid_id_uspkicommon_piv_interim,
check_Null, D_C },
- { "Netscape cert comment", oid_id_netscape_cert_comment,
+ { "Netscape cert comment", &asn1_oid_id_netscape_cert_comment,
check_Null, D_C },
{ NULL }
};
@@ -949,7 +948,7 @@ hx509_validate_cert(hx509_context context,
for (i = 0; i < t->extensions->len; i++) {
for (j = 0; check_extension[j].name; j++)
- if (der_heim_oid_cmp((*check_extension[j].oid)(),
+ if (der_heim_oid_cmp(check_extension[j].oid,
&t->extensions->val[i].extnID) == 0)
break;
if (check_extension[j].name == NULL) {
diff --git a/source4/heimdal/lib/hx509/req.c b/source4/heimdal/lib/hx509/req.c
index 9836777143..0d174e0cec 100644
--- a/source4/heimdal/lib/hx509/req.c
+++ b/source4/heimdal/lib/hx509/req.c
@@ -33,7 +33,6 @@
#include "hx_locl.h"
#include <pkcs10_asn1.h>
-RCSID("$Id$");
struct hx509_request_data {
hx509_name name;
diff --git a/source4/heimdal/lib/hx509/revoke.c b/source4/heimdal/lib/hx509/revoke.c
index 3f35b0d190..adb31164c1 100644
--- a/source4/heimdal/lib/hx509/revoke.c
+++ b/source4/heimdal/lib/hx509/revoke.c
@@ -50,7 +50,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
struct revoke_crl {
char *path;
@@ -235,7 +234,7 @@ verify_ocsp(hx509_context context,
}
ret = hx509_cert_check_eku(context, signer,
- oid_id_pkix_kp_OCSPSigning(), 0);
+ &asn1_oid_id_pkix_kp_OCSPSigning, 0);
if (ret)
goto out;
}
@@ -295,7 +294,7 @@ parse_ocsp_basic(const void *data, size_t length, OCSPBasicOCSPResponse *basic)
}
ret = der_heim_oid_cmp(&resp.responseBytes->responseType,
- oid_id_pkix_ocsp_basic());
+ &asn1_oid_id_pkix_ocsp_basic);
if (ret != 0) {
free_OCSPResponse(&resp);
return HX509_REVOKE_WRONG_DATA;
@@ -1011,8 +1010,7 @@ hx509_ocsp_request(hx509_context context,
goto out;
}
es->len = 1;
-
- ret = der_copy_oid(oid_id_pkix_ocsp_nonce(), &es->val[0].extnID);
+ ret = der_copy_oid(&asn1_oid_id_pkix_ocsp_nonce, &es->val[0].extnID);
if (ret) {
free_OCSPRequest(&req);
return ret;
diff --git a/source4/heimdal/lib/hx509/sel-gram.y b/source4/heimdal/lib/hx509/sel-gram.y
index e529479724..7f7c9980e0 100644
--- a/source4/heimdal/lib/hx509/sel-gram.y
+++ b/source4/heimdal/lib/hx509/sel-gram.y
@@ -39,7 +39,6 @@
#include <stdlib.h>
#include <hx_locl.h>
-RCSID("$Id$");
%}
diff --git a/source4/heimdal/lib/hx509/test_name.c b/source4/heimdal/lib/hx509/test_name.c
index da83e52786..2cdcdf85f6 100644
--- a/source4/heimdal/lib/hx509/test_name.c
+++ b/source4/heimdal/lib/hx509/test_name.c
@@ -32,7 +32,6 @@
*/
#include "hx_locl.h"
-RCSID("$Id$");
static int
test_name(hx509_context context, const char *name)
diff --git a/source4/heimdal/lib/krb5/acache.c b/source4/heimdal/lib/krb5/acache.c
index bd0a9846e4..0ecda99348 100644
--- a/source4/heimdal/lib/krb5/acache.c
+++ b/source4/heimdal/lib/krb5/acache.c
@@ -37,12 +37,8 @@
#include <dlfcn.h>
#endif
-RCSID("$Id$");
-
-/* XXX should we fetch these for each open ? */
static HEIMDAL_MUTEX acc_mutex = HEIMDAL_MUTEX_INITIALIZER;
static cc_initialize_func init_func;
-
#ifdef HAVE_DLOPEN
static void *cc_handle;
#endif
@@ -135,7 +131,7 @@ init_ccapi(krb5_context context)
#else
HEIMDAL_MUTEX_unlock(&acc_mutex);
krb5_set_error_message(context, KRB5_CC_NOSUPP,
- N_("no support for shared object", "file, error"));
+ N_("no support for shared object", ""));
return KRB5_CC_NOSUPP;
#endif
}
@@ -342,6 +338,7 @@ make_ccred_from_cred(krb5_context context,
addr->length = incred->addresses.val[i].address.length;
addr->data = malloc(addr->length);
if (addr->data == NULL) {
+ free(addr);
ret = ENOMEM;
goto fail;
}
@@ -490,16 +487,23 @@ acc_resolve(krb5_context context, krb5_ccache *id, const char *res)
error = (*a->context->func->open_ccache)(a->context, res, &a->ccache);
if (error == ccNoError) {
+ cc_time_t offset;
error = get_cc_name(a);
if (error != ccNoError) {
acc_close(context, *id);
*id = NULL;
return translate_cc_error(context, error);
}
+
+ error = (*a->ccache->func->get_kdc_time_offset)(a->ccache,
+ cc_credentials_v5,
+ &offset);
+ if (error == 0)
+ context->kdc_sec_offset = offset;
+
} else if (error == ccErrCCacheNotFound) {
a->ccache = NULL;
a->cache_name = NULL;
- error = 0;
} else {
*id = NULL;
return translate_cc_error(context, error);
@@ -572,6 +576,11 @@ acc_initialize(krb5_context context,
name);
}
+ if (error == 0 && context->kdc_sec_offset)
+ error = (*a->ccache->func->set_kdc_time_offset)(a->ccache,
+ cc_credentials_v5,
+ context->kdc_sec_offset);
+
return translate_cc_error(context, error);
}
@@ -946,8 +955,10 @@ acc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
return translate_cc_error(context, error);
}
-
error = (*ato->ccache->func->move)(afrom->ccache, ato->ccache);
+
+ acc_destroy(context, from);
+
return translate_cc_error(context, error);
}
diff --git a/source4/heimdal/lib/krb5/add_et_list.c b/source4/heimdal/lib/krb5/add_et_list.c
index f08c0fe718..ccffd93b2c 100644
--- a/source4/heimdal/lib/krb5/add_et_list.c
+++ b/source4/heimdal/lib/krb5/add_et_list.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/**
* Add a specified list of error messages to the et list in context.
* Call func (probably a comerr-generated function) with a pointer to
diff --git a/source4/heimdal/lib/krb5/addr_families.c b/source4/heimdal/lib/krb5/addr_families.c
index 9e2fb3d63a..f88fb2276a 100644
--- a/source4/heimdal/lib/krb5/addr_families.c
+++ b/source4/heimdal/lib/krb5/addr_families.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
struct addr_operations {
int af;
krb5_address_type atype;
@@ -678,6 +676,9 @@ addrport_print_addr (const krb5_address *addr, char *str, size_t len)
krb5_storage *sp;
sp = krb5_storage_from_data((krb5_data*)rk_UNCONST(&addr->address));
+ if (sp == NULL)
+ return ENOMEM;
+
/* for totally obscure reasons, these are not in network byteorder */
krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
@@ -1142,10 +1143,12 @@ krb5_parse_address(krb5_context context,
for (a = ai, i = 0; a != NULL; a = a->ai_next) {
if (krb5_sockaddr2address (context, ai->ai_addr, &addresses->val[i]))
continue;
- if(krb5_address_search(context, &addresses->val[i], addresses))
+ if(krb5_address_search(context, &addresses->val[i], addresses)) {
+ krb5_free_address(context, &addresses->val[i]);
continue;
- addresses->len = i;
+ }
i++;
+ addresses->len = i;
}
freeaddrinfo (ai);
return 0;
@@ -1454,7 +1457,6 @@ krb5_make_addrport (krb5_context context,
*p++ = (2 >> 24) & 0xFF;
memcpy (p, &port, 2);
- p += 2;
return 0;
}
diff --git a/source4/heimdal/lib/krb5/appdefault.c b/source4/heimdal/lib/krb5/appdefault.c
index d49fc4997a..383e82dad4 100644
--- a/source4/heimdal/lib/krb5/appdefault.c
+++ b/source4/heimdal/lib/krb5/appdefault.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
void KRB5_LIB_FUNCTION
krb5_appdefault_boolean(krb5_context context, const char *appname,
krb5_const_realm realm, const char *option,
diff --git a/source4/heimdal/lib/krb5/asn1_glue.c b/source4/heimdal/lib/krb5/asn1_glue.c
index cb86c324fb..59c0fbd64b 100644
--- a/source4/heimdal/lib/krb5/asn1_glue.c
+++ b/source4/heimdal/lib/krb5/asn1_glue.c
@@ -37,8 +37,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
_krb5_principal2principalname (PrincipalName *p,
const krb5_principal from)
@@ -52,13 +50,23 @@ _krb5_principalname2krb5_principal (krb5_context context,
const PrincipalName from,
const Realm realm)
{
- krb5_principal p = malloc(sizeof(*p));
+ krb5_error_code ret;
+ krb5_principal p;
+
+ p = malloc(sizeof(*p));
if (p == NULL)
return ENOMEM;
- copy_PrincipalName(&from, &p->name);
+ ret = copy_PrincipalName(&from, &p->name);
+ if (ret) {
+ free(p);
+ return ret;
+ }
p->realm = strdup(realm);
- if (p->realm == NULL)
+ if (p->realm == NULL) {
+ free_PrincipalName(&p->name);
+ free(p);
return ENOMEM;
+ }
*principal = p;
return 0;
}
diff --git a/source4/heimdal/lib/krb5/auth_context.c b/source4/heimdal/lib/krb5/auth_context.c
index 66eccbbc07..bfc183d168 100644
--- a/source4/heimdal/lib/krb5/auth_context.c
+++ b/source4/heimdal/lib/krb5/auth_context.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_auth_con_init(krb5_context context,
krb5_auth_context *auth_context)
diff --git a/source4/heimdal/lib/krb5/build_ap_req.c b/source4/heimdal/lib/krb5/build_ap_req.c
index 92c03cb782..1550239faf 100644
--- a/source4/heimdal/lib/krb5/build_ap_req.c
+++ b/source4/heimdal/lib/krb5/build_ap_req.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_build_ap_req (krb5_context context,
krb5_enctype enctype,
diff --git a/source4/heimdal/lib/krb5/build_auth.c b/source4/heimdal/lib/krb5/build_auth.c
index bbf4f274af..bf77fd4e77 100644
--- a/source4/heimdal/lib/krb5/build_auth.c
+++ b/source4/heimdal/lib/krb5/build_auth.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
static krb5_error_code
make_etypelist(krb5_context context,
krb5_authdata **auth_data)
@@ -81,12 +79,14 @@ make_etypelist(krb5_context context,
ALLOC(*auth_data, 1);
if (*auth_data == NULL) {
+ free(buf);
krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
return ENOMEM;
}
ALLOC_SEQ(*auth_data, 1);
if ((*auth_data)->val == NULL) {
+ free(*auth_data);
free(buf);
krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
return ENOMEM;
diff --git a/source4/heimdal/lib/krb5/cache.c b/source4/heimdal/lib/krb5/cache.c
index 80b755cd27..12097470d5 100644
--- a/source4/heimdal/lib/krb5/cache.c
+++ b/source4/heimdal/lib/krb5/cache.c
@@ -33,7 +33,70 @@
#include "krb5_locl.h"
-RCSID("$Id$");
+/**
+ * @page krb5_ccache_intro The credential cache functions
+ * @section section_krb5_ccache Kerberos credential caches
+ *
+ * krb5_ccache structure holds a Kerberos credential cache.
+ *
+ * Heimdal support the follow types of credential caches:
+ *
+ * - SCC
+ * Store the credential in a database
+ * - FILE
+ * Store the credential in memory
+ * - MEMORY
+ * Store the credential in memory
+ * - API
+ * A credential cache server based solution for Mac OS X
+ * - KCM
+ * A credential cache server based solution for all platforms
+ *
+ * @subsection Example
+ *
+ * This is a minimalistic version of klist:
+@code
+#include <krb5.h>
+
+int
+main (int argc, char **argv)
+{
+ krb5_context context;
+ krb5_cc_cursor cursor;
+ krb5_error_code ret;
+ krb5_ccache id;
+ krb5_creds creds;
+
+ if (krb5_init_context (&context) != 0)
+ errx(1, "krb5_context");
+
+ ret = krb5_cc_default (context, &id);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_cc_default");
+
+ ret = krb5_cc_start_seq_get(context, id, &cursor);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_cc_start_seq_get");
+
+ while((ret = krb5_cc_next_cred(context, id, &cursor, &creds)) == 0){
+ char *principal;
+
+ krb5_unparse_name_short(context, creds.server, &principal);
+ printf("principal: %s\\n", principal);
+ free(principal);
+ krb5_free_cred_contents (context, &creds);
+ }
+ ret = krb5_cc_end_seq_get(context, id, &cursor);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_cc_end_seq_get");
+
+ krb5_cc_close(context, id);
+
+ krb5_free_context(context);
+ return 0;
+}
+* @endcode
+*/
/**
* Add a new ccache type with operations `ops', overwriting any
@@ -176,23 +239,6 @@ krb5_cc_resolve(krb5_context context,
}
/**
- * Generate a new ccache of type `ops' in `id'.
- *
- * @return Return an error code or 0, see krb5_get_error_message().
- *
- * @ingroup krb5_ccache
- */
-
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_cc_gen_new(krb5_context context,
- const krb5_cc_ops *ops,
- krb5_ccache *id)
-{
- return krb5_cc_new_unique(context, ops->prefix, NULL, id);
-}
-
-/**
* Generates a new unique ccache of `type` in `id'. If `type' is NULL,
* the library chooses the default credential cache type. The supplied
* `hint' (that can be NULL) is a string that the credential cache
@@ -221,7 +267,12 @@ krb5_cc_new_unique(krb5_context context, const char *type,
ret = _krb5_cc_allocate(context, ops, id);
if (ret)
return ret;
- return (*id)->ops->gen_new(context, id);
+ ret = (*id)->ops->gen_new(context, id);
+ if (ret) {
+ free(*id);
+ *id = NULL;
+ }
+ return ret;
}
/**
@@ -676,7 +727,7 @@ krb5_cc_get_principal(krb5_context context,
/**
* Start iterating over `id', `cursor' is initialized to the
- * beginning.
+ * beginning. Caller must free the cursor with krb5_cc_end_seq_get().
*
* @return Return an error code or 0, see krb5_get_error_message().
*
@@ -712,32 +763,6 @@ krb5_cc_next_cred (krb5_context context,
}
/**
- * Like krb5_cc_next_cred, but allow for selective retrieval
- *
- * @ingroup krb5_ccache
- */
-
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_cc_next_cred_match(krb5_context context,
- const krb5_ccache id,
- krb5_cc_cursor * cursor,
- krb5_creds * creds,
- krb5_flags whichfields,
- const krb5_creds * mcreds)
-{
- krb5_error_code ret;
- while (1) {
- ret = krb5_cc_next_cred(context, id, cursor, creds);
- if (ret)
- return ret;
- if (mcreds == NULL || krb5_compare_creds(context, whichfields, mcreds, creds))
- return 0;
- krb5_free_cred_contents(context, creds);
- }
-}
-
-/**
* Destroy the cursor `cursor'.
*
* @ingroup krb5_ccache
@@ -806,25 +831,37 @@ krb5_cc_get_flags(krb5_context context,
}
/**
- * Copy the contents of `from' to `to'.
+ * Copy the contents of `from' to `to' if the given match function
+ * return true.
+ *
+ * @param context A Kerberos 5 context.
+ * @param from the cache to copy data from.
+ * @param to the cache to copy data to.
+ * @param match a match function that should return TRUE if cred argument should be copied, if NULL, all credentials are copied.
+ * @param matchctx context passed to match function.
+ * @param matched set to true if there was a credential that matched, may be NULL.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
*
* @ingroup krb5_ccache
*/
-
krb5_error_code KRB5_LIB_FUNCTION
-krb5_cc_copy_cache_match(krb5_context context,
- const krb5_ccache from,
- krb5_ccache to,
- krb5_flags whichfields,
- const krb5_creds * mcreds,
- unsigned int *matched)
+krb5_cc_copy_match_f(krb5_context context,
+ const krb5_ccache from,
+ krb5_ccache to,
+ krb5_boolean (*match)(krb5_context, void *, const krb5_creds *),
+ void *matchctx,
+ unsigned int *matched)
{
krb5_error_code ret;
krb5_cc_cursor cursor;
krb5_creds cred;
krb5_principal princ;
+ if (matched)
+ *matched = 0;
+
ret = krb5_cc_get_principal(context, from, &princ);
if (ret)
return ret;
@@ -838,24 +875,26 @@ krb5_cc_copy_cache_match(krb5_context context,
krb5_free_principal(context, princ);
return ret;
}
- if (matched)
- *matched = 0;
- while (ret == 0 &&
- krb5_cc_next_cred_match(context, from, &cursor, &cred,
- whichfields, mcreds) == 0) {
- if (matched)
- (*matched)++;
- ret = krb5_cc_store_cred(context, to, &cred);
- krb5_free_cred_contents(context, &cred);
+
+ while ((ret = krb5_cc_next_cred(context, from, &cursor, &cred)) == 0) {
+ if (match == NULL || (*match)(context, matchctx, &cred) == 0) {
+ if (matched)
+ (*matched)++;
+ ret = krb5_cc_store_cred(context, to, &cred);
+ if (ret)
+ break;
+ }
+ krb5_free_cred_contents(context, &cred);
}
krb5_cc_end_seq_get(context, from, &cursor);
krb5_free_principal(context, princ);
+ if (ret == KRB5_CC_END)
+ ret = 0;
return ret;
}
-
/**
- * Just like krb5_cc_copy_cache_match, but copy everything.
+ * Just like krb5_cc_copy_match_f(), but copy everything.
*
* @ingroup @krb5_ccache
*/
@@ -865,21 +904,7 @@ krb5_cc_copy_cache(krb5_context context,
const krb5_ccache from,
krb5_ccache to)
{
- return krb5_cc_copy_cache_match(context, from, to, 0, NULL, NULL);
-}
-
-/**
- * MIT compat glue
- *
- * @ingroup krb5_ccache
- */
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_cc_copy_creds(krb5_context context,
- const krb5_ccache from,
- krb5_ccache to)
-{
- return krb5_cc_copy_cache(context, from, to);
+ return krb5_cc_copy_match_f(context, from, to, NULL, NULL, NULL);
}
/**
@@ -1057,10 +1082,14 @@ krb5_cc_cache_end_seq_get (krb5_context context,
}
/**
- * Search for a matching credential cache of type `type' that have the
+ * Search for a matching credential cache that have the
* `principal' as the default principal. On success, `id' needs to be
* freed with krb5_cc_close() or krb5_cc_destroy().
*
+ * @param context A Kerberos 5 context
+ * @param client The principal to search for
+ * @param id the returned credential cache
+ *
* @return On failure, error code is returned and `id' is set to NULL.
*
* @ingroup krb5_ccache
@@ -1082,7 +1111,7 @@ krb5_cc_cache_match (krb5_context context,
if (ret)
return ret;
- while ((ret = krb5_cccol_cursor_next (context, cursor, &cache)) == 0) {
+ while (krb5_cccol_cursor_next (context, cursor, &cache) == 0 && cache != NULL) {
krb5_principal principal;
ret = krb5_cc_get_principal(context, cache, &principal);
@@ -1107,7 +1136,7 @@ krb5_cc_cache_match (krb5_context context,
krb5_unparse_name(context, client, &str);
krb5_set_error_message(context, KRB5_CC_NOTFOUND,
- N_("Principal %s not found in a "
+ N_("Principal %s not found in any "
"credential cache", ""),
str ? str : "<out of memory>");
if (str)
@@ -1178,7 +1207,7 @@ build_conf_principals(krb5_context context, krb5_ccache id,
}
ret = krb5_make_principal(context, &cred->server,
- krb5_principal_get_realm(context, client),
+ KRB5_REALM_NAME,
KRB5_CONF_NAME, name, pname, NULL);
free(pname);
if (ret) {
@@ -1224,7 +1253,7 @@ krb5_is_config_principal(krb5_context context,
* @param principal configuration for a specific principal, if
* NULL, global for the whole cache.
* @param name name under which the configuraion is stored.
- * @param data data to store
+ * @param data data to store, if NULL, configure is removed.
*
* @ingroup krb5_ccache
*/
@@ -1246,15 +1275,17 @@ krb5_cc_set_config(krb5_context context, krb5_ccache id,
if (ret && ret != KRB5_CC_NOTFOUND)
goto out;
- /* not that anyone care when this expire */
- cred.times.authtime = time(NULL);
- cred.times.endtime = cred.times.authtime + 3600 * 24 * 30;
-
- ret = krb5_data_copy(&cred.ticket, data->data, data->length);
- if (ret)
- goto out;
-
- ret = krb5_cc_store_cred(context, id, &cred);
+ if (data) {
+ /* not that anyone care when this expire */
+ cred.times.authtime = time(NULL);
+ cred.times.endtime = cred.times.authtime + 3600 * 24 * 30;
+
+ ret = krb5_data_copy(&cred.ticket, data->data, data->length);
+ if (ret)
+ goto out;
+
+ ret = krb5_cc_store_cred(context, id, &cred);
+ }
out:
krb5_free_cred_contents (context, &cred);
@@ -1345,6 +1376,8 @@ krb5_cccol_cursor_new(krb5_context context, krb5_cccol_cursor *cursor)
* @param cache the returned cursor, pointer is set to NULL on failure
* and a cache on success. The returned cache needs to be freed
* with krb5_cc_close() or destroyed with krb5_cc_destroy().
+ * MIT Kerberos behavies slightly diffrent and sets cache to NULL
+ * when all caches are iterated over and return 0.
*
* @return Return 0 or and error, KRB5_CC_END is returned at the end
* of iteration. See krb5_get_error_message().
@@ -1446,7 +1479,7 @@ krb5_cc_last_change_time(krb5_context context,
* and mtime is 0, there was no credentials in the caches.
*
* @param context A Kerberos 5 context
- * @param id The credential cache to probe
+ * @param type The credential cache to probe, if NULL, all type are traversed.
* @param mtime the last modification time, set to 0 on error.
* @return Return 0 or and error. See krb5_get_error_message().
@@ -1470,7 +1503,7 @@ krb5_cccol_last_change_time(krb5_context context,
if (ret)
return ret;
- while ((ret = krb5_cccol_cursor_next (context, cursor, &id)) == 0) {
+ while (krb5_cccol_cursor_next(context, cursor, &id) == 0 && id != NULL) {
if (type && strcmp(krb5_cc_get_type(context, id), type) != 0)
continue;
@@ -1487,3 +1520,106 @@ krb5_cccol_last_change_time(krb5_context context,
return 0;
}
+/**
+ * Return a friendly name on credential cache. Free the result with krb5_xfree().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_ccache
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_get_friendly_name(krb5_context context,
+ krb5_ccache id,
+ char **name)
+{
+ krb5_error_code ret;
+ krb5_data data;
+
+ ret = krb5_cc_get_config(context, id, NULL, "FriendlyName", &data);
+ if (ret) {
+ krb5_principal principal;
+ ret = krb5_cc_get_principal(context, id, &principal);
+ if (ret)
+ return ret;
+ ret = krb5_unparse_name(context, principal, name);
+ krb5_free_principal(context, principal);
+ } else {
+ ret = asprintf(name, "%.*s", (int)data.length, (char *)data.data);
+ krb5_data_free(&data);
+ if (ret <= 0) {
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ } else
+ ret = 0;
+ }
+
+ return ret;
+}
+
+/**
+ * Set the friendly name on credential cache.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_ccache
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_set_friendly_name(krb5_context context,
+ krb5_ccache id,
+ const char *name)
+{
+ krb5_data data;
+
+ data.data = rk_UNCONST(name);
+ data.length = strlen(name);
+
+ return krb5_cc_set_config(context, id, NULL, "FriendlyName", &data);
+}
+
+/**
+ * Get the lifetime of the initial ticket in the cache
+ *
+ * Get the lifetime of the initial ticket in the cache, if the initial
+ * ticket was not found, the error code KRB5_CC_END is returned.
+ *
+ * @param context A Kerberos 5 context.
+ * @param id a credential cache
+ * @param t the relative lifetime of the initial ticket
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_ccache
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_get_lifetime(krb5_context context, krb5_ccache id, time_t *t)
+{
+ krb5_cc_cursor cursor;
+ krb5_error_code ret;
+ krb5_creds cred;
+ time_t now;
+
+ *t = 0;
+ now = time(NULL);
+
+ ret = krb5_cc_start_seq_get(context, id, &cursor);
+ if (ret)
+ return ret;
+
+ while ((ret = krb5_cc_next_cred(context, id, &cursor, &cred)) == 0) {
+ if (cred.flags.b.initial) {
+ if (now < cred.times.endtime)
+ *t = cred.times.endtime - now;
+ krb5_free_cred_contents(context, &cred);
+ goto out;
+ }
+ krb5_free_cred_contents(context, &cred);
+ }
+
+ out:
+ krb5_cc_end_seq_get(context, id, &cursor);
+
+ return ret;
+}
diff --git a/source4/heimdal/lib/krb5/changepw.c b/source4/heimdal/lib/krb5/changepw.c
index 91ed9c5ba0..207b86b488 100644
--- a/source4/heimdal/lib/krb5/changepw.c
+++ b/source4/heimdal/lib/krb5/changepw.c
@@ -31,9 +31,9 @@
* SUCH DAMAGE.
*/
-#include <krb5_locl.h>
+#define KRB5_DEPRECATED
-RCSID("$Id$");
+#include <krb5_locl.h>
#undef __attribute__
#define __attribute__(X)
@@ -82,7 +82,6 @@ chgpw_send_request (krb5_context context,
krb5_data passwd_data;
size_t len;
u_char header[6];
- u_char *p;
struct iovec iov[3];
struct msghdr msghdr;
@@ -118,13 +117,12 @@ chgpw_send_request (krb5_context context,
goto out2;
len = 6 + ap_req_data.length + krb_priv_data.length;
- p = header;
- *p++ = (len >> 8) & 0xFF;
- *p++ = (len >> 0) & 0xFF;
- *p++ = 0;
- *p++ = 1;
- *p++ = (ap_req_data.length >> 8) & 0xFF;
- *p++ = (ap_req_data.length >> 0) & 0xFF;
+ header[0] = (len >> 8) & 0xFF;
+ header[1] = (len >> 0) & 0xFF;
+ header[2] = 0;
+ header[3] = 1;
+ header[4] = (ap_req_data.length >> 8) & 0xFF;
+ header[5] = (ap_req_data.length >> 0) & 0xFF;
memset(&msghdr, 0, sizeof(msghdr));
msghdr.msg_name = NULL;
@@ -231,7 +229,7 @@ setpw_send_request (krb5_context context,
*p++ = 0xff;
*p++ = 0x80;
*p++ = (ap_req_data.length >> 8) & 0xFF;
- *p++ = (ap_req_data.length >> 0) & 0xFF;
+ *p = (ap_req_data.length >> 0) & 0xFF;
memset(&msghdr, 0, sizeof(msghdr));
msghdr.msg_name = NULL;
@@ -693,7 +691,7 @@ krb5_change_password (krb5_context context,
int *result_code,
krb5_data *result_code_string,
krb5_data *result_string)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
struct kpwd_proc *p = find_chpw_proto("change password");
@@ -711,7 +709,7 @@ krb5_change_password (krb5_context context,
#endif /* HEIMDAL_SMALLER */
/**
- * Change passwrod using creds.
+ * Change password using creds.
*
* @param context a Keberos context
* @param creds The initial kadmin/passwd for the principal or an admin principal
@@ -767,8 +765,6 @@ krb5_set_password(krb5_context context,
return ret;
}
-#ifndef HEIMDAL_SMALLER
-
/*
*
*/
@@ -834,8 +830,6 @@ krb5_set_password_using_ccache(krb5_context context,
return ret;
}
-#endif /* !HEIMDAL_SMALLER */
-
/*
*
*/
diff --git a/source4/heimdal/lib/krb5/codec.c b/source4/heimdal/lib/krb5/codec.c
index bd0dcc5371..ebda3e51f7 100644
--- a/source4/heimdal/lib/krb5/codec.c
+++ b/source4/heimdal/lib/krb5/codec.c
@@ -31,12 +31,9 @@
* SUCH DAMAGE.
*/
-#include "krb5_locl.h"
-
-#undef __attribute__
-#define __attribute__(x)
+#define KRB5_DEPRECATED
-RCSID("$Id$");
+#include "krb5_locl.h"
#ifndef HEIMDAL_SMALLER
@@ -46,7 +43,7 @@ krb5_decode_EncTicketPart (krb5_context context,
size_t length,
EncTicketPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_EncTicketPart(data, length, t, len);
}
@@ -57,7 +54,7 @@ krb5_encode_EncTicketPart (krb5_context context,
size_t length,
EncTicketPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_EncTicketPart(data, length, t, len);
}
@@ -68,7 +65,7 @@ krb5_decode_EncASRepPart (krb5_context context,
size_t length,
EncASRepPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_EncASRepPart(data, length, t, len);
}
@@ -79,7 +76,7 @@ krb5_encode_EncASRepPart (krb5_context context,
size_t length,
EncASRepPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_EncASRepPart(data, length, t, len);
}
@@ -90,7 +87,7 @@ krb5_decode_EncTGSRepPart (krb5_context context,
size_t length,
EncTGSRepPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_EncTGSRepPart(data, length, t, len);
}
@@ -101,7 +98,7 @@ krb5_encode_EncTGSRepPart (krb5_context context,
size_t length,
EncTGSRepPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_EncTGSRepPart(data, length, t, len);
}
@@ -112,7 +109,7 @@ krb5_decode_EncAPRepPart (krb5_context context,
size_t length,
EncAPRepPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_EncAPRepPart(data, length, t, len);
}
@@ -123,7 +120,7 @@ krb5_encode_EncAPRepPart (krb5_context context,
size_t length,
EncAPRepPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_EncAPRepPart(data, length, t, len);
}
@@ -134,7 +131,7 @@ krb5_decode_Authenticator (krb5_context context,
size_t length,
Authenticator *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_Authenticator(data, length, t, len);
}
@@ -145,7 +142,7 @@ krb5_encode_Authenticator (krb5_context context,
size_t length,
Authenticator *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_Authenticator(data, length, t, len);
}
@@ -156,7 +153,7 @@ krb5_decode_EncKrbCredPart (krb5_context context,
size_t length,
EncKrbCredPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_EncKrbCredPart(data, length, t, len);
}
@@ -167,7 +164,7 @@ krb5_encode_EncKrbCredPart (krb5_context context,
size_t length,
EncKrbCredPart *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_EncKrbCredPart (data, length, t, len);
}
@@ -178,7 +175,7 @@ krb5_decode_ETYPE_INFO (krb5_context context,
size_t length,
ETYPE_INFO *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_ETYPE_INFO(data, length, t, len);
}
@@ -189,7 +186,7 @@ krb5_encode_ETYPE_INFO (krb5_context context,
size_t length,
ETYPE_INFO *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_ETYPE_INFO (data, length, t, len);
}
@@ -200,7 +197,7 @@ krb5_decode_ETYPE_INFO2 (krb5_context context,
size_t length,
ETYPE_INFO2 *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return decode_ETYPE_INFO2(data, length, t, len);
}
@@ -211,7 +208,7 @@ krb5_encode_ETYPE_INFO2 (krb5_context context,
size_t length,
ETYPE_INFO2 *t,
size_t *len)
- __attribute__((deprecated))
+ KRB5_DEPRECATED
{
return encode_ETYPE_INFO2 (data, length, t, len);
}
diff --git a/source4/heimdal/lib/krb5/config_file.c b/source4/heimdal/lib/krb5/config_file.c
index 75c48a001b..ee226c78a2 100644
--- a/source4/heimdal/lib/krb5/config_file.c
+++ b/source4/heimdal/lib/krb5/config_file.c
@@ -32,9 +32,6 @@
*/
#include "krb5_locl.h"
-RCSID("$Id$");
-
-#ifndef HAVE_NETINFO
/* Gaah! I want a portable funopen */
struct fileptr {
@@ -302,21 +299,65 @@ krb5_config_parse_string_multi(krb5_context context,
return 0;
}
+/**
+ * Parse a configuration file and add the result into res. This
+ * interface can be used to parse several configuration files into one
+ * resulting krb5_config_section by calling it repeatably.
+ *
+ * @param context a Kerberos 5 context.
+ * @param fname a file name to a Kerberos configuration file
+ * @param res the returned result, must be free with krb5_free_config_files().
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_support
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_config_parse_file_multi (krb5_context context,
const char *fname,
krb5_config_section **res)
{
const char *str;
+ char *newfname = NULL;
unsigned lineno = 0;
krb5_error_code ret;
struct fileptr f;
+
+ /**
+ * If the fname starts with "~/" parse configuration file in the
+ * current users home directory. The behavior can be disabled and
+ * enabled by calling krb5_set_home_dir_access().
+ */
+ if (_krb5_homedir_access(context) && fname[0] == '~' && fname[1] == '/') {
+ const char *home = NULL;
+
+ if(!issuid())
+ home = getenv("HOME");
+
+ if (home == NULL) {
+ struct passwd *pw = getpwuid(getuid());
+ if(pw != NULL)
+ home = pw->pw_dir;
+ }
+ if (home) {
+ asprintf(&newfname, "%s%s", home, &fname[1]);
+ if (newfname == NULL) {
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ fname = newfname;
+ }
+ }
+
f.f = fopen(fname, "r");
f.s = NULL;
if(f.f == NULL) {
ret = errno;
krb5_set_error_message (context, ret, "open %s: %s",
fname, strerror(ret));
+ if (newfname)
+ free(newfname);
return ret;
}
@@ -324,8 +365,12 @@ krb5_config_parse_file_multi (krb5_context context,
fclose(f.f);
if (ret) {
krb5_set_error_message (context, ret, "%s:%u: %s", fname, lineno, str);
+ if (newfname)
+ free(newfname);
return ret;
}
+ if (newfname)
+ free(newfname);
return 0;
}
@@ -338,8 +383,6 @@ krb5_config_parse_file (krb5_context context,
return krb5_config_parse_file_multi(context, fname, res);
}
-#endif /* !HAVE_NETINFO */
-
static void
free_binding (krb5_context context, krb5_config_binding *b)
{
diff --git a/source4/heimdal/lib/krb5/config_file_netinfo.c b/source4/heimdal/lib/krb5/config_file_netinfo.c
deleted file mode 100644
index e6993bbb4a..0000000000
--- a/source4/heimdal/lib/krb5/config_file_netinfo.c
+++ /dev/null
@@ -1,180 +0,0 @@
-/*
- * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "krb5_locl.h"
-RCSID("$Id$");
-
-/*
- * Netinfo implementation from Luke Howard <lukeh@xedoc.com.au>
- */
-
-#ifdef HAVE_NETINFO
-#include <netinfo/ni.h>
-static ni_status
-ni_proplist2binding(ni_proplist *pl, krb5_config_section **ret)
-{
- int i, j;
- krb5_config_section **next = NULL;
-
- for (i = 0; i < pl->ni_proplist_len; i++) {
- if (!strcmp(pl->nipl_val[i].nip_name, "name"))
- continue;
-
- for (j = 0; j < pl->nipl_val[i].nip_val.ni_namelist_len; j++) {
- krb5_config_binding *b;
-
- b = malloc(sizeof(*b));
- if (b == NULL)
- return NI_FAILED;
-
- b->next = NULL;
- b->type = krb5_config_string;
- b->name = ni_name_dup(pl->nipl_val[i].nip_name);
- b->u.string = ni_name_dup(pl->nipl_val[i].nip_val.ninl_val[j]);
-
- if (next == NULL) {
- *ret = b;
- } else {
- *next = b;
- }
- next = &b->next;
- }
- }
- return NI_OK;
-}
-
-static ni_status
-ni_idlist2binding(void *ni, ni_idlist *idlist, krb5_config_section **ret)
-{
- int i;
- ni_status nis;
- krb5_config_section **next;
-
- for (i = 0; i < idlist->ni_idlist_len; i++) {
- ni_proplist pl;
- ni_id nid;
- ni_idlist children;
- krb5_config_binding *b;
- ni_index index;
-
- nid.nii_instance = 0;
- nid.nii_object = idlist->ni_idlist_val[i];
-
- nis = ni_read(ni, &nid, &pl);
-
- if (nis != NI_OK) {
- return nis;
- }
- index = ni_proplist_match(pl, "name", NULL);
- b = malloc(sizeof(*b));
- if (b == NULL) return NI_FAILED;
-
- if (i == 0) {
- *ret = b;
- } else {
- *next = b;
- }
-
- b->type = krb5_config_list;
- b->name = ni_name_dup(pl.nipl_val[index].nip_val.ninl_val[0]);
- b->next = NULL;
- b->u.list = NULL;
-
- /* get the child directories */
- nis = ni_children(ni, &nid, &children);
- if (nis == NI_OK) {
- nis = ni_idlist2binding(ni, &children, &b->u.list);
- if (nis != NI_OK) {
- return nis;
- }
- }
-
- nis = ni_proplist2binding(&pl, b->u.list == NULL ? &b->u.list : &b->u.list->next);
- ni_proplist_free(&pl);
- if (nis != NI_OK) {
- return nis;
- }
- next = &b->next;
- }
- ni_idlist_free(idlist);
- return NI_OK;
-}
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_config_parse_file (krb5_context context,
- const char *fname,
- krb5_config_section **res)
-{
- void *ni = NULL, *lastni = NULL;
- int i;
- ni_status nis;
- ni_id nid;
- ni_idlist children;
-
- krb5_config_section *s;
- int ret;
-
- s = NULL;
-
- for (i = 0; i < 256; i++) {
- if (i == 0) {
- nis = ni_open(NULL, ".", &ni);
- } else {
- if (lastni != NULL) ni_free(lastni);
- lastni = ni;
- nis = ni_open(lastni, "..", &ni);
- }
- if (nis != NI_OK)
- break;
- nis = ni_pathsearch(ni, &nid, "/locations/kerberos");
- if (nis == NI_OK) {
- nis = ni_children(ni, &nid, &children);
- if (nis != NI_OK)
- break;
- nis = ni_idlist2binding(ni, &children, &s);
- break;
- }
- }
-
- if (ni != NULL) ni_free(ni);
- if (ni != lastni && lastni != NULL) ni_free(lastni);
-
- ret = (nis == NI_OK) ? 0 : -1;
- if (ret == 0) {
- *res = s;
- } else {
- *res = NULL;
- }
- return ret;
-}
-#endif /* HAVE_NETINFO */
diff --git a/source4/heimdal/lib/krb5/constants.c b/source4/heimdal/lib/krb5/constants.c
index b41fb3f663..a3b3d09f41 100644
--- a/source4/heimdal/lib/krb5/constants.c
+++ b/source4/heimdal/lib/krb5/constants.c
@@ -33,11 +33,16 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
KRB5_LIB_VARIABLE const char *krb5_config_file =
#ifdef __APPLE__
+"~/Library/Preferences/edu.mit.Kerberos:"
"/Library/Preferences/edu.mit.Kerberos:"
#endif
SYSCONFDIR "/krb5.conf:/etc/krb5.conf";
KRB5_LIB_VARIABLE const char *krb5_defkeyname = KEYTAB_DEFAULT;
+
+KRB5_LIB_VARIABLE const char *krb5_cc_type_api = "API";
+KRB5_LIB_VARIABLE const char *krb5_cc_type_file = "FILE";
+KRB5_LIB_VARIABLE const char *krb5_cc_type_memory = "MEMORY";
+KRB5_LIB_VARIABLE const char *krb5_cc_type_kcm = "KCM";
+KRB5_LIB_VARIABLE const char *krb5_cc_type_scc = "SCC";
diff --git a/source4/heimdal/lib/krb5/context.c b/source4/heimdal/lib/krb5/context.c
index 127dfa117d..fe94135030 100644
--- a/source4/heimdal/lib/krb5/context.c
+++ b/source4/heimdal/lib/krb5/context.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include <com_err.h>
-RCSID("$Id$");
-
#define INIT_FIELD(C, T, E, D, F) \
(C)->E = krb5_config_get_ ## T ## _default ((C), NULL, (D), \
"libdefaults", F, NULL)
@@ -243,9 +241,7 @@ cc_ops_register(krb5_context context)
krb5_cc_register(context, &krb5_acc_ops, TRUE);
krb5_cc_register(context, &krb5_fcc_ops, TRUE);
krb5_cc_register(context, &krb5_mcc_ops, TRUE);
-#ifdef HAVE_SQLITE
krb5_cc_register(context, &krb5_scc_ops, TRUE);
-#endif
#ifdef HAVE_KCM
krb5_cc_register(context, &krb5_kcm_ops, TRUE);
#endif
@@ -310,6 +306,8 @@ krb5_init_context(krb5_context *context)
}
HEIMDAL_MUTEX_init(p->mutex);
+ p->flags |= KRB5_CTX_F_HOMEDIR_ACCESS;
+
ret = krb5_get_default_config_files(&files);
if(ret)
goto out;
@@ -336,7 +334,7 @@ out:
* Make a copy for the Kerberos 5 context, allocated krb5_contex shoud
* be freed with krb5_free_context().
*
- * @param in the Kerberos context to copy
+ * @param context the Kerberos context to copy
* @param out the copy of the Kerberos, set to NULL error.
*
* @return Returns 0 to indicate success. Otherwise an kerberos et
@@ -453,10 +451,10 @@ krb5_free_context(krb5_context context)
krb5_set_extra_addresses(context, NULL);
krb5_set_ignore_addresses(context, NULL);
krb5_set_send_to_kdc_func(context, NULL, NULL);
- if (context->mutex != NULL) {
- HEIMDAL_MUTEX_destroy(context->mutex);
- free(context->mutex);
- }
+
+ HEIMDAL_MUTEX_destroy(context->mutex);
+ free(context->mutex);
+
memset(context, 0, sizeof(*context));
free(context);
}
@@ -552,7 +550,7 @@ krb5_prepend_config_files(const char *filelist, char **pq, char ***ret_pp)
krb5_free_config_files(pp);
return ENOMEM;
}
- l = strsep_copy(&p, ":", fn, l + 1);
+ (void)strsep_copy(&p, ":", fn, l + 1);
ret = add_file(&pp, &len, fn);
if (ret) {
krb5_free_config_files(pp);
@@ -641,7 +639,8 @@ krb5_get_default_config_files(char ***pfilenames)
/**
* Free a list of configuration files.
*
- * @param filenames list to be freed.
+ * @param filenames list, terminated with a NULL pointer, to be
+ * freed. NULL is an valid argument.
*
* @return Returns 0 to indicate success. Otherwise an kerberos et
* error code is returned, see krb5_get_error_message().
@@ -653,7 +652,7 @@ void KRB5_LIB_FUNCTION
krb5_free_config_files(char **filenames)
{
char **p;
- for(p = filenames; *p != NULL; p++)
+ for(p = filenames; p && *p != NULL; p++)
free(*p);
free(filenames);
}
@@ -1226,3 +1225,115 @@ krb5_set_max_time_skew (krb5_context context, time_t t)
{
context->max_skew = t;
}
+
+/**
+ * Init encryption types in len, val with etypes.
+ *
+ * @param context Kerberos 5 context.
+ * @param len output length of val.
+ * @param val output array of enctypes.
+ * @param etypes etypes to set val and len to, if NULL, use default enctypes.
+
+ * @return Returns 0 to indicate success. Otherwise an kerberos et
+ * error code is returned, see krb5_get_error_message().
+ *
+ * @ingroup krb5
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_etype (krb5_context context,
+ unsigned *len,
+ krb5_enctype **val,
+ const krb5_enctype *etypes)
+{
+ unsigned int i;
+ krb5_error_code ret;
+ krb5_enctype *tmp = NULL;
+
+ ret = 0;
+ if (etypes == NULL) {
+ ret = krb5_get_default_in_tkt_etypes(context, &tmp);
+ if (ret)
+ return ret;
+ etypes = tmp;
+ }
+
+ for (i = 0; etypes[i]; ++i)
+ ;
+ *len = i;
+ *val = malloc(i * sizeof(**val));
+ if (i != 0 && *val == NULL) {
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto cleanup;
+ }
+ memmove (*val,
+ etypes,
+ i * sizeof(*tmp));
+cleanup:
+ if (tmp != NULL)
+ free (tmp);
+ return ret;
+}
+
+/*
+ * Allow homedir accces
+ */
+
+static HEIMDAL_MUTEX homedir_mutex = HEIMDAL_MUTEX_INITIALIZER;
+static krb5_boolean allow_homedir = TRUE;
+
+krb5_boolean
+_krb5_homedir_access(krb5_context context)
+{
+ krb5_boolean allow;
+
+ /* is never allowed for root */
+ if (geteuid() == 0)
+ return FALSE;
+
+ if (context && (context->flags & KRB5_CTX_F_HOMEDIR_ACCESS) == 0)
+ return FALSE;
+
+ HEIMDAL_MUTEX_lock(&homedir_mutex);
+ allow = allow_homedir;
+ HEIMDAL_MUTEX_unlock(&homedir_mutex);
+ return allow;
+}
+
+/**
+ * Enable and disable home directory access on either the global state
+ * or the krb5_context state. By calling krb5_set_home_dir_access()
+ * with context set to NULL, the global state is configured otherwise
+ * the state for the krb5_context is modified.
+ *
+ * For home directory access to be allowed, both the global state and
+ * the krb5_context state have to be allowed.
+ *
+ * Administrator (root user), never uses the home directory.
+ *
+ * @param context a Kerberos 5 context or NULL
+ * @param allow allow if TRUE home directory
+ * @return the old value
+ *
+ */
+
+krb5_boolean
+krb5_set_home_dir_access(krb5_context context, krb5_boolean allow)
+{
+ krb5_boolean old;
+ if (context) {
+ old = (context->flags & KRB5_CTX_F_HOMEDIR_ACCESS) ? TRUE : FALSE;
+ if (allow)
+ context->flags |= KRB5_CTX_F_HOMEDIR_ACCESS;
+ else
+ context->flags &= ~KRB5_CTX_F_HOMEDIR_ACCESS;
+ } else {
+ HEIMDAL_MUTEX_lock(&homedir_mutex);
+ old = allow_homedir;
+ allow_homedir = allow;
+ HEIMDAL_MUTEX_unlock(&homedir_mutex);
+ }
+
+ return old;
+}
diff --git a/source4/heimdal/lib/krb5/convert_creds.c b/source4/heimdal/lib/krb5/convert_creds.c
index fc81d96bec..35454bf983 100644
--- a/source4/heimdal/lib/krb5/convert_creds.c
+++ b/source4/heimdal/lib/krb5/convert_creds.c
@@ -32,10 +32,10 @@
*/
#include "krb5_locl.h"
-RCSID("$Id$");
-
#include "krb5-v4compat.h"
+#ifndef HEIMDAL_SMALLER
+
static krb5_error_code
check_ticket_flags(TicketFlags f)
{
@@ -204,3 +204,5 @@ krb524_convert_creds_kdc_ccache(krb5_context context,
krb5_free_creds (context, v5_creds);
return ret;
}
+
+#endif
diff --git a/source4/heimdal/lib/krb5/copy_host_realm.c b/source4/heimdal/lib/krb5/copy_host_realm.c
index 37e27110b6..7f19ddd3de 100644
--- a/source4/heimdal/lib/krb5/copy_host_realm.c
+++ b/source4/heimdal/lib/krb5/copy_host_realm.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/**
* Copy the list of realms from `from' to `to'.
*
diff --git a/source4/heimdal/lib/krb5/crc.c b/source4/heimdal/lib/krb5/crc.c
index a900cabbba..eab946541d 100644
--- a/source4/heimdal/lib/krb5/crc.c
+++ b/source4/heimdal/lib/krb5/crc.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
static u_long table[256];
#define CRC_GEN 0xEDB88320L
diff --git a/source4/heimdal/lib/krb5/creds.c b/source4/heimdal/lib/krb5/creds.c
index 087a4850eb..26c0dfbecb 100644
--- a/source4/heimdal/lib/krb5/creds.c
+++ b/source4/heimdal/lib/krb5/creds.c
@@ -33,23 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
-#undef __attribute__
-#define __attribute__(X)
-
-#ifndef HEIMDAL_SMALLER
-
-/* keep this for compatibility with older code */
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_free_creds_contents (krb5_context context, krb5_creds *c)
- __attribute__((deprecated))
-{
- return krb5_free_cred_contents (context, c);
-}
-
-#endif /* HEIMDAL_SMALLER */
-
/**
* Free content of krb5_creds.
*
@@ -235,9 +218,7 @@ krb5_compare_creds(krb5_context context, krb5_flags whichfields,
}
if (match && (whichfields & KRB5_TC_MATCH_KEYTYPE))
- match = krb5_enctypes_compatible_keys(context,
- mcreds->session.keytype,
- creds->session.keytype);
+ match = mcreds->session.keytype == creds->session.keytype;
if (match && (whichfields & KRB5_TC_MATCH_FLAGS_EXACT))
match = mcreds->flags.i == creds->flags.i;
diff --git a/source4/heimdal/lib/krb5/crypto.c b/source4/heimdal/lib/krb5/crypto.c
index bc6512cf1a..9fd2117345 100644
--- a/source4/heimdal/lib/krb5/crypto.c
+++ b/source4/heimdal/lib/krb5/crypto.c
@@ -31,13 +31,11 @@
* SUCH DAMAGE.
*/
+#define KRB5_DEPRECATED
+
#include "krb5_locl.h"
-RCSID("$Id$");
#include <pkinit_asn1.h>
-#undef __attribute__
-#define __attribute__(X)
-
#define WEAK_ENCTYPES 1
#ifndef HEIMDAL_SMALLER
@@ -164,6 +162,9 @@ static krb5_error_code hmac(krb5_context context,
static void free_key_data(krb5_context,
struct key_data *,
struct encryption_type *);
+static void free_key_schedule(krb5_context,
+ struct key_data *,
+ struct encryption_type *);
static krb5_error_code usage2arcfour (krb5_context, unsigned *);
static void xor (DES_cblock *, const unsigned char *);
@@ -1158,7 +1159,16 @@ _key_schedule(krb5_context context,
{
krb5_error_code ret;
struct encryption_type *et = _find_enctype(key->key->keytype);
- struct key_type *kt = et->keytype;
+ struct key_type *kt;
+
+ if (et == NULL) {
+ krb5_set_error_message (context, KRB5_PROG_ETYPE_NOSUPP,
+ N_("encryption type %d not supported", ""),
+ key->key->keytype);
+ return KRB5_PROG_ETYPE_NOSUPP;
+ }
+
+ kt = et->keytype;
if(kt->schedule == NULL)
return 0;
@@ -1841,14 +1851,25 @@ verify_checksum(krb5_context context,
return KRB5KRB_AP_ERR_BAD_INTEGRITY; /* XXX */
}
keyed_checksum = (ct->flags & F_KEYED) != 0;
- if(keyed_checksum && crypto == NULL) {
- krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
- N_("Checksum type %s is keyed but no "
- "crypto context (key) was passed in", ""),
- ct->name);
- return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
- }
if(keyed_checksum) {
+ struct checksum_type *kct;
+ if (crypto == NULL) {
+ krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
+ N_("Checksum type %s is keyed but no "
+ "crypto context (key) was passed in", ""),
+ ct->name);
+ return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
+ }
+ kct = crypto->et->keyed_checksum;
+ if (kct != NULL && kct->type != ct->type) {
+ krb5_set_error_message (context, KRB5_PROG_SUMTYPE_NOSUPP,
+ N_("Checksum type %s is keyed, but "
+ "the key type %s passed didnt have that checksum "
+ "type as the keyed type", ""),
+ ct->name, crypto->et->name);
+ return KRB5_PROG_SUMTYPE_NOSUPP; /* XXX */
+ }
+
ret = get_checksum_key(context, crypto, usage, ct, &dkey);
if (ret)
return ret;
@@ -2348,10 +2369,11 @@ AES_PRF(krb5_context context,
{
const EVP_CIPHER *c = (*crypto->et->keytype->evp)();
EVP_CIPHER_CTX ctx;
- /* XXX blksz 1 for cts, so we can't use that */
+
EVP_CIPHER_CTX_init(&ctx); /* ivec all zero */
EVP_CipherInit_ex(&ctx, c, NULL, derived->keyvalue.data, NULL, 1);
- EVP_Cipher(&ctx, out->data, result.checksum.data, 16);
+ EVP_Cipher(&ctx, out->data, result.checksum.data,
+ crypto->et->blocksize);
EVP_CIPHER_CTX_cleanup(&ctx);
}
@@ -2737,17 +2759,6 @@ krb5_cksumtype_valid(krb5_context context,
}
-/* if two enctypes have compatible keys */
-krb5_boolean KRB5_LIB_FUNCTION
-krb5_enctypes_compatible_keys(krb5_context context,
- krb5_enctype etype1,
- krb5_enctype etype2)
-{
- struct encryption_type *e1 = _find_enctype(etype1);
- struct encryption_type *e2 = _find_enctype(etype2);
- return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
-}
-
static krb5_boolean
derived_crypto(krb5_context context,
krb5_crypto crypto)
@@ -3147,10 +3158,10 @@ find_iv(krb5_crypto_iov *data, int num_data, int type)
* Kerberos encrypted data look like this:
*
* 1. KRB5_CRYPTO_TYPE_HEADER
- * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
- * any order, however the receiver have to aware of the
- * order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used headers and
- * trailers.
+ * 2. array [1,...] KRB5_CRYPTO_TYPE_DATA and array [0,...]
+ * KRB5_CRYPTO_TYPE_SIGN_ONLY in any order, however the receiver
+ * have to aware of the order. KRB5_CRYPTO_TYPE_SIGN_ONLY is
+ * commonly used headers and trailers.
* 3. KRB5_CRYPTO_TYPE_PADDING, at least on padsize long if padsize > 1
* 4. KRB5_CRYPTO_TYPE_TRAILER
*/
@@ -3160,17 +3171,23 @@ krb5_encrypt_iov_ivec(krb5_context context,
krb5_crypto crypto,
unsigned usage,
krb5_crypto_iov *data,
- size_t num_data,
+ int num_data,
void *ivec)
{
size_t headersz, trailersz, len;
- size_t i, sz, block_sz, pad_sz;
+ int i;
+ size_t sz, block_sz, pad_sz;
Checksum cksum;
unsigned char *p, *q;
krb5_error_code ret;
struct key_data *dkey;
const struct encryption_type *et = crypto->et;
- krb5_crypto_iov *tiv, *piv, *hiv;
+ krb5_crypto_iov *tiv, *piv, *hiv, *div;
+
+ if (num_data < 0) {
+ krb5_clear_error_message(context);
+ return KRB5_CRYPTO_INTERNAL;
+ }
if(!derived_crypto(context, crypto)) {
krb5_clear_error_message(context);
@@ -3180,18 +3197,16 @@ krb5_encrypt_iov_ivec(krb5_context context,
headersz = et->confoundersize;
trailersz = CHECKSUMSIZE(et->keyed_checksum);
- for (len = 0, i = 0; i < num_data; i++) {
- if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER &&
- data[i].flags == KRB5_CRYPTO_TYPE_DATA) {
- len += data[i].data.length;
- }
- }
+ div = find_iv(data, num_data, KRB5_CRYPTO_TYPE_DATA);
+ if (div == NULL)
+ return KRB5_CRYPTO_INTERNAL;
+
+ len = div->data.length;
sz = headersz + len;
block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
pad_sz = block_sz - sz;
- trailersz += pad_sz;
/* header */
@@ -3278,13 +3293,9 @@ krb5_encrypt_iov_ivec(krb5_context context,
/* XXX replace with EVP_Cipher */
- len = hiv->data.length;
- for (i = 0; i < num_data; i++) {
- if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
- data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
- continue;
- len += data[i].data.length;
- }
+ len = hiv->data.length + div->data.length;
+ if (piv)
+ len += piv->data.length;
p = q = malloc(len);
if(p == NULL)
@@ -3292,13 +3303,9 @@ krb5_encrypt_iov_ivec(krb5_context context,
memcpy(q, hiv->data.data, hiv->data.length);
q += hiv->data.length;
- for (i = 0; i < num_data; i++) {
- if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
- data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
- continue;
- memcpy(q, data[i].data.data, data[i].data.length);
- q += data[i].data.length;
- }
+ memcpy(q, div->data.data, div->data.length);
+ q += div->data.length;
+ memset(q, 0, pad_sz);
ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
if(ret) {
@@ -3319,16 +3326,15 @@ krb5_encrypt_iov_ivec(krb5_context context,
/* now copy data back to buffers */
q = p;
+
memcpy(hiv->data.data, q, hiv->data.length);
q += hiv->data.length;
- for (i = 0; i < num_data; i++) {
- if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
- data[i].flags != KRB5_CRYPTO_TYPE_PADDING)
- continue;
- memcpy(data[i].data.data, q, data[i].data.length);
- q += data[i].data.length;
- }
+ memcpy(div->data.data, q, div->data.length);
+ q += div->data.length;
+
+ if (piv)
+ memcpy(piv->data.data, q, pad_sz);
free(p);
return ret;
@@ -3348,7 +3354,7 @@ krb5_encrypt_iov_ivec(krb5_context context,
* @ingroup krb5_crypto
*
* 1. KRB5_CRYPTO_TYPE_HEADER
- * 2. array KRB5_CRYPTO_TYPE_DATA and KRB5_CRYPTO_TYPE_SIGN_ONLY in
+ * 2. one KRB5_CRYPTO_TYPE_DATA and array [0,...] of KRB5_CRYPTO_TYPE_SIGN_ONLY in
* any order, however the receiver have to aware of the
* order. KRB5_CRYPTO_TYPE_SIGN_ONLY is commonly used unencrypoted
* protocol headers and trailers. The output data will be of same
@@ -3360,17 +3366,23 @@ krb5_decrypt_iov_ivec(krb5_context context,
krb5_crypto crypto,
unsigned usage,
krb5_crypto_iov *data,
- size_t num_data,
+ unsigned int num_data,
void *ivec)
{
+ unsigned int i;
size_t headersz, trailersz, len;
- size_t i, sz, block_sz, pad_sz;
+ size_t sz, block_sz, pad_sz;
Checksum cksum;
unsigned char *p, *q;
krb5_error_code ret;
struct key_data *dkey;
struct encryption_type *et = crypto->et;
- krb5_crypto_iov *tiv, *hiv;
+ krb5_crypto_iov *tiv, *hiv, *div;
+
+ if (num_data < 0) {
+ krb5_clear_error_message(context);
+ return KRB5_CRYPTO_INTERNAL;
+ }
if(!derived_crypto(context, crypto)) {
krb5_clear_error_message(context);
@@ -3380,9 +3392,13 @@ krb5_decrypt_iov_ivec(krb5_context context,
headersz = et->confoundersize;
trailersz = CHECKSUMSIZE(et->keyed_checksum);
- for (len = 0, i = 0; i < num_data; i++)
- if (data[i].flags == KRB5_CRYPTO_TYPE_DATA)
+ for (len = 0, i = 0; i < num_data; i++) {
+ if (data[i].flags == KRB5_CRYPTO_TYPE_DATA) {
+ if (len != 0)
+ return KRB5_CRYPTO_INTERNAL;
len += data[i].data.length;
+ }
+ }
sz = headersz + len;
block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
@@ -3404,7 +3420,9 @@ krb5_decrypt_iov_ivec(krb5_context context,
return KRB5_BAD_MSIZE;
tiv->data.length = trailersz;
- /* body */
+ div = find_iv(data, num_data, KRB5_CRYPTO_TYPE_DATA);
+ if (div == NULL)
+ return KRB5_CRYPTO_INTERNAL;
/* XXX replace with EVP_Cipher */
@@ -3421,12 +3439,7 @@ krb5_decrypt_iov_ivec(krb5_context context,
memcpy(q, hiv->data.data, hiv->data.length);
q += hiv->data.length;
- for (i = 0; i < num_data; i++) {
- if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
- continue;
- memcpy(q, data[i].data.data, data[i].data.length);
- q += data[i].data.length;
- }
+ memcpy(q, div->data.data, div->data.length);
ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
if(ret) {
@@ -3445,24 +3458,12 @@ krb5_decrypt_iov_ivec(krb5_context context,
return ret;
}
- /* XXX now copy data back to buffers */
- q = p;
- memcpy(hiv->data.data, q, hiv->data.length);
- q += hiv->data.length;
- len -= hiv->data.length;
-
- for (i = 0; i < num_data; i++) {
- if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
- continue;
- if (len < data[i].data.length)
- data[i].data.length = len;
- memcpy(data[i].data.data, q, data[i].data.length);
- q += data[i].data.length;
- len -= data[i].data.length;
- }
+ /* copy data back to buffers */
+ memcpy(hiv->data.data, p, hiv->data.length);
+ memcpy(div->data.data, p + hiv->data.length, len - hiv->data.length);
free(p);
- if (len)
- krb5_abortx(context, "data still in the buffer");
+
+ /* check signature */
len = hiv->data.length;
for (i = 0; i < num_data; i++) {
@@ -3506,7 +3507,7 @@ krb5_decrypt_iov_ivec(krb5_context context,
* @param usage Key usage for this buffer
* @param data array of buffers to process
* @param num_data length of array
- * @param result output data
+ * @param type output data
*
* @return Return an error code or 0.
* @ingroup krb5_crypto
@@ -3517,16 +3518,21 @@ krb5_create_checksum_iov(krb5_context context,
krb5_crypto crypto,
unsigned usage,
krb5_crypto_iov *data,
- size_t num_data,
+ unsigned int num_data,
krb5_cksumtype *type)
{
Checksum cksum;
krb5_crypto_iov *civ;
krb5_error_code ret;
- unsigned int i;
+ int i;
size_t len;
char *p, *q;
+ if (num_data < 0) {
+ krb5_clear_error_message(context);
+ return KRB5_CRYPTO_INTERNAL;
+ }
+
if(!derived_crypto(context, crypto)) {
krb5_clear_error_message(context);
return KRB5_CRYPTO_INTERNAL;
@@ -3765,18 +3771,6 @@ krb5_generate_random_block(void *buf, size_t len)
krb5_abortx(NULL, "Failed to generate random block");
}
-static void
-DES3_postproc(krb5_context context,
- unsigned char *k, size_t len, struct key_data *key)
-{
- DES3_random_to_key(context, key->key, k, len);
-
- if (key->schedule) {
- krb5_free_data(context, key->schedule);
- key->schedule = NULL;
- }
-}
-
static krb5_error_code
derive_key(krb5_context context,
struct encryption_type *et,
@@ -3784,7 +3778,7 @@ derive_key(krb5_context context,
const void *constant,
size_t len)
{
- unsigned char *k;
+ unsigned char *k = NULL;
unsigned int nblocks = 0, i;
krb5_error_code ret = 0;
struct key_type *kt = et->keytype;
@@ -3796,15 +3790,16 @@ derive_key(krb5_context context,
nblocks = (kt->bits + et->blocksize * 8 - 1) / (et->blocksize * 8);
k = malloc(nblocks * et->blocksize);
if(k == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
}
ret = _krb5_n_fold(constant, len, k, et->blocksize);
if (ret) {
- free(k);
krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- return ret;
+ goto out;
}
+
for(i = 0; i < nblocks; i++) {
if(i > 0)
memcpy(k + i * et->blocksize,
@@ -3819,30 +3814,31 @@ derive_key(krb5_context context,
size_t res_len = (kt->bits + 7) / 8;
if(len != 0 && c == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
}
memcpy(c, constant, len);
(*et->encrypt)(context, key, c, len, 1, 0, NULL);
k = malloc(res_len);
if(res_len != 0 && k == NULL) {
free(c);
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
}
ret = _krb5_n_fold(c, len, k, res_len);
+ free(c);
if (ret) {
- free(k);
krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- return ret;
+ goto out;
}
- free(c);
}
/* XXX keytype dependent post-processing */
switch(kt->type) {
case KEYTYPE_DES3:
- DES3_postproc(context, k, nblocks * et->blocksize, key);
+ DES3_random_to_key(context, key->key, k, nblocks * et->blocksize);
break;
case KEYTYPE_AES128:
case KEYTYPE_AES256:
@@ -3855,12 +3851,15 @@ derive_key(krb5_context context,
kt->type);
break;
}
+ out:
if (key->schedule) {
- krb5_free_data(context, key->schedule);
+ free_key_schedule(context, key, et);
key->schedule = NULL;
}
- memset(k, 0, nblocks * et->blocksize);
- free(k);
+ if (k) {
+ memset(k, 0, nblocks * et->blocksize);
+ free(k);
+ }
return ret;
}
@@ -3983,15 +3982,24 @@ krb5_crypto_init(krb5_context context,
}
static void
+free_key_schedule(krb5_context context,
+ struct key_data *key,
+ struct encryption_type *et)
+{
+ if (et->keytype->cleanup)
+ (*et->keytype->cleanup)(context, key);
+ memset(key->schedule->data, 0, key->schedule->length);
+ krb5_free_data(context, key->schedule);
+}
+
+static void
free_key_data(krb5_context context, struct key_data *key,
struct encryption_type *et)
{
krb5_free_keyblock(context, key->key);
if(key->schedule) {
- if (et->keytype->cleanup)
- (*et->keytype->cleanup)(context, key);
- memset(key->schedule->data, 0, key->schedule->length);
- krb5_free_data(context, key->schedule);
+ free_key_schedule(context, key, et);
+ key->schedule = NULL;
}
}
@@ -4154,7 +4162,7 @@ krb5_string_to_key_derived(krb5_context context,
return ret;
}
kd.schedule = NULL;
- DES3_postproc (context, tmp, keylen, &kd); /* XXX */
+ DES3_random_to_key(context, kd.key, tmp, keylen);
memset(tmp, 0, keylen);
free(tmp);
ret = derive_key(context,
@@ -4263,6 +4271,23 @@ krb5_crypto_overhead (krb5_context context, krb5_crypto crypto)
return crypto_overhead (context, crypto);
}
+/**
+ * Converts the random bytestring to a protocol key according to
+ * Kerberos crypto frame work. It may be assumed that all the bits of
+ * the input string are equally random, even though the entropy
+ * present in the random source may be limited.
+ *
+ * @param context Kerberos 5 context
+ * @param type the enctype resulting key will be of
+ * @param data input random data to convert to a key
+ * @param data size of input random data, at least krb5_enctype_keysize() long
+ * @param data key, output key, free with krb5_free_keyblock_contents()
+ *
+ * @return Return an error code or 0.
+ *
+ * @ingroup krb5_crypto
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_random_to_key(krb5_context context,
krb5_enctype type,
@@ -4312,7 +4337,7 @@ _krb5_pk_octetstring2key(krb5_context context,
size_t keylen, offset;
void *keydata;
unsigned char counter;
- unsigned char shaoutput[20];
+ unsigned char shaoutput[SHA_DIGEST_LENGTH];
if(et == NULL) {
krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
@@ -4463,9 +4488,9 @@ _krb5_pk_kdf(krb5_context context,
size_t keylen, offset;
uint32_t counter;
unsigned char *keydata;
- unsigned char shaoutput[20];
+ unsigned char shaoutput[SHA_DIGEST_LENGTH];
- if (der_heim_oid_cmp(oid_id_pkinit_kdf_ah_sha1(), &ai->algorithm) != 0) {
+ if (der_heim_oid_cmp(&asn1_oid_id_pkinit_kdf_ah_sha1, &ai->algorithm) != 0) {
krb5_set_error_message(context, KRB5_PROG_ETYPE_NOSUPP,
N_("KDF not supported", ""));
return KRB5_PROG_ETYPE_NOSUPP;
@@ -4572,118 +4597,131 @@ krb5_crypto_prf(krb5_context context,
return (*et->prf)(context, crypto, input, output);
}
-#ifndef HEIMDAL_SMALLER
+static krb5_error_code
+krb5_crypto_prfplus(krb5_context context,
+ const krb5_crypto crypto,
+ const krb5_data *input,
+ size_t length,
+ krb5_data *output)
+{
+ krb5_error_code ret;
+ krb5_data input2;
+ unsigned char i = 1;
+ unsigned char *p;
-static struct key_type *keytypes[] = {
- &keytype_null,
- &keytype_des,
- &keytype_des3_derived,
-#ifdef DES3_OLD_ENCTYPE
- &keytype_des3,
-#endif
- &keytype_aes128,
- &keytype_aes256,
- &keytype_arcfour
-};
+ krb5_data_zero(&input2);
+ krb5_data_zero(output);
-static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
+ krb5_clear_error_message(context);
+ ret = krb5_data_alloc(output, length);
+ if (ret) goto out;
+ ret = krb5_data_alloc(&input2, input->length + 1);
+ if (ret) goto out;
-static struct key_type *
-_find_keytype(krb5_keytype type)
-{
- int i;
- for(i = 0; i < num_keytypes; i++)
- if(keytypes[i]->type == type)
- return keytypes[i];
- return NULL;
-}
+ krb5_clear_error_message(context);
-/*
- * First take the configured list of etypes for `keytype' if available,
- * else, do `krb5_keytype_to_enctypes'.
- */
+ memcpy(((unsigned char *)input2.data) + 1, input->data, input->length);
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_keytype_to_enctypes_default (krb5_context context,
- krb5_keytype keytype,
- unsigned *len,
- krb5_enctype **val)
- __attribute__((deprecated))
-{
- unsigned int i, n;
- krb5_enctype *ret;
+ p = output->data;
- if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
- return krb5_keytype_to_enctypes (context, keytype, len, val);
+ while (length) {
+ krb5_data block;
- for (n = 0; context->etypes_des[n]; ++n)
- ;
- ret = malloc (n * sizeof(*ret));
- if (ret == NULL && n != 0) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
- }
- for (i = 0; i < n; ++i)
- ret[i] = context->etypes_des[i];
- *len = n;
- *val = ret;
- return 0;
-}
+ ((unsigned char *)input2.data)[0] = i++;
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_keytype_to_string(krb5_context context,
- krb5_keytype keytype,
- char **string)
- __attribute__((deprecated))
-{
- struct key_type *kt = _find_keytype(keytype);
- if(kt == NULL) {
- krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
- "key type %d not supported", keytype);
- return KRB5_PROG_KEYTYPE_NOSUPP;
- }
- *string = strdup(kt->name);
- if(*string == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ ret = krb5_crypto_prf(context, crypto, &input2, &block);
+ if (ret)
+ goto out;
+
+ if (block.length < length) {
+ memcpy(p, block.data, block.length);
+ length -= block.length;
+ } else {
+ memcpy(p, block.data, length);
+ length = 0;
+ }
+ p += block.length;
+ krb5_data_free(&block);
}
+
+ out:
+ krb5_data_free(&input2);
+ if (ret)
+ krb5_data_free(output);
return 0;
}
+/**
+ * The FX-CF2 key derivation function, used in FAST and preauth framework.
+ *
+ * @param context Kerberos 5 context
+ * @param crypto1 first key to combine
+ * @param crypto2 second key to combine
+ * @param pepper1 factor to combine with first key to garante uniqueness
+ * @param pepper1 factor to combine with second key to garante uniqueness
+ * @param enctype the encryption type of the resulting key
+ * @param res allocated key, free with krb5_free_keyblock_contents()
+ *
+ * @return Return an error code or 0.
+ *
+ * @ingroup krb5_crypto
+ */
krb5_error_code KRB5_LIB_FUNCTION
-krb5_string_to_keytype(krb5_context context,
- const char *string,
- krb5_keytype *keytype)
- __attribute__((deprecated))
+krb5_crypto_fx_cf2(krb5_context context,
+ const krb5_crypto crypto1,
+ const krb5_crypto crypto2,
+ krb5_data *pepper1,
+ krb5_data *pepper2,
+ krb5_enctype enctype,
+ krb5_keyblock *res)
{
- char *end;
- int i;
+ krb5_error_code ret;
+ krb5_data os1, os2;
+ size_t i, keysize;
- for(i = 0; i < num_keytypes; i++)
- if(strcasecmp(keytypes[i]->name, string) == 0){
- *keytype = keytypes[i]->type;
- return 0;
- }
+ memset(res, 0, sizeof(*res));
- /* check if the enctype is a number */
- *keytype = strtol(string, &end, 0);
- if(*end == '\0' && *keytype != 0) {
- if (krb5_enctype_valid(context, *keytype) == 0)
- return 0;
+ ret = krb5_enctype_keysize(context, enctype, &keysize);
+ if (ret)
+ return ret;
+
+ ret = krb5_data_alloc(&res->keyvalue, keysize);
+ if (ret)
+ goto out;
+ ret = krb5_crypto_prfplus(context, crypto1, pepper1, keysize, &os1);
+ if (ret)
+ goto out;
+ ret = krb5_crypto_prfplus(context, crypto2, pepper2, keysize, &os2);
+ if (ret)
+ goto out;
+
+ res->keytype = enctype;
+ {
+ unsigned char *p1 = os1.data, *p2 = os2.data, *p3 = res->keyvalue.data;
+ for (i = 0; i < keysize; i++)
+ p3[i] = p1[i] ^ p2[i];
}
+ out:
+ if (ret)
+ krb5_data_free(&res->keyvalue);
+ krb5_data_free(&os1);
+ krb5_data_free(&os2);
- krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
- "key type %s not supported", string);
- return KRB5_PROG_KEYTYPE_NOSUPP;
+ return ret;
}
+
+
+#ifndef HEIMDAL_SMALLER
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_keytype_to_enctypes (krb5_context context,
krb5_keytype keytype,
unsigned *len,
krb5_enctype **val)
+ KRB5_DEPRECATED
{
int i;
unsigned n = 0;
@@ -4691,18 +4729,26 @@ krb5_keytype_to_enctypes (krb5_context context,
for (i = num_etypes - 1; i >= 0; --i) {
if (etypes[i]->keytype->type == keytype
- && !(etypes[i]->flags & F_PSEUDO))
+ && !(etypes[i]->flags & F_PSEUDO)
+ && krb5_enctype_valid(context, etypes[i]->type) == 0)
++n;
}
+ if (n == 0) {
+ krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
+ "Keytype have no mapping");
+ return KRB5_PROG_KEYTYPE_NOSUPP;
+ }
+
ret = malloc(n * sizeof(*ret));
if (ret == NULL && n != 0) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
}
n = 0;
for (i = num_etypes - 1; i >= 0; --i) {
if (etypes[i]->keytype->type == keytype
- && !(etypes[i]->flags & F_PSEUDO))
+ && !(etypes[i]->flags & F_PSEUDO)
+ && krb5_enctype_valid(context, etypes[i]->type) == 0)
ret[n++] = etypes[i]->type;
}
*len = n;
@@ -4710,4 +4756,16 @@ krb5_keytype_to_enctypes (krb5_context context,
return 0;
}
+/* if two enctypes have compatible keys */
+krb5_boolean KRB5_LIB_FUNCTION
+krb5_enctypes_compatible_keys(krb5_context context,
+ krb5_enctype etype1,
+ krb5_enctype etype2)
+ KRB5_DEPRECATED
+{
+ struct encryption_type *e1 = _find_enctype(etype1);
+ struct encryption_type *e2 = _find_enctype(etype2);
+ return e1 != NULL && e2 != NULL && e1->keytype == e2->keytype;
+}
+
#endif /* HEIMDAL_SMALLER */
diff --git a/source4/heimdal/lib/krb5/data.c b/source4/heimdal/lib/krb5/data.c
index d6099c3c6c..993d6058bf 100644
--- a/source4/heimdal/lib/krb5/data.c
+++ b/source4/heimdal/lib/krb5/data.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/**
* Reset the (potentially uninitalized) krb5_data structure.
*
@@ -52,7 +50,9 @@ krb5_data_zero(krb5_data *p)
/**
* Free the content of krb5_data structure, its ok to free a zeroed
- * structure. When done, the structure will be zeroed.
+ * structure (with memset() or krb5_data_zero()). When done, the
+ * structure will be zeroed. The same function is called
+ * krb5_free_data_contents() in MIT Kerberos.
*
* @param p krb5_data to free.
*
@@ -68,21 +68,6 @@ krb5_data_free(krb5_data *p)
}
/**
- * Same as krb5_data_free().
- *
- * @param context Kerberos 5 context.
- * @param data krb5_data to free.
- *
- * @ingroup krb5
- */
-
-void KRB5_LIB_FUNCTION
-krb5_free_data_contents(krb5_context context, krb5_data *data)
-{
- krb5_data_free(data);
-}
-
-/**
* Free krb5_data (and its content).
*
* @param context Kerberos 5 context.
diff --git a/source4/heimdal/lib/krb5/eai_to_heim_errno.c b/source4/heimdal/lib/krb5/eai_to_heim_errno.c
index 594f998e26..499150f469 100644
--- a/source4/heimdal/lib/krb5/eai_to_heim_errno.c
+++ b/source4/heimdal/lib/krb5/eai_to_heim_errno.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
/**
* Convert the getaddrinfo() error code to a Kerberos et error code.
*
diff --git a/source4/heimdal/lib/krb5/error_string.c b/source4/heimdal/lib/krb5/error_string.c
index 6374fa17ae..829c080a55 100644
--- a/source4/heimdal/lib/krb5/error_string.c
+++ b/source4/heimdal/lib/krb5/error_string.c
@@ -33,10 +33,8 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
#undef __attribute__
-#define __attribute__(X)
+#define __attribute__(x)
/**
* Clears the error message from the Kerberos 5 context.
@@ -172,6 +170,9 @@ krb5_get_error_message(krb5_context context, krb5_error_code code)
}
HEIMDAL_MUTEX_unlock(context->mutex);
+ if (code == 0)
+ return strdup("Success");
+
cstr = krb5_get_err_text(context, code);
if (cstr)
return strdup(cstr);
@@ -198,80 +199,3 @@ krb5_free_error_message(krb5_context context, const char *msg)
{
free(rk_UNCONST(msg));
}
-
-#ifndef HEIMDAL_SMALLER
-
-/**
- * Free the error message returned by krb5_get_error_string(),
- * deprecated, use krb5_free_error_message().
- *
- * @param context Kerberos context
- * @param msg error message to free
- *
- * @ingroup krb5_deprecated
- */
-
-void KRB5_LIB_FUNCTION
-krb5_free_error_string(krb5_context context, char *str)
- __attribute__((deprecated))
-{
- krb5_free_error_message(context, str);
-}
-
-/**
- * Set the error message returned by krb5_get_error_string(),
- * deprecated, use krb5_set_error_message().
- *
- * @param context Kerberos context
- * @param msg error message to free
- *
- * @ingroup krb5_deprecated
- */
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_set_error_string(krb5_context context, const char *fmt, ...)
- __attribute__((format (printf, 2, 3))) __attribute__((deprecated))
-{
- va_list ap;
-
- va_start(ap, fmt);
- krb5_vset_error_message (context, 0, fmt, ap);
- va_end(ap);
- return 0;
-}
-
-/**
- * Set the error message returned by krb5_get_error_string(),
- * deprecated, use krb5_set_error_message().
- *
- * @param context Kerberos context
- * @param msg error message to free
- *
- * @ingroup krb5_deprecated
- */
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_vset_error_string(krb5_context context, const char *fmt, va_list args)
- __attribute__ ((format (printf, 2, 0))) __attribute__((deprecated))
-{
- krb5_vset_error_message(context, 0, fmt, args);
- return 0;
-}
-
-/**
- * Clar the error message returned by krb5_get_error_string(),
- * deprecated, use krb5_clear_error_message().
- *
- * @param context Kerberos context
- *
- * @ingroup krb5_deprecated
- */
-
-void KRB5_LIB_FUNCTION
-krb5_clear_error_string(krb5_context context)
- __attribute__((deprecated))
-{
- krb5_clear_error_message(context);
-}
-
-#endif /* !HEIMDAL_SMALLER */
diff --git a/source4/heimdal/lib/krb5/expand_hostname.c b/source4/heimdal/lib/krb5/expand_hostname.c
index a712d9c83a..67988d0d7b 100644
--- a/source4/heimdal/lib/krb5/expand_hostname.c
+++ b/source4/heimdal/lib/krb5/expand_hostname.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
static krb5_error_code
copy_hostname(krb5_context context,
const char *orig_hostname,
@@ -50,9 +48,19 @@ copy_hostname(krb5_context context,
return 0;
}
-/*
- * Try to make `orig_hostname' into a more canonical one in the newly
- * allocated space returned in `new_hostname'.
+/**
+ * krb5_expand_hostname() tries to make orig_hostname into a more
+ * canonical one in the newly allocated space returned in
+ * new_hostname.
+
+ * @param context a Keberos context
+ * @param orig_hostname hostname to canonicalise.
+ * @param new_hostname output hostname, caller must free hostname with
+ * krb5_xfree().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_support
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -114,9 +122,22 @@ vanilla_hostname (krb5_context context,
return 0;
}
-/*
- * expand `hostname' to a name we believe to be a hostname in newly
- * allocated space in `host' and return realms in `realms'.
+/**
+ * krb5_expand_hostname_realms() expands orig_hostname to a name we
+ * believe to be a hostname in newly allocated space in new_hostname
+ * and return the realms new_hostname is believed to belong to in
+ * realms.
+ *
+ * @param context a Keberos context
+ * @param orig_hostname hostname to canonicalise.
+ * @param new_hostname output hostname, caller must free hostname with
+ * krb5_xfree().
+ * @param realms output possible realms, is an array that is terminated
+ * with NULL. Caller must free with krb5_free_host_realm().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_support
*/
krb5_error_code KRB5_LIB_FUNCTION
diff --git a/source4/heimdal/lib/krb5/fcache.c b/source4/heimdal/lib/krb5/fcache.c
index b745c67e11..f8e74f1ddc 100644
--- a/source4/heimdal/lib/krb5/fcache.c
+++ b/source4/heimdal/lib/krb5/fcache.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
typedef struct krb5_fcache{
char *filename;
int version;
@@ -233,8 +231,8 @@ scrub_file (int fd)
* hardlink)
*/
-static krb5_error_code
-erase_file(krb5_context context, const char *filename)
+krb5_error_code
+_krb5_erase_file(krb5_context context, const char *filename)
{
int fd;
struct stat sb1, sb2;
@@ -453,7 +451,7 @@ static krb5_error_code
fcc_destroy(krb5_context context,
krb5_ccache id)
{
- erase_file(context, FILENAME(id));
+ _krb5_erase_file(context, FILENAME(id));
return 0;
}
@@ -740,8 +738,10 @@ fcc_remove_cred(krb5_context context,
{
krb5_error_code ret;
krb5_ccache copy, newfile;
+ char *newname;
+ int fd;
- ret = krb5_cc_gen_new(context, &krb5_mcc_ops, &copy);
+ ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &copy);
if (ret)
return ret;
@@ -757,8 +757,24 @@ fcc_remove_cred(krb5_context context,
return ret;
}
- ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &newfile);
+ asprintf(&newname, "FILE:%s.XXXXXX", FILENAME(id));
+ if (newname == NULL) {
+ krb5_cc_destroy(context, copy);
+ return ret;
+ }
+
+ fd = mkstemp(&newname[5]);
+ if (fd < 0) {
+ ret = errno;
+ krb5_cc_destroy(context, copy);
+ return ret;
+ }
+ close(fd);
+
+ ret = krb5_cc_resolve(context, newname, &newfile);
if (ret) {
+ unlink(&newname[5]);
+ free(newname);
krb5_cc_destroy(context, copy);
return ret;
}
@@ -766,11 +782,18 @@ fcc_remove_cred(krb5_context context,
ret = krb5_cc_copy_cache(context, copy, newfile);
krb5_cc_destroy(context, copy);
if (ret) {
+ free(newname);
krb5_cc_destroy(context, newfile);
return ret;
}
- return krb5_cc_move(context, newfile, id);
+ ret = rename(&newname[5], FILENAME(id));
+ if (ret)
+ ret = errno;
+ free(newname);
+ krb5_cc_close(context, newfile);
+
+ return ret;
}
static krb5_error_code
@@ -822,12 +845,13 @@ fcc_get_cache_next(krb5_context context, krb5_cc_cursor cursor, krb5_ccache *id)
iter->first = 0;
fn = krb5_cc_default_name(context);
- if (strncasecmp(fn, "FILE:", 5) != 0) {
+ if (fn == NULL || strncasecmp(fn, "FILE:", 5) != 0) {
ret = _krb5_expand_default_cc_name(context,
KRB5_DEFAULT_CCNAME_FILE,
&expandedfn);
if (ret)
return ret;
+ fn = expandedfn;
}
ret = krb5_cc_resolve(context, fn, id);
if (expandedfn)
@@ -900,10 +924,10 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
fcc_unlock(context, fd1);
close(fd1);
- erase_file(context, FILENAME(from));
+ _krb5_erase_file(context, FILENAME(from));
if (ret) {
- erase_file(context, FILENAME(to));
+ _krb5_erase_file(context, FILENAME(to));
return ret;
}
}
@@ -913,10 +937,14 @@ fcc_move(krb5_context context, krb5_ccache from, krb5_ccache to)
krb5_storage *sp;
int fd;
ret = init_fcc (context, to, &sp, &fd);
- krb5_storage_free(sp);
+ if (sp)
+ krb5_storage_free(sp);
fcc_unlock(context, fd);
close(fd);
}
+
+ fcc_destroy(context, from);
+
return ret;
}
diff --git a/source4/heimdal/lib/krb5/free.c b/source4/heimdal/lib/krb5/free.c
index da1eb1de1c..7f4374374b 100644
--- a/source4/heimdal/lib/krb5/free.c
+++ b/source4/heimdal/lib/krb5/free.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_free_kdc_rep(krb5_context context, krb5_kdc_rep *rep)
{
diff --git a/source4/heimdal/lib/krb5/free_host_realm.c b/source4/heimdal/lib/krb5/free_host_realm.c
index 581b61a15b..f6e9f6e247 100644
--- a/source4/heimdal/lib/krb5/free_host_realm.c
+++ b/source4/heimdal/lib/krb5/free_host_realm.c
@@ -33,10 +33,15 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
-/*
+/**
* Free all memory allocated by `realmlist'
+ *
+ * @param context A Kerberos 5 context.
+ * @param realmlist realmlist to free, NULL is ok
+ *
+ * @return a Kerberos error code, always 0.
+ *
+ * @ingroup krb5_support
*/
krb5_error_code KRB5_LIB_FUNCTION
diff --git a/source4/heimdal/lib/krb5/generate_seq_number.c b/source4/heimdal/lib/krb5/generate_seq_number.c
index 99745b8305..2764f1a914 100644
--- a/source4/heimdal/lib/krb5/generate_seq_number.c
+++ b/source4/heimdal/lib/krb5/generate_seq_number.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_generate_seq_number(krb5_context context,
const krb5_keyblock *key,
diff --git a/source4/heimdal/lib/krb5/generate_subkey.c b/source4/heimdal/lib/krb5/generate_subkey.c
index 4ab4b9bf6c..efb6cce288 100644
--- a/source4/heimdal/lib/krb5/generate_subkey.c
+++ b/source4/heimdal/lib/krb5/generate_subkey.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_generate_subkey(krb5_context context,
const krb5_keyblock *key,
diff --git a/source4/heimdal/lib/krb5/get_addrs.c b/source4/heimdal/lib/krb5/get_addrs.c
index ce16785319..8f366fa148 100644
--- a/source4/heimdal/lib/krb5/get_addrs.c
+++ b/source4/heimdal/lib/krb5/get_addrs.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id: get_addrs.c 23815 2008-09-13 09:21:03Z lha $");
-
#ifdef __osf__
/* hate */
struct rtentry;
@@ -43,9 +41,7 @@ struct mbuf;
#ifdef HAVE_NET_IF_H
#include <net/if.h>
#endif
-#ifdef HAVE_IFADDR_H
#include <ifaddrs.h>
-#endif
static krb5_error_code
gethostname_fallback (krb5_context context, krb5_addresses *res)
@@ -106,8 +102,6 @@ find_all_addresses (krb5_context context, krb5_addresses *res, int flags)
unsigned int num, idx;
krb5_addresses ignore_addresses;
- res->val = NULL;
-
if (getifaddrs(&ifa0) == -1) {
ret = errno;
krb5_set_error_message(context, ret, "getifaddrs: %s", strerror(ret));
@@ -232,13 +226,14 @@ get_addrs_int (krb5_context context, krb5_addresses *res, int flags)
{
krb5_error_code ret = -1;
+ res->len = 0;
+ res->val = NULL;
+
if (flags & SCAN_INTERFACES) {
ret = find_all_addresses (context, res, flags);
if(ret || res->len == 0)
ret = gethostname_fallback (context, res);
} else {
- res->len = 0;
- res->val = NULL;
ret = 0;
}
diff --git a/source4/heimdal/lib/krb5/get_cred.c b/source4/heimdal/lib/krb5/get_cred.c
index 97e0022ee1..e609bcadcc 100644
--- a/source4/heimdal/lib/krb5/get_cred.c
+++ b/source4/heimdal/lib/krb5/get_cred.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
/*
* Take the `body' and encode it into `padata' using the credentials
* in `creds'.
@@ -375,17 +373,18 @@ decrypt_tkt_with_subkey (krb5_context context,
if (ret)
return ret;
- ret = krb5_decode_EncASRepPart(context,
- data.data,
+ ret = decode_EncASRepPart(data.data,
+ data.length,
+ &dec_rep->enc_part,
+ &size);
+ if (ret)
+ ret = decode_EncTGSRepPart(data.data,
data.length,
&dec_rep->enc_part,
&size);
if (ret)
- ret = krb5_decode_EncTGSRepPart(context,
- data.data,
- data.length,
- &dec_rep->enc_part,
- &size);
+ krb5_set_error_message(context, ret,
+ N_("Failed to decode encpart in ticket", ""));
krb5_data_free (&data);
return ret;
}
@@ -477,7 +476,7 @@ get_cred_kdc(krb5_context context,
if (len != size)
krb5_abortx(context, "internal asn1 error");
- ret = krb5_padata_add(context, &padata, KRB5_PADATA_S4U2SELF, buf, len);
+ ret = krb5_padata_add(context, &padata, KRB5_PADATA_FOR_USER, buf, len);
if (ret)
goto out;
}
@@ -561,7 +560,7 @@ get_cred_kdc(krb5_context context,
} else if(krb5_rd_error(context, &resp, &error) == 0) {
ret = krb5_error_from_rd_error(context, &error, in_creds);
krb5_free_error_contents(context, &error);
- } else if(resp.data && ((char*)resp.data)[0] == 4) {
+ } else if(resp.length > 0 && ((char*)resp.data)[0] == 4) {
ret = KRB5KRB_AP_ERR_V4_REPLY;
krb5_clear_error_message(context);
} else {
@@ -1217,6 +1216,10 @@ krb5_get_creds_opt_free(krb5_context context, krb5_get_creds_opt opt)
{
if (opt->self)
krb5_free_principal(context, opt->self);
+ if (opt->ticket) {
+ free_Ticket(opt->ticket);
+ free(opt->ticket);
+ }
memset(opt, 0, sizeof(*opt));
free(opt);
}
diff --git a/source4/heimdal/lib/krb5/get_default_principal.c b/source4/heimdal/lib/krb5/get_default_principal.c
index c804ab9e56..82d0642934 100644
--- a/source4/heimdal/lib/krb5/get_default_principal.c
+++ b/source4/heimdal/lib/krb5/get_default_principal.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/*
* Try to find out what's a reasonable default principal.
*/
diff --git a/source4/heimdal/lib/krb5/get_default_realm.c b/source4/heimdal/lib/krb5/get_default_realm.c
index a2518bbab7..f09df264c1 100644
--- a/source4/heimdal/lib/krb5/get_default_realm.c
+++ b/source4/heimdal/lib/krb5/get_default_realm.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/*
* Return a NULL-terminated list of default realms in `realms'.
* Free this memory with krb5_free_host_realm.
diff --git a/source4/heimdal/lib/krb5/get_for_creds.c b/source4/heimdal/lib/krb5/get_for_creds.c
index a7072a0136..19e48173df 100644
--- a/source4/heimdal/lib/krb5/get_for_creds.c
+++ b/source4/heimdal/lib/krb5/get_for_creds.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
static krb5_error_code
add_addrs(krb5_context context,
krb5_addresses *addr,
diff --git a/source4/heimdal/lib/krb5/get_host_realm.c b/source4/heimdal/lib/krb5/get_host_realm.c
index 2ea075f6c5..7d7fef6e1c 100644
--- a/source4/heimdal/lib/krb5/get_host_realm.c
+++ b/source4/heimdal/lib/krb5/get_host_realm.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include <resolve.h>
-RCSID("$Id$");
-
/* To automagically find the correct realm of a host (without
* [domain_realm] in krb5.conf) add a text record for your domain with
* the name of your realm, like this:
@@ -51,14 +49,14 @@ RCSID("$Id$");
*/
static int
-copy_txt_to_realms (struct resource_record *head,
+copy_txt_to_realms (struct rk_resource_record *head,
krb5_realm **realms)
{
- struct resource_record *rr;
+ struct rk_resource_record *rr;
unsigned int n, i;
for(n = 0, rr = head; rr; rr = rr->next)
- if (rr->type == T_TXT)
+ if (rr->type == rk_ns_t_txt)
++n;
if (n == 0)
@@ -72,7 +70,7 @@ copy_txt_to_realms (struct resource_record *head,
(*realms)[i] = NULL;
for (i = 0, rr = head; rr; rr = rr->next) {
- if (rr->type == T_TXT) {
+ if (rr->type == rk_ns_t_txt) {
char *tmp;
tmp = strdup(rr->u.txt);
@@ -96,7 +94,7 @@ dns_find_realm(krb5_context context,
{
static const char *default_labels[] = { "_kerberos", NULL };
char dom[MAXHOSTNAMELEN];
- struct dns_reply *r;
+ struct rk_dns_reply *r;
const char **labels;
char **config_labels;
int i, ret;
@@ -116,10 +114,10 @@ dns_find_realm(krb5_context context,
krb5_config_free_strings(config_labels);
return -1;
}
- r = dns_lookup(dom, "TXT");
+ r = rk_dns_lookup(dom, "TXT");
if(r != NULL) {
ret = copy_txt_to_realms (r->head, realms);
- dns_free_data(r);
+ rk_dns_free_data(r);
if(ret == 0) {
if (config_labels)
krb5_config_free_strings(config_labels);
diff --git a/source4/heimdal/lib/krb5/get_in_tkt.c b/source4/heimdal/lib/krb5/get_in_tkt.c
index cc49e16030..84b1ffb71f 100644
--- a/source4/heimdal/lib/krb5/get_in_tkt.c
+++ b/source4/heimdal/lib/krb5/get_in_tkt.c
@@ -31,529 +31,11 @@
* SUCH DAMAGE.
*/
-#include "krb5_locl.h"
-
-RCSID("$Id$");
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_init_etype (krb5_context context,
- unsigned *len,
- krb5_enctype **val,
- const krb5_enctype *etypes)
-{
- unsigned int i;
- krb5_error_code ret;
- krb5_enctype *tmp = NULL;
-
- ret = 0;
- if (etypes == NULL) {
- ret = krb5_get_default_in_tkt_etypes(context,
- &tmp);
- if (ret)
- return ret;
- etypes = tmp;
- }
-
- for (i = 0; etypes[i]; ++i)
- ;
- *len = i;
- *val = malloc(i * sizeof(**val));
- if (i != 0 && *val == NULL) {
- ret = ENOMEM;
- krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- goto cleanup;
- }
- memmove (*val,
- etypes,
- i * sizeof(*tmp));
-cleanup:
- if (tmp != NULL)
- free (tmp);
- return ret;
-}
-
-static krb5_error_code
-check_server_referral(krb5_context context,
- krb5_kdc_rep *rep,
- unsigned flags,
- krb5_const_principal requested,
- krb5_const_principal returned,
- const krb5_keyblock const * key)
-{
- krb5_error_code ret;
- PA_ServerReferralData ref;
- krb5_crypto session;
- EncryptedData ed;
- size_t len;
- krb5_data data;
- PA_DATA *pa;
- int i = 0, cmp;
-
- if (rep->kdc_rep.padata == NULL)
- goto noreferral;
-
- pa = krb5_find_padata(rep->kdc_rep.padata->val,
- rep->kdc_rep.padata->len,
- KRB5_PADATA_SERVER_REFERRAL, &i);
- if (pa == NULL)
- goto noreferral;
-
- memset(&ed, 0, sizeof(ed));
- memset(&ref, 0, sizeof(ref));
-
- ret = decode_EncryptedData(pa->padata_value.data,
- pa->padata_value.length,
- &ed, &len);
- if (ret)
- return ret;
- if (len != pa->padata_value.length) {
- free_EncryptedData(&ed);
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("Referral EncryptedData wrong for realm %s",
- "realm"), requested->realm);
- return KRB5KRB_AP_ERR_MODIFIED;
- }
-
- ret = krb5_crypto_init(context, key, 0, &session);
- if (ret) {
- free_EncryptedData(&ed);
- return ret;
- }
-
- ret = krb5_decrypt_EncryptedData(context, session,
- KRB5_KU_PA_SERVER_REFERRAL,
- &ed, &data);
- free_EncryptedData(&ed);
- krb5_crypto_destroy(context, session);
- if (ret)
- return ret;
-
- ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len);
- if (ret) {
- krb5_data_free(&data);
- return ret;
- }
- krb5_data_free(&data);
-
- if (strcmp(requested->realm, returned->realm) != 0) {
- free_PA_ServerReferralData(&ref);
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("server ref realm mismatch, "
- "requested realm %s got back %s", ""),
- requested->realm, returned->realm);
- return KRB5KRB_AP_ERR_MODIFIED;
- }
-
- if (returned->name.name_string.len == 2 &&
- strcmp(returned->name.name_string.val[0], KRB5_TGS_NAME) == 0)
- {
- const char *realm = returned->name.name_string.val[1];
-
- if (ref.referred_realm == NULL
- || strcmp(*ref.referred_realm, realm) != 0)
- {
- free_PA_ServerReferralData(&ref);
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("tgt returned with wrong ref", ""));
- return KRB5KRB_AP_ERR_MODIFIED;
- }
- } else if (krb5_principal_compare(context, returned, requested) == 0) {
- free_PA_ServerReferralData(&ref);
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("req princ no same as returned", ""));
- return KRB5KRB_AP_ERR_MODIFIED;
- }
-
- if (ref.requested_principal_name) {
- cmp = _krb5_principal_compare_PrincipalName(context,
- requested,
- ref.requested_principal_name);
- if (!cmp) {
- free_PA_ServerReferralData(&ref);
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("referred principal not same "
- "as requested", ""));
- return KRB5KRB_AP_ERR_MODIFIED;
- }
- } else if (flags & EXTRACT_TICKET_AS_REQ) {
- free_PA_ServerReferralData(&ref);
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("Requested principal missing on AS-REQ", ""));
- return KRB5KRB_AP_ERR_MODIFIED;
- }
-
- free_PA_ServerReferralData(&ref);
-
- return ret;
-noreferral:
- if (krb5_principal_compare(context, requested, returned) == FALSE) {
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("Not same server principal returned "
- "as requested", ""));
- return KRB5KRB_AP_ERR_MODIFIED;
- }
- return 0;
-}
-
-
-/*
- * Verify referral data
- */
-
-
-static krb5_error_code
-check_client_referral(krb5_context context,
- krb5_kdc_rep *rep,
- krb5_const_principal requested,
- krb5_const_principal mapped,
- krb5_keyblock const * key)
-{
- krb5_error_code ret;
- PA_ClientCanonicalized canon;
- krb5_crypto crypto;
- krb5_data data;
- PA_DATA *pa;
- size_t len;
- int i = 0;
-
- if (rep->kdc_rep.padata == NULL)
- goto noreferral;
-
- pa = krb5_find_padata(rep->kdc_rep.padata->val,
- rep->kdc_rep.padata->len,
- KRB5_PADATA_CLIENT_CANONICALIZED, &i);
- if (pa == NULL)
- goto noreferral;
-
- ret = decode_PA_ClientCanonicalized(pa->padata_value.data,
- pa->padata_value.length,
- &canon, &len);
- if (ret) {
- krb5_set_error_message(context, ret,
- N_("Failed to decode ClientCanonicalized "
- "from realm %s", ""), requested->realm);
- return ret;
- }
-
- ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
- &canon.names, &len, ret);
- if (ret) {
- free_PA_ClientCanonicalized(&canon);
- return ret;
- }
- if (data.length != len)
- krb5_abortx(context, "internal asn.1 error");
-
- ret = krb5_crypto_init(context, key, 0, &crypto);
- if (ret) {
- free(data.data);
- free_PA_ClientCanonicalized(&canon);
- return ret;
- }
-
- ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES,
- data.data, data.length,
- &canon.canon_checksum);
- krb5_crypto_destroy(context, crypto);
- free(data.data);
- if (ret) {
- krb5_set_error_message(context, ret,
- N_("Failed to verify client canonicalized "
- "data from realm %s", ""),
- requested->realm);
- free_PA_ClientCanonicalized(&canon);
- return ret;
- }
-
- if (!_krb5_principal_compare_PrincipalName(context,
- requested,
- &canon.names.requested_name))
- {
- free_PA_ClientCanonicalized(&canon);
- krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
- N_("Requested name doesn't match"
- " in client referral", ""));
- return KRB5_PRINC_NOMATCH;
- }
- if (!_krb5_principal_compare_PrincipalName(context,
- mapped,
- &canon.names.mapped_name))
- {
- free_PA_ClientCanonicalized(&canon);
- krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
- N_("Mapped name doesn't match"
- " in client referral", ""));
- return KRB5_PRINC_NOMATCH;
- }
-
- return 0;
-
-noreferral:
- if (krb5_principal_compare(context, requested, mapped) == FALSE) {
- krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
- N_("Not same client principal returned "
- "as requested", ""));
- return KRB5KRB_AP_ERR_MODIFIED;
- }
- return 0;
-}
-
-
+#define KRB5_DEPRECATED
-static krb5_error_code
-decrypt_tkt (krb5_context context,
- krb5_keyblock *key,
- krb5_key_usage usage,
- krb5_const_pointer decrypt_arg,
- krb5_kdc_rep *dec_rep)
-{
- krb5_error_code ret;
- krb5_data data;
- size_t size;
- krb5_crypto crypto;
-
- ret = krb5_crypto_init(context, key, 0, &crypto);
- if (ret)
- return ret;
-
- ret = krb5_decrypt_EncryptedData (context,
- crypto,
- usage,
- &dec_rep->kdc_rep.enc_part,
- &data);
- krb5_crypto_destroy(context, crypto);
-
- if (ret)
- return ret;
-
- ret = krb5_decode_EncASRepPart(context,
- data.data,
- data.length,
- &dec_rep->enc_part,
- &size);
- if (ret)
- ret = krb5_decode_EncTGSRepPart(context,
- data.data,
- data.length,
- &dec_rep->enc_part,
- &size);
- krb5_data_free (&data);
- if (ret)
- return ret;
- return 0;
-}
-
-int
-_krb5_extract_ticket(krb5_context context,
- krb5_kdc_rep *rep,
- krb5_creds *creds,
- krb5_keyblock *key,
- krb5_const_pointer keyseed,
- krb5_key_usage key_usage,
- krb5_addresses *addrs,
- unsigned nonce,
- unsigned flags,
- krb5_decrypt_proc decrypt_proc,
- krb5_const_pointer decryptarg)
-{
- krb5_error_code ret;
- krb5_principal tmp_principal;
- size_t len;
- time_t tmp_time;
- krb5_timestamp sec_now;
-
- /* decrypt */
-
- if (decrypt_proc == NULL)
- decrypt_proc = decrypt_tkt;
-
- ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
- if (ret)
- goto out;
-
- /* save session key */
-
- creds->session.keyvalue.length = 0;
- creds->session.keyvalue.data = NULL;
- creds->session.keytype = rep->enc_part.key.keytype;
- ret = krb5_data_copy (&creds->session.keyvalue,
- rep->enc_part.key.keyvalue.data,
- rep->enc_part.key.keyvalue.length);
- if (ret) {
- krb5_clear_error_message(context);
- goto out;
- }
-
- /*
- * HACK:
- * this is really a ugly hack, to support using the Netbios Domain Name
- * as realm against windows KDC's, they always return the full realm
- * based on the DNS Name.
- */
- flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
- flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
-
- /* compare client and save */
- ret = _krb5_principalname2krb5_principal (context,
- &tmp_principal,
- rep->kdc_rep.cname,
- rep->kdc_rep.crealm);
- if (ret)
- goto out;
-
- /* check client referral and save principal */
- /* anonymous here ? */
- if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) {
- ret = check_client_referral(context, rep,
- creds->client,
- tmp_principal,
- &creds->session);
- if (ret) {
- krb5_free_principal (context, tmp_principal);
- goto out;
- }
- }
- krb5_free_principal (context, creds->client);
- creds->client = tmp_principal;
-
- /* check server referral and save principal */
- ret = _krb5_principalname2krb5_principal (context,
- &tmp_principal,
- rep->kdc_rep.ticket.sname,
- rep->kdc_rep.ticket.realm);
- if (ret)
- goto out;
- if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
- ret = check_server_referral(context,
- rep,
- flags,
- creds->server,
- tmp_principal,
- &creds->session);
- if (ret) {
- krb5_free_principal (context, tmp_principal);
- goto out;
- }
- }
- krb5_free_principal(context, creds->server);
- creds->server = tmp_principal;
-
- /* verify names */
- if(flags & EXTRACT_TICKET_MATCH_REALM){
- const char *srealm = krb5_principal_get_realm(context, creds->server);
- const char *crealm = krb5_principal_get_realm(context, creds->client);
-
- if (strcmp(rep->enc_part.srealm, srealm) != 0 ||
- strcmp(rep->enc_part.srealm, crealm) != 0)
- {
- ret = KRB5KRB_AP_ERR_MODIFIED;
- krb5_clear_error_message(context);
- goto out;
- }
- }
-
- /* compare nonces */
-
- if (nonce != rep->enc_part.nonce) {
- ret = KRB5KRB_AP_ERR_MODIFIED;
- krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- goto out;
- }
-
- /* set kdc-offset */
-
- krb5_timeofday (context, &sec_now);
- if (rep->enc_part.flags.initial
- && context->kdc_sec_offset == 0
- && krb5_config_get_bool (context, NULL,
- "libdefaults",
- "kdc_timesync",
- NULL)) {
- context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
- krb5_timeofday (context, &sec_now);
- }
-
- /* check all times */
-
- if (rep->enc_part.starttime) {
- tmp_time = *rep->enc_part.starttime;
- } else
- tmp_time = rep->enc_part.authtime;
-
- if (creds->times.starttime == 0
- && abs(tmp_time - sec_now) > context->max_skew) {
- ret = KRB5KRB_AP_ERR_SKEW;
- krb5_set_error_message (context, ret,
- N_("time skew (%d) larger than max (%d)", ""),
- abs(tmp_time - sec_now),
- (int)context->max_skew);
- goto out;
- }
-
- if (creds->times.starttime != 0
- && tmp_time != creds->times.starttime) {
- krb5_clear_error_message (context);
- ret = KRB5KRB_AP_ERR_MODIFIED;
- goto out;
- }
-
- creds->times.starttime = tmp_time;
-
- if (rep->enc_part.renew_till) {
- tmp_time = *rep->enc_part.renew_till;
- } else
- tmp_time = 0;
-
- if (creds->times.renew_till != 0
- && tmp_time > creds->times.renew_till) {
- krb5_clear_error_message (context);
- ret = KRB5KRB_AP_ERR_MODIFIED;
- goto out;
- }
-
- creds->times.renew_till = tmp_time;
-
- creds->times.authtime = rep->enc_part.authtime;
-
- if (creds->times.endtime != 0
- && rep->enc_part.endtime > creds->times.endtime) {
- krb5_clear_error_message (context);
- ret = KRB5KRB_AP_ERR_MODIFIED;
- goto out;
- }
-
- creds->times.endtime = rep->enc_part.endtime;
-
- if(rep->enc_part.caddr)
- krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
- else if(addrs)
- krb5_copy_addresses (context, addrs, &creds->addresses);
- else {
- creds->addresses.len = 0;
- creds->addresses.val = NULL;
- }
- creds->flags.b = rep->enc_part.flags;
-
- creds->authdata.len = 0;
- creds->authdata.val = NULL;
-
- /* extract ticket */
- ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
- &rep->kdc_rep.ticket, &len, ret);
- if(ret)
- goto out;
- if (creds->ticket.length != len)
- krb5_abortx(context, "internal error in ASN.1 encoder");
- creds->second_ticket.length = 0;
- creds->second_ticket.data = NULL;
-
-
-out:
- memset (rep->enc_part.key.keyvalue.data, 0,
- rep->enc_part.key.keyvalue.length);
- return ret;
-}
+#include "krb5_locl.h"
+#ifndef HEIMDAL_SMALLER
static krb5_error_code
make_pa_enc_timestamp(krb5_context context, PA_DATA *pa,
@@ -626,6 +108,8 @@ add_padata(krb5_context context,
if(salt == NULL) {
/* default to standard salt */
ret = krb5_get_pw_salt (context, client, &salt2);
+ if (ret)
+ return ret;
salt = &salt2;
}
if (!enctypes) {
@@ -861,11 +345,10 @@ set_ptypes(krb5_context context,
*preauth = &preauth2;
ALLOC_SEQ(*preauth, 1);
(*preauth)->val[0].type = KRB5_PADATA_ENC_TIMESTAMP;
- krb5_decode_ETYPE_INFO(context,
- md.val[i].padata_value.data,
- md.val[i].padata_value.length,
- &(*preauth)->val[0].info,
- NULL);
+ decode_ETYPE_INFO(md.val[i].padata_value.data,
+ md.val[i].padata_value.length,
+ &(*preauth)->val[0].info,
+ NULL);
break;
default:
break;
@@ -891,6 +374,7 @@ krb5_get_in_cred(krb5_context context,
krb5_const_pointer decryptarg,
krb5_creds *creds,
krb5_kdc_rep *ret_as_reply)
+ KRB5_DEPRECATED
{
krb5_error_code ret;
AS_REQ a;
@@ -1055,6 +539,7 @@ krb5_get_in_tkt(krb5_context context,
krb5_creds *creds,
krb5_ccache ccache,
krb5_kdc_rep *ret_as_reply)
+ KRB5_DEPRECATED
{
krb5_error_code ret;
@@ -1076,3 +561,5 @@ krb5_get_in_tkt(krb5_context context,
ret = krb5_cc_store_cred (context, ccache, creds);
return ret;
}
+
+#endif /* HEIMDAL_SMALLER */
diff --git a/source4/heimdal/lib/krb5/get_port.c b/source4/heimdal/lib/krb5/get_port.c
index c9869eb450..5d0361b816 100644
--- a/source4/heimdal/lib/krb5/get_port.c
+++ b/source4/heimdal/lib/krb5/get_port.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
int KRB5_LIB_FUNCTION
krb5_getportbyname (krb5_context context,
const char *service,
diff --git a/source4/heimdal/lib/krb5/heim_err.et b/source4/heimdal/lib/krb5/heim_err.et
index 547a14e04c..2e8a0d18d8 100644
--- a/source4/heimdal/lib/krb5/heim_err.et
+++ b/source4/heimdal/lib/krb5/heim_err.et
@@ -17,6 +17,8 @@ error_code OPNOTSUPP, "Operation not supported"
error_code EOF, "End of file"
error_code BAD_MKEY, "Failed to get the master key"
error_code SERVICE_NOMATCH, "Unacceptable service used"
+error_code NOT_SEEKABLE, "File descriptor not seekable"
+error_code TOO_BIG, "Offset too large"
index 64
prefix HEIM_PKINIT
diff --git a/source4/heimdal/lib/krb5/init_creds.c b/source4/heimdal/lib/krb5/init_creds.c
index 89ea3004ed..b1bd94d3b9 100644
--- a/source4/heimdal/lib/krb5/init_creds.c
+++ b/source4/heimdal/lib/krb5/init_creds.c
@@ -36,14 +36,19 @@
#undef __attribute__
#define __attribute__(x)
-RCSID("$Id$");
+/**
+ * @page krb5_init_creds_intro The initial credential handing functions
+ * @section section_krb5_init_creds Initial credential
+ *
+ * Functions to get initial credentials: @ref krb5_credential .
+ */
-void KRB5_LIB_FUNCTION
-krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
- __attribute__((deprecated))
-{
- memset (opt, 0, sizeof(*opt));
-}
+/**
+ * Allocate a new krb5_get_init_creds_opt structure, free with
+ * krb5_get_init_creds_opt_free().
+ *
+ * @ingroup krb5_credential
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_alloc(krb5_context context,
@@ -71,67 +76,11 @@ krb5_get_init_creds_opt_alloc(krb5_context context,
return 0;
}
-krb5_error_code
-_krb5_get_init_creds_opt_copy(krb5_context context,
- const krb5_get_init_creds_opt *in,
- krb5_get_init_creds_opt **out)
-{
- krb5_get_init_creds_opt *opt;
-
- *out = NULL;
- opt = calloc(1, sizeof(*opt));
- if (opt == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
- }
- if (in)
- *opt = *in;
- if(opt->opt_private == NULL) {
- opt->opt_private = calloc(1, sizeof(*opt->opt_private));
- if (opt->opt_private == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- free(opt);
- return ENOMEM;
- }
- opt->opt_private->refcount = 1;
- } else
- opt->opt_private->refcount++;
- *out = opt;
- return 0;
-}
-
-void KRB5_LIB_FUNCTION
-_krb5_get_init_creds_opt_free_krb5_error(krb5_get_init_creds_opt *opt)
-{
- if (opt->opt_private == NULL || opt->opt_private->error == NULL)
- return;
- free_KRB_ERROR(opt->opt_private->error);
- free(opt->opt_private->error);
- opt->opt_private->error = NULL;
-}
-
-void KRB5_LIB_FUNCTION
-_krb5_get_init_creds_opt_set_krb5_error(krb5_context context,
- krb5_get_init_creds_opt *opt,
- const KRB_ERROR *error)
-{
- krb5_error_code ret;
-
- if (opt->opt_private == NULL)
- return;
-
- _krb5_get_init_creds_opt_free_krb5_error(opt);
-
- opt->opt_private->error = malloc(sizeof(*opt->opt_private->error));
- if (opt->opt_private->error == NULL)
- return;
- ret = copy_KRB_ERROR(error, opt->opt_private->error);
- if (ret) {
- free(opt->opt_private->error);
- opt->opt_private->error = NULL;
- }
-}
-
+/**
+ * Free krb5_get_init_creds_opt structure.
+ *
+ * @ingroup krb5_credential
+ */
void KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_free(krb5_context context,
@@ -142,7 +91,6 @@ krb5_get_init_creds_opt_free(krb5_context context,
if (opt->opt_private->refcount < 1) /* abort ? */
return;
if (--opt->opt_private->refcount == 0) {
- _krb5_get_init_creds_opt_free_krb5_error(opt);
_krb5_get_init_creds_opt_free_pkinit(opt);
free(opt->opt_private);
}
@@ -369,35 +317,6 @@ krb5_get_init_creds_opt_set_pac_request(krb5_context context,
}
krb5_error_code KRB5_LIB_FUNCTION
-krb5_get_init_creds_opt_get_error(krb5_context context,
- krb5_get_init_creds_opt *opt,
- KRB_ERROR **error)
-{
- krb5_error_code ret;
-
- *error = NULL;
-
- ret = require_ext_opt(context, opt, "init_creds_opt_get_error");
- if (ret)
- return ret;
-
- if (opt->opt_private->error == NULL)
- return 0;
-
- *error = malloc(sizeof(**error));
- if (*error == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
- }
-
- ret = copy_KRB_ERROR(opt->opt_private->error, *error);
- if (ret)
- krb5_clear_error_message(context);
-
- return 0;
-}
-
-krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_opt_set_addressless(krb5_context context,
krb5_get_init_creds_opt *opt,
krb5_boolean addressless)
@@ -445,3 +364,54 @@ krb5_get_init_creds_opt_set_win2k(krb5_context context,
return 0;
}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_set_process_last_req(krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ krb5_gic_process_last_req func,
+ void *ctx)
+{
+ krb5_error_code ret;
+ ret = require_ext_opt(context, opt, "init_creds_opt_set_win2k");
+ if (ret)
+ return ret;
+
+ opt->opt_private->lr.func = func;
+ opt->opt_private->lr.ctx = ctx;
+
+ return 0;
+}
+
+
+#ifndef HEIMDAL_SMALLER
+
+void KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
+ KRB5_DEPRECATED
+{
+ memset (opt, 0, sizeof(*opt));
+}
+
+/**
+ * Deprecated: use the new krb5_init_creds_init() and
+ * krb5_init_creds_get_error().
+ *
+ * @ingroup krb5_deprecated
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_opt_get_error(krb5_context context,
+ krb5_get_init_creds_opt *opt,
+ KRB_ERROR **error)
+ KRB5_DEPRECATED
+{
+ *error = calloc(1, sizeof(**error));
+ if (*error == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+
+ return 0;
+}
+
+#endif /* HEIMDAL_SMALLER */
diff --git a/source4/heimdal/lib/krb5/init_creds_pw.c b/source4/heimdal/lib/krb5/init_creds_pw.c
index 0b75522e9d..0435ab5d3b 100644
--- a/source4/heimdal/lib/krb5/init_creds_pw.c
+++ b/source4/heimdal/lib/krb5/init_creds_pw.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2007 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997 - 2008 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,15 +33,13 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
typedef struct krb5_get_init_creds_ctx {
KDCOptions flags;
krb5_creds cred;
krb5_addresses *addrs;
krb5_enctype *etypes;
krb5_preauthtype *pre_auth_types;
- const char *in_tkt_service;
+ char *in_tkt_service;
unsigned nonce;
unsigned pk_nonce;
@@ -49,13 +47,26 @@ typedef struct krb5_get_init_creds_ctx {
AS_REQ as_req;
int pa_counter;
- const char *password;
- krb5_s2k_proc key_proc;
+ /* password and keytab_data is freed on completion */
+ char *password;
+ krb5_keytab_key_proc_args *keytab_data;
+
+ krb5_pointer *keyseed;
+ krb5_s2k_proc keyproc;
krb5_get_init_creds_tristate req_pac;
krb5_pk_init_ctx pk_init_ctx;
int ic_flags;
+
+ METHOD_DATA md;
+ KRB_ERROR error;
+ AS_REP as_rep;
+ EncKDCRepPart enc_part;
+
+ krb5_prompter_fct prompter;
+ void *prompter_data;
+
} krb5_get_init_creds_ctx;
static krb5_error_code
@@ -74,7 +85,7 @@ default_s2k_func(krb5_context context, krb5_enctype type,
opaque = *s2kparms;
else
krb5_data_zero(&opaque);
-
+
*key = malloc(sizeof(**key));
if (*key == NULL)
return ENOMEM;
@@ -88,14 +99,24 @@ default_s2k_func(krb5_context context, krb5_enctype type,
}
static void
-free_init_creds_ctx(krb5_context context, krb5_get_init_creds_ctx *ctx)
+free_init_creds_ctx(krb5_context context, krb5_init_creds_context ctx)
{
if (ctx->etypes)
free(ctx->etypes);
if (ctx->pre_auth_types)
free (ctx->pre_auth_types);
+ if (ctx->in_tkt_service)
+ free(ctx->in_tkt_service);
+ if (ctx->keytab_data)
+ free(ctx->keytab_data);
+ krb5_data_free(&ctx->req_buffer);
+ krb5_free_cred_contents(context, &ctx->cred);
+ free_METHOD_DATA(&ctx->md);
+ free_AS_REP(&ctx->as_rep);
+ free_EncKDCRepPart(&ctx->enc_part);
+ free_KRB_ERROR(&ctx->error);
free_AS_REQ(&ctx->as_req);
- memset(&ctx->as_req, 0, sizeof(ctx->as_req));
+ memset(ctx, 0, sizeof(*ctx));
}
static int
@@ -127,11 +148,9 @@ init_cred (krb5_context context,
krb5_creds *cred,
krb5_principal client,
krb5_deltat start_time,
- const char *in_tkt_service,
krb5_get_init_creds_opt *options)
{
krb5_error_code ret;
- krb5_const_realm client_realm;
int tmp;
krb5_timestamp now;
@@ -148,8 +167,6 @@ init_cred (krb5_context context,
goto out;
}
- client_realm = krb5_principal_get_realm (context, cred->client);
-
if (start_time)
cred->times.starttime = now + start_time;
@@ -164,18 +181,6 @@ init_cred (krb5_context context,
cred->times.renew_till = now + options->renew_life;
}
- if (in_tkt_service) {
- ret = krb5_parse_name (context, in_tkt_service, &cred->server);
- if (ret)
- goto out;
- krb5_principal_set_realm (context, cred->server, client_realm);
- } else {
- ret = krb5_make_principal(context, &cred->server,
- client_realm, KRB5_TGS_NAME, client_realm,
- NULL);
- if (ret)
- goto out;
- }
return 0;
out:
@@ -195,28 +200,71 @@ report_expiration (krb5_context context,
time_t now)
{
char *p;
-
+
asprintf (&p, "%s%s", str, ctime(&now));
(*prompter) (context, data, NULL, p, 0, NULL);
free (p);
}
/*
- * Parse the last_req data and show it to the user if it's interesting
+ * Check the context, and in the case there is a expiration warning,
+ * use the prompter to print the warning.
+ *
+ * @param context A Kerberos 5 context.
+ * @param options An GIC options structure
+ * @param ctx The krb5_init_creds_context check for expiration.
*/
-static void
-print_expire (krb5_context context,
- krb5_const_realm realm,
- krb5_kdc_rep *rep,
- krb5_prompter_fct prompter,
- krb5_data *data)
+static krb5_error_code
+process_last_request(krb5_context context,
+ krb5_get_init_creds_opt *options,
+ krb5_init_creds_context ctx)
{
- int i;
- LastReq *lr = &rep->enc_part.last_req;
+ krb5_const_realm realm;
+ LastReq *lr;
+ krb5_boolean reported = FALSE;
krb5_timestamp sec;
time_t t;
- krb5_boolean reported = FALSE;
+ size_t i;
+
+ /*
+ * First check if there is a API consumer.
+ */
+
+ realm = krb5_principal_get_realm (context, ctx->cred.client);
+ lr = &ctx->enc_part.last_req;
+
+ if (options && options->opt_private && options->opt_private->lr.func) {
+ krb5_last_req_entry **lre;
+
+ lre = calloc(lr->len + 1, sizeof(**lre));
+ if (lre == NULL) {
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ for (i = 0; i < lr->len; i++) {
+ lre[i] = calloc(1, sizeof(*lre[i]));
+ if (lre[i] == NULL)
+ break;
+ lre[i]->lr_type = lr->val[i].lr_type;
+ lre[i]->value = lr->val[i].lr_value;
+ }
+
+ (*options->opt_private->lr.func)(context, lre,
+ options->opt_private->lr.ctx);
+
+ for (i = 0; i < lr->len; i++)
+ free(lre[i]);
+ free(lre);
+ }
+
+ /*
+ * Now check if we should prompt the user
+ */
+
+ if (ctx->prompter == NULL)
+ return 0;
krb5_timeofday (context, &sec);
@@ -229,13 +277,15 @@ print_expire (krb5_context context,
if (lr->val[i].lr_value <= t) {
switch (abs(lr->val[i].lr_type)) {
case LR_PW_EXPTIME :
- report_expiration(context, prompter, data,
+ report_expiration(context, ctx->prompter,
+ ctx->prompter_data,
"Your password will expire at ",
lr->val[i].lr_value);
reported = TRUE;
break;
case LR_ACCT_EXPTIME :
- report_expiration(context, prompter, data,
+ report_expiration(context, ctx->prompter,
+ ctx->prompter_data,
"Your account will expire at ",
lr->val[i].lr_value);
reported = TRUE;
@@ -245,12 +295,14 @@ print_expire (krb5_context context,
}
if (!reported
- && rep->enc_part.key_expiration
- && *rep->enc_part.key_expiration <= t) {
- report_expiration(context, prompter, data,
+ && ctx->enc_part.key_expiration
+ && *ctx->enc_part.key_expiration <= t) {
+ report_expiration(context, ctx->prompter,
+ ctx->prompter_data,
"Your password/account will expire at ",
- *rep->enc_part.key_expiration);
+ *ctx->enc_part.key_expiration);
}
+ return 0;
}
static krb5_addresses no_addrs = { 0, NULL };
@@ -259,11 +311,10 @@ static krb5_error_code
get_init_creds_common(krb5_context context,
krb5_principal client,
krb5_deltat start_time,
- const char *in_tkt_service,
krb5_get_init_creds_opt *options,
- krb5_get_init_creds_ctx *ctx)
+ krb5_init_creds_context ctx)
{
- krb5_get_init_creds_opt default_opt;
+ krb5_get_init_creds_opt *default_opt = NULL;
krb5_error_code ret;
krb5_enctype *etypes;
krb5_preauthtype *pre_auth_types;
@@ -271,37 +322,51 @@ get_init_creds_common(krb5_context context,
memset(ctx, 0, sizeof(*ctx));
if (options == NULL) {
- krb5_get_init_creds_opt_init (&default_opt);
- options = &default_opt;
- } else {
- _krb5_get_init_creds_opt_free_krb5_error(options);
+ const char *realm = krb5_principal_get_realm(context, client);
+
+ krb5_get_init_creds_opt_alloc (context, &default_opt);
+ options = default_opt;
+ krb5_get_init_creds_opt_set_default_flags(context, NULL, realm, options);
}
if (options->opt_private) {
- ctx->password = options->opt_private->password;
- ctx->key_proc = options->opt_private->key_proc;
+ if (options->opt_private->password) {
+ ret = krb5_init_creds_set_password(context, ctx,
+ options->opt_private->password);
+ if (ret)
+ goto out;
+ }
+
+ ctx->keyproc = options->opt_private->key_proc;
ctx->req_pac = options->opt_private->req_pac;
ctx->pk_init_ctx = options->opt_private->pk_init_ctx;
ctx->ic_flags = options->opt_private->flags;
} else
ctx->req_pac = KRB5_INIT_CREDS_TRISTATE_UNSET;
- if (ctx->key_proc == NULL)
- ctx->key_proc = default_s2k_func;
+ if (ctx->keyproc == NULL)
+ ctx->keyproc = default_s2k_func;
- if (ctx->ic_flags & KRB5_INIT_CREDS_CANONICALIZE)
+ /* Enterprise name implicitly turns on canonicalize */
+ if ((ctx->ic_flags & KRB5_INIT_CREDS_CANONICALIZE) ||
+ krb5_principal_get_type(context, client) == KRB5_NT_ENTERPRISE_PRINCIPAL)
ctx->flags.canonicalize = 1;
ctx->pre_auth_types = NULL;
ctx->addrs = NULL;
ctx->etypes = NULL;
ctx->pre_auth_types = NULL;
- ctx->in_tkt_service = in_tkt_service;
- ret = init_cred (context, &ctx->cred, client, start_time,
- in_tkt_service, options);
- if (ret)
+ ret = init_cred(context, &ctx->cred, client, start_time, options);
+ if (ret) {
+ if (default_opt)
+ krb5_get_init_creds_opt_free(context, default_opt);
return ret;
+ }
+
+ ret = krb5_init_creds_set_service(context, ctx, NULL);
+ if (ret)
+ goto out;
if (options->flags & KRB5_GET_INIT_CREDS_OPT_FORWARDABLE)
ctx->flags.forwardable = options->forwardable;
@@ -336,8 +401,9 @@ get_init_creds_common(krb5_context context,
etypes = malloc((options->etype_list_length + 1)
* sizeof(krb5_enctype));
if (etypes == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
}
memcpy (etypes, options->etype_list,
options->etype_list_length * sizeof(krb5_enctype));
@@ -348,19 +414,24 @@ get_init_creds_common(krb5_context context,
pre_auth_types = malloc((options->preauth_list_length + 1)
* sizeof(krb5_preauthtype));
if (pre_auth_types == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
- return ENOMEM;
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
}
memcpy (pre_auth_types, options->preauth_list,
options->preauth_list_length * sizeof(krb5_preauthtype));
pre_auth_types[options->preauth_list_length] = KRB5_PADATA_NONE;
ctx->pre_auth_types = pre_auth_types;
}
- if (options->flags & KRB5_GET_INIT_CREDS_OPT_SALT)
- ; /* XXX */
if (options->flags & KRB5_GET_INIT_CREDS_OPT_ANONYMOUS)
ctx->flags.request_anonymous = options->anonymous;
+ if (default_opt)
+ krb5_get_init_creds_opt_free(context, default_opt);
return 0;
+ out:
+ if (default_opt)
+ krb5_get_init_creds_opt_free(context, default_opt);
+ return ret;
}
static krb5_error_code
@@ -382,18 +453,20 @@ change_password (krb5_context context,
krb5_data result_code_string;
krb5_data result_string;
char *p;
- krb5_get_init_creds_opt options;
+ krb5_get_init_creds_opt *options;
memset (&cpw_cred, 0, sizeof(cpw_cred));
- krb5_get_init_creds_opt_init (&options);
- krb5_get_init_creds_opt_set_tkt_life (&options, 60);
- krb5_get_init_creds_opt_set_forwardable (&options, FALSE);
- krb5_get_init_creds_opt_set_proxiable (&options, FALSE);
+ ret = krb5_get_init_creds_opt_alloc(context, &options);
+ if (ret)
+ return ret;
+ krb5_get_init_creds_opt_set_tkt_life (options, 60);
+ krb5_get_init_creds_opt_set_forwardable (options, FALSE);
+ krb5_get_init_creds_opt_set_proxiable (options, FALSE);
if (old_options && old_options->flags & KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST)
- krb5_get_init_creds_opt_set_preauth_list (&options,
+ krb5_get_init_creds_opt_set_preauth_list (options,
old_options->preauth_list,
- old_options->preauth_list_length);
+ old_options->preauth_list_length);
krb5_data_zero (&result_code_string);
krb5_data_zero (&result_string);
@@ -406,7 +479,8 @@ change_password (krb5_context context,
data,
0,
"kadmin/changepw",
- &options);
+ options);
+ krb5_get_init_creds_opt_free(context, options);
if (ret)
goto out;
@@ -455,7 +529,9 @@ change_password (krb5_context context,
(int)result_string.length,
result_string.length > 0 ? (char*)result_string.data : "");
- ret = (*prompter) (context, data, NULL, p, 0, NULL);
+ /* return the result */
+ (*prompter) (context, data, NULL, p, 0, NULL);
+
free (p);
if (result_code == 0) {
strlcpy (newpw, buf1, newpw_sz);
@@ -475,6 +551,7 @@ out:
return ret;
}
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_keyblock_key_proc (krb5_context context,
krb5_keytype type,
@@ -485,68 +562,17 @@ krb5_keyblock_key_proc (krb5_context context,
return krb5_copy_keyblock (context, keyseed, key);
}
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_get_init_creds_keytab(krb5_context context,
- krb5_creds *creds,
- krb5_principal client,
- krb5_keytab keytab,
- krb5_deltat start_time,
- const char *in_tkt_service,
- krb5_get_init_creds_opt *options)
-{
- krb5_get_init_creds_ctx ctx;
- krb5_error_code ret;
- krb5_keytab_key_proc_args *a;
-
- ret = get_init_creds_common(context, client, start_time,
- in_tkt_service, options, &ctx);
- if (ret)
- goto out;
-
- a = malloc (sizeof(*a));
- if (a == NULL) {
- ret = ENOMEM;
- krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- goto out;
- }
- a->principal = ctx.cred.client;
- a->keytab = keytab;
-
- ret = krb5_get_in_cred (context,
- KDCOptions2int(ctx.flags),
- ctx.addrs,
- ctx.etypes,
- ctx.pre_auth_types,
- NULL,
- krb5_keytab_key_proc,
- a,
- NULL,
- NULL,
- &ctx.cred,
- NULL);
- free (a);
-
- if (ret == 0 && creds)
- *creds = ctx.cred;
- else
- krb5_free_cred_contents (context, &ctx.cred);
-
- out:
- free_init_creds_ctx(context, &ctx);
- return ret;
-}
-
/*
*
*/
static krb5_error_code
-init_creds_init_as_req (krb5_context context,
- KDCOptions opts,
- const krb5_creds *creds,
- const krb5_addresses *addrs,
- const krb5_enctype *etypes,
- AS_REQ *a)
+init_as_req (krb5_context context,
+ KDCOptions opts,
+ const krb5_creds *creds,
+ const krb5_addresses *addrs,
+ const krb5_enctype *etypes,
+ AS_REQ *a)
{
krb5_error_code ret;
@@ -906,7 +932,7 @@ make_pa_enc_timestamp(krb5_context context, METHOD_DATA *md,
krb5_crypto_destroy(context, crypto);
if (ret)
return ret;
-
+
ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_size, &encdata, &len, ret);
free_EncryptedData(&encdata);
if (ret)
@@ -924,7 +950,7 @@ static krb5_error_code
add_enc_ts_padata(krb5_context context,
METHOD_DATA *md,
krb5_principal client,
- krb5_s2k_proc key_proc,
+ krb5_s2k_proc keyproc,
krb5_const_pointer keyseed,
krb5_enctype *enctypes,
unsigned netypes,
@@ -939,6 +965,8 @@ add_enc_ts_padata(krb5_context context,
if(salt == NULL) {
/* default to standard salt */
ret = krb5_get_pw_salt (context, client, &salt2);
+ if (ret)
+ return ret;
salt = &salt2;
}
if (!enctypes) {
@@ -951,8 +979,8 @@ add_enc_ts_padata(krb5_context context,
for (i = 0; i < netypes; ++i) {
krb5_keyblock *key;
- ret = (*key_proc)(context, enctypes[i], keyseed,
- *salt, s2kparams, &key);
+ ret = (*keyproc)(context, enctypes[i], keyseed,
+ *salt, s2kparams, &key);
if (ret)
continue;
ret = make_pa_enc_timestamp (context, md, enctypes[i], key);
@@ -973,28 +1001,28 @@ pa_data_to_md_ts_enc(krb5_context context,
struct pa_info_data *ppaid,
METHOD_DATA *md)
{
- if (ctx->key_proc == NULL || ctx->password == NULL)
+ if (ctx->keyproc == NULL || ctx->keyseed == NULL)
return 0;
if (ppaid) {
add_enc_ts_padata(context, md, client,
- ctx->key_proc, ctx->password,
+ ctx->keyproc, ctx->keyseed,
&ppaid->etype, 1,
&ppaid->salt, ppaid->s2kparams);
} else {
krb5_salt salt;
-
+
/* make a v5 salted pa-data */
add_enc_ts_padata(context, md, client,
- ctx->key_proc, ctx->password,
+ ctx->keyproc, ctx->keyseed,
a->req_body.etype.val, a->req_body.etype.len,
NULL, NULL);
-
+
/* make a v4 salted pa-data */
salt.salttype = KRB5_PW_SALT;
krb5_data_zero(&salt.saltvalue);
add_enc_ts_padata(context, md, client,
- ctx->key_proc, ctx->password,
+ ctx->keyproc, ctx->keyseed,
a->req_body.etype.val, a->req_body.etype.len,
&salt, NULL);
}
@@ -1012,7 +1040,7 @@ pa_data_to_key_plain(krb5_context context,
{
krb5_error_code ret;
- ret = (*ctx->key_proc)(context, etype, ctx->password,
+ ret = (*ctx->keyproc)(context, etype, ctx->keyseed,
salt, s2kparams, key);
return ret;
}
@@ -1058,7 +1086,7 @@ pa_data_add_pac_request(krb5_context context,
break;
case KRB5_INIT_CREDS_TRISTATE_FALSE:
req.include_pac = 0;
- }
+ }
ASN1_MALLOC_ENCODE(PA_PAC_REQUEST, buf, length,
&req, &len, ret);
@@ -1111,12 +1139,12 @@ process_pa_data_to_md(krb5_context context,
} else if (in_md->len != 0) {
struct pa_info_data paid, *ppaid;
-
+
memset(&paid, 0, sizeof(paid));
-
+
paid.etype = ENCTYPE_NULL;
ppaid = process_pa_info(context, creds->client, a, &paid, in_md);
-
+
pa_data_to_md_ts_enc(context, a, creds->client, ctx, ppaid, *out_md);
if (ppaid)
free_paid(context, ppaid);
@@ -1137,7 +1165,7 @@ process_pa_data_to_key(krb5_context context,
krb5_get_init_creds_ctx *ctx,
krb5_creds *creds,
AS_REQ *a,
- krb5_kdc_rep *rep,
+ AS_REP *rep,
const krb5_krbhst_info *hi,
krb5_keyblock **key)
{
@@ -1148,12 +1176,12 @@ process_pa_data_to_key(krb5_context context,
memset(&paid, 0, sizeof(paid));
- etype = rep->kdc_rep.enc_part.etype;
+ etype = rep->enc_part.etype;
- if (rep->kdc_rep.padata) {
+ if (rep->padata) {
paid.etype = etype;
ppaid = process_pa_info(context, creds->client, a, &paid,
- rep->kdc_rep.padata);
+ rep->padata);
}
if (ppaid == NULL) {
ret = krb5_get_pw_salt (context, creds->client, &paid.salt);
@@ -1164,16 +1192,16 @@ process_pa_data_to_key(krb5_context context,
}
pa = NULL;
- if (rep->kdc_rep.padata) {
+ if (rep->padata) {
int idx = 0;
- pa = krb5_find_padata(rep->kdc_rep.padata->val,
- rep->kdc_rep.padata->len,
+ pa = krb5_find_padata(rep->padata->val,
+ rep->padata->len,
KRB5_PADATA_PK_AS_REP,
&idx);
if (pa == NULL) {
idx = 0;
- pa = krb5_find_padata(rep->kdc_rep.padata->val,
- rep->kdc_rep.padata->len,
+ pa = krb5_find_padata(rep->padata->val,
+ rep->padata->len,
KRB5_PADATA_PK_AS_REP_19,
&idx);
}
@@ -1193,7 +1221,7 @@ process_pa_data_to_key(krb5_context context,
ret = EINVAL;
krb5_set_error_message(context, ret, N_("no support for PKINIT compiled in", ""));
#endif
- } else if (ctx->password)
+ } else if (ctx->keyseed)
ret = pa_data_to_key_plain(context, creds->client, ctx,
paid.salt, paid.s2kparams, etype, key);
else {
@@ -1205,109 +1233,340 @@ process_pa_data_to_key(krb5_context context,
return ret;
}
-static krb5_error_code
-init_cred_loop(krb5_context context,
- krb5_get_init_creds_opt *init_cred_opts,
- const krb5_prompter_fct prompter,
- void *prompter_data,
- krb5_get_init_creds_ctx *ctx,
- krb5_creds *creds,
- krb5_kdc_rep *ret_as_reply)
+/**
+ * Start a new context to get a new initial credential.
+ *
+ * @param context A Kerberos 5 context.
+ * @param client The Kerberos principal to get the credential for, if
+ * NULL is given, the default principal is used as determined by
+ * krb5_get_default_principal().
+ * @param prompter
+ * @param prompter_data
+ * @param start_time the time the ticket should start to be valid or 0 for now.
+ * @param options a options structure, can be NULL for default options.
+ * @param rctx A new allocated free with krb5_init_creds_free().
+ *
+ * @return 0 for success or an Kerberos 5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_credential
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_init(krb5_context context,
+ krb5_principal client,
+ krb5_prompter_fct prompter,
+ void *prompter_data,
+ krb5_deltat start_time,
+ krb5_get_init_creds_opt *options,
+ krb5_init_creds_context *rctx)
{
+ krb5_init_creds_context ctx;
krb5_error_code ret;
- krb5_kdc_rep rep;
- METHOD_DATA md;
- krb5_data resp;
- size_t len;
- size_t size;
- krb5_krbhst_info *hi = NULL;
- krb5_sendto_ctx stctx = NULL;
-
- memset(&md, 0, sizeof(md));
- memset(&rep, 0, sizeof(rep));
+ *rctx = NULL;
- _krb5_get_init_creds_opt_free_krb5_error(init_cred_opts);
-
- if (ret_as_reply)
- memset(ret_as_reply, 0, sizeof(*ret_as_reply));
+ ctx = calloc(1, sizeof(*ctx));
+ if (ctx == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
- ret = init_creds_init_as_req(context, ctx->flags, creds,
- ctx->addrs, ctx->etypes, &ctx->as_req);
- if (ret)
+ ret = get_init_creds_common(context, client, start_time, options, ctx);
+ if (ret) {
+ free(ctx);
return ret;
-
- ret = krb5_sendto_ctx_alloc(context, &stctx);
- if (ret)
- goto out;
- krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);
+ }
/* Set a new nonce. */
krb5_generate_random_block (&ctx->nonce, sizeof(ctx->nonce));
- ctx->nonce &= 0xffffffff;
+ ctx->nonce &= 0x7fffffff;
/* XXX these just needs to be the same when using Windows PK-INIT */
ctx->pk_nonce = ctx->nonce;
- /*
- * Increase counter when we want other pre-auth types then
- * KRB5_PA_ENC_TIMESTAMP.
- */
-#define MAX_PA_COUNTER 3
+ ctx->prompter = prompter;
+ ctx->prompter_data = prompter_data;
- ctx->pa_counter = 0;
- while (ctx->pa_counter < MAX_PA_COUNTER) {
+ *rctx = ctx;
- ctx->pa_counter++;
+ return ret;
+}
- if (ctx->as_req.padata) {
- free_METHOD_DATA(ctx->as_req.padata);
- free(ctx->as_req.padata);
- ctx->as_req.padata = NULL;
- }
+/**
+ * Sets the service that the is requested. This call is only neede for
+ * special initial tickets, by default the a krbtgt is fetched in the default realm.
+ *
+ * @param context a Kerberos 5 context.
+ * @param ctx a krb5_init_creds_context context.
+ * @param service the service given as a string, for example
+ * "kadmind/admin". If NULL, the default krbtgt in the clients
+ * realm is set.
+ *
+ * @return 0 for success, or an Kerberos 5 error code, see krb5_get_error_message().
+ * @ingroup krb5_credential
+ */
- /* Set a new nonce. */
- ctx->as_req.req_body.nonce = ctx->nonce;
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_set_service(krb5_context context,
+ krb5_init_creds_context ctx,
+ const char *service)
+{
+ krb5_const_realm client_realm;
+ krb5_principal principal;
+ krb5_error_code ret;
+
+ client_realm = krb5_principal_get_realm (context, ctx->cred.client);
- /* fill_in_md_data */
- ret = process_pa_data_to_md(context, creds, &ctx->as_req, ctx,
- &md, &ctx->as_req.padata,
- prompter, prompter_data);
+ if (service) {
+ ret = krb5_parse_name (context, service, &principal);
if (ret)
- goto out;
+ return ret;
+ krb5_principal_set_realm (context, principal, client_realm);
+ } else {
+ ret = krb5_make_principal(context, &principal,
+ client_realm, KRB5_TGS_NAME, client_realm,
+ NULL);
+ if (ret)
+ return ret;
+ }
+ krb5_free_principal(context, ctx->cred.server);
+ ctx->cred.server = principal;
- krb5_data_free(&ctx->req_buffer);
+ return 0;
+}
- ASN1_MALLOC_ENCODE(AS_REQ,
- ctx->req_buffer.data, ctx->req_buffer.length,
- &ctx->as_req, &len, ret);
- if (ret)
- goto out;
- if(len != ctx->req_buffer.length)
- krb5_abortx(context, "internal error in ASN.1 encoder");
+/**
+ * Sets the password that will use for the request.
+ *
+ * @param context a Kerberos 5 context.
+ * @param ctx ctx krb5_init_creds_context context.
+ * @param password the password to use.
+ *
+ * @return 0 for success, or an Kerberos 5 error code, see krb5_get_error_message().
+ * @ingroup krb5_credential
+ */
- ret = krb5_sendto_context (context, stctx, &ctx->req_buffer,
- creds->client->realm, &resp);
- if (ret)
- goto out;
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_set_password(krb5_context context,
+ krb5_init_creds_context ctx,
+ const char *password)
+{
+ if (ctx->password)
+ memset(ctx->password, 0, strlen(ctx->password));
+ if (password) {
+ ctx->password = strdup(password);
+ if (ctx->password == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ ctx->keyseed = (void *) ctx->password;
+ } else {
+ ctx->keyseed = NULL;
+ ctx->password = NULL;
+ }
+
+ return 0;
+}
+
+static krb5_error_code
+keytab_key_proc(krb5_context context, krb5_enctype enctype,
+ krb5_const_pointer keyseed,
+ krb5_salt salt, krb5_data *s2kparms,
+ krb5_keyblock **key)
+{
+ krb5_keytab_key_proc_args *args = rk_UNCONST(keyseed);
+ krb5_keytab keytab = args->keytab;
+ krb5_principal principal = args->principal;
+ krb5_error_code ret;
+ krb5_keytab real_keytab;
+ krb5_keytab_entry entry;
+
+ if(keytab == NULL)
+ krb5_kt_default(context, &real_keytab);
+ else
+ real_keytab = keytab;
+
+ ret = krb5_kt_get_entry (context, real_keytab, principal,
+ 0, enctype, &entry);
+
+ if (keytab == NULL)
+ krb5_kt_close (context, real_keytab);
+
+ if (ret)
+ return ret;
+
+ ret = krb5_copy_keyblock (context, &entry.keyblock, key);
+ krb5_kt_free_entry(context, &entry);
+ return ret;
+}
+
+
+/**
+ * Set the keytab to use for authentication.
+ *
+ * @param context a Kerberos 5 context.
+ * @param ctx ctx krb5_init_creds_context context.
+ * @param keytab the keytab to read the key from.
+ *
+ * @return 0 for success, or an Kerberos 5 error code, see krb5_get_error_message().
+ * @ingroup krb5_credential
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_set_keytab(krb5_context context,
+ krb5_init_creds_context ctx,
+ krb5_keytab keytab)
+{
+ krb5_keytab_key_proc_args *a;
+
+ a = malloc(sizeof(*a));
+ if (a == NULL) {
+ krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+
+ a->principal = ctx->cred.client;
+ a->keytab = keytab;
+
+ ctx->keytab_data = a;
+ ctx->keyseed = (void *)a;
+ ctx->keyproc = keytab_key_proc;
+
+ return 0;
+}
+
+static krb5_error_code
+keyblock_key_proc(krb5_context context, krb5_enctype enctype,
+ krb5_const_pointer keyseed,
+ krb5_salt salt, krb5_data *s2kparms,
+ krb5_keyblock **key)
+{
+ return krb5_copy_keyblock (context, keyseed, key);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_set_keyblock(krb5_context context,
+ krb5_init_creds_context ctx,
+ krb5_keyblock *keyblock)
+{
+ ctx->keyseed = (void *)keyblock;
+ ctx->keyproc = keyblock_key_proc;
+
+ return 0;
+}
+
+/**
+ * The core loop if krb5_get_init_creds() function family. Create the
+ * packets and have the caller send them off to the KDC.
+ *
+ * If the caller want all work been done for them, use
+ * krb5_init_creds_get() instead.
+ *
+ * @param context a Kerberos 5 context.
+ * @param ctx ctx krb5_init_creds_context context.
+ * @param in input data from KDC, first round it should be reset by krb5_data_zer().
+ * @param out reply to KDC.
+ * @param hostinfo KDC address info, first round it can be NULL.
+ * @param flags status of the round, if 1 is set, continue one more round.
+ *
+ * @return 0 for success, or an Kerberos 5 error code, see
+ * krb5_get_error_message().
+ *
+ * @ingroup krb5_credential
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_step(krb5_context context,
+ krb5_init_creds_context ctx,
+ krb5_data *in,
+ krb5_data *out,
+ krb5_krbhst_info *hostinfo,
+ unsigned int *flags)
+{
+ krb5_error_code ret;
+ size_t len;
+ size_t size;
- memset (&rep, 0, sizeof(rep));
- ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size);
+ krb5_data_zero(out);
+
+ if (ctx->as_req.req_body.cname == NULL) {
+ ret = init_as_req(context, ctx->flags, &ctx->cred,
+ ctx->addrs, ctx->etypes, &ctx->as_req);
+ if (ret) {
+ free_init_creds_ctx(context, ctx);
+ return ret;
+ }
+ }
+
+#define MAX_PA_COUNTER 10
+ if (ctx->pa_counter > MAX_PA_COUNTER) {
+ krb5_set_error_message(context, KRB5_GET_IN_TKT_LOOP,
+ N_("Looping %d times while getting "
+ "initial credentials", ""),
+ ctx->pa_counter);
+ return KRB5_GET_IN_TKT_LOOP;
+ }
+ ctx->pa_counter++;
+
+ /* Lets process the input packet */
+ if (in && in->length) {
+ krb5_kdc_rep rep;
+
+ memset(&rep, 0, sizeof(rep));
+
+ ret = decode_AS_REP(in->data, in->length, &rep.kdc_rep, &size);
if (ret == 0) {
- krb5_data_free(&resp);
- krb5_clear_error_message(context);
- break;
+ krb5_keyblock *key = NULL;
+ unsigned eflags = EXTRACT_TICKET_AS_REQ;
+
+ if (ctx->flags.canonicalize) {
+ eflags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
+ eflags |= EXTRACT_TICKET_MATCH_REALM;
+ }
+ if (ctx->ic_flags & KRB5_INIT_CREDS_NO_C_CANON_CHECK)
+ eflags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
+
+ ret = process_pa_data_to_key(context, ctx, &ctx->cred,
+ &ctx->as_req, &rep.kdc_rep, hostinfo, &key);
+ if (ret) {
+ free_AS_REP(&rep.kdc_rep);
+ goto out;
+ }
+
+ ret = _krb5_extract_ticket(context,
+ &rep,
+ &ctx->cred,
+ key,
+ NULL,
+ KRB5_KU_AS_REP_ENC_PART,
+ NULL,
+ ctx->nonce,
+ eflags,
+ NULL,
+ NULL);
+ krb5_free_keyblock(context, key);
+
+ *flags = 0;
+
+ if (ret == 0)
+ ret = copy_EncKDCRepPart(&rep.enc_part, &ctx->enc_part);
+
+ free_AS_REP(&rep.kdc_rep);
+ free_EncASRepPart(&rep.enc_part);
+
+ return ret;
+
} else {
/* let's try to parse it as a KRB-ERROR */
- KRB_ERROR error;
- ret = krb5_rd_error(context, &resp, &error);
- if(ret && resp.data && ((char*)resp.data)[0] == 4)
+ free_KRB_ERROR(&ctx->error);
+
+ ret = krb5_rd_error(context, in, &ctx->error);
+ if(ret && in->length && ((char*)in->data)[0] == 4)
ret = KRB5KRB_AP_ERR_V4_REPLY;
- krb5_data_free(&resp);
if (ret)
goto out;
- ret = krb5_error_from_rd_error(context, &error, creds);
+ ret = krb5_error_from_rd_error(context, &ctx->error, &ctx->cred);
/*
* If no preauth was set and KDC requires it, give it one
@@ -1315,169 +1574,198 @@ init_cred_loop(krb5_context context,
*/
if (ret == KRB5KDC_ERR_PREAUTH_REQUIRED) {
- free_METHOD_DATA(&md);
- memset(&md, 0, sizeof(md));
- if (error.e_data) {
- ret = decode_METHOD_DATA(error.e_data->data,
- error.e_data->length,
- &md,
+ free_METHOD_DATA(&ctx->md);
+ memset(&ctx->md, 0, sizeof(ctx->md));
+
+ if (ctx->error.e_data) {
+ ret = decode_METHOD_DATA(ctx->error.e_data->data,
+ ctx->error.e_data->length,
+ &ctx->md,
NULL);
if (ret)
krb5_set_error_message(context, ret,
- N_("failed to decode METHOD DATA", ""));
+ N_("Failed to decode METHOD-DATA", ""));
} else {
- /* XXX guess what the server want here add add md */
+ krb5_set_error_message(context, ret,
+ N_("Preauth required but no preauth "
+ "options send by KDC", ""));
}
- krb5_free_error_contents(context, &error);
- if (ret)
+ } else if (ret == KRB5KRB_AP_ERR_SKEW && context->kdc_sec_offset == 0) {
+ /*
+ * Try adapt to timeskrew when we are using pre-auth, and
+ * if there was a time skew, try again.
+ */
+ krb5_set_real_time(context, ctx->error.stime, -1);
+ if (context->kdc_sec_offset)
+ ret = 0;
+ } else if (ret == KRB5_KDC_ERR_WRONG_REALM && ctx->flags.canonicalize) {
+ /* client referal to a new realm */
+ if (ctx->error.crealm) {
+ krb5_set_error_message(context, ret,
+ N_("Got a client referral, not but no realm", ""));
goto out;
- } else {
- _krb5_get_init_creds_opt_set_krb5_error(context,
- init_cred_opts,
- &error);
- if (ret_as_reply)
- rep.error = error;
- else
- krb5_free_error_contents(context, &error);
- goto out;
+ }
+ ret = krb5_principal_set_realm(context,
+ ctx->cred.client,
+ *ctx->error.crealm);
}
+ if (ret)
+ goto out;
}
}
- {
- krb5_keyblock *key = NULL;
- unsigned flags = EXTRACT_TICKET_AS_REQ;
+ if (ctx->as_req.padata) {
+ free_METHOD_DATA(ctx->as_req.padata);
+ free(ctx->as_req.padata);
+ ctx->as_req.padata = NULL;
+ }
- if (ctx->flags.request_anonymous)
- flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
- if (ctx->flags.canonicalize) {
- flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
- flags |= EXTRACT_TICKET_MATCH_REALM;
- }
- if (ctx->ic_flags & KRB5_INIT_CREDS_NO_C_CANON_CHECK)
- flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
+ /* Set a new nonce. */
+ ctx->as_req.req_body.nonce = ctx->nonce;
+
+ /* fill_in_md_data */
+ ret = process_pa_data_to_md(context, &ctx->cred, &ctx->as_req, ctx,
+ &ctx->md, &ctx->as_req.padata,
+ ctx->prompter, ctx->prompter_data);
+ if (ret)
+ goto out;
- ret = process_pa_data_to_key(context, ctx, creds,
- &ctx->as_req, &rep, hi, &key);
- if (ret)
- goto out;
-
- ret = _krb5_extract_ticket(context,
- &rep,
- creds,
- key,
- NULL,
- KRB5_KU_AS_REP_ENC_PART,
- NULL,
- ctx->nonce,
- flags,
- NULL,
- NULL);
- krb5_free_keyblock(context, key);
- }
-out:
- if (stctx)
- krb5_sendto_ctx_free(context, stctx);
krb5_data_free(&ctx->req_buffer);
- free_METHOD_DATA(&md);
- memset(&md, 0, sizeof(md));
- if (ret == 0 && ret_as_reply)
- *ret_as_reply = rep;
- else
- krb5_free_kdc_rep (context, &rep);
+ ASN1_MALLOC_ENCODE(AS_REQ,
+ ctx->req_buffer.data, ctx->req_buffer.length,
+ &ctx->as_req, &len, ret);
+ if (ret)
+ goto out;
+ if(len != ctx->req_buffer.length)
+ krb5_abortx(context, "internal error in ASN.1 encoder");
+
+ out->data = ctx->req_buffer.data;
+ out->length = ctx->req_buffer.length;
+
+ *flags = 1;
+
+ return 0;
+ out:
return ret;
}
+/**
+ * Extract the newly acquired credentials from krb5_init_creds_context
+ * context.
+ *
+ * @param context A Kerberos 5 context.
+ * @param ctx
+ * @param cred credentials, free with krb5_free_cred_contents().
+ *
+ * @return 0 for sucess or An Kerberos error code, see krb5_get_error_message().
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
-krb5_get_init_creds(krb5_context context,
- krb5_creds *creds,
- krb5_principal client,
- krb5_prompter_fct prompter,
- void *data,
- krb5_deltat start_time,
- const char *in_tkt_service,
- krb5_get_init_creds_opt *options)
+krb5_init_creds_get_creds(krb5_context context,
+ krb5_init_creds_context ctx,
+ krb5_creds *cred)
{
- krb5_get_init_creds_ctx ctx;
- krb5_kdc_rep kdc_reply;
- krb5_error_code ret;
- char buf[BUFSIZ];
- int done;
+ return krb5_copy_creds_contents(context, &ctx->cred, cred);
+}
+
+/**
+ * Get the last error from the transaction.
+ *
+ * @return Returns 0 or an error code
+ *
+ * @ingroup krb5_credential
+ */
- memset(&kdc_reply, 0, sizeof(kdc_reply));
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_get_error(krb5_context context,
+ krb5_init_creds_context ctx,
+ KRB_ERROR *error)
+{
+ krb5_error_code ret;
- ret = get_init_creds_common(context, client, start_time,
- in_tkt_service, options, &ctx);
+ ret = copy_KRB_ERROR(&ctx->error, error);
if (ret)
- goto out;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- done = 0;
- while(!done) {
- memset(&kdc_reply, 0, sizeof(kdc_reply));
-
- ret = init_cred_loop(context,
- options,
- prompter,
- data,
- &ctx,
- &ctx.cred,
- &kdc_reply);
-
- switch (ret) {
- case 0 :
- done = 1;
- break;
- case KRB5KDC_ERR_KEY_EXPIRED :
- /* try to avoid recursion */
+ return ret;
+}
- /* don't try to change password where then where none */
- if (prompter == NULL || ctx.password == NULL)
- goto out;
+/**
+ * Free the krb5_init_creds_context allocated by krb5_init_creds_init().
+ *
+ * @param context A Kerberos 5 context.
+ * @param ctx The krb5_init_creds_context to free.
+ *
+ * @ingroup krb5_credential
+ */
- krb5_clear_error_message (context);
+void KRB5_LIB_FUNCTION
+krb5_init_creds_free(krb5_context context,
+ krb5_init_creds_context ctx)
+{
+ free_init_creds_ctx(context, ctx);
+ free(ctx);
+}
- if (ctx.in_tkt_service != NULL
- && strcmp (ctx.in_tkt_service, "kadmin/changepw") == 0)
- goto out;
+/**
+ * Get new credentials as setup by the krb5_init_creds_context.
+ *
+ * @param context A Kerberos 5 context.
+ * @param ctx The krb5_init_creds_context to process.
+ *
+ * @ingroup krb5_credential
+ */
- ret = change_password (context,
- client,
- ctx.password,
- buf,
- sizeof(buf),
- prompter,
- data,
- options);
- if (ret)
- goto out;
- ctx.password = buf;
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_init_creds_get(krb5_context context, krb5_init_creds_context ctx)
+{
+ krb5_sendto_ctx stctx = NULL;
+ krb5_krbhst_info *hostinfo = NULL;
+ krb5_error_code ret;
+ krb5_data in, out;
+ unsigned int flags = 0;
+
+ krb5_data_zero(&in);
+ krb5_data_zero(&out);
+
+ ret = krb5_sendto_ctx_alloc(context, &stctx);
+ if (ret)
+ goto out;
+ krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);
+
+ while (1) {
+ flags = 0;
+ ret = krb5_init_creds_step(context, ctx, &in, &out, hostinfo, &flags);
+ krb5_data_free(&in);
+ if (ret)
+ goto out;
+
+ if ((flags & 1) == 0)
break;
- default:
+
+ ret = krb5_sendto_context (context, stctx, &out,
+ ctx->cred.client->realm, &in);
+ if (ret)
goto out;
- }
- }
- if (prompter)
- print_expire (context,
- krb5_principal_get_realm (context, ctx.cred.client),
- &kdc_reply,
- prompter,
- data);
+ }
out:
- memset (buf, 0, sizeof(buf));
- free_init_creds_ctx(context, &ctx);
- krb5_free_kdc_rep (context, &kdc_reply);
- if (ret == 0)
- *creds = ctx.cred;
- else
- krb5_free_cred_contents (context, &ctx.cred);
+ if (stctx)
+ krb5_sendto_ctx_free(context, stctx);
return ret;
}
+/**
+ * Get new credentials using password.
+ *
+ * @ingroup krb5_credential
+ */
+
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_password(krb5_context context,
krb5_creds *creds,
@@ -1487,29 +1775,23 @@ krb5_get_init_creds_password(krb5_context context,
void *data,
krb5_deltat start_time,
const char *in_tkt_service,
- krb5_get_init_creds_opt *in_options)
+ krb5_get_init_creds_opt *options)
{
- krb5_get_init_creds_opt *options;
+ krb5_init_creds_context ctx;
char buf[BUFSIZ];
krb5_error_code ret;
+ int chpw = 0;
- if (in_options == NULL) {
- const char *realm = krb5_principal_get_realm(context, client);
- ret = krb5_get_init_creds_opt_alloc(context, &options);
- if (ret == 0)
- krb5_get_init_creds_opt_set_default_flags(context,
- NULL,
- realm,
- options);
- } else
- ret = _krb5_get_init_creds_opt_copy(context, in_options, &options);
+ again:
+ ret = krb5_init_creds_init(context, client, prompter, data, start_time, options, &ctx);
if (ret)
- return ret;
+ goto out;
- if (password == NULL &&
- options->opt_private->password == NULL &&
- options->opt_private->pk_init_ctx == NULL)
- {
+ ret = krb5_init_creds_set_service(context, ctx, in_tkt_service);
+ if (ret)
+ goto out;
+
+ if (prompter != NULL && ctx->password == NULL && password == NULL) {
krb5_prompt prompt;
krb5_data password_data;
char *p, *q;
@@ -1528,40 +1810,67 @@ krb5_get_init_creds_password(krb5_context context,
free (q);
if (ret) {
memset (buf, 0, sizeof(buf));
- krb5_get_init_creds_opt_free(context, options);
ret = KRB5_LIBOS_PWDINTR;
krb5_clear_error_message (context);
- return ret;
+ goto out;
}
password = password_data.data;
}
- if (options->opt_private->password == NULL) {
- ret = krb5_get_init_creds_opt_set_pa_password(context, options,
- password, NULL);
- if (ret) {
- krb5_get_init_creds_opt_free(context, options);
- memset(buf, 0, sizeof(buf));
- return ret;
- }
+ if (password) {
+ ret = krb5_init_creds_set_password(context, ctx, password);
+ if (ret)
+ goto out;
}
- ret = krb5_get_init_creds(context, creds, client, prompter,
- data, start_time, in_tkt_service, options);
- krb5_get_init_creds_opt_free(context, options);
+ ret = krb5_init_creds_get(context, ctx);
+
+ if (ret == 0)
+ process_last_request(context, options, ctx);
+
+
+ if (ret == KRB5KDC_ERR_KEY_EXPIRED && chpw == 0) {
+ char buf[1024];
+
+ /* try to avoid recursion */
+ if (in_tkt_service != NULL && strcmp(in_tkt_service, "kadmin/changepw") == 0)
+ goto out;
+
+ /* don't try to change password where then where none */
+ if (prompter == NULL)
+ goto out;
+
+ ret = change_password (context,
+ client,
+ ctx->password,
+ buf,
+ sizeof(buf),
+ prompter,
+ data,
+ options);
+ if (ret)
+ goto out;
+ chpw = 1;
+ krb5_init_creds_free(context, ctx);
+ goto again;
+ }
+
+ out:
+ if (ret == 0)
+ krb5_init_creds_get_creds(context, ctx, creds);
+
+ if (ctx)
+ krb5_init_creds_free(context, ctx);
+
memset(buf, 0, sizeof(buf));
return ret;
}
-static krb5_error_code
-init_creds_keyblock_key_proc (krb5_context context,
- krb5_enctype type,
- krb5_salt salt,
- krb5_const_pointer keyseed,
- krb5_keyblock **key)
-{
- return krb5_copy_keyblock (context, keyseed, key);
-}
+/**
+ * Get new credentials using keyblock.
+ *
+ * @ingroup krb5_credential
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_get_init_creds_keyblock(krb5_context context,
@@ -1572,33 +1881,80 @@ krb5_get_init_creds_keyblock(krb5_context context,
const char *in_tkt_service,
krb5_get_init_creds_opt *options)
{
- struct krb5_get_init_creds_ctx ctx;
+ krb5_init_creds_context ctx;
krb5_error_code ret;
- ret = get_init_creds_common(context, client, start_time,
- in_tkt_service, options, &ctx);
+ memset(creds, 0, sizeof(*creds));
+
+ ret = krb5_init_creds_init(context, client, NULL, NULL, start_time, options, &ctx);
if (ret)
goto out;
- ret = krb5_get_in_cred (context,
- KDCOptions2int(ctx.flags),
- ctx.addrs,
- ctx.etypes,
- ctx.pre_auth_types,
- NULL,
- init_creds_keyblock_key_proc,
- keyblock,
- NULL,
- NULL,
- &ctx.cred,
- NULL);
-
- if (ret == 0 && creds)
- *creds = ctx.cred;
- else
- krb5_free_cred_contents (context, &ctx.cred);
+ ret = krb5_init_creds_set_service(context, ctx, in_tkt_service);
+ if (ret)
+ goto out;
+
+ ret = krb5_init_creds_set_keyblock(context, ctx, keyblock);
+ if (ret)
+ goto out;
+
+ ret = krb5_init_creds_get(context, ctx);
+
+ if (ret == 0)
+ process_last_request(context, options, ctx);
+
+ out:
+ if (ret == 0)
+ krb5_init_creds_get_creds(context, ctx, creds);
+
+ if (ctx)
+ krb5_init_creds_free(context, ctx);
+
+ return ret;
+}
+
+/**
+ * Get new credentials using keytab.
+ *
+ * @ingroup krb5_credential
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_init_creds_keytab(krb5_context context,
+ krb5_creds *creds,
+ krb5_principal client,
+ krb5_keytab keytab,
+ krb5_deltat start_time,
+ const char *in_tkt_service,
+ krb5_get_init_creds_opt *options)
+{
+ krb5_init_creds_context ctx;
+ krb5_error_code ret;
+
+ memset(creds, 0, sizeof(*creds));
+
+ ret = krb5_init_creds_init(context, client, NULL, NULL, start_time, options, &ctx);
+ if (ret)
+ goto out;
+
+ ret = krb5_init_creds_set_service(context, ctx, in_tkt_service);
+ if (ret)
+ goto out;
+
+ ret = krb5_init_creds_set_keytab(context, ctx, keytab);
+ if (ret)
+ goto out;
+
+ ret = krb5_init_creds_get(context, ctx);
+ if (ret == 0)
+ process_last_request(context, options, ctx);
out:
- free_init_creds_ctx(context, &ctx);
+ if (ret == 0)
+ krb5_init_creds_get_creds(context, ctx, creds);
+
+ if (ctx)
+ krb5_init_creds_free(context, ctx);
+
return ret;
}
diff --git a/source4/heimdal/lib/krb5/kcm.c b/source4/heimdal/lib/krb5/kcm.c
index 8a8f1efc11..f034341972 100644
--- a/source4/heimdal/lib/krb5/kcm.c
+++ b/source4/heimdal/lib/krb5/kcm.c
@@ -43,17 +43,24 @@
#include "kcm.h"
-RCSID("$Id$");
-
typedef struct krb5_kcmcache {
char *name;
struct sockaddr_un path;
char *door_path;
} krb5_kcmcache;
+typedef struct krb5_kcm_cursor {
+ unsigned long offset;
+ unsigned long length;
+ kcmuuid_t *uuids;
+} *krb5_kcm_cursor;
+
+
#define KCMCACHE(X) ((krb5_kcmcache *)(X)->data.data)
#define CACHENAME(X) (KCMCACHE(X)->name)
-#define KCMCURSOR(C) (*(uint32_t *)(C))
+#define KCMCURSOR(C) ((krb5_kcm_cursor)(C))
+
+#ifdef HAVE_DOOR_CREATE
static krb5_error_code
try_door(krb5_context context,
@@ -61,7 +68,6 @@ try_door(krb5_context context,
krb5_data *request_data,
krb5_data *response_data)
{
-#ifdef HAVE_DOOR_CREATE
door_arg_t arg;
int fd;
int ret;
@@ -91,10 +97,8 @@ try_door(krb5_context context,
return ret;
return 0;
-#else
- return KRB5_CC_IO;
-#endif
}
+#endif /* HAVE_DOOR_CREATE */
static krb5_error_code
try_unix_socket(krb5_context context,
@@ -143,9 +147,11 @@ kcm_send_request(krb5_context context,
ret = KRB5_CC_NOSUPP;
for (i = 0; i < context->max_retries; i++) {
+#ifdef HAVE_DOOR_CREATE
ret = try_door(context, k, &request_data, response_data);
if (ret == 0 && response_data->length != 0)
break;
+#endif
ret = try_unix_socket(context, k, &request_data, response_data);
if (ret == 0 && response_data->length != 0)
break;
@@ -207,7 +213,8 @@ kcm_alloc(krb5_context context, const char *name, krb5_ccache *id)
k = malloc(sizeof(*k));
if (k == NULL) {
- krb5_set_error_message(context, KRB5_CC_NOMEM, N_("malloc: out of memory", ""));
+ krb5_set_error_message(context, KRB5_CC_NOMEM,
+ N_("malloc: out of memory", ""));
return KRB5_CC_NOMEM;
}
@@ -309,8 +316,6 @@ kcm_free(krb5_context context, krb5_ccache *id)
memset(k, 0, sizeof(*k));
krb5_data_free(&(*id)->data);
}
-
- *id = NULL;
}
static const char *
@@ -609,10 +614,10 @@ kcm_get_first (krb5_context context,
krb5_cc_cursor *cursor)
{
krb5_error_code ret;
+ krb5_kcm_cursor c;
krb5_kcmcache *k = KCMCACHE(id);
krb5_storage *request, *response;
krb5_data response_data;
- int32_t tmp;
ret = kcm_storage_request(context, KCM_OP_GET_FIRST, &request);
if (ret)
@@ -625,27 +630,56 @@ kcm_get_first (krb5_context context,
}
ret = kcm_call(context, k, request, &response, &response_data);
- if (ret) {
- krb5_storage_free(request);
+ krb5_storage_free(request);
+ if (ret)
+ return ret;
+
+ c = calloc(1, sizeof(*c));
+ if (c == NULL) {
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret,
+ N_("malloc: out of memory", ""));
return ret;
}
- ret = krb5_ret_int32(response, &tmp);
- if (ret || tmp < 0)
- ret = KRB5_CC_IO;
+ while (1) {
+ ssize_t sret;
+ kcmuuid_t uuid;
+ void *ptr;
+
+ sret = krb5_storage_read(response, &uuid, sizeof(uuid));
+ if (sret == 0) {
+ ret = 0;
+ break;
+ } else if (sret != sizeof(uuid)) {
+ ret = EINVAL;
+ break;
+ }
+
+ ptr = realloc(c->uuids, sizeof(c->uuids[0]) * (c->length + 1));
+ if (ptr == NULL) {
+ free(c->uuids);
+ free(c);
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+ c->uuids = ptr;
+
+ memcpy(&c->uuids[c->length], &uuid, sizeof(uuid));
+ c->length += 1;
+ }
- krb5_storage_free(request);
krb5_storage_free(response);
krb5_data_free(&response_data);
- if (ret)
+ if (ret) {
+ free(c->uuids);
+ free(c);
return ret;
+ }
- *cursor = malloc(sizeof(tmp));
- if (*cursor == NULL)
- return KRB5_CC_NOMEM;
-
- KCMCURSOR(*cursor) = tmp;
+ *cursor = c;
return 0;
}
@@ -666,8 +700,15 @@ kcm_get_next (krb5_context context,
{
krb5_error_code ret;
krb5_kcmcache *k = KCMCACHE(id);
+ krb5_kcm_cursor c = KCMCURSOR(*cursor);
krb5_storage *request, *response;
krb5_data response_data;
+ ssize_t sret;
+
+ again:
+
+ if (c->offset >= c->length)
+ return KRB5_CC_END;
ret = kcm_storage_request(context, KCM_OP_GET_NEXT, &request);
if (ret)
@@ -679,23 +720,26 @@ kcm_get_next (krb5_context context,
return ret;
}
- ret = krb5_store_int32(request, KCMCURSOR(*cursor));
- if (ret) {
+ sret = krb5_storage_write(request,
+ &c->uuids[c->offset],
+ sizeof(c->uuids[c->offset]));
+ c->offset++;
+ if (sret != sizeof(c->uuids[c->offset])) {
krb5_storage_free(request);
- return ret;
+ krb5_clear_error_message(context);
+ return ENOMEM;
}
ret = kcm_call(context, k, request, &response, &response_data);
- if (ret) {
- krb5_storage_free(request);
- return ret;
+ krb5_storage_free(request);
+ if (ret == KRB5_CC_END) {
+ goto again;
}
ret = krb5_ret_creds(response, creds);
if (ret)
ret = KRB5_CC_IO;
- krb5_storage_free(request);
krb5_storage_free(response);
krb5_data_free(&response_data);
@@ -717,6 +761,7 @@ kcm_end_get (krb5_context context,
{
krb5_error_code ret;
krb5_kcmcache *k = KCMCACHE(id);
+ krb5_kcm_cursor c = KCMCURSOR(*cursor);
krb5_storage *request;
ret = kcm_storage_request(context, KCM_OP_END_GET, &request);
@@ -729,22 +774,14 @@ kcm_end_get (krb5_context context,
return ret;
}
- ret = krb5_store_int32(request, KCMCURSOR(*cursor));
- if (ret) {
- krb5_storage_free(request);
- return ret;
- }
-
ret = kcm_call(context, k, request, NULL, NULL);
- if (ret) {
- krb5_storage_free(request);
+ krb5_storage_free(request);
+ if (ret)
return ret;
- }
- krb5_storage_free(request);
+ free(c->uuids);
+ free(c);
- KCMCURSOR(*cursor) = 0;
- free(*cursor);
*cursor = NULL;
return ret;
diff --git a/source4/heimdal/lib/krb5/keyblock.c b/source4/heimdal/lib/krb5/keyblock.c
index aa6353d7c8..57ed7875fc 100644
--- a/source4/heimdal/lib/krb5/keyblock.c
+++ b/source4/heimdal/lib/krb5/keyblock.c
@@ -33,7 +33,13 @@
#include "krb5_locl.h"
-RCSID("$Id$");
+/**
+ * Zero out a keyblock
+ *
+ * @param keyblock keyblock to zero out
+ *
+ * @ingroup krb5_crypto
+ */
void KRB5_LIB_FUNCTION
krb5_keyblock_zero(krb5_keyblock *keyblock)
@@ -42,6 +48,15 @@ krb5_keyblock_zero(krb5_keyblock *keyblock)
krb5_data_zero(&keyblock->keyvalue);
}
+/**
+ * Free a keyblock's content, also zero out the content of the keyblock.
+ *
+ * @param context a Kerberos 5 context
+ * @param keyblock keyblock content to free, NULL is valid argument
+ *
+ * @ingroup krb5_crypto
+ */
+
void KRB5_LIB_FUNCTION
krb5_free_keyblock_contents(krb5_context context,
krb5_keyblock *keyblock)
@@ -54,6 +69,16 @@ krb5_free_keyblock_contents(krb5_context context,
}
}
+/**
+ * Free a keyblock, also zero out the content of the keyblock, uses
+ * krb5_free_keyblock_contents() to free the content.
+ *
+ * @param context a Kerberos 5 context
+ * @param keyblock keyblock to free, NULL is valid argument
+ *
+ * @ingroup krb5_crypto
+ */
+
void KRB5_LIB_FUNCTION
krb5_free_keyblock(krb5_context context,
krb5_keyblock *keyblock)
@@ -64,6 +89,19 @@ krb5_free_keyblock(krb5_context context,
}
}
+/**
+ * Copy a keyblock, free the output keyblock with
+ * krb5_free_keyblock_contents().
+ *
+ * @param context a Kerberos 5 context
+ * @param inblock the key to copy
+ * @param to the output key.
+ *
+ * @param 0 on success or a Kerberos 5 error code
+ *
+ * @ingroup krb5_crypto
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_keyblock_contents (krb5_context context,
const krb5_keyblock *inblock,
@@ -72,31 +110,62 @@ krb5_copy_keyblock_contents (krb5_context context,
return copy_EncryptionKey(inblock, to);
}
+/**
+ * Copy a keyblock, free the output keyblock with
+ * krb5_free_keyblock().
+ *
+ * @param context a Kerberos 5 context
+ * @param inblock the key to copy
+ * @param to the output key.
+ *
+ * @param 0 on success or a Kerberos 5 error code
+ *
+ * @ingroup krb5_crypto
+ */
+
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_copy_keyblock (krb5_context context,
const krb5_keyblock *inblock,
krb5_keyblock **to)
{
+ krb5_error_code ret;
krb5_keyblock *k;
+
+ *to = NULL;
- k = malloc (sizeof(*k));
+ k = calloc (1, sizeof(*k));
if (k == NULL) {
krb5_set_error_message(context, ENOMEM, "malloc: out of memory");
return ENOMEM;
}
+
+ ret = krb5_copy_keyblock_contents (context, inblock, k);
+ if (ret) {
+ free(k);
+ return ret;
+ }
*to = k;
- return krb5_copy_keyblock_contents (context, inblock, k);
+ return 0;
}
+/**
+ * Get encryption type of a keyblock.
+ *
+ * @ingroup krb5_crypto
+ */
+
krb5_enctype
krb5_keyblock_get_enctype(const krb5_keyblock *block)
{
return block->keytype;
}
-/*
+/**
* Fill in `key' with key data of type `enctype' from `data' of length
- * `size'. Key should be freed using krb5_free_keyblock_contents.
+ * `size'. Key should be freed using krb5_free_keyblock_contents().
+ *
+ * @ingroup krb5_crypto
*/
krb5_error_code KRB5_LIB_FUNCTION
diff --git a/source4/heimdal/lib/krb5/keytab.c b/source4/heimdal/lib/krb5/keytab.c
index aa7c77ce46..fcc74e847e 100644
--- a/source4/heimdal/lib/krb5/keytab.c
+++ b/source4/heimdal/lib/krb5/keytab.c
@@ -33,11 +33,114 @@
#include "krb5_locl.h"
-RCSID("$Id$");
+/**
+ * @page krb5_keytab_intro The keytab handing functions
+ * @section section_krb5_keytab Kerberos Keytabs
+ *
+ * See the library functions here: @ref krb5_keytab
+ *
+ * Keytabs are long term key storage for servers, their equvalment of
+ * password files.
+ *
+ * Normally the only function that useful for server are to specify
+ * what keytab to use to other core functions like krb5_rd_req()
+ * krb5_kt_resolve(), and krb5_kt_close().
+ *
+ * @subsection krb5_keytab_names Keytab names
+ *
+ * A keytab name is on the form type:residual. The residual part is
+ * specific to each keytab-type.
+ *
+ * When a keytab-name is resolved, the type is matched with an internal
+ * list of keytab types. If there is no matching keytab type,
+ * the default keytab is used. The current default type is FILE.
+ *
+ * The default value can be changed in the configuration file
+ * /etc/krb5.conf by setting the variable
+ * [defaults]default_keytab_name.
+ *
+ * The keytab types that are implemented in Heimdal are:
+ * - file
+ * store the keytab in a file, the type's name is FILE . The
+ * residual part is a filename. For compatibility with other
+ * Kerberos implemtation WRFILE and JAVA14 is also accepted. WRFILE
+ * has the same format as FILE. JAVA14 have a format that is
+ * compatible with older versions of MIT kerberos and SUN's Java
+ * based installation. They store a truncted kvno, so when the knvo
+ * excess 255, they are truncted in this format.
+ *
+ * - keytab
+ * store the keytab in a AFS keyfile (usually /usr/afs/etc/KeyFile ),
+ * the type's name is AFSKEYFILE. The residual part is a filename.
+ *
+ * - krb4
+ * the keytab is a Kerberos 4 srvtab that is on-the-fly converted to
+ * a keytab. The type's name is krb4 The residual part is a
+ * filename.
+ *
+ * - memory
+ * The keytab is stored in a memory segment. This allows sensitive
+ * and/or temporary data not to be stored on disk. The type's name
+ * is MEMORY. Each MEMORY keytab is referenced counted by and
+ * opened by the residual name, so two handles can point to the
+ * same memory area. When the last user closes the entry, it
+ * disappears.
+ *
+ *
+ * @subsection krb5_keytab_example Keytab example
+ *
+ * This is a minimalistic version of ktutil.
+ *
+ * @code
+int
+main (int argc, char **argv)
+{
+ krb5_context context;
+ krb5_keytab keytab;
+ krb5_kt_cursor cursor;
+ krb5_keytab_entry entry;
+ krb5_error_code ret;
+ char *principal;
-/*
- * Register a new keytab in `ops'
- * Return 0 or an error.
+ if (krb5_init_context (&context) != 0)
+ errx(1, "krb5_context");
+
+ ret = krb5_kt_default (context, &keytab);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_kt_default");
+
+ ret = krb5_kt_start_seq_get(context, keytab, &cursor);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_kt_start_seq_get");
+ while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0){
+ krb5_unparse_name_short(context, entry.principal, &principal);
+ printf("principal: %s\n", principal);
+ free(principal);
+ krb5_kt_free_entry(context, &entry);
+ }
+ ret = krb5_kt_end_seq_get(context, keytab, &cursor);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_kt_end_seq_get");
+ ret = krb5_kt_close(context, keytab);
+ if (ret)
+ krb5_err(context, 1, ret, "krb5_kt_close");
+ krb5_free_context(context);
+ return 0;
+}
+ * @endcode
+ *
+ */
+
+
+/**
+ * Register a new keytab backend.
+ *
+ * @param context a Keberos context.
+ * @param ops a backend to register.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -55,7 +158,8 @@ krb5_kt_register(krb5_context context,
tmp = realloc(context->kt_types,
(context->num_kt_types + 1) * sizeof(*context->kt_types));
if(tmp == NULL) {
- krb5_set_error_message(context, ENOMEM, N_("malloc: out of memory", ""));
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
return ENOMEM;
}
memcpy(&tmp[context->num_kt_types], ops,
@@ -65,12 +169,20 @@ krb5_kt_register(krb5_context context,
return 0;
}
-/*
+/**
* Resolve the keytab name (of the form `type:residual') in `name'
* into a keytab in `id'.
- * Return 0 or an error
+ *
+ * @param context a Keberos context.
+ * @param name name to resolve
+ * @param id resulting keytab, free with krb5_kt_close().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_resolve(krb5_context context,
const char *name,
@@ -120,9 +232,16 @@ krb5_kt_resolve(krb5_context context,
return ret;
}
-/*
+/**
* copy the name of the default keytab into `name'.
- * Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short.
+ *
+ * @param context a Keberos context.
+ * @param name buffer where the name will be written
+ * @param namesize length of name
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -135,9 +254,16 @@ krb5_kt_default_name(krb5_context context, char *name, size_t namesize)
return 0;
}
-/*
- * copy the name of the default modify keytab into `name'.
- * Return 0 or KRB5_CONFIG_NOTENUFSPACE if `namesize' is too short.
+/**
+ * Copy the name of the default modify keytab into `name'.
+ *
+ * @param context a Keberos context.
+ * @param name buffer where the name will be written
+ * @param namesize length of name
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -166,9 +292,15 @@ krb5_kt_default_modify_name(krb5_context context, char *name, size_t namesize)
return 0;
}
-/*
+/**
* Set `id' to the default keytab.
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param id the new default keytab.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -177,10 +309,20 @@ krb5_kt_default(krb5_context context, krb5_keytab *id)
return krb5_kt_resolve (context, context->default_keytab, id);
}
-/*
+/**
* Read the key identified by `(principal, vno, enctype)' from the
* keytab in `keyprocarg' (the default if == NULL) into `*key'.
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param keyprocarg
+ * @param principal
+ * @param vno
+ * @param enctype
+ * @param key
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -212,9 +354,18 @@ krb5_kt_read_service_key(krb5_context context,
return ret;
}
-/*
+/**
* Return the type of the `keytab' in the string `prefix of length
* `prefixsize'.
+ *
+ * @param context a Keberos context.
+ * @param keytab the keytab to get the prefix for
+ * @param prefix prefix buffer
+ * @param prefixsize length of prefix buffer
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -227,9 +378,17 @@ krb5_kt_get_type(krb5_context context,
return 0;
}
-/*
+/**
* Retrieve the name of the keytab `keytab' into `name', `namesize'
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param keytab the keytab to get the name for.
+ * @param name name buffer.
+ * @param namesize size of name buffer.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -241,10 +400,18 @@ krb5_kt_get_name(krb5_context context,
return (*keytab->get_name)(context, keytab, name, namesize);
}
-/*
+/**
* Retrieve the full name of the keytab `keytab' and store the name in
- * `str'. `str' needs to be freed by the caller using free(3).
- * Returns 0 or an error. On error, *str is set to NULL.
+ * `str'.
+ *
+ * @param context a Keberos context.
+ * @param keytab keytab to get name for.
+ * @param str the name of the keytab name, usee krb5_xfree() to free
+ * the string. On error, *str is set to NULL.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -275,9 +442,16 @@ krb5_kt_get_full_name(krb5_context context,
return 0;
}
-/*
+/**
* Finish using the keytab in `id'. All resources will be released,
- * even on errors. Return 0 or an error.
+ * even on errors.
+ *
+ * @param context a Keberos context.
+ * @param id keytab to close.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -292,10 +466,61 @@ krb5_kt_close(krb5_context context,
return ret;
}
+/**
+ * Destroy (remove) the keytab in `id'. All resources will be released,
+ * even on errors, does the equvalment of krb5_kt_close() on the resources.
+ *
+ * @param context a Keberos context.
+ * @param id keytab to destroy.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_kt_destroy(krb5_context context,
+ krb5_keytab id)
+{
+ krb5_error_code ret;
+
+ ret = (*id->destroy)(context, id);
+ krb5_kt_close(context, id);
+ return ret;
+}
+
/*
+ * Match any aliases in keytab `entry' with `principal'.
+ */
+
+static krb5_boolean
+compare_aliseses(krb5_context context,
+ krb5_keytab_entry *entry,
+ krb5_const_principal principal)
+{
+ unsigned int i;
+ if (entry->aliases == NULL)
+ return FALSE;
+ for (i = 0; i < entry->aliases->len; i++)
+ if (krb5_principal_compare(context, &entry->aliases->val[i], principal))
+ return TRUE;
+ return FALSE;
+}
+
+/**
* Compare `entry' against `principal, vno, enctype'.
* Any of `principal, vno, enctype' might be 0 which acts as a wildcard.
* Return TRUE if they compare the same, FALSE otherwise.
+ *
+ * @param context a Keberos context.
+ * @param entry an entry to match with.
+ * @param principal principal to match, NULL matches all principals.
+ * @param vno key version to match, 0 matches all key version numbers.
+ * @param enctype encryption type to match, 0 matches all encryption types.
+ *
+ * @return Return TRUE or match, FALSE if not matched.
+ *
+ * @ingroup krb5_keytab
*/
krb5_boolean KRB5_LIB_FUNCTION
@@ -306,7 +531,8 @@ krb5_kt_compare(krb5_context context,
krb5_enctype enctype)
{
if(principal != NULL &&
- !krb5_principal_compare(context, entry->principal, principal))
+ !(krb5_principal_compare(context, entry->principal, principal) ||
+ compare_aliseses(context, entry, principal)))
return FALSE;
if(vno && vno != entry->vno)
return FALSE;
@@ -315,11 +541,53 @@ krb5_kt_compare(krb5_context context,
return TRUE;
}
-/*
+krb5_error_code
+_krb5_kt_principal_not_found(krb5_context context,
+ krb5_error_code ret,
+ krb5_keytab id,
+ krb5_const_principal principal,
+ krb5_enctype enctype,
+ int kvno)
+{
+ char princ[256], kvno_str[25], *kt_name;
+ char *enctype_str = NULL;
+
+ krb5_unparse_name_fixed (context, principal, princ, sizeof(princ));
+ krb5_kt_get_full_name (context, id, &kt_name);
+ krb5_enctype_to_string(context, enctype, &enctype_str);
+
+ if (kvno)
+ snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno);
+ else
+ kvno_str[0] = '\0';
+
+ krb5_set_error_message (context, ret,
+ N_("Failed to find %s%s in keytab %s (%s)",
+ "principal, kvno, keytab file, enctype"),
+ princ,
+ kvno_str,
+ kt_name ? kt_name : "unknown keytab",
+ enctype_str ? enctype_str : "unknown enctype");
+ free(kt_name);
+ free(enctype_str);
+ return ret;
+}
+
+
+/**
* Retrieve the keytab entry for `principal, kvno, enctype' into `entry'
- * from the keytab `id'.
- * kvno == 0 is a wildcard and gives the keytab with the highest vno.
- * Return 0 or an error.
+ * from the keytab `id'. Matching is done like krb5_kt_compare().
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param principal principal to match, NULL matches all principals.
+ * @param kvno key version to match, 0 matches all key version numbers.
+ * @param enctype encryption type to match, 0 matches all encryption types.
+ * @param entry the returned entry, free with krb5_kt_free_entry().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -365,37 +633,23 @@ krb5_kt_get_entry(krb5_context context,
krb5_kt_free_entry(context, &tmp);
}
krb5_kt_end_seq_get (context, id, &cursor);
- if (entry->vno) {
- return 0;
- } else {
- char princ[256], kvno_str[25], *kt_name;
- char *enctype_str = NULL;
-
- krb5_unparse_name_fixed (context, principal, princ, sizeof(princ));
- krb5_kt_get_full_name (context, id, &kt_name);
- krb5_enctype_to_string(context, enctype, &enctype_str);
-
- if (kvno)
- snprintf(kvno_str, sizeof(kvno_str), "(kvno %d)", kvno);
- else
- kvno_str[0] = '\0';
-
- krb5_set_error_message (context, KRB5_KT_NOTFOUND,
- N_("Failed to find %s%s in keytab %s (%s)",
- "principal, kvno, keytab file, enctype"),
- princ,
- kvno_str,
- kt_name ? kt_name : "unknown keytab",
- enctype_str ? enctype_str : "unknown enctype");
- free(kt_name);
- free(enctype_str);
- return KRB5_KT_NOTFOUND;
- }
+ if (entry->vno == 0)
+ return _krb5_kt_principal_not_found(context, KRB5_KT_NOTFOUND,
+ id, principal, enctype, kvno);
+ return 0;
}
-/*
+/**
* Copy the contents of `in' into `out'.
- * Return 0 or an error. */
+ *
+ * @param context a Keberos context.
+ * @param in the keytab entry to copy.
+ * @param out the copy of the keytab entry, free with krb5_kt_free_entry().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_kt_copy_entry_contents(krb5_context context,
@@ -422,8 +676,15 @@ fail:
return ret;
}
-/*
+/**
* Free the contents of `entry'.
+ *
+ * @param context a Keberos context.
+ * @param entry the entry to free
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -436,9 +697,16 @@ krb5_kt_free_entry(krb5_context context,
return 0;
}
-/*
+/**
* Set `cursor' to point at the beginning of `id'.
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param cursor a newly allocated cursor, free with krb5_kt_end_seq_get().
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -456,10 +724,18 @@ krb5_kt_start_seq_get(krb5_context context,
return (*id->start_seq_get)(context, id, cursor);
}
-/*
- * Get the next entry from `id' pointed to by `cursor' and advance the
- * `cursor'.
- * Return 0 or an error.
+/**
+ * Get the next entry from keytab, advance the cursor. On last entry
+ * the function will return KRB5_KT_END.
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param entry the returned entry, free with krb5_kt_free_entry().
+ * @param cursor the cursor of the iteration.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -478,8 +754,16 @@ krb5_kt_next_entry(krb5_context context,
return (*id->next_entry)(context, id, entry, cursor);
}
-/*
+/**
* Release all resources associated with `cursor'.
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param cursor the cursor to free.
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -496,9 +780,16 @@ krb5_kt_end_seq_get(krb5_context context,
return (*id->end_seq_get)(context, id, cursor);
}
-/*
+/**
* Add the entry in `entry' to the keytab `id'.
- * Return 0 or an error.
+ *
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param entry the entry to add
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -516,9 +807,17 @@ krb5_kt_add_entry(krb5_context context,
return (*id->add)(context, id,entry);
}
-/*
- * Remove the entry `entry' from the keytab `id'.
- * Return 0 or an error.
+/**
+ * Remove an entry from the keytab, matching is done using
+ * krb5_kt_compare().
+
+ * @param context a Keberos context.
+ * @param id a keytab.
+ * @param entry the entry to remove
+ *
+ * @return Return an error code or 0, see krb5_get_error_message().
+ *
+ * @ingroup krb5_keytab
*/
krb5_error_code KRB5_LIB_FUNCTION
diff --git a/source4/heimdal/lib/krb5/keytab_any.c b/source4/heimdal/lib/krb5/keytab_any.c
index 7a2d9b9f70..02de8c8028 100644
--- a/source4/heimdal/lib/krb5/keytab_any.c
+++ b/source4/heimdal/lib/krb5/keytab_any.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
struct any_data {
krb5_keytab kt;
char *name;
@@ -253,6 +251,7 @@ const krb5_kt_ops krb5_any_ops = {
any_resolve,
any_get_name,
any_close,
+ NULL, /* destroy */
NULL, /* get */
any_start_seq_get,
any_next_entry,
diff --git a/source4/heimdal/lib/krb5/keytab_file.c b/source4/heimdal/lib/krb5/keytab_file.c
index f494cac253..819366443f 100644
--- a/source4/heimdal/lib/krb5/keytab_file.c
+++ b/source4/heimdal/lib/krb5/keytab_file.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
#define KRB5_KT_VNO_1 1
#define KRB5_KT_VNO_2 2
#define KRB5_KT_VNO KRB5_KT_VNO_2
@@ -332,6 +330,14 @@ fkt_close(krb5_context context, krb5_keytab id)
}
static krb5_error_code
+fkt_destroy(krb5_context context, krb5_keytab id)
+{
+ struct fkt_data *d = id->data;
+ _krb5_erase_file(context, d->filename);
+ return 0;
+}
+
+static krb5_error_code
fkt_get_name(krb5_context context,
krb5_keytab id,
char *name,
@@ -445,6 +451,7 @@ fkt_next_entry_int(krb5_context context,
int ret;
int8_t tmp8;
int32_t tmp32;
+ uint32_t utmp32;
off_t pos, curpos;
pos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
@@ -459,8 +466,8 @@ loop:
ret = krb5_kt_ret_principal (context, d, cursor->sp, &entry->principal);
if (ret)
goto out;
- ret = krb5_ret_int32(cursor->sp, &tmp32);
- entry->timestamp = tmp32;
+ ret = krb5_ret_uint32(cursor->sp, &utmp32);
+ entry->timestamp = utmp32;
if (ret)
goto out;
ret = krb5_ret_int8(cursor->sp, &tmp8);
@@ -476,10 +483,19 @@ loop:
curpos = krb5_storage_seek(cursor->sp, 0, SEEK_CUR);
if(len + 4 + pos - curpos >= 4) {
ret = krb5_ret_int32(cursor->sp, &tmp32);
- if (ret == 0 && tmp32 != 0) {
+ if (ret == 0 && tmp32 != 0)
entry->vno = tmp32;
- }
}
+ /* there might be a flags field here */
+ if(len + 4 + pos - curpos >= 8) {
+ ret = krb5_ret_uint32(cursor->sp, &utmp32);
+ if (ret == 0)
+ entry->flags = tmp32;
+ } else
+ entry->flags = 0;
+
+ entry->aliases = NULL;
+
if(start) *start = pos;
if(end) *end = pos + 4 + len;
out:
@@ -653,6 +669,15 @@ fkt_add_entry(krb5_context context,
krb5_storage_free(emem);
goto out;
}
+ ret = krb5_store_uint32 (emem, entry->flags);
+ if (ret) {
+ krb5_set_error_message(context, ret,
+ N_("Failed storing extended kvno "
+ "in keytab %s", ""),
+ d->filename);
+ krb5_storage_free(emem);
+ goto out;
+ }
}
ret = krb5_storage_to_data(emem, &keytab);
@@ -744,6 +769,7 @@ const krb5_kt_ops krb5_fkt_ops = {
fkt_resolve,
fkt_get_name,
fkt_close,
+ fkt_destroy,
NULL, /* get */
fkt_start_seq_get,
fkt_next_entry,
@@ -757,6 +783,7 @@ const krb5_kt_ops krb5_wrfkt_ops = {
fkt_resolve,
fkt_get_name,
fkt_close,
+ fkt_destroy,
NULL, /* get */
fkt_start_seq_get,
fkt_next_entry,
@@ -770,6 +797,7 @@ const krb5_kt_ops krb5_javakt_ops = {
fkt_resolve_java14,
fkt_get_name,
fkt_close,
+ fkt_destroy,
NULL, /* get */
fkt_start_seq_get,
fkt_next_entry,
diff --git a/source4/heimdal/lib/krb5/keytab_keyfile.c b/source4/heimdal/lib/krb5/keytab_keyfile.c
index 71d3d89d58..54666c7d44 100644
--- a/source4/heimdal/lib/krb5/keytab_keyfile.c
+++ b/source4/heimdal/lib/krb5/keytab_keyfile.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
#ifndef HEIMDAL_SMALLER
/* afs keyfile operations --------------------------------------- */
@@ -275,6 +273,8 @@ akf_next_entry(krb5_context context,
ret = 0;
entry->timestamp = time(NULL);
+ entry->flags = 0;
+ entry->aliases = NULL;
out:
krb5_storage_seek(cursor->sp, pos + 4 + 8, SEEK_SET);
@@ -440,6 +440,7 @@ const krb5_kt_ops krb5_akf_ops = {
akf_resolve,
akf_get_name,
akf_close,
+ NULL, /* destroy */
NULL, /* get */
akf_start_seq_get,
akf_next_entry,
diff --git a/source4/heimdal/lib/krb5/keytab_memory.c b/source4/heimdal/lib/krb5/keytab_memory.c
index defd10d67c..73ffa1c67d 100644
--- a/source4/heimdal/lib/krb5/keytab_memory.c
+++ b/source4/heimdal/lib/krb5/keytab_memory.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/* memory operations -------------------------------------------- */
struct mkt_data {
@@ -228,6 +226,7 @@ const krb5_kt_ops krb5_mkt_ops = {
mkt_resolve,
mkt_get_name,
mkt_close,
+ NULL, /* destroy */
NULL, /* get */
mkt_start_seq_get,
mkt_next_entry,
diff --git a/source4/heimdal/lib/krb5/krb5.h b/source4/heimdal/lib/krb5/krb5.h
index 0ba4e7b54a..13dafacf21 100644
--- a/source4/heimdal/lib/krb5/krb5.h
+++ b/source4/heimdal/lib/krb5/krb5.h
@@ -51,6 +51,10 @@
#define KRB5KDC_ERR_KEY_EXP KRB5KDC_ERR_KEY_EXPIRED
#endif
+#ifndef KRB5_DEPRECATED
+#define KRB5_DEPRECATED __attribute__((deprecated))
+#endif
+
/* simple constants */
#ifndef TRUE
@@ -92,6 +96,8 @@ typedef Checksum krb5_checksum;
typedef ENCTYPE krb5_enctype;
+typedef struct krb5_get_init_creds_ctx *krb5_init_creds_context;
+
typedef heim_octet_string krb5_data;
/* PKINIT related forward declarations */
@@ -219,6 +225,8 @@ typedef enum krb5_key_usage {
/* Keyusage for the server referral in a TGS req */
KRB5_KU_SAM_ENC_NONCE_SAD = 27,
/* Encryption of the SAM-NONCE-OR-SAD field */
+ KRB5_KU_PA_PKINIT_KX = 44,
+ /* Encryption type of the kdc session contribution in pk-init */
KRB5_KU_DIGEST_ENCRYPT = -18,
/* Encryption key usage used in the digest encryption field */
KRB5_KU_DIGEST_OPAQUE = -19,
@@ -272,13 +280,13 @@ typedef HostAddress krb5_address;
typedef HostAddresses krb5_addresses;
typedef enum krb5_keytype {
- KEYTYPE_NULL = 0,
- KEYTYPE_DES = 1,
- KEYTYPE_DES3 = 7,
- KEYTYPE_AES128 = 17,
- KEYTYPE_AES256 = 18,
- KEYTYPE_ARCFOUR = 23,
- KEYTYPE_ARCFOUR_56 = 24
+ KEYTYPE_NULL = ETYPE_NULL,
+ KEYTYPE_DES = ETYPE_DES_CBC_CRC,
+ KEYTYPE_DES3 = ETYPE_OLD_DES3_CBC_SHA1,
+ KEYTYPE_AES128 = ETYPE_AES128_CTS_HMAC_SHA1_96,
+ KEYTYPE_AES256 = ETYPE_AES256_CTS_HMAC_SHA1_96,
+ KEYTYPE_ARCFOUR = ETYPE_ARCFOUR_HMAC_MD5,
+ KEYTYPE_ARCFOUR_56 = ETYPE_ARCFOUR_HMAC_MD5_56
} krb5_keytype;
typedef EncryptionKey krb5_keyblock;
@@ -317,6 +325,7 @@ typedef const char *krb5_const_realm; /* stupid language */
typedef Principal krb5_principal_data;
typedef struct Principal *krb5_principal;
typedef const struct Principal *krb5_const_principal;
+typedef struct Principals *krb5_principals;
typedef time_t krb5_deltat;
typedef time_t krb5_timestamp;
@@ -478,6 +487,8 @@ typedef struct krb5_keytab_entry {
krb5_kvno vno;
krb5_keyblock keyblock;
uint32_t timestamp;
+ uint32_t flags;
+ krb5_principals aliases;
} krb5_keytab_entry;
typedef struct krb5_kt_cursor {
@@ -497,6 +508,7 @@ struct krb5_keytab_data {
krb5_error_code (*resolve)(krb5_context, const char*, krb5_keytab);
krb5_error_code (*get_name)(krb5_context, krb5_keytab, char*, size_t);
krb5_error_code (*close)(krb5_context, krb5_keytab);
+ krb5_error_code (*destroy)(krb5_context, krb5_keytab);
krb5_error_code (*get)(krb5_context, krb5_keytab, krb5_const_principal,
krb5_kvno, krb5_enctype, krb5_keytab_entry*);
krb5_error_code (*start_seq_get)(krb5_context, krb5_keytab, krb5_kt_cursor*);
@@ -593,7 +605,8 @@ typedef EncAPRepPart krb5_ap_rep_enc_part;
#define KRB5_TGS_NAME_SIZE (6)
#define KRB5_TGS_NAME ("krbtgt")
-
+#define KRB5_WELLKNOWN_NAME ("WELLKNOWN")
+#define KRB5_ANON_NAME ("ANONYMOUS")
#define KRB5_DIGEST_NAME ("digest")
typedef enum {
@@ -636,7 +649,7 @@ typedef krb5_error_code (*krb5_s2k_proc)(krb5_context /*context*/,
struct _krb5_get_init_creds_opt_private;
-typedef struct _krb5_get_init_creds_opt {
+struct _krb5_get_init_creds_opt {
krb5_flags flags;
krb5_deltat tkt_life;
krb5_deltat renew_life;
@@ -652,7 +665,9 @@ typedef struct _krb5_get_init_creds_opt {
int preauth_list_length;
krb5_data *salt;
struct _krb5_get_init_creds_opt_private *opt_private;
-} krb5_get_init_creds_opt;
+};
+
+typedef struct _krb5_get_init_creds_opt krb5_get_init_creds_opt;
#define KRB5_GET_INIT_CREDS_OPT_TKT_LIFE 0x0001
#define KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE 0x0002
@@ -661,7 +676,7 @@ typedef struct _krb5_get_init_creds_opt {
#define KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST 0x0010
#define KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST 0x0020
#define KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST 0x0040
-#define KRB5_GET_INIT_CREDS_OPT_SALT 0x0080
+#define KRB5_GET_INIT_CREDS_OPT_SALT 0x0080 /* no supported */
#define KRB5_GET_INIT_CREDS_OPT_ANONYMOUS 0x0100
#define KRB5_GET_INIT_CREDS_OPT_DISABLE_TRANSITED_CHECK 0x0200
@@ -727,22 +742,22 @@ enum {
typedef krb5_error_code (*krb5_send_to_kdc_func)(krb5_context,
void *,
krb5_krbhst_info *,
- time_t timeout,
+ time_t,
const krb5_data *,
krb5_data *);
-/* flags for krb5_parse_name_flags */
+/** flags for krb5_parse_name_flags */
enum {
- KRB5_PRINCIPAL_PARSE_NO_REALM = 1,
- KRB5_PRINCIPAL_PARSE_MUST_REALM = 2,
- KRB5_PRINCIPAL_PARSE_ENTERPRISE = 4
+ KRB5_PRINCIPAL_PARSE_NO_REALM = 1, /**< Require that there are no realm */
+ KRB5_PRINCIPAL_PARSE_REQUIRE_REALM = 2, /**< Require a realm present */
+ KRB5_PRINCIPAL_PARSE_ENTERPRISE = 4 /**< Parse as a NT-ENTERPRISE name */
};
-/* flags for krb5_unparse_name_flags */
+/** flags for krb5_unparse_name_flags */
enum {
- KRB5_PRINCIPAL_UNPARSE_SHORT = 1,
- KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2,
- KRB5_PRINCIPAL_UNPARSE_DISPLAY = 4
+ KRB5_PRINCIPAL_UNPARSE_SHORT = 1, /**< No realm if it is the default realm */
+ KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2, /**< No realm */
+ KRB5_PRINCIPAL_UNPARSE_DISPLAY = 4 /**< No quoting */
};
typedef struct krb5_sendto_ctx_data *krb5_sendto_ctx;
@@ -787,6 +802,20 @@ typedef struct krb5_crypto_iov {
} krb5_crypto_iov;
+/* Glue for MIT */
+
+typedef struct {
+ int32_t lr_type;
+ krb5_timestamp value;
+} krb5_last_req_entry;
+
+typedef krb5_error_code
+(*krb5_gic_process_last_req)(krb5_context, krb5_last_req_entry **, void *);
+
+/*
+ *
+ */
+
#include <krb5-protos.h>
/* variables */
@@ -810,5 +839,11 @@ extern KRB5_LIB_VARIABLE const krb5_kt_ops krb4_fkt_ops;
extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_srvtab_fkt_ops;
extern KRB5_LIB_VARIABLE const krb5_kt_ops krb5_any_ops;
+extern KRB5_LIB_VARIABLE const char *krb5_cc_type_api;
+extern KRB5_LIB_VARIABLE const char *krb5_cc_type_file;
+extern KRB5_LIB_VARIABLE const char *krb5_cc_type_memory;
+extern KRB5_LIB_VARIABLE const char *krb5_cc_type_kcm;
+extern KRB5_LIB_VARIABLE const char *krb5_cc_type_scc;
+
#endif /* __KRB5_H__ */
diff --git a/source4/heimdal/lib/krb5/krb5_ccapi.h b/source4/heimdal/lib/krb5/krb5_ccapi.h
index ec0cb3bc0b..5a7fe6a413 100644
--- a/source4/heimdal/lib/krb5/krb5_ccapi.h
+++ b/source4/heimdal/lib/krb5/krb5_ccapi.h
@@ -38,6 +38,10 @@
#include <krb5-types.h>
+ #ifdef __APPLE__
+#pragma pack(push,2)
+#endif
+
enum {
cc_credentials_v5 = 2
};
@@ -92,7 +96,7 @@ typedef struct cc_credentials_v5_t cc_credentials_v5_t;
typedef struct cc_credentials_t *cc_credentials_t;
typedef struct cc_credentials_iterator_t *cc_credentials_iterator_t;
typedef struct cc_string_t *cc_string_t;
-typedef time_t cc_time_t;
+typedef cc_uint32 cc_time_t;
typedef struct cc_data {
cc_uint32 type;
@@ -227,4 +231,9 @@ struct cc_context_t {
typedef cc_int32
(*cc_initialize_func)(cc_context_t*, cc_int32, cc_int32 *, char const **);
+#ifdef __APPLE__
+#pragma pack(pop)
+#endif
+
+
#endif /* KRB5_CCAPI_H */
diff --git a/source4/heimdal/lib/krb5/krb5_err.et b/source4/heimdal/lib/krb5/krb5_err.et
index c076992d0b..098e04b959 100644
--- a/source4/heimdal/lib/krb5/krb5_err.et
+++ b/source4/heimdal/lib/krb5/krb5_err.et
@@ -106,7 +106,13 @@ error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not suppo
#error_code ERR_KDC_NOT_FOUND, "IAKERB proxy could not find a KDC"
#error_code ERR_KDC_NO_RESPONSE, "IAKERB proxy never reeived a response from a KDC"
-# 82-127 are reserved
+# 82-93 are reserved
+
+index 94
+error_code INVALID_HASH_ALG, "Invalid OTP digest algorithm"
+error_code INVALID_ITERATION_COUNT, "Invalid OTP iteration count"
+
+# 97-127 are reserved
index 128
prefix
diff --git a/source4/heimdal/lib/krb5/krb5_locl.h b/source4/heimdal/lib/krb5/krb5_locl.h
index ced722f2d9..2d8bc07de3 100644
--- a/source4/heimdal/lib/krb5/krb5_locl.h
+++ b/source4/heimdal/lib/krb5/krb5_locl.h
@@ -36,9 +36,7 @@
#ifndef __KRB5_LOCL_H__
#define __KRB5_LOCL_H__
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include <errno.h>
#include <ctype.h>
@@ -214,11 +212,14 @@ struct _krb5_get_init_creds_opt_private {
krb5_get_init_creds_tristate req_pac;
/* PKINIT */
krb5_pk_init_ctx pk_init_ctx;
- KRB_ERROR *error;
krb5_get_init_creds_tristate addressless;
int flags;
#define KRB5_INIT_CREDS_CANONICALIZE 1
#define KRB5_INIT_CREDS_NO_C_CANON_CHECK 2
+ struct {
+ krb5_gic_process_last_req func;
+ void *ctx;
+ } lr;
};
typedef struct krb5_context_data {
@@ -261,6 +262,7 @@ typedef struct krb5_context_data {
int flags;
#define KRB5_CTX_F_DNS_CANONICALIZE_HOSTNAME 1
#define KRB5_CTX_F_CHECK_PAC 2
+#define KRB5_CTX_F_HOMEDIR_ACCESS 4
struct send_to_kdc *send_to_kdc;
} krb5_context_data;
@@ -295,6 +297,7 @@ struct krb5_pk_identity {
hx509_context hx509ctx;
hx509_verify_ctx verify_ctx;
hx509_certs certs;
+ hx509_cert cert;
hx509_certs anchors;
hx509_certs certpool;
hx509_revoke_ctx revokectx;
diff --git a/source4/heimdal/lib/krb5/krbhst.c b/source4/heimdal/lib/krb5/krbhst.c
index 7348ac3f00..e9111abec9 100644
--- a/source4/heimdal/lib/krb5/krbhst.c
+++ b/source4/heimdal/lib/krb5/krbhst.c
@@ -35,8 +35,6 @@
#include <resolve.h>
#include "locate_plugin.h"
-RCSID("$Id$");
-
static int
string_to_proto(const char *string)
{
@@ -61,8 +59,8 @@ srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count,
const char *proto, const char *service, int port)
{
char domain[1024];
- struct dns_reply *r;
- struct resource_record *rr;
+ struct rk_dns_reply *r;
+ struct rk_resource_record *rr;
int num_srv;
int proto_num;
int def_port;
@@ -87,32 +85,32 @@ srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count,
snprintf(domain, sizeof(domain), "_%s._%s.%s.", service, proto, realm);
- r = dns_lookup(domain, dns_type);
+ r = rk_dns_lookup(domain, dns_type);
if(r == NULL)
return KRB5_KDC_UNREACH;
for(num_srv = 0, rr = r->head; rr; rr = rr->next)
- if(rr->type == T_SRV)
+ if(rr->type == rk_ns_t_srv)
num_srv++;
*res = malloc(num_srv * sizeof(**res));
if(*res == NULL) {
- dns_free_data(r);
+ rk_dns_free_data(r);
krb5_set_error_message(context, ENOMEM,
N_("malloc: out of memory", ""));
return ENOMEM;
}
- dns_srv_order(r);
+ rk_dns_srv_order(r);
for(num_srv = 0, rr = r->head; rr; rr = rr->next)
- if(rr->type == T_SRV) {
+ if(rr->type == rk_ns_t_srv) {
krb5_krbhst_info *hi;
size_t len = strlen(rr->u.srv->target);
hi = calloc(1, sizeof(*hi) + len);
if(hi == NULL) {
- dns_free_data(r);
+ rk_dns_free_data(r);
while(--num_srv >= 0)
free((*res)[num_srv]);
free(*res);
@@ -134,7 +132,7 @@ srv_find_realm(krb5_context context, krb5_krbhst_info ***res, int *count,
*count = num_srv;
- dns_free_data(r);
+ rk_dns_free_data(r);
return 0;
}
@@ -948,7 +946,7 @@ gethostlist(krb5_context context, const char *realm,
return ENOMEM;
}
}
- (*hostlist)[nhost++] = NULL;
+ (*hostlist)[nhost] = NULL;
krb5_krbhst_free(context, handle);
return 0;
}
diff --git a/source4/heimdal/lib/krb5/locate_plugin.h b/source4/heimdal/lib/krb5/locate_plugin.h
index 529488ddfd..b1b1f0ef23 100644
--- a/source4/heimdal/lib/krb5/locate_plugin.h
+++ b/source4/heimdal/lib/krb5/locate_plugin.h
@@ -36,9 +36,7 @@
#ifndef HEIMDAL_KRB5_LOCATE_PLUGIN_H
#define HEIMDAL_KRB5_LOCATE_PLUGIN_H 1
-#include <krb5.h>
-
-#define KRB5_PLUGIN_LOCATE "resolve"
+#define KRB5_PLUGIN_LOCATE "service_locator"
enum locate_service_type {
locate_service_kdc = 1,
diff --git a/source4/heimdal/lib/krb5/log.c b/source4/heimdal/lib/krb5/log.c
index 587cf7ed97..31d267320f 100644
--- a/source4/heimdal/lib/krb5/log.c
+++ b/source4/heimdal/lib/krb5/log.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
struct facility {
int min;
int max;
diff --git a/source4/heimdal/lib/krb5/mcache.c b/source4/heimdal/lib/krb5/mcache.c
index 752608069d..78ef68db3d 100644
--- a/source4/heimdal/lib/krb5/mcache.c
+++ b/source4/heimdal/lib/krb5/mcache.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
typedef struct krb5_mcache {
char *name;
unsigned int refcnt;
diff --git a/source4/heimdal/lib/krb5/misc.c b/source4/heimdal/lib/krb5/misc.c
index 4cee5e22e1..e47383880c 100644
--- a/source4/heimdal/lib/krb5/misc.c
+++ b/source4/heimdal/lib/krb5/misc.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
_krb5_s4u2self_to_checksumdata(krb5_context context,
const PA_S4U2Self *self,
diff --git a/source4/heimdal/lib/krb5/mit_glue.c b/source4/heimdal/lib/krb5/mit_glue.c
index f8f13922f5..dab5c6046a 100644
--- a/source4/heimdal/lib/krb5/mit_glue.c
+++ b/source4/heimdal/lib/krb5/mit_glue.c
@@ -31,8 +31,9 @@
* SUCH DAMAGE.
*/
+#define KRB5_DEPRECATED
+
#include "krb5_locl.h"
-RCSID("$Id$");
#ifndef HEIMDAL_SMALLER
@@ -315,8 +316,9 @@ krb5_c_enctype_compare(krb5_context context,
krb5_enctype e1,
krb5_enctype e2,
krb5_boolean *similar)
+ KRB5_DEPRECATED
{
- *similar = krb5_enctypes_compatible_keys(context, e1, e2);
+ *similar = (e1 == e2);
return 0;
}
@@ -370,4 +372,18 @@ krb5_c_prf(krb5_context context,
return ret;
}
+/**
+ * MIT compat glue
+ *
+ * @ingroup krb5_ccache
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_cc_copy_creds(krb5_context context,
+ const krb5_ccache from,
+ krb5_ccache to)
+{
+ return krb5_cc_copy_cache(context, from, to);
+}
+
#endif /* HEIMDAL_SMALLER */
diff --git a/source4/heimdal/lib/krb5/mk_error.c b/source4/heimdal/lib/krb5/mk_error.c
index 989aa23d75..f623fc495b 100644
--- a/source4/heimdal/lib/krb5/mk_error.c
+++ b/source4/heimdal/lib/krb5/mk_error.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_error(krb5_context context,
krb5_error_code error_code,
diff --git a/source4/heimdal/lib/krb5/mk_priv.c b/source4/heimdal/lib/krb5/mk_priv.c
index 86a6b669b1..40f09ae33f 100644
--- a/source4/heimdal/lib/krb5/mk_priv.c
+++ b/source4/heimdal/lib/krb5/mk_priv.c
@@ -33,9 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_priv(krb5_context context,
krb5_auth_context auth_context,
diff --git a/source4/heimdal/lib/krb5/mk_rep.c b/source4/heimdal/lib/krb5/mk_rep.c
index bba276183a..8eef0ea652 100644
--- a/source4/heimdal/lib/krb5/mk_rep.c
+++ b/source4/heimdal/lib/krb5/mk_rep.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_rep(krb5_context context,
krb5_auth_context auth_context,
diff --git a/source4/heimdal/lib/krb5/mk_req.c b/source4/heimdal/lib/krb5/mk_req.c
index 1570637738..c87fa61293 100644
--- a/source4/heimdal/lib/krb5/mk_req.c
+++ b/source4/heimdal/lib/krb5/mk_req.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_mk_req_exact(krb5_context context,
krb5_auth_context *auth_context,
diff --git a/source4/heimdal/lib/krb5/mk_req_ext.c b/source4/heimdal/lib/krb5/mk_req_ext.c
index aba804716c..d130272aa1 100644
--- a/source4/heimdal/lib/krb5/mk_req_ext.c
+++ b/source4/heimdal/lib/krb5/mk_req_ext.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code
_krb5_mk_req_internal(krb5_context context,
krb5_auth_context *auth_context,
diff --git a/source4/heimdal/lib/krb5/n-fold.c b/source4/heimdal/lib/krb5/n-fold.c
index fa45b09f18..0623f6aae1 100644
--- a/source4/heimdal/lib/krb5/n-fold.c
+++ b/source4/heimdal/lib/krb5/n-fold.c
@@ -32,8 +32,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
static krb5_error_code
rr13(unsigned char *buf, size_t len)
{
@@ -109,8 +107,10 @@ _krb5_n_fold(const void *str, size_t len, void *key, size_t size)
unsigned char *tmp = malloc(maxlen);
unsigned char *buf = malloc(len);
- if (tmp == NULL || buf == NULL)
- return ENOMEM;
+ if (tmp == NULL || buf == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
memcpy(buf, str, len);
memset(key, 0, size);
@@ -129,9 +129,13 @@ _krb5_n_fold(const void *str, size_t len, void *key, size_t size)
}
} while(l != 0);
out:
- memset(buf, 0, len);
- free(buf);
- memset(tmp, 0, maxlen);
- free(tmp);
+ if (buf) {
+ memset(buf, 0, len);
+ free(buf);
+ }
+ if (tmp) {
+ memset(tmp, 0, maxlen);
+ free(tmp);
+ }
return ret;
}
diff --git a/source4/heimdal/lib/krb5/pac.c b/source4/heimdal/lib/krb5/pac.c
index 3c55eb3dc3..b66e79960d 100644
--- a/source4/heimdal/lib/krb5/pac.c
+++ b/source4/heimdal/lib/krb5/pac.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include <wind.h>
-RCSID("$Id$");
-
struct PAC_INFO_BUFFER {
uint32_t type;
uint32_t buffersize;
@@ -613,6 +611,7 @@ verify_logonname(krb5_context context,
ret = wind_ucs2utf8(ucs2, ucs2len, s, &u8len);
free(ucs2);
if (ret) {
+ free(s);
krb5_set_error_message(context, ret, "Failed to convert to UTF-8");
return ret;
}
diff --git a/source4/heimdal/lib/krb5/padata.c b/source4/heimdal/lib/krb5/padata.c
index 022260e709..aa08248ed1 100644
--- a/source4/heimdal/lib/krb5/padata.c
+++ b/source4/heimdal/lib/krb5/padata.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
PA_DATA *
krb5_find_padata(PA_DATA *val, unsigned len, int type, int *idx)
{
diff --git a/source4/heimdal/lib/krb5/pkinit.c b/source4/heimdal/lib/krb5/pkinit.c
index de5e90a68e..18b5b5e017 100644
--- a/source4/heimdal/lib/krb5/pkinit.c
+++ b/source4/heimdal/lib/krb5/pkinit.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
struct krb5_dh_moduli {
char *name;
unsigned long bits;
@@ -60,7 +58,13 @@ struct krb5_pk_cert {
struct krb5_pk_init_ctx_data {
struct krb5_pk_identity *id;
- DH *dh;
+ enum { USE_RSA, USE_DH, USE_ECDH } keyex;
+ union {
+ DH *dh;
+#ifdef HAVE_OPENSSL
+ EC_KEY *eckey;
+#endif
+ } u;
krb5_data *clientDHNonce;
struct krb5_dh_moduli **m;
hx509_peer_info peer;
@@ -122,6 +126,45 @@ integer_to_BN(krb5_context context, const char *field, const heim_integer *f)
return bn;
}
+static krb5_error_code
+select_dh_group(krb5_context context, DH *dh, unsigned long bits,
+ struct krb5_dh_moduli **moduli)
+{
+ const struct krb5_dh_moduli *m;
+
+ if (bits == 0) {
+ m = moduli[1]; /* XXX */
+ if (m == NULL)
+ m = moduli[0]; /* XXX */
+ } else {
+ int i;
+ for (i = 0; moduli[i] != NULL; i++) {
+ if (bits < moduli[i]->bits)
+ break;
+ }
+ if (moduli[i] == NULL) {
+ krb5_set_error_message(context, EINVAL,
+ N_("Did not find a DH group parameter "
+ "matching requirement of %lu bits", ""),
+ bits);
+ return EINVAL;
+ }
+ m = moduli[i];
+ }
+
+ dh->p = integer_to_BN(context, "p", &m->p);
+ if (dh->p == NULL)
+ return ENOMEM;
+ dh->g = integer_to_BN(context, "g", &m->g);
+ if (dh->g == NULL)
+ return ENOMEM;
+ dh->q = integer_to_BN(context, "q", &m->q);
+ if (dh->q == NULL)
+ return ENOMEM;
+
+ return 0;
+}
+
struct certfind {
const char *type;
const heim_oid *oid;
@@ -139,12 +182,12 @@ find_cert(krb5_context context, struct krb5_pk_identity *id,
struct certfind cf[3] = {
{ "PKINIT EKU" },
{ "MS EKU" },
- { "no" }
+ { "any (or no)" }
};
int i, ret;
- cf[0].oid = oid_id_pkekuoid();
- cf[1].oid = oid_id_pkinit_ms_eku();
+ cf[0].oid = &asn1_oid_id_pkekuoid;
+ cf[1].oid = &asn1_oid_id_pkinit_ms_eku;
cf[2].oid = NULL;
for (i = 0; i < sizeof(cf)/sizeof(cf[0]); i++) {
@@ -159,7 +202,7 @@ find_cert(krb5_context context, struct krb5_pk_identity *id,
if (ret == 0)
break;
pk_copy_error(context, id->hx509ctx, ret,
- "Failed cert for finding %s OID", cf[i].type);
+ "Failed finding certificate with %s OID", cf[i].type);
}
return ret;
}
@@ -173,37 +216,22 @@ create_signature(krb5_context context,
hx509_peer_info peer,
krb5_data *sd_data)
{
- hx509_cert cert = NULL;
- hx509_query *q = NULL;
- int ret;
-
- ret = hx509_query_alloc(id->hx509ctx, &q);
- if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
- "Allocate query to find signing certificate");
- return ret;
- }
+ int ret, flags = 0;
- hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
- hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
-
- ret = find_cert(context, id, q, &cert);
- hx509_query_free(id->hx509ctx, q);
- if (ret)
- return ret;
+ if (id->cert == NULL)
+ flags |= HX509_CMS_SIGNATURE_NO_SIGNER;
ret = hx509_cms_create_signed_1(id->hx509ctx,
- 0,
+ flags,
eContentType,
eContent->data,
eContent->length,
NULL,
- cert,
+ id->cert,
peer,
NULL,
id->certs,
sd_data);
- hx509_cert_free(cert);
if (ret) {
pk_copy_error(context, id->hx509ctx, ret,
"Create CMS signedData");
@@ -222,6 +250,9 @@ cert2epi(hx509_context context, void *ctx, hx509_cert c)
void *p;
int ret;
+ if (ids->len > 10)
+ return 0;
+
memset(&id, 0, sizeof(id));
ret = hx509_cert_get_subject(c, &subject);
@@ -319,7 +350,6 @@ static krb5_error_code
build_auth_pack(krb5_context context,
unsigned nonce,
krb5_pk_init_ctx ctx,
- DH *dh,
const KDC_REQ_BODY *body,
AuthPack *a)
{
@@ -368,12 +398,49 @@ build_auth_pack(krb5_context context,
if (ret)
return ret;
- if (dh) {
- DomainParameters dp;
- heim_integer dh_pub_key;
+ if (ctx->keyex == USE_DH || ctx->keyex == USE_ECDH) {
+ const char *moduli_file;
+ unsigned long dh_min_bits;
krb5_data dhbuf;
size_t size;
+ krb5_data_zero(&dhbuf);
+
+
+
+ moduli_file = krb5_config_get_string(context, NULL,
+ "libdefaults",
+ "moduli",
+ NULL);
+
+ dh_min_bits =
+ krb5_config_get_int_default(context, NULL, 0,
+ "libdefaults",
+ "pkinit_dh_min_bits",
+ NULL);
+
+ ret = _krb5_parse_moduli(context, moduli_file, &ctx->m);
+ if (ret)
+ return ret;
+
+ ctx->u.dh = DH_new();
+ if (ctx->u.dh == NULL) {
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
+
+ ret = select_dh_group(context, ctx->u.dh, dh_min_bits, ctx->m);
+ if (ret)
+ return ret;
+
+ if (DH_generate_key(ctx->u.dh) != 1) {
+ krb5_set_error_message(context, ENOMEM,
+ N_("pkinit: failed to generate DH key", ""));
+ return ENOMEM;
+ }
+
+
if (1 /* support_cached_dh */) {
ALLOC(a->clientDHNonce, 1);
if (a->clientDHNonce == NULL) {
@@ -385,7 +452,7 @@ build_auth_pack(krb5_context context,
krb5_clear_error_message(context);
return ret;
}
- memset(a->clientDHNonce->data, 0, a->clientDHNonce->length);
+ RAND_bytes(a->clientDHNonce->data, a->clientDHNonce->length);
ret = krb5_copy_data(context, a->clientDHNonce,
&ctx->clientDHNonce);
if (ret)
@@ -395,64 +462,135 @@ build_auth_pack(krb5_context context,
ALLOC(a->clientPublicValue, 1);
if (a->clientPublicValue == NULL)
return ENOMEM;
- ret = der_copy_oid(oid_id_dhpublicnumber(),
- &a->clientPublicValue->algorithm.algorithm);
- if (ret)
- return ret;
-
- memset(&dp, 0, sizeof(dp));
- ret = BN_to_integer(context, dh->p, &dp.p);
- if (ret) {
- free_DomainParameters(&dp);
- return ret;
- }
- ret = BN_to_integer(context, dh->g, &dp.g);
- if (ret) {
- free_DomainParameters(&dp);
- return ret;
- }
- ret = BN_to_integer(context, dh->q, &dp.q);
- if (ret) {
- free_DomainParameters(&dp);
- return ret;
- }
- dp.j = NULL;
- dp.validationParms = NULL;
+ if (ctx->keyex == USE_DH) {
+ DH *dh = ctx->u.dh;
+ DomainParameters dp;
+ heim_integer dh_pub_key;
- a->clientPublicValue->algorithm.parameters =
- malloc(sizeof(*a->clientPublicValue->algorithm.parameters));
- if (a->clientPublicValue->algorithm.parameters == NULL) {
+ ret = der_copy_oid(&asn1_oid_id_dhpublicnumber,
+ &a->clientPublicValue->algorithm.algorithm);
+ if (ret)
+ return ret;
+
+ memset(&dp, 0, sizeof(dp));
+
+ ret = BN_to_integer(context, dh->p, &dp.p);
+ if (ret) {
+ free_DomainParameters(&dp);
+ return ret;
+ }
+ ret = BN_to_integer(context, dh->g, &dp.g);
+ if (ret) {
+ free_DomainParameters(&dp);
+ return ret;
+ }
+ ret = BN_to_integer(context, dh->q, &dp.q);
+ if (ret) {
+ free_DomainParameters(&dp);
+ return ret;
+ }
+ dp.j = NULL;
+ dp.validationParms = NULL;
+
+ a->clientPublicValue->algorithm.parameters =
+ malloc(sizeof(*a->clientPublicValue->algorithm.parameters));
+ if (a->clientPublicValue->algorithm.parameters == NULL) {
+ free_DomainParameters(&dp);
+ return ret;
+ }
+
+ ASN1_MALLOC_ENCODE(DomainParameters,
+ a->clientPublicValue->algorithm.parameters->data,
+ a->clientPublicValue->algorithm.parameters->length,
+ &dp, &size, ret);
free_DomainParameters(&dp);
- return ret;
- }
+ if (ret)
+ return ret;
+ if (size != a->clientPublicValue->algorithm.parameters->length)
+ krb5_abortx(context, "Internal ASN1 encoder error");
+
+ ret = BN_to_integer(context, dh->pub_key, &dh_pub_key);
+ if (ret)
+ return ret;
+
+ ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length,
+ &dh_pub_key, &size, ret);
+ der_free_heim_integer(&dh_pub_key);
+ if (ret)
+ return ret;
+ if (size != dhbuf.length)
+ krb5_abortx(context, "asn1 internal error");
+ } else if (ctx->keyex == USE_ECDH) {
+#ifdef HAVE_OPENSSL
+ ECParameters ecp;
+ unsigned char *p;
+ int len;
+
+ /* copy in public key, XXX find the best curve that the server support or use the clients curve if possible */
+
+ ecp.element = choice_ECParameters_namedCurve;
+ ret = der_copy_oid(&asn1_oid_id_ec_group_secp256r1,
+ &ecp.u.namedCurve);
+ if (ret)
+ return ret;
- ASN1_MALLOC_ENCODE(DomainParameters,
- a->clientPublicValue->algorithm.parameters->data,
- a->clientPublicValue->algorithm.parameters->length,
- &dp, &size, ret);
- free_DomainParameters(&dp);
- if (ret)
- return ret;
- if (size != a->clientPublicValue->algorithm.parameters->length)
- krb5_abortx(context, "Internal ASN1 encoder error");
+ ALLOC(a->clientPublicValue->algorithm.parameters, 1);
+ if (a->clientPublicValue->algorithm.parameters == NULL) {
+ free_ECParameters(&ecp);
+ return ENOMEM;
+ }
+ ASN1_MALLOC_ENCODE(ECParameters, p, len, &ecp, &size, ret);
+ free_ECParameters(&ecp);
+ if (ret)
+ return ret;
+ if (size != len)
+ krb5_abortx(context, "asn1 internal error");
+
+ a->clientPublicValue->algorithm.parameters->data = p;
+ a->clientPublicValue->algorithm.parameters->length = size;
- ret = BN_to_integer(context, dh->pub_key, &dh_pub_key);
- if (ret)
- return ret;
+ /* copy in public key */
- ASN1_MALLOC_ENCODE(DHPublicKey, dhbuf.data, dhbuf.length,
- &dh_pub_key, &size, ret);
- der_free_heim_integer(&dh_pub_key);
- if (ret)
- return ret;
- if (size != dhbuf.length)
- krb5_abortx(context, "asn1 internal error");
+ ret = der_copy_oid(&asn1_oid_id_ecPublicKey,
+ &a->clientPublicValue->algorithm.algorithm);
+ if (ret)
+ return ret;
+
+ ctx->u.eckey = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+ if (ctx->u.eckey == NULL)
+ return ENOMEM;
+
+ ret = EC_KEY_generate_key(ctx->u.eckey);
+ if (ret != 1)
+ return EINVAL;
+ /* encode onto dhkey */
+
+ len = i2o_ECPublicKey(ctx->u.eckey, NULL);
+ if (len <= 0)
+ abort();
+
+ dhbuf.data = malloc(len);
+ if (dhbuf.data == NULL)
+ abort();
+ dhbuf.length = len;
+ p = dhbuf.data;
+
+ len = i2o_ECPublicKey(ctx->u.eckey, &p);
+ if (len <= 0)
+ abort();
+
+ /* XXX verify that this is right with RFC3279 */
+#else
+ return EINVAL;
+#endif
+ } else
+ krb5_abortx(context, "internal error");
a->clientPublicValue->subjectPublicKey.length = dhbuf.length * 8;
a->clientPublicValue->subjectPublicKey.data = dhbuf.data;
}
-
+
{
a->supportedCMSTypes = calloc(1, sizeof(*a->supportedCMSTypes));
if (a->supportedCMSTypes == NULL)
@@ -546,13 +684,13 @@ pk_mk_padata(krb5_context context,
if (buf.length != size)
krb5_abortx(context, "internal ASN1 encoder error");
- oid = oid_id_pkcs7_data();
+ oid = &asn1_oid_id_pkcs7_data;
} else if (ctx->type == PKINIT_27) {
AuthPack ap;
memset(&ap, 0, sizeof(ap));
- ret = build_auth_pack(context, nonce, ctx, ctx->dh, req_body, &ap);
+ ret = build_auth_pack(context, nonce, ctx, req_body, &ap);
if (ret) {
free_AuthPack(&ap);
goto out;
@@ -569,7 +707,7 @@ pk_mk_padata(krb5_context context,
if (buf.length != size)
krb5_abortx(context, "internal ASN1 encoder error");
- oid = oid_id_pkauthdata();
+ oid = &asn1_oid_id_pkauthdata;
} else
krb5_abortx(context, "internal pkinit error");
@@ -579,7 +717,7 @@ pk_mk_padata(krb5_context context,
if (ret)
goto out;
- ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &sd_buf, &buf);
+ ret = hx509_cms_wrap_ContentInfo(&asn1_oid_id_pkcs7_signedData, &sd_buf, &buf);
krb5_data_free(&sd_buf);
if (ret) {
krb5_set_error_message(context, ret,
@@ -648,8 +786,8 @@ pk_mk_padata(krb5_context context,
if (ret)
free(buf.data);
- if (ret == 0 && ctx->type == PKINIT_WIN2K)
- krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0);
+ if (ret == 0)
+ krb5_padata_add(context, md, KRB5_PADATA_PK_AS_09_BINDING, NULL, 0);
out:
free_ContentInfo(&content_info);
@@ -721,14 +859,14 @@ _krb5_pk_mk_padata(krb5_context context,
return pk_mk_padata(context, ctx, req_body, nonce, md);
}
-krb5_error_code KRB5_LIB_FUNCTION
-_krb5_pk_verify_sign(krb5_context context,
- const void *data,
- size_t length,
- struct krb5_pk_identity *id,
- heim_oid *contentType,
- krb5_data *content,
- struct krb5_pk_cert **signer)
+static krb5_error_code
+pk_verify_sign(krb5_context context,
+ const void *data,
+ size_t length,
+ struct krb5_pk_identity *id,
+ heim_oid *contentType,
+ krb5_data *content,
+ struct krb5_pk_cert **signer)
{
hx509_certs signer_certs;
int ret;
@@ -737,6 +875,7 @@ _krb5_pk_verify_sign(krb5_context context,
ret = hx509_cms_verify_signed(id->hx509ctx,
id->verify_ctx,
+ HX509_CMS_VS_ALLOW_DATA_OID_MISMATCH|HX509_CMS_VS_NO_KU_CHECK,
data,
length,
NULL,
@@ -902,7 +1041,7 @@ pk_verify_host(krb5_context context,
if (ctx->require_eku) {
ret = hx509_cert_check_eku(ctx->id->hx509ctx, host->cert,
- oid_id_pkkdcekuoid(), 0);
+ &asn1_oid_id_pkkdcekuoid, 0);
if (ret) {
krb5_set_error_message(context, ret,
N_("No PK-INIT KDC EKU in kdc certificate", ""));
@@ -915,7 +1054,7 @@ pk_verify_host(krb5_context context,
ret = hx509_cert_find_subjectAltName_otherName(ctx->id->hx509ctx,
host->cert,
- oid_id_pkinit_san(),
+ &asn1_oid_id_pkinit_san,
&list);
if (ret) {
krb5_set_error_message(context, ret,
@@ -995,16 +1134,20 @@ pk_rd_pa_reply_enckey(krb5_context context,
struct krb5_pk_cert *host = NULL;
krb5_data content;
heim_oid contentType = { 0, NULL };
+ int flags = HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT;
- if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), dataType)) {
+ if (der_heim_oid_cmp(&asn1_oid_id_pkcs7_envelopedData, dataType)) {
krb5_set_error_message(context, EINVAL,
N_("PKINIT: Invalid content type", ""));
return EINVAL;
}
+ if (ctx->type == PKINIT_WIN2K)
+ flags |= HX509_CMS_UE_ALLOW_WEAK;
+
ret = hx509_cms_unenvelope(ctx->id->hx509ctx,
ctx->id->certs,
- HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT,
+ flags,
indata->data,
indata->length,
NULL,
@@ -1042,7 +1185,9 @@ pk_rd_pa_reply_enckey(krb5_context context,
heim_octet_string out;
ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL);
- if (der_heim_oid_cmp(&type, oid_id_pkcs7_signedData())) {
+ if (ret)
+ goto out;
+ if (der_heim_oid_cmp(&type, &asn1_oid_id_pkcs7_signedData)) {
ret = EINVAL; /* XXX */
krb5_set_error_message(context, ret,
N_("PKINIT: Invalid content type", ""));
@@ -1061,13 +1206,13 @@ pk_rd_pa_reply_enckey(krb5_context context,
}
}
- ret = _krb5_pk_verify_sign(context,
- content.data,
- content.length,
- ctx->id,
- &contentType,
- &content,
- &host);
+ ret = pk_verify_sign(context,
+ content.data,
+ content.length,
+ ctx->id,
+ &contentType,
+ &content,
+ &host);
if (ret)
goto out;
@@ -1079,13 +1224,13 @@ pk_rd_pa_reply_enckey(krb5_context context,
#if 0
if (type == PKINIT_WIN2K) {
- if (der_heim_oid_cmp(&contentType, oid_id_pkcs7_data()) != 0) {
+ if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkcs7_data) != 0) {
ret = KRB5KRB_AP_ERR_MSG_TYPE;
krb5_set_error_message(context, ret, "PKINIT: reply key, wrong oid");
goto out;
}
} else {
- if (der_heim_oid_cmp(&contentType, oid_id_pkrkeydata()) != 0) {
+ if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkrkeydata) != 0) {
ret = KRB5KRB_AP_ERR_MSG_TYPE;
krb5_set_error_message(context, ret, "PKINIT: reply key, wrong oid");
goto out;
@@ -1131,32 +1276,33 @@ pk_rd_pa_reply_dh(krb5_context context,
PA_DATA *pa,
krb5_keyblock **key)
{
- unsigned char *p, *dh_gen_key = NULL;
+ const unsigned char *p;
+ unsigned char *dh_gen_key = NULL;
struct krb5_pk_cert *host = NULL;
BIGNUM *kdc_dh_pubkey = NULL;
KDCDHKeyInfo kdc_dh_info;
heim_oid contentType = { 0, NULL };
krb5_data content;
krb5_error_code ret;
- int dh_gen_keylen;
+ int dh_gen_keylen = 0;
size_t size;
krb5_data_zero(&content);
memset(&kdc_dh_info, 0, sizeof(kdc_dh_info));
- if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), dataType)) {
+ if (der_heim_oid_cmp(&asn1_oid_id_pkcs7_signedData, dataType)) {
krb5_set_error_message(context, EINVAL,
N_("PKINIT: Invalid content type", ""));
return EINVAL;
}
- ret = _krb5_pk_verify_sign(context,
- indata->data,
- indata->length,
- ctx->id,
- &contentType,
- &content,
- &host);
+ ret = pk_verify_sign(context,
+ indata->data,
+ indata->length,
+ ctx->id,
+ &contentType,
+ &content,
+ &host);
if (ret)
goto out;
@@ -1165,7 +1311,7 @@ pk_rd_pa_reply_dh(krb5_context context,
if (ret)
goto out;
- if (der_heim_oid_cmp(&contentType, oid_id_pkdhkeydata())) {
+ if (der_heim_oid_cmp(&contentType, &asn1_oid_id_pkdhkeydata)) {
ret = KRB5KRB_AP_ERR_MSG_TYPE;
krb5_set_error_message(context, ret,
N_("pkinit - dh reply contains wrong oid", ""));
@@ -1221,7 +1367,7 @@ pk_rd_pa_reply_dh(krb5_context context,
p = kdc_dh_info.subjectPublicKey.data;
size = (kdc_dh_info.subjectPublicKey.length + 7) / 8;
- {
+ if (ctx->keyex == USE_DH) {
DHPublicKey k;
ret = decode_DHPublicKey(p, size, &k, NULL);
if (ret) {
@@ -1237,30 +1383,78 @@ pk_rd_pa_reply_dh(krb5_context context,
ret = ENOMEM;
goto out;
}
- }
- dh_gen_keylen = DH_size(ctx->dh);
- size = BN_num_bytes(ctx->dh->p);
- if (size < dh_gen_keylen)
- size = dh_gen_keylen;
- dh_gen_key = malloc(size);
- if (dh_gen_key == NULL) {
- ret = ENOMEM;
- krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
- goto out;
- }
- memset(dh_gen_key, 0, size - dh_gen_keylen);
+ dh_gen_keylen = DH_size(ctx->u.dh);
+ size = BN_num_bytes(ctx->u.dh->p);
+ if (size < dh_gen_keylen)
+ size = dh_gen_keylen;
- dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen),
- kdc_dh_pubkey, ctx->dh);
- if (dh_gen_keylen == -1) {
- ret = KRB5KRB_ERR_GENERIC;
- krb5_set_error_message(context, ret,
- N_("PKINIT: Can't compute Diffie-Hellman key", ""));
- goto out;
- }
+ dh_gen_key = malloc(size);
+ if (dh_gen_key == NULL) {
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
+ }
+ memset(dh_gen_key, 0, size - dh_gen_keylen);
+
+ dh_gen_keylen = DH_compute_key(dh_gen_key + (size - dh_gen_keylen),
+ kdc_dh_pubkey, ctx->u.dh);
+ if (dh_gen_keylen == -1) {
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret,
+ N_("PKINIT: Can't compute Diffie-Hellman key", ""));
+ goto out;
+ }
+ } else {
+#ifdef HAVE_OPENSSL
+ const EC_GROUP *group;
+ EC_KEY *public = NULL;
+
+ group = EC_KEY_get0_group(ctx->u.eckey);
+
+ public = EC_KEY_new();
+ if (public == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+ if (EC_KEY_set_group(public, group) != 1) {
+ EC_KEY_free(public);
+ ret = ENOMEM;
+ goto out;
+ }
+ if (o2i_ECPublicKey(&public, &p, size) == NULL) {
+ EC_KEY_free(public);
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret,
+ N_("PKINIT: Can't parse ECDH public key", ""));
+ goto out;
+ }
+
+ size = (EC_GROUP_get_degree(group) + 7) / 8;
+ dh_gen_key = malloc(size);
+ if (dh_gen_key == NULL) {
+ EC_KEY_free(public);
+ ret = ENOMEM;
+ krb5_set_error_message(context, ret,
+ N_("malloc: out of memory", ""));
+ goto out;
+ }
+ dh_gen_keylen = ECDH_compute_key(dh_gen_key, size,
+ EC_KEY_get0_public_key(public), ctx->u.eckey, NULL);
+ EC_KEY_free(public);
+ if (dh_gen_keylen == -1) {
+ ret = KRB5KRB_ERR_GENERIC;
+ krb5_set_error_message(context, ret,
+ N_("PKINIT: Can't compute ECDH public key", ""));
+ goto out;
+ }
+#else
+ ret = EINVAL;
+#endif
+ }
+
*key = malloc (sizeof (**key));
if (*key == NULL) {
ret = ENOMEM;
@@ -1286,7 +1480,7 @@ pk_rd_pa_reply_dh(krb5_context context,
if (kdc_dh_pubkey)
BN_free(kdc_dh_pubkey);
if (dh_gen_key) {
- memset(dh_gen_key, 0, DH_size(ctx->dh));
+ memset(dh_gen_key, 0, dh_gen_keylen);
free(dh_gen_key);
}
if (host)
@@ -1343,12 +1537,42 @@ _krb5_pk_rd_pa_reply(krb5_context context,
case choice_PA_PK_AS_REP_encKeyPack:
os = rep.u.encKeyPack;
break;
- default:
+ default: {
+ PA_PK_AS_REP_BTMM btmm;
free_PA_PK_AS_REP(&rep);
- krb5_set_error_message(context, EINVAL,
- N_("PKINIT: -27 reply "
- "invalid content type", ""));
- return EINVAL;
+ memset(&rep, 0, sizeof(rep));
+
+ ret = decode_PA_PK_AS_REP_BTMM(pa->padata_value.data,
+ pa->padata_value.length,
+ &btmm,
+ &size);
+ if (ret) {
+ krb5_set_error_message(context, EINVAL,
+ N_("PKINIT: -27 reply "
+ "invalid content type", ""));
+ return EINVAL;
+ }
+
+ if (btmm.dhSignedData || btmm.encKeyPack == NULL) {
+ free_PA_PK_AS_REP_BTMM(&btmm);
+ ret = EINVAL;
+ krb5_set_error_message(context, ret,
+ N_("DH mode not supported for BTMM mode", ""));
+ return ret;
+ }
+
+ /*
+ * Transform to IETF style PK-INIT reply so that free works below
+ */
+
+ rep.element = choice_PA_PK_AS_REP_encKeyPack;
+ rep.u.encKeyPack.data = btmm.encKeyPack->data;
+ rep.u.encKeyPack.length = btmm.encKeyPack->length;
+ btmm.encKeyPack->data = NULL;
+ btmm.encKeyPack->length = 0;
+ free_PA_PK_AS_REP_BTMM(&btmm);
+ os = rep.u.encKeyPack;
+ }
}
ret = hx509_cms_unwrap_ContentInfo(&os, &oid, &data, NULL);
@@ -1484,18 +1708,10 @@ hx_pass_prompter(void *data, const hx509_prompt *prompter)
return 0;
}
-
-void KRB5_LIB_FUNCTION
-_krb5_pk_allow_proxy_certificate(struct krb5_pk_identity *id,
- int boolean)
-{
- hx509_verify_set_proxy_certificate(id->verify_ctx, boolean);
-}
-
-
krb5_error_code KRB5_LIB_FUNCTION
_krb5_pk_load_id(krb5_context context,
struct krb5_pk_identity **ret_id,
+ int flags,
const char *user_id,
const char *anchor_id,
char * const *chain_list,
@@ -1517,7 +1733,7 @@ _krb5_pk_load_id(krb5_context context,
return HEIM_PKINIT_NO_VALID_CA;
}
- if (user_id == NULL) {
+ if (user_id == NULL && (flags & 4) == 0) {
krb5_set_error_message(context, HEIM_PKINIT_NO_PRIVATE_KEY,
N_("PKINIT: No user certificate given", ""));
return HEIM_PKINIT_NO_PRIVATE_KEY;
@@ -1537,6 +1753,11 @@ _krb5_pk_load_id(krb5_context context,
goto out;
ret = hx509_lock_init(id->hx509ctx, &lock);
+ if (ret) {
+ pk_copy_error(context, id->hx509ctx, ret, "Failed init lock");
+ goto out;
+ }
+
if (password && password[0])
hx509_lock_add_password(lock, password);
@@ -1550,11 +1771,15 @@ _krb5_pk_load_id(krb5_context context,
goto out;
}
- ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs);
- if (ret) {
- pk_copy_error(context, id->hx509ctx, ret,
- "Failed to init cert certs");
- goto out;
+ if (user_id) {
+ ret = hx509_certs_init(id->hx509ctx, user_id, 0, lock, &id->certs);
+ if (ret) {
+ pk_copy_error(context, id->hx509ctx, ret,
+ "Failed to init cert certs");
+ goto out;
+ }
+ } else {
+ id->certs = NULL;
}
ret = hx509_certs_init(id->hx509ctx, anchor_id, 0, NULL, &id->anchors);
@@ -1628,50 +1853,12 @@ _krb5_pk_load_id(krb5_context context,
} else
*ret_id = id;
- hx509_lock_free(lock);
+ if (lock)
+ hx509_lock_free(lock);
return ret;
}
-static krb5_error_code
-select_dh_group(krb5_context context, DH *dh, unsigned long bits,
- struct krb5_dh_moduli **moduli)
-{
- const struct krb5_dh_moduli *m;
-
- if (bits == 0) {
- m = moduli[1]; /* XXX */
- if (m == NULL)
- m = moduli[0]; /* XXX */
- } else {
- int i;
- for (i = 0; moduli[i] != NULL; i++) {
- if (bits < moduli[i]->bits)
- break;
- }
- if (moduli[i] == NULL) {
- krb5_set_error_message(context, EINVAL,
- N_("Did not find a DH group parameter "
- "matching requirement of %lu bits", ""),
- bits);
- return EINVAL;
- }
- m = moduli[i];
- }
-
- dh->p = integer_to_BN(context, "p", &m->p);
- if (dh->p == NULL)
- return ENOMEM;
- dh->g = integer_to_BN(context, "g", &m->g);
- if (dh->g == NULL)
- return ENOMEM;
- dh->q = integer_to_BN(context, "q", &m->q);
- if (dh->q == NULL)
- return ENOMEM;
-
- return 0;
-}
-
/*
*
*/
@@ -1752,8 +1939,10 @@ _krb5_parse_moduli_line(krb5_context context,
while (isspace((unsigned char)*p))
p++;
- if (*p == '#')
+ if (*p == '#') {
+ free(m1);
return 0;
+ }
ret = EINVAL;
p1 = strsep(&p, " \t");
@@ -1764,7 +1953,7 @@ _krb5_parse_moduli_line(krb5_context context,
goto out;
}
m1->name = strdup(p1);
- if (p1 == NULL) {
+ if (m1->name == NULL) {
ret = ENOMEM;
krb5_set_error_message(context, ret, N_("malloc: out of memeory", ""));
goto out;
@@ -2002,12 +2191,22 @@ _krb5_get_init_creds_opt_free_pkinit(krb5_get_init_creds_opt *opt)
if (opt->opt_private == NULL || opt->opt_private->pk_init_ctx == NULL)
return;
ctx = opt->opt_private->pk_init_ctx;
- if (ctx->dh)
- DH_free(ctx->dh);
- ctx->dh = NULL;
+ switch (ctx->keyex) {
+ case USE_DH:
+ DH_free(ctx->u.dh);
+ break;
+ case USE_RSA:
+ break;
+ case USE_ECDH:
+#ifdef HAVE_OPENSSL
+ EC_KEY_free(ctx->u.eckey);
+#endif
+ break;
+ }
if (ctx->id) {
hx509_verify_destroy_ctx(ctx->id->verify_ctx);
hx509_certs_free(&ctx->id->certs);
+ hx509_cert_free(ctx->id->cert);
hx509_certs_free(&ctx->id->anchors);
hx509_certs_free(&ctx->id->certpool);
hx509_context_free(&ctx->id->hx509ctx);
@@ -2056,9 +2255,6 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
N_("malloc: out of memory", ""));
return ENOMEM;
}
- opt->opt_private->pk_init_ctx->dh = NULL;
- opt->opt_private->pk_init_ctx->id = NULL;
- opt->opt_private->pk_init_ctx->clientDHNonce = NULL;
opt->opt_private->pk_init_ctx->require_binding = 0;
opt->opt_private->pk_init_ctx->require_eku = 1;
opt->opt_private->pk_init_ctx->require_krbtgt_otherName = 1;
@@ -2086,6 +2282,7 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
ret = _krb5_pk_load_id(context,
&opt->opt_private->pk_init_ctx->id,
+ flags,
user_id,
x509_anchors,
pool,
@@ -2099,50 +2296,58 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
return ret;
}
- if ((flags & 2) == 0) {
- const char *moduli_file;
- unsigned long dh_min_bits;
-
- moduli_file = krb5_config_get_string(context, NULL,
- "libdefaults",
- "moduli",
- NULL);
+ if (opt->opt_private->pk_init_ctx->id->certs) {
+ hx509_query *q = NULL;
+ hx509_cert cert = NULL;
+ hx509_context hx509ctx = opt->opt_private->pk_init_ctx->id->hx509ctx;
- dh_min_bits =
- krb5_config_get_int_default(context, NULL, 0,
- "libdefaults",
- "pkinit_dh_min_bits",
- NULL);
-
- ret = _krb5_parse_moduli(context, moduli_file,
- &opt->opt_private->pk_init_ctx->m);
+ ret = hx509_query_alloc(hx509ctx, &q);
if (ret) {
- _krb5_get_init_creds_opt_free_pkinit(opt);
+ pk_copy_error(context, hx509ctx, ret,
+ "Allocate query to find signing certificate");
return ret;
}
- opt->opt_private->pk_init_ctx->dh = DH_new();
- if (opt->opt_private->pk_init_ctx->dh == NULL) {
- _krb5_get_init_creds_opt_free_pkinit(opt);
- krb5_set_error_message(context, ENOMEM,
- N_("malloc: out of memory", ""));
- return ENOMEM;
- }
-
- ret = select_dh_group(context, opt->opt_private->pk_init_ctx->dh,
- dh_min_bits,
- opt->opt_private->pk_init_ctx->m);
- if (ret) {
- _krb5_get_init_creds_opt_free_pkinit(opt);
+ hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
+ hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
+
+ ret = find_cert(context, opt->opt_private->pk_init_ctx->id, q, &cert);
+ hx509_query_free(hx509ctx, q);
+ if (ret)
return ret;
- }
- if (DH_generate_key(opt->opt_private->pk_init_ctx->dh) != 1) {
- _krb5_get_init_creds_opt_free_pkinit(opt);
- krb5_set_error_message(context, ENOMEM,
- N_("pkinit: failed to generate DH key", ""));
- return ENOMEM;
+ opt->opt_private->pk_init_ctx->id->cert = cert;
+ } else
+ opt->opt_private->pk_init_ctx->id->cert = NULL;
+
+ if ((flags & 2) == 0) {
+ hx509_context hx509ctx = opt->opt_private->pk_init_ctx->id->hx509ctx;
+ hx509_cert cert = opt->opt_private->pk_init_ctx->id->cert;
+
+ opt->opt_private->pk_init_ctx->keyex = USE_DH;
+
+ /*
+ * If its a ECDSA certs, lets select ECDSA as the keyex algorithm.
+ */
+ if (cert) {
+ AlgorithmIdentifier alg;
+
+ ret = hx509_cert_get_SPKI_AlgorithmIdentifier(hx509ctx, cert, &alg);
+ if (ret == 0) {
+ if (der_heim_oid_cmp(&alg.algorithm, &asn1_oid_id_ecPublicKey) == 0)
+ opt->opt_private->pk_init_ctx->keyex = USE_ECDH;
+ free_AlgorithmIdentifier(&alg);
+ }
}
+
+ } else {
+ opt->opt_private->pk_init_ctx->keyex = USE_RSA;
+
+ if (opt->opt_private->pk_init_ctx->id->certs == NULL) {
+ krb5_set_error_message(context, EINVAL,
+ N_("No anonymous pkinit support in RSA mode", ""));
+ return EINVAL;
+ }
}
return 0;
@@ -2152,3 +2357,122 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
return EINVAL;
#endif
}
+
+#ifdef PKINIT
+
+static int
+get_ms_san(hx509_context context, hx509_cert cert, char **upn)
+{
+ hx509_octet_string_list list;
+ int ret;
+
+ *upn = NULL;
+
+ ret = hx509_cert_find_subjectAltName_otherName(context,
+ cert,
+ &asn1_oid_id_pkinit_ms_san,
+ &list);
+ if (ret)
+ return 0;
+
+ if (list.len > 0 && list.val[0].length > 0)
+ ret = decode_MS_UPN_SAN(list.val[0].data, list.val[0].length,
+ upn, NULL);
+ else
+ ret = 1;
+ hx509_free_octet_string_list(&list);
+
+ return ret;
+}
+
+static int
+find_ms_san(hx509_context context, hx509_cert cert, void *ctx)
+{
+ char *upn;
+ int ret;
+
+ ret = get_ms_san(context, cert, &upn);
+ if (ret == 0)
+ free(upn);
+ return ret;
+}
+
+
+
+#endif
+
+/*
+ * Private since it need to be redesigned using krb5_get_init_creds()
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+_krb5_pk_enterprise_cert(krb5_context context,
+ const char *user_id,
+ krb5_const_realm realm,
+ krb5_principal *principal)
+{
+#ifdef PKINIT
+ krb5_error_code ret;
+ hx509_context hx509ctx;
+ hx509_certs certs, result;
+ hx509_cert cert;
+ hx509_query *q;
+ char *name;
+
+ *principal = NULL;
+
+ if (user_id == NULL)
+ return ENOENT;
+
+ ret = hx509_context_init(&hx509ctx);
+ if (ret)
+ return ret;
+
+ ret = hx509_certs_init(hx509ctx, user_id, 0, NULL, &certs);
+ if (ret) {
+ pk_copy_error(context, hx509ctx, ret,
+ "Failed to init cert certs");
+ return ret;
+ }
+
+ ret = hx509_query_alloc(hx509ctx, &q);
+ if (ret) {
+ hx509_certs_free(&certs);
+ return ret;
+ }
+
+ hx509_query_match_option(q, HX509_QUERY_OPTION_PRIVATE_KEY);
+ hx509_query_match_option(q, HX509_QUERY_OPTION_KU_DIGITALSIGNATURE);
+ hx509_query_match_eku(q, &asn1_oid_id_pkinit_ms_eku);
+ hx509_query_match_cmp_func(q, find_ms_san, NULL);
+
+ ret = hx509_certs_filter(hx509ctx, certs, q, &result);
+ hx509_query_free(hx509ctx, q);
+ hx509_certs_free(&certs);
+ if (ret)
+ return ret;
+
+ ret = hx509_get_one_cert(hx509ctx, result, &cert);
+ hx509_certs_free(&result);
+ if (ret)
+ return ret;
+
+ ret = get_ms_san(hx509ctx, cert, &name);
+ if (ret)
+ return ret;
+
+ ret = krb5_make_principal(context, principal, realm, name, NULL);
+ free(name);
+ hx509_context_free(&hx509ctx);
+ if (ret)
+ return ret;
+
+ krb5_principal_set_type(context, *principal, KRB5_NT_ENTERPRISE_PRINCIPAL);
+
+ return ret;
+#else
+ krb5_set_error_message(context, EINVAL,
+ N_("no support for PKINIT compiled in", ""));
+ return EINVAL;
+#endif
+}
diff --git a/source4/heimdal/lib/krb5/plugin.c b/source4/heimdal/lib/krb5/plugin.c
index a71dd8b6f7..844cb7ab88 100644
--- a/source4/heimdal/lib/krb5/plugin.c
+++ b/source4/heimdal/lib/krb5/plugin.c
@@ -32,7 +32,7 @@
*/
#include "krb5_locl.h"
-RCSID("$Id$");
+
#ifdef HAVE_DLFCN_H
#include <dlfcn.h>
#endif
@@ -54,7 +54,13 @@ struct plugin {
static HEIMDAL_MUTEX plugin_mutex = HEIMDAL_MUTEX_INITIALIZER;
static struct plugin *registered = NULL;
-static const char *plugin_dir = LIBDIR "/plugin/krb5";
+static const char *sysplugin_dirs[] = {
+ LIBDIR "/plugin/krb5",
+#ifdef __APPLE__
+ "/System/Library/KerberosPlugins/KerberosFrameworkPlugins",
+#endif
+ NULL
+};
/*
*
@@ -94,8 +100,11 @@ loadlib(krb5_context context,
#ifndef RTLD_LAZY
#define RTLD_LAZY 0
#endif
+#ifndef RTLD_LOCAL
+#define RTLD_LOCAL 0
+#endif
- (*e)->dsohandle = dlopen(lib, RTLD_LAZY);
+ (*e)->dsohandle = dlopen(lib, RTLD_LOCAL|RTLD_LAZY);
if ((*e)->dsohandle == NULL) {
free(*e);
*e = NULL;
@@ -173,7 +182,6 @@ _krb5_plugin_find(krb5_context context,
struct krb5_plugin *e;
struct plugin *p;
krb5_error_code ret;
- char *sysdirs[2] = { NULL, NULL };
char **dirs = NULL, **di;
struct dirent *entry;
char *path;
@@ -205,10 +213,8 @@ _krb5_plugin_find(krb5_context context,
dirs = krb5_config_get_strings(context, NULL, "libdefaults",
"plugin_dir", NULL);
- if (dirs == NULL) {
- sysdirs[0] = rk_UNCONST(plugin_dir);
- dirs = sysdirs;
- }
+ if (dirs == NULL)
+ dirs = rk_UNCONST(sysplugin_dirs);
for (di = dirs; *di != NULL; di++) {
@@ -218,7 +224,23 @@ _krb5_plugin_find(krb5_context context,
rk_cloexec(dirfd(d));
while ((entry = readdir(d)) != NULL) {
- asprintf(&path, "%s/%s", *di, entry->d_name);
+ char *n = entry->d_name;
+
+ /* skip . and .. */
+ if (n[0] == '.' && (n[1] == '\0' || (n[1] == '.' && n[2] == '\0')))
+ continue;
+
+ path = NULL;
+#ifdef __APPLE__
+ { /* support loading bundles on MacOS */
+ size_t len = strlen(n);
+ if (len > 7 && strcmp(&n[len - 7], ".bundle") == 0)
+ asprintf(&path, "%s/%s/Contents/MacOS/%.*s", *di, n, (int)(len - 7), n);
+ }
+#endif
+ if (path == NULL)
+ asprintf(&path, "%s/%s", *di, n);
+
if (path == NULL) {
ret = ENOMEM;
krb5_set_error_message(context, ret, "malloc: out of memory");
@@ -234,7 +256,7 @@ _krb5_plugin_find(krb5_context context,
}
closedir(d);
}
- if (dirs != sysdirs)
+ if (dirs != rk_UNCONST(sysplugin_dirs))
krb5_config_free_strings(dirs);
#endif /* HAVE_DLOPEN */
@@ -246,7 +268,7 @@ _krb5_plugin_find(krb5_context context,
return 0;
out:
- if (dirs && dirs != sysdirs)
+ if (dirs != rk_UNCONST(sysplugin_dirs))
krb5_config_free_strings(dirs);
if (d)
closedir(d);
diff --git a/source4/heimdal/lib/krb5/principal.c b/source4/heimdal/lib/krb5/principal.c
index f27355f2d8..50b7bb8813 100644
--- a/source4/heimdal/lib/krb5/principal.c
+++ b/source4/heimdal/lib/krb5/principal.c
@@ -32,7 +32,7 @@
*/
/**
- * @page page_principal The principal handing functions.
+ * @page krb5_principal_intro The principal handing functions.
*
* A Kerberos principal is a email address looking string that
* contains to parts separeted by a @. The later part is the kerbero
@@ -57,8 +57,6 @@ host/admin@H5L.ORG
#include <fnmatch.h>
#include "resolve.h"
-RCSID("$Id$");
-
#define princ_num_comp(P) ((P)->name.name_string.len)
#define princ_type(P) ((P)->name.name_type)
#define princ_comp(P) ((P)->name.name_string.val)
@@ -78,8 +76,6 @@ RCSID("$Id$");
* @ingroup krb5_principal
*/
-
-
void KRB5_LIB_FUNCTION
krb5_free_principal(krb5_context context,
krb5_principal p)
@@ -90,6 +86,18 @@ krb5_free_principal(krb5_context context,
}
}
+/**
+ * Set the type of the principal
+ *
+ * @param context A Kerberos context.
+ * @param principal principal to set the type for
+ * @param type the new type
+ *
+ * @return An krb5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_principal
+ */
+
void KRB5_LIB_FUNCTION
krb5_principal_set_type(krb5_context context,
krb5_principal principal,
@@ -127,8 +135,10 @@ krb5_principal_get_comp_string(krb5_context context,
*
* @param context Kerberos 5 context
* @param principal principal to query
+ *
* @return number of components in string
- * @ingroup krb5
+ *
+ * @ingroup krb5_principal
*/
unsigned int KRB5_LIB_FUNCTION
@@ -162,7 +172,7 @@ krb5_parse_name_flags(krb5_context context,
*principal = NULL;
-#define RFLAGS (KRB5_PRINCIPAL_PARSE_NO_REALM|KRB5_PRINCIPAL_PARSE_MUST_REALM)
+#define RFLAGS (KRB5_PRINCIPAL_PARSE_NO_REALM|KRB5_PRINCIPAL_PARSE_REQUIRE_REALM)
if ((flags & RFLAGS) == RFLAGS) {
krb5_set_error_message(context, KRB5_ERR_NO_SERVICE,
@@ -276,7 +286,7 @@ krb5_parse_name_flags(krb5_context context,
memcpy(realm, start, q - start);
realm[q - start] = 0;
}else{
- if (flags & KRB5_PRINCIPAL_PARSE_MUST_REALM) {
+ if (flags & KRB5_PRINCIPAL_PARSE_REQUIRE_REALM) {
ret = KRB5_PARSE_MALFORMED;
krb5_set_error_message(context, ret,
N_("realm NOT found in principal "
@@ -524,22 +534,6 @@ krb5_unparse_name_ext(krb5_context context,
#endif
-krb5_realm * KRB5_LIB_FUNCTION
-krb5_princ_realm(krb5_context context,
- krb5_principal principal)
-{
- return &princ_realm(principal);
-}
-
-
-void KRB5_LIB_FUNCTION
-krb5_princ_set_realm(krb5_context context,
- krb5_principal principal,
- krb5_realm *realm)
-{
- princ_realm(principal) = *realm;
-}
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_principal_set_realm(krb5_context context,
krb5_principal principal,
@@ -821,6 +815,7 @@ krb5_principal_match(krb5_context context,
return TRUE;
}
+#if defined(KRB4) || !defined(HEIMDAL_SMALLER)
static struct v4_name_convert {
const char *from;
@@ -835,6 +830,10 @@ static struct v4_name_convert {
{ NULL, NULL }
};
+#endif
+
+#ifdef KRB4
+
/*
* return the converted instance name of `name' in `realm'.
* look in the configuration file and then in the default set above.
@@ -925,6 +924,8 @@ krb5_425_conv_principal_ext2(krb5_context context,
if(p){
instance = p;
ret = krb5_make_principal(context, &pr, realm, name, instance, NULL);
+ if (ret)
+ return ret;
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
return 0;
@@ -938,23 +939,23 @@ krb5_425_conv_principal_ext2(krb5_context context,
krb5_boolean passed = FALSE;
char *inst = NULL;
#ifdef USE_RESOLVER
- struct dns_reply *r;
+ struct rk_dns_reply *r;
- r = dns_lookup(instance, "aaaa");
+ r = rk_dns_lookup(instance, "aaaa");
if (r) {
- if (r->head && r->head->type == T_AAAA) {
+ if (r->head && r->head->type == rk_ns_t_aaaa) {
inst = strdup(r->head->domain);
passed = TRUE;
}
- dns_free_data(r);
+ rk_dns_free_data(r);
} else {
- r = dns_lookup(instance, "a");
+ r = rk_dns_lookup(instance, "a");
if (r) {
- if(r->head && r->head->type == T_A) {
+ if(r->head && r->head->type == rk_ns_t_a) {
inst = strdup(r->head->domain);
passed = TRUE;
}
- dns_free_data(r);
+ rk_dns_free_data(r);
}
}
#else
@@ -998,6 +999,8 @@ krb5_425_conv_principal_ext2(krb5_context context,
snprintf(host, sizeof(host), "%s.%s", instance, realm);
strlwr(host);
ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
+ if (ret)
+ return ret;
if((*func)(context, funcctx, pr)){
*princ = pr;
return 0;
@@ -1025,6 +1028,10 @@ krb5_425_conv_principal_ext2(krb5_context context,
for(d = domains; d && *d; d++){
snprintf(host, sizeof(host), "%s.%s", instance, *d);
ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
+ if (ret) {
+ krb5_config_free_strings(domains);
+ return ret;
+ }
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
krb5_config_free_strings(domains);
@@ -1049,6 +1056,8 @@ krb5_425_conv_principal_ext2(krb5_context context,
snprintf(host, sizeof(host), "%s.%s", instance, p);
local_host:
ret = krb5_make_principal(context, &pr, realm, name, host, NULL);
+ if (ret)
+ return ret;
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
return 0;
@@ -1075,6 +1084,8 @@ no_host:
name = p;
ret = krb5_make_principal(context, &pr, realm, name, instance, NULL);
+ if (ret)
+ return ret;
if(func == NULL || (*func)(context, funcctx, pr)){
*princ = pr;
return 0;
@@ -1084,51 +1095,9 @@ no_host:
return HEIM_ERR_V4_PRINC_NO_CONV;
}
-static krb5_boolean
-convert_func(krb5_context conxtext, void *funcctx, krb5_principal principal)
-{
- krb5_boolean (*func)(krb5_context, krb5_principal) = funcctx;
- return (*func)(conxtext, principal);
-}
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_425_conv_principal_ext(krb5_context context,
- const char *name,
- const char *instance,
- const char *realm,
- krb5_boolean (*func)(krb5_context, krb5_principal),
- krb5_boolean resolve,
- krb5_principal *principal)
-{
- return krb5_425_conv_principal_ext2(context,
- name,
- instance,
- realm,
- func ? convert_func : NULL,
- func,
- resolve,
- principal);
-}
-
-
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_425_conv_principal(krb5_context context,
- const char *name,
- const char *instance,
- const char *realm,
- krb5_principal *princ)
-{
- krb5_boolean resolve = krb5_config_get_bool(context,
- NULL,
- "libdefaults",
- "v4_instance_resolve",
- NULL);
-
- return krb5_425_conv_principal_ext(context, name, instance, realm,
- NULL, resolve, princ);
-}
+#endif /* KRB4 */
+#ifndef HEIMDAL_SMALLER
static int
check_list(const krb5_config_binding *l, const char *name, const char **out)
@@ -1186,6 +1155,7 @@ name_convert(krb5_context context, const char *name, const char *realm,
return KRB5_NT_UNKNOWN;
/* didn't find it in config file, try built-in list */
+#ifdef KRB4
{
struct v4_name_convert *q;
for(q = default_v4_name_convert; q->from; q++) {
@@ -1195,6 +1165,7 @@ name_convert(krb5_context context, const char *name, const char *realm,
}
}
}
+#endif
return -1;
}
@@ -1273,6 +1244,8 @@ krb5_524_conv_principal(krb5_context context,
return 0;
}
+#endif /* !HEIMDAL_SMALLER */
+
/**
* Create a principal for the service running on hostname. If
* KRB5_NT_SRV_HST is used, the hostname is canonization using DNS (or
diff --git a/source4/heimdal/lib/krb5/prog_setup.c b/source4/heimdal/lib/krb5/prog_setup.c
index b368573b8d..4c060973d6 100644
--- a/source4/heimdal/lib/krb5/prog_setup.c
+++ b/source4/heimdal/lib/krb5/prog_setup.c
@@ -35,8 +35,6 @@
#include <getarg.h>
#include <err.h>
-RCSID("$Id$");
-
void KRB5_LIB_FUNCTION
krb5_std_usage(int code, struct getargs *args, int num_args)
{
diff --git a/source4/heimdal/lib/krb5/prompter_posix.c b/source4/heimdal/lib/krb5/prompter_posix.c
index 7d63935423..05deaff525 100644
--- a/source4/heimdal/lib/krb5/prompter_posix.c
+++ b/source4/heimdal/lib/krb5/prompter_posix.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
int KRB5_LIB_FUNCTION
krb5_prompter_posix (krb5_context context,
void *data,
diff --git a/source4/heimdal/lib/krb5/rd_cred.c b/source4/heimdal/lib/krb5/rd_cred.c
index dc51033019..f41edfa2b5 100644
--- a/source4/heimdal/lib/krb5/rd_cred.c
+++ b/source4/heimdal/lib/krb5/rd_cred.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
static krb5_error_code
compare_addrs(krb5_context context,
krb5_address *a,
@@ -149,15 +147,18 @@ krb5_rd_cred(krb5_context context,
goto out;
}
- ret = krb5_decode_EncKrbCredPart (context,
- enc_krb_cred_part_data.data,
- enc_krb_cred_part_data.length,
- &enc_krb_cred_part,
- &len);
+ ret = decode_EncKrbCredPart(enc_krb_cred_part_data.data,
+ enc_krb_cred_part_data.length,
+ &enc_krb_cred_part,
+ &len);
if (enc_krb_cred_part_data.data != cred.enc_part.cipher.data)
krb5_data_free(&enc_krb_cred_part_data);
- if (ret)
+ if (ret) {
+ krb5_set_error_message(context, ret,
+ N_("Failed to decode "
+ "encrypte credential part", ""));
goto out;
+ }
/* check sender address */
diff --git a/source4/heimdal/lib/krb5/rd_error.c b/source4/heimdal/lib/krb5/rd_error.c
index 75ae8b1e8a..1561188fad 100644
--- a/source4/heimdal/lib/krb5/rd_error.c
+++ b/source4/heimdal/lib/krb5/rd_error.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_error(krb5_context context,
const krb5_data *msg,
diff --git a/source4/heimdal/lib/krb5/rd_priv.c b/source4/heimdal/lib/krb5/rd_priv.c
index 6778ccad88..fb6cfcee4f 100644
--- a/source4/heimdal/lib/krb5/rd_priv.c
+++ b/source4/heimdal/lib/krb5/rd_priv.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_priv(krb5_context context,
krb5_auth_context auth_context,
diff --git a/source4/heimdal/lib/krb5/rd_rep.c b/source4/heimdal/lib/krb5/rd_rep.c
index 010726b180..2d5792cd40 100644
--- a/source4/heimdal/lib/krb5/rd_rep.c
+++ b/source4/heimdal/lib/krb5/rd_rep.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_rep(krb5_context context,
krb5_auth_context auth_context,
@@ -48,7 +46,6 @@ krb5_rd_rep(krb5_context context,
krb5_crypto crypto;
krb5_data_zero (&data);
- ret = 0;
ret = decode_AP_REP(inbuf->data, inbuf->length, &ap_rep, &len);
if (ret)
@@ -82,13 +79,11 @@ krb5_rd_rep(krb5_context context,
krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
goto out;
}
- ret = krb5_decode_EncAPRepPart(context,
- data.data,
- data.length,
- *repl,
- &len);
- if (ret)
+ ret = decode_EncAPRepPart(data.data, data.length, *repl, &len);
+ if (ret) {
+ krb5_set_error_message(context, ret, N_("Failed to decode EncAPRepPart", ""));
return ret;
+ }
if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
if ((*repl)->ctime != auth_context->authenticator->ctime ||
diff --git a/source4/heimdal/lib/krb5/rd_req.c b/source4/heimdal/lib/krb5/rd_req.c
index a416f90c10..784427fe40 100644
--- a/source4/heimdal/lib/krb5/rd_req.c
+++ b/source4/heimdal/lib/krb5/rd_req.c
@@ -33,8 +33,6 @@
#include <krb5_locl.h>
-RCSID("$Id$");
-
static krb5_error_code
decrypt_tkt_enc_part (krb5_context context,
krb5_keyblock *key,
@@ -58,8 +56,11 @@ decrypt_tkt_enc_part (krb5_context context,
if (ret)
return ret;
- ret = krb5_decode_EncTicketPart(context, plain.data, plain.length,
- decr_part, &len);
+ ret = decode_EncTicketPart(plain.data, plain.length, decr_part, &len);
+ if (ret)
+ krb5_set_error_message(context, ret,
+ N_("Failed to decode encrypted "
+ "ticket part", ""));
krb5_data_free (&plain);
return ret;
}
@@ -95,8 +96,8 @@ decrypt_authenticator (krb5_context context,
if (ret)
return ret;
- ret = krb5_decode_Authenticator(context, plain.data, plain.length,
- authenticator, &len);
+ ret = decode_Authenticator(plain.data, plain.length,
+ authenticator, &len);
krb5_data_free (&plain);
return ret;
}
@@ -521,10 +522,20 @@ struct krb5_rd_req_out_ctx_data {
krb5_keyblock *keyblock;
krb5_flags ap_req_options;
krb5_ticket *ticket;
+ krb5_principal server;
};
-/*
+/**
+ * Allocate a krb5_rd_req_in_ctx as an input parameter to
+ * krb5_rd_req_ctx(). The caller should free the context with
+ * krb5_rd_req_in_ctx_free() when done with the context.
+ *
+ * @param context Keberos 5 context.
+ * @param ctx in ctx to krb5_rd_req_ctx().
+ *
+ * @return Kerberos 5 error code, see krb5_get_error_message().
*
+ * @ingroup krb5_auth
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -540,12 +551,26 @@ krb5_rd_req_in_ctx_alloc(krb5_context context, krb5_rd_req_in_ctx *ctx)
return 0;
}
+/**
+ * Set the keytab that krb5_rd_req_ctx() will use.
+ *
+ * @param context Keberos 5 context.
+ * @param in in ctx to krb5_rd_req_ctx().
+ * @param keytab keytab that krb5_rd_req_ctx() will use, only copy the
+ * pointer, so the caller must free they keytab after
+ * krb5_rd_req_in_ctx_free() is called.
+ *
+ * @return Kerberos 5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_auth
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_rd_req_in_set_keytab(krb5_context context,
krb5_rd_req_in_ctx in,
krb5_keytab keytab)
{
- in->keytab = keytab; /* XXX should make copy */
+ in->keytab = keytab;
return 0;
}
@@ -558,7 +583,7 @@ krb5_rd_req_in_set_keytab(krb5_context context,
*
* @return Kerberos 5 error code, see krb5_get_error_message().
*
- * @ingroup krb5
+ * @ingroup krb5_auth
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -605,28 +630,50 @@ krb5_rd_req_out_get_keyblock(krb5_context context,
return krb5_copy_keyblock(context, out->keyblock, keyblock);
}
+/**
+ * Get the principal that was used in the request from the
+ * client. Might not match whats in the ticket if krb5_rd_req_ctx()
+ * searched in the keytab for a matching key.
+ *
+ * @param context a Kerberos 5 context.
+ * @param out a krb5_rd_req_out_ctx from krb5_rd_req_ctx().
+ * @param principal return principal, free with krb5_free_principal().
+ *
+ * @ingroup krb5_auth
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_rd_req_out_get_server(krb5_context context,
+ krb5_rd_req_out_ctx out,
+ krb5_principal *principal)
+{
+ return krb5_copy_principal(context, out->server, principal);
+}
+
void KRB5_LIB_FUNCTION
krb5_rd_req_in_ctx_free(krb5_context context, krb5_rd_req_in_ctx ctx)
{
free(ctx);
}
-krb5_error_code KRB5_LIB_FUNCTION
-_krb5_rd_req_out_ctx_alloc(krb5_context context, krb5_rd_req_out_ctx *ctx)
-{
- *ctx = calloc(1, sizeof(**ctx));
- if (*ctx == NULL) {
- krb5_set_error_message(context, ENOMEM,
- N_("malloc: out of memory", ""));
- return ENOMEM;
- }
- return 0;
-}
+/**
+ * Free the krb5_rd_req_out_ctx.
+ *
+ * @param context Keberos 5 context.
+ * @param ctx krb5_rd_req_out_ctx context to free.
+ *
+ * @ingroup krb5_auth
+ */
void KRB5_LIB_FUNCTION
krb5_rd_req_out_ctx_free(krb5_context context, krb5_rd_req_out_ctx ctx)
{
- krb5_free_keyblock(context, ctx->keyblock);
+ if (ctx->ticket)
+ krb5_free_ticket(context, ctx->ticket);
+ if (ctx->keyblock)
+ krb5_free_keyblock(context, ctx->keyblock);
+ if (ctx->server)
+ krb5_free_principal(context, ctx->server);
free(ctx);
}
@@ -726,7 +773,6 @@ out:
static krb5_error_code
get_key_from_keytab(krb5_context context,
- krb5_auth_context *auth_context,
krb5_ap_req *ap_req,
krb5_const_principal server,
krb5_keytab keytab,
@@ -764,8 +810,28 @@ out:
return ret;
}
-/*
+/**
+ * The core server function that verify application authentication
+ * requests from clients.
+ *
+ * @param context Keberos 5 context.
+ * @param auth_context the authentication context, can be NULL, then
+ * default values for the authentication context will used.
+ * @param inbuf the (AP-REQ) authentication buffer
+ *
+ * @param server the server with authenticate as, if NULL the function
+ * will try to find any avaiable credentintial in the keytab
+ * that will verify the reply. The function will prefer the
+ * server the server client specified in the AP-REQ, but if
+ * there is no mach, it will try all keytab entries for a
+ * match. This have serious performance issues for larger keytabs.
*
+ * @param inctx control the behavior of the function, if NULL, the
+ * default behavior is used.
+ * @param outctx the return outctx, free with krb5_rd_req_out_ctx_free().
+ * @return Kerberos 5 error code, see krb5_get_error_message().
+ *
+ * @ingroup krb5_auth
*/
krb5_error_code KRB5_LIB_FUNCTION
@@ -778,12 +844,18 @@ krb5_rd_req_ctx(krb5_context context,
{
krb5_error_code ret;
krb5_ap_req ap_req;
- krb5_principal service = NULL;
krb5_rd_req_out_ctx o = NULL;
+ krb5_keytab id = NULL, keytab = NULL;
+ krb5_principal service = NULL;
- ret = _krb5_rd_req_out_ctx_alloc(context, &o);
- if (ret)
- goto out;
+ *outctx = NULL;
+
+ o = calloc(1, sizeof(*o));
+ if (o == NULL) {
+ krb5_set_error_message(context, ENOMEM,
+ N_("malloc: out of memory", ""));
+ return ENOMEM;
+ }
if (*auth_context == NULL) {
ret = krb5_auth_con_init(context, auth_context);
@@ -795,15 +867,14 @@ krb5_rd_req_ctx(krb5_context context,
if(ret)
goto out;
- if(server == NULL){
- ret = _krb5_principalname2krb5_principal(context,
- &service,
- ap_req.ticket.sname,
- ap_req.ticket.realm);
- if (ret)
- goto out;
- server = service;
- }
+ /* Save that principal that was in the request */
+ ret = _krb5_principalname2krb5_principal(context,
+ &o->server,
+ ap_req.ticket.sname,
+ ap_req.ticket.realm);
+ if (ret)
+ goto out;
+
if (ap_req.ap_options.use_session_key &&
(*auth_context)->keyblock == NULL) {
ret = KRB5KRB_AP_ERR_NOKEY;
@@ -813,49 +884,155 @@ krb5_rd_req_ctx(krb5_context context,
goto out;
}
+ if (inctx && inctx->keytab)
+ id = inctx->keytab;
+
if((*auth_context)->keyblock){
ret = krb5_copy_keyblock(context,
(*auth_context)->keyblock,
&o->keyblock);
if (ret)
goto out;
- } else if(inctx->keyblock){
+ } else if(inctx && inctx->keyblock){
ret = krb5_copy_keyblock(context,
inctx->keyblock,
&o->keyblock);
if (ret)
goto out;
} else {
- krb5_keytab keytab = NULL;
- if (inctx && inctx->keytab)
- keytab = inctx->keytab;
+ if(id == NULL) {
+ krb5_kt_default(context, &keytab);
+ id = keytab;
+ }
+ if (id == NULL)
+ goto out;
+
+ if (server == NULL) {
+ ret = _krb5_principalname2krb5_principal(context,
+ &service,
+ ap_req.ticket.sname,
+ ap_req.ticket.realm);
+ if (ret)
+ goto out;
+ server = service;
+ }
ret = get_key_from_keytab(context,
- auth_context,
&ap_req,
server,
- keytab,
+ id,
&o->keyblock);
- if(ret)
- goto out;
+ if (ret) {
+ /* If caller specified a server, fail. */
+ if (service == NULL)
+ goto out;
+ /* Otherwise, fall back to iterating over the keytab. This
+ * have serious performace issues for larger keytab.
+ */
+ o->keyblock = NULL;
+ }
}
- ret = krb5_verify_ap_req2(context,
- auth_context,
- &ap_req,
- server,
- o->keyblock,
- 0,
- &o->ap_req_options,
- &o->ticket,
- KRB5_KU_AP_REQ_AUTH);
+ if (o->keyblock) {
+ /*
+ * We got an exact keymatch, use that.
+ */
- if (ret)
- goto out;
+ ret = krb5_verify_ap_req2(context,
+ auth_context,
+ &ap_req,
+ server,
+ o->keyblock,
+ 0,
+ &o->ap_req_options,
+ &o->ticket,
+ KRB5_KU_AP_REQ_AUTH);
+
+ if (ret)
+ goto out;
+
+ } else {
+ /*
+ * Interate over keytab to find a key that can decrypt the request.
+ */
+
+ krb5_keytab_entry entry;
+ krb5_kt_cursor cursor;
+ int done = 0, kvno = 0;
+
+ memset(&cursor, 0, sizeof(cursor));
+
+ if (ap_req.ticket.enc_part.kvno)
+ kvno = *ap_req.ticket.enc_part.kvno;
+
+ ret = krb5_kt_start_seq_get(context, id, &cursor);
+ if (ret)
+ goto out;
+
+ done = 0;
+ while (!done) {
+ krb5_principal p;
+
+ ret = krb5_kt_next_entry(context, id, &entry, &cursor);
+ if (ret) {
+ _krb5_kt_principal_not_found(context, ret, id, o->server,
+ ap_req.ticket.enc_part.etype,
+ kvno);
+ goto out;
+ }
+
+ if (entry.keyblock.keytype != ap_req.ticket.enc_part.etype ||
+ (kvno && kvno != entry.vno)) {
+ krb5_kt_free_entry (context, &entry);
+ continue;
+ }
+
+ ret = krb5_verify_ap_req2(context,
+ auth_context,
+ &ap_req,
+ server,
+ &entry.keyblock,
+ 0,
+ &o->ap_req_options,
+ &o->ticket,
+ KRB5_KU_AP_REQ_AUTH);
+ if (ret) {
+ krb5_kt_free_entry (context, &entry);
+ continue;
+ }
+
+ /*
+ * Found a match, save the keyblock for PAC processing,
+ * and update the service principal in the ticket to match
+ * whatever is in the keytab.
+ */
+
+ ret = krb5_copy_keyblock(context,
+ &entry.keyblock,
+ &o->keyblock);
+ if (ret) {
+ krb5_kt_free_entry (context, &entry);
+ goto out;
+ }
+
+ ret = krb5_copy_principal(context, entry.principal, &p);
+ if (ret) {
+ krb5_kt_free_entry (context, &entry);
+ goto out;
+ }
+ krb5_free_principal(context, o->ticket->server);
+ o->ticket->server = p;
+
+ krb5_kt_free_entry (context, &entry);
+
+ done = 1;
+ }
+ krb5_kt_end_seq_get (context, id, &cursor);
+ }
/* If there is a PAC, verify its server signature */
- if (inctx->check_pac) {
+ if (inctx == NULL || inctx->check_pac) {
krb5_pac pac;
krb5_data data;
@@ -878,17 +1055,23 @@ krb5_rd_req_ctx(krb5_context context,
krb5_pac_free(context, pac);
if (ret)
goto out;
- }
- ret = 0;
+ } else
+ ret = 0;
}
out:
+
if (ret || outctx == NULL) {
krb5_rd_req_out_ctx_free(context, o);
} else
*outctx = o;
free_AP_REQ(&ap_req);
- if(service)
+
+ if (service)
krb5_free_principal(context, service);
+
+ if (keytab)
+ krb5_kt_close(context, keytab);
+
return ret;
}
diff --git a/source4/heimdal/lib/krb5/replay.c b/source4/heimdal/lib/krb5/replay.c
index 25a6da0262..37556cfbc5 100644
--- a/source4/heimdal/lib/krb5/replay.c
+++ b/source4/heimdal/lib/krb5/replay.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include <vis.h>
-RCSID("$Id$");
-
struct krb5_rcache_data {
char *name;
};
diff --git a/source4/heimdal/lib/krb5/send_to_kdc.c b/source4/heimdal/lib/krb5/send_to_kdc.c
index 53c4a69a3f..50b42f2f10 100644
--- a/source4/heimdal/lib/krb5/send_to_kdc.c
+++ b/source4/heimdal/lib/krb5/send_to_kdc.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include "send_to_kdc_plugin.h"
-RCSID("$Id$");
-
struct send_to_kdc {
krb5_send_to_kdc_func func;
void *data;
@@ -384,8 +382,8 @@ krb5_sendto (krb5_context context,
if (context->send_to_kdc) {
struct send_to_kdc *s = context->send_to_kdc;
- ret = (*s->func)(context, s->data,
- hi, context->kdc_timeout, send_data, receive);
+ ret = (*s->func)(context, s->data, hi,
+ context->kdc_timeout, send_data, receive);
if (ret == 0 && receive->length != 0)
goto out;
continue;
diff --git a/source4/heimdal/lib/krb5/set_default_realm.c b/source4/heimdal/lib/krb5/set_default_realm.c
index 6907b11d10..91201eeb53 100644
--- a/source4/heimdal/lib/krb5/set_default_realm.c
+++ b/source4/heimdal/lib/krb5/set_default_realm.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/*
* Convert the simple string `s' into a NULL-terminated and freshly allocated
* list in `list'. Return an error code.
diff --git a/source4/heimdal/lib/krb5/store-int.h b/source4/heimdal/lib/krb5/store-int.h
index 8489f98453..0b7accb860 100644
--- a/source4/heimdal/lib/krb5/store-int.h
+++ b/source4/heimdal/lib/krb5/store-int.h
@@ -39,6 +39,7 @@ struct krb5_storage_data {
ssize_t (*fetch)(struct krb5_storage_data*, void*, size_t);
ssize_t (*store)(struct krb5_storage_data*, const void*, size_t);
off_t (*seek)(struct krb5_storage_data*, off_t, int);
+ int (*trunc)(struct krb5_storage_data*, off_t);
void (*free)(struct krb5_storage_data*);
krb5_flags flags;
int eof_code;
diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c
index 47f9abe1de..2ba83ef0d5 100644
--- a/source4/heimdal/lib/krb5/store.c
+++ b/source4/heimdal/lib/krb5/store.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 1997-2008 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include "store-int.h"
-RCSID("$Id$");
-
#define BYTEORDER_IS(SP, V) (((SP)->flags & KRB5_STORAGE_BYTEORDER_MASK) == (V))
#define BYTEORDER_IS_LE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_LE)
#define BYTEORDER_IS_BE(SP) BYTEORDER_IS((SP), KRB5_STORAGE_BYTEORDER_BE)
@@ -54,12 +52,36 @@ krb5_storage_clear_flags(krb5_storage *sp, krb5_flags flags)
sp->flags &= ~flags;
}
+/**
+ * Return true or false depending on if the storage flags is set or
+ * not. NB testing for the flag 0 always return true.
+ *
+ * @param sp the storage buffer to check flags on
+ * @param flags The flags to test for
+ *
+ * @return true if all the flags are set, false if not.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_boolean KRB5_LIB_FUNCTION
krb5_storage_is_flags(krb5_storage *sp, krb5_flags flags)
{
return (sp->flags & flags) == flags;
}
+/**
+ * Set the new byte order of the storage buffer.
+ *
+ * @param sp the storage buffer to set the byte order for.
+ * @param byteorder the new byte order.
+ *
+ * The byte order are: KRB5_STORAGE_BYTEORDER_BE,
+ * KRB5_STORAGE_BYTEORDER_LE and KRB5_STORAGE_BYTEORDER_HOST.
+ *
+ * @ingroup krb5_storage
+ */
+
void KRB5_LIB_FUNCTION
krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
{
@@ -67,36 +89,121 @@ krb5_storage_set_byteorder(krb5_storage *sp, krb5_flags byteorder)
sp->flags |= byteorder;
}
+/**
+ * Return the current byteorder for the buffer. See krb5_storage_set_byteorder() for the list or byte order contants.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_flags KRB5_LIB_FUNCTION
-krb5_storage_get_byteorder(krb5_storage *sp, krb5_flags byteorder)
+krb5_storage_get_byteorder(krb5_storage *sp)
{
return sp->flags & KRB5_STORAGE_BYTEORDER_MASK;
}
+/**
+ * Seek to a new offset.
+ *
+ * @param sp the storage buffer to seek in.
+ * @param offset the offset to seek
+ * @param whence relateive searching, SEEK_CUR from the current
+ * position, SEEK_END from the end, SEEK_SET absolute from the start.
+ *
+ * @return The new current offset
+ *
+ * @ingroup krb5_storage
+ */
+
off_t KRB5_LIB_FUNCTION
krb5_storage_seek(krb5_storage *sp, off_t offset, int whence)
{
return (*sp->seek)(sp, offset, whence);
}
+/**
+ * Truncate the storage buffer in sp to offset.
+ *
+ * @param sp the storage buffer to truncate.
+ * @param offset the offset to truncate too.
+ *
+ * @return An Kerberos 5 error code.
+ *
+ * @ingroup krb5_storage
+ */
+
+int KRB5_LIB_FUNCTION
+krb5_storage_truncate(krb5_storage *sp, off_t offset)
+{
+ return (*sp->trunc)(sp, offset);
+}
+
+/**
+ * Read to the storage buffer.
+ *
+ * @param sp the storage buffer to read from
+ * @param buf the buffer to store the data in
+ * @param len the length to read
+ *
+ * @return The length of data read (can be shorter then len), or negative on error.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_ssize_t KRB5_LIB_FUNCTION
krb5_storage_read(krb5_storage *sp, void *buf, size_t len)
{
return sp->fetch(sp, buf, len);
}
+/**
+ * Write to the storage buffer.
+ *
+ * @param sp the storage buffer to write to
+ * @param buf the buffer to write to the storage buffer
+ * @param len the length to write
+ *
+ * @return The length of data written (can be shorter then len), or negative on error.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_ssize_t KRB5_LIB_FUNCTION
krb5_storage_write(krb5_storage *sp, const void *buf, size_t len)
{
return sp->store(sp, buf, len);
}
+/**
+ * Set the return code that will be used when end of storage is reached.
+ *
+ * @param sp the storage
+ * @param code the error code to return on end of storage
+ *
+ * @ingroup krb5_storage
+ */
+
void KRB5_LIB_FUNCTION
krb5_storage_set_eof_code(krb5_storage *sp, int code)
{
sp->eof_code = code;
}
+/**
+ * Get the return code that will be used when end of storage is reached.
+ *
+ * @param sp the storage
+ *
+ * @return storage error code
+ *
+ * @ingroup krb5_storage
+ */
+
+int KRB5_LIB_FUNCTION
+krb5_storage_get_eof_code(krb5_storage *sp)
+{
+ return sp->eof_code;
+}
+
krb5_ssize_t KRB5_LIB_FUNCTION
_krb5_put_int(void *buffer, unsigned long value, size_t size)
{
@@ -121,6 +228,16 @@ _krb5_get_int(void *buffer, unsigned long *value, size_t size)
return size;
}
+/**
+ * Free a krb5 storage.
+ *
+ * @param sp the storage to free.
+ *
+ * @return An Kerberos 5 error code.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_storage_free(krb5_storage *sp)
{
@@ -131,15 +248,29 @@ krb5_storage_free(krb5_storage *sp)
return 0;
}
+/**
+ * Copy the contnent of storage
+ *
+ * @param sp the storage to copy to a data
+ * @param data the copied data, free with krb5_data_free()
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_storage_to_data(krb5_storage *sp, krb5_data *data)
{
- off_t pos;
- size_t size;
+ off_t pos, size;
krb5_error_code ret;
pos = sp->seek(sp, 0, SEEK_CUR);
+ if (pos < 0)
+ return HEIM_ERR_NOT_SEEKABLE;
size = (size_t)sp->seek(sp, 0, SEEK_END);
+ if (size > (size_t)-1)
+ return HEIM_ERR_TOO_BIG;
ret = krb5_data_alloc (data, size);
if (ret) {
sp->seek(sp, pos, SEEK_SET);
@@ -170,6 +301,18 @@ krb5_store_int(krb5_storage *sp,
return 0;
}
+/**
+ * Store a int32 to storage, byte order is controlled by the settings
+ * on the storage, see krb5_storage_set_byteorder().
+ *
+ * @param sp the storage to write too
+ * @param value the value to store
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_int32(krb5_storage *sp,
int32_t value)
@@ -181,6 +324,18 @@ krb5_store_int32(krb5_storage *sp,
return krb5_store_int(sp, value, 4);
}
+/**
+ * Store a uint32 to storage, byte order is controlled by the settings
+ * on the storage, see krb5_storage_set_byteorder().
+ *
+ * @param sp the storage to write too
+ * @param value the value to store
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_uint32(krb5_storage *sp,
uint32_t value)
@@ -232,6 +387,18 @@ krb5_ret_uint32(krb5_storage *sp,
return ret;
}
+/**
+ * Store a int16 to storage, byte order is controlled by the settings
+ * on the storage, see krb5_storage_set_byteorder().
+ *
+ * @param sp the storage to write too
+ * @param value the value to store
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_int16(krb5_storage *sp,
int16_t value)
@@ -243,6 +410,18 @@ krb5_store_int16(krb5_storage *sp,
return krb5_store_int(sp, value, 2);
}
+/**
+ * Store a uint16 to storage, byte order is controlled by the settings
+ * on the storage, see krb5_storage_set_byteorder().
+ *
+ * @param sp the storage to write too
+ * @param value the value to store
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_uint16(krb5_storage *sp,
uint16_t value)
@@ -281,6 +460,17 @@ krb5_ret_uint16(krb5_storage *sp,
return ret;
}
+/**
+ * Store a int8 to storage.
+ *
+ * @param sp the storage to write too
+ * @param value the value to store
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_int8(krb5_storage *sp,
int8_t value)
@@ -293,6 +483,17 @@ krb5_store_int8(krb5_storage *sp,
return 0;
}
+/**
+ * Store a uint8 to storage.
+ *
+ * @param sp the storage to write too
+ * @param value the value to store
+ *
+ * @return 0 for success, or a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_uint8(krb5_storage *sp,
uint8_t value)
@@ -326,6 +527,17 @@ krb5_ret_uint8(krb5_storage *sp,
return ret;
}
+/**
+ * Store a data to the storage.
+ *
+ * @param sp the storage buffer to write to
+ * @param data the buffer to store.
+ *
+ * @return 0 on success, a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_data(krb5_storage *sp,
krb5_data data)
@@ -343,6 +555,17 @@ krb5_store_data(krb5_storage *sp,
return 0;
}
+/**
+ * Parse a data from the storage.
+ *
+ * @param sp the storage buffer to read from
+ * @param data the parsed data
+ *
+ * @return 0 on success, a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_data(krb5_storage *sp,
krb5_data *data)
@@ -594,6 +817,17 @@ krb5_ret_principal(krb5_storage *sp,
return 0;
}
+/**
+ * Store a keyblock to the storage.
+ *
+ * @param sp the storage buffer to write to
+ * @param p the keyblock to write
+ *
+ * @return 0 on success, a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
{
@@ -612,6 +846,17 @@ krb5_store_keyblock(krb5_storage *sp, krb5_keyblock p)
return ret;
}
+/**
+ * Read a keyblock from the storage.
+ *
+ * @param sp the storage buffer to write to
+ * @param p the keyblock read from storage, free using krb5_free_keyblock()
+ *
+ * @return 0 on success, a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
{
@@ -631,6 +876,17 @@ krb5_ret_keyblock(krb5_storage *sp, krb5_keyblock *p)
return ret;
}
+/**
+ * Write a times block to storage.
+ *
+ * @param sp the storage buffer to write to
+ * @param times the times block to write.
+ *
+ * @return 0 on success, a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_store_times(krb5_storage *sp, krb5_times times)
{
@@ -645,6 +901,17 @@ krb5_store_times(krb5_storage *sp, krb5_times times)
return ret;
}
+/**
+ * Read a times block from the storage.
+ *
+ * @param sp the storage buffer to write to
+ * @param times the times block read from storage
+ *
+ * @return 0 on success, a Kerberos 5 error code on failure.
+ *
+ * @ingroup krb5_storage
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_ret_times(krb5_storage *sp, krb5_times *times)
{
@@ -903,6 +1170,8 @@ krb5_store_creds_tag(krb5_storage *sp, krb5_creds *creds)
header |= SC_ADDRESSES;
ret = krb5_store_int32(sp, header);
+ if (ret)
+ return ret;
if (creds->client) {
ret = krb5_store_principal(sp, creds->client);
diff --git a/source4/heimdal/lib/krb5/store_emem.c b/source4/heimdal/lib/krb5/store_emem.c
index 8a587600fd..4be89b6564 100644
--- a/source4/heimdal/lib/krb5/store_emem.c
+++ b/source4/heimdal/lib/krb5/store_emem.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include "store-int.h"
-RCSID("$Id$");
-
typedef struct emem_storage{
unsigned char *base;
size_t size;
@@ -67,7 +65,7 @@ emem_store(krb5_storage *sp, const void *data, size_t size)
sz *= 2;
base = realloc(s->base, sz);
if(base == NULL)
- return 0;
+ return -1;
s->size = sz;
s->base = base;
s->ptr = (unsigned char*)base + off;
@@ -104,6 +102,34 @@ emem_seek(krb5_storage *sp, off_t offset, int whence)
return s->ptr - s->base;
}
+static int
+emem_trunc(krb5_storage *sp, off_t offset)
+{
+ emem_storage *s = (emem_storage*)sp->data;
+ /*
+ * If offset is larget then current size, or current size is
+ * shrunk more then half of the current size, adjust buffer.
+ */
+ if (offset > s->size || (s->size / 2) > offset) {
+ void *base;
+ size_t off;
+ off = s->ptr - s->base;
+ base = realloc(s->base, offset);
+ if(base == NULL)
+ return ENOMEM;
+ if (offset > s->size)
+ memset((char *)base + s->size, 0, offset - s->size);
+ s->size = offset;
+ s->base = base;
+ s->ptr = (unsigned char *)base + off;
+ }
+ s->len = offset;
+ if ((s->ptr - s->base) > offset)
+ s->ptr = s->base + offset;
+ return 0;
+}
+
+
static void
emem_free(krb5_storage *sp)
{
@@ -112,6 +138,21 @@ emem_free(krb5_storage *sp)
free(s->base);
}
+/**
+ * Create a elastic (allocating) memory storage backend. Memory is
+ * allocated on demand. Free returned krb5_storage with
+ * krb5_storage_free().
+ *
+ * @return A krb5_storage on success, or NULL on out of memory error.
+ *
+ * @ingroup krb5_storage
+ *
+ * @sa krb5_storage_from_mem()
+ * @sa krb5_storage_from_readonly_mem()
+ * @sa krb5_storage_from_fd()
+ * @sa krb5_storage_from_data()
+ */
+
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_emem(void)
{
@@ -142,6 +183,7 @@ krb5_storage_emem(void)
sp->fetch = emem_fetch;
sp->store = emem_store;
sp->seek = emem_seek;
+ sp->trunc = emem_trunc;
sp->free = emem_free;
return sp;
}
diff --git a/source4/heimdal/lib/krb5/store_fd.c b/source4/heimdal/lib/krb5/store_fd.c
index fe3c513ee9..38d67ae4d3 100644
--- a/source4/heimdal/lib/krb5/store_fd.c
+++ b/source4/heimdal/lib/krb5/store_fd.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include "store-int.h"
-RCSID("$Id$");
-
typedef struct fd_storage {
int fd;
} fd_storage;
@@ -60,12 +58,33 @@ fd_seek(krb5_storage * sp, off_t offset, int whence)
return lseek(FD(sp), offset, whence);
}
+static int
+fd_trunc(krb5_storage * sp, off_t offset)
+{
+ if (ftruncate(FD(sp), offset) == -1)
+ return errno;
+ return 0;
+}
+
static void
fd_free(krb5_storage * sp)
{
close(FD(sp));
}
+/**
+ *
+ *
+ * @return A krb5_storage on success, or NULL on out of memory error.
+ *
+ * @ingroup krb5_storage
+ *
+ * @sa krb5_storage_from_emem()
+ * @sa krb5_storage_from_mem()
+ * @sa krb5_storage_from_readonly_mem()
+ * @sa krb5_storage_from_data()
+ */
+
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_from_fd(int fd)
{
@@ -93,6 +112,7 @@ krb5_storage_from_fd(int fd)
sp->fetch = fd_fetch;
sp->store = fd_store;
sp->seek = fd_seek;
+ sp->trunc = fd_trunc;
sp->free = fd_free;
return sp;
}
diff --git a/source4/heimdal/lib/krb5/store_mem.c b/source4/heimdal/lib/krb5/store_mem.c
index 5c7cd17fba..db1abc1e90 100644
--- a/source4/heimdal/lib/krb5/store_mem.c
+++ b/source4/heimdal/lib/krb5/store_mem.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include "store-int.h"
-RCSID("$Id$");
-
typedef struct mem_storage{
unsigned char *base;
size_t size;
@@ -93,6 +91,37 @@ mem_seek(krb5_storage *sp, off_t offset, int whence)
return s->ptr - s->base;
}
+static int
+mem_trunc(krb5_storage *sp, off_t offset)
+{
+ mem_storage *s = (mem_storage*)sp->data;
+ if(offset > s->size)
+ return ERANGE;
+ s->size = offset;
+ if ((s->ptr - s->base) > offset)
+ s->ptr = s->base + offset;
+ return 0;
+}
+
+static int
+mem_no_trunc(krb5_storage *sp, off_t offset)
+{
+ return EINVAL;
+}
+
+/**
+ *
+ *
+ * @return A krb5_storage on success, or NULL on out of memory error.
+ *
+ * @ingroup krb5_storage
+ *
+ * @sa krb5_storage_from_emem()
+ * @sa krb5_storage_from_readonly_mem()
+ * @sa krb5_storage_from_data()
+ * @sa krb5_storage_from_fd()
+ */
+
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_from_mem(void *buf, size_t len)
{
@@ -114,16 +143,43 @@ krb5_storage_from_mem(void *buf, size_t len)
sp->fetch = mem_fetch;
sp->store = mem_store;
sp->seek = mem_seek;
+ sp->trunc = mem_trunc;
sp->free = NULL;
return sp;
}
+/**
+ *
+ *
+ * @return A krb5_storage on success, or NULL on out of memory error.
+ *
+ * @ingroup krb5_storage
+ *
+ * @sa krb5_storage_from_emem()
+ * @sa krb5_storage_from_mem()
+ * @sa krb5_storage_from_readonly_mem()
+ * @sa krb5_storage_from_fd()
+ */
+
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_from_data(krb5_data *data)
{
return krb5_storage_from_mem(data->data, data->length);
}
+/**
+ *
+ *
+ * @return A krb5_storage on success, or NULL on out of memory error.
+ *
+ * @ingroup krb5_storage
+ *
+ * @sa krb5_storage_from_emem()
+ * @sa krb5_storage_from_mem()
+ * @sa krb5_storage_from_data()
+ * @sa krb5_storage_from_fd()
+ */
+
krb5_storage * KRB5_LIB_FUNCTION
krb5_storage_from_readonly_mem(const void *buf, size_t len)
{
@@ -145,6 +201,7 @@ krb5_storage_from_readonly_mem(const void *buf, size_t len)
sp->fetch = mem_fetch;
sp->store = mem_no_store;
sp->seek = mem_seek;
+ sp->trunc = mem_no_trunc;
sp->free = NULL;
return sp;
}
diff --git a/source4/heimdal/lib/krb5/ticket.c b/source4/heimdal/lib/krb5/ticket.c
index db78626570..86c4924506 100644
--- a/source4/heimdal/lib/krb5/ticket.c
+++ b/source4/heimdal/lib/krb5/ticket.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
krb5_error_code KRB5_LIB_FUNCTION
krb5_free_ticket(krb5_context context,
krb5_ticket *ticket)
@@ -301,3 +299,485 @@ krb5_ticket_get_authorization_data_type(krb5_context context,
}
return 0;
}
+
+static krb5_error_code
+check_server_referral(krb5_context context,
+ krb5_kdc_rep *rep,
+ unsigned flags,
+ krb5_const_principal requested,
+ krb5_const_principal returned,
+ krb5_keyblock * key)
+{
+ krb5_error_code ret;
+ PA_ServerReferralData ref;
+ krb5_crypto session;
+ EncryptedData ed;
+ size_t len;
+ krb5_data data;
+ PA_DATA *pa;
+ int i = 0, cmp;
+
+ if (rep->kdc_rep.padata == NULL)
+ goto noreferral;
+
+ pa = krb5_find_padata(rep->kdc_rep.padata->val,
+ rep->kdc_rep.padata->len,
+ KRB5_PADATA_SERVER_REFERRAL, &i);
+ if (pa == NULL)
+ goto noreferral;
+
+ memset(&ed, 0, sizeof(ed));
+ memset(&ref, 0, sizeof(ref));
+
+ ret = decode_EncryptedData(pa->padata_value.data,
+ pa->padata_value.length,
+ &ed, &len);
+ if (ret)
+ return ret;
+ if (len != pa->padata_value.length) {
+ free_EncryptedData(&ed);
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("Referral EncryptedData wrong for realm %s",
+ "realm"), requested->realm);
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+
+ ret = krb5_crypto_init(context, key, 0, &session);
+ if (ret) {
+ free_EncryptedData(&ed);
+ return ret;
+ }
+
+ ret = krb5_decrypt_EncryptedData(context, session,
+ KRB5_KU_PA_SERVER_REFERRAL,
+ &ed, &data);
+ free_EncryptedData(&ed);
+ krb5_crypto_destroy(context, session);
+ if (ret)
+ return ret;
+
+ ret = decode_PA_ServerReferralData(data.data, data.length, &ref, &len);
+ if (ret) {
+ krb5_data_free(&data);
+ return ret;
+ }
+ krb5_data_free(&data);
+
+ if (strcmp(requested->realm, returned->realm) != 0) {
+ free_PA_ServerReferralData(&ref);
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("server ref realm mismatch, "
+ "requested realm %s got back %s", ""),
+ requested->realm, returned->realm);
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+
+ if (returned->name.name_string.len == 2 &&
+ strcmp(returned->name.name_string.val[0], KRB5_TGS_NAME) == 0)
+ {
+ const char *realm = returned->name.name_string.val[1];
+
+ if (ref.referred_realm == NULL
+ || strcmp(*ref.referred_realm, realm) != 0)
+ {
+ free_PA_ServerReferralData(&ref);
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("tgt returned with wrong ref", ""));
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+ } else if (krb5_principal_compare(context, returned, requested) == 0) {
+ free_PA_ServerReferralData(&ref);
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("req princ no same as returned", ""));
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+
+ if (ref.requested_principal_name) {
+ cmp = _krb5_principal_compare_PrincipalName(context,
+ requested,
+ ref.requested_principal_name);
+ if (!cmp) {
+ free_PA_ServerReferralData(&ref);
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("referred principal not same "
+ "as requested", ""));
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+ } else if (flags & EXTRACT_TICKET_AS_REQ) {
+ free_PA_ServerReferralData(&ref);
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("Requested principal missing on AS-REQ", ""));
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+
+ free_PA_ServerReferralData(&ref);
+
+ return ret;
+noreferral:
+ if (krb5_principal_compare(context, requested, returned) == FALSE) {
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("Not same server principal returned "
+ "as requested", ""));
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+ return 0;
+}
+
+
+/*
+ * Verify referral data
+ */
+
+
+static krb5_error_code
+check_client_referral(krb5_context context,
+ krb5_kdc_rep *rep,
+ krb5_const_principal requested,
+ krb5_const_principal mapped,
+ krb5_keyblock const * key)
+{
+ krb5_error_code ret;
+ PA_ClientCanonicalized canon;
+ krb5_crypto crypto;
+ krb5_data data;
+ PA_DATA *pa;
+ size_t len;
+ int i = 0;
+
+ if (rep->kdc_rep.padata == NULL)
+ goto noreferral;
+
+ pa = krb5_find_padata(rep->kdc_rep.padata->val,
+ rep->kdc_rep.padata->len,
+ KRB5_PADATA_CLIENT_CANONICALIZED, &i);
+ if (pa == NULL)
+ goto noreferral;
+
+ ret = decode_PA_ClientCanonicalized(pa->padata_value.data,
+ pa->padata_value.length,
+ &canon, &len);
+ if (ret) {
+ krb5_set_error_message(context, ret,
+ N_("Failed to decode ClientCanonicalized "
+ "from realm %s", ""), requested->realm);
+ return ret;
+ }
+
+ ASN1_MALLOC_ENCODE(PA_ClientCanonicalizedNames, data.data, data.length,
+ &canon.names, &len, ret);
+ if (ret) {
+ free_PA_ClientCanonicalized(&canon);
+ return ret;
+ }
+ if (data.length != len)
+ krb5_abortx(context, "internal asn.1 error");
+
+ ret = krb5_crypto_init(context, key, 0, &crypto);
+ if (ret) {
+ free(data.data);
+ free_PA_ClientCanonicalized(&canon);
+ return ret;
+ }
+
+ ret = krb5_verify_checksum(context, crypto, KRB5_KU_CANONICALIZED_NAMES,
+ data.data, data.length,
+ &canon.canon_checksum);
+ krb5_crypto_destroy(context, crypto);
+ free(data.data);
+ if (ret) {
+ krb5_set_error_message(context, ret,
+ N_("Failed to verify client canonicalized "
+ "data from realm %s", ""),
+ requested->realm);
+ free_PA_ClientCanonicalized(&canon);
+ return ret;
+ }
+
+ if (!_krb5_principal_compare_PrincipalName(context,
+ requested,
+ &canon.names.requested_name))
+ {
+ free_PA_ClientCanonicalized(&canon);
+ krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
+ N_("Requested name doesn't match"
+ " in client referral", ""));
+ return KRB5_PRINC_NOMATCH;
+ }
+ if (!_krb5_principal_compare_PrincipalName(context,
+ mapped,
+ &canon.names.mapped_name))
+ {
+ free_PA_ClientCanonicalized(&canon);
+ krb5_set_error_message(context, KRB5_PRINC_NOMATCH,
+ N_("Mapped name doesn't match"
+ " in client referral", ""));
+ return KRB5_PRINC_NOMATCH;
+ }
+
+ return 0;
+
+noreferral:
+ if (krb5_principal_compare(context, requested, mapped) == FALSE) {
+ krb5_set_error_message(context, KRB5KRB_AP_ERR_MODIFIED,
+ N_("Not same client principal returned "
+ "as requested", ""));
+ return KRB5KRB_AP_ERR_MODIFIED;
+ }
+ return 0;
+}
+
+
+static krb5_error_code
+decrypt_tkt (krb5_context context,
+ krb5_keyblock *key,
+ krb5_key_usage usage,
+ krb5_const_pointer decrypt_arg,
+ krb5_kdc_rep *dec_rep)
+{
+ krb5_error_code ret;
+ krb5_data data;
+ size_t size;
+ krb5_crypto crypto;
+
+ ret = krb5_crypto_init(context, key, 0, &crypto);
+ if (ret)
+ return ret;
+
+ ret = krb5_decrypt_EncryptedData (context,
+ crypto,
+ usage,
+ &dec_rep->kdc_rep.enc_part,
+ &data);
+ krb5_crypto_destroy(context, crypto);
+
+ if (ret)
+ return ret;
+
+ ret = decode_EncASRepPart(data.data,
+ data.length,
+ &dec_rep->enc_part,
+ &size);
+ if (ret)
+ ret = decode_EncTGSRepPart(data.data,
+ data.length,
+ &dec_rep->enc_part,
+ &size);
+ krb5_data_free (&data);
+ if (ret) {
+ krb5_set_error_message(context, ret,
+ N_("Failed to decode encpart in ticket", ""));
+ return ret;
+ }
+ return 0;
+}
+
+int
+_krb5_extract_ticket(krb5_context context,
+ krb5_kdc_rep *rep,
+ krb5_creds *creds,
+ krb5_keyblock *key,
+ krb5_const_pointer keyseed,
+ krb5_key_usage key_usage,
+ krb5_addresses *addrs,
+ unsigned nonce,
+ unsigned flags,
+ krb5_decrypt_proc decrypt_proc,
+ krb5_const_pointer decryptarg)
+{
+ krb5_error_code ret;
+ krb5_principal tmp_principal;
+ size_t len;
+ time_t tmp_time;
+ krb5_timestamp sec_now;
+
+ /* decrypt */
+
+ if (decrypt_proc == NULL)
+ decrypt_proc = decrypt_tkt;
+
+ ret = (*decrypt_proc)(context, key, key_usage, decryptarg, rep);
+ if (ret)
+ goto out;
+
+ /* save session key */
+
+ creds->session.keyvalue.length = 0;
+ creds->session.keyvalue.data = NULL;
+ creds->session.keytype = rep->enc_part.key.keytype;
+ ret = krb5_data_copy (&creds->session.keyvalue,
+ rep->enc_part.key.keyvalue.data,
+ rep->enc_part.key.keyvalue.length);
+ if (ret) {
+ krb5_clear_error_message(context);
+ goto out;
+ }
+
+ /*
+ * HACK:
+ * this is really a ugly hack, to support using the Netbios Domain Name
+ * as realm against windows KDC's, they always return the full realm
+ * based on the DNS Name.
+ */
+ flags |= EXTRACT_TICKET_ALLOW_SERVER_MISMATCH;
+ flags |= EXTRACT_TICKET_ALLOW_CNAME_MISMATCH;
+
+ /* compare client and save */
+ ret = _krb5_principalname2krb5_principal (context,
+ &tmp_principal,
+ rep->kdc_rep.cname,
+ rep->kdc_rep.crealm);
+ if (ret)
+ goto out;
+
+ /* check client referral and save principal */
+ /* anonymous here ? */
+ if((flags & EXTRACT_TICKET_ALLOW_CNAME_MISMATCH) == 0) {
+ ret = check_client_referral(context, rep,
+ creds->client,
+ tmp_principal,
+ &creds->session);
+ if (ret) {
+ krb5_free_principal (context, tmp_principal);
+ goto out;
+ }
+ }
+ krb5_free_principal (context, creds->client);
+ creds->client = tmp_principal;
+
+ /* check server referral and save principal */
+ ret = _krb5_principalname2krb5_principal (context,
+ &tmp_principal,
+ rep->kdc_rep.ticket.sname,
+ rep->kdc_rep.ticket.realm);
+ if (ret)
+ goto out;
+ if((flags & EXTRACT_TICKET_ALLOW_SERVER_MISMATCH) == 0){
+ ret = check_server_referral(context,
+ rep,
+ flags,
+ creds->server,
+ tmp_principal,
+ &creds->session);
+ if (ret) {
+ krb5_free_principal (context, tmp_principal);
+ goto out;
+ }
+ }
+ krb5_free_principal(context, creds->server);
+ creds->server = tmp_principal;
+
+ /* verify names */
+ if(flags & EXTRACT_TICKET_MATCH_REALM){
+ const char *srealm = krb5_principal_get_realm(context, creds->server);
+ const char *crealm = krb5_principal_get_realm(context, creds->client);
+
+ if (strcmp(rep->enc_part.srealm, srealm) != 0 ||
+ strcmp(rep->enc_part.srealm, crealm) != 0)
+ {
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ krb5_clear_error_message(context);
+ goto out;
+ }
+ }
+
+ /* compare nonces */
+
+ if (nonce != rep->enc_part.nonce) {
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
+ goto out;
+ }
+
+ /* set kdc-offset */
+
+ krb5_timeofday (context, &sec_now);
+ if (rep->enc_part.flags.initial
+ && context->kdc_sec_offset == 0
+ && krb5_config_get_bool (context, NULL,
+ "libdefaults",
+ "kdc_timesync",
+ NULL)) {
+ context->kdc_sec_offset = rep->enc_part.authtime - sec_now;
+ krb5_timeofday (context, &sec_now);
+ }
+
+ /* check all times */
+
+ if (rep->enc_part.starttime) {
+ tmp_time = *rep->enc_part.starttime;
+ } else
+ tmp_time = rep->enc_part.authtime;
+
+ if (creds->times.starttime == 0
+ && abs(tmp_time - sec_now) > context->max_skew) {
+ ret = KRB5KRB_AP_ERR_SKEW;
+ krb5_set_error_message (context, ret,
+ N_("time skew (%d) larger than max (%d)", ""),
+ abs(tmp_time - sec_now),
+ (int)context->max_skew);
+ goto out;
+ }
+
+ if (creds->times.starttime != 0
+ && tmp_time != creds->times.starttime) {
+ krb5_clear_error_message (context);
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ goto out;
+ }
+
+ creds->times.starttime = tmp_time;
+
+ if (rep->enc_part.renew_till) {
+ tmp_time = *rep->enc_part.renew_till;
+ } else
+ tmp_time = 0;
+
+ if (creds->times.renew_till != 0
+ && tmp_time > creds->times.renew_till) {
+ krb5_clear_error_message (context);
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ goto out;
+ }
+
+ creds->times.renew_till = tmp_time;
+
+ creds->times.authtime = rep->enc_part.authtime;
+
+ if (creds->times.endtime != 0
+ && rep->enc_part.endtime > creds->times.endtime) {
+ krb5_clear_error_message (context);
+ ret = KRB5KRB_AP_ERR_MODIFIED;
+ goto out;
+ }
+
+ creds->times.endtime = rep->enc_part.endtime;
+
+ if(rep->enc_part.caddr)
+ krb5_copy_addresses (context, rep->enc_part.caddr, &creds->addresses);
+ else if(addrs)
+ krb5_copy_addresses (context, addrs, &creds->addresses);
+ else {
+ creds->addresses.len = 0;
+ creds->addresses.val = NULL;
+ }
+ creds->flags.b = rep->enc_part.flags;
+
+ creds->authdata.len = 0;
+ creds->authdata.val = NULL;
+
+ /* extract ticket */
+ ASN1_MALLOC_ENCODE(Ticket, creds->ticket.data, creds->ticket.length,
+ &rep->kdc_rep.ticket, &len, ret);
+ if(ret)
+ goto out;
+ if (creds->ticket.length != len)
+ krb5_abortx(context, "internal error in ASN.1 encoder");
+ creds->second_ticket.length = 0;
+ creds->second_ticket.data = NULL;
+
+
+out:
+ memset (rep->enc_part.key.keyvalue.data, 0,
+ rep->enc_part.key.keyvalue.length);
+ return ret;
+}
diff --git a/source4/heimdal/lib/krb5/time.c b/source4/heimdal/lib/krb5/time.c
index cd786fedde..ed235783a2 100644
--- a/source4/heimdal/lib/krb5/time.c
+++ b/source4/heimdal/lib/krb5/time.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/**
* Set the absolute time that the caller knows the kdc has so the
* kerberos library can calculate the relative diffrence beteen the
diff --git a/source4/heimdal/lib/krb5/transited.c b/source4/heimdal/lib/krb5/transited.c
index 7e11d5579a..196ef447ee 100644
--- a/source4/heimdal/lib/krb5/transited.c
+++ b/source4/heimdal/lib/krb5/transited.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/* this is an attempt at one of the most horrible `compression'
schemes that has ever been invented; it's so amazingly brain-dead
that words can not describe it, and all this just to save a few
diff --git a/source4/heimdal/lib/krb5/v4_glue.c b/source4/heimdal/lib/krb5/v4_glue.c
index 6911cb20f8..168268ceab 100644
--- a/source4/heimdal/lib/krb5/v4_glue.c
+++ b/source4/heimdal/lib/krb5/v4_glue.c
@@ -32,7 +32,6 @@
*/
#include "krb5_locl.h"
-RCSID("$Id$");
#include "krb5-v4compat.h"
@@ -217,14 +216,16 @@ write_v4_cc(krb5_context context, const char *tkfile,
ret = write(fd, data.data, data.length);
if (ret != data.length)
ret = KRB5_CC_IO;
+ else
+ ret = 0;
- krb5_free_data_contents(context, &data);
+ krb5_data_free(&data);
flock(fd, LOCK_UN);
free(path);
close(fd);
- return 0;
+ return ret;
}
/*
diff --git a/source4/heimdal/lib/krb5/version.c b/source4/heimdal/lib/krb5/version.c
index d43b83e26e..a0e750604e 100644
--- a/source4/heimdal/lib/krb5/version.c
+++ b/source4/heimdal/lib/krb5/version.c
@@ -33,8 +33,6 @@
#include "krb5_locl.h"
-RCSID("$Id$");
-
/* this is just to get a version stamp in the library file */
#define heimdal_version __heimdal_version
diff --git a/source4/heimdal/lib/krb5/warn.c b/source4/heimdal/lib/krb5/warn.c
index a00ae80697..58fb73189e 100644
--- a/source4/heimdal/lib/krb5/warn.c
+++ b/source4/heimdal/lib/krb5/warn.c
@@ -34,8 +34,6 @@
#include "krb5_locl.h"
#include <err.h>
-RCSID("$Id$");
-
static krb5_error_code _warnerr(krb5_context context, int do_errtext,
krb5_error_code code, int level, const char *fmt, va_list ap)
__attribute__((__format__(__printf__, 5, 0)));
@@ -96,6 +94,18 @@ _warnerr(krb5_context context, int do_errtext,
#undef __attribute__
#define __attribute__(X)
+/**
+ * Log a warning to the log, default stderr, include the error from
+ * the last failure.
+ *
+ * @param context A Kerberos 5 context.
+ * @param code error code of the last error
+ * @param fmt message to print
+ * @param ap arguments
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_vwarn(krb5_context context, krb5_error_code code,
const char *fmt, va_list ap)
@@ -104,6 +114,16 @@ krb5_vwarn(krb5_context context, krb5_error_code code,
return _warnerr(context, 1, code, 1, fmt, ap);
}
+/**
+ * Log a warning to the log, default stderr, include the error from
+ * the last failure.
+ *
+ * @param context A Kerberos 5 context.
+ * @param code error code of the last error
+ * @param fmt message to print
+ *
+ * @ingroup krb5_error
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_warn(krb5_context context, krb5_error_code code, const char *fmt, ...)
@@ -113,6 +133,16 @@ krb5_warn(krb5_context context, krb5_error_code code, const char *fmt, ...)
return ret;
}
+/**
+ * Log a warning to the log, default stderr.
+ *
+ * @param context A Kerberos 5 context.
+ * @param fmt message to print
+ * @param ap arguments
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_vwarnx(krb5_context context, const char *fmt, va_list ap)
__attribute__ ((format (printf, 2, 0)))
@@ -120,6 +150,15 @@ krb5_vwarnx(krb5_context context, const char *fmt, va_list ap)
return _warnerr(context, 0, 0, 1, fmt, ap);
}
+/**
+ * Log a warning to the log, default stderr.
+ *
+ * @param context A Kerberos 5 context.
+ * @param fmt message to print
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_warnx(krb5_context context, const char *fmt, ...)
__attribute__ ((format (printf, 2, 3)))
@@ -128,6 +167,19 @@ krb5_warnx(krb5_context context, const char *fmt, ...)
return ret;
}
+/**
+ * Log a warning to the log, default stderr, include bthe error from
+ * the last failure and then exit.
+ *
+ * @param context A Kerberos 5 context
+ * @param eval the exit code to exit with
+ * @param code error code of the last error
+ * @param fmt message to print
+ * @param ap arguments
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_verr(krb5_context context, int eval, krb5_error_code code,
const char *fmt, va_list ap)
@@ -137,6 +189,17 @@ krb5_verr(krb5_context context, int eval, krb5_error_code code,
exit(eval);
}
+/**
+ * Log a warning to the log, default stderr, include bthe error from
+ * the last failure and then exit.
+ *
+ * @param context A Kerberos 5 context
+ * @param eval the exit code to exit with
+ * @param code error code of the last error
+ * @param fmt message to print
+ *
+ * @ingroup krb5_error
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_err(krb5_context context, int eval, krb5_error_code code,
@@ -147,6 +210,17 @@ krb5_err(krb5_context context, int eval, krb5_error_code code,
exit(eval);
}
+/**
+ * Log a warning to the log, default stderr, and then exit.
+ *
+ * @param context A Kerberos 5 context
+ * @param eval the exit code to exit with
+ * @param fmt message to print
+ * @param ap arguments
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_verrx(krb5_context context, int eval, const char *fmt, va_list ap)
__attribute__ ((noreturn, format (printf, 3, 0)))
@@ -155,6 +229,16 @@ krb5_verrx(krb5_context context, int eval, const char *fmt, va_list ap)
exit(eval);
}
+/**
+ * Log a warning to the log, default stderr, and then exit.
+ *
+ * @param context A Kerberos 5 context
+ * @param eval the exit code to exit with
+ * @param fmt message to print
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_errx(krb5_context context, int eval, const char *fmt, ...)
__attribute__ ((noreturn, format (printf, 3, 4)))
@@ -163,6 +247,18 @@ krb5_errx(krb5_context context, int eval, const char *fmt, ...)
exit(eval);
}
+/**
+ * Log a warning to the log, default stderr, include bthe error from
+ * the last failure and then abort.
+ *
+ * @param context A Kerberos 5 context
+ * @param code error code of the last error
+ * @param fmt message to print
+ * @param ap arguments
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_vabort(krb5_context context, krb5_error_code code,
const char *fmt, va_list ap)
@@ -172,6 +268,16 @@ krb5_vabort(krb5_context context, krb5_error_code code,
abort();
}
+/**
+ * Log a warning to the log, default stderr, include bthe error from
+ * the last failure and then abort.
+ *
+ * @param context A Kerberos 5 context
+ * @param code error code of the last error
+ * @param fmt message to print
+ *
+ * @ingroup krb5_error
+ */
krb5_error_code KRB5_LIB_FUNCTION
krb5_abort(krb5_context context, krb5_error_code code, const char *fmt, ...)
@@ -189,6 +295,16 @@ krb5_vabortx(krb5_context context, const char *fmt, va_list ap)
abort();
}
+/**
+ * Log a warning to the log, default stderr, and then abort.
+ *
+ * @param context A Kerberos 5 context
+ * @param code error code of the last error
+ * @param fmt message to print
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_abortx(krb5_context context, const char *fmt, ...)
__attribute__ ((noreturn, format (printf, 2, 3)))
@@ -197,6 +313,15 @@ krb5_abortx(krb5_context context, const char *fmt, ...)
abort();
}
+/**
+ * Set the default logging facility.
+ *
+ * @param context A Kerberos 5 context
+ * @param fac Facility to use for logging.
+ *
+ * @ingroup krb5_error
+ */
+
krb5_error_code KRB5_LIB_FUNCTION
krb5_set_warn_dest(krb5_context context, krb5_log_facility *fac)
{
@@ -204,6 +329,14 @@ krb5_set_warn_dest(krb5_context context, krb5_log_facility *fac)
return 0;
}
+/**
+ * Get the default logging facility.
+ *
+ * @param context A Kerberos 5 context
+ *
+ * @ingroup krb5_error
+ */
+
krb5_log_facility * KRB5_LIB_FUNCTION
krb5_get_warn_dest(krb5_context context)
{
diff --git a/source4/heimdal/lib/ntlm/ntlm.c b/source4/heimdal/lib/ntlm/ntlm.c
index 1002b67cc8..1fe456d022 100644
--- a/source4/heimdal/lib/ntlm/ntlm.c
+++ b/source4/heimdal/lib/ntlm/ntlm.c
@@ -33,8 +33,6 @@
#include <config.h>
-RCSID("$Id$");
-
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
@@ -440,7 +438,8 @@ heim_ntlm_decode_type1(const struct ntlm_buf *buf, struct ntlm_type1 *data)
CHECK(ret_string(in, 0, &hostname, &data->hostname), 0);
out:
- krb5_storage_free(in);
+ if (in)
+ krb5_storage_free(in);
if (ret)
heim_ntlm_free_type1(data);
@@ -589,7 +588,8 @@ heim_ntlm_decode_type2(const struct ntlm_buf *buf, struct ntlm_type2 *type2)
ret = 0;
out:
- krb5_storage_free(in);
+ if (in)
+ krb5_storage_free(in);
if (ret)
heim_ntlm_free_type2(type2);
@@ -748,7 +748,8 @@ heim_ntlm_decode_type3(const struct ntlm_buf *buf,
CHECK(ret_buf(in, &sessionkey, &type3->sessionkey), 0);
out:
- krb5_storage_free(in);
+ if (in)
+ krb5_storage_free(in);
if (ret)
heim_ntlm_free_type3(type3);
@@ -1041,15 +1042,18 @@ heim_ntlm_build_ntlm1_master(void *key, size_t len,
* @param target the name of the target, assumed to be in UTF8.
* @param ntlmv2 the ntlmv2 session key
*
+ * @return 0 on success, or an error code on failure.
+ *
* @ingroup ntlm_core
*/
-void
+int
heim_ntlm_ntlmv2_key(const void *key, size_t len,
const char *username,
const char *target,
unsigned char ntlmv2[16])
{
+ int ret;
unsigned int hmaclen;
HMAC_CTX c;
@@ -1058,17 +1062,23 @@ heim_ntlm_ntlmv2_key(const void *key, size_t len,
{
struct ntlm_buf buf;
/* uppercase username and turn it into ucs2-le */
- ascii2ucs2le(username, 1, &buf);
+ ret = ascii2ucs2le(username, 1, &buf);
+ if (ret)
+ goto out;
HMAC_Update(&c, buf.data, buf.length);
free(buf.data);
/* uppercase target and turn into ucs2-le */
- ascii2ucs2le(target, 1, &buf);
+ ret = ascii2ucs2le(target, 1, &buf);
+ if (ret)
+ goto out;
HMAC_Update(&c, buf.data, buf.length);
free(buf.data);
}
HMAC_Final(&c, ntlmv2, &hmaclen);
+ out:
HMAC_CTX_cleanup(&c);
+ return ret;
}
/*
diff --git a/source4/heimdal/lib/roken/base64.c b/source4/heimdal/lib/roken/base64.c
index d0096447b3..5e720eb6d4 100644
--- a/source4/heimdal/lib/roken/base64.c
+++ b/source4/heimdal/lib/roken/base64.c
@@ -31,10 +31,8 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
+
#include <stdlib.h>
#include <string.h>
#include "base64.h"
@@ -61,8 +59,10 @@ base64_encode(const void *data, int size, char **str)
const unsigned char *q;
p = s = (char *) malloc(size * 4 / 3 + 4);
- if (p == NULL)
+ if (p == NULL) {
+ *str = NULL;
return -1;
+ }
q = (const unsigned char *) data;
for (i = 0; i < size;) {
diff --git a/source4/heimdal/lib/roken/bswap.c b/source4/heimdal/lib/roken/bswap.c
index a87345be3f..67d240c231 100644
--- a/source4/heimdal/lib/roken/bswap.c
+++ b/source4/heimdal/lib/roken/bswap.c
@@ -31,13 +31,9 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "roken.h"
-RCSID("$Id$");
-
#ifndef HAVE_BSWAP32
unsigned int ROKEN_LIB_FUNCTION
diff --git a/source4/heimdal/lib/roken/cloexec.c b/source4/heimdal/lib/roken/cloexec.c
index 7a64233309..c015b1d8fa 100644
--- a/source4/heimdal/lib/roken/cloexec.c
+++ b/source4/heimdal/lib/roken/cloexec.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <unistd.h>
#include <fcntl.h>
diff --git a/source4/heimdal/lib/roken/closefrom.c b/source4/heimdal/lib/roken/closefrom.c
index 9198c05e26..7aa0ef7372 100644
--- a/source4/heimdal/lib/roken/closefrom.c
+++ b/source4/heimdal/lib/roken/closefrom.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
diff --git a/source4/heimdal/lib/roken/copyhostent.c b/source4/heimdal/lib/roken/copyhostent.c
index 58f5a112f2..69c1ba40ff 100644
--- a/source4/heimdal/lib/roken/copyhostent.c
+++ b/source4/heimdal/lib/roken/copyhostent.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/dumpdata.c b/source4/heimdal/lib/roken/dumpdata.c
index 88a86815ef..c5513c323d 100644
--- a/source4/heimdal/lib/roken/dumpdata.c
+++ b/source4/heimdal/lib/roken/dumpdata.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <unistd.h>
diff --git a/source4/heimdal/lib/roken/ecalloc.c b/source4/heimdal/lib/roken/ecalloc.c
index 6c579e99f3..c8e6504030 100644
--- a/source4/heimdal/lib/roken/ecalloc.c
+++ b/source4/heimdal/lib/roken/ecalloc.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <stdlib.h>
#include <err.h>
diff --git a/source4/heimdal/lib/roken/emalloc.c b/source4/heimdal/lib/roken/emalloc.c
index d033e16a07..c937e6d707 100644
--- a/source4/heimdal/lib/roken/emalloc.c
+++ b/source4/heimdal/lib/roken/emalloc.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <stdlib.h>
#include <err.h>
diff --git a/source4/heimdal/lib/roken/erealloc.c b/source4/heimdal/lib/roken/erealloc.c
index 239d6a0eab..f77c8ec733 100644
--- a/source4/heimdal/lib/roken/erealloc.c
+++ b/source4/heimdal/lib/roken/erealloc.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <stdlib.h>
#include <err.h>
diff --git a/source4/heimdal/lib/roken/estrdup.c b/source4/heimdal/lib/roken/estrdup.c
index fb353d0d85..ab7f26550b 100644
--- a/source4/heimdal/lib/roken/estrdup.c
+++ b/source4/heimdal/lib/roken/estrdup.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <stdlib.h>
#include <err.h>
diff --git a/source4/heimdal/lib/roken/freeaddrinfo.c b/source4/heimdal/lib/roken/freeaddrinfo.c
index 1721d20aaf..434e49e888 100644
--- a/source4/heimdal/lib/roken/freeaddrinfo.c
+++ b/source4/heimdal/lib/roken/freeaddrinfo.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/freehostent.c b/source4/heimdal/lib/roken/freehostent.c
index 38c27d3380..335504300a 100644
--- a/source4/heimdal/lib/roken/freehostent.c
+++ b/source4/heimdal/lib/roken/freehostent.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/gai_strerror.c b/source4/heimdal/lib/roken/gai_strerror.c
index 084900a58a..10beac05ea 100644
--- a/source4/heimdal/lib/roken/gai_strerror.c
+++ b/source4/heimdal/lib/roken/gai_strerror.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/get_window_size.c b/source4/heimdal/lib/roken/get_window_size.c
index 9b200c1159..60fb1764fa 100644
--- a/source4/heimdal/lib/roken/get_window_size.c
+++ b/source4/heimdal/lib/roken/get_window_size.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
diff --git a/source4/heimdal/lib/roken/getaddrinfo.c b/source4/heimdal/lib/roken/getaddrinfo.c
index a8fc029c32..8c61299763 100644
--- a/source4/heimdal/lib/roken/getaddrinfo.c
+++ b/source4/heimdal/lib/roken/getaddrinfo.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/getarg.c b/source4/heimdal/lib/roken/getarg.c
index 3168ccc53d..60b0f645af 100644
--- a/source4/heimdal/lib/roken/getarg.c
+++ b/source4/heimdal/lib/roken/getarg.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <stdio.h>
#include <stdlib.h>
diff --git a/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c b/source4/heimdal/lib/roken/getdtablesize.c
index 0dedbefd2c..a515af3454 100644
--- a/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c
+++ b/source4/heimdal/lib/roken/getdtablesize.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan
+ * Copyright (c) 1995-2001 Kungliga Tekniska Högskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -31,69 +31,69 @@
* SUCH DAMAGE.
*/
-#include "krb5_locl.h"
+#include <config.h>
-RCSID("$Id$");
+#include "roken.h"
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_keytab_key_proc (krb5_context context,
- krb5_enctype enctype,
- krb5_salt salt,
- krb5_const_pointer keyseed,
- krb5_keyblock **key)
-{
- krb5_keytab_key_proc_args *args = rk_UNCONST(keyseed);
- krb5_keytab keytab = args->keytab;
- krb5_principal principal = args->principal;
- krb5_error_code ret;
- krb5_keytab real_keytab;
- krb5_keytab_entry entry;
+#ifdef HAVE_SYS_TYPES_H
+#include <sys/types.h>
+#endif
+#ifdef TIME_WITH_SYS_TIME
+#include <sys/time.h>
+#include <time.h>
+#elif defined(HAVE_SYS_TIME_H)
+#include <sys/time.h>
+#else
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
- if(keytab == NULL)
- krb5_kt_default(context, &real_keytab);
- else
- real_keytab = keytab;
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
- ret = krb5_kt_get_entry (context, real_keytab, principal,
- 0, enctype, &entry);
+#ifdef HAVE_SYS_SYSCTL_H
+#include <sys/sysctl.h>
+#endif
- if (keytab == NULL)
- krb5_kt_close (context, real_keytab);
+int ROKEN_LIB_FUNCTION
+getdtablesize(void)
+{
+ int files = -1;
+#if defined(HAVE_SYSCONF) && defined(_SC_OPEN_MAX)
+ files = sysconf(_SC_OPEN_MAX);
+#else /* !defined(HAVE_SYSCONF) */
+#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_NOFILE)
+ struct rlimit res;
+ if (getrlimit(RLIMIT_NOFILE, &res) == 0)
+ files = res.rlim_cur;
+#else /* !definded(HAVE_GETRLIMIT) */
+#if defined(HAVE_SYSCTL) && defined(CTL_KERN) && defined(KERN_MAXFILES)
+ int mib[2];
+ size_t len;
- if (ret)
- return ret;
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_MAXFILES;
+ len = sizeof(files);
+ sysctl(&mib, 2, &files, sizeof(files), NULL, 0);
+#endif /* defined(HAVE_SYSCTL) */
+#endif /* !definded(HAVE_GETRLIMIT) */
+#endif /* !defined(HAVE_SYSCONF) */
- ret = krb5_copy_keyblock (context, &entry.keyblock, key);
- krb5_kt_free_entry(context, &entry);
- return ret;
-}
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_get_in_tkt_with_keytab (krb5_context context,
- krb5_flags options,
- krb5_addresses *addrs,
- const krb5_enctype *etypes,
- const krb5_preauthtype *pre_auth_types,
- krb5_keytab keytab,
- krb5_ccache ccache,
- krb5_creds *creds,
- krb5_kdc_rep *ret_as_reply)
-{
- krb5_keytab_key_proc_args a;
+#ifdef OPEN_MAX
+ if (files < 0)
+ files = OPEN_MAX;
+#endif
- a.principal = creds->client;
- a.keytab = keytab;
+#ifdef NOFILE
+ if (files < 0)
+ files = NOFILE;
+#endif
- return krb5_get_in_tkt (context,
- options,
- addrs,
- etypes,
- pre_auth_types,
- krb5_keytab_key_proc,
- &a,
- NULL,
- NULL,
- creds,
- ccache,
- ret_as_reply);
+ return files;
}
diff --git a/source4/heimdal/lib/roken/getipnodebyaddr.c b/source4/heimdal/lib/roken/getipnodebyaddr.c
index e3c2b50e32..ddaec03a89 100644
--- a/source4/heimdal/lib/roken/getipnodebyaddr.c
+++ b/source4/heimdal/lib/roken/getipnodebyaddr.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/getipnodebyname.c b/source4/heimdal/lib/roken/getipnodebyname.c
index ec578937b7..16fdbdd24a 100644
--- a/source4/heimdal/lib/roken/getipnodebyname.c
+++ b/source4/heimdal/lib/roken/getipnodebyname.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/getnameinfo.c b/source4/heimdal/lib/roken/getnameinfo.c
index 865cc09dc8..0621cfeee1 100644
--- a/source4/heimdal/lib/roken/getnameinfo.c
+++ b/source4/heimdal/lib/roken/getnameinfo.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/getprogname.c b/source4/heimdal/lib/roken/getprogname.c
index b01a3d7e45..933b6dec79 100644
--- a/source4/heimdal/lib/roken/getprogname.c
+++ b/source4/heimdal/lib/roken/getprogname.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/h_errno.c b/source4/heimdal/lib/roken/h_errno.c
index 0cee02d472..7e49f8008f 100644
--- a/source4/heimdal/lib/roken/h_errno.c
+++ b/source4/heimdal/lib/roken/h_errno.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#ifndef HAVE_H_ERRNO
int h_errno = -17; /* Some magic number */
diff --git a/source4/heimdal/lib/roken/hex.c b/source4/heimdal/lib/roken/hex.c
index 2167172f9f..95488af5c7 100644
--- a/source4/heimdal/lib/roken/hex.c
+++ b/source4/heimdal/lib/roken/hex.c
@@ -31,10 +31,8 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
+
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
#include <ctype.h>
#include "hex.h"
@@ -60,12 +58,16 @@ hex_encode(const void *data, size_t size, char **str)
char *p;
/* check for overflow */
- if (size * 2 < size)
+ if (size * 2 < size) {
+ *str = NULL;
return -1;
+ }
p = malloc(size * 2 + 1);
- if (p == NULL)
+ if (p == NULL) {
+ *str = NULL;
return -1;
+ }
for (i = 0; i < size; i++) {
p[i * 2] = hexchar[(*q >> 4) & 0xf];
diff --git a/source4/heimdal/lib/roken/hostent_find_fqdn.c b/source4/heimdal/lib/roken/hostent_find_fqdn.c
index 9376c1da36..b5f2b42f60 100644
--- a/source4/heimdal/lib/roken/hostent_find_fqdn.c
+++ b/source4/heimdal/lib/roken/hostent_find_fqdn.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/inet_aton.c b/source4/heimdal/lib/roken/inet_aton.c
index c42697c63c..c9b21e00f8 100644
--- a/source4/heimdal/lib/roken/inet_aton.c
+++ b/source4/heimdal/lib/roken/inet_aton.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/inet_ntop.c b/source4/heimdal/lib/roken/inet_ntop.c
index 5e4e4f9dc7..daf3e926dd 100644
--- a/source4/heimdal/lib/roken/inet_ntop.c
+++ b/source4/heimdal/lib/roken/inet_ntop.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/inet_pton.c b/source4/heimdal/lib/roken/inet_pton.c
index f2a9af3aa3..ad60824f4a 100644
--- a/source4/heimdal/lib/roken/inet_pton.c
+++ b/source4/heimdal/lib/roken/inet_pton.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/issuid.c b/source4/heimdal/lib/roken/issuid.c
index 257481cffb..2999e8249c 100644
--- a/source4/heimdal/lib/roken/issuid.c
+++ b/source4/heimdal/lib/roken/issuid.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/net_read.c b/source4/heimdal/lib/roken/net_read.c
index ae025ffc71..9d055d0068 100644
--- a/source4/heimdal/lib/roken/net_read.c
+++ b/source4/heimdal/lib/roken/net_read.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <sys/types.h>
#include <unistd.h>
diff --git a/source4/heimdal/lib/roken/net_write.c b/source4/heimdal/lib/roken/net_write.c
index 11f5b8d7be..515f210973 100644
--- a/source4/heimdal/lib/roken/net_write.c
+++ b/source4/heimdal/lib/roken/net_write.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <sys/types.h>
#include <unistd.h>
diff --git a/source4/heimdal/lib/roken/parse_time.c b/source4/heimdal/lib/roken/parse_time.c
index 6065eeb425..b581970bd7 100644
--- a/source4/heimdal/lib/roken/parse_time.c
+++ b/source4/heimdal/lib/roken/parse_time.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <parse_units.h>
#include "parse_time.h"
diff --git a/source4/heimdal/lib/roken/parse_units.c b/source4/heimdal/lib/roken/parse_units.c
index 4dbd7b489b..a848298c57 100644
--- a/source4/heimdal/lib/roken/parse_units.c
+++ b/source4/heimdal/lib/roken/parse_units.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <stdio.h>
#include <ctype.h>
diff --git a/source4/heimdal/lib/roken/resolve.c b/source4/heimdal/lib/roken/resolve.c
index f358a5b266..a74e438cf8 100644
--- a/source4/heimdal/lib/roken/resolve.c
+++ b/source4/heimdal/lib/roken/resolve.c
@@ -31,9 +31,9 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
+
#include <config.h>
-#endif
+
#include "roken.h"
#ifdef HAVE_ARPA_NAMESER_H
#include <arpa/nameser.h>
@@ -41,6 +41,9 @@
#ifdef HAVE_RESOLV_H
#include <resolv.h>
#endif
+#ifdef HAVE_DNS_H
+#include <dns.h>
+#endif
#include "resolve.h"
#include <assert.h>
@@ -78,7 +81,7 @@ static struct stot{
int _resolve_debug = 0;
int ROKEN_LIB_FUNCTION
-dns_string_to_type(const char *name)
+rk_dns_string_to_type(const char *name)
{
struct stot *p = stot;
for(p = stot; p->name; p++)
@@ -88,7 +91,7 @@ dns_string_to_type(const char *name)
}
const char * ROKEN_LIB_FUNCTION
-dns_type_to_string(int type)
+rk_dns_type_to_string(int type)
{
struct stot *p = stot;
for(p = stot; p->name; p++)
@@ -100,7 +103,7 @@ dns_type_to_string(int type)
#if (defined(HAVE_RES_SEARCH) || defined(HAVE_RES_NSEARCH)) && defined(HAVE_DN_EXPAND)
static void
-dns_free_rr(struct resource_record *rr)
+dns_free_rr(struct rk_resource_record *rr)
{
if(rr->domain)
free(rr->domain);
@@ -110,13 +113,13 @@ dns_free_rr(struct resource_record *rr)
}
void ROKEN_LIB_FUNCTION
-dns_free_data(struct dns_reply *r)
+rk_dns_free_data(struct rk_dns_reply *r)
{
- struct resource_record *rr;
+ struct rk_resource_record *rr;
if(r->q.domain)
free(r->q.domain);
for(rr = r->head; rr;){
- struct resource_record *tmp = rr;
+ struct rk_resource_record *tmp = rr;
rr = rr->next;
dns_free_rr(tmp);
}
@@ -125,9 +128,9 @@ dns_free_data(struct dns_reply *r)
static int
parse_record(const unsigned char *data, const unsigned char *end_data,
- const unsigned char **pp, struct resource_record **ret_rr)
+ const unsigned char **pp, struct rk_resource_record **ret_rr)
{
- struct resource_record *rr;
+ struct rk_resource_record *rr;
int type, class, ttl;
unsigned size;
int status;
@@ -401,7 +404,7 @@ parse_record(const unsigned char *data, const unsigned char *end_data,
#ifndef TEST_RESOLVE
static
#endif
-struct dns_reply*
+struct rk_dns_reply*
parse_reply(const unsigned char *data, size_t len)
{
const unsigned char *p;
@@ -409,8 +412,8 @@ parse_reply(const unsigned char *data, size_t len)
int i;
char host[MAXDNAME];
const unsigned char *end_data = data + len;
- struct dns_reply *r;
- struct resource_record **rr;
+ struct rk_dns_reply *r;
+ struct rk_resource_record **rr;
r = calloc(1, sizeof(*r));
if (r == NULL)
@@ -449,16 +452,16 @@ parse_reply(const unsigned char *data, size_t len)
}
status = dn_expand(data, end_data, p, host, sizeof(host));
if(status < 0){
- dns_free_data(r);
+ rk_dns_free_data(r);
return NULL;
}
r->q.domain = strdup(host);
if(r->q.domain == NULL) {
- dns_free_data(r);
+ rk_dns_free_data(r);
return NULL;
}
if (p + status + 4 > end_data) {
- dns_free_data(r);
+ rk_dns_free_data(r);
return NULL;
}
p += status;
@@ -470,21 +473,21 @@ parse_reply(const unsigned char *data, size_t len)
rr = &r->head;
for(i = 0; i < r->h.ancount; i++) {
if(parse_record(data, end_data, &p, rr) != 0) {
- dns_free_data(r);
+ rk_dns_free_data(r);
return NULL;
}
rr = &(*rr)->next;
}
for(i = 0; i < r->h.nscount; i++) {
if(parse_record(data, end_data, &p, rr) != 0) {
- dns_free_data(r);
+ rk_dns_free_data(r);
return NULL;
}
rr = &(*rr)->next;
}
for(i = 0; i < r->h.arcount; i++) {
if(parse_record(data, end_data, &p, rr) != 0) {
- dns_free_data(r);
+ rk_dns_free_data(r);
return NULL;
}
rr = &(*rr)->next;
@@ -501,20 +504,42 @@ parse_reply(const unsigned char *data, size_t len)
#endif
#endif
-static struct dns_reply *
+#if defined(HAVE_DNS_SEARCH)
+#define resolve_search(h,n,c,t,r,l) \
+ ((int)dns_search(h,n,c,t,r,l,(struct sockaddr *)&from,&fromsize))
+#define resolve_free_handle(h) dns_free(h)
+#elif defined(HAVE_RES_NSEARCH)
+#define resolve_search(h,n,c,t,r,l) res_nsearch(h,n,c,t,r,l)
+#define resolve_free_handle(h) rk_res_free(h);
+#else
+#define resolve_search(h,n,c,t,r,l) res_search(n,c,t,r,l)
+#define handle 0
+#define resolve_free_handle(h)
+#endif
+
+
+static struct rk_dns_reply *
dns_lookup_int(const char *domain, int rr_class, int rr_type)
{
- struct dns_reply *r;
- unsigned char *reply = NULL;
+ struct rk_dns_reply *r;
+ void *reply = NULL;
int size;
int len;
-#ifdef HAVE_RES_NSEARCH
+#if defined(HAVE_DNS_SEARCH)
+ struct sockaddr_storage from;
+ uint32_t fromsize = sizeof(from);
+ dns_handle_t handle;
+
+ handle = dns_open(NULL);
+ if (handle == NULL)
+ return NULL;
+#elif defined(HAVE_RES_NSEARCH)
struct __res_state state;
+ struct __res_state *handle = &state;
+
memset(&state, 0, sizeof(state));
- if(res_ninit(&state))
+ if(res_ninit(handle))
return NULL; /* is this the best we can do? */
-#elif defined(HAVE__RES)
- u_long old_options = 0;
#endif
size = 0;
@@ -527,45 +552,33 @@ dns_lookup_int(const char *domain, int rr_class, int rr_type)
if (size <= len)
size = len;
if (_resolve_debug) {
-#ifdef HAVE_RES_NSEARCH
+#if defined(HAVE_DNS_SEARCH)
+ dns_set_debug(handle, 1);
+#elif defined(HAVE_RES_NSEARCH)
state.options |= RES_DEBUG;
-#elif defined(HAVE__RES)
- old_options = _res.options;
- _res.options |= RES_DEBUG;
#endif
fprintf(stderr, "dns_lookup(%s, %d, %s), buffer size %d\n", domain,
- rr_class, dns_type_to_string(rr_type), size);
+ rr_class, rk_dns_type_to_string(rr_type), size);
}
reply = malloc(size);
if (reply == NULL) {
-#ifdef HAVE_RES_NSEARCH
- rk_res_free(&state);
-#endif
+ resolve_free_handle(handle);
return NULL;
}
-#ifdef HAVE_RES_NSEARCH
- len = res_nsearch(&state, domain, rr_class, rr_type, reply, size);
-#else
- len = res_search(domain, rr_class, rr_type, reply, size);
-#endif
+
+ len = resolve_search(handle, domain, rr_class, rr_type, reply, size);
+
if (_resolve_debug) {
-#if defined(HAVE__RES) && !defined(HAVE_RES_NSEARCH)
- _res.options = old_options;
-#endif
fprintf(stderr, "dns_lookup(%s, %d, %s) --> %d\n",
- domain, rr_class, dns_type_to_string(rr_type), len);
+ domain, rr_class, rk_dns_type_to_string(rr_type), len);
}
- if (len < 0) {
-#ifdef HAVE_RES_NSEARCH
- rk_res_free(&state);
-#endif
+ if (len <= 0) {
+ resolve_free_handle(handle);
free(reply);
return NULL;
}
} while (size < len && len < rk_DNS_MAX_PACKET_SIZE);
-#ifdef HAVE_RES_NSEARCH
- rk_res_free(&state);
-#endif
+ resolve_free_handle(handle);
len = min(len, size);
r = parse_reply(reply, len);
@@ -573,25 +586,25 @@ dns_lookup_int(const char *domain, int rr_class, int rr_type)
return r;
}
-struct dns_reply * ROKEN_LIB_FUNCTION
-dns_lookup(const char *domain, const char *type_name)
+struct rk_dns_reply * ROKEN_LIB_FUNCTION
+rk_dns_lookup(const char *domain, const char *type_name)
{
int type;
- type = dns_string_to_type(type_name);
+ type = rk_dns_string_to_type(type_name);
if(type == -1) {
if(_resolve_debug)
fprintf(stderr, "dns_lookup: unknown resource type: `%s'\n",
type_name);
return NULL;
}
- return dns_lookup_int(domain, C_IN, type);
+ return dns_lookup_int(domain, rk_ns_c_in, type);
}
static int
compare_srv(const void *a, const void *b)
{
- const struct resource_record *const* aa = a, *const* bb = b;
+ const struct rk_resource_record *const* aa = a, *const* bb = b;
if((*aa)->u.srv->priority == (*bb)->u.srv->priority)
return ((*aa)->u.srv->weight - (*bb)->u.srv->weight);
@@ -604,10 +617,10 @@ compare_srv(const void *a, const void *b)
/* try to rearrange the srv-records by the algorithm in RFC2782 */
void ROKEN_LIB_FUNCTION
-dns_srv_order(struct dns_reply *r)
+rk_dns_srv_order(struct rk_dns_reply *r)
{
- struct resource_record **srvs, **ss, **headp;
- struct resource_record *rr;
+ struct rk_resource_record **srvs, **ss, **headp;
+ struct rk_resource_record *rr;
int num_srv = 0;
#if defined(HAVE_INITSTATE) && defined(HAVE_SETSTATE)
@@ -648,7 +661,7 @@ dns_srv_order(struct dns_reply *r)
for(ss = srvs; ss < srvs + num_srv; ) {
int sum, rnd, count;
- struct resource_record **ee, **tt;
+ struct rk_resource_record **ee, **tt;
/* find the last record with the same priority and count the
sum of all weights */
for(sum = 0, tt = ss; tt < srvs + num_srv; tt++) {
@@ -693,19 +706,19 @@ dns_srv_order(struct dns_reply *r)
#else /* NOT defined(HAVE_RES_SEARCH) && defined(HAVE_DN_EXPAND) */
-struct dns_reply * ROKEN_LIB_FUNCTION
-dns_lookup(const char *domain, const char *type_name)
+struct rk_dns_reply * ROKEN_LIB_FUNCTION
+rk_dns_lookup(const char *domain, const char *type_name)
{
return NULL;
}
void ROKEN_LIB_FUNCTION
-dns_free_data(struct dns_reply *r)
+rk_dns_free_data(struct rk_dns_reply *r)
{
}
void ROKEN_LIB_FUNCTION
-dns_srv_order(struct dns_reply *r)
+rk_dns_srv_order(struct rk_dns_reply *r)
{
}
diff --git a/source4/heimdal/lib/roken/resolve.h b/source4/heimdal/lib/roken/resolve.h
index d181dfa070..91b2afefe7 100644
--- a/source4/heimdal/lib/roken/resolve.h
+++ b/source4/heimdal/lib/roken/resolve.h
@@ -44,7 +44,11 @@
#endif
#endif
-typedef enum {
+enum {
+ rk_ns_c_in = 1
+};
+
+enum {
rk_ns_t_invalid = 0, /* Cookie. */
rk_ns_t_a = 1, /* Host address. */
rk_ns_t_ns = 2, /* Authoritative server. */
@@ -99,99 +103,38 @@ typedef enum {
rk_ns_t_any = 255, /* Wildcard match. */
rk_ns_t_zxfr = 256, /* BIND-specific, nonstandard. */
rk_ns_t_max = 65536
-} rk_ns_type;
-
-/* We use these, but they are not always present in <arpa/nameser.h> */
-
-#ifndef C_IN
-#define C_IN 1
-#endif
-
-#ifndef T_A
-#define T_A 1
-#endif
-#ifndef T_NS
-#define T_NS 2
-#endif
-#ifndef T_CNAME
-#define T_CNAME 5
-#endif
-#ifndef T_SOA
-#define T_SOA 5
-#endif
-#ifndef T_PTR
-#define T_PTR 12
-#endif
-#ifndef T_MX
-#define T_MX 15
-#endif
-#ifndef T_TXT
-#define T_TXT 16
-#endif
-#ifndef T_AFSDB
-#define T_AFSDB 18
-#endif
-#ifndef T_SIG
-#define T_SIG 24
-#endif
-#ifndef T_KEY
-#define T_KEY 25
-#endif
-#ifndef T_AAAA
-#define T_AAAA 28
-#endif
-#ifndef T_SRV
-#define T_SRV 33
-#endif
-#ifndef T_NAPTR
-#define T_NAPTR 35
-#endif
-#ifndef T_CERT
-#define T_CERT 37
-#endif
-#ifndef T_SSHFP
-#define T_SSHFP 44
-#endif
+};
#ifndef MAXDNAME
#define MAXDNAME 1025
#endif
-#define dns_query rk_dns_query
#define mx_record rk_mx_record
#define srv_record rk_srv_record
#define key_record rk_key_record
#define sig_record rk_sig_record
#define cert_record rk_cert_record
#define sshfp_record rk_sshfp_record
-#define resource_record rk_resource_record
-#define dns_reply rk_dns_reply
-
-#define dns_lookup rk_dns_lookup
-#define dns_free_data rk_dns_free_data
-#define dns_string_to_type rk_dns_string_to_type
-#define dns_type_to_string rk_dns_type_to_string
-#define dns_srv_order rk_dns_srv_order
-struct dns_query{
+struct rk_dns_query{
char *domain;
unsigned type;
unsigned class;
};
-struct mx_record{
+struct rk_mx_record{
unsigned preference;
char domain[1];
};
-struct srv_record{
+struct rk_srv_record{
unsigned priority;
unsigned weight;
unsigned port;
char target[1];
};
-struct key_record {
+struct rk_key_record {
unsigned flags;
unsigned protocol;
unsigned algorithm;
@@ -199,7 +142,7 @@ struct key_record {
u_char key_data[1];
};
-struct sig_record {
+struct rk_sig_record {
unsigned type;
unsigned algorithm;
unsigned labels;
@@ -212,7 +155,7 @@ struct sig_record {
char sig_data[1]; /* also includes signer */
};
-struct cert_record {
+struct rk_cert_record {
unsigned type;
unsigned tag;
unsigned algorithm;
@@ -220,14 +163,14 @@ struct cert_record {
u_char cert_data[1];
};
-struct sshfp_record {
+struct rk_sshfp_record {
unsigned algorithm;
unsigned type;
size_t sshfp_len;
u_char sshfp_data[1];
};
-struct ds_record {
+struct rk_ds_record {
unsigned key_tag;
unsigned algorithm;
unsigned digest_type;
@@ -235,7 +178,7 @@ struct ds_record {
u_char digest_data[1];
};
-struct resource_record{
+struct rk_resource_record{
char *domain;
unsigned type;
unsigned class;
@@ -243,23 +186,23 @@ struct resource_record{
unsigned size;
union {
void *data;
- struct mx_record *mx;
- struct mx_record *afsdb; /* mx and afsdb are identical */
- struct srv_record *srv;
+ struct rk_mx_record *mx;
+ struct rk_mx_record *afsdb; /* mx and afsdb are identical */
+ struct rk_srv_record *srv;
struct in_addr *a;
char *txt;
- struct key_record *key;
- struct cert_record *cert;
- struct sig_record *sig;
- struct sshfp_record *sshfp;
- struct ds_record *ds;
+ struct rk_key_record *key;
+ struct rk_cert_record *cert;
+ struct rk_sig_record *sig;
+ struct rk_sshfp_record *sshfp;
+ struct rk_ds_record *ds;
}u;
- struct resource_record *next;
+ struct rk_resource_record *next;
};
#define rk_DNS_MAX_PACKET_SIZE 0xffff
-struct dns_header {
+struct rk_dns_header {
unsigned id;
unsigned flags;
#define rk_DNS_HEADER_RESPONSE_FLAG 1
@@ -277,22 +220,30 @@ struct dns_header {
unsigned arcount;
};
-struct dns_reply{
- struct dns_header h;
- struct dns_query q;
- struct resource_record *head;
+struct rk_dns_reply{
+ struct rk_dns_header h;
+ struct rk_dns_query q;
+ struct rk_resource_record *head;
};
-struct dns_reply* ROKEN_LIB_FUNCTION
- dns_lookup(const char *, const char *);
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct rk_dns_reply* ROKEN_LIB_FUNCTION
+ rk_dns_lookup(const char *, const char *);
void ROKEN_LIB_FUNCTION
- dns_free_data(struct dns_reply *);
+ rk_dns_free_data(struct rk_dns_reply *);
int ROKEN_LIB_FUNCTION
- dns_string_to_type(const char *name);
+ rk_dns_string_to_type(const char *name);
const char *ROKEN_LIB_FUNCTION
- dns_type_to_string(int type);
+ rk_dns_type_to_string(int type);
void ROKEN_LIB_FUNCTION
- dns_srv_order(struct dns_reply*);
+ rk_dns_srv_order(struct rk_dns_reply*);
+
+#ifdef __cplusplus
+}
+#endif
#endif /* __RESOLVE_H__ */
diff --git a/source4/heimdal/lib/roken/rkpty.c b/source4/heimdal/lib/roken/rkpty.c
index ebc3a5d208..bff632f0f1 100644
--- a/source4/heimdal/lib/roken/rkpty.c
+++ b/source4/heimdal/lib/roken/rkpty.c
@@ -52,6 +52,10 @@
#include <libutil.h>
#endif
+#ifdef STREAMSPTY
+#include <stropts.h>
+#endif /* STREAMPTY */
+
#include "roken.h"
#include <getarg.h>
@@ -93,6 +97,39 @@ open_pty(void)
if(openpty(&master, &slave, line, 0, 0) == 0)
return;
#endif /* HAVE_OPENPTY .... */
+#ifdef STREAMSPTY
+ {
+ char *clone[] = {
+ "/dev/ptc",
+ "/dev/ptmx",
+ "/dev/ptm",
+ "/dev/ptym/clone",
+ NULL
+ };
+ char **q;
+
+ for(q = clone; *q; q++){
+ master = open(*q, O_RDWR);
+ if(master >= 0){
+#ifdef HAVE_GRANTPT
+ grantpt(master);
+#endif
+#ifdef HAVE_UNLOCKPT
+ unlockpt(master);
+#endif
+ strlcpy(line, ptsname(master), sizeof(line));
+ slave = open(line, O_RDWR);
+ if (slave < 0)
+ errx(1, "failed to open slave when using %s", q);
+ ioctl(slave, I_PUSH, "ptem");
+ ioctl(slave, I_PUSH, "ldterm");
+
+ return;
+ }
+ }
+ }
+#endif /* STREAMSPTY */
+
/* more cases, like open /dev/ptmx, etc */
exit(77);
@@ -302,7 +339,6 @@ main(int argc, char **argv)
parse_configuration(argv[0]);
argv += 1;
- argc -= 1;
open_pty();
diff --git a/source4/heimdal/lib/roken/roken-common.h b/source4/heimdal/lib/roken/roken-common.h
index 1d341258fe..1713b6609e 100644
--- a/source4/heimdal/lib/roken/roken-common.h
+++ b/source4/heimdal/lib/roken/roken-common.h
@@ -267,119 +267,154 @@ SigAction signal(int iSig, SigAction pAction); /* BSD compatible */
#endif
#endif
+#define simple_execve rk_simple_execve
int ROKEN_LIB_FUNCTION
simple_execve(const char*, char*const[], char*const[]);
+#define simple_execve_timed rk_simple_execve_timed
int ROKEN_LIB_FUNCTION
simple_execve_timed(const char *, char *const[],
char *const [], time_t (*)(void *),
void *, time_t);
+
+#define simple_execvp rk_simple_execvp
int ROKEN_LIB_FUNCTION
simple_execvp(const char*, char *const[]);
+#define simple_execvp_timed rk_simple_execvp_timed
int ROKEN_LIB_FUNCTION
simple_execvp_timed(const char *, char *const[],
time_t (*)(void *), void *, time_t);
+
+#define simple_execlp rk_simple_execlp
int ROKEN_LIB_FUNCTION
simple_execlp(const char*, ...);
+#define simple_execle rk_simple_execle
int ROKEN_LIB_FUNCTION
simple_execle(const char*, ...);
-int ROKEN_LIB_FUNCTION
-simple_execl(const char *file, ...);
-
+#define wait_for_process rk_wait_for_process
int ROKEN_LIB_FUNCTION
wait_for_process(pid_t);
+#define wait_for_process_timed rk_wait_for_process_timed
int ROKEN_LIB_FUNCTION
wait_for_process_timed(pid_t, time_t (*)(void *),
void *, time_t);
+#define pipe_execv rk_pipe_execv
int ROKEN_LIB_FUNCTION
pipe_execv(FILE**, FILE**, FILE**, const char*, ...);
+#define print_version rk_print_version
void ROKEN_LIB_FUNCTION
print_version(const char *);
+#define eread rk_eread
ssize_t ROKEN_LIB_FUNCTION
eread (int fd, void *buf, size_t nbytes);
+#define ewrite rk_ewrite
ssize_t ROKEN_LIB_FUNCTION
ewrite (int fd, const void *buf, size_t nbytes);
struct hostent;
+#define hostent_find_fqdn rk_hostent_find_fqdn
const char * ROKEN_LIB_FUNCTION
hostent_find_fqdn (const struct hostent *);
+#define esetenv rk_esetenv
void ROKEN_LIB_FUNCTION
esetenv(const char *, const char *, int);
+#define socket_set_address_and_port rk_socket_set_address_and_port
void ROKEN_LIB_FUNCTION
socket_set_address_and_port (struct sockaddr *, const void *, int);
+#define socket_addr_size rk_socket_addr_size
size_t ROKEN_LIB_FUNCTION
socket_addr_size (const struct sockaddr *);
+#define socket_set_any rk_socket_set_any
void ROKEN_LIB_FUNCTION
socket_set_any (struct sockaddr *, int);
+#define socket_sockaddr_size rk_socket_sockaddr_size
size_t ROKEN_LIB_FUNCTION
socket_sockaddr_size (const struct sockaddr *);
+#define socket_get_address rk_socket_get_address
void * ROKEN_LIB_FUNCTION
-socket_get_address (struct sockaddr *);
+socket_get_address (const struct sockaddr *);
+#define socket_get_port rk_socket_get_port
int ROKEN_LIB_FUNCTION
socket_get_port (const struct sockaddr *);
+#define socket_set_port rk_socket_set_port
void ROKEN_LIB_FUNCTION
socket_set_port (struct sockaddr *, int);
+#define socket_set_portrange rk_socket_set_portrange
void ROKEN_LIB_FUNCTION
socket_set_portrange (int, int, int);
+#define socket_set_debug rk_socket_set_debug
void ROKEN_LIB_FUNCTION
socket_set_debug (int);
+#define socket_set_tos rk_socket_set_tos
void ROKEN_LIB_FUNCTION
socket_set_tos (int, int);
+#define socket_set_reuseaddr rk_socket_set_reuseaddr
void ROKEN_LIB_FUNCTION
socket_set_reuseaddr (int, int);
+#define socket_set_ipv6only rk_socket_set_ipv6only
void ROKEN_LIB_FUNCTION
socket_set_ipv6only (int, int);
+#define vstrcollect rk_vstrcollect
char ** ROKEN_LIB_FUNCTION
vstrcollect(va_list *ap);
+#define strcollect rk_strcollect
char ** ROKEN_LIB_FUNCTION
strcollect(char *first, ...);
+#define timevalfix rk_timevalfix
void ROKEN_LIB_FUNCTION
timevalfix(struct timeval *t1);
+#define timevaladd rk_timevaladd
void ROKEN_LIB_FUNCTION
timevaladd(struct timeval *t1, const struct timeval *t2);
+#define timevalsub rk_timevalsub
void ROKEN_LIB_FUNCTION
timevalsub(struct timeval *t1, const struct timeval *t2);
+#define pid_file_write rk_pid_file_write
char *ROKEN_LIB_FUNCTION
pid_file_write (const char *progname);
+#define pid_file_delete rk_pid_file_delete
void ROKEN_LIB_FUNCTION
pid_file_delete (char **);
+#define read_environment rk_read_environment
int ROKEN_LIB_FUNCTION
read_environment(const char *file, char ***env);
+#define free_environment rk_free_environment
void ROKEN_LIB_FUNCTION
free_environment(char **);
+#define warnerr rk_warnerr
void ROKEN_LIB_FUNCTION
-warnerr(int doerrno, const char *fmt, va_list ap)
+rk_warnerr(int doerrno, const char *fmt, va_list ap)
__attribute__ ((format (printf, 2, 0)));
void * ROKEN_LIB_FUNCTION
diff --git a/source4/heimdal/lib/roken/roken.h.in b/source4/heimdal/lib/roken/roken.h.in
index d71bee7b46..3fce136875 100644
--- a/source4/heimdal/lib/roken/roken.h.in
+++ b/source4/heimdal/lib/roken/roken.h.in
@@ -125,9 +125,6 @@ struct sockaddr_dl;
#else
#include <time.h>
#endif
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
#ifdef HAVE_PATHS_H
#include <paths.h>
@@ -152,82 +149,125 @@ ROKEN_CPP_START
#endif
#ifndef HAVE_PUTENV
+#define putenv rk_putenv
int ROKEN_LIB_FUNCTION putenv(const char *);
#endif
#if !defined(HAVE_SETENV) || defined(NEED_SETENV_PROTO)
+#ifndef HAVE_SETENV
+#define setenv rk_setenv
+#endif
int ROKEN_LIB_FUNCTION setenv(const char *, const char *, int);
#endif
#if !defined(HAVE_UNSETENV) || defined(NEED_UNSETENV_PROTO)
+#ifndef HAVE_UNSETENV
+#define unsetenv rk_unsetenv
+#endif
void ROKEN_LIB_FUNCTION unsetenv(const char *);
#endif
#if !defined(HAVE_GETUSERSHELL) || defined(NEED_GETUSERSHELL_PROTO)
+#ifndef HAVE_GETUSERSHELL
+#define getusershell rk_getusershell
+#define endusershell rk_endusershell
+#endif
char * ROKEN_LIB_FUNCTION getusershell(void);
void ROKEN_LIB_FUNCTION endusershell(void);
#endif
#if !defined(HAVE_SNPRINTF) || defined(NEED_SNPRINTF_PROTO)
-int ROKEN_LIB_FUNCTION snprintf (char *, size_t, const char *, ...)
+#ifndef HAVE_SNPRINTF
+#define snprintf rk_snprintf
+#endif
+int ROKEN_LIB_FUNCTION
+ rk_snprintf (char *, size_t, const char *, ...)
__attribute__ ((format (printf, 3, 4)));
#endif
#if !defined(HAVE_VSNPRINTF) || defined(NEED_VSNPRINTF_PROTO)
+#ifndef HAVE_VSNPRINTF
+#define vsnprintf rk_vsnprintf
+#endif
int ROKEN_LIB_FUNCTION
- vsnprintf (char *, size_t, const char *, va_list)
+ rk_vsnprintf (char *, size_t, const char *, va_list)
__attribute__((format (printf, 3, 0)));
#endif
#if !defined(HAVE_ASPRINTF) || defined(NEED_ASPRINTF_PROTO)
+#ifndef HAVE_ASPRINTF
+#define asprintf rk_asprintf
+#endif
int ROKEN_LIB_FUNCTION
- asprintf (char **, const char *, ...)
+ rk_asprintf (char **, const char *, ...)
__attribute__ ((format (printf, 2, 3)));
#endif
#if !defined(HAVE_VASPRINTF) || defined(NEED_VASPRINTF_PROTO)
+#ifndef HAVE_VASPRINTF
+#define vasprintf rk_vasprintf
+#endif
int ROKEN_LIB_FUNCTION
- vasprintf (char **, const char *, va_list)
+ rk_vasprintf (char **, const char *, va_list)
__attribute__((format (printf, 2, 0)));
#endif
#if !defined(HAVE_ASNPRINTF) || defined(NEED_ASNPRINTF_PROTO)
+#ifndef HAVE_ASNPRINTF
+#define asnprintf rk_asnprintf
+#endif
int ROKEN_LIB_FUNCTION
- asnprintf (char **, size_t, const char *, ...)
+ rk_asnprintf (char **, size_t, const char *, ...)
__attribute__ ((format (printf, 3, 4)));
#endif
#if !defined(HAVE_VASNPRINTF) || defined(NEED_VASNPRINTF_PROTO)
+#ifndef HAVE_VASNPRINTF
+#define vasnprintf rk_vasnprintf
+#endif
int ROKEN_LIB_FUNCTION
vasnprintf (char **, size_t, const char *, va_list)
__attribute__((format (printf, 3, 0)));
#endif
#ifndef HAVE_STRDUP
+#define strdup rk_strdup
char * ROKEN_LIB_FUNCTION strdup(const char *);
#endif
#if !defined(HAVE_STRNDUP) || defined(NEED_STRNDUP_PROTO)
+#ifndef HAVE_STRNDUP
+#define strndup rk_strndup
+#endif
char * ROKEN_LIB_FUNCTION strndup(const char *, size_t);
#endif
#ifndef HAVE_STRLWR
+#define strlwr rk_strlwr
char * ROKEN_LIB_FUNCTION strlwr(char *);
#endif
#ifndef HAVE_STRNLEN
+#define strnlen rk_strnlen
size_t ROKEN_LIB_FUNCTION strnlen(const char*, size_t);
#endif
#if !defined(HAVE_STRSEP) || defined(NEED_STRSEP_PROTO)
+#ifndef HAVE_STRSEP
+#define strsep rk_strsep
+#endif
char * ROKEN_LIB_FUNCTION strsep(char**, const char*);
#endif
#if !defined(HAVE_STRSEP_COPY) || defined(NEED_STRSEP_COPY_PROTO)
+#ifndef HAVE_STRSEP_COPY
+#define strsep_copy rk_strsep_copy
+#endif
ssize_t ROKEN_LIB_FUNCTION strsep_copy(const char**, const char*, char*, size_t);
#endif
#ifndef HAVE_STRCASECMP
+#define strcasecmp rk_strcasecmp
int ROKEN_LIB_FUNCTION strcasecmp(const char *, const char *);
#endif
@@ -240,26 +280,34 @@ char * ROKEN_LIB_FUNCTION strtok_r(char *, const char *, char **);
#endif
#ifndef HAVE_STRUPR
+#define strupr rk_strupr
char * ROKEN_LIB_FUNCTION strupr(char *);
#endif
#ifndef HAVE_STRLCPY
+#define strlcpy rk_strlcpy
size_t ROKEN_LIB_FUNCTION strlcpy (char *, const char *, size_t);
#endif
#ifndef HAVE_STRLCAT
+#define strlcat rk_strlcat
size_t ROKEN_LIB_FUNCTION strlcat (char *, const char *, size_t);
#endif
#ifndef HAVE_GETDTABLESIZE
+#define getdtablesize rk_getdtablesize
int ROKEN_LIB_FUNCTION getdtablesize(void);
#endif
#if !defined(HAVE_STRERROR) && !defined(strerror)
+#define strerror rk_strerror
char * ROKEN_LIB_FUNCTION strerror(int);
#endif
#if !defined(HAVE_HSTRERROR) || defined(NEED_HSTRERROR_PROTO)
+#ifndef HAVE_HSTRERROR
+#define hstrerror rk_hstrerror
+#endif
/* This causes a fatal error under Psoriasis */
#if !(defined(SunOS) && (SunOS >= 50))
const char * ROKEN_LIB_FUNCTION hstrerror(int);
@@ -271,20 +319,26 @@ extern int h_errno;
#endif
#if !defined(HAVE_INET_ATON) || defined(NEED_INET_ATON_PROTO)
+#ifndef HAVE_INET_ATON
+#define inet_aton rk_inet_aton
+#endif
int ROKEN_LIB_FUNCTION inet_aton(const char *, struct in_addr *);
#endif
#ifndef HAVE_INET_NTOP
+#define inet_ntop rk_inet_ntop
const char * ROKEN_LIB_FUNCTION
inet_ntop(int af, const void *src, char *dst, size_t size);
#endif
#ifndef HAVE_INET_PTON
+#define inet_pton rk_inet_pton
int ROKEN_LIB_FUNCTION
inet_pton(int, const char *, void *);
#endif
#if !defined(HAVE_GETCWD)
+#define getcwd rk_getcwd
char* ROKEN_LIB_FUNCTION getcwd(char *, size_t);
#endif
@@ -297,91 +351,108 @@ struct passwd * ROKEN_LIB_FUNCTION k_getpwuid (uid_t);
const char * ROKEN_LIB_FUNCTION get_default_username (void);
#ifndef HAVE_SETEUID
+#define seteuid rk_seteuid
int ROKEN_LIB_FUNCTION seteuid(uid_t);
#endif
#ifndef HAVE_SETEGID
+#define setegid rk_setegid
int ROKEN_LIB_FUNCTION setegid(gid_t);
#endif
#ifndef HAVE_LSTAT
+#define lstat rk_lstat
int ROKEN_LIB_FUNCTION lstat(const char *, struct stat *);
#endif
#if !defined(HAVE_MKSTEMP) || defined(NEED_MKSTEMP_PROTO)
+#ifndef HAVE_MKSTEMP
+#define mkstemp rk_mkstemp
+#endif
int ROKEN_LIB_FUNCTION mkstemp(char *);
#endif
#ifndef HAVE_CGETENT
+#define cgetent rk_cgetent
+#define cgetstr rk_cgetstr
int ROKEN_LIB_FUNCTION cgetent(char **, char **, const char *);
int ROKEN_LIB_FUNCTION cgetstr(char *, const char *, char **);
#endif
#ifndef HAVE_INITGROUPS
+#define initgroups rk_initgroups
int ROKEN_LIB_FUNCTION initgroups(const char *, gid_t);
#endif
#ifndef HAVE_FCHOWN
+#define fchown rk_fchown
int ROKEN_LIB_FUNCTION fchown(int, uid_t, gid_t);
#endif
#if !defined(HAVE_DAEMON) || defined(NEED_DAEMON_PROTO)
-int ROKEN_LIB_FUNCTION daemon(int, int);
+#ifndef HAVE_DAEMON
+#define daemon rk_daemon
#endif
-
-#ifndef HAVE_INNETGR
-int ROKEN_LIB_FUNCTION innetgr(const char *, const char *,
- const char *, const char *);
+int ROKEN_LIB_FUNCTION daemon(int, int);
#endif
#ifndef HAVE_CHOWN
+#define chown rk_chown
int ROKEN_LIB_FUNCTION chown(const char *, uid_t, gid_t);
#endif
#ifndef HAVE_RCMD
+#define rcmd rk_rcmd
int ROKEN_LIB_FUNCTION
rcmd(char **, unsigned short, const char *,
const char *, const char *, int *);
#endif
#if !defined(HAVE_INNETGR) || defined(NEED_INNETGR_PROTO)
+#ifndef HAVE_INNETGR
+#define innetgr rk_innetgr
+#endif
int ROKEN_LIB_FUNCTION innetgr(const char*, const char*,
const char*, const char*);
#endif
#ifndef HAVE_IRUSEROK
+#define iruserok rk_iruserok
int ROKEN_LIB_FUNCTION iruserok(unsigned, int,
const char *, const char *);
#endif
#if !defined(HAVE_GETHOSTNAME) || defined(NEED_GETHOSTNAME_PROTO)
+#ifndef HAVE_GETHOSTNAME
+#define gethostname rk_gethostname
+#endif
int ROKEN_LIB_FUNCTION gethostname(char *, int);
#endif
#ifndef HAVE_WRITEV
+#define writev rk_writev
ssize_t ROKEN_LIB_FUNCTION
writev(int, const struct iovec *, int);
#endif
#ifndef HAVE_READV
+#define readv rk_readv
ssize_t ROKEN_LIB_FUNCTION
readv(int, const struct iovec *, int);
#endif
-#ifndef HAVE_MKSTEMP
-int ROKEN_LIB_FUNCTION
-mkstemp(char *);
-#endif
-
#ifndef HAVE_PIDFILE
+#define pidfile rk_pidfile
void ROKEN_LIB_FUNCTION pidfile (const char*);
#endif
#ifndef HAVE_BSWAP32
+#define bswap32 rk_bswap32
unsigned int ROKEN_LIB_FUNCTION bswap32(unsigned int);
#endif
#ifndef HAVE_BSWAP16
+#define bswap16 rk_bswap16
unsigned short ROKEN_LIB_FUNCTION bswap16(unsigned short);
#endif
@@ -399,6 +470,7 @@ unsigned short ROKEN_LIB_FUNCTION bswap16(unsigned short);
#define LOCK_UN 8 /* Unlock */
#endif
+#define flock rk_flock
int flock(int fd, int operation);
#endif /* HAVE_FLOCK */
@@ -431,6 +503,7 @@ struct winsize {
int ROKEN_LIB_FUNCTION get_window_size(int fd, struct winsize *);
#ifndef HAVE_VSYSLOG
+#define vsyslog rk_vsyslog
void ROKEN_LIB_FUNCTION vsyslog(int, const char *, va_list);
#endif
@@ -445,21 +518,25 @@ extern int opterr;
#endif
#ifndef HAVE_GETIPNODEBYNAME
+#define getipnodebyname rk_getipnodebyname
struct hostent * ROKEN_LIB_FUNCTION
getipnodebyname (const char *, int, int, int *);
#endif
#ifndef HAVE_GETIPNODEBYADDR
+#define getipnodebyaddr rk_getipnodebyaddr
struct hostent * ROKEN_LIB_FUNCTION
getipnodebyaddr (const void *, size_t, int, int *);
#endif
#ifndef HAVE_FREEHOSTENT
+#define freehostent rk_freehostent
void ROKEN_LIB_FUNCTION
freehostent (struct hostent *);
#endif
#ifndef HAVE_COPYHOSTENT
+#define copyhostent rk_copyhostent
struct hostent * ROKEN_LIB_FUNCTION
copyhostent (const struct hostent *);
#endif
@@ -527,6 +604,7 @@ struct addrinfo {
#endif
#ifndef HAVE_GETADDRINFO
+#define getaddrinfo rk_getaddrinfo
int ROKEN_LIB_FUNCTION
getaddrinfo(const char *,
const char *,
@@ -535,6 +613,7 @@ getaddrinfo(const char *,
#endif
#ifndef HAVE_GETNAMEINFO
+#define getnameinfo rk_getnameinfo
int ROKEN_LIB_FUNCTION
getnameinfo(const struct sockaddr *, socklen_t,
char *, size_t,
@@ -543,11 +622,13 @@ getnameinfo(const struct sockaddr *, socklen_t,
#endif
#ifndef HAVE_FREEADDRINFO
+#define freeaddrinfo rk_freeaddrinfo
void ROKEN_LIB_FUNCTION
freeaddrinfo(struct addrinfo *);
#endif
#ifndef HAVE_GAI_STRERROR
+#define gai_strerror rk_gai_strerror
const char * ROKEN_LIB_FUNCTION
gai_strerror(int);
#endif
@@ -564,25 +645,31 @@ int ROKEN_LIB_FUNCTION
roken_getaddrinfo_hostspec2(const char *, int, int, struct addrinfo **);
#ifndef HAVE_STRFTIME
+#define strftime rk_strftime
size_t ROKEN_LIB_FUNCTION
strftime (char *, size_t, const char *, const struct tm *);
#endif
#ifndef HAVE_STRPTIME
+#define strptime rk_strptime
char * ROKEN_LIB_FUNCTION
strptime (const char *, const char *, struct tm *);
#endif
#ifndef HAVE_EMALLOC
+#define emalloc rk_emalloc
void * ROKEN_LIB_FUNCTION emalloc (size_t);
#endif
#ifndef HAVE_ECALLOC
+#define ecalloc rk_ecalloc
void * ROKEN_LIB_FUNCTION ecalloc(size_t, size_t);
#endif
#ifndef HAVE_EREALLOC
+#define erealloc rk_erealloc
void * ROKEN_LIB_FUNCTION erealloc (void *, size_t);
#endif
#ifndef HAVE_ESTRDUP
+#define estrdup rk_estrdup
char * ROKEN_LIB_FUNCTION estrdup (const char *);
#endif
@@ -630,10 +717,12 @@ roken_gethostbyaddr(const void*, size_t, int);
#endif
#ifndef HAVE_SETPROGNAME
+#define setprogname rk_setprogname
void ROKEN_LIB_FUNCTION setprogname(const char *);
#endif
#ifndef HAVE_GETPROGNAME
+#define getprogname rk_getprogname
const char * ROKEN_LIB_FUNCTION getprogname(void);
#endif
@@ -645,46 +734,69 @@ void ROKEN_LIB_FUNCTION mini_inetd_addrinfo (struct addrinfo*);
void ROKEN_LIB_FUNCTION mini_inetd (int);
#ifndef HAVE_LOCALTIME_R
+#define localtime_r rk_localtime_r
struct tm * ROKEN_LIB_FUNCTION
localtime_r(const time_t *, struct tm *);
#endif
#if !defined(HAVE_STRSVIS) || defined(NEED_STRSVIS_PROTO)
+#ifndef HAVE_STRSVIS
+#define strsvis rk_strsvis
+#endif
int ROKEN_LIB_FUNCTION
strsvis(char *, const char *, int, const char *);
#endif
#if !defined(HAVE_STRUNVIS) || defined(NEED_STRUNVIS_PROTO)
+#ifndef HAVE_STRUNVIS
+#define strunvis rk_strunvis
+#endif
int ROKEN_LIB_FUNCTION
strunvis(char *, const char *);
#endif
#if !defined(HAVE_STRVIS) || defined(NEED_STRVIS_PROTO)
+#ifndef HAVE_STRVIS
+#define strvis rk_strvis
+#endif
int ROKEN_LIB_FUNCTION
strvis(char *, const char *, int);
#endif
#if !defined(HAVE_STRVISX) || defined(NEED_STRVISX_PROTO)
+#ifndef HAVE_STRVISX
+#define strvisx rk_strvisx
+#endif
int ROKEN_LIB_FUNCTION
strvisx(char *, const char *, size_t, int);
#endif
#if !defined(HAVE_SVIS) || defined(NEED_SVIS_PROTO)
+#ifndef HAVE_SVIS
+#define svis rk_svis
+#endif
char * ROKEN_LIB_FUNCTION
svis(char *, int, int, int, const char *);
#endif
#if !defined(HAVE_UNVIS) || defined(NEED_UNVIS_PROTO)
+#ifndef HAVE_UNVIS
+#define unvis rk_unvis
+#endif
int ROKEN_LIB_FUNCTION
unvis(char *, int, int *, int);
#endif
#if !defined(HAVE_VIS) || defined(NEED_VIS_PROTO)
+#ifndef HAVE_VIS
+#define vis rk_vis
+#endif
char * ROKEN_LIB_FUNCTION
vis(char *, int, int, int);
#endif
#if !defined(HAVE_CLOSEFROM)
+#define closefrom rk_closefrom
int ROKEN_LIB_FUNCTION
closefrom(int);
#endif
diff --git a/source4/heimdal/lib/roken/roken_gethostby.c b/source4/heimdal/lib/roken/roken_gethostby.c
index 12760456a4..d87a49a04b 100644
--- a/source4/heimdal/lib/roken/roken_gethostby.c
+++ b/source4/heimdal/lib/roken/roken_gethostby.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/rtbl.c b/source4/heimdal/lib/roken/rtbl.c
index cfb7657091..7d11a487cf 100644
--- a/source4/heimdal/lib/roken/rtbl.c
+++ b/source4/heimdal/lib/roken/rtbl.c
@@ -31,10 +31,8 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID ("$Id$");
-#endif
+
#include "roken.h"
#include "rtbl.h"
diff --git a/source4/heimdal/lib/roken/setprogname.c b/source4/heimdal/lib/roken/setprogname.c
index 9beb07afe9..225e6ae092 100644
--- a/source4/heimdal/lib/roken/setprogname.c
+++ b/source4/heimdal/lib/roken/setprogname.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/signal.c b/source4/heimdal/lib/roken/signal.c
index 9141ca2bb1..19a4845435 100644
--- a/source4/heimdal/lib/roken/signal.c
+++ b/source4/heimdal/lib/roken/signal.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <signal.h>
#include "roken.h"
diff --git a/source4/heimdal/lib/roken/simple_exec.c b/source4/heimdal/lib/roken/simple_exec.c
index 7060cb8d37..86dde1bad2 100644
--- a/source4/heimdal/lib/roken/simple_exec.c
+++ b/source4/heimdal/lib/roken/simple_exec.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <stdarg.h>
#include <stdlib.h>
@@ -51,10 +48,6 @@ RCSID("$Id$");
#include "roken.h"
-#if !HAVE_DECL_ENVIRON
-extern char **environ;
-#endif
-
#define EX_NOEXEC 126
#define EX_NOTFOUND 127
@@ -316,20 +309,3 @@ simple_execle(const char *file, ... /* ,char *const envp[] */)
free(argv);
return ret;
}
-
-int ROKEN_LIB_FUNCTION
-simple_execl(const char *file, ...)
-{
- va_list ap;
- char **argv;
- int ret;
-
- va_start(ap, file);
- argv = vstrcollect(&ap);
- va_end(ap);
- if(argv == NULL)
- return -1;
- ret = simple_execve(file, argv, environ);
- free(argv);
- return ret;
-}
diff --git a/source4/heimdal/lib/roken/socket.c b/source4/heimdal/lib/roken/socket.c
index a373eb7ed2..ab1b7ff344 100644
--- a/source4/heimdal/lib/roken/socket.c
+++ b/source4/heimdal/lib/roken/socket.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
#include <err.h>
@@ -152,17 +149,17 @@ socket_sockaddr_size (const struct sockaddr *sa)
*/
void * ROKEN_LIB_FUNCTION
-socket_get_address (struct sockaddr *sa)
+socket_get_address (const struct sockaddr *sa)
{
switch (sa->sa_family) {
case AF_INET : {
- struct sockaddr_in *sin4 = (struct sockaddr_in *)sa;
- return &sin4->sin_addr;
+ const struct sockaddr_in *sin4 = (const struct sockaddr_in *)sa;
+ return rk_UNCONST(&sin4->sin_addr);
}
#ifdef HAVE_IPV6
case AF_INET6 : {
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
- return &sin6->sin6_addr;
+ const struct sockaddr_in6 *sin6 = (const struct sockaddr_in6 *)sa;
+ return rk_UNCONST(&sin6->sin6_addr);
}
#endif
default :
diff --git a/source4/heimdal/lib/roken/strcollect.c b/source4/heimdal/lib/roken/strcollect.c
index a33d52134a..f444d05e25 100644
--- a/source4/heimdal/lib/roken/strcollect.c
+++ b/source4/heimdal/lib/roken/strcollect.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <stdarg.h>
#include <stdlib.h>
diff --git a/source4/heimdal/lib/roken/strlwr.c b/source4/heimdal/lib/roken/strlwr.c
index ea787d8184..1a6634b736 100644
--- a/source4/heimdal/lib/roken/strlwr.c
+++ b/source4/heimdal/lib/roken/strlwr.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <string.h>
#include <ctype.h>
diff --git a/source4/heimdal/lib/roken/strpool.c b/source4/heimdal/lib/roken/strpool.c
index aa80996946..dc56892144 100644
--- a/source4/heimdal/lib/roken/strpool.c
+++ b/source4/heimdal/lib/roken/strpool.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <stdarg.h>
#include <stdlib.h>
diff --git a/source4/heimdal/lib/roken/strsep.c b/source4/heimdal/lib/roken/strsep.c
index 7a93fb17aa..5cbf8557a5 100644
--- a/source4/heimdal/lib/roken/strsep.c
+++ b/source4/heimdal/lib/roken/strsep.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <string.h>
diff --git a/source4/heimdal/lib/roken/strsep_copy.c b/source4/heimdal/lib/roken/strsep_copy.c
index 61b7d39c57..908e37ca40 100644
--- a/source4/heimdal/lib/roken/strsep_copy.c
+++ b/source4/heimdal/lib/roken/strsep_copy.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <string.h>
diff --git a/source4/heimdal/lib/roken/strupr.c b/source4/heimdal/lib/roken/strupr.c
index d67dd20dd0..db2d987f9f 100644
--- a/source4/heimdal/lib/roken/strupr.c
+++ b/source4/heimdal/lib/roken/strupr.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <string.h>
#include <ctype.h>
diff --git a/source4/heimdal/lib/roken/vis.c b/source4/heimdal/lib/roken/vis.c
index 43705e4d50..c8d19a4455 100644
--- a/source4/heimdal/lib/roken/vis.c
+++ b/source4/heimdal/lib/roken/vis.c
@@ -56,10 +56,7 @@
*/
#if 1
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include "roken.h"
#ifndef _DIAGASSERT
#define _DIAGASSERT(X)
diff --git a/source4/heimdal/lib/roken/xfree.c b/source4/heimdal/lib/roken/xfree.c
index 5f6d86ee56..13366ce132 100644
--- a/source4/heimdal/lib/roken/xfree.c
+++ b/source4/heimdal/lib/roken/xfree.c
@@ -31,10 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-RCSID("$Id$");
-#endif
#include <unistd.h>
diff --git a/source4/heimdal/lib/vers/print_version.c b/source4/heimdal/lib/vers/print_version.c
index 63e016174a..9d102c7dc5 100644
--- a/source4/heimdal/lib/vers/print_version.c
+++ b/source4/heimdal/lib/vers/print_version.c
@@ -31,18 +31,17 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
+
#include <config.h>
-RCSID("$Id$");
-#endif
+
#include "roken.h"
-#include "print_version.h"
+#include "version.h"
-void
+void ROKEN_LIB_FUNCTION
print_version(const char *progname)
{
- const char *package_list = VERSIONLIST;
+ const char *package_list = heimdal_version;
if(progname == NULL)
progname = getprogname();
diff --git a/source4/heimdal/lib/wind/normalize.c b/source4/heimdal/lib/wind/normalize.c
index c7af0e4958..3f71449fac 100644
--- a/source4/heimdal/lib/wind/normalize.c
+++ b/source4/heimdal/lib/wind/normalize.c
@@ -235,10 +235,9 @@ combine(const uint32_t *in, size_t in_len,
int ostarter;
unsigned o = 0;
int old_cc;
- int cc;
for (i = 0; i < in_len;) {
- while (i < in_len && (cc = _wind_combining_class(in[i])) != 0) {
+ while (i < in_len && _wind_combining_class(in[i]) != 0) {
out[o++] = in[i++];
}
if (i < in_len) {
@@ -251,6 +250,7 @@ combine(const uint32_t *in, size_t in_len,
while (i < in_len) {
uint32_t comb;
uint32_t v[2];
+ int cc;
v[0] = out[ostarter];
v[1] = in[i];
diff --git a/source4/heimdal/lib/wind/stringprep.c b/source4/heimdal/lib/wind/stringprep.c
index 6e99cfc86b..aa04b3fd1d 100644
--- a/source4/heimdal/lib/wind/stringprep.c
+++ b/source4/heimdal/lib/wind/stringprep.c
@@ -107,7 +107,7 @@ wind_stringprep(const uint32_t *in, size_t in_len,
return ret;
}
-static struct {
+const static struct {
const char *name;
wind_profile_flags flags;
} profiles[] = {
diff --git a/source4/heimdal/lib/wind/utf8.c b/source4/heimdal/lib/wind/utf8.c
index f563b79107..ed944b4c7d 100644
--- a/source4/heimdal/lib/wind/utf8.c
+++ b/source4/heimdal/lib/wind/utf8.c
@@ -31,9 +31,7 @@
* SUCH DAMAGE.
*/
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "windlocl.h"
RCSID("$Id$");
diff --git a/source4/heimdal/lib/wind/wind_err.et b/source4/heimdal/lib/wind/wind_err.et
index f90c252e7d..01c0d0f1c5 100644
--- a/source4/heimdal/lib/wind/wind_err.et
+++ b/source4/heimdal/lib/wind/wind_err.et
@@ -12,8 +12,8 @@ error_code NONE, "No error"
error_code NO_PROFILE, "No such profile"
error_code OVERRUN, "Buffer overrun"
error_code UNDERUN, "Buffer underrun"
-error_code LENGTH_NOT_MOD2, "Lenght not mod2"
-error_code LENGTH_NOT_MOD4, "Lenght not mod4"
+error_code LENGTH_NOT_MOD2, "Length not mod2"
+error_code LENGTH_NOT_MOD4, "Length not mod4"
error_code INVALID_UTF8, "Invalid UTF-8 combination in string"
error_code INVALID_UTF16, "Invalid UTF-16 combination in string"
error_code INVALID_UTF32, "Invalid UTF-32 combination in string"