2 * Copyright (c) 1995, 1996, 1997, 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the Institute nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * Copyright 1992, 2002 by the Massachusetts Institute of Technology.
35 * All Rights Reserved.
37 * Export of this software from the United States of America may
38 * require a specific license from the United States Government.
39 * It is the responsibility of any person or organization contemplating
40 * export to obtain such a license before exporting.
42 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
43 * distribute this software and its documentation for any purpose and
44 * without fee is hereby granted, provided that the above copyright
45 * notice appear in all copies and that both that copyright notice and
46 * this permission notice appear in supporting documentation, and that
47 * the name of M.I.T. not be used in advertising or publicity pertaining
48 * to distribution of the software without specific, written prior
49 * permission. Furthermore if you modify this software you must label
50 * your software as modified software and not distribute it in such a
51 * fashion that it might be confused with the original M.I.T. software.
52 * M.I.T. makes no representations about the suitability of
53 * this software for any purpose. It is provided "as is" without express
54 * or implied warranty.
57 #include <afsconfig.h>
58 #include <afs/param.h>
63 #ifdef IGNORE_SOME_GCC_WARNINGS
64 # pragma GCC diagnostic warning "-Wimplicit-function-declaration"
70 #include <hcrypto/md4.h>
71 #include <hcrypto/md5.h>
72 #include <hcrypto/des.h>
74 #include "lifetimes.h"
76 #include "rxkad_convert.h"
78 #include "v5gen-rewrite.h"
84 #define RFC3961_NO_ENUMS
85 #define RFC3961_NO_CKSUM
86 #include <afs/rfc3961.h>
89 * Principal conversion Taken from src/lib/krb5/krb/conv_princ from MIT Kerberos. If you
90 * find a need to change the services here, please consider opening a
91 * bug with MIT by sending mail to krb5-bugs@mit.edu.
101 #define DO_REALM_CONVERSION 0x00000001
104 * Kadmin doesn't do realm conversion because it's currently
105 * kadmin/REALM.NAME. Zephyr doesn't because it's just zephyr/zephyr.
107 * "Realm conversion" is a bit of a misnomer; really, the v5 name is
108 * using a FQDN or something that looks like it, where the v4 name is
109 * just using the first label. Sometimes that second principal name
110 * component is a hostname, sometimes the realm name, sometimes it's
113 * This list should probably be more configurable, and more than
114 * likely on a per-realm basis, so locally-defined services can be
117 static const struct krb_convert sconv_list[] = {
118 /* Realm conversion, Change service name */
119 #define RC(V5NAME,V4NAME) { V5NAME, V4NAME, DO_REALM_CONVERSION, sizeof(V5NAME)-1 }
120 /* Realm conversion */
121 #define R(NAME) { NAME, NAME, DO_REALM_CONVERSION, sizeof(NAME)-1 }
122 /* No Realm conversion */
123 #define NR(NAME) { NAME, NAME, 0, sizeof(NAME)-1 }
174 krb5_des_decrypt(struct ktc_encryptionKey *, int, void *, size_t, void *,
181 tkt_DecodeTicket5(char *ticket, afs_int32 ticket_len,
182 int (*get_key) (void *, int, struct ktc_encryptionKey *),
183 rxkad_get_key_enctype_func get_key_enctype,
184 char *get_key_rock, int serv_kvno, char *name, char *inst,
185 char *cell, struct ktc_encryptionKey *session_key, afs_int32 * host,
186 afs_uint32 * start, afs_uint32 * end, afs_int32 disableCheckdot)
188 char plain[MAXKRB5TICKETLEN];
189 struct ktc_encryptionKey serv_key;
191 size_t keysize, allocsiz;
192 krb5_context context;
196 Ticket t5; /* Must free */
197 EncTicketPart decr_part; /* Must free */
199 size_t siz, plainsiz;
201 char *v5_comp0, *v5_comp1, *c;
202 const struct krb_convert *p;
204 memset(&t5, 0, sizeof(t5));
205 memset(&decr_part, 0, sizeof(decr_part));
210 return RXKADBADTICKET; /* no ticket */
212 if (serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5) {
213 code = decode_Ticket((unsigned char *)ticket, ticket_len, &t5, &siz);
220 code = decode_EncryptedData((unsigned char *)ticket, ticket_len, &t5.enc_part, &siz);
225 /* If kvno is null, it's probably not included because it was kvno==0
227 if (t5.enc_part.kvno == NULL) {
230 v5_serv_kvno = *t5.enc_part.kvno;
233 /* Check that the key type really fit into 8 bytes */
234 switch (t5.enc_part.etype) {
235 case ETYPE_DES_CBC_CRC:
236 case ETYPE_DES_CBC_MD4:
237 case ETYPE_DES_CBC_MD5:
239 if (t5.enc_part.cipher.length > sizeof(plain)
240 || t5.enc_part.cipher.length % 8 != 0)
243 code = (*get_key) (get_key_rock, v5_serv_kvno, &serv_key);
247 /* Decrypt data here, save in plain, assume it will shrink */
249 krb5_des_decrypt(&serv_key, t5.enc_part.etype,
250 t5.enc_part.cipher.data, t5.enc_part.cipher.length,
254 if (get_key_enctype == NULL)
256 code = krb5_init_context(&context);
259 code = krb5_enctype_valid(context, t5.enc_part.etype);
261 krb5_free_context(context);
264 code = krb5_enctype_keybits(context, t5.enc_part.etype, &keysize);
266 krb5_free_context(context);
269 keysize = keysize / 8;
271 keybuf = rxi_Alloc(allocsiz);
272 /* this is not quite a hole for afsconf_GetKeyByTypes. A wrapper
273 that calls afsconf_GetKeyByTypes and afsconf_typedKey_values
275 code = get_key_enctype(get_key_rock, v5_serv_kvno, t5.enc_part.etype,
278 rxi_Free(keybuf, allocsiz);
279 krb5_free_context(context);
282 code = krb5_keyblock_init(context, t5.enc_part.etype,
283 keybuf, keysize, &k);
284 rxi_Free(keybuf, allocsiz);
286 krb5_free_context(context);
289 code = krb5_crypto_init(context, &k, t5.enc_part.etype, &cr);
290 krb5_free_keyblock_contents(context, &k);
292 krb5_free_context(context);
295 #ifndef KRB5_KU_TICKET
296 #define KRB5_KU_TICKET 2
298 code = krb5_decrypt(context, cr, KRB5_KU_TICKET, t5.enc_part.cipher.data,
299 t5.enc_part.cipher.length, &plaindata);
300 krb5_crypto_destroy(context, cr);
302 if (plaindata.length > MAXKRB5TICKETLEN) {
303 krb5_data_free(&plaindata);
304 krb5_free_context(context);
307 memcpy(plain, plaindata.data, plaindata.length);
308 plainsiz = plaindata.length;
309 krb5_data_free(&plaindata);
311 krb5_free_context(context);
318 code = decode_EncTicketPart((unsigned char *)plain, plainsiz, &decr_part, &siz);
322 /* Extract realm and principal */
323 strncpy(cell, decr_part.crealm, MAXKTCNAMELEN);
324 cell[MAXKTCNAMELEN - 1] = '\0';
326 switch (decr_part.cname.name_string.len) {
328 v5_comp0 = decr_part.cname.name_string.val[0];
329 v5_comp1 = decr_part.cname.name_string.val[1];
332 if (strcmp(p->v5_str, v5_comp0) == 0) {
334 * It is, so set the new name now, and chop off
335 * instance's domain name if requested.
337 strncpy(name, p->v4_str, MAXKTCNAMELEN);
338 name[MAXKTCNAMELEN - 1] = '\0';
339 if (p->flags & DO_REALM_CONVERSION) {
340 c = strchr(v5_comp1, '.');
341 if (!c || (c - v5_comp1) >= MAXKTCNAMELEN - 1)
343 strncpy(inst, v5_comp1, c - v5_comp1);
344 inst[c - v5_comp1] = '\0';
352 strncpy(inst, decr_part.cname.name_string.val[1], MAXKTCNAMELEN);
353 inst[MAXKTCNAMELEN - 1] = '\0';
354 strncpy(name, decr_part.cname.name_string.val[0], MAXKTCNAMELEN);
355 name[MAXKTCNAMELEN - 1] = '\0';
359 strncpy(name, decr_part.cname.name_string.val[0], MAXKTCNAMELEN);
360 name[MAXKTCNAMELEN - 1] = '\0';
366 if (!disableCheckdot) {
368 * If the first part of the name_string contains a dot, punt since
369 * then we can't see the diffrence between the kerberos 5
370 * principals foo.root and foo/root later in the fileserver.
372 if (strchr(decr_part.cname.name_string.val[0], '.') != NULL)
376 /* Verify that decr_part.key is of right type */
377 switch (decr_part.key.keytype) {
378 case ETYPE_DES_CBC_CRC:
379 case ETYPE_DES_CBC_MD4:
380 case ETYPE_DES_CBC_MD5:
386 if (decr_part.key.keyvalue.length != 8)
389 /* Extract session key */
390 memcpy(session_key, decr_part.key.keyvalue.data, 8);
392 /* Check lifetimes and host addresses, flags etc */
394 time_t now = time(0); /* Use fast time package instead??? */
395 *start = decr_part.authtime;
396 if (decr_part.starttime)
397 *start = *decr_part.starttime;
399 if (*start - now > CLOCK_SKEW || decr_part.flags.invalid)
402 if (decr_part.flags.invalid)
405 if (now > decr_part.endtime)
407 *end = decr_part.endtime;
411 if (serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5)
414 free_EncryptedData(&t5.enc_part);
415 free_EncTicketPart(&decr_part);
416 memset(&serv_key, 0, sizeof(serv_key));
420 code = RXKADUNKNOWNKEY;
429 code = RXKADBADTICKET;
435 verify_checksum_md4(void *data, size_t len,
436 void *cksum, size_t cksumsz,
437 struct ktc_encryptionKey *key)
440 unsigned char tmp[16];
443 MD4_Update(&md4, data, len);
444 MD4_Final(tmp, &md4);
446 if (memcmp(tmp, cksum, cksumsz) != 0)
452 verify_checksum_md5(void *data, size_t len,
453 void *cksum, size_t cksumsz,
454 struct ktc_encryptionKey *key)
457 unsigned char tmp[16];
460 MD5_Update(&md5, data, len);
461 MD5_Final(tmp, &md5);
463 if (memcmp(tmp, cksum, cksumsz) != 0)
469 verify_checksum_crc(void *data, size_t len, void *cksum, size_t cksumsz,
470 struct ktc_encryptionKey *key)
475 _rxkad_crc_init_table();
476 crc = _rxkad_crc_update(data, len, 0);
478 r[1] = (crc >> 8) & 0xff;
479 r[2] = (crc >> 16) & 0xff;
480 r[3] = (crc >> 24) & 0xff;
482 if (memcmp(cksum, r, 4) != 0)
489 krb5_des_decrypt(struct ktc_encryptionKey *key, int etype, void *in,
490 size_t insz, void *out, size_t * outsz)
492 int (*cksum_func) (void *, size_t, void *, size_t,
493 struct ktc_encryptionKey *);
498 int ret = 1; /* failure */
502 DES_key_sched(ktc_to_cblock(key), &s);
504 #define CONFOUNDERSZ 8
507 case ETYPE_DES_CBC_CRC:
508 memcpy(&ivec, key, sizeof(ivec));
510 cksum_func = verify_checksum_crc;
512 case ETYPE_DES_CBC_MD4:
513 memset(&ivec, 0, sizeof(ivec));
515 cksum_func = verify_checksum_md4;
517 case ETYPE_DES_CBC_MD5:
518 memset(&ivec, 0, sizeof(ivec));
520 cksum_func = verify_checksum_md5;
526 DES_cbc_encrypt(in, out, insz, &s, &ivec, 0);
528 memcpy(cksum, (char *)out + CONFOUNDERSZ, cksumsz);
529 memset((char *)out + CONFOUNDERSZ, 0, cksumsz);
532 ret = (*cksum_func) (out, insz, cksum, cksumsz, key);
534 *outsz = insz - CONFOUNDERSZ - cksumsz;
535 memmove(out, (char *)out + CONFOUNDERSZ + cksumsz, *outsz);