s4:heimdal: import lorikeet-heimdal-200903260854 (commit 8f3b61e3fb466bb9dd457ae88ee0...
authorStefan Metzmacher <metze@samba.org>
Thu, 26 Mar 2009 19:12:06 +0000 (20:12 +0100)
committerStefan Metzmacher <metze@samba.org>
Thu, 26 Mar 2009 19:12:06 +0000 (20:12 +0100)
252 files changed:
source4/heimdal/README
source4/heimdal/cf/make-proto.pl
source4/heimdal/cf/resolv.m4
source4/heimdal/kdc/524.c
source4/heimdal/kdc/default_config.c
source4/heimdal/kdc/digest.c
source4/heimdal/kdc/headers.h
source4/heimdal/kdc/kaserver.c
source4/heimdal/kdc/kdc.h
source4/heimdal/kdc/kdc_locl.h
source4/heimdal/kdc/kerberos4.c
source4/heimdal/kdc/kerberos5.c
source4/heimdal/kdc/krb5tgs.c
source4/heimdal/kdc/kx509.c
source4/heimdal/kdc/pkinit.c
source4/heimdal/kdc/process.c
source4/heimdal/kuser/kinit.c
source4/heimdal/kuser/kuser_locl.h
source4/heimdal/lib/asn1/CMS.asn1 [deleted file]
source4/heimdal/lib/asn1/asn1_err.et
source4/heimdal/lib/asn1/der_get.c
source4/heimdal/lib/asn1/der_locl.h
source4/heimdal/lib/asn1/extra.c
source4/heimdal/lib/asn1/gen.c
source4/heimdal/lib/asn1/gen_decode.c
source4/heimdal/lib/asn1/gen_locl.h
source4/heimdal/lib/asn1/k5.asn1 [deleted file]
source4/heimdal/lib/asn1/kx509.asn1
source4/heimdal/lib/asn1/main.c
source4/heimdal/lib/asn1/parse.y
source4/heimdal/lib/asn1/pkinit.asn1
source4/heimdal/lib/asn1/rfc2459.asn1
source4/heimdal/lib/com_err/com_err.c
source4/heimdal/lib/com_err/compile_et.c
source4/heimdal/lib/com_err/compile_et.h
source4/heimdal/lib/com_err/error.c
source4/heimdal/lib/com_err/lex.l
source4/heimdal/lib/com_err/parse.y
source4/heimdal/lib/gssapi/gssapi/gssapi.h
source4/heimdal/lib/gssapi/gssapi/gssapi_krb5.h
source4/heimdal/lib/gssapi/gssapi_mech.h
source4/heimdal/lib/gssapi/krb5/8003.c
source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
source4/heimdal/lib/gssapi/krb5/acquire_cred.c
source4/heimdal/lib/gssapi/krb5/add_cred.c
source4/heimdal/lib/gssapi/krb5/address_to_krb5addr.c
source4/heimdal/lib/gssapi/krb5/arcfour.c
source4/heimdal/lib/gssapi/krb5/canonicalize_name.c
source4/heimdal/lib/gssapi/krb5/cfx.c
source4/heimdal/lib/gssapi/krb5/compare_name.c
source4/heimdal/lib/gssapi/krb5/compat.c
source4/heimdal/lib/gssapi/krb5/context_time.c
source4/heimdal/lib/gssapi/krb5/copy_ccache.c
source4/heimdal/lib/gssapi/krb5/decapsulate.c
source4/heimdal/lib/gssapi/krb5/delete_sec_context.c
source4/heimdal/lib/gssapi/krb5/display_name.c
source4/heimdal/lib/gssapi/krb5/display_status.c
source4/heimdal/lib/gssapi/krb5/duplicate_name.c
source4/heimdal/lib/gssapi/krb5/encapsulate.c
source4/heimdal/lib/gssapi/krb5/export_name.c
source4/heimdal/lib/gssapi/krb5/export_sec_context.c
source4/heimdal/lib/gssapi/krb5/external.c
source4/heimdal/lib/gssapi/krb5/get_mic.c
source4/heimdal/lib/gssapi/krb5/gsskrb5_locl.h
source4/heimdal/lib/gssapi/krb5/import_name.c
source4/heimdal/lib/gssapi/krb5/import_sec_context.c
source4/heimdal/lib/gssapi/krb5/indicate_mechs.c
source4/heimdal/lib/gssapi/krb5/init.c
source4/heimdal/lib/gssapi/krb5/init_sec_context.c
source4/heimdal/lib/gssapi/krb5/inquire_context.c
source4/heimdal/lib/gssapi/krb5/inquire_cred.c
source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c
source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c
source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c
source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c
source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c
source4/heimdal/lib/gssapi/krb5/prf.c
source4/heimdal/lib/gssapi/krb5/process_context_token.c
source4/heimdal/lib/gssapi/krb5/release_buffer.c
source4/heimdal/lib/gssapi/krb5/release_cred.c
source4/heimdal/lib/gssapi/krb5/release_name.c
source4/heimdal/lib/gssapi/krb5/sequence.c
source4/heimdal/lib/gssapi/krb5/set_cred_option.c
source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c
source4/heimdal/lib/gssapi/krb5/unwrap.c
source4/heimdal/lib/gssapi/krb5/verify_mic.c
source4/heimdal/lib/gssapi/krb5/wrap.c
source4/heimdal/lib/gssapi/mech/context.c
source4/heimdal/lib/gssapi/mech/gss_canonicalize_name.c
source4/heimdal/lib/gssapi/mech/gss_get_mic.c
source4/heimdal/lib/gssapi/mech/gss_import_name.c
source4/heimdal/lib/gssapi/mech/gss_mech_switch.c
source4/heimdal/lib/gssapi/mech/gss_pseudo_random.c
source4/heimdal/lib/gssapi/mech/gss_verify_mic.c
source4/heimdal/lib/gssapi/mech/gss_wrap.c
source4/heimdal/lib/gssapi/mech/gss_wrap_size_limit.c
source4/heimdal/lib/gssapi/mech/mech_locl.h
source4/heimdal/lib/gssapi/mech/mech_switch.h
source4/heimdal/lib/gssapi/spnego/accept_sec_context.c
source4/heimdal/lib/gssapi/spnego/compat.c
source4/heimdal/lib/gssapi/spnego/context_stubs.c
source4/heimdal/lib/gssapi/spnego/cred_stubs.c
source4/heimdal/lib/gssapi/spnego/external.c
source4/heimdal/lib/gssapi/spnego/init_sec_context.c
source4/heimdal/lib/gssapi/spnego/spnego_locl.h
source4/heimdal/lib/hcrypto/bn.c
source4/heimdal/lib/hcrypto/bn.h
source4/heimdal/lib/hcrypto/evp-aes-cts.c
source4/heimdal/lib/hcrypto/evp.c
source4/heimdal/lib/hcrypto/rand-unix.c
source4/heimdal/lib/hcrypto/rand.c
source4/heimdal/lib/hdb/dbinfo.c
source4/heimdal/lib/hdb/hdb.asn1
source4/heimdal/lib/hdb/hdb.c
source4/heimdal/lib/hdb/keys.c
source4/heimdal/lib/hdb/keytab.c
source4/heimdal/lib/hx509/ca.c
source4/heimdal/lib/hx509/cert.c
source4/heimdal/lib/hx509/cms.c
source4/heimdal/lib/hx509/collector.c
source4/heimdal/lib/hx509/crypto.c
source4/heimdal/lib/hx509/env.c
source4/heimdal/lib/hx509/error.c
source4/heimdal/lib/hx509/file.c
source4/heimdal/lib/hx509/hx509.h
source4/heimdal/lib/hx509/hx509_err.et
source4/heimdal/lib/hx509/hx_locl.h
source4/heimdal/lib/hx509/keyset.c
source4/heimdal/lib/hx509/ks_dir.c
source4/heimdal/lib/hx509/ks_file.c
source4/heimdal/lib/hx509/ks_keychain.c
source4/heimdal/lib/hx509/ks_mem.c
source4/heimdal/lib/hx509/ks_null.c
source4/heimdal/lib/hx509/ks_p11.c
source4/heimdal/lib/hx509/ks_p12.c
source4/heimdal/lib/hx509/lock.c
source4/heimdal/lib/hx509/name.c
source4/heimdal/lib/hx509/peer.c
source4/heimdal/lib/hx509/print.c
source4/heimdal/lib/hx509/req.c
source4/heimdal/lib/hx509/revoke.c
source4/heimdal/lib/hx509/sel-gram.y
source4/heimdal/lib/hx509/test_name.c
source4/heimdal/lib/krb5/acache.c
source4/heimdal/lib/krb5/addr_families.c
source4/heimdal/lib/krb5/asn1_glue.c
source4/heimdal/lib/krb5/build_auth.c
source4/heimdal/lib/krb5/cache.c
source4/heimdal/lib/krb5/changepw.c
source4/heimdal/lib/krb5/codec.c
source4/heimdal/lib/krb5/config_file.c
source4/heimdal/lib/krb5/constants.c
source4/heimdal/lib/krb5/context.c
source4/heimdal/lib/krb5/convert_creds.c
source4/heimdal/lib/krb5/crc.c
source4/heimdal/lib/krb5/creds.c
source4/heimdal/lib/krb5/crypto.c
source4/heimdal/lib/krb5/data.c
source4/heimdal/lib/krb5/error_string.c
source4/heimdal/lib/krb5/fcache.c
source4/heimdal/lib/krb5/get_addrs.c
source4/heimdal/lib/krb5/get_cred.c
source4/heimdal/lib/krb5/get_host_realm.c
source4/heimdal/lib/krb5/get_in_tkt.c
source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c [deleted file]
source4/heimdal/lib/krb5/heim_err.et
source4/heimdal/lib/krb5/init_creds.c
source4/heimdal/lib/krb5/init_creds_pw.c
source4/heimdal/lib/krb5/kcm.c
source4/heimdal/lib/krb5/keyblock.c
source4/heimdal/lib/krb5/keytab.c
source4/heimdal/lib/krb5/keytab_any.c
source4/heimdal/lib/krb5/keytab_file.c
source4/heimdal/lib/krb5/keytab_keyfile.c
source4/heimdal/lib/krb5/keytab_memory.c
source4/heimdal/lib/krb5/krb5.h
source4/heimdal/lib/krb5/krb5_ccapi.h
source4/heimdal/lib/krb5/krb5_locl.h
source4/heimdal/lib/krb5/krbhst.c
source4/heimdal/lib/krb5/mit_glue.c
source4/heimdal/lib/krb5/n-fold.c
source4/heimdal/lib/krb5/pac.c
source4/heimdal/lib/krb5/pkinit.c
source4/heimdal/lib/krb5/principal.c
source4/heimdal/lib/krb5/prog_setup.c
source4/heimdal/lib/krb5/rd_cred.c
source4/heimdal/lib/krb5/rd_rep.c
source4/heimdal/lib/krb5/rd_req.c
source4/heimdal/lib/krb5/store-int.h
source4/heimdal/lib/krb5/store.c
source4/heimdal/lib/krb5/store_emem.c
source4/heimdal/lib/krb5/store_fd.c
source4/heimdal/lib/krb5/store_mem.c
source4/heimdal/lib/krb5/ticket.c
source4/heimdal/lib/krb5/v4_glue.c
source4/heimdal/lib/krb5/warn.c
source4/heimdal/lib/ntlm/ntlm.c
source4/heimdal/lib/roken/base64.c
source4/heimdal/lib/roken/bswap.c
source4/heimdal/lib/roken/cloexec.c
source4/heimdal/lib/roken/closefrom.c
source4/heimdal/lib/roken/copyhostent.c
source4/heimdal/lib/roken/dumpdata.c
source4/heimdal/lib/roken/ecalloc.c
source4/heimdal/lib/roken/emalloc.c
source4/heimdal/lib/roken/erealloc.c
source4/heimdal/lib/roken/estrdup.c
source4/heimdal/lib/roken/freeaddrinfo.c
source4/heimdal/lib/roken/freehostent.c
source4/heimdal/lib/roken/gai_strerror.c
source4/heimdal/lib/roken/get_window_size.c
source4/heimdal/lib/roken/getaddrinfo.c
source4/heimdal/lib/roken/getarg.c
source4/heimdal/lib/roken/getipnodebyaddr.c
source4/heimdal/lib/roken/getipnodebyname.c
source4/heimdal/lib/roken/getnameinfo.c
source4/heimdal/lib/roken/getprogname.c
source4/heimdal/lib/roken/h_errno.c
source4/heimdal/lib/roken/hex.c
source4/heimdal/lib/roken/hostent_find_fqdn.c
source4/heimdal/lib/roken/inet_aton.c
source4/heimdal/lib/roken/inet_ntop.c
source4/heimdal/lib/roken/inet_pton.c
source4/heimdal/lib/roken/issuid.c
source4/heimdal/lib/roken/net_read.c
source4/heimdal/lib/roken/net_write.c
source4/heimdal/lib/roken/parse_time.c
source4/heimdal/lib/roken/parse_units.c
source4/heimdal/lib/roken/resolve.c
source4/heimdal/lib/roken/resolve.h
source4/heimdal/lib/roken/rkpty.c
source4/heimdal/lib/roken/roken-common.h
source4/heimdal/lib/roken/roken.h.in
source4/heimdal/lib/roken/roken_gethostby.c
source4/heimdal/lib/roken/rtbl.c
source4/heimdal/lib/roken/setprogname.c
source4/heimdal/lib/roken/signal.c
source4/heimdal/lib/roken/simple_exec.c
source4/heimdal/lib/roken/socket.c
source4/heimdal/lib/roken/strcollect.c
source4/heimdal/lib/roken/strlwr.c
source4/heimdal/lib/roken/strpool.c
source4/heimdal/lib/roken/strsep.c
source4/heimdal/lib/roken/strsep_copy.c
source4/heimdal/lib/roken/strupr.c
source4/heimdal/lib/roken/vis.c
source4/heimdal/lib/roken/xfree.c
source4/heimdal/lib/vers/print_version.c
source4/heimdal/lib/wind/normalize.c
source4/heimdal/lib/wind/stringprep.c
source4/heimdal/lib/wind/utf8.c
source4/heimdal/lib/wind/wind_err.et

index 3b938248fcb7c159523686182682d5b66263db41..f130698597c86861fce9d59cf180d2a553377f8e 100644 (file)
@@ -1,4 +1,3 @@
-$Id$
 
 Heimdal is a Kerberos 5 implementation.
 
index b89ef790670b4b7fce0e306bc689e1359b4fd748..f62fb4cd0db43364e02fbcce5cf677ce5a6ef507 100644 (file)
@@ -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*\(/</;
index b4045094d8026522e0dee0671f66379eb44ed372..49c868ab0ec6042ead5b2e3d0999d1c62a919348 100644 (file)
@@ -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>
index d15310384aed52ef76645c5c5ab063446f144970..76641b389222871e215a5c655453383a1e21b8b9 100644 (file)
@@ -304,7 +304,6 @@ _kdc_do_524(krb5_context context,
     krb5_storage *sp;
     char *spn = NULL;
     unsigned char buf[MAX_KTXT_LEN + 4 * 4];
-    size_t len;
     int kvno = 0;
 
     if(!config->enable_524) {
@@ -342,8 +341,7 @@ _kdc_do_524(krb5_context context,
                "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);
+    ret = decode_EncTicketPart(et_data.data, et_data.length, &et, NULL);
     krb5_data_free(&et_data);
     if(ret){
        kdc_log(context, config, 0,
index 60fbc92903ce926e035f8d35460d891f72419373..bf65af3cb9e3ea72f69c67e81474334d2b8f57c7 100644 (file)
@@ -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);
 
index 96986c1a877d3ab20582d884bb46967e10d7fc74..d13507fc1f80b8f55f5c8a70bab825b4f289ecfe 100644 (file)
@@ -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 */
index 3635d3c56a885b88150e2a18b71ffe325e864e00..2240336e31f3789aea4e38a31185da69937452af 100644 (file)
 #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
index 9226ae115db0b9353679a6bf4d40bc20f3daae17..3702ab9281291836d18a78fa8bf31b6643edebd5 100644 (file)
@@ -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 */
index 843bd5fa5689df16cc789e437287a7d974259e8c..e493c74cfc2fe08512b4d51afdc75768c6b6e130 100644 (file)
@@ -75,6 +75,7 @@ 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;
 
@@ -91,6 +92,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
index 8e34c50049aa267b701c246494dec3b9ff713fab..9b291ac896511314b51cd1cdbde617c4a10098f7 100644 (file)
@@ -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[];
 
index 2bd2383940527c62e58e3a82b8a0dbb54726cb14..2fc946a38e266a9afdd2705f086aa1c23dd304fe 100644 (file)
@@ -33,9 +33,9 @@
 
 #include "kdc_locl.h"
 
-#include <krb5-v4compat.h>
+#ifdef KRB4
 
-RCSID("$Id$");
+#include <krb5-v4compat.h>
 
 #ifndef swap32
 static uint32_t
@@ -792,3 +792,4 @@ _kdc_get_des_key(krb5_context context,
     return 0;
 }
 
+#endif /* KRB4 */
index c715e0812f319c8aa7021a10637e5c5ad84366a4..ff29592c6fb8d3ef0d8301dbc3432b9ee7f6d751 100644 (file)
@@ -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;
@@ -1127,11 +1067,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 +1099,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,
@@ -1298,6 +1245,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;
@@ -1335,17 +1283,26 @@ _kdc_as_rep(krb5_context context,
         *   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.
         */
 
-       /* XXX check ret */
-       if (only_older_enctype_p(req))
+       if (older_enctype(ckey->key.keytype)) {
            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);
-
+                                   &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 +1320,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 +1412,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 +1465,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 +1534,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.
@@ -1640,19 +1604,26 @@ _kdc_as_rep(krb5_context context,
     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,
                                           config,
                                           pkp,
                                           &et);
-       if (ret)
-           goto out;
-    }
+    } else
+#else
+       ret = krb5_generate_random_keyblock(context, sessionetype, &et.key);
 #endif
+    if (ret)
+       goto out;
+
+    ret = copy_EncryptionKey(&et.key, &ek.key);
+    if (ret)
+       goto out;
 
     set_salt_padata (rep.padata, ckey->salt);
 
index 4cf93e5a54be2dc0691677b3d8794d3fb0cbe419..688e355bd09385e07c060f1f7461399ef5b47be6 100644 (file)
@@ -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,
@@ -1205,9 +1205,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 +1230,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 +1250,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);
@@ -1375,13 +1373,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 +1388,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 +1557,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 +1574,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 +1589,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;
@@ -1603,10 +1600,6 @@ server_lookup:
            goto out;
     }
 
-    /*
-     * 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
@@ -1628,13 +1621,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;
     }
 
index 83e05b81c5952ed2d2f26240d7140eb2410c6df4..358fd6098c125c7113d4073bf8a7aa813cea60a9 100644 (file)
 #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;
@@ -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;
@@ -458,3 +457,5 @@ out:
 
     return 0;
 }
+
+#endif /* KX509 */
index 82358682d8d9f9cb5f6bf6a97794932bd7241107..eee8d9a433445c0ed5f2a76fcf9814bd58538cc4 100644 (file)
@@ -47,10 +47,21 @@ 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;
@@ -158,12 +169,24 @@ void
 _kdc_pk_free_client_param(krb5_context context,
                          pk_client_params *client_params)
 {
+    if (client_params == NULL)
+        return;
     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);
+    if (client_params->keyex == USE_DH) {
+       if (client_params->u.dh.key)
+           DH_free(client_params->u.dh.key);
+       if (client_params->u.dh.public_key)
+           BN_free(client_params->u.dh.public_key);
+    }
+#ifdef HAVE_OPENSSL
+    if (client_params->keyex == USE_ECDH) {
+       if (client_params->u.ecdh.key)
+           EC_KEY_free(client_params->u.ecdh.key);
+       if (client_params->u.ecdh.public_key)
+           EC_KEY_free(client_params->u.ecdh.public_key);
+    }
+#endif
     krb5_free_keyblock_contents(context, &client_params->reply_key);
     if (client_params->dh_group_name)
        free(client_params->dh_group_name);
@@ -176,8 +199,9 @@ _kdc_pk_free_client_param(krb5_context context,
 }
 
 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 +210,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
+    } 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 +295,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 +333,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 +358,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 +396,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,6 +417,69 @@ 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
+
 krb5_error_code
 _kdc_pk_rd_padata(krb5_context context,
                  krb5_kdc_configuration *config,
@@ -389,6 +517,13 @@ _kdc_pk_rd_padata(krb5_context context,
 
        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 +541,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,7 +555,8 @@ _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;
        }
        
@@ -434,7 +570,9 @@ _kdc_pk_rd_padata(krb5_context context,
                                   0, NULL,
                                   &client_params->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;
 
            }
@@ -464,8 +602,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,
@@ -514,9 +654,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,
+                                     flags,
                                      signed_content.data,
                                      signed_content.length,
                                      NULL,
@@ -532,9 +677,11 @@ _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,
+                                    &client_params->cert);
+           hx509_certs_free(&signer_certs);
+       }
        if (ret)
            goto out;
     }
@@ -556,7 +703,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;
        }
 
@@ -573,7 +721,8 @@ _kdc_pk_rd_padata(krb5_context context,
 
        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 +735,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);
@@ -603,13 +762,26 @@ _kdc_pk_rd_padata(krb5_context context,
        client_params->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) {
+               client_params->keyex = USE_DH;
+               ret = get_dh_param(context, config,
+                                  ap.clientPublicValue, client_params);
+#ifdef HAVE_OPENSSL
+           } else if (der_heim_oid_cmp(&ap.clientPublicValue->algorithm.algorithm, &asn1_oid_id_ecPublicKey) == 0) {
+               client_params->keyex = USE_ECDH;
+               ret = get_ecdh_param(context, config,
+                                    ap.clientPublicValue, client_params);
+#endif
+           } else {
+               ret = KRB5_BADMSGTYPE;
+               krb5_set_error_message(context, ret, "PKINIT unknown DH mechanism");
+           }
            if (ret) {
                free_AuthPack(&ap);
                goto out;
            }
-       }
+       } else
+           client_params->keyex = USE_RSA;
 
        if (ap.supportedCMSTypes) {
            ret = hx509_peer_info_alloc(kdc_identity->hx509ctx,
@@ -642,9 +814,9 @@ out:
     krb5_data_free(&eContent);
     der_free_oid(&eContentType);
     der_free_oid(&contentInfoOid);
-    if (ret)
-       _kdc_pk_free_client_param(context, client_params);
-    else
+    if (ret) {
+        _kdc_pk_free_client_param(context, client_params);
+    } else 
        *ret_params = client_params;
     return ret;
 }
@@ -674,7 +846,8 @@ pk_mk_pa_reply_enckey(krb5_context context,
                      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,6 +858,8 @@ 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
@@ -777,7 +952,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,
@@ -798,7 +974,7 @@ pk_mk_pa_reply_enckey(krb5_context context,
                                        client_params->client_anchors,
                                        kdc_identity->certpool,
                                        &signed_data);
-       hx509_cert_free(cert);
+       *kdc_cert = cert;
     }
 
     krb5_data_free(&buf);
@@ -816,7 +992,7 @@ pk_mk_pa_reply_enckey(krb5_context context,
     }
 
     ret = hx509_cms_envelope_1(kdc_identity->hx509ctx,
-                              0,
+                              HX509_CMS_EV_NO_KU_CHECK,
                               client_params->cert,
                               signed_data.data, signed_data.length,
                               envelopedAlg,
@@ -829,6 +1005,11 @@ pk_mk_pa_reply_enckey(krb5_context context,
                                  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 +1021,8 @@ out:
 
 static krb5_error_code
 pk_mk_pa_reply_dh(krb5_context context,
-                  DH *kdc_dh,
+                 krb5_kdc_configuration *config,
                  pk_client_params *client_params,
-                  krb5_keyblock *reply_key,
                  ContentInfo *content_info,
                  hx509_cert *kdc_cert)
 {
@@ -851,31 +1031,61 @@ pk_mk_pa_reply_dh(krb5_context context,
     ContentInfo contentinfo;
     krb5_error_code ret;
     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 (client_params->keyex == USE_DH) {
+       DH *kdc_dh = client_params->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);
+    } else if (client_params->keyex == USE_ECDH) {
+#ifdef HAVE_OPENSSL
+       unsigned char *p;
+       int len;
+
+       len = i2o_ECPublicKey(client_params->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(client_params->u.ecdh.key, &p);
+       if (len <= 0)
+           abort();
+#else
+       return ENOMEM;
+#endif
+    } else
+       krb5_abortx(context, "no keyex selected ?");
 
+       
     dh_info.nonce = client_params->nonce;
 
     ASN1_MALLOC_ENCODE(KDCDHKeyInfo, buf.data, buf.length, &dh_info, &size,
@@ -902,7 +1112,8 @@ pk_mk_pa_reply_dh(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,
@@ -957,9 +1168,11 @@ _kdc_pk_mk_pa_reply(krb5_context context,
                    krb5_kdc_configuration *config,
                    pk_client_params *client_params,
                    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;
@@ -997,7 +1210,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
 
        pa_type = KRB5_PADATA_PK_AS_REP;
 
-       if (client_params->dh == NULL) {
+       if (client_params->keyex == USE_RSA) {
            ContentInfo info;
 
            type = "enckey";
@@ -1016,7 +1229,8 @@ _kdc_pk_mk_pa_reply(krb5_context context,
                                        req,
                                        req_buffer,
                                        &client_params->reply_key,
-                                       &info);
+                                       &info,
+                                       &kdc_cert);
            if (ret) {
                free_PA_PK_AS_REP(&rep);
                goto out;
@@ -1034,23 +1248,33 @@ _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";
+           switch (client_params->keyex) {
+           case USE_DH: type = "dh"; break;
+           case USE_ECDH: type = "ecdh"; break;
+           default: krb5_abortx(context, "unknown keyex"); break;
+           }
+
            if (client_params->dh_group_name)
                other = client_params->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, client_params, enctype);
            if (ret)
                return ret;
 
-           ret = pk_mk_pa_reply_dh(context, client_params->dh,
+           ret = pk_mk_pa_reply_dh(context, config,
                                    client_params,
-                                   &client_params->reply_key,
                                    &info,
                                    &kdc_cert);
 
@@ -1059,7 +1283,8 @@ _kdc_pk_mk_pa_reply(krb5_context context,
                               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 +1292,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)
@@ -1089,9 +1320,10 @@ _kdc_pk_mk_pa_reply(krb5_context context,
        PA_PK_AS_REP_Win2k rep;
        ContentInfo info;
 
-       if (client_params->dh) {
+       if (client_params->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;
        }
 
@@ -1112,7 +1344,8 @@ _kdc_pk_mk_pa_reply(krb5_context context,
                                    req,
                                    req_buffer,
                                    &client_params->reply_key,
-                                   &info);
+                                   &info,
+                                   &kdc_cert);
        if (ret) {
            free_PA_PK_AS_REP_Win2k(&rep);
            goto out;
@@ -1140,13 +1373,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;
     }
@@ -1371,6 +1610,14 @@ _kdc_pk_check_client(krb5_context context,
     hx509_name name;
     int i;
 
+    if (client_params->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,
                                      &name);
@@ -1594,6 +1841,7 @@ _kdc_pk_initialize(krb5_context context,
 
     ret = _krb5_pk_load_id(context,
                           &kdc_identity,
+                          0,
                           user_id,
                           anchors,
                           pool,
@@ -1618,7 +1866,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,10 +1876,17 @@ _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 "
+                                    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 "
index a27911914b52434fba48ae7463275a830335fb06..d3557ee6c9e45af0733ba5006d73f0c09bfcd251 100644 (file)
@@ -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;
 }
 
index fbb2d2287bcd012b4b2d7cda162b98742b768ae7..bf52a38391b665bccd7d6ce200f057fd019c1e47 100644 (file)
  */
 
 #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", "") },
@@ -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)
@@ -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;
index eed9e00af6bf9e05f437b9f73202c59d73c713b0..eafffe9bffc99897aa143c451821f65c2e67b6e3 100644 (file)
@@ -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/CMS.asn1 b/source4/heimdal/lib/asn1/CMS.asn1
deleted file mode 100644 (file)
index 65a4675..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
--- From RFC 3369 --
--- $Id$ --
-
-CMS DEFINITIONS ::= BEGIN
-
-IMPORTS CertificateSerialNumber, AlgorithmIdentifier, Name,
-       Attribute, Certificate, Name, SubjectKeyIdentifier FROM rfc2459
-       heim_any, heim_any_set FROM heim;
-
-id-pkcs7 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
-         us(840) rsadsi(113549) pkcs(1) pkcs7(7) }
-
-id-pkcs7-data OBJECT IDENTIFIER ::=                    { id-pkcs7 1 }
-id-pkcs7-signedData OBJECT IDENTIFIER ::=              { id-pkcs7 2 }
-id-pkcs7-envelopedData OBJECT IDENTIFIER ::=           { id-pkcs7 3 }
-id-pkcs7-signedAndEnvelopedData OBJECT IDENTIFIER ::=  { id-pkcs7 4 }
-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_v2(2),
-          CMSVersion_v3(3),
-          CMSVersion_v4(4)
-}
-
-DigestAlgorithmIdentifier ::= AlgorithmIdentifier
-DigestAlgorithmIdentifiers ::= SET OF DigestAlgorithmIdentifier
-SignatureAlgorithmIdentifier ::= AlgorithmIdentifier
-
-ContentType ::= OBJECT IDENTIFIER
-MessageDigest ::= OCTET STRING
-
-ContentInfo ::= SEQUENCE {
-       contentType ContentType,
-       content [0] EXPLICIT heim_any OPTIONAL --  DEFINED BY contentType 
-}
-
-EncapsulatedContentInfo ::= SEQUENCE {
-       eContentType ContentType,
-       eContent [0] EXPLICIT OCTET STRING OPTIONAL
-}
-
-CertificateSet ::= SET OF heim_any
-
-CertificateList ::= Certificate
-
-CertificateRevocationLists ::= SET OF CertificateList
-
-IssuerAndSerialNumber ::= SEQUENCE {
-       issuer Name,
-       serialNumber CertificateSerialNumber
-}
-
--- RecipientIdentifier is same as SignerIdentifier, 
--- lets glue them togheter and save some bytes and share code for them
-
-CMSIdentifier ::= CHOICE {
-       issuerAndSerialNumber IssuerAndSerialNumber,
-       subjectKeyIdentifier [0] SubjectKeyIdentifier
-}
-
-SignerIdentifier ::= CMSIdentifier
-RecipientIdentifier ::= CMSIdentifier
-
---- CMSAttributes are the combined UnsignedAttributes and SignedAttributes
---- to store space and share code
-
-CMSAttributes ::= SET OF Attribute             -- SIZE (1..MAX) 
-
-SignatureValue ::= OCTET STRING
-
-SignerInfo ::= SEQUENCE {
-       version CMSVersion,
-       sid SignerIdentifier,
-       digestAlgorithm DigestAlgorithmIdentifier,
-       signedAttrs [0] IMPLICIT -- CMSAttributes --
-               SET OF Attribute OPTIONAL,
-       signatureAlgorithm SignatureAlgorithmIdentifier,
-       signature SignatureValue,
-       unsignedAttrs [1] IMPLICIT -- CMSAttributes -- 
-               SET OF Attribute OPTIONAL
-}
-
-SignerInfos ::= SET OF SignerInfo
-
-SignedData ::= SEQUENCE {
-       version CMSVersion,
-       digestAlgorithms DigestAlgorithmIdentifiers,
-       encapContentInfo EncapsulatedContentInfo,
-       certificates [0] IMPLICIT -- CertificateSet --
-               SET OF heim_any OPTIONAL,
-       crls [1] IMPLICIT -- CertificateRevocationLists --
-               heim_any OPTIONAL,
-       signerInfos SignerInfos
-}
-
-OriginatorInfo ::= SEQUENCE {
-       certs [0] IMPLICIT -- CertificateSet --
-               SET OF heim_any OPTIONAL,
-       crls [1] IMPLICIT --CertificateRevocationLists --
-               heim_any OPTIONAL
-}
-
-KeyEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
-ContentEncryptionAlgorithmIdentifier ::= AlgorithmIdentifier
-
-EncryptedKey ::= OCTET STRING
-
-KeyTransRecipientInfo ::= SEQUENCE {
-       version CMSVersion,  -- always set to 0 or 2
-       rid RecipientIdentifier,
-       keyEncryptionAlgorithm KeyEncryptionAlgorithmIdentifier,
-       encryptedKey EncryptedKey
-}
-
-RecipientInfo ::= KeyTransRecipientInfo
-
-RecipientInfos ::= SET OF RecipientInfo
-
-EncryptedContent ::= OCTET STRING
-
-EncryptedContentInfo ::= SEQUENCE {
-       contentType ContentType,
-       contentEncryptionAlgorithm ContentEncryptionAlgorithmIdentifier,
-       encryptedContent [0] IMPLICIT OCTET STRING OPTIONAL
-}
-
-UnprotectedAttributes ::= SET OF Attribute     -- SIZE (1..MAX)
-
-CMSEncryptedData ::= SEQUENCE {
-       version CMSVersion,
-       encryptedContentInfo EncryptedContentInfo,
-        unprotectedAttrs [1] IMPLICIT -- UnprotectedAttributes --
-               heim_any OPTIONAL
-}
-
-EnvelopedData ::= SEQUENCE {
-       version CMSVersion,
-       originatorInfo [0] IMPLICIT -- OriginatorInfo -- heim_any OPTIONAL,
-       recipientInfos RecipientInfos,
-       encryptedContentInfo EncryptedContentInfo,
-       unprotectedAttrs [1] IMPLICIT -- UnprotectedAttributes --
-               heim_any OPTIONAL
-}
-
--- Data ::= OCTET STRING
-
-CMSRC2CBCParameter ::= SEQUENCE {
-       rc2ParameterVersion     INTEGER (0..4294967295),
-       iv                      OCTET STRING -- exactly 8 octets
-}
-
-CMSCBCParameter ::= OCTET STRING
-
-END
index 26bda55c1900656ff985742544ced2d9b1eed666..f1a653b1f9ac929a2c9fe11661c10845c6f6b82c 100644 (file)
@@ -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
index 8a709664133d3ab28990045a596afe6624a99cd8..28ec70c293adfa44e1f8a19c3dccad389092d746 100644 (file)
 
 #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
@@ -251,6 +247,75 @@ der_get_octet_string (const unsigned char *p, size_t len,
     return 0;
 }
 
+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)
@@ -456,16 +521,29 @@ int
 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,13 +555,13 @@ 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;
@@ -497,6 +575,8 @@ der_match_tag_and_length (const unsigned char *p, size_t len,
     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 +619,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;
 }
index f8a21de71c1d78ab7493bf230fd46d4fb253111d..1f27e7290304d2f6002c9dff31764f6db5df6cc1 100644 (file)
@@ -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>
index 49240605c82a4bc8f6e8a4af7608dc5a88341ef9..bbf75c838828286ad55084a108d6a078e1a63504 100644 (file)
@@ -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;
 
index 52fd0d393b7832cc609397d53adc3de9870b7835..7098f2675e673dd381640298311fea86301b25fe 100644 (file)
@@ -229,7 +229,7 @@ gen_compare_defval(const char *var, struct value *val)
     }
 }
 
-static void
+void
 generate_header_of_codefile(const char *name)
 {
     char *filename;
@@ -267,7 +267,7 @@ generate_header_of_codefile(const char *name)
 
 }
 
-static void
+void
 close_codefile(void)
 {
     if (codefile == NULL)
@@ -296,7 +296,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 +321,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 +335,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;
     }
@@ -787,7 +795,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 +807,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();
+       }
 }
index 2bd5acb47e82d727b3d5084d4454c2b06cb9840f..641355e401b3e90bf2f4e39575212e673eb307bf 100644 (file)
@@ -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,7 +350,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);
            free (s);
        }
        
@@ -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: {
@@ -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"
index c8b38963141ac36d2b5f3c1649391d15aff75767..2bb64b5a38590c5cbc6f3241de3cbd6636a00c70 100644 (file)
@@ -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/k5.asn1
deleted file mode 100644 (file)
index 9b36498..0000000
+++ /dev/null
@@ -1,671 +0,0 @@
--- $Id$
-
-KERBEROS5 DEFINITIONS ::=
-BEGIN
-
-NAME-TYPE ::= INTEGER {
-       KRB5_NT_UNKNOWN(0),     -- Name type not known
-       KRB5_NT_PRINCIPAL(1),   -- Just the name of the principal as in
-       KRB5_NT_SRV_INST(2),    -- Service and other unique instance (krbtgt)
-       KRB5_NT_SRV_HST(3),     -- Service with host name as instance
-       KRB5_NT_SRV_XHST(4),    -- Service with host as remaining components
-       KRB5_NT_UID(5),         -- Unique ID
-       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_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
-}
-
--- message types
-
-MESSAGE-TYPE ::= INTEGER {
-       krb-as-req(10), -- Request for initial authentication
-       krb-as-rep(11), -- Response to KRB_AS_REQ request
-       krb-tgs-req(12), -- Request for authentication based on TGT
-       krb-tgs-rep(13), -- Response to KRB_TGS_REQ request
-       krb-ap-req(14), -- application request to server
-       krb-ap-rep(15), -- Response to KRB_AP_REQ_MUTUAL
-       krb-safe(20), -- Safe (checksummed) application message
-       krb-priv(21), -- Private (encrypted) application message
-       krb-cred(22), -- Private (encrypted) message to forward credentials
-       krb-error(30) -- Error response
-}
-
-
--- pa-data types
-
-PADATA-TYPE ::= INTEGER {
-       KRB5-PADATA-NONE(0),
-       KRB5-PADATA-TGS-REQ(1),
-       KRB5-PADATA-AP-REQ(1),
-       KRB5-PADATA-ENC-TIMESTAMP(2),
-       KRB5-PADATA-PW-SALT(3),
-       KRB5-PADATA-ENC-UNIX-TIME(5),
-       KRB5-PADATA-SANDIA-SECUREID(6),
-       KRB5-PADATA-SESAME(7),
-       KRB5-PADATA-OSF-DCE(8),
-       KRB5-PADATA-CYBERSAFE-SECUREID(9),
-       KRB5-PADATA-AFS3-SALT(10),
-       KRB5-PADATA-ETYPE-INFO(11),
-       KRB5-PADATA-SAM-CHALLENGE(12), -- (sam/otp)
-       KRB5-PADATA-SAM-RESPONSE(13), -- (sam/otp)
-       KRB5-PADATA-PK-AS-REQ-19(14), -- (PKINIT-19)
-       KRB5-PADATA-PK-AS-REP-19(15), -- (PKINIT-19)
-       KRB5-PADATA-PK-AS-REQ-WIN(15), -- (PKINIT - old number)
-       KRB5-PADATA-PK-AS-REQ(16), -- (PKINIT-25)
-       KRB5-PADATA-PK-AS-REP(17), -- (PKINIT-25)
-       KRB5-PADATA-PA-PK-OCSP-RESPONSE(18),
-       KRB5-PADATA-ETYPE-INFO2(19),
-       KRB5-PADATA-USE-SPECIFIED-KVNO(20),
-       KRB5-PADATA-SVR-REFERRAL-INFO(20), --- old ms referral number
-       KRB5-PADATA-SAM-REDIRECT(21), -- (sam/otp)
-       KRB5-PADATA-GET-FROM-TYPED-DATA(22),
-       KRB5-PADATA-SAM-ETYPE-INFO(23),
-       KRB5-PADATA-SERVER-REFERRAL(25),
-       KRB5-PADATA-TD-KRB-PRINCIPAL(102),      -- PrincipalName
-       KRB5-PADATA-PK-TD-TRUSTED-CERTIFIERS(104), -- PKINIT
-       KRB5-PADATA-PK-TD-CERTIFICATE-INDEX(105), -- PKINIT
-       KRB5-PADATA-TD-APP-DEFINED-ERROR(106),  -- application specific
-       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 
-                                               -- the asCheckSum in the
-                                               --  PK-AS-REP
-       KRB5-PADATA-CLIENT-CANONICALIZED(133)   -- 
-}
-
-AUTHDATA-TYPE ::= INTEGER {
-       KRB5-AUTHDATA-IF-RELEVANT(1),
-       KRB5-AUTHDATA-INTENDED-FOR_SERVER(2),
-       KRB5-AUTHDATA-INTENDED-FOR-APPLICATION-CLASS(3),
-       KRB5-AUTHDATA-KDC-ISSUED(4),
-       KRB5-AUTHDATA-AND-OR(5),
-       KRB5-AUTHDATA-MANDATORY-TICKET-EXTENSIONS(6),
-       KRB5-AUTHDATA-IN-TICKET-EXTENSIONS(7),
-       KRB5-AUTHDATA-MANDATORY-FOR-KDC(8),
-       KRB5-AUTHDATA-INITIAL-VERIFIED-CAS(9),
-       KRB5-AUTHDATA-OSF-DCE(64),
-       KRB5-AUTHDATA-SESAME(65),
-       KRB5-AUTHDATA-OSF-DCE-PKI-CERTID(66),
-       KRB5-AUTHDATA-WIN2K-PAC(128),
-       KRB5-AUTHDATA-GSS-API-ETYPE-NEGOTIATION(129), -- Authenticator only
-       KRB5-AUTHDATA-SIGNTICKET-OLD(-17),
-       KRB5-AUTHDATA-SIGNTICKET(142)
-}
-
--- checksumtypes
-
-CKSUMTYPE ::= INTEGER {
-       CKSUMTYPE_NONE(0),
-       CKSUMTYPE_CRC32(1),
-       CKSUMTYPE_RSA_MD4(2),
-       CKSUMTYPE_RSA_MD4_DES(3),
-       CKSUMTYPE_DES_MAC(4),
-       CKSUMTYPE_DES_MAC_K(5),
-       CKSUMTYPE_RSA_MD4_DES_K(6),
-       CKSUMTYPE_RSA_MD5(7),
-       CKSUMTYPE_RSA_MD5_DES(8),
-       CKSUMTYPE_RSA_MD5_DES3(9),
-       CKSUMTYPE_SHA1_OTHER(10),
-       CKSUMTYPE_HMAC_SHA1_DES3(12),
-       CKSUMTYPE_SHA1(14),
-       CKSUMTYPE_HMAC_SHA1_96_AES_128(15),
-       CKSUMTYPE_HMAC_SHA1_96_AES_256(16),
-       CKSUMTYPE_GSSAPI(0x8003),
-       CKSUMTYPE_HMAC_MD5(-138),       -- unofficial microsoft number
-       CKSUMTYPE_HMAC_MD5_ENC(-1138)   -- even more unofficial
-}
-
---enctypes
-ENCTYPE ::= INTEGER {
-       ETYPE_NULL(0),
-       ETYPE_DES_CBC_CRC(1),
-       ETYPE_DES_CBC_MD4(2),
-       ETYPE_DES_CBC_MD5(3),
-       ETYPE_DES3_CBC_MD5(5),
-       ETYPE_OLD_DES3_CBC_SHA1(7),
-       ETYPE_SIGN_DSA_GENERATE(8),
-       ETYPE_ENCRYPT_RSA_PRIV(9),
-       ETYPE_ENCRYPT_RSA_PUB(10),
-       ETYPE_DES3_CBC_SHA1(16),        -- with key derivation
-       ETYPE_AES128_CTS_HMAC_SHA1_96(17),
-       ETYPE_AES256_CTS_HMAC_SHA1_96(18),
-       ETYPE_ARCFOUR_HMAC_MD5(23),
-       ETYPE_ARCFOUR_HMAC_MD5_56(24),
-       ETYPE_ENCTYPE_PK_CROSS(48),
--- some "old" windows types
-       ETYPE_ARCFOUR_MD4(-128),
-       ETYPE_ARCFOUR_HMAC_OLD(-133),
-       ETYPE_ARCFOUR_HMAC_OLD_EXP(-135),
--- these are for Heimdal internal use
-       ETYPE_DES_CBC_NONE(-0x1000),
-       ETYPE_DES3_CBC_NONE(-0x1001),
-       ETYPE_DES_CFB64_NONE(-0x1002),
-       ETYPE_DES_PCBC_NONE(-0x1003),
-       ETYPE_DIGEST_MD5_NONE(-0x1004),         -- private use, lukeh@padl.com
-       ETYPE_CRAM_MD5_NONE(-0x1005)            -- private use, lukeh@padl.com
-}
-
-
-
-
--- this is sugar to make something ASN1 does not have: unsigned
-
-krb5uint32 ::= INTEGER (0..4294967295)
-krb5int32 ::= INTEGER (-2147483648..2147483647)
-
-KerberosString  ::= GeneralString
-
-Realm ::= GeneralString
-PrincipalName ::= SEQUENCE {
-       name-type[0]            NAME-TYPE,
-       name-string[1]          SEQUENCE OF GeneralString
-}
-
--- this is not part of RFC1510
-Principal ::= SEQUENCE {
-       name[0]                 PrincipalName,
-       realm[1]                Realm
-}
-
-HostAddress ::= SEQUENCE  {
-       addr-type[0]            krb5int32,
-       address[1]              OCTET STRING
-}
-
--- This is from RFC1510.
---
--- HostAddresses ::= SEQUENCE OF SEQUENCE {
---     addr-type[0]            krb5int32,
---     address[1]              OCTET STRING
--- }
-
--- This seems much better.
-HostAddresses ::= SEQUENCE OF HostAddress
-
-
-KerberosTime ::= GeneralizedTime -- Specifying UTC time zone (Z)
-
-AuthorizationDataElement ::= SEQUENCE {
-       ad-type[0]              krb5int32,
-       ad-data[1]              OCTET STRING
-}
-
-AuthorizationData ::= SEQUENCE OF AuthorizationDataElement
-
-APOptions ::= BIT STRING {
-       reserved(0),
-       use-session-key(1),
-       mutual-required(2)
-}
-
-TicketFlags ::= BIT STRING {
-       reserved(0),
-       forwardable(1),
-       forwarded(2),
-       proxiable(3),
-       proxy(4),
-       may-postdate(5),
-       postdated(6),
-       invalid(7),
-       renewable(8),
-       initial(9),
-       pre-authent(10),
-       hw-authent(11),
-       transited-policy-checked(12),
-       ok-as-delegate(13),
-       anonymous(14)
-}
-
-KDCOptions ::= BIT STRING {
-       reserved(0),
-       forwardable(1),
-       forwarded(2),
-       proxiable(3),
-       proxy(4),
-       allow-postdate(5),
-       postdated(6),
-       unused7(7),
-       renewable(8),
-       unused9(9),
-       unused10(10),
-       unused11(11),
-       request-anonymous(14),
-       canonicalize(15),
-       constrained-delegation(16), -- ms extension
-       disable-transited-check(26),
-       renewable-ok(27),
-       enc-tkt-in-skey(28),
-       renew(30),
-       validate(31)
-}
-
-LR-TYPE ::= INTEGER {
-       LR_NONE(0),             -- no information
-       LR_INITIAL_TGT(1),      -- last initial TGT request
-       LR_INITIAL(2),          -- last initial request
-       LR_ISSUE_USE_TGT(3),    -- time of newest TGT used
-       LR_RENEWAL(4),          -- time of last renewal
-       LR_REQUEST(5),          -- time of last request (of any type)
-       LR_PW_EXPTIME(6),       -- expiration time of password
-       LR_ACCT_EXPTIME(7)      -- expiration time of account
-}
-
-LastReq ::= SEQUENCE OF SEQUENCE {
-       lr-type[0]              LR-TYPE,
-       lr-value[1]             KerberosTime
-}
-
-
-EncryptedData ::= SEQUENCE {
-       etype[0]                ENCTYPE, -- EncryptionType
-       kvno[1]                 krb5int32 OPTIONAL,
-       cipher[2]               OCTET STRING -- ciphertext
-}
-
-EncryptionKey ::= SEQUENCE {
-       keytype[0]              krb5int32,
-       keyvalue[1]             OCTET STRING
-}
-
--- encoded Transited field
-TransitedEncoding ::= SEQUENCE {
-       tr-type[0]              krb5int32, -- must be registered
-       contents[1]             OCTET STRING
-}
-
-Ticket ::= [APPLICATION 1] SEQUENCE {
-       tkt-vno[0]              krb5int32,
-       realm[1]                Realm,
-       sname[2]                PrincipalName,
-       enc-part[3]             EncryptedData
-}
--- Encrypted part of ticket
-EncTicketPart ::= [APPLICATION 3] SEQUENCE {
-       flags[0]                TicketFlags,
-       key[1]                  EncryptionKey,
-       crealm[2]               Realm,
-       cname[3]                PrincipalName,
-       transited[4]            TransitedEncoding,
-       authtime[5]             KerberosTime,
-       starttime[6]            KerberosTime OPTIONAL,
-       endtime[7]              KerberosTime,
-       renew-till[8]           KerberosTime OPTIONAL,
-       caddr[9]                HostAddresses OPTIONAL,
-       authorization-data[10]  AuthorizationData OPTIONAL
-}
-
-Checksum ::= SEQUENCE {
-       cksumtype[0]            CKSUMTYPE,
-       checksum[1]             OCTET STRING
-}
-
-Authenticator ::= [APPLICATION 2] SEQUENCE    {
-       authenticator-vno[0]    krb5int32,
-       crealm[1]               Realm,
-       cname[2]                PrincipalName,
-       cksum[3]                Checksum OPTIONAL,
-       cusec[4]                krb5int32,
-       ctime[5]                KerberosTime,
-       subkey[6]               EncryptionKey OPTIONAL,
-       seq-number[7]           krb5uint32 OPTIONAL,
-       authorization-data[8]   AuthorizationData OPTIONAL
-}
-
-PA-DATA ::= SEQUENCE {
-       -- might be encoded AP-REQ
-       padata-type[1]          PADATA-TYPE,
-       padata-value[2]         OCTET STRING
-}
-
-ETYPE-INFO-ENTRY ::= SEQUENCE {
-       etype[0]                ENCTYPE,
-       salt[1]                 OCTET STRING OPTIONAL,
-       salttype[2]             krb5int32 OPTIONAL
-}
-
-ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY
-
-ETYPE-INFO2-ENTRY ::= SEQUENCE {
-       etype[0]                ENCTYPE,
-       salt[1]                 KerberosString OPTIONAL,
-       s2kparams[2]            OCTET STRING OPTIONAL
-}
-
-ETYPE-INFO2 ::= SEQUENCE SIZE (1..MAX) OF ETYPE-INFO2-ENTRY
-
-METHOD-DATA ::= SEQUENCE OF PA-DATA
-
-TypedData ::=   SEQUENCE {
-       data-type[0]            krb5int32,
-       data-value[1]           OCTET STRING OPTIONAL
-}
-
-TYPED-DATA ::= SEQUENCE SIZE (1..MAX) OF TypedData
-
-KDC-REQ-BODY ::= SEQUENCE {
-       kdc-options[0]          KDCOptions,
-       cname[1]                PrincipalName OPTIONAL, -- Used only in AS-REQ
-       realm[2]                Realm,  -- Server's realm
-                                       -- Also client's in AS-REQ
-       sname[3]                PrincipalName OPTIONAL,
-       from[4]                 KerberosTime OPTIONAL,
-       till[5]                 KerberosTime OPTIONAL,
-       rtime[6]                KerberosTime OPTIONAL,
-       nonce[7]                krb5int32,
-       etype[8]                SEQUENCE OF ENCTYPE, -- EncryptionType,
-                                       -- in preference order
-       addresses[9]            HostAddresses OPTIONAL,
-       enc-authorization-data[10] EncryptedData OPTIONAL,
-                                       -- Encrypted AuthorizationData encoding
-       additional-tickets[11]  SEQUENCE OF Ticket OPTIONAL
-}
-
-KDC-REQ ::= SEQUENCE {
-       pvno[1]                 krb5int32,
-       msg-type[2]             MESSAGE-TYPE,
-       padata[3]               METHOD-DATA OPTIONAL,
-       req-body[4]             KDC-REQ-BODY
-}
-
-AS-REQ ::= [APPLICATION 10] KDC-REQ
-TGS-REQ ::= [APPLICATION 12] KDC-REQ
-
--- padata-type ::= PA-ENC-TIMESTAMP
--- padata-value ::= EncryptedData - PA-ENC-TS-ENC
-
-PA-ENC-TS-ENC ::= SEQUENCE {
-       patimestamp[0]          KerberosTime, -- client's time
-       pausec[1]               krb5int32 OPTIONAL
-}
-
--- draft-brezak-win2k-krb-authz-01
-PA-PAC-REQUEST ::= SEQUENCE {
-       include-pac[0]          BOOLEAN -- Indicates whether a PAC 
-                                       -- should be included or not
-}
-
--- PacketCable provisioning server location, PKT-SP-SEC-I09-030728.pdf
-PROV-SRV-LOCATION ::= GeneralString
-
-KDC-REP ::= SEQUENCE {
-       pvno[0]                 krb5int32,
-       msg-type[1]             MESSAGE-TYPE,
-       padata[2]               METHOD-DATA OPTIONAL,
-       crealm[3]               Realm,
-       cname[4]                PrincipalName,
-       ticket[5]               Ticket,
-       enc-part[6]             EncryptedData
-}
-
-AS-REP ::= [APPLICATION 11] KDC-REP
-TGS-REP ::= [APPLICATION 13] KDC-REP
-
-EncKDCRepPart ::= SEQUENCE {
-       key[0]                  EncryptionKey,
-       last-req[1]             LastReq,
-       nonce[2]                krb5int32,
-       key-expiration[3]       KerberosTime OPTIONAL,
-       flags[4]                TicketFlags,
-       authtime[5]             KerberosTime,
-       starttime[6]            KerberosTime OPTIONAL,
-       endtime[7]              KerberosTime,
-       renew-till[8]           KerberosTime OPTIONAL,
-       srealm[9]               Realm,
-       sname[10]               PrincipalName,
-       caddr[11]               HostAddresses OPTIONAL,
-       encrypted-pa-data[12]   METHOD-DATA OPTIONAL
-}
-
-EncASRepPart ::= [APPLICATION 25] EncKDCRepPart
-EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart
-
-AP-REQ ::= [APPLICATION 14] SEQUENCE {
-       pvno[0]                 krb5int32,
-       msg-type[1]             MESSAGE-TYPE,
-       ap-options[2]           APOptions,
-       ticket[3]               Ticket,
-       authenticator[4]        EncryptedData
-}
-
-AP-REP ::= [APPLICATION 15] SEQUENCE {
-       pvno[0]                 krb5int32,
-       msg-type[1]             MESSAGE-TYPE,
-       enc-part[2]             EncryptedData
-}
-
-EncAPRepPart ::= [APPLICATION 27]     SEQUENCE {
-       ctime[0]                KerberosTime,
-       cusec[1]                krb5int32,
-       subkey[2]               EncryptionKey OPTIONAL,
-       seq-number[3]           krb5uint32 OPTIONAL
-}
-
-KRB-SAFE-BODY ::= SEQUENCE {
-       user-data[0]            OCTET STRING,
-       timestamp[1]            KerberosTime OPTIONAL,
-       usec[2]                 krb5int32 OPTIONAL,
-       seq-number[3]           krb5uint32 OPTIONAL,
-       s-address[4]            HostAddress OPTIONAL,
-       r-address[5]            HostAddress OPTIONAL
-}
-
-KRB-SAFE ::= [APPLICATION 20] SEQUENCE {
-       pvno[0]                 krb5int32,
-       msg-type[1]             MESSAGE-TYPE,
-       safe-body[2]            KRB-SAFE-BODY,
-       cksum[3]                Checksum
-}
-
-KRB-PRIV ::= [APPLICATION 21] SEQUENCE {
-       pvno[0]                 krb5int32,
-       msg-type[1]             MESSAGE-TYPE,
-       enc-part[3]             EncryptedData
-}
-EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE {
-       user-data[0]            OCTET STRING,
-       timestamp[1]            KerberosTime OPTIONAL,
-       usec[2]                 krb5int32 OPTIONAL,
-       seq-number[3]           krb5uint32 OPTIONAL,
-       s-address[4]            HostAddress OPTIONAL, -- sender's addr
-       r-address[5]            HostAddress OPTIONAL  -- recip's addr
-}
-
-KRB-CRED ::= [APPLICATION 22]   SEQUENCE {
-       pvno[0]                 krb5int32,
-       msg-type[1]             MESSAGE-TYPE, -- KRB_CRED
-       tickets[2]              SEQUENCE OF Ticket,
-       enc-part[3]             EncryptedData
-}
-
-KrbCredInfo ::= SEQUENCE {
-       key[0]                  EncryptionKey,
-       prealm[1]               Realm OPTIONAL,
-       pname[2]                PrincipalName OPTIONAL,
-       flags[3]                TicketFlags OPTIONAL,
-       authtime[4]             KerberosTime OPTIONAL,
-       starttime[5]            KerberosTime OPTIONAL,
-       endtime[6]              KerberosTime OPTIONAL,
-       renew-till[7]           KerberosTime OPTIONAL,
-       srealm[8]               Realm OPTIONAL,
-       sname[9]                PrincipalName OPTIONAL,
-       caddr[10]               HostAddresses OPTIONAL
-}
-
-EncKrbCredPart ::= [APPLICATION 29]   SEQUENCE {
-       ticket-info[0]          SEQUENCE OF KrbCredInfo,
-       nonce[1]                krb5int32 OPTIONAL,
-       timestamp[2]            KerberosTime OPTIONAL,
-       usec[3]                 krb5int32 OPTIONAL,
-       s-address[4]            HostAddress OPTIONAL,
-       r-address[5]            HostAddress OPTIONAL
-}
-
-KRB-ERROR ::= [APPLICATION 30] SEQUENCE {
-       pvno[0]                 krb5int32,
-       msg-type[1]             MESSAGE-TYPE,
-       ctime[2]                KerberosTime OPTIONAL,
-       cusec[3]                krb5int32 OPTIONAL,
-       stime[4]                KerberosTime,
-       susec[5]                krb5int32,
-       error-code[6]           krb5int32,
-       crealm[7]               Realm OPTIONAL,
-       cname[8]                PrincipalName OPTIONAL,
-       realm[9]                Realm, -- Correct realm
-       sname[10]               PrincipalName, -- Correct name
-       e-text[11]              GeneralString OPTIONAL,
-       e-data[12]              OCTET STRING OPTIONAL
-}
-
-ChangePasswdDataMS ::= SEQUENCE {
-       newpasswd[0]            OCTET STRING,
-       targname[1]             PrincipalName OPTIONAL,
-       targrealm[2]            Realm OPTIONAL
-}
-
-EtypeList ::= SEQUENCE OF krb5int32
-       -- the client's proposed enctype list in
-       -- decreasing preference order, favorite choice first
-
-krb5-pvno krb5int32 ::= 5 -- current Kerberos protocol version number
-
--- transited encodings
-
-DOMAIN-X500-COMPRESS   krb5int32 ::= 1
-
--- authorization data primitives
-
-AD-IF-RELEVANT ::= AuthorizationData
-
-AD-KDCIssued ::= SEQUENCE {
-       ad-checksum[0]          Checksum,
-       i-realm[1]              Realm OPTIONAL,
-       i-sname[2]              PrincipalName OPTIONAL,
-       elements[3]             AuthorizationData
-}
-
-AD-AND-OR ::= SEQUENCE {
-       condition-count[0]      INTEGER,
-       elements[1]             AuthorizationData
-}
-
-AD-MANDATORY-FOR-KDC ::= AuthorizationData
-
--- PA-SAM-RESPONSE-2/PA-SAM-RESPONSE-2
-
-PA-SAM-TYPE ::= INTEGER {
-       PA_SAM_TYPE_ENIGMA(1),          -- Enigma Logic
-       PA_SAM_TYPE_DIGI_PATH(2),       -- Digital Pathways
-       PA_SAM_TYPE_SKEY_K0(3),         -- S/key where  KDC has key 0
-       PA_SAM_TYPE_SKEY(4),            -- Traditional S/Key
-       PA_SAM_TYPE_SECURID(5),         -- Security Dynamics
-       PA_SAM_TYPE_CRYPTOCARD(6)       -- CRYPTOCard
-}
-
-PA-SAM-REDIRECT ::= HostAddresses
-
-SAMFlags ::= BIT STRING {
-       use-sad-as-key(0),
-       send-encrypted-sad(1),
-       must-pk-encrypt-sad(2)
-}
-
-PA-SAM-CHALLENGE-2-BODY ::= SEQUENCE {
-       sam-type[0]             krb5int32,
-       sam-flags[1]            SAMFlags,
-       sam-type-name[2]        GeneralString OPTIONAL,
-       sam-track-id[3]         GeneralString OPTIONAL,
-       sam-challenge-label[4]  GeneralString OPTIONAL,
-       sam-challenge[5]        GeneralString OPTIONAL,
-       sam-response-prompt[6]  GeneralString OPTIONAL,
-       sam-pk-for-sad[7]       EncryptionKey OPTIONAL,
-       sam-nonce[8]            krb5int32,
-       sam-etype[9]            krb5int32,
-       ...
-}
-
-PA-SAM-CHALLENGE-2 ::= SEQUENCE {
-       sam-body[0]             PA-SAM-CHALLENGE-2-BODY,
-       sam-cksum[1]            SEQUENCE OF Checksum, -- (1..MAX)
-       ...
-}
-
-PA-SAM-RESPONSE-2 ::= SEQUENCE {
-       sam-type[0]             krb5int32,
-       sam-flags[1]            SAMFlags,
-       sam-track-id[2]         GeneralString OPTIONAL,
-       sam-enc-nonce-or-sad[3] EncryptedData, -- PA-ENC-SAM-RESPONSE-ENC
-       sam-nonce[4]            krb5int32,
-       ...
-}
-
-PA-ENC-SAM-RESPONSE-ENC ::= SEQUENCE {
-       sam-nonce[0]            krb5int32,
-       sam-sad[1]              GeneralString OPTIONAL,
-       ...
-}
-
-PA-S4U2Self ::= SEQUENCE {
-       name[0]         PrincipalName,
-        realm[1]       Realm,
-        cksum[2]       Checksum,
-        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
-}
-
-KRB5SignedPath ::= SEQUENCE {
-       -- DERcoded KRB5SignedPathData
-       -- krbtgt key (etype), KeyUsage = XXX 
-       etype[0]        ENCTYPE,
-       cksum[1]        Checksum,
-       -- srvs delegated though
-       delegated[2]    KRB5SignedPathPrincipals OPTIONAL
-}
-
-PA-ClientCanonicalizedNames ::= SEQUENCE{
-       requested-name  [0] PrincipalName,
-       mapped-name     [1] PrincipalName
-}
-
-PA-ClientCanonicalized ::= SEQUENCE {
-       names           [0] PA-ClientCanonicalizedNames,
-       canon-checksum  [1] Checksum
-}
-
-AD-LoginAlias ::= SEQUENCE { -- ad-type number TBD --
-       login-alias     [0] PrincipalName,
-       checksum        [1] Checksum
-}
-
--- old ms referral
-PA-SvrReferralData ::= SEQUENCE {
-       referred-name   [1] PrincipalName OPTIONAL,
-       referred-realm  [0] Realm
-}
-
-PA-SERVER-REFERRAL-DATA ::= EncryptedData
-
-PA-ServerReferralData ::= SEQUENCE {
-       referred-realm          [0] Realm OPTIONAL,
-       true-principal-name     [1] PrincipalName OPTIONAL,
-       requested-principal-name [2] PrincipalName OPTIONAL,
-       referral-valid-until     [3] KerberosTime OPTIONAL,
-       ...
-}
-
-END
-
--- etags -r '/\([A-Za-z][-A-Za-z0-9]*\).*::=/\1/' k5.asn1
index 820abc810687bf4d2d52b7a677aec540dbba56c0..14ebf50ecdbcbd73e18580d49437207ccb7773af 100644 (file)
@@ -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,
index 6a9763431051ac42273fd8d44bddfa695ca43789..f53c8c3204d2dc0d5098d6ccd95ff70856eb594f 100644 (file)
@@ -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;
 }
index aca4a062b8b393bb642266964bdaeeba360ed16b..3ff89c8a49ab7150e2a6bca098f7f20fc9c615b0 100644 (file)
@@ -34,9 +34,9 @@
 /* $Id$ */
 
 %{
-#ifdef HAVE_CONFIG_H
+
 #include <config.h>
-#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
index 758af6f86e8734879b75c562113762c993f4a239..302b0c3e8ef8629b3690dd8456b91334f4b0e3cb 100644 (file)
@@ -164,7 +164,6 @@ PA-PK-AS-REP-Win2k ::= CHOICE {
        encKeyPack              [1] IMPLICIT OCTET STRING
 }
 
-
 KDCDHKeyInfo-Win2k ::= SEQUENCE {
        nonce                   [0] INTEGER (-2147483648..2147483647),
        subjectPublicKey        [2] BIT STRING
@@ -176,6 +175,12 @@ ReplyKeyPack-Win2k ::= SEQUENCE {
        ...
 }
 
+PA-PK-AS-REP-BTMM ::= SEQUENCE {
+       dhSignedData            [0] heim_any OPTIONAL,
+       encKeyPack              [1] heim_any OPTIONAL
+}
+
+
 PkinitSP80056AOtherInfo ::= SEQUENCE { 
        algorithmID   AlgorithmIdentifier, 
        partyUInfo     [0] OCTET STRING, 
index 8e24f0740b8a6b6f5a1f70b4bb4e4fcd37c484b8..0c4ffe884b435d0af5b8393a44dc28fb6f56d866 100644 (file)
@@ -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 }
@@ -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 {
index 89c8ab2c8958d39c8a01934cd1d47b5a1a1de3c4..a43d1e3e6cde5c01fa9e983c371615be6838c41a 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
+
 #include <config.h>
-RCSID("$Id$");
-#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
index 239617d1debafb4570da97b34d711090ad1427ec..a28e51f8da1003cb7744c6032825ebe99f908d10 100644 (file)
@@ -35,8 +35,6 @@
 #include "compile_et.h"
 #include <getarg.h>
 
-RCSID("$Id$");
-
 #include <roken.h>
 #include <err.h>
 #include "parse.h"
index 430405d9d545e19b98da96ef8c87d16c81572e10..b0b8e21da1662bfc6fb96037ce0a803a0eebf56b 100644 (file)
@@ -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>
index d64225a758f3aeb60a09e3ed757079ee3b652ddf..6b12c00c7a22434a7b7e9f15f38417d7ae3909d9 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
+
 #include <config.h>
-RCSID("$Id$");
-#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
index 84356405ddf2370422aa8b4cce2f3a07e94c953f..b68814b21caa0993ae4b45acc31efb7118091543 100644 (file)
@@ -44,8 +44,6 @@
 #include "parse.h"
 #include "lex.h"
 
-RCSID("$Id$");
-
 static unsigned lineno = 1;
 static int getstring(void);
 
index 99dddbe1e146bc47cf1a1c59516abcb191002566..d64681d90234dc0434426f2508a92e5ee15ddee0 100644 (file)
@@ -35,8 +35,6 @@
 #include "compile_et.h"
 #include "lex.h"
 
-RCSID("$Id$");
-
 void yyerror (char *s);
 static long name2number(const char *str);
 
index f8b599a6644b4b2f3286e58f76c6c121757d9a6d..9fe2bb8b46e182bc7ee2fbb18d2b2065e8ce000e 100644 (file)
 #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
@@ -743,6 +768,75 @@ gss_pseudo_random
         gss_buffer_t prf_out
        );
 
+/*
+ * 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
@@ -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_ */
index a821f73d2a01c472654daf7a296ed553f7594cac..0baccf5098f65ad750363e8d0deace89393f070d 100644 (file)
@@ -36,7 +36,7 @@
 #ifndef GSSAPI_KRB5_H_
 #define GSSAPI_KRB5_H_
 
-#include <gssapi/gssapi.h>
+#include <gssapi.h>
 
 #ifdef __cplusplus
 extern "C" {
index b360de13fcaf53192de49fc62d6c719ef72610cb..6470df30a031c56c0c531444bea96782d25e8019 100644 (file)
@@ -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
index 119d49a0c50c761919efa7c35d98f6557eaa7b33..f5181cc311b877cd50ed9a666bcda8db0d6b414c 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 626afa93843459ba2fabe2ddca470ec145219aa6..7e248b6f711ea16707976ae98713f0774b28881e 100644 (file)
@@ -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);
 }
 
 
@@ -210,7 +212,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,
@@ -526,7 +529,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;
index be680840f525d0906d86ae1211250b3448cbbc45..6c4996515e20352a93eb4ca591b7cd34f05285de 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index d6fd8f6f158144bbd0121c0398d621daf4bae0c8..1c251d96697d1891ffba0e7388ae513ed139c284 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index ff0afdc05984b451c3405d7a001b3bf7707bb0d1..fa115d964a89a62c936f526b2b86c36afde2087a 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 #include <roken.h>
 
index 7288b58493ef3ea0b863c2f9195c2905c5f18c95..b48cfebcf1b13b3d82864f6fc67d2df14b844264 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index fa2258ce82f9151dbcdc765e198eacf8998f5a47..3a206b1be1b036195ba25e6cfb59ea54942d5d29 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index d029f55ce4d27f45b4ac0bd1a895bb29e23dc921..7ae26e2e7a556ac6b1775afb4b5d1c5b5cf20ab8 100755 (executable)
@@ -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);
index d92f3ef4059e1e2ccdbeb86e50fa47c42e48d2a5..fbb0f0218e7e1d15f27f63dc0fb641be73f67cb3 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index ee0d07d98399b712e9c4c51fb983047447a187fb..012602c07441623b6841156f5331f4d9634b06f8 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 3854b687829f4eb35c5f407738bc668f2e78149b..323038993880670aa5b59d812d3bf93c3850c97e 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 8961642671bf7f8519b334735999d6d4220da08d..40a8fab1b7b42a3fde291b00a97018c105832945 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 22386fa737673062a4138d18a7cda69a52de11ff..a2a5de9fe75b87b286bceb04e5610308977619fc 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 5ccfe9d01533c11b32af443ee6dc592bb8b4f0c3..ea0831815a27f50ec1167590651914972005229f 100644 (file)
@@ -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);
index d1834ebaf8ade1e8175ea58a4e21593698df2272..0b377315108ab3782be025c29cddd894b49b5278 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 18622610d5dc90df69d7074ea1ca6697a355aa9c..4136c25e533c31a76be8ee73f5e99ad5846d6be0 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 6c281f43dea4db83c10481bc495b343de463af49..2b5e5c0ef48a781ec10ec379627040fb46f3da36 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 19c6ec8ca7fc0c9df4d48049e0e4f94875b3b15e..838a34d7db9a20f6d1c43d4222ec03e198edd6c4 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index b28777ea2eb6ed6e2d6f7a2d87e36d9622a3f169..bad73611dc84a277854cc83bfb615c667e3a3aa3 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 842921fe5008175597a5d8494ade257171d378ad..305d5c334e64312ceaab52276fb57d06ab0f996c 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 4efa61fd70885cf8a09df053481e09beb9955e31..1c28f7c141d8f47ab54c83d9d8b51c4265466fde 100644 (file)
@@ -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
index 199c414ef48780ba15f3432ad81f812c7ae0cd5d..66aaba44d67827dff7578f1179b3303b5934d7f0 100644 (file)
@@ -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);
index 6db842395f711a6ac6105305ed04ec0cd225d328..aadb80db0d90ae7ccfd031a08a587484a8684673 100644 (file)
 #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;                             \
index 2f6b002f306c287f1290834df748db12405c96af..8f5387fe2b56b32fc8eea7b05ca1bb7cfd1a689a 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index e1e8e551b416a88377bb4ae361c0b304ed7998b1..ba1a977d2dc6ee8aa7a2b3717d92fa64dbaf2d57 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 05b9447746dea7649222cd32dafcacdc3152ecbc..3702106e7903cbda61b4a14e0c2c825a7cf22140 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 6c1c5949e02dc678962961ac4783e2dfb9b5a615..b28e6a4c12b536e997a47895fd5b8d23ca0da8d2 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index dfa0e935e6c700822d6ed75de8cfbbf8d024cef1..57dc43d320c02d05168bf13817aa489db61b7cef 100644 (file)
@@ -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,
@@ -686,7 +688,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 +760,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,
index e0aeb032cea4cf8cb1aea19fa908f6efe85c4ba8..188a6135a4b1cd14793c6a8a1e54d4a9663e0398 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index bb75978adbbf22abed8b8fbc64719de8504b0203..27e3014923602ac1ebda43479267dea25db67869 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index cdf05d79340a286b0fabb68f895d4289ba130bbd..1fd973394093638af1758247941574f5af84073b 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 2bcc17683b401aaf0dcc780264d5a7a962e2637a..5a35202a6a04d9a26c037f4327e01f2ed23df9dc 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 4fd730deab73346a777c421c240049a1ea743a84..5d54bd65086792eeef84a524809c5cd1c931e5f5 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index a9d6495c7b516e78e813e4e5e7d3361ef6ead56b..9eba7b7f4ddc8586f9f5ac6df70bbd03a89b09ed 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 8d40706294554201b4d15e8c8fe9748f307c2c70..f8ef2a3aa4e0719dde8b1a21c4bdcdf15d352be9 100644 (file)
@@ -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;
index 9cbe6034357f9031d463e306ef7ffdb9a20b15dd..9fd13f51bd27b7318417fb6e3af9aa1d593e0b38 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 6892d3ca604f592d76ecc98d00f6646c97378ff9..3229b36292b1007175ed5c8aaddc6c3c55b0ef99 100644 (file)
@@ -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,
index a0f37c06f4cf02e2c0a22394702f8f434bea3c7b..18e0279939730f958701f3889dffaf09414e0aba 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 5a0ec829d224e08c7e1c702ca036ecf7cdd47504..62674a1d530870c23d334cf0806009efad2c0a99 100644 (file)
@@ -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
index d39c7054332a78d82b9767c33370840ef9a54385..5491052c59378b9b7608833db13fc1ec5d570490 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 61164ffec113e1fb821513bc13bfa82354ccfdd4..6391d44429d46be458003a0c04805dd6f2993aa9 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index e47e6fdb6ce0bcfda6939edaeec0bec96f9ece7c..2a2390f8d1f3a86870c4d4a69ea2ac44a1eb2e53 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index 6591ab04dd63027232f0ea6379a91b5d348cb80b..460cfe942ad2736e16dd4696b7c9730b7a70c222 100644 (file)
@@ -34,7 +34,7 @@
  *  glue routine for _gsskrb5_inquire_sec_context_by_oid
  */
 
-#include "krb5/gsskrb5_locl.h"
+#include "gsskrb5_locl.h"
 
 RCSID("$Id$");
 
index f34f72542ea7e967a7230d5303fcd1cc0b19ee2f..0e87cb88b73d8682f897cbbb22239cca8551bf10 100644 (file)
@@ -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);
index 1832d35b5afe8d6c6a6c5c83545134d10b0b49c1..6eb7ae4b089fee2f3aabc3b626ef1b5ebfda4753 100644 (file)
@@ -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);
 
index ad21bcb57bd371a843f1ff2c03c56f9e69581f00..b9f4c237c767d540e124abb2c3e34aaa0593eb31 100644 (file)
@@ -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);
index a06a1e9e37a7b5484ac508d337db00c6bc05b71c..b032d8aa0e1fe6e28f659ce075148174fcc22f37 100644 (file)
@@ -1,4 +1,4 @@
-#include "mech/mech_locl.h"
+#include "mech_locl.h"
 #include "heim_threads.h"
 
 RCSID("$Id$");
index 91a08fb2bcb3e6d6352b1e10bf1a54a1c4222d2f..db976f2453ef33a349fd68c1dfdc07bb5880c1d9 100644 (file)
 #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,
index 9cd5060fc941bf7e9786d1410093b1571a096243..3a0f3fb757b9ebb851a7dd8075531d5b21e545bc 100644 (file)
@@ -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));
 }
index 040e2284105b95c2046decf4a204a7defd96097d..c1dffdc614cb7bd8991314cc09eb97dfcf8259a6 100644 (file)
@@ -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;
 }
index fc2e8816c5fceea0632d0ed0d83ab88b61604af1..3321819d28fc1db6d45eaa0a116d9b3ab1f15fd7 100644 (file)
@@ -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;
index b907f94038bbd82a30cad1e065e1a7616a8b3ad1..771efcb4342dd07b708cf70a267983d075e98367 100644 (file)
@@ -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;
 
index 1a411729c68ae3ea5d5fbb117fc021755fffcec0..60ef3bff85f1cf2206357633cb4222d37877b222 100644 (file)
@@ -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));
 }
index b3363d3f207dbfd9457be6699d5ac030d6855f34..9476d01ddd898002c7d49b8caa08bffd9dc7e2f9 100644 (file)
@@ -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));
index 15b86a9367b4dcc547fcd95198a43dbb91a1a2c2..a5a80b21d7f0a440673beaba66bdf1021c04c3dc 100644 (file)
@@ -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));
 }
index 42c069eb2d1f9e3c12fbefda39eb0a3e39373a1a..17721fd3ce6ed2b966085c7316e8fa92545ea2f5 100644 (file)
@@ -53,6 +53,7 @@
 
 #include <gssapi.h>
 #include <gssapi_mech.h>
+#include <gssapi_krb5.h>
 
 #include "mechqueue.h"
 
index e83a4c8a5aaffb40aa4b1c00e81e2ec297686753..56e3b7dea79a466592d05924ee2fa7f8ec562162 100644 (file)
@@ -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;
 };
index cabd806fbfd0be62fe835da3aef45aecfa21bb2a..158126d99f96cd1c7876121cf0e42d1ececbc774 100644 (file)
@@ -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);
index 67d9b202a7309533dc9de724d4e624af69e1d91b..ee25b594358286cae977cda07a964a1eef74ae2c 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  */
 
-#include "spnego/spnego_locl.h"
+#include "spnego_locl.h"
 
 RCSID("$Id$");
 
index 5bc1a486563ae6ac00ed5b287fb98e92eaca3997..1998c44edf2588a812020278356923096bc7a28a 100644 (file)
@@ -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,
index f6b3fecaa016044747f6bac0a66ac30c2596e036..a3a984e22c3eb05137b7e569fd9b1ca64b7677f8 100644 (file)
@@ -30,7 +30,7 @@
  * SUCH DAMAGE.
  */
 
-#include "spnego/spnego_locl.h"
+#include "spnego_locl.h"
 
 RCSID("$Id$");
 
index 02404237a70c987cd1e0a5dba87b6efe51b8ca9e..2dc809bbbaa58af610b3e1d0c54064b36f69f560 100644 (file)
@@ -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,
index 7a5814413b92340116c7fb55132f5b21804425aa..ac32432d550320e4b7db48961e5fbcea45e469ae 100644 (file)
@@ -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)
index 8344e750ae78ab388c70b6d88a0eb3c8640633bd..44fa8b117d344e56f74748db683b60cc14b1f9df 100644 (file)
@@ -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 */
index b91a65a7bfc6f21dd11d0e0c01dc4911de476e75..179595ae5cd3ee62bb908db1456cf906cce5b6f2 100644 (file)
@@ -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;
+}
+
index aac770b5a8c666bc21eccece03e532c9ba8197af..2fa25ac1a08a191d10990df21ecad2580dc1547d 100644 (file)
 #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
index 685dcac18b4e3b19e86fb583ac0f95ef0717ec0b..66f87982c00b44f93a5e3486db2c5fba68fcec9d 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-#endif
-
-RCSID("$Id$");
 
 #define HC_DEPRECATED
 
index 517ca2a2bc08782bfee762c6415ef17f79b24f27..ac6cac972af06865832b355e39eac1c973a1bfb0 100644 (file)
@@ -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
index 0c2185776c873700fc0db73e40ecd28b4de00acb..07d81eb62041a45ec150da1ec45a3829a1a2e508 100644 (file)
@@ -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;
 }
index b8ac2155d11b2685017a38e21fd37f23c2a6d5ba..a61c9cdfb2d993c2260319a0adea8c28f71dbc8b 100644 (file)
@@ -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
 }
 
 /**
index 2121577bb1224d96c852117453bf8706a7e0d7b8..7e2961c61438610c62d1f1b2d6e61603fc701989 100644 (file)
@@ -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;
index 5cddf8f1d0536d2d26dabcab87f9692c10a61a84..7ea8c80aae444e5e219ed1c80194f911788fa48b 100644 (file)
@@ -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 {
@@ -101,6 +102,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 
index ad2c35a43a58a9dbfc68f72979df15a84afc6e22..b533fc5952bd7288ecc9348228ce8b1824fc25ec 100644 (file)
@@ -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.
  *
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "krb5.h"
 #include "krb5_locl.h"
 #include "hdb_locl.h"
 RCSID("$Id$");
@@ -46,22 +41,24 @@ RCSID("$Id$");
 
 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 +262,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");
index b9f294e2eb01eda3ba805a3277457233a8353570..748e1ba0a17c1022d82c03c76408686557df00a2 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (c) 1997 - 2001, 2003 - 2004 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden).
@@ -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;
 
index a890ba62cd8a51ee1d4bdf76950bb7084401836c..f8e26da3117ab72266973429c33d7c98fa2a8ce8 100644 (file)
@@ -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 */
index cbd58ebd019b347f940b6b56693ceb0c9f2b9084..eca5cb4fc88551471a1383d14a2b67452d530049 100644 (file)
@@ -33,7 +33,6 @@
 
 #include "hx_locl.h"
 #include <pkinit_asn1.h>
-RCSID("$Id$");
 
 /**
  * @page page_ca Hx509 CA functions
index 121847faaaa238104743be56fa8c0097021564a9..9498735a7d40670c893c2bc9858b9e1bf30cd79a 100644 (file)
@@ -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
@@ -569,6 +569,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)
 {
@@ -748,8 +758,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 +782,6 @@ hx509_cert_find_subjectAltName_otherName(hx509_context context,
        }
        free_GeneralNames(&sa);
     }
-    return 0;
 }
 
 
@@ -1472,7 +1480,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().
  *
@@ -2263,6 +2273,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:
@@ -2746,7 +2774,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)
@@ -2891,7 +2919,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;
     }
@@ -3348,6 +3376,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;
index ba1800ddf2fe8174f2269d6567d0ee226dd5b48c..c39eaee6f4a96218489418553e2c4f7b85e8928d 100644 (file)
@@ -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) {
@@ -567,14 +569,19 @@ hx509_cms_envelope_1(hx509_context context,
     if (encryption_type == NULL)
        encryption_type = 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 +745,13 @@ 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.
+ * @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 +763,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 +806,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 +839,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 +857,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;
@@ -885,7 +915,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) {
@@ -922,36 +952,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);
+           signed_data.data = content->data;
+           signed_data.length = content->length;
            match_oid = 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 +993,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 +1027,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 +1053,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 +1136,52 @@ 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);
+
+    ret = hx509_cms_create_signed(context, flags, eContentType, data, length,
+                                 digest_alg, certs, peer, anchors, pool,
+                                 signed_data);
+
+    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 +1189,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[sd->signerInfos.len];
 
-    signer_info = &sd.signerInfos.val[0];
+    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 +1228,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 +1238,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, oid_id_pkcs7_data()) != 0) {
        CMSAttributes sa;       
        heim_octet_string sig;
 
@@ -1205,7 +1251,7 @@ hx509_cms_create_signed_1(hx509_context context,
        ret = _hx509_create_signature(context,
                                      NULL,
                                      &digest,
-                                     &content,
+                                     &sigctx->content,
                                      NULL,
                                      &sig);
        if (ret)
@@ -1230,6 +1276,7 @@ hx509_cms_create_signed_1(hx509_context context,
                                oid_id_pkcs9_messageDigest(),
                                &buf);
        if (ret) {
+           free(buf.data);
            hx509_clear_error_string(context);
            goto out;
        }
@@ -1238,7 +1285,7 @@ hx509_cms_create_signed_1(hx509_context context,
        ASN1_MALLOC_ENCODE(ContentType,
                           buf.data,
                           buf.length,
-                          eContentType,
+                          sigctx->eContentType,
                           &size,
                           ret);
        if (ret)
@@ -1251,6 +1298,7 @@ hx509_cms_create_signed_1(hx509_context context,
                                oid_id_pkcs9_contentType(),
                                &buf);
        if (ret) {
+           free(buf.data);
            hx509_clear_error_string(context);
            goto out;
        }
@@ -1271,16 +1319,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 +1343,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 = 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 +1509,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 +1533,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;
 }
index b59052bb4e6b330c97e37fe66a2ce235dd26eaeb..3aaa17e6cd61ed60aa9e9f950e54fdc16cff6a2e 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 
 struct private_key {
     AlgorithmIdentifier alg;
@@ -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;
 }
index 4a8ec8f7565dc121679aa4376d8fb65e4074019b..989e8245c22f00c8be066b7900495f10b0bae6f3 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 
 struct hx509_crypto;
 
@@ -50,7 +49,9 @@ 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 *);
@@ -65,25 +66,6 @@ struct hx509_private_key_ops {
                                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 +75,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 +88,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 +102,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 +116,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 +278,225 @@ set_digest_alg(DigestAlgorithmIdentifier *id,
     return 0;
 }
 
+#ifdef HAVE_OPENSSL
+
+/*
+ *
+ */
+
+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;
+    size_t size;
+    ECParameters ecparam;
+    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 ||
+       spi->algorithm.parameters == NULL)
+       return HX509_CRYPTO_SIG_INVALID_FORMAT;
+
+#ifdef HAVE_OPENSSL
+    /*
+     * Find the group id
+     */
+
+    ret = decode_ECParameters(spi->algorithm.parameters->data,
+                             spi->algorithm.parameters->length,
+                             &ecparam, &size);
+    if (ret) {
+       der_free_octet_string(&digest);
+       return ret;
+    }
+
+    if (ecparam.element != choice_ECParameters_namedCurve) {
+       der_free_octet_string(&digest);
+       free_ECParameters(&ecparam);
+       return HX509_CRYPTO_SIG_INVALID_FORMAT;
+    }
+
+    /*
+     * Now map to openssl OID fun
+     */
+    groupnid = -1;
+
+    if (der_heim_oid_cmp(&ecparam.u.namedCurve, &asn1_oid_id_ec_group_secp256r1) == 0)
+       groupnid = NID_X9_62_prime256v1;
+    else if (der_heim_oid_cmp(&ecparam.u.namedCurve, &asn1_oid_id_ec_group_secp160r1) == 0)
+       groupnid = NID_secp160r1;
+    else if (der_heim_oid_cmp(&ecparam.u.namedCurve, &asn1_oid_id_ec_group_secp160r2) == 0)
+       groupnid = NID_secp160r2;
+
+    free_ECParameters(&ecparam);
+    if (groupnid == -1) {
+       der_free_octet_string(&digest);
+       return HX509_CRYPTO_SIG_INVALID_FORMAT;
+    }
+
+    /*
+     * 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);
+           return ret;
+       }
+    }
+
+    ret = _hx509_create_signature(context,
+                                 NULL,
+                                 digest_alg,
+                                 data,
+                                 NULL,
+                                 &indata);
+
+    sig->length = ECDSA_size(signer->private_key.ecdsa);
+    sig->data = malloc(sig->length);
+    if (sig->data == NULL) {
+       der_free_octet_string(&indata);
+       hx509_set_error_string(context, 0, ENOMEM, "out of memory");
+       return ENOMEM;
+    }
+
+    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) {
+       hx509_set_error_string(context, 0, HX509_CMS_FAILED_CREATE_SIGATURE,
+                              "ECDSA sign failed: %d", ret);
+       return HX509_CMS_FAILED_CREATE_SIGATURE;
+    }
+    if (siglen > sig->length)
+       _hx509_abort("ECDSA signature prelen longer the output len");
+
+    sig->length = siglen;
+
+    return 0;
+}
+
+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 +581,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 +637,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;
@@ -426,7 +742,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 +765,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 +819,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 +859,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 +875,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 +884,74 @@ 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 void *data,
+                        size_t len,
+                        hx509_private_key private_key)
+{
+    const unsigned char *p = data;
+
+    private_key->private_key.ecdsa =
+       d2i_ECPrivateKey(NULL, &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 +1055,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 +1111,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 +1177,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 +1258,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 +1445,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 +1500,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 +1558,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 +1597,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 +1703,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");
@@ -1330,7 +1812,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 +1882,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; }
@@ -1516,6 +1910,18 @@ const AlgorithmIdentifier *
 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; }
@@ -1617,8 +2023,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 +2044,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 +2054,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,6 +2096,8 @@ _hx509_private_key_export(hx509_context context,
 
 struct hx509cipher {
     const char *name;
+    int flags;
+#define CIPHER_WEAK 1
     const heim_oid *(*oid_func)(void);
     const AlgorithmIdentifier *(*ai_func)(void);
     const EVP_CIPHER *(*evp_func)(void);
@@ -1694,6 +2109,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;
@@ -1853,6 +2270,7 @@ CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param,
 static const struct hx509cipher ciphers[] = {
     {
        "rc2-cbc",
+       CIPHER_WEAK,
        oid_id_pkcs3_rc2_cbc,
        NULL,
        EVP_rc2_cbc,
@@ -1861,6 +2279,7 @@ static const struct hx509cipher ciphers[] = {
     },
     {
        "rc2-cbc",
+       CIPHER_WEAK,
        oid_id_rsadsi_rc2_cbc,
        NULL,
        EVP_rc2_cbc,
@@ -1869,6 +2288,7 @@ static const struct hx509cipher ciphers[] = {
     },
     {
        "rc2-40-cbc",
+       CIPHER_WEAK,
        oid_private_rc2_40,
        NULL,
        EVP_rc2_40_cbc,
@@ -1877,6 +2297,7 @@ static const struct hx509cipher ciphers[] = {
     },
     {
        "des-ede3-cbc",
+       0,
        oid_id_pkcs3_des_ede3_cbc,
        NULL,
        EVP_des_ede3_cbc,
@@ -1885,6 +2306,7 @@ static const struct hx509cipher ciphers[] = {
     },
     {
        "des-ede3-cbc",
+       0,
        oid_id_rsadsi_des_ede3_cbc,
        hx509_crypto_des_rsdi_ede3_cbc,
        EVP_des_ede3_cbc,
@@ -1893,6 +2315,7 @@ static const struct hx509cipher ciphers[] = {
     },
     {
        "aes-128-cbc",
+       0,
        oid_id_aes_128_cbc,
        hx509_crypto_aes128_cbc,
        EVP_aes_128_cbc,
@@ -1901,6 +2324,7 @@ static const struct hx509cipher ciphers[] = {
     },
     {
        "aes-192-cbc",
+       0,
        oid_id_aes_192_cbc,
        NULL,
        EVP_aes_192_cbc,
@@ -1909,6 +2333,7 @@ static const struct hx509cipher ciphers[] = {
     },
     {
        "aes-256-cbc",
+       0,
        oid_id_aes_256_cbc,
        hx509_crypto_aes256_cbc,
        EVP_aes_256_cbc,
@@ -2015,6 +2440,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 +2542,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 +2624,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 +2751,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,7 +2771,7 @@ 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;
@@ -2467,8 +2908,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 +2964,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 +2994,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 +3004,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 +3012,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 +3041,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 +3113,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 +3122,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 +3132,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;
 
index 0b0a68ceae16614e9ca5999c976e67df0ff200b4..7598aebaae74142152ff97f9aadf5e5b24773e31 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 
 /**
  * @page page_env Hx509 enviroment functions
index 6f25404145afcf98d045fb44dee25e2ecd0178de..45813efb38b15e931af287ac340e8569f23ff0ec 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 
 /**
  * @page page_error Hx509 error reporting functions
index a364dd2179176eb04c4466386425a3027b945a0e..ba7a23f471238442067f998febf47372e84b1bc3 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$ID$");
 
 int
 _hx509_map_file_os(const char *fn, heim_octet_string *os)
index 5e5a2f811bff36bc1c94546dbe477f4adf8d138d..86aad7ec9cdd054c81736601021b1b2cc68c0254 100644 (file)
@@ -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  {
index c1dfaf587e69dfe58376cdd6b892ce7c18f0e87e..76bbfaeabaa1a8fdb482f08282d5668a567562b8 100644 (file)
@@ -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
index 8de2353f159b867baaee9d1ac9cf809885f43850..2d1c036d53717bae3ca68f54ccaa30c2521d6396 100644 (file)
@@ -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;
index b68064b512cbaa5549f5086d41febef8982067ba..c4f035ab87ee51ec9b149b0f3185bb63fba3548c 100644 (file)
@@ -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)
 {
index 76c0c4263309f9d9036fbe3341c37b5f44f25282..ef07b03ceccb54b2cb412e4a294473b23a2f7568 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 #include <dirent.h>
 
 /*
index ca0171f8b9970ab362cc30b8166e777140241767..0f5ded701cff7a95f24b51ed8a3f60e8dce92727 100644 (file)
@@ -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,11 @@ out:
 }
 
 static int
-parse_rsa_private_key(hx509_context context, const char *fn,
-                     struct hx509_collector *c,
-                     const hx509_pem_header *headers,
-                     const void *data, size_t len)
+parse_private_key(hx509_context context, const char *fn,
+                 struct hx509_collector *c,
+                 const hx509_pem_header *headers,
+                 const void *data, size_t len,
+                 const AlgorithmIdentifier *ai)
 {
     int ret = 0;
     const char *enc;
@@ -159,7 +160,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 +170,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 +202,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 +219,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 +233,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 +254,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 +267,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 +278,13 @@ 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 },
+    { "RSA PRIVATE KEY", parse_private_key, hx509_signature_rsa },
+    { "EC PRIVATE KEY", parse_private_key, hx509_signature_ecPublicKey }
 };
 
 
@@ -305,7 +304,12 @@ 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);
+           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 == 0)
                break;
        }
@@ -409,7 +413,11 @@ 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;
            }
index 2dc07215636f04a09eb4fa9e758a966f06b2ed8d..01d0c55d1c6da71b513c8bae08f58ffa6bee3935 100644 (file)
@@ -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);
index bf952fbeeea403586156514fbe7c8b7ffa98b9bd..299a3932c9b515b42bf474de12242933719c6450 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("Id$");
 
 /*
  * Should use two hash/tree certificates intead of a array.  Criteria
index fae631fb3fdc52801c2714cc75feca2173b4d8ed..136d2d43459fc8453f0dfd6dfb1fb028294acc88 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 
 
 static int
index 652cdc22104cb18bce174b6f8f2d94dd49e371ea..ed84e43a3aa20b5b410277426a232915af3ce09a 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 #ifdef HAVE_DLFCN_H
 #include <dlfcn.h>
 #endif
index b59bd215f0f50a98c37ac82c3be244fd9b28102e..dc4ba28e25e3017a7fce26e2ff212dafedaae385 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 
 struct ks_pkcs12 {
     hx509_certs certs;
index e2ceedecb8ce993a9e7948585e28f25b7f5ea9b5..219a301928c6296a8f276063c53932d30c85e601 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 
 /**
  * @page page_lock Locking and unlocking certificates and encrypted data.
index 069eed606266f95bd115092412a4383b92fcb014..053a71d517ff7691dc5a5f9249632cd3f4a87c31 100644 (file)
@@ -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
@@ -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);
index f5841e497b14b18ba018387f7238e7c5a8b3f160..435564d821b7d869bc1aeab7b569d7749be4dc1f 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 
 /**
  * @page page_peer Hx509 crypto selecting functions
index 38d103905ffd341a848d4ddc327972a1e114ef57..577d34f8690c086ac628f178e128f4ce546df0be 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 
 /**
  * @page page_print Hx509 printing functions
index 983677714350721eede0bf91ade08b0ab37ceaf0..0d174e0cece8aad1cfa2bf75215759128b47ae67 100644 (file)
@@ -33,7 +33,6 @@
 
 #include "hx_locl.h"
 #include <pkcs10_asn1.h>
-RCSID("$Id$");
 
 struct hx509_request_data {
     hx509_name name;
index 3f35b0d190083f9ab4b8310ec54943c3dd448de7..c67381ff2d5741a0aa81228852d4adb510df7633 100644 (file)
@@ -50,7 +50,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 
 struct revoke_crl {
     char *path;
index e52947972426d4514b925d4ba85f85aa64620c1a..7f7c9980e03bc6f062eb05b71ec7f316fbba5a40 100644 (file)
@@ -39,7 +39,6 @@
 #include <stdlib.h>
 #include <hx_locl.h>
 
-RCSID("$Id$");
 
 %}
 
index da83e527864a3bc15c99462f306409030deb9020..2cdcdf85f63f3d761a390f913a41b602d6d12568 100644 (file)
@@ -32,7 +32,6 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id$");
 
 static int
 test_name(hx509_context context, const char *name)
index bd0a9846e4c8173c98a2f9e5ea370afade98fc7f..2dcf603cd04a44346f9832c35bdaf6be9ff11132 100644 (file)
@@ -135,7 +135,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 +342,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 +491,24 @@ 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;
+
+       error = 0;
     } else if (error == ccErrCCacheNotFound) {
        a->ccache = NULL;
        a->cache_name = NULL;
-       error = 0;
     } else {
        *id = NULL;
        return translate_cc_error(context, error);
@@ -572,6 +581,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);
 }
 
index 9e2fb3d63a154b4426c81f4f366417245ba47ee4..8923340c69e54ad3855cf83494e229fe4f18c785 100644 (file)
@@ -678,6 +678,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 +1145,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 +1459,6 @@ krb5_make_addrport (krb5_context context,
     *p++ = (2 >> 24) & 0xFF;
 
     memcpy (p, &port, 2);
-    p += 2;
 
     return 0;
 }
index cb86c324fb34a8564653178b39e6e15c5f3a074b..9603dce12f7de266ff2dee29609404a4ad00560d 100644 (file)
@@ -52,13 +52,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;
 }
index bbf4f274af1d0c9b4a147271416c1034eff1fa4b..ce0a905e97425d327fcb92f8e7a71c9dced8e8aa 100644 (file)
@@ -81,12 +81,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;
index 80b755cd2774eb56a1336bf0ba06b73179c5fd44..62a5488904a4de51352b307d86271d7b32c69ec7 100644 (file)
 
 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:
+ *
+ * - SDB
+ *   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
  * existing one if `override'.
@@ -676,7 +741,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().
  *
@@ -1057,10 +1122,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 +1151,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 +1176,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 +1247,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 +1293,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 +1315,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 +1416,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 +1519,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 +1543,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 +1560,60 @@ 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);
+}
index 91ed9c5ba07b05cd59fe1b7343cfb6bef8ff24c3..0e19e5f20093f6098af478c1acb6ee6b12a64772 100644 (file)
@@ -35,6 +35,8 @@
 
 RCSID("$Id$");
 
+#undef KRB5_DEPRECATED
+#define KRB5_DEPRECATED
 #undef __attribute__
 #define __attribute__(X)
 
@@ -82,7 +84,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 +119,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 +231,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 +693,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 +711,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 +767,6 @@ krb5_set_password(krb5_context context,
     return ret;
 }
 
-#ifndef HEIMDAL_SMALLER
-
 /*
  *
  */
@@ -834,8 +832,6 @@ krb5_set_password_using_ccache(krb5_context context,
     return ret;
 }
 
-#endif /* !HEIMDAL_SMALLER */
-
 /*
  *
  */
index bd0dcc53711a60eee744d08c108e9505ebfc10e3..5d2edcee79e06159395295695755a93891eea036 100644 (file)
@@ -33,8 +33,8 @@
 
 #include "krb5_locl.h"
 
-#undef __attribute__
-#define __attribute__(x)
+#undef KRB5_DEPRECATED
+#define KRB5_DEPRECATED
 
 RCSID("$Id$");
 
@@ -46,7 +46,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 +57,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 +68,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 +79,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 +90,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 +101,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 +112,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 +123,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 +134,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 +145,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 +156,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 +167,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 +178,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 +189,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 +200,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 +211,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);
 }
index 75c48a001ba1e42d2404c16e1048d9b98a10cd48..162f862dd9bd159e2bc62da30b906c2b3cef71d2 100644 (file)
@@ -302,21 +302,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, ret,
+                                      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 +368,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;
 }
 
index b41fb3f663790826ea8fbcc50eaf730c7bf40e2d..03bd59b0b1c09535d22ac34f8405257e56276537 100644 (file)
@@ -37,6 +37,7 @@ 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";
index 127dfa117dc83b2dd22d402775826c17db0e9684..26c1697ea01412e695f4a4269eb55a431dc85ee5 100644 (file)
@@ -243,9 +243,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 +308,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 +336,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 +453,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 +552,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 +641,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 +654,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 +1227,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;
+}
index fc81d96bec3e2eb39b22ff8932d312c999d35cee..72ee5f0ebd960d44be66db3f8b2a6a3b5fec86fc 100644 (file)
@@ -36,6 +36,8 @@ RCSID("$Id$");
 
 #include "krb5-v4compat.h"
 
+#ifndef HEIMDAL_SMALLER
+
 static krb5_error_code
 check_ticket_flags(TicketFlags f)
 {
@@ -204,3 +206,5 @@ krb524_convert_creds_kdc_ccache(krb5_context context,
        krb5_free_creds (context, v5_creds);
     return ret;
 }
+
+#endif
index a900cabbba39d4d594c5e4980cfab96f04be5a54..eab946541db7d49bf032c80b698ea9aacb5e487e 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "krb5_locl.h"
 
-RCSID("$Id$");
-
 static u_long table[256];
 
 #define CRC_GEN 0xEDB88320L
index 087a4850eba145cc46c137706f2e36dc9abc3931..b91a5605b4efe763b9494b6cf72fc5a8fd74bcc0 100644 (file)
 
 RCSID("$Id$");
 
-#undef __attribute__
-#define __attribute__(X)
+#undef KRB5_DEPRECATED
+#define KRB5_DEPRECATED
 
 #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))
+    KRB5_DEPRECATED
 {
     return krb5_free_cred_contents (context, c);
 }
@@ -235,9 +235,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;
index bc6512cf1ab850d0b932b9ee20aba4d2243386e5..035026018aa4d59443e7617695c510fef4fed4ff 100644 (file)
@@ -35,8 +35,8 @@
 RCSID("$Id$");
 #include <pkinit_asn1.h>
 
-#undef __attribute__
-#define __attribute__(X)
+#undef KRB5_DEPRECATED
+#define KRB5_DEPRECATED
 
 #define WEAK_ENCTYPES 1
 
@@ -164,6 +164,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 +1161,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 +1853,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 +2371,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 +2761,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 +3160,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. one 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 +3173,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 +3199,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 +3295,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 +3305,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 +3328,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 +3356,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 +3368,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 +3394,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 +3422,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 +3441,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 +3460,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 +3509,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 +3520,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 +3773,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 +3780,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 +3792,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 +3816,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 +3853,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;
 }
 
@@ -3982,16 +3983,25 @@ krb5_crypto_init(krb5_context context,
     return 0;
 }
 
+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 +4164,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,
@@ -4574,116 +4584,12 @@ krb5_crypto_prf(krb5_context context,
 
 #ifndef HEIMDAL_SMALLER
 
-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
-};
-
-static int num_keytypes = sizeof(keytypes) / sizeof(keytypes[0]);
-
-
-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;
-}
-
-/*
- * First take the configured list of etypes for `keytype' if available,
- * else, do `krb5_keytype_to_enctypes'.
- */
-
-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;
-
-    if (keytype != KEYTYPE_DES || context->etypes_des == NULL)
-       return krb5_keytype_to_enctypes (context, keytype, len, val);
-
-    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;
-}
-
-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;
-    }
-    return 0;
-}
-
-
-krb5_error_code KRB5_LIB_FUNCTION
-krb5_string_to_keytype(krb5_context context,
-                      const char *string,
-                      krb5_keytype *keytype)
-    __attribute__((deprecated))
-{
-    char *end;
-    int i;
-
-    for(i = 0; i < num_keytypes; i++)
-       if(strcasecmp(keytypes[i]->name, string) == 0){
-           *keytype = keytypes[i]->type;
-           return 0;
-       }
-
-    /* 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;
-    }
-
-    krb5_set_error_message(context, KRB5_PROG_KEYTYPE_NOSUPP,
-                          "key type %s not supported", string);
-    return KRB5_PROG_KEYTYPE_NOSUPP;
-}
-
 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 +4597,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 +4624,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 */
index d6099c3c6c36fe2282379e092197371da0e79a68..888d394ad813687c7837c1a2fa319e09ce8f8bf1 100644 (file)
@@ -52,7 +52,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.
  *
@@ -67,21 +69,6 @@ krb5_data_free(krb5_data *p)
     krb5_data_zero(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).
  *
index 6374fa17aef669c2c91c9aac90d5aae9271e1d2d..d602c4b0e1b760645ad5e3d3c54eabedc8899b7b 100644 (file)
 
 RCSID("$Id$");
 
-#undef __attribute__
-#define __attribute__(X)
+#undef KRB5_DEPRECATED
+#define KRB5_DEPRECATED
+#undef __attribute__(x)
+#define __attribute__(x)
 
 /**
  * Clears the error message from the Kerberos 5 context.
@@ -172,6 +174,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);
@@ -213,7 +218,7 @@ krb5_free_error_message(krb5_context context, const char *msg)
 
 void KRB5_LIB_FUNCTION
 krb5_free_error_string(krb5_context context, char *str)
-    __attribute__((deprecated))
+    KRB5_DEPRECATED
 {
     krb5_free_error_message(context, str);
 }
@@ -230,7 +235,7 @@ krb5_free_error_string(krb5_context context, char *str)
 
 krb5_error_code KRB5_LIB_FUNCTION
 krb5_set_error_string(krb5_context context, const char *fmt, ...)
-    __attribute__((format (printf, 2, 3))) __attribute__((deprecated))
+    __attribute__((format (printf, 2, 3))) KRB5_DEPRECATED
 {
     va_list ap;
 
@@ -252,7 +257,7 @@ krb5_set_error_string(krb5_context context, const char *fmt, ...)
 
 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))
+    __attribute__ ((format (printf, 2, 0))) KRB5_DEPRECATED
 {
     krb5_vset_error_message(context, 0, fmt, args);
     return 0;
@@ -269,7 +274,7 @@ krb5_vset_error_string(krb5_context context, const char *fmt, va_list args)
 
 void KRB5_LIB_FUNCTION
 krb5_clear_error_string(krb5_context context)
-     __attribute__((deprecated))
+     KRB5_DEPRECATED
 {
     krb5_clear_error_message(context);
 }
index b745c67e11daca70a0308beef5ef45122ad25cf7..d34f041cf5a8a48319eb450bee3d70de9c3024e4 100644 (file)
@@ -233,8 +233,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 +453,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;
 }
 
@@ -770,7 +770,13 @@ fcc_remove_cred(krb5_context context,
        return ret;
     }
 
-    return krb5_cc_move(context, newfile, id);
+    ret = krb5_cc_move(context, newfile, id);
+    if (ret) {
+       krb5_cc_destroy(context, newfile);
+       return ret;
+    }
+    
+    return ret;
 }
 
 static krb5_error_code
@@ -822,12 +828,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 +907,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,7 +920,8 @@ 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);
     }
index ce167853192ac0c43eda16f1b736c320a9d44ed5..2bef0ae956dbf07c8ed6fef46906d2f96b9e1f00 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "krb5_locl.h"
 
-RCSID("$Id: get_addrs.c 23815 2008-09-13 09:21:03Z lha $");
+RCSID("$Id$");
 
 #ifdef __osf__
 /* hate */
@@ -43,9 +43,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 +104,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 +228,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;
     }
 
index 97e0022ee12f5a3cd3da8194c45d152b8b12b0ff..3ee6f1b445d8c5135c2c76e45de8ddf9ca8d845b 100644 (file)
@@ -375,17 +375,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;
 }
@@ -561,7 +562,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 +1218,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);
 }
index 2ea075f6c5d5a77abb0cd08fc46c399c28ee0a40..18aa95f95aa0ffe0d923c8fa7165db1e9c69e6e3 100644 (file)
@@ -51,14 +51,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 +72,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 +96,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 +116,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);
index cc49e16030cbb4f78d50770dcba47dceb615ff3e..36180917738dbc15bf38d050c7eba21eea22a86f 100644 (file)
  * SUCH DAMAGE.
  */
 
+#define KRB5_DEPRECATED
+
 #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;
-}
-
-
-
-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;
-}
-
+#ifndef HEIMDAL_SMALLER
 
 static krb5_error_code
 make_pa_enc_timestamp(krb5_context context, PA_DATA *pa,
@@ -626,6 +110,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 +347,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 +376,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 +541,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 +563,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_in_tkt_with_keytab.c b/source4/heimdal/lib/krb5/get_in_tkt_with_keytab.c
deleted file mode 100644 (file)
index 0dedbef..0000000
+++ /dev/null
@@ -1,99 +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$");
-
-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;
-
-    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;
-}
-
-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;
-
-    a.principal = creds->client;
-    a.keytab    = keytab;
-
-    return krb5_get_in_tkt (context,
-                           options,
-                           addrs,
-                           etypes,
-                           pre_auth_types,
-                           krb5_keytab_key_proc,
-                           &a,
-                           NULL,
-                           NULL,
-                           creds,
-                           ccache,
-                           ret_as_reply);
-}
index 547a14e04cebd2ce4854a62fd950b0bbffd59cbf..2e8a0d18d85f37ada44eb3653eef6f8f0b2f5789 100644 (file)
@@ -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
index 89ea3004ed06f67486854599ea9ed4085f86d085..b1bd94d3b9cd113433dcb72d8e8908e59ab917b3 100644 (file)
 #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);
     }
@@ -368,35 +316,6 @@ krb5_get_init_creds_opt_set_pac_request(krb5_context context,
     return 0;
 }
 
-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,
@@ -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 */
index 0b75522e9df5bfccf127862d1f69bc9eb2836dcc..ae680fe30985a940f0aa33b46487a6fca93ac6c0 100644 (file)
@@ -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.
  *
@@ -41,7 +41,7 @@ typedef struct krb5_get_init_creds_ctx {
     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 +49,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 +87,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 +101,23 @@ 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_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 +149,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 +168,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 +182,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 +201,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 +278,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 +296,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 +312,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 +323,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 +402,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,8 +415,9 @@ 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));
@@ -360,7 +428,13 @@ get_init_creds_common(krb5_context context,
        ;                       /* 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 +456,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 +482,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 +532,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 +554,7 @@ out:
     return ret;
 }
 
+
 krb5_error_code KRB5_LIB_FUNCTION
 krb5_keyblock_key_proc (krb5_context context,
                        krb5_keytype type,
@@ -485,68 +565,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 +935,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 +953,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 +968,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 +982,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 +1004,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 +1043,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 +1089,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 +1142,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 +1168,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 +1179,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 +1195,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 +1224,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 +1236,339 @@ 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;
 
+    *rctx = NULL;
 
-    memset(&md, 0, sizeof(md));
-    memset(&rep, 0, sizeof(rep));
-
-    _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;
 
-       /* fill_in_md_data */
-       ret = process_pa_data_to_md(context, creds, &ctx->as_req, ctx,
-                                   &md, &ctx->as_req.padata,
-                                   prompter, prompter_data);
+    client_realm = krb5_principal_get_realm (context, ctx->cred.client);
+
+    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;
+
+    return 0;
+}
 
-       krb5_data_free(&ctx->req_buffer);
+/**
+ * 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
+ */
 
-       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");
+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;
+    }
 
-       ret = krb5_sendto_context (context, stctx, &ctx->req_buffer,
-                                  creds->client->realm, &resp);
-       if (ret)
-           goto out;
+    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;
+
+    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++;
 
-       memset (&rep, 0, sizeof(rep));
-       ret = decode_AS_REP(resp.data, resp.length, &rep.kdc_rep, &size);
+    /* 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);
+
+           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 +1576,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 +1777,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 (ctx->password == NULL && password == NULL) {
        krb5_prompt prompt;
        krb5_data password_data;
        char *p, *q;
@@ -1528,40 +1812,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 +1883,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;
 }
index 8a8f1efc11a09334db2498adf12d8bb240675b73..9e569acdf84c29daab249c33e3013af09430bc46 100644 (file)
@@ -51,9 +51,18 @@ typedef struct krb5_kcmcache {
     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 +70,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 +99,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 +149,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 +215,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;
     }
 
@@ -609,10 +618,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 +634,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 +704,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 +724,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 +765,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 +778,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;
index aa6353d7c82c109e616bf0b59f87d8b8cd57e729..337dc44ad029bf980ac1d49fc2a6e0a88ba12409 100644 (file)
@@ -77,15 +77,24 @@ 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;
 }
 
 krb5_enctype
index aa7c77ce46c2f79f8feacd2c5e531bf12dbb7201..20534218f04e3ea46c202da59a1fe9006bb7f16c 100644 (file)
 
 RCSID("$Id$");
 
-/*
- * Register a new keytab in `ops'
- * Return 0 or an error.
+/**
+ * @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;
+
+    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 +160,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 +171,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 +234,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 +256,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 +294,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 +311,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 +356,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 +380,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 +402,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 +444,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 +468,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 +533,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 +543,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 +635,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 +678,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 +699,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 +726,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 +756,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 +782,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 +809,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
index 7a2d9b9f706145426c5079b99d21c925d9c99e0a..0315677827c1576c4392a1950c42c3444bbf21c0 100644 (file)
@@ -253,6 +253,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,
index f494cac253c4886190dfe3b1fa9058188a4f5683..7d45497e959c74bcab8fd01077bd31f7adc48638 100644 (file)
@@ -331,6 +331,14 @@ fkt_close(krb5_context context, krb5_keytab id)
     return 0;
 }
 
+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,
@@ -445,6 +453,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 +468,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 +485,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 +671,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 +771,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 +785,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 +799,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,
index 71d3d89d583abcf15f498f2b3862f5ddd6b68a9e..c0a2baa9fec6c1e383f0f0e6db919ba6b0b8a833 100644 (file)
@@ -275,6 +275,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 +442,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,
index defd10d67cc74be16ae2f9187e827e53608bd74e..ec5da9a26e91742042e79f5cc89d97578890e668 100644 (file)
@@ -228,6 +228,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,
index 0ba4e7b54ac6d1af10465fa6c035c4fb57d4d448..3477e9d1d01ca92792edcf82423e798c4a8a0b84 100644 (file)
 #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
@@ -731,18 +746,18 @@ typedef krb5_error_code (*krb5_send_to_kdc_func)(krb5_context,
                                                 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 */
index ec0cb3bc0b23745fe58941c41d3fccd7c408b5c1..5a7fe6a41334db5766ed065bf0c794611cc366ff 100644 (file)
 
 #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 */
index ced722f2d9c05f4a58dabe5ba8cf7d1a06b1ba8a..2d8bc07de39204fdc57f195006a0b0d54c471595 100644 (file)
@@ -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;
index 7348ac3f00a2f3947865cd9f9085e8578f6bd696..e9111abec992cfb0215631e8dc5afd4a1b2a51d7 100644 (file)
@@ -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;
 }
index f8f13922f590d750e1237e0964f3e83265ec472e..8ccda6f9506c9ec824888dd574fcb2db9c55bcfc 100644 (file)
@@ -34,6 +34,9 @@
 #include "krb5_locl.h"
 RCSID("$Id$");
 
+#undef KRB5_DEPRECATED
+#define KRB5_DEPRECATED
+
 #ifndef HEIMDAL_SMALLER
 
 /*
@@ -315,8 +318,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;
 }
 
index fa45b09f18ed8a9a30c3c52d275a13f816812039..39b70a872208f624de3e9e0de198df61b1d62132 100644 (file)
@@ -109,8 +109,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 +131,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;
 }
index 3c55eb3dc3aa5b6180e2aa8de1116faeee311e50..bfa3d2136b2e119e5fa8a801571d32c06e1679d4 100644 (file)
@@ -613,6 +613,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;
        }
index de5e90a68e13615c855c9e48572fc154031f9f22..ebe44f5de690602ec2d20e02147d7484e482f35a 100644 (file)
@@ -60,7 +60,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 +128,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,7 +184,7 @@ 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;
 
@@ -159,7 +204,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 +218,22 @@ create_signature(krb5_context context,
                 hx509_peer_info peer,
                 krb5_data *sd_data)
 {
-    hx509_cert cert = NULL;
-    hx509_query *q = NULL;
-    int ret;
+    int ret, flags = 0;
 
-    ret = hx509_query_alloc(id->hx509ctx, &q);
-    if (ret) {
-       pk_copy_error(context, id->hx509ctx, ret,
-                     "Allocate query to find signing certificate");
-       return ret;
-    }
-
-    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");
@@ -319,7 +349,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 +397,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 +451,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 +461,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(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)
@@ -552,7 +689,7 @@ pk_mk_padata(krb5_context context,
        
        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;
@@ -648,8 +785,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);
@@ -737,6 +874,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,
@@ -995,6 +1133,7 @@ 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)) {
        krb5_set_error_message(context, EINVAL,
@@ -1002,9 +1141,12 @@ pk_rd_pa_reply_enckey(krb5_context context,
        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,6 +1184,8 @@ pk_rd_pa_reply_enckey(krb5_context context,
        heim_octet_string out;
 
        ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL);
+       if (ret)
+           goto out;
        if (der_heim_oid_cmp(&type, oid_id_pkcs7_signedData())) {
            ret = EINVAL; /* XXX */
            krb5_set_error_message(context, ret,
@@ -1131,14 +1275,15 @@ 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);
@@ -1221,7 +1366,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 +1382,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 +1479,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 +1536,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);
@@ -1496,6 +1719,7 @@ _krb5_pk_allow_proxy_certificate(struct krb5_pk_identity *id,
 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 +1741,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 +1761,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 +1779,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 +1861,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 +1947,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 +1961,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 +2199,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 +2263,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 +2290,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 +2304,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 +2365,109 @@ krb5_get_init_creds_opt_set_pkinit(krb5_context context,
     return EINVAL;
 #endif
 }
+
+#ifdef PKINIT
+
+static int
+match_ms_san(hx509_context context, hx509_cert cert, void *ctx)
+{
+    hx509_octet_string_list list;
+    char **result = ctx;
+    int ret;
+
+    if (*result) 
+       return 0;
+
+    ret = hx509_cert_find_subjectAltName_otherName(context,
+                                                  cert,
+                                                  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,
+                               result, NULL);
+       if (ret)
+           *result = NULL;
+    }
+    hx509_free_octet_string_list(&list);          
+
+    if (*result == NULL)
+       return 0;
+    return 1;
+}
+
+#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;
+    char *enterprise_name = NULL;
+    hx509_context hx509ctx;
+    hx509_certs certs, result;
+    hx509_query *q;
+
+    *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, oid_id_pkinit_ms_eku());
+    hx509_query_match_cmp_func(q, match_ms_san, &enterprise_name);
+
+    ret = hx509_certs_filter(hx509ctx, certs, q, &result);
+    hx509_query_free(hx509ctx, q);
+    hx509_certs_free(&certs);
+
+    if (ret)
+       return ret;
+    if (enterprise_name == NULL)
+       return ENOENT; /* XXX */
+
+    ret = krb5_make_principal(context, principal, realm,
+                             enterprise_name, NULL);
+    free(enterprise_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
+}
index f27355f2d8049428bfe0b5213ea2cccc57a36cea..0aea01a04f29bd0d8b9c01ff9d1b747787c89047 100644 (file)
@@ -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
@@ -78,8 +78,6 @@ RCSID("$Id$");
  * @ingroup krb5_principal
  */
 
-
-
 void KRB5_LIB_FUNCTION
 krb5_free_principal(krb5_context context,
                    krb5_principal p)
@@ -90,6 +88,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 +137,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 +174,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 +288,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 "
@@ -821,6 +833,7 @@ krb5_principal_match(krb5_context context,
     return TRUE;
 }
 
+#ifdef KRB4
 
 static struct v4_name_convert {
     const char *from;
@@ -925,6 +938,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 +953,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 +1013,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 +1042,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 +1070,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 +1098,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 +1109,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 +1169,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 +1179,7 @@ name_convert(krb5_context context, const char *name, const char *realm,
            }
        }
     }
+#endif
     return -1;
 }
 
@@ -1273,6 +1258,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
index b368573b8d93dc8be971abddcf723760bb0d2c3d..4c060973d69de092c5be030b81e27593efc33cf1 100644 (file)
@@ -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)
 {
index dc510330190bcbc4506fc35de3b4e446b64ac969..30e82d8de83be97f5c216c432ed51265bab7d265 100644 (file)
@@ -149,15 +149,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 */
 
index 010726b180961ee236b998952f9c046e0771a324..14541c2c15a73525548340ea8069c9d9f6b1bcbd 100644 (file)
@@ -48,7 +48,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 +81,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 ||
index a416f90c10f48336716b4cbeeaa58c874084c71e..824646897b70b2db3bbed5f8987df8b0ad5e7001 100644 (file)
@@ -58,8 +58,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 +98,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 +524,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 +553,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 +585,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 +632,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 +775,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 +812,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 +846,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 +869,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 +886,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 +1057,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;
 }
index 8489f984535a940656c80a99672f4b265d322a00..0b7accb860fff9f0abb46326c938e156eece2ff9 100644 (file)
@@ -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;
index 47f9abe1de3aeca5dbe86ac990c2012b793ec386..8037c259155cc097cccf238bcb89ecfb40c226cf 100644 (file)
@@ -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.
  *
@@ -54,12 +54,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 +91,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 +230,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 +250,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 +303,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 +326,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 +389,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 +412,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 +462,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 +485,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 +529,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 +557,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 +819,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 +848,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 +878,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 +903,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 +1172,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);
index 8a587600fdad129fd984c795bf08726257aa654a..7c52947aa8c1e71a7db66a1845cd61f7c4b8cbd1 100644 (file)
@@ -67,7 +67,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 +104,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 +140,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 +185,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;
 }
index fe3c513ee9a9a1e879a53193df066162d121cc80..40f3e8db891a2cea6f34430b6697f45233284b2b 100644 (file)
@@ -60,12 +60,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 +114,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;
 }
index 5c7cd17fba95bd19d6052c1bdb9dd2bb58064bff..d908e4617c36b1c10449c1136729110651ccee01 100644 (file)
@@ -93,6 +93,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 +145,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 +203,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;
 }
index db786265707a02bdced5189b3bf2aa3b5a30a723..9b57fe54774a5986592c0af461dfdb0485187295 100644 (file)
@@ -301,3 +301,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;
+}
index 6911cb20f8f31bc0647c30243bbf2cc5932764da..cfcc8ca4790d4a9a9cc41aafa398da23c5427700 100644 (file)
@@ -217,14 +217,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;
 }
 
 /*
index a00ae80697bda74e8ae2952a1fbf20004c262ca0..29906b75f8c61630c4c3c37f06cbe133d059d35b 100644 (file)
@@ -96,6 +96,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 +116,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 +135,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 +152,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 +169,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 +191,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 +212,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 +231,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 +249,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 +270,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 +297,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 +315,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 +331,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)
 {
index 1002b67cc8d49d213d40ad9ed8da949989080cbd..1fe456d022f065afe4ad727bea79d8ae0d7356bb 100644 (file)
@@ -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;
 }
 
 /*
index d0096447b35d864065a5471234e4873fa9800463..5e720eb6d4c95002c819f09817a6c4cba2acc285 100644 (file)
  * 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;) {
index a87345be3f60e6483efe5835f1f0b191191938c2..67d240c2313db9f89335f55fbe521f7be7d845d8 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-#endif
 #include "roken.h"
 
-RCSID("$Id$");
-
 #ifndef HAVE_BSWAP32
 
 unsigned int ROKEN_LIB_FUNCTION
index 7a64233309c03c1564bfb725234ec1e3fac93eed..c015b1d8fa742886e1516d90a66228a7fb76f37e 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <unistd.h>
 #include <fcntl.h>
index 9198c05e26c5976c75080492bbf58528f992c627..7aa0ef7372a2e823c1ff992133142fcaea76e4f6 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
index 58f5a112f2a3c7738bd1db871f56c666e957ada4..69c1ba40ff89290020bf47895c46cc029d80c19a 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index 88a86815efc779f05d94c50a9d7106db281525f1..c5513c323de1531edaa1e90496d1d416d13b3366 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <unistd.h>
 
index 6c579e99f3d8a6b2bf33c9322694045cfaa2017c..c8e6504030fee028e0e5562183d7a24b1961320f 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <stdlib.h>
 #include <err.h>
index d033e16a075113e7541301753d8a6734a876e2c4..c937e6d7070c55455eae012402bb5041e29745e5 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <stdlib.h>
 #include <err.h>
index 239d6a0eab46d254ff57c09e686c515854820620..f77c8ec7332242f15f07b10fc600e4193a81ff82 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <stdlib.h>
 #include <err.h>
index fb353d0d8509917cfe94e229a49998439e8ec4f2..ab7f26550b77006ae0cab05ada82ee670f81f0b1 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <stdlib.h>
 #include <err.h>
index 1721d20aafed7fd7414c6c4c2f0f924a4f5c39f1..434e49e888db6f3f0a306e986106ad5486b26436 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index 38c27d33800ec691cbf2dd263b3a3044a233d87a..335504300a6451257f048f43dcad3bd9464b8647 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index 084900a58aafc2c77ba83ba94202ff2c9129107e..10beac05eaddbbac38615a908a0ec6da044b7d42 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index 9b200c115978fa9981ea26a37a4c5c0490d1c368..60fb1764fabda74a352243e87204473f4b16c744 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <stdlib.h>
 #ifdef HAVE_UNISTD_H
index a8fc029c32258fd0ef729db8f5c03c04307647dc..8c61299763b9bbccd2b57cd68c74e7eba4da8392 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index 3168ccc53d2c5cd68f73b26b898173f95ab73cf9..60b0f645afc085899d6d0937f805f91056b6897e 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <stdio.h>
 #include <stdlib.h>
index e3c2b50e3257dfb65a7745095179e67ba5aa1d7b..ddaec03a8914de11f302acbf50895d94309a0661 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index ec578937b7bade14025a4b0076b3d3761da5ca5b..16fdbdd24a661eabd07778cbba837f36cb42b0fa 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index 865cc09dc8bf4012ca19e897dcf409ea15a4f9b6..0621cfeee1cd99ea4935922361d07373cd45223f 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index b01a3d7e45ebd54795f023b767478b38a7186183..933b6dec7997455758300c0c39d97965d31c455a 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index 0cee02d4721abe2910cc0bc74d8fb8afd7d6605b..7e49f8008f9a2f6aaf7bf0b1738c7395f13b52d8 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #ifndef HAVE_H_ERRNO
 int h_errno = -17; /* Some magic number */
index 2167172f9f6e65eb5cf0dfc04ea9214e46032574..95488af5c741b472b7caae63c2e2d527fc5eaf21 100644 (file)
  * 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];
index 9376c1da3607f2322a112a77e871d31bbcdf8b18..b5f2b42f60aa797dd9145afcd0b55d18aaecbcbb 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index c42697c63c5c01f320c013656fea62a03518312c..c9b21e00f8b55c7497f3d66d3db6506ac1e0d9ac 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index 5e4e4f9dc7682559ab9321e47465df09126d78b9..daf3e926ddc5d2a82e39acfc6810e01fe1344591 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index f2a9af3aa325a45fc77b98489c7ee8b7fda8091b..ad60824f4aa18caa8ae4b0eeaaba6d30a8bff24c 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index 257481cffb125919905e0718a9c5df6378bcf53b..2999e8249cea89074a0bea44e90a3c60861a61fa 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index ae025ffc719c1387314762a34851c3acaca56e31..9d055d0068287420a51610ef195f4ff64e6a8713 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <sys/types.h>
 #include <unistd.h>
index 11f5b8d7be8879cd99182aab4b7e926d18ad38d1..515f210973feff3388fddc578045cce85c667b13 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <sys/types.h>
 #include <unistd.h>
index 6065eeb42514d839ea5e86b15e4f8effd495b06c..b581970bd7c468a7ccf2da7c9481d28f6811c90f 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <parse_units.h>
 #include "parse_time.h"
index 4dbd7b489bd8c437dcdffea88f367d0ff4efed2a..a848298c57326969f3cfe5a164d3352720df40c4 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <stdio.h>
 #include <ctype.h>
index f358a5b26621245a53fd85b7699f455528a587c5..a74e438cf8316c3a44c5cfed5003b5d48f17abfb 100644 (file)
@@ -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)
 {
 }
 
index d181dfa070cd0043087f594226a24565e6a7d74d..91b2afefe7ed0c1d1c731d998f4d2c26f469fc08 100644 (file)
 #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__ */
index 309469722b8295c5f4a52f94b05f4daf5f601413..78e877e6accc9709dda30c2a778b2361c215ebce 100644 (file)
 #include <util.h>
 #endif
 
+#ifdef STREAMSPTY
+#include <stropts.h>
+#endif /* STREAMPTY */
+
 #include "roken.h"
 #include <getarg.h>
 
@@ -90,6 +94,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);
@@ -299,7 +336,6 @@ main(int argc, char **argv)
     parse_configuration(argv[0]);
 
     argv += 1;
-    argc -= 1;
 
     open_pty();
 
index 1d341258fe1f6b7603d9a828c7a2a82adb234c05..4d2f3b5d5c467aa36f4dee554e3325bafd7b1a5b 100644 (file)
@@ -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 *);
 
+#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
index d71bee7b46af29c9d0c77d0901ce73aaa32d4d71..3fce136875ebfc6dacf920ec0b9fefe55d6e038f 100644 (file)
@@ -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
index 12760456a43920350742f16924bf9be4391a81d0..d87a49a04b2d63d338c45a51a54ca54d568724c7 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index cfb7657091ddf753dea0849d174d7a4f4f4b3724..7d11a487cff6dda8ba265d994c0cc2924ecd1f90 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID ("$Id$");
-#endif
+
 #include "roken.h"
 #include "rtbl.h"
 
index 9beb07afe9ee9fe04e2ba6cb1e57dfd6a1aa10cc..225e6ae0924db97214cfb35b964c786acbaa9a32 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 
index 9141ca2bb1884e28446d448387ba9b967d6bd315..19a4845435254136f10fb0bc487032d614cd9ff6 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <signal.h>
 #include "roken.h"
index 7060cb8d37dd52a0fe48d21dfa6429f2bc950a95..86dde1bad22df5913f077e85288953fd4a5370fd 100644 (file)
  * 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;
-}
index a373eb7ed2a7f156665b2ec5dc3de8729522fe8c..e7cdce63eb09cdbc6a300f9b3bd59dba4b9f9e86 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include "roken.h"
 #include <err.h>
index a33d52134a0f32bbce02b53a17073f6128144fe9..f444d05e2546962a51c34e75be6d212ec91b5fbc 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <stdarg.h>
 #include <stdlib.h>
index ea787d81840002b2e76d3e5d8b6edcffc6473cdd..1a6634b73685495f0d3acf40c6bdfeaf76d33cd1 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 #include <string.h>
 #include <ctype.h>
 
index aa80996946eb79021008ce99829a7d4316e07b0b..dc56892144ba3bc36c99be3e426604c8210d18a8 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <stdarg.h>
 #include <stdlib.h>
index 7a93fb17aa62df7462b14e5c9430555fbdfeed8e..5cbf8557a54075742b5452af51d5b671db3ad3a9 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <string.h>
 
index 61b7d39c579df98118710b6fedc24da73fe53aa4..908e37ca405919eab83e6c6099d69cbc82e5b734 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <string.h>
 
index d67dd20dd0eb27dccd4aad985a83bcef92241e75..db2d987f9f73ada6080879d30ca6c5314a4c2e8f 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 #include <string.h>
 #include <ctype.h>
 
index 43705e4d50d97688473d26093af53a145884bbb0..c8d19a44557c06b1a899fdf1e1308ace3c613cad 100644 (file)
  */
 
 #if 1
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 #include "roken.h"
 #ifndef _DIAGASSERT
 #define _DIAGASSERT(X)
index 5f6d86ee5692b59a8360706f37d80558026c0e33..13366ce1327e1822fcc5bd0f3cf4137008ccf5d6 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id$");
-#endif
 
 #include <unistd.h>
 
index 63e016174a73b01fc631ca03184f3971cf839dca..20c3fd98344b1523a53899f435cac9c5706ca905 100644 (file)
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
+
 #include <config.h>
-RCSID("$Id$");
-#endif
+
 #include "roken.h"
 
-#include "print_version.h"
+#include "version.h"
 
 void
 print_version(const char *progname)
 {
-    const char *package_list = VERSIONLIST;
+    const char *package_list = heimdal_version;
 
     if(progname == NULL)
        progname = getprogname();
index c7af0e4958ffa12c65264d09424dcf7b285b90b7..3f71449fac5d15788bff1c15eeecb907bc111c45 100644 (file)
@@ -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];
index 6e99cfc86b8daaae9ef5cc9c33e695faf6ea2bbf..aa04b3fd1d403b532f058ee5190bd4cc2f16f311 100644 (file)
@@ -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[] = {
index f563b79107063fc99be7762d7fae2000c7e6fa64..ed944b4c7d28dd5e90ccbd2e34ff1965f8701175 100644 (file)
@@ -31,9 +31,7 @@
  * SUCH DAMAGE.
  */
 
-#ifdef HAVE_CONFIG_H
 #include <config.h>
-#endif
 #include "windlocl.h"
 
 RCSID("$Id$");
index f90c252e7dd8da94f1fdb6740ccaa52976497769..01c0d0f1c5f29a6aeb845f394e50ecf676f2907f 100644 (file)
@@ -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"