r23678: Update to current lorikeet-heimdal (-r 767), which should fix the
authorAndrew Bartlett <abartlet@samba.org>
Tue, 3 Jul 2007 08:00:08 +0000 (08:00 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 19:58:59 +0000 (14:58 -0500)
panics on hosts without /dev/random.

Andrew Bartlett
(This used to be commit 14a4ddb131993fec72316f7e8e371638749e6f1f)

67 files changed:
source4/heimdal/kdc/default_config.c
source4/heimdal/kdc/digest.c
source4/heimdal/kdc/kdc-protos.h
source4/heimdal/kdc/kdc.h
source4/heimdal/kdc/krb5tgs.c
source4/heimdal/kdc/misc.c
source4/heimdal/kdc/pkinit.c
source4/heimdal/lib/asn1/k5.asn1
source4/heimdal/lib/asn1/lex.c
source4/heimdal/lib/asn1/pkinit.asn1
source4/heimdal/lib/com_err/lex.c
source4/heimdal/lib/gssapi/krb5/acquire_cred.c
source4/heimdal/lib/gssapi/krb5/display_name.c
source4/heimdal/lib/gssapi/krb5/prf.c
source4/heimdal/lib/gssapi/krb5/release_name.c
source4/heimdal/lib/gssapi/mech/context.c
source4/heimdal/lib/gssapi/mech/gss_accept_sec_context.c
source4/heimdal/lib/gssapi/mech/gss_display_name.c
source4/heimdal/lib/gssapi/mech/gss_display_status.c
source4/heimdal/lib/gssapi/mech/gss_duplicate_name.c
source4/heimdal/lib/gssapi/mech/gss_inquire_context.c
source4/heimdal/lib/gssapi/mech/gss_inquire_cred_by_mech.c
source4/heimdal/lib/gssapi/mech/gss_krb5.c
source4/heimdal/lib/gssapi/mech/gss_set_cred_option.c
source4/heimdal/lib/gssapi/spnego/accept_sec_context.c
source4/heimdal/lib/hcrypto/pkcs12.c
source4/heimdal/lib/hcrypto/rand-egd.c
source4/heimdal/lib/hcrypto/rand-fortuna.c
source4/heimdal/lib/hcrypto/rand-timer.c [new file with mode: 0644]
source4/heimdal/lib/hcrypto/rand.c
source4/heimdal/lib/hcrypto/randi.h
source4/heimdal/lib/hcrypto/rsa-imath.c
source4/heimdal/lib/hdb/ext.c
source4/heimdal/lib/hx509/cert.c
source4/heimdal/lib/hx509/cms.c
source4/heimdal/lib/hx509/crypto.c
source4/heimdal/lib/hx509/file.c
source4/heimdal/lib/hx509/hx509-private.h
source4/heimdal/lib/hx509/hx509-protos.h
source4/heimdal/lib/hx509/hx509.h
source4/heimdal/lib/hx509/hx_locl.h
source4/heimdal/lib/hx509/keyset.c
source4/heimdal/lib/hx509/ks_file.c
source4/heimdal/lib/hx509/ks_keychain.c
source4/heimdal/lib/hx509/ks_p11.c
source4/heimdal/lib/hx509/ks_p12.c
source4/heimdal/lib/hx509/req.c
source4/heimdal/lib/hx509/revoke.c
source4/heimdal/lib/krb5/crypto.c
source4/heimdal/lib/krb5/get_cred.c
source4/heimdal/lib/krb5/init_creds_pw.c
source4/heimdal/lib/krb5/krb5-private.h
source4/heimdal/lib/krb5/krb5-protos.h
source4/heimdal/lib/krb5/krb5.h
source4/heimdal/lib/krb5/krb5_err.et
source4/heimdal/lib/krb5/krbhst.c
source4/heimdal/lib/krb5/misc.c
source4/heimdal/lib/krb5/pac.c
source4/heimdal/lib/krb5/pkinit.c
source4/heimdal/lib/krb5/plugin.c
source4/heimdal/lib/krb5/principal.c
source4/heimdal/lib/krb5/rd_error.c
source4/heimdal/lib/krb5/send_to_kdc.c
source4/heimdal/lib/ntlm/heimntlm-protos.h
source4/heimdal/lib/ntlm/ntlm.c
source4/heimdal/lib/roken/roken_gethostby.c
source4/heimdal_build/config.mk

index c28bd424ead197893793630326674b54791922b1..e06366f214b39105fa2c9f3d236da93823fc7b65 100644 (file)
 #include <getarg.h>
 #include <parse_bytes.h>
 
-RCSID("$Id: default_config.c 20532 2007-04-23 07:46:57Z lha $");
+RCSID("$Id: default_config.c 21296 2007-06-25 14:49:11Z lha $");
 
-
-int
+krb5_error_code
 krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
 {
     krb5_kdc_configuration *c;
@@ -62,7 +61,8 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
     c->enable_524 = FALSE;
     c->enable_v4_cross_realm = FALSE;
     c->enable_pkinit = FALSE;
-    c->enable_pkinit_princ_in_cert = TRUE;
+    c->pkinit_princ_in_cert = TRUE;
+    c->pkinit_require_binding = TRUE;
     c->db = NULL;
     c->num_db = 0;
     c->logf = NULL;
@@ -257,12 +257,19 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config)
        krb5_config_free_strings(pool_list);
        krb5_config_free_strings(revoke_list);
 
-       c->enable_pkinit_princ_in_cert = 
+       c->pkinit_princ_in_cert = 
            krb5_config_get_bool_default(context, NULL,
-                                        c->enable_pkinit_princ_in_cert,
+                                        c->pkinit_princ_in_cert,
                                         "kdc",
                                         "pkinit_principal_in_certificate",
                                         NULL);
+
+       c->pkinit_require_binding = 
+           krb5_config_get_bool_default(context, NULL,
+                                        c->pkinit_require_binding,
+                                        "kdc",
+                                        "pkinit_win2k_require_binding",
+                                        NULL);
     }
 
     c->pkinit_dh_min_bits =
index 811ab639f1c2da78552a33511fb8a316631d9d13..801449fe5e5319a4c71709ac940c019b5329e2cb 100644 (file)
@@ -34,7 +34,7 @@
 #include "kdc_locl.h"
 #include <hex.h>
 
-RCSID("$Id: digest.c 20877 2007-06-04 04:07:26Z lha $");
+RCSID("$Id: digest.c 21241 2007-06-20 11:30:19Z lha $");
 
 #define MS_CHAP_V2     0x20
 #define CHAP_MD5       0x10
@@ -156,6 +156,44 @@ static const unsigned char ms_rfc3079_magic1[27] = {
     0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
 };
 
+/*
+ *
+ */
+
+static krb5_error_code
+get_password_entry(krb5_context context,
+                  krb5_kdc_configuration *config,
+                  const char *username,
+                  char **password)
+{
+    krb5_principal clientprincipal;
+    krb5_error_code ret;
+    hdb_entry_ex *user;
+    HDB *db;
+
+    /* get username */
+    ret = krb5_parse_name(context, username, &clientprincipal);
+    if (ret)
+       return ret;
+
+    ret = _kdc_db_fetch(context, config, clientprincipal,
+                       HDB_F_GET_CLIENT, &db, &user);
+    krb5_free_principal(context, clientprincipal);
+    if (ret)
+       return ret;
+
+    ret = hdb_entry_get_password(context, db, &user->entry, password);
+    if (ret || password == NULL) {
+       if (ret == 0) {
+           ret = EINVAL;
+           krb5_set_error_string(context, "password missing");
+       }
+       memset(user, 0, sizeof(*user));
+    }
+    _kdc_free_ent (context, user);
+    return ret;
+}
+
 /*
  *
  */
@@ -461,9 +499,6 @@ _kdc_do_digest(krb5_context context,
        break;
     }
     case choice_DigestReqInner_digestRequest: {
-       krb5_principal clientprincipal;
-       HDB *db;
-
        sp = krb5_storage_emem();
        if (sp == NULL) {
            ret = ENOMEM;
@@ -571,29 +606,6 @@ _kdc_do_digest(krb5_context context,
            }
        }
 
-       /* get username */
-       ret = krb5_parse_name(context,
-                             ireq.u.digestRequest.username,
-                             &clientprincipal);
-       if (ret)
-           goto out;
-
-       ret = _kdc_db_fetch(context, config, clientprincipal,
-                           HDB_F_GET_CLIENT, &db, &user);
-
-       krb5_free_principal(context, clientprincipal);
-       if (ret)
-           goto out;
-
-       ret = hdb_entry_get_password(context, db, &user->entry, &password);
-       if (ret || password == NULL) {
-           if (ret == 0) {
-               ret = EINVAL;
-               krb5_set_error_string(context, "password missing");
-           }
-           goto out;
-       }
-
        if (strcasecmp(ireq.u.digestRequest.type, "CHAP") == 0) {
            MD5_CTX ctx;
            unsigned char md[MD5_DIGEST_LENGTH];
@@ -618,6 +630,12 @@ _kdc_do_digest(krb5_context context,
                goto out;
            }
            
+           ret = get_password_entry(context, config, 
+                                    ireq.u.digestRequest.username,
+                                    &password);
+           if (ret)
+               goto out;
+
            MD5_Init(&ctx);
            MD5_Update(&ctx, &id, 1);
            MD5_Update(&ctx, password, strlen(password));
@@ -664,6 +682,12 @@ _kdc_do_digest(krb5_context context,
            if (ireq.u.digestRequest.realm == NULL) 
                goto out;
            
+           ret = get_password_entry(context, config, 
+                                    ireq.u.digestRequest.username,
+                                    &password);
+           if (ret)
+               goto failed;
+
            MD5_Init(&ctx);
            MD5_Update(&ctx, ireq.u.digestRequest.username,
                       strlen(ireq.u.digestRequest.username));
@@ -692,7 +716,7 @@ _kdc_do_digest(krb5_context context,
            if (A1 == NULL) {
                krb5_set_error_string(context, "out of memory");
                ret = ENOMEM;
-               goto out;
+               goto failed;
            }
            
            MD5_Init(&ctx);
@@ -712,7 +736,7 @@ _kdc_do_digest(krb5_context context,
                krb5_set_error_string(context, "out of memory");
                ret = ENOMEM;
                free(A1);
-               goto out;
+               goto failed;
            }
 
            MD5_Init(&ctx);
@@ -758,6 +782,7 @@ _kdc_do_digest(krb5_context context,
 
        } else if (strcasecmp(ireq.u.digestRequest.type, "MS-CHAP-V2") == 0) {
            unsigned char md[SHA_DIGEST_LENGTH], challange[SHA_DIGEST_LENGTH];
+           krb5_principal clientprincipal = NULL;
            char *mdx;
            const char *username;
            struct ntlm_buf answer;
@@ -766,20 +791,20 @@ _kdc_do_digest(krb5_context context,
 
            if ((config->digests_allowed & MS_CHAP_V2) == 0) {
                kdc_log(context, config, 0, "MS-CHAP-V2 not allowed");
-               goto out;
+               goto failed;
            }
 
            if (ireq.u.digestRequest.clientNonce == NULL)  {
                krb5_set_error_string(context, 
                                      "MS-CHAP-V2 clientNonce missing");
                ret = EINVAL;
-               goto out;
+               goto failed;
            }       
            if (serverNonce.length != 16) {
                krb5_set_error_string(context, 
                                      "MS-CHAP-V2 serverNonce wrong length");
                ret = EINVAL;
-               goto out;
+               goto failed;
            }
 
            /* strip of the domain component */
@@ -821,7 +846,7 @@ _kdc_do_digest(krb5_context context,
            /* NtPasswordHash */
            ret = krb5_parse_name(context, username, &clientprincipal);
            if (ret)
-               goto out;
+               goto failed;
            
            ret = _kdc_db_fetch(context, config, clientprincipal,
                                HDB_F_GET_CLIENT, NULL, &user);
@@ -830,7 +855,7 @@ _kdc_do_digest(krb5_context context,
                krb5_set_error_string(context, 
                                      "MS-CHAP-V2 user %s not in database",
                                      username);
-               goto out;
+               goto failed;
            }
 
            ret = hdb_enctype2key(context, &user->entry, 
@@ -839,7 +864,7 @@ _kdc_do_digest(krb5_context context,
                krb5_set_error_string(context, 
                                      "MS-CHAP-V2 missing arcfour key %s",
                                      username);
-               goto out;
+               goto failed;
            }
 
            /* ChallengeResponse */
@@ -848,7 +873,7 @@ _kdc_do_digest(krb5_context context,
                                            challange, &answer);
            if (ret) {
                krb5_set_error_string(context, "NTLM missing arcfour key");
-               goto out;
+               goto failed;
            }
            
            hex_encode(answer.data, answer.length, &mdx);
@@ -861,15 +886,15 @@ _kdc_do_digest(krb5_context context,
 
            r.element = choice_DigestRepInner_response;
            ret = strcasecmp(mdx, ireq.u.digestRequest.responseData);
-           free(mdx);
            if (ret == 0) {
                r.u.response.success = TRUE;
            } else {
                kdc_log(context, config, 0, 
-                       "MS-CHAP-V2 reply mismatch for %s",
+                       "MS-CHAP-V2 hash mismatch for %s",
                        ireq.u.digestRequest.username);
                r.u.response.success = FALSE;
            }
+           free(mdx);
 
            if (r.u.response.success) {
                unsigned char hashhash[MD4_DIGEST_LENGTH];
@@ -958,7 +983,7 @@ _kdc_do_digest(krb5_context context,
 
        if ((config->digests_allowed & (NTLM_V1|NTLM_V1_SESSION|NTLM_V2)) == 0) {
            kdc_log(context, config, 0, "NTLM not allowed");
-           goto out;
+           goto failed;
        }
 
        r.element = choice_DigestRepInner_ntlmInitReply;
@@ -967,14 +992,14 @@ _kdc_do_digest(krb5_context context,
 
        if ((ireq.u.ntlmInit.flags & NTLM_NEG_UNICODE) == 0) {
            kdc_log(context, config, 0, "NTLM client have no unicode");
-           goto out;
+           goto failed;
        }
 
        if (ireq.u.ntlmInit.flags & NTLM_NEG_NTLM)
            r.u.ntlmInitReply.flags |= NTLM_NEG_NTLM;
        else {
            kdc_log(context, config, 0, "NTLM client doesn't support NTLM");
-           goto out;
+           goto failed;
        }
 
        r.u.ntlmInitReply.flags |= 
@@ -1095,7 +1120,7 @@ _kdc_do_digest(krb5_context context,
                              ireq.u.ntlmRequest.username,
                              &clientprincipal);
        if (ret)
-           goto out;
+           goto failed;
 
        ret = _kdc_db_fetch(context, config, clientprincipal,
                            HDB_F_GET_CLIENT, NULL, &user);
@@ -1103,20 +1128,23 @@ _kdc_do_digest(krb5_context context,
        if (ret) {
            krb5_set_error_string(context, "NTLM user %s not in database",
                                  ireq.u.ntlmRequest.username);
-           goto out;
+           goto failed;
        }
 
        ret = get_digest_key(context, config, server, &crypto);
        if (ret)
-           goto out;
+           goto failed;
 
        ret = krb5_decrypt(context, crypto, KRB5_KU_DIGEST_OPAQUE,
                           ireq.u.ntlmRequest.opaque.data,
                           ireq.u.ntlmRequest.opaque.length, &buf);
        krb5_crypto_destroy(context, crypto);
        crypto = NULL;
-       if (ret)
-           goto out;
+       if (ret) {
+           kdc_log(context, config, 0, 
+                   "Failed to decrypt nonce from %s", from);
+           goto failed;
+       }
 
        sp = krb5_storage_from_data(&buf);
        if (sp == NULL) {
@@ -1185,7 +1213,7 @@ _kdc_do_digest(krb5_context context,
            free(targetname);
            if (ret) {
                krb5_set_error_string(context, "NTLM v2 verify failed");
-               goto out;
+               goto failed;
            }
 
            /* XXX verify infotarget matches client (checksum ?) */
@@ -1205,14 +1233,14 @@ _kdc_do_digest(krb5_context context,
                if ((config->digests_allowed & NTLM_V1_SESSION) == 0) {
                    kdc_log(context, config, 0, "NTLM v1-session not allowed");
                    ret = EINVAL;
-                   goto out;
+                   goto failed;
                }
 
                if (ireq.u.ntlmRequest.lm.length != 24) {
                    krb5_set_error_string(context, "LM hash have wrong length "
                                          "for NTLM session key");
                    ret = EINVAL;
-                   goto out;
+                   goto failed;
                }
                
                MD5_Init(&md5ctx);
@@ -1223,7 +1251,7 @@ _kdc_do_digest(krb5_context context,
            } else {
                if ((config->digests_allowed & NTLM_V1) == 0) {
                    kdc_log(context, config, 0, "NTLM v1 not allowed");
-                   goto out;
+                   goto failed;
                }
            }
            
@@ -1232,7 +1260,7 @@ _kdc_do_digest(krb5_context context,
                                            challange, &answer);
            if (ret) {
                krb5_set_error_string(context, "NTLM missing arcfour key");
-               goto out;
+               goto failed;
            }
            
            if (ireq.u.ntlmRequest.ntlm.length != answer.length ||
@@ -1241,7 +1269,7 @@ _kdc_do_digest(krb5_context context,
                free(answer.data);
                ret = EINVAL;
                krb5_set_error_string(context, "NTLM hash mismatch");
-               goto out;
+               goto failed;
            }
            free(answer.data);
 
@@ -1265,7 +1293,7 @@ _kdc_do_digest(krb5_context context,
                                      "NTLM client failed to neg key "
                                      "exchange but still sent key");
                ret = EINVAL;
-               goto out;
+               goto failed;
            }
            
            len = ireq.u.ntlmRequest.sessionkey->length;
@@ -1273,7 +1301,7 @@ _kdc_do_digest(krb5_context context,
                krb5_set_error_string(context,
                                      "NTLM master key wrong length: %lu",
                                      (unsigned long)len);
-               goto out;
+               goto failed;
            }
            
            RC4_set_key(&rc4, sizeof(sessionkey), sessionkey);
@@ -1301,12 +1329,12 @@ _kdc_do_digest(krb5_context context,
        r.u.ntlmResponse.success = 1;
        kdc_log(context, config, 0, "NTLM version %d successful for %s",
                version, ireq.u.ntlmRequest.username);
-
        break;
     }
     default:
+    failed:
        r.element = choice_DigestRepInner_error;
-       r.u.error.reason = strdup("unknown operation");
+       r.u.error.reason = strdup("unknown/failed operation");
        if (r.u.error.reason == NULL) {
            krb5_set_error_string(context, "out of memory");
            ret = ENOMEM;
index f7df365eb2aa9503f2178da17cc56723a3050010..15e8c29f4cb13f2bc3d4462e1c0569ba5e69f8ac 100644 (file)
@@ -37,7 +37,7 @@ kdc_openlog (
        krb5_context /*context*/,
        krb5_kdc_configuration */*config*/);
 
-int
+krb5_error_code
 krb5_kdc_get_config (
        krb5_context /*context*/,
        krb5_kdc_configuration **/*config*/);
@@ -74,6 +74,11 @@ krb5_kdc_save_request (
        const krb5_data */*reply*/,
        const struct sockaddr */*sa*/);
 
+krb5_error_code
+krb5_kdc_set_dbinfo (
+       krb5_context /*context*/,
+       struct krb5_kdc_configuration */*c*/);
+
 void
 krb5_kdc_update_time (struct timeval */*tv*/);
 
index eb24b4ee97012dad0ef50f801763d1d7c7cf1df4..6c129f38f520bb99a70c74f4acbb702675deb34e 100644 (file)
@@ -35,7 +35,7 @@
  */
 
 /* 
- * $Id: kdc.h 19907 2007-01-14 23:10:24Z lha $ 
+ * $Id: kdc.h 21287 2007-06-25 14:09:03Z lha $ 
  */
 
 #ifndef __KDC_H__
@@ -73,13 +73,13 @@ typedef struct krb5_kdc_configuration {
     krb5_boolean enable_524;
 
     krb5_boolean enable_pkinit;
-    krb5_boolean enable_pkinit_princ_in_cert;
+    krb5_boolean pkinit_princ_in_cert;
     char *pkinit_kdc_ocsp_file;
+    int pkinit_dh_min_bits;
+    int pkinit_require_binding;
 
     krb5_log_facility *logf;
 
-    int pkinit_dh_min_bits;
-
     int enable_digest;
     int digests_allowed;
 
index 02cd92de2e3cb17f059ba31bc271ebf946d1b14c..4d6be60f68fe2d40012604b2069a72dadaee161d 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "kdc_locl.h"
 
-RCSID("$Id: krb5tgs.c 21041 2007-06-10 06:21:12Z lha $");
+RCSID("$Id: krb5tgs.c 21262 2007-06-21 15:18:37Z lha $");
 
 /*
  * return the realm of a krbtgt-ticket or NULL
@@ -475,12 +475,14 @@ check_tgs_flags(krb5_context context,
            et->endtime = min(*et->renew_till, et->endtime);
     }      
     
+#if 0
     /* checks for excess flags */
     if(f.request_anonymous && !config->allow_anonymous){
        kdc_log(context, config, 0,
                "Request for anonymous ticket");
        return KRB5KDC_ERR_BADOPTION;
     }
+#endif
     return 0;
 }
 
@@ -731,10 +733,12 @@ tgs_make_reply(krb5_context context,
               &rep.ticket.realm);
     _krb5_principal2principalname(&rep.ticket.sname, server->entry.principal);
     copy_Realm(&tgt_name->realm, &rep.crealm);
+/*
     if (f.request_anonymous)
        _kdc_make_anonymous_principalname (&rep.cname);
-    else
-       copy_PrincipalName(&tgt_name->name, &rep.cname);
+    else */
+
+    copy_PrincipalName(&tgt_name->name, &rep.cname);
     rep.ticket.tkt_vno = 5;
 
     ek.caddr = et.caddr;
@@ -1707,24 +1711,20 @@ server_lookup:
            goto out;
     }
 
-    /* check PAC if there is one */
-    {
+    /* check PAC if not cross realm and if there is one */
+    if (!cross_realm) {
        Key *tkey;
-       krb5_keyblock *tgtkey = NULL;
 
-       if (!cross_realm) {
-           ret = hdb_enctype2key(context, &krbtgt->entry, 
-                                 krbtgt_etype, &tkey);
-           if(ret) {
-               kdc_log(context, config, 0,
-                       "Failed to find key for krbtgt PAC check");
-               goto out;
-           }
-           tgtkey = &tkey->key;
+       ret = hdb_enctype2key(context, &krbtgt->entry, 
+                             krbtgt_etype, &tkey);
+       if(ret) {
+           kdc_log(context, config, 0,
+                   "Failed to find key for krbtgt PAC check");
+           goto out;
        }
 
        ret = check_PAC(context, config, client_principal, 
-                       client, server, ekey, tgtkey,
+                       client, server, ekey, &tkey->key,
                        tgt, &rspac, &require_signedpath);
        if (ret) {
            kdc_log(context, config, 0,
index ebf28735996a08c782af748133a62a09fa29fde3..072df44042979c06116d83fcfb0ec4b6fc9fac6c 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "kdc_locl.h"
 
-RCSID("$Id: misc.c 17951 2006-08-28 14:41:49Z lha $");
+RCSID("$Id: misc.c 21106 2007-06-18 10:18:11Z lha $");
 
 struct timeval _kdc_now;
 
@@ -46,12 +46,14 @@ _kdc_db_fetch(krb5_context context,
              hdb_entry_ex **h)
 {
     hdb_entry_ex *ent;
-    krb5_error_code ret = HDB_ERR_NOENTRY;
+    krb5_error_code ret;
     int i;
 
     ent = calloc (1, sizeof (*ent));
-    if (ent == NULL)
+    if (ent == NULL) {
+       krb5_set_error_string(context, "out of memory");
        return ENOMEM;
+    }
 
     for(i = 0; i < config->num_db; i++) {
        ret = config->db[i]->hdb_open(context, config->db[i], O_RDONLY, 0);
@@ -74,7 +76,8 @@ _kdc_db_fetch(krb5_context context,
        }
     }
     free(ent);
-    return ret;
+    krb5_set_error_string(context, "no such entry found in hdb");
+    return  HDB_ERR_NOENTRY;
 }
 
 void
index bf62f879db7719eb18132d6a7cf0055bc3076a75..ead961022d18a27fc9f3c177d03157112ab0a7d6 100755 (executable)
@@ -33,7 +33,7 @@
 
 #include "kdc_locl.h"
 
-RCSID("$Id: pkinit.c 21039 2007-06-10 06:20:31Z lha $");
+RCSID("$Id: pkinit.c 21290 2007-06-25 14:13:23Z lha $");
 
 #ifdef PKINIT
 
@@ -380,6 +380,7 @@ _kdc_pk_rd_padata(krb5_context context,
     *ret_params = NULL;
     
     if (!config->enable_pkinit) {
+       kdc_log(context, config, 0, "PK-INIT request but PK-INIT not enabled");
        krb5_clear_error_string(context);
        return 0;
     }
@@ -676,6 +677,7 @@ BN_to_integer(krb5_context context, BIGNUM *bn, heim_integer *integer)
 
 static krb5_error_code
 pk_mk_pa_reply_enckey(krb5_context context,
+                     krb5_kdc_configuration *config,
                      pk_client_params *client_params,
                      const KDC_REQ *req,
                      const krb5_data *req_buffer,
@@ -700,8 +702,11 @@ pk_mk_pa_reply_enckey(krb5_context context,
     switch (client_params->type) {
     case PKINIT_COMPAT_WIN2K: {
        int i = 0;
-       if (_kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_09_BINDING) == NULL)
+       if (_kdc_find_padata(req, &i, KRB5_PADATA_PK_AS_09_BINDING) == NULL
+           && config->pkinit_require_binding == 0)
+       {
            do_win2k = 1;
+       }
        break;
     }
     case PKINIT_COMPAT_27:
@@ -1015,6 +1020,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
                goto out;
            }
            ret = pk_mk_pa_reply_enckey(context,
+                                       config,
                                        client_params,
                                        req,
                                        req_buffer,
@@ -1110,6 +1116,7 @@ _kdc_pk_mk_pa_reply(krb5_context context,
            goto out;
        }
        ret = pk_mk_pa_reply_enckey(context,
+                                   config,
                                    client_params,
                                    req,
                                    req_buffer,
@@ -1384,7 +1391,7 @@ _kdc_pk_check_client(krb5_context context,
            "Trying to authorize PK-INIT subject DN %s", 
            *subject_name);
 
-    if (config->enable_pkinit_princ_in_cert) {
+    if (config->pkinit_princ_in_cert) {
        ret = match_rfc_san(context, config,
                            client_params->cert,
                            client->entry.principal);
@@ -1508,7 +1515,8 @@ _kdc_add_inital_verified_cas(krb5_context context,
        krb5_abortx(context, "internal asn.1 encoder error");
 
     ret = _kdc_tkt_add_if_relevant_ad(context, tkt, 
-                                     ad_initial_verified_cas, &data);
+                                     KRB5_AUTHDATA_INITIAL_VERIFIED_CAS,
+                                     &data);
     krb5_data_free(&data);
     return ret;
 }
index 0c7021f87f42e469276debac220d808e6b4b8fed..14e9793fdc0e741e0a59e75a326a803b0241d0db 100644 (file)
@@ -1,4 +1,4 @@
--- $Id: k5.asn1 21004 2007-06-08 01:53:10Z lha $
+-- $Id: k5.asn1 21092 2007-06-15 19:47:46Z lha $
 
 KERBEROS5 DEFINITIONS ::=
 BEGIN
@@ -88,6 +88,7 @@ AUTHDATA-TYPE ::= INTEGER {
        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),
index fe488eb904e8b1070fa18ca308eab1fc14ab844b..d628e4696f5d7caf68d2fcc4aa105bc6d2d122fe 100644 (file)
@@ -1,6 +1,5 @@
-#include "config.h"
 
-#line 3 "lex.yy.c"
+#line 3 "lex.c"
 
 #define  YY_INT_ALIGNED short int
 
@@ -343,6 +342,9 @@ FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
 typedef int yy_state_type;
 
 extern int yylineno;
+
+int yylineno = 1;
+
 extern char *yytext;
 #define yytext_ptr yytext
 
@@ -824,7 +826,7 @@ char *yytext;
  * SUCH DAMAGE. 
  */
 
-/* $Id: lex.l,v 1.31 2006/10/21 11:57:22 lha Exp $ */
+/* $Id: lex.l 18738 2006-10-21 11:57:22Z lha $ */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -849,7 +851,7 @@ static unsigned lineno = 1;
 static void unterminated(const char *, unsigned);
 
 /* This is for broken old lexes (solaris 10 and hpux) */
-#line 852 "lex.yy.c"
+#line 855 "lex.c"
 
 #define INITIAL 0
 
@@ -1004,7 +1006,7 @@ YY_DECL
     
 #line 68 "lex.l"
 
-#line 1007 "lex.yy.c"
+#line 1010 "lex.c"
 
        if ( !(yy_init) )
                {
@@ -1673,7 +1675,7 @@ YY_RULE_SETUP
 #line 274 "lex.l"
 ECHO;
        YY_BREAK
-#line 1676 "lex.yy.c"
+#line 1679 "lex.c"
 case YY_STATE_EOF(INITIAL):
        yyterminate();
 
@@ -2483,6 +2485,15 @@ static void yy_fatal_error (yyconst char* msg )
 
 /* Accessor  methods (get/set functions) to struct members. */
 
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+        
+    return yylineno;
+}
+
 /** Get the input stream.
  * 
  */
@@ -2516,6 +2527,16 @@ char *yyget_text  (void)
         return yytext;
 }
 
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void yyset_lineno (int  line_number )
+{
+    
+    yylineno = line_number;
+}
+
 /** Set the input stream. This does not discard the current
  * input buffer.
  * @param in_str A readable stream.
index e89a7217af5f9737726b5dfd3237c317e6bac5a2..1bfc11ad740f362539094b45307fdec0388a2c3e 100644 (file)
@@ -34,8 +34,6 @@ MS-UPN-SAN ::= UTF8String
 pa-pk-as-req INTEGER ::=                  16
 pa-pk-as-rep INTEGER ::=                  17
 
-ad-initial-verified-cas INTEGER ::=        9
-
 td-trusted-certifiers INTEGER ::=        104
 td-invalid-certificates INTEGER ::=      105
 td-dh-parameters INTEGER ::=             109
@@ -160,7 +158,7 @@ KDCDHKeyInfo-Win2k ::= SEQUENCE {
 
 ReplyKeyPack-Win2k ::= SEQUENCE {
         replyKey                [0] EncryptionKey,
-        nonce                   [1] INTEGER (0..4294967295),
+        nonce                   [1] INTEGER (-2147483648..2147483647),
        ...
 }
 
index 83f1f309a423b1470a9fe32437e3dc753eecd405..c5af2ead5c47715437a061beda9b2167e30c7e31 100644 (file)
@@ -1,6 +1,5 @@
-#include "config.h"
 
-#line 3 "lex.yy.c"
+#line 3 "lex.c"
 
 #define  YY_INT_ALIGNED short int
 
@@ -343,6 +342,9 @@ FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0;
 typedef int yy_state_type;
 
 extern int yylineno;
+
+int yylineno = 1;
+
 extern char *yytext;
 #define yytext_ptr yytext
 
@@ -521,7 +523,7 @@ char *yytext;
 #include "parse.h"
 #include "lex.h"
 
-RCSID("$Id: lex.l,v 1.8 2005/05/16 08:52:54 lha Exp $");
+RCSID("$Id: lex.l 15143 2005-05-16 08:52:54Z lha $");
 
 static unsigned lineno = 1;
 static int getstring(void);
@@ -530,7 +532,7 @@ static int getstring(void);
 
 #undef ECHO
 
-#line 533 "lex.yy.c"
+#line 536 "lex.c"
 
 #define INITIAL 0
 
@@ -685,7 +687,7 @@ YY_DECL
     
 #line 59 "lex.l"
 
-#line 688 "lex.yy.c"
+#line 691 "lex.c"
 
        if ( !(yy_init) )
                {
@@ -849,7 +851,7 @@ YY_RULE_SETUP
 #line 75 "lex.l"
 ECHO;
        YY_BREAK
-#line 852 "lex.yy.c"
+#line 855 "lex.c"
 case YY_STATE_EOF(INITIAL):
        yyterminate();
 
@@ -1659,6 +1661,15 @@ static void yy_fatal_error (yyconst char* msg )
 
 /* Accessor  methods (get/set functions) to struct members. */
 
+/** Get the current line number.
+ * 
+ */
+int yyget_lineno  (void)
+{
+        
+    return yylineno;
+}
+
 /** Get the input stream.
  * 
  */
@@ -1692,6 +1703,16 @@ char *yyget_text  (void)
         return yytext;
 }
 
+/** Set the current line number.
+ * @param line_number
+ * 
+ */
+void yyset_lineno (int  line_number )
+{
+    
+    yylineno = line_number;
+}
+
 /** Set the input stream. This does not discard the current
  * input buffer.
  * @param in_str A readable stream.
index 42b57cdadddc16efe951620fa909566d79235585..d5c70636bc5824f9834fa8232494d460e65c4765 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "krb5/gsskrb5_locl.h"
 
-RCSID("$Id: acquire_cred.c 20688 2007-05-17 18:44:31Z lha $");
+RCSID("$Id: acquire_cred.c 21221 2007-06-20 08:42:10Z lha $");
 
 OM_uint32
 __gsskrb5_ccache_lifetime(OM_uint32 *minor_status,
@@ -256,8 +256,8 @@ static OM_uint32 acquire_acceptor_cred
        if (kret)
            goto end;
        krb5_kt_free_entry(context, &entry);
+       ret = GSS_S_COMPLETE;
     }
-    ret = GSS_S_COMPLETE;
  
 end:
     if (ret != GSS_S_COMPLETE) {
index 93fac8d67b57d01185b1852eda4ec78f009d5d74..727c447d2a0630e0bfe1fd480de39992f8374b9c 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "krb5/gsskrb5_locl.h"
 
-RCSID("$Id: display_name.c 19031 2006-11-13 18:02:57Z lha $");
+RCSID("$Id: display_name.c 21077 2007-06-12 22:42:56Z lha $");
 
 OM_uint32 _gsskrb5_display_name
            (OM_uint32 * minor_status,
@@ -50,7 +50,8 @@ OM_uint32 _gsskrb5_display_name
 
     GSSAPI_KRB5_INIT (&context);
 
-    kret = krb5_unparse_name (context, name, &buf);
+    kret = krb5_unparse_name_flags (context, name,
+                                   KRB5_PRINCIPAL_UNPARSE_DISPLAY, &buf);
     if (kret) {
        *minor_status = kret;
        return GSS_S_FAILURE;
index 3eb90d279f32ca0ce3b21bcf46e1e06ee63d7c0e..f79c9374a9c7583ebb5bb772776bb952e9613143 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "krb5/gsskrb5_locl.h"
 
-RCSID("$Id: prf.c 20679 2007-05-14 03:12:05Z lha $");
+RCSID("$Id: prf.c 21129 2007-06-18 20:28:44Z lha $");
 
 OM_uint32
 _gsskrb5_pseudo_random(OM_uint32 *minor_status,
@@ -67,6 +67,7 @@ _gsskrb5_pseudo_random(OM_uint32 *minor_status,
     switch(prf_key) {
     case GSS_C_PRF_KEY_FULL:
        _gsskrb5i_get_acceptor_subkey(ctx, context, &key);
+       break;
     case GSS_C_PRF_KEY_PARTIAL:
        _gsskrb5i_get_initiator_subkey(ctx, context, &key);
        break;
index a01a9a2a62b3fbed5bc6d721e98f82e2dd5ed055..80b91930fd37b71832adfed5c07a6f0138add3c5 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "krb5/gsskrb5_locl.h"
 
-RCSID("$Id: release_name.c 19031 2006-11-13 18:02:57Z lha $");
+RCSID("$Id: release_name.c 21128 2007-06-18 20:26:50Z lha $");
 
 OM_uint32 _gsskrb5_release_name
            (OM_uint32 * minor_status,
@@ -43,8 +43,7 @@ OM_uint32 _gsskrb5_release_name
     krb5_context context;
     krb5_principal name = (krb5_principal)*input_name;
 
-    if (minor_status)
-      *minor_status = 0;
+    *minor_status = 0;
 
     GSSAPI_KRB5_INIT (&context);
 
index 1691fd940177a909531c197ff82c42630025911b..e4517bee449cbcb364d4997c7b141ee22a130813 100644 (file)
@@ -1,7 +1,7 @@
 #include "mech/mech_locl.h"
 #include "heim_threads.h"
 
-RCSID("$Id: context.c 19924 2007-01-16 10:17:01Z lha $");
+RCSID("$Id: context.c 21248 2007-06-21 00:45:13Z lha $");
 
 struct mg_thread_ctx {
     gss_OID mech;
@@ -79,7 +79,7 @@ _gss_mg_get_error(const gss_OID mech, OM_uint32 type,
 
     switch (type) {
     case GSS_C_GSS_CODE: {
-       if (value != mg->maj_stat)
+       if (value != mg->maj_stat || mg->maj_error.length == 0)
            break;
        string->value = malloc(mg->maj_error.length);
        string->length = mg->maj_error.length;
@@ -87,7 +87,7 @@ _gss_mg_get_error(const gss_OID mech, OM_uint32 type,
        return GSS_S_COMPLETE;
     }
     case GSS_C_MECH_CODE: {
-       if (value != mg->min_stat)
+       if (value != mg->min_stat || mg->min_error.length == 0)
            break;
        string->value = malloc(mg->min_error.length);
        string->length = mg->min_error.length;
index 8c5f4d0b08e107599c769a1936bff0dfa949a2da..d1e243d8b854a16c47a8ece08b8024e5ca700b5b 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #include "mech_locl.h"
-RCSID("$Id: gss_accept_sec_context.c 20626 2007-05-08 13:56:49Z lha $");
+RCSID("$Id: gss_accept_sec_context.c 21237 2007-06-20 11:21:09Z lha $");
 
 static OM_uint32
 parse_header(const gss_buffer_t input_token, gss_OID mech_oid)
@@ -237,9 +237,7 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status,
                return (major_status);
        }
 
-       if (!src_name) {
-               m->gm_release_name(minor_status, &src_mn);
-       } else {
+       if (src_name && src_mn) {
                /*
                 * Make a new name and mark it as an MN.
                 */
@@ -250,13 +248,15 @@ OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status,
                        return (GSS_S_FAILURE);
                }
                *src_name = (gss_name_t) name;
+       } else if (src_mn) {
+           m->gm_release_name(minor_status, &src_mn);
        }
 
        if (mech_ret_flags & GSS_C_DELEG_FLAG) {
                if (!delegated_cred_handle) {
                        m->gm_release_cred(minor_status, &delegated_mc);
                        *ret_flags &= ~GSS_C_DELEG_FLAG;
-               } else {
+               } else if (delegated_mc) {
                        struct _gss_cred *dcred;
                        struct _gss_mechanism_cred *dmc;
 
index e57e5dd795da242be68cad9993af23bec2d7f1d3..fc10933692cb9f44272cb6290dabe7c4a16fd5af 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #include "mech_locl.h"
-RCSID("$Id: gss_display_name.c 19952 2007-01-17 10:16:15Z lha $");
+RCSID("$Id: gss_display_name.c 21246 2007-06-20 15:25:19Z lha $");
 
 OM_uint32
 gss_display_name(OM_uint32 *minor_status,
@@ -43,6 +43,11 @@ gss_display_name(OM_uint32 *minor_status,
        if (output_name_type)
            *output_name_type = GSS_C_NO_OID;
 
+       if (name == NULL) {
+               *minor_status = 0;
+               return (GSS_S_BAD_NAME);
+       }
+
        /*
         * If we know it, copy the buffer used to import the name in
         * the first place. Otherwise, ask all the MNs in turn if
index c316c26fd764d80cb67569d19b501d5f6d00c3a8..37ded26db690129b03dfd6f3218b3e16db67cb14 100644 (file)
@@ -59,7 +59,7 @@
  */
 
 #include "mech_locl.h"
-RCSID("$Id: gss_display_status.c 20084 2007-01-31 12:12:08Z lha $");
+RCSID("$Id: gss_display_status.c 21247 2007-06-21 00:37:27Z lha $");
 
 static const char *
 calling_error(OM_uint32 v)
@@ -85,7 +85,7 @@ static const char *
 routine_error(OM_uint32 v)
 {
     static const char *msgs[] = {
-       NULL,                   /* 0 */
+       "Function completed successfully",                      /* 0 */
        "An unsupported mechanism was requested",
        "An invalid name was supplied",
        "A supplied name was of an unsupported type",
@@ -109,9 +109,7 @@ routine_error(OM_uint32 v)
 
     v >>= GSS_C_ROUTINE_ERROR_OFFSET;
 
-    if (v == 0)
-       return "";
-    else if (v >= sizeof(msgs)/sizeof(*msgs))
+    if (v >= sizeof(msgs)/sizeof(*msgs))
        return "unknown routine error";
     else
        return msgs[v];
index 3aab0b9bbcd234ddb661b60d8d4693b0c664c6f2..4ff81fdf2df6f29be0dc8c1748d751b5ba0b5dc1 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #include "mech_locl.h"
-RCSID("$Id: gss_duplicate_name.c 19953 2007-01-17 11:16:35Z lha $");
+RCSID("$Id: gss_duplicate_name.c 21219 2007-06-20 08:27:11Z lha $");
 
 OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
     const gss_name_t src_name,
@@ -44,7 +44,7 @@ OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
        /*
         * If this name has a value (i.e. it didn't come from
         * gss_canonicalize_name(), we re-import the thing. Otherwise,
-        * we make an empty name to hold the MN copy.
+        * we make copy of each mech names.
         */
        if (name->gn_value.value) {
                major_status = gss_import_name(minor_status,
@@ -52,6 +52,10 @@ OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
                if (major_status != GSS_S_COMPLETE)
                        return (major_status);
                new_name = (struct _gss_name *) *dest_name;
+               
+               SLIST_FOREACH(mn, &name->gn_mn, gmn_link) {
+                       _gss_find_mn(new_name, mn->gmn_mech_oid);
+               }
        } else {
                new_name = malloc(sizeof(struct _gss_name));
                if (!new_name) {
@@ -59,17 +63,30 @@ OM_uint32 gss_duplicate_name(OM_uint32 *minor_status,
                        return (GSS_S_FAILURE);
                }
                memset(new_name, 0, sizeof(struct _gss_name));
-               SLIST_INIT(&name->gn_mn);
+               SLIST_INIT(&new_name->gn_mn);
                *dest_name = (gss_name_t) new_name;
-       }
+               
+               SLIST_FOREACH(mn, &name->gn_mn, gmn_link) {
+                       struct _gss_mechanism_name *new_mn;
+                       
+                       new_mn = malloc(sizeof(*new_mn));
+                       if (!new_mn) {
+                               *minor_status = ENOMEM;
+                               return GSS_S_FAILURE;
+                       }
+                       new_mn->gmn_mech = mn->gmn_mech;
+                       new_mn->gmn_mech_oid = mn->gmn_mech_oid;
+                       
+                       major_status = 
+                           mn->gmn_mech->gm_duplicate_name(minor_status,
+                               mn->gmn_name, &new_mn->gmn_name);
+                       if (major_status != GSS_S_COMPLETE) {
+                               free(new_mn);
+                               continue;
+                       }
+                       SLIST_INSERT_HEAD(&new_name->gn_mn, new_mn, gmn_link);
+               }
 
-       /*
-        * Import the new name into any mechanisms listed in the
-        * original name. We could probably get away with only doing
-        * this if the original was canonical.
-        */
-       SLIST_FOREACH(mn, &name->gn_mn, gmn_link) {
-               _gss_find_mn(new_name, mn->gmn_mech_oid);
        }
 
        return (GSS_S_COMPLETE);
index 5cce30c6bd86a28226f93fc8a95207dd437f238b..d45baac6027c3f54630ed0e3d6e404e1c3d94b86 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #include "mech_locl.h"
-RCSID("$Id: gss_inquire_context.c 19958 2007-01-17 13:56:18Z lha $");
+RCSID("$Id: gss_inquire_context.c 21125 2007-06-18 20:11:07Z lha $");
 
 OM_uint32
 gss_inquire_context(OM_uint32 *minor_status,
@@ -79,7 +79,8 @@ gss_inquire_context(OM_uint32 *minor_status,
        if (src_name) {
                name = _gss_make_name(m, src_mn);
                if (!name) {
-                       *mech_type = GSS_C_NO_OID;
+                       if (mech_type)
+                               *mech_type = GSS_C_NO_OID;
                        m->gm_release_name(minor_status, &src_mn);
                        *minor_status = 0;
                        return (GSS_S_FAILURE);
@@ -90,8 +91,10 @@ gss_inquire_context(OM_uint32 *minor_status,
        if (targ_name) {
                name = _gss_make_name(m, targ_mn);
                if (!name) {
-                       *mech_type = GSS_C_NO_OID;
-                       gss_release_name(minor_status, src_name);
+                       if (mech_type)
+                               *mech_type = GSS_C_NO_OID;
+                       if (src_name)
+                               gss_release_name(minor_status, src_name);
                        m->gm_release_name(minor_status, &targ_mn);
                        *minor_status = 0;
                        return (GSS_S_FAILURE);
index a4ace9e9e93e3d200e87e0bb5eaf8e38960451ee..aa83efb0c285c3145965a2eb446d17e7aec7c573 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #include "mech_locl.h"
-RCSID("$Id: gss_inquire_cred_by_mech.c 19960 2007-01-17 15:09:24Z lha $");
+RCSID("$Id: gss_inquire_cred_by_mech.c 21124 2007-06-18 20:08:24Z lha $");
 
 OM_uint32
 gss_inquire_cred_by_mech(OM_uint32 *minor_status,
@@ -78,12 +78,16 @@ gss_inquire_cred_by_mech(OM_uint32 *minor_status,
                return (major_status);
        }
 
-       name = _gss_make_name(m, mn);
-       if (!name) {
+       if (cred_name) {
+           name = _gss_make_name(m, mn);
+           if (!name) {
                m->gm_release_name(minor_status, &mn);
                return (GSS_S_NO_CRED);
-       }
+           }
+           *cred_name = (gss_name_t) name;
+       } else
+           m->gm_release_name(minor_status, &mn);
+
 
-       *cred_name = (gss_name_t) name;
        return (GSS_S_COMPLETE);
 }
index 2500928baf31935da3da57fb5dc94302d2e1aac2..9e77f429828e1be63a73be0cb212adff807253c3 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #include "mech_locl.h"
-RCSID("$Id: gss_krb5.c 20383 2007-04-18 08:49:53Z lha $");
+RCSID("$Id: gss_krb5.c 21123 2007-06-18 20:05:26Z lha $");
 
 #include <krb5.h>
 #include <roken.h>
@@ -650,7 +650,7 @@ gsskrb5_extract_authz_data_from_sec_context(OM_uint32 *minor_status,
     if (der_put_oid((unsigned char *)oid_flat.elements + oid_flat.length - 1, 
                    oid_flat.length, &oid, &size) != 0) {
        free(oid.components);
-
+       free(oid_flat.elements);
        *minor_status = EINVAL;
        return GSS_S_FAILURE;
     }
index 78c8cc79c105500ab1bc413517144a42639b45ff..c32291396f175a7c7127a69a2ca2b4d35ae413aa 100644 (file)
@@ -31,7 +31,7 @@
  */
 
 #include "mech_locl.h"
-RCSID("$Id: gss_set_cred_option.c 20626 2007-05-08 13:56:49Z lha $");
+RCSID("$Id: gss_set_cred_option.c 21126 2007-06-18 20:19:59Z lha $");
 
 OM_uint32
 gss_set_cred_option (OM_uint32 *minor_status,
@@ -64,7 +64,9 @@ gss_set_cred_option (OM_uint32 *minor_status,
 
                        mc = malloc(sizeof(*mc));
                        if (mc == NULL) {
-                           /* XXX free the other mc's */
+                           *cred_handle = (gss_cred_id_t)cred;
+                           gss_release_cred(minor_status, cred_handle);
+                           *minor_status = ENOMEM;
                            return GSS_S_FAILURE;
                        }
 
index 106897b9b09832b3a1b29e3b59e5f711b92feeb0..d20c913bf016d86ab016f337073727b29c4400b8 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "spnego/spnego_locl.h"
 
-RCSID("$Id: accept_sec_context.c 20929 2007-06-05 21:19:22Z lha $");
+RCSID("$Id: accept_sec_context.c 21243 2007-06-20 15:16:22Z lha $");
 
 static OM_uint32
 send_reject (OM_uint32 *minor_status,
@@ -540,12 +540,12 @@ acceptor_start
            gss_cred_id_t *delegated_cred_handle
           )
 {
-    OM_uint32 ret, ret2, minor;
-    NegTokenInit ni;
-    size_t ni_len;
+    OM_uint32 ret, junk, minor;
+    NegotiationToken nt;
+    size_t nt_len;
+    NegTokenInit *ni;
     int i;
     gss_buffer_desc data;
-    size_t len, taglen;
     gss_buffer_t mech_input_token = GSS_C_NO_BUFFER;
     gss_buffer_desc mech_output_token;
     gss_buffer_desc mech_buf;
@@ -555,6 +555,9 @@ acceptor_start
     int get_mic = 0;
     int first_ok = 0;
 
+    if (src_name)
+       *src_name = GSS_C_NO_NAME;
+
     mech_output_token.value = NULL;
     mech_output_token.length = 0;
     mech_buf.value = NULL;
@@ -582,39 +585,30 @@ acceptor_start
     if (ret)
        return ret;
 
-    ret = der_match_tag_and_length(data.value, data.length,
-                                  ASN1_C_CONTEXT, CONS,
-                                  0,
-                                  &len, &taglen);
+    ret = decode_NegotiationToken(data.value, data.length, &nt, &nt_len);
+    gss_release_buffer(minor_status, &data);
     if (ret) {
        *minor_status = ret;
-       return GSS_S_FAILURE;
-    }
-
-    if (len > data.length - taglen) {
-       *minor_status = ASN1_OVERRUN;
-       return GSS_S_FAILURE;
+       return GSS_S_DEFECTIVE_TOKEN;
     }
-
-    ret = decode_NegTokenInit((const unsigned char *)data.value + taglen, 
-                                 len, &ni, &ni_len);
-    if (ret) {
-       *minor_status = ret;
+    if (nt.element != choice_NegotiationToken_negTokenInit) {
+       *minor_status = 0;
        return GSS_S_DEFECTIVE_TOKEN;
     }
+    ni = &nt.u.negTokenInit;
 
-    if (ni.mechTypes.len < 1) {
-       free_NegTokenInit(&ni);
+    if (ni->mechTypes.len < 1) {
+       free_NegotiationToken(&nt);
        *minor_status = 0;
        return GSS_S_DEFECTIVE_TOKEN;
     }
 
     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
 
-    ret = copy_MechTypeList(&ni.mechTypes, &ctx->initiator_mech_types);
+    ret = copy_MechTypeList(&ni->mechTypes, &ctx->initiator_mech_types);
     if (ret) {
        HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
-       free_NegTokenInit(&ni);
+       free_NegotiationToken(&nt);
        *minor_status = ret;
        return GSS_S_FAILURE;
     }
@@ -627,17 +621,17 @@ acceptor_start
      */
 
     ret = select_mech(minor_status,
-                     &ni.mechTypes.val[0], 
+                     &ni->mechTypes.val[0], 
                      0,
                      &preferred_mech_type);
 
-    if (ret == 0 && ni.mechToken != NULL) {
+    if (ret == 0 && ni->mechToken != NULL) {
        gss_cred_id_t mech_delegated_cred = GSS_C_NO_CREDENTIAL;
        gss_cred_id_t mech_cred;
        gss_buffer_desc ibuf;
 
-       ibuf.length = ni.mechToken->length;
-       ibuf.value = ni.mechToken->data;
+       ibuf.length = ni->mechToken->length;
+       ibuf.value = ni->mechToken->data;
        mech_input_token = &ibuf;
 
        if (acceptor_cred != NULL)
@@ -668,12 +662,12 @@ acceptor_start
            if (ret == GSS_S_COMPLETE)
                ctx->open = 1;
 
-           if (delegated_cred_handle)
+           if (mech_delegated_cred && delegated_cred_handle)
                ret = _gss_spnego_alloc_cred(minor_status,
                                             mech_delegated_cred,
                                             delegated_cred_handle);
            else
-               gss_release_cred(&ret2, &mech_delegated_cred);
+               gss_release_cred(&junk, &mech_delegated_cred);
 
            ret = acceptor_complete(minor_status,
                                    ctx,
@@ -681,7 +675,7 @@ acceptor_start
                                    &mech_buf,
                                    mech_input_token,
                                    &mech_output_token,
-                                   ni.mechListMIC,
+                                   ni->mechListMIC,
                                    output_token);
            if (ret != GSS_S_COMPLETE)
                goto out;
@@ -697,9 +691,9 @@ acceptor_start
     if (!first_ok) {
 
        /* Call glue layer to find first mech we support */
-       for (i = 1; i < ni.mechTypes.len; ++i) {
+       for (i = 1; i < ni->mechTypes.len; ++i) {
            ret = select_mech(minor_status,
-                             &ni.mechTypes.val[i],
+                             &ni->mechTypes.val[i],
                              1,
                              &preferred_mech_type);
            if (ret == 0)
@@ -707,7 +701,7 @@ acceptor_start
        }
        if (preferred_mech_type == GSS_C_NO_OID) {
            HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
-           free_NegTokenInit(&ni);
+           free_NegotiationToken(&nt);
            return GSS_S_BAD_MECH;
        }
 
@@ -735,7 +729,8 @@ out:
        free(mech_buf.value);
        mech_buf.value = NULL;
     }
-    free_NegTokenInit(&ni);
+    free_NegotiationToken(&nt);
+
 
     if (ret == GSS_S_COMPLETE) {
        if (src_name != NULL && ctx->mech_src_name != NULL) {
@@ -746,8 +741,7 @@ out:
                name->mech = ctx->mech_src_name;
                ctx->mech_src_name = NULL;
                *src_name = (gss_name_t)name;
-           } else
-               *src_name = GSS_C_NO_NAME;
+           }
        }
         if (delegated_cred_handle != NULL) {
            *delegated_cred_handle = ctx->delegated_cred_id;
@@ -790,10 +784,9 @@ acceptor_continue
           )
 {
     OM_uint32 ret, ret2, minor;
-    NegTokenResp na;
-    size_t na_len;
-    gss_buffer_desc data;
-    size_t len, taglen;
+    NegotiationToken nt;
+    size_t nt_len;
+    NegTokenResp *na;
     unsigned int negResult = accept_incomplete;
     gss_buffer_t mech_input_token = GSS_C_NO_BUFFER;
     gss_buffer_t mech_output_token = GSS_C_NO_BUFFER;
@@ -810,45 +803,34 @@ acceptor_continue
      * context token (negTokenInit).
      */
 
-    data.value  = input_token_buffer->value;
-    data.length = input_token_buffer->length;
-
-    ret = der_match_tag_and_length(data.value, data.length,
-                                  ASN1_C_CONTEXT, CONS,
-                                  1,
-                                  &len, &taglen);
+    ret = decode_NegotiationToken(input_token_buffer->value, 
+                                 input_token_buffer->length,
+                                 &nt, &nt_len);
     if (ret) {
        *minor_status = ret;
-       return GSS_S_FAILURE;
-    }
-
-    if (len > data.length - taglen) {
-       *minor_status = ASN1_OVERRUN;
-       return GSS_S_FAILURE;
+       return GSS_S_DEFECTIVE_TOKEN;
     }
-
-    ret = decode_NegTokenResp((const unsigned char *)data.value + taglen, 
-                             len, &na, &na_len);
-    if (ret) {
-       *minor_status = ret;
+    if (nt.element != choice_NegotiationToken_negTokenResp) {
+       *minor_status = 0;
        return GSS_S_DEFECTIVE_TOKEN;
     }
+    na = &nt.u.negTokenResp;
 
-    if (na.negResult != NULL) {
-       negResult = *(na.negResult);
+    if (na->negResult != NULL) {
+       negResult = *(na->negResult);
     }
 
     HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
 
     {
        gss_buffer_desc ibuf, obuf;
-       int require_mic, get_mic;
+       int require_mic, get_mic = 0;
        int require_response;
        heim_octet_string *mic;
 
-       if (na.responseToken != NULL) {
-           ibuf.length = na.responseToken->length;
-           ibuf.value = na.responseToken->data;
+       if (na->responseToken != NULL) {
+           ibuf.length = na->responseToken->length;
+           ibuf.value = na->responseToken->data;
            mech_input_token = &ibuf;
        } else {
            ibuf.value = NULL;
@@ -901,7 +883,7 @@ acceptor_continue
                mech_output_token = &obuf;
            }
            if (ret != GSS_S_COMPLETE && ret != GSS_S_CONTINUE_NEEDED) {
-               free_NegTokenResp(&na);
+               free_NegotiationToken(&nt);
                send_reject (minor_status, output_token);
                HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
                return ret;
@@ -919,7 +901,7 @@ acceptor_continue
 
        ctx->require_mic = require_mic;
 
-       mic = na.mechListMIC;
+       mic = na->mechListMIC;
        if (mic != NULL)
            require_mic = 1;
 
@@ -930,7 +912,7 @@ acceptor_continue
                                    &mech_buf,
                                    mech_input_token,
                                    mech_output_token,
-                                   na.mechListMIC,
+                                   na->mechListMIC,
                                    output_token);
 
        if (ctx->mech_flags & GSS_C_DCE_STYLE)
@@ -964,16 +946,19 @@ acceptor_continue
            gss_release_buffer(&minor, mech_output_token);
        if (mech_buf.value != NULL)
            free(mech_buf.value);
-       free_NegTokenResp(&na);
+       free_NegotiationToken(&nt);
     }
 
     if (ret == GSS_S_COMPLETE) {
-       if (src_name != NULL) {
-           ret2 = gss_duplicate_name(minor_status,
-                                     ctx->mech_src_name,
-                                     src_name);
-           if (ret2 != GSS_S_COMPLETE)
-               ret = ret2;
+       if (src_name != NULL && ctx->mech_src_name != NULL) {
+           spnego_name name;
+
+           name = calloc(1, sizeof(*name));
+           if (name) {
+               name->mech = ctx->mech_src_name;
+               ctx->mech_src_name = NULL;
+               *src_name = (gss_name_t)name;
+           }
        }
         if (delegated_cred_handle != NULL) {
            *delegated_cred_handle = ctx->delegated_cred_id;
index dcfbdfad424c49c5d16b4ed333f649e900382ea9..b43fe571d6c8ea8b606f6fc88f78905d64cbabc6 100644 (file)
@@ -35,7 +35,7 @@
 #include <config.h>
 #endif
 
-RCSID("$Id: pkcs12.c 20661 2007-05-10 21:57:58Z lha $");
+RCSID("$Id: pkcs12.c 21155 2007-06-18 21:59:44Z lha $");
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -93,8 +93,11 @@ PKCS12_key_gen(const void *key, size_t keylen,
     while (1) {
        BIGNUM *bnB, *bnOne;
 
-       if (!EVP_DigestInit_ex(&ctx, md, NULL))
+       if (!EVP_DigestInit_ex(&ctx, md, NULL)) {
+           free(I);
+           free(v);
            return 0;
+       }
        for (i = 0; i < vlen; i++)
            EVP_DigestUpdate(&ctx, &idc, 1);
        EVP_DigestUpdate(&ctx, I, size_I);
index d1b024b535dbbef350113c425aec133c6868bb6c..497a3ab5f805bc338b4d311e705276eccc8f16d7 100644 (file)
@@ -35,7 +35,7 @@
 #include <config.h>
 #endif
 
-RCSID("$Id: rand-egd.c 20093 2007-01-31 12:44:28Z lha $");
+RCSID("$Id: rand-egd.c 21156 2007-06-18 22:00:59Z lha $");
 
 #include <sys/types.h>
 #ifdef HAVE_SYS_UN_H
@@ -255,7 +255,7 @@ RAND_egd_bytes(const char *filename, int size)
 
     RAND_seed(data, size);
 
-    memset(data, 0, sizeof(data));
+    memset(data, 0, size);
     free(data);
 
     return 1;
index 6cc4267c1342de9acf0c77ca24c9e40dd2d12a81..1d47ed49cc3521649cfef5c7c789a45659e2405b 100644 (file)
@@ -33,7 +33,7 @@
 #include <config.h>
 #endif
 
-RCSID("$Id: rand-fortuna.c 20029 2007-01-21 09:55:42Z lha $");
+RCSID("$Id: rand-fortuna.c 21196 2007-06-20 05:08:58Z lha $");
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -427,6 +427,8 @@ extract_data(FState * st, unsigned count, unsigned char *dst)
 static FState  main_state;
 static int     init_done;
 static int     have_entropy;
+#define FORTUNA_RESEED_BYTE    10000
+static unsigned        resend_bytes;
 
 /*
  * Try our best to do an inital seed
@@ -472,6 +474,35 @@ fortuna_reseed(void)
            memset(buf, 0, sizeof(buf));
        }
     }
+    /*
+     * Fall back to gattering data from timer and secret files, this
+     * is really the last resort.
+     */
+    if (!entropy_p) {
+       /* to save stackspace */
+       union {
+           unsigned char buf[INIT_BYTES];
+           unsigned char shad[1001];
+       } u;
+       int fd;
+
+       /* add timer info */
+       if ((*hc_rand_timer_method.bytes)(u.buf, sizeof(u.buf)) == 1)
+           add_entropy(&main_state, u.buf, sizeof(u.buf));
+       /* add /etc/shadow */
+       fd = open("/etc/shadow", O_RDONLY, 0);
+       if (fd >= 0) {
+           ssize_t n;
+           /* add_entropy will hash the buf */
+           while ((n = read(fd, (char *)u.shad, sizeof(u.shad))) > 0)
+               add_entropy(&main_state, u.shad, sizeof(u.shad));
+           close(fd);
+       }
+
+       memset(&u, 0, sizeof(u));
+
+       entropy_p = 1; /* sure about this ? */
+    }
     {
        pid_t pid = getpid();
        add_entropy(&main_state, (void *)&pid, sizeof(pid));
@@ -517,6 +548,11 @@ fortuna_bytes(unsigned char *outdata, int size)
 {
     if (!fortuna_init())
        return 0;
+    resend_bytes += size;
+    if (resend_bytes > FORTUNA_RESEED_BYTE || resend_bytes < size) {
+       resend_bytes = 0;
+       fortuna_reseed();
+    }
     extract_data(&main_state, size, outdata);
     return 1;
 }
diff --git a/source4/heimdal/lib/hcrypto/rand-timer.c b/source4/heimdal/lib/hcrypto/rand-timer.c
new file mode 100644 (file)
index 0000000..67a77b0
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1995, 1996, 1997, 1999, 2007 Kungliga Tekniska Högskolan
+ * (Royal Institute of Technology, Stockholm, Sweden). 
+ * All rights reserved. 
+ *
+ * Redistribution and use in source and binary forms, with or without 
+ * modification, are permitted provided that the following conditions 
+ * are met: 
+ *
+ * 1. Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer. 
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright 
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the distribution. 
+ *
+ * 3. Neither the name of the Institute nor the names of its contributors 
+ *    may be used to endorse or promote products derived from this software 
+ *    without specific prior written permission. 
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
+ * SUCH DAMAGE. 
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+RCSID("$Id$");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <rand.h>
+
+#include <roken.h>
+
+#include "randi.h"
+
+#ifndef WIN32 /* don't bother with this on windows */
+
+static volatile int counter;
+static volatile unsigned char *gdata; /* Global data */
+static volatile int igdata;    /* Index into global data */
+static int gsize;
+
+static
+RETSIGTYPE
+sigALRM(int sig)
+{
+    if (igdata < gsize)
+       gdata[igdata++] ^= counter & 0xff;
+
+#ifndef HAVE_SIGACTION
+    signal(SIGALRM, sigALRM); /* Reinstall SysV signal handler */
+#endif
+    SIGRETURN(0);
+}
+
+#ifndef HAVE_SETITIMER
+static void
+pacemaker(struct timeval *tv)
+{
+    fd_set fds;
+    pid_t pid;
+    pid = getppid();
+    while(1){
+       FD_ZERO(&fds);
+       FD_SET(0, &fds);
+       select(1, &fds, NULL, NULL, tv);
+       kill(pid, SIGALRM);
+    }
+}
+#endif
+
+#ifdef HAVE_SIGACTION
+/* XXX ugly hack, should perhaps use function from roken */
+static RETSIGTYPE 
+(*fake_signal(int sig, RETSIGTYPE (*f)(int)))(int)
+{
+    struct sigaction sa, osa;
+    sa.sa_handler = f;
+    sa.sa_flags = 0;
+    sigemptyset(&sa.sa_mask);
+    sigaction(sig, &sa, &osa);
+    return osa.sa_handler;
+}
+#define signal(S, F) fake_signal((S), (F))
+#endif
+
+#endif /* WIN32*/
+
+/*
+ *
+ */
+
+static void
+timer_seed(const void *indata, int size)
+{
+}
+
+static int 
+timer_bytes(unsigned char *outdata, int size)
+{
+#ifdef WIN32
+    return 0;
+#else /* WIN32 */
+    struct itimerval tv, otv;
+    RETSIGTYPE (*osa)(int);
+    int i, j;
+#ifndef HAVE_SETITIMER 
+    RETSIGTYPE (*ochld)(int);
+    pid_t pid;
+#endif
+
+    gdata = outdata;
+    gsize = size;
+    igdata = 0;
+
+    osa = signal(SIGALRM, sigALRM);
+  
+    /* Start timer */
+    tv.it_value.tv_sec = 0;
+    tv.it_value.tv_usec = 10 * 1000; /* 10 ms */
+    tv.it_interval = tv.it_value;
+#ifdef HAVE_SETITIMER
+    setitimer(ITIMER_REAL, &tv, &otv);
+#else
+    ochld = signal(SIGCHLD, SIG_IGN);
+    pid = fork();
+    if(pid == -1){
+       signal(SIGCHLD, ochld != SIG_ERR ? ochld : SIG_DFL);
+       des_not_rand_data(data, size);
+       return;
+    }
+    if(pid == 0)
+       pacemaker(&tv.it_interval);
+#endif
+
+    for(i = 0; i < 4; i++) {
+       for (igdata = 0; igdata < size;) /* igdata++ in sigALRM */
+           counter++;
+       for (j = 0; j < size; j++) /* Only use 2 bits each lap */
+           gdata[j] = (gdata[j]>>2) | (gdata[j]<<6);
+    }
+#ifdef HAVE_SETITIMER
+    setitimer(ITIMER_REAL, &otv, 0);
+#else
+    kill(pid, SIGKILL);
+    while(waitpid(pid, NULL, 0) != pid);
+    signal(SIGCHLD, ochld != SIG_ERR ? ochld : SIG_DFL);
+#endif
+    signal(SIGALRM, osa != SIG_ERR ? osa : SIG_DFL);
+
+    return 1;
+#endif
+}
+
+static void
+timer_cleanup(void)
+{
+}
+
+static void
+timer_add(const void *indata, int size, double entropi)
+{
+}
+
+static int
+timer_pseudorand(unsigned char *outdata, int size)
+{
+    return timer_bytes(outdata, size);
+}
+
+static int
+timer_status(void)
+{
+#ifdef WIN32
+    return 0;
+#else
+    return 1;
+#endif
+}
+
+const RAND_METHOD hc_rand_timer_method = {
+    timer_seed,
+    timer_bytes,
+    timer_cleanup,
+    timer_add,
+    timer_pseudorand,
+    timer_status
+};
+
+const RAND_METHOD *
+RAND_timer_method(void)
+{
+    return &hc_rand_timer_method;
+}
index 29f2d46dba930371a80243b44f66513a96c49cd2..248fdde620845ee583555c29afee3061edb07684 100644 (file)
@@ -35,7 +35,7 @@
 #include <config.h>
 #endif
 
-RCSID("$Id: rand.c 20126 2007-02-01 22:08:41Z lha $");
+RCSID("$Id: rand.c 21198 2007-06-20 05:10:41Z lha $");
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -56,11 +56,7 @@ init_method(void)
 {
     if (selected_meth != NULL)
        return;
-
-    if ((*hc_rand_unix_method.status)() == 1)
-       selected_meth = &hc_rand_unix_method;
-    else
-       selected_meth = &hc_rand_fortuna_method;
+    selected_meth = &hc_rand_fortuna_method;
 }
 
 void
index b9b9b5309c0042a5f7a7d2c49c67916fffe51d72..6ae75f262b38b5a54f01fd87611f72f99d8952f3 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 /*
- * $Id: randi.h 20027 2007-01-21 09:54:00Z lha $
+ * $Id: randi.h 21101 2007-06-18 03:53:46Z lha $
  */
 
 #ifndef _HEIM_RANDI_H
@@ -41,5 +41,8 @@
 extern const RAND_METHOD hc_rand_fortuna_method;
 extern const RAND_METHOD hc_rand_unix_method;
 extern const RAND_METHOD hc_rand_egd_method;
+extern const RAND_METHOD hc_rand_timer_method;
+
+const RAND_METHOD * RAND_timer_method(void);
 
 #endif /* _HEIM_RANDI_H */
index e05ead1e666ae8463ce3362a214dab903b47d1e1..74093ff7ba0e5e879ad8556e043297168b7eafe2 100644 (file)
@@ -35,7 +35,7 @@
 #include <config.h>
 #endif
 
-RCSID("$Id: rsa-imath.c 19750 2007-01-06 13:45:25Z lha $");
+RCSID("$Id: rsa-imath.c 21154 2007-06-18 21:58:12Z lha $");
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -180,7 +180,6 @@ imath_rsa_public_encrypt(int flen, const unsigned char* from,
     }
 
     padlen = size - flen - 3;
-    assert(padlen >= 8);
 
     *p++ = 2;
     if (RAND_bytes(p, padlen) != 1) {
index aac0ff5367078a70aa7c97593e045c64480ea441..5f60999946b819b99e78f9cd0c2fdc5fc8e68d62 100644 (file)
@@ -34,7 +34,7 @@
 #include "hdb_locl.h"
 #include <der.h>
 
-RCSID("$Id: ext.c 20236 2007-02-16 23:52:29Z lha $");
+RCSID("$Id: ext.c 21113 2007-06-18 12:59:32Z lha $");
 
 krb5_error_code
 hdb_entry_check_mandatory(krb5_context context, const hdb_entry *ent)
@@ -268,6 +268,7 @@ hdb_entry_get_password(krb5_context context, HDB *db,
                       const hdb_entry *entry, char **p)
 {
     HDB_extension *ext;
+    char *str;
     int ret;
 
     ext = hdb_find_extension(entry, choice_HDB_extension_data_password);
@@ -314,7 +315,14 @@ hdb_entry_get_password(krb5_context context, HDB *db,
        }
        return 0;
     }
-    krb5_set_error_string(context, "password attribute not found");
+
+    ret = krb5_unparse_name(context, entry->principal, &str);
+    if (ret == 0) {
+       krb5_set_error_string(context, "no password attributefor %s", str);
+       free(str);
+    } else 
+       krb5_clear_error_string(context);
+
     return ENOENT;
 }
 
index 27b17a02049147e51674e5de6cc5477e607aeae7..caf163f8e4b7918deeed09b60dce332a1468c897 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id: cert.c 20915 2007-06-05 03:58:56Z lha $");
+RCSID("$Id: cert.c 21294 2007-06-25 14:37:15Z lha $");
 #include "crypto-headers.h"
 #include <rtbl.h>
 
@@ -43,6 +43,7 @@ struct hx509_verify_ctx_data {
 #define HX509_VERIFY_CTX_F_ALLOW_PROXY_CERTIFICATE     2
 #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
     time_t time_now;
     unsigned int max_depth;
 #define HX509_VERIFY_MAX_DEPTH 30
@@ -51,6 +52,7 @@ struct hx509_verify_ctx_data {
 
 #define REQUIRE_RFC3280(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_REQUIRE_RFC3280)
 #define CHECK_TA(ctx) ((ctx)->flags & HX509_VERIFY_CTX_F_CHECK_TRUST_ANCHORS)
+#define ALLOW_DEF_TA(ctx) (((ctx)->flags & HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS) == 0)
 
 struct _hx509_cert_attrs {
     size_t len;
@@ -76,22 +78,6 @@ typedef struct hx509_name_constraints {
 #define GeneralSubtrees_SET(g,var) \
        (g)->len = (var)->len, (g)->val = (var)->val;
 
-/*
- *
- */
-
-void
-_hx509_abort(const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    vprintf(fmt, ap);
-    va_end(ap);
-    printf("\n");
-    fflush(stdout);
-    abort();
-}
-
 /*
  *
  */
@@ -227,7 +213,34 @@ hx509_cert_init(hx509_context context, const Certificate *c, hx509_cert *cert)
     if (ret) {
        free((*cert)->data);
        free(*cert);
+       *cert = NULL;
+    }
+    return ret;
+}
+
+int
+hx509_cert_init_data(hx509_context context, 
+            const void *ptr,
+                    size_t len,
+                    hx509_cert *cert)
+{
+    Certificate t;
+    size_t size;
+    int ret;
+
+    ret = decode_Certificate(ptr, len, &t, &size);
+    if (ret) {
+       hx509_set_error_string(context, 0, ret, "Failed to decode certificate");
+       return ret;
+    }
+    if (size != len) {
+       hx509_set_error_string(context, 0, HX509_EXTRA_DATA_AFTER_STRUCTURE,
+                              "Extra data after certificate");
+       return HX509_EXTRA_DATA_AFTER_STRUCTURE;
     }
+
+    ret = hx509_cert_init(context, &t, cert);
+    free_Certificate(&t);
     return ret;
 }
 
@@ -291,10 +304,10 @@ hx509_cert
 hx509_cert_ref(hx509_cert cert)
 {
     if (cert->ref <= 0)
-       _hx509_abort("refcount <= 0");
+       _hx509_abort("cert refcount <= 0");
     cert->ref++;
     if (cert->ref == 0)
-       _hx509_abort("refcount == 0");
+       _hx509_abort("cert refcount == 0");
     return cert;
 }
 
@@ -341,6 +354,12 @@ hx509_verify_set_time(hx509_verify_ctx ctx, time_t t)
     ctx->time_now = t;
 }
 
+void
+hx509_verify_set_max_depth(hx509_verify_ctx ctx, unsigned int max_depth)
+{
+    ctx->max_depth = max_depth;
+}
+
 void
 hx509_verify_set_proxy_certificate(hx509_verify_ctx ctx, int boolean)
 {
@@ -359,6 +378,15 @@ hx509_verify_set_strict_rfc3280_verification(hx509_verify_ctx ctx, int boolean)
        ctx->flags &= ~HX509_VERIFY_CTX_F_REQUIRE_RFC3280;
 }
 
+void
+hx509_verify_ctx_f_allow_default_trustanchors(hx509_verify_ctx ctx, int boolean)
+{
+    if (boolean)
+       ctx->flags &= ~HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
+    else
+       ctx->flags |= HX509_VERIFY_CTX_F_NO_DEFAULT_ANCHORS;
+}
+
 static const Extension *
 find_extension(const Certificate *cert, const heim_oid *oid, int *idx)
 {
@@ -1295,13 +1323,15 @@ match_general_name(const GeneralName *c, const GeneralName *n, int *match)
        return 0;
     }
     case choice_GeneralName_dNSName: {
-       size_t len1, len2;
+       size_t lenc, lenn;
 
-       len1 = strlen(c->u.dNSName);
-       len2 = strlen(n->u.dNSName);
-       if (len1 > len2)
+       lenc = strlen(c->u.dNSName);
+       lenn = strlen(n->u.dNSName);
+       if (lenc > lenn)
            return HX509_NAME_CONSTRAINT_ERROR;
-       if (strcasecmp(&n->u.dNSName[len2 - len1], c->u.dNSName) != 0)
+       if (strcasecmp(&n->u.dNSName[lenn - lenc], c->u.dNSName) != 0)
+           return HX509_NAME_CONSTRAINT_ERROR;
+       if (lenc != lenn && n->u.dNSName[lenn - lenc - 1] != '.')
            return HX509_NAME_CONSTRAINT_ERROR;
        *match = 1;
        return 0;
@@ -1488,15 +1518,15 @@ hx509_verify_path(hx509_context context,
     /*
      *
      */
-    ret = hx509_certs_init(context, "MEMORY:trust-anchors", 0, NULL, &anchors);
-    if (ret)
-       goto out;
-    ret = hx509_certs_merge(context, anchors, ctx->trust_anchors);
-    if (ret)
-       goto out;
-    ret = hx509_certs_merge(context, anchors, context->default_trust_anchors);
-    if (ret)
-       goto out;
+    if (ctx->trust_anchors)
+       anchors = _hx509_certs_ref(ctx->trust_anchors);
+    else if (context->default_trust_anchors && ALLOW_DEF_TA(ctx))
+       anchors = _hx509_certs_ref(context->default_trust_anchors);
+    else {
+       ret = hx509_certs_init(context, "MEMORY:no-TA", 0, NULL, &anchors);
+       if (ret)
+           goto out;
+    }
 
     /*
      * Calculate the path from the certificate user presented to the
@@ -1843,17 +1873,82 @@ hx509_verify_signature(hx509_context context,
     return _hx509_verify_signature(context, signer->data, alg, data, sig);
 }
 
+#define HX509_VHN_F_ALLOW_NO_MATCH 1
+
 int
 hx509_verify_hostname(hx509_context context,
                      const hx509_cert cert,
-                     int require_match,
+                     int flags,
+                     hx509_hostname_type type,
                      const char *hostname,
                      const struct sockaddr *sa,
                      /* XXX krb5_socklen_t */ int sa_size) 
 {
+    GeneralNames san;
+    int ret, i, j;
+
     if (sa && sa_size <= 0)
        return EINVAL;
-    return 0;
+
+    memset(&san, 0, sizeof(san));
+
+    i = 0;
+    do {
+       ret = find_extension_subject_alt_name(cert->data, &i, &san);
+       if (ret == HX509_EXTENSION_NOT_FOUND) {
+           ret = 0;
+           break;
+       } else if (ret != 0)
+           break;
+
+       for (j = 0; j < san.len; j++) {
+           switch (san.val[j].element) {
+           case choice_GeneralName_dNSName:
+               if (strcasecmp(san.val[j].u.dNSName, hostname) == 0) {
+                   free_GeneralNames(&san);
+                   return 0;
+               }
+               break;
+           default:
+               break;
+           }
+       }
+       free_GeneralNames(&san);
+    } while (1);
+
+    {
+       Name *name = &cert->data->tbsCertificate.subject;
+
+       /* match if first component is a CN= */
+       if (name->u.rdnSequence.len > 0
+           && name->u.rdnSequence.val[0].len == 1
+           && der_heim_oid_cmp(&name->u.rdnSequence.val[0].val[0].type,
+                               oid_id_at_commonName()) == 0)
+       {
+           DirectoryString *ds = &name->u.rdnSequence.val[0].val[0].value;
+
+           switch (ds->element) {
+           case choice_DirectoryString_printableString:
+               if (strcasecmp(ds->u.printableString, hostname) == 0)
+                   return 0;
+               break;
+           case choice_DirectoryString_ia5String:
+               if (strcasecmp(ds->u.ia5String, hostname) == 0)
+                   return 0;
+               break;
+           case choice_DirectoryString_utf8String:
+               if (strcasecmp(ds->u.utf8String, hostname) == 0)
+                   return 0;
+           default:
+               break;
+           }
+       }
+    }
+
+    if ((flags & HX509_VHN_F_ALLOW_NO_MATCH) == 0)
+       ret = HX509_NAME_CONSTRAINT_ERROR;
+
+    return ret;
 }
 
 int
@@ -2434,3 +2529,24 @@ hx509_cert_binary(hx509_context context, hx509_cert c, heim_octet_string *os)
 
     return ret;
 }
+
+/*
+ * Last to avoid lost __attribute__s due to #undef.
+ */
+
+#undef __attribute__
+#define __attribute__(X)
+
+void
+_hx509_abort(const char *fmt, ...)
+     __attribute__ ((noreturn, format (printf, 1, 2)))
+{
+    va_list ap;
+    va_start(ap, fmt);
+    vprintf(fmt, ap);
+    va_end(ap);
+    printf("\n");
+    fflush(stdout);
+    abort();
+}
+
index 29ca80e1941cf2859b81106d7d6cb095a4ad900c..30f364060d0b5ef14096304650575661962940da 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id: cms.c 20937 2007-06-06 20:50:55Z lha $");
+RCSID("$Id: cms.c 21319 2007-06-25 19:46:52Z lha $");
 
 #define ALLOC(X, N) (X) = calloc((N), sizeof(*(X)))
 #define ALLOC_SEQ(X, N) do { (X)->len = (N); ALLOC((X)->val, (N)); } while(0)
@@ -115,24 +115,42 @@ hx509_cms_unwrap_ContentInfo(const heim_octet_string *in,
     return 0;
 }
 
+#define CMS_ID_SKI     0
+#define CMS_ID_NAME    1
+
 static int
-fill_CMSIdentifier(const hx509_cert cert, CMSIdentifier *id)
+fill_CMSIdentifier(const hx509_cert cert,
+                  int type,
+                  CMSIdentifier *id)
 {
-    hx509_name name;
     int ret;
 
-    id->element = choice_CMSIdentifier_issuerAndSerialNumber;
-    ret = hx509_cert_get_issuer(cert, &name);
-    if (ret)
-       return ret;
-    ret = copy_Name(&name->der_name,
-                   &id->u.issuerAndSerialNumber.issuer);
-    hx509_name_free(&name);
-    if (ret)
-       return ret;
+    switch (type) {
+    case CMS_ID_SKI:
+       id->element = choice_CMSIdentifier_subjectKeyIdentifier;
+       ret = _hx509_find_extension_subject_key_id(_hx509_get_cert(cert),
+                                                  &id->u.subjectKeyIdentifier);
+       if (ret == 0)
+           break;
+       /* FALL THOUGH */
+    case CMS_ID_NAME: {
+       hx509_name name;
 
-    ret = hx509_cert_get_serialnumber(cert,
-                                     &id->u.issuerAndSerialNumber.serialNumber);
+       id->element = choice_CMSIdentifier_issuerAndSerialNumber;
+       ret = hx509_cert_get_issuer(cert, &name);
+       if (ret)
+           return ret;
+       ret = hx509_name_to_Name(name, &id->u.issuerAndSerialNumber.issuer);
+       hx509_name_free(&name);
+       if (ret)
+           return ret;
+
+       ret = hx509_cert_get_serialnumber(cert, &id->u.issuerAndSerialNumber.serialNumber);
+       break;
+    }
+    default:
+       _hx509_abort("CMS fill identifier with unknown type");
+    }
     return ret;
 }
 
@@ -467,6 +485,13 @@ hx509_cms_envelope_1(hx509_context context,
        goto out;
     }
 
+    ret = hx509_crypto_random_iv(crypto, &ivec);
+    if (ret) {
+       hx509_set_error_string(context, 0, ret,
+                              "Failed to create a random iv");
+       goto out;
+    }
+
     ret = hx509_crypto_encrypt(crypto,
                               data,
                               length,
@@ -518,7 +543,7 @@ hx509_cms_envelope_1(hx509_context context,
     ri = &ed.recipientInfos.val[0];
 
     ri->version = 0;
-    ret = fill_CMSIdentifier(cert, &ri->rid);
+    ret = fill_CMSIdentifier(cert, CMS_ID_SKI, &ri->rid);
     if (ret) {
        hx509_set_error_string(context, 0, ret,
                               "Failed to set CMS identifier info "
@@ -585,22 +610,12 @@ any_to_certs(hx509_context context, const SignedData *sd, hx509_certs certs)
        return 0;
 
     for (i = 0; i < sd->certificates->len; i++) {
-       Certificate cert;
        hx509_cert c;
 
-       const void *p = sd->certificates->val[i].data;
-       size_t size, length = sd->certificates->val[i].length;
-
-       ret = decode_Certificate(p, length, &cert, &size);
-       if (ret) {
-           hx509_set_error_string(context, 0, ret,
-                                  "Failed to decode certificate %d "
-                                  "in SignedData.certificates", i);
-           return ret;
-       }
-
-       ret = hx509_cert_init(context, &cert, &c);
-       free_Certificate(&cert);
+       ret = hx509_cert_init_data(context, 
+                                  sd->certificates->val[i].data, 
+                                  sd->certificates->val[i].length,
+                                  &c);
        if (ret)
            return ret;
        ret = hx509_certs_add(context, certs, c);
@@ -951,6 +966,7 @@ hx509_cms_create_signed_1(hx509_context context,
     int ret;
     size_t size;
     hx509_path path;
+    int cmsidflag = CMS_ID_SKI;
 
     memset(&sd, 0, sizeof(sd));
     memset(&name, 0, sizeof(name));
@@ -960,6 +976,9 @@ hx509_cms_create_signed_1(hx509_context context,
     content.data = rk_UNCONST(data);
     content.length = length;
 
+    if (flags & HX509_CMS_SIGATURE_ID_NAME)
+       cmsidflag = CMS_ID_NAME;
+
     if (_hx509_cert_private_key(cert) == NULL) {
        hx509_set_error_string(context, 0, HX509_PRIVATE_KEY_MISSING,
                               "Private key missing for signing");
@@ -1014,7 +1033,7 @@ hx509_cms_create_signed_1(hx509_context context,
 
     signer_info->version = 1;
 
-    ret = fill_CMSIdentifier(cert, &signer_info->sid);
+    ret = fill_CMSIdentifier(cert, cmsidflag, &signer_info->sid);
     if (ret) {
        hx509_clear_error_string(context);
        goto out;
index 96d9693cc25f58081afd9f52561ed729f2be6694..d86300bd586ce9071ef5f1827eeab6303af41ef6 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id: crypto.c 20939 2007-06-06 20:53:02Z lha $");
+RCSID("$Id: crypto.c 21318 2007-06-25 19:46:32Z lha $");
 
 struct hx509_crypto;
 
@@ -362,6 +362,7 @@ rsa_create_signature(hx509_context context,
     sig->length = RSA_size(signer->private_key.rsa);
     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;
     }
@@ -1761,15 +1762,17 @@ CMSRC2CBCParam_set(hx509_context context, const heim_octet_string *param,
        p->maximum_effective_key = 128;
        break;
     default:
+       free(p);
        free_CMSRC2CBCParameter(&rc2param);
        return HX509_CRYPTO_SIG_INVALID_FORMAT;
     }
     if (ivec)
        ret = der_copy_octet_string(&rc2param.iv, ivec);
     free_CMSRC2CBCParameter(&rc2param);
-    if (ret)
+    if (ret) {
+       free(p);
        hx509_clear_error_string(context);
-    else
+    else
        crypto->param = p;
 
     return ret;
@@ -2008,11 +2011,30 @@ hx509_crypto_get_params(hx509_context context,
     return (*crypto->cipher->get_params)(context, crypto, ivec, param);
 }
 
+int
+hx509_crypto_random_iv(hx509_crypto crypto, heim_octet_string *ivec)
+{
+    ivec->length = EVP_CIPHER_iv_length(crypto->c);
+    ivec->data = malloc(ivec->length);
+    if (ivec->data == NULL) {
+       ivec->length = 0;
+       return ENOMEM;
+    }
+
+    if (RAND_bytes(ivec->data, ivec->length) <= 0) {
+       free(ivec->data);
+       ivec->data = NULL;
+       ivec->length = 0;
+       return HX509_CRYPTO_INTERNAL_ERROR;
+    }
+    return 0;
+}
+
 int
 hx509_crypto_encrypt(hx509_crypto crypto,
                     const void *data,
                     const size_t length,
-                    heim_octet_string *ivec,
+                    const heim_octet_string *ivec,
                     heim_octet_string **ciphertext)
 {
     EVP_CIPHER_CTX evp;
@@ -2021,19 +2043,9 @@ hx509_crypto_encrypt(hx509_crypto crypto,
 
     *ciphertext = NULL;
 
-    EVP_CIPHER_CTX_init(&evp);
-
-    ivec->length = EVP_CIPHER_iv_length(crypto->c);
-    ivec->data = malloc(ivec->length);
-    if (ivec->data == NULL) {
-       ret = ENOMEM;
-       goto out;
-    }
+    assert(EVP_CIPHER_iv_length(crypto->c) == ivec->length);
 
-    if (RAND_bytes(ivec->data, ivec->length) <= 0) {
-       ret = HX509_CRYPTO_INTERNAL_ERROR;
-       goto out;
-    }
+    EVP_CIPHER_CTX_init(&evp);
 
     ret = EVP_CipherInit_ex(&evp, crypto->c, NULL,
                            crypto->key.data, ivec->data, 1);
@@ -2082,10 +2094,6 @@ hx509_crypto_encrypt(hx509_crypto crypto,
 
  out:
     if (ret) {
-       if (ivec->data) {
-           free(ivec->data);
-           memset(ivec, 0, sizeof(*ivec));
-       }
        if (*ciphertext) {
            if ((*ciphertext)->data) {
                free((*ciphertext)->data);
@@ -2286,6 +2294,24 @@ find_string2key(const heim_oid *oid,
     return NULL;
 }
 
+/*
+ *
+ */
+
+int
+_hx509_pbe_encrypt(hx509_context context,
+                  hx509_lock lock,
+                  const AlgorithmIdentifier *ai,
+                  const heim_octet_string *content,
+                  heim_octet_string *econtent)
+{
+    hx509_clear_error_string(context);
+    return EINVAL;
+}
+
+/*
+ *
+ */
 
 int
 _hx509_pbe_decrypt(hx509_context context,
index 1152af2423c473d1b8f6ba783c016feda9527963..b076b74f44df661485ba84c065e572b54f357729 100644 (file)
@@ -134,3 +134,243 @@ _hx509_write_file(const char *fn, const void *data, size_t length)
 
     return 0;
 }
+
+/*
+ *
+ */
+
+static void
+header(FILE *f, const char *type, const char *str)
+{
+    fprintf(f, "-----%s %s-----\n", type, str);
+}
+
+int
+hx509_pem_write(hx509_context context, const char *type, 
+               hx509_pem_header *headers, FILE *f,
+               const void *data, size_t size)
+{
+    const char *p = data;
+    size_t length;
+    char *line;
+
+#define ENCODE_LINE_LENGTH     54
+    
+    header(f, "BEGIN", type);
+
+    while (headers) {
+       fprintf(f, "%s: %s\n%s", 
+               headers->header, headers->value,
+               headers->next ? "" : "\n");
+       headers = headers->next;
+    }
+
+    while (size > 0) {
+       ssize_t l;
+       
+       length = size;
+       if (length > ENCODE_LINE_LENGTH)
+           length = ENCODE_LINE_LENGTH;
+       
+       l = base64_encode(p, length, &line);
+       if (l < 0) {
+           hx509_set_error_string(context, 0, ENOMEM,
+                                  "malloc - out of memory");
+           return ENOMEM;
+       }
+       size -= length;
+       fprintf(f, "%s\n", line);
+       p += length;
+       free(line);
+    }
+
+    header(f, "END", type);
+
+    return 0;
+}
+
+/*
+ *
+ */
+
+int
+hx509_pem_add_header(hx509_pem_header **headers, 
+                    const char *header, const char *value)
+{
+    hx509_pem_header *h;
+
+    h = calloc(1, sizeof(*h));
+    if (h == NULL)
+       return ENOMEM;
+    h->header = strdup(header);
+    if (h->header == NULL) {
+       free(h);
+       return ENOMEM;
+    }
+    h->value = strdup(value);
+    if (h->value == NULL) {
+       free(h->header);
+       free(h);
+       return ENOMEM;
+    }
+
+    h->next = *headers;
+    *headers = h;
+
+    return 0;
+}
+
+void
+hx509_pem_free_header(hx509_pem_header *headers)
+{
+    hx509_pem_header *h;
+    while (headers) {
+       h = headers;
+       headers = headers->next;
+       free(h->header);
+       free(h->value);
+       free(h);
+    }
+}
+
+/*
+ *
+ */
+
+const char *
+hx509_pem_find_header(const hx509_pem_header *h, const char *header)
+{
+    while(h) {
+       if (strcmp(header, h->header) == 0)
+           return h->value;
+       h = h->next;
+    }
+    return NULL;
+}
+
+
+/*
+ *
+ */
+
+int
+hx509_pem_read(hx509_context context,
+              FILE *f, 
+              hx509_pem_read_func func,
+              void *ctx)
+{
+    hx509_pem_header *headers = NULL;
+    char *type = NULL;
+    void *data = NULL;
+    size_t len = 0;
+    char buf[1024];
+    int ret = HX509_PARSING_KEY_FAILED;
+
+    enum { BEFORE, SEARCHHEADER, INHEADER, INDATA, DONE } where;
+
+    where = BEFORE;
+
+    while (fgets(buf, sizeof(buf), f) != NULL) {
+       char *p;
+       int i;
+
+       i = strcspn(buf, "\n");
+       if (buf[i] == '\n') {
+           buf[i] = '\0';
+           if (i > 0)
+               i--;
+       }
+       if (buf[i] == '\r') {
+           buf[i] = '\0';
+           if (i > 0)
+               i--;
+       }
+           
+       switch (where) {
+       case BEFORE:
+           if (strncmp("-----BEGIN ", buf, 11) == 0) {
+               type = strdup(buf + 11);
+               if (type == NULL)
+                   break;
+               p = strchr(type, '-');
+               if (p)
+                   *p = '\0';
+               where = SEARCHHEADER;
+           }
+           break;
+       case SEARCHHEADER:
+           p = strchr(buf, ':');
+           if (p == NULL) {
+               where = INDATA;
+               goto indata;
+           }
+           /* FALLTHOUGH */
+       case INHEADER:
+           if (buf[0] == '\0') {
+               where = INDATA;
+               break;
+           }
+           p = strchr(buf, ':');
+           if (p) {
+               *p++ = '\0';
+               while (isspace((int)*p))
+                   p++;
+               ret = hx509_pem_add_header(&headers, buf, p);
+               if (ret)
+                   abort();
+           }
+           break;
+       case INDATA:
+       indata:
+
+           if (strncmp("-----END ", buf, 9) == 0) {
+               where = DONE;
+               break;
+           }
+
+           p = emalloc(i);
+           i = base64_decode(buf, p);
+           if (i < 0) {
+               free(p);
+               goto out;
+           }
+           
+           data = erealloc(data, len + i);
+           memcpy(((char *)data) + len, p, i);
+           free(p);
+           len += i;
+           break;
+       case DONE:
+           abort();
+       }
+
+       if (where == DONE) {
+           ret = (*func)(context, type, headers, data, len, ctx);
+       out:
+           free(data);
+           data = NULL;
+           len = 0;
+           free(type);
+           type = NULL;
+           where = BEFORE;
+           hx509_pem_free_header(headers);
+           headers = NULL;
+           if (ret)
+               break;
+       }
+    }
+
+    if (where != BEFORE) {
+       hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
+                              "File ends before end of PEM end tag");
+       ret = HX509_PARSING_KEY_FAILED;
+    }
+    if (data)
+       free(data);
+    if (type)
+       free(type);
+    if (headers)
+       hx509_pem_free_header(headers);
+
+    return ret;
+}
index 2763df957f6f065ee7d0432803bd873651c2aa29..451c3c89f2b6e5f0138ef2bda9cfddc2422847f3 100644 (file)
@@ -4,6 +4,10 @@
 
 #include <stdarg.h>
 
+#if !defined(__GNUC__) && !defined(__attribute__)
+#define __attribute__(x)
+#endif
+
 int
 _hx509_Certificate_cmp (
        const Certificate */*p*/,
@@ -20,7 +24,8 @@ _hx509_Time2time_t (const Time */*t*/);
 void
 _hx509_abort (
        const char */*fmt*/,
-       ...);
+       ...)
+    __attribute__ ((noreturn, format (printf, 1, 2)));
 
 int
 _hx509_calculate_path (
@@ -104,6 +109,9 @@ _hx509_certs_keys_get (
        hx509_certs /*certs*/,
        hx509_private_key **/*keys*/);
 
+hx509_certs
+_hx509_certs_ref (hx509_certs /*certs*/);
+
 int
 _hx509_check_key_usage (
        hx509_context /*context*/,
@@ -306,6 +314,14 @@ _hx509_pbe_decrypt (
        const heim_octet_string */*econtent*/,
        heim_octet_string */*content*/);
 
+int
+_hx509_pbe_encrypt (
+       hx509_context /*context*/,
+       hx509_lock /*lock*/,
+       const AlgorithmIdentifier */*ai*/,
+       const heim_octet_string */*content*/,
+       heim_octet_string */*econtent*/);
+
 void
 _hx509_pi_printf (
        int (*/*func*/)(void *, const char *),
@@ -406,11 +422,35 @@ _hx509_request_add_email (
 void
 _hx509_request_free (hx509_request */*req*/);
 
+int
+_hx509_request_get_SubjectPublicKeyInfo (
+       hx509_context /*context*/,
+       hx509_request /*req*/,
+       SubjectPublicKeyInfo */*key*/);
+
+int
+_hx509_request_get_name (
+       hx509_context /*context*/,
+       hx509_request /*req*/,
+       hx509_name */*name*/);
+
 int
 _hx509_request_init (
        hx509_context /*context*/,
        hx509_request */*req*/);
 
+int
+_hx509_request_parse (
+       hx509_context /*context*/,
+       const char */*path*/,
+       hx509_request */*req*/);
+
+int
+_hx509_request_print (
+       hx509_context /*context*/,
+       hx509_request /*req*/,
+       FILE */*f*/);
+
 int
 _hx509_request_set_SubjectPublicKeyInfo (
        hx509_context /*context*/,
index ab312cdbdfdca701c671eddee18035066535f260..71fb29d59dd042759ce5d1ff20940aa9fb85bc67 100644 (file)
@@ -236,6 +236,13 @@ hx509_cert_init (
        const Certificate */*c*/,
        hx509_cert */*cert*/);
 
+int
+hx509_cert_init_data (
+       hx509_context /*context*/,
+       const void */*ptr*/,
+       size_t /*len*/,
+       hx509_cert */*cert*/);
+
 int
 hx509_cert_keyusage_print (
        hx509_context /*context*/,
@@ -479,7 +486,7 @@ hx509_crypto_encrypt (
        hx509_crypto /*crypto*/,
        const void */*data*/,
        const size_t /*length*/,
-       heim_octet_string */*ivec*/,
+       const heim_octet_string */*ivec*/,
        heim_octet_string **/*ciphertext*/);
 
 const heim_oid *
@@ -507,6 +514,11 @@ hx509_crypto_init (
 const char *
 hx509_crypto_provider (hx509_crypto /*crypto*/);
 
+int
+hx509_crypto_random_iv (
+       hx509_crypto /*crypto*/,
+       heim_octet_string */*ivec*/);
+
 int
 hx509_crypto_select (
        const hx509_context /*context*/,
@@ -740,6 +752,36 @@ hx509_peer_info_set_cms_algs (
        const AlgorithmIdentifier */*val*/,
        size_t /*len*/);
 
+int
+hx509_pem_add_header (
+       hx509_pem_header **/*headers*/,
+       const char */*header*/,
+       const char */*value*/);
+
+const char *
+hx509_pem_find_header (
+       const hx509_pem_header */*h*/,
+       const char */*header*/);
+
+void
+hx509_pem_free_header (hx509_pem_header */*headers*/);
+
+int
+hx509_pem_read (
+       hx509_context /*context*/,
+       FILE */*f*/,
+       hx509_pem_read_func /*func*/,
+       void */*ctx*/);
+
+int
+hx509_pem_write (
+       hx509_context /*context*/,
+       const char */*type*/,
+       hx509_pem_header */*headers*/,
+       FILE */*f*/,
+       const void */*data*/,
+       size_t /*size*/);
+
 void
 hx509_print_func (
        hx509_vprint_func /*func*/,
@@ -930,6 +972,11 @@ hx509_verify_attach_revoke (
        hx509_verify_ctx /*ctx*/,
        hx509_revoke_ctx /*revoke_ctx*/);
 
+void
+hx509_verify_ctx_f_allow_default_trustanchors (
+       hx509_verify_ctx /*ctx*/,
+       int /*boolean*/);
+
 void
 hx509_verify_destroy_ctx (hx509_verify_ctx /*ctx*/);
 
@@ -937,7 +984,8 @@ int
 hx509_verify_hostname (
        hx509_context /*context*/,
        const hx509_cert /*cert*/,
-       int /*require_match*/,
+       int /*flags*/,
+       hx509_hostname_type /*type*/,
        const char */*hostname*/,
        const struct sockaddr */*sa*/,
        int /*sa_size*/);
@@ -954,6 +1002,11 @@ hx509_verify_path (
        hx509_cert /*cert*/,
        hx509_certs /*pool*/);
 
+void
+hx509_verify_set_max_depth (
+       hx509_verify_ctx /*ctx*/,
+       unsigned int /*max_depth*/);
+
 void
 hx509_verify_set_proxy_certificate (
        hx509_verify_ctx /*ctx*/,
index 664c12e045a1124c0f592fa053ef568398e5f96c..2f22cedfbc831fc2bc343a14dc29318293fdf0ce 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE. 
  */
 
-/* $Id: hx509.h 20798 2007-06-02 03:28:55Z lha $ */
+/* $Id: hx509.h 21310 2007-06-25 18:26:06Z lha $ */
 
 typedef struct hx509_cert_attribute_data *hx509_cert_attribute;
 typedef struct hx509_cert_data *hx509_cert;
@@ -84,6 +84,16 @@ typedef struct hx509_octet_string_list {
     heim_octet_string *val;
 } hx509_octet_string_list;
 
+typedef struct hx509_pem_header {
+    struct hx509_pem_header *next;
+    char *header;
+    char *value;
+} hx509_pem_header;
+
+typedef int
+(*hx509_pem_read_func)(hx509_context, const char *, const hx509_pem_header *,
+                      const void *, size_t, void *ctx);
+
 /*
  * Options passed to hx509_query_match_option.
  */
@@ -122,5 +132,12 @@ typedef enum {
 
 /* flags hx509_cms_create_signed* */
 #define HX509_CMS_SIGATURE_DETACHED 1
+#define HX509_CMS_SIGATURE_ID_NAME 2
+
+/* hx509_verify_hostname nametype */
+typedef enum  {
+    HX509_HN_HOSTNAME = 0,
+    HX509_HN_DNSSRV
+} hx509_hostname_type;
 
 #include <hx509-protos.h>
index bfbee0943ebc7dc052261bbc1f3529a7092edfb4..145bfcc006d038c215b6cd74b8a54cf5742f3286 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE. 
  */
 
-/* $Id: hx_locl.h 20930 2007-06-06 00:23:42Z lha $ */
+/* $Id: hx_locl.h 21083 2007-06-13 02:11:19Z lha $ */
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -194,6 +194,6 @@ extern const AlgorithmIdentifier * _hx509_crypto_default_secret_alg;
  * Configurable options
  */
 
-#if 0 /* fdef __APPLE__*/
-#define HX509_DEFAULT_ANCHORS "KEYCHAIN:system"
+#ifdef __APPLE__
+#define HX509_DEFAULT_ANCHORS "KEYCHAIN:system-anchors"
 #endif
index 475835b9b09a5820acec85240532b5f7c70e6fa8..7da5705a80295d989dcba2c565a8173811e8c06e 100644 (file)
  */
 
 #include "hx_locl.h"
-RCSID("$Id: keyset.c 20911 2007-06-05 03:41:17Z lha $");
+RCSID("$Id: keyset.c 21140 2007-06-18 21:24:19Z lha $");
 
 struct hx509_certs_data {
+    int ref;
     struct hx509_keyset_ops *ops;
     void *ops_data;
 };
@@ -99,18 +100,20 @@ hx509_certs_init(hx509_context context,
     }
     
     ops = _hx509_ks_type(context, type);
-    free(type);
     if (ops == NULL) {
        hx509_set_error_string(context, 0, ENOENT, 
                               "Keyset type %s is not supported", type);
+       free(type);
        return ENOENT;
     }
+    free(type);
     c = calloc(1, sizeof(*c));
     if (c == NULL) {
        hx509_clear_error_string(context);
        return ENOMEM;
     }
     c->ops = ops;
+    c->ref = 1;
 
     ret = (*ops->init)(context, c, &c->ops_data, flags, residue, lock);
     if (ret) {
@@ -140,10 +143,26 @@ hx509_certs_store(hx509_context context,
 }
 
 
+hx509_certs
+_hx509_certs_ref(hx509_certs certs)
+{
+    if (certs->ref <= 0)
+       _hx509_abort("certs refcount <= 0");
+    certs->ref++;
+    if (certs->ref == 0)
+       _hx509_abort("certs refcount == 0");
+    return certs;
+}
+
 void
 hx509_certs_free(hx509_certs *certs)
 {
     if (*certs) {
+       if ((*certs)->ref <= 0)
+           _hx509_abort("refcount <= 0");
+       if (--(*certs)->ref > 0)
+           return;
+
        (*(*certs)->ops->free)(*certs, (*certs)->ops_data);
        free(*certs);
        *certs = NULL;
index f9a35808805ab1d3f4ed9a652fe4fb47ca6f2cc3..269afd03b10a1e0c9f44b451eca987d704cd71de 100644 (file)
  */
 
 #include "hx_locl.h"
-RCSID("$Id: ks_file.c 20776 2007-06-01 22:02:01Z lha $");
+RCSID("$Id: ks_file.c 21314 2007-06-25 18:45:07Z lha $");
+
+typedef enum { USE_PEM, USE_DER } outformat;
 
 struct ks_file {
     hx509_certs certs;
     char *fn;
+    outformat format;
 };
 
-struct header {
-    char *header;
-    char *value;
-    struct header *next;
-};
-
-static int
-add_headers(struct header **headers, const char *header, const char *value)
-{
-    struct header *h;
-    h = calloc(1, sizeof(*h));
-    if (h == NULL)
-       return ENOMEM;
-    h->header = strdup(header);
-    if (h->header == NULL) {
-       free(h);
-       return ENOMEM;
-    }
-    h->value = strdup(value);
-    if (h->value == NULL) {
-       free(h->header);
-       free(h);
-       return ENOMEM;
-    }
-
-    h->next = *headers;
-    *headers = h;
-
-    return 0;
-}
-
-static void
-free_headers(struct header *headers)
-{
-    struct header *h;
-    while (headers) {
-       h = headers;
-       headers = headers->next;
-       free(h->header);
-       free(h->value);
-       free(h);
-    }
-}
-
-static const char *
-find_header(const struct header *headers, const char *header)
-{
-    while(headers) {
-       if (strcmp(header, headers->header) == 0)
-           return headers->value;
-       headers = headers->next;
-    }
-    return NULL;
-}
-
 /*
  *
  */
@@ -101,24 +49,13 @@ find_header(const struct header *headers, const char *header)
 static int
 parse_certificate(hx509_context context, const char *fn, 
                  struct hx509_collector *c, 
-                 const struct header *headers,
+                 const hx509_pem_header *headers,
                  const void *data, size_t len)
 {
     hx509_cert cert;
-    Certificate t;
-    size_t size;
     int ret;
 
-    ret = decode_Certificate(data, len, &t, &size);
-    if (ret) {
-       hx509_set_error_string(context, 0, ret, 
-                              "Failed to parse certificate in %s",
-                              fn);
-       return ret;
-    }
-
-    ret = hx509_cert_init(context, &t, &cert);
-    free_Certificate(&t);
+    ret = hx509_cert_init_data(context, data, len, &cert);
     if (ret)
        return ret;
 
@@ -195,13 +132,13 @@ out:
 static int
 parse_rsa_private_key(hx509_context context, const char *fn,
                      struct hx509_collector *c, 
-                     const struct header *headers,
+                     const hx509_pem_header *headers,
                      const void *data, size_t len)
 {
     int ret = 0;
     const char *enc;
 
-    enc = find_header(headers, "Proc-Type");
+    enc = hx509_pem_find_header(headers, "Proc-Type");
     if (enc) {
        const char *dek;
        char *type, *iv;
@@ -229,7 +166,7 @@ parse_rsa_private_key(hx509_context context, const char *fn,
            return HX509_PARSING_KEY_FAILED;
        }
 
-       dek = find_header(headers, "DEK-Info");
+       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");
@@ -243,8 +180,14 @@ parse_rsa_private_key(hx509_context context, const char *fn,
        }
 
        iv = strchr(type, ',');
-       if (iv)
-           *iv++ = '\0';
+       if (iv == NULL) {
+           free(type);
+           hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
+                                  "IV missing");
+           return HX509_PARSING_KEY_FAILED;
+       }
+
+       *iv++ = '\0';
 
        size = strlen(iv);
        ivdata = malloc(size);
@@ -339,7 +282,7 @@ 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 struct header *, const void *, size_t);
+               const hx509_pem_header *, const void *, size_t);
 } formats[] = {
     { "CERTIFICATE", parse_certificate },
     { "RSA PRIVATE KEY", parse_rsa_private_key }
@@ -347,152 +290,27 @@ struct pem_formats {
 
 
 static int
-parse_pem_file(hx509_context context, 
-              const char *fn,
-              struct hx509_collector *c,
-              int *found_data)
+pem_func(hx509_context context, const char *type,
+        const hx509_pem_header *header,
+        const void *data, size_t len, void *ctx)
 {
-    struct header *headers = NULL;
-    char *type = NULL;
-    void *data = NULL;
-    size_t len = 0;
-    char buf[1024];
-    int ret;
-    FILE *f;
-
-
-    enum { BEFORE, SEARCHHEADER, INHEADER, INDATA, DONE } where;
-
-    where = BEFORE;
-    *found_data = 0;
+    struct hx509_collector *c = ctx;
+    int ret, j;
 
-    if ((f = fopen(fn, "r")) == NULL) {
-       hx509_set_error_string(context, 0, ENOENT, 
-                              "Failed to open PEM file \"%s\": %s", 
-                              fn, strerror(errno));
-       return ENOENT;
-    }
-    ret = 0;
-
-    while (fgets(buf, sizeof(buf), f) != NULL) {
-       char *p;
-       int i;
-
-       i = strcspn(buf, "\n");
-       if (buf[i] == '\n') {
-           buf[i] = '\0';
-           if (i > 0)
-               i--;
-       }
-       if (buf[i] == '\r') {
-           buf[i] = '\0';
-           if (i > 0)
-               i--;
-       }
-           
-       switch (where) {
-       case BEFORE:
-           if (strncmp("-----BEGIN ", buf, 11) == 0) {
-               type = strdup(buf + 11);
-               if (type == NULL)
-                   break;
-               p = strchr(type, '-');
-               if (p)
-                   *p = '\0';
-               *found_data = 1;
-               where = SEARCHHEADER;
-           }
+    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, c,  header, data, len);
            break;
-       case SEARCHHEADER:
-           p = strchr(buf, ':');
-           if (p == NULL) {
-               where = INDATA;
-               goto indata;
-           }
-           /* FALLTHOUGH */
-       case INHEADER:
-           if (buf[0] == '\0') {
-               where = INDATA;
-               break;
-           }
-           p = strchr(buf, ':');
-           if (p) {
-               *p++ = '\0';
-               while (isspace((int)*p))
-                   p++;
-               add_headers(&headers, buf, p);
-           }
-           break;
-       case INDATA:
-       indata:
-
-           if (strncmp("-----END ", buf, 9) == 0) {
-               where = DONE;
-               break;
-           }
-
-           p = emalloc(i);
-           i = base64_decode(buf, p);
-           if (i < 0) {
-               free(p);
-               goto out;
-           }
-           
-           data = erealloc(data, len + i);
-           memcpy(((char *)data) + len, p, i);
-           free(p);
-           len += i;
-           break;
-       case DONE:
-           abort();
-       }
-
-       if (where == DONE) {
-           int j;
-
-           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, fn, c, 
-                                            headers, data, len);
-                   break;
-               }
-           }
-           if (j == sizeof(formats)/sizeof(formats[0])) {
-               ret = HX509_UNSUPPORTED_OPERATION;
-               hx509_set_error_string(context, 0, ret,
-                                      "Found no matching PEM format for %s",
-                                      type);
-           }
-       out:
-           free(data);
-           data = NULL;
-           len = 0;
-           free(type);
-           type = NULL;
-           where = BEFORE;
-           free_headers(headers);
-           headers = NULL;
-           if (ret)
-               break;
        }
     }
-
-    fclose(f);
-
-    if (where != BEFORE) {
-       hx509_set_error_string(context, 0, HX509_PARSING_KEY_FAILED,
-                              "File ends before end of PEM end tag");
-       ret = HX509_PARSING_KEY_FAILED;
+    if (j == sizeof(formats)/sizeof(formats[0])) {
+       ret = HX509_UNSUPPORTED_OPERATION;
+       hx509_set_error_string(context, 0, ret,
+                              "Found no matching PEM format for %s", type);
+       return ret;
     }
-    if (data)
-       free(data);
-    if (type)
-       free(type);
-    if (headers)
-       free_headers(headers);
-
-    return ret;
+    return 0;
 }
 
 /*
@@ -500,9 +318,9 @@ parse_pem_file(hx509_context context,
  */
 
 static int
-file_init(hx509_context context,
-         hx509_certs certs, void **data, int flags, 
-         const char *residue, hx509_lock lock)
+file_init_common(hx509_context context,
+                hx509_certs certs, void **data, int flags, 
+                const char *residue, hx509_lock lock, outformat format)
 {
     char *p, *pnext;
     struct ks_file *f = NULL;
@@ -520,6 +338,7 @@ file_init(hx509_context context,
        hx509_clear_error_string(context);
        return ENOMEM;
     }
+    f->format = format;
 
     f->fn = strdup(residue);
     if (f->fn == NULL) {
@@ -547,17 +366,26 @@ file_init(hx509_context context,
        goto out;
 
     for (p = f->fn; p != NULL; p = pnext) {
-       int found_data;
+       FILE *f;
 
        pnext = strchr(p, ',');
        if (pnext)
            *pnext++ = '\0';
        
-       ret = parse_pem_file(context, p, c, &found_data);
-       if (ret)
+
+       if ((f = fopen(p, "r")) == NULL) {
+           ret = ENOENT;
+           hx509_set_error_string(context, 0, ret, 
+                                  "Failed to open PEM file \"%s\": %s", 
+                                  p, strerror(errno));
            goto out;
+       }
 
-       if (!found_data) {
+       ret = hx509_pem_read(context, f, pem_func, c);
+       fclose(f);                   
+       if (ret != 0 && ret != HX509_PARSING_KEY_FAILED)
+           goto out;
+       else if (ret == HX509_PARSING_KEY_FAILED) {
            size_t length;
            void *ptr;
            int i;
@@ -606,75 +434,40 @@ out:
 }
 
 static int
-file_free(hx509_certs certs, void *data)
+file_init_pem(hx509_context context,
+             hx509_certs certs, void **data, int flags, 
+             const char *residue, hx509_lock lock)
 {
-    struct ks_file *f = data;
-    hx509_certs_free(&f->certs);
-    free(f->fn);
-    free(f);
-    return 0;
+    return file_init_common(context, certs, data, flags, residue, lock, USE_PEM);
 }
 
-static void
-pem_header(FILE *f, const char *type, const char *str)
+static int
+file_init_der(hx509_context context,
+             hx509_certs certs, void **data, int flags, 
+             const char *residue, hx509_lock lock)
 {
-    fprintf(f, "-----%s %s-----\n", type, str);
+    return file_init_common(context, certs, data, flags, residue, lock, USE_DER);
 }
 
 static int
-dump_pem_file(hx509_context context, const char *header,
-             FILE *f, const void *data, size_t size)
+file_free(hx509_certs certs, void *data)
 {
-    const char *p = data;
-    size_t length;
-    char *line;
-
-#define ENCODE_LINE_LENGTH     54
-    
-    pem_header(f, "BEGIN", header);
-
-    while (size > 0) {
-       ssize_t l;
-       
-       length = size;
-       if (length > ENCODE_LINE_LENGTH)
-           length = ENCODE_LINE_LENGTH;
-       
-       l = base64_encode(p, length, &line);
-       if (l < 0) {
-           hx509_set_error_string(context, 0, ENOMEM,
-                                  "malloc - out of memory");
-           return ENOMEM;
-       }
-       size -= length;
-       fprintf(f, "%s\n", line);
-       p += length;
-       free(line);
-    }
-
-    pem_header(f, "END", header);
-
+    struct ks_file *f = data;
+    hx509_certs_free(&f->certs);
+    free(f->fn);
+    free(f);
     return 0;
 }
 
-static int
-store_private_key(hx509_context context, FILE *f, hx509_private_key key)
-{
-    heim_octet_string data;
-    int ret;
-
-    ret = _hx509_private_key_export(context, key, &data);
-    if (ret == 0)
-       dump_pem_file(context, _hx509_private_pem_name(key), f,
-                     data.data, data.length);
-    free(data.data);
-    return ret;
-}
+struct store_ctx {
+    FILE *f;
+    outformat format;
+};
 
 static int
 store_func(hx509_context context, void *ctx, hx509_cert c)
 {
-    FILE *f = (FILE *)ctx;
+    struct store_ctx *sc = ctx;
     heim_octet_string data;
     int ret;
 
@@ -682,11 +475,26 @@ store_func(hx509_context context, void *ctx, hx509_cert c)
     if (ret)
        return ret;
     
-    dump_pem_file(context, "CERTIFICATE", f, data.data, data.length);
-    free(data.data);
-
-    if (_hx509_cert_private_key_exportable(c))
-       store_private_key(context, f, _hx509_cert_private_key(c));
+    switch (sc->format) {
+    case USE_DER:
+       fwrite(data.data, data.length, 1, sc->f);
+       free(data.data);
+       break;
+    case USE_PEM:
+       hx509_pem_write(context, "CERTIFICATE", NULL, sc->f, 
+                       data.data, data.length);
+       free(data.data);
+       if (_hx509_cert_private_key_exportable(c)) {
+           hx509_private_key key = _hx509_cert_private_key(c);
+           ret = _hx509_private_key_export(context, key, &data);
+           if (ret)
+               break;
+           hx509_pem_write(context, _hx509_private_pem_name(key), NULL, sc->f,
+                           data.data, data.length);
+           free(data.data);
+       }
+       break;
+    }
 
     return 0;
 }
@@ -696,18 +504,19 @@ file_store(hx509_context context,
           hx509_certs certs, void *data, int flags, hx509_lock lock)
 {
     struct ks_file *f = data;
-    FILE *fh;
+    struct store_ctx sc;
     int ret;
 
-    fh = fopen(f->fn, "w");
-    if (fh == NULL) {
+    sc.f = fopen(f->fn, "w");
+    if (sc.f == NULL) {
        hx509_set_error_string(context, 0, ENOENT,
                               "Failed to open file %s for writing");
        return ENOENT;
     }
+    sc.format = f->format;
 
-    ret = hx509_certs_iter(context, f->certs, store_func, fh);
-    fclose(fh);
+    ret = hx509_certs_iter(context, f->certs, store_func, &sc);
+    fclose(sc.f);
     return ret;
 }
 
@@ -767,7 +576,7 @@ file_addkey(hx509_context context,
 static struct hx509_keyset_ops keyset_file = {
     "FILE",
     0,
-    file_init,
+    file_init_pem,
     file_store,
     file_free,
     file_add,
@@ -780,8 +589,43 @@ static struct hx509_keyset_ops keyset_file = {
     file_addkey
 };
 
+static struct hx509_keyset_ops keyset_pemfile = {
+    "PEM-FILE",
+    0,
+    file_init_pem,
+    file_store,
+    file_free,
+    file_add,
+    NULL,
+    file_iter_start,
+    file_iter,
+    file_iter_end,
+    NULL,
+    file_getkeys,
+    file_addkey
+};
+
+static struct hx509_keyset_ops keyset_derfile = {
+    "DER-FILE",
+    0,
+    file_init_der,
+    file_store,
+    file_free,
+    file_add,
+    NULL,
+    file_iter_start,
+    file_iter,
+    file_iter_end,
+    NULL,
+    file_getkeys,
+    file_addkey
+};
+
+
 void
 _hx509_ks_file_register(hx509_context context)
 {
     _hx509_ks_register(context, &keyset_file);
+    _hx509_ks_register(context, &keyset_pemfile);
+    _hx509_ks_register(context, &keyset_derfile);
 }
index 2f0f72cd147e58ef8713f108a6823e49680728ae..33c4d6774b37ed3aaa5cc3eb0db62ef28c228380 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id: ks_keychain.c 20945 2007-06-06 22:17:17Z lha $");
+RCSID("$Id: ks_keychain.c 21097 2007-06-16 07:00:49Z lha $");
 
 #ifdef HAVE_FRAMEWORK_SECURITY
 
@@ -254,6 +254,7 @@ set_private_key(hx509_context context,
  */
 
 struct ks_keychain {
+    int anchors;
     SecKeychainRef keychain;
 };
 
@@ -263,7 +264,6 @@ keychain_init(hx509_context context,
              const char *residue, hx509_lock lock)
 {
     struct ks_keychain *ctx;
-    OSStatus ret;
 
     ctx = calloc(1, sizeof(*ctx));
     if (ctx == NULL) {
@@ -272,13 +272,20 @@ keychain_init(hx509_context context,
     }
 
     if (residue) {
-       if (strcasecmp(residue, "system") == 0)
-           residue = "/System/Library/Keychains/X509Anchors";
-
-       ret = SecKeychainOpen(residue, &ctx->keychain);
-       if (ret != noErr) {
+       if (strcasecmp(residue, "system-anchors") == 0) {
+           ctx->anchors = 1;
+       } else if (strncasecmp(residue, "FILE:", 5) == 0) {
+           OSStatus ret;
+
+           ret = SecKeychainOpen(residue + 5, &ctx->keychain);
+           if (ret != noErr) {
+               hx509_set_error_string(context, 0, ENOENT, 
+                                      "Failed to open %s", residue);
+               return ENOENT;
+           }
+       } else {
            hx509_set_error_string(context, 0, ENOENT, 
-                                  "Failed to open %s", residue);
+                                  "Unknown subtype %s", residue);
            return ENOENT;
        }
     }
@@ -307,6 +314,8 @@ keychain_free(hx509_certs certs, void *data)
  */
 
 struct iter {
+    hx509_certs certs;
+    void *cursor;
     SecKeychainSearchRef searchRef;
 };
 
@@ -316,7 +325,6 @@ keychain_iter_start(hx509_context context,
 {
     struct ks_keychain *ctx = data;
     struct iter *iter;
-    OSStatus ret;
 
     iter = calloc(1, sizeof(*iter));
     if (iter == NULL) {
@@ -324,15 +332,66 @@ keychain_iter_start(hx509_context context,
        return ENOMEM;
     }
 
-    ret = SecKeychainSearchCreateFromAttributes(ctx->keychain,
-                                               kSecCertificateItemClass,
-                                               NULL,
-                                               &iter->searchRef);
-    if (ret) {
-       free(iter);
-       hx509_set_error_string(context, 0, ret, 
-                              "Failed to start search for attributes");
-       return ENOMEM;
+    if (ctx->anchors) {
+        CFArrayRef anchors;
+       int ret;
+       int i;
+
+       ret = hx509_certs_init(context, "MEMORY:ks-file-create", 
+                              0, NULL, &iter->certs);
+       if (ret) {
+           free(iter);
+           return ret;
+       }
+
+       ret = SecTrustCopyAnchorCertificates(&anchors);
+       if (ret != 0) {
+           hx509_certs_free(&iter->certs);
+           free(iter);
+           hx509_set_error_string(context, 0, ENOMEM, 
+                                  "Can't get trust anchors from Keychain");
+           return ENOMEM;
+       }
+       for (i = 0; i < CFArrayGetCount(anchors); i++) {
+           SecCertificateRef cr; 
+           hx509_cert cert;
+           CSSM_DATA cssm;
+
+           cr = (SecCertificateRef)CFArrayGetValueAtIndex(anchors, i);
+
+           SecCertificateGetData(cr, &cssm);
+
+           ret = hx509_cert_init_data(context, cssm.Data, cssm.Length, &cert);
+           if (ret)
+               continue;
+
+           ret = hx509_certs_add(context, iter->certs, cert);
+           hx509_cert_free(cert);
+       }
+       CFRelease(anchors);
+    }
+
+    if (iter->certs) {
+       int ret;
+       ret = hx509_certs_start_seq(context, iter->certs, &iter->cursor);
+       if (ret) {
+           hx509_certs_free(&iter->certs);
+           free(iter);
+           return ret;
+       }
+    } else {
+       OSStatus ret;
+
+       ret = SecKeychainSearchCreateFromAttributes(ctx->keychain,
+                                                   kSecCertificateItemClass,
+                                                   NULL,
+                                                   &iter->searchRef);
+       if (ret) {
+           free(iter);
+           hx509_set_error_string(context, 0, ret, 
+                                  "Failed to start search for attributes");
+           return ENOMEM;
+       }
     }
 
     *cursor = iter;
@@ -349,15 +408,16 @@ keychain_iter(hx509_context context,
 {
     SecKeychainAttributeList *attrs = NULL;
     SecKeychainAttributeInfo attrInfo;
-    uint32 attrFormat = 0;
+    uint32 attrFormat[1] = { 0 };
     SecKeychainItemRef itemRef;
-    SecItemAttr item;
+    SecItemAttr item[1];
     struct iter *iter = cursor;
-    Certificate t;
     OSStatus ret;
     UInt32 len;
     void *ptr = NULL;
-    size_t size;
+
+    if (iter->certs)
+       return hx509_certs_next_cert(context, iter->certs, iter->cursor, cert);
 
     *cert = NULL;
 
@@ -371,26 +431,18 @@ keychain_iter(hx509_context context,
      * Pick out certificate and matching "keyid"
      */
 
-    item = kSecPublicKeyHashItemAttr;
+    item[0] = kSecPublicKeyHashItemAttr;
 
     attrInfo.count = 1;
-    attrInfo.tag = &item;
-    attrInfo.format = &attrFormat;
+    attrInfo.tag = item;
+    attrInfo.format = attrFormat;
   
     ret = SecKeychainItemCopyAttributesAndData(itemRef, &attrInfo, NULL,
                                               &attrs, &len, &ptr);
     if (ret)
        return EINVAL;
-    
-    ret = decode_Certificate(ptr, len, &t, &size);
-    CFRelease(itemRef);
-    if (ret) {
-       hx509_set_error_string(context, 0, ret, "Failed to parse certificate");
-       goto out;
-    }
 
-    ret = hx509_cert_init(context, &t, cert);
-    free_Certificate(&t);
+    ret = hx509_cert_init_data(context, ptr, len, cert);
     if (ret)
        goto out;
 
@@ -449,7 +501,14 @@ keychain_iter_end(hx509_context context,
 {
     struct iter *iter = cursor;
 
-    CFRelease(iter->searchRef);
+    if (iter->certs) {
+       int ret;
+       ret = hx509_certs_end_seq(context, iter->certs, iter->cursor);
+       hx509_certs_free(&iter->certs);
+    } else {
+       CFRelease(iter->searchRef);
+    }
+
     memset(iter, 0, sizeof(*iter));
     free(iter);
     return 0;
index 90c716213fd450b747e3ab1f9f5cced3973d2098..b899005b333fbe00a2a4015e8395f13f4e42c14f 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id: ks_p11.c 20920 2007-06-05 05:47:06Z lha $");
+RCSID("$Id: ks_p11.c 21085 2007-06-13 06:39:53Z lha $");
 #ifdef HAVE_DLFCN_H
 #include <dlfcn.h>
 #endif
@@ -682,7 +682,6 @@ collect_cert(hx509_context context,
 {
     struct hx509_collector *collector = ptr;
     hx509_cert cert;
-    Certificate t;
     int ret;
 
     if ((CK_LONG)query[0].ulValueLen == -1 ||
@@ -691,16 +690,8 @@ collect_cert(hx509_context context,
        return 0;
     }
 
-
-    ret = decode_Certificate(query[1].pValue, query[1].ulValueLen,
-                            &t, NULL);
-    if (ret) {
-       hx509_clear_error_string(context);
-       return 0;
-    }
-
-    ret = hx509_cert_init(context, &t, &cert);
-    free_Certificate(&t);
+    ret = hx509_cert_init_data(context, query[1].pValue, 
+                              query[1].ulValueLen, &cert);
     if (ret)
        return ret;
 
index 5fddbd07def011589a31bc7124c22e6b64657108..12756e6c071dbfd10479e59f1d2aa1537e36314c 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id: ks_p12.c 20909 2007-06-05 03:09:13Z lha $");
+RCSID("$Id: ks_p12.c 21146 2007-06-18 21:37:25Z lha $");
 
 struct ks_pkcs12 {
     hx509_certs certs;
@@ -90,7 +90,7 @@ keyBag_parser(hx509_context context,
                                     &ki.privateKeyAlgorithm,
                                     NULL,
                                     &ki.privateKey,
-                                    &attr->attrValues);
+                                    os);
     free_PKCS8PrivateKeyInfo(&ki);
     return 0;
 }
@@ -132,7 +132,6 @@ certBag_parser(hx509_context context,
               const PKCS12_Attributes *attrs)
 {
     heim_octet_string os;
-    Certificate t;
     hx509_cert cert;
     PKCS12_CertBag cb;
     int ret;
@@ -154,16 +153,11 @@ certBag_parser(hx509_context context,
     if (ret)
        return ret;
 
-    ret = decode_Certificate(os.data, os.length, &t, NULL);
+    ret = hx509_cert_init_data(context, os.data, os.length, &cert);
     der_free_octet_string(&os);
     if (ret)
        return ret;
 
-    ret = hx509_cert_init(context, &t, &cert);
-    free_Certificate(&t);
-    if (ret)
-       return ret;
-
     ret = _hx509_collector_certs_add(context, c, cert);
     if (ret) {
        hx509_cert_free(cert);
@@ -437,7 +431,9 @@ p12_init(hx509_context context,
 out:
     _hx509_collector_free(c);
 
-    if (ret) {
+    if (ret && p12) {
+       if (p12->fn)
+           free(p12->fn);
        if (p12->certs)
            hx509_certs_free(&p12->certs);
        free(p12);
index 34e3a4ea27c22ff6a85b0ad4fcf520877a1e58b5..d7a85e1cecd20291136bd9df6542a13c5c535233 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "hx_locl.h"
 #include <pkcs10_asn1.h>
-RCSID("$Id: req.c 20934 2007-06-06 15:30:02Z lha $");
+RCSID("$Id: req.c 21344 2007-06-26 14:22:34Z lha $");
 
 struct hx509_request_data {
     hx509_name name;
@@ -84,6 +84,18 @@ _hx509_request_set_name(hx509_context context,
     return 0;
 }
 
+int
+_hx509_request_get_name(hx509_context context,
+                       hx509_request req,
+                       hx509_name *name)
+{
+    if (req->name == NULL) {
+       hx509_set_error_string(context, 0, EINVAL, "Request have no name");
+       return EINVAL;
+    }
+    return hx509_name_copy(context, req->name, name);
+}
+
 int
 _hx509_request_set_SubjectPublicKeyInfo(hx509_context context,
                                        hx509_request req,
@@ -93,6 +105,14 @@ _hx509_request_set_SubjectPublicKeyInfo(hx509_context context,
     return copy_SubjectPublicKeyInfo(key, &req->key);
 }
 
+int
+_hx509_request_get_SubjectPublicKeyInfo(hx509_context context,
+                                       hx509_request req,
+                                       SubjectPublicKeyInfo *key)
+{
+    return copy_SubjectPublicKeyInfo(&req->key, key);
+}
+
 int
 _hx509_request_add_eku(hx509_context context,
                       hx509_request req,
@@ -215,3 +235,91 @@ out:
 
     return ret;
 }
+
+int
+_hx509_request_parse(hx509_context context, 
+                    const char *path,
+                    hx509_request *req)
+{
+    CertificationRequest r;
+    CertificationRequestInfo *rinfo;
+    hx509_name subject;
+    size_t len, size;
+    void *p;
+    int ret;
+
+    if (strncmp(path, "PKCS10:", 7) != 0) {
+       hx509_set_error_string(context, 0, HX509_UNSUPPORTED_OPERATION,
+                              "unsupport type in %s", path);
+       return HX509_UNSUPPORTED_OPERATION;
+    }
+    path += 7;
+
+    /* XXX PEM request */
+
+    ret = _hx509_map_file(path, &p, &len, NULL);
+    if (ret) {
+       hx509_set_error_string(context, 0, ret, "Failed to map file %s", path);
+       return ret;
+    }
+
+    ret = decode_CertificationRequest(p, len, &r, &size);
+    _hx509_unmap_file(p, len);
+    if (ret) {
+       hx509_set_error_string(context, 0, ret, "Failed to decode %s", path);
+       return ret;
+    }
+
+    ret = _hx509_request_init(context, req);
+    if (ret) {
+       free_CertificationRequest(&r);
+       return ret;
+    }
+
+    rinfo = &r.certificationRequestInfo;
+
+    ret = _hx509_request_set_SubjectPublicKeyInfo(context, *req,
+                                                 &rinfo->subjectPKInfo);
+    if (ret) {
+       free_CertificationRequest(&r);
+       _hx509_request_free(req);
+       return ret;
+    }
+
+    ret = _hx509_name_from_Name(&rinfo->subject, &subject);
+    if (ret) {
+       free_CertificationRequest(&r);
+       _hx509_request_free(req);
+       return ret;
+    }
+    ret = _hx509_request_set_name(context, *req, subject);
+    hx509_name_free(&subject);
+    free_CertificationRequest(&r);
+    if (ret) {
+       _hx509_request_free(req);
+       return ret;
+    }
+
+    return 0;
+}
+
+
+int
+_hx509_request_print(hx509_context context, hx509_request req, FILE *f)
+{
+    int ret;
+
+    if (req->name) {
+       char *subject;
+       ret = hx509_name_to_string(req->name, &subject);
+       if (ret) {
+           hx509_set_error_string(context, 0, ret, "Failed to print name");
+           return ret;
+       }
+        fprintf(f, "name: %s\n", subject);
+       free(subject);
+    }
+    
+    return 0;
+}
+
index 0d477945c88d1e6641fd4ca506013790dc0d151b..ddcb17ee38d82ae3faf1fb460556cd0ca8128881 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #include "hx_locl.h"
-RCSID("$Id: revoke.c 20871 2007-06-03 21:22:51Z lha $");
+RCSID("$Id: revoke.c 21153 2007-06-18 21:55:46Z lha $");
 
 struct revoke_crl {
     char *path;
@@ -572,10 +572,10 @@ hx509_revoke_verify(hx509_context context,
                continue;
        }
 
-       for (i = 0; i < ocsp->ocsp.tbsResponseData.responses.len; i++) {
+       for (j = 0; j < ocsp->ocsp.tbsResponseData.responses.len; j++) {
            heim_octet_string os;
 
-           ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[i].certID.serialNumber,
+           ret = der_heim_integer_cmp(&ocsp->ocsp.tbsResponseData.responses.val[j].certID.serialNumber,
                                   &c->tbsCertificate.serialNumber);
            if (ret != 0)
                continue;
@@ -594,13 +594,13 @@ hx509_revoke_verify(hx509_context context,
 
            ret = _hx509_verify_signature(context,
                                          NULL,
-                                         &ocsp->ocsp.tbsResponseData.responses.val[i].certID.hashAlgorithm,
+                                         &ocsp->ocsp.tbsResponseData.responses.val[j].certID.hashAlgorithm,
                                          &os,
-                                         &ocsp->ocsp.tbsResponseData.responses.val[i].certID.issuerKeyHash);
+                                         &ocsp->ocsp.tbsResponseData.responses.val[j].certID.issuerKeyHash);
            if (ret != 0)
                continue;
 
-           switch (ocsp->ocsp.tbsResponseData.responses.val[i].certStatus.element) {
+           switch (ocsp->ocsp.tbsResponseData.responses.val[j].certStatus.element) {
            case choice_OCSPCertStatus_good:
                break;
            case choice_OCSPCertStatus_revoked:
@@ -609,13 +609,13 @@ hx509_revoke_verify(hx509_context context,
            }
 
            /* don't allow the update to be in the future */
-           if (ocsp->ocsp.tbsResponseData.responses.val[i].thisUpdate > 
+           if (ocsp->ocsp.tbsResponseData.responses.val[j].thisUpdate > 
                now + context->ocsp_time_diff)
                continue;
 
            /* don't allow the next updte to be in the past */
-           if (ocsp->ocsp.tbsResponseData.responses.val[i].nextUpdate) {
-               if (*ocsp->ocsp.tbsResponseData.responses.val[i].nextUpdate < now)
+           if (ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate) {
+               if (*ocsp->ocsp.tbsResponseData.responses.val[j].nextUpdate < now)
                    continue;
            } else
                /* Should force a refetch, but can we ? */;
@@ -1077,6 +1077,7 @@ hx509_crl_alloc(hx509_context context, hx509_crl *crl)
     if (ret) {
        free(*crl);
        *crl = NULL;
+       return ret;
     }
     (*crl)->expire = 0;
     return ret;
index 93f3e44ba1c34050d57bc3141b5ac79986114cd3..12f75d0bcde6c656c9518fa31fa07cd49e161349 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #include "krb5_locl.h"
-RCSID("$Id: crypto.c 20981 2007-06-07 20:05:50Z lha $");
+RCSID("$Id: crypto.c 21130 2007-06-18 20:45:21Z lha $");
 
 #undef CRYPTO_DEBUG
 #ifdef CRYPTO_DEBUG
@@ -3162,8 +3162,9 @@ decrypt_internal_derived(krb5_context context,
     unsigned long l;
     
     checksum_sz = CHECKSUMSIZE(et->keyed_checksum);
-    if (len < checksum_sz) {
-       krb5_set_error_string(context, "Encrypted data shorter then checksum");
+    if (len < checksum_sz + et->confoundersize) {
+       krb5_set_error_string(context, "Encrypted data shorter then "
+                             "checksum + confunder");
        return KRB5_BAD_MSIZE;
     }
 
index 761224b82c84b5ea67970e661d3b1c3b40467e4f..8a0af23e408f77e05c211dd442047ebf6bcc4d50 100644 (file)
@@ -33,7 +33,7 @@
 
 #include <krb5_locl.h>
 
-RCSID("$Id: get_cred.c 21004 2007-06-08 01:53:10Z lha $");
+RCSID("$Id: get_cred.c 21327 2007-06-26 10:54:15Z lha $");
 
 /*
  * Take the `body' and encode it into `padata' using the credentials
@@ -411,7 +411,6 @@ get_cred_kdc_usage(krb5_context context,
     krb5_keyblock *subkey = NULL;
     size_t len;
     Ticket second_ticket_data;
-    int send_to_kdc_flags = 0;
     METHOD_DATA padata;
     
     krb5_data_zero(&resp);
@@ -511,11 +510,18 @@ get_cred_kdc_usage(krb5_context context,
     /*
      * Send and receive
      */
-again:
-    ret = krb5_sendto_kdc_flags (context, &enc, 
-                                &krbtgt->server->name.name_string.val[1],
-                                &resp,
-                                send_to_kdc_flags);
+    {
+       krb5_sendto_ctx stctx;
+       ret = krb5_sendto_ctx_alloc(context, &stctx);
+       if (ret)
+           return ret;
+       krb5_sendto_ctx_set_func(stctx, _krb5_kdc_retry, NULL);
+
+       ret = krb5_sendto_context (context, stctx, &enc,
+                                  krbtgt->server->name.name_string.val[1],
+                                  &resp);
+       krb5_sendto_ctx_free(context, stctx);
+    }
     if(ret)
        goto out;
 
@@ -550,12 +556,6 @@ again:
     } 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);
-
-       if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG && !(send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG)) {
-           send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
-           krb5_data_free(&resp);
-           goto again;
-       }
     } else if(resp.data && ((char*)resp.data)[0] == 4) {
        ret = KRB5KRB_AP_ERR_V4_REPLY;
        krb5_clear_error_string(context);
@@ -1191,6 +1191,10 @@ krb5_get_creds(krb5_context context,
        flags.b.forwardable = 1;
     if (options & KRB5_GC_NO_TRANSIT_CHECK)
        flags.b.disable_transited_check = 1;
+    if (options & KRB5_GC_CONSTRAINED_DELEGATION) {
+       flags.b.request_anonymous = 1; /* XXX ARGH confusion */
+       flags.b.constrained_delegation = 1;
+    }
 
     tgts = NULL;
     ret = get_cred_from_kdc_flags(context, flags, ccache, 
@@ -1206,3 +1210,62 @@ krb5_get_creds(krb5_context context,
        krb5_cc_store_cred(context, ccache, *out_creds);
     return ret;
 }
+
+/*
+ *
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_renewed_creds(krb5_context context,
+                      krb5_creds *creds,
+                      krb5_const_principal client,
+                      krb5_ccache ccache,
+                      const char *in_tkt_service)
+{
+    krb5_error_code ret;
+    krb5_kdc_flags flags;
+    krb5_creds in, *template;
+
+    memset(&in, 0, sizeof(in));
+
+    ret = krb5_copy_principal(context, client, &in.client);
+    if (ret)
+       return ret;
+
+    if (in_tkt_service) {
+       ret = krb5_parse_name(context, in_tkt_service, &in.server);
+       if (ret) {
+           krb5_free_principal(context, in.client);
+           return ret;
+       }
+    } else {
+       const char *realm = krb5_principal_get_realm(context, client);
+       
+       ret = krb5_make_principal(context, &in.server, realm, KRB5_TGS_NAME,
+                                 realm, NULL);
+       if (ret) {
+           krb5_free_principal(context, in.client);
+           return ret;
+       }
+    }
+
+    flags.i = 0;
+    flags.b.renewable = flags.b.renew = 1;
+
+    /*
+     * Get template from old credential cache for the same entry, if
+     * this failes, no worries.
+     */
+    ret = krb5_get_credentials(context, KRB5_GC_CACHED, ccache, &in, &template);
+    if (ret == 0) {
+       flags.b.forwardable = template->flags.b.forwardable;
+       flags.b.proxiable = template->flags.b.proxiable;
+       krb5_free_creds (context, template);
+    }
+
+    ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &in, &creds);
+    krb5_free_principal(context, in.client);
+    krb5_free_principal(context, in.server);
+
+    return ret;
+}
index a58435a9eaf7ff0db00e965e64704aad26d26b77..1676da3bd627ff43b12154387c921b2a755c13ef 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "krb5_locl.h"
 
-RCSID("$Id: init_creds_pw.c 20262 2007-02-18 00:33:01Z lha $");
+RCSID("$Id: init_creds_pw.c 21061 2007-06-12 17:56:30Z lha $");
 
 typedef struct krb5_get_init_creds_ctx {
     KDCOptions flags;
@@ -1221,8 +1221,8 @@ init_cred_loop(krb5_context context,
     krb5_data resp;
     size_t len;
     size_t size;
-    int send_to_kdc_flags = 0;
     krb5_krbhst_info *hi = NULL;
+    krb5_sendto_ctx stctx = NULL;
 
 
     memset(&md, 0, sizeof(md));
@@ -1238,6 +1238,11 @@ init_cred_loop(krb5_context context,
     if (ret)
        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;
@@ -1281,10 +1286,9 @@ init_cred_loop(krb5_context context,
        if(len != ctx->req_buffer.length)
            krb5_abortx(context, "internal error in ASN.1 encoder");
 
-       ret = krb5_sendto_kdc_flags (context, &ctx->req_buffer, 
-                                    &creds->client->realm, &resp,
-                                    send_to_kdc_flags);
-       if (ret)
+       ret = krb5_sendto_context (context, stctx, &ctx->req_buffer,
+                                  creds->client->realm, &resp);
+       if (ret)
            goto out;
 
        memset (&rep, 0, sizeof(rep));
@@ -1329,16 +1333,6 @@ init_cred_loop(krb5_context context,
                krb5_free_error_contents(context, &error);
                if (ret)
                    goto out;
-           } else if (ret == KRB5KRB_ERR_RESPONSE_TOO_BIG) {
-               if (send_to_kdc_flags & KRB5_KRBHST_FLAGS_LARGE_MSG) {
-                   if (ret_as_reply)
-                       rep.error = error;
-                   else
-                       krb5_free_error_contents(context, &error);
-                   goto out;
-               }
-               krb5_free_error_contents(context, &error);
-               send_to_kdc_flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
            } else {
                _krb5_get_init_creds_opt_set_krb5_error(context,
                                                        init_cred_opts,
@@ -1437,6 +1431,8 @@ init_cred_loop(krb5_context context,
        }
     }
 out:
+    if (stctx)
+       krb5_sendto_ctx_free(context, stctx);
     krb5_data_free(&ctx->req_buffer);
     free_METHOD_DATA(&md);
     memset(&md, 0, sizeof(md));
index be718f67143391f7b0e40a53fa7aac5678566395..a551c42ecd1dfed3b7f9e9fbad58f64be8bcd572 100644 (file)
@@ -149,6 +149,14 @@ _krb5_kcm_noop (
        krb5_context /*context*/,
        krb5_ccache /*id*/);
 
+krb5_error_code
+_krb5_kdc_retry (
+       krb5_context /*context*/,
+       krb5_sendto_ctx /*ctx*/,
+       void */*data*/,
+       const krb5_data */*reply*/,
+       int */*action*/);
+
 krb5_error_code KRB5_LIB_FUNCTION
 _krb5_krb_cr_err_reply (
        krb5_context /*context*/,
index e852bffeb1af40a06db60369473f395a1d15fa80..058496434e067e390805cd64e126d693ed9657b9 100644 (file)
@@ -2243,6 +2243,14 @@ krb5_get_pw_salt (
        krb5_const_principal /*principal*/,
        krb5_salt */*salt*/);
 
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_get_renewed_creds (
+       krb5_context /*context*/,
+       krb5_creds */*creds*/,
+       krb5_const_principal /*client*/,
+       krb5_ccache /*ccache*/,
+       const char */*in_tkt_service*/);
+
 krb5_error_code KRB5_LIB_FUNCTION
 krb5_get_server_rcache (
        krb5_context /*context*/,
@@ -2868,6 +2876,12 @@ krb5_parse_name_flags (
        int /*flags*/,
        krb5_principal */*principal*/);
 
+krb5_error_code
+krb5_parse_nametype (
+       krb5_context /*context*/,
+       const char */*str*/,
+       int32_t */*nametype*/);
+
 const char* KRB5_LIB_FUNCTION
 krb5_passwd_result_to_string (
        krb5_context /*context*/,
@@ -3071,7 +3085,7 @@ krb5_rd_cred2 (
 krb5_error_code KRB5_LIB_FUNCTION
 krb5_rd_error (
        krb5_context /*context*/,
-       krb5_data */*msg*/,
+       const krb5_data */*msg*/,
        KRB_ERROR */*result*/);
 
 krb5_error_code KRB5_LIB_FUNCTION
@@ -3346,6 +3360,43 @@ krb5_sendto (
        krb5_krbhst_handle /*handle*/,
        krb5_data */*receive*/);
 
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto_context (
+       krb5_context /*context*/,
+       krb5_sendto_ctx /*ctx*/,
+       const krb5_data */*send_data*/,
+       const krb5_realm /*realm*/,
+       krb5_data */*receive*/);
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_add_flags (
+       krb5_sendto_ctx /*ctx*/,
+       int /*flags*/);
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto_ctx_alloc (
+       krb5_context /*context*/,
+       krb5_sendto_ctx */*ctx*/);
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_free (
+       krb5_context /*context*/,
+       krb5_sendto_ctx /*ctx*/);
+
+int KRB5_LIB_FUNCTION
+krb5_sendto_ctx_get_flags (krb5_sendto_ctx /*ctx*/);
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_set_func (
+       krb5_sendto_ctx /*ctx*/,
+       krb5_sendto_ctx_func /*func*/,
+       void */*data*/);
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_set_type (
+       krb5_sendto_ctx /*ctx*/,
+       int /*type*/);
+
 krb5_error_code KRB5_LIB_FUNCTION
 krb5_sendto_kdc (
        krb5_context /*context*/,
index eefda81ca903dcc87506daf27c2de61248c33b40..345fe70764f6069c2c3c0b2b8bd3a17c5aa32bfe 100644 (file)
@@ -31,7 +31,7 @@
  * SUCH DAMAGE. 
  */
 
-/* $Id: krb5.h 20245 2007-02-17 00:09:57Z lha $ */
+/* $Id: krb5.h 21252 2007-06-21 04:18:28Z lha $ */
 
 #ifndef __KRB5_H__
 #define __KRB5_H__
@@ -361,6 +361,7 @@ typedef union {
 #define KRB5_GC_NO_STORE               (1U << 3)
 #define KRB5_GC_FORWARDABLE            (1U << 4)
 #define KRB5_GC_NO_TRANSIT_CHECK       (1U << 5)
+#define KRB5_GC_CONSTRAINED_DELEGATION (1U << 6)
 
 /* constants for compare_creds (and cc_retrieve_cred) */
 #define KRB5_TC_DONT_MATCH_REALM       (1U << 31)
@@ -753,9 +754,18 @@ enum {
 /* flags for krb5_unparse_name_flags */
 enum {
     KRB5_PRINCIPAL_UNPARSE_SHORT = 1,
-    KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2
+    KRB5_PRINCIPAL_UNPARSE_NO_REALM = 2,
+    KRB5_PRINCIPAL_UNPARSE_DISPLAY = 4
 };
 
+typedef struct krb5_sendto_ctx *krb5_sendto_ctx;
+
+#define KRB5_SENDTO_DONE       0
+#define KRB5_SENDTO_RESTART    1
+#define KRB5_SENDTO_CONTINUE   2
+
+typedef krb5_error_code (*krb5_sendto_ctx_func)(krb5_context, krb5_sendto_ctx, void *, const krb5_data *, int *);
+
 struct credentials; /* this is to keep the compiler happy */
 struct getargs;
 struct sockaddr;
index 785c258ee0c2a4dbe165a8bc813afa1434031519..6714401e4503f1e880269986955de2ec65700465 100644 (file)
@@ -3,7 +3,7 @@
 #
 # This might look like a com_err file, but is not
 #
-id "$Id: krb5_err.et 20760 2007-06-01 03:24:49Z lha $"
+id "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $"
 
 error_table krb5
 
@@ -35,8 +35,10 @@ error_code KEY_EXPIRED,              "Password has expired"
 error_code PREAUTH_FAILED,     "Preauthentication failed"
 error_code PREAUTH_REQUIRED,   "Additional pre-authentication required"
 error_code SERVER_NOMATCH,     "Requested server and ticket don't match"
+error_code KDC_ERR_MUST_USE_USER2USER, "Server principal valid for user2user only"
+error_code PATH_NOT_ACCEPTED,   "KDC Policy rejects transited path"
+error_code SVC_UNAVAILABLE,    "A service is not available"
 
-# 27-30 are reserved
 index 31
 prefix KRB5KRB_AP
 error_code ERR_BAD_INTEGRITY,  "Decrypt integrity check failed"
@@ -108,7 +110,7 @@ error_code PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED, "Public key encryption not suppo
 
 index 128
 prefix
-error_code KRB5_ERR_RCSID,     "$Id: krb5_err.et 20760 2007-06-01 03:24:49Z lha $"
+error_code KRB5_ERR_RCSID,     "$Id: krb5_err.et 21050 2007-06-12 02:00:40Z lha $"
 
 error_code KRB5_LIBOS_BADLOCKFLAG,     "Invalid flag for file lock mode"
 error_code KRB5_LIBOS_CANTREADPWD,     "Cannot read password"
index 51bf934bfd159bfbbd4b097c239c6219152d7e5c..69b52dd808c296f7b6423a60130d99093df7a95b 100644 (file)
@@ -35,7 +35,7 @@
 #include <resolve.h>
 #include "locate_plugin.h"
 
-RCSID("$Id: krbhst.c 19198 2006-11-30 17:23:08Z lha $");
+RCSID("$Id: krbhst.c 21131 2007-06-18 20:48:09Z lha $");
 
 static int
 string_to_proto(const char *string)
@@ -501,10 +501,8 @@ add_locate(void *ctx, int type, struct sockaddr *addr)
     hostlen = strlen(host);
 
     hi = calloc(1, sizeof(*hi) + hostlen);
-    if(hi == NULL) {
-       free(host);
+    if(hi == NULL)
        return ENOMEM;
-    }
     
     hi->proto = krbhst_get_default_proto(kd);
     hi->port  = hi->def_port = socket_get_port(addr);
index 0d410b57d218bfea469215a9c3d5c70cae87f2de..8050bdb9b467eca07464e79a7a9e9df74a54062a 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "krb5_locl.h"
 
-RCSID("$Id: misc.c 17616 2006-06-06 14:57:47Z lha $");
+RCSID("$Id: misc.c 21174 2007-06-19 10:10:58Z lha $");
 
 krb5_error_code KRB5_LIB_FUNCTION
 _krb5_s4u2self_to_checksumdata(krb5_context context, 
@@ -51,6 +51,7 @@ _krb5_s4u2self_to_checksumdata(krb5_context context,
        krb5_clear_error_string(context);
        return ENOMEM;
     }
+    krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
     ret = krb5_store_int32(sp, self->name.name_type);
     if (ret)
        goto out;
index 55d4f5ff5646165fed066b50c4e8ae980f523740..f7a5e83ea3470b504bbd042c879f9f180e6d7196 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "krb5_locl.h"
 
-RCSID("$Id: pac.c 20845 2007-06-03 14:31:16Z lha $");
+RCSID("$Id: pac.c 21149 2007-06-18 21:50:22Z lha $");
 
 struct PAC_INFO_BUFFER {
     uint32_t type;
@@ -409,6 +409,8 @@ verify_checksum(krb5_context context,
     krb5_error_code ret;
     Checksum cksum;
 
+    memset(&cksum, 0, sizeof(cksum));
+
     sp = krb5_storage_from_mem((char *)data->data + sig->offset_lo,
                               sig->buffersize);
     if (sp == NULL) {
index dd828420847681a84f7ac11399082987422c386d..105cab554d86814af483afb2450dd6522366dc8c 100755 (executable)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003 - 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2003 - 2007 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden). 
  * All rights reserved. 
  *
@@ -33,7 +33,7 @@
 
 #include "krb5_locl.h"
 
-RCSID("$Id: pkinit.c 21004 2007-06-08 01:53:10Z lha $");
+RCSID("$Id: pkinit.c 21321 2007-06-26 05:21:56Z lha $");
 
 struct krb5_dh_moduli {
     char *name;
@@ -554,18 +554,13 @@ pk_mk_padata(krb5_context context,
     if (ret)
        goto out;
 
-    ret = _krb5_pk_mk_ContentInfo(context, &sd_buf, oid_id_pkcs7_signedData(), 
-                                 &content_info);
+    ret = hx509_cms_wrap_ContentInfo(oid_id_pkcs7_signedData(), &sd_buf, &buf);
     krb5_data_free(&sd_buf);
-    if (ret)
-       goto out;
-
-    ASN1_MALLOC_ENCODE(ContentInfo, buf.data, buf.length,
-                      &content_info, &size, ret);
-    if (ret)
+    if (ret) {
+       krb5_set_error_string(context,
+                             "ContentInfo wrapping of signedData failed");
        goto out;
-    if (buf.length != size)
-       krb5_abortx(context, "Internal ASN1 encoder error");
+    }
 
     if (ctx->type == COMPAT_WIN2K) {
        PA_PK_AS_REQ_Win2k winreq;
@@ -794,6 +789,7 @@ get_reply_key_win(krb5_context context,
     if (ret) {
        krb5_set_error_string(context, "PKINIT failed copying reply key");
        free(*key);
+       *key = NULL;
     }
 
     return ret;
@@ -856,6 +852,7 @@ get_reply_key(krb5_context context,
     if (ret) {
        krb5_set_error_string(context, "PKINIT failed copying reply key");
        free(*key);
+       *key = NULL;
     }
 
     return ret;
@@ -929,6 +926,7 @@ pk_verify_host(krb5_context context,
     if (hi) {
        ret = hx509_verify_hostname(ctx->id->hx509ctx, host->cert, 
                                    ctx->require_hostname_match,
+                                   HX509_HN_HOSTNAME,
                                    hi->hostname,
                                    hi->ai->ai_addr, hi->ai->ai_addrlen);
 
@@ -942,7 +940,8 @@ pk_verify_host(krb5_context context,
 static krb5_error_code
 pk_rd_pa_reply_enckey(krb5_context context,
                      int type,
-                      const ContentInfo *rep,
+                     const heim_octet_string *indata,
+                     const heim_oid *dataType,
                      const char *realm,
                      krb5_pk_init_ctx ctx,
                      krb5_enctype etype,
@@ -954,27 +953,19 @@ pk_rd_pa_reply_enckey(krb5_context context,
 {
     krb5_error_code ret;
     struct krb5_pk_cert *host = NULL;
-    size_t size;
-    int length;
-    void *p;
     krb5_data content;
     heim_oid contentType = { 0, NULL };
 
-    if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), &rep->contentType)) {
+    if (der_heim_oid_cmp(oid_id_pkcs7_envelopedData(), dataType)) {
        krb5_set_error_string(context, "PKINIT: Invalid content type");
        return EINVAL;
     }
 
-    if (rep->content == NULL) {
-       krb5_set_error_string(context, "PKINIT: No content in reply");
-       return EINVAL;
-    }
-
     ret = hx509_cms_unenvelope(ctx->id->hx509ctx,
                               ctx->id->certs,
                               HX509_CMS_UE_DONT_REQUIRE_KU_ENCIPHERMENT,
-                              rep->content->data,
-                              rep->content->length,
+                              indata->data,
+                              indata->length,
                               NULL,
                               &contentType,
                               &content);
@@ -983,41 +974,52 @@ pk_rd_pa_reply_enckey(krb5_context context,
                            "Failed to unenvelope CMS data in PK-INIT reply");
        return ret;
     }
+    der_free_oid(&contentType);
+
+#if 0 /* windows LH with interesting CMS packets, leaks memory */
+    {
+       size_t ph = 1 + der_length_len (length);
+       unsigned char *ptr = malloc(length + ph);
+       size_t l;
 
-    p = content.data;
-    length = content.length;
+       memcpy(ptr + ph, p, length);
+
+       ret = der_put_length_and_tag (ptr + ph - 1, ph, length,
+                                     ASN1_C_UNIV, CONS, UT_Sequence, &l);
+       if (ret)
+           return ret;
+       ptr += ph - l;
+       length += l;
+       p = ptr;
+    }
+#endif
 
     /* win2k uses ContentInfo */
     if (type == COMPAT_WIN2K) {
-       ContentInfo ci;
+       heim_oid type;
+       heim_octet_string out;
 
-       ret = decode_ContentInfo(p, length, &ci, &size);
-       if (ret) {
-           krb5_set_error_string(context,
-                                 "PKINIT: failed decoding ContentInfo: %d",
-                                 ret);
-           goto out;
-       }
-
-       if (der_heim_oid_cmp(&ci.contentType, oid_id_pkcs7_signedData())) {
+       ret = hx509_cms_unwrap_ContentInfo(&content, &type, &out, NULL);
+       if (der_heim_oid_cmp(&type, oid_id_pkcs7_signedData())) {
            ret = EINVAL; /* XXX */
            krb5_set_error_string(context, "PKINIT: Invalid content type");
+           der_free_oid(&type);
+           der_free_octet_string(&out);
            goto out;
        }
-       if (ci.content == NULL) {
-           ret = EINVAL; /* XXX */
-           krb5_set_error_string(context, "PKINIT: Invalid content type");
+       der_free_oid(&type);
+       krb5_data_free(&content);
+       ret = krb5_data_copy(&content, out.data, out.length);
+       der_free_octet_string(&out);
+       if (ret) {
+           krb5_set_error_string(context, "PKINIT: out of memory");
            goto out;
        }
-       krb5_data_free(&content);
-       content = *ci.content;
-       p = ci.content->data;
-       length = ci.content->length;
     }
 
     ret = _krb5_pk_verify_sign(context, 
-                              p,
-                              length,
+                              content.data,
+                              content.length,
                               ctx->id,
                               &contentType,
                               &content,
@@ -1073,7 +1075,8 @@ pk_rd_pa_reply_enckey(krb5_context context,
 
 static krb5_error_code
 pk_rd_pa_reply_dh(krb5_context context,
-                  const ContentInfo *rep,
+                 const heim_octet_string *indata,
+                 const heim_oid *dataType,
                  const char *realm,
                  krb5_pk_init_ctx ctx,
                  krb5_enctype etype,
@@ -1097,19 +1100,14 @@ pk_rd_pa_reply_dh(krb5_context context,
     krb5_data_zero(&content);
     memset(&kdc_dh_info, 0, sizeof(kdc_dh_info));
 
-    if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), &rep->contentType)) {
+    if (der_heim_oid_cmp(oid_id_pkcs7_signedData(), dataType)) {
        krb5_set_error_string(context, "PKINIT: Invalid content type");
        return EINVAL;
     }
 
-    if (rep->content == NULL) {
-       krb5_set_error_string(context, "PKINIT: No content in reply");
-       return EINVAL;
-    }
-
     ret = _krb5_pk_verify_sign(context, 
-                              rep->content->data,
-                              rep->content->length,
+                              indata->data,
+                              indata->length,
                               ctx->id,
                               &contentType,
                               &content,
@@ -1261,20 +1259,19 @@ _krb5_pk_rd_pa_reply(krb5_context context,
 {
     krb5_pk_init_ctx ctx = c;
     krb5_error_code ret;
-    ContentInfo ci;
     size_t size;
 
     /* Check for IETF PK-INIT first */
     if (ctx->type == COMPAT_IETF) {
        PA_PK_AS_REP rep;
+       heim_octet_string os, data;
+       heim_oid oid;
        
        if (pa->padata_type != KRB5_PADATA_PK_AS_REP) {
            krb5_set_error_string(context, "PKINIT: wrong padata recv");
            return EINVAL;
        }
 
-       memset(&rep, 0, sizeof(rep));
-
        ret = decode_PA_PK_AS_REP(pa->padata_value.data,
                                  pa->padata_value.length,
                                  &rep,
@@ -1286,49 +1283,42 @@ _krb5_pk_rd_pa_reply(krb5_context context,
 
        switch (rep.element) {
        case choice_PA_PK_AS_REP_dhInfo:
-           ret = decode_ContentInfo(rep.u.dhInfo.dhSignedData.data,
-                                    rep.u.dhInfo.dhSignedData.length,
-                                    &ci,
-                                    &size);
-           if (ret) {
-               krb5_set_error_string(context,
-                                     "PKINIT: decoding failed DH "
-                                     "ContentInfo: %d", ret);
-
-               free_PA_PK_AS_REP(&rep);
-               break;
-           }
-           ret = pk_rd_pa_reply_dh(context, &ci, realm, ctx, etype, hi,
-                                   ctx->clientDHNonce,
-                                   rep.u.dhInfo.serverDHNonce,
-                                   nonce, pa, key);
-           free_ContentInfo(&ci);
-           free_PA_PK_AS_REP(&rep);
-
+           os = rep.u.dhInfo.dhSignedData;
            break;
        case choice_PA_PK_AS_REP_encKeyPack:
-           ret = decode_ContentInfo(rep.u.encKeyPack.data,
-                                    rep.u.encKeyPack.length,
-                                    &ci,
-                                    &size);
-           free_PA_PK_AS_REP(&rep);
-           if (ret) {
-               krb5_set_error_string(context,
-                                     "PKINIT: -25 decoding failed "
-                                     "ContentInfo: %d", ret);
-               break;
-           }
-           ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &ci, realm, ctx,
-                                       etype, hi, nonce, req_buffer, pa, key);
-           free_ContentInfo(&ci);
-           return ret;
+           os = rep.u.encKeyPack;
+           break;
        default:
            free_PA_PK_AS_REP(&rep);
            krb5_set_error_string(context, "PKINIT: -27 reply "
                                  "invalid content type");
-           ret = EINVAL;
+           return EINVAL;
+       }
+
+       ret = hx509_cms_unwrap_ContentInfo(&os, &oid, &data, NULL);
+       if (ret) {
+           free_PA_PK_AS_REP(&rep);
+           krb5_set_error_string(context, "PKINIT: failed to unwrap CI");
+           return ret;
+       }
+
+       switch (rep.element) {
+       case choice_PA_PK_AS_REP_dhInfo:
+           ret = pk_rd_pa_reply_dh(context, &data, &oid, realm, ctx, etype, hi,
+                                   ctx->clientDHNonce,
+                                   rep.u.dhInfo.serverDHNonce,
+                                   nonce, pa, key);
            break;
+       case choice_PA_PK_AS_REP_encKeyPack:
+           ret = pk_rd_pa_reply_enckey(context, COMPAT_IETF, &data, &oid, realm, 
+                                       ctx, etype, hi, nonce, req_buffer, pa, key);
+           break;
+       default:
+           krb5_abortx(context, "pk-init as-rep case not possible to happen");
        }
+       der_free_octet_string(&data);
+       der_free_oid(&oid);
+       free_PA_PK_AS_REP(&rep);
 
     } else if (ctx->type == COMPAT_WIN2K) {
        PA_PK_AS_REP_Win2k w2krep;
@@ -1357,23 +1347,25 @@ _krb5_pk_rd_pa_reply(krb5_context context,
        krb5_clear_error_string(context);
        
        switch (w2krep.element) {
-       case choice_PA_PK_AS_REP_Win2k_encKeyPack:
-           ret = decode_ContentInfo(w2krep.u.encKeyPack.data,
-                                    w2krep.u.encKeyPack.length,
-                                    &ci,
-                                    &size);
+       case choice_PA_PK_AS_REP_Win2k_encKeyPack: {
+           heim_octet_string data;
+           heim_oid oid;
+           
+           ret = hx509_cms_unwrap_ContentInfo(&w2krep.u.encKeyPack, 
+                                              &oid, &data, NULL);
            free_PA_PK_AS_REP_Win2k(&w2krep);
            if (ret) {
-               krb5_set_error_string(context,
-                                     "PKINIT: decoding failed "
-                                     "ContentInfo: %d",
-                                     ret);
+               krb5_set_error_string(context, "PKINIT: failed to unwrap CI");
                return ret;
            }
-           ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &ci, realm, ctx,
-                                       etype, hi, nonce, req_buffer, pa, key);
-           free_ContentInfo(&ci);
+
+           ret = pk_rd_pa_reply_enckey(context, COMPAT_WIN2K, &data, &oid, realm,
+                                       ctx, etype, hi, nonce, req_buffer, pa, key);
+           der_free_octet_string(&data);
+           der_free_oid(&oid);
+
            break;
+       }
        default:
            free_PA_PK_AS_REP_Win2k(&w2krep);
            krb5_set_error_string(context, "PKINIT: win2k reply invalid "
@@ -1473,8 +1465,7 @@ _krb5_pk_load_id(krb5_context context,
     id = calloc(1, sizeof(*id));
     if (id == NULL) {
        krb5_set_error_string(context, "malloc: out of memory");
-       ret = ENOMEM;
-       goto out;
+       return ENOMEM;
     }  
 
     ret = hx509_context_init(&id->hx509ctx);
index f19464bf3c8609452fa1ffc24b13a2d0e3a99298..68317a12c0d2594dc6e46a6aeecf1b9a0ac17097 100644 (file)
@@ -32,7 +32,7 @@
  */
 
 #include "krb5_locl.h"
-RCSID("$Id: plugin.c 19789 2007-01-09 17:46:01Z lha $");
+RCSID("$Id: plugin.c 21134 2007-06-18 21:02:23Z lha $");
 #ifdef HAVE_DLFCN_H
 #include <dlfcn.h>
 #endif
@@ -96,6 +96,7 @@ loadlib(krb5_context context,
     (*e)->dsohandle = dlopen(lib, RTLD_LAZY);
     if ((*e)->dsohandle == NULL) {
        free(*e);
+       *e = NULL;
        krb5_set_error_string(context, "Failed to load %s: %s", 
                              lib, dlerror());
        return ENOMEM;
index ef3f5412db008ecd81d5e12c70c73f0c4e70770d..c1a29d266b636c01372d5e813a8d556eba11d4f6 100644 (file)
@@ -41,7 +41,7 @@
 #include <fnmatch.h>
 #include "resolve.h"
 
-RCSID("$Id: principal.c 20223 2007-02-15 04:17:04Z lha $");
+RCSID("$Id: principal.c 21285 2007-06-25 12:30:55Z lha $");
 
 #define princ_num_comp(P) ((P)->name.name_string.len)
 #define princ_type(P) ((P)->name.name_type)
@@ -281,15 +281,19 @@ krb5_parse_name(krb5_context context,
 
 static const char quotable_chars[] = " \n\t\b\\/@";
 static const char replace_chars[] = " ntb\\/@";
+static const char nq_chars[] = "    \\/@";
 
 #define add_char(BASE, INDEX, LEN, C) do { if((INDEX) < (LEN)) (BASE)[(INDEX)++] = (C); }while(0);
 
 static size_t
-quote_string(const char *s, char *out, size_t idx, size_t len)
+quote_string(const char *s, char *out, size_t idx, size_t len, int display)
 {
     const char *p, *q;
     for(p = s; *p && idx < len; p++){
-       if((q = strchr(quotable_chars, *p))){
+       q = strchr(quotable_chars, *p);
+       if (q && display) {
+           add_char(out, idx, len, replace_chars[q - quotable_chars]);
+       } else if (q) {
            add_char(out, idx, len, '\\');
            add_char(out, idx, len, replace_chars[q - quotable_chars]);
        }else
@@ -312,6 +316,7 @@ unparse_name_fixed(krb5_context context,
     int i;
     int short_form = (flags & KRB5_PRINCIPAL_UNPARSE_SHORT) != 0;
     int no_realm = (flags & KRB5_PRINCIPAL_UNPARSE_NO_REALM) != 0;
+    int display = (flags & KRB5_PRINCIPAL_UNPARSE_DISPLAY) != 0;
 
     if (!no_realm && princ_realm(principal) == NULL) {
        krb5_set_error_string(context, "Realm missing from principal, "
@@ -322,7 +327,7 @@ unparse_name_fixed(krb5_context context,
     for(i = 0; i < princ_num_comp(principal); i++){
        if(i)
            add_char(name, idx, len, '/');
-       idx = quote_string(princ_ncomp(principal, i), name, idx, len);
+       idx = quote_string(princ_ncomp(principal, i), name, idx, len, display);
        if(idx == len) {
            krb5_set_error_string(context, "Out of space printing principal");
            return ERANGE;
@@ -341,7 +346,7 @@ unparse_name_fixed(krb5_context context,
     }
     if(!short_form && !no_realm) {
        add_char(name, idx, len, '@');
-       idx = quote_string(princ_realm(principal), name, idx, len);
+       idx = quote_string(princ_realm(principal), name, idx, len, display);
        if(idx == len) {
            krb5_set_error_string(context, 
                                  "Out of space printing realm of principal");
@@ -1213,3 +1218,37 @@ krb5_sname_to_principal (krb5_context context,
     krb5_free_host_realm(context, realms);
     return ret;
 }
+
+static const struct {
+    const char *type;
+    int32_t value;
+} nametypes[] = {
+    { "UNKNOWN", KRB5_NT_UNKNOWN },
+    { "PRINCIPAL", KRB5_NT_PRINCIPAL },
+    { "SRV_INST", KRB5_NT_SRV_INST },
+    { "SRV_HST", KRB5_NT_SRV_HST },
+    { "SRV_XHST", KRB5_NT_SRV_XHST },
+    { "UID", KRB5_NT_UID },
+    { "X500_PRINCIPAL", KRB5_NT_X500_PRINCIPAL },
+    { "SMTP_NAME", KRB5_NT_SMTP_NAME },
+    { "ENTERPRISE_PRINCIPAL", KRB5_NT_ENTERPRISE_PRINCIPAL },
+    { "ENT_PRINCIPAL_AND_ID", KRB5_NT_ENT_PRINCIPAL_AND_ID },
+    { "MS_PRINCIPAL", KRB5_NT_MS_PRINCIPAL },
+    { "MS_PRINCIPAL_AND_ID", KRB5_NT_MS_PRINCIPAL_AND_ID },
+    { NULL }
+};
+
+krb5_error_code
+krb5_parse_nametype(krb5_context context, const char *str, int32_t *nametype)
+{
+    size_t i;
+    
+    for(i = 0; nametypes[i].type; i++) {
+       if (strcasecmp(nametypes[i].type, str) == 0) {
+           *nametype = nametypes[i].value;
+           return 0;
+       }
+    }
+    krb5_set_error_string(context, "Failed to find name type %s", str);
+    return KRB5_PARSE_MALFORMED;
+}
index 89615ee8ac71b7e08fdcf6dba351a87d0761a143..e7646467afdb784984314154a7f0185340a9b9e8 100644 (file)
 
 #include "krb5_locl.h"
 
-RCSID("$Id: rd_error.c 20304 2007-04-11 11:15:05Z lha $");
+RCSID("$Id: rd_error.c 21057 2007-06-12 17:22:31Z lha $");
 
 krb5_error_code KRB5_LIB_FUNCTION
 krb5_rd_error(krb5_context context,
-             krb5_data *msg,
+             const krb5_data *msg,
              KRB_ERROR *result)
 {
     
index 6c70244327667e47c9f4e92609fced41b0d3ced5..c1a4df2b01c8766993b8aac53bbf815d2b060f9d 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "krb5_locl.h"
 
-RCSID("$Id: send_to_kdc.c 19973 2007-01-17 17:19:52Z lha $");
+RCSID("$Id: send_to_kdc.c 21062 2007-06-12 17:58:57Z lha $");
 
 struct send_to_kdc {
     krb5_send_to_kdc_func func;
@@ -413,26 +413,16 @@ krb5_sendto_kdc_flags(krb5_context context,
                      int flags)
 {
     krb5_error_code ret;
-    krb5_krbhst_handle handle;
-    int type;
-
-    if ((flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc)
-       type = KRB5_KRBHST_ADMIN;
-    else
-       type = KRB5_KRBHST_KDC;
+    krb5_sendto_ctx ctx;
 
-    if (send_data->length > context->large_msg_size)
-       flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
-
-    ret = krb5_krbhst_init_flags(context, *realm, type, flags, &handle);
+    ret = krb5_sendto_ctx_alloc(context, &ctx);
     if (ret)
        return ret;
+    krb5_sendto_ctx_add_flags(ctx, flags);
+    krb5_sendto_ctx_set_func(ctx, _krb5_kdc_retry, NULL);
 
-    ret = krb5_sendto(context, send_data, handle, receive);
-    krb5_krbhst_free(context, handle);
-    if (ret == KRB5_KDC_UNREACH)
-       krb5_set_error_string(context,
-                             "unable to reach any KDC in realm %s", *realm);
+    ret = krb5_sendto_context(context, ctx, send_data, *realm, receive);
+    krb5_sendto_ctx_free(context, ctx);
     return ret;
 }
 
@@ -458,4 +448,157 @@ krb5_set_send_to_kdc_func(krb5_context context,
     return 0;
 }
 
+struct krb5_sendto_ctx {
+    int flags;
+    int type;
+    krb5_sendto_ctx_func func;
+    void *data;
+};
 
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto_ctx_alloc(krb5_context context, krb5_sendto_ctx *ctx)
+{
+    *ctx = calloc(1, sizeof(**ctx));
+    if (*ctx == NULL) {
+       krb5_set_error_string(context, "out of memory");
+       return ENOMEM;
+    }
+    return 0;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_add_flags(krb5_sendto_ctx ctx, int flags)
+{
+    ctx->flags |= flags;
+}
+
+int KRB5_LIB_FUNCTION
+krb5_sendto_ctx_get_flags(krb5_sendto_ctx ctx)
+{
+    return ctx->flags;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_set_type(krb5_sendto_ctx ctx, int type)
+{
+    ctx->type = type;
+}
+
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_set_func(krb5_sendto_ctx ctx,
+                        krb5_sendto_ctx_func func,
+                        void *data)
+{
+    ctx->func = func;
+    ctx->data = data;
+}
+
+void KRB5_LIB_FUNCTION
+krb5_sendto_ctx_free(krb5_context context, krb5_sendto_ctx ctx)
+{
+    memset(ctx, 0, sizeof(*ctx));
+    free(ctx);
+}
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_sendto_context(krb5_context context,
+                   krb5_sendto_ctx ctx,
+                   const krb5_data *send_data,
+                   const krb5_realm realm,
+                   krb5_data *receive)
+{
+    krb5_error_code ret;
+    krb5_krbhst_handle handle = NULL;
+    int type, freectx = 0;
+    int action;
+
+    krb5_data_zero(receive);
+
+    if (ctx == NULL) {
+       freectx = 1;
+       ret = krb5_sendto_ctx_alloc(context, &ctx);
+       if (ret)
+           return ret;
+    }
+
+    type = ctx->type;
+    if (type == 0) {
+       if ((ctx->flags & KRB5_KRBHST_FLAGS_MASTER) || context->use_admin_kdc)
+           type = KRB5_KRBHST_ADMIN;
+       else
+           type = KRB5_KRBHST_KDC;
+    }
+
+    if (send_data->length > context->large_msg_size)
+       ctx->flags |= KRB5_KRBHST_FLAGS_LARGE_MSG;
+
+    /* loop until we get back a appropriate response */
+
+    do {
+       action = KRB5_SENDTO_DONE;
+
+       krb5_data_free(receive);
+
+       if (handle == NULL) {
+           ret = krb5_krbhst_init_flags(context, realm, type, 
+                                        ctx->flags, &handle);
+           if (ret) {
+               if (freectx)
+                   krb5_sendto_ctx_free(context, ctx);
+               return ret;
+           }
+       }
+    
+       ret = krb5_sendto(context, send_data, handle, receive);
+       if (ret)
+           break;
+       if (ctx->func) {
+           ret = (*ctx->func)(context, ctx, ctx->data, receive, &action);
+           if (ret)
+               break;
+       }
+       if (action != KRB5_SENDTO_CONTINUE) {
+           krb5_krbhst_free(context, handle);
+           handle = NULL;
+       }
+    } while (action != KRB5_SENDTO_DONE);
+    if (handle)
+       krb5_krbhst_free(context, handle);
+    if (ret == KRB5_KDC_UNREACH)
+       krb5_set_error_string(context, 
+                             "unable to reach any KDC in realm %s", realm);
+    if (ret)
+       krb5_data_free(receive);
+    if (freectx)
+       krb5_sendto_ctx_free(context, ctx);
+    return ret;
+}
+
+krb5_error_code
+_krb5_kdc_retry(krb5_context context, krb5_sendto_ctx ctx, void *data,
+               const krb5_data *reply, int *action)
+{
+    krb5_error_code ret;
+    KRB_ERROR error;
+
+    if(krb5_rd_error(context, reply, &error))
+       return 0;
+
+    ret = krb5_error_from_rd_error(context, &error, NULL);
+    krb5_free_error_contents(context, &error);
+
+    switch(ret) {
+    case KRB5KRB_ERR_RESPONSE_TOO_BIG: {
+       if (krb5_sendto_ctx_get_flags(ctx) & KRB5_KRBHST_FLAGS_LARGE_MSG)
+           break;
+       krb5_sendto_ctx_add_flags(ctx, KRB5_KRBHST_FLAGS_LARGE_MSG);
+       *action = KRB5_SENDTO_RESTART;
+       break;
+    }
+    case KRB5KDC_ERR_SVC_UNAVAILABLE:
+       *action = KRB5_SENDTO_CONTINUE;
+       break;
+    }
+    return 0;
+}
index 2df32dfa50d9ea2dcee4c5420a71588410333c0a..438ba2b94d1a8f1019b436ce7cc26e8a06c1aa79 100644 (file)
@@ -33,6 +33,14 @@ heim_ntlm_calculate_ntlm2 (
        unsigned char ntlmv2[16],
        struct ntlm_buf */*answer*/);
 
+int
+heim_ntlm_calculate_ntlm2_sess (
+       const unsigned char clnt_nonce[8],
+       const unsigned char svr_chal[8],
+       const unsigned char ntlm_hash[16],
+       struct ntlm_buf */*lm*/,
+       struct ntlm_buf */*ntlm*/);
+
 int
 heim_ntlm_decode_targetinfo (
        struct ntlm_buf */*data*/,
index af950cc3b5205fe4ce6b161065fbabac937642e0..1961c7fa22f09b9f5c199175ee0c851bf12dd07f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006 Kungliga Tekniska Högskolan
+ * Copyright (c) 2006 - 2007 Kungliga Tekniska Högskolan
  * (Royal Institute of Technology, Stockholm, Sweden). 
  * All rights reserved. 
  *
@@ -33,7 +33,7 @@
 
 #include <config.h>
 
-RCSID("$Id: ntlm.c 20816 2007-06-03 04:36:31Z lha $");
+RCSID("$Id: ntlm.c 21317 2007-06-25 19:22:02Z lha $");
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -52,6 +52,12 @@ RCSID("$Id: ntlm.c 20816 2007-06-03 04:36:31Z lha $");
 #include <heimntlm.h>
 
 
+/*
+ * Source of NTLM information:
+ * http://davenport.sourceforge.net/ntlm.html
+ */
+
+
 struct sec_buffer {
     uint16_t length;
     uint16_t allocated;
@@ -760,6 +766,10 @@ splitandenc(unsigned char *hash,
     memset(key, 0, sizeof(key));
 }
 
+/*
+ * String-to-key function for NTLM
+ */
+
 int
 heim_ntlm_nt_key(const char *password, struct ntlm_buf *key)
 {
@@ -784,6 +794,10 @@ heim_ntlm_nt_key(const char *password, struct ntlm_buf *key)
     return 0;
 }
 
+/*
+ * Calculate NTLMv1 response hash
+ */
+
 int
 heim_ntlm_calculate_ntlm1(void *key, size_t len,
                          unsigned char challange[8],
@@ -809,6 +823,10 @@ heim_ntlm_calculate_ntlm1(void *key, size_t len,
     return 0;
 }
 
+/*
+ * Calculate NTLMv1 master key
+ */
+
 int
 heim_ntlm_build_ntlm1_master(void *key, size_t len,
                             struct ntlm_buf *session,
@@ -880,8 +898,8 @@ heim_ntlm_ntlmv2_key(const void *key, size_t len,
        ascii2ucs2le(username, 1, &buf);
        HMAC_Update(&c, buf.data, buf.length);
        free(buf.data);
-       /* turn target into ucs2-le */
-       ascii2ucs2le(target, 0, &buf);
+       /* uppercase target and turn into ucs2-le */
+       ascii2ucs2le(target, 1, &buf);
        HMAC_Update(&c, buf.data, buf.length);
        free(buf.data);
     }
@@ -914,6 +932,10 @@ nt2unixtime(uint64_t t)
 }
 
 
+/*
+ * Calculate NTLMv2 response
+ */
+
 int
 heim_ntlm_calculate_ntlm2(const void *key, size_t len,
                          const char *username,
@@ -948,25 +970,27 @@ heim_ntlm_calculate_ntlm2(const void *key, size_t len,
        return ENOMEM;
     krb5_storage_set_flags(sp, KRB5_STORAGE_BYTEORDER_LE);
 
-    CHECK(krb5_store_uint32(sp, 0x01010000), 0);
+    CHECK(krb5_store_uint32(sp, 0x00000101), 0);
     CHECK(krb5_store_uint32(sp, 0), 0);
     /* timestamp le 64 bit ts */
     CHECK(krb5_store_uint32(sp, t & 0xffffffff), 0);
     CHECK(krb5_store_uint32(sp, t >> 32), 0);
+
     CHECK(krb5_storage_write(sp, clientchallange, 8), 8);
+
+    CHECK(krb5_store_uint32(sp, 0), 0);  /* unknown but zero will work */
     CHECK(krb5_storage_write(sp, infotarget->data, infotarget->length), 
          infotarget->length);
-    /* unknown */
-    /* CHECK(krb5_store_uint32(sp, 0), 0);  */
+    CHECK(krb5_store_uint32(sp, 0), 0); /* unknown but zero will work */
     
     CHECK(krb5_storage_to_data(sp, &data), 0);
     krb5_storage_free(sp);
     sp = NULL;
 
     HMAC_CTX_init(&c);
-    HMAC_Init_ex(&c, ntlmv2, sizeof(ntlmv2), EVP_md5(), NULL);
-    HMAC_Update(&c, data.data, data.length);
+    HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL);
     HMAC_Update(&c, serverchallange, 8);
+    HMAC_Update(&c, data.data, data.length);
     HMAC_Final(&c, ntlmv2answer, &hmaclen);
     HMAC_CTX_cleanup(&c);
 
@@ -996,6 +1020,10 @@ out:
 
 static const int authtimediff = 3600 * 2; /* 2 hours */
 
+/*
+ * Verify NTLMv2 response.
+ */
+
 int
 heim_ntlm_verify_ntlm2(const void *key, size_t len,
                       const char *username,
@@ -1009,6 +1037,7 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
     krb5_error_code ret;
     unsigned int hmaclen;
     unsigned char clientanswer[16];
+    unsigned char clientnonce[8];
     unsigned char serveranswer[16];
     krb5_storage *sp;
     HMAC_CTX c;
@@ -1039,7 +1068,7 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
     CHECK(krb5_storage_read(sp, clientanswer, 16), 16);
 
     CHECK(krb5_ret_uint32(sp, &temp), 0);
-    CHECK(temp, 0x01010000);
+    CHECK(temp, 0x00000101);
     CHECK(krb5_ret_uint32(sp, &temp), 0);
     CHECK(temp, 0);
     /* timestamp le 64 bit ts */
@@ -1056,9 +1085,12 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
     }
 
     /* client challange */
-    CHECK(krb5_storage_read(sp, serveranswer, 8), 8);
+    CHECK(krb5_storage_read(sp, clientnonce, 8), 8);
 
-    infotarget->length = answer->length - 40;
+    CHECK(krb5_ret_uint32(sp, &temp), 0); /* unknown */
+
+    /* should really unparse the infotarget, but lets pick up everything */
+    infotarget->length = answer->length - krb5_storage_seek(sp, 0, SEEK_CUR);
     infotarget->data = malloc(infotarget->length);
     if (infotarget->data == NULL) {
        ret = ENOMEM;
@@ -1066,14 +1098,14 @@ heim_ntlm_verify_ntlm2(const void *key, size_t len,
     }
     CHECK(krb5_storage_read(sp, infotarget->data, infotarget->length), 
          infotarget->length);
-    /* XXX remove the unknown uint32_t */
+    /* XXX remove the unknown ?? */
     krb5_storage_free(sp);
     sp = NULL;
 
     HMAC_CTX_init(&c);
-    HMAC_Init_ex(&c, ntlmv2, sizeof(ntlmv2), EVP_md5(), NULL);
-    HMAC_Update(&c, ((char *)answer->data) + 16, answer->length - 16);
+    HMAC_Init_ex(&c, ntlmv2, 16, EVP_md5(), NULL);
     HMAC_Update(&c, serverchallange, 8);
+    HMAC_Update(&c, ((char *)answer->data) + 16, answer->length - 16);
     HMAC_Final(&c, serveranswer, &hmaclen);
     HMAC_CTX_cleanup(&c);
 
@@ -1089,3 +1121,52 @@ out:
        krb5_storage_free(sp);
     return ret;
 }
+
+
+/*
+ * Calculate the NTLM2 Session Response
+ */
+
+int
+heim_ntlm_calculate_ntlm2_sess(const unsigned char clnt_nonce[8],
+                              const unsigned char svr_chal[8],
+                              const unsigned char ntlm_hash[16],
+                              struct ntlm_buf *lm,
+                              struct ntlm_buf *ntlm)
+{
+    unsigned char ntlm2_sess_hash[MD5_DIGEST_LENGTH];
+    unsigned char res[21], *resp;
+    MD5_CTX md5;
+
+    lm->data = malloc(24);
+    if (lm->data == NULL)
+       return ENOMEM;
+    lm->length = 24;
+
+    ntlm->data = malloc(24);
+    if (ntlm->data == NULL) {
+       free(lm->data);
+       lm->data = NULL;
+       return ENOMEM;
+    }
+    ntlm->length = 24;
+
+    /* first setup the lm resp */
+    memset(lm->data, 0, 24);
+    memcpy(lm->data, clnt_nonce, 8);
+
+    MD5_Init(&md5);
+    MD5_Update(&md5, svr_chal, 8); /* session nonce part 1 */
+    MD5_Update(&md5, clnt_nonce, 8); /* session nonce part 2 */
+    MD5_Final(ntlm2_sess_hash, &md5); /* will only use first 8 bytes */
+
+    memset(res, 0, sizeof(res));
+    memcpy(res, ntlm_hash, 16);
+
+    resp = ntlm->data;
+    splitandenc(&res[0], ntlm2_sess_hash, resp + 0);
+    splitandenc(&res[7], ntlm2_sess_hash, resp + 8);
+    splitandenc(&res[14], ntlm2_sess_hash, resp + 16);
+
+    return 0;
+}
index 08eed5f8ed3cb884e942119497f92431d5dd357a..0b25fbdb3daa2e07b1cc8342d2d37a208334fff8 100644 (file)
@@ -33,7 +33,7 @@
 
 #ifdef HAVE_CONFIG_H
 #include <config.h>
-RCSID("$Id: roken_gethostby.c 21005 2007-06-08 01:54:35Z lha $");
+RCSID("$Id: roken_gethostby.c 21157 2007-06-18 22:03:13Z lha $");
 #endif
 
 #include <roken.h>
@@ -111,7 +111,7 @@ int ROKEN_LIB_FUNCTION
 roken_gethostby_setup(const char *proxy_spec, const char *dns_spec)
 {
     char *proxy_host = NULL;
-    int proxy_port;
+    int proxy_port = 0;
     char *dns_host, *dns_path;
     int dns_port;
     
index a13a8741013f1e066cd42878a4a4ccf10ea13bb5..73187c31dcb2f2488b5ddd53df5bcb2eebaf44c1 100644 (file)
@@ -325,6 +325,7 @@ OBJ_FILES = \
        ../heimdal/lib/hcrypto/rand-egd.o \
        ../heimdal/lib/hcrypto/rand-unix.o \
        ../heimdal/lib/hcrypto/rand-fortuna.o \
+       ../heimdal/lib/hcrypto/rand-timer.o \
        ../heimdal/lib/hcrypto/hmac.o
 # End SUBSYSTEM HEIMDAL_HCRYPTO
 #######################