1 /* This file is part of the Project Athena Zephyr Notification System.
2 * It contains functions for dealing with Kerberos functions in the server.
4 * Created by: John T Kohl
6 * Copyright (c) 1988 by the Massachusetts Institute of Technology.
7 * For copying and distribution information, see the file
11 * $Source: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/kstuff.c,v $
12 * $Header: /afs/dev.mit.edu/source/repository/athena/lib/zephyr/server/kstuff.c,v 1.26 2001/04/10 23:28:20 ghudson Exp $
19 static const char rcsid_kstuff_c[] = "$Id: kstuff.c,v 1.26 2001/04/10 23:28:20 ghudson Exp $";
25 /* Keep a hash table mapping tickets to session keys, so we can do a fast
26 * check of the cryptographic checksum without doing and DES decryptions.
27 * Also remember the expiry time of the ticket, so that we can sweep the
28 * table periodically. */
30 #define HASHTAB_SIZE 4091
32 typedef struct hash_entry Hash_entry;
34 /* The ticket comes at the end, in a variable-length array. */
38 char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4];
41 unsigned char ticket[1];
44 Hash_entry *hashtab[HASHTAB_SIZE];
46 static ZChecksum_t compute_checksum __P((ZNotice_t *, C_Block));
47 static ZChecksum_t compute_rlm_checksum __P((ZNotice_t *, C_Block));
52 * get ticket from file descriptor and decode it.
53 * Return KFAILURE if we barf on reading the ticket, else return
54 * the value of rd_ap_req() applied to the ticket.
57 GetKerberosData(fd, haddr, kdata, service, srvtab)
58 int fd; /* file descr. to read from */
59 struct in_addr haddr; /* address of foreign host on fd */
60 AUTH_DAT *kdata; /* kerberos data (returned) */
61 char *service; /* service principal desired */
62 char *srvtab; /* file to get keys from */
65 KTEXT_ST ticket; /* will get Kerberos ticket from client */
67 char instance[INST_SZ];
70 * Get the Kerberos ticket. The first few characters, terminated
71 * by a blank, should give us a length; then get than many chars
72 * which will be the ticket proper.
74 for (i=0; i<20; i++) {
75 if (read(fd, &p[i], 1) != 1) {
76 syslog(LOG_WARNING,"bad read tkt len");
84 ticket.length = atoi(p);
85 if ((i==20) || (ticket.length<=0) || (ticket.length>MAX_KTXT_LEN)) {
86 syslog(LOG_WARNING,"bad tkt len %d",ticket.length);
89 for (i=0; i<ticket.length; i++) {
90 if (read(fd, (caddr_t) &(ticket.dat[i]), 1) != 1) {
91 syslog(LOG_WARNING,"bad tkt read");
96 * now have the ticket. use it to get the authenticated
99 (void) strcpy(instance,"*"); /* let Kerberos fill it in */
101 return(krb_rd_req(&ticket, service, instance, haddr.s_addr,
102 kdata, srvtab ? srvtab : ""));
108 * create and transmit a ticket over the file descriptor for service.host
109 * return failure codes if appropriate, or 0 if we
110 * get the ticket and write it to the file descriptor
114 SendKerberosData(fd, ticket, service, host)
115 int fd; /* file descriptor to write onto */
116 KTEXT ticket; /* where to put ticket (return) */
117 char *service; /* service name, foreign host */
125 rem = krb_mk_req(ticket, service, host, ZGetRealm(), (u_long) 0);
127 return rem + krb_err_base;
129 (void) sprintf(p,"%d ",ticket->length);
130 size_to_write = strlen (p);
131 if ((written = write(fd, p, size_to_write)) != size_to_write)
132 return (written < 0) ? errno : ZSRV_PKSHORT;
133 if ((written = write(fd, (caddr_t) (ticket->dat), ticket->length))
135 return (written < 0) ? errno : ZSRV_PKSHORT;
140 #endif /* HAVE_KRB4 */
143 ZCheckRealmAuthentication(notice, from, realm)
145 struct sockaddr_in *from;
150 char rlmprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4+1024];
151 krb5_principal princ;
155 krb5_error_code result;
156 krb5_principal server;
157 krb5_keytab keytabid = 0;
158 krb5_auth_context authctx;
159 krb5_keyblock *keyblock;
160 krb5_enctype enctype;
161 krb5_cksumtype cksumtype;
163 #if HAVE_KRB5_C_MAKE_CHECKSUM
164 krb5_checksum checksum;
167 krb5_crypto cryptctx;
171 char *cksum0_base, *cksum1_base, *cksum2_base;
172 char *svcinst, *x, *y;
173 char *asn1_data, *key_data;
174 int asn1_len, key_len, cksum0_len, cksum1_len, cksum2_len;
175 #ifdef KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER
176 krb5_authenticator *authenticator;
177 #define KRB5AUTHENT authenticator
179 krb5_authenticator authenticator;
180 #define KRB5AUTHENT &authenticator
187 /* Check for bogus authentication data length. */
188 if (notice->z_authent_len <= 0)
191 len = strlen(notice->z_ascii_authent)+1;
194 /* Read in the authentication data. */
195 if (ZReadZcode(notice->z_ascii_authent,
197 len, &len) == ZERR_BADFIELD) {
201 (void) sprintf(rlmprincipal, "%s/%s@%s", SERVER_SERVICE,
202 SERVER_INSTANCE, realm);
205 packet.data = authbuf;
207 result = krb5_kt_resolve(Z_krb5_ctx,
208 keytab_file, &keytabid);
214 /* HOLDING: authbuf, keytabid */
215 /* Create the auth context */
216 result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
218 krb5_kt_close(Z_krb5_ctx, keytabid);
223 /* HOLDING: authbuf, authctx */
224 result = krb5_build_principal(Z_krb5_ctx, &server, strlen(__Zephyr_realm),
225 __Zephyr_realm, SERVER_SERVICE,
226 SERVER_INSTANCE, NULL);
228 result = krb5_rd_req(Z_krb5_ctx, &authctx, &packet, server,
230 krb5_free_principal(Z_krb5_ctx, server);
232 krb5_kt_close(Z_krb5_ctx, keytabid);
235 if (result == KRB5KRB_AP_ERR_REPEAT)
236 syslog(LOG_DEBUG, "k5 auth failed: %s", error_message(result));
238 syslog(LOG_WARNING,"k5 auth failed: %s", error_message(result));
240 krb5_auth_con_free(Z_krb5_ctx, authctx);
244 /* HOLDING: authbuf, authctx */
245 #ifndef HAVE_KRB5_TICKET_ENC_PART2
246 if (tkt == 0 || tkt->client == 0) {
247 if (tkt) krb5_free_ticket(Z_krb5_ctx, tkt);
249 krb5_auth_con_free(Z_krb5_ctx, authctx);
254 if (tkt == 0 || tkt->enc_part2 == 0) {
255 if (tkt) krb5_free_ticket(Z_krb5_ctx, tkt);
257 krb5_auth_con_free(Z_krb5_ctx, authctx);
260 princ = tkt->enc_part2->client;
263 krb5_free_ticket(Z_krb5_ctx, tkt);
265 krb5_auth_con_free(Z_krb5_ctx, authctx);
269 /* HOLDING: authbuf, authctx, tkt */
270 result = krb5_unparse_name(Z_krb5_ctx, princ, &name);
272 syslog(LOG_WARNING, "k5 unparse_name failed: %s",
273 error_message(result));
275 krb5_auth_con_free(Z_krb5_ctx, authctx);
276 krb5_free_ticket(Z_krb5_ctx, tkt);
280 krb5_free_ticket(Z_krb5_ctx, tkt);
282 /* HOLDING: authbuf, authctx, name */
283 if (strcmp(name, rlmprincipal)) {
284 syslog(LOG_WARNING, "k5 name mismatch: '%s' vs '%s'",
286 krb5_auth_con_free(Z_krb5_ctx, authctx);
294 /* HOLDING: authctx */
295 /* Get an authenticator so we can get the keyblock */
296 result = krb5_auth_con_getauthenticator (Z_krb5_ctx, authctx,
299 krb5_auth_con_free(Z_krb5_ctx, authctx);
303 /* HOLDING: authctx, authenticator */
304 result = krb5_auth_con_getkey(Z_krb5_ctx, authctx, &keyblock);
306 krb5_auth_con_free(Z_krb5_ctx, authctx);
307 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
308 return (ZAUTH_FAILED);
311 /* HOLDING: authctx, authenticator, keyblock */
312 /* Figure out what checksum type to use */
313 #if HAVE_KRB5_CREDS_KEYBLOCK_ENCTYPE
314 key_data = keyblock->contents;
315 key_len = keyblock->length;
316 enctype = keyblock->enctype;
317 result = Z_krb5_lookup_cksumtype(enctype, &cksumtype);
319 krb5_free_keyblock(Z_krb5_ctx, keyblock);
320 krb5_auth_con_free(Z_krb5_ctx, authctx);
321 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
322 return (ZAUTH_FAILED);
325 key_data = keyblock->keyvalue.data;
326 key_len = keyblock->keyvalue.length;
332 result = krb5_keytype_to_enctypes(Z_krb5_ctx, keyblock->keytype,
335 krb5_free_keyblock(Z_krb5_ctx, keyblock);
336 krb5_auth_con_free(Z_krb5_ctx, authctx);
337 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
338 return (ZAUTH_FAILED);
343 result = Z_krb5_lookup_cksumtype(val[i], &cksumtype);
345 } while (result != 0);
348 krb5_free_keyblock(Z_krb5_ctx, keyblock);
349 krb5_auth_con_free(Z_krb5_ctx, authctx);
350 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
351 return (ZAUTH_FAILED);
356 /* HOLDING: authctx, authenticator, keyblock */
358 /* Assemble the things to be checksummed */
359 /* first part is from start of packet through z_default_format:
361 * - z_num_other_fields
375 cksum0_base = notice->z_packet;
376 x = notice->z_default_format;
377 cksum0_len = x + strlen(x) + 1 - cksum0_base;
378 /* second part is from z_multinotice through other fields:
383 cksum1_base = notice->z_multinotice;
384 if (notice->z_num_other_fields)
385 x = notice->z_other_fields[notice->z_num_other_fields];
387 x = cksum1_base + strlen(cksum1_base) + 1; /* multiuid */
388 cksum1_len = x + strlen(x) + 1 - cksum1_base;
390 /* last part is the message body */
391 cksum2_base = notice->z_message;
392 cksum2_len = notice->z_message_len;
394 if ((!notice->z_ascii_checksum || *notice->z_ascii_checksum != 'Z') &&
396 (enctype == ENCTYPE_DES_CBC_CRC ||
397 enctype == ENCTYPE_DES_CBC_MD4 ||
398 enctype == ENCTYPE_DES_CBC_MD5)) {
399 /* try old-format checksum (covers cksum0 only) */
401 ZChecksum_t our_checksum;
403 our_checksum = des_quad_cksum(cksum0_base, NULL, cksum0_len, 0,
405 if (our_checksum == notice->z_checksum) {
406 krb5_free_keyblock(Z_krb5_ctx, keyblock);
407 krb5_auth_con_free(Z_krb5_ctx, authctx);
408 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
413 /* HOLDING: authctx, authenticator */
415 cksumbuf.length = cksum0_len + cksum1_len + cksum2_len;
416 cksumbuf.data = malloc(cksumbuf.length);
417 if (!cksumbuf.data) {
418 krb5_free_keyblock(Z_krb5_ctx, keyblock);
419 krb5_auth_con_free(Z_krb5_ctx, authctx);
420 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
423 /* HOLDING: authctx, authenticator, cksumbuf.data */
425 memcpy(cksumbuf.data, cksum0_base, cksum0_len);
426 memcpy(cksumbuf.data + cksum0_len, cksum1_base, cksum1_len);
427 memcpy(cksumbuf.data + cksum0_len + cksum1_len,
428 cksum2_base, cksum2_len);
430 /* decode zcoded checksum */
431 /* The encoded form is always longer than the original */
432 asn1_len = strlen(notice->z_ascii_checksum) + 1;
433 asn1_data = malloc(asn1_len);
435 krb5_free_keyblock(Z_krb5_ctx, keyblock);
436 krb5_auth_con_free(Z_krb5_ctx, authctx);
437 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
441 /* HOLDING: authctx, authenticator, cksumbuf.data, asn1_data */
442 result = ZReadZcode(notice->z_ascii_checksum,
443 asn1_data, asn1_len, &asn1_len);
444 if (result != ZERR_NONE) {
445 krb5_free_keyblock(Z_krb5_ctx, keyblock);
446 krb5_auth_con_free(Z_krb5_ctx, authctx);
447 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
452 /* HOLDING: asn1_data, cksumbuf.data */
454 #if HAVE_KRB5_C_MAKE_CHECKSUM
455 /* Verify the checksum -- MIT crypto API */
456 memset(&checksum, 0, sizeof(checksum));
457 checksum.length = asn1_len;
458 checksum.contents = asn1_data;
459 checksum.checksum_type = cksumtype;
460 result = krb5_c_verify_checksum(Z_krb5_ctx,
461 keyblock, Z_KEYUSAGE_SRV_CKSUM,
462 &cksumbuf, &checksum, &valid);
464 krb5_auth_con_free(Z_krb5_ctx, authctx);
465 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
466 krb5_free_keyblock(Z_krb5_ctx, keyblock);
468 if (!result && valid)
471 return (ZAUTH_FAILED);
473 /* Verify the checksum -- heimdal crypto API */
474 checksum.checksum.length = asn1_len;
475 checksum.checksum.data = asn1_data;
476 checksum.cksumtype = cksumtype;
478 /* HOLDING: authctx, authenticator, cksumbuf.data, asn1_data */
480 result = krb5_crypto_init(Z_krb5_ctx, keyblock, enctype, &cryptctx);
482 krb5_auth_con_free(Z_krb5_ctx, authctx);
483 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
484 krb5_free_keyblock(Z_krb5_ctx, keyblock);
489 /* HOLDING: authctx, authenticator, cryptctx, cksumbuf.data, checksum */
490 result = krb5_verify_checksum(Z_krb5_ctx, cryptctx,
491 Z_KEYUSAGE_SRV_CKSUM,
492 cksumbuf.data, cksumbuf.length,
494 krb5_free_keyblock(Z_krb5_ctx, keyblock);
495 krb5_crypto_destroy(Z_krb5_ctx, cryptctx);
496 krb5_auth_con_free(Z_krb5_ctx, authctx);
497 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
501 return (ZAUTH_FAILED);
506 return (notice->z_auth) ? ZAUTH_YES : ZAUTH_NO;
511 ZCheckAuthentication(notice, from)
513 struct sockaddr_in *from;
517 krb5_principal princ;
521 krb5_error_code result;
522 krb5_principal server;
523 krb5_keytab keytabid = 0;
524 krb5_auth_context authctx;
525 krb5_keyblock *keyblock;
526 krb5_enctype enctype;
527 krb5_cksumtype cksumtype;
530 char *cksum0_base, *cksum1_base, *cksum2_base;
531 char *svcinst, *x, *y;
532 char *asn1_data, *key_data;
533 int asn1_len, key_len, cksum0_len, cksum1_len, cksum2_len;
534 #ifdef KRB5_AUTH_CON_GETAUTHENTICATOR_TAKES_DOUBLE_POINTER
535 krb5_authenticator *authenticator;
536 #define KRB5AUTHENT authenticator
538 krb5_authenticator authenticator;
539 #define KRB5AUTHENT &authenticator
546 /* Check for bogus authentication data length. */
547 if (notice->z_authent_len <= 1)
551 if (notice->z_ascii_authent[0] != 'Z')
552 return ZCheckAuthentication4(notice, from);
555 len = strlen(notice->z_ascii_authent)+1;
558 /* Read in the authentication data. */
559 if (ZReadZcode(notice->z_ascii_authent,
561 len, &len) == ZERR_BADFIELD) {
566 packet.data = authbuf;
568 result = krb5_kt_resolve(Z_krb5_ctx,
569 keytab_file, &keytabid);
575 /* HOLDING: authbuf, keytabid */
576 /* Create the auth context */
577 result = krb5_auth_con_init(Z_krb5_ctx, &authctx);
579 krb5_kt_close(Z_krb5_ctx, keytabid);
584 /* HOLDING: authbuf, authctx */
585 result = krb5_build_principal(Z_krb5_ctx, &server, strlen(__Zephyr_realm),
586 __Zephyr_realm, SERVER_SERVICE,
587 SERVER_INSTANCE, NULL);
589 result = krb5_rd_req(Z_krb5_ctx, &authctx, &packet, server,
591 krb5_free_principal(Z_krb5_ctx, server);
593 krb5_kt_close(Z_krb5_ctx, keytabid);
596 if (result == KRB5KRB_AP_ERR_REPEAT)
597 syslog(LOG_DEBUG, "k5 auth failed: %s", error_message(result));
599 syslog(LOG_WARNING,"k5 auth failed: %s", error_message(result));
601 krb5_auth_con_free(Z_krb5_ctx, authctx);
605 /* HOLDING: authbuf, authctx, tkt */
607 if (tkt == 0 || !Z_tktprincp(tkt)) {
608 if (tkt) krb5_free_ticket(Z_krb5_ctx, tkt);
610 krb5_auth_con_free(Z_krb5_ctx, authctx);
613 princ = Z_tktprinc(tkt);
616 krb5_free_ticket(Z_krb5_ctx, tkt);
618 krb5_auth_con_free(Z_krb5_ctx, authctx);
622 /* HOLDING: authbuf, authctx, tkt */
623 result = krb5_unparse_name(Z_krb5_ctx, princ, &name);
625 syslog(LOG_WARNING, "k5 unparse_name failed: %s",
626 error_message(result));
628 krb5_auth_con_free(Z_krb5_ctx, authctx);
629 krb5_free_ticket(Z_krb5_ctx, tkt);
633 krb5_free_ticket(Z_krb5_ctx, tkt);
635 /* HOLDING: authbuf, authctx, name */
636 if (strcmp(name, notice->z_sender)) {
637 syslog(LOG_WARNING, "k5 name mismatch: '%s' vs '%s'",
638 name, notice->z_sender);
639 krb5_auth_con_free(Z_krb5_ctx, authctx);
647 /* HOLDING: authctx */
648 /* Get an authenticator so we can get the keyblock */
649 result = krb5_auth_con_getauthenticator (Z_krb5_ctx, authctx,
652 krb5_auth_con_free(Z_krb5_ctx, authctx);
656 /* HOLDING: authctx, authenticator */
657 result = krb5_auth_con_getkey(Z_krb5_ctx, authctx, &keyblock);
659 krb5_auth_con_free(Z_krb5_ctx, authctx);
660 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
661 return (ZAUTH_FAILED);
664 /* HOLDING: authctx, authenticator, keyblock */
665 /* Figure out what checksum type to use */
666 key_data = Z_keydata(keyblock);
667 key_len = Z_keylen(keyblock);
668 result = Z_ExtractEncCksum(keyblock, &enctype, &cksumtype);
670 krb5_free_keyblock(Z_krb5_ctx, keyblock);
671 krb5_auth_con_free(Z_krb5_ctx, authctx);
672 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
673 return (ZAUTH_FAILED);
675 /* HOLDING: authctx, authenticator, keyblock */
677 memcpy(__Zephyr_session, key_data, sizeof(C_Block)); /* XXX */
679 /* Assemble the things to be checksummed */
680 /* first part is from start of packet through z_default_format:
682 * - z_num_other_fields
696 cksum0_base = notice->z_packet;
697 x = notice->z_default_format;
698 cksum0_len = x + strlen(x) + 1 - cksum0_base;
699 /* second part is from z_multinotice through other fields:
704 cksum1_base = notice->z_multinotice;
705 if (notice->z_num_other_fields)
706 x = notice->z_other_fields[notice->z_num_other_fields];
708 x = cksum1_base + strlen(cksum1_base) + 1; /* multiuid */
709 cksum1_len = x + strlen(x) + 1 - cksum1_base;
711 /* last part is the message body */
712 cksum2_base = notice->z_message;
713 cksum2_len = notice->z_message_len;
715 if ((!notice->z_ascii_checksum || *notice->z_ascii_checksum != 'Z') &&
717 (enctype == ENCTYPE_DES_CBC_CRC ||
718 enctype == ENCTYPE_DES_CBC_MD4 ||
719 enctype == ENCTYPE_DES_CBC_MD5)) {
720 /* try old-format checksum (covers cksum0 only) */
722 ZChecksum_t our_checksum;
724 our_checksum = compute_checksum(notice, key_data);
726 krb5_free_keyblock(Z_krb5_ctx, keyblock);
727 krb5_auth_con_free(Z_krb5_ctx, authctx);
728 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
730 if (our_checksum == notice->z_checksum)
736 /* HOLDING: authctx, authenticator */
738 cksumbuf.length = cksum0_len + cksum1_len + cksum2_len;
739 cksumbuf.data = malloc(cksumbuf.length);
740 if (!cksumbuf.data) {
741 krb5_free_keyblock(Z_krb5_ctx, keyblock);
742 krb5_auth_con_free(Z_krb5_ctx, authctx);
743 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
746 /* HOLDING: authctx, authenticator, cksumbuf.data */
748 memcpy(cksumbuf.data, cksum0_base, cksum0_len);
749 memcpy(cksumbuf.data + cksum0_len, cksum1_base, cksum1_len);
750 memcpy(cksumbuf.data + cksum0_len + cksum1_len,
751 cksum2_base, cksum2_len);
753 /* decode zcoded checksum */
754 /* The encoded form is always longer than the original */
755 asn1_len = strlen(notice->z_ascii_checksum) + 1;
756 asn1_data = malloc(asn1_len);
758 krb5_free_keyblock(Z_krb5_ctx, keyblock);
759 krb5_auth_con_free(Z_krb5_ctx, authctx);
760 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
764 /* HOLDING: authctx, authenticator, cksumbuf.data, asn1_data */
765 result = ZReadZcode(notice->z_ascii_checksum,
766 asn1_data, asn1_len, &asn1_len);
767 if (result != ZERR_NONE) {
768 krb5_free_keyblock(Z_krb5_ctx, keyblock);
769 krb5_auth_con_free(Z_krb5_ctx, authctx);
770 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
775 /* HOLDING: asn1_data, cksumbuf.data, authctx, authenticator */
777 valid = Z_krb5_verify_cksum(keyblock, &cksumbuf, cksumtype, asn1_data, asn1_len);
780 krb5_auth_con_free(Z_krb5_ctx, authctx);
781 krb5_free_authenticator(Z_krb5_ctx, KRB5AUTHENT);
782 krb5_free_keyblock(Z_krb5_ctx, keyblock);
788 return (ZAUTH_FAILED);
790 return (notice->z_auth) ? ZAUTH_YES : ZAUTH_NO;
797 ZCheckAuthentication4(notice, from)
799 struct sockaddr_in *from;
803 char srcprincipal[ANAME_SZ+INST_SZ+REALM_SZ+4];
804 KTEXT_ST authent, ticket;
806 ZChecksum_t checksum;
808 char instance[INST_SZ+1];
813 /* Check for bogus authentication data length. */
814 if (notice->z_authent_len <= 0)
817 /* Read in the authentication data. */
818 if (ZReadAscii(notice->z_ascii_authent,
819 strlen(notice->z_ascii_authent)+1,
820 (unsigned char *)authent.dat,
821 notice->z_authent_len) == ZERR_BADFIELD) {
824 authent.length = notice->z_authent_len;
826 strcpy(instance, SERVER_INSTANCE);
828 /* We don't have the session key cached; do it the long way. */
829 result = krb_rd_req(&authent, SERVER_SERVICE, instance,
830 from->sin_addr.s_addr, &dat, srvtab_file);
831 if (result == RD_AP_OK) {
832 memcpy(__Zephyr_session, dat.session, sizeof(C_Block));
833 sprintf(srcprincipal, "%s%s%s@%s", dat.pname, dat.pinst[0] ? "." : "",
834 dat.pinst, dat.prealm);
835 if (strcmp(srcprincipal, notice->z_sender))
838 return ZAUTH_FAILED; /* didn't decode correctly */
841 /* Check the cryptographic checksum. */
845 checksum = compute_checksum(notice, dat.session);
847 if (checksum != notice->z_checksum)
852 #else /* !HAVE_KRB4 */
853 return (notice->z_auth) ? ZAUTH_YES : ZAUTH_NO;
859 static ZChecksum_t compute_checksum(notice, session_key)
866 ZChecksum_t checksum;
867 char *cstart, *cend, *hstart = notice->z_packet, *hend = notice->z_message;
869 cstart = notice->z_default_format + strlen(notice->z_default_format) + 1;
870 cend = cstart + strlen(cstart) + 1;
871 checksum = des_quad_cksum(hstart, NULL, cstart - hstart, 0, session_key);
872 checksum ^= des_quad_cksum(cend, NULL, hend - cend, 0, session_key);
873 checksum ^= des_quad_cksum(notice->z_message, NULL, notice->z_message_len,
879 static ZChecksum_t compute_rlm_checksum(notice, session_key)
886 ZChecksum_t checksum;
887 char *cstart, *cend, *hstart = notice->z_packet, *hend = notice->z_message;
889 cstart = notice->z_default_format + strlen(notice->z_default_format) + 1;
890 cend = cstart + strlen(cstart) + 1;
891 checksum = des_quad_cksum(hstart, NULL, cstart - hstart, 0, session_key);
896 void sweep_ticket_hash_table(arg)
900 Hash_entry **ptr, *entry;
902 for (i = 0; i < HASHTAB_SIZE; i++) {
906 if (entry->expires < NOW) {
914 timer_set_rel(SWEEP_INTERVAL, sweep_ticket_hash_table, NULL);
917 #endif /* HAVE_KRB4 */