s4:heimdal: import lorikeet-heimdal-200907152325 (commit 2bef9cd5378c01e9c2a74d622176...
authorAndrew Bartlett <abartlet@samba.org>
Wed, 15 Jul 2009 23:53:14 +0000 (09:53 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 16 Jul 2009 01:31:36 +0000 (11:31 +1000)
67 files changed:
source4/heimdal/kdc/kaserver.c
source4/heimdal/kdc/kerberos5.c
source4/heimdal/kdc/krb5tgs.c
source4/heimdal/lib/gssapi/gssapi/gssapi.h
source4/heimdal/lib/gssapi/krb5/8003.c
source4/heimdal/lib/gssapi/krb5/accept_sec_context.c
source4/heimdal/lib/gssapi/krb5/acquire_cred.c
source4/heimdal/lib/gssapi/krb5/add_cred.c
source4/heimdal/lib/gssapi/krb5/aeap.c
source4/heimdal/lib/gssapi/krb5/arcfour.c
source4/heimdal/lib/gssapi/krb5/canonicalize_name.c
source4/heimdal/lib/gssapi/krb5/cfx.c
source4/heimdal/lib/gssapi/krb5/compare_name.c
source4/heimdal/lib/gssapi/krb5/compat.c
source4/heimdal/lib/gssapi/krb5/context_time.c
source4/heimdal/lib/gssapi/krb5/copy_ccache.c
source4/heimdal/lib/gssapi/krb5/decapsulate.c
source4/heimdal/lib/gssapi/krb5/delete_sec_context.c
source4/heimdal/lib/gssapi/krb5/display_name.c
source4/heimdal/lib/gssapi/krb5/display_status.c
source4/heimdal/lib/gssapi/krb5/duplicate_name.c
source4/heimdal/lib/gssapi/krb5/encapsulate.c
source4/heimdal/lib/gssapi/krb5/export_name.c
source4/heimdal/lib/gssapi/krb5/export_sec_context.c
source4/heimdal/lib/gssapi/krb5/external.c
source4/heimdal/lib/gssapi/krb5/get_mic.c
source4/heimdal/lib/gssapi/krb5/import_name.c
source4/heimdal/lib/gssapi/krb5/import_sec_context.c
source4/heimdal/lib/gssapi/krb5/indicate_mechs.c
source4/heimdal/lib/gssapi/krb5/init.c
source4/heimdal/lib/gssapi/krb5/init_sec_context.c
source4/heimdal/lib/gssapi/krb5/inquire_context.c
source4/heimdal/lib/gssapi/krb5/inquire_cred.c
source4/heimdal/lib/gssapi/krb5/inquire_cred_by_mech.c
source4/heimdal/lib/gssapi/krb5/inquire_cred_by_oid.c
source4/heimdal/lib/gssapi/krb5/inquire_mechs_for_name.c
source4/heimdal/lib/gssapi/krb5/inquire_names_for_mech.c
source4/heimdal/lib/gssapi/krb5/inquire_sec_context_by_oid.c
source4/heimdal/lib/gssapi/krb5/prf.c
source4/heimdal/lib/gssapi/krb5/process_context_token.c
source4/heimdal/lib/gssapi/krb5/release_buffer.c
source4/heimdal/lib/gssapi/krb5/release_cred.c
source4/heimdal/lib/gssapi/krb5/release_name.c
source4/heimdal/lib/gssapi/krb5/sequence.c
source4/heimdal/lib/gssapi/krb5/set_cred_option.c
source4/heimdal/lib/gssapi/krb5/set_sec_context_option.c
source4/heimdal/lib/gssapi/krb5/unwrap.c
source4/heimdal/lib/gssapi/krb5/verify_mic.c
source4/heimdal/lib/gssapi/krb5/wrap.c
source4/heimdal/lib/gssapi/mech/gss_acquire_cred.c
source4/heimdal/lib/gssapi/mech/gss_aeap.c
source4/heimdal/lib/gssapi/spnego/accept_sec_context.c
source4/heimdal/lib/hdb/db.c
source4/heimdal/lib/hdb/dbinfo.c
source4/heimdal/lib/hdb/ext.c
source4/heimdal/lib/hdb/hdb.asn1
source4/heimdal/lib/hdb/hdb.c
source4/heimdal/lib/hdb/hdb.h
source4/heimdal/lib/hdb/keys.c
source4/heimdal/lib/hdb/keytab.c
source4/heimdal/lib/hdb/mkey.c
source4/heimdal/lib/hdb/ndbm.c
source4/heimdal/lib/hx509/crypto.c
source4/heimdal/lib/krb5/crypto.c
source4/heimdal/lib/krb5/get_addrs.c
source4/heimdal/lib/krb5/init_creds_pw.c
source4/heimdal/lib/krb5/store_emem.c

index 3702ab9281291836d18a78fa8bf31b6643edebd5..69b5bb1d6e9cfc7f030d48f63a3b3290276f7ce0 100644 (file)
@@ -493,10 +493,10 @@ do_authenticate (krb5_context context,
        goto out;
     }
 
-    ret = _kdc_check_flags (context, config,
-                           client_entry, client_name,
-                           server_entry, server_name,
-                           TRUE);
+    ret = kdc_check_flags (context, config,
+                          client_entry, client_name,
+                          server_entry, server_name,
+                          TRUE);
     if (ret) {
        make_error_reply (hdr, KAPWEXPIRED, reply);
        goto out;
@@ -790,10 +790,10 @@ do_getticket (krb5_context context,
        goto out;
     }
 
-    ret = _kdc_check_flags (context, config,
-                           client_entry, client_name,
-                           server_entry, server_name,
-                           FALSE);
+    ret = kdc_check_flags (context, config,
+                          client_entry, client_name,
+                          server_entry, server_name,
+                          FALSE);
     if (ret) {
        make_error_reply (hdr, KAPWEXPIRED, reply);
        goto out;
index e364dcc1d1f5dba8dc6c1a67d00aefdb38e873e3..43d54bf702540bf24178fb53c4bc169d160648bf 100644 (file)
@@ -678,6 +678,12 @@ kdc_check_flags(krb5_context context,
        hdb_entry *client = &client_ex->entry;
 
        /* check client */
+       if (client->flags.locked_out) {
+           kdc_log(context, config, 0,
+                   "Client (%s) is locked out", client_name);
+           return KRB5KDC_ERR_POLICY;
+       }
+
        if (client->flags.invalid) {
            kdc_log(context, config, 0,
                    "Client (%s) has invalid bit set", client_name);
@@ -727,6 +733,11 @@ kdc_check_flags(krb5_context context,
     if (server_ex != NULL) {
        hdb_entry *server = &server_ex->entry;
 
+       if (server->flags.locked_out) {
+           kdc_log(context, config, 0,
+                   "Client server locked out -- %s", server_name);
+           return KRB5KDC_ERR_POLICY;
+       }
        if (server->flags.invalid) {
            kdc_log(context, config, 0,
                    "Server has invalid flag set -- %s", server_name);
@@ -883,6 +894,7 @@ _kdc_as_rep(krb5_context context,
     AS_REP rep;
     KDCOptions f = b->kdc_options;
     hdb_entry_ex *client = NULL, *server = NULL;
+    HDB *clientdb;
     krb5_enctype cetype, setype, sessionetype;
     krb5_data e_data;
     EncTicketPart et;
@@ -966,7 +978,7 @@ _kdc_as_rep(krb5_context context,
      */
 
     ret = _kdc_db_fetch(context, config, client_princ,
-                       HDB_F_GET_CLIENT | flags, NULL, &client);
+                       HDB_F_GET_CLIENT | flags, &clientdb, &client);
     if(ret){
        kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name,
                krb5_get_err_text(context, ret));
@@ -1114,8 +1126,8 @@ _kdc_as_rep(krb5_context context,
                            "No client key matching pa-data (%s) -- %s",
                            estr, client_name);
                free(estr);
-               
                free_EncryptedData(&enc_data);
+
                continue;
            }
 
@@ -1159,6 +1171,10 @@ _kdc_as_rep(krb5_context context,
                e_text = "Failed to decrypt PA-DATA";
 
                free_EncryptedData(&enc_data);
+
+               if (clientdb->hdb_auth_status)
+                   (clientdb->hdb_auth_status)(context, clientdb, client, HDB_AUTH_WRONG_PASSWORD);
+
                ret = KRB5KDC_ERR_PREAUTH_FAILED;
                continue;
            }
@@ -1323,6 +1339,10 @@ _kdc_as_rep(krb5_context context,
        goto out;
     }
 
+    if (clientdb->hdb_auth_status)
+       (clientdb->hdb_auth_status)(context, clientdb, client, 
+                                   HDB_AUTH_SUCCESS);
+
     /*
      * Verify flags after the user been required to prove its identity
      * with in a preauth mech.
index 59104da3d60ec74657e332a91b86872b5fba107a..6b98506e81caa2cda4207be9481065f02bfe6cab 100644 (file)
@@ -492,6 +492,7 @@ check_tgs_flags(krb5_context context,
 static krb5_error_code
 check_constrained_delegation(krb5_context context,
                             krb5_kdc_configuration *config,
+                            HDB *clientdb,
                             hdb_entry_ex *client,
                             krb5_const_principal server)
 {
@@ -499,21 +500,32 @@ check_constrained_delegation(krb5_context context,
     krb5_error_code ret;
     int i;
 
-    ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl);
-    if (ret) {
-       krb5_clear_error_message(context);
-       return ret;
-    }
+    /* if client delegates to itself, that ok */
+    if (krb5_principal_compare(context, client->entry.principal, server) == TRUE)
+       return 0;
 
-    if (acl) {
-       for (i = 0; i < acl->len; i++) {
-           if (krb5_principal_compare(context, server, &acl->val[i]) == TRUE)
-               return 0;
+    if (clientdb->hdb_check_constrained_delegation) {
+       ret = clientdb->hdb_check_constrained_delegation(context, clientdb, client, server);
+       if (ret == 0)
+           return 0;
+    } else {
+       ret = hdb_entry_get_ConstrainedDelegACL(&client->entry, &acl);
+       if (ret) {
+           krb5_clear_error_message(context);
+           return ret;
+       }
+       
+       if (acl) {
+           for (i = 0; i < acl->len; i++) {
+               if (krb5_principal_compare(context, server, &acl->val[i]) == TRUE)
+                   return 0;
+           }
        }
+       ret = KRB5KDC_ERR_BADOPTION;
     }
     kdc_log(context, config, 0,
            "Bad request for constrained delegation");
-    return KRB5KDC_ERR_BADOPTION;
+    return ret;
 }
 
 /*
@@ -1369,6 +1381,7 @@ tgs_build_reply(krb5_context context,
     krb5_principal client_principal = NULL;
     char *spn = NULL, *cpn = NULL;
     hdb_entry_ex *server = NULL, *client = NULL;
+    HDB *clientdb;
     krb5_realm ref_realm = NULL;
     EncTicketPart *tgt = &ticket->ticket;
     krb5_principals spp = NULL;
@@ -1531,7 +1544,7 @@ server_lookup:
     }
 
     ret = _kdc_db_fetch(context, config, cp, HDB_F_GET_CLIENT | HDB_F_CANON,
-                       NULL, &client);
+                       &clientdb, &client);
     if(ret) {
        const char *krbtgt_realm;
 
@@ -1792,7 +1805,7 @@ server_lookup:
        if (ret) {
            kdc_log(context, config, 0,
                    "failed to decrypt ticket for "
-                   "constrained delegation from %s to %s ", spn, cpn);
+                   "constrained delegation from %s to %s ", cpn, spn);
            goto out;
        }
 
@@ -1800,16 +1813,17 @@ server_lookup:
        if (adtkt.flags.forwardable == 0) {
            kdc_log(context, config, 0,
                    "Missing forwardable flag on ticket for "
-                   "constrained delegation from %s to %s ", spn, cpn);
+                   "constrained delegation from %s to %s ", cpn, spn);
            ret = KRB5KDC_ERR_BADOPTION;
            goto out;
        }
 
-       ret = check_constrained_delegation(context, config, client, sp);
+       ret = check_constrained_delegation(context, config, clientdb, 
+                                          client, sp);
        if (ret) {
            kdc_log(context, config, 0,
                    "constrained delegation from %s to %s not allowed",
-                   spn, cpn);
+                   cpn, spn);
            goto out;
        }
 
index 9fe2bb8b46e182bc7ee2fbb18d2b2065e8ce000e..07c4b36325d307f93054fdae5a8eb9cd8e028725 100644 (file)
@@ -768,42 +768,6 @@ gss_pseudo_random
         gss_buffer_t prf_out
        );
 
-/*
- * AEAD support
- */
-
-OM_uint32 GSSAPI_LIB_FUNCTION
-gss_wrap_iov(OM_uint32 * /* minor_status */,
-            gss_ctx_id_t /* context_handle */,
-            int /* conf_req_flag */,
-            gss_qop_t /* qop_req */,
-            int * /* conf_state */,
-            gss_iov_buffer_desc * /*iov */,
-            int /* iov_count */);
-
-OM_uint32 GSSAPI_LIB_FUNCTION
-gss_unwrap_iov(OM_uint32 * /* minor_status */,
-              gss_ctx_id_t /* context_handle */,
-              int * /* conf_state */,
-              gss_qop_t * /* qop_state */,
-              gss_iov_buffer_desc * /* iov */,
-              int /* iov_count */);
-    
-OM_uint32  GSSAPI_LIB_FUNCTION
-gss_wrap_iov_length(OM_uint32 * /* minor_status */,
-                   gss_ctx_id_t /* context_handle */,
-                   int /* conf_req_flag */,
-                   gss_qop_t /* qop_req */,
-                   int * /* conf_state */,
-                   gss_iov_buffer_desc * /* iov */,
-                   int /* iov_count */);
-
-OM_uint32 GSSAPI_LIB_FUNCTION
-gss_release_iov_buffer(OM_uint32 * /* minor_status */,
-                      gss_iov_buffer_desc * /* iov */,
-                      int /* iov_count */);
-
-
 OM_uint32
 gss_store_cred(OM_uint32         * /* minor_status */,
               gss_cred_id_t     /* input_cred_handle */,
@@ -899,6 +863,31 @@ gss_decapsulate_token(gss_buffer_t /* input_token */,
 
 
 
+/*
+ * AEAD support
+ */
+
+/*
+ * GSS_IOV
+ */
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_wrap_iov(OM_uint32 *, gss_ctx_id_t, int, gss_qop_t, int *,
+            gss_iov_buffer_desc *, int);
+
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_unwrap_iov(OM_uint32 *, gss_ctx_id_t, int *, gss_qop_t *,
+              gss_iov_buffer_desc *, int);
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_wrap_iov_length(OM_uint32 *, gss_ctx_id_t, int, gss_qop_t, int *,
+                   gss_iov_buffer_desc *, int);
+
+OM_uint32 GSSAPI_LIB_FUNCTION
+gss_release_iov_buffer(OM_uint32 *, gss_iov_buffer_desc *, int);
+
+
 #ifdef __cplusplus
 }
 #endif
index f5181cc311b877cd50ed9a666bcda8db0d6b414c..a6f0165e7247c3863dd3934dfef247a75b938b10 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 krb5_error_code
 _gsskrb5_encode_om_uint32(OM_uint32 n, u_char *p)
 {
index 8ead2bdf75e40d76fbfa1df71f8eb80d2b14c1a9..8d998ed0988f3ec3b5d033ccb761f0b006dcb913 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 HEIMDAL_MUTEX gssapi_keytab_mutex = HEIMDAL_MUTEX_INITIALIZER;
 krb5_keytab _gsskrb5_keytab;
 
@@ -519,13 +517,12 @@ gsskrb5_acceptor_start(OM_uint32 * minor_status,
            }
 
            /*
-            * Samba style get some flags (but not DCE-STYLE)
+            * Samba style get some flags (but not DCE-STYLE), use
+            * ap_options to guess the mutual flag.
             */
-           ctx->flags =
-               GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG;
-           if (ap_options & AP_OPTS_MUTUAL_REQUIRED) {
-                   ctx->flags |= GSS_C_MUTUAL_FLAG;
-           }
+           ctx->flags = GSS_C_REPLAY_FLAG | GSS_C_SEQUENCE_FLAG;
+           if (ap_options & AP_OPTS_MUTUAL_REQUIRED)
+               ctx->flags |= GSS_C_MUTUAL_FLAG;
         }
     }
 
index bfab5667beb5cd6403b9a5cf39f5a3dfaac9b549..4f6f38e6743d8edba818a661d25c7d6affeea457 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32
 __gsskrb5_ccache_lifetime(OM_uint32 *minor_status,
                          krb5_context context,
index aa96a45e451966da2d58690c7c1690adb9a44640..adc8a09fa44502d85455eb7edc31586a7a1459f0 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_add_cred (
      OM_uint32           *minor_status,
      const gss_cred_id_t input_cred_handle,
index 7dab7877d7f8aaa99222e0c010aff46be33aa2bf..38a5ac2dbe5200904eb3cb5ad35f3e0fcb4913ab 100644 (file)
 
 #include <roken.h>
 
-static OM_uint32
-iov_allocate(OM_uint32 *minor_status, gss_iov_buffer_desc *iov, int iov_count)
-{
-    unsigned int i;
-    
-    for (i = 0; i < iov_count; i++) {
-       if (GSS_IOV_BUFFER_FLAGS(iov[i].type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE){
-           void *ptr = malloc(iov[i].buffer.length);
-           if (ptr == NULL)
-               abort();
-           if (iov[i].buffer.value)
-               memcpy(ptr, iov[i].buffer.value, iov[i].buffer.length);
-           iov[i].buffer.value = ptr;
-           iov[i].type |= GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED;
-       }
-    }
-    return GSS_S_COMPLETE;
-}
-
-static OM_uint32
-iov_map(OM_uint32 *minor_status,
-       const gss_iov_buffer_desc *iov,
-       int iov_count,
-       krb5_crypto_iov *data)
-{
-    unsigned int i;
-
-    for (i = 0; i < iov_count; i++) {
-       switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) {
-       case GSS_IOV_BUFFER_TYPE_EMPTY:
-           data[i].flags = KRB5_CRYPTO_TYPE_EMPTY;
-           break;
-       case GSS_IOV_BUFFER_TYPE_DATA:
-           data[i].flags = KRB5_CRYPTO_TYPE_DATA;
-           break;
-       case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
-           data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
-           break;
-       case GSS_IOV_BUFFER_TYPE_HEADER:
-           data[i].flags = KRB5_CRYPTO_TYPE_HEADER;
-           break;
-       case GSS_IOV_BUFFER_TYPE_TRAILER:
-           data[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
-           break;
-       case GSS_IOV_BUFFER_TYPE_PADDING:
-           data[i].flags = KRB5_CRYPTO_TYPE_PADDING;
-           break;
-       case GSS_IOV_BUFFER_TYPE_STREAM:
-           abort();
-           break;
-       default:
-           *minor_status = EINVAL;
-           return GSS_S_FAILURE;
-       }
-       data[i].data.data = iov[i].buffer.value;
-       data[i].data.length = iov[i].buffer.length;
-    }
-    return GSS_S_COMPLETE;
-}
-
 OM_uint32 GSSAPI_LIB_FUNCTION
 _gk_wrap_iov(OM_uint32 * minor_status,
             gss_ctx_id_t  context_handle,
@@ -104,50 +44,17 @@ _gk_wrap_iov(OM_uint32 * minor_status,
             gss_iov_buffer_desc *iov,
             int iov_count)
 {
-    gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
-    krb5_context context;
-    OM_uint32 major_status, junk;
-    krb5_crypto_iov *data;
-    krb5_error_code ret;
-    unsigned usage;
-
-    GSSAPI_KRB5_INIT (&context);
-
-    major_status = iov_allocate(minor_status, iov, iov_count);
-    if (major_status != GSS_S_COMPLETE)
-       return major_status;
-
-    data = calloc(iov_count, sizeof(data[0]));
-    if (data == NULL) {
-       gss_release_iov_buffer(&junk, iov, iov_count);
-       *minor_status = ENOMEM;
-       return GSS_S_FAILURE;
-    }
-
-    major_status = iov_map(minor_status, iov, iov_count, data);
-    if (major_status != GSS_S_COMPLETE) {
-       gss_release_iov_buffer(&junk, iov, iov_count);
-       free(data);
-       return major_status;
-    }
+  const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
+  krb5_context context;
 
-    if (ctx->more_flags & LOCAL) {
-       usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;
-    } else {
-       usage = KRB5_KU_USAGE_INITIATOR_SIGN;
-    }
+  GSSAPI_KRB5_INIT (&context);
 
-    ret = krb5_encrypt_iov_ivec(context, ctx->crypto, usage,
-                               data, iov_count, NULL);
-    free(data);
-    if (ret) {
-       gss_release_iov_buffer(&junk, iov, iov_count);
-        *minor_status = ret;
-       return GSS_S_FAILURE;
-    }
+  if (ctx->more_flags & IS_CFX)
+      return _gssapi_wrap_cfx_iov(minor_status, ctx, context,
+                                 conf_req_flag, conf_state,
+                                 iov, iov_count);
 
-    *minor_status = 0;
-    return GSS_S_COMPLETE;
+    return GSS_S_FAILURE;
 }
 
 OM_uint32 GSSAPI_LIB_FUNCTION
@@ -158,50 +65,16 @@ _gk_unwrap_iov(OM_uint32 *minor_status,
               gss_iov_buffer_desc *iov,
               int iov_count)
 {
-    gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
+    const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
     krb5_context context;
-    krb5_error_code ret;
-    OM_uint32 major_status, junk;
-    krb5_crypto_iov *data;
-    unsigned usage;
 
     GSSAPI_KRB5_INIT (&context);
-
-    major_status = iov_allocate(minor_status, iov, iov_count);
-    if (major_status != GSS_S_COMPLETE)
-       return major_status;
-
-    data = calloc(iov_count, sizeof(data[0]));
-    if (data == NULL) {
-       gss_release_iov_buffer(&junk, iov, iov_count);
-       *minor_status = ENOMEM;
-       return GSS_S_FAILURE;
-    }
-
-    major_status = iov_map(minor_status, iov, iov_count, data);
-    if (major_status != GSS_S_COMPLETE) {
-       gss_release_iov_buffer(&junk, iov, iov_count);
-       free(data);
-       return major_status;
-    }
-
-    if (ctx->more_flags & LOCAL) {
-       usage = KRB5_KU_USAGE_INITIATOR_SIGN;
-    } else {
-       usage = KRB5_KU_USAGE_ACCEPTOR_SIGN;
-    }
-
-    ret = krb5_decrypt_iov_ivec(context, ctx->crypto, usage,
-                               data, iov_count, NULL);
-    free(data);
-    if (ret) {
-        *minor_status = ret;
-       gss_release_iov_buffer(&junk, iov, iov_count);
-       return GSS_S_FAILURE;
-    }
-
-    *minor_status = 0;
-    return GSS_S_COMPLETE;
+    
+    if (ctx->more_flags & IS_CFX)
+       return _gssapi_unwrap_cfx_iov(minor_status, ctx, context,
+                                     conf_state, qop_state, iov, iov_count);
+    
+    return GSS_S_FAILURE;
 }
 
 OM_uint32  GSSAPI_LIB_FUNCTION
@@ -213,59 +86,15 @@ _gk_wrap_iov_length(OM_uint32 * minor_status,
                    gss_iov_buffer_desc *iov,
                    int iov_count)
 {
-    gsskrb5_ctx ctx = (gsskrb5_ctx) context_handle;
+    const gsskrb5_ctx ctx = (const gsskrb5_ctx) context_handle;
     krb5_context context;
-    unsigned int i;
-    size_t size;
-    size_t *padding = NULL;
-
+    
     GSSAPI_KRB5_INIT (&context);
-    *minor_status = 0;
-
-    for (size = 0, i = 0; i < iov_count; i++) {
-       switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) {
-       case GSS_IOV_BUFFER_TYPE_EMPTY:
-           break;
-       case GSS_IOV_BUFFER_TYPE_DATA:
-           size += iov[i].buffer.length;
-           break;
-       case GSS_IOV_BUFFER_TYPE_HEADER:
-           iov[i].buffer.length =
-             krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER);
-           size += iov[i].buffer.length;
-           break;
-       case GSS_IOV_BUFFER_TYPE_TRAILER:
-           iov[i].buffer.length =
-             krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER);
-           size += iov[i].buffer.length;
-           break;
-       case GSS_IOV_BUFFER_TYPE_PADDING:
-           if (padding != NULL) {
-               *minor_status = 0;
-               return GSS_S_FAILURE;
-           }
-           padding = &iov[i].buffer.length;
-           break;
-       case GSS_IOV_BUFFER_TYPE_STREAM:
-           size += iov[i].buffer.length;
-           break;
-       case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
-           break;
-       default:
-           *minor_status = EINVAL;
-           return GSS_S_FAILURE;
-       }
-    }
-    if (padding) {
-       size_t pad = krb5_crypto_length(context, ctx->crypto,
-                                       KRB5_CRYPTO_TYPE_PADDING);
-       if (pad > 1) {
-           *padding = pad - (size % pad);
-           if (*padding == pad)
-               *padding = 0;
-       } else
-           *padding = 0;
-    }
-
-    return GSS_S_COMPLETE;
+    
+    if (ctx->more_flags & IS_CFX)
+       return _gssapi_wrap_iov_length_cfx(minor_status, ctx, context,
+                                          conf_req_flag, qop_req, conf_state,
+                                          iov, iov_count);
+    
+    return GSS_S_FAILURE;
 }
index b48cfebcf1b13b3d82864f6fc67d2df14b844264..e7331b0119c4988f92f9db12bebbc16d2c8115dc 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 /*
  * Implements draft-brezak-win2k-krb-rc4-hmac-04.txt
  *
index 3a206b1be1b036195ba25e6cfb59ea54942d5d29..7e0c3fe72703b17f8b99267e58e580720f184d96 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_canonicalize_name (
             OM_uint32 * minor_status,
             const gss_name_t input_name,
index 7ae26e2e7a556ac6b1775afb4b5d1c5b5cf20ab8..35e5a9e45a8787b1f8927a66e05646f281d156f8 100755 (executable)
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 /*
- * Implementation of draft-ietf-krb-wg-gssapi-cfx-06.txt
+ * Implementation of RFC 4121
  */
 
 #define CFXSentByAcceptor      (1 << 0)
@@ -101,13 +99,14 @@ _gsskrb5cfx_wrap_length_cfx(const gsskrb5_ctx context_handle,
     return 0;
 }
 
-OM_uint32 _gssapi_wrap_size_cfx(OM_uint32 *minor_status,
-                               const gsskrb5_ctx ctx,
-                               krb5_context context,
-                               int conf_req_flag,
-                               gss_qop_t qop_req,
-                               OM_uint32 req_output_size,
-                               OM_uint32 *max_input_size)
+OM_uint32
+_gssapi_wrap_size_cfx(OM_uint32 *minor_status,
+                     const gsskrb5_ctx ctx,
+                     krb5_context context,
+                     int conf_req_flag,
+                     gss_qop_t qop_req,
+                     OM_uint32 req_output_size,
+                     OM_uint32 *max_input_size)
 {
     krb5_error_code ret;
 
@@ -203,11 +202,763 @@ rrc_rotate(void *data, size_t len, uint16_t rrc, krb5_boolean unrotate)
     return 0;
 }
 
+gss_iov_buffer_desc *
+_gk_find_buffer(gss_iov_buffer_desc *iov, int iov_count, OM_uint32 type)
+{
+    int i;
+
+    for (i = 0; i < iov_count; i++)
+       if (type == GSS_IOV_BUFFER_TYPE(iov[i].type))
+           return &iov[i];
+    return NULL;
+}
+
+static OM_uint32
+allocate_buffer(OM_uint32 *minor_status, gss_iov_buffer_desc *buffer, size_t size)
+{
+    if (buffer->type & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED) {
+       if (buffer->buffer.length == size)
+           return GSS_S_COMPLETE;
+       free(buffer->buffer.value);
+    }
+
+    buffer->buffer.value = malloc(size);
+    buffer->buffer.length = size;
+    if (buffer->buffer.value == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    buffer->type |= GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED;
+
+    return GSS_S_COMPLETE;
+}
+
+
+
+OM_uint32
+_gssapi_wrap_cfx_iov(OM_uint32 *minor_status,
+                    gsskrb5_ctx ctx,
+                    krb5_context context,
+                    int conf_req_flag,
+                    int *conf_state,
+                    gss_iov_buffer_desc *iov,
+                    int iov_count)
+{
+    OM_uint32 major_status, junk;
+    gss_iov_buffer_desc *header, *trailer, *padding;
+    size_t gsshsize, k5hsize;
+    size_t gsstsize, k5tsize;
+    size_t i, padlength, rrc = 0, ec = 0;
+    gss_cfx_wrap_token token;
+    krb5_error_code ret;
+    int32_t seq_number;
+    unsigned usage;
+    krb5_crypto_iov *data = NULL;
+    int paddingoffset = 0;
+       
+    header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
+    if (header == NULL) {
+       *minor_status = EINVAL;
+       return GSS_S_FAILURE;
+    }
+
+    krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_PADDING, &padlength);
+
+    padding = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_PADDING);
+    if (padlength != 0 && padding == NULL) {
+       *minor_status = EINVAL;
+       return GSS_S_FAILURE;
+    }
+
+    trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
+
+    if (conf_req_flag) {
+       ec = padlength;
+
+       krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER, &k5tsize);
+       krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER, &k5hsize);
+
+       gsshsize = k5hsize + sizeof(*token);
+       gsstsize = k5tsize + sizeof(*token); /* encrypted token stored in trailer */
+
+    } else {
+
+       krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_CHECKSUM, &k5tsize);
+
+       gsshsize = sizeof(*token);
+       gsstsize = k5tsize;
+    }
+
+    /*
+     *
+     */
+
+    if (trailer == NULL) {
+       /* conf_req_flag=0 doesn't support DCE_STYLE */
+       if (conf_req_flag == 0) {
+           *minor_status = EINVAL;
+           major_status = GSS_S_FAILURE;
+           goto failure;
+       }           
+       rrc = gsstsize;
+       if (IS_DCE_STYLE(ctx))
+           rrc -= ec;
+       gsshsize += gsstsize;
+       gsstsize = 0;
+    } else if (GSS_IOV_BUFFER_FLAGS(trailer->type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE) {
+       major_status = allocate_buffer(minor_status, trailer, gsstsize);
+       if (major_status)
+           goto failure;
+    } else if (trailer->buffer.length < gsstsize) {
+       *minor_status = KRB5_BAD_MSIZE;
+       major_status = GSS_S_FAILURE;
+       goto failure;
+    } else
+       trailer->buffer.length = gsstsize;
+
+    /*
+     *
+     */
+
+    if (GSS_IOV_BUFFER_FLAGS(header->type) & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATE) {
+       major_status = allocate_buffer(minor_status, header, gsshsize);
+       if (major_status != GSS_S_COMPLETE)
+           goto failure;
+    } else if (header->buffer.length < gsshsize) {
+       *minor_status = KRB5_BAD_MSIZE;
+       major_status = GSS_S_FAILURE;
+       goto failure;
+    } else
+       header->buffer.length = gsshsize;
+
+    token = (gss_cfx_wrap_token)header->buffer.value;
+
+    token->TOK_ID[0] = 0x05;
+    token->TOK_ID[1] = 0x04;
+    token->Flags     = 0;
+    token->Filler    = 0xFF;
+
+    if (ctx->more_flags & ACCEPTOR_SUBKEY)
+       token->Flags |= CFXAcceptorSubkey;
+
+    if (ctx->more_flags & LOCAL)
+       usage = KRB5_KU_USAGE_INITIATOR_SEAL;
+    else
+       usage = KRB5_KU_USAGE_ACCEPTOR_SEAL;
+
+    if (conf_req_flag) {
+       /*
+        * In Wrap tokens with confidentiality, the EC field is
+        * used to encode the size (in bytes) of the random filler.
+        */
+       token->Flags |= CFXSealed;
+       token->EC[0] = (padlength >> 8) & 0xFF;
+       token->EC[1] = (padlength >> 0) & 0xFF;
+
+    } else {
+       /*
+        * In Wrap tokens without confidentiality, the EC field is
+        * used to encode the size (in bytes) of the trailing
+        * checksum.
+        *
+        * This is not used in the checksum calcuation itself,
+        * because the checksum length could potentially vary
+        * depending on the data length.
+        */
+       token->EC[0] = 0;
+       token->EC[1] = 0;
+    }
+
+    /*
+     * In Wrap tokens that provide for confidentiality, the RRC
+     * field in the header contains the hex value 00 00 before
+     * encryption.
+     *
+     * In Wrap tokens that do not provide for confidentiality,
+     * both the EC and RRC fields in the appended checksum
+     * contain the hex value 00 00 for the purpose of calculating
+     * the checksum.
+     */
+    token->RRC[0] = 0;
+    token->RRC[1] = 0;
+
+    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
+    krb5_auth_con_getlocalseqnumber(context,
+                                   ctx->auth_context,
+                                   &seq_number);
+    _gsskrb5_encode_be_om_uint32(0,          &token->SND_SEQ[0]);
+    _gsskrb5_encode_be_om_uint32(seq_number, &token->SND_SEQ[4]);
+    krb5_auth_con_setlocalseqnumber(context,
+                                   ctx->auth_context,
+                                   ++seq_number);
+    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
+
+    data = calloc(iov_count + 3, sizeof(data[0]));
+    if (data == NULL) {
+       *minor_status = ENOMEM;
+       major_status = GSS_S_FAILURE;
+       goto failure;
+    }
+
+    if (conf_req_flag) {
+       /*
+         plain packet:
+
+         {"header" | encrypt(plaintext-data | padding | E"header")}
+
+         Expanded, this is with with RRC = 0:
+
+         {"header" | krb5-header | plaintext-data | padding | E"header" | krb5-trailer }
+
+         In DCE-RPC mode == no trailer: RRC = gss "trailer" == length(padding | E"header" | krb5-trailer)
+
+         {"header" | padding | E"header" | krb5-trailer | krb5-header | plaintext-data  }
+        */
+
+       i = 0;
+       data[i].flags = KRB5_CRYPTO_TYPE_HEADER;
+       data[i].data.data = ((uint8_t *)header->buffer.value) + header->buffer.length - k5hsize;
+       data[i].data.length = k5hsize;
+
+       for (i = 1; i < iov_count + 1; i++) {
+           switch (GSS_IOV_BUFFER_TYPE(iov[i - 1].type)) {
+           case GSS_IOV_BUFFER_TYPE_DATA:
+               data[i].flags = KRB5_CRYPTO_TYPE_DATA;
+               break;
+           case GSS_IOV_BUFFER_TYPE_PADDING:
+               data[i].flags = KRB5_CRYPTO_TYPE_PADDING;
+               paddingoffset = i;
+               break;
+           case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
+               data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+               break;
+           default:
+               data[i].flags = KRB5_CRYPTO_TYPE_EMPTY;
+               break;
+           }
+           data[i].data.length = iov[i - 1].buffer.length;
+           data[i].data.data = iov[i - 1].buffer.value;
+       }
+
+       /*
+        * Any necessary padding is added here to ensure that the
+        * encrypted token header is always at the end of the
+        * ciphertext.
+        */
+
+       /* XXX KRB5_CRYPTO_TYPE_PADDING */
+
+       /* encrypted CFX header in trailer (or after the header if in
+          DCE mode). Copy in header into E"header"
+       */
+       data[i].flags = KRB5_CRYPTO_TYPE_DATA;
+       if (trailer)
+           data[i].data.data = trailer->buffer.value;
+       else
+           data[i].data.data = ((uint8_t *)header->buffer.value) + header->buffer.length - k5hsize - k5tsize - sizeof(*token);
+
+       data[i].data.length = sizeof(*token);
+       memcpy(data[i].data.data, token, sizeof(*token));
+       i++;
+
+       /* Kerberos trailer comes after the gss trailer */
+       data[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
+       data[i].data.data = ((uint8_t *)data[i-1].data.data) + sizeof(*token);
+       data[i].data.length = k5tsize;
+       i++;
+
+       ret = krb5_encrypt_iov_ivec(context, ctx->crypto, usage, data, i, NULL);
+       if (ret != 0) {
+           *minor_status = ret;
+           major_status = GSS_S_FAILURE;
+           goto failure;
+       }
+
+       if (rrc) {
+           token->RRC[0] = (rrc >> 8) & 0xFF;
+           token->RRC[1] = (rrc >> 0) & 0xFF;
+       }
+
+       if (paddingoffset)
+           padding->buffer.length = data[paddingoffset].data.length;
+
+    } else {
+       /*
+         plain packet:
+
+         {data | "header" | gss-trailer (krb5 checksum)
+         
+         don't do RRC != 0
+
+        */
+
+       for (i = 0; i < iov_count; i++) {
+           switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
+           case GSS_IOV_BUFFER_TYPE_DATA:
+           case GSS_IOV_BUFFER_TYPE_PADDING:
+               data[i].flags = KRB5_CRYPTO_TYPE_DATA;
+               break;
+           case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
+               data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+               break;
+           default:
+               data[i].flags = KRB5_CRYPTO_TYPE_EMPTY;
+               break;
+           }
+           data[i].data.length = iov[i].buffer.length;
+           data[i].data.data = iov[i].buffer.value;
+       }
+
+       data[i].flags = KRB5_CRYPTO_TYPE_DATA;
+       data[i].data.data = header->buffer.value;
+       data[i].data.length = header->buffer.length;
+       i++;
+
+       data[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
+       data[i].data.data = trailer->buffer.value;
+       data[i].data.length = trailer->buffer.length;
+       i++;
+
+       ret = krb5_create_checksum_iov(context, ctx->crypto, usage, data, i, NULL);
+       if (ret) {
+           *minor_status = ret;
+           major_status = GSS_S_FAILURE;
+           goto failure;
+       }
+
+       token->EC[0] =  (trailer->buffer.length >> 8) & 0xFF;
+       token->EC[1] =  (trailer->buffer.length >> 0) & 0xFF;
+    }
+
+    if (conf_state != NULL)
+       *conf_state = conf_req_flag;
+
+    free(data);
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+
+ failure:
+    if (data)
+       free(data);
+
+    gss_release_iov_buffer(&junk, iov, iov_count);
+
+    return major_status;
+}
+
+/* This is slowpath */
+static OM_uint32
+unrotate_iov(OM_uint32 *minor_status, size_t rrc, gss_iov_buffer_desc *iov, int iov_count)
+{
+    uint8_t *p, *q;
+    size_t len = 0, skip;
+    int i;
+
+    for (i = 0; i < iov_count; i++)
+       if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA ||
+           GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING ||
+           GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER)
+           len += iov[i].buffer.length;
+    
+    p = malloc(len);
+    if (p == NULL) {
+       *minor_status = ENOMEM;
+       return GSS_S_FAILURE;
+    }
+    q = p;
+
+    /* copy up */
+
+    for (i = 0; i < iov_count; i++) {
+       if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA ||
+           GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING ||
+           GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER)
+       {
+           memcpy(q, iov[i].buffer.value, iov[i].buffer.length);
+           q += iov[i].buffer.length;
+       }
+    }
+    assert((q - p) == len);
+
+    /* unrotate first part */
+    q = p + rrc;
+    skip = rrc;
+    for (i = 0; i < iov_count; i++) {
+       if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA ||
+           GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING ||
+           GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER)
+       {
+           if (iov[i].buffer.length <= skip) {
+               skip -= iov[i].buffer.length;
+           } else {
+               memcpy(((uint8_t *)iov[i].buffer.value) + skip, q, iov[i].buffer.length - skip);
+               q += iov[i].buffer.length - skip;
+               skip = 0;
+           }
+       }
+    }
+    /* copy trailer */
+    q = p;
+    skip = rrc;
+    for (i = 0; i < iov_count; i++) {
+       if (GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_DATA ||
+           GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_PADDING ||
+           GSS_IOV_BUFFER_TYPE(iov[i].type) == GSS_IOV_BUFFER_TYPE_TRAILER)
+       {
+           memcpy(q, iov[i].buffer.value, MIN(iov[i].buffer.length, skip));
+           if (iov[i].buffer.length > skip)
+               break;
+           skip -= iov[i].buffer.length;
+           q += iov[i].buffer.length;
+       }
+    }
+    return GSS_S_COMPLETE;
+}
+
+
+OM_uint32
+_gssapi_unwrap_cfx_iov(OM_uint32 *minor_status,
+                      gsskrb5_ctx ctx,
+                      krb5_context context,
+                      int *conf_state,
+                      gss_qop_t *qop_state,
+                      gss_iov_buffer_desc *iov,
+                      int iov_count)
+{
+    OM_uint32 seq_number_lo, seq_number_hi, major_status, junk;
+    gss_iov_buffer_desc *header, *trailer;
+    gss_cfx_wrap_token token, ttoken;
+    u_char token_flags;
+    krb5_error_code ret;
+    unsigned usage;
+    uint16_t ec, rrc;
+    krb5_crypto_iov *data = NULL;
+    int i, j;
+
+    *minor_status = 0;
+
+    header = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_HEADER);
+    if (header == NULL) {
+       *minor_status = EINVAL;
+       return GSS_S_FAILURE;
+    }
+
+    if (header->buffer.length < sizeof(*token)) /* we check exact below */
+       return GSS_S_DEFECTIVE_TOKEN;
+
+    trailer = _gk_find_buffer(iov, iov_count, GSS_IOV_BUFFER_TYPE_TRAILER);
+
+    token = (gss_cfx_wrap_token)header->buffer.value;
+
+    if (token->TOK_ID[0] != 0x05 || token->TOK_ID[1] != 0x04)
+       return GSS_S_DEFECTIVE_TOKEN;
+
+    /* Ignore unknown flags */
+    token_flags = token->Flags &
+       (CFXSentByAcceptor | CFXSealed | CFXAcceptorSubkey);
+
+    if (token_flags & CFXSentByAcceptor) {
+       if ((ctx->more_flags & LOCAL) == 0)
+           return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    if (ctx->more_flags & ACCEPTOR_SUBKEY) {
+       if ((token_flags & CFXAcceptorSubkey) == 0)
+           return GSS_S_DEFECTIVE_TOKEN;
+    } else {
+       if (token_flags & CFXAcceptorSubkey)
+           return GSS_S_DEFECTIVE_TOKEN;
+    }
+
+    if (token->Filler != 0xFF)
+       return GSS_S_DEFECTIVE_TOKEN;
+
+    if (conf_state != NULL)
+       *conf_state = (token_flags & CFXSealed) ? 1 : 0;
+
+    ec  = (token->EC[0]  << 8) | token->EC[1];
+    rrc = (token->RRC[0] << 8) | token->RRC[1];
+
+    /*
+     * Check sequence number
+     */
+    _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[0], &seq_number_hi);
+    _gsskrb5_decode_be_om_uint32(&token->SND_SEQ[4], &seq_number_lo);
+    if (seq_number_hi) {
+       /* no support for 64-bit sequence numbers */
+       *minor_status = ERANGE;
+       return GSS_S_UNSEQ_TOKEN;
+    }
+
+    HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
+    ret = _gssapi_msg_order_check(ctx->order, seq_number_lo);
+    if (ret != 0) {
+       *minor_status = 0;
+       HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
+       return ret;
+    }
+    HEIMDAL_MUTEX_unlock(&ctx->ctx_id_mutex);
+
+    /*
+     * Decrypt and/or verify checksum
+     */
+
+    if (ctx->more_flags & LOCAL) {
+       usage = KRB5_KU_USAGE_ACCEPTOR_SEAL;
+    } else {
+       usage = KRB5_KU_USAGE_INITIATOR_SEAL;
+    }
+
+    data = calloc(iov_count + 3, sizeof(data[0]));
+    if (data == NULL) {
+       *minor_status = ENOMEM;
+       major_status = GSS_S_FAILURE;
+       goto failure;
+    }
+
+    if (token_flags & CFXSealed) {
+       size_t k5tsize, k5hsize;
+
+       krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER, &k5hsize);
+       krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER, &k5tsize);
+
+       /* Rotate by RRC; bogus to do this in-place XXX */
+       /* Check RRC */
+
+       if (trailer == NULL) {
+           size_t gsstsize = k5tsize + sizeof(*token);
+           size_t gsshsize = k5hsize + sizeof(*token);
+
+           if (IS_DCE_STYLE(ctx))
+               gsstsize += ec;
+           gsshsize += gsstsize;
+
+           if (rrc != gsstsize) {
+               major_status = GSS_S_DEFECTIVE_TOKEN;
+               goto failure;
+           }
+           if (header->buffer.length != gsshsize) {
+               major_status = GSS_S_DEFECTIVE_TOKEN;
+               goto failure;
+           }
+       } else if (trailer->buffer.length != sizeof(*token) + k5tsize) {
+           major_status = GSS_S_DEFECTIVE_TOKEN;
+           goto failure;
+       } else if (header->buffer.length != sizeof(*token) + k5hsize) {
+           major_status = GSS_S_DEFECTIVE_TOKEN;
+           goto failure;
+       } else if (rrc != 0) {
+           /* go though slowpath */
+           major_status = unrotate_iov(minor_status, rrc, iov, iov_count);
+           if (major_status)
+               goto failure;
+       }
+
+       i = 0;
+       data[i].flags = KRB5_CRYPTO_TYPE_HEADER;
+       data[i].data.data = ((uint8_t *)header->buffer.value) + header->buffer.length - k5hsize;
+       data[i].data.length = k5hsize;
+       i++;
+
+       for (j = 0; j < iov_count; i++, j++) {
+           switch (GSS_IOV_BUFFER_TYPE(iov[j].type)) {
+           case GSS_IOV_BUFFER_TYPE_DATA:
+           case GSS_IOV_BUFFER_TYPE_PADDING:
+               data[i].flags = KRB5_CRYPTO_TYPE_DATA;
+               break;
+           case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
+               data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+               break;
+           default:
+               data[i].flags = KRB5_CRYPTO_TYPE_EMPTY;
+               break;
+           }
+           data[i].data.length = iov[j].buffer.length;
+           data[i].data.data = iov[j].buffer.value;
+       }
+
+       /* encrypted CFX header in trailer (or after the header if in
+          DCE mode). Copy in header into E"header"
+       */
+       data[i].flags = KRB5_CRYPTO_TYPE_DATA;
+       if (trailer)
+           data[i].data.data = trailer->buffer.value;
+       else
+           data[i].data.data = ((uint8_t *)header->buffer.value) + header->buffer.length - k5hsize - k5tsize - sizeof(*token);
+       data[i].data.length = sizeof(*token);
+       ttoken = (gss_cfx_wrap_token)data[i].data.data;
+       i++;
+
+       /* Kerberos trailer comes after the gss trailer */
+       data[i].flags = KRB5_CRYPTO_TYPE_TRAILER;
+       data[i].data.data = ((uint8_t *)data[i-1].data.data) + sizeof(*token);
+       data[i].data.length = k5tsize;
+       i++;
+
+       ret = krb5_decrypt_iov_ivec(context, ctx->crypto, usage, data, i, NULL);
+       if (ret != 0) {
+           *minor_status = ret;
+           major_status = GSS_S_FAILURE;
+           goto failure;
+       }
+
+       ttoken->RRC[0] = token->RRC[0];
+       ttoken->RRC[1] = token->RRC[1];
+
+       /* Check the integrity of the header */
+       if (memcmp(ttoken, token, sizeof(*token)) != 0) {
+           major_status = GSS_S_BAD_MIC;
+           goto failure;
+       }
+    } else {
+       /* Check RRC */
+       if (rrc != 0) {
+           *minor_status = EINVAL;
+           major_status = GSS_S_FAILURE;
+           goto failure;
+       }
+
+       if (trailer == NULL) {
+           *minor_status = EINVAL;
+           major_status = GSS_S_FAILURE;
+           goto failure;
+       }
+
+       if (trailer->buffer.length != ec) {
+           *minor_status = EINVAL;
+           major_status = GSS_S_FAILURE;
+           goto failure;
+       }
+
+       for (i = 0; i < iov_count; i++) {
+           switch (GSS_IOV_BUFFER_TYPE(iov[i].type)) {
+           case GSS_IOV_BUFFER_TYPE_DATA:
+           case GSS_IOV_BUFFER_TYPE_PADDING:
+               data[i].flags = KRB5_CRYPTO_TYPE_DATA;
+               break;
+           case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
+               data[i].flags = KRB5_CRYPTO_TYPE_SIGN_ONLY;
+               break;
+           default:
+               data[i].flags = KRB5_CRYPTO_TYPE_EMPTY;
+               break;
+           }
+           data[i].data.length = iov[i].buffer.length;
+           data[i].data.data = iov[i].buffer.value;
+       }
+
+       data[i].flags = KRB5_CRYPTO_TYPE_DATA;
+       data[i].data.data = header->buffer.value;
+       data[i].data.length = header->buffer.length;
+       i++;
+
+       data[i].flags = KRB5_CRYPTO_TYPE_CHECKSUM;
+       data[i].data.data = trailer->buffer.value;
+       data[i].data.length = trailer->buffer.length;
+       i++;
+
+       token = (gss_cfx_wrap_token)header->buffer.value;
+       token->EC[0]  = 0;
+       token->EC[1]  = 0;
+       token->RRC[0] = 0;
+       token->RRC[1] = 0;
+
+       ret = krb5_verify_checksum_iov(context, ctx->crypto, usage, data, i, NULL);
+       if (ret) {
+           *minor_status = ret;
+           major_status = GSS_S_FAILURE;
+           goto failure;
+       }
+    }
+
+    if (qop_state != NULL) {
+       *qop_state = GSS_C_QOP_DEFAULT;
+    }
+
+    free(data);
+
+    *minor_status = 0;
+    return GSS_S_COMPLETE;
+
+ failure:
+    if (data)
+       free(data);
+
+    gss_release_iov_buffer(&junk, iov, iov_count);
+
+    return major_status;
+}
+
+OM_uint32
+_gssapi_wrap_iov_length_cfx(OM_uint32 *minor_status,
+                           gsskrb5_ctx ctx,
+                           krb5_context context,
+                           int conf_req_flag,
+                           gss_qop_t qop_req,
+                           int *conf_state,
+                           gss_iov_buffer_desc *iov,
+                           int iov_count)
+{
+    size_t size;
+    int i;
+    size_t *padding = NULL;
+
+    GSSAPI_KRB5_INIT (&context);
+    *minor_status = 0;
+
+    for (size = 0, i = 0; i < iov_count; i++) {
+       switch(GSS_IOV_BUFFER_TYPE(iov[i].type)) {
+       case GSS_IOV_BUFFER_TYPE_EMPTY:
+           break;
+       case GSS_IOV_BUFFER_TYPE_DATA:
+           size += iov[i].buffer.length;
+           break;
+       case GSS_IOV_BUFFER_TYPE_HEADER:
+           *minor_status = krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_HEADER, &iov[i].buffer.length);
+           if (*minor_status)
+               return GSS_S_FAILURE;
+           break;
+       case GSS_IOV_BUFFER_TYPE_TRAILER:
+           *minor_status = krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_TRAILER, &iov[i].buffer.length);
+           if (*minor_status)
+               return GSS_S_FAILURE;
+           break;
+       case GSS_IOV_BUFFER_TYPE_PADDING:
+           if (padding != NULL) {
+               *minor_status = 0;
+               return GSS_S_FAILURE;
+           }
+           padding = &iov[i].buffer.length;
+           break;
+       case GSS_IOV_BUFFER_TYPE_SIGN_ONLY:
+           break;
+       default:
+           *minor_status = EINVAL;
+           return GSS_S_FAILURE;
+       }
+    }
+    if (padding) {
+       size_t pad;
+       krb5_crypto_length(context, ctx->crypto, KRB5_CRYPTO_TYPE_PADDING, &pad);
+       if (pad > 1) {
+           *padding = pad - (size % pad);
+           if (*padding == pad)
+               *padding = 0;
+       } else
+           *padding = 0;
+    }
+
+    return GSS_S_COMPLETE;
+}
+
+
+
+
 OM_uint32 _gssapi_wrap_cfx(OM_uint32 *minor_status,
                           const gsskrb5_ctx ctx,
                           krb5_context context,
                           int conf_req_flag,
-                          gss_qop_t qop_req,
                           const gss_buffer_t input_message_buffer,
                           int *conf_state,
                           gss_buffer_t output_message_buffer)
index fbb0f0218e7e1d15f27f63dc0fb641be73f67cb3..f45e4df3e2059306821433738b4e91ad12daf0c2 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_compare_name
            (OM_uint32 * minor_status,
             const gss_name_t name1,
index 012602c07441623b6841156f5331f4d9634b06f8..221d219c69fa3739ead198f9fdc38f3fe360163e 100644 (file)
@@ -33,9 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
-
 static krb5_error_code
 check_compat(OM_uint32 *minor_status,
             krb5_context context, krb5_const_principal name,
index 323038993880670aa5b59d812d3bf93c3850c97e..987ceea4aa99717d9c09e17f0e2d02a088df97d0 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32
 _gsskrb5_lifetime_left(OM_uint32 *minor_status,
                       krb5_context context,
index 40a8fab1b7b42a3fde291b00a97018c105832945..a4b28f91ed04b22c156d444e7db2ac788d70543c 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 #if 0
 OM_uint32
 gss_krb5_copy_ccache(OM_uint32 *minor_status,
index a2a5de9fe75b87b286bceb04e5610308977619fc..7ccf0b0f79c154113cbc2078634c55390ffa0a66 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 /*
  * return the length of the mechanism in token or -1
  * (which implies that the token was bad - GSS_S_DEFECTIVE_TOKEN
index ea0831815a27f50ec1167590651914972005229f..b3d436ea019c681b3ff450936cda78639625d1bd 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32
 _gsskrb5_delete_sec_context(OM_uint32 * minor_status,
                            gss_ctx_id_t * context_handle,
index 0b377315108ab3782be025c29cddd894b49b5278..6487d8488033c707ba49e30f9e6d07c6347af4a1 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_display_name
            (OM_uint32 * minor_status,
             const gss_name_t input_name,
index 4136c25e533c31a76be8ee73f5e99ad5846d6be0..f9d84fc762843eee5fe21bbcb01e0b2ec50beb23 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 static const char *
 calling_error(OM_uint32 v)
 {
index 2b5e5c0ef48a781ec10ec379627040fb46f3da36..b0188acd517671b9b1a4b0de21d45fa195477694 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_duplicate_name (
             OM_uint32 * minor_status,
             const gss_name_t src_name,
index 838a34d7db9a20f6d1c43d4222ec03e198edd6c4..79cd9232e19dc4cc761af66e78b541d565710286 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 void
 _gssapi_encap_length (size_t data_len,
                      size_t *len,
index bad73611dc84a277854cc83bfb615c667e3a3aa3..705bb70d91cb8decb8a88e9b68043268b10d4099 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_export_name
            (OM_uint32  * minor_status,
             const gss_name_t input_name,
index 305d5c334e64312ceaab52276fb57d06ab0f996c..3d3870a6b45de0c4487a2037e4aa787433f451eb 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32
 _gsskrb5_export_sec_context (
     OM_uint32 * minor_status,
index 1c28f7c141d8f47ab54c83d9d8b51c4265466fde..df23776a63c35da9c82b7fe6450d0c2083a4cb4f 100644 (file)
@@ -34,8 +34,6 @@
 #include "gsskrb5_locl.h"
 #include <gssapi_mech.h>
 
-RCSID("$Id$");
-
 /*
  * The implementation must reserve static storage for a
  * gss_OID_desc object containing the value
index 66aaba44d67827dff7578f1179b3303b5934d7f0..ad3009c73e09adbd80eab3bb84adf3b27fe50d2e 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 static OM_uint32
 mic_des
            (OM_uint32 * minor_status,
index 8f5387fe2b56b32fc8eea7b05ca1bb7cfd1a689a..d488ce754b893e75a91ccaf493d81b23c4a86e1b 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 static OM_uint32
 parse_krb5_name (OM_uint32 *minor_status,
                 krb5_context context,
index ba1a977d2dc6ee8aa7a2b3717d92fa64dbaf2d57..2af942338fb0f8ab2c5f2868900f9ed960609579 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32
 _gsskrb5_import_sec_context (
     OM_uint32 * minor_status,
index 3702106e7903cbda61b4a14e0c2c825a7cf22140..b1d18bd244c9c5df0915526ec0ead588f16e4c7b 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_indicate_mechs
            (OM_uint32 * minor_status,
             gss_OID_set * mech_set
index b28e6a4c12b536e997a47895fd5b8d23ca0da8d2..3a22c33ed69f3d7a43588405a50e297e0da938b7 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 static HEIMDAL_MUTEX context_mutex = HEIMDAL_MUTEX_INITIALIZER;
 static int created_key;
 static HEIMDAL_thread_key context_key;
index 4b632bd95ac768852df380b9951eca4ace827468..35ab9dd88d3abbfb353dbe6030a02e12a3b93d53 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 /*
  * copy the addresses from `input_chan_bindings' (if any) to
  * the auth context `ac'
@@ -697,7 +695,7 @@ repl_mutual
     if (actual_mech_type)
        *actual_mech_type = GSS_KRB5_MECHANISM;
 
-    if (ctx->flags & GSS_C_DCE_STYLE) {
+    if (IS_DCE_STYLE(ctx)) {
        /* There is no OID wrapping. */
        indata.length   = input_token->length;
        indata.data     = input_token->value;
index 188a6135a4b1cd14793c6a8a1e54d4a9663e0398..381ffc9e6f6bdb9572b7e8be68b737f7574df184 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_inquire_context (
     OM_uint32 * minor_status,
        const gss_ctx_id_t context_handle,
index 27e3014923602ac1ebda43479267dea25db67869..518736d78e4142a90763dc064c548b3121075635 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_inquire_cred
 (OM_uint32 * minor_status,
  const gss_cred_id_t cred_handle,
index 1fd973394093638af1758247941574f5af84073b..9da1ac43f181a13e21f73ffd40fbd899921af2eb 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_inquire_cred_by_mech (
     OM_uint32 * minor_status,
        const gss_cred_id_t cred_handle,
index 5a35202a6a04d9a26c037f4327e01f2ed23df9dc..f32342f1d860993846c6e8fa699688249b14ed48 100644 (file)
@@ -32,8 +32,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_inquire_cred_by_oid
           (OM_uint32 * minor_status,
            const gss_cred_id_t cred_handle,
index 5d54bd65086792eeef84a524809c5cd1c931e5f5..5fa3c302a28004209f6209ff8832caff3dc8edf6 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_inquire_mechs_for_name (
             OM_uint32 * minor_status,
             const gss_name_t input_name,
index 9eba7b7f4ddc8586f9f5ac6df70bbd03a89b09ed..591343307e48d5c60764184053daf569fa67a4a5 100644 (file)
@@ -33,9 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
-
 static gss_OID *name_list[] = {
     &GSS_C_NT_HOSTBASED_SERVICE,
     &GSS_C_NT_USER_NAME,
index f8ef2a3aa4e0719dde8b1a21c4bdcdf15d352be9..ce01e666fa028316b27fc96e9da0750306ec1a22 100644 (file)
@@ -32,8 +32,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 static int
 oid_prefix_equal(gss_OID oid_enc, gss_OID prefix_enc, unsigned *suffix)
 {
index 9fd13f51bd27b7318417fb6e3af9aa1d593e0b38..76ae3b78ed33301280f49733935d249bd1503021 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32
 _gsskrb5_pseudo_random(OM_uint32 *minor_status,
                       gss_ctx_id_t context_handle,
index 3229b36292b1007175ed5c8aaddc6c3c55b0ef99..1c9d44588fdea93e5af509c9e71f51bcbee0fe43 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_process_context_token (
        OM_uint32          *minor_status,
        const gss_ctx_id_t context_handle,
index 18e0279939730f958701f3889dffaf09414e0aba..b704e001ebd1c5127b184bdb527a284087914f20 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_release_buffer
            (OM_uint32 * minor_status,
             gss_buffer_t buffer
index 62674a1d530870c23d334cf0806009efad2c0a99..5eec3c48cbd89065b3d3950e5a4be0ea4d2ce55c 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_release_cred
            (OM_uint32 * minor_status,
             gss_cred_id_t * cred_handle
index 5491052c59378b9b7608833db13fc1ec5d570490..0fafc275d0675aa57b472e49c605b2edab618973 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 OM_uint32 _gsskrb5_release_name
            (OM_uint32 * minor_status,
             gss_name_t * input_name
index 6391d44429d46be458003a0c04805dd6f2993aa9..fbbc5b6c7037ca0d5d1b859b08976db0a6e632c8 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 #define DEFAULT_JITTER_WINDOW 20
 
 struct gss_msg_order {
index 2a2390f8d1f3a86870c4d4a69ea2ac44a1eb2e53..15d7632e4c99bc2c83da9410b02e973fb1f0990d 100644 (file)
@@ -32,8 +32,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 /* 1.2.752.43.13.17 */
 static gss_OID_desc gss_krb5_cred_no_ci_flags_x_oid_desc =
 {6, rk_UNCONST("\x2a\x85\x70\x2b\x0d\x11")};
index 460cfe942ad2736e16dd4696b7c9730b7a70c222..096e83504530aedc2aeffb705d1cec2b0ce592df 100644 (file)
@@ -36,8 +36,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 static OM_uint32
 get_bool(OM_uint32 *minor_status,
         const gss_buffer_t value,
index 0e87cb88b73d8682f897cbbb22239cca8551bf10..20cf952b4eb4a96092ad64dfe6fa5364436bb9eb 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 static OM_uint32
 unwrap_des
            (OM_uint32 * minor_status,
index 6eb7ae4b089fee2f3aabc3b626ef1b5ebfda4753..c7e16e81f77f28fac2e83f9f404d52a8fe5c801e 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 static OM_uint32
 verify_mic_des
            (OM_uint32 * minor_status,
index b9f4c237c767d540e124abb2c3e34aaa0593eb31..3de13f908f1621e1c7e4fc873aa20ac6cfc55196 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "gsskrb5_locl.h"
 
-RCSID("$Id$");
-
 /*
  * Return initiator subkey, or if that doesn't exists, the subkey.
  */
@@ -540,7 +538,7 @@ OM_uint32 _gsskrb5_wrap
 
   if (ctx->more_flags & IS_CFX)
       return _gssapi_wrap_cfx (minor_status, ctx, context, conf_req_flag,
-                              qop_req, input_message_buffer, conf_state,
+                              input_message_buffer, conf_state,
                               output_message_buffer);
 
   HEIMDAL_MUTEX_lock(&ctx->ctx_id_mutex);
index a8ebe644ab239c88d18e3b76f610e233e2bbe43c..b1bc7dd98132faa4cd1f2a29de33d116f5827f7c 100644 (file)
@@ -50,7 +50,7 @@ gss_acquire_cred(OM_uint32 *minor_status,
        int i;
 
        *minor_status = 0;
-       if (output_cred_handle)
+       if (output_cred_handle == NULL)
            return GSS_S_CALL_INACCESSIBLE_READ;
        if (actual_mechs)
            *actual_mechs = GSS_C_NO_OID_SET;
index cbe0cd146093399237b7fa5fc1e8e8c81fada39f..9c784f42de108f42a37d84decc8beeaeaf663cdd 100644 (file)
@@ -3,27 +3,39 @@
  */ 
 
 #include "mech_locl.h"
-RCSID("$Id$");
 
 /**
  * Encrypts or sign the data.
  *
+ * This is a more complicated version of gss_wrap(), it allows the
+ * caller to use AEAD data (signed header/trailer) and allow greater
+ * controll over where the encrypted data is placed.
+ *
  * The maximum packet size is gss_context_stream_sizes.max_msg_size.
  *
- * The caller needs provide the folloing buffers:
+ * The caller needs provide the folloing buffers when using in conf_req_flag=1 mode:
  *
  * - HEADER (of size gss_context_stream_sizes.header)
- *   SIGN_ONLY (optional, zero or more)
- *   DATA
- *   SIGN_ONLY (optional, zero or more)
- *   PADDING (of size gss_context_stream_sizes.blocksize)
+ *   { DATA or SIGN_ONLY } (optional, zero or more)
+ *   PADDING (of size gss_context_stream_sizes.blocksize, if zero padding is zero, can be omitted)
  *   TRAILER (of size gss_context_stream_sizes.trailer)
  *
  * - on DCE-RPC mode, the caller can skip PADDING and TRAILER if the
- *   DATA elements is padded to a block bountry.
+ *   DATA elements is padded to a block bountry and header is of at
+ *   least size gss_context_stream_sizes.header + gss_context_stream_sizes.trailer.
+ *
+ * HEADER, PADDING, TRAILER will be shrunken to the size required to transmit any of them too large.
  *
  * To generate gss_wrap() compatible packets, use: HEADER | DATA | PADDING | TRAILER
  *
+ * When used in conf_req_flag=0,
+ *
+ * - HEADER (of size gss_context_stream_sizes.header)
+ *   { DATA or SIGN_ONLY } (optional, zero or more)
+ *   PADDING (of size gss_context_stream_sizes.blocksize, if zero padding is zero, can be omitted)
+ *   TRAILER (of size gss_context_stream_sizes.trailer)
+ *
+ *
  * The input sizes of HEADER, PADDING and TRAILER can be fetched using gss_wrap_iov_length() or
  * gss_context_query_attributes().
  *
@@ -65,6 +77,13 @@ gss_wrap_iov(OM_uint32 * minor_status,
                                iov, iov_count);
 }
 
+/**
+ * Decrypt or verifies the signature on the data.
+ *
+ *
+ * @ingroup gssapi
+ */
+
 OM_uint32 GSSAPI_LIB_FUNCTION
 gss_unwrap_iov(OM_uint32 *minor_status,
               gss_ctx_id_t context_handle,
@@ -99,7 +118,18 @@ gss_unwrap_iov(OM_uint32 *minor_status,
                                  iov, iov_count);
 }
 
-OM_uint32  GSSAPI_LIB_FUNCTION
+/**
+ * Update the length fields in iov buffer for the types:
+ * - GSS_IOV_BUFFER_TYPE_HEADER
+ * - GSS_IOV_BUFFER_TYPE_PADDING
+ * - GSS_IOV_BUFFER_TYPE_TRAILER
+ *
+ * Consider using gss_context_query_attributes() to fetch the data instead.
+ *
+ * @ingroup gssapi
+ */
+
+OM_uint32 GSSAPI_LIB_FUNCTION
 gss_wrap_iov_length(OM_uint32 * minor_status,
                    gss_ctx_id_t context_handle,
                    int conf_req_flag,
@@ -132,6 +162,13 @@ gss_wrap_iov_length(OM_uint32 * minor_status,
                                       iov, iov_count);
 }
 
+/**
+ * Free all buffer allocated by gss_wrap_iov() or gss_unwrap_iov() by
+ * looking at the GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED flag.
+ *
+ * @ingroup gssapi
+ */
+
 OM_uint32 GSSAPI_LIB_FUNCTION
 gss_release_iov_buffer(OM_uint32 *minor_status,
                       gss_iov_buffer_desc *iov,
@@ -146,9 +183,10 @@ gss_release_iov_buffer(OM_uint32 *minor_status,
        return GSS_S_CALL_INACCESSIBLE_READ;
 
     for (i = 0; i < iov_count; i++) {
-       if (iov[i].type & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED)
+       if ((iov[i].type & GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED) == 0)
            continue;
        gss_release_buffer(&junk, &iov[i].buffer);
+       iov[i].type &= ~GSS_IOV_BUFFER_TYPE_FLAG_ALLOCATED;
     }
     return GSS_S_COMPLETE;
 }
@@ -159,6 +197,8 @@ gss_release_iov_buffer(OM_uint32 *minor_status,
  * SSPI equivalent if this function is QueryContextAttributes.
  *
  * - GSS_C_ATTR_STREAM_SIZES data is a gss_context_stream_sizes.
+ *
+ * @ingroup gssapi
  */
 
 static gss_OID_desc gss_c_attr_stream_sizes_desc =
index 158126d99f96cd1c7876121cf0e42d1ececbc774..2bdfc28ebf9582f7d11296a9df48be456183a3c8 100644 (file)
@@ -92,12 +92,6 @@ send_supported_mechs (OM_uint32 *minor_status,
                      gss_buffer_t output_token)
 {
     NegotiationTokenWin nt;
-    char hostname[MAXHOSTNAMELEN + 1], *p;
-    gss_buffer_desc name_buf;
-    gss_OID name_type;
-    gss_name_t target_princ;
-    gss_name_t canon_princ;
-    OM_uint32 minor;
     size_t buf_len;
     gss_buffer_desc data;
     OM_uint32 ret;
@@ -116,62 +110,9 @@ send_supported_mechs (OM_uint32 *minor_status,
        return ret;
     }
 
-    memset(&target_princ, 0, sizeof(target_princ));
-    if (gethostname(hostname, sizeof(hostname) - 2) != 0) {
-       *minor_status = errno;
-       free_NegotiationTokenWin(&nt);
-       return GSS_S_FAILURE;
-    }
-    hostname[sizeof(hostname) - 1] = '\0';
-
-    /* Send the constructed SAM name for this host */
-    for (p = hostname; *p != '\0' && *p != '.'; p++) {
-       *p = toupper((unsigned char)*p);
-    }
-    *p++ = '$';
-    *p = '\0';
-
-    name_buf.length = strlen(hostname);
-    name_buf.value = hostname;
-
-    ret = gss_import_name(minor_status, &name_buf,
-                         GSS_C_NO_OID,
-                         &target_princ);
-    if (ret != GSS_S_COMPLETE) {
-       free_NegotiationTokenWin(&nt);
-       return ret;
-    }
-
-    name_buf.length = 0;
-    name_buf.value = NULL;
-
-    /* Canonicalize the name using the preferred mechanism */
-    ret = gss_canonicalize_name(minor_status,
-                               target_princ,
-                               GSS_C_NO_OID,
-                               &canon_princ);
-    if (ret != GSS_S_COMPLETE) {
-       free_NegotiationTokenWin(&nt);
-       gss_release_name(&minor, &target_princ);
-       return ret;
-    }
-
-    ret = gss_display_name(minor_status, canon_princ,
-                          &name_buf, &name_type);
-    if (ret != GSS_S_COMPLETE) {
-       free_NegotiationTokenWin(&nt);
-       gss_release_name(&minor, &canon_princ);
-       gss_release_name(&minor, &target_princ);
-       return ret;
-    }
-
-    gss_release_name(&minor, &canon_princ);
-    gss_release_name(&minor, &target_princ);
-
     ALLOC(nt.u.negTokenInit.negHints, 1);
     if (nt.u.negTokenInit.negHints == NULL) {
        *minor_status = ENOMEM;
-       gss_release_buffer(&minor, &name_buf);
        free_NegotiationTokenWin(&nt);
        return GSS_S_FAILURE;
     }
@@ -179,20 +120,19 @@ send_supported_mechs (OM_uint32 *minor_status,
     ALLOC(nt.u.negTokenInit.negHints->hintName, 1);
     if (nt.u.negTokenInit.negHints->hintName == NULL) {
        *minor_status = ENOMEM;
-       gss_release_buffer(&minor, &name_buf);
        free_NegotiationTokenWin(&nt);
        return GSS_S_FAILURE;
     }
 
-    *(nt.u.negTokenInit.negHints->hintName) = name_buf.value;
-    name_buf.value = NULL;
+    *nt.u.negTokenInit.negHints->hintName = strdup("not_defined_in_RFC4178@please_ignore");
     nt.u.negTokenInit.negHints->hintAddress = NULL;
 
     ASN1_MALLOC_ENCODE(NegotiationTokenWin,
                       data.value, data.length, &nt, &buf_len, ret);
     free_NegotiationTokenWin(&nt);
     if (ret) {
-       return ret;
+       *minor_status = ret;
+       return GSS_S_FAILURE;
     }
     if (data.length != buf_len)
        abort();
index 556833d1c452a5429098053ed11a1dda89d81ad8..9de0a04a1fadf881f71e408414c0d9c855315b15 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "hdb_locl.h"
 
-RCSID("$Id$");
-
 #if HAVE_DB1
 
 #if defined(HAVE_DB_185_H)
@@ -317,6 +315,7 @@ hdb_db_create(krb5_context context, HDB **db,
     }
     (*db)->hdb_master_key_set = 0;
     (*db)->hdb_openp = 0;
+    (*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL;
     (*db)->hdb_open = DB_open;
     (*db)->hdb_close = DB_close;
     (*db)->hdb_fetch = _hdb_fetch;
index 7e2961c61438610c62d1f1b2d6e61603fc701989..a399ab0a5cac5d35fafd1a10331e6fd15f85c9eb 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "hdb_locl.h"
 
-RCSID("$Id$");
-
 struct hdb_dbinfo {
     char *label;
     char *realm;
index 9053fd66335c1d56e7516b0ebdac2c66a4b9b0fa..faf0b6bdf29149227bb5dfc4afb50ad074e923d6 100644 (file)
@@ -34,8 +34,6 @@
 #include "hdb_locl.h"
 #include <der.h>
 
-RCSID("$Id$");
-
 krb5_error_code
 hdb_entry_check_mandatory(krb5_context context, const hdb_entry *ent)
 {
index c2abd4af73ee78b71984f33d75ba5899e12c9f77..a72851c9f2011b65895aa46ba2c33aabbc2da192 100644 (file)
@@ -45,7 +45,9 @@ HDBFlags ::= BIT STRING {
        immutable(13),                  -- may not be deleted
        trusted-for-delegation(14),     -- Trusted to print forwardabled tickets
        allow-kerberos4(15),            -- Allow Kerberos 4 requests
-       allow-digest(16)                -- Allow digest requests
+       allow-digest(16),               -- Allow digest requests
+       locked-out(17)                  -- Account is locked out,
+                                       -- authentication will be denied
 }
 
 GENERATION ::= SEQUENCE {
index e55b0bed03ce286d51f8ed1f66db1c3bcf142217..9795f8b255b75b885c6d1da8f69e936816c2f34d 100644 (file)
@@ -33,7 +33,6 @@
 
 #include "krb5_locl.h"
 #include "hdb_locl.h"
-RCSID("$Id$");
 
 #ifdef HAVE_DLFCN_H
 #include <dlfcn.h>
index a5e6514e6c836bdd375052cb1b09e0ec70341c90..f490dbf2f0f1a5807013ef452741f41d47f11508 100644 (file)
@@ -54,7 +54,15 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK };
 #define HDB_F_GET_ANY          28      /* fetch any of client,server,krbtgt */
 #define HDB_F_CANON            32      /* want canonicalition */
 
+/* hdb_capability_flags */
 #define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1
+#define HDB_CAP_F_HANDLE_PASSWORDS     2
+#define HDB_CAP_F_PASSWORD_UPDATE_KEYS 4
+
+/* auth status values */
+#define HDB_AUTH_SUCCESS               0
+#define HDB_AUTH_WRONG_PASSWORD                1
+#define HDB_AUTH_INVALID_SIGNATURE     2
 
 /* key usage for master key */
 #define HDB_KU_MKEY    0x484442
@@ -184,6 +192,34 @@ typedef struct HDB{
      * point for the module.
      */
     krb5_error_code (*hdb_destroy)(krb5_context, struct HDB*);
+    /**
+     * Change password.
+     *
+     * Will update keys for the entry when given password.  The new
+     * keys must be written into the entry and and will then later be
+     * ->hdb_store() into the database. The backend will still perform
+     * all other operations, increasing the kvno, and update
+     * modification timestamp.
+     * 
+     * The backen need to call _kadm5_set_keys() and perform password
+     * quality checks.
+     */
+    krb5_error_code (*hdb_password)(krb5_context, struct HDB*, hdb_entry_ex*, const char *, int);
+
+    /**
+     * Auth feedback
+     *
+     * This is a feedback call that allows backends that provides
+     * lockout functionality to register failure and/or successes.
+     *
+     * In case the entry is locked out, the backend should set the
+     * hdb_entry.flags.locked-out flag.
+     */
+    krb5_error_code (*hdb_auth_status)(krb5_context, struct HDB *, hdb_entry_ex *, int);
+    /**
+     * Check is delegation is allowed.
+     */
+    krb5_error_code (*hdb_check_constrained_delegation)(krb5_context, struct HDB *, hdb_entry_ex *, krb5_const_principal);
 }HDB;
 
 #define HDB_INTERFACE_VERSION  5
index 50fe7d7fda531b69b945a67d9f89521f2c3affe0..63f254d0022ae95c267a81c147713c402e3207bd 100644 (file)
@@ -34,8 +34,6 @@
 
 #include "hdb_locl.h"
 
-RCSID("$Id$");
-
 /*
  * free all the memory used by (len, keys)
  */
index 97989a97641a1f3e6d0c5357d25ec602aad792dc..9b36a268cfd7b34feddf9134c1a334b0bb68382b 100644 (file)
@@ -35,8 +35,6 @@
 
 /* keytab backend for HDB databases */
 
-RCSID("$Id$");
-
 struct hdb_data {
     char *dbname;
     char *mkey;
@@ -123,61 +121,43 @@ hdb_get_name(krb5_context context,
     return 0;
 }
 
-static void
-set_config (krb5_context context,
-           const krb5_config_binding *binding,
-           const char **dbname,
-           const char **mkey)
-{
-    *dbname = krb5_config_get_string(context, binding, "dbname", NULL);
-    *mkey   = krb5_config_get_string(context, binding, "mkey_file", NULL);
-}
-
 /*
  * try to figure out the database (`dbname') and master-key (`mkey')
  * that should be used for `principal'.
  */
 
-static void
+static krb5_error_code
 find_db (krb5_context context,
-        const char **dbname,
-        const char **mkey,
+        char **dbname,
+        char **mkey,
         krb5_const_principal principal)
 {
-    const krb5_config_binding *top_bind = NULL;
-    const krb5_config_binding *default_binding = NULL;
-    const krb5_config_binding *db;
     krb5_const_realm realm = krb5_principal_get_realm(context, principal);
+    krb5_error_code ret;
+    struct hdb_dbinfo *head, *dbinfo = NULL;
 
     *dbname = *mkey = NULL;
 
-    while ((db =
-           krb5_config_get_next(context,
-                                NULL,
-                                &top_bind,
-                                krb5_config_list,
-                                "kdc",
-                                "database",
-                                NULL)) != NULL) {
-       const char *p;
-       
-       p = krb5_config_get_string (context, db, "realm", NULL);
-       if (p == NULL) {
-           if(default_binding) {
-               krb5_warnx(context, "WARNING: more than one realm-less "
-                          "database specification");
-               krb5_warnx(context, "WARNING: using the first encountered");
-           } else
-               default_binding = db;
-       } else if (strcmp (realm, p) == 0) {
-           set_config (context, db, dbname, mkey);
+    ret = hdb_get_dbinfo(context, &head);
+    if (ret)
+       return ret;
+
+    while ((dbinfo = hdb_dbinfo_get_next(head, dbinfo)) != NULL) {
+       const char *p = hdb_dbinfo_get_realm(context, dbinfo);
+       if (p && strcmp (realm, p) == 0) {
+           p = hdb_dbinfo_get_dbname(context, dbinfo);
+           if (p)
+               *dbname = strdup(p);
+           p = hdb_dbinfo_get_mkey_file(context, dbinfo);
+           if (p)
+               *mkey = strdup(p);
            break;
        }
     }
-    if (*dbname == NULL && default_binding != NULL)
-       set_config (context, default_binding, dbname, mkey);
+    hdb_free_dbinfo(context, &head);
     if (*dbname == NULL)
-       *dbname = HDB_DEFAULT_DB;
+       *dbname = strdup(HDB_DEFAULT_DB);
+    return 0;
 }
 
 /*
@@ -196,29 +176,35 @@ hdb_get_entry(krb5_context context,
     hdb_entry_ex ent;
     krb5_error_code ret;
     struct hdb_data *d = id->data;
-    int i;
-    HDB *db;
     const char *dbname = d->dbname;
     const char *mkey   = d->mkey;
+    char *fdbname = NULL, *fmkey = NULL;
+    HDB *db;
+    int i;
 
     memset(&ent, 0, sizeof(ent));
 
-    if (dbname == NULL)
-       find_db (context, &dbname, &mkey, principal);
+    if (dbname == NULL) {
+       ret = find_db(context, &fdbname, &fmkey, principal);
+       if (ret)
+           return ret;
+       dbname = fdbname;
+       mkey = fmkey;
+    }
 
     ret = hdb_create (context, &db, dbname);
     if (ret)
-       return ret;
+       goto out2;
     ret = hdb_set_master_keyfile (context, db, mkey);
     if (ret) {
        (*db->hdb_destroy)(context, db);
-       return ret;
+       goto out2;
     }
        
     ret = (*db->hdb_open)(context, db, O_RDONLY, 0);
     if (ret) {
        (*db->hdb_destroy)(context, db);
-       return ret;
+       goto out2;
     }
     ret = (*db->hdb_fetch)(context, db, principal,
                           HDB_F_DECRYPT|
@@ -252,9 +238,12 @@ hdb_get_entry(krb5_context context,
        }
     }
     hdb_free_entry(context, &ent);
-out:
+ out:
     (*db->hdb_close)(context, db);
     (*db->hdb_destroy)(context, db);
+ out2:
+    free(fdbname);
+    free(fmkey);
     return ret;
 }
 
index 1520c4f7e9a06641afcb71da5ab5a58035e03e91..35323cf10038804501c3422e9489c0e4f8e12f89 100644 (file)
@@ -36,8 +36,6 @@
 #define O_BINARY 0
 #endif
 
-RCSID("$Id$");
-
 struct hdb_master_key_data {
     krb5_keytab_entry keytab;
     krb5_crypto crypto;
index 1e9df8165202b2cd85a693d5d50349c9b40517c2..d97a98ed6b5a1261aa3e5cc10bb464fafdc6b0da 100644 (file)
@@ -33,8 +33,6 @@
 
 #include "hdb_locl.h"
 
-RCSID("$Id$");
-
 #if HAVE_NDBM
 
 #if defined(HAVE_GDBM_NDBM_H)
@@ -348,6 +346,7 @@ hdb_ndbm_create(krb5_context context, HDB **db,
     }
     (*db)->hdb_master_key_set = 0;
     (*db)->hdb_openp = 0;
+    (*db)->hdb_capability_flags = HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL;
     (*db)->hdb_open = NDBM_open;
     (*db)->hdb_close = NDBM_close;
     (*db)->hdb_fetch = _hdb_fetch;
index 80631007173dc76463f3cd1347e18cfdffd296ca..f4667c6e31596d3a61ba2de4b22fe47700a239b7 100644 (file)
@@ -37,10 +37,6 @@ struct hx509_crypto;
 
 struct signature_alg;
 
-enum crypto_op_type {
-    COT_SIGN
-};
-
 struct hx509_generate_private_context {
     const heim_oid *key_oid;
     int isCA;
index 9fd21173454db2389e284599720f60dab645d2c2..a30780d1edcfc0b665b8688b0bfde436e37b2072 100644 (file)
@@ -3182,7 +3182,7 @@ krb5_encrypt_iov_ivec(krb5_context context,
     krb5_error_code ret;
     struct key_data *dkey;
     const struct encryption_type *et = crypto->et;
-    krb5_crypto_iov *tiv, *piv, *hiv, *div;
+    krb5_crypto_iov *tiv, *piv, *hiv;
 
     if (num_data < 0) {
         krb5_clear_error_message(context);
@@ -3197,11 +3197,11 @@ krb5_encrypt_iov_ivec(krb5_context context,
     headersz = et->confoundersize;
     trailersz = CHECKSUMSIZE(et->keyed_checksum);
 
-    div = find_iv(data, num_data, KRB5_CRYPTO_TYPE_DATA);
-    if (div == NULL)
-       return KRB5_CRYPTO_INTERNAL;
-    
-    len = div->data.length;
+    for (len = 0, i = 0; i < num_data; i++) {
+       if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
+           continue;
+       len += data[i].data.length;
+    }
 
     sz = headersz + len;
     block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
@@ -3217,7 +3217,6 @@ krb5_encrypt_iov_ivec(krb5_context context,
     krb5_generate_random_block(hiv->data.data, hiv->data.length);
 
     /* padding */
-
     piv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_PADDING);
     /* its ok to have no TYPE_PADDING if there is no padding */
     if (piv == NULL && pad_sz != 0)
@@ -3226,26 +3225,26 @@ krb5_encrypt_iov_ivec(krb5_context context,
        if (piv->data.length < pad_sz)
            return KRB5_BAD_MSIZE;
        piv->data.length = pad_sz;
+       if (pad_sz)
+           memset(piv->data.data, pad_sz, pad_sz);
+       else
+           piv = NULL;
     }
 
-
     /* trailer */
-
     tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
     if (tiv == NULL || tiv->data.length != trailersz)
        return KRB5_BAD_MSIZE;
 
-
     /*
      * XXX replace with EVP_Sign? at least make create_checksum an iov
      * function.
      * XXX CTS EVP is broken, can't handle multi buffers :(
      */
 
-    len = hiv->data.length;
+    len = block_sz;
     for (i = 0; i < num_data; i++) {
-       if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
-           data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
+       if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
            continue;
        len += data[i].data.length;
     }
@@ -3261,6 +3260,10 @@ krb5_encrypt_iov_ivec(krb5_context context,
        memcpy(q, data[i].data.data, data[i].data.length);
        q += data[i].data.length;
     }
+    if (piv) {
+       memset(q, 0, piv->data.length);
+       q += piv->data.length;
+    }
 
     ret = create_checksum(context,
                          et->keyed_checksum,
@@ -3282,30 +3285,24 @@ krb5_encrypt_iov_ivec(krb5_context context,
     memcpy(tiv->data.data, cksum.checksum.data, cksum.checksum.length);
     free_Checksum (&cksum);
 
-    /* now encrypt data */
-
-    ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
-    if(ret)
-       return ret;
-    ret = _key_schedule(context, dkey);
-    if(ret)
-       return ret;
-
     /* XXX replace with EVP_Cipher */
-
-    len = hiv->data.length + div->data.length;
-    if (piv)
-       len += piv->data.length;
-
-    p = q = malloc(len);
+    p = q = malloc(block_sz);
     if(p == NULL)
        return ENOMEM;
 
     memcpy(q, hiv->data.data, hiv->data.length);
     q += hiv->data.length;
-    memcpy(q, div->data.data, div->data.length);
-    q += div->data.length;
-    memset(q, 0, pad_sz);
+
+    for (i = 0; i < num_data; i++) {
+       if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
+           continue;
+       memcpy(q, data[i].data.data, data[i].data.length);
+       q += data[i].data.length;
+    }
+    if (piv) {
+       memset(q, 0, piv->data.length);
+       q += piv->data.length;
+    }
 
     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
     if(ret) {
@@ -3318,7 +3315,7 @@ krb5_encrypt_iov_ivec(krb5_context context,
        return ret;
     }
 
-    ret = (*et->encrypt)(context, dkey, p, len, 1, usage, ivec);
+    ret = (*et->encrypt)(context, dkey, p, block_sz, 1, usage, ivec);
     if (ret) {
        free(p);
        return ret;
@@ -3330,11 +3327,17 @@ krb5_encrypt_iov_ivec(krb5_context context,
     memcpy(hiv->data.data, q, hiv->data.length);
     q += hiv->data.length;
 
-    memcpy(div->data.data, q, div->data.length);
-    q += div->data.length;
-
-    if (piv)
+    for (i = 0; i < num_data; i++) {
+       if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
+           continue;
+       memcpy(data[i].data.data, q, data[i].data.length);
+       q += data[i].data.length;
+    }
+    if (piv) {
        memcpy(piv->data.data, q, pad_sz);
+       q += pad_sz;
+    }
+
     free(p);
 
     return ret;
@@ -3371,13 +3374,12 @@ krb5_decrypt_iov_ivec(krb5_context context,
 {
     unsigned int i;
     size_t headersz, trailersz, len;
-    size_t sz, block_sz, pad_sz;
     Checksum cksum;
     unsigned char *p, *q;
     krb5_error_code ret;
     struct key_data *dkey;
     struct encryption_type *et = crypto->et;
-    krb5_crypto_iov *tiv, *hiv, *div;
+    krb5_crypto_iov *tiv, *hiv;
 
     if (num_data < 0) {
         krb5_clear_error_message(context);
@@ -3390,56 +3392,47 @@ krb5_decrypt_iov_ivec(krb5_context context,
     }
 
     headersz = et->confoundersize;
-    trailersz = CHECKSUMSIZE(et->keyed_checksum);
-
-    for (len = 0, i = 0; i < num_data; i++) {
-       if (data[i].flags == KRB5_CRYPTO_TYPE_DATA) {
-           if (len != 0) 
-               return KRB5_CRYPTO_INTERNAL;
-           len += data[i].data.length;
-       }
-    }
-
-    sz = headersz + len;
-    block_sz = (sz + et->padsize - 1) &~ (et->padsize - 1); /* pad */
-
-    pad_sz = block_sz - sz;
-    trailersz += pad_sz;
-
-    /* header */
 
     hiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_HEADER);
-    if (hiv == NULL || hiv->data.length < headersz)
+    if (hiv == NULL || hiv->data.length != headersz)
        return KRB5_BAD_MSIZE;
-    hiv->data.length = headersz;
 
     /* trailer */
+    trailersz = CHECKSUMSIZE(et->keyed_checksum);
 
     tiv = find_iv(data, num_data, KRB5_CRYPTO_TYPE_TRAILER);
-    if (tiv == NULL || tiv->data.length < trailersz)
+    if (tiv->data.length != trailersz)
        return KRB5_BAD_MSIZE;
-    tiv->data.length = trailersz;
-
-    div = find_iv(data, num_data, KRB5_CRYPTO_TYPE_DATA);
-    if (div == NULL)
-       return KRB5_CRYPTO_INTERNAL;
 
-    /* XXX replace with EVP_Cipher */
+    /* Find length of data we will decrypt */
 
-    for (len = 0, i = 0; i < num_data; i++) {
-       if (data[i].flags != KRB5_CRYPTO_TYPE_HEADER &&
-           data[i].flags != KRB5_CRYPTO_TYPE_DATA)
+    len = headersz;
+    for (i = 0; i < num_data; i++) {
+       if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
            continue;
        len += data[i].data.length;
     }
 
+    if ((len % et->padsize) != 0) {
+       krb5_clear_error_message(context);
+       return KRB5_BAD_MSIZE;
+    }
+
+    /* XXX replace with EVP_Cipher */
+
     p = q = malloc(len);
     if (p == NULL)
        return ENOMEM;
 
     memcpy(q, hiv->data.data, hiv->data.length);
     q += hiv->data.length;
-    memcpy(q, div->data.data, div->data.length);
+
+    for (i = 0; i < num_data; i++) {
+       if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
+           continue;
+       memcpy(q, data[i].data.data, data[i].data.length);
+       q += data[i].data.length;
+    }
 
     ret = _get_derived_key(context, crypto, ENCRYPTION_USAGE(usage), &dkey);
     if(ret) {
@@ -3460,20 +3453,26 @@ krb5_decrypt_iov_ivec(krb5_context context,
 
     /* copy data back to buffers */
     memcpy(hiv->data.data, p, hiv->data.length);
-    memcpy(div->data.data, p + hiv->data.length, len - hiv->data.length);
+    q = p + hiv->data.length;
+    for (i = 0; i < num_data; i++) {
+       if (data[i].flags != KRB5_CRYPTO_TYPE_DATA)
+           continue;
+       memcpy(data[i].data.data, q, data[i].data.length);
+       q += data[i].data.length;
+    }
+
     free(p);
 
     /* check signature */
-
-    len = hiv->data.length;
     for (i = 0; i < num_data; i++) {
-       if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
-           data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
+       if (data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
            continue;
        len += data[i].data.length;
     }
 
     p = q = malloc(len);
+    if (p == NULL)
+       return ENOMEM;
 
     memcpy(q, hiv->data.data, hiv->data.length);
     q += hiv->data.length;
@@ -3582,33 +3581,145 @@ krb5_create_checksum_iov(krb5_context context,
     return 0;
 }
 
+/**
+ * Verify a Kerberos message checksum.
+ *
+ * @param context Kerberos context
+ * @param crypto Kerberos crypto context
+ * @param usage Key usage for this buffer
+ * @param data array of buffers to process
+ * @param num_data length of array
+ *
+ * @return Return an error code or 0.
+ * @ingroup krb5_crypto
+ */
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_verify_checksum_iov(krb5_context context,
+                        krb5_crypto crypto,
+                        unsigned usage,
+                        krb5_crypto_iov *data,
+                        unsigned int num_data,
+                        krb5_cksumtype *type)
+{
+    struct encryption_type *et = crypto->et;
+    Checksum cksum;
+    krb5_crypto_iov *civ;
+    krb5_error_code ret;
+    int i;
+    size_t len;
+    char *p, *q;
+
+    if (num_data < 0) {
+        krb5_clear_error_message(context);
+       return KRB5_CRYPTO_INTERNAL;
+    }
+
+    if(!derived_crypto(context, crypto)) {
+       krb5_clear_error_message(context);
+       return KRB5_CRYPTO_INTERNAL;
+    }
+
+    civ = find_iv(data, num_data, KRB5_CRYPTO_TYPE_CHECKSUM);
+    if (civ == NULL)
+       return KRB5_BAD_MSIZE;
+
+    len = 0;
+    for (i = 0; i < num_data; i++) {
+       if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
+           data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
+           continue;
+       len += data[i].data.length;
+    }
+
+    p = q = malloc(len);
+
+    for (i = 0; i < num_data; i++) {
+       if (data[i].flags != KRB5_CRYPTO_TYPE_DATA &&
+           data[i].flags != KRB5_CRYPTO_TYPE_SIGN_ONLY)
+           continue;
+       memcpy(q, data[i].data.data, data[i].data.length);
+       q += data[i].data.length;
+    }
+
+    cksum.cksumtype = CHECKSUMTYPE(et->keyed_checksum);
+    cksum.checksum.length = civ->data.length;
+    cksum.checksum.data = civ->data.data;
+
+    ret = krb5_verify_checksum(context, crypto, usage, p, len, &cksum);
+    free(p);
+
+    if (ret == 0 && type)
+       *type = cksum.cksumtype;
+
+    return ret;
+}
+
 
-size_t KRB5_LIB_FUNCTION
+krb5_error_code KRB5_LIB_FUNCTION
 krb5_crypto_length(krb5_context context,
                   krb5_crypto crypto,
-                  int type)
+                  int type,
+                  size_t *len)
 {
-    if (!derived_crypto(context, crypto))
-       return (size_t)-1;
+    if (!derived_crypto(context, crypto)) {
+       krb5_set_error_message(context, EINVAL, "not a derived crypto");
+       return EINVAL;
+    }
+       
     switch(type) {
     case KRB5_CRYPTO_TYPE_EMPTY:
+       *len = 0;
        return 0;
     case KRB5_CRYPTO_TYPE_HEADER:
-       return crypto->et->blocksize;
+       *len = crypto->et->blocksize;
+       return 0;
+    case KRB5_CRYPTO_TYPE_DATA:
+    case KRB5_CRYPTO_TYPE_SIGN_ONLY:
+       /* len must already been filled in */
+       return 0;
     case KRB5_CRYPTO_TYPE_PADDING:
        if (crypto->et->padsize > 1)
-           return crypto->et->padsize;
+           *len = crypto->et->padsize;
+       else
+           *len = 0;
        return 0;
     case KRB5_CRYPTO_TYPE_TRAILER:
-       return CHECKSUMSIZE(crypto->et->keyed_checksum);
+       *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
+       return 0;
     case KRB5_CRYPTO_TYPE_CHECKSUM:
        if (crypto->et->keyed_checksum)
-           return CHECKSUMSIZE(crypto->et->keyed_checksum);
-       return CHECKSUMSIZE(crypto->et->checksum);
+           *len = CHECKSUMSIZE(crypto->et->keyed_checksum);
+       else
+           *len = CHECKSUMSIZE(crypto->et->checksum);
+       return 0;
+    }
+    krb5_set_error_message(context, EINVAL,
+                          "%d not a supported type", type);
+    return EINVAL;
+}
+
+
+krb5_error_code KRB5_LIB_FUNCTION
+krb5_crypto_length_iov(krb5_context context,
+                      krb5_crypto crypto,
+                      krb5_crypto_iov *data,
+                      unsigned int num_data)
+{
+    krb5_error_code ret;
+    int i;
+
+    for (i = 0; i < num_data; i++) {
+       ret = krb5_crypto_length(context, crypto,
+                                data[i].flags,
+                                &data[i].data.length);
+       if (ret)
+           return ret;
     }
-    return (size_t)-1;
+    return 0;
 }
 
+
 krb5_error_code KRB5_LIB_FUNCTION
 krb5_encrypt_ivec(krb5_context context,
                  krb5_crypto crypto,
index 96571af531a9f5ac577264dda5f118fcd2eaf015..8f366fa1487dc7d9ea3eebb5be5936c88c54cdff 100644 (file)
@@ -41,9 +41,7 @@ struct mbuf;
 #ifdef HAVE_NET_IF_H
 #include <net/if.h>
 #endif
-#ifdef HAVE_IFADDR_H
 #include <ifaddrs.h>
-#endif
 
 static krb5_error_code
 gethostname_fallback (krb5_context context, krb5_addresses *res)
index 0435ab5d3b825210f2421bf6bf40f309409218d0..ff89a90d55a89afb45cd07d5248c8b4023194ce4 100644 (file)
@@ -1601,7 +1601,7 @@ krb5_init_creds_step(krb5_context context,
                    ret = 0; 
            } else if (ret == KRB5_KDC_ERR_WRONG_REALM && ctx->flags.canonicalize) {
                /* client referal to a new realm */
-               if (ctx->error.crealm) {
+               if (ctx->error.crealm == NULL) {
                    krb5_set_error_message(context, ret,
                                           N_("Got a client referral, not but no realm", ""));
                    goto out;
index 4be89b6564bcfeb20a61f008a87d4ccb90386716..acf984280ee1a16bae20680afb93c35d21f2d106 100644 (file)
@@ -110,7 +110,12 @@ emem_trunc(krb5_storage *sp, off_t offset)
      * If offset is larget then current size, or current size is
      * shrunk more then half of the current size, adjust buffer.
      */
-    if (offset > s->size || (s->size / 2) > offset) {
+    if (offset == 0) {
+       free(s->base);
+       s->size = 0;
+       s->base = NULL;
+       s->ptr = NULL;
+    } else if (offset > s->size || (s->size / 2) > offset) {
        void *base;
        size_t off;
        off = s->ptr - s->base;