Fix -exit patch rebasing mistake
[pkg-k5-afs_openafs.git] / src / rxkad / ticket5.c
blob5c153d0510adb2cf47c21e93ad24e8332f309183
1 /*
2 * Copyright (c) 1995, 1996, 1997, 2002 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
31 * SUCH DAMAGE.
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>
60 #ifdef IGNORE_SOME_GCC_WARNINGS
61 # pragma GCC diagnostic warning "-Wimplicit-function-declaration"
62 #endif
64 #include <afs/stds.h>
65 #include <sys/types.h>
66 #ifdef AFS_NT40_ENV
67 #include <winsock2.h>
68 #else
69 #include <netinet/in.h>
70 #endif
71 #include <string.h>
72 #include <rx/xdr.h>
73 #include <rx/rx.h>
74 #include <des.h>
75 #include <des_prototypes.h>
76 #include "lifetimes.h"
77 #include "rxkad.h"
79 #include "v5gen-rewrite.h"
80 #include "v5gen.h"
81 #include "der.h"
82 #include "v5der.c"
83 #include "v5gen.c"
84 #include "md4.h"
85 #include "md5.h"
88 * Principal conversion Taken from src/lib/krb5/krb/conv_princ from MIT Kerberos. If you
89 * find a need to change the services here, please consider opening a
90 * bug with MIT by sending mail to krb5-bugs@mit.edu.
93 extern afs_int32 des_cbc_encrypt(void * in, void * out,
94 afs_int32 length,
95 des_key_schedule key, des_cblock *iv,
96 int encrypt);
97 extern int des_key_sched(des_cblock k, des_key_schedule schedule);
99 struct krb_convert {
100 char *v4_str;
101 char *v5_str;
102 unsigned int flags;
103 unsigned int len;
106 #define DO_REALM_CONVERSION 0x00000001
109 * Kadmin doesn't do realm conversion because it's currently
110 * kadmin/REALM.NAME. Zephyr doesn't because it's just zephyr/zephyr.
112 * "Realm conversion" is a bit of a misnomer; really, the v5 name is
113 * using a FQDN or something that looks like it, where the v4 name is
114 * just using the first label. Sometimes that second principal name
115 * component is a hostname, sometimes the realm name, sometimes it's
116 * neither.
118 * This list should probably be more configurable, and more than
119 * likely on a per-realm basis, so locally-defined services can be
120 * added, or not.
122 static const struct krb_convert sconv_list[] = {
123 /* Realm conversion, Change service name */
124 #define RC(V5NAME,V4NAME) { V5NAME, V4NAME, DO_REALM_CONVERSION, sizeof(V5NAME)-1 }
125 /* Realm conversion */
126 #define R(NAME) { NAME, NAME, DO_REALM_CONVERSION, sizeof(NAME)-1 }
127 /* No Realm conversion */
128 #define NR(NAME) { NAME, NAME, 0, sizeof(NAME)-1 }
130 NR("kadmin"),
131 RC("rcmd", "host"),
132 R("discuss"),
133 R("rvdsrv"),
134 R("sample"),
135 R("olc"),
136 R("pop"),
137 R("sis"),
138 R("rfs"),
139 R("imap"),
140 R("ftp"),
141 R("ecat"),
142 R("daemon"),
143 R("gnats"),
144 R("moira"),
145 R("prms"),
146 R("mandarin"),
147 R("register"),
148 R("changepw"),
149 R("sms"),
150 R("afpserver"),
151 R("gdss"),
152 R("news"),
153 R("abs"),
154 R("nfs"),
155 R("tftp"),
156 NR("zephyr"),
157 R("http"),
158 R("khttp"),
159 R("pgpsigner"),
160 R("irc"),
161 R("mandarin-agent"),
162 R("write"),
163 R("palladium"),
164 R("imap"),
165 R("smtp"),
166 R("lmtp"),
167 R("ldap"),
168 R("acap"),
169 R("argus"),
170 R("mupdate"),
171 R("argus"),
172 {0, 0, 0, 0},
173 #undef R
174 #undef RC
175 #undef NR
178 static int
179 krb5_des_decrypt(struct ktc_encryptionKey *, int, void *, size_t, void *,
180 size_t *);
181 static int rxkad_derive_des_key(const void *, size_t,
182 struct ktc_encryptionKey *);
183 static int compress_parity_bits(void *, size_t *);
184 static void hmac_md5_iov(const void *, size_t, const struct iovec *,
185 unsigned int, void *);
189 tkt_DecodeTicket5(char *ticket, afs_int32 ticket_len,
190 int (*get_key) (void *, int, struct ktc_encryptionKey *),
191 char *get_key_rock, int serv_kvno, char *name, char *inst,
192 char *cell, struct ktc_encryptionKey *session_key, afs_int32 * host,
193 afs_uint32 * start, afs_uint32 * end, afs_int32 disableCheckdot,
194 rxkad_alt_decrypt_func alt_decrypt)
196 char plain[MAXKRB5TICKETLEN];
197 struct ktc_encryptionKey serv_key;
198 Ticket t5; /* Must free */
199 EncTicketPart decr_part; /* Must free */
200 int code;
201 size_t siz, plainsiz;
202 int v5_serv_kvno;
203 char *v5_comp0, *v5_comp1, *c;
204 const struct krb_convert *p;
206 memset(&t5, 0, sizeof(t5));
207 memset(&decr_part, 0, sizeof(decr_part));
209 *host = 0;
211 if (ticket_len == 0)
212 return RXKADBADTICKET; /* no ticket */
214 if (serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5) {
215 code = decode_Ticket((unsigned char *)ticket, ticket_len, &t5, &siz);
216 if (code != 0)
217 goto cleanup;
219 if (t5.tkt_vno != 5)
220 goto bad_ticket;
221 } else {
222 code = decode_EncryptedData((unsigned char *)ticket, ticket_len, &t5.enc_part, &siz);
223 if (code != 0)
224 goto cleanup;
227 /* If kvno is null, it's probably not included because it was kvno==0
228 * in the ticket */
229 if (t5.enc_part.kvno == NULL) {
230 v5_serv_kvno = 0;
231 } else {
232 v5_serv_kvno = *t5.enc_part.kvno;
235 /* check ticket */
236 if (t5.enc_part.cipher.length > sizeof(plain))
237 goto bad_ticket;
238 switch (t5.enc_part.etype) {
239 case ETYPE_DES_CBC_CRC:
240 case ETYPE_DES_CBC_MD4:
241 case ETYPE_DES_CBC_MD5:
242 /* Check that the key type really fit into 8 bytes */
243 if (t5.enc_part.cipher.length % 8 != 0)
244 goto bad_ticket;
246 code = (*get_key) (get_key_rock, v5_serv_kvno, &serv_key);
247 if (code)
248 goto unknown_key;
250 /* Decrypt data here, save in plain, assume it will shrink */
251 code =
252 krb5_des_decrypt(&serv_key, t5.enc_part.etype,
253 t5.enc_part.cipher.data,
254 t5.enc_part.cipher.length, plain, &plainsiz);
255 if (code != 0)
256 goto bad_ticket;
257 break;
258 default:
259 if (alt_decrypt != NULL) {
260 plainsiz = sizeof(plain);
261 code = alt_decrypt(v5_serv_kvno, t5.enc_part.etype,
262 t5.enc_part.cipher.data,
263 t5.enc_part.cipher.length, plain, &plainsiz);
264 if (code != 0)
265 goto cleanup;
266 } else
267 goto unknown_key;
270 /* Decode ticket */
271 code = decode_EncTicketPart((unsigned char *)plain, plainsiz, &decr_part, &siz);
272 if (code != 0)
273 goto bad_ticket;
275 /* Extract realm and principal */
276 strncpy(cell, decr_part.crealm, MAXKTCNAMELEN);
277 cell[MAXKTCNAMELEN - 1] = '\0';
278 inst[0] = '\0';
279 switch (decr_part.cname.name_string.len) {
280 case 2:
281 v5_comp0 = decr_part.cname.name_string.val[0];
282 v5_comp1 = decr_part.cname.name_string.val[1];
283 p = sconv_list;
284 while (p->v4_str) {
285 if (strcmp(p->v5_str, v5_comp0) == 0) {
287 * It is, so set the new name now, and chop off
288 * instance's domain name if requested.
290 strncpy(name, p->v4_str, MAXKTCNAMELEN);
291 name[MAXKTCNAMELEN - 1] = '\0';
292 if (p->flags & DO_REALM_CONVERSION) {
293 c = strchr(v5_comp1, '.');
294 if (!c || (c - v5_comp1) >= MAXKTCNAMELEN - 1)
295 goto bad_ticket;
296 strncpy(inst, v5_comp1, c - v5_comp1);
297 inst[c - v5_comp1] = '\0';
299 break;
301 p++;
304 if (!p->v4_str) {
305 strncpy(inst, decr_part.cname.name_string.val[1], MAXKTCNAMELEN);
306 inst[MAXKTCNAMELEN - 1] = '\0';
307 strncpy(name, decr_part.cname.name_string.val[0], MAXKTCNAMELEN);
308 name[MAXKTCNAMELEN - 1] = '\0';
310 break;
311 case 1:
312 strncpy(name, decr_part.cname.name_string.val[0], MAXKTCNAMELEN);
313 name[MAXKTCNAMELEN - 1] = '\0';
314 break;
315 default:
316 goto bad_ticket;
319 if (!disableCheckdot) {
321 * If the first part of the name_string contains a dot, punt since
322 * then we can't see the diffrence between the kerberos 5
323 * principals foo.root and foo/root later in the fileserver.
325 if (strchr(decr_part.cname.name_string.val[0], '.') != NULL)
326 goto bad_ticket;
329 /* Verify that decr_part.key is of right type */
330 if (tkt_DeriveDesKey(decr_part.key.keytype, decr_part.key.keyvalue.data,
331 decr_part.key.keyvalue.length, session_key) != 0)
332 goto bad_ticket;
333 /* Check lifetimes and host addresses, flags etc */
335 time_t now = time(0); /* Use fast time package instead??? */
336 *start = decr_part.authtime;
337 if (decr_part.starttime)
338 *start = *decr_part.starttime;
339 #if 0
340 if (*start - now > CLOCK_SKEW || decr_part.flags.invalid)
341 goto no_auth;
342 #else
343 if (decr_part.flags.invalid)
344 goto no_auth;
345 #endif
346 if (now > decr_part.endtime)
347 goto tkt_expired;
348 *end = decr_part.endtime;
351 cleanup:
352 if (serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5)
353 free_Ticket(&t5);
354 else
355 free_EncryptedData(&t5.enc_part);
356 free_EncTicketPart(&decr_part);
357 memset(&serv_key, 0, sizeof(serv_key));
358 return code;
360 unknown_key:
361 code = RXKADUNKNOWNKEY;
362 goto cleanup;
363 no_auth:
364 code = RXKADNOAUTH;
365 goto cleanup;
366 tkt_expired:
367 code = RXKADEXPIRED;
368 goto cleanup;
369 bad_ticket:
370 code = RXKADBADTICKET;
371 goto cleanup;
375 static int
376 verify_checksum_md4(void *data, size_t len,
377 void *cksum, size_t cksumsz,
378 struct ktc_encryptionKey *key)
380 MD4_CTX md4;
381 unsigned char tmp[16];
383 MD4_Init(&md4);
384 MD4_Update(&md4, data, len);
385 MD4_Final(tmp, &md4);
387 if (memcmp(tmp, cksum, cksumsz) != 0)
388 return 1;
389 return 0;
392 static int
393 verify_checksum_md5(void *data, size_t len,
394 void *cksum, size_t cksumsz,
395 struct ktc_encryptionKey *key)
397 MD5_CTX md5;
398 unsigned char tmp[16];
400 MD5_Init(&md5);
401 MD5_Update(&md5, data, len);
402 MD5_Final(tmp, &md5);
404 if (memcmp(tmp, cksum, cksumsz) != 0)
405 return 1;
406 return 0;
409 static int
410 verify_checksum_crc(void *data, size_t len, void *cksum, size_t cksumsz,
411 struct ktc_encryptionKey *key)
413 afs_uint32 crc;
414 char r[4];
416 _rxkad_crc_init_table();
417 crc = _rxkad_crc_update(data, len, 0);
418 r[0] = crc & 0xff;
419 r[1] = (crc >> 8) & 0xff;
420 r[2] = (crc >> 16) & 0xff;
421 r[3] = (crc >> 24) & 0xff;
423 if (memcmp(cksum, r, 4) != 0)
424 return 1;
425 return 0;
429 static int
430 krb5_des_decrypt(struct ktc_encryptionKey *key, int etype, void *in,
431 size_t insz, void *out, size_t * outsz)
433 int (*cksum_func) (void *, size_t, void *, size_t,
434 struct ktc_encryptionKey *);
435 des_cblock ivec;
436 des_key_schedule s;
437 char cksum[24];
438 size_t cksumsz;
439 int ret = 1; /* failure */
441 cksum_func = NULL;
443 des_key_sched(ktc_to_cblock(key), (struct des_ks_struct *)&s);
445 #define CONFOUNDERSZ 8
447 switch (etype) {
448 case ETYPE_DES_CBC_CRC:
449 memcpy(&ivec, key, sizeof(ivec));
450 cksumsz = 4;
451 cksum_func = verify_checksum_crc;
452 break;
453 case ETYPE_DES_CBC_MD4:
454 memset(&ivec, 0, sizeof(ivec));
455 cksumsz = 16;
456 cksum_func = verify_checksum_md4;
457 break;
458 case ETYPE_DES_CBC_MD5:
459 memset(&ivec, 0, sizeof(ivec));
460 cksumsz = 16;
461 cksum_func = verify_checksum_md5;
462 break;
463 default:
464 abort();
467 des_cbc_encrypt(in, out, insz, s, &ivec, 0);
469 memcpy(cksum, (char *)out + CONFOUNDERSZ, cksumsz);
470 memset((char *)out + CONFOUNDERSZ, 0, cksumsz);
472 if (cksum_func)
473 ret = (*cksum_func) (out, insz, cksum, cksumsz, key);
475 *outsz = insz - CONFOUNDERSZ - cksumsz;
476 memmove(out, (char *)out + CONFOUNDERSZ + cksumsz, *outsz);
478 return ret;
482 * Use NIST SP800-108 with HMAC(MD5) in counter mode as the PRF to derive a
483 * des key from another type of key.
485 * L is 64, as we take 64 random bits and turn them into a 56-bit des key.
486 * The output of hmac_md5 is 128 bits; we take the first 64 only, so n
487 * properly should be 1. However, we apply a slight variation due to the
488 * possibility of producing a weak des key. If the output key is weak, do NOT
489 * simply correct it, instead, the counter is advanced and the next output
490 * used. As such, we code so as to have n be the full 255 permitted by our
491 * encoding of the counter i in an 8-bit field. L itself is encoded as a
492 * 32-bit field, big-endian. We use the constant string "rxkad" as a label
493 * for this key derivation, the standard NUL byte separator, and omit a
494 * key-derivation context. The input key is unique to the krb5 service ticket,
495 * which is unlikely to be used in an other location. If it is used in such
496 * a fashion, both locations will derive the same des key from the PRF, but
497 * this is no different from if a krb5 des key had been used in the same way,
498 * as traditional krb5 rxkad uses the ticket session key directly as the token
499 * key.
501 static int
502 rxkad_derive_des_key(const void *in, size_t insize,
503 struct ktc_encryptionKey *out)
505 unsigned char i;
506 char Lbuf[4]; /* bits of output, as 32 bit word, MSB first */
507 char tmp[16];
508 struct iovec iov[3];
509 des_cblock ktmp;
511 Lbuf[0] = 0;
512 Lbuf[1] = 0;
513 Lbuf[2] = 0;
514 Lbuf[3] = 64;
516 iov[0].iov_base = &i;
517 iov[0].iov_len = 1;
518 iov[1].iov_base = "rxkad";
519 iov[1].iov_len = strlen("rxkad") + 1; /* includes label and separator */
520 iov[2].iov_base = Lbuf;
521 iov[2].iov_len = 4;
523 /* stop when 8 bit counter wraps to 0 */
524 for (i = 1; i ; i++) {
525 hmac_md5_iov(in, insize, iov, 3, tmp);
526 memcpy(ktmp, tmp, 8);
527 des_fixup_key_parity(ktmp);
528 if (!des_is_weak_key(ktmp)) {
529 memcpy(out->data, ktmp, 8);
530 return 0;
533 return -1;
537 * This is the inverse of the random-to-key for 3des specified in
538 * rfc3961, converting blocks of 8 bytes to blocks of 7 bytes by distributing
539 * the bits of each 8th byte as the lsb of the previous 7 bytes.
541 static int
542 compress_parity_bits(void *buffer, size_t *bufsiz)
544 unsigned char *cb, tmp;
545 int i, j, nk;
547 if (*bufsiz % 8 != 0)
548 return 1;
549 cb = (unsigned char *)buffer;
550 nk = *bufsiz / 8;
551 for (i = 0; i < nk; i++) {
552 tmp = cb[8 * i + 7] >> 1;
553 for (j = 0; j < 7; j++) {
554 cb[8 * i + j] &= 0xfe;
555 cb[8 * i + j] |= tmp & 0x1;
556 tmp >>= 1;
559 for (i = 1; i < nk; i++)
560 memmove(cb + 7 * i, cb + 8 * i, 7);
561 *bufsiz = 7 * nk;
562 return 0;
565 /* HMAC: Keyed-Hashing for Message Authentication, using MD5 as the hash.
566 * See RFC 2104.
568 * The constants 64 and 16 are the input block size and output length,
569 * respectively, of md5.
571 static void
572 hmac_md5_iov(const void *key, size_t ks,
573 const struct iovec *data, unsigned int niov, void *output)
575 MD5_CTX md5;
576 const unsigned char *kp;
577 unsigned int i;
578 unsigned char tmp[16], tmpk[16], i_pad[64], o_pad[64];
579 if (ks > 64) {
580 MD5_Init(&md5);
581 MD5_Update(&md5, key, ks);
582 MD5_Final(tmpk, &md5);
583 key = tmpk;
584 ks = 16;
586 kp = key;
587 for (i = 0; i < ks; i++)
588 i_pad[i] = kp[i] ^ 0x36;
589 memset(i_pad + ks, 0x36, 64 - ks);
590 MD5_Init(&md5);
591 MD5_Update(&md5, i_pad, 64);
592 for (i = 0; i < niov; i++)
593 MD5_Update(&md5, data[i].iov_base, data[i].iov_len);
594 MD5_Final(tmp, &md5);
595 for (i = 0; i < ks; i++)
596 o_pad[i] = kp[i] ^ 0x5c;
597 memset(o_pad + ks, 0x5c, 64 - ks);
598 MD5_Init(&md5);
599 MD5_Update(&md5, o_pad, 64);
600 MD5_Update(&md5, tmp, 16);
601 MD5_Final(output, &md5);
605 * Enctype-specific knowledge about how to derive a des key from a given
606 * key. If given a des key, use it directly; otherwise, perform any
607 * parity fixup that may be needed and pass through to the hmad-md5 bits.
610 tkt_DeriveDesKey(int enctype, void *keydata, size_t keylen,
611 struct ktc_encryptionKey *output)
613 switch (enctype) {
614 case ETYPE_DES_CBC_CRC:
615 case ETYPE_DES_CBC_MD4:
616 case ETYPE_DES_CBC_MD5:
617 if (keylen != 8)
618 return 1;
620 /* Extract session key */
621 memcpy(output, keydata, 8);
622 break;
623 case ETYPE_NULL:
624 case 4:
625 case 6:
626 case 8:
627 case 9:
628 case 10:
629 case 11:
630 case 12:
631 case 13:
632 case 14:
633 case 15:
634 return 1;
635 /*In order to become a "Cryptographic Key" as specified in
636 * SP800-108, it must be indistinguishable from a random bitstring. */
637 case ETYPE_DES3_CBC_MD5:
638 case ETYPE_OLD_DES3_CBC_SHA1:
639 case ETYPE_DES3_CBC_SHA1:
640 if (compress_parity_bits(keydata, &keylen))
641 return 1;
642 /* FALLTHROUGH */
643 default:
644 if (enctype < 0)
645 return 1;
646 if (keylen < 7)
647 return 1;
648 if (rxkad_derive_des_key(keydata, keylen, output) != 0)
649 return 1;
651 return 0;