1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */ 2 /* kdc/kdc_preauth_encts.c - Encrypted timestamp kdcpreauth module */ 3 /* 4 * Copyright (C) 1995, 2003, 2007, 2011 by the Massachusetts Institute of Technology. 5 * All rights reserved. 6 * 7 * Export of this software from the United States of America may 8 * require a specific license from the United States Government. 9 * It is the responsibility of any person or organization contemplating 10 * export to obtain such a license before exporting. 11 * 12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 13 * distribute this software and its documentation for any purpose and 14 * without fee is hereby granted, provided that the above copyright 15 * notice appear in all copies and that both that copyright notice and 16 * this permission notice appear in supporting documentation, and that 17 * the name of M.I.T. not be used in advertising or publicity pertaining 18 * to distribution of the software without specific, written prior 19 * permission. Furthermore if you modify this software you must label 20 * your software as modified software and not distribute it in such a 21 * fashion that it might be confused with the original M.I.T. software. 22 * M.I.T. makes no representations about the suitability of 23 * this software for any purpose. It is provided "as is" without express 24 * or implied warranty. 25 */ 26 27 #include <k5-int.h> 28 #include <krb5/kdcpreauth_plugin.h> 29 #include "kdc_util.h" 30 31 static void 32 enc_ts_get(krb5_context context, krb5_kdc_req *request, 33 krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, 34 krb5_kdcpreauth_moddata moddata, krb5_preauthtype pa_type, 35 krb5_kdcpreauth_edata_respond_fn respond, void *arg) 36 { 37 krb5_keyblock *armor_key = cb->fast_armor(context, rock); 38 39 /* Encrypted timestamp must not be used with FAST, and requires a key. */ 40 if (armor_key != NULL || !cb->have_client_keys(context, rock)) 41 (*respond)(arg, ENOENT, NULL); 42 else 43 (*respond)(arg, 0, NULL); 44 } 45 46 static void 47 enc_ts_verify(krb5_context context, krb5_data *req_pkt, krb5_kdc_req *request, 48 krb5_enc_tkt_part *enc_tkt_reply, krb5_pa_data *pa, 49 krb5_kdcpreauth_callbacks cb, krb5_kdcpreauth_rock rock, 50 krb5_kdcpreauth_moddata moddata, 51 krb5_kdcpreauth_verify_respond_fn respond, void *arg) 52 { 53 krb5_pa_enc_ts * pa_enc = 0; 54 krb5_error_code retval; 55 krb5_data scratch; 56 krb5_data enc_ts_data; 57 krb5_enc_data *enc_data = 0; 58 krb5_keyblock key; 59 krb5_key_data * client_key; 60 krb5_int32 start; 61 62 scratch.data = (char *)pa->contents; 63 scratch.length = pa->length; 64 65 enc_ts_data.data = 0; 66 67 if ((retval = decode_krb5_enc_data(&scratch, &enc_data)) != 0) 68 goto cleanup; 69 70 enc_ts_data.length = enc_data->ciphertext.length; 71 if ((enc_ts_data.data = (char *) malloc(enc_ts_data.length)) == NULL) 72 goto cleanup; 73 74 start = 0; 75 while (1) { 76 if ((retval = krb5_dbe_search_enctype(context, rock->client, 77 &start, enc_data->enctype, 78 -1, 0, &client_key))) 79 goto cleanup; 80 81 if ((retval = krb5_dbe_decrypt_key_data(context, NULL, client_key, 82 &key, NULL))) 83 goto cleanup; 84 85 key.enctype = enc_data->enctype; 86 87 retval = krb5_c_decrypt(context, &key, KRB5_KEYUSAGE_AS_REQ_PA_ENC_TS, 88 0, enc_data, &enc_ts_data); 89 krb5_free_keyblock_contents(context, &key); 90 if (retval == 0) 91 break; 92 } 93 94 if ((retval = decode_krb5_pa_enc_ts(&enc_ts_data, &pa_enc)) != 0) 95 goto cleanup; 96 97 retval = krb5_check_clockskew(context, pa_enc->patimestamp); 98 if (retval) 99 goto cleanup; 100 101 setflag(enc_tkt_reply->flags, TKT_FLG_PRE_AUTH); 102 103 retval = 0; 104 105 cleanup: 106 if (enc_data) { 107 krb5_free_data_contents(context, &enc_data->ciphertext); 108 free(enc_data); 109 } 110 krb5_free_data_contents(context, &enc_ts_data); 111 if (pa_enc) 112 free(pa_enc); 113 /* If we get NO_MATCHING_KEY, it probably means that the password was 114 * incorrect. */ 115 if (retval == KRB5_KDB_NO_MATCHING_KEY) 116 retval = KRB5KDC_ERR_PREAUTH_FAILED; 117 118 (*respond)(arg, retval, NULL, NULL, NULL); 119 } 120 121 static krb5_preauthtype enc_ts_types[] = { 122 KRB5_PADATA_ENC_TIMESTAMP, 0 }; 123 124 krb5_error_code 125 kdcpreauth_encrypted_timestamp_initvt(krb5_context context, int maj_ver, 126 int min_ver, krb5_plugin_vtable vtable) 127 { 128 krb5_kdcpreauth_vtable vt; 129 130 if (maj_ver != 1) 131 return KRB5_PLUGIN_VER_NOTSUPP; 132 vt = (krb5_kdcpreauth_vtable)vtable; 133 vt->name = "encrypted_timestamp"; 134 vt->pa_type_list = enc_ts_types; 135 vt->edata = enc_ts_get; 136 vt->verify = enc_ts_verify; 137 return 0; 138 } 139