]> git.ipfire.org Git - thirdparty/krb5.git/commitdiff
Implement client AS armor
authorSam Hartman <hartmans@mit.edu>
Thu, 26 Mar 2009 05:37:06 +0000 (05:37 +0000)
committerSam Hartman <hartmans@mit.edu>
Thu, 26 Mar 2009 05:37:06 +0000 (05:37 +0000)
* fast_armor_ap_request: generate ap_request armor
* krb5int_fast_as_armor: parse GIC options and request armor
* krb5_get_init_creds: call
* krb5_get_init_creds_opt_set_fast_ccache_name: API to indicate where armor credentials are found
* krb5_free_fast_armored_req: implement

git-svn-id: svn://anonsvn.mit.edu/krb5/branches/fast@22134 dc483132-0cff-0310-8789-dd5450dbe970

src/include/k5-int.h
src/include/krb5/krb5.hin
src/lib/krb5/krb/fast.c
src/lib/krb5/krb/fast.h
src/lib/krb5/krb/get_in_tkt.c
src/lib/krb5/krb/gic_opt.c
src/lib/krb5/krb/kfree.c
src/lib/krb5/libkrb5.exports

index 957f39c8c50a684811006ae11eec1724f345ebb4..b7e793bb94604e96215c85b196eeebace03fb98c 100644 (file)
@@ -963,6 +963,10 @@ typedef struct _krb5_pa_for_user {
     krb5_data          auth_package;
 } krb5_pa_for_user;
 
+enum {
+  KRB5_FAST_ARMOR_AP_REQUEST = 0x1
+};
+
 typedef struct _krb5_fast_armor {
     krb5_int32 armor_type;
     krb5_data armor_value;
@@ -1130,6 +1134,7 @@ void krb5_free_etype_info
 typedef struct _krb5_gic_opt_private {
     int num_preauth_data;
     krb5_gic_opt_pa_data *preauth_data;
+  char * fast_ccache_name;
 } krb5_gic_opt_private;
 
 /*
index c3853879084599b13a93cb3c3f3a5c7fb70034ae..4443d33ac23c994a91405682bf2dd864699653e6 100644 (file)
@@ -2410,6 +2410,15 @@ krb5_get_init_creds_opt_set_pa
                const char *attr,
                const char *value);
 
+krb5_error_code KRB5_CALLCONV krb5_get_init_creds_opt_set_fast_ccache_name
+(krb5_context context, krb5_get_init_creds_opt *opt,
+ const char * fast_ccache_name);
+    /*   This API sets a ccache name that will contain some TGT on
+        calls to get_init_creds functions.   If set, this ccache will
+        be used for FAST (draft-ietf-krb-wg-preauth-framework) to
+        protect the AS-REQ from observation and active attack.  If
+        the fast_ccache_name is set, then FAST may be required by the
+        client library.  In this version FAST is required.*/
 krb5_error_code KRB5_CALLCONV
 krb5_get_init_creds_password
 (krb5_context context,
index 41f3731f23eb96ff1de568d1a90f6c0f08fdefa4..4d5f62e8e9534f4e644afd9658fd4d3e1727ec43 100644 (file)
  * important questions there is the presence of a cookie.
  */
 #include "fast.h"
+#include "int-proto.h"
 
 
+static krb5_error_code fast_armor_ap_request
+(krb5_context context, struct krb5int_fast_request_state *state,
+ krb5_ccache ccache, krb5_data *target_realm)
+{
+    krb5_error_code retval = 0;
+    krb5_creds creds, *out_creds = NULL;
+    krb5_auth_context authcontext = NULL;
+    krb5_data encoded_authenticator;
+    krb5_fast_armor *armor = NULL;
+    krb5_keyblock *subkey = NULL, *armor_key = NULL;
+    encoded_authenticator.data = NULL;
+    memset(&creds, 0, sizeof(creds));
+    retval = krb5_tgtname(context, target_realm, target_realm, &creds.server);
+    if (retval ==0)
+       retval = krb5_cc_get_principal(context, ccache, &creds.client);
+    if (retval == 0)
+       retval = krb5_get_credentials(context, 0, ccache,  &creds, &out_creds);
+    if (retval == 0)
+       retval = krb5_mk_req_extended(context, &authcontext, AP_OPTS_USE_SUBKEY, NULL /*data*/,
+                                     out_creds, &encoded_authenticator);
+    if (retval == 0)
+       retval = krb5_auth_con_getsendsubkey(context, authcontext, &subkey);
+    if (retval == 0)
+       retval = krb5_c_fx_cf2_simple(context, subkey, "subkeyarmor",
+                                     &out_creds->keyblock, "ticketarmor", &armor_key);
+    if (retval == 0) {
+       armor = calloc(1, sizeof(krb5_fast_armor));
+       if (armor == NULL)
+           retval = ENOMEM;
+    }
+    if (retval == 0) {
+       armor->armor_type = KRB5_FAST_ARMOR_AP_REQUEST;
+       armor->armor_value = encoded_authenticator;
+       encoded_authenticator.data = NULL;
+       encoded_authenticator.length = 0;
+       state->armor = armor;
+       armor = NULL;
+       state->armor_key = armor_key;
+       armor_key = NULL;
+    }
+    krb5_free_keyblock(context, armor_key);
+    krb5_free_keyblock(context, subkey);
+    if (out_creds)
+       krb5_free_creds(context, out_creds);
+    krb5_free_cred_contents(context, &creds);
+    if (encoded_authenticator.data)
+       krb5_free_data_contents(context, &encoded_authenticator);
+    krb5_auth_con_free(context, authcontext);
+    return retval;
+}
 
 krb5_error_code
 krb5int_fast_prep_req_body(krb5_context context, struct krb5int_fast_request_state *state,
@@ -77,6 +128,34 @@ krb5int_fast_prep_req_body(krb5_context context, struct krb5int_fast_request_sta
     return retval;
 }
 
+krb5_error_code krb5int_fast_as_armor
+(krb5_context context, struct krb5int_fast_request_state *state,
+ krb5_gic_opt_ext *opte,
+ krb5_kdc_req *request)
+{
+    krb5_error_code retval = 0;
+    krb5_ccache ccache = NULL;
+    krb5_clear_error_message(context);
+    if (opte->opt_private->fast_ccache_name) {
+       retval = krb5_cc_resolve(context, opte->opt_private->fast_ccache_name,
+                                &ccache);
+       if (retval==0)
+               retval = fast_armor_ap_request(context, state, ccache,
+                                              krb5_princ_realm(context, request->server));
+       if (retval != 0) {
+           const char * errmsg;
+           errmsg = krb5_get_error_message(context, retval);
+           if (errmsg) {
+               krb5_set_error_message(context, retval, "%s constructing AP-REQ armor", errmsg);
+               krb5_free_error_message(context, errmsg);
+           }
+       }
+    }
+    if (ccache)
+       krb5_cc_close(context, ccache);
+    return retval;
+}
+
 
 krb5_error_code 
 krb5int_fast_prep_req (krb5_context context, struct krb5int_fast_request_state *state,
@@ -88,28 +167,51 @@ krb5int_fast_prep_req (krb5_context context, struct krb5int_fast_request_state *
     krb5_pa_data *pa_array[3];
     krb5_pa_data pa[2];
     krb5_fast_req fast_req;
+    krb5_fast_armored_req *armored_req = NULL;
     krb5_data *encoded_fast_req = NULL;
+    krb5_data *encoded_armored_req = NULL;
     krb5_data *local_encoded_result = NULL;
+    krb5_cksumtype cksumtype;
 
     assert(state != NULL);
-        assert(state->fast_outer_request.padata == NULL);
+    assert(state->fast_outer_request.padata == NULL);
     memset(pa_array, 0, sizeof pa_array);
     if (state->armor_key == NULL) {
        return encoder(request, encoded_request);
     }
     fast_req.req_body =  request;
     if (fast_req.req_body->padata == NULL) {
-      fast_req.req_body->padata = calloc(1, sizeof(krb5_pa_data *));
-      if (fast_req.req_body->padata == NULL)
-       retval = ENOMEM;
+       fast_req.req_body->padata = calloc(1, sizeof(krb5_pa_data *));
+       if (fast_req.req_body->padata == NULL)
+           retval = ENOMEM;
     }
     fast_req.fast_options = state->fast_options;
     if (retval == 0)
        retval = encode_krb5_fast_req(&fast_req, &encoded_fast_req);
+    if (retval == 0) {
+       armored_req = calloc(1, sizeof(krb5_fast_armored_req));
+       if (armored_req == NULL)
+           retval = ENOMEM;
+    }
+    if (retval == 0)
+       armored_req->armor = state->armor;
+    if (retval == 0)
+       retval = krb5int_c_mandatory_cksumtype(context, state->armor_key->enctype,
+                                              &cksumtype);
+    if (retval ==0)
+       retval = krb5_c_make_checksum(context, cksumtype, state->armor_key,
+                                     KRB5_KEYUSAGE_FAST_REQ_CHKSUM, to_be_checksummed,
+                                     &armored_req->req_checksum);
+    if (retval == 0)
+       retval = krb5_encrypt_helper(context, state->armor_key,
+                                    KRB5_KEYUSAGE_FAST_ENC, encoded_fast_req,
+                                    &armored_req->enc_part);
+    if (retval == 0)
+       retval = encode_krb5_pa_fx_fast_request(armored_req, &encoded_armored_req);
     if (retval==0) {
        pa[0].pa_type = KRB5_PADATA_FX_FAST;
-       pa[0].contents = (unsigned char *) encoded_fast_req->data;
-       pa[0].length = encoded_fast_req->length;
+       pa[0].contents = (unsigned char *) encoded_armored_req->data;
+       pa[0].length = encoded_armored_req->length;
        pa_array[0] = &pa[0];
     }
     if (state->cookie_contents.data) {
@@ -125,6 +227,12 @@ krb5int_fast_prep_req (krb5_context context, struct krb5int_fast_request_state *
        *encoded_request = local_encoded_result;
        local_encoded_result = NULL;
     }
+    if (encoded_armored_req)
+       krb5_free_data(context, encoded_armored_req);
+    if (armored_req) {
+       armored_req->armor = NULL; /*owned by state*/
+       krb5_free_fast_armored_req(context, armored_req);
+    }
     if (encoded_fast_req)
        krb5_free_data(context, encoded_fast_req);
     if (local_encoded_result)
index 3225eabec8ed56e0c88b954647b23f5716165814..acd12b345cdf78d130b031540f3fecdbe7e1eb6b 100644 (file)
@@ -62,6 +62,10 @@ krb5int_fast_make_state( krb5_context context, struct krb5int_fast_request_state
 
 void
 krb5int_fast_free_state( krb5_context , struct krb5int_fast_request_state *state);
+krb5_error_code krb5int_fast_as_armor
+(krb5_context context, struct krb5int_fast_request_state *state,
+ krb5_gic_opt_ext *opte,
+ krb5_kdc_req *request);
 
 
 #endif
index 7bfca3f0200c86892e8cbc54588e3c4af6b8a68c..eb23e544a6fea0629e1e2ff43eed7f5b991027f9 100644 (file)
@@ -1239,6 +1239,9 @@ krb5_get_init_creds(krb5_context context,
            /* XXX  Yuck.  Old version.  */
            request.nonce = (krb5_int32) time_now;
     }
+    ret = krb5int_fast_as_armor(context, fast_state, options, &request);
+    if (ret != 0)
+       goto cleanup;
     /* give the preauth plugins a chance to prep the request body */
     krb5_preauth_prepare_request(context, options, &request);
     ret = krb5int_fast_prep_req_body(context, fast_state,
index 348637ca3cf1a89b44cf464fe0f58097852c8ee3..72203f0e70d9f61389df092dea1cf4463bed61b3 100644 (file)
@@ -146,6 +146,8 @@ krb5int_gic_opte_private_free(krb5_context context, krb5_gic_opt_ext *opte)
     /* Free up any private stuff */
     if (opte->opt_private->preauth_data != NULL)
        free_gic_opt_ext_preauth_data(context, opte);
+    if (opte->opt_private->fast_ccache_name)
+       free(opte->opt_private->fast_ccache_name);
     free(opte->opt_private);
     opte->opt_private = NULL;
     return 0;
@@ -465,3 +467,21 @@ krb5_get_init_creds_opt_free_pa(krb5_context context,
     }
     free(preauth_data);
 }
+krb5_error_code KRB5_CALLCONV krb5_get_init_creds_opt_set_fast_ccache_name
+(krb5_context context, krb5_get_init_creds_opt *opt, const char *ccache_name)
+{
+    krb5_error_code retval = 0;
+    krb5_gic_opt_ext *opte;
+
+    retval = krb5int_gic_opt_to_opte(context, opt, &opte, 0,
+                                    "krb5_get_init_creds_opt_set_fast_ccache_name");
+    if (retval)
+       return retval;
+    if (opte->opt_private->fast_ccache_name) {
+       free(opte->opt_private->fast_ccache_name);
+    }
+    opte->opt_private->fast_ccache_name = strdup(ccache_name);
+    if (opte->opt_private->fast_ccache_name == NULL)
+       retval = ENOMEM;
+    return retval;
+}
index 5813fc0242b7daf691dda5832a896aa2532b2f4a..d3ad3f7fae47687d41823d05e5c9da3cb02fbb57 100644 (file)
@@ -830,6 +830,7 @@ void krb5_free_fast_finished
   krb5_free_principal(context, val->client);
   krb5_free_checksum_contents(context, &val->checksum);
   krb5_free_checksum_contents(context, &val->ticket_checksum);
+  free(val);
 }
 
 void krb5_free_typed_data(krb5_context context, krb5_typed_data **in)
@@ -844,3 +845,16 @@ void krb5_free_typed_data(krb5_context context, krb5_typed_data **in)
   }
   free(in);
 }
+
+void krb5_free_fast_armored_req(krb5_context context,
+                               krb5_fast_armored_req *val)
+{
+    if (val == NULL)
+       return;
+    if (val->armor)
+       krb5_free_fast_armor(context, val->armor);
+    krb5_free_data_contents(context, &val->enc_part.ciphertext);
+    if (val->req_checksum.contents)
+      krb5_free_checksum_contents(context, &val->req_checksum);
+    free(val);
+}
index 17b8fd3c65e78aeef92692ba4fb04256724cf4d9..45192f5620ad0635ed875ecb2455d3309acb06eb 100644 (file)
@@ -305,6 +305,7 @@ krb5_get_init_creds_opt_set_address_list
 krb5_get_init_creds_opt_set_canonicalize
 krb5_get_init_creds_opt_set_change_password_prompt
 krb5_get_init_creds_opt_set_etype_list
+krb5_get_init_creds_opt_set_fast_ccache_name
 krb5_get_init_creds_opt_set_forwardable
 krb5_get_init_creds_opt_set_pa
 krb5_get_init_creds_opt_set_preauth_list