diff options
Diffstat (limited to 'eBones/krb')
67 files changed, 9573 insertions, 0 deletions
diff --git a/eBones/krb/Makefile b/eBones/krb/Makefile new file mode 100644 index 0000000..8336132 --- /dev/null +++ b/eBones/krb/Makefile @@ -0,0 +1,31 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1994/09/07 16:10:17 g89r4222 Exp $ + +LIB= krb +SHLIB_MAJOR= 2 +SHLIB_MINOR= 0 +CFLAGS+=-DKERBEROS -DCRYPT -DDEBUG -I${.CURDIR}/../include -DBSD42 +SRCS= create_auth_reply.c create_ciph.c \ + create_death_packet.c create_ticket.c debug_decl.c decomp_ticket.c \ + des_rw.c dest_tkt.c extract_ticket.c fgetst.c get_ad_tkt.c \ + get_admhst.c get_cred.c get_in_tkt.c get_krbhst.c get_krbrlm.c \ + get_phost.c get_pw_tkt.c get_request.c get_svc_in_tkt.c \ + get_tf_fullname.c get_tf_realm.c getrealm.c getst.c in_tkt.c \ + k_gethostname.c klog.c kname_parse.c kntoln.c kparse.c \ + krb_err_txt.c krb_get_in_tkt.c kuserok.c log.c mk_err.c \ + mk_priv.c mk_req.c mk_safe.c month_sname.c \ + netread.c netwrite.c one.c pkt_cipher.c pkt_clen.c rd_err.c \ + rd_priv.c rd_req.c rd_safe.c read_service_key.c recvauth.c \ + save_credentials.c send_to_kdc.c sendauth.c stime.c tf_util.c \ + tkt_string.c util.c + +TDIR= ${.CURDIR}/.. +krb_err.et.c: ${COMPILE_ET} + (cd ${TDIR}/compile_et; make) + ${COMPILE_ET} ${.CURDIR}/krb_err.et -n + +beforedepend: krb_err.et.c + +CLEANFILES+= krb_err.et.c krb_err.h + +.include <bsd.lib.mk> diff --git a/eBones/krb/add_ticket.c b/eBones/krb/add_ticket.c new file mode 100644 index 0000000..cb79a18 --- /dev/null +++ b/eBones/krb/add_ticket.c @@ -0,0 +1,88 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: add_ticket.c,v 4.7 88/10/07 06:06:26 shanzer Exp $ + * $Id: add_ticket.c,v 1.2 1994/07/19 19:24:54 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: add_ticket.c,v 1.2 1994/07/19 19:24:54 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <prot.h> +#include <strings.h> + +/* + * This routine is now obsolete. It used to be possible to request + * more than one ticket at a time from the authentication server, and + * it looks like this routine was used by the server to package the + * tickets to be returned to the client. + */ + +/* + * This routine adds a new ticket to the ciphertext to be returned to + * the client. The routine takes the ciphertext (which doesn't get + * encrypted till later), the number of the ticket (i.e. 1st, 2nd, + * etc) the session key which goes in the ticket and is sent back to + * the user, the lifetime for the ticket, the service name, the + * instance, the realm, the key version number, and the ticket itself. + * + * This routine returns 0 (KSUCCESS) on success, and 1 (KFAILURE) on + * failure. On failure, which occurs when there isn't enough room + * for the ticket, a 0 length ticket is added. + * + * Notes: This routine must be called with successive values of n. + * i.e. the ticket must be added in order. The corresponding routine + * on the client side is extract ticket. + */ + +/* XXX they aren't all used; to avoid incompatible changes we will + * fool lint for the moment */ +/*ARGSUSED */ +add_ticket(cipher,n,session,lifetime,sname,instance,realm,kvno,ticket) + KTEXT cipher; /* Ciphertext info for ticket */ + char *sname; /* Service name */ + char *instance; /* Instance */ + int n; /* Relative position of this ticket */ + char *session; /* Session key for this tkt */ + int lifetime; /* Lifetime of this ticket */ + char *realm; /* Realm in which ticket is valid */ + int kvno; /* Key version number of service key */ + KTEXT ticket; /* The ticket itself */ +{ + + /* Note, the 42 is a temporary hack; it will have to be changed. */ + + /* Begin check of ticket length */ + if ((cipher->length + ticket->length + 4 + 42 + + (*(cipher->dat)+1-n)*(11+strlen(realm))) > + MAX_KTXT_LEN) { + bcopy(session,(char *)(cipher->dat+cipher->length),8); + *(cipher->dat+cipher->length+8) = (char) lifetime; + *(cipher->dat+cipher->length+9) = (char) kvno; + (void) strcpy((char *)(cipher->dat+cipher->length+10),realm); + cipher->length += 11 + strlen(realm); + *(cipher->dat+n) = 0; + return(KFAILURE); + } + /* End check of ticket length */ + + /* Add the session key, lifetime, kvno, ticket to the ciphertext */ + bcopy(session,(char *)(cipher->dat+cipher->length),8); + *(cipher->dat+cipher->length+8) = (char) lifetime; + *(cipher->dat+cipher->length+9) = (char) kvno; + (void) strcpy((char *)(cipher->dat+cipher->length+10),realm); + cipher->length += 11 + strlen(realm); + bcopy((char *)(ticket->dat),(char *)(cipher->dat+cipher->length), + ticket->length); + cipher->length += ticket->length; + + /* Set the ticket length at beginning of ciphertext */ + *(cipher->dat+n) = ticket->length; + return(KSUCCESS); +} diff --git a/eBones/krb/create_auth_reply.c b/eBones/krb/create_auth_reply.c new file mode 100644 index 0000000..e47d4df --- /dev/null +++ b/eBones/krb/create_auth_reply.c @@ -0,0 +1,116 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: create_auth_reply.c,v 4.10 89/01/13 17:47:38 steiner Exp $ + * $Id: create_auth_reply.c,v 1.2 1994/07/19 19:24:56 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: create_auth_reply.c,v 1.2 1994/07/19 19:24:56 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <prot.h> +#include <strings.h> + +/* + * This routine is called by the Kerberos authentication server + * to create a reply to an authentication request. The routine + * takes the user's name, instance, and realm, the client's + * timestamp, the number of tickets, the user's key version + * number and the ciphertext containing the tickets themselves. + * It constructs a packet and returns a pointer to it. + * + * Notes: The packet returned by this routine is static. Thus, if you + * intend to keep the result beyond the next call to this routine, you + * must copy it elsewhere. + * + * The packet is built in the following format: + * + * variable + * type or constant data + * ---- ----------- ---- + * + * unsigned char KRB_PROT_VERSION protocol version number + * + * unsigned char AUTH_MSG_KDC_REPLY protocol message type + * + * [least significant HOST_BYTE_ORDER sender's (server's) byte + * bit of above field] order + * + * string pname principal's name + * + * string pinst principal's instance + * + * string prealm principal's realm + * + * unsigned long time_ws client's timestamp + * + * unsigned char n number of tickets + * + * unsigned long x_date expiration date + * + * unsigned char kvno master key version + * + * short w_1 cipher length + * + * --- cipher->dat cipher data + */ + +KTEXT +create_auth_reply(pname,pinst,prealm,time_ws,n,x_date,kvno,cipher) + char *pname; /* Principal's name */ + char *pinst; /* Principal's instance */ + char *prealm; /* Principal's authentication domain */ + long time_ws; /* Workstation time */ + int n; /* Number of tickets */ + unsigned long x_date; /* Principal's expiration date */ + int kvno; /* Principal's key version number */ + KTEXT cipher; /* Cipher text with tickets and + * session keys */ +{ + static KTEXT_ST pkt_st; + KTEXT pkt = &pkt_st; + unsigned char *v = pkt->dat; /* Prot vers number */ + unsigned char *t = (pkt->dat+1); /* Prot message type */ + short w_l; /* Cipher length */ + + /* Create fixed part of packet */ + *v = (unsigned char) KRB_PROT_VERSION; + *t = (unsigned char) AUTH_MSG_KDC_REPLY; + *t |= HOST_BYTE_ORDER; + + if (n != 0) + *v = 3; + + /* Add the basic info */ + (void) strcpy((char *) (pkt->dat+2), pname); + pkt->length = 3 + strlen(pname); + (void) strcpy((char *) (pkt->dat+pkt->length),pinst); + pkt->length += 1 + strlen(pinst); + (void) strcpy((char *) (pkt->dat+pkt->length),prealm); + pkt->length += 1 + strlen(prealm); + /* Workstation timestamp */ + bcopy((char *) &time_ws, (char *) (pkt->dat+pkt->length), 4); + pkt->length += 4; + *(pkt->dat+(pkt->length)++) = (unsigned char) n; + /* Expiration date */ + bcopy((char *) &x_date, (char *) (pkt->dat+pkt->length),4); + pkt->length += 4; + + /* Now send the ciphertext and info to help decode it */ + *(pkt->dat+(pkt->length)++) = (unsigned char) kvno; + w_l = (short) cipher->length; + bcopy((char *) &w_l,(char *) (pkt->dat+pkt->length),2); + pkt->length += 2; + bcopy((char *) (cipher->dat), (char *) (pkt->dat+pkt->length), + cipher->length); + pkt->length += cipher->length; + + /* And return the packet */ + return pkt; +} diff --git a/eBones/krb/create_ciph.c b/eBones/krb/create_ciph.c new file mode 100644 index 0000000..c3bc0db --- /dev/null +++ b/eBones/krb/create_ciph.c @@ -0,0 +1,109 @@ +/* + * Copyright 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: create_ciph.c,v 4.8 89/05/18 21:24:26 jis Exp $ + * $Id: create_ciph.c,v 1.2 1994/07/19 19:24:58 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: create_ciph.c,v 1.2 1994/07/19 19:24:58 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <des.h> +#include <strings.h> + +/* + * This routine is used by the authentication server to create + * a packet for its client, containing a ticket for the requested + * service (given in "tkt"), and some information about the ticket, + * + * Returns KSUCCESS no matter what. + * + * The length of the cipher is stored in c->length; the format of + * c->dat is as follows: + * + * variable + * type or constant data + * ---- ----------- ---- + * + * + * 8 bytes session session key for client, service + * + * string service service name + * + * string instance service instance + * + * string realm KDC realm + * + * unsigned char life ticket lifetime + * + * unsigned char kvno service key version number + * + * unsigned char tkt->length length of following ticket + * + * data tkt->dat ticket for service + * + * 4 bytes kdc_time KDC's timestamp + * + * <=7 bytes null null pad to 8 byte multiple + * + */ + +create_ciph(c, session, service, instance, realm, life, kvno, tkt, + kdc_time, key) + KTEXT c; /* Text block to hold ciphertext */ + C_Block session; /* Session key to send to user */ + char *service; /* Service name on ticket */ + char *instance; /* Instance name on ticket */ + char *realm; /* Realm of this KDC */ + unsigned long life; /* Lifetime of the ticket */ + int kvno; /* Key version number for service */ + KTEXT tkt; /* The ticket for the service */ + unsigned long kdc_time; /* KDC time */ + C_Block key; /* Key to encrypt ciphertext with */ +{ + char *ptr; + Key_schedule key_s; + + ptr = (char *) c->dat; + + bcopy((char *) session, ptr, 8); + ptr += 8; + + (void) strcpy(ptr,service); + ptr += strlen(service) + 1; + + (void) strcpy(ptr,instance); + ptr += strlen(instance) + 1; + + (void) strcpy(ptr,realm); + ptr += strlen(realm) + 1; + + *(ptr++) = (unsigned char) life; + *(ptr++) = (unsigned char) kvno; + *(ptr++) = (unsigned char) tkt->length; + + bcopy((char *)(tkt->dat),ptr,tkt->length); + ptr += tkt->length; + + bcopy((char *) &kdc_time,ptr,4); + ptr += 4; + + /* guarantee null padded encrypted data to multiple of 8 bytes */ + bzero(ptr, 7); + + c->length = (((ptr - (char *) c->dat) + 7) / 8) * 8; + +#ifndef NOENCRYPTION + key_sched(key,key_s); + pcbc_encrypt((C_Block *)c->dat,(C_Block *)c->dat,(long) c->length,key_s, + key,ENCRYPT); +#endif /* NOENCRYPTION */ + + return(KSUCCESS); +} diff --git a/eBones/krb/create_death_packet.c b/eBones/krb/create_death_packet.c new file mode 100644 index 0000000..f747d6b --- /dev/null +++ b/eBones/krb/create_death_packet.c @@ -0,0 +1,63 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: create_death_packet.c,v 4.9 89/01/17 16:05:59 rfrench Exp $ + * $Id: create_death_packet.c,v 1.2 1994/07/19 19:24:59 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: create_death_packet.c,v 1.2 1994/07/19 19:24:59 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <prot.h> +#include <strings.h> + +/* + * This routine creates a packet to type AUTH_MSG_DIE which is sent to + * the Kerberos server to make it shut down. It is used only in the + * development environment. + * + * It takes a string "a_name" which is sent in the packet. A pointer + * to the packet is returned. + * + * The format of the killer packet is: + * + * type variable data + * or constant + * ---- ----------- ---- + * + * unsigned char KRB_PROT_VERSION protocol version number + * + * unsigned char AUTH_MSG_DIE message type + * + * [least significant HOST_BYTE_ORDER byte order of sender + * bit of above field] + * + * string a_name presumably, name of + * principal sending killer + * packet + */ + +#ifdef DEBUG +KTEXT +krb_create_death_packet(a_name) + char *a_name; +{ + static KTEXT_ST pkt_st; + KTEXT pkt = &pkt_st; + + unsigned char *v = pkt->dat; + unsigned char *t = (pkt->dat+1); + *v = (unsigned char) KRB_PROT_VERSION; + *t = (unsigned char) AUTH_MSG_DIE; + *t |= HOST_BYTE_ORDER; + (void) strcpy((char *) (pkt->dat+2),a_name); + pkt->length = 3 + strlen(a_name); + return pkt; +} +#endif /* DEBUG */ diff --git a/eBones/krb/create_ticket.c b/eBones/krb/create_ticket.c new file mode 100644 index 0000000..984d8e9 --- /dev/null +++ b/eBones/krb/create_ticket.c @@ -0,0 +1,130 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: create_ticket.c,v 4.11 89/03/22 14:43:23 jtkohl Exp $ + * $Id: create_ticket.c,v 1.2 1994/07/19 19:25:01 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: create_ticket.c,v 1.2 1994/07/19 19:25:01 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <des.h> +#include <krb.h> +#include <prot.h> +#include <strings.h> + +/* + * Create ticket takes as arguments information that should be in a + * ticket, and the KTEXT object in which the ticket should be + * constructed. It then constructs a ticket and returns, leaving the + * newly created ticket in tkt. + * The length of the ticket is a multiple of + * eight bytes and is in tkt->length. + * + * If the ticket is too long, the ticket will contain nulls. + * The return value of the routine is undefined. + * + * The corresponding routine to extract information from a ticket it + * decomp_ticket. When changes are made to this routine, the + * corresponding changes should also be made to that file. + * + * The packet is built in the following format: + * + * variable + * type or constant data + * ---- ----------- ---- + * + * tkt->length length of ticket (multiple of 8 bytes) + * + * tkt->dat: + * + * unsigned char flags namely, HOST_BYTE_ORDER + * + * string pname client's name + * + * string pinstance client's instance + * + * string prealm client's realm + * + * 4 bytes paddress client's address + * + * 8 bytes session session key + * + * 1 byte life ticket lifetime + * + * 4 bytes time_sec KDC timestamp + * + * string sname service's name + * + * string sinstance service's instance + * + * <=7 bytes null null pad to 8 byte multiple + * + */ + +int krb_create_ticket(tkt, flags, pname, pinstance, prealm, paddress, + session, life, time_sec, sname, sinstance, key) + KTEXT tkt; /* Gets filled in by the ticket */ + unsigned char flags; /* Various Kerberos flags */ + char *pname; /* Principal's name */ + char *pinstance; /* Principal's instance */ + char *prealm; /* Principal's authentication domain */ + long paddress; /* Net address of requesting entity */ + char *session; /* Session key inserted in ticket */ + short life; /* Lifetime of the ticket */ + long time_sec; /* Issue time and date */ + char *sname; /* Service Name */ + char *sinstance; /* Instance Name */ + C_Block key; /* Service's secret key */ +{ + Key_schedule key_s; + register char *data; /* running index into ticket */ + + tkt->length = 0; /* Clear previous data */ + flags |= HOST_BYTE_ORDER; /* ticket byte order */ + bcopy((char *) &flags,(char *) (tkt->dat),sizeof(flags)); + data = ((char *)tkt->dat) + sizeof(flags); + (void) strcpy(data, pname); + data += 1 + strlen(pname); + (void) strcpy(data, pinstance); + data += 1 + strlen(pinstance); + (void) strcpy(data, prealm); + data += 1 + strlen(prealm); + bcopy((char *) &paddress, data, 4); + data += 4; + + bcopy((char *) session, data, 8); + data += 8; + *(data++) = (char) life; + /* issue time */ + bcopy((char *) &time_sec, data, 4); + data += 4; + (void) strcpy(data, sname); + data += 1 + strlen(sname); + (void) strcpy(data, sinstance); + data += 1 + strlen(sinstance); + + /* guarantee null padded ticket to multiple of 8 bytes */ + bzero(data, 7); + tkt->length = ((data - ((char *)tkt->dat) + 7)/8)*8; + + /* Check length of ticket */ + if (tkt->length > (sizeof(KTEXT_ST) - 7)) { + bzero(tkt->dat, tkt->length); + tkt->length = 0; + return KFAILURE /* XXX */; + } + +#ifndef NOENCRYPTION + key_sched(key,key_s); + pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat,(long)tkt->length, + key_s,key,ENCRYPT); +#endif + return 0; +} diff --git a/eBones/krb/debug_decl.c b/eBones/krb/debug_decl.c new file mode 100644 index 0000000..1a0f6df --- /dev/null +++ b/eBones/krb/debug_decl.c @@ -0,0 +1,18 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: debug_decl.c,v 4.5 88/10/07 06:07:49 shanzer Exp $ + * $Id: debug_decl.c,v 1.2 1994/07/19 19:25:03 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: debug_decl.c,v 1.2 1994/07/19 19:25:03 g89r4222 Exp $"; +#endif lint + +/* Declare global debugging variables. */ + +int krb_ap_req_debug = 0; +int krb_debug = 0; diff --git a/eBones/krb/decomp_ticket.c b/eBones/krb/decomp_ticket.c new file mode 100644 index 0000000..181864c --- /dev/null +++ b/eBones/krb/decomp_ticket.c @@ -0,0 +1,123 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: decomp_ticket.c,v 4.12 89/05/16 18:44:46 jtkohl Exp $ + * $Id: decomp_ticket.c,v 1.2 1994/07/19 19:25:05 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: decomp_ticket.c,v 1.2 1994/07/19 19:25:05 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <des.h> +#include <krb.h> +#include <prot.h> +#include <strings.h> + +/* + * This routine takes a ticket and pointers to the variables that + * should be filled in based on the information in the ticket. It + * fills in values for its arguments. + * + * Note: if the client realm field in the ticket is the null string, + * then the "prealm" variable is filled in with the local realm (as + * defined by KRB_REALM). + * + * If the ticket byte order is different than the host's byte order + * (as indicated by the byte order bit of the "flags" field), then + * the KDC timestamp "time_sec" is byte-swapped. The other fields + * potentially affected by byte order, "paddress" and "session" are + * not byte-swapped. + * + * The routine returns KFAILURE if any of the "pname", "pinstance", + * or "prealm" fields is too big, otherwise it returns KSUCCESS. + * + * The corresponding routine to generate tickets is create_ticket. + * When changes are made to this routine, the corresponding changes + * should also be made to that file. + * + * See create_ticket.c for the format of the ticket packet. + */ + +decomp_ticket(tkt, flags, pname, pinstance, prealm, paddress, session, + life, time_sec, sname, sinstance, key, key_s) + KTEXT tkt; /* The ticket to be decoded */ + unsigned char *flags; /* Kerberos ticket flags */ + char *pname; /* Authentication name */ + char *pinstance; /* Principal's instance */ + char *prealm; /* Principal's authentication domain */ + unsigned long *paddress; /* Net address of entity + * requesting ticket */ + C_Block session; /* Session key inserted in ticket */ + int *life; /* Lifetime of the ticket */ + unsigned long *time_sec; /* Issue time and date */ + char *sname; /* Service name */ + char *sinstance; /* Service instance */ + C_Block key; /* Service's secret key + * (to decrypt the ticket) */ + Key_schedule key_s; /* The precomputed key schedule */ +{ + static int tkt_swap_bytes; + unsigned char *uptr; + char *ptr = (char *)tkt->dat; + +#ifndef NOENCRYPTION + pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat,(long)tkt->length, + key_s,key,DECRYPT); +#endif /* ! NOENCRYPTION */ + + *flags = *ptr; /* get flags byte */ + ptr += sizeof(*flags); + tkt_swap_bytes = 0; + if (HOST_BYTE_ORDER != ((*flags >> K_FLAG_ORDER)& 1)) + tkt_swap_bytes++; + + if (strlen(ptr) > ANAME_SZ) + return(KFAILURE); + (void) strcpy(pname,ptr); /* pname */ + ptr += strlen(pname) + 1; + + if (strlen(ptr) > INST_SZ) + return(KFAILURE); + (void) strcpy(pinstance,ptr); /* instance */ + ptr += strlen(pinstance) + 1; + + if (strlen(ptr) > REALM_SZ) + return(KFAILURE); + (void) strcpy(prealm,ptr); /* realm */ + ptr += strlen(prealm) + 1; + /* temporary hack until realms are dealt with properly */ + if (*prealm == 0) + (void) strcpy(prealm,KRB_REALM); + + bcopy(ptr,(char *)paddress,4); /* net address */ + ptr += 4; + + bcopy(ptr,(char *)session,8); /* session key */ + ptr+= 8; +#ifdef notdef /* DONT SWAP SESSION KEY spm 10/22/86 */ + if (tkt_swap_bytes) + swap_C_Block(session); +#endif + + /* get lifetime, being certain we don't get negative lifetimes */ + uptr = (unsigned char *) ptr++; + *life = (int) *uptr; + + bcopy(ptr,(char *) time_sec,4); /* issue time */ + ptr += 4; + if (tkt_swap_bytes) + swap_u_long(*time_sec); + + (void) strcpy(sname,ptr); /* service name */ + ptr += 1 + strlen(sname); + + (void) strcpy(sinstance,ptr); /* instance */ + ptr += 1 + strlen(sinstance); + return(KSUCCESS); +} diff --git a/eBones/krb/des_rw.c b/eBones/krb/des_rw.c new file mode 100644 index 0000000..c958355 --- /dev/null +++ b/eBones/krb/des_rw.c @@ -0,0 +1,265 @@ +/* - + * Copyright (c) 1994 Geoffrey M. Rehmet, Rhodes University + * All rights reserved. + * + * This code is derived from a specification based on software + * which forms part of the 4.4BSD-Lite distribution, which was developed + * by the University of California and its contributors. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the entire comment, + * including the above copyright notice, this list of conditions + * and the following disclaimer, verbatim, at the beginning of + * the source file. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Geoffrey M. Rehmet + * 4. Neither the name of Geoffrey M. Rehmet nor that of Rhodes University + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL GEOFFREY M. REHMET OR RHODES UNIVERSITY BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: des_rw.c,v 1.5 1994/09/24 18:54:41 g89r4222 Exp $ + */ + +/* + * + * NB: THESE ROUTINES WILL FAIL IF NON-BLOCKING I/O IS USED. + * + */ + +/* + * Routines for reading and writing DES encrypted messages onto sockets. + * (These routines will fail if non-blocking I/O is used.) + * + * When a message is written, its length is first transmitted as an int, + * in network byte order. The encrypted message is then transmitted, + * to a multiple of 8 bytes. Messages shorter than 8 bytes are right + * justified into a buffer of length 8 bytes, and the remainder of the + * buffer is filled with random garbage (before encryption): + * + * DDD -------->--+--------+ + * | | + * +--+--+--+--+--+--+--+--+ + * |x |x |x |x |x |D |D |D | + * +--+--+--+--+--+--+--+--+ + * | garbage | data | + * | | + * +-----------------------+----> des_pcbc_encrypt() --> + * + * (Note that the length field sent before the actual message specifies + * the number of data bytes, not the length of the entire padded message. + * + * When data is read, if the message received is longer than the number + * of bytes requested, then the remaining bytes are stored until the + * following call to des_read(). If the number of bytes received is + * less then the number of bytes received, then only the number of bytes + * actually received is returned. + * + * This interface corresponds with the original des_rw.c, except for the + * bugs in des_read() in the original 4.4BSD version. (One bug is + * normally not visible, due to undocumented behaviour of + * des_pcbc_encrypt() in the original MIT libdes.) + * + * XXX Todo: + * 1) Give better error returns on writes + * 2) Improve error checking on reads + * 3) Get rid of need for extern decl. of krb_net_read() + * 4) Tidy garbage generation a bit + * 5) Make the above comment more readable + */ + +#ifdef CRYPT +#ifdef KERBEROS + +#ifndef BUFFER_LEN +#define BUFFER_LEN 10240 +#endif + +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#include <sys/param.h> +#include <sys/types.h> + +#include <kerberosIV/des.h> +#include <kerberosIV/krb.h> + +extern int krb_net_read(int fd, void * data, size_t length); +extern int des_pcbc_encrypt(des_cblock *input, des_cblock *output, + register long length, + des_key_schedule schedule, + des_cblock *ivec, + int encrypt); + +static bit_64 des_key; +static des_key_schedule key_sched; + +/* + * Buffer for storing extra data when more data is received, then was + * actually requested in des_read(). + */ +static u_char des_buff[BUFFER_LEN]; +static u_char buffer[BUFFER_LEN]; +static unsigned stored = 0; +static u_char *buff_ptr = buffer; + +/* + * Set the encryption key for des_read() and des_write(). + * inkey is the initial vector for the DES encryption, while insched is + * the DES key, in unwrapped form. + */ +void des_set_key(inkey, insched) + bit_64 *inkey; + u_char *insched; +{ + bcopy(inkey, &des_key, sizeof(bit_64)); + bcopy(insched, &key_sched, sizeof(des_key_schedule)); +} + +/* + * Clear the key schedule, and initial vector, which were previously + * stored in static vars by des_set_key(). + */ +void des_clear_key() +{ + bzero(&des_key, sizeof(des_cblock)); + bzero(&key_sched, sizeof(des_key_schedule)); +} + +int des_read(fd, buf, len) + int fd; + register char * buf; + int len; +{ + int msg_length; /* length of actual message data */ + int pad_length; /* length of padded message */ + int nread; /* number of bytes actually read */ + int nreturned = 0; + + if(stored >= len) { + bcopy(buff_ptr, buf, len); + stored -= len; + buff_ptr += len; + return(len); + } else { + if (stored) { + bcopy(buff_ptr, buf, stored); + nreturned = stored; + len -= stored; + stored = 0; + buff_ptr = buffer; + } else { + nreturned = 0; + buff_ptr = buffer; + } + } + + nread = krb_net_read(fd, &msg_length, sizeof(msg_length)); + if(nread != (int)(sizeof(msg_length))) + return(0); + + msg_length = ntohl(msg_length); + pad_length = roundup(msg_length, 8); + + nread = krb_net_read(fd, des_buff, pad_length); + if(nread != pad_length) + return(0); + + des_pcbc_encrypt((des_cblock*) des_buff, (des_cblock*) buff_ptr, + (msg_length < 8 ? 8 : msg_length), + key_sched, (des_cblock*) &des_key, DES_DECRYPT); + + + if(msg_length < 8) + buff_ptr += (8 - msg_length); + stored = msg_length; + + if(stored >= len) { + bcopy(buff_ptr, buf, len); + stored -= len; + buff_ptr += len; + nreturned += len; + } else { + bcopy(buff_ptr, buf, stored); + nreturned += stored; + stored = 0; + } + + return(nreturned); +} + + +/* + * Write a message onto a file descriptor (generally a socket), using + * DES to encrypt the message. + */ +int des_write(fd, buf, len) + int fd; + char * buf; + int len; +{ + static int seeded = 0; + char garbage[8]; + long rnd; + int pad_len; + int write_len; + int nwritten = 0; + int i; + char *data; + + if(len < 8) { + /* + * Right justify the message in 8 bytes of random garbage. + */ + if(!seeded) { + seeded = 1; + srandom((unsigned)time(NULL)); + } + + for(i = 0 ; i < 8 ; i+= sizeof(long)) { + rnd = random(); + bcopy(&rnd, garbage+i, + (i <= (8 - sizeof(long)))?sizeof(long):(8-i)); + } + bcopy(buf, garbage + 8 - len, len); + data = garbage; + pad_len = 8; + } else { + data = buf; + pad_len = roundup(len, 8); + } + + des_pcbc_encrypt((des_cblock*) data, (des_cblock*) des_buff, + (len < 8)?8:len, key_sched, (des_cblock*) &des_key, DES_ENCRYPT); + + + write_len = htonl(len); + if(write(fd, &write_len, sizeof(write_len)) != sizeof(write_len)) + return(-1); + if(write(fd, des_buff, pad_len) != pad_len) + return(-1); + + return(len); +} + +#endif /* KERBEROS */ +#endif /* CRYPT */ diff --git a/eBones/krb/dest_tkt.c b/eBones/krb/dest_tkt.c new file mode 100644 index 0000000..17c7855 --- /dev/null +++ b/eBones/krb/dest_tkt.c @@ -0,0 +1,87 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: dest_tkt.c,v 4.9 89/10/02 16:23:07 jtkohl Exp $ + * $Id: dest_tkt.c,v 1.2 1994/07/19 19:25:07 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: dest_tkt.c,v 1.2 1994/07/19 19:25:07 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <krb.h> +#include <sys/file.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifdef TKT_SHMEM +#include <sys/param.h> +#endif +#include <errno.h> + +/* + * dest_tkt() is used to destroy the ticket store upon logout. + * If the ticket file does not exist, dest_tkt() returns RET_TKFIL. + * Otherwise the function returns RET_OK on success, KFAILURE on + * failure. + * + * The ticket file (TKT_FILE) is defined in "krb.h". + */ + +dest_tkt() +{ + char *file = TKT_FILE; + int i,fd; + extern int errno; + struct stat statb; + char buf[BUFSIZ]; +#ifdef TKT_SHMEM + char shmidname[MAXPATHLEN]; +#endif /* TKT_SHMEM */ + + errno = 0; + if (lstat(file,&statb) < 0) + goto out; + + if (!(statb.st_mode & S_IFREG) +#ifdef notdef + || statb.st_mode & 077 +#endif + ) + goto out; + + if ((fd = open(file, O_RDWR, 0)) < 0) + goto out; + + bzero(buf, BUFSIZ); + + for (i = 0; i < statb.st_size; i += BUFSIZ) + if (write(fd, buf, BUFSIZ) != BUFSIZ) { + (void) fsync(fd); + (void) close(fd); + goto out; + } + + (void) fsync(fd); + (void) close(fd); + + (void) unlink(file); + +out: + if (errno == ENOENT) return RET_TKFIL; + else if (errno != 0) return KFAILURE; +#ifdef TKT_SHMEM + /* + * handle the shared memory case + */ + (void) strcpy(shmidname, file); + (void) strcat(shmidname, ".shm"); + if ((i = krb_shm_dest(shmidname)) != KSUCCESS) + return(i); +#endif /* TKT_SHMEM */ + return(KSUCCESS); +} diff --git a/eBones/krb/extract_ticket.c b/eBones/krb/extract_ticket.c new file mode 100644 index 0000000..571d5da --- /dev/null +++ b/eBones/krb/extract_ticket.c @@ -0,0 +1,58 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: extract_ticket.c,v 4.6 88/10/07 06:08:15 shanzer Exp $ + * $Id: extract_ticket.c,v 1.2 1994/07/19 19:25:08 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: extract_ticket.c,v 1.2 1994/07/19 19:25:08 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <prot.h> +#include <strings.h> + +/* + * This routine is obsolete. + * + * This routine accepts the ciphertext returned by kerberos and + * extracts the nth ticket. It also fills in the variables passed as + * session, liftime and kvno. + */ + +extract_ticket(cipher,n,session,lifetime,kvno,realm,ticket) + KTEXT cipher; /* The ciphertext */ + int n; /* Which ticket */ + char *session; /* The session key for this tkt */ + int *lifetime; /* The life of this ticket */ + int *kvno; /* The kvno for the service */ + char *realm; /* Realm in which tkt issued */ + KTEXT ticket; /* The ticket itself */ +{ + char *ptr; + int i; + + /* Start after the ticket lengths */ + ptr = (char *) cipher->dat; + ptr = ptr + 1 + (int) *(cipher->dat); + + /* Step through earlier tickets */ + for (i = 1; i < n; i++) + ptr = ptr + 11 + strlen(ptr+10) + (int) *(cipher->dat+i); + bcopy(ptr, (char *) session, 8); /* Save the session key */ + ptr += 8; + *lifetime = *(ptr++); /* Save the life of the ticket */ + *kvno = *(ptr++); /* Save the kvno */ + (void) strcpy(realm,ptr); /* instance */ + ptr += strlen(realm) + 1; + + /* Save the ticket if its length is non zero */ + ticket->length = *(cipher->dat+n); + if (ticket->length) + bcopy(ptr, (char *) (ticket->dat), ticket->length); +} diff --git a/eBones/krb/fgetst.c b/eBones/krb/fgetst.c new file mode 100644 index 0000000..d938013 --- /dev/null +++ b/eBones/krb/fgetst.c @@ -0,0 +1,39 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: fgetst.c,v 4.0 89/01/23 10:08:31 jtkohl Exp $ + * $Id: fgetst.c,v 1.2 1994/07/19 19:25:10 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: fgetst.c,v 1.2 1994/07/19 19:25:10 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> + +/* + * fgetst takes a file descriptor, a character pointer, and a count. + * It reads from the file it has either read "count" characters, or + * until it reads a null byte. When finished, what has been read exists + * in "s". If "count" characters were actually read, the last is changed + * to a null, so the returned string is always null-terminated. fgetst + * returns the number of characters read, including the null terminator. + */ + +fgetst(f, s, n) + FILE *f; + register char *s; + int n; +{ + register count = n; + int ch; /* NOT char; otherwise you don't see EOF */ + + while ((ch = getc(f)) != EOF && ch && --count) { + *s++ = ch; + } + *s = '\0'; + return (n - count); +} diff --git a/eBones/krb/get_ad_tkt.c b/eBones/krb/get_ad_tkt.c new file mode 100644 index 0000000..d8e1283 --- /dev/null +++ b/eBones/krb/get_ad_tkt.c @@ -0,0 +1,234 @@ +/* + * Copyright 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: get_ad_tkt.c,v 4.15 89/07/07 15:18:51 jtkohl Exp $ + * $Id: get_ad_tkt.c,v 1.2 1994/07/19 19:25:11 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: get_ad_tkt.c,v 1.2 1994/07/19 19:25:11 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <des.h> +#include <prot.h> +#include <strings.h> + +#include <stdio.h> +#include <errno.h> + +/* use the bsd time.h struct defs for PC too! */ +#include <sys/time.h> +#include <sys/types.h> + +extern int krb_debug; + +struct timeval tt_local = { 0, 0 }; + +int swap_bytes; +unsigned long rep_err_code; + +/* + * get_ad_tkt obtains a new service ticket from Kerberos, using + * the ticket-granting ticket which must be in the ticket file. + * It is typically called by krb_mk_req() when the client side + * of an application is creating authentication information to be + * sent to the server side. + * + * get_ad_tkt takes four arguments: three pointers to strings which + * contain the name, instance, and realm of the service for which the + * ticket is to be obtained; and an integer indicating the desired + * lifetime of the ticket. + * + * It returns an error status if the ticket couldn't be obtained, + * or AD_OK if all went well. The ticket is stored in the ticket + * cache. + * + * The request sent to the Kerberos ticket-granting service looks + * like this: + * + * pkt->dat + * + * TEXT original contents of authenticator+ticket + * pkt->dat built in krb_mk_req call + * + * 4 bytes time_ws always 0 (?) + * char lifetime lifetime argument passed + * string service service name argument + * string sinstance service instance arg. + * + * See "prot.h" for the reply packet layout and definitions of the + * extraction macros like pkt_version(), pkt_msg_type(), etc. + */ + +get_ad_tkt(service,sinstance,realm,lifetime) + char *service; + char *sinstance; + char *realm; + int lifetime; +{ + static KTEXT_ST pkt_st; + KTEXT pkt = & pkt_st; /* Packet to KDC */ + static KTEXT_ST rpkt_st; + KTEXT rpkt = &rpkt_st; /* Returned packet */ + static KTEXT_ST cip_st; + KTEXT cip = &cip_st; /* Returned Ciphertext */ + static KTEXT_ST tkt_st; + KTEXT tkt = &tkt_st; /* Current ticket */ + C_Block ses; /* Session key for tkt */ + CREDENTIALS cr; + int kvno; /* Kvno for session key */ + char lrealm[REALM_SZ]; + C_Block key; /* Key for decrypting cipher */ + Key_schedule key_s; + long time_ws = 0; + + char s_name[SNAME_SZ]; + char s_instance[INST_SZ]; + int msg_byte_order; + int kerror; + char rlm[REALM_SZ]; + char *ptr; + + unsigned long kdc_time; /* KDC time */ + + if ((kerror = krb_get_tf_realm(TKT_FILE, lrealm)) != KSUCCESS) + return(kerror); + + /* Create skeleton of packet to be sent */ + (void) gettimeofday(&tt_local,(struct timezone *) 0); + + pkt->length = 0; + + /* + * Look for the session key (and other stuff we don't need) + * in the ticket file for krbtgt.realm@lrealm where "realm" + * is the service's realm (passed in "realm" argument) and + * lrealm is the realm of our initial ticket. If we don't + * have this, we will try to get it. + */ + + if ((kerror = krb_get_cred("krbtgt",realm,lrealm,&cr)) != KSUCCESS) { + /* + * If realm == lrealm, we have no hope, so let's not even try. + */ + if ((strncmp(realm, lrealm, REALM_SZ)) == 0) + return(AD_NOTGT); + else{ + if ((kerror = + get_ad_tkt("krbtgt",realm,lrealm,lifetime)) != KSUCCESS) + return(kerror); + if ((kerror = krb_get_cred("krbtgt",realm,lrealm,&cr)) != KSUCCESS) + return(kerror); + } + } + + /* + * Make up a request packet to the "krbtgt.realm@lrealm". + * Start by calling krb_mk_req() which puts ticket+authenticator + * into "pkt". Then tack other stuff on the end. + */ + + kerror = krb_mk_req(pkt,"krbtgt",realm,lrealm,0L); + + if (kerror) + return(AD_NOTGT); + + /* timestamp */ + bcopy((char *) &time_ws,(char *) (pkt->dat+pkt->length),4); + pkt->length += 4; + *(pkt->dat+(pkt->length)++) = (char) lifetime; + (void) strcpy((char *) (pkt->dat+pkt->length),service); + pkt->length += 1 + strlen(service); + (void) strcpy((char *)(pkt->dat+pkt->length),sinstance); + pkt->length += 1 + strlen(sinstance); + + rpkt->length = 0; + + /* Send the request to the local ticket-granting server */ + if (kerror = send_to_kdc(pkt, rpkt, realm)) return(kerror); + + /* check packet version of the returned packet */ + if (pkt_version(rpkt) != KRB_PROT_VERSION ) + return(INTK_PROT); + + /* Check byte order */ + msg_byte_order = pkt_msg_type(rpkt) & 1; + swap_bytes = 0; + if (msg_byte_order != HOST_BYTE_ORDER) + swap_bytes++; + + switch (pkt_msg_type(rpkt) & ~1) { + case AUTH_MSG_KDC_REPLY: + break; + case AUTH_MSG_ERR_REPLY: + bcopy(pkt_err_code(rpkt), (char *) &rep_err_code, 4); + if (swap_bytes) + swap_u_long(rep_err_code); + return(rep_err_code); + + default: + return(INTK_PROT); + } + + /* Extract the ciphertext */ + cip->length = pkt_clen(rpkt); /* let clen do the swap */ + + bcopy((char *) pkt_cipher(rpkt),(char *) (cip->dat),cip->length); + +#ifndef NOENCRYPTION + key_sched(cr.session,key_s); + pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat,(long)cip->length, + key_s,cr.session,DECRYPT); +#endif + /* Get rid of all traces of key */ + bzero((char *) cr.session, sizeof(key)); + bzero((char *) key_s, sizeof(key_s)); + + ptr = (char *) cip->dat; + + bcopy(ptr,(char *)ses,8); + ptr += 8; + + (void) strcpy(s_name,ptr); + ptr += strlen(s_name) + 1; + + (void) strcpy(s_instance,ptr); + ptr += strlen(s_instance) + 1; + + (void) strcpy(rlm,ptr); + ptr += strlen(rlm) + 1; + + lifetime = (unsigned long) ptr[0]; + kvno = (unsigned long) ptr[1]; + tkt->length = (int) ptr[2]; + ptr += 3; + bcopy(ptr,(char *)(tkt->dat),tkt->length); + ptr += tkt->length; + + if (strcmp(s_name, service) || strcmp(s_instance, sinstance) || + strcmp(rlm, realm)) /* not what we asked for */ + return(INTK_ERR); /* we need a better code here XXX */ + + /* check KDC time stamp */ + bcopy(ptr,(char *)&kdc_time,4); /* Time (coarse) */ + if (swap_bytes) swap_u_long(kdc_time); + + ptr += 4; + + (void) gettimeofday(&tt_local,(struct timezone *) 0); + if (abs((int)(tt_local.tv_sec - kdc_time)) > CLOCK_SKEW) { + return(RD_AP_TIME); /* XXX should probably be better + code */ + } + + if (kerror = save_credentials(s_name,s_instance,rlm,ses,lifetime, + kvno,tkt,tt_local.tv_sec)) + return(kerror); + + return(AD_OK); +} diff --git a/eBones/krb/get_admhst.c b/eBones/krb/get_admhst.c new file mode 100644 index 0000000..c36e997 --- /dev/null +++ b/eBones/krb/get_admhst.c @@ -0,0 +1,79 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: get_admhst.c,v 4.0 89/01/23 10:08:55 jtkohl Exp $ + * $Id: get_admhst.c,v 1.2 1994/07/19 19:25:13 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: get_admhst.c,v 1.2 1994/07/19 19:25:13 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <krb.h> +#include <string.h> + +/* + * Given a Kerberos realm, find a host on which the Kerberos database + * administration server can be found. + * + * krb_get_admhst takes a pointer to be filled in, a pointer to the name + * of the realm for which a server is desired, and an integer n, and + * returns (in h) the nth administrative host entry from the configuration + * file (KRB_CONF, defined in "krb.h") associated with the specified realm. + * + * On error, get_admhst returns KFAILURE. If all goes well, the routine + * returns KSUCCESS. + * + * For the format of the KRB_CONF file, see comments describing the routine + * krb_get_krbhst(). + * + * This is a temporary hack to allow us to find the nearest system running + * a Kerberos admin server. In the long run, this functionality will be + * provided by a nameserver. + */ + +krb_get_admhst(h, r, n) + char *h; + char *r; + int n; +{ + FILE *cnffile; + char tr[REALM_SZ]; + char linebuf[BUFSIZ]; + char scratch[64]; + register int i; + + if ((cnffile = fopen(KRB_CONF,"r")) == NULL) { + return(KFAILURE); + } + if (fgets(linebuf, BUFSIZ, cnffile) == NULL) { + /* error reading */ + (void) fclose(cnffile); + return(KFAILURE); + } + if (!index(linebuf, '\n')) { + /* didn't all fit into buffer, punt */ + (void) fclose(cnffile); + return(KFAILURE); + } + for (i = 0; i < n; ) { + /* run through the file, looking for admin host */ + if (fgets(linebuf, BUFSIZ, cnffile) == NULL) { + (void) fclose(cnffile); + return(KFAILURE); + } + /* need to scan for a token after 'admin' to make sure that + admin matched correctly */ + if (sscanf(linebuf, "%s %s admin %s", tr, h, scratch) != 3) + continue; + if (!strcmp(tr,r)) + i++; + } + (void) fclose(cnffile); + return(KSUCCESS); +} diff --git a/eBones/krb/get_cred.c b/eBones/krb/get_cred.c new file mode 100644 index 0000000..baf7ae2 --- /dev/null +++ b/eBones/krb/get_cred.c @@ -0,0 +1,60 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: get_cred.c,v 4.10 89/05/31 17:46:22 jtkohl Exp $ + * $Id: get_cred.c,v 1.2 1994/07/19 19:25:14 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: get_cred.c,v 1.2 1994/07/19 19:25:14 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <krb.h> + +/* + * krb_get_cred takes a service name, instance, and realm, and a + * structure of type CREDENTIALS to be filled in with ticket + * information. It then searches the ticket file for the appropriate + * ticket and fills in the structure with the corresponding + * information from the file. If successful, it returns KSUCCESS. + * On failure it returns a Kerberos error code. + */ + +krb_get_cred(service,instance,realm,c) + char *service; /* Service name */ + char *instance; /* Instance */ + char *realm; /* Auth domain */ + CREDENTIALS *c; /* Credentials struct */ +{ + int tf_status; /* return value of tf function calls */ + + /* Open ticket file and lock it for shared reading */ + if ((tf_status = tf_init(TKT_FILE, R_TKT_FIL)) != KSUCCESS) + return(tf_status); + + /* Copy principal's name and instance into the CREDENTIALS struc c */ + + if ( (tf_status = tf_get_pname(c->pname)) != KSUCCESS || + (tf_status = tf_get_pinst(c->pinst)) != KSUCCESS ) + return (tf_status); + + /* Search for requested service credentials and copy into c */ + + while ((tf_status = tf_get_cred(c)) == KSUCCESS) { + /* Is this the right ticket? */ + if ((strcmp(c->service,service) == 0) && + (strcmp(c->instance,instance) == 0) && + (strcmp(c->realm,realm) == 0)) + break; + } + (void) tf_close(); + + if (tf_status == EOF) + return (GC_NOTKT); + return(tf_status); +} diff --git a/eBones/krb/get_in_tkt.c b/eBones/krb/get_in_tkt.c new file mode 100644 index 0000000..5fb1560 --- /dev/null +++ b/eBones/krb/get_in_tkt.c @@ -0,0 +1,288 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: get_in_tkt.c,v 4.12 89/07/18 16:32:56 jtkohl Exp $ + * $Id: get_in_tkt.c,v 1.2 1994/07/19 19:25:16 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: get_in_tkt.c,v 1.2 1994/07/19 19:25:16 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <prot.h> + +#ifndef NULL +#define NULL 0 +#endif + +/* + * This file contains two routines: passwd_to_key() converts + * a password into a DES key (prompting for the password if + * not supplied), and krb_get_pw_in_tkt() gets an initial ticket for + * a user. + */ + +/* + * passwd_to_key(): given a password, return a DES key. + * There are extra arguments here which (used to be?) + * used by srvtab_to_key(). + * + * If the "passwd" argument is not null, generate a DES + * key from it, using string_to_key(). + * + * If the "passwd" argument is null, call des_read_password() + * to prompt for a password and then convert it into a DES key. + * + * In either case, the resulting key is put in the "key" argument, + * and 0 is returned. + */ + +/*ARGSUSED */ +static int passwd_to_key(user,instance,realm,passwd,key) + char *user, *instance, *realm, *passwd; + C_Block key; +{ +#ifdef NOENCRYPTION + if (!passwd) + placebo_read_password(key, "Password: ", 0); +#else + if (passwd) + string_to_key(passwd,key); + else + des_read_password(key,"Password: ",0); +#endif + return (0); +} + +/* + * krb_get_pw_in_tkt() takes the name of the server for which the initial + * ticket is to be obtained, the name of the principal the ticket is + * for, the desired lifetime of the ticket, and the user's password. + * It passes its arguments on to krb_get_in_tkt(), which contacts + * Kerberos to get the ticket, decrypts it using the password provided, + * and stores it away for future use. + * + * krb_get_pw_in_tkt() passes two additional arguments to krb_get_in_tkt(): + * the name of a routine (passwd_to_key()) to be used to get the + * password in case the "password" argument is null and NULL for the + * decryption procedure indicating that krb_get_in_tkt should use the + * default method of decrypting the response from the KDC. + * + * The result of the call to krb_get_in_tkt() is returned. + */ + +krb_get_pw_in_tkt(user,instance,realm,service,sinstance,life,password) + char *user, *instance, *realm, *service, *sinstance; + int life; + char *password; +{ + return(krb_get_in_tkt(user,instance,realm,service,sinstance,life, + passwd_to_key, NULL, password)); +} + +#ifdef NOENCRYPTION +/* + * $Source: /home/CVS/src/eBones/krb/get_in_tkt.c,v $ + * $Author: g89r4222 $ + * + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * + * For copying and distribution information, please see the file + * <mit-copyright.h>. + * + * This routine prints the supplied string to standard + * output as a prompt, and reads a password string without + * echoing. + */ + +#ifndef lint +static char rcsid_read_password_c[] = +"Bones$Header: /home/CVS/src/eBones/krb/get_in_tkt.c,v 1.2 1994/07/19 19:25:16 g89r4222 Exp $"; +#endif lint + +#include <des.h> +#include "conf.h" + +#include <stdio.h> +#ifdef BSDUNIX +#include <strings.h> +#include <sys/ioctl.h> +#include <signal.h> +#include <setjmp.h> +#else +char *strcpy(); +int strcmp(); +#endif + +#ifdef BSDUNIX +static jmp_buf env; +#endif + +#ifdef BSDUNIX +static void sig_restore(); +static push_signals(), pop_signals(); +int placebo_read_pw_string(); +#endif + +/*** Routines ****************************************************** */ +int +placebo_read_password(k,prompt,verify) + des_cblock *k; + char *prompt; + int verify; +{ + int ok; + char key_string[BUFSIZ]; + +#ifdef BSDUNIX + if (setjmp(env)) { + ok = -1; + goto lose; + } +#endif + + ok = placebo_read_pw_string(key_string, BUFSIZ, prompt, verify); + if (ok == 0) + bzero(k, sizeof(C_Block)); + +lose: + bzero(key_string, sizeof (key_string)); + return ok; +} + +/* + * This version just returns the string, doesn't map to key. + * + * Returns 0 on success, non-zero on failure. + */ + +int +placebo_read_pw_string(s,max,prompt,verify) + char *s; + int max; + char *prompt; + int verify; +{ + int ok = 0; + char *ptr; + +#ifdef BSDUNIX + jmp_buf old_env; + struct sgttyb tty_state; +#endif + char key_string[BUFSIZ]; + + if (max > BUFSIZ) { + return -1; + } + +#ifdef BSDUNIX + bcopy(old_env, env, sizeof(env)); + if (setjmp(env)) + goto lose; + + /* save terminal state*/ + if (ioctl(0,TIOCGETP,&tty_state) == -1) + return -1; + + push_signals(); + /* Turn off echo */ + tty_state.sg_flags &= ~ECHO; + if (ioctl(0,TIOCSETP,&tty_state) == -1) + return -1; +#endif + while (!ok) { + printf(prompt); + fflush(stdout); +#ifdef CROSSMSDOS + h19line(s,sizeof(s),0); + if (!strlen(s)) + continue; +#else + if (!fgets(s, max, stdin)) { + clearerr(stdin); + continue; + } + if ((ptr = index(s, '\n'))) + *ptr = '\0'; +#endif + if (verify) { + printf("\nVerifying, please re-enter %s",prompt); + fflush(stdout); +#ifdef CROSSMSDOS + h19line(key_string,sizeof(key_string),0); + if (!strlen(key_string)) + continue; +#else + if (!fgets(key_string, sizeof(key_string), stdin)) { + clearerr(stdin); + continue; + } + if ((ptr = index(key_string, '\n'))) + *ptr = '\0'; +#endif + if (strcmp(s,key_string)) { + printf("\n\07\07Mismatch - try again\n"); + fflush(stdout); + continue; + } + } + ok = 1; + } + +#ifdef BSDUNIX +lose: + if (!ok) + bzero(s, max); + printf("\n"); + /* turn echo back on */ + tty_state.sg_flags |= ECHO; + if (ioctl(0,TIOCSETP,&tty_state)) + ok = 0; + pop_signals(); + bcopy(env, old_env, sizeof(env)); +#endif + if (verify) + bzero(key_string, sizeof (key_string)); + s[max-1] = 0; /* force termination */ + return !ok; /* return nonzero if not okay */ +} + +#ifdef BSDUNIX +/* + * this can be static since we should never have more than + * one set saved.... + */ +#ifdef POSIX +static void (*old_sigfunc[NSIG])(); +#else +static int (*old_sigfunc[NSIG])(); +#endif POSIX + +static push_signals() +{ + register i; + for (i = 0; i < NSIG; i++) + old_sigfunc[i] = signal(i,sig_restore); +} + +static pop_signals() +{ + register i; + for (i = 0; i < NSIG; i++) + signal(i,old_sigfunc[i]); +} + +static void sig_restore(sig,code,scp) + int sig,code; + struct sigcontext *scp; +{ + longjmp(env,1); +} +#endif +#endif /* NOENCRYPTION */ diff --git a/eBones/krb/get_krbhst.c b/eBones/krb/get_krbhst.c new file mode 100644 index 0000000..16c4ff2 --- /dev/null +++ b/eBones/krb/get_krbhst.c @@ -0,0 +1,84 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: get_krbhst.c,v 4.8 89/01/22 20:00:29 rfrench Exp $ + * $Id: get_krbhst.c,v 1.2 1994/07/19 19:25:17 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: get_krbhst.c,v 1.2 1994/07/19 19:25:17 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <krb.h> +#include <strings.h> + +/* + * Given a Kerberos realm, find a host on which the Kerberos authenti- + * cation server can be found. + * + * krb_get_krbhst takes a pointer to be filled in, a pointer to the name + * of the realm for which a server is desired, and an integer, n, and + * returns (in h) the nth entry from the configuration file (KRB_CONF, + * defined in "krb.h") associated with the specified realm. + * + * On end-of-file, krb_get_krbhst returns KFAILURE. If n=1 and the + * configuration file does not exist, krb_get_krbhst will return KRB_HOST + * (also defined in "krb.h"). If all goes well, the routine returnes + * KSUCCESS. + * + * The KRB_CONF file contains the name of the local realm in the first + * line (not used by this routine), followed by lines indicating realm/host + * entries. The words "admin server" following the hostname indicate that + * the host provides an administrative database server. + * + * For example: + * + * ATHENA.MIT.EDU + * ATHENA.MIT.EDU kerberos-1.mit.edu admin server + * ATHENA.MIT.EDU kerberos-2.mit.edu + * LCS.MIT.EDU kerberos.lcs.mit.edu admin server + * + * This is a temporary hack to allow us to find the nearest system running + * kerberos. In the long run, this functionality will be provided by a + * nameserver. + */ + +krb_get_krbhst(h,r,n) + char *h; + char *r; + int n; +{ + FILE *cnffile; + char tr[REALM_SZ]; + char linebuf[BUFSIZ]; + register int i; + + if ((cnffile = fopen(KRB_CONF,"r")) == NULL) { + if (n==1) { + (void) strcpy(h,KRB_HOST); + return(KSUCCESS); + } + else + return(KFAILURE); + } + if (fscanf(cnffile,"%s",tr) == EOF) + return(KFAILURE); + /* run through the file, looking for the nth server for this realm */ + for (i = 1; i <= n;) { + if (fgets(linebuf, BUFSIZ, cnffile) == NULL) { + (void) fclose(cnffile); + return(KFAILURE); + } + if (sscanf(linebuf, "%s %s", tr, h) != 2) + continue; + if (!strcmp(tr,r)) + i++; + } + (void) fclose(cnffile); + return(KSUCCESS); +} diff --git a/eBones/krb/get_krbrlm.c b/eBones/krb/get_krbrlm.c new file mode 100644 index 0000000..7df073d --- /dev/null +++ b/eBones/krb/get_krbrlm.c @@ -0,0 +1,59 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: get_krbrlm.c,v 4.8 89/01/22 20:02:54 rfrench Exp $ + * $Id: get_krbrlm.c,v 1.2 1994/07/19 19:25:19 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: get_krbrlm.c,v 1.2 1994/07/19 19:25:19 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <krb.h> +#include <strings.h> + +/* + * krb_get_lrealm takes a pointer to a string, and a number, n. It fills + * in the string, r, with the name of the nth realm specified on the + * first line of the kerberos config file (KRB_CONF, defined in "krb.h"). + * It returns 0 (KSUCCESS) on success, and KFAILURE on failure. If the + * config file does not exist, and if n=1, a successful return will occur + * with r = KRB_REALM (also defined in "krb.h"). + * + * NOTE: for archaic & compatibility reasons, this routine will only return + * valid results when n = 1. + * + * For the format of the KRB_CONF file, see comments describing the routine + * krb_get_krbhst(). + */ + +krb_get_lrealm(r,n) + char *r; + int n; +{ + FILE *cnffile, *fopen(); + + if (n > 1) + return(KFAILURE); /* Temporary restriction */ + + if ((cnffile = fopen(KRB_CONF, "r")) == NULL) { + if (n == 1) { + (void) strcpy(r, KRB_REALM); + return(KSUCCESS); + } + else + return(KFAILURE); + } + + if (fscanf(cnffile,"%s",r) != 1) { + (void) fclose(cnffile); + return(KFAILURE); + } + (void) fclose(cnffile); + return(KSUCCESS); +} diff --git a/eBones/krb/get_phost.c b/eBones/krb/get_phost.c new file mode 100644 index 0000000..9b12d10 --- /dev/null +++ b/eBones/krb/get_phost.c @@ -0,0 +1,53 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: get_phost.c,v 4.6 89/01/23 09:25:40 jtkohl Exp $ + * $Id: get_phost.c,v 1.2 1994/07/19 19:25:20 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: get_phost.c,v 1.2 1994/07/19 19:25:20 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <ctype.h> +#include <netdb.h> + +char *index(); + +/* + * This routine takes an alias for a host name and returns the first + * field, lower case, of its domain name. For example, if "menel" is + * an alias for host officially named "menelaus" (in /etc/hosts), for + * the host whose official name is "MENELAUS.MIT.EDU", the name "menelaus" + * is returned. + * + * This is done for historical Athena reasons: the Kerberos name of + * rcmd servers (rlogin, rsh, rcp) is of the form "rcmd.host@realm" + * where "host"is the lowercase for of the host name ("menelaus"). + * This should go away: the instance should be the domain name + * (MENELAUS.MIT.EDU). But for now we need this routine... + * + * A pointer to the name is returned, if found, otherwise a pointer + * to the original "alias" argument is returned. + */ + +char * krb_get_phost(alias) + char *alias; +{ + struct hostent *h; + char *phost = alias; + if ((h=gethostbyname(alias)) != (struct hostent *)NULL ) { + char *p = index( h->h_name, '.' ); + if (p) + *p = NULL; + p = phost = h->h_name; + do { + if (isupper(*p)) *p=tolower(*p); + } while (*p++); + } + return(phost); +} diff --git a/eBones/krb/get_pw_tkt.c b/eBones/krb/get_pw_tkt.c new file mode 100644 index 0000000..48a003c --- /dev/null +++ b/eBones/krb/get_pw_tkt.c @@ -0,0 +1,72 @@ +/* + * Copyright 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: get_pw_tkt.c,v 4.6 89/01/13 18:19:11 steiner Exp $ + * $Id: get_pw_tkt.c,v 1.2 1994/07/19 19:25:23 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: get_pw_tkt.c,v 1.2 1994/07/19 19:25:23 g89r4222 Exp $"; +#endif /* lint */ + + +#include <krb.h> + +/* + * Get a ticket for the password-changing server ("changepw.KRB_MASTER"). + * + * Given the name, instance, realm, and current password of the + * principal for which the user wants a password-changing-ticket, + * return either: + * + * GT_PW_BADPW if current password was wrong, + * GT_PW_NULL if principal had a NULL password, + * or the result of the krb_get_pw_in_tkt() call. + * + * First, try to get a ticket for "user.instance@realm" to use the + * "changepw.KRB_MASTER" server (KRB_MASTER is defined in "krb.h"). + * The requested lifetime for the ticket is "1", and the current + * password is the "cpw" argument given. + * + * If the password was bad, give up. + * + * If the principal had a NULL password in the Kerberos database + * (indicating that the principal is known to Kerberos, but hasn't + * got a password yet), try instead to get a ticket for the principal + * "default.changepw@realm" to use the "changepw.KRB_MASTER" server. + * Use the password "changepwkrb" instead of "cpw". Return GT_PW_NULL + * if all goes well, otherwise the error. + * + * If this routine succeeds, a ticket and session key for either the + * principal "user.instance@realm" or "default.changepw@realm" to use + * the password-changing server will be in the user's ticket file. + */ + +get_pw_tkt(user,instance,realm,cpw) + char *user; + char *instance; + char *realm; + char *cpw; +{ + int kerror; + + kerror = krb_get_pw_in_tkt(user, instance, realm, "changepw", + KRB_MASTER, 1, cpw); + + if (kerror == INTK_BADPW) + return(GT_PW_BADPW); + + if (kerror == KDC_NULL_KEY) { + kerror = krb_get_pw_in_tkt("default","changepw",realm,"changepw", + KRB_MASTER,1,"changepwkrb"); + if (kerror) + return(kerror); + return(GT_PW_NULL); + } + + return(kerror); +} diff --git a/eBones/krb/get_request.c b/eBones/krb/get_request.c new file mode 100644 index 0000000..131ffd5 --- /dev/null +++ b/eBones/krb/get_request.c @@ -0,0 +1,52 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: get_request.c,v 4.7 88/12/01 14:00:11 jtkohl Exp $ + * $Id: get_request.c,v 1.2 1994/07/19 19:25:24 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: get_request.c,v 1.2 1994/07/19 19:25:24 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <prot.h> + +/* + * This procedure is obsolete. It is used in the kerberos_slave + * code for Version 3 tickets. + * + * This procedure sets s_name, and instance to point to + * the corresponding fields from tne nth request in the packet. + * it returns the lifetime requested. Garbage will be returned + * if there are less than n requests in the packet. + */ + +get_request(pkt, n, s_name, instance) + KTEXT pkt; /* The packet itself */ + int n; /* Which request do we want */ + char **s_name; /* Service name to be filled in */ + char **instance; /* Instance name to be filled in */ +{ + /* Go to the beginning of the request list */ + char *ptr = (char *) pkt_a_realm(pkt) + 6 + + strlen((char *)pkt_a_realm(pkt)); + + /* Read requests until we hit the right one */ + while (n-- > 1) { + ptr++; + ptr += 1 + strlen(ptr); + ptr += 1 + strlen(ptr); + } + + /* Set the arguments to point to the right place */ + *s_name = 1 + ptr; + *instance = 2 + ptr + strlen(*s_name); + + /* Return the requested lifetime */ + return((int) *ptr); +} diff --git a/eBones/krb/get_svc_in_tkt.c b/eBones/krb/get_svc_in_tkt.c new file mode 100644 index 0000000..6d9702f --- /dev/null +++ b/eBones/krb/get_svc_in_tkt.c @@ -0,0 +1,73 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: get_svc_in_tkt.c,v 4.9 89/07/18 16:33:34 jtkohl Exp $ + * $Id: get_svc_in_tkt.c,v 1.2 1994/07/19 19:25:26 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: get_svc_in_tkt.c,v 1.2 1994/07/19 19:25:26 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <prot.h> + +#ifndef NULL +#define NULL 0 +#endif + +/* + * This file contains two routines: srvtab_to_key(), which gets + * a server's key from a srvtab file, and krb_get_svc_in_tkt() which + * gets an initial ticket for a server. + */ + +/* + * srvtab_to_key(): given a "srvtab" file (where the keys for the + * service on a host are stored), return the private key of the + * given service (user.instance@realm). + * + * srvtab_to_key() passes its arguments on to read_service_key(), + * plus one additional argument, the key version number. + * (Currently, the key version number is always 0; this value + * is treated as a wildcard by read_service_key().) + * + * If the "srvtab" argument is null, KEYFILE (defined in "krb.h") + * is passed in its place. + * + * It returns the return value of the read_service_key() call. + * The service key is placed in "key". + */ + +static int srvtab_to_key(user, instance, realm, srvtab, key) + char *user, *instance, *realm, *srvtab; + C_Block key; +{ + if (!srvtab) + srvtab = KEYFILE; + + return(read_service_key(user, instance, realm, 0, srvtab, + (char *)key)); +} + +/* + * krb_get_svc_in_tkt() passes its arguments on to krb_get_in_tkt(), + * plus two additional arguments: a pointer to the srvtab_to_key() + * function to be used to get the key from the key file and a NULL + * for the decryption procedure indicating that krb_get_in_tkt should + * use the default method of decrypting the response from the KDC. + * + * It returns the return value of the krb_get_in_tkt() call. + */ + +krb_get_svc_in_tkt(user, instance, realm, service, sinstance, life, srvtab) + char *user, *instance, *realm, *service, *sinstance; + int life; + char *srvtab; +{ + return(krb_get_in_tkt(user, instance, realm, service, sinstance, + life, srvtab_to_key, NULL, srvtab)); +} diff --git a/eBones/krb/get_tf_fullname.c b/eBones/krb/get_tf_fullname.c new file mode 100644 index 0000000..753ad1e --- /dev/null +++ b/eBones/krb/get_tf_fullname.c @@ -0,0 +1,66 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: get_tf_fullname.c,v 4.3 90/03/10 22:40:20 jon Exp $ + * $Id: get_tf_fullname.c,v 1.2 1994/07/19 19:25:28 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: get_tf_fullname.c,v 1.2 1994/07/19 19:25:28 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <strings.h> +#include <stdio.h> + +/* + * This file contains a routine to extract the fullname of a user + * from the ticket file. + */ + +/* + * krb_get_tf_fullname() takes four arguments: the name of the + * ticket file, and variables for name, instance, and realm to be + * returned in. Since the realm of a ticket file is not really fully + * supported, the realm used will be that of the the first ticket in + * the file as this is the one that was obtained with a password by + * krb_get_in_tkt(). + */ + +krb_get_tf_fullname(ticket_file, name, instance, realm) + char *ticket_file; + char *name; + char *instance; + char *realm; +{ + int tf_status; + CREDENTIALS c; + + if ((tf_status = tf_init(ticket_file, R_TKT_FIL)) != KSUCCESS) + return(tf_status); + + if (((tf_status = tf_get_pname(c.pname)) != KSUCCESS) || + ((tf_status = tf_get_pinst(c.pinst)) != KSUCCESS)) + return (tf_status); + + if (name) + strcpy(name, c.pname); + if (instance) + strcpy(instance, c.pinst); + if ((tf_status = tf_get_cred(&c)) == KSUCCESS) { + if (realm) + strcpy(realm, c.realm); + } + else { + if (tf_status == EOF) + return(KFAILURE); + else + return(tf_status); + } + (void) tf_close(); + + return(tf_status); +} diff --git a/eBones/krb/get_tf_realm.c b/eBones/krb/get_tf_realm.c new file mode 100644 index 0000000..f405dcb --- /dev/null +++ b/eBones/krb/get_tf_realm.c @@ -0,0 +1,34 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: get_tf_realm.c,v 4.2 90/01/02 13:40:19 jtkohl Exp $ + * $Id: get_tf_realm.c,v 1.2 1994/07/19 19:25:30 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: get_tf_realm.c,v 1.2 1994/07/19 19:25:30 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <strings.h> + +/* + * This file contains a routine to extract the realm of a kerberos + * ticket file. + */ + +/* + * krb_get_tf_realm() takes two arguments: the name of a ticket + * and a variable to store the name of the realm in. + * + */ + +krb_get_tf_realm(ticket_file, realm) + char *ticket_file; + char *realm; +{ + return(krb_get_tf_fullname(ticket_file, 0, 0, realm)); +} diff --git a/eBones/krb/getrealm.c b/eBones/krb/getrealm.c new file mode 100644 index 0000000..96e9588 --- /dev/null +++ b/eBones/krb/getrealm.c @@ -0,0 +1,104 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * routine to convert hostname into realm name. + * + * from: getrealm.c,v 4.6 90/01/02 13:35:56 jtkohl Exp $ + * $Id: getrealm.c,v 1.2 1994/07/19 19:25:31 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: getrealm.c,v 1.2 1994/07/19 19:25:31 g89r4222 Exp $"; +#endif lint + +#include <strings.h> +#include <stdio.h> +#include <ctype.h> +#include <krb.h> +#include <sys/param.h> + +/* for Ultrix and friends ... */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +/* + * krb_realmofhost. + * Given a fully-qualified domain-style primary host name, + * return the name of the Kerberos realm for the host. + * If the hostname contains no discernable domain, or an error occurs, + * return the local realm name, as supplied by get_krbrlm(). + * If the hostname contains a domain, but no translation is found, + * the hostname's domain is converted to upper-case and returned. + * + * The format of each line of the translation file is: + * domain_name kerberos_realm + * -or- + * host_name kerberos_realm + * + * domain_name should be of the form .XXX.YYY (e.g. .LCS.MIT.EDU) + * host names should be in the usual form (e.g. FOO.BAR.BAZ) + */ + +static char ret_realm[REALM_SZ+1]; + +char * +krb_realmofhost(host) +char *host; +{ + char *domain; + FILE *trans_file; + char trans_host[MAXHOSTNAMELEN+1]; + char trans_realm[REALM_SZ+1]; + int retval; + + domain = index(host, '.'); + + /* prepare default */ + if (domain) { + char *cp; + + strncpy(ret_realm, &domain[1], REALM_SZ); + ret_realm[REALM_SZ] = '\0'; + /* Upper-case realm */ + for (cp = ret_realm; *cp; cp++) + if (islower(*cp)) + *cp = toupper(*cp); + } else { + krb_get_lrealm(ret_realm, 1); + } + + if ((trans_file = fopen(KRB_RLM_TRANS, "r")) == (FILE *) 0) { + /* krb_errno = KRB_NO_TRANS */ + return(ret_realm); + } + while (1) { + if ((retval = fscanf(trans_file, "%s %s", + trans_host, trans_realm)) != 2) { + if (retval == EOF) { + fclose(trans_file); + return(ret_realm); + } + continue; /* ignore broken lines */ + } + trans_host[MAXHOSTNAMELEN] = '\0'; + trans_realm[REALM_SZ] = '\0'; + if (!strcasecmp(trans_host, host)) { + /* exact match of hostname, so return the realm */ + (void) strcpy(ret_realm, trans_realm); + fclose(trans_file); + return(ret_realm); + } + if ((trans_host[0] == '.') && domain) { + /* this is a domain match */ + if (!strcasecmp(trans_host, domain)) { + /* domain match, save for later */ + (void) strcpy(ret_realm, trans_realm); + continue; + } + } + } +} diff --git a/eBones/krb/getst.c b/eBones/krb/getst.c new file mode 100644 index 0000000..edd55ec --- /dev/null +++ b/eBones/krb/getst.c @@ -0,0 +1,35 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * form: getst.c,v 4.5 88/11/15 16:31:39 jtkohl Exp $ + * $Id: getst.c,v 1.2 1994/07/19 19:25:33 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: getst.c,v 1.2 1994/07/19 19:25:33 g89r4222 Exp $"; +#endif /* lint */ + +/* + * getst() takes a file descriptor, a string and a count. It reads + * from the file until either it has read "count" characters, or until + * it reads a null byte. When finished, what has been read exists in + * the given string "s". If "count" characters were actually read, the + * last is changed to a null, so the returned string is always null- + * terminated. getst() returns the number of characters read, including + * the null terminator. + */ + +getst(fd, s, n) + int fd; + register char *s; +{ + register count = n; + while (read(fd, s, 1) > 0 && --count) + if (*s++ == '\0') + return (n - count); + *s = '\0'; + return (n - count); +} diff --git a/eBones/krb/in_tkt.c b/eBones/krb/in_tkt.c new file mode 100644 index 0000000..53510da --- /dev/null +++ b/eBones/krb/in_tkt.c @@ -0,0 +1,142 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: kt.c,v 4.9 89/10/25 19:03:35 qjb Exp $ + * $Id: in_tkt.c,v 1.5 1994/09/24 14:30:09 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: in_tkt.c,v 1.5 1994/09/24 14:30:09 g89r4222 Exp $"; +#endif /* lint */ + +#include <unistd.h> +#include <stdio.h> +#include <krb.h> +#include <sys/file.h> +#include <sys/fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#ifdef TKT_SHMEM +#include <sys/param.h> +#endif + +extern int krb_debug; + +/* + * in_tkt() is used to initialize the ticket store. It creates the + * file to contain the tickets and writes the given user's name "pname" + * and instance "pinst" in the file. in_tkt() returns KSUCCESS on + * success, or KFAILURE if something goes wrong. + */ + +in_tkt(pname,pinst) + char *pname; + char *pinst; +{ + int tktfile; + uid_t me, metoo; + struct stat buf; + int count; + char *file = TKT_FILE; + int fd; + register int i; + char charbuf[BUFSIZ]; +#ifdef TKT_SHMEM + char shmidname[MAXPATHLEN]; +#endif /* TKT_SHMEM */ + + me = getuid (); + metoo = geteuid(); + if (lstat(file,&buf) == 0) { + if (buf.st_uid != me && me == 0) { + unlink(file); + } else { + if (buf.st_uid != me || !(buf.st_mode & S_IFREG) || + buf.st_mode & 077) { + if (krb_debug) + fprintf(stderr,"Error initializing %s",file); + return(KFAILURE); + } + /* file already exists, and permissions appear ok, so nuke it */ + if ((fd = open(file, O_RDWR, 0)) < 0) + goto out; /* can't zero it, but we can still try truncating it */ + + bzero(charbuf, sizeof(charbuf)); + + for (i = 0; i < buf.st_size; i += sizeof(charbuf)) + if (write(fd, charbuf, sizeof(charbuf)) != sizeof(charbuf)) { + (void) fsync(fd); + (void) close(fd); + goto out; + } + + (void) fsync(fd); + (void) close(fd); + } + } + out: + /* arrange so the file is owned by the ruid + (swap real & effective uid if necessary). + This isn't a security problem, since the ticket file, if it already + exists, has the right uid (== ruid) and mode. */ + if (me != metoo) { + if (setreuid(metoo, me) < 0) { + /* can't switch??? barf! */ + if (krb_debug) + perror("in_tkt: setreuid"); + return(KFAILURE); + } else + if (krb_debug) + printf("swapped UID's %d and %d\n",metoo,me); + } + if ((tktfile = open(file,O_CREAT | O_TRUNC | O_WRONLY,0600)) < 0) { + if (krb_debug) + fprintf(stderr,"Error initializing %s",TKT_FILE); + return(KFAILURE); + } + if (me != metoo) { + if (setreuid(me, metoo) < 0) { + /* can't switch??? barf! */ + if (krb_debug) + perror("in_tkt: setreuid2"); + return(KFAILURE); + } else + if (krb_debug) + printf("swapped UID's %d and %d\n",me,metoo); + } + if (lstat(file,&buf) < 0) { + if (krb_debug) + fprintf(stderr,"Error initializing %s",TKT_FILE); + return(KFAILURE); + } + + if (buf.st_uid != me || !(buf.st_mode & S_IFREG) || + buf.st_mode & 077) { + if (krb_debug) + fprintf(stderr,"Error initializing %s",TKT_FILE); + return(KFAILURE); + } + + count = strlen(pname)+1; + if (write(tktfile,pname,count) != count) { + (void) close(tktfile); + return(KFAILURE); + } + count = strlen(pinst)+1; + if (write(tktfile,pinst,count) != count) { + (void) close(tktfile); + return(KFAILURE); + } + (void) close(tktfile); +#ifdef TKT_SHMEM + (void) strcpy(shmidname, file); + (void) strcat(shmidname, ".shm"); + return(krb_shm_create(shmidname)); +#else /* !TKT_SHMEM */ + return(KSUCCESS); +#endif /* TKT_SHMEM */ +} diff --git a/eBones/krb/k_gethostname.c b/eBones/krb/k_gethostname.c new file mode 100644 index 0000000..e5c11ca --- /dev/null +++ b/eBones/krb/k_gethostname.c @@ -0,0 +1,65 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: k_gethostname.c,v 4.1 88/12/01 14:04:42 jtkohl Exp $ + * $Id: k_gethostname.c,v 1.2 1994/07/19 19:25:36 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: k_gethostname.c,v 1.2 1994/07/19 19:25:36 g89r4222 Exp $"; +#endif /* lint */ + +#ifndef PC +#ifndef BSD42 +/* teach me how to k_gethostname for your system here */ +#endif +#endif + +#ifdef PC +#include <stdio.h> +typedef long in_name; +#include "custom.h" /* where is this file? */ +extern get_custom(); +#define LEN 64 /* just a guess */ +#endif /* PC */ + +/* + * Return the local host's name in "name", up to "namelen" characters. + * "name" will be null-terminated if "namelen" is big enough. + * The return code is 0 on success, -1 on failure. (The calling + * interface is identical to gethostname(2).) + * + * Currently defined for BSD 4.2 and PC. The BSD version just calls + * gethostname(); the PC code was taken from "kinit.c", and may or may + * not work. + */ + +k_gethostname(name, namelen) + char *name; +{ +#ifdef BSD42 + return gethostname(name, namelen); +#endif + +#ifdef PC + char buf[LEN]; + char b1, b2, b3, b4; + register char *ptr; + + get_custom(); /* should check for errors, + * return -1 on failure */ + ptr = (char *) &(custom.c_me); + b1 = *ptr++; + b2 = *ptr++; + b3 = *ptr++; + b4 = *ptr; + (void) sprintf(buf,"PC address %d.%d.%d.%d",b1,b2,b3,b4); + if (strlen(buf) > namelen) + fprintf(stderr, "gethostname: namelen too small; truncating"); + strnpcy(name, buf, namelen); + return 0; +#endif +} diff --git a/eBones/krb/klog.c b/eBones/krb/klog.c new file mode 100644 index 0000000..b530e8b --- /dev/null +++ b/eBones/krb/klog.c @@ -0,0 +1,108 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: klog.c,v 4.6 88/12/01 14:06:05 jtkohl Exp $ + * $Id: klog.c,v 1.2 1994/07/19 19:25:37 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: klog.c,v 1.2 1994/07/19 19:25:37 g89r4222 Exp $"; +#endif /* lint */ + +#include <sys/time.h> +#include <stdio.h> + +#include <krb.h> +#include <klog.h> + +static char *log_name = KRBLOG; +static int is_open; +static char logtxt[1000]; + +/* + * This file contains two logging routines: kset_logfile() + * to determine the file to which log entries should be written; + * and klog() to write log entries to the file. + */ + +/* + * klog() is used to add entries to the logfile (see kset_logfile() + * below). Note that it is probably not portable since it makes + * assumptions about what the compiler will do when it is called + * with less than the correct number of arguments which is the + * way it is usually called. + * + * The log entry consists of a timestamp and the given arguments + * printed according to the given "format" string. + * + * The log file is opened and closed for each log entry. + * + * If the given log type "type" is unknown, or if the log file + * cannot be opened, no entry is made to the log file. + * + * The return value is always a pointer to the formatted log + * text string "logtxt". + */ + +char * klog(type,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a0) + int type; + char *format; + int a1,a2,a3,a4,a5,a6,a7,a8,a9,a0; +{ + FILE *logfile, *fopen(); + long time(),now; + char *month_sname(); + struct tm *tm; + static int logtype_array[NLOGTYPE] = {0,0}; + static int array_initialized; + + if (!(array_initialized++)) { + logtype_array[L_NET_ERR] = 1; + logtype_array[L_KRB_PERR] = 1; + logtype_array[L_KRB_PWARN] = 1; + logtype_array[L_APPL_REQ] = 1; + logtype_array[L_INI_REQ] = 1; + logtype_array[L_DEATH_REQ] = 1; + logtype_array[L_NTGT_INTK] = 1; + logtype_array[L_ERR_SEXP] = 1; + logtype_array[L_ERR_MKV] = 1; + logtype_array[L_ERR_NKY] = 1; + logtype_array[L_ERR_NUN] = 1; + logtype_array[L_ERR_UNK] = 1; + } + + (void) sprintf(logtxt,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a0); + + if (!logtype_array[type]) + return(logtxt); + + if ((logfile = fopen(log_name,"a")) == NULL) + return(logtxt); + + (void) time(&now); + tm = localtime(&now); + + fprintf(logfile,"%2d-%s-%02d %02d:%02d:%02d ",tm->tm_mday, + month_sname(tm->tm_mon + 1),tm->tm_year, + tm->tm_hour, tm->tm_min, tm->tm_sec); + fprintf(logfile,"%s\n",logtxt); + (void) fclose(logfile); + return(logtxt); +} + +/* + * kset_logfile() changes the name of the file to which + * messages are logged. If kset_logfile() is not called, + * the logfile defaults to KRBLOG, defined in "krb.h". + */ + +kset_logfile(filename) + char *filename; +{ + log_name = filename; + is_open = 0; +} diff --git a/eBones/krb/kname_parse.c b/eBones/krb/kname_parse.c new file mode 100644 index 0000000..dd5fe0b --- /dev/null +++ b/eBones/krb/kname_parse.c @@ -0,0 +1,233 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: kname_parse.c,v 4.4 88/12/01 14:07:29 jtkohl Exp $ + * $Id: kname_parse.c,v 1.2 1994/07/19 19:25:39 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: kname_parse.c,v 1.2 1994/07/19 19:25:39 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <krb.h> +#include <strings.h> + +/* max size of full name */ +#define FULL_SZ (ANAME_SZ + INST_SZ + REALM_SZ) + +#define NAME 0 /* which field are we in? */ +#define INST 1 +#define REALM 2 + +extern char *krb_err_txt[]; + +/* + * This file contains four routines for handling Kerberos names. + * + * kname_parse() breaks a Kerberos name into its name, instance, + * and realm components. + * + * k_isname(), k_isinst(), and k_isrealm() check a given string to see if + * it's a syntactically legitimate respective part of a Kerberos name, + * returning 1 if it is, 0 if it isn't. + * + * Definition of "syntactically legitimate" names is according to + * the Project Athena Technical Plan Section E.2.1, page 7 "Specifying + * names", version dated 21 Dec 1987. + * / + +/* + * kname_parse() takes a Kerberos name "fullname" of the form: + * + * username[.instance][@realm] + * + * and returns the three components ("name", "instance", and "realm" + * in the example above) in the given arguments "np", "ip", and "rp". + * + * If successful, it returns KSUCCESS. If there was an error, + * KNAME_FMT is returned. + */ + +kname_parse(np, ip, rp, fullname) + char *np, *ip, *rp, *fullname; +{ + static char buf[FULL_SZ]; + char *rnext, *wnext; /* next char to read, write */ + register char c; + int backslash; + int field; + + backslash = 0; + rnext = buf; + wnext = np; + field = NAME; + + if (strlen(fullname) > FULL_SZ) + return KNAME_FMT; + (void) strcpy(buf, fullname); + + while (c = *rnext++) { + if (backslash) { + *wnext++ = c; + backslash = 0; + continue; + } + switch (c) { + case '\\': + backslash++; + break; + case '.': + switch (field) { + case NAME: + if (wnext == np) + return KNAME_FMT; + *wnext = '\0'; + field = INST; + wnext = ip; + break; + case INST: + return KNAME_FMT; + /* break; */ + case REALM: + *wnext++ = c; + break; + default: + fprintf(stderr, "unknown field value\n"); + exit(1); + } + break; + case '@': + switch (field) { + case NAME: + if (wnext == np) + return KNAME_FMT; + *ip = '\0'; + /* fall through */ + case INST: + *wnext = '\0'; + field = REALM; + wnext = rp; + break; + case REALM: + return KNAME_FMT; + default: + fprintf(stderr, "unknown field value\n"); + exit(1); + } + break; + default: + *wnext++ = c; + } + } + *wnext = '\0'; + if ((strlen(np) > ANAME_SZ - 1) || + (strlen(ip) > INST_SZ - 1) || + (strlen(rp) > REALM_SZ - 1)) + return KNAME_FMT; + return KSUCCESS; +} + +/* + * k_isname() returns 1 if the given name is a syntactically legitimate + * Kerberos name; returns 0 if it's not. + */ + +k_isname(s) + char *s; +{ + register char c; + int backslash = 0; + + if (!*s) + return 0; + if (strlen(s) > ANAME_SZ - 1) + return 0; + while(c = *s++) { + if (backslash) { + backslash = 0; + continue; + } + switch(c) { + case '\\': + backslash = 1; + break; + case '.': + return 0; + /* break; */ + case '@': + return 0; + /* break; */ + } + } + return 1; +} + + +/* + * k_isinst() returns 1 if the given name is a syntactically legitimate + * Kerberos instance; returns 0 if it's not. + */ + +k_isinst(s) + char *s; +{ + register char c; + int backslash = 0; + + if (strlen(s) > INST_SZ - 1) + return 0; + while(c = *s++) { + if (backslash) { + backslash = 0; + continue; + } + switch(c) { + case '\\': + backslash = 1; + break; + case '.': + return 0; + /* break; */ + case '@': + return 0; + /* break; */ + } + } + return 1; +} + +/* + * k_isrealm() returns 1 if the given name is a syntactically legitimate + * Kerberos realm; returns 0 if it's not. + */ + +k_isrealm(s) + char *s; +{ + register char c; + int backslash = 0; + + if (!*s) + return 0; + if (strlen(s) > REALM_SZ - 1) + return 0; + while(c = *s++) { + if (backslash) { + backslash = 0; + continue; + } + switch(c) { + case '\\': + backslash = 1; + break; + case '@': + return 0; + /* break; */ + } + } + return 1; +} diff --git a/eBones/krb/kntoln.c b/eBones/krb/kntoln.c new file mode 100644 index 0000000..62ec1b5 --- /dev/null +++ b/eBones/krb/kntoln.c @@ -0,0 +1,60 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: kntoln.c,v 4.7 89/01/23 09:25:15 jtkohl Exp $ + * $Id: kntoln.c,v 1.2 1994/07/19 19:25:40 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: kntoln.c,v 1.2 1994/07/19 19:25:40 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <strings.h> + +/* + * krb_kntoln converts an auth name into a local name by looking up + * the auth name in the /etc/aname file. The format of the aname + * file is: + * + * +-----+-----+-----+-----+------+----------+-------+-------+ + * | anl | inl | rll | lnl | name | instance | realm | lname | + * +-----+-----+-----+-----+------+----------+-------+-------+ + * | 1by | 1by | 1by | 1by | name | instance | realm | lname | + * +-----+-----+-----+-----+------+----------+-------+-------+ + * + * If the /etc/aname file can not be opened it will set the + * local name to the auth name. Thus, in this case it performs as + * the identity function. + * + * The name instance and realm are passed to krb_kntoln through + * the AUTH_DAT structure (ad). + * + * Now here's what it *really* does: + * + * Given a Kerberos name in an AUTH_DAT structure, check that the + * instance is null, and that the realm is the same as the local + * realm, and return the principal's name in "lname". Return + * KSUCCESS if all goes well, otherwise KFAILURE. + */ + +krb_kntoln(ad,lname) + AUTH_DAT *ad; + char *lname; +{ + static char lrealm[REALM_SZ] = ""; + + if (!(*lrealm) && (krb_get_lrealm(lrealm,1) == KFAILURE)) + return(KFAILURE); + + if (strcmp(ad->pinst,"")) + return(KFAILURE); + if (strcmp(ad->prealm,lrealm)) + return(KFAILURE); + (void) strcpy(lname,ad->pname); + return(KSUCCESS); +} diff --git a/eBones/krb/kparse.c b/eBones/krb/kparse.c new file mode 100644 index 0000000..d79f1cf --- /dev/null +++ b/eBones/krb/kparse.c @@ -0,0 +1,763 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * Purpose: + * This module was developed to parse the "~/.klogin" files for + * Kerberos-authenticated rlogin/rcp/rsh services. However, it is + * general purpose and can be used to parse any such parameter file. + * + * The parameter file should consist of one or more entries, with each + * entry on a separate line and consisting of zero or more + * "keyword=value" combinations. The keyword is case insensitive, but + * the value is not. Any string may be enclosed in quotes, and + * c-style "\" literals are supported. A comma may be used to + * separate the k/v combinations, and multiple commas are ignored. + * Whitespace (blank or tab) may be used freely and is ignored. + * + * Full error processing is available. When PS_BAD_KEYWORD or + * PS_SYNTAX is returned from fGetParameterSet(), the string ErrorMsg + * contains a meaningful error message. + * + * Keywords and their default values are programmed by an external + * table. + * + * Routines: + * fGetParameterSet() parse one line of the parameter file + * fGetKeywordValue() parse one "keyword=value" combo + * fGetToken() parse one token + * + * + * from: kparse.c,v 4.5 89/01/21 17:20:39 jtkohl Exp $ + * $Id: kparse.c,v 1.2 1994/07/19 19:25:42 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: kparse.c,v 1.2 1994/07/19 19:25:42 g89r4222 Exp $"; +#endif lint + +#include <stdio.h> +#include <ctype.h> +#include <kparse.h> + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +#define void int + +#define MAXKEY 80 +#define MAXVALUE 80 + +char *malloc(); +char *strcpy(); + +int LineNbr=1; /* current line nbr in parameter file */ +char ErrorMsg[80]; /* meaningful only when KV_SYNTAX, PS_SYNTAX, + * or PS_BAD_KEYWORD is returned by + * fGetKeywordValue or fGetParameterSet */ + +int fGetParameterSet( fp,parm,parmcount ) + FILE *fp; + parmtable parm[]; + int parmcount; +{ + int rc,i; + char keyword[MAXKEY]; + char value[MAXVALUE]; + + while (TRUE) { + rc=fGetKeywordValue(fp,keyword,MAXKEY,value,MAXVALUE); + + switch (rc) { + + case KV_EOF: + return(PS_EOF); + + case KV_EOL: + return(PS_OKAY); + + case KV_SYNTAX: + return(PS_SYNTAX); + + case KV_OKAY: + /* + * got a reasonable keyword/value pair. Search the + * parameter table to see if we recognize the keyword; if + * not, return an error. If we DO recognize it, make sure + * it has not already been given. If not already given, + * save the value. + */ + for (i=0; i<parmcount; i++) { + if (strcmp(strutol(keyword),parm[i].keyword)==0) { + if (parm[i].value) { + sprintf(ErrorMsg,"duplicate keyword \"%s\" found", + keyword); + return(PS_BAD_KEYWORD); + } + parm[i].value = strsave( value ); + break; + } + } + if (i >= parmcount) { + sprintf(ErrorMsg, "unrecognized keyword \"%s\" found", + keyword); + return(PS_BAD_KEYWORD); + } + break; + + default: + sprintf(ErrorMsg, + "panic: bad return (%d) from fGetToken()",rc); + break; + } + } +} + +/* + * Routine: ParmCompare + * + * Purpose: + * ParmCompare checks a specified value for a particular keyword. + * fails if keyword not found or keyword found but the value was + * different. Like strcmp, ParmCompare returns 0 for a match found, -1 + * otherwise + */ +int ParmCompare( parm, parmcount, keyword, value ) + parmtable parm[]; + int parmcount; + char *keyword; + char *value; +{ + int i; + + for (i=0; i<parmcount; i++) { + if (strcmp(parm[i].keyword,keyword)==0) { + if (parm[i].value) { + return(strcmp(parm[i].value,value)); + } else { + return(strcmp(parm[i].defvalue,value)); + } + } + } + return(-1); +} + +void FreeParameterSet(parm,parmcount) + parmtable parm[]; + int parmcount; +{ + int i; + + for (i=0; i<parmcount; i++) { + if (parm[i].value) { + free(parm[i].value); + parm[i].value = (char *)NULL; + } + } +} + +int fGetKeywordValue( fp, keyword, klen, value, vlen ) + FILE *fp; + char *keyword; + int klen; + char *value; + int vlen; +{ + int rc; + int gotit; + + *keyword = *value = '\0'; /* preset strings to NULL */ + + /* + * Looking for a keyword. + * return an exception for EOF or BAD_QSTRING + * ignore leading WHITEspace + * ignore any number of leading commas + * newline means we have all the parms for this + * statement; give an indication that there is + * nothing more on this line. + * stop looking if we find QSTRING, STRING, or NUMBER + * return syntax error for any other PUNKtuation + */ + gotit = FALSE; + do { + rc = fGetToken(fp,keyword,klen); + + switch (rc) { + + case GTOK_WHITE: + break; + + case GTOK_EOF: + return(KV_EOF); + + case GTOK_BAD_QSTRING: + sprintf(ErrorMsg,"unterminated string \"%s found",keyword); + return(KV_SYNTAX); + + case GTOK_PUNK: + if (strcmp("\n",keyword)==0) { + return(KV_EOL); + } else if (strcmp(",",keyword)!=0) { + sprintf(ErrorMsg,"expecting rvalue, found \'%s\'",keyword); + } + break; + + case GTOK_STRING: + case GTOK_QSTRING: + case GTOK_NUMBER: + gotit = TRUE; + break; + + default: + sprintf(ErrorMsg,"panic: bad return (%d) from fGetToken()",rc); + return(KV_SYNTAX); + } + + } while (!gotit); + + /* + * now we expect an equal sign. + * skip any whitespace + * stop looking if we find an equal sign + * anything else causes a syntax error + */ + gotit = FALSE; + do { + rc = fGetToken(fp,value,vlen); + + switch (rc) { + + case GTOK_WHITE: + break; + + case GTOK_BAD_QSTRING: + sprintf(ErrorMsg, + "expecting \'=\', found unterminated string \"%s", + value); + return(KV_SYNTAX); + + case GTOK_PUNK: + if (strcmp("=",value)==0) { + gotit = TRUE; + } else { + if (strcmp("\n",value)==0) { + sprintf(ErrorMsg,"expecting \"=\", found newline"); + fUngetChar('\n',fp); + } else { + sprintf(ErrorMsg, + "expecting rvalue, found \'%s\'",keyword); + } + return(KV_SYNTAX); + } + break; + + case GTOK_STRING: + case GTOK_QSTRING: + case GTOK_NUMBER: + sprintf(ErrorMsg,"expecting \'=\', found \"%s\"",value); + return(KV_SYNTAX); + + case GTOK_EOF: + sprintf(ErrorMsg,"expecting \'=\', found EOF"); + return(KV_SYNTAX); + + default: + sprintf(ErrorMsg, + "panic: bad return (%d) from fGetToken()",rc); + return(KV_SYNTAX); + } + + } while ( !gotit ); + + /* + * got the keyword and equal sign, now get a value. + * ignore any whitespace + * any punctuation is a syntax error + */ + gotit = FALSE; + do { + rc = fGetToken(fp,value,vlen); + + switch (rc) { + + case GTOK_WHITE: + break; + + case GTOK_EOF: + sprintf(ErrorMsg,"expecting rvalue, found EOF"); + return(KV_SYNTAX); + + case GTOK_BAD_QSTRING: + sprintf(ErrorMsg,"unterminated quoted string \"%s",value); + return(KV_SYNTAX); + + case GTOK_PUNK: + if (strcmp("\n",value)==0) { + sprintf(ErrorMsg,"expecting rvalue, found newline"); + fUngetChar('\n',fp); + } else { + sprintf(ErrorMsg, + "expecting rvalue, found \'%s\'",value); + } + return(KV_SYNTAX); + break; + + case GTOK_STRING: + case GTOK_QSTRING: + case GTOK_NUMBER: + gotit = TRUE; + return(KV_OKAY); + + default: + sprintf(ErrorMsg, + "panic: bad return (%d) from fGetToken()",rc); + return(KV_SYNTAX); + } + + } while ( !gotit ); + /*NOTREACHED*/ +} + +/* + * Routine Name: fGetToken + * + * Function: read the next token from the specified file. + * A token is defined as a group of characters + * terminated by a white space char (SPACE, CR, + * LF, FF, TAB). The token returned is stripped of + * both leading and trailing white space, and is + * terminated by a NULL terminator. An alternate + * definition of a token is a string enclosed in + * single or double quotes. + * + * Explicit Parameters: + * fp pointer to the input FILE + * dest pointer to destination buffer + * maxlen length of the destination buffer. The buffer + * length INCLUDES the NULL terminator. + * + * Implicit Parameters: stderr where the "token too long" message goes + * + * External Procedures: fgetc + * + * Side Effects: None + * + * Return Value: A token classification value, as + * defined in kparse.h. Note that the + * classification for end of file is + * always zero. + */ +int fGetToken(fp, dest, maxlen) + FILE *fp; + char *dest; + int maxlen; +{ + int ch='\0'; + int len=0; + char *p = dest; + int digits; + + ch=fGetChar(fp); + + /* + * check for a quoted string. If found, take all characters + * that fit until a closing quote is found. Note that this + * algorithm will not behave well for a string which is too long. + */ + if (ISQUOTE(ch)) { + int done = FALSE; + do { + ch = fGetChar(fp); + done = ((maxlen<++len)||ISLINEFEED(ch)||(ch==EOF) + ||ISQUOTE(ch)); + if (ch=='\\') + ch = fGetLiteral(fp); + if (!done) + *p++ = ch; + else if ((ch!=EOF) && !ISQUOTE(ch)) + fUngetChar(ch,fp); + } while (!done); + *p = '\0'; + if (ISLINEFEED(ch)) return(GTOK_BAD_QSTRING); + return(GTOK_QSTRING); + } + + /* + * Not a quoted string. If its a token character (rules are + * defined via the ISTOKENCHAR macro, in kparse.h) take it and all + * token chars following it until we run out of space. + */ + digits=TRUE; + if (ISTOKENCHAR(ch)) { + while ( (ISTOKENCHAR(ch)) && len<maxlen-1 ) { + if (!isdigit(ch)) digits=FALSE; + *p++ = ch; + len++; + ch = fGetChar(fp); + }; + *p = '\0'; + + if (ch!=EOF) { + fUngetChar(ch,fp); + } + if (digits) { + return(GTOK_NUMBER); + } else { + return(GTOK_STRING); + } + } + + /* + * Neither a quoted string nor a token character. Return a string + * with just that one character in it. + */ + if (ch==EOF) { + return(GTOK_EOF); + } + if (!ISWHITESPACE(ch)) { + *p++ = ch; + *p='\0'; + } else { + *p++ = ' '; /* white space is always the + * blank character */ + *p='\0'; + /* + * The character is a white space. Flush all additional white + * space. + */ + while (ISWHITESPACE(ch) && ((ch=fGetChar(fp)) != EOF)) + ; + if (ch!=EOF) { + fUngetChar(ch,fp); + } + return(GTOK_WHITE); + } + return(GTOK_PUNK); +} + +/* + * fGetLiteral is called after we find a '\' in the input stream. A + * string of numbers following the backslash are converted to the + * appropriate value; hex (0xn), octal (0n), and decimal (otherwise) + * are all supported. If the char after the \ is not a number, we + * special case certain values (\n, \f, \r, \b) or return a literal + * otherwise (useful for \", for example). + */ +fGetLiteral(fp) + FILE *fp; +{ + int ch; + int n=0; + int base; + + ch = fGetChar(fp); + + if (!isdigit(ch)) { + switch (ch) { + case 'n': return('\n'); + case 'f': return('\f'); + case 'r': return('\r'); + case 'b': return('\b'); + default: return(ch); + } + } + + /* + * got a number. might be decimal (no prefix), octal (prefix 0), + * or hexadecimal (prefix 0x). Set the base appropriately. + */ + if (ch!='0') { + base=10; /* its a decimal number */ + } else { + /* + * found a zero, its either hex or octal + */ + ch = fGetChar(fp); + if ((ch!='x') && (ch!='X')) { + base=010; + } else { + ch = fGetChar(fp); + base=0x10; + } + } + + switch (base) { + + case 010: /* octal */ + while (ISOCTAL(ch)) { + n = (n*base) + ch - '0'; + ch = fGetChar(fp); + } + break; + + case 10: /* decimal */ + while (isdigit(ch)) { + n = (n*base) + ch - '0'; + ch = fGetChar(fp); + } + break; + case 0x10: /* hexadecimal */ + while (isxdigit(ch)) { + if (isdigit(ch)) { + n = (n*base) + ch - '0'; + } else { + n = (n*base) + toupper(ch) - 'A' + 0xA ; + } + ch = fGetChar(fp); + } + break; + default: + fprintf(stderr,"fGetLiteral() died real bad. Fix gettoken.c."); + exit(1); + break; + } + fUngetChar(ch,fp); + return(n); +} + +/* + * exactly the same as ungetc(3) except that the line number of the + * input file is maintained. + */ +fUngetChar(ch,fp) + int ch; + FILE *fp; +{ + if (ch=='\n') LineNbr--; + return(ungetc(ch,fp)); +} + + +/* + * exactly the same as fgetc(3) except that the line number of the + * input file is maintained. + */ +fGetChar(fp) + FILE *fp; +{ + int ch = fgetc(fp); + if (ch=='\n') LineNbr++; + return(ch); +} + + +/* + * Routine Name: strsave + * + * Function: return a pointer to a saved copy of the + * input string. the copy will be allocated + * as large as necessary. + * + * Explicit Parameters: pointer to string to save + * + * Implicit Parameters: None + * + * External Procedures: malloc,strcpy,strlen + * + * Side Effects: None + * + * Return Value: pointer to copied string + * + */ +char * strsave(p) + char *p; +{ + return(strcpy(malloc(strlen(p)+1),p)); +} + + +/* + * strutol changes all characters in a string to lower case, in place. + * the pointer to the beginning of the string is returned. + */ + +char * strutol( start ) + char *start; +{ + char *q; + for (q=start; *q; q++) + if (isupper(*q)) + *q=tolower(*q); + return(start); +} + +#ifdef GTOK_TEST /* mainline test routine for fGetToken() */ + +#define MAXTOKEN 100 + +char *pgm = "gettoken"; + +main(argc,argv) + int argc; + char **argv; +{ + char *p; + int type; + FILE *fp; + + if (--argc) { + fp = fopen(*++argv,"ra"); + if (fp == (FILE *)NULL) { + fprintf(stderr,"can\'t open \"%s\"\n",*argv); + } + } else + fp = stdin; + + p = malloc(MAXTOKEN); + while (type = fGetToken(fp,p,MAXTOKEN)) { + switch(type) { + case GTOK_BAD_QSTRING: + printf("BAD QSTRING!\t"); + break; + case GTOK_EOF: + printf("EOF!\t"); + break; + case GTOK_QSTRING: + printf("QSTRING\t"); + break; + case GTOK_STRING: + printf("STRING\t"); + break; + case GTOK_NUMBER: + printf("NUMBER\t"); + break; + case GTOK_PUNK: + printf("PUNK\t"); + break; + case GTOK_WHITE: + printf("WHITE\t"); + break; + default: + printf("HUH?\t"); + break; + } + if (*p=='\n') + printf("\\n\n"); + else + printf("%s\n",p); + } + exit(0); +} +#endif + +#ifdef KVTEST + +main(argc,argv) + int argc; + char **argv; +{ + int rc,ch; + FILE *fp; + char key[MAXKEY],valu[MAXVALUE]; + char *filename; + + if (argc != 2) { + fprintf(stderr,"usage: test <filename>\n"); + exit(1); + } + + if (!(fp=fopen(*++argv,"r"))) { + fprintf(stderr,"can\'t open input file \"%s\"\n",filename); + exit(1); + } + filename = *argv; + + while ((rc=fGetKeywordValue(fp,key,MAXKEY,valu,MAXVALUE))!=KV_EOF){ + + switch (rc) { + + case KV_EOL: + printf("%s, line %d: nada mas.\n",filename,LineNbr-1); + break; + + case KV_SYNTAX: + printf("%s, line %d: syntax error: %s\n", + filename,LineNbr,ErrorMsg); + while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') ); + break; + + case KV_OKAY: + printf("%s, line %d: okay, %s=\"%s\"\n", + filename,LineNbr,key,valu); + break; + + default: + printf("panic: bad return (%d) from fGetKeywordValue\n",rc); + break; + } + } + printf("EOF"); + fclose(fp); + exit(0); +} +#endif + +#ifdef PSTEST + +parmtable kparm[] = { + /* keyword, default, found value */ + { "user", "", (char *)NULL }, + { "realm", "Athena", (char *)NULL }, + { "instance", "", (char *)NULL } +}; + +main(argc,argv) + int argc; + char **argv; +{ + int rc,i,ch; + FILE *fp; + char *filename; + + if (argc != 2) { + fprintf(stderr,"usage: test <filename>\n"); + exit(1); + } + + if (!(fp=fopen(*++argv,"r"))) { + fprintf(stderr,"can\'t open input file \"%s\"\n",filename); + exit(1); + } + filename = *argv; + + while ((rc=fGetParameterSet(fp,kparm,PARMCOUNT(kparm))) != PS_EOF) { + + switch (rc) { + + case PS_BAD_KEYWORD: + printf("%s, line %d: %s\n",filename,LineNbr,ErrorMsg); + while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') ); + break; + + case PS_SYNTAX: + printf("%s, line %d: syntax error: %s\n", + filename,LineNbr,ErrorMsg); + while ( ((ch=fGetChar(fp))!=EOF) && (ch!='\n') ); + break; + + case PS_OKAY: + printf("%s, line %d: valid parameter set found:\n", + filename,LineNbr-1); + for (i=0; i<PARMCOUNT(kparm); i++) { + printf("\t%s = \"%s\"\n",kparm[i].keyword, + (kparm[i].value ? kparm[i].value + : kparm[i].defvalue)); + } + break; + + default: + printf("panic: bad return (%d) from fGetParameterSet\n",rc); + break; + } + FreeParameterSet(kparm,PARMCOUNT(kparm)); + } + printf("EOF"); + fclose(fp); + exit(0); +} +#endif diff --git a/eBones/krb/krb_err.et b/eBones/krb/krb_err.et new file mode 100644 index 0000000..2c6830b --- /dev/null +++ b/eBones/krb/krb_err.et @@ -0,0 +1,257 @@ +# Copyright 1987,1988 Massachusetts Institute of Technology +# For copying and distribution information, see the file +# "Copyright.MIT". +# +# from: krb_err.et,v 4.1 89/09/26 09:24:20 jtkohl Exp $ +# $Id: krb_err.et,v 1.2 1994/07/19 19:25:44 g89r4222 Exp $ +# + error_table krb + + ec KRBET_KSUCCESS, + "Kerberos successful" + + ec KRBET_KDC_NAME_EXP, + "Kerberos principal expired" + + ec KRBET_KDC_SERVICE_EXP, + "Kerberos service expired" + + ec KRBET_KDC_AUTH_EXP, + "Kerberos auth expired" + + ec KRBET_KDC_PKT_VER, + "Incorrect kerberos master key version" + + ec KRBET_KDC_P_MKEY_VER, + "Incorrect kerberos master key version" + + ec KRBET_KDC_S_MKEY_VER, + "Incorrect kerberos master key version" + + ec KRBET_KDC_BYTE_ORDER, + "Kerberos error: byte order unknown" + + ec KRBET_KDC_PR_UNKNOWN, + "Kerberos principal unknown" + + ec KRBET_KDC_PR_N_UNIQUE, + "Kerberos principal not unique" + + ec KRBET_KDC_NULL_KEY, + "Kerberos principal has null key" + + ec KRBET_KRB_RES11, + "Reserved 11" + + ec KRBET_KRB_RES12, + "Reserved 12" + + ec KRBET_KRB_RES13, + "Reserved 13" + + ec KRBET_KRB_RES14, + "Reserved 14" + + ec KRBET_KRB_RES15, + "Reserved 15" + + ec KRBET_KRB_RES16, + "Reserved 16" + + ec KRBET_KRB_RES17, + "Reserved 17" + + ec KRBET_KRB_RES18, + "Reserved 18" + + ec KRBET_KRB_RES19, + "Reserved 19" + + ec KRBET_KDC_GEN_ERR, + "Generic error from Kerberos KDC" + + ec KRBET_GC_TKFIL, + "Can't read Kerberos ticket file" + + ec KRBET_GC_NOTKT, + "Can't find Kerberos ticket or TGT" + + ec KRBET_KRB_RES23, + "Reserved 23" + + ec KRBET_KRB_RES24, + "Reserved 24" + + ec KRBET_KRB_RES25, + "Reserved 25" + + ec KRBET_MK_AP_TGTEXP, + "Kerberos TGT Expired" + + ec KRBET_KRB_RES27, + "Reserved 27" + + ec KRBET_KRB_RES28, + "Reserved 28" + + ec KRBET_KRB_RES29, + "Reserved 29" + + ec KRBET_KRB_RES30, + "Reserved 30" + + ec KRBET_RD_AP_UNDEC, + "Kerberos error: Can't decode authenticator" + + ec KRBET_RD_AP_EXP, + "Kerberos ticket expired" + + ec KRBET_RD_AP_NYV, + "Kerberos ticket not yet valid" + + ec KRBET_RD_AP_REPEAT, + "Kerberos error: Repeated request" + + ec KRBET_RD_AP_NOT_US, + "The kerberos ticket isn't for us" + + ec KRBET_RD_AP_INCON, + "Kerberos request inconsistent" + + ec KRBET_RD_AP_TIME, + "Kerberos error: delta_t too big" + + ec KRBET_RD_AP_BADD, + "Kerberos error: incorrect net address" + + ec KRBET_RD_AP_VERSION, + "Kerberos protocol version mismatch" + + ec KRBET_RD_AP_MSG_TYPE, + "Kerberos error: invalid msg type" + + ec KRBET_RD_AP_MODIFIED, + "Kerberos error: message stream modified" + + ec KRBET_RD_AP_ORDER, + "Kerberos error: message out of order" + + ec KRBET_RD_AP_UNAUTHOR, + "Kerberos error: unauthorized request" + + ec KRBET_KRB_RES44, + "Reserved 44" + + ec KRBET_KRB_RES45, + "Reserved 45" + + ec KRBET_KRB_RES46, + "Reserved 46" + + ec KRBET_KRB_RES47, + "Reserved 47" + + ec KRBET_KRB_RES48, + "Reserved 48" + + ec KRBET_KRB_RES49, + "Reserved 49" + + ec KRBET_KRB_RES50, + "Reserved 50" + + ec KRBET_GT_PW_NULL, + "Kerberos error: current PW is null" + + ec KRBET_GT_PW_BADPW, + "Kerberos error: Incorrect current password" + + ec KRBET_GT_PW_PROT, + "Kerberos protocol error" + + ec KRBET_GT_PW_KDCERR, + "Error returned by Kerberos KDC" + + ec KRBET_GT_PW_NULLTKT, + "Null Kerberos ticket returned by KDC" + + ec KRBET_SKDC_RETRY, + "Kerberos error: Retry count exceeded" + + ec KRBET_SKDC_CANT, + "Kerberos error: Can't send request" + + ec KRBET_KRB_RES58, + "Reserved 58" + + ec KRBET_KRB_RES59, + "Reserved 59" + + ec KRBET_KRB_RES60, + "Reserved 60" + + ec KRBET_INTK_W_NOTALL, + "Kerberos error: not all tickets returned" + + ec KRBET_INTK_BADPW, + "Kerberos error: incorrect password" + + ec KRBET_INTK_PROT, + "Kerberos error: Protocol Error" + + ec KRBET_KRB_RES64, + "Reserved 64" + + ec KRBET_KRB_RES65, + "Reserved 65" + + ec KRBET_KRB_RES66, + "Reserved 66" + + ec KRBET_KRB_RES67, + "Reserved 67" + + ec KRBET_KRB_RES68, + "Reserved 68" + + ec KRBET_KRB_RES69, + "Reserved 69" + + ec KRBET_INTK_ERR, + "Other error" + + ec KRBET_AD_NOTGT, + "Don't have Kerberos ticket-granting ticket" + + ec KRBET_KRB_RES72, + "Reserved 72" + + ec KRBET_KRB_RES73, + "Reserved 73" + + ec KRBET_KRB_RES74, + "Reserved 74" + + ec KRBET_KRB_RES75, + "Reserved 75" + + ec KRBET_NO_TKT_FIL, + "No ticket file found" + + ec KRBET_TKT_FIL_ACC, + "Couldn't access ticket file" + + ec KRBET_TKT_FIL_LCK, + "Couldn't lock ticket file" + + ec KRBET_TKT_FIL_FMT, + "Bad ticket file format" + + ec KRBET_TKT_FIL_INI, + "tf_init not called first" + + ec KRBET_KNAME_FMT, + "Bad Kerberos name format" + + end + diff --git a/eBones/krb/krb_err_txt.c b/eBones/krb/krb_err_txt.c new file mode 100644 index 0000000..785563f --- /dev/null +++ b/eBones/krb/krb_err_txt.c @@ -0,0 +1,278 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: krb_err_txt.c,v 4.7 88/12/01 14:10:14 jtkohl Exp $ + * $Id: krb_err_txt.c,v 1.2 1994/07/19 19:25:45 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: krb_err_txt.c,v 1.2 1994/07/19 19:25:45 g89r4222 Exp $"; +#endif lint + +/* + * This file contains an array of error text strings. + * The associated error codes (which are defined in "krb.h") + * follow the string in the comments at the end of each line. + */ + +char *krb_err_txt[256] = { + "OK", /* 000 */ + "Principal expired (kerberos)", /* 001 */ + "Service expired (kerberos)", /* 002 */ + "Authentication expired (kerberos)", /* 003 */ + "Unknown protocol version number (kerberos)", /* 004 */ + "Principal: Incorrect master key version (kerberos)", /* 005 */ + "Service: Incorrect master key version (kerberos)", /* 006 */ + "Bad byte order (kerberos)", /* 007 */ + "Principal unknown (kerberos)", /* 008 */ + "Principal not unique (kerberos)", /* 009 */ + "Principal has null key (kerberos)", /* 010 */ + "Reserved error message 11 (kerberos)", /* 011 */ + "Reserved error message 12 (kerberos)", /* 012 */ + "Reserved error message 13 (kerberos)", /* 013 */ + "Reserved error message 14 (kerberos)", /* 014 */ + "Reserved error message 15 (kerberos)", /* 015 */ + "Reserved error message 16 (kerberos)", /* 016 */ + "Reserved error message 17 (kerberos)", /* 017 */ + "Reserved error message 18 (kerberos)", /* 018 */ + "Reserved error message 19 (kerberos)", /* 019 */ + "Permission Denied (kerberos)", /* 020 */ + "Can't read ticket file (krb_get_cred)", /* 021 */ + "Can't find ticket (krb_get_cred)", /* 022 */ + "Reserved error message 23 (krb_get_cred)", /* 023 */ + "Reserved error message 24 (krb_get_cred)", /* 024 */ + "Reserved error message 25 (krb_get_cred)", /* 025 */ + "Ticket granting ticket expired (krb_mk_req)", /* 026 */ + "Reserved error message 27 (krb_mk_req)", /* 027 */ + "Reserved error message 28 (krb_mk_req)", /* 028 */ + "Reserved error message 29 (krb_mk_req)", /* 029 */ + "Reserved error message 30 (krb_mk_req)", /* 030 */ + "Can't decode authenticator (krb_rd_req)", /* 031 */ + "Ticket expired (krb_rd_req)", /* 032 */ + "Ticket issue date too far in the future (krb_rd_req)",/* 033 */ + "Repeat request (krb_rd_req)", /* 034 */ + "Ticket for wrong server (krb_rd_req)", /* 035 */ + "Request inconsistent (krb_rd_req)", /* 036 */ + "Time is out of bounds (krb_rd_req)", /* 037 */ + "Incorrect network address (krb_rd_req)", /* 038 */ + "Protocol version mismatch (krb_rd_req)", /* 039 */ + "Illegal message type (krb_rd_req)", /* 040 */ + "Message integrity error (krb_rd_req)", /* 041 */ + "Message duplicate or out of order (krb_rd_req)", /* 042 */ + "Unauthorized request (krb_rd_req)", /* 043 */ + "Reserved error message 44 (krb_rd_req)", /* 044 */ + "Reserved error message 45 (krb_rd_req)", /* 045 */ + "Reserved error message 46 (krb_rd_req)", /* 046 */ + "Reserved error message 47 (krb_rd_req)", /* 047 */ + "Reserved error message 48 (krb_rd_req)", /* 048 */ + "Reserved error message 49 (krb_rd_req)", /* 049 */ + "Reserved error message 50 (krb_rd_req)", /* 050 */ + "Current password is NULL (get_pw_tkt)", /* 051 */ + "Current password incorrect (get_pw_tkt)", /* 052 */ + "Protocol error (gt_pw_tkt)", /* 053 */ + "Error returned by KDC (gt_pw_tkt)", /* 054 */ + "Null ticket returned by KDC (gt_pw_tkt)", /* 055 */ + "Retry count exceeded (send_to_kdc)", /* 056 */ + "Can't send request (send_to_kdc)", /* 057 */ + "Reserved error message 58 (send_to_kdc)", /* 058 */ + "Reserved error message 59 (send_to_kdc)", /* 059 */ + "Reserved error message 60 (send_to_kdc)", /* 060 */ + "Warning: Not ALL tickets returned", /* 061 */ + "Password incorrect", /* 062 */ + "Protocol error (get_intkt)", /* 063 */ + "Reserved error message 64 (get_in_tkt)", /* 064 */ + "Reserved error message 65 (get_in_tkt)", /* 065 */ + "Reserved error message 66 (get_in_tkt)", /* 066 */ + "Reserved error message 67 (get_in_tkt)", /* 067 */ + "Reserved error message 68 (get_in_tkt)", /* 068 */ + "Reserved error message 69 (get_in_tkt)", /* 069 */ + "Generic error (get_intkt)", /* 070 */ + "Don't have ticket granting ticket (get_ad_tkt)", /* 071 */ + "Reserved error message 72 (get_ad_tkt)", /* 072 */ + "Reserved error message 73 (get_ad_tkt)", /* 073 */ + "Reserved error message 74 (get_ad_tkt)", /* 074 */ + "Reserved error message 75 (get_ad_tkt)", /* 075 */ + "No ticket file (tf_util)", /* 076 */ + "Can't access ticket file (tf_util)", /* 077 */ + "Can't lock ticket file; try later (tf_util)", /* 078 */ + "Bad ticket file format (tf_util)", /* 079 */ + "Read ticket file before tf_init (tf_util)", /* 080 */ + "Bad Kerberos name format (kname_parse)", /* 081 */ + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "(reserved)", + "Generic kerberos error (kfailure)", /* 255 */ +}; diff --git a/eBones/krb/krb_get_in_tkt.c b/eBones/krb/krb_get_in_tkt.c new file mode 100644 index 0000000..a37bb60 --- /dev/null +++ b/eBones/krb/krb_get_in_tkt.c @@ -0,0 +1,297 @@ +/* + * Copyright 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: der: krb_get_in_tkt.c,v 4.19 89/07/18 16:31:31 jtkohl Exp $ + * $Id: krb_get_in_tkt.c,v 1.2 1994/07/19 19:25:47 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: krb_get_in_tkt.c,v 1.2 1994/07/19 19:25:47 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <des.h> +#include <prot.h> + +#include <stdio.h> +#include <strings.h> +#include <errno.h> + +/* use the bsd time.h struct defs for PC too! */ +#include <sys/time.h> +#include <sys/types.h> + +int swap_bytes; + +/* + * decrypt_tkt(): Given user, instance, realm, passwd, key_proc + * and the cipher text sent from the KDC, decrypt the cipher text + * using the key returned by key_proc. + */ + +static int decrypt_tkt(user, instance, realm, arg, key_proc, cipp) + char *user; + char *instance; + char *realm; + char *arg; + int (*key_proc)(); + KTEXT *cipp; +{ + KTEXT cip = *cipp; + C_Block key; /* Key for decrypting cipher */ + Key_schedule key_s; + +#ifndef NOENCRYPTION + /* Attempt to decrypt it */ +#endif + + /* generate a key */ + + { + register int rc; + rc = (*key_proc)(user,instance,realm,arg,key); + if (rc) + return(rc); + } + +#ifndef NOENCRYPTION + key_sched(key,key_s); + pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat, + (long) cip->length,key_s,key,DES_DECRYPT); +#endif /* !NOENCRYPTION */ + /* Get rid of all traces of key */ + bzero((char *)key,sizeof(key)); + bzero((char *)key_s,sizeof(key_s)); + + return(0); +} + +/* + * krb_get_in_tkt() gets a ticket for a given principal to use a given + * service and stores the returned ticket and session key for future + * use. + * + * The "user", "instance", and "realm" arguments give the identity of + * the client who will use the ticket. The "service" and "sinstance" + * arguments give the identity of the server that the client wishes + * to use. (The realm of the server is the same as the Kerberos server + * to whom the request is sent.) The "life" argument indicates the + * desired lifetime of the ticket; the "key_proc" argument is a pointer + * to the routine used for getting the client's private key to decrypt + * the reply from Kerberos. The "decrypt_proc" argument is a pointer + * to the routine used to decrypt the reply from Kerberos; and "arg" + * is an argument to be passed on to the "key_proc" routine. + * + * If all goes well, krb_get_in_tkt() returns INTK_OK, otherwise it + * returns an error code: If an AUTH_MSG_ERR_REPLY packet is returned + * by Kerberos, then the error code it contains is returned. Other + * error codes returned by this routine include INTK_PROT to indicate + * wrong protocol version, INTK_BADPW to indicate bad password (if + * decrypted ticket didn't make sense), INTK_ERR if the ticket was for + * the wrong server or the ticket store couldn't be initialized. + * + * The format of the message sent to Kerberos is as follows: + * + * Size Variable Field + * ---- -------- ----- + * + * 1 byte KRB_PROT_VERSION protocol version number + * 1 byte AUTH_MSG_KDC_REQUEST | message type + * HOST_BYTE_ORDER local byte order in lsb + * string user client's name + * string instance client's instance + * string realm client's realm + * 4 bytes tlocal.tv_sec timestamp in seconds + * 1 byte life desired lifetime + * string service service's name + * string sinstance service's instance + */ + +krb_get_in_tkt(user, instance, realm, service, sinstance, life, + key_proc, decrypt_proc, arg) + char *user; + char *instance; + char *realm; + char *service; + char *sinstance; + int life; + int (*key_proc)(); + int (*decrypt_proc)(); + char *arg; +{ + KTEXT_ST pkt_st; + KTEXT pkt = &pkt_st; /* Packet to KDC */ + KTEXT_ST rpkt_st; + KTEXT rpkt = &rpkt_st; /* Returned packet */ + KTEXT_ST cip_st; + KTEXT cip = &cip_st; /* Returned Ciphertext */ + KTEXT_ST tkt_st; + KTEXT tkt = &tkt_st; /* Current ticket */ + C_Block ses; /* Session key for tkt */ + int kvno; /* Kvno for session key */ + unsigned char *v = pkt->dat; /* Prot vers no */ + unsigned char *t = (pkt->dat+1); /* Prot msg type */ + + char s_name[SNAME_SZ]; + char s_instance[INST_SZ]; + char rlm[REALM_SZ]; + int lifetime; + int msg_byte_order; + int kerror; + unsigned long exp_date; + char *ptr; + + struct timeval t_local; + + unsigned long rep_err_code; + + unsigned long kdc_time; /* KDC time */ + + /* BUILD REQUEST PACKET */ + + /* Set up the fixed part of the packet */ + *v = (unsigned char) KRB_PROT_VERSION; + *t = (unsigned char) AUTH_MSG_KDC_REQUEST; + *t |= HOST_BYTE_ORDER; + + /* Now for the variable info */ + (void) strcpy((char *)(pkt->dat+2),user); /* aname */ + pkt->length = 3 + strlen(user); + (void) strcpy((char *)(pkt->dat+pkt->length), + instance); /* instance */ + pkt->length += 1 + strlen(instance); + (void) strcpy((char *)(pkt->dat+pkt->length),realm); /* realm */ + pkt->length += 1 + strlen(realm); + + (void) gettimeofday(&t_local,(struct timezone *) 0); + /* timestamp */ + bcopy((char *)&(t_local.tv_sec),(char *)(pkt->dat+pkt->length), 4); + pkt->length += 4; + + *(pkt->dat+(pkt->length)++) = (char) life; + (void) strcpy((char *)(pkt->dat+pkt->length),service); + pkt->length += 1 + strlen(service); + (void) strcpy((char *)(pkt->dat+pkt->length),sinstance); + pkt->length += 1 + strlen(sinstance); + + rpkt->length = 0; + + /* SEND THE REQUEST AND RECEIVE THE RETURN PACKET */ + + if (kerror = send_to_kdc(pkt, rpkt, realm)) return(kerror); + + /* check packet version of the returned packet */ + if (pkt_version(rpkt) != KRB_PROT_VERSION) + return(INTK_PROT); + + /* Check byte order */ + msg_byte_order = pkt_msg_type(rpkt) & 1; + swap_bytes = 0; + if (msg_byte_order != HOST_BYTE_ORDER) { + swap_bytes++; + } + + switch (pkt_msg_type(rpkt) & ~1) { + case AUTH_MSG_KDC_REPLY: + break; + case AUTH_MSG_ERR_REPLY: + bcopy(pkt_err_code(rpkt),(char *) &rep_err_code,4); + if (swap_bytes) swap_u_long(rep_err_code); + return((int)rep_err_code); + default: + return(INTK_PROT); + } + + /* EXTRACT INFORMATION FROM RETURN PACKET */ + + /* get the principal's expiration date */ + bcopy(pkt_x_date(rpkt),(char *) &exp_date,sizeof(exp_date)); + if (swap_bytes) swap_u_long(exp_date); + + /* Extract the ciphertext */ + cip->length = pkt_clen(rpkt); /* let clen do the swap */ + + if ((cip->length < 0) || (cip->length > sizeof(cip->dat))) + return(INTK_ERR); /* no appropriate error code + currently defined for INTK_ */ + /* copy information from return packet into "cip" */ + bcopy((char *) pkt_cipher(rpkt),(char *)(cip->dat),cip->length); + + /* Attempt to decrypt the reply. */ + if (decrypt_proc == NULL) + decrypt_proc = decrypt_tkt; + (*decrypt_proc)(user, instance, realm, arg, key_proc, &cip); + + ptr = (char *) cip->dat; + + /* extract session key */ + bcopy(ptr,(char *)ses,8); + ptr += 8; + + if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length) + return(INTK_BADPW); + + /* extract server's name */ + (void) strcpy(s_name,ptr); + ptr += strlen(s_name) + 1; + + if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length) + return(INTK_BADPW); + + /* extract server's instance */ + (void) strcpy(s_instance,ptr); + ptr += strlen(s_instance) + 1; + + if ((strlen(ptr) + (ptr - (char *) cip->dat)) > cip->length) + return(INTK_BADPW); + + /* extract server's realm */ + (void) strcpy(rlm,ptr); + ptr += strlen(rlm) + 1; + + /* extract ticket lifetime, server key version, ticket length */ + /* be sure to avoid sign extension on lifetime! */ + lifetime = (unsigned char) ptr[0]; + kvno = (unsigned char) ptr[1]; + tkt->length = (unsigned char) ptr[2]; + ptr += 3; + + if ((tkt->length < 0) || + ((tkt->length + (ptr - (char *) cip->dat)) > cip->length)) + return(INTK_BADPW); + + /* extract ticket itself */ + bcopy(ptr,(char *)(tkt->dat),tkt->length); + ptr += tkt->length; + + if (strcmp(s_name, service) || strcmp(s_instance, sinstance) || + strcmp(rlm, realm)) /* not what we asked for */ + return(INTK_ERR); /* we need a better code here XXX */ + + /* check KDC time stamp */ + bcopy(ptr,(char *)&kdc_time,4); /* Time (coarse) */ + if (swap_bytes) swap_u_long(kdc_time); + + ptr += 4; + + (void) gettimeofday(&t_local,(struct timezone *) 0); + if (abs((int)(t_local.tv_sec - kdc_time)) > CLOCK_SKEW) { + return(RD_AP_TIME); /* XXX should probably be better + code */ + } + + /* initialize ticket cache */ + if (in_tkt(user,instance) != KSUCCESS) + return(INTK_ERR); + + /* stash ticket, session key, etc. for future use */ + if (kerror = save_credentials(s_name, s_instance, rlm, ses, + lifetime, kvno, tkt, t_local.tv_sec)) + return(kerror); + + return(INTK_OK); +} diff --git a/eBones/krb/krb_realmofhost.3 b/eBones/krb/krb_realmofhost.3 new file mode 100644 index 0000000..f284069 --- /dev/null +++ b/eBones/krb/krb_realmofhost.3 @@ -0,0 +1,161 @@ +.\" from: krb_realmofhost.3,v 4.1 89/01/23 11:10:47 jtkohl Exp $ +.\" $Id: krb_realmofhost.3,v 1.2 1994/07/19 19:27:46 g89r4222 Exp $ +.\" Copyright 1989 by the Massachusetts Institute of Technology. +.\" +.\" For copying and distribution information, +.\" please see the file <Copyright.MIT>. +.\" +.TH KRB_REALMOFHOST 3 "Kerberos Version 4.0" "MIT Project Athena" +.SH NAME +krb_realmofhost, krb_get_phost, krb_get_krbhst, krb_get_admhst, +krb_get_lrealm \- additional Kerberos utility routines +.SH SYNOPSIS +.nf +.nj +.ft B +#include <krb.h> +#include <des.h> +#include <netinet/in.h> +.PP +.ft B +char *krb_realmofhost(host) +char *host; +.PP +.ft B +char *krb_get_phost(alias) +char *alias; +.PP +.ft B +krb_get_krbhst(host,realm,n) +char *host; +char *realm; +int n; +.PP +.ft B +krb_get_admhst(host,realm,n) +char *host; +char *realm; +int n; +.PP +.ft B +krb_get_lrealm(realm,n) +char *realm; +int n; +.fi +.ft R +.SH DESCRIPTION +.I krb_realmofhost +returns the Kerberos realm of the host +.IR host , +as determined by the translation table +.IR /etc/krb.realms . +.I host +should be the fully-qualified domain-style primary host name of the host +in question. In order to prevent certain security attacks, this routine +must either have +.I a priori +knowledge of a host's realm, or obtain such information securely. +.PP +The format of the translation file is described by +.IR krb.realms (5). +If +.I host +exactly matches a host_name line, the corresponding realm +is returned. +Otherwise, if the domain portion of +.I host +matches a domain_name line, the corresponding realm +is returned. +If +.I host +contains a domain, but no translation is found, +.IR host 's +domain is converted to upper-case and returned. +If +.I host +contains no discernable domain, or an error occurs, +the local realm name, as supplied by +.IR krb_get_lrealm (3), +is returned. +.PP +.I krb_get_phost +converts the hostname +.I alias +(which can be either an official name or an alias) into the instance +name to be used in obtaining Kerberos tickets for most services, +including the Berkeley rcmd suite (rlogin, rcp, rsh). +.br +The current convention is to return the first segment of the official +domain-style name after conversion to lower case. +.PP +.I krb_get_krbhst +fills in +.I host +with the hostname of the +.IR n th +host running a Kerberos key distribution center (KDC) +for realm +.IR realm , +as specified in the configuration file (\fI/etc/krb.conf\fR). +The configuration file is described by +.IR krb.conf (5). +If the host is successfully filled in, the routine +returns KSUCCESS. +If the file cannot be opened, and +.I n +equals 1, then the value of KRB_HOST as defined in +.I <krb.h> +is filled in, and KSUCCESS is returned. If there are fewer than +.I n +hosts running a Kerberos KDC for the requested realm, or the +configuration file is malformed, the routine +returns KFAILURE. +.PP +.I krb_get_admhst +fills in +.I host +with the hostname of the +.IR n th +host running a Kerberos KDC database administration server +for realm +.IR realm , +as specified in the configuration file (\fI/etc/krb.conf\fR). +If the file cannot be opened or is malformed, or there are fewer than +.I n +hosts running a Kerberos KDC database administration server, +the routine returns KFAILURE. +.PP +The character arrays used as return values for +.IR krb_get_krbhst , +.IR krb_get_admhst , +should be large enough to +hold any hostname (MAXHOSTNAMELEN from <sys/param.h>). +.PP +.I krb_get_lrealm +fills in +.I realm +with the +.IR n th +realm of the local host, as specified in the configuration file. +.I realm +should be at least REALM_SZ (from +.IR <krb.h>) characters long. +.PP +.SH SEE ALSO +kerberos(3), krb.conf(5), krb.realms(5) +.SH FILES +.TP 20n +/etc/krb.realms +translation file for host-to-realm mapping. +.TP +/etc/krb.conf +local realm-name and realm/server configuration file. +.SH BUGS +The current convention for instance names is too limited; the full +domain name should be used. +.PP +.I krb_get_lrealm +currently only supports +.I n += 1. It should really consult the user's ticket cache to determine the +user's current realm, rather than consulting a file on the host. diff --git a/eBones/krb/krb_sendauth.3 b/eBones/krb/krb_sendauth.3 new file mode 100644 index 0000000..f5e95b7 --- /dev/null +++ b/eBones/krb/krb_sendauth.3 @@ -0,0 +1,348 @@ +.\" from: krb_sendauth.3,v 4.1 89/01/23 11:10:58 jtkohl Exp $ +.\" $Id: krb_sendauth.3,v 1.2 1994/07/19 19:27:47 g89r4222 Exp $ +.\" Copyright 1988 by the Massachusetts Institute of Technology. +.\" +.\" For copying and distribution information, +.\" please see the file <Copyright.MIT>. +.\" +.TH KRB_SENDAUTH 3 "Kerberos Version 4.0" "MIT Project Athena" +.SH NAME +krb_sendauth, krb_recvauth, krb_net_write, krb_net_read \- +Kerberos routines for sending authentication via network stream sockets +.SH SYNOPSIS +.nf +.nj +.ft B +#include <krb.h> +#include <des.h> +#include <netinet/in.h> +.PP +.fi +.HP 1i +.ft B +int krb_sendauth(options, fd, ktext, service, inst, realm, checksum, +msg_data, cred, schedule, laddr, faddr, version) +.nf +.RS 0 +.ft B +long options; +int fd; +KTEXT ktext; +char *service, *inst, *realm; +u_long checksum; +MSG_DAT *msg_data; +CREDENTIALS *cred; +Key_schedule schedule; +struct sockaddr_in *laddr, *faddr; +char *version; +.PP +.fi +.HP 1i +.ft B +int krb_recvauth(options, fd, ktext, service, inst, faddr, laddr, +auth_data, filename, schedule, version) +.nf +.RS 0 +.ft B +long options; +int fd; +KTEXT ktext; +char *service, *inst; +struct sockaddr_in *faddr, *laddr; +AUTH_DAT *auth_data; +char *filename; +Key_schedule schedule; +char *version; +.PP +.ft B +int krb_net_write(fd, buf, len) +int fd; +char *buf; +int len; +.PP +.ft B +int krb_net_read(fd, buf, len) +int fd; +char *buf; +int len; +.fi +.SH DESCRIPTION +.PP +These functions, +which are built on top of the core Kerberos library, +provide a convenient means for client and server +programs to send authentication messages +to one another through network connections. +The +.I krb_sendauth +function sends an authenticated ticket from the client program to +the server program by writing the ticket to a network socket. +The +.I krb_recvauth +function receives the ticket from the client by +reading from a network socket. + +.SH KRB_SENDAUTH +.PP +This function writes the ticket to +the network socket specified by the +file descriptor +.IR fd, +returning KSUCCESS if the write proceeds successfully, +and an error code if it does not. + +The +.I ktext +argument should point to an allocated KTEXT_ST structure. +The +.IR service, +.IR inst, +and +.IR realm +arguments specify the server program's Kerberos principal name, +instance, and realm. +If you are writing a client that uses the local realm exclusively, +you can set the +.I realm +argument to NULL. + +The +.I version +argument allows the client program to pass an application-specific +version string that the server program can then match against +its own version string. +The +.I version +string can be up to KSEND_VNO_LEN (see +.IR <krb.h> ) +characters in length. + +The +.I checksum +argument can be used to pass checksum information to the +server program. +The client program is responsible for specifying this information. +This checksum information is difficult to corrupt because +.I krb_sendauth +passes it over the network in encrypted form. +The +.I checksum +argument is passed as the checksum argument to +.IR krb_mk_req . + +You can set +.IR krb_sendauth's +other arguments to NULL unless you want the +client and server programs to mutually authenticate +themselves. +In the case of mutual authentication, +the client authenticates itself to the server program, +and demands that the server in turn authenticate itself to +the client. + +.SH KRB_SENDAUTH AND MUTUAL AUTHENTICATION +.PP +If you want mutual authentication, +make sure that you read all pending data from the local socket +before calling +.IR krb_sendauth. +Set +.IR krb_sendauth's +.I options +argument to +.BR KOPT_DO_MUTUAL +(this macro is defined in the +.IR krb.h +file); +make sure that the +.I laddr +argument points to +the address of the local socket, +and that +.I faddr +points to the foreign socket's network address. + +.I Krb_sendauth +fills in the other arguments-- +.IR msg_data , +.IR cred , +and +.IR schedule --before +sending the ticket to the server program. +You must, however, allocate space for these arguments +before calling the function. + +.I Krb_sendauth +supports two other options: +.BR KOPT_DONT_MK_REQ, +and +.BR KOPT_DONT_CANON. +If called with +.I options +set as KOPT_DONT_MK_REQ, +.I krb_sendauth +will not use the +.I krb_mk_req +function to retrieve the ticket from the Kerberos server. +The +.I ktext +argument must point to an existing ticket and authenticator (such as +would be created by +.IR krb_mk_req ), +and the +.IR service, +.IR inst, +and +.IR realm +arguments can be set to NULL. + +If called with +.I options +set as KOPT_DONT_CANON, +.I krb_sendauth +will not convert the service's instance to canonical form using +.IR krb_get_phost (3). + +If you want to call +.I krb_sendauth +with a multiple +.I options +specification, +construct +.I options +as a bitwise-OR of the options you want to specify. + +.SH KRB_RECVAUTH +.PP +The +.I krb_recvauth +function +reads a ticket/authenticator pair from the socket pointed to by the +.I fd +argument. +Set the +.I options +argument +as a bitwise-OR of the options desired. +Currently only KOPT_DO_MUTUAL is useful to the receiver. + +The +.I ktext +argument +should point to an allocated KTEXT_ST structure. +.I Krb_recvauth +fills +.I ktext +with the +ticket/authenticator pair read from +.IR fd , +then passes it to +.IR krb_rd_req . + +The +.I service +and +.I inst +arguments +specify the expected service and instance for which the ticket was +generated. They are also passed to +.IR krb_rd_req. +The +.I inst +argument may be set to "*" if the caller wishes +.I krb_mk_req +to fill in the instance used (note that there must be space in the +.I inst +argument to hold a full instance name, see +.IR krb_mk_req (3)). + +The +.I faddr +argument +should point to the address of the peer which is presenting the ticket. +It is also passed to +.IR krb_rd_req . + +If the client and server plan to mutually authenticate +one another, +the +.I laddr +argument +should point to the local address of the file descriptor. +Otherwise you can set this argument to NULL. + +The +.I auth_data +argument +should point to an allocated AUTH_DAT area. +It is passed to and filled in by +.IR krb_rd_req . +The checksum passed to the corresponding +.I krb_sendauth +is available as part of the filled-in AUTH_DAT area. + +The +.I filename +argument +specifies the filename +which the service program should use to obtain its service key. +.I Krb_recvauth +passes +.I filename +to the +.I krb_rd_req +function. +If you set this argument to "", +.I krb_rd_req +looks for the service key in the file +.IR /etc/srvtab. + +If the client and server are performing mutual authenication, +the +.I schedule +argument +should point to an allocated Key_schedule. +Otherwise it is ignored and may be NULL. + +The +.I version +argument should point to a character array of at least KSEND_VNO_LEN +characters. It is filled in with the version string passed by the client to +.IR krb_sendauth. +.PP +.SH KRB_NET_WRITE AND KRB_NET_READ +.PP +The +.I krb_net_write +function +emulates the write(2) system call, but guarantees that all data +specified is written to +.I fd +before returning, unless an error condition occurs. +.PP +The +.I krb_net_read +function +emulates the read(2) system call, but guarantees that the requested +amount of data is read from +.I fd +before returning, unless an error condition occurs. +.PP +.SH BUGS +.IR krb_sendauth, +.IR krb_recvauth, +.IR krb_net_write, +and +.IR krb_net_read +will not work properly on sockets set to non-blocking I/O mode. + +.SH SEE ALSO + +krb_mk_req(3), krb_rd_req(3), krb_get_phost(3) + +.SH AUTHOR +John T. Kohl, MIT Project Athena +.SH RESTRICTIONS +Copyright 1988, Massachusetts Instititute of Technology. +For copying and distribution information, +please see the file <mit-copyright.h>. diff --git a/eBones/krb/krb_set_tkt_string.3 b/eBones/krb/krb_set_tkt_string.3 new file mode 100644 index 0000000..c9f3dcf --- /dev/null +++ b/eBones/krb/krb_set_tkt_string.3 @@ -0,0 +1,43 @@ +.\" from: krb_set_tkt_string.3,v 4.1 89/01/23 11:11:09 jtkohl Exp $ +.\" $Id: krb_set_tkt_string.3,v 1.2 1994/07/19 19:27:49 g89r4222 Exp $ +.\" Copyright 1989 by the Massachusetts Institute of Technology. +.\" +.\" For copying and distribution information, +.\" please see the file <Copyright.MIT>. +.\" +.TH KRB_SET_TKT_STRING 3 "Kerberos Version 4.0" "MIT Project Athena" +.SH NAME +krb_set_tkt_string \- set Kerberos ticket cache file name +.SH SYNOPSIS +.nf +.nj +.ft B +#include <krb.h> +.PP +.ft B +void krb_set_tkt_string(filename) +char *filename; +.fi +.ft R +.SH DESCRIPTION +.I krb_set_tkt_string +sets the name of the file that holds the user's +cache of Kerberos server tickets and associated session keys. +.PP +The string +.I filename +passed in is copied into local storage. +Only MAXPATHLEN-1 (see <sys/param.h>) characters of the filename are +copied in for use as the cache file name. +.PP +This routine should be called during initialization, before other +Kerberos routines are called; otherwise the routines which fetch the +ticket cache file name may be called and return an undesired ticket file +name until this routine is called. +.SH FILES +.TP 20n +/tmp/tkt[uid] +default ticket file name, unless the environment variable KRBTKFILE is set. +[uid] denotes the user's uid, in decimal. +.SH SEE ALSO +kerberos(3), setenv(3) diff --git a/eBones/krb/krbglue.c b/eBones/krb/krbglue.c new file mode 100644 index 0000000..8e864c1 --- /dev/null +++ b/eBones/krb/krbglue.c @@ -0,0 +1,252 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: krbglue.c,v 4.1 89/01/23 15:51:50 wesommer Exp $ + * $Id: krbglue.c,v 1.2 1994/07/19 19:25:49 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +$Id: krbglue.c,v 1.2 1994/07/19 19:25:49 g89r4222 Exp $"; +#endif lint + +#ifndef NCOMPAT +/* + * glue together new libraries and old clients + */ + +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include "des.h" +#include "krb.h" + +/* These definitions should be in krb.h, no? */ +#if defined(__HIGHC__) +#undef __STDC__ +#endif +#ifdef __STDC__ +extern int krb_mk_req (KTEXT, char *, char *, char *, long); +extern int krb_rd_req (KTEXT, char *, char *, long, AUTH_DAT *, char *); +extern int krb_kntoln (AUTH_DAT *, char *); +extern int krb_set_key (char *, int); +extern int krb_get_cred (char *, char *, char *, CREDENTIALS *); +extern long krb_mk_priv (u_char *, u_char *, u_long, Key_schedule, + C_Block, struct sockaddr_in *, + struct sockaddr_in *); +extern long krb_rd_priv (u_char *, u_long, Key_schedule, + C_Block, struct sockaddr_in *, + struct sockaddr_in *, MSG_DAT *); +extern long krb_mk_safe (u_char *, u_char *, u_long, C_Block *, + struct sockaddr_in *, struct sockaddr_in *); +extern long krb_rd_safe (u_char *, u_long, C_Block *, + struct sockaddr_in *, struct sockaddr_in *, + MSG_DAT *); +extern long krb_mk_err (u_char *, long, char *); +extern int krb_rd_err (u_char *, u_long, long *, MSG_DAT *); +extern int krb_get_pw_in_tkt (char *, char *, char *, char *, char *, int, + char *); +extern int krb_get_svc_in_tkt (char *, char *, char *, char *, char *, int, + char *); +extern int krb_get_pw_tkt (char *, char *, char *, char *); +extern int krb_get_lrealm (char *, char *); +extern int krb_realmofhost (char *); +extern char *krb_get_phost (char *); +extern int krb_get_krbhst (char *, char *, int); +#ifdef DEBUG +extern KTEXT krb_create_death_packet (char *); +#endif /* DEBUG */ +#else +extern int krb_mk_req (); +extern int krb_rd_req (); +extern int krb_kntoln (); +extern int krb_set_key (); +extern int krb_get_cred (); +extern long krb_mk_priv (); +extern long krb_rd_priv (); +extern long krb_mk_safe (); +extern long krb_rd_safe (); +extern long krb_mk_err (); +extern int krb_rd_err (); +extern int krb_get_pw_in_tkt (); +extern int krb_get_svc_in_tkt (); +extern int krb_get_pw_tkt (); +extern int krb_get_lrealm (); +extern int krb_realmofhost (); +extern char *krb_get_phost (); +extern int krb_get_krbhst (); +#ifdef DEBUG +extern KTEXT krb_create_death_packet (); +#endif /* DEBUG */ +#endif /* STDC */ +int mk_ap_req(authent, service, instance, realm, checksum) + KTEXT authent; + char *service, *instance, *realm; + u_long checksum; +{ + return krb_mk_req(authent,service,instance,realm,checksum); +} + +int rd_ap_req(authent, service, instance, from_addr, ad, fn) + KTEXT authent; + char *service, *instance; + u_long from_addr; + AUTH_DAT *ad; + char *fn; +{ + return krb_rd_req(authent,service,instance,from_addr,ad,fn); +} + +int an_to_ln(ad, lname) + AUTH_DAT *ad; + char *lname; +{ + return krb_kntoln (ad,lname); +} + +int set_serv_key (key, cvt) + char *key; + int cvt; +{ + return krb_set_key(key,cvt); +} + +int get_credentials (svc,inst,rlm,cred) + char *svc, *inst, *rlm; + CREDENTIALS *cred; +{ + return krb_get_cred (svc, inst, rlm, cred); +} + +long mk_private_msg (in,out,in_length,schedule,key,sender,receiver) + u_char *in, *out; + u_long in_length; + Key_schedule schedule; + C_Block key; + struct sockaddr_in *sender, *receiver; +{ + return krb_mk_priv (in,out,in_length,schedule,key,sender,receiver); +} + +long rd_private_msg (in,in_length,schedule,key,sender,receiver,msg_data) + u_char *in; + u_long in_length; + Key_schedule schedule; + C_Block key; + struct sockaddr_in *sender, *receiver; + MSG_DAT *msg_data; +{ + return krb_rd_priv (in,in_length,schedule,key,sender,receiver,msg_data); +} + +long mk_safe_msg (in,out,in_length,key,sender,receiver) + u_char *in, *out; + u_long in_length; + C_Block *key; + struct sockaddr_in *sender, *receiver; +{ + return krb_mk_safe (in,out,in_length,key,sender,receiver); +} + +long rd_safe_msg (in,length,key,sender,receiver,msg_data) + u_char *in; + u_long length; + C_Block *key; + struct sockaddr_in *sender, *receiver; + MSG_DAT *msg_data; +{ + return krb_rd_safe (in,length,key,sender,receiver,msg_data); +} + +long mk_appl_err_msg (out,code,string) + u_char *out; + long code; + char *string; +{ + return krb_mk_err (out,code,string); +} + +long rd_appl_err_msg (in,length,code,msg_data) + u_char *in; + u_long length; + long *code; + MSG_DAT *msg_data; +{ + return krb_rd_err (in,length,code,msg_data); +} + +int get_in_tkt(user,instance,realm,service,sinstance,life,password) + char *user, *instance, *realm, *service, *sinstance; + int life; + char *password; +{ + return krb_get_pw_in_tkt(user,instance,realm,service,sinstance, + life,password); +} + +int get_svc_in_tkt(user, instance, realm, service, sinstance, life, srvtab) + char *user, *instance, *realm, *service, *sinstance; + int life; + char *srvtab; +{ + return krb_get_svc_in_tkt(user, instance, realm, service, sinstance, + life, srvtab); +} + +int get_pw_tkt(user,instance,realm,cpw) + char *user; + char *instance; + char *realm; + char *cpw; +{ + return krb_get_pw_tkt(user,instance,realm,cpw); +} + +int +get_krbrlm (r, n) +char *r; +int n; +{ + return krb_get_lream(r,n); +} + +int +krb_getrealm (host) +{ + return krb_realmofhost(host); +} + +char * +get_phost (host) +char *host +{ + return krb_get_phost(host); +} + +int +get_krbhst (h, r, n) +char *h; +char *r; +int n; +{ + return krb_get_krbhst(h,r,n); +} +#ifdef DEBUG +struct ktext *create_death_packet(a_name) + char *a_name; +{ + return krb_create_death_packet(a_name); +} +#endif /* DEBUG */ + +#if 0 +extern int krb_ck_repl (); + +int check_replay () +{ + return krb_ck_repl (); +} +#endif +#endif /* NCOMPAT */ diff --git a/eBones/krb/kuserok.3 b/eBones/krb/kuserok.3 new file mode 100644 index 0000000..36968ba --- /dev/null +++ b/eBones/krb/kuserok.3 @@ -0,0 +1,63 @@ +.\" from: kuserok.3,v 4.1 89/01/23 11:11:49 jtkohl Exp $ +.\" $Id: kuserok.3,v 1.2 1994/07/19 19:27:58 g89r4222 Exp $ +.\" Copyright 1989 by the Massachusetts Institute of Technology. +.\" +.\" For copying and distribution information, +.\" please see the file <Copyright.MIT>. +.\" +.TH KUSEROK 3 "Kerberos Version 4.0" "MIT Project Athena" +.SH NAME +kuserok \- Kerberos version of ruserok +.SH SYNOPSIS +.nf +.nj +.ft B +#include <krb.h> +.PP +.ft B +kuserok(kdata, localuser) +AUTH_DAT *auth_data; +char *localuser; +.fi +.ft R +.SH DESCRIPTION +.I kuserok +determines whether a Kerberos principal described by the structure +.I auth_data +is authorized to login as user +.I localuser +according to the authorization file +("~\fIlocaluser\fR/.klogin" by default). It returns 0 (zero) if authorized, +1 (one) if not authorized. +.PP +If there is no account for +.I localuser +on the local machine, authorization is not granted. +If there is no authorization file, and the Kerberos principal described +by +.I auth_data +translates to +.I localuser +(using +.IR krb_kntoln (3)), +authorization is granted. +If the authorization file +can't be accessed, or the file is not owned by +.IR localuser, +authorization is denied. Otherwise, the file is searched for +a matching principal name, instance, and realm. If a match is found, +authorization is granted, else authorization is denied. +.PP +The file entries are in the format: +.nf +.in +5n + name.instance@realm +.in -5n +.fi +with one entry per line. +.SH SEE ALSO +kerberos(3), ruserok(3), krb_kntoln(3) +.SH FILES +.TP 20n +~\fIlocaluser\fR/.klogin +authorization list diff --git a/eBones/krb/kuserok.c b/eBones/krb/kuserok.c new file mode 100644 index 0000000..cb1f708 --- /dev/null +++ b/eBones/krb/kuserok.c @@ -0,0 +1,195 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * kuserok: check if a kerberos principal has + * access to a local account + * + * from: kuserok.c,v 4.5 89/01/23 09:25:21 jtkohl Exp $ + * $Id: kuserok.c,v 1.2 1994/07/19 19:25:50 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: kuserok.c,v 1.2 1994/07/19 19:25:50 g89r4222 Exp $"; +#endif lint + +#include <krb.h> +#include <stdio.h> +#include <pwd.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <strings.h> + +#define OK 0 +#define NOTOK 1 +#define MAX_USERNAME 10 + +/* + * Given a Kerberos principal "kdata", and a local username "luser", + * determine whether user is authorized to login according to the + * authorization file ("~luser/.klogin" by default). Returns OK + * if authorized, NOTOK if not authorized. + * + * If there is no account for "luser" on the local machine, returns + * NOTOK. If there is no authorization file, and the given Kerberos + * name "kdata" translates to the same name as "luser" (using + * krb_kntoln()), returns OK. Otherwise, if the authorization file + * can't be accessed, returns NOTOK. Otherwise, the file is read for + * a matching principal name, instance, and realm. If one is found, + * returns OK, if none is found, returns NOTOK. + * + * The file entries are in the format: + * + * name.instance@realm + * + * one entry per line. + * + * The ATHENA_COMPAT code supports old-style Athena ~luser/.klogin + * file entries. See the file "kparse.c". + */ + +#ifdef ATHENA_COMPAT + +#include <kparse.h> + +/* + * The parmtable defines the keywords we will recognize with their + * default values, and keeps a pointer to the found value. The found + * value should be filled in with strsave(), since FreeParameterSet() + * will release memory for all non-NULL found strings. + * +*** NOTE WELL! *** + * + * The table below is very nice, but we cannot hard-code a default for the + * realm: we have to get the realm via krb_get_lrealm(). Even though the + * default shows as "from krb_get_lrealm, below", it gets changed in + * kuserok to whatever krb_get_lrealm() tells us. That code assumes that + * the realm will be the entry number in the table below, so if you + * change the order of the entries below, you have to change the + * #definition of REALM_SCRIPT to reflect it. + */ +#define REALM_SUBSCRIPT 1 +parmtable kparm[] = { + +/* keyword default found value */ +{"user", "", (char *) NULL}, +{"realm", "see krb_get_lrealm, below", (char *) NULL}, +{"instance", "", (char *) NULL}, +}; +#define KPARMS kparm,PARMCOUNT(kparm) +#endif ATHENA_COMPAT + +kuserok(kdata, luser) + AUTH_DAT *kdata; + char *luser; +{ + struct stat sbuf; + struct passwd *pwd; + char pbuf[MAXPATHLEN]; + int isok = NOTOK, rc; + FILE *fp; + char kuser[MAX_USERNAME]; + char principal[ANAME_SZ], inst[INST_SZ], realm[REALM_SZ]; + char linebuf[BUFSIZ]; + char *newline; + int gobble; +#ifdef ATHENA_COMPAT + char local_realm[REALM_SZ]; +#endif ATHENA_COMPAT + + /* no account => no access */ + if ((pwd = getpwnam(luser)) == NULL) { + return(NOTOK); + } + (void) strcpy(pbuf, pwd->pw_dir); + (void) strcat(pbuf, "/.klogin"); + + if (access(pbuf, F_OK)) { /* not accessible */ + /* + * if he's trying to log in as himself, and there is no .klogin file, + * let him. To find out, call + * krb_kntoln to convert the triple in kdata to a name which we can + * string compare. + */ + if (!krb_kntoln(kdata, kuser) && (strcmp(kuser, luser) == 0)) { + return(OK); + } + } + /* open ~/.klogin */ + if ((fp = fopen(pbuf, "r")) == NULL) { + return(NOTOK); + } + /* + * security: if the user does not own his own .klogin file, + * do not grant access + */ + if (fstat(fileno(fp), &sbuf)) { + fclose(fp); + return(NOTOK); + } + if (sbuf.st_uid != pwd->pw_uid) { + fclose(fp); + return(NOTOK); + } + +#ifdef ATHENA_COMPAT + /* Accept old-style .klogin files */ + + /* + * change the default realm from the hard-coded value to the + * accepted realm that Kerberos specifies. + */ + rc = krb_get_lrealm(local_realm, 1); + if (rc == KSUCCESS) + kparm[REALM_SUBSCRIPT].defvalue = local_realm; + else + return (rc); + + /* check each line */ + while ((isok != OK) && (rc = fGetParameterSet(fp, KPARMS)) != PS_EOF) { + switch (rc) { + case PS_BAD_KEYWORD: + case PS_SYNTAX: + while (((gobble = fGetChar(fp)) != EOF) && (gobble != '\n')); + break; + + case PS_OKAY: + isok = (ParmCompare(KPARMS, "user", kdata->pname) || + ParmCompare(KPARMS, "instance", kdata->pinst) || + ParmCompare(KPARMS, "realm", kdata->prealm)); + break; + + default: + break; + } + FreeParameterSet(kparm, PARMCOUNT(kparm)); + } + /* reset the stream for parsing new-style names, if necessary */ + rewind(fp); +#endif ATHENA_COMPAT + + /* check each line */ + while ((isok != OK) && (fgets(linebuf, BUFSIZ, fp) != NULL)) { + /* null-terminate the input string */ + linebuf[BUFSIZ-1] = '\0'; + newline = NULL; + /* nuke the newline if it exists */ + if (newline = index(linebuf, '\n')) + *newline = '\0'; + rc = kname_parse(principal, inst, realm, linebuf); + if (rc == KSUCCESS) { + isok = (strncmp(kdata->pname, principal, ANAME_SZ) || + strncmp(kdata->pinst, inst, INST_SZ) || + strncmp(kdata->prealm, realm, REALM_SZ)); + } + /* clean up the rest of the line if necessary */ + if (!newline) + while (((gobble = getc(fp)) != EOF) && gobble != '\n'); + } + fclose(fp); + return(isok); +} diff --git a/eBones/krb/log.c b/eBones/krb/log.c new file mode 100644 index 0000000..42fccfb --- /dev/null +++ b/eBones/krb/log.c @@ -0,0 +1,121 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: log.c,v 4.7 88/12/01 14:15:14 jtkohl Exp $ + * $Id: log.c,v 1.2 1994/07/19 19:25:53 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: log.c,v 1.2 1994/07/19 19:25:53 g89r4222 Exp $"; +#endif /* lint */ + +#include <sys/time.h> +#include <stdio.h> +#include <krb.h> +#include <klog.h> + +static char *log_name = KRBLOG; +static is_open; + +/* + * This file contains three logging routines: set_logfile() + * to determine the file that log entries should be written to; + * and log() and new_log() to write log entries to the file. + */ + +/* + * log() is used to add entries to the logfile (see set_logfile() + * below). Note that it is probably not portable since it makes + * assumptions about what the compiler will do when it is called + * with less than the correct number of arguments which is the + * way it is usually called. + * + * The log entry consists of a timestamp and the given arguments + * printed according to the given "format". + * + * The log file is opened and closed for each log entry. + * + * The return value is undefined. + */ + +__BEGIN_DECLS +char *month_sname __P((int)); +__END_DECLS + + +/*VARARGS1 */ +void log(format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a0) + char *format; + int a1,a2,a3,a4,a5,a6,a7,a8,a9,a0; +{ + FILE *logfile, *fopen(); + long time(),now; + struct tm *tm; + + if ((logfile = fopen(log_name,"a")) == NULL) + return; + + (void) time(&now); + tm = localtime(&now); + + fprintf(logfile,"%2d-%s-%02d %02d:%02d:%02d ",tm->tm_mday, + month_sname(tm->tm_mon + 1),tm->tm_year, + tm->tm_hour, tm->tm_min, tm->tm_sec); + fprintf(logfile,format,a1,a2,a3,a4,a5,a6,a7,a8,a9,a0); + fprintf(logfile,"\n"); + (void) fclose(logfile); + return; +} + +/* + * set_logfile() changes the name of the file to which + * messages are logged. If set_logfile() is not called, + * the logfile defaults to KRBLOG, defined in "krb.h". + */ + +set_logfile(filename) + char *filename; +{ + log_name = filename; + is_open = 0; +} + +/* + * new_log() appends a log entry containing the give time "t" and the + * string "string" to the logfile (see set_logfile() above). The file + * is opened once and left open. The routine returns 1 on failure, 0 + * on success. + */ + +new_log(t,string) + long t; + char *string; +{ + static FILE *logfile; + + long time(); + struct tm *tm; + + if (!is_open) { + if ((logfile = fopen(log_name,"a")) == NULL) return(1); + is_open = 1; + } + + if (t) { + tm = localtime(&t); + + fprintf(logfile,"\n%2d-%s-%02d %02d:%02d:%02d %s",tm->tm_mday, + month_sname(tm->tm_mon + 1),tm->tm_year, + tm->tm_hour, tm->tm_min, tm->tm_sec, string); + } + else { + fprintf(logfile,"\n%20s%s","",string); + } + + (void) fflush(logfile); + return(0); +} diff --git a/eBones/krb/mk_err.c b/eBones/krb/mk_err.c new file mode 100644 index 0000000..331cba9 --- /dev/null +++ b/eBones/krb/mk_err.c @@ -0,0 +1,63 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: mk_err.c,v 4.4 88/11/15 16:33:36 jtkohl Exp $ + * $Id: mk_err.c,v 1.2 1994/07/19 19:25:54 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: mk_err.c,v 1.2 1994/07/19 19:25:54 g89r4222 Exp $"; +#endif /* lint */ + +#include <sys/types.h> +#include <krb.h> +#include <prot.h> +#include <strings.h> + +/* + * This routine creates a general purpose error reply message. It + * doesn't use KTEXT because application protocol may have long + * messages, and may want this part of buffer contiguous to other + * stuff. + * + * The error reply is built in "p", using the error code "e" and + * error text "e_string" given. The length of the error reply is + * returned. + * + * The error reply is in the following format: + * + * unsigned char KRB_PROT_VERSION protocol version no. + * unsigned char AUTH_MSG_APPL_ERR message type + * (least significant + * bit of above) HOST_BYTE_ORDER local byte order + * 4 bytes e given error code + * string e_string given error text + */ + +long krb_mk_err(p,e,e_string) + u_char *p; /* Where to build error packet */ + long e; /* Error code */ + char *e_string; /* Text of error */ +{ + u_char *start; + + start = p; + + /* Create fixed part of packet */ + *p++ = (unsigned char) KRB_PROT_VERSION; + *p = (unsigned char) AUTH_MSG_APPL_ERR; + *p++ |= HOST_BYTE_ORDER; + + /* Add the basic info */ + bcopy((char *)&e,(char *)p,4); /* err code */ + p += sizeof(e); + (void) strcpy((char *)p,e_string); /* err text */ + p += strlen(e_string); + + /* And return the length */ + return p-start; +} diff --git a/eBones/krb/mk_priv.c b/eBones/krb/mk_priv.c new file mode 100644 index 0000000..3bae4ed --- /dev/null +++ b/eBones/krb/mk_priv.c @@ -0,0 +1,203 @@ +/* + * Copyright 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * This routine constructs a Kerberos 'private msg', i.e. + * cryptographically sealed with a private session key. + * + * Note-- bcopy is used to avoid alignment problems on IBM RT. + * + * Note-- It's too bad that it did a long int compare on the RT before. + * + * Returns either < 0 ===> error, or resulting size of message + * + * Steve Miller Project Athena MIT/DEC + * + * from: mk_priv.c,v 4.13 89/03/22 14:48:59 jtkohl Exp $ + * $Id: mk_priv.c,v 1.2 1994/07/19 19:25:56 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: mk_priv.c,v 1.2 1994/07/19 19:25:56 g89r4222 Exp $"; +#endif /* lint */ + +/* system include files */ +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/time.h> + +/* application include files */ +#include <des.h> +#include <krb.h> +#include <prot.h> +#include "lsb_addr_comp.h" + +extern char *errmsg(); +extern int errno; +extern int krb_debug; + +/* static storage */ + + +static u_long c_length; +static struct timeval msg_time; +static u_char msg_time_5ms; +static long msg_time_sec; + +/* + * krb_mk_priv() constructs an AUTH_MSG_PRIVATE message. It takes + * some user data "in" of "length" bytes and creates a packet in "out" + * consisting of the user data, a timestamp, and the sender's network + * address. +#ifndef NOENCRYTION + * The packet is encrypted by pcbc_encrypt(), using the given + * "key" and "schedule". +#endif + * The length of the resulting packet "out" is + * returned. + * + * It is similar to krb_mk_safe() except for the additional key + * schedule argument "schedule" and the fact that the data is encrypted + * rather than appended with a checksum. Also, the protocol version + * number is "private_msg_ver", defined in krb_rd_priv.c, rather than + * KRB_PROT_VERSION, defined in "krb.h". + * + * The "out" packet consists of: + * + * Size Variable Field + * ---- -------- ----- + * + * 1 byte private_msg_ver protocol version number + * 1 byte AUTH_MSG_PRIVATE | message type plus local + * HOST_BYTE_ORDER byte order in low bit + * + * 4 bytes c_length length of data +#ifndef NOENCRYPT + * we encrypt from here with pcbc_encrypt +#endif + * + * 4 bytes length length of user data + * length in user data + * 1 byte msg_time_5ms timestamp milliseconds + * 4 bytes sender->sin.addr.s_addr sender's IP address + * + * 4 bytes msg_time_sec or timestamp seconds with + * -msg_time_sec direction in sign bit + * + * 0<=n<=7 bytes pad to 8 byte multiple zeroes + */ + +long krb_mk_priv(in,out,length,schedule,key,sender,receiver) + u_char *in; /* application data */ + u_char *out; /* put msg here, leave room for + * header! breaks if in and out + * (header stuff) overlap */ + u_long length; /* of in data */ + Key_schedule schedule; /* precomputed key schedule */ + C_Block key; /* encryption key for seed and ivec */ + struct sockaddr_in *sender; /* sender address */ + struct sockaddr_in *receiver; /* receiver address */ +{ + register u_char *p,*q; + static u_char *c_length_ptr; + extern int private_msg_ver; /* in krb_rd_priv.c */ + + /* + * get the current time to use instead of a sequence #, since + * process lifetime may be shorter than the lifetime of a session + * key. + */ + if (gettimeofday(&msg_time,(struct timezone *)0)) { + return -1; + } + msg_time_sec = (long) msg_time.tv_sec; + msg_time_5ms = msg_time.tv_usec/5000; /* 5ms quanta */ + + p = out; + + *p++ = private_msg_ver; + *p++ = AUTH_MSG_PRIVATE | HOST_BYTE_ORDER; + + /* calculate cipher length */ + c_length_ptr = p; + p += sizeof(c_length); + + q = p; + + /* stuff input length */ + bcopy((char *)&length,(char *)p,sizeof(length)); + p += sizeof(length); + +#ifdef NOENCRYPTION + /* make all the stuff contiguous for checksum */ +#else + /* make all the stuff contiguous for checksum and encryption */ +#endif + bcopy((char *)in,(char *)p,(int) length); + p += length; + + /* stuff time 5ms */ + bcopy((char *)&msg_time_5ms,(char *)p,sizeof(msg_time_5ms)); + p += sizeof(msg_time_5ms); + + /* stuff source address */ + bcopy((char *)&sender->sin_addr.s_addr,(char *)p, + sizeof(sender->sin_addr.s_addr)); + p += sizeof(sender->sin_addr.s_addr); + + /* + * direction bit is the sign bit of the timestamp. Ok + * until 2038?? + */ + /* For compatibility with broken old code, compares are done in VAX + byte order (LSBFIRST) */ + if (lsb_net_ulong_less(sender->sin_addr.s_addr, /* src < recv */ + receiver->sin_addr.s_addr)==-1) + msg_time_sec = -msg_time_sec; + else if (lsb_net_ulong_less(sender->sin_addr.s_addr, + receiver->sin_addr.s_addr)==0) + if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port) == -1) + msg_time_sec = -msg_time_sec; + /* stuff time sec */ + bcopy((char *)&msg_time_sec,(char *)p,sizeof(msg_time_sec)); + p += sizeof(msg_time_sec); + + /* + * All that for one tiny bit! Heaven help those that talk to + * themselves. + */ + +#ifdef notdef + /* + * calculate the checksum of the length, address, sequence, and + * inp data + */ + cksum = quad_cksum(q,NULL,p-q,0,key); + if (krb_debug) + printf("\ncksum = %u",cksum); + /* stuff checksum */ + bcopy((char *) &cksum,(char *) p,sizeof(cksum)); + p += sizeof(cksum); +#endif + + /* + * All the data have been assembled, compute length + */ + + c_length = p - q; + c_length = ((c_length + sizeof(C_Block) -1)/sizeof(C_Block)) * + sizeof(C_Block); + /* stuff the length */ + bcopy((char *) &c_length,(char *)c_length_ptr,sizeof(c_length)); + +#ifndef NOENCRYPTION + pcbc_encrypt((C_Block *)q,(C_Block *)q,(long)(p-q),schedule,key,ENCRYPT); +#endif /* NOENCRYPTION */ + + return (q - out + c_length); /* resulting size */ +} diff --git a/eBones/krb/mk_req.c b/eBones/krb/mk_req.c new file mode 100644 index 0000000..bb0f097 --- /dev/null +++ b/eBones/krb/mk_req.c @@ -0,0 +1,195 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: der: mk_req.c,v 4.17 89/07/07 15:20:35 jtkohl Exp $ + * $Id: mk_req.c,v 1.2 1994/07/19 19:25:57 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: mk_req.c,v 1.2 1994/07/19 19:25:57 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <prot.h> +#include <des.h> +#include <sys/time.h> +#include <strings.h> + +extern int krb_ap_req_debug; +static struct timeval tv_local = { 0, 0 }; +static int lifetime = DEFAULT_TKT_LIFE; + +/* + * krb_mk_req takes a text structure in which an authenticator is to + * be built, the name of a service, an instance, a realm, + * and a checksum. It then retrieves a ticket for + * the desired service and creates an authenticator in the text + * structure passed as the first argument. krb_mk_req returns + * KSUCCESS on success and a Kerberos error code on failure. + * + * The peer procedure on the other end is krb_rd_req. When making + * any changes to this routine it is important to make corresponding + * changes to krb_rd_req. + * + * The authenticator consists of the following: + * + * authent->dat + * + * unsigned char KRB_PROT_VERSION protocol version no. + * unsigned char AUTH_MSG_APPL_REQUEST message type + * (least significant + * bit of above) HOST_BYTE_ORDER local byte ordering + * unsigned char kvno from ticket server's key version + * string realm server's realm + * unsigned char tl ticket length + * unsigned char idl request id length + * text ticket->dat ticket for server + * text req_id->dat request id + * + * The ticket information is retrieved from the ticket cache or + * fetched from Kerberos. The request id (called the "authenticator" + * in the papers on Kerberos) contains the following: + * + * req_id->dat + * + * string cr.pname {name, instance, and + * string cr.pinst realm of principal + * string myrealm making this request} + * 4 bytes checksum checksum argument given + * unsigned char tv_local.tf_usec time (milliseconds) + * 4 bytes tv_local.tv_sec time (seconds) + * + * req_id->length = 3 strings + 3 terminating nulls + 5 bytes for time, + * all rounded up to multiple of 8. + */ + +krb_mk_req(authent,service,instance,realm,checksum) + register KTEXT authent; /* Place to build the authenticator */ + char *service; /* Name of the service */ + char *instance; /* Service instance */ + char *realm; /* Authentication domain of service */ + long checksum; /* Checksum of data (optional) */ +{ + static KTEXT_ST req_st; /* Temp storage for req id */ + register KTEXT req_id = &req_st; + unsigned char *v = authent->dat; /* Prot version number */ + unsigned char *t = (authent->dat+1); /* Message type */ + unsigned char *kv = (authent->dat+2); /* Key version no */ + unsigned char *tl = (authent->dat+4+strlen(realm)); /* Tkt len */ + unsigned char *idl = (authent->dat+5+strlen(realm)); /* Reqid len */ + CREDENTIALS cr; /* Credentials used by retr */ + register KTEXT ticket = &(cr.ticket_st); /* Pointer to tkt_st */ + int retval; /* Returned by krb_get_cred */ + static Key_schedule key_s; + char myrealm[REALM_SZ]; + + /* The fixed parts of the authenticator */ + *v = (unsigned char) KRB_PROT_VERSION; + *t = (unsigned char) AUTH_MSG_APPL_REQUEST; + *t |= HOST_BYTE_ORDER; + + /* Get the ticket and move it into the authenticator */ + if (krb_ap_req_debug) + printf("Realm: %s\n",realm); + /* + * Determine realm of these tickets. We will send this to the + * KDC from which we are requesting tickets so it knows what to + * with our session key. + */ + if ((retval = krb_get_tf_realm(TKT_FILE, myrealm)) != KSUCCESS) + return(retval); + + retval = krb_get_cred(service,instance,realm,&cr); + + if (retval == RET_NOTKT) { + if (retval = get_ad_tkt(service,instance,realm,lifetime)) + return(retval); + if (retval = krb_get_cred(service,instance,realm,&cr)) + return(retval); + } + + if (retval != KSUCCESS) return (retval); + + if (krb_ap_req_debug) + printf("%s %s %s %s %s\n", service, instance, realm, + cr.pname, cr.pinst); + *kv = (unsigned char) cr.kvno; + (void) strcpy((char *)(authent->dat+3),realm); + *tl = (unsigned char) ticket->length; + bcopy((char *)(ticket->dat),(char *)(authent->dat+6+strlen(realm)), + ticket->length); + authent->length = 6 + strlen(realm) + ticket->length; + if (krb_ap_req_debug) + printf("Ticket->length = %d\n",ticket->length); + if (krb_ap_req_debug) + printf("Issue date: %d\n",cr.issue_date); + + /* Build request id */ + (void) strcpy((char *)(req_id->dat),cr.pname); /* Auth name */ + req_id->length = strlen(cr.pname)+1; + /* Principal's instance */ + (void) strcpy((char *)(req_id->dat+req_id->length),cr.pinst); + req_id->length += strlen(cr.pinst)+1; + /* Authentication domain */ + (void) strcpy((char *)(req_id->dat+req_id->length),myrealm); + req_id->length += strlen(myrealm)+1; + /* Checksum */ + bcopy((char *)&checksum,(char *)(req_id->dat+req_id->length),4); + req_id->length += 4; + + /* Fill in the times on the request id */ + (void) gettimeofday(&tv_local,(struct timezone *) 0); + *(req_id->dat+(req_id->length)++) = + (unsigned char) tv_local.tv_usec; + /* Time (coarse) */ + bcopy((char *)&(tv_local.tv_sec), + (char *)(req_id->dat+req_id->length), 4); + req_id->length += 4; + + /* Fill to a multiple of 8 bytes for DES */ + req_id->length = ((req_id->length+7)/8)*8; + +#ifndef NOENCRYPTION + key_sched(cr.session,key_s); + pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat, + (long)req_id->length,key_s,cr.session,ENCRYPT); + bzero((char *) key_s, sizeof(key_s)); +#endif /* NOENCRYPTION */ + + /* Copy it into the authenticator */ + bcopy((char *)(req_id->dat),(char *)(authent->dat+authent->length), + req_id->length); + authent->length += req_id->length; + /* And set the id length */ + *idl = (unsigned char) req_id->length; + /* clean up */ + bzero((char *)req_id, sizeof(*req_id)); + + if (krb_ap_req_debug) + printf("Authent->length = %d\n",authent->length); + if (krb_ap_req_debug) + printf("idl = %d, tl = %d\n",(int) *idl, (int) *tl); + + return(KSUCCESS); +} + +/* + * krb_set_lifetime sets the default lifetime for additional tickets + * obtained via krb_mk_req(). + * + * It returns the previous value of the default lifetime. + */ + +int +krb_set_lifetime(newval) +int newval; +{ + int olife = lifetime; + + lifetime = newval; + return(olife); +} diff --git a/eBones/krb/mk_safe.c b/eBones/krb/mk_safe.c new file mode 100644 index 0000000..567004b --- /dev/null +++ b/eBones/krb/mk_safe.c @@ -0,0 +1,168 @@ +/* + * Copyright 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * This routine constructs a Kerberos 'safe msg', i.e. authenticated + * using a private session key to seed a checksum. Msg is NOT + * encrypted. + * + * Note-- bcopy is used to avoid alignment problems on IBM RT + * + * Returns either <0 ===> error, or resulting size of message + * + * Steve Miller Project Athena MIT/DEC + * + * from: mk_safe.c,v 4.12 89/03/22 14:50:49 jtkohl Exp $ + * $Id: mk_safe.c,v 1.2 1994/07/19 19:25:59 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: mk_safe.c,v 1.2 1994/07/19 19:25:59 g89r4222 Exp $"; +#endif /* lint */ + +/* system include files */ +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/time.h> + +/* application include files */ +#include <des.h> +#include <krb.h> +#include <prot.h> +#include "lsb_addr_comp.h" + +extern char *errmsg(); +extern int errno; +extern int krb_debug; + +/* static storage */ + +static u_long cksum; +static C_Block big_cksum[2]; +static struct timeval msg_time; +static u_char msg_time_5ms; +static long msg_time_sec; + +/* + * krb_mk_safe() constructs an AUTH_MSG_SAFE message. It takes some + * user data "in" of "length" bytes and creates a packet in "out" + * consisting of the user data, a timestamp, and the sender's network + * address, followed by a checksum computed on the above, using the + * given "key". The length of the resulting packet is returned. + * + * The "out" packet consists of: + * + * Size Variable Field + * ---- -------- ----- + * + * 1 byte KRB_PROT_VERSION protocol version number + * 1 byte AUTH_MSG_SAFE | message type plus local + * HOST_BYTE_ORDER byte order in low bit + * + * ===================== begin checksum ================================ + * + * 4 bytes length length of user data + * length in user data + * 1 byte msg_time_5ms timestamp milliseconds + * 4 bytes sender->sin.addr.s_addr sender's IP address + * + * 4 bytes msg_time_sec or timestamp seconds with + * -msg_time_sec direction in sign bit + * + * ======================= end checksum ================================ + * + * 16 bytes big_cksum quadratic checksum of + * above using "key" + */ + +long krb_mk_safe(in,out,length,key,sender,receiver) + u_char *in; /* application data */ + u_char *out; /* + * put msg here, leave room for header! + * breaks if in and out (header stuff) + * overlap + */ + u_long length; /* of in data */ + C_Block *key; /* encryption key for seed and ivec */ + struct sockaddr_in *sender; /* sender address */ + struct sockaddr_in *receiver; /* receiver address */ +{ + register u_char *p,*q; + + /* + * get the current time to use instead of a sequence #, since + * process lifetime may be shorter than the lifetime of a session + * key. + */ + if (gettimeofday(&msg_time,(struct timezone *)0)) { + return -1; + } + msg_time_sec = (long) msg_time.tv_sec; + msg_time_5ms = msg_time.tv_usec/5000; /* 5ms quanta */ + + p = out; + + *p++ = KRB_PROT_VERSION; + *p++ = AUTH_MSG_SAFE | HOST_BYTE_ORDER; + + q = p; /* start for checksum stuff */ + /* stuff input length */ + bcopy((char *)&length,(char *)p,sizeof(length)); + p += sizeof(length); + + /* make all the stuff contiguous for checksum */ + bcopy((char *)in,(char *)p,(int) length); + p += length; + + /* stuff time 5ms */ + bcopy((char *)&msg_time_5ms,(char *)p,sizeof(msg_time_5ms)); + p += sizeof(msg_time_5ms); + + /* stuff source address */ + bcopy((char *) &sender->sin_addr.s_addr,(char *)p, + sizeof(sender->sin_addr.s_addr)); + p += sizeof(sender->sin_addr.s_addr); + + /* + * direction bit is the sign bit of the timestamp. Ok until + * 2038?? + */ + /* For compatibility with broken old code, compares are done in VAX + byte order (LSBFIRST) */ + if (lsb_net_ulong_less(sender->sin_addr.s_addr, /* src < recv */ + receiver->sin_addr.s_addr)==-1) + msg_time_sec = -msg_time_sec; + else if (lsb_net_ulong_less(sender->sin_addr.s_addr, + receiver->sin_addr.s_addr)==0) + if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port) == -1) + msg_time_sec = -msg_time_sec; + /* + * all that for one tiny bit! Heaven help those that talk to + * themselves. + */ + + /* stuff time sec */ + bcopy((char *)&msg_time_sec,(char *)p,sizeof(msg_time_sec)); + p += sizeof(msg_time_sec); + +#ifdef NOENCRYPTION + cksum = 0; + bzero(big_cksum, sizeof(big_cksum)); +#else + cksum=quad_cksum(q,big_cksum,p-q,2,key); +#endif + if (krb_debug) + printf("\ncksum = %u",cksum); + + /* stuff checksum */ + bcopy((char *)big_cksum,(char *)p,sizeof(big_cksum)); + p += sizeof(big_cksum); + + return ((long)(p - out)); /* resulting size */ + +} diff --git a/eBones/krb/month_sname.c b/eBones/krb/month_sname.c new file mode 100644 index 0000000..e7a63ec --- /dev/null +++ b/eBones/krb/month_sname.c @@ -0,0 +1,31 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: month_sname.c,v 4.4 88/11/15 16:39:32 jtkohl Exp $ + * $Id: month_sname.c,v 1.2 1994/07/19 19:26:00 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: month_sname.c,v 1.2 1994/07/19 19:26:00 g89r4222 Exp $"; +#endif /* lint */ + + +/* + * Given an integer 1-12, month_sname() returns a string + * containing the first three letters of the corresponding + * month. Returns 0 if the argument is out of range. + */ + +char *month_sname(n) + int n; +{ + static char *name[] = { + "Jan","Feb","Mar","Apr","May","Jun", + "Jul","Aug","Sep","Oct","Nov","Dec" + }; + return((n < 1 || n > 12) ? 0 : name [n-1]); +} diff --git a/eBones/krb/netread.c b/eBones/krb/netread.c new file mode 100644 index 0000000..eb86327 --- /dev/null +++ b/eBones/krb/netread.c @@ -0,0 +1,46 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: netread.c,v 4.1 88/11/15 16:47:21 jtkohl Exp $ + * $Id: netread.c,v 1.2 1994/07/19 19:26:03 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: netread.c,v 1.2 1994/07/19 19:26:03 g89r4222 Exp $"; +#endif lint + +/* + * krb_net_read() reads from the file descriptor "fd" to the buffer + * "buf", until either 1) "len" bytes have been read or 2) cannot + * read anymore from "fd". It returns the number of bytes read + * or a read() error. (The calling interface is identical to + * read(2).) + * + * XXX must not use non-blocking I/O + */ + +int +krb_net_read(fd, buf, len) +int fd; +register char *buf; +register int len; +{ + int cc, len2 = 0; + + do { + cc = read(fd, buf, len); + if (cc < 0) + return(cc); /* errno is already set */ + else if (cc == 0) { + return(len2); + } else { + buf += cc; + len2 += cc; + len -= cc; + } + } while (len > 0); + return(len2); +} diff --git a/eBones/krb/netwrite.c b/eBones/krb/netwrite.c new file mode 100644 index 0000000..5945ce0 --- /dev/null +++ b/eBones/krb/netwrite.c @@ -0,0 +1,42 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: netwrite.c,v 4.1 88/11/15 16:48:58 jtkohl Exp $"; + * $Id: netwrite.c,v 1.2 1994/07/19 19:26:04 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: netwrite.c,v 1.2 1994/07/19 19:26:04 g89r4222 Exp $"; +#endif lint + +/* + * krb_net_write() writes "len" bytes from "buf" to the file + * descriptor "fd". It returns the number of bytes written or + * a write() error. (The calling interface is identical to + * write(2).) + * + * XXX must not use non-blocking I/O + */ + +int +krb_net_write(fd, buf, len) +int fd; +register char *buf; +int len; +{ + int cc; + register int wrlen = len; + do { + cc = write(fd, buf, wrlen); + if (cc < 0) + return(cc); + else { + buf += cc; + wrlen -= cc; + } + } while (wrlen > 0); + return(len); +} diff --git a/eBones/krb/one.c b/eBones/krb/one.c new file mode 100644 index 0000000..c0e8bc6 --- /dev/null +++ b/eBones/krb/one.c @@ -0,0 +1,20 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * form: one.c,v 4.1 88/11/15 16:51:41 jtkohl Exp $ + * $Id: one.c,v 1.2 1994/07/19 19:26:05 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: one.c,v 1.2 1994/07/19 19:26:05 g89r4222 Exp $"; +#endif lint + +/* + * definition of variable set to 1. + * used in krb_conf.h to determine host byte order. + */ + +int krbONE = 1; diff --git a/eBones/krb/pkt_cipher.c b/eBones/krb/pkt_cipher.c new file mode 100644 index 0000000..6ef870c --- /dev/null +++ b/eBones/krb/pkt_cipher.c @@ -0,0 +1,38 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: pkt_cipher.c,v 4.8 89/01/13 17:46:14 steiner Exp $ + * $Id: pkt_cipher.c,v 1.2 1994/07/19 19:26:07 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: pkt_cipher.c,v 1.2 1994/07/19 19:26:07 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <prot.h> + + +/* + * This routine takes a reply packet from the Kerberos ticket-granting + * service and returns a pointer to the beginning of the ciphertext in it. + * + * See "prot.h" for packet format. + */ + +KTEXT +pkt_cipher(packet) + KTEXT packet; +{ + unsigned char *ptr = pkt_a_realm(packet) + 6 + + strlen((char *)pkt_a_realm(packet)); + /* Skip a few more fields */ + ptr += 3 + 4; /* add 4 for exp_date */ + + /* And return the pointer */ + return((KTEXT) ptr); +} diff --git a/eBones/krb/pkt_clen.c b/eBones/krb/pkt_clen.c new file mode 100644 index 0000000..23ad4c3 --- /dev/null +++ b/eBones/krb/pkt_clen.c @@ -0,0 +1,53 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: pkt_clen.c,v 4.7 88/11/15 16:56:36 jtkohl Exp $ + * $Id: pkt_clen.c,v 1.2 1994/07/19 19:26:09 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: pkt_clen.c,v 1.2 1994/07/19 19:26:09 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <prot.h> + +extern int krb_debug; +extern int swap_bytes; + +/* + * Given a pointer to an AUTH_MSG_KDC_REPLY packet, return the length of + * its ciphertext portion. The external variable "swap_bytes" is assumed + * to have been set to indicate whether or not the packet is in local + * byte order. pkt_clen() takes this into account when reading the + * ciphertext length out of the packet. + */ + +pkt_clen(pkt) + KTEXT pkt; +{ + static unsigned short temp,temp2; + int clen = 0; + + /* Start of ticket list */ + unsigned char *ptr = pkt_a_realm(pkt) + 10 + + strlen((char *)pkt_a_realm(pkt)); + + /* Finally the length */ + bcopy((char *)(++ptr),(char *)&temp,2); /* alignment */ + if (swap_bytes) { + /* assume a short is 2 bytes?? */ + swab((char *)&temp,(char *)&temp2,2); + temp = temp2; + } + + clen = (int) temp; + + if (krb_debug) + printf("Clen is %d\n",clen); + return(clen); +} diff --git a/eBones/krb/rd_err.c b/eBones/krb/rd_err.c new file mode 100644 index 0000000..e73c47b --- /dev/null +++ b/eBones/krb/rd_err.c @@ -0,0 +1,79 @@ +/* + * Copyright 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * This routine dissects a a Kerberos 'safe msg', + * checking its integrity, and returning a pointer to the application + * data contained and its length. + * + * Returns 0 (RD_AP_OK) for success or an error code (RD_AP_...) + * + * Steve Miller Project Athena MIT/DEC + * + * from: rd_err.c,v 4.5 89/01/13 17:26:38 steiner Exp $ + * $Id: rd_err.c,v 1.2 1994/07/19 19:26:10 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: rd_err.c,v 1.2 1994/07/19 19:26:10 g89r4222 Exp $"; +#endif /* lint */ + +/* system include files */ +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/time.h> + +/* application include files */ +#include <krb.h> +#include <prot.h> + +/* + * Given an AUTH_MSG_APPL_ERR message, "in" and its length "in_length", + * return the error code from the message in "code" and the text in + * "m_data" as follows: + * + * m_data->app_data points to the error text + * m_data->app_length points to the length of the error text + * + * If all goes well, return RD_AP_OK. If the version number + * is wrong, return RD_AP_VERSION, and if it's not an AUTH_MSG_APPL_ERR + * type message, return RD_AP_MSG_TYPE. + * + * The AUTH_MSG_APPL_ERR message format can be found in mk_err.c + */ + +int +krb_rd_err(in,in_length,code,m_data) + u_char *in; /* pointer to the msg received */ + u_long in_length; /* of in msg */ + long *code; /* received error code */ + MSG_DAT *m_data; +{ + register u_char *p; + int swap_bytes = 0; + p = in; /* beginning of message */ + + if (*p++ != KRB_PROT_VERSION) + return(RD_AP_VERSION); + if (((*p) & ~1) != AUTH_MSG_APPL_ERR) + return(RD_AP_MSG_TYPE); + if ((*p++ & 1) != HOST_BYTE_ORDER) + swap_bytes++; + + /* safely get code */ + bcopy((char *)p,(char *)code,sizeof(*code)); + if (swap_bytes) + swap_u_long(*code); + p += sizeof(*code); /* skip over */ + + m_data->app_data = p; /* we're now at the error text + * message */ + m_data->app_length = in_length; + + return(RD_AP_OK); /* OK == 0 */ +} diff --git a/eBones/krb/rd_priv.c b/eBones/krb/rd_priv.c new file mode 100644 index 0000000..9adefec --- /dev/null +++ b/eBones/krb/rd_priv.c @@ -0,0 +1,204 @@ +/* + * Copyright 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * This routine dissects a a Kerberos 'private msg', decrypting it, + * checking its integrity, and returning a pointer to the application + * data contained and its length. + * + * Returns 0 (RD_AP_OK) for success or an error code (RD_AP_...). If + * the return value is RD_AP_TIME, then either the times are too far + * out of synch, OR the packet was modified. + * + * Steve Miller Project Athena MIT/DEC + * + * from: rd_priv.c,v 4.14 89/04/28 11:59:42 jtkohl Exp $ + * $Id: rd_priv.c,v 1.2 1994/07/19 19:26:11 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[]= +"$Id: rd_priv.c,v 1.2 1994/07/19 19:26:11 g89r4222 Exp $"; +#endif /* lint */ + +/* system include files */ +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/time.h> + +/* application include files */ +#include <des.h> +#include <krb.h> +#include <prot.h> +#include "lsb_addr_comp.h" + +extern char *errmsg(); +extern int errno; +extern int krb_debug; + +/* static storage */ + +static u_long c_length; +static int swap_bytes; +static struct timeval local_time; +static long delta_t; +int private_msg_ver = KRB_PROT_VERSION; + +/* +#ifdef NOENCRPYTION + * krb_rd_priv() checks the integrity of an +#else + * krb_rd_priv() decrypts and checks the integrity of an +#endif + * AUTH_MSG_PRIVATE message. Given the message received, "in", + * the length of that message, "in_length", the key "schedule" + * and "key", and the network addresses of the + * "sender" and "receiver" of the message, krb_rd_safe() returns + * RD_AP_OK if the message is okay, otherwise some error code. + * + * The message data retrieved from "in" are returned in the structure + * "m_data". The pointer to the application data + * (m_data->app_data) refers back to the appropriate place in "in". + * + * See the file "mk_priv.c" for the format of the AUTH_MSG_PRIVATE + * message. The structure containing the extracted message + * information, MSG_DAT, is defined in "krb.h". + */ + +long krb_rd_priv(in,in_length,schedule,key,sender,receiver,m_data) + u_char *in; /* pointer to the msg received */ + u_long in_length; /* length of "in" msg */ + Key_schedule schedule; /* precomputed key schedule */ + C_Block key; /* encryption key for seed and ivec */ + struct sockaddr_in *sender; + struct sockaddr_in *receiver; + MSG_DAT *m_data; /*various input/output data from msg */ +{ + register u_char *p,*q; + static u_long src_addr; /* Can't send structs since no + * guarantees on size */ + + if (gettimeofday(&local_time,(struct timezone *)0)) + return -1; + + p = in; /* beginning of message */ + swap_bytes = 0; + + if (*p++ != KRB_PROT_VERSION && *(p-1) != 3) + return RD_AP_VERSION; + private_msg_ver = *(p-1); + if (((*p) & ~1) != AUTH_MSG_PRIVATE) + return RD_AP_MSG_TYPE; + if ((*p++ & 1) != HOST_BYTE_ORDER) + swap_bytes++; + + /* get cipher length */ + bcopy((char *)p,(char *)&c_length,sizeof(c_length)); + if (swap_bytes) + swap_u_long(c_length); + p += sizeof(c_length); + /* check for rational length so we don't go comatose */ + if (VERSION_SZ + MSG_TYPE_SZ + c_length > in_length) + return RD_AP_MODIFIED; + + + q = p; /* mark start of encrypted stuff */ + +#ifndef NOENCRYPTION + pcbc_encrypt((C_Block *)q,(C_Block *)q,(long)c_length,schedule,key,DECRYPT); +#endif + + /* safely get application data length */ + bcopy((char *) p,(char *)&(m_data->app_length), + sizeof(m_data->app_length)); + if (swap_bytes) + swap_u_long(m_data->app_length); + p += sizeof(m_data->app_length); /* skip over */ + + if (m_data->app_length + sizeof(c_length) + sizeof(in_length) + + sizeof(m_data->time_sec) + sizeof(m_data->time_5ms) + + sizeof(src_addr) + VERSION_SZ + MSG_TYPE_SZ + > in_length) + return RD_AP_MODIFIED; + +#ifndef NOENCRYPTION + /* we're now at the decrypted application data */ +#endif + m_data->app_data = p; + + p += m_data->app_length; + + /* safely get time_5ms */ + bcopy((char *) p, (char *)&(m_data->time_5ms), + sizeof(m_data->time_5ms)); + /* don't need to swap-- one byte for now */ + p += sizeof(m_data->time_5ms); + + /* safely get src address */ + bcopy((char *) p,(char *)&src_addr,sizeof(src_addr)); + /* don't swap, net order always */ + p += sizeof(src_addr); + + if (src_addr != (u_long) sender->sin_addr.s_addr) + return RD_AP_MODIFIED; + + /* safely get time_sec */ + bcopy((char *) p, (char *)&(m_data->time_sec), + sizeof(m_data->time_sec)); + if (swap_bytes) swap_u_long(m_data->time_sec); + + p += sizeof(m_data->time_sec); + + /* check direction bit is the sign bit */ + /* For compatibility with broken old code, compares are done in VAX + byte order (LSBFIRST) */ + if (lsb_net_ulong_less(sender->sin_addr.s_addr, + receiver->sin_addr.s_addr)==-1) + /* src < recv */ + m_data->time_sec = - m_data->time_sec; + else if (lsb_net_ulong_less(sender->sin_addr.s_addr, + receiver->sin_addr.s_addr)==0) + if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port)==-1) + /* src < recv */ + m_data->time_sec = - m_data->time_sec; + /* + * all that for one tiny bit! + * Heaven help those that talk to themselves. + */ + + /* check the time integrity of the msg */ + delta_t = abs((int)((long) local_time.tv_sec + - m_data->time_sec)); + if (delta_t > CLOCK_SKEW) + return RD_AP_TIME; + if (krb_debug) + printf("\ndelta_t = %d",delta_t); + + /* + * caller must check timestamps for proper order and + * replays, since server might have multiple clients + * each with its own timestamps and we don't assume + * tightly synchronized clocks. + */ + +#ifdef notdef + bcopy((char *) p,(char *)&cksum,sizeof(cksum)); + if (swap_bytes) swap_u_long(cksum) + /* + * calculate the checksum of the length, sequence, + * and input data, on the sending byte order!! + */ + calc_cksum = quad_cksum(q,NULL,p-q,0,key); + + if (krb_debug) + printf("\ncalc_cksum = %u, received cksum = %u", + calc_cksum, cksum); + if (cksum != calc_cksum) + return RD_AP_MODIFIED; +#endif + return RD_AP_OK; /* OK == 0 */ +} diff --git a/eBones/krb/rd_req.c b/eBones/krb/rd_req.c new file mode 100644 index 0000000..22b6540 --- /dev/null +++ b/eBones/krb/rd_req.c @@ -0,0 +1,328 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: der: rd_req.c,v 4.16 89/03/22 14:52:06 jtkohl Exp $ + * $Id: rd_req.c,v 1.2 1994/07/19 19:26:13 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: rd_req.c,v 1.2 1994/07/19 19:26:13 g89r4222 Exp $"; +#endif /* lint */ + +#include <des.h> +#include <krb.h> +#include <prot.h> +#include <sys/time.h> +#include <strings.h> + +extern int krb_ap_req_debug; + +static struct timeval t_local = { 0, 0 }; + +/* + * Keep the following information around for subsequent calls + * to this routine by the same server using the same key. + */ + +static Key_schedule serv_key; /* Key sched to decrypt ticket */ +static C_Block ky; /* Initialization vector */ +static int st_kvno; /* version number for this key */ +static char st_rlm[REALM_SZ]; /* server's realm */ +static char st_nam[ANAME_SZ]; /* service name */ +static char st_inst[INST_SZ]; /* server's instance */ + +/* + * This file contains two functions. krb_set_key() takes a DES + * key or password string and returns a DES key (either the original + * key, or the password converted into a DES key) and a key schedule + * for it. + * + * krb_rd_req() reads an authentication request and returns information + * about the identity of the requestor, or an indication that the + * identity information was not authentic. + */ + +/* + * krb_set_key() takes as its first argument either a DES key or a + * password string. The "cvt" argument indicates how the first + * argument "key" is to be interpreted: if "cvt" is null, "key" is + * taken to be a DES key; if "cvt" is non-null, "key" is taken to + * be a password string, and is converted into a DES key using + * string_to_key(). In either case, the resulting key is returned + * in the external static variable "ky". A key schedule is + * generated for "ky" and returned in the external static variable + * "serv_key". + * + * This routine returns the return value of des_key_sched. + * + * krb_set_key() needs to be in the same .o file as krb_rd_req() so that + * the key set by krb_set_key() is available in private storage for + * krb_rd_req(). + */ + +int +krb_set_key(key,cvt) + char *key; + int cvt; +{ +#ifdef NOENCRYPTION + bzero(ky, sizeof(ky)); + return KSUCCESS; +#else + if (cvt) + string_to_key(key,ky); + else + bcopy(key,(char *)ky,8); + return(des_key_sched(ky,serv_key)); +#endif +} + + +/* + * krb_rd_req() takes an AUTH_MSG_APPL_REQUEST or + * AUTH_MSG_APPL_REQUEST_MUTUAL message created by krb_mk_req(), + * checks its integrity and returns a judgement as to the requestor's + * identity. + * + * The "authent" argument is a pointer to the received message. + * The "service" and "instance" arguments name the receiving server, + * and are used to get the service's ticket to decrypt the ticket + * in the message, and to compare against the server name inside the + * ticket. "from_addr" is the network address of the host from which + * the message was received; this is checked against the network + * address in the ticket. If "from_addr" is zero, the check is not + * performed. "ad" is an AUTH_DAT structure which is + * filled in with information about the sender's identity according + * to the authenticator and ticket sent in the message. Finally, + * "fn" contains the name of the file containing the server's key. + * (If "fn" is NULL, the server's key is assumed to have been set + * by krb_set_key(). If "fn" is the null string ("") the default + * file KEYFILE, defined in "krb.h", is used.) + * + * krb_rd_req() returns RD_AP_OK if the authentication information + * was genuine, or one of the following error codes (defined in + * "krb.h"): + * + * RD_AP_VERSION - wrong protocol version number + * RD_AP_MSG_TYPE - wrong message type + * RD_AP_UNDEC - couldn't decipher the message + * RD_AP_INCON - inconsistencies found + * RD_AP_BADD - wrong network address + * RD_AP_TIME - client time (in authenticator) + * too far off server time + * RD_AP_NYV - Kerberos time (in ticket) too + * far off server time + * RD_AP_EXP - ticket expired + * + * For the message format, see krb_mk_req(). + * + * Mutual authentication is not implemented. + */ + +krb_rd_req(authent,service,instance,from_addr,ad,fn) + register KTEXT authent; /* The received message */ + char *service; /* Service name */ + char *instance; /* Service instance */ + long from_addr; /* Net address of originating host */ + AUTH_DAT *ad; /* Structure to be filled in */ + char *fn; /* Filename to get keys from */ +{ + static KTEXT_ST ticket; /* Temp storage for ticket */ + static KTEXT tkt = &ticket; + static KTEXT_ST req_id_st; /* Temp storage for authenticator */ + register KTEXT req_id = &req_id_st; + + char realm[REALM_SZ]; /* Realm of issuing kerberos */ + static Key_schedule seskey_sched; /* Key sched for session key */ + unsigned char skey[KKEY_SZ]; /* Session key from ticket */ + char sname[SNAME_SZ]; /* Service name from ticket */ + char iname[INST_SZ]; /* Instance name from ticket */ + char r_aname[ANAME_SZ]; /* Client name from authenticator */ + char r_inst[INST_SZ]; /* Client instance from authenticator */ + char r_realm[REALM_SZ]; /* Client realm from authenticator */ + unsigned int r_time_ms; /* Fine time from authenticator */ + unsigned long r_time_sec; /* Coarse time from authenticator */ + register char *ptr; /* For stepping through */ + unsigned long delta_t; /* Time in authenticator - local time */ + long tkt_age; /* Age of ticket */ + static int swap_bytes; /* Need to swap bytes? */ + static int mutual; /* Mutual authentication requested? */ + static unsigned char s_kvno;/* Version number of the server's key + * Kerberos used to encrypt ticket */ + int status; + + if (authent->length <= 0) + return(RD_AP_MODIFIED); + + ptr = (char *) authent->dat; + + /* get msg version, type and byte order, and server key version */ + + /* check version */ + if (KRB_PROT_VERSION != (unsigned int) *ptr++) + return(RD_AP_VERSION); + + /* byte order */ + swap_bytes = 0; + if ((*ptr & 1) != HOST_BYTE_ORDER) + swap_bytes++; + + /* check msg type */ + mutual = 0; + switch (*ptr++ & ~1) { + case AUTH_MSG_APPL_REQUEST: + break; + case AUTH_MSG_APPL_REQUEST_MUTUAL: + mutual++; + break; + default: + return(RD_AP_MSG_TYPE); + } + +#ifdef lint + /* XXX mutual is set but not used; why??? */ + /* this is a crock to get lint to shut up */ + if (mutual) + mutual = 0; +#endif /* lint */ + s_kvno = *ptr++; /* get server key version */ + (void) strcpy(realm,ptr); /* And the realm of the issuing KDC */ + ptr += strlen(ptr) + 1; /* skip the realm "hint" */ + + /* + * If "fn" is NULL, key info should already be set; don't + * bother with ticket file. Otherwise, check to see if we + * already have key info for the given server and key version + * (saved in the static st_* variables). If not, go get it + * from the ticket file. If "fn" is the null string, use the + * default ticket file. + */ + if (fn && (strcmp(st_nam,service) || strcmp(st_inst,instance) || + strcmp(st_rlm,realm) || (st_kvno != s_kvno))) { + if (*fn == 0) fn = KEYFILE; + st_kvno = s_kvno; +#ifndef NOENCRYPTION + if (read_service_key(service,instance,realm,s_kvno,fn,(char *)skey)) + return(RD_AP_UNDEC); + if (status=krb_set_key((char *)skey,0)) return(status); +#endif + (void) strcpy(st_rlm,realm); + (void) strcpy(st_nam,service); + (void) strcpy(st_inst,instance); + } + + /* Get ticket from authenticator */ + tkt->length = (int) *ptr++; + if ((tkt->length + (ptr+1 - (char *) authent->dat)) > authent->length) + return(RD_AP_MODIFIED); + bcopy(ptr+1,(char *)(tkt->dat),tkt->length); + + if (krb_ap_req_debug) + log("ticket->length: %d",tkt->length); + +#ifndef NOENCRYPTION + /* Decrypt and take apart ticket */ +#endif + + if (decomp_ticket(tkt,&ad->k_flags,ad->pname,ad->pinst,ad->prealm, + &(ad->address),ad->session, &(ad->life), + &(ad->time_sec),sname,iname,ky,serv_key)) + return(RD_AP_UNDEC); + + if (krb_ap_req_debug) { + log("Ticket Contents."); + log(" Aname: %s.%s",ad->pname, + ((int)*(ad->prealm) ? ad->prealm : "Athena")); + log(" Service: %s%s%s",sname,((int)*iname ? "." : ""),iname); + } + + /* Extract the authenticator */ + req_id->length = (int) *(ptr++); + if ((req_id->length + (ptr + tkt->length - (char *) authent->dat)) > + authent->length) + return(RD_AP_MODIFIED); + bcopy(ptr + tkt->length, (char *)(req_id->dat),req_id->length); + +#ifndef NOENCRYPTION + key_sched(ad->session,seskey_sched); + pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat, + (long)req_id->length,seskey_sched,ad->session,DES_DECRYPT); +#endif /* NOENCRYPTION */ + +#define check_ptr() if ((ptr - (char *) req_id->dat) > req_id->length) return(RD_AP_MODIFIED); + + ptr = (char *) req_id->dat; + (void) strcpy(r_aname,ptr); /* Authentication name */ + ptr += strlen(r_aname)+1; + check_ptr(); + (void) strcpy(r_inst,ptr); /* Authentication instance */ + ptr += strlen(r_inst)+1; + check_ptr(); + (void) strcpy(r_realm,ptr); /* Authentication name */ + ptr += strlen(r_realm)+1; + check_ptr(); + bcopy(ptr,(char *)&ad->checksum,4); /* Checksum */ + ptr += 4; + check_ptr(); + if (swap_bytes) swap_u_long(ad->checksum); + r_time_ms = *(ptr++); /* Time (fine) */ +#ifdef lint + /* XXX r_time_ms is set but not used. why??? */ + /* this is a crock to get lint to shut up */ + if (r_time_ms) + r_time_ms = 0; +#endif /* lint */ + check_ptr(); + /* assume sizeof(r_time_sec) == 4 ?? */ + bcopy(ptr,(char *)&r_time_sec,4); /* Time (coarse) */ + if (swap_bytes) swap_u_long(r_time_sec); + + /* Check for authenticity of the request */ + if (krb_ap_req_debug) + log("Pname: %s %s",ad->pname,r_aname); + if (strcmp(ad->pname,r_aname) != 0) + return(RD_AP_INCON); + if (strcmp(ad->pinst,r_inst) != 0) + return(RD_AP_INCON); + if (krb_ap_req_debug) + log("Realm: %s %s",ad->prealm,r_realm); + if ((strcmp(ad->prealm,r_realm) != 0)) + return(RD_AP_INCON); + + if (krb_ap_req_debug) + log("Address: %d %d",ad->address,from_addr); + if (from_addr && (ad->address != from_addr)) + return(RD_AP_BADD); + + (void) gettimeofday(&t_local,(struct timezone *) 0); + delta_t = abs((int)(t_local.tv_sec - r_time_sec)); + if (delta_t > CLOCK_SKEW) { + if (krb_ap_req_debug) + log("Time out of range: %d - %d = %d", + t_local.tv_sec,r_time_sec,delta_t); + return(RD_AP_TIME); + } + + /* Now check for expiration of ticket */ + + tkt_age = t_local.tv_sec - ad->time_sec; + if (krb_ap_req_debug) + log("Time: %d Issue Date: %d Diff: %d Life %x", + t_local.tv_sec,ad->time_sec,tkt_age,ad->life); + + if (t_local.tv_sec < ad->time_sec) { + if ((ad->time_sec - t_local.tv_sec) > CLOCK_SKEW) + return(RD_AP_NYV); + } + else if ((t_local.tv_sec - ad->time_sec) > 5 * 60 * ad->life) + return(RD_AP_EXP); + + /* All seems OK */ + ad->reply.length = 0; + + return(RD_AP_OK); +} diff --git a/eBones/krb/rd_safe.c b/eBones/krb/rd_safe.c new file mode 100644 index 0000000..e500b4d --- /dev/null +++ b/eBones/krb/rd_safe.c @@ -0,0 +1,180 @@ +/* + * Copyright 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * This routine dissects a a Kerberos 'safe msg', checking its + * integrity, and returning a pointer to the application data + * contained and its length. + * + * Returns 0 (RD_AP_OK) for success or an error code (RD_AP_...) + * + * Steve Miller Project Athena MIT/DEC + * + * from: rd_safe.c,v 4.12 89/01/23 15:16:16 steiner Exp $ + * $Id: rd_safe.c,v 1.2 1994/07/19 19:26:15 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: rd_safe.c,v 1.2 1994/07/19 19:26:15 g89r4222 Exp $"; +#endif /* lint */ + +/* system include files */ +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/time.h> + +/* application include files */ +#include <des.h> +#include <krb.h> +#include <prot.h> +#include "lsb_addr_comp.h" + +extern char *errmsg(); +extern int errno; +extern int krb_debug; + +/* static storage */ + +static C_Block calc_cksum[2]; +static C_Block big_cksum[2]; +static int swap_bytes; +static struct timeval local_time; +static u_long delta_t; + +/* + * krb_rd_safe() checks the integrity of an AUTH_MSG_SAFE message. + * Given the message received, "in", the length of that message, + * "in_length", the "key" to compute the checksum with, and the + * network addresses of the "sender" and "receiver" of the message, + * krb_rd_safe() returns RD_AP_OK if message is okay, otherwise + * some error code. + * + * The message data retrieved from "in" is returned in the structure + * "m_data". The pointer to the application data (m_data->app_data) + * refers back to the appropriate place in "in". + * + * See the file "mk_safe.c" for the format of the AUTH_MSG_SAFE + * message. The structure containing the extracted message + * information, MSG_DAT, is defined in "krb.h". + */ + +long krb_rd_safe(in,in_length,key,sender,receiver,m_data) + u_char *in; /* pointer to the msg received */ + u_long in_length; /* length of "in" msg */ + C_Block *key; /* encryption key for seed and ivec */ + struct sockaddr_in *sender; /* sender's address */ + struct sockaddr_in *receiver; /* receiver's address -- me */ + MSG_DAT *m_data; /* where to put message information */ +{ + register u_char *p,*q; + static u_long src_addr; /* Can't send structs since no + * guarantees on size */ + /* Be very conservative */ + if (sizeof(u_long) != sizeof(struct in_addr)) { + fprintf(stderr,"\n\ +krb_rd_safe protocol err sizeof(u_long) != sizeof(struct in_addr)"); + exit(-1); + } + + if (gettimeofday(&local_time,(struct timezone *)0)) + return -1; + + p = in; /* beginning of message */ + swap_bytes = 0; + + if (*p++ != KRB_PROT_VERSION) return RD_AP_VERSION; + if (((*p) & ~1) != AUTH_MSG_SAFE) return RD_AP_MSG_TYPE; + if ((*p++ & 1) != HOST_BYTE_ORDER) swap_bytes++; + + q = p; /* mark start of cksum stuff */ + + /* safely get length */ + bcopy((char *)p,(char *)&(m_data->app_length), + sizeof(m_data->app_length)); + if (swap_bytes) swap_u_long(m_data->app_length); + p += sizeof(m_data->app_length); /* skip over */ + + if (m_data->app_length + sizeof(in_length) + + sizeof(m_data->time_sec) + sizeof(m_data->time_5ms) + + sizeof(big_cksum) + sizeof(src_addr) + + VERSION_SZ + MSG_TYPE_SZ > in_length) + return(RD_AP_MODIFIED); + + m_data->app_data = p; /* we're now at the application data */ + + /* skip app data */ + p += m_data->app_length; + + /* safely get time_5ms */ + bcopy((char *)p, (char *)&(m_data->time_5ms), + sizeof(m_data->time_5ms)); + + /* don't need to swap-- one byte for now */ + p += sizeof(m_data->time_5ms); + + /* safely get src address */ + bcopy((char *)p,(char *)&src_addr,sizeof(src_addr)); + + /* don't swap, net order always */ + p += sizeof(src_addr); + + if (src_addr != (u_long) sender->sin_addr.s_addr) + return RD_AP_MODIFIED; + + /* safely get time_sec */ + bcopy((char *)p, (char *)&(m_data->time_sec), + sizeof(m_data->time_sec)); + if (swap_bytes) + swap_u_long(m_data->time_sec); + p += sizeof(m_data->time_sec); + + /* check direction bit is the sign bit */ + /* For compatibility with broken old code, compares are done in VAX + byte order (LSBFIRST) */ + if (lsb_net_ulong_less(sender->sin_addr.s_addr, + receiver->sin_addr.s_addr)==-1) + /* src < recv */ + m_data->time_sec = - m_data->time_sec; + else if (lsb_net_ulong_less(sender->sin_addr.s_addr, + receiver->sin_addr.s_addr)==0) + if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port)==-1) + /* src < recv */ + m_data->time_sec = - m_data->time_sec; + + /* + * All that for one tiny bit! Heaven help those that talk to + * themselves. + */ + + /* check the time integrity of the msg */ + delta_t = abs((int)((long) local_time.tv_sec - m_data->time_sec)); + if (delta_t > CLOCK_SKEW) return RD_AP_TIME; + + /* + * caller must check timestamps for proper order and replays, since + * server might have multiple clients each with its own timestamps + * and we don't assume tightly synchronized clocks. + */ + + bcopy((char *)p,(char *)big_cksum,sizeof(big_cksum)); + if (swap_bytes) swap_u_16(big_cksum); + +#ifdef NOENCRYPTION + bzero(calc_cksum, sizeof(calc_cksum)); +#else + quad_cksum(q,calc_cksum,p-q,2,key); +#endif + + if (krb_debug) + printf("\ncalc_cksum = %u, received cksum = %u", + (long) calc_cksum[0], (long) big_cksum[0]); + if (bcmp((char *)big_cksum,(char *)calc_cksum,sizeof(big_cksum))) + return(RD_AP_MODIFIED); + + return(RD_AP_OK); /* OK == 0 */ +} diff --git a/eBones/krb/read_service_key.c b/eBones/krb/read_service_key.c new file mode 100644 index 0000000..4d66710 --- /dev/null +++ b/eBones/krb/read_service_key.c @@ -0,0 +1,120 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: _service_key.c,v 4.10 90/03/10 19:06:56 jon Exp $ + * $Id: read_service_key.c,v 1.2 1994/07/19 19:26:16 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: read_service_key.c,v 1.2 1994/07/19 19:26:16 g89r4222 Exp $"; +#endif /* lint */ + +#include <krb.h> +#include <stdio.h> +#include <strings.h> + +/* + * The private keys for servers on a given host are stored in a + * "srvtab" file (typically "/etc/srvtab"). This routine extracts + * a given server's key from the file. + * + * read_service_key() takes the server's name ("service"), "instance", + * and "realm" and a key version number "kvno", and looks in the given + * "file" for the corresponding entry, and if found, returns the entry's + * key field in "key". + * + * If "instance" contains the string "*", then it will match + * any instance, and the chosen instance will be copied to that + * string. For this reason it is important that the there is enough + * space beyond the "*" to receive the entry. + * + * If "kvno" is 0, it is treated as a wild card and the first + * matching entry regardless of the "vno" field is returned. + * + * This routine returns KSUCCESS on success, otherwise KFAILURE. + * + * The format of each "srvtab" entry is as follows: + * + * Size Variable Field in file + * ---- -------- ------------- + * string serv server name + * string inst server instance + * string realm server realm + * 1 byte vno server key version # + * 8 bytes key server's key + * ... ... ... + */ + + +/*ARGSUSED */ +read_service_key(service,instance,realm,kvno,file,key) + char *service; /* Service Name */ + char *instance; /* Instance name or "*" */ + char *realm; /* Realm */ + int kvno; /* Key version number */ + char *file; /* Filename */ + char *key; /* Pointer to key to be filled in */ +{ + char serv[SNAME_SZ]; + char inst[INST_SZ]; + char rlm[REALM_SZ]; + unsigned char vno; /* Key version number */ + int wcard; + + int stab, open(); + + if ((stab = open(file, 0, 0)) < NULL) + return(KFAILURE); + + wcard = (instance[0] == '*') && (instance[1] == '\0'); + + while(getst(stab,serv,SNAME_SZ) > 0) { /* Read sname */ + (void) getst(stab,inst,INST_SZ); /* Instance */ + (void) getst(stab,rlm,REALM_SZ); /* Realm */ + /* Vers number */ + if (read(stab,(char *)&vno,1) != 1) { + close(stab); + return(KFAILURE); + } + /* Key */ + if (read(stab,key,8) != 8) { + close(stab); + return(KFAILURE); + } + /* Is this the right service */ + if (strcmp(serv,service)) + continue; + /* How about instance */ + if (!wcard && strcmp(inst,instance)) + continue; + if (wcard) + (void) strncpy(instance,inst,INST_SZ); + /* Is this the right realm */ +#ifdef ATHENA_COMPAT + /* XXX For backward compatibility: if keyfile says "Athena" + and caller wants "ATHENA.MIT.EDU", call it a match */ + if (strcmp(rlm,realm) && + (strcmp(rlm,"Athena") || + strcmp(realm,"ATHENA.MIT.EDU"))) + continue; +#else /* ! ATHENA_COMPAT */ + if (strcmp(rlm,realm)) + continue; +#endif /* ATHENA_COMPAT */ + + /* How about the key version number */ + if (kvno && kvno != (int) vno) + continue; + + (void) close(stab); + return(KSUCCESS); + } + + /* Can't find the requested service */ + (void) close(stab); + return(KFAILURE); +} diff --git a/eBones/krb/recvauth.c b/eBones/krb/recvauth.c new file mode 100644 index 0000000..fe26814 --- /dev/null +++ b/eBones/krb/recvauth.c @@ -0,0 +1,286 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: recvauth.c,v 4.4 90/03/10 19:03:08 jon Exp $"; + * $Id: recvauth.c,v 1.2 1994/07/19 19:26:18 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: recvauth.c,v 1.2 1994/07/19 19:26:18 g89r4222 Exp $"; +#endif lint + +#include <krb.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <syslog.h> +#include <errno.h> +#include <stdio.h> +#include <strings.h> + + +#define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN + chars */ + +/* + * If the protocol changes, you will need to change the version string + * and make appropriate changes in krb_sendauth.c + * be sure to support old versions of krb_sendauth! + */ + +extern int errno; + +/* + * krb_recvauth() reads (and optionally responds to) a message sent + * using krb_sendauth(). The "options" argument is a bit-field of + * selected options (see "sendauth.c" for options description). + * The only option relevant to krb_recvauth() is KOPT_DO_MUTUAL + * (mutual authentication requested). The "fd" argument supplies + * a file descriptor to read from (and write to, if mutual authenti- + * cation is requested). + * + * Part of the received message will be a Kerberos ticket sent by the + * client; this is read into the "ticket" argument. The "service" and + * "instance" arguments supply the server's Kerberos name. If the + * "instance" argument is the string "*", it is treated as a wild card + * and filled in during the krb_rd_req() call (see read_service_key()). + * + * The "faddr" and "laddr" give the sending (client) and receiving + * (local server) network addresses. ("laddr" may be left NULL unless + * mutual authentication is requested, in which case it must be set.) + * + * The authentication information extracted from the message is returned + * in "kdata". The "filename" argument indicates the file where the + * server's key can be found. (It is passed on to krb_rd_req().) If + * left null, the default "/etc/srvtab" will be used. + * + * If mutual authentication is requested, the session key schedule must + * be computed in order to reply; this schedule is returned in the + * "schedule" argument. A string containing the application version + * number from the received message is returned in "version", which + * should be large enough to hold a KRB_SENDAUTH_VLEN-character string. + * + * See krb_sendauth() for the format of the received client message. + * + * This routine supports another client format, for backward + * compatibility, consisting of: + * + * Size Variable Field + * ---- -------- ----- + * + * string tmp_buf, tkt_len length of ticket, in + * ascii + * + * char ' ' (space char) separator + * + * tkt_len ticket->dat the ticket + * + * This old-style version does not support mutual authentication. + * + * krb_recvauth() first reads the protocol version string from the + * given file descriptor. If it doesn't match the current protocol + * version (KRB_SENDAUTH_VERS), the old-style format is assumed. In + * that case, the string of characters up to the first space is read + * and interpreted as the ticket length, then the ticket is read. + * + * If the first string did match KRB_SENDAUTH_VERS, krb_recvauth() + * next reads the application protocol version string. Then the + * ticket length and ticket itself are read. + * + * The ticket is decrypted and checked by the call to krb_rd_req(). + * If no mutual authentication is required, the result of the + * krb_rd_req() call is retured by this routine. If mutual authenti- + * cation is required, a message in the following format is returned + * on "fd": + * + * Size Variable Field + * ---- -------- ----- + * + * 4 bytes tkt_len length of ticket or -1 + * if error occurred + * + * priv_len tmp_buf "private" message created + * by krb_mk_priv() which + * contains the incremented + * checksum sent by the client + * encrypted in the session + * key. (This field is not + * present in case of error.) + * + * If all goes well, KSUCCESS is returned; otherwise KFAILURE or some + * other error code is returned. + */ + +#ifndef max +#define max(a,b) (((a) > (b)) ? (a) : (b)) +#endif /* max */ + +int +krb_recvauth(options, fd, ticket, service, instance, faddr, laddr, kdata, + filename, schedule, version) +long options; /* bit-pattern of options */ +int fd; /* file descr. to read from */ +KTEXT ticket; /* storage for client's ticket */ +char *service; /* service expected */ +char *instance; /* inst expected (may be filled in) */ +struct sockaddr_in *faddr; /* address of foreign host on fd */ +struct sockaddr_in *laddr; /* local address */ +AUTH_DAT *kdata; /* kerberos data (returned) */ +char *filename; /* name of file with service keys */ +Key_schedule schedule; /* key schedule (return) */ +char *version; /* version string (filled in) */ +{ + + int i, cc, old_vers = 0; + char krb_vers[KRB_SENDAUTH_VLEN + 1]; /* + 1 for the null terminator */ + char *cp; + int rem; + long tkt_len, priv_len; + u_long cksum; + u_char tmp_buf[MAX_KTXT_LEN+max(KRB_SENDAUTH_VLEN+1,21)]; + + /* read the protocol version number */ + if (krb_net_read(fd, krb_vers, KRB_SENDAUTH_VLEN) != + KRB_SENDAUTH_VLEN) + return(errno); + krb_vers[KRB_SENDAUTH_VLEN] = '\0'; + + /* check version string */ + if (strcmp(krb_vers,KRB_SENDAUTH_VERS)) { + /* Assume the old version of sendkerberosdata: send ascii + length, ' ', and ticket. */ + if (options & KOPT_DO_MUTUAL) + return(KFAILURE); /* XXX can't do old style with mutual auth */ + old_vers = 1; + + /* copy what we have read into tmp_buf */ + (void) bcopy(krb_vers, (char *) tmp_buf, KRB_SENDAUTH_VLEN); + + /* search for space, and make it a null */ + for (i = 0; i < KRB_SENDAUTH_VLEN; i++) + if (tmp_buf[i]== ' ') { + tmp_buf[i] = '\0'; + /* point cp to the beginning of the real ticket */ + cp = (char *) &tmp_buf[i+1]; + break; + } + + if (i == KRB_SENDAUTH_VLEN) + /* didn't find the space, keep reading to find it */ + for (; i<20; i++) { + if (read(fd, (char *)&tmp_buf[i], 1) != 1) { + return(KFAILURE); + } + if (tmp_buf[i] == ' ') { + tmp_buf[i] = '\0'; + /* point cp to the beginning of the real ticket */ + cp = (char *) &tmp_buf[i+1]; + break; + } + } + + tkt_len = (long) atoi((char *) tmp_buf); + + /* sanity check the length */ + if ((i==20)||(tkt_len<=0)||(tkt_len>MAX_KTXT_LEN)) + return(KFAILURE); + + if (i < KRB_SENDAUTH_VLEN) { + /* since we already got the space, and part of the ticket, + we read fewer bytes to get the rest of the ticket */ + if (krb_net_read(fd, (char *)(tmp_buf+KRB_SENDAUTH_VLEN), + (int) (tkt_len - KRB_SENDAUTH_VLEN + 1 + i)) + != (int)(tkt_len - KRB_SENDAUTH_VLEN + 1 + i)) + return(errno); + } else { + if (krb_net_read(fd, (char *)(tmp_buf+i), (int)tkt_len) != + (int) tkt_len) + return(errno); + } + ticket->length = tkt_len; + /* copy the ticket into the struct */ + (void) bcopy(cp, (char *) ticket->dat, ticket->length); + + } else { + /* read the application version string */ + if (krb_net_read(fd, version, KRB_SENDAUTH_VLEN) != + KRB_SENDAUTH_VLEN) + return(errno); + version[KRB_SENDAUTH_VLEN] = '\0'; + + /* get the length of the ticket */ + if (krb_net_read(fd, (char *)&tkt_len, sizeof(tkt_len)) != + sizeof(tkt_len)) + return(errno); + + /* sanity check */ + ticket->length = ntohl((unsigned long)tkt_len); + if ((ticket->length <= 0) || (ticket->length > MAX_KTXT_LEN)) { + if (options & KOPT_DO_MUTUAL) { + rem = KFAILURE; + goto mutual_fail; + } else + return(KFAILURE); /* XXX there may still be junk on the fd? */ + } + + /* read the ticket */ + if (krb_net_read(fd, (char *) ticket->dat, ticket->length) + != ticket->length) + return(errno); + } + /* + * now have the ticket. decrypt it to get the authenticated + * data. + */ + rem = krb_rd_req(ticket,service,instance,faddr->sin_addr.s_addr, + kdata,filename); + + if (old_vers) return(rem); /* XXX can't do mutual with old client */ + + /* if we are doing mutual auth, compose a response */ + if (options & KOPT_DO_MUTUAL) { + if (rem != KSUCCESS) + /* the krb_rd_req failed */ + goto mutual_fail; + + /* add one to the (formerly) sealed checksum, and re-seal it + for return to the client */ + cksum = kdata->checksum + 1; + cksum = htonl(cksum); +#ifndef NOENCRYPTION + key_sched(kdata->session,schedule); +#endif + priv_len = krb_mk_priv((unsigned char *)&cksum, + tmp_buf, + (unsigned long) sizeof(cksum), + schedule, + kdata->session, + laddr, + faddr); + if (priv_len < 0) { + /* re-sealing failed; notify the client */ + rem = KFAILURE; /* XXX */ +mutual_fail: + priv_len = -1; + tkt_len = htonl((unsigned long) priv_len); + /* a length of -1 is interpreted as an authentication + failure by the client */ + if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len))) + != sizeof(tkt_len)) + return(cc); + return(rem); + } else { + /* re-sealing succeeded, send the private message */ + tkt_len = htonl((unsigned long)priv_len); + if ((cc = krb_net_write(fd, (char *)&tkt_len, sizeof(tkt_len))) + != sizeof(tkt_len)) + return(cc); + if ((cc = krb_net_write(fd, (char *)tmp_buf, (int) priv_len)) + != (int) priv_len) + return(cc); + } + } + return(rem); +} diff --git a/eBones/krb/save_credentials.c b/eBones/krb/save_credentials.c new file mode 100644 index 0000000..129c912 --- /dev/null +++ b/eBones/krb/save_credentials.c @@ -0,0 +1,53 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: save_credentials.c,v 4.9 89/05/31 17:45:43 jtkohl Exp $ + * $Id: save_credentials.c,v 1.2 1994/07/19 19:26:19 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: save_credentials.c,v 1.2 1994/07/19 19:26:19 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <krb.h> + +/* + * This routine takes a ticket and associated info and calls + * tf_save_cred() to store them in the ticket cache. The peer + * routine for extracting a ticket and associated info from the + * ticket cache is krb_get_cred(). When changes are made to + * this routine, the corresponding changes should be made + * in krb_get_cred() as well. + * + * Returns KSUCCESS if all goes well, otherwise an error returned + * by the tf_init() or tf_save_cred() routines. + */ + +save_credentials(service, instance, realm, session, lifetime, kvno, + ticket, issue_date) + char *service; /* Service name */ + char *instance; /* Instance */ + char *realm; /* Auth domain */ + C_Block session; /* Session key */ + int lifetime; /* Lifetime */ + int kvno; /* Key version number */ + KTEXT ticket; /* The ticket itself */ + long issue_date; /* The issue time */ +{ + int tf_status; /* return values of the tf_util calls */ + + /* Open and lock the ticket file for writing */ + if ((tf_status = tf_init(TKT_FILE, W_TKT_FIL)) != KSUCCESS) + return(tf_status); + + /* Save credentials by appending to the ticket file */ + tf_status = tf_save_cred(service, instance, realm, session, + lifetime, kvno, ticket, issue_date); + (void) tf_close(); + return (tf_status); +} diff --git a/eBones/krb/send_to_kdc.c b/eBones/krb/send_to_kdc.c new file mode 100644 index 0000000..aeaf389 --- /dev/null +++ b/eBones/krb/send_to_kdc.c @@ -0,0 +1,313 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: send_to_kdc.c,v 4.20 90/01/02 13:40:37 jtkohl Exp $ + * $Id: send_to_kdc.c,v 1.2 1994/07/19 19:26:21 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid_send_to_kdc_c[] = +"$Id: send_to_kdc.c,v 1.1 1994/03/21 17:35:39 piero Exp "; +#endif /* lint */ + +#include <krb.h> +#include <prot.h> + +#include <stdio.h> +#include <errno.h> +#include <sys/time.h> +#include <sys/types.h> +#ifdef lint +#include <sys/uio.h> /* struct iovec to make lint happy */ +#endif /* lint */ +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <strings.h> + +#define S_AD_SZ sizeof(struct sockaddr_in) + +extern int errno; +extern int krb_debug; + +extern char *malloc(), *calloc(), *realloc(); + +int krb_udp_port = 0; + +/* CLIENT_KRB_TIMEOUT indicates the time to wait before + * retrying a server. It's defined in "krb.h". + */ +static struct timeval timeout = { CLIENT_KRB_TIMEOUT, 0}; +static char *prog = "send_to_kdc"; +static send_recv(); + +/* + * This file contains two routines, send_to_kdc() and send_recv(). + * send_recv() is a static routine used by send_to_kdc(). + */ + +/* + * send_to_kdc() sends a message to the Kerberos authentication + * server(s) in the given realm and returns the reply message. + * The "pkt" argument points to the message to be sent to Kerberos; + * the "rpkt" argument will be filled in with Kerberos' reply. + * The "realm" argument indicates the realm of the Kerberos server(s) + * to transact with. If the realm is null, the local realm is used. + * + * If more than one Kerberos server is known for a given realm, + * different servers will be queried until one of them replies. + * Several attempts (retries) are made for each server before + * giving up entirely. + * + * If an answer was received from a Kerberos host, KSUCCESS is + * returned. The following errors can be returned: + * + * SKDC_CANT - can't get local realm + * - can't find "kerberos" in /etc/services database + * - can't open socket + * - can't bind socket + * - all ports in use + * - couldn't find any Kerberos host + * + * SKDC_RETRY - couldn't get an answer from any Kerberos server, + * after several retries + */ + +send_to_kdc(pkt,rpkt,realm) + KTEXT pkt; + KTEXT rpkt; + char *realm; +{ + int i, f; + int no_host; /* was a kerberos host found? */ + int retry; + int n_hosts; + int retval; + struct sockaddr_in to; + struct hostent *host, *hostlist; + char *cp; + char krbhst[MAX_HSTNM]; + char lrealm[REALM_SZ]; + + /* + * If "realm" is non-null, use that, otherwise get the + * local realm. + */ + if (realm) + (void) strcpy(lrealm, realm); + else + if (krb_get_lrealm(lrealm,1)) { + if (krb_debug) + fprintf(stderr, "%s: can't get local realm\n", prog); + return(SKDC_CANT); + } + if (krb_debug) + printf("lrealm is %s\n", lrealm); + if (krb_udp_port == 0) { + register struct servent *sp; + if ((sp = getservbyname("kerberos","udp")) == 0) { + if (krb_debug) + fprintf(stderr, "%s: Can't get kerberos/udp service\n", + prog); + return(SKDC_CANT); + } + krb_udp_port = sp->s_port; + if (krb_debug) + printf("krb_udp_port is %d\n", krb_udp_port); + } + bzero((char *)&to, S_AD_SZ); + hostlist = (struct hostent *) malloc(sizeof(struct hostent)); + if (!hostlist) + return (/*errno */SKDC_CANT); + if ((f = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + if (krb_debug) + fprintf(stderr,"%s: Can't open socket\n", prog); + return(SKDC_CANT); + } + /* from now on, exit through rtn label for cleanup */ + + no_host = 1; + /* get an initial allocation */ + n_hosts = 0; + for (i = 1; krb_get_krbhst(krbhst, lrealm, i) == KSUCCESS; ++i) { + if (krb_debug) { + printf("Getting host entry for %s...",krbhst); + (void) fflush(stdout); + } + host = gethostbyname(krbhst); + if (krb_debug) { + printf("%s.\n", + host ? "Got it" : "Didn't get it"); + (void) fflush(stdout); + } + if (!host) + continue; + no_host = 0; /* found at least one */ + n_hosts++; + /* preserve host network address to check later + * (would be better to preserve *all* addresses, + * take care of that later) + */ + hostlist = (struct hostent *) + realloc((char *)hostlist, + (unsigned) + sizeof(struct hostent)*(n_hosts+1)); + if (!hostlist) + return /*errno */SKDC_CANT; + bcopy((char *)host, (char *)&hostlist[n_hosts-1], + sizeof(struct hostent)); + host = &hostlist[n_hosts-1]; + cp = malloc((unsigned)host->h_length); + if (!cp) { + retval = /*errno */SKDC_CANT; + goto rtn; + } + bcopy((char *)host->h_addr, cp, host->h_length); +/* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2 + (or worse) only return one name ... */ +#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) + host->h_addr_list = (char **)malloc(sizeof(char *)); + if (!host->h_addr_list) { + retval = /*errno */SKDC_CANT; + goto rtn; + } +#endif /* ULTRIX022 || SunOS */ + host->h_addr = cp; + bzero((char *)&hostlist[n_hosts], + sizeof(struct hostent)); + to.sin_family = host->h_addrtype; + bcopy(host->h_addr, (char *)&to.sin_addr, + host->h_length); + to.sin_port = krb_udp_port; + if (send_recv(pkt, rpkt, f, &to, hostlist)) { + retval = KSUCCESS; + goto rtn; + } + if (krb_debug) { + printf("Timeout, error, or wrong descriptor\n"); + (void) fflush(stdout); + } + } + if (no_host) { + if (krb_debug) + fprintf(stderr, "%s: can't find any Kerberos host.\n", + prog); + retval = SKDC_CANT; + goto rtn; + } + /* retry each host in sequence */ + for (retry = 0; retry < CLIENT_KRB_RETRY; ++retry) { + for (host = hostlist; host->h_name != (char *)NULL; host++) { + to.sin_family = host->h_addrtype; + bcopy(host->h_addr, (char *)&to.sin_addr, + host->h_length); + if (send_recv(pkt, rpkt, f, &to, hostlist)) { + retval = KSUCCESS; + goto rtn; + } + } + } + retval = SKDC_RETRY; +rtn: + (void) close(f); + if (hostlist) { + register struct hostent *hp; + for (hp = hostlist; hp->h_name; hp++) +#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) + if (hp->h_addr_list) { +#endif /* ULTRIX022 || SunOS */ + if (hp->h_addr) + free(hp->h_addr); +#if !(defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) + free((char *)hp->h_addr_list); + } +#endif /* ULTRIX022 || SunOS */ + free((char *)hostlist); + } + return(retval); +} + +/* + * try to send out and receive message. + * return 1 on success, 0 on failure + */ + +static send_recv(pkt,rpkt,f,_to,addrs) + KTEXT pkt; + KTEXT rpkt; + int f; + struct sockaddr_in *_to; + struct hostent *addrs; +{ + fd_set readfds; + register struct hostent *hp; + struct sockaddr_in from; + int sin_size; + int numsent; + + if (krb_debug) { + if (_to->sin_family == AF_INET) + printf("Sending message to %s...", + inet_ntoa(_to->sin_addr)); + else + printf("Sending message..."); + (void) fflush(stdout); + } + if ((numsent = sendto(f,(char *)(pkt->dat), pkt->length, 0, + (struct sockaddr *)_to, + S_AD_SZ)) != pkt->length) { + if (krb_debug) + printf("sent only %d/%d\n",numsent, pkt->length); + return 0; + } + if (krb_debug) { + printf("Sent\nWaiting for reply..."); + (void) fflush(stdout); + } + FD_ZERO(&readfds); + FD_SET(f, &readfds); + errno = 0; + /* select - either recv is ready, or timeout */ + /* see if timeout or error or wrong descriptor */ + if (select(f + 1, &readfds, (fd_set *)0, (fd_set *)0, &timeout) < 1 + || !FD_ISSET(f, &readfds)) { + if (krb_debug) { + fprintf(stderr, "select failed: readfds=%x", + readfds); + perror(""); + } + return 0; + } + sin_size = sizeof(from); + if (recvfrom(f, (char *)(rpkt->dat), sizeof(rpkt->dat), 0, + (struct sockaddr *)&from, &sin_size) + < 0) { + if (krb_debug) + perror("recvfrom"); + return 0; + } + if (krb_debug) { + printf("received packet from %s\n", inet_ntoa(from.sin_addr)); + fflush(stdout); + } + for (hp = addrs; hp->h_name != (char *)NULL; hp++) { + if (!bcmp(hp->h_addr, (char *)&from.sin_addr.s_addr, + hp->h_length)) { + if (krb_debug) { + printf("Received it\n"); + (void) fflush(stdout); + } + return 1; + } + if (krb_debug) + fprintf(stderr, + "packet not from %x\n", + hp->h_addr); + } + if (krb_debug) + fprintf(stderr, "%s: received packet from wrong host! (%x)\n", + "send_to_kdc(send_rcv)", from.sin_addr.s_addr); + return 0; +} diff --git a/eBones/krb/sendauth.c b/eBones/krb/sendauth.c new file mode 100644 index 0000000..7d798bb --- /dev/null +++ b/eBones/krb/sendauth.c @@ -0,0 +1,257 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: sendauth.c,v 4.6 90/03/10 23:18:28 jon Exp $ + * $Id: sendauth.c,v 1.2 1994/07/19 19:26:23 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: sendauth.c,v 1.2 1994/07/19 19:26:23 g89r4222 Exp $"; +#endif lint + +#include <krb.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <syslog.h> +#include <errno.h> +#include <stdio.h> +#include <strings.h> + +#define KRB_SENDAUTH_VERS "AUTHV0.1" /* MUST be KRB_SENDAUTH_VLEN chars */ +/* + * If the protocol changes, you will need to change the version string + * and make appropriate changes in krb_recvauth.c + */ + +extern int errno; + +extern char *krb_get_phost(); + +/* + * This file contains two routines: krb_sendauth() and krb_sendsrv(). + * + * krb_sendauth() transmits a ticket over a file descriptor for a + * desired service, instance, and realm, doing mutual authentication + * with the server if desired. + * + * krb_sendsvc() sends a service name to a remote knetd server. + */ + +/* + * The first argument to krb_sendauth() contains a bitfield of + * options (the options are defined in "krb.h"): + * + * KOPT_DONT_CANON Don't canonicalize instance as a hostname. + * (If this option is not chosen, krb_get_phost() + * is called to canonicalize it.) + * + * KOPT_DONT_MK_REQ Don't request server ticket from Kerberos. + * A ticket must be supplied in the "ticket" + * argument. + * (If this option is not chosen, and there + * is no ticket for the given server in the + * ticket cache, one will be fetched using + * krb_mk_req() and returned in "ticket".) + * + * KOPT_DO_MUTUAL Do mutual authentication, requiring that the + * receiving server return the checksum+1 encrypted + * in the session key. The mutual authentication + * is done using krb_mk_priv() on the other side + * (see "recvauth.c") and krb_rd_priv() on this + * side. + * + * The "fd" argument is a file descriptor to write to the remote + * server on. The "ticket" argument is used to store the new ticket + * from the krb_mk_req() call. If the KOPT_DONT_MK_REQ options is + * chosen, the ticket must be supplied in the "ticket" argument. + * The "service", "inst", and "realm" arguments identify the ticket. + * If "realm" is null, the local realm is used. + * + * The following arguments are only needed if the KOPT_DO_MUTUAL option + * is chosen: + * + * The "checksum" argument is a number that the server will add 1 to + * to authenticate itself back to the client; the "msg_data" argument + * holds the returned mutual-authentication message from the server + * (i.e., the checksum+1); the "cred" structure is used to hold the + * session key of the server, extracted from the ticket file, for use + * in decrypting the mutual authentication message from the server; + * and "schedule" holds the key schedule for that decryption. The + * the local and server addresses are given in "laddr" and "faddr". + * + * The application protocol version number (of up to KRB_SENDAUTH_VLEN + * characters) is passed in "version". + * + * If all goes well, KSUCCESS is returned, otherwise some error code. + * + * The format of the message sent to the server is: + * + * Size Variable Field + * ---- -------- ----- + * + * KRB_SENDAUTH_VLEN KRB_SENDAUTH_VER sendauth protocol + * bytes version number + * + * KRB_SENDAUTH_VLEN version application protocol + * bytes version number + * + * 4 bytes ticket->length length of ticket + * + * ticket->length ticket->dat ticket itself + */ + +/* + * XXX: Note that krb_rd_priv() is coded in such a way that + * "msg_data->app_data" will be pointing into "priv_buf", which + * will disappear when krb_sendauth() returns. + */ + +int +krb_sendauth(options, fd, ticket, service, inst, realm, checksum, + msg_data, cred, schedule, laddr, faddr, version) +long options; /* bit-pattern of options */ +int fd; /* file descriptor to write onto */ +KTEXT ticket; /* where to put ticket (return); or + * supplied in case of KOPT_DONT_MK_REQ */ +char *service, *inst, *realm; /* service name, instance, realm */ +u_long checksum; /* checksum to include in request */ +MSG_DAT *msg_data; /* mutual auth MSG_DAT (return) */ +CREDENTIALS *cred; /* credentials (return) */ +Key_schedule schedule; /* key schedule (return) */ +struct sockaddr_in *laddr; /* local address */ +struct sockaddr_in *faddr; /* address of foreign host on fd */ +char *version; /* version string */ +{ + int rem, i, cc; + char srv_inst[INST_SZ]; + char krb_realm[REALM_SZ]; + char buf[BUFSIZ]; + long tkt_len; + u_char priv_buf[1024]; + u_long cksum; + + rem=KSUCCESS; + + /* get current realm if not passed in */ + if (!realm) { + rem = krb_get_lrealm(krb_realm,1); + if (rem != KSUCCESS) + return(rem); + realm = krb_realm; + } + + /* copy instance into local storage, canonicalizing if desired */ + if (options & KOPT_DONT_CANON) + (void) strncpy(srv_inst, inst, INST_SZ); + else + (void) strncpy(srv_inst, krb_get_phost(inst), INST_SZ); + + /* get the ticket if desired */ + if (!(options & KOPT_DONT_MK_REQ)) { + rem = krb_mk_req(ticket, service, srv_inst, realm, checksum); + if (rem != KSUCCESS) + return(rem); + } + +#ifdef ATHENA_COMPAT + /* this is only for compatibility with old servers */ + if (options & KOPT_DO_OLDSTYLE) { + (void) sprintf(buf,"%d ",ticket->length); + (void) write(fd, buf, strlen(buf)); + (void) write(fd, (char *) ticket->dat, ticket->length); + return(rem); + } +#endif ATHENA_COMPAT + /* if mutual auth, get credentials so we have service session + keys for decryption below */ + if (options & KOPT_DO_MUTUAL) + if (cc = krb_get_cred(service, srv_inst, realm, cred)) + return(cc); + + /* zero the buffer */ + (void) bzero(buf, BUFSIZ); + + /* insert version strings */ + (void) strncpy(buf, KRB_SENDAUTH_VERS, KRB_SENDAUTH_VLEN); + (void) strncpy(buf+KRB_SENDAUTH_VLEN, version, KRB_SENDAUTH_VLEN); + + /* increment past vers strings */ + i = 2*KRB_SENDAUTH_VLEN; + + /* put ticket length into buffer */ + tkt_len = htonl((unsigned long) ticket->length); + (void) bcopy((char *) &tkt_len, buf+i, sizeof(tkt_len)); + i += sizeof(tkt_len); + + /* put ticket into buffer */ + (void) bcopy((char *) ticket->dat, buf+i, ticket->length); + i += ticket->length; + + /* write the request to the server */ + if ((cc = krb_net_write(fd, buf, i)) != i) + return(cc); + + /* mutual authentication, if desired */ + if (options & KOPT_DO_MUTUAL) { + /* get the length of the reply */ + if (krb_net_read(fd, (char *) &tkt_len, sizeof(tkt_len)) != + sizeof(tkt_len)) + return(errno); + tkt_len = ntohl((unsigned long)tkt_len); + + /* if the length is negative, the server failed to recognize us. */ + if ((tkt_len < 0) || (tkt_len > sizeof(priv_buf))) + return(KFAILURE); /* XXX */ + /* read the reply... */ + if (krb_net_read(fd, (char *)priv_buf, (int) tkt_len) != (int) tkt_len) + return(errno); + + /* ...and decrypt it */ +#ifndef NOENCRYPTION + key_sched(cred->session,schedule); +#endif + if (cc = krb_rd_priv(priv_buf,(unsigned long) tkt_len, schedule, + cred->session, faddr, laddr, msg_data)) + return(cc); + + /* fetch the (modified) checksum */ + (void) bcopy((char *)msg_data->app_data, (char *)&cksum, + sizeof(cksum)); + cksum = ntohl(cksum); + + /* if it doesn't match, fail */ + if (cksum != checksum + 1) + return(KFAILURE); /* XXX */ + } + return(KSUCCESS); +} + +#ifdef ATHENA_COMPAT +/* + * krb_sendsvc + */ + +int +krb_sendsvc(fd, service) +int fd; +char *service; +{ + /* write the service name length and then the service name to + the fd */ + long serv_length; + int cc; + + serv_length = htonl((unsigned long)strlen(service)); + if ((cc = krb_net_write(fd, (char *) &serv_length, + sizeof(serv_length))) + != sizeof(serv_length)) + return(cc); + if ((cc = krb_net_write(fd, service, strlen(service))) + != strlen(service)) + return(cc); + return(KSUCCESS); +} +#endif ATHENA_COMPAT diff --git a/eBones/krb/stime.c b/eBones/krb/stime.c new file mode 100644 index 0000000..c040374 --- /dev/null +++ b/eBones/krb/stime.c @@ -0,0 +1,40 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: stime.c,v 4.5 88/11/15 16:58:05 jtkohl Exp $ + * $Id: stime.c,v 1.2 1994/07/19 19:26:25 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: stime.c,v 1.2 1994/07/19 19:26:25 g89r4222 Exp $"; +#endif /* lint */ + +#include <sys/time.h> +#include <stdio.h> /* for sprintf() */ + +/* + * Given a pointer to a long containing the number of seconds + * since the beginning of time (midnight 1 Jan 1970 GMT), return + * a string containing the local time in the form: + * + * "25-Jan-88 10:17:56" + */ + +char *stime(t) + long *t; +{ + static char st_data[40]; + static char *st = st_data; + struct tm *tm; + char *month_sname(); + + tm = localtime(t); + (void) sprintf(st,"%2d-%s-%02d %02d:%02d:%02d",tm->tm_mday, + month_sname(tm->tm_mon + 1),tm->tm_year, + tm->tm_hour, tm->tm_min, tm->tm_sec); + return st; +} diff --git a/eBones/krb/tf_shm.c b/eBones/krb/tf_shm.c new file mode 100644 index 0000000..5548f0d --- /dev/null +++ b/eBones/krb/tf_shm.c @@ -0,0 +1,174 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * Shared memory segment functions for session keys. Derived from code + * contributed by Dan Kolkowitz (kolk@jessica.stanford.edu). + * + * from: tf_shm.c,v 4.2 89/10/25 23:26:46 qjb Exp $ + * $Id: tf_shm.c,v 1.2 1994/07/19 19:26:26 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: tf_shm.c,v 1.2 1994/07/19 19:26:26 g89r4222 Exp $"; +#endif lint + +#include <stdio.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <krb.h> +#include <des.h> +#include <sys/stat.h> +#include <fcntl.h> + +#define MAX_BUFF sizeof(des_cblock)*1000 /* room for 1k keys */ + +extern int errno; +extern int krb_debug; + +/* + * krb_create_shmtkt: + * + * create a shared memory segment for session keys, leaving its id + * in the specified filename. + */ + +int +krb_shm_create(file_name) +char *file_name; +{ + int retval; + int shmid; + struct shmid_ds shm_buf; + FILE *sfile; + uid_t me, metoo, getuid(), geteuid(); + + (void) krb_shm_dest(file_name); /* nuke it if it exists... + this cleans up to make sure we + don't slowly lose memory. */ + + shmid = shmget((long)IPC_PRIVATE,MAX_BUFF, IPC_CREAT); + if (shmid == -1) { + if (krb_debug) + perror("krb_shm_create shmget"); + return(KFAILURE); /* XXX */ + } + me = getuid(); + metoo = geteuid(); + /* + * now set up the buffer so that we can modify it + */ + shm_buf.shm_perm.uid = me; + shm_buf.shm_perm.gid = getgid(); + shm_buf.shm_perm.mode = 0600; + if (shmctl(shmid,IPC_SET,&shm_buf) < 0) { /*can now map it */ + if (krb_debug) + perror("krb_shm_create shmctl"); + (void) shmctl(shmid, IPC_RMID, 0); + return(KFAILURE); /* XXX */ + } + (void) shmctl(shmid, SHM_LOCK, 0); /* attempt to lock-in-core */ + /* arrange so the file is owned by the ruid + (swap real & effective uid if necessary). */ + if (me != metoo) { + if (setreuid(metoo, me) < 0) { + /* can't switch??? barf! */ + if (krb_debug) + perror("krb_shm_create: setreuid"); + (void) shmctl(shmid, IPC_RMID, 0); + return(KFAILURE); + } else + if (krb_debug) + printf("swapped UID's %d and %d\n",metoo,me); + } + if ((sfile = fopen(file_name,"w")) == 0) { + if (krb_debug) + perror("krb_shm_create file"); + (void) shmctl(shmid, IPC_RMID, 0); + return(KFAILURE); /* XXX */ + } + if (fchmod(fileno(sfile),0600) < 0) { + if (krb_debug) + perror("krb_shm_create fchmod"); + (void) shmctl(shmid, IPC_RMID, 0); + return(KFAILURE); /* XXX */ + } + if (me != metoo) { + if (setreuid(me, metoo) < 0) { + /* can't switch??? barf! */ + if (krb_debug) + perror("krb_shm_create: setreuid2"); + (void) shmctl(shmid, IPC_RMID, 0); + return(KFAILURE); + } else + if (krb_debug) + printf("swapped UID's %d and %d\n",me,metoo); + } + + (void) fprintf(sfile,"%d",shmid); + (void) fflush(sfile); + (void) fclose(sfile); + return(KSUCCESS); +} + + +/* + * krb_is_diskless: + * + * check / to see if file .diskless exists. If so it is diskless. + * Do it this way now to avoid dependencies on a particular routine. + * Choose root file system since that will be private to the client. + */ + +int krb_is_diskless() +{ + struct stat buf; + if (stat("/.diskless",&buf) < 0) + return(0); + else return(1); +} + +/* + * krb_shm_dest: destroy shared memory segment with session keys, and remove + * file pointing to it. + */ + +int krb_shm_dest(file) +char *file; +{ + int shmid; + FILE *sfile; + struct stat st_buf; + + if (stat(file,&st_buf) == 0) { + /* successful stat */ + if ((sfile = fopen(file,"r")) == 0) { + if (krb_debug) + perror("cannot open shared memory file"); + return(KFAILURE); /* XXX */ + } + if (fscanf(sfile,"%d",&shmid) == 1) { + if (shmctl(shmid,IPC_RMID,0) != 0) { + if (krb_debug) + perror("krb_shm_dest: cannot delete shm segment"); + (void) fclose(sfile); + return(KFAILURE); /* XXX */ + } + } else { + if (krb_debug) + fprintf(stderr, "bad format in shmid file\n"); + (void) fclose(sfile); + return(KFAILURE); /* XXX */ + } + (void) fclose(sfile); + (void) unlink(file); + return(KSUCCESS); + } else + return(RET_TKFIL); /* XXX */ +} + + + diff --git a/eBones/krb/tf_util.3 b/eBones/krb/tf_util.3 new file mode 100644 index 0000000..3a9bc94 --- /dev/null +++ b/eBones/krb/tf_util.3 @@ -0,0 +1,151 @@ +.\" from: tf_util.3,v 4.2 89/04/25 17:17:11 jtkohl Exp $ +.\" $Id: tf_util.3,v 1.2 1994/07/19 19:28:05 g89r4222 Exp $ +.\" Copyright 1989 by the Massachusetts Institute of Technology. +.\" +.\" For copying and distribution information, +.\" please see the file <Copyright.MIT>. +.\" +.TH TF_UTIL 3 "Kerberos Version 4.0" "MIT Project Athena" +.SH NAME +tf_init, tf_get_pname, tf_get_pinst, tf_get_cred, tf_close \ +\- Routines for manipulating a Kerberos ticket file +.SH SYNOPSIS +.nf +.nj +.ft B +#include <krb.h> +.PP +.ft B +extern char *krb_err_txt[]; +.PP +.ft B +tf_init(tf_name, rw) +char *tf_name; +int rw; +.PP +.ft B +tf_get_pname(pname) +char *pname; +.PP +.ft B +tf_get_pinst(pinst) +char *pinst; +.PP +.ft B +tf_get_cred(c) +CREDENTIALS *c; +.PP +.ft B +tf_close() +.PP +.fi +.SH DESCRIPTION +This group of routines are provided to manipulate the Kerberos tickets +file. A ticket file has the following format: +.nf +.in +4 +.sp +principal's name (null-terminated string) +principal's instance (null-terminated string) +CREDENTIAL_1 +CREDENTIAL_2 + ... +CREDENTIAL_n +EOF +.sp +.in -4 +.LP +Where "CREDENTIAL_x" consists of the following fixed-length +fields from the CREDENTIALS structure (defined in <krb.h>): +.nf +.sp +.in +4 + char service[ANAME_SZ] + char instance[INST_SZ] + char realm[REALM_SZ] + des_cblock session + int lifetime + int kvno + KTEXT_ST ticket_st + long issue_date +.in -4 +.sp +.fi +.PP +.I tf_init +must be called before the other ticket file +routines. +It takes the name of the ticket file to use, +and a read/write flag as arguments. +It tries to open the ticket file, checks the mode and if +everything is okay, locks the file. If it's opened for +reading, the lock is shared. If it's opened for writing, +the lock is exclusive. +KSUCCESS is returned if all went well, otherwise one of the +following: +.nf +.sp +NO_TKT_FIL - file wasn't there +TKT_FIL_ACC - file was in wrong mode, etc. +TKT_FIL_LCK - couldn't lock the file, even after a retry +.sp +.fi +.PP +The +.I tf_get_pname +reads the principal's name from a ticket file. +It should only be called after tf_init has been called. The +principal's name is filled into the +.I pname +parameter. If all goes +well, KSUCCESS is returned. +If tf_init wasn't called, TKT_FIL_INI +is returned. +If the principal's name was null, or EOF was encountered, or the +name was longer than ANAME_SZ, TKT_FIL_FMT is returned. +.PP +The +.I tf_get_pinst +reads the principal's instance from a ticket file. +It should only be called after tf_init and tf_get_pname +have been called. +The principal's instance is filled into the +.I pinst +parameter. +If all goes +well, KSUCCESS is returned. +If tf_init wasn't called, TKT_FIL_INI +is returned. +If EOF was encountered, or the +name was longer than INST_SZ, TKT_FIL_FMT is returned. +Note that, unlike the principal name, the instance name may be null. +.PP +The +.I tf_get_cred +routine reads a CREDENTIALS record from a ticket file and +fills in the given structure. +It should only be called after +tf_init, tf_get_pname, and tf_get_pinst have been called. +If all goes well, KSUCCESS is returned. Possible error codes +are: +.nf +.sp +TKT_FIL_INI - tf_init wasn't called first +TKT_FIL_FMT - bad format +EOF - end of file encountered +.sp +.fi +.PP +.I tf_close +closes the ticket file and releases the lock on it. +.SH "SEE ALSO" +krb(3) +.SH DIAGNOSTICS +.SH BUGS +The ticket file routines have to be called in a certain order. +.SH AUTHORS +Jennifer Steiner, MIT Project Athena +.br +Bill Bryant, MIT Project Athena +.SH RESTRICTIONS +Copyright 1987 Massachusetts Institute of Technology diff --git a/eBones/krb/tf_util.c b/eBones/krb/tf_util.c new file mode 100644 index 0000000..a9e8551 --- /dev/null +++ b/eBones/krb/tf_util.c @@ -0,0 +1,572 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: tf_util.c,v 4.9 90/03/10 19:19:45 jon Exp $ + * $Id: tf_util.c,v 1.2 1994/07/19 19:26:28 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: tf_util.c,v 1.2 1994/07/19 19:26:28 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <krb.h> + +#ifdef TKT_SHMEM +#include <sys/param.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#endif /* TKT_SHMEM */ + +#define TOO_BIG -1 +#define TF_LCK_RETRY ((unsigned)2) /* seconds to sleep before + * retry if ticket file is + * locked */ +extern errno; +extern int krb_debug; + +#ifdef TKT_SHMEM +char *krb_shm_addr = 0; +static char *tmp_shm_addr = 0; +static char krb_dummy_skey[8] = {0,0,0,0,0,0,0,0}; + +char *shmat(); +#endif /* TKT_SHMEM */ + +/* + * fd must be initialized to something that won't ever occur as a real + * file descriptor. Since open(2) returns only non-negative numbers as + * valid file descriptors, and tf_init always stuffs the return value + * from open in here even if it is an error flag, we must + * a. Initialize fd to a negative number, to indicate that it is + * not initially valid. + * b. When checking for a valid fd, assume that negative values + * are invalid (ie. when deciding whether tf_init has been + * called.) + * c. In tf_close, be sure it gets reinitialized to a negative + * number. + */ +static fd = -1; +static curpos; /* Position in tfbfr */ +static lastpos; /* End of tfbfr */ +static char tfbfr[BUFSIZ]; /* Buffer for ticket data */ + +static tf_gets(), tf_read(); + +/* + * This file contains routines for manipulating the ticket cache file. + * + * The ticket file is in the following format: + * + * principal's name (null-terminated string) + * principal's instance (null-terminated string) + * CREDENTIAL_1 + * CREDENTIAL_2 + * ... + * CREDENTIAL_n + * EOF + * + * Where "CREDENTIAL_x" consists of the following fixed-length + * fields from the CREDENTIALS structure (see "krb.h"): + * + * char service[ANAME_SZ] + * char instance[INST_SZ] + * char realm[REALM_SZ] + * C_Block session + * int lifetime + * int kvno + * KTEXT_ST ticket_st + * long issue_date + * + * Short description of routines: + * + * tf_init() opens the ticket file and locks it. + * + * tf_get_pname() returns the principal's name. + * + * tf_get_pinst() returns the principal's instance (may be null). + * + * tf_get_cred() returns the next CREDENTIALS record. + * + * tf_save_cred() appends a new CREDENTIAL record to the ticket file. + * + * tf_close() closes the ticket file and releases the lock. + * + * tf_gets() returns the next null-terminated string. It's an internal + * routine used by tf_get_pname(), tf_get_pinst(), and tf_get_cred(). + * + * tf_read() reads a given number of bytes. It's an internal routine + * used by tf_get_cred(). + */ + +/* + * tf_init() should be called before the other ticket file routines. + * It takes the name of the ticket file to use, "tf_name", and a + * read/write flag "rw" as arguments. + * + * It tries to open the ticket file, checks the mode, and if everything + * is okay, locks the file. If it's opened for reading, the lock is + * shared. If it's opened for writing, the lock is exclusive. + * + * Returns KSUCCESS if all went well, otherwise one of the following: + * + * NO_TKT_FIL - file wasn't there + * TKT_FIL_ACC - file was in wrong mode, etc. + * TKT_FIL_LCK - couldn't lock the file, even after a retry + */ + +tf_init(tf_name, rw) + char *tf_name; +{ + int wflag; + uid_t me, getuid(); + struct stat stat_buf; +#ifdef TKT_SHMEM + char shmidname[MAXPATHLEN]; + FILE *sfp; + int shmid; +#endif + + switch (rw) { + case R_TKT_FIL: + wflag = 0; + break; + case W_TKT_FIL: + wflag = 1; + break; + default: + if (krb_debug) fprintf(stderr, "tf_init: illegal parameter\n"); + return TKT_FIL_ACC; + } + if (lstat(tf_name, &stat_buf) < 0) + switch (errno) { + case ENOENT: + return NO_TKT_FIL; + default: + return TKT_FIL_ACC; + } + me = getuid(); + if ((stat_buf.st_uid != me && me != 0) || + ((stat_buf.st_mode & S_IFMT) != S_IFREG)) + return TKT_FIL_ACC; +#ifdef TKT_SHMEM + (void) strcpy(shmidname, tf_name); + (void) strcat(shmidname, ".shm"); + if (stat(shmidname,&stat_buf) < 0) + return(TKT_FIL_ACC); + if ((stat_buf.st_uid != me && me != 0) || + ((stat_buf.st_mode & S_IFMT) != S_IFREG)) + return TKT_FIL_ACC; +#endif /* TKT_SHMEM */ + + /* + * If "wflag" is set, open the ticket file in append-writeonly mode + * and lock the ticket file in exclusive mode. If unable to lock + * the file, sleep and try again. If we fail again, return with the + * proper error message. + */ + + curpos = sizeof(tfbfr); + +#ifdef TKT_SHMEM + sfp = fopen(shmidname, "r"); /* only need read/write on the + actual tickets */ + if (sfp == 0) + return TKT_FIL_ACC; + shmid = -1; + { + char buf[BUFSIZ]; + int val; /* useful for debugging fscanf */ + /* We provide our own buffer here since some STDIO libraries + barf on unbuffered input with fscanf() */ + + setbuf(sfp, buf); + if ((val = fscanf(sfp,"%d",&shmid)) != 1) { + (void) fclose(sfp); + return TKT_FIL_ACC; + } + if (shmid < 0) { + (void) fclose(sfp); + return TKT_FIL_ACC; + } + (void) fclose(sfp); + } + /* + * global krb_shm_addr is initialized to 0. Ultrix bombs when you try and + * attach the same segment twice so we need this check. + */ + if (!krb_shm_addr) { + if ((krb_shm_addr = shmat(shmid,0,0)) == -1){ + if (krb_debug) + fprintf(stderr, + "cannot attach shared memory for segment %d\n", + shmid); + krb_shm_addr = 0; /* reset so we catch further errors */ + return TKT_FIL_ACC; + } + } + tmp_shm_addr = krb_shm_addr; +#endif /* TKT_SHMEM */ + + if (wflag) { + fd = open(tf_name, O_RDWR, 0600); + if (fd < 0) { + return TKT_FIL_ACC; + } + if (flock(fd, LOCK_EX | LOCK_NB) < 0) { + sleep(TF_LCK_RETRY); + if (flock(fd, LOCK_EX | LOCK_NB) < 0) { + (void) close(fd); + fd = -1; + return TKT_FIL_LCK; + } + } + return KSUCCESS; + } + /* + * Otherwise "wflag" is not set and the ticket file should be opened + * for read-only operations and locked for shared access. + */ + + fd = open(tf_name, O_RDONLY, 0600); + if (fd < 0) { + return TKT_FIL_ACC; + } + if (flock(fd, LOCK_SH | LOCK_NB) < 0) { + sleep(TF_LCK_RETRY); + if (flock(fd, LOCK_SH | LOCK_NB) < 0) { + (void) close(fd); + fd = -1; + return TKT_FIL_LCK; + } + } + return KSUCCESS; +} + +/* + * tf_get_pname() reads the principal's name from the ticket file. It + * should only be called after tf_init() has been called. The + * principal's name is filled into the "p" parameter. If all goes well, + * KSUCCESS is returned. If tf_init() wasn't called, TKT_FIL_INI is + * returned. If the name was null, or EOF was encountered, or the name + * was longer than ANAME_SZ, TKT_FIL_FMT is returned. + */ + +tf_get_pname(p) + char *p; +{ + if (fd < 0) { + if (krb_debug) + fprintf(stderr, "tf_get_pname called before tf_init.\n"); + return TKT_FIL_INI; + } + if (tf_gets(p, ANAME_SZ) < 2) /* can't be just a null */ + return TKT_FIL_FMT; + return KSUCCESS; +} + +/* + * tf_get_pinst() reads the principal's instance from a ticket file. + * It should only be called after tf_init() and tf_get_pname() have been + * called. The instance is filled into the "inst" parameter. If all + * goes well, KSUCCESS is returned. If tf_init() wasn't called, + * TKT_FIL_INI is returned. If EOF was encountered, or the instance + * was longer than ANAME_SZ, TKT_FIL_FMT is returned. Note that the + * instance may be null. + */ + +tf_get_pinst(inst) + char *inst; +{ + if (fd < 0) { + if (krb_debug) + fprintf(stderr, "tf_get_pinst called before tf_init.\n"); + return TKT_FIL_INI; + } + if (tf_gets(inst, INST_SZ) < 1) + return TKT_FIL_FMT; + return KSUCCESS; +} + +/* + * tf_get_cred() reads a CREDENTIALS record from a ticket file and fills + * in the given structure "c". It should only be called after tf_init(), + * tf_get_pname(), and tf_get_pinst() have been called. If all goes well, + * KSUCCESS is returned. Possible error codes are: + * + * TKT_FIL_INI - tf_init wasn't called first + * TKT_FIL_FMT - bad format + * EOF - end of file encountered + */ + +tf_get_cred(c) + CREDENTIALS *c; +{ + KTEXT ticket = &c->ticket_st; /* pointer to ticket */ + int k_errno; + + if (fd < 0) { + if (krb_debug) + fprintf(stderr, "tf_get_cred called before tf_init.\n"); + return TKT_FIL_INI; + } + if ((k_errno = tf_gets(c->service, SNAME_SZ)) < 2) + switch (k_errno) { + case TOO_BIG: + case 1: /* can't be just a null */ + tf_close(); + return TKT_FIL_FMT; + case 0: + return EOF; + } + if ((k_errno = tf_gets(c->instance, INST_SZ)) < 1) + switch (k_errno) { + case TOO_BIG: + return TKT_FIL_FMT; + case 0: + return EOF; + } + if ((k_errno = tf_gets(c->realm, REALM_SZ)) < 2) + switch (k_errno) { + case TOO_BIG: + case 1: /* can't be just a null */ + tf_close(); + return TKT_FIL_FMT; + case 0: + return EOF; + } + if ( + tf_read((char *) (c->session), KEY_SZ) < 1 || + tf_read((char *) &(c->lifetime), sizeof(c->lifetime)) < 1 || + tf_read((char *) &(c->kvno), sizeof(c->kvno)) < 1 || + tf_read((char *) &(ticket->length), sizeof(ticket->length)) + < 1 || + /* don't try to read a silly amount into ticket->dat */ + ticket->length > MAX_KTXT_LEN || + tf_read((char *) (ticket->dat), ticket->length) < 1 || + tf_read((char *) &(c->issue_date), sizeof(c->issue_date)) < 1 + ) { + tf_close(); + return TKT_FIL_FMT; + } +#ifdef TKT_SHMEM + bcopy(tmp_shm_addr,c->session,KEY_SZ); + tmp_shm_addr += KEY_SZ; +#endif /* TKT_SHMEM */ + return KSUCCESS; +} + +/* + * tf_close() closes the ticket file and sets "fd" to -1. If "fd" is + * not a valid file descriptor, it just returns. It also clears the + * buffer used to read tickets. + * + * The return value is not defined. + */ + +tf_close() +{ + if (!(fd < 0)) { +#ifdef TKT_SHMEM + if (shmdt(krb_shm_addr)) { + /* what kind of error? */ + if (krb_debug) + fprintf(stderr, "shmdt 0x%x: errno %d",krb_shm_addr, errno); + } else { + krb_shm_addr = 0; + } +#endif TKT_SHMEM + (void) flock(fd, LOCK_UN); + (void) close(fd); + fd = -1; /* see declaration of fd above */ + } + bzero(tfbfr, sizeof(tfbfr)); +} + +/* + * tf_gets() is an internal routine. It takes a string "s" and a count + * "n", and reads from the file until either it has read "n" characters, + * or until it reads a null byte. When finished, what has been read exists + * in "s". If it encounters EOF or an error, it closes the ticket file. + * + * Possible return values are: + * + * n the number of bytes read (including null terminator) + * when all goes well + * + * 0 end of file or read error + * + * TOO_BIG if "count" characters are read and no null is + * encountered. This is an indication that the ticket + * file is seriously ill. + */ + +static +tf_gets(s, n) + register char *s; +{ + register count; + + if (fd < 0) { + if (krb_debug) + fprintf(stderr, "tf_gets called before tf_init.\n"); + return TKT_FIL_INI; + } + for (count = n - 1; count > 0; --count) { + if (curpos >= sizeof(tfbfr)) { + lastpos = read(fd, tfbfr, sizeof(tfbfr)); + curpos = 0; + } + if (curpos == lastpos) { + tf_close(); + return 0; + } + *s = tfbfr[curpos++]; + if (*s++ == '\0') + return (n - count); + } + tf_close(); + return TOO_BIG; +} + +/* + * tf_read() is an internal routine. It takes a string "s" and a count + * "n", and reads from the file until "n" bytes have been read. When + * finished, what has been read exists in "s". If it encounters EOF or + * an error, it closes the ticket file. + * + * Possible return values are: + * + * n the number of bytes read when all goes well + * + * 0 on end of file or read error + */ + +static +tf_read(s, n) + register char *s; + register n; +{ + register count; + + for (count = n; count > 0; --count) { + if (curpos >= sizeof(tfbfr)) { + lastpos = read(fd, tfbfr, sizeof(tfbfr)); + curpos = 0; + } + if (curpos == lastpos) { + tf_close(); + return 0; + } + *s++ = tfbfr[curpos++]; + } + return n; +} + +char *tkt_string(); + +/* + * tf_save_cred() appends an incoming ticket to the end of the ticket + * file. You must call tf_init() before calling tf_save_cred(). + * + * The "service", "instance", and "realm" arguments specify the + * server's name; "session" contains the session key to be used with + * the ticket; "kvno" is the server key version number in which the + * ticket is encrypted, "ticket" contains the actual ticket, and + * "issue_date" is the time the ticket was requested (local host's time). + * + * Returns KSUCCESS if all goes well, TKT_FIL_INI if tf_init() wasn't + * called previously, and KFAILURE for anything else that went wrong. + */ + +tf_save_cred(service, instance, realm, session, lifetime, kvno, + ticket, issue_date) + char *service; /* Service name */ + char *instance; /* Instance */ + char *realm; /* Auth domain */ + C_Block session; /* Session key */ + int lifetime; /* Lifetime */ + int kvno; /* Key version number */ + KTEXT ticket; /* The ticket itself */ + long issue_date; /* The issue time */ +{ + + off_t lseek(); + int count; /* count for write */ +#ifdef TKT_SHMEM + int *skey_check; +#endif /* TKT_SHMEM */ + + if (fd < 0) { /* fd is ticket file as set by tf_init */ + if (krb_debug) + fprintf(stderr, "tf_save_cred called before tf_init.\n"); + return TKT_FIL_INI; + } + /* Find the end of the ticket file */ + (void) lseek(fd, 0L, 2); +#ifdef TKT_SHMEM + /* scan to end of existing keys: pick first 'empty' slot. + we assume that no real keys will be completely zero (it's a weak + key under DES) */ + + skey_check = (int *) krb_shm_addr; + + while (*skey_check && *(skey_check+1)) + skey_check += 2; + tmp_shm_addr = (char *)skey_check; +#endif /* TKT_SHMEM */ + + /* Write the ticket and associated data */ + /* Service */ + count = strlen(service) + 1; + if (write(fd, service, count) != count) + goto bad; + /* Instance */ + count = strlen(instance) + 1; + if (write(fd, instance, count) != count) + goto bad; + /* Realm */ + count = strlen(realm) + 1; + if (write(fd, realm, count) != count) + goto bad; + /* Session key */ +#ifdef TKT_SHMEM + bcopy(session,tmp_shm_addr,8); + tmp_shm_addr+=8; + if (write(fd,krb_dummy_skey,8) != 8) + goto bad; +#else /* ! TKT_SHMEM */ + if (write(fd, (char *) session, 8) != 8) + goto bad; +#endif /* TKT_SHMEM */ + /* Lifetime */ + if (write(fd, (char *) &lifetime, sizeof(int)) != sizeof(int)) + goto bad; + /* Key vno */ + if (write(fd, (char *) &kvno, sizeof(int)) != sizeof(int)) + goto bad; + /* Tkt length */ + if (write(fd, (char *) &(ticket->length), sizeof(int)) != + sizeof(int)) + goto bad; + /* Ticket */ + count = ticket->length; + if (write(fd, (char *) (ticket->dat), count) != count) + goto bad; + /* Issue date */ + if (write(fd, (char *) &issue_date, sizeof(long)) + != sizeof(long)) + goto bad; + + /* Actually, we should check each write for success */ + return (KSUCCESS); +bad: + return (KFAILURE); +} diff --git a/eBones/krb/tkt_string.c b/eBones/krb/tkt_string.c new file mode 100644 index 0000000..ba22db8 --- /dev/null +++ b/eBones/krb/tkt_string.c @@ -0,0 +1,79 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: tkt_string.c,v 4.6 89/01/05 12:31:51 raeburn Exp $ + * $Id: tkt_string.c,v 1.2 1994/07/19 19:26:29 g89r4222 Exp $ + */ + +#ifndef lint +static char *rcsid = +"$Id: tkt_string.c,v 1.2 1994/07/19 19:26:29 g89r4222 Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <sys/types.h> +#include <krb.h> +#include <string.h> +#include <sys/param.h> + +char *getenv(); + +/* + * This routine is used to generate the name of the file that holds + * the user's cache of server tickets and associated session keys. + * + * If it is set, krb_ticket_string contains the ticket file name. + * Otherwise, the filename is constructed as follows: + * + * If it is set, the environment variable "KRBTKFILE" will be used as + * the ticket file name. Otherwise TKT_ROOT (defined in "krb.h") and + * the user's uid are concatenated to produce the ticket file name + * (e.g., "/tmp/tkt123"). A pointer to the string containing the ticket + * file name is returned. + */ + +static char krb_ticket_string[MAXPATHLEN] = ""; + +char *tkt_string() +{ + char *env; + uid_t getuid(); + + if (!*krb_ticket_string) { + if (env = getenv("KRBTKFILE")) { + (void) strncpy(krb_ticket_string, env, + sizeof(krb_ticket_string)-1); + krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0'; + } else { + /* 32 bits of signed integer will always fit in 11 characters + (including the sign), so no need to worry about overflow */ + (void) sprintf(krb_ticket_string, "%s%d",TKT_ROOT,getuid()); + } + } + return krb_ticket_string; +} + +/* + * This routine is used to set the name of the file that holds the user's + * cache of server tickets and associated session keys. + * + * The value passed in is copied into local storage. + * + * NOTE: This routine should be called during initialization, before other + * Kerberos routines are called; otherwise tkt_string() above may be called + * and return an undesired ticket file name until this routine is called. + */ + +void +krb_set_tkt_string(val) +char *val; +{ + + (void) strncpy(krb_ticket_string, val, sizeof(krb_ticket_string)-1); + krb_ticket_string[sizeof(krb_ticket_string)-1] = '\0'; + + return; +} diff --git a/eBones/krb/util.c b/eBones/krb/util.c new file mode 100644 index 0000000..8e48557 --- /dev/null +++ b/eBones/krb/util.c @@ -0,0 +1,72 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <mit-copyright.h>. + * + * Miscellaneous debug printing utilities + * + * from: util.c,v 4.8 89/01/17 22:02:08 wesommer Exp $ + * $Id: util.c,v 1.2 1994/07/19 19:26:31 g89r4222 Exp $ + */ + +#ifndef lint +static char rcsid[] = +"$Id: util.c,v 1.2 1994/07/19 19:26:31 g89r4222 Exp $"; +#endif lint + +#include <krb.h> +#include <des.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdio.h> + +/* + * Print some of the contents of the given authenticator structure + * (AUTH_DAT defined in "krb.h"). Fields printed are: + * + * pname, pinst, prealm, netaddr, flags, cksum, timestamp, session + */ + +ad_print(x) +AUTH_DAT *x; +{ + struct in_addr in; + + /* Print the contents of an auth_dat struct. */ + in.s_addr = x->address; + printf("\n%s %s %s %s flags %u cksum 0x%X\n\ttkt_tm 0x%X sess_key", + x->pname, x->pinst, x->prealm, inet_ntoa(in), x->k_flags, + x->checksum, x->time_sec); + + printf("[8] ="); +#ifdef NOENCRYPTION + placebo_cblock_print(x->session); +#else + des_cblock_print_file(x->session,stdout); +#endif + /* skip reply for now */ +} + +/* + * Print in hex the 8 bytes of the given session key. + * + * Printed format is: " 0x { x, x, x, x, x, x, x, x }" + */ + +#ifdef NOENCRYPTION +placebo_cblock_print(x) + des_cblock x; +{ + unsigned char *y = (unsigned char *) x; + register int i = 0; + + printf(" 0x { "); + + while (i++ <8) { + printf("%x",*y++); + if (i<8) printf(", "); + } + printf(" }"); +} +#endif |