diff options
author | cvs2svn <cvs2svn@FreeBSD.org> | 1995-09-15 20:15:11 +0000 |
---|---|---|
committer | cvs2svn <cvs2svn@FreeBSD.org> | 1995-09-15 20:15:11 +0000 |
commit | bfbc580797babffd502df152b40ad384c9638c2c (patch) | |
tree | d1b8ea42f49e396daa8df631fbbd15a1973c8fdc | |
parent | 93ecce1be0f50592ae4f2c3dc798a862c4fae52c (diff) |
Notes
191 files changed, 34064 insertions, 0 deletions
diff --git a/eBones/Makefile b/eBones/Makefile new file mode 100644 index 0000000000000..8b0b6187903c7 --- /dev/null +++ b/eBones/Makefile @@ -0,0 +1,48 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id$ + +SUBDIR= des include lib libexec usr.bin usr.sbin + +SDIR= ${.CURDIR}/.. + +CODAI= ${MAKE} ${MFLAGS} cleandir; \ + ${MAKE} ${MFLAGS} obj; \ + ${MAKE} ${MFLAGS} depend all install + +CODAD= ${MAKE} ${MFLAGS} MAKE_EBONES=yes cleandir; \ + ${MAKE} ${MFLAGS} MAKE_EBONES=yes obj; \ + ${MAKE} ${MFLAGS} MAKE_EBONES=yes depend all distribute + +# These are the programs which depend on kerberos +kprog: + cd ${SDIR}/bin/rcp; ${CODAI} + cd ${SDIR}/libexec/rlogind; ${CODAI} + cd ${SDIR}/libexec/rshd; ${CODAI} + cd ${SDIR}/sbin/mount_nfs; ${CODAI} + cd ${SDIR}/sbin/nfsd; ${CODAI} + cd ${SDIR}/usr.bin/login; ${CODAI} + cd ${SDIR}/usr.bin/passwd; ${CODAI} + cd ${SDIR}/usr.bin/rlogin; ${CODAI} + cd ${SDIR}/usr.bin/rsh; ${CODAI} + cd ${SDIR}/usr.bin/su; ${CODAI} + +bootstrap: + ( cd include; ${MAKE} ${MFLAGS} install ) + ( cd des; ${MAKE} ${MFLAGS} depend all install ) + ${MAKE} ${MFLAGS} cleandir + ${MAKE} ${MFLAGS} obj + ${MAKE} ${MFLAGS} depend all install kprog + +help-distribute: distribute + cd ${SDIR}/bin/rcp; ${CODAD} + cd ${SDIR}/libexec/rlogind; ${CODAD} + cd ${SDIR}/libexec/rshd; ${CODAD} + cd ${SDIR}/sbin/mount_nfs; ${CODAD} + cd ${SDIR}/sbin/nfsd; ${CODAD} + cd ${SDIR}/usr.bin/login; ${CODAD} + cd ${SDIR}/usr.bin/passwd; ${CODAD} + cd ${SDIR}/usr.bin/rlogin; ${CODAD} + cd ${SDIR}/usr.bin/rsh; ${CODAD} + cd ${SDIR}/usr.bin/su; ${CODAD} + +.include <bsd.subdir.mk> diff --git a/eBones/Makefile.inc b/eBones/Makefile.inc new file mode 100644 index 0000000000000..1dc84372bfe00 --- /dev/null +++ b/eBones/Makefile.inc @@ -0,0 +1,65 @@ +# From: @(#)Makefile.inc 5.1 (Berkeley) 6/25/90 +# $Id: Makefile.inc,v 1.8 1995/09/14 18:16:08 gibbs Exp $ + +DISTRIBUTION= krb + +INCLUDEDIR= ${.CURDIR}/../../include + +.if exists(${.CURDIR}/../../des/obj) +DESOBJDIR= ${.CURDIR}/../../des/obj +.else +DESOBJDIR= ${.CURDIR}/../../des +.endif + +.if exists(${.CURDIR}/../../lib/libkrb/obj) +KRBOBJDIR= ${.CURDIR}/../../lib/libkrb/obj +.else +KRBOBJDIR= ${.CURDIR}/../../lib/libkrb +.endif + +.if exists(${.CURDIR}/../../lib/libkdb/obj) +KDBOBJDIR= ${.CURDIR}/../../lib/libkdb/obj +.else +KDBOBJDIR= ${.CURDIR}/../../lib/libkdb +.endif + +.if exists(${.CURDIR}/../../lib/libacl/obj) +ACLOBJDIR= ${.CURDIR}/../../lib/libacl/obj +.else +ACLOBJDIR= ${.CURDIR}/../../lib/libacl +.endif + +.if exists(${.CURDIR}/../../lib/libkadm/obj) +KADMOBJDIR= ${.CURDIR}/../../lib/libkadm/obj +.else +KADMOBJDIR= ${.CURDIR}/../../lib/libkadm +.endif + +.if exists(${.CURDIR}/../../lib/librkinit/obj) +RKINITOBJDIR= ${.CURDIR}/../../lib/librkinit/obj +.else +RKINITOBJDIR= ${.CURDIR}/../../lib/librkinit +.endif + +CFLAGS+= -I${INCLUDEDIR} -Wall + +COMPILE_ET= compile_et + +${KRBOBJDIR}/krb_err.h: ${.CURDIR}/../../lib/libkrb/krb_err.et + test -e ${KRBOBJDIR}/krb_err.et || ln -s ${.ALLSRC} ${KRBOBJDIR} + cd ${KRBOBJDIR}; compile_et krb_err.et + +CLEANFILES+=${KRBOBJDIR}/krb_err.h ${KRBOBJDIR}/krb_err.c + +${KADMOBJDIR}/kadm_err.h: ${.CURDIR}/../../lib/libkadm/kadm_err.et + test -e ${KADMOBJDIR}/kadm_err.et || ln -s ${.ALLSRC} ${KADMOBJDIR} + cd ${KADMOBJDIR}; compile_et kadm_err.et + +CLEANFILES+=${KADMOBJDIR}/kadm_err.h ${KADMOBJDIR}/kadm_err.c + +${RKINITOBJDIR}/rkinit_err.h: ${.CURDIR}/../../lib/librkinit/rkinit_err.et + test -e ${RKINITOBJDIR}/rkinit_err.et || \ + ln -s ${.ALLSRC} ${RKINITOBJDIR} + cd ${RKINITOBJDIR}; compile_et rkinit_err.et + +CLEANFILES+=${RKINITOBJDIR}/rkinit_err.h ${RKINITOBJDIR}/rkinit_err.c diff --git a/eBones/des/3cbc_enc.c b/eBones/des/3cbc_enc.c new file mode 100644 index 0000000000000..1f64502e99541 --- /dev/null +++ b/eBones/des/3cbc_enc.c @@ -0,0 +1,60 @@ +/* 3cbc_enc.c */ +/* Copyright (C) 1993 Eric Young - see README for more details */ + +/*- + * $Id: 3cbc_enc.c,v 1.1.1.1 1994/09/30 14:49:50 csgr Exp $ + */ + +#include "des_locl.h" + +void +xp(a) +unsigned char *a; +{ int i; for(i=0; i<8; i++) printf("%02X",a[i]);printf("\n");} + +int des_3cbc_encrypt(input,output,length,ks1,ks2,iv1,iv2,encrypt) +des_cblock *input; +des_cblock *output; +long length; +des_key_schedule ks1,ks2; +des_cblock *iv1,*iv2; +int encrypt; + { + int off=length/8-1; + des_cblock niv1,niv2; + +printf("3cbc\n"); +xp(iv1); +xp(iv1); +xp(iv2); +xp(input); + if (encrypt == DES_ENCRYPT) + { + des_cbc_encrypt(input,output,length,ks1,iv1,encrypt); + if (length >= sizeof(des_cblock)) + bcopy(output[off],niv1,sizeof(des_cblock)); + des_cbc_encrypt(output,output,length,ks2,iv1,!encrypt); + des_cbc_encrypt(output,output,length,ks1,iv2, encrypt); + if (length >= sizeof(des_cblock)) + bcopy(output[off],niv2,sizeof(des_cblock)); + bcopy(niv1,*iv1,sizeof(des_cblock)); + } + else + { + if (length >= sizeof(des_cblock)) + bcopy(input[off],niv1,sizeof(des_cblock)); + des_cbc_encrypt(input,output,length,ks1,iv1,encrypt); + des_cbc_encrypt(output,output,length,ks2,iv2,!encrypt); + if (length >= sizeof(des_cblock)) + bcopy(output[off],niv2,sizeof(des_cblock)); + des_cbc_encrypt(output,output,length,ks1,iv2, encrypt); + } + bcopy(niv1,iv1,sizeof(des_cblock)); + bcopy(niv2,iv2,sizeof(des_cblock)); +xp(iv1); +xp(iv1); +xp(iv2); +xp(output); + return(0); + } + diff --git a/eBones/des/3ecb_enc.c b/eBones/des/3ecb_enc.c new file mode 100644 index 0000000000000..4bd22865c6a9d --- /dev/null +++ b/eBones/des/3ecb_enc.c @@ -0,0 +1,35 @@ +/* 3ecb_enc.c */ +/* Copyright (C) 1993 Eric Young - see README for more details */ + +/*- + * $Id: 3ecb_enc.c,v 1.1.1.1 1994/09/30 14:49:50 csgr Exp $ + */ + +#include "des_locl.h" + +int des_3ecb_encrypt(input,output,ks1,ks2,encrypt) +des_cblock *input; +des_cblock *output; +des_key_schedule ks1,ks2; +int encrypt; + { + register unsigned long l0,l1; + register unsigned char *in,*out; + unsigned long ll[2]; + + in=(unsigned char *)input; + out=(unsigned char *)output; + c2l(in,l0); + c2l(in,l1); + ll[0]=l0; + ll[1]=l1; + des_encrypt(ll,ll,ks1,encrypt); + des_encrypt(ll,ll,ks2,!encrypt); + des_encrypt(ll,ll,ks1,encrypt); + l0=ll[0]; + l1=ll[1]; + l2c(l0,out); + l2c(l1,out); + return(0); + } + diff --git a/eBones/des/Makefile b/eBones/des/Makefile new file mode 100644 index 0000000000000..af0859192d5dc --- /dev/null +++ b/eBones/des/Makefile @@ -0,0 +1,27 @@ +# @(#)Makefile 5.4 (Berkeley) 5/7/91 +# $Id: Makefile,v 1.4 1995/09/14 18:16:11 gibbs Exp $ + +LIB= des +SRCS= cbc_cksm.c cbc_enc.c ecb_enc.c enc_read.c enc_writ.c pcbc_enc.c \ + qud_cksm.c rand_key.c read_pwd.c set_key.c str2key.c \ + cfb_enc.c 3ecb_enc.c ofb_enc.c 3cbc_enc.c new_rnd_key.c +#MAN1= des.1 +#MAN3= des.3 + +#LINKS= crypt +CFLAGS+= -DDES_ENCRYPT -DKRBDES_ENCRYPT + +# Kerberos 4? +#CFLAGS+=-DKRB4 +#SRCS+= kerberos.c + +# Kerberos 5? +#CFLAGS+= -DKRB5 +#SRCS+= kerberos5.c + +CFLAGS+= -I${.CURDIR}/include -I${.CURDIR}/../include -DAUTHENTICATE +SHLIB_MAJOR?= 2 +SHLIB_MINOR?= 0 + +.include "/usr/src/lib/Makefile.inc" +.include <bsd.lib.mk> diff --git a/eBones/des/enc_read.c b/eBones/des/enc_read.c new file mode 100644 index 0000000000000..ffd3ba977549c --- /dev/null +++ b/eBones/des/enc_read.c @@ -0,0 +1,150 @@ +/* enc_read.c */ +/* Copyright (C) 1993 Eric Young - see README for more details */ + +/*- + * $Id: enc_read.c,v 1.2 1995/05/30 06:40:11 rgrimes Exp $ + */ + +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> +#include <errno.h> +#include "des_locl.h" + +/* This has some uglies in it but it works - even over sockets. */ +extern int errno; +int des_rw_mode=DES_PCBC_MODE; + +int des_enc_read(fd,buf,len,sched,iv) +int fd; +char *buf; +int len; +des_key_schedule sched; +des_cblock *iv; + { + /* data to be unencrypted */ + int net_num=0; + unsigned char net[BSIZE]; + /* extra unencrypted data + * for when a block of 100 comes in but is des_read one byte at + * a time. */ + static char unnet[BSIZE]; + static int unnet_start=0; + static int unnet_left=0; + int i; + long num=0,rnum; + unsigned char *p; + + /* left over data from last decrypt */ + if (unnet_left != 0) + { + if (unnet_left < len) + { + /* we still still need more data but will return + * with the number of bytes we have - should always + * check the return value */ + bcopy(&(unnet[unnet_start]),buf,unnet_left); + /* eay 26/08/92 I had the next 2 lines + * reversed :-( */ + i=unnet_left; + unnet_start=unnet_left=0; + } + else + { + bcopy(&(unnet[unnet_start]),buf,len); + unnet_start+=len; + unnet_left-=len; + i=len; + } + return(i); + } + + /* We need to get more data. */ + if (len > MAXWRITE) len=MAXWRITE; + + /* first - get the length */ + net_num=0; + while (net_num < HDRSIZE) + { + i=read(fd,&(net[net_num]),HDRSIZE-net_num); + if ((i == -1) && (errno == EINTR)) continue; + if (i <= 0) return(0); + net_num+=i; + } + + /* we now have at net_num bytes in net */ + p=net; + num=0; + n2l(p,num); + /* num should be rounded up to the next group of eight + * we make sure that we have read a multiple of 8 bytes from the net. + */ + if ((num > MAXWRITE) || (num < 0)) /* error */ + return(-1); + rnum=(num < 8)?8:((num+7)/8*8); + + net_num=0; + while (net_num < rnum) + { + i=read(fd,&(net[net_num]),rnum-net_num); + if ((i == -1) && (errno == EINTR)) continue; + if (i <= 0) return(0); + net_num+=i; + } + + /* Check if there will be data left over. */ + if (len < num) + { + if (des_rw_mode & DES_PCBC_MODE) + pcbc_encrypt((des_cblock *)net,(des_cblock *)unnet, + num,sched,iv,DES_DECRYPT); + else + cbc_encrypt((des_cblock *)net,(des_cblock *)unnet, + num,sched,iv,DES_DECRYPT); + bcopy(unnet,buf,len); + unnet_start=len; + unnet_left=num-len; + + /* The following line is done because we return num + * as the number of bytes read. */ + num=len; + } + else + { + /* >output is a multiple of 8 byes, if len < rnum + * >we must be careful. The user must be aware that this + * >routine will write more bytes than he asked for. + * >The length of the buffer must be correct. + * FIXED - Should be ok now 18-9-90 - eay */ + if (len < rnum) + { + char tmpbuf[BSIZE]; + + if (des_rw_mode & DES_PCBC_MODE) + pcbc_encrypt((des_cblock *)net, + (des_cblock *)tmpbuf, + num,sched,iv,DES_DECRYPT); + else + cbc_encrypt((des_cblock *)net, + (des_cblock *)tmpbuf, + num,sched,iv,DES_DECRYPT); + + /* eay 26/08/92 fix a bug that returned more + * bytes than you asked for (returned len bytes :-( */ + bcopy(tmpbuf,buf,num); + } + else + { + if (des_rw_mode & DES_PCBC_MODE) + pcbc_encrypt((des_cblock *)net, + (des_cblock *)buf,num,sched,iv, + DES_DECRYPT); + else + cbc_encrypt((des_cblock *)net, + (des_cblock *)buf,num,sched,iv, + DES_DECRYPT); + } + } + return(num); + } + diff --git a/eBones/des/enc_writ.c b/eBones/des/enc_writ.c new file mode 100644 index 0000000000000..e820e1fd3cb49 --- /dev/null +++ b/eBones/des/enc_writ.c @@ -0,0 +1,99 @@ +/* enc_writ.c */ +/* Copyright (C) 1993 Eric Young - see README for more details */ + +/*- + * $Id: enc_writ.c,v 1.2 1995/05/30 06:40:12 rgrimes Exp $ + */ + +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> +#include <stdlib.h> +#include <time.h> +#include <errno.h> +#include "des_locl.h" + +int des_enc_write(fd,buf,len,sched,iv) +int fd; +char *buf; +int len; +des_key_schedule sched; +des_cblock *iv; + { + long rnum; + int i,j,k,outnum; + char outbuf[BSIZE+HDRSIZE]; + char shortbuf[8]; + char *p; + static int start=1; + + /* If we are sending less than 8 bytes, the same char will look + * the same if we don't pad it out with random bytes */ + if (start) + { + start=0; + srandom(time(NULL)); + } + + /* lets recurse if we want to send the data in small chunks */ + if (len > MAXWRITE) + { + j=0; + for (i=0; i<len; i+=k) + { + k=des_enc_write(fd,&(buf[i]), + ((len-i) > MAXWRITE)?MAXWRITE:(len-i),sched,iv); + if (k < 0) + return(k); + else + j+=k; + } + return(j); + } + + /* write length first */ + p=outbuf; + l2n(len,p); + + /* pad short strings */ + if (len < 8) + { + p=shortbuf; + bcopy(buf,shortbuf,len); + for (i=len; i<8; i++) + shortbuf[i]=random(); + rnum=8; + } + else + { + p=buf; + rnum=((len+7)/8*8); /* round up to nearest eight */ + } + + if (des_rw_mode & DES_PCBC_MODE) + pcbc_encrypt((des_cblock *)p,(des_cblock *)&(outbuf[HDRSIZE]), + (long)((len<8)?8:len),sched,iv,DES_ENCRYPT); + else + cbc_encrypt((des_cblock *)p,(des_cblock *)&(outbuf[HDRSIZE]), + (long)((len<8)?8:len),sched,iv,DES_ENCRYPT); + + /* output */ + outnum=rnum+HDRSIZE; + + for (j=0; j<outnum; j+=i) + { + /* eay 26/08/92 I was not doing writing from where we + * got upto. */ + i=write(fd,&(outbuf[j]),(int)(outnum-j)); + if (i == -1) + { + if (errno == EINTR) + i=0; + else /* This is really a bad error - very bad + * It will stuff-up both ends. */ + return(-1); + } + } + + return(len); + } diff --git a/eBones/des/new_rnd_key.c b/eBones/des/new_rnd_key.c new file mode 100644 index 0000000000000..18335289b4faf --- /dev/null +++ b/eBones/des/new_rnd_key.c @@ -0,0 +1,207 @@ +/* + * $Source: /home/ncvs/src/eBones/des/new_rnd_key.c,v $ + * $Author: rgrimes $ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * <mit-copyright.h>. + * + * New pseudo-random key generator, using DES encryption to make the + * pseudo-random cycle as hard to break as DES. + * + * Written by Mark Lillibridge, MIT Project Athena + * + * Under U.S. law, this software may not be exported outside the US + * without license from the U.S. Commerce department. + */ + +#ifndef lint +static char rcsid_new_rnd_key_c[] = +"$Header: /home/ncvs/src/eBones/des/new_rnd_key.c,v 1.1.1.1 1994/05/27 05:12:12 rgrimes Exp $"; +#endif lint + +#include <mit-copyright.h> + +#include <des.h> +#include "des_locl.h" + +void des_set_random_generator_seed(), des_set_sequence_number(); +void des_generate_random_block(); + +/* + * des_new_random_key: create a random des key + * + * Requires: des_set_random_number_generater_seed must be at called least + * once before this routine is called. + * + * Notes: the returned key has correct parity and is guarenteed not + * to be a weak des key. Des_generate_random_block is used to + * provide the random bits. + */ +int +des_new_random_key(key) + des_cblock *key; +{ + do { + des_generate_random_block(key); + des_fixup_key_parity(key); + } while (des_is_weak_key(key)); + + return(0); +} + +/* + * des_init_random_number_generator: + * + * This routine takes a secret key possibly shared by a number + * of servers and uses it to generate a random number stream that is + * not shared by any of the other servers. It does this by using the current + * process id, host id, and the current time to the nearest second. The + * resulting stream seed is not useful information for cracking the secret + * key. Moreover, this routine keeps no copy of the secret key. + * This routine is used for example, by the kerberos server(s) with the + * key in question being the kerberos master key. + * + * Note: this routine calls des_set_random_generator_seed. + */ +#if NOTBSDUNIX + you lose... (aka, you get to implement an analog of this for your + system...) +#else + +#include <sys/time.h> + +void des_init_random_number_generator(key) + des_cblock *key; +{ + struct { /* This must be 64 bits exactly */ + long process_id; + long host_id; + } seed; + struct timeval time; /* this must also be 64 bits exactly */ + des_cblock new_key; + long gethostid(); + + /* + * use a host id and process id in generating the seed to ensure + * that different servers have different streams: + */ + seed.host_id = gethostid(); + seed.process_id = getpid(); + + /* + * Generate a tempory value that depends on the key, host_id, and + * process_id such that it gives no useful information about the key: + */ + des_set_random_generator_seed(key); + des_set_sequence_number((unsigned char *)&seed); + des_new_random_key(&new_key); + + /* + * use it to select a random stream: + */ + des_set_random_generator_seed(&new_key); + + /* + * use a time stamp to ensure that a server started later does not reuse + * an old stream: + */ + gettimeofday(&time, (struct timezone *)0); + des_set_sequence_number((unsigned char *)&time); + + /* + * use the time stamp finally to select the final seed using the + * current random number stream: + */ + des_new_random_key(&new_key); + des_set_random_generator_seed(&new_key); +} + +#endif /* ifdef BSDUNIX */ + +/* + * This module implements a random number generator faculty such that the next + * number in any random number stream is very hard to predict without knowing + * the seed for that stream even given the preceeding random numbers. + */ + +/* + * The secret des key schedule for the current stream of random numbers: + */ +static des_key_schedule random_sequence_key; + +/* + * The sequence # in the current stream of random numbers: + */ +static unsigned char sequence_number[8]; + +/* + * des_set_random_generator_seed: this routine is used to select a random + * number stream. The stream that results is + * totally determined by the passed in key. + * (I.e., calling this routine again with the + * same key allows repeating a sequence of + * random numbers) + * + * Requires: key is a valid des key. I.e., has correct parity and is not a + * weak des key. + */ +void +des_set_random_generator_seed(key) + des_cblock *key; +{ + register int i; + + /* select the new stream: (note errors are not possible here...) */ + des_key_sched(key, random_sequence_key); + + /* "seek" to the start of the stream: */ + for (i=0; i<8; i++) + sequence_number[i] = 0; +} + +/* + * des_set_sequence_number: this routine is used to set the sequence number + * of the current random number stream. This routine + * may be used to "seek" within the current random + * number stream. + * + * Note that des_set_random_generator_seed resets the sequence number to 0. + */ +void +des_set_sequence_number(new_sequence_number) + des_cblock new_sequence_number; +{ + bcopy((char *)new_sequence_number, (char *)sequence_number, + sizeof(sequence_number)); +} + +/* + * des_generate_random_block: routine to return the next random number + * from the current random number stream. + * The returned number is 64 bits long. + * + * Requires: des_set_random_generator_seed must have been called at least once + * before this routine is called. + */ +void des_generate_random_block(block) + des_cblock *block; +{ + int i; + + /* + * Encrypt the sequence number to get the new random block: + */ + des_ecb_encrypt(&sequence_number, block, random_sequence_key, 1); + + /* + * Increment the sequence number as an 8 byte unsigned number with wrap: + * (using LSB here) + */ + for (i=0; i<8; i++) { + sequence_number[i] = (sequence_number[i] + 1) & 0xff; + if (sequence_number[i]) + break; + } +} diff --git a/eBones/des/rand_key.c b/eBones/des/rand_key.c new file mode 100644 index 0000000000000..30369febd1f8c --- /dev/null +++ b/eBones/des/rand_key.c @@ -0,0 +1,49 @@ +/* rand_key.c */ +/* Copyright (C) 1993 Eric Young - see README for more details */ + +/*- + * $Id: rand_key.c,v 1.2 1995/05/09 18:05:15 wollman Exp $ + */ + +#include <sys/types.h> +#include <sys/time.h> +#include <unistd.h> +#include "des_locl.h" + +int des_random_key(ret) +des_cblock ret; + { + des_key_schedule ks; + static unsigned long c=0; + static unsigned short pid=0; + static des_cblock data={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef}; + des_cblock key; + unsigned char *p; + unsigned long t; + +#ifdef MSDOS + pid=1; +#else + if (!pid) pid=getpid(); +#endif + p=key; + t=(unsigned long)time(NULL); + l2c(t,p); + t=(unsigned long)((pid)|((c++)<<16)); + l2c(t,p); + + des_set_odd_parity((des_cblock *)data); + des_set__key((des_cblock *)data,ks); + des_cbc_cksum((des_cblock *)key,(des_cblock *)key, + (long)sizeof(key),ks,(des_cblock *)data); + des_set_odd_parity((des_cblock *)key); + des_cbc_cksum((des_cblock *)key,(des_cblock *)key, + (long)sizeof(key),ks,(des_cblock *)data); + des_set_odd_parity((des_cblock *)key); + + bcopy(key,ret,sizeof(key)); + bzero(key,sizeof(key)); + bzero(ks,sizeof(ks)); + t=0; + return(0); + } diff --git a/eBones/include/Makefile b/eBones/include/Makefile new file mode 100644 index 0000000000000..0e95002dd3a79 --- /dev/null +++ b/eBones/include/Makefile @@ -0,0 +1,19 @@ +# from: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1995/09/13 17:23:44 markm Exp $ + +FILES= kparse.h krb.h krb_db.h des.h + +# mit-copyright.h kadm_err.h krb_err.h + +NOOBJ= noobj +NOMAN= noman + +all include clean cleandir depend lint tags: + +beforeinstall: + -cd ${.CURDIR}; for file in ${FILES}; do \ + cmp -s $$file ${DESTDIR}/usr/include/kerberosIV/$$file || \ + install -c -o ${BINOWN} -g ${BINGRP} -m 444 $$file \ + ${DESTDIR}/usr/include/kerberosIV; done + +.include <bsd.prog.mk> diff --git a/eBones/include/des.h b/eBones/include/des.h new file mode 100644 index 0000000000000..7a44374b428bc --- /dev/null +++ b/eBones/include/des.h @@ -0,0 +1,181 @@ +/* des.h */ +/* Copyright (C) 1995 Eric Young (eay@mincom.oz.au). + * All rights reserved. + * Copyright remains Eric Young's, and as such any Copyright notices in + * the code are not to be removed. + * See the COPYRIGHT file in the libdes distribution for more details. + */ + +#ifndef HEADER_DES_H +#define HEADER_DES_H + +#include <stdio.h> + +typedef unsigned char des_cblock[8]; +typedef struct des_ks_struct { des_cblock _; } des_key_schedule[16]; + +#define DES_KEY_SZ (sizeof(des_cblock)) +#define DES_SCHEDULE_SZ (sizeof(des_key_schedule)) + +#define DES_ENCRYPT 1 +#define DES_DECRYPT 0 + +#define DES_CBC_MODE 0 +#define DES_PCBC_MODE 1 + +#define C_Block des_cblock +#define Key_schedule des_key_schedule +#define ENCRYPT DES_ENCRYPT +#define DECRYPT DES_DECRYPT +#define KEY_SZ DES_KEY_SZ +#define string_to_key des_string_to_key +#define read_pw_string des_read_pw_string +#define random_key des_random_key +#define pcbc_encrypt des_pcbc_encrypt +#define set_key des_set_key +#define key_sched des_key_sched +#define ecb_encrypt des_ecb_encrypt +#define cbc_encrypt des_cbc_encrypt +#define ncbc_encrypt des_ncbc_encrypt +#define cbc_cksum des_cbc_cksum +#define quad_cksum des_quad_cksum + +/* For compatibility with the MIT lib - eay 20/05/92 */ +typedef struct des_ks_struct bit_64; +#define des_fixup_key_parity des_set_odd_parity +#define des_check_key_parity check_parity + +extern int des_check_key; /* defaults to false */ +extern int des_rw_mode; /* defaults to DES_PCBC_MODE */ + +/* The next line is used to disable full ANSI prototypes, if your + * compiler has problems with the prototypes, make sure this line always + * evaluates to true :-) */ +#if defined(MSDOS) && defined(__STDC__) +#undef PROTO +#define PROTO +#endif + +/* markm - dirty hack */ +#define PROTO + +#ifdef PROTO +int des_2ecb_encrypt(des_cblock *input,des_cblock *output, + des_key_schedule ks1,des_key_schedule ks2,int enc); +int des_3ecb_encrypt(des_cblock *input,des_cblock *output, + des_key_schedule ks1,des_key_schedule ks2, int enc); +unsigned long des_cbc_cksum(des_cblock *input,des_cblock *output, + long length,des_key_schedule schedule,des_cblock *ivec); +int des_cbc_encrypt(des_cblock *input,des_cblock *output,long length, + des_key_schedule schedule,des_cblock *ivec,int enc); +int des_ncbc_encrypt(des_cblock *input,des_cblock *output,long length, + des_key_schedule schedule,des_cblock *ivec,int enc); +int des_3cbc_encrypt(des_cblock *input,des_cblock *output,long length, + des_key_schedule sk1,des_key_schedule sk2, + des_cblock *ivec1,des_cblock *ivec2,int enc); +int des_cfb_encrypt(unsigned char *in,unsigned char *out,int numbits, + long length,des_key_schedule schedule,des_cblock *ivec,int enc); +int des_ecb_encrypt(des_cblock *input,des_cblock *output, + des_key_schedule ks,int enc); +int des_encrypt(unsigned long *input,unsigned long *output, + des_key_schedule ks, int enc); +int des_encrypt2(unsigned long *input,unsigned long *output, + des_key_schedule ks, int enc); +int des_ede3_cbc_encrypt(des_cblock *input, des_cblock *output, + long length, des_key_schedule ks1, des_key_schedule ks2, + des_key_schedule ks3, des_cblock *ivec, int enc); +int des_ede2_cbc_encrypt(des_cblock *input, des_cblock *output, + long length, des_key_schedule ks1, des_key_schedule ks2, + des_cblock *ivec, int enc); +int des_enc_read(int fd,char *buf,int len,des_key_schedule sched, + des_cblock *iv); +int des_enc_write(int fd,char *buf,int len,des_key_schedule sched, + des_cblock *iv); +#if 0 +#ifdef PERL5 +char *des_crypt(const char *buf,const char *salt); +#else +/* some stupid compilers complain because I have declared char instead + * of const char */ +#ifdef HEADER_DES_LOCL_H +char *crypt(const char *buf,const char *salt); +#else +char *crypt(); +#endif /* HEADER_DES_LOCL_H */ +#endif /* PERL5 */ +#endif /* 0 */ + +int des_ofb_encrypt(unsigned char *in,unsigned char *out, + int numbits,long length,des_key_schedule schedule,des_cblock *ivec); +int des_pcbc_encrypt(des_cblock *input,des_cblock *output,long length, + des_key_schedule schedule,des_cblock *ivec,int enc); +unsigned long des_quad_cksum(des_cblock *input,des_cblock *output, + long length,int out_count,des_cblock *seed); +void des_random_seed(des_cblock key); +int des_random_key(des_cblock ret); +int des_read_password(des_cblock *key,char *prompt,int verify); +int des_read_2passwords(des_cblock *key1,des_cblock *key2, + char *prompt,int verify); +int des_read_pw_string(char *buf,int length,char *prompt,int verify); +void des_set_odd_parity(des_cblock *key); +int des_is_weak_key(des_cblock *key); +int des_set_key(des_cblock *key,des_key_schedule schedule); +int des_key_sched(des_cblock *key,des_key_schedule schedule); +int des_string_to_key(char *str,des_cblock *key); +int des_string_to_2keys(char *str,des_cblock *key1,des_cblock *key2); +int des_cfb64_encrypt(unsigned char *in, unsigned char *out, long length, + des_key_schedule schedule, des_cblock *ivec, int *num, int enc); +int des_ofb64_encrypt(unsigned char *in, unsigned char *out, long length, + des_key_schedule schedule, des_cblock *ivec, int *num); +void des_cblock_print_file(des_cblock *cb, FILE *fp); +int des_new_random_key(des_cblock *key); +void des_init_random_number_generator(des_cblock *key); +void des_set_random_generator_seed(des_cblock *key); +void des_set_sequence_number(des_cblock new_sequence_number); +void des_generate_random_block(des_cblock *block); + +#else + +int des_2ecb_encrypt(); +int des_3ecb_encrypt(); +unsigned long des_cbc_cksum(); +int des_cbc_encrypt(); +int des_ncbc_encrypt(); +int des_3cbc_encrypt(); +int des_cfb_encrypt(); +int des_ecb_encrypt(); +int des_encrypt(); +int des_encrypt2(); +int des_ede3_cbc_encrypt(); +int des_ede2_cbc_encrypt(); +int des_enc_read(); +int des_enc_write(); +#ifdef PERL5 +char *des_crypt(); +#else +char *crypt(); +#endif +int des_ofb_encrypt(); +int des_pcbc_encrypt(); +unsigned long des_quad_cksum(); +void des_random_seed(); +int des_random_key(); +int des_read_password(); +int des_read_2passwords(); +int des_read_pw_string(); +void des_set_odd_parity(); +int des_is_weak_key(); +int des_set_key(); +int des_key_sched(); +int des_string_to_key(); +int des_string_to_2keys(); +int des_cfb64_encrypt(); +int des_ofb64_encrypt(); +void des_cblock_print_file(); +int des_new_random_key(); +void des_init_random_number_generator(); +void des_set_random_generator_seed(); +void des_set_sequence_number(); +void des_generate_random_block(); +#endif +#endif diff --git a/eBones/include/kparse.h b/eBones/include/kparse.h new file mode 100644 index 0000000000000..d506d9dc3b312 --- /dev/null +++ b/eBones/include/kparse.h @@ -0,0 +1,91 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * Include file for kparse routines. + * + * from: kparse.h,v 4.5 89/01/11 12:05:53 steiner Exp $ + * $Id: kparse.h,v 1.4 1995/09/07 20:50:34 mark Exp $ + */ + +#ifndef KPARSE_DEFS +#define KPARSE_DEFS + +/* + * values returned by fGetParameterSet() + */ + +#define PS_BAD_KEYWORD -2 /* unknown or duplicate keyword */ +#define PS_SYNTAX -1 /* syntax error */ +#define PS_OKAY 0 /* got a complete parameter set */ +#define PS_EOF 1 /* nothing more in the file */ + +/* + * values returned by fGetKeywordValue() + */ + +#define KV_SYNTAX -2 /* syntax error */ +#define KV_EOF -1 /* nothing more in the file */ +#define KV_OKAY 0 /* got a keyword/value pair */ +#define KV_EOL 1 /* nothing more on this line */ + +/* + * values returned by fGetToken() + */ + +#define GTOK_BAD_QSTRING -1 /* newline found in quoted string */ +#define GTOK_EOF 0 /* end of file encountered */ +#define GTOK_QSTRING 1 /* quoted string */ +#define GTOK_STRING 2 /* unquoted string */ +#define GTOK_NUMBER 3 /* one or more digits */ +#define GTOK_PUNK 4 /* punks are punctuation, newline, + * etc. */ +#define GTOK_WHITE 5 /* one or more whitespace chars */ + +/* + * extended character classification macros + */ + +#define ISOCTAL(CH) ( (CH>='0') && (CH<='7') ) +#define ISQUOTE(CH) ( (CH=='\"') || (CH=='\'') || (CH=='`') ) +#define ISWHITESPACE(C) ( (C==' ') || (C=='\t') ) +#define ISLINEFEED(C) ( (C=='\n') || (C=='\r') || (C=='\f') ) + +/* + * tokens consist of any printable charcacter except comma, equal, or + * whitespace + */ + +#define ISTOKENCHAR(C) ((C>040) && (C<0177) && (C != ',') && (C != '=')) + +/* + * the parameter table defines the keywords that will be recognized by + * fGetParameterSet, and their default values if not specified. + */ + +typedef struct { + char *keyword; + char *defvalue; + char *value; +} parmtable; + +#define PARMCOUNT(P) (sizeof(P)/sizeof(P[0])) + +extern int LineNbr; /* current line # in parameter file */ + +extern char ErrorMsg[]; /* + * meaningful only when KV_SYNTAX, + * PS_SYNTAX, or PS_BAD_KEYWORD is + * returned by fGetKeywordValue or + * fGetParameterSet + */ + +extern char *strsave(char *p); /* defined in this module */ +extern char *strutol(char *p); /* defined in this module */ + +int fGetParameterSet(FILE *fp, parmtable parm[], int parmcount); +int fGetKeywordValue(FILE *fp, char *keyword, int klen, char *value, int vlen); +int fGetToken(FILE *fp, char *dest, int maxlen); + +#endif /* KPARSE_DEFS */ diff --git a/eBones/include/krb.h b/eBones/include/krb.h new file mode 100644 index 0000000000000..0b1ae090a2ab1 --- /dev/null +++ b/eBones/include/krb.h @@ -0,0 +1,504 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * Include file for the Kerberos library. + * + * from: krb.h,v 4.26 89/08/08 17:55:25 jtkohl Exp $ + * $Id: krb.h,v 1.7 1995/09/07 20:50:36 mark Exp $ + */ + +/* Only one time, please */ +#ifndef KRB_DEFS +#define KRB_DEFS + +/* Need some defs from des.h */ +#include <stdio.h> +#include <kerberosIV/des.h> +#include <netinet/in.h> + +/* Text describing error codes */ +#define MAX_KRB_ERRORS 256 +extern char *krb_err_txt[MAX_KRB_ERRORS]; + +/* These are not defined for at least SunOS 3.3 and Ultrix 2.2 */ +#if defined(ULTRIX022) || (defined(SunOS) && SunOS < 40) +#define FD_ZERO(p) ((p)->fds_bits[0] = 0) +#define FD_SET(n, p) ((p)->fds_bits[0] |= (1 << (n))) +#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1 << (n))) +#endif /* ULTRIX022 || SunOS */ + +/* General definitions */ +#define KSUCCESS 0 +#define KFAILURE 255 + +#ifdef NO_UIDGID_T +typedef unsigned short uid_t; +typedef unsigned short gid_t; +#endif /* NO_UIDGID_T */ + +/* + * Kerberos specific definitions + * + * KRBLOG is the log file for the kerberos master server. KRB_CONF is + * the configuration file where different host machines running master + * and slave servers can be found. KRB_MASTER is the name of the + * machine with the master database. The admin_server runs on this + * machine, and all changes to the db (as opposed to read-only + * requests, which can go to slaves) must go to it. KRB_HOST is the + * default machine * when looking for a kerberos slave server. Other + * possibilities are * in the KRB_CONF file. KRB_REALM is the name of + * the realm. + */ + +#ifdef notdef +this is server - only, does not belong here; +#define KRBLOG "/etc/kerberosIV/kerberos.log" +are these used anyplace '?'; +#define VX_KRB_HSTFILE "/etc/krbhst" +#define PC_KRB_HSTFILE "\\kerberos\\krbhst" +#endif + +#define KRB_CONF "/etc/kerberosIV/krb.conf" +#define KRB_RLM_TRANS "/etc/kerberosIV/krb.realms" +#define KRB_MASTER "kerberos" +#define KRB_HOST KRB_MASTER +#define KRB_REALM "ATHENA.MIT.EDU" + +/* The maximum sizes for aname, realm, sname, and instance +1 */ +#define ANAME_SZ 40 +#define REALM_SZ 40 +#define SNAME_SZ 40 +#define INST_SZ 40 +/* include space for '.' and '@' */ +#define MAX_K_NAME_SZ (ANAME_SZ + INST_SZ + REALM_SZ + 2) +#define KKEY_SZ 100 +#define VERSION_SZ 1 +#define MSG_TYPE_SZ 1 +#define DATE_SZ 26 /* RTI date output */ + +#define MAX_HSTNM 100 + +#ifndef DEFAULT_TKT_LIFE /* allow compile-time override */ +#define DEFAULT_TKT_LIFE 96 /* default lifetime for krb_mk_req + & co., 8 hrs */ +#endif + +/* Definition of text structure used to pass text around */ +#define MAX_KTXT_LEN 1250 + +struct ktext { + int length; /* Length of the text */ + unsigned char dat[MAX_KTXT_LEN]; /* The data itself */ + unsigned long mbz; /* zero to catch runaway strings */ +}; + +typedef struct ktext *KTEXT; +typedef struct ktext KTEXT_ST; + + +/* Definitions for send_to_kdc */ +#define CLIENT_KRB_TIMEOUT 4 /* time between retries */ +#define CLIENT_KRB_RETRY 5 /* retry this many times */ +#define CLIENT_KRB_BUFLEN 512 /* max unfragmented packet */ + +/* Definitions for ticket file utilities */ +#define R_TKT_FIL 0 +#define W_TKT_FIL 1 + +/* Definitions for cl_get_tgt */ +#ifdef PC +#define CL_GTGT_INIT_FILE "\\kerberos\\k_in_tkts" +#else +#define CL_GTGT_INIT_FILE "/etc/k_in_tkts" +#endif PC + +/* Parameters for rd_ap_req */ +/* Maximum alloable clock skew in seconds */ +#define CLOCK_SKEW 5*60 +/* Filename for readservkey */ +#define KEYFILE "/etc/kerberosIV/srvtab" + +/* Structure definition for rd_ap_req */ + +struct auth_dat { + unsigned char k_flags; /* Flags from ticket */ + char pname[ANAME_SZ]; /* Principal's name */ + char pinst[INST_SZ]; /* His Instance */ + char prealm[REALM_SZ]; /* His Realm */ + unsigned long checksum; /* Data checksum (opt) */ + C_Block session; /* Session Key */ + int life; /* Life of ticket */ + unsigned long time_sec; /* Time ticket issued */ + unsigned long address; /* Address in ticket */ + KTEXT_ST reply; /* Auth reply (opt) */ +}; + +typedef struct auth_dat AUTH_DAT; + +/* Structure definition for credentials returned by get_cred */ + +struct credentials { + char service[ANAME_SZ]; /* Service name */ + char instance[INST_SZ]; /* Instance */ + char realm[REALM_SZ]; /* Auth domain */ + C_Block session; /* Session key */ + int lifetime; /* Lifetime */ + int kvno; /* Key version number */ + KTEXT_ST ticket_st; /* The ticket itself */ + long issue_date; /* The issue time */ + char pname[ANAME_SZ]; /* Principal's name */ + char pinst[INST_SZ]; /* Principal's instance */ +}; + +typedef struct credentials CREDENTIALS; + +/* Structure definition for rd_private_msg and rd_safe_msg */ + +struct msg_dat { + unsigned char *app_data; /* pointer to appl data */ + unsigned long app_length; /* length of appl data */ + unsigned long hash; /* hash to lookup replay */ + int swap; /* swap bytes? */ + long time_sec; /* msg timestamp seconds */ + unsigned char time_5ms; /* msg timestamp 5ms units */ +}; + +typedef struct msg_dat MSG_DAT; + + +/* Location of ticket file for save_cred and get_cred */ +#ifdef PC +#define TKT_FILE "\\kerberos\\ticket.ses" +#else +#define TKT_FILE tkt_string() +#define TKT_ROOT "/tmp/tkt" +#endif PC + +/* Error codes returned from the KDC */ +#define KDC_OK 0 /* Request OK */ +#define KDC_NAME_EXP 1 /* Principal expired */ +#define KDC_SERVICE_EXP 2 /* Service expired */ +#define KDC_AUTH_EXP 3 /* Auth expired */ +#define KDC_PKT_VER 4 /* Protocol version unknown */ +#define KDC_P_MKEY_VER 5 /* Wrong master key version */ +#define KDC_S_MKEY_VER 6 /* Wrong master key version */ +#define KDC_BYTE_ORDER 7 /* Byte order unknown */ +#define KDC_PR_UNKNOWN 8 /* Principal unknown */ +#define KDC_PR_N_UNIQUE 9 /* Principal not unique */ +#define KDC_NULL_KEY 10 /* Principal has null key */ +#define KDC_GEN_ERR 20 /* Generic error from KDC */ + + +/* Values returned by get_credentials */ +#define GC_OK 0 /* Retrieve OK */ +#define RET_OK 0 /* Retrieve OK */ +#define GC_TKFIL 21 /* Can't read ticket file */ +#define RET_TKFIL 21 /* Can't read ticket file */ +#define GC_NOTKT 22 /* Can't find ticket or TGT */ +#define RET_NOTKT 22 /* Can't find ticket or TGT */ + + +/* Values returned by mk_ap_req */ +#define MK_AP_OK 0 /* Success */ +#define MK_AP_TGTEXP 26 /* TGT Expired */ + +/* Values returned by rd_ap_req */ +#define RD_AP_OK 0 /* Request authentic */ +#define RD_AP_UNDEC 31 /* Can't decode authenticator */ +#define RD_AP_EXP 32 /* Ticket expired */ +#define RD_AP_NYV 33 /* Ticket not yet valid */ +#define RD_AP_REPEAT 34 /* Repeated request */ +#define RD_AP_NOT_US 35 /* The ticket isn't for us */ +#define RD_AP_INCON 36 /* Request is inconsistent */ +#define RD_AP_TIME 37 /* delta_t too big */ +#define RD_AP_BADD 38 /* Incorrect net address */ +#define RD_AP_VERSION 39 /* protocol version mismatch */ +#define RD_AP_MSG_TYPE 40 /* invalid msg type */ +#define RD_AP_MODIFIED 41 /* message stream modified */ +#define RD_AP_ORDER 42 /* message out of order */ +#define RD_AP_UNAUTHOR 43 /* unauthorized request */ + +/* Values returned by get_pw_tkt */ +#define GT_PW_OK 0 /* Got password changing tkt */ +#define GT_PW_NULL 51 /* Current PW is null */ +#define GT_PW_BADPW 52 /* Incorrect current password */ +#define GT_PW_PROT 53 /* Protocol Error */ +#define GT_PW_KDCERR 54 /* Error returned by KDC */ +#define GT_PW_NULLTKT 55 /* Null tkt returned by KDC */ + + +/* Values returned by send_to_kdc */ +#define SKDC_OK 0 /* Response received */ +#define SKDC_RETRY 56 /* Retry count exceeded */ +#define SKDC_CANT 57 /* Can't send request */ + +/* + * Values returned by get_intkt + * (can also return SKDC_* and KDC errors) + */ + +#define INTK_OK 0 /* Ticket obtained */ +#define INTK_W_NOTALL 61 /* Not ALL tickets returned */ +#define INTK_BADPW 62 /* Incorrect password */ +#define INTK_PROT 63 /* Protocol Error */ +#define INTK_ERR 70 /* Other error */ + +/* Values returned by get_adtkt */ +#define AD_OK 0 /* Ticket Obtained */ +#define AD_NOTGT 71 /* Don't have tgt */ + +/* Error codes returned by ticket file utilities */ +#define NO_TKT_FIL 76 /* No ticket file found */ +#define TKT_FIL_ACC 77 /* Couldn't access tkt file */ +#define TKT_FIL_LCK 78 /* Couldn't lock ticket file */ +#define TKT_FIL_FMT 79 /* Bad ticket file format */ +#define TKT_FIL_INI 80 /* tf_init not called first */ + +/* Error code returned by kparse_name */ +#define KNAME_FMT 81 /* Bad Kerberos name format */ + +/* Error code returned by krb_mk_safe */ +#define SAFE_PRIV_ERROR -1 /* syscall error */ + +/* + * macros for byte swapping; also scratch space + * u_quad 0-->7, 1-->6, 2-->5, 3-->4, 4-->3, 5-->2, 6-->1, 7-->0 + * u_long 0-->3, 1-->2, 2-->1, 3-->0 + * u_short 0-->1, 1-->0 + */ + +#define swap_u_16(x) {\ + unsigned long _krb_swap_tmp[4];\ + swab(((char *) x) +0, ((char *) _krb_swap_tmp) +14 ,2); \ + swab(((char *) x) +2, ((char *) _krb_swap_tmp) +12 ,2); \ + swab(((char *) x) +4, ((char *) _krb_swap_tmp) +10 ,2); \ + swab(((char *) x) +6, ((char *) _krb_swap_tmp) +8 ,2); \ + swab(((char *) x) +8, ((char *) _krb_swap_tmp) +6 ,2); \ + swab(((char *) x) +10,((char *) _krb_swap_tmp) +4 ,2); \ + swab(((char *) x) +12,((char *) _krb_swap_tmp) +2 ,2); \ + swab(((char *) x) +14,((char *) _krb_swap_tmp) +0 ,2); \ + bcopy((char *)_krb_swap_tmp,(char *)x,16);\ + } + +#define swap_u_12(x) {\ + unsigned long _krb_swap_tmp[4];\ + swab(( char *) x, ((char *) _krb_swap_tmp) +10 ,2); \ + swab(((char *) x) +2, ((char *) _krb_swap_tmp) +8 ,2); \ + swab(((char *) x) +4, ((char *) _krb_swap_tmp) +6 ,2); \ + swab(((char *) x) +6, ((char *) _krb_swap_tmp) +4 ,2); \ + swab(((char *) x) +8, ((char *) _krb_swap_tmp) +2 ,2); \ + swab(((char *) x) +10,((char *) _krb_swap_tmp) +0 ,2); \ + bcopy((char *)_krb_swap_tmp,(char *)x,12);\ + } + +#define swap_C_Block(x) {\ + unsigned long _krb_swap_tmp[4];\ + swab(( char *) x, ((char *) _krb_swap_tmp) +6 ,2); \ + swab(((char *) x) +2,((char *) _krb_swap_tmp) +4 ,2); \ + swab(((char *) x) +4,((char *) _krb_swap_tmp) +2 ,2); \ + swab(((char *) x) +6,((char *) _krb_swap_tmp) ,2); \ + bcopy((char *)_krb_swap_tmp,(char *)x,8);\ + } +#define swap_u_quad(x) {\ + unsigned long _krb_swap_tmp[4];\ + swab(( char *) &x, ((char *) _krb_swap_tmp) +6 ,2); \ + swab(((char *) &x) +2,((char *) _krb_swap_tmp) +4 ,2); \ + swab(((char *) &x) +4,((char *) _krb_swap_tmp) +2 ,2); \ + swab(((char *) &x) +6,((char *) _krb_swap_tmp) ,2); \ + bcopy((char *)_krb_swap_tmp,(char *)&x,8);\ + } + +#define swap_u_long(x) {\ + unsigned long _krb_swap_tmp[4];\ + swab((char *) &x, ((char *) _krb_swap_tmp) +2 ,2); \ + swab(((char *) &x) +2,((char *) _krb_swap_tmp),2); \ + x = _krb_swap_tmp[0]; \ + } + +#define swap_u_short(x) {\ + unsigned short _krb_swap_sh_tmp; \ + swab((char *) &x, ( &_krb_swap_sh_tmp) ,2); \ + x = (unsigned short) _krb_swap_sh_tmp; \ + } + +/* Kerberos ticket flag field bit definitions */ +#define K_FLAG_ORDER 0 /* bit 0 --> lsb */ +#define K_FLAG_1 /* reserved */ +#define K_FLAG_2 /* reserved */ +#define K_FLAG_3 /* reserved */ +#define K_FLAG_4 /* reserved */ +#define K_FLAG_5 /* reserved */ +#define K_FLAG_6 /* reserved */ +#define K_FLAG_7 /* reserved, bit 7 --> msb */ + +#ifndef PC +char *tkt_string(); +#endif PC + +#ifdef OLDNAMES +#define krb_mk_req mk_ap_req +#define krb_rd_req rd_ap_req +#define krb_kntoln an_to_ln +#define krb_set_key set_serv_key +#define krb_get_cred get_credentials +#define krb_mk_priv mk_private_msg +#define krb_rd_priv rd_private_msg +#define krb_mk_safe mk_safe_msg +#define krb_rd_safe rd_safe_msg +#define krb_mk_err mk_appl_err_msg +#define krb_rd_err rd_appl_err_msg +#define krb_ck_repl check_replay +#define krb_get_pw_in_tkt get_in_tkt +#define krb_get_svc_in_tkt get_svc_in_tkt +#define krb_get_pw_tkt get_pw_tkt +#define krb_realmofhost krb_getrealm +#define krb_get_phost get_phost +#define krb_get_krbhst get_krbhst +#define krb_get_lrealm get_krbrlm +#endif OLDNAMES + +/* Defines for krb_sendauth and krb_recvauth */ + +#define KOPT_DONT_MK_REQ 0x00000001 /* don't call krb_mk_req */ +#define KOPT_DO_MUTUAL 0x00000002 /* do mutual auth */ + +#define KOPT_DONT_CANON 0x00000004 /* + * don't canonicalize inst as + * a hostname + */ + +#define KRB_SENDAUTH_VLEN 8 /* length for version strings */ + +#ifdef ATHENA_COMPAT +#define KOPT_DO_OLDSTYLE 0x00000008 /* use the old-style protocol */ +#endif ATHENA_COMPAT + +/* libacl */ +void acl_canonicalize_principal __P((char *principal, char *buf)); +int acl_check __P((char *acl, char *principal)); +int acl_exact_match __P((char *acl, char *principal)); +int acl_add __P((char *acl, char *principal)); +int acl_delete __P((char *acl, char *principal)); +int acl_initialize __P((char *acl_file, int mode)); + +/* libkrb - krb.3 */ +int krb_mk_req __P((KTEXT authent, char *service, char *instance, char *realm, + long checksum); +int krb_rd_req __P((KTEXT authent, char *service, char *instance, + long from_addr, AUTH_DAT *ad, char *fn)); +int krb_kntoln __P((AUTH_DAT *ad, char *lname)); +int krb_set_key __P((char *key, int cvt)); +int krb_get_cred __P((char *service, char *instance, char *realm, + CREDENTIALS *c)); +long krb_mk_priv __P((u_char *in, u_char *out, u_long in_length, + des_key_schedule schedule, des_cblock key, struct sockaddr_in *sender, + struct sockaddr_in *receiver)); +long krb_rd_priv __P((u_char *in, u_long in_length, Key_schedule schedule, + des_cblock key, struct sockaddr_in *sender, struct sockaddr_in *receiver, + MSG_DAT *msg_data)); +long krb_mk_safe __P((u_char *in, u_char *out, u_long in_length, + des_cblock *key, struct sockaddr_in *sender, struct sockaddr_in *receiver)); +long krb_rd_safe __P((u_char *in, u_long length, des_cblock *key, + struct sockaddr_in *sender, struct sockaddr_in *receiver, + MSG_DAT *msg_data)); +long krb_mk_err __P((u_char *out, long code, char *string)); +int krb_rd_err __P((u_char *in, u_long in_length, long *code, MSG_DAT *m_data)); + +/* libkrb - krb_sendauth.3 */ +int krb_sendauth __P((long options, int fd, KTEXT ticket, char *service, + char *inst, char *realm, u_long checksum, MSG_DAT *msg_data, + CREDENTIALS *cred, Key_schedule schedule, struct sockaddr_in *laddr, + struct sockaddr_in *faddr, char *version)); +int krb_recvauth __P((long options, int fd, KTEXT ticket, char *service, + char *instance, struct sockaddr_in *faddr, struct sockaddr_in *laddr, + AUTH_DAT *kdata, char *filename, Key_schedule schedule, char *version)); +int krb_net_write __P((int fd, char *buf, int len)); +int krb_net_read __P((int fd, char *buf, int len)); + +/* libkrb - krb_realmofhost.3 */ +char *krb_realmofhost __P((char *host)); +char *krb_get_phost __P((char *alias)); +int krb_get_krbhst __P((char *h, char *r, int n)); +int krb_get_admhst __P((char *h, char *r, int n)); +int krb_get_lrealm __P((char *r, int n)); + +/* libkrb - krb_set_tkt_string.3 */ +void krb_set_tkt_string(char *val); + +/* libkrb - kuserok.3 */ +int kuserok __P((AUTH_DAT *authdata, char *localuser)); + +/* libkrb - tf_util.3 */ +int tf_init __P((char *tf_name, int rw)); +int tf_get_pname __P((char *p)); +int tf_get_pinst __P((char *inst)); +int tf_get_cred __P((CREDENTIALS *c)); +void tf_close __P((void)); + +/* Internal routines */ +int des_read __P((int fd, char *buf, int len)); +int des_write __P((int fd, char *buf, int len)); +int krb_get_tf_realm __P((char *ticket_file, char *realm)); +int krb_get_in_tkt __P((char *user, char *instance, char *realm, char *service, + char *sinstance, int life, int (*key_proc)(), int (*decrypt_proc)(), + char *arg)); +int krb_get_pw_in_tkt __P((char *user, char *instance, char *realm, + char *service, char *sinstance, int life, char *password)); +int krb_get_svc_in_tkt __P((char *user, char *instance, char *realm, + char *service, char *sinstance, int life, char *srvtab)); +int krb_get_tf_fullname __P((char *ticket_file, char *name, char *instance, + char *realm)); +int save_credentials __P((char *service, char *instance, char *realm, + des_cblock session, int lifetime, int kvno, KTEXT ticket, long issue_date)); +int read_service_key __P((char *service, char *instance, char *realm, int kvno, + char *file, char *key)); +int get_ad_tkt __P((char *service, char *sinstance, char *realm, int lifetime)); +int send_to_kdc __P((KTEXT pkt, KTEXT rpkt, char *realm)); +int krb_create_ticket __P((KTEXT tkt, unsigned char flags, char *pname, + char *pinstance, char *prealm, long paddress, char *session, short life, + long time_sec, char *sname, char *sinstance, C_Block key)); +int decomp_ticket __P((KTEXT tkt, unsigned char *flags, char *pname, + char *pinstance, char *prealm, unsigned long *paddress, des_cblock session, + int *life, unsigned long *time_sec, char *sname, char *sinstance, + des_cblock key, des_key_schedule key_s)); +int create_ciph __P((KTEXT c, C_Block session, char *service, char *instance, + char *realm, unsigned long life, int kvno, KTEXT tkt, + unsigned long kdc_time, C_Block key)); +int kname_parse __P((char *np, char *ip, char *rp, char *fullname)); +int tf_save_cred __P((char *service, char *instance, char *realm, + des_cblock session, int lifetime, int kvno, KTEXT ticket, long issue_date)); +int getst(int fd, char *s, int n)); +int pkt_clen __P((KTEXT pkt)); +int in_tkt __P((char *pname, char *pinst)); +int dest_tkt __P((void)); +char *month_sname __P((int n)); +void log __P(()); /* Actually VARARGS - markm */ +void kset_logfile __P((char *filename)); +void set_logfile __P((char *filename)); +int k_isinst __P((char *s)); +int k_isrealm __P((char *s)); +int k_isname __P((char *s)); +int k_gethostname __P((char *name, int namelen)); +int kerb_init __P((void)); +void kerb_fini __P((void)); +int kerb_db_set_name __P((char *name)); +int kerb_db_set_lockmode __P((int mode)); +int kerb_db_create __P((char *db_name)); +int kerb_db_iterate __P((int (*func)(), char *arg)); +int kerb_db_rename __P((char *from, char *to)); +long kerb_get_db_age __P((void)); +char * stime __P((long *t)); + +long kdb_get_master_key __P((int prompt, C_Block master_key, + Key_schedule master_key_sched)); +long kdb_verify_master_key __P((C_Block master_key, + Key_schedule master_key_sched, FILE *out)); +void kdb_encrypt_key __P((C_Block in, C_Block out, C_Block master_key, + Key_schedule master_key_sched, int e_d_flag)); + +extern int krb_ap_req_debug; +extern int krb_debug; + +#endif KRB_DEFS diff --git a/eBones/include/krb_db.h b/eBones/include/krb_db.h new file mode 100644 index 0000000000000..d6d125a3551f4 --- /dev/null +++ b/eBones/include/krb_db.h @@ -0,0 +1,110 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * spm Project Athena 8/85 + * + * This file defines data structures for the kerberos + * authentication/authorization database. + * + * They MUST correspond to those defined in *.rel + * + * from: krb_db.h,v 4.9 89/01/24 17:55:39 jon Exp $ + * $Id: krb_db.h,v 1.4 1995/08/25 21:25:12 mark Exp $ + */ + +#ifndef KRB_DB_DEFS +#define KRB_DB_DEFS + +#define KERB_M_NAME "K" /* Kerberos */ +#define KERB_M_INST "M" /* Master */ +#define KERB_DEFAULT_NAME "default" +#define KERB_DEFAULT_INST "" +#define DBM_FILE "/etc/kerberosIV/principal" + +/* this also defines the number of queue headers */ +#define KERB_DB_HASH_MODULO 64 + + +/* Arguments to kerb_dbl_lock() */ + +#define KERB_DBL_EXCLUSIVE 1 +#define KERB_DBL_SHARED 0 + +/* arguments to kerb_db_set_lockmode() */ + +#define KERB_DBL_BLOCKING 0 +#define KERB_DBL_NONBLOCKING 1 + +/* Principal defines the structure of a principal's name */ + +typedef struct { + char name[ANAME_SZ]; + char instance[INST_SZ]; + + unsigned long key_low; + unsigned long key_high; + unsigned long exp_date; + char exp_date_txt[DATE_SZ]; + unsigned long mod_date; + char mod_date_txt[DATE_SZ]; + unsigned short attributes; + unsigned char max_life; + unsigned char kdc_key_ver; + unsigned char key_version; + + char mod_name[ANAME_SZ]; + char mod_instance[INST_SZ]; + char *old; /* cast to (Principal *); not in db, + * ptr to old vals */ +} + Principal; + +typedef struct { + long cpu; + long elapsed; + long dio; + long pfault; + long t_stamp; + long n_retrieve; + long n_replace; + long n_append; + long n_get_stat; + long n_put_stat; +} + DB_stat; + +/* Dba defines the structure of a database administrator */ + +typedef struct { + char name[ANAME_SZ]; + char instance[INST_SZ]; + unsigned short attributes; + unsigned long exp_date; + char exp_date_txt[DATE_SZ]; + char *old; /* + * cast to (Dba *); not in db, ptr to + * old vals + */ +} + Dba; + +extern int kerb_get_principal(char *name, char *inst, Principal *principal, + unsigned int max, int *more); +extern int kerb_put_principal(Principal *principal, unsigned int n); +extern void kerb_db_get_stat(DB_stat *s); +extern void kerb_db_put_stat(DB_stat *s); +extern int kerb_get_dba(char *name, char *inst, Dba *dba, unsigned int max, + int *more); +extern int kerb_db_get_dba(char *dba_name, char *dba_inst, Dba *dba, + unsigned int max, int *more); + +extern void krb_print_principal(Principal *p); +extern int kerb_db_get_principal(char *name, char *inst, Principal *principal, + unsigned int max, int *more); +extern int kerb_db_put_principal(Principal *principal, unsigned int max); +extern int kerb_db_init(void); +extern void kerb_db_fini(void); + +#endif /* KRB_DB_DEFS */ diff --git a/eBones/include/rkinit.h b/eBones/include/rkinit.h new file mode 100644 index 0000000000000..8be12029cd8e6 --- /dev/null +++ b/eBones/include/rkinit.h @@ -0,0 +1,42 @@ +/* + * $Id: rkinit.h,v 1.2 1993/12/23 16:47:27 dglo Exp $ + * $Source: /usr/sww/share/src/kerberosIV.BSD/include/RCS/rkinit.h,v $ + * $Author: dglo $ + * + * Main header file for rkinit library users + */ + +#ifndef __RKINIT_H__ +#define __RKINIT_H__ + +#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS) +static char *rcsid_rkinit_h = "$Id: rkinit.h,v 1.2 1993/12/23 16:47:27 dglo Exp $"; +#endif /* lint || SABER || LOCORE || RCS_HDRS */ + +#include <krb.h> +#include <sys/param.h> + +#ifdef __STDC__ +#define RK_PROTO(x) x +#else +#define RK_PROTO(x) () +#endif /* __STDC__ */ + +typedef struct { + char aname[ANAME_SZ + 1]; + char inst[INST_SZ + 1]; + char realm[REALM_SZ + 1]; + char sname[ANAME_SZ + 1]; + char sinst[INST_SZ + 1]; + char username[9]; /* max local name length + 1 */ + char tktfilename[MAXPATHLEN + 1]; + u_int lifetime; +} rkinit_info; + +#define RKINIT_SUCCESS 0 + +/* Function declarations */ +extern int rkinit RK_PROTO((char *, char *, rkinit_info *, int)); +extern char *rkinit_errmsg RK_PROTO((char *)); + +#endif /* __RKINIT_H__ */ diff --git a/eBones/include/rkinit_private.h b/eBones/include/rkinit_private.h new file mode 100644 index 0000000000000..7784b6e51d0a6 --- /dev/null +++ b/eBones/include/rkinit_private.h @@ -0,0 +1,106 @@ +/* + * $Id: rkinit_private.h,v 1.4 1993/12/23 16:47:39 dglo Exp $ + * $Source: /usr/sww/share/src/kerberosIV.BSD/include/RCS/rkinit_private.h,v $ + * $Author: dglo $ + * + * Header file for rkinit library and server internal use + */ + +#ifndef __RKINIT_PRIVATE_H__ +#define __RKINIT_PRIVATE_H__ + +#if !defined(lint) && !defined(SABER) +static const char *rcsid_rkinit_private_h = "$Id: rkinit_private.h,v 1.4 1993/12/23 16:47:39 dglo Exp $"; +#endif /* lint || SABER */ + +#include <sys/types.h> +#include <netinet/in.h> + +#ifdef __STDC__ +#define RK_PROTO(x) x +#else +#define RK_PROTO(x) () +#define const +#endif /* __STDC__ */ + +/* Lowest and highest versions supported */ +#define RKINIT_LVERSION 3 +#define RKINIT_HVERSION 3 + +/* Service to be used; port number to fall back on if service isn't found */ +#define SERVENT "rkinit" +#define PORT 2108 + +/* Key for kerberos authentication */ +#define KEY "rcmd" + +/* Packet format information */ +#define PKT_TYPE 0 +#define PKT_LEN 1 +#define PKT_DATA (PKT_LEN + sizeof(u_int32_t)) + +/* Number of retries during message reads */ +#define RETRIES 15 + +/* + * Message types for packets. Make sure that rki_mt_to_string is right in + * rk_util.c + */ +#define MT_STATUS 0 +#define MT_CVERSION 1 +#define MT_SVERSION 2 +#define MT_RKINIT_INFO 3 +#define MT_SKDC 4 +#define MT_CKDC 5 +#define MT_AUTH 6 +#define MT_DROP 7 + +/* Miscellaneous protocol constants */ +#define VERSION_INFO_SIZE 2 + +/* Useful definitions */ +#define BCLEAR(a) bzero((char *)(a), sizeof(a)) +#define SBCLEAR(a) bzero((char *)&(a), sizeof(a)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef _JBLEN +#define SETJMP_TYPEDEFED +#endif + +/* Function declarations */ +int rki_key_proc RK_PROTO((char *, char *, char *, char *, des_cblock *)); +int rki_get_tickets RK_PROTO((int, char *, char *, rkinit_info *)); +int rki_send_packet RK_PROTO((int, char, u_int32_t, const char *)); +int rki_get_packet RK_PROTO((int, u_char, u_int32_t *, char *)); +int rki_setup_rpc RK_PROTO((char *)); +int rki_rpc_exchange_version_info RK_PROTO((int, int, int *, int *)); +int rki_rpc_send_rkinit_info RK_PROTO((rkinit_info *)); +int rki_rpc_get_status RK_PROTO((void)); +int rki_rpc_get_ktext RK_PROTO((int, KTEXT, u_char)); +int rki_rpc_sendauth RK_PROTO((KTEXT)); +int rki_rpc_get_skdc RK_PROTO((KTEXT)); +int rki_rpc_send_ckdc RK_PROTO((MSG_DAT *)); +int rki_get_csaddr RK_PROTO((struct sockaddr_in *, struct sockaddr_in *)); +void rki_drop_server RK_PROTO((void)); +void rki_cleanup_rpc RK_PROTO((void)); +void rki_dmsg RK_PROTO((char *)); +const char *rki_mt_to_string RK_PROTO((int)); +int rki_choose_version RK_PROTO((int *)); +int rki_send_rkinit_info RK_PROTO((int, rkinit_info *)); +#ifdef SETJMP_TYPEDEFED +void (*rki_setup_timer RK_PROTO((jmp_buf env))) RK_PROTO((int)); +#endif +void rki_restore_timer RK_PROTO((void (*old_alrm)(int))); +void rki_cleanup_rpc RK_PROTO((void)); + + +#endif /* __RKINIT_PRIVATE_H__ */ diff --git a/eBones/lib/Makefile b/eBones/lib/Makefile new file mode 100644 index 0000000000000..3ca4918934345 --- /dev/null +++ b/eBones/lib/Makefile @@ -0,0 +1,6 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.1 1995/09/13 17:23:48 markm Exp $ + +SUBDIR= libacl libkadm libkdb libkrb librkinit + +.include <bsd.subdir.mk> diff --git a/eBones/lib/Makefile.inc b/eBones/lib/Makefile.inc new file mode 100644 index 0000000000000..b0b4ed25a2904 --- /dev/null +++ b/eBones/lib/Makefile.inc @@ -0,0 +1,4 @@ +SHLIB_MAJOR?= 2 +SHLIB_MINOR?= 0 + +.include "../Makefile.inc" diff --git a/eBones/lib/libacl/Makefile b/eBones/lib/libacl/Makefile new file mode 100644 index 0000000000000..7fa05c06a09cc --- /dev/null +++ b/eBones/lib/libacl/Makefile @@ -0,0 +1,12 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1995/09/13 17:23:49 markm Exp $ + +LIB= acl +CFLAGS+=-DDEBUG -DKERBEROS +SRCS= acl_files.c +MAN3= acl_check.3 +MLINKS= acl_check.3 acl_canonicalize_principal.3 \ + acl_check.3 acl_exact_match.3 acl_check.3 acl_add.3 \ + acl_check.3 acl_delete.3 acl_check.3 acl_initialize.3 + +.include <bsd.lib.mk> diff --git a/eBones/lib/libacl/acl_files.c b/eBones/lib/libacl/acl_files.c new file mode 100644 index 0000000000000..7670f2aa22aac --- /dev/null +++ b/eBones/lib/libacl/acl_files.c @@ -0,0 +1,555 @@ +/* + * + * Copyright 1987,1989 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * <mit-copyright.h>. + * + * from: acl_files.c,v 4.4 89/12/19 13:30:53 jtkohl Exp $ + * $Id: acl_files.c,v 1.5 1995/09/07 20:50:26 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: acl_files.c,v 1.5 1995/09/07 20:50:26 mark Exp $"; +#endif lint +#endif + + +/*** Routines for manipulating access control list files ***/ + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <strings.h> +#include <sys/file.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/errno.h> +#include <ctype.h> +#include "krb.h" + +__BEGIN_DECLS +static int acl_abort __P((char *, FILE *)); +__END_DECLS + +#ifndef KRB_REALM +#define KRB_REALM "ATHENA.MIT.EDU" +#endif + +/* "aname.inst@realm" */ +#define MAX_PRINCIPAL_SIZE (ANAME_SZ + INST_SZ + REALM_SZ + 3) +#define INST_SEP '.' +#define REALM_SEP '@' + +#define LINESIZE 2048 /* Maximum line length in an acl file */ + +#define NEW_FILE "%s.~NEWACL~" /* Format for name of altered acl file */ +#define WAIT_TIME 300 /* Maximum time allowed write acl file */ + +#define CACHED_ACLS 8 /* How many acls to cache */ + /* Each acl costs 1 open file descriptor */ +#define ACL_LEN 16 /* Twice a reasonable acl length */ + +#define MAX(a,b) (((a)>(b))?(a):(b)) +#define MIN(a,b) (((a)<(b))?(a):(b)) + +#define COR(a,b) ((a!=NULL)?(a):(b)) + +/* Canonicalize a principal name */ +/* If instance is missing, it becomes "" */ +/* If realm is missing, it becomes the local realm */ +/* Canonicalized form is put in canon, which must be big enough to hold + MAX_PRINCIPAL_SIZE characters */ +void +acl_canonicalize_principal(principal, canon) +char *principal; +char *canon; +{ + char *dot, *atsign, *end; + int len; + + dot = index(principal, INST_SEP); + atsign = index(principal, REALM_SEP); + + /* Maybe we're done already */ + if(dot != NULL && atsign != NULL) { + if(dot < atsign) { + /* It's for real */ + /* Copy into canon */ + strncpy(canon, principal, MAX_PRINCIPAL_SIZE); + canon[MAX_PRINCIPAL_SIZE-1] = '\0'; + return; + } else { + /* Nope, it's part of the realm */ + dot = NULL; + } + } + + /* No such luck */ + end = principal + strlen(principal); + + /* Get the principal name */ + len = MIN(ANAME_SZ, COR(dot, COR(atsign, end)) - principal); + strncpy(canon, principal, len); + canon += len; + + /* Add INST_SEP */ + *canon++ = INST_SEP; + + /* Get the instance, if it exists */ + if(dot != NULL) { + ++dot; + len = MIN(INST_SZ, COR(atsign, end) - dot); + strncpy(canon, dot, len); + canon += len; + } + + /* Add REALM_SEP */ + *canon++ = REALM_SEP; + + /* Get the realm, if it exists */ + /* Otherwise, default to local realm */ + if(atsign != NULL) { + ++atsign; + len = MIN(REALM_SZ, end - atsign); + strncpy(canon, atsign, len); + canon += len; + *canon++ = '\0'; + } else if(krb_get_lrealm(canon, 1) != KSUCCESS) { + strcpy(canon, KRB_REALM); + } +} + +/* Get a lock to modify acl_file */ +/* Return new FILE pointer */ +/* or NULL if file cannot be modified */ +/* REQUIRES WRITE PERMISSION TO CONTAINING DIRECTORY */ +static FILE * +acl_lock_file(acl_file) +char *acl_file; +{ + struct stat s; + char new[LINESIZE]; + int nfd; + FILE *nf; + int mode; + + if(stat(acl_file, &s) < 0) return(NULL); + mode = s.st_mode; + sprintf(new, NEW_FILE, acl_file); + for(;;) { + /* Open the new file */ + if((nfd = open(new, O_WRONLY|O_CREAT|O_EXCL, mode)) < 0) { + if(errno == EEXIST) { + /* Maybe somebody got here already, maybe it's just old */ + if(stat(new, &s) < 0) return(NULL); + if(time(0) - s.st_ctime > WAIT_TIME) { + /* File is stale, kill it */ + unlink(new); + continue; + } else { + /* Wait and try again */ + sleep(1); + continue; + } + } else { + /* Some other error, we lose */ + return(NULL); + } + } + + /* If we got to here, the lock file is ours and ok */ + /* Reopen it under stdio */ + if((nf = fdopen(nfd, "w")) == NULL) { + /* Oops, clean up */ + unlink(new); + } + return(nf); + } +} + +/* Commit changes to acl_file written onto FILE *f */ +/* Returns zero if successful */ +/* Returns > 0 if lock was broken */ +/* Returns < 0 if some other error occurs */ +/* Closes f */ +static int +acl_commit(acl_file, f) +char *acl_file; +FILE *f; +{ + char new[LINESIZE]; + int ret; + struct stat s; + + sprintf(new, NEW_FILE, acl_file); + if(fflush(f) < 0 + || fstat(fileno(f), &s) < 0 + || s.st_nlink == 0) { + acl_abort(acl_file, f); + return(-1); + } + + ret = rename(new, acl_file); + fclose(f); + return(ret); +} + +/* + * Abort changes to acl_file written onto FILE *f + * Returns 0 if successful, < 0 otherwise + * Closes f + */ +static int +acl_abort(acl_file, f) +char *acl_file; +FILE *f; +{ + char new[LINESIZE]; + int ret; + struct stat s; + + /* make sure we aren't nuking someone else's file */ + if(fstat(fileno(f), &s) < 0 || s.st_nlink == 0) { + fclose(f); + return(-1); + } else { + sprintf(new, NEW_FILE, acl_file); + ret = unlink(new); + fclose(f); + return(ret); + } +} + +/* Initialize an acl_file */ +/* Creates the file with permissions perm if it does not exist */ +/* Erases it if it does */ +/* Returns return value of acl_commit */ +int +acl_initialize(acl_file, perm) +char *acl_file; +int perm; +{ + FILE *new; + int fd; + + /* Check if the file exists already */ + if((new = acl_lock_file(acl_file)) != NULL) { + return(acl_commit(acl_file, new)); + } else { + /* File must be readable and writable by owner */ + if((fd = open(acl_file, O_CREAT|O_EXCL, perm|0600)) < 0) { + return(-1); + } else { + close(fd); + return(0); + } + } +} + +/* Eliminate all whitespace character in buf */ +/* Modifies its argument */ +static void +nuke_whitespace(buf) +char *buf; +{ + register char *pin, *pout; + + for(pin = pout = buf; *pin != '\0'; pin++) + if(!isspace(*pin)) *pout++ = *pin; + *pout = '\0'; /* Terminate the string */ +} + +/* Hash table stuff */ + +struct hashtbl { + int size; /* Max number of entries */ + int entries; /* Actual number of entries */ + char **tbl; /* Pointer to start of table */ +}; + +/* Make an empty hash table of size s */ +static struct hashtbl * +make_hash(size) +int size; +{ + struct hashtbl *h; + + if(size < 1) size = 1; + h = (struct hashtbl *) malloc(sizeof(struct hashtbl)); + h->size = size; + h->entries = 0; + h->tbl = (char **) calloc(size, sizeof(char *)); + return(h); +} + +/* Destroy a hash table */ +static void +destroy_hash(h) +struct hashtbl *h; +{ + int i; + + for(i = 0; i < h->size; i++) { + if(h->tbl[i] != NULL) free(h->tbl[i]); + } + free(h->tbl); + free(h); +} + +/* Compute hash value for a string */ +static unsigned +hashval(s) +register char *s; +{ + register unsigned hv; + + for(hv = 0; *s != '\0'; s++) { + hv ^= ((hv << 3) ^ *s); + } + return(hv); +} + +/* Add an element to a hash table */ +static void +add_hash(h, el) +struct hashtbl *h; +char *el; +{ + unsigned hv; + char *s; + char **old; + int i; + + /* Make space if it isn't there already */ + if(h->entries + 1 > (h->size >> 1)) { + old = h->tbl; + h->tbl = (char **) calloc(h->size << 1, sizeof(char *)); + for(i = 0; i < h->size; i++) { + if(old[i] != NULL) { + hv = hashval(old[i]) % (h->size << 1); + while(h->tbl[hv] != NULL) hv = (hv+1) % (h->size << 1); + h->tbl[hv] = old[i]; + } + } + h->size = h->size << 1; + free(old); + } + + hv = hashval(el) % h->size; + while(h->tbl[hv] != NULL && strcmp(h->tbl[hv], el)) hv = (hv+1) % h->size; + s = malloc(strlen(el)+1); + strcpy(s, el); + h->tbl[hv] = s; + h->entries++; +} + +/* Returns nonzero if el is in h */ +static int +check_hash(h, el) +struct hashtbl *h; +char *el; +{ + unsigned hv; + + for(hv = hashval(el) % h->size; + h->tbl[hv] != NULL; + hv = (hv + 1) % h->size) { + if(!strcmp(h->tbl[hv], el)) return(1); + } + return(0); +} + +struct acl { + char filename[LINESIZE]; /* Name of acl file */ + int fd; /* File descriptor for acl file */ + struct stat status; /* File status at last read */ + struct hashtbl *acl; /* Acl entries */ +}; + +static struct acl acl_cache[CACHED_ACLS]; + +static int acl_cache_count = 0; +static int acl_cache_next = 0; + +/* Returns < 0 if unsuccessful in loading acl */ +/* Returns index into acl_cache otherwise */ +/* Note that if acl is already loaded, this is just a lookup */ +static int +acl_load(name) +char *name; +{ + int i; + FILE *f; + struct stat s; + char buf[MAX_PRINCIPAL_SIZE]; + char canon[MAX_PRINCIPAL_SIZE]; + + /* See if it's there already */ + for(i = 0; i < acl_cache_count; i++) { + if(!strcmp(acl_cache[i].filename, name) + && acl_cache[i].fd >= 0) goto got_it; + } + + /* It isn't, load it in */ + /* maybe there's still room */ + if(acl_cache_count < CACHED_ACLS) { + i = acl_cache_count++; + } else { + /* No room, clean one out */ + i = acl_cache_next; + acl_cache_next = (acl_cache_next + 1) % CACHED_ACLS; + close(acl_cache[i].fd); + if(acl_cache[i].acl) { + destroy_hash(acl_cache[i].acl); + acl_cache[i].acl = (struct hashtbl *) 0; + } + } + + /* Set up the acl */ + strcpy(acl_cache[i].filename, name); + if((acl_cache[i].fd = open(name, O_RDONLY, 0)) < 0) return(-1); + /* Force reload */ + acl_cache[i].acl = (struct hashtbl *) 0; + + got_it: + /* + * See if the stat matches + * + * Use stat(), not fstat(), as the file may have been re-created by + * acl_add or acl_delete. If this happens, the old inode will have + * no changes in the mod-time and the following test will fail. + */ + if(stat(acl_cache[i].filename, &s) < 0) return(-1); + if(acl_cache[i].acl == (struct hashtbl *) 0 + || s.st_nlink != acl_cache[i].status.st_nlink + || s.st_mtime != acl_cache[i].status.st_mtime + || s.st_ctime != acl_cache[i].status.st_ctime) { + /* Gotta reload */ + if(acl_cache[i].fd >= 0) close(acl_cache[i].fd); + if((acl_cache[i].fd = open(name, O_RDONLY, 0)) < 0) return(-1); + if((f = fdopen(acl_cache[i].fd, "r")) == NULL) return(-1); + if(acl_cache[i].acl) destroy_hash(acl_cache[i].acl); + acl_cache[i].acl = make_hash(ACL_LEN); + while(fgets(buf, sizeof(buf), f) != NULL) { + nuke_whitespace(buf); + acl_canonicalize_principal(buf, canon); + add_hash(acl_cache[i].acl, canon); + } + fclose(f); + acl_cache[i].status = s; + } + return(i); +} + +/* Returns nonzero if it can be determined that acl contains principal */ +/* Principal is not canonicalized, and no wildcarding is done */ +int +acl_exact_match(acl, principal) +char *acl; +char *principal; +{ + int idx; + + return((idx = acl_load(acl)) >= 0 + && check_hash(acl_cache[idx].acl, principal)); +} + +/* Returns nonzero if it can be determined that acl contains principal */ +/* Recognizes wildcards in acl of the form + name.*@realm, *.*@realm, and *.*@* */ +int +acl_check(acl, principal) +char *acl; +char *principal; +{ + char buf[MAX_PRINCIPAL_SIZE]; + char canon[MAX_PRINCIPAL_SIZE]; + char *realm; + + acl_canonicalize_principal(principal, canon); + + /* Is it there? */ + if(acl_exact_match(acl, canon)) return(1); + + /* Try the wildcards */ + realm = index(canon, REALM_SEP); + *index(canon, INST_SEP) = '\0'; /* Chuck the instance */ + + sprintf(buf, "%s.*%s", canon, realm); + if(acl_exact_match(acl, buf)) return(1); + + sprintf(buf, "*.*%s", realm); + if(acl_exact_match(acl, buf) || acl_exact_match(acl, "*.*@*")) return(1); + + return(0); +} + +/* Adds principal to acl */ +/* Wildcards are interpreted literally */ +int +acl_add(acl, principal) +char *acl; +char *principal; +{ + int idx; + int i; + FILE *new; + char canon[MAX_PRINCIPAL_SIZE]; + + acl_canonicalize_principal(principal, canon); + + if((new = acl_lock_file(acl)) == NULL) return(-1); + if((acl_exact_match(acl, canon)) + || (idx = acl_load(acl)) < 0) { + acl_abort(acl, new); + return(-1); + } + /* It isn't there yet, copy the file and put it in */ + for(i = 0; i < acl_cache[idx].acl->size; i++) { + if(acl_cache[idx].acl->tbl[i] != NULL) { + if(fputs(acl_cache[idx].acl->tbl[i], new) == NULL + || putc('\n', new) != '\n') { + acl_abort(acl, new); + return(-1); + } + } + } + fputs(canon, new); + putc('\n', new); + return(acl_commit(acl, new)); +} + +/* Removes principal from acl */ +/* Wildcards are interpreted literally */ +int +acl_delete(acl, principal) +char *acl; +char *principal; +{ + int idx; + int i; + FILE *new; + char canon[MAX_PRINCIPAL_SIZE]; + + acl_canonicalize_principal(principal, canon); + + if((new = acl_lock_file(acl)) == NULL) return(-1); + if((!acl_exact_match(acl, canon)) + || (idx = acl_load(acl)) < 0) { + acl_abort(acl, new); + return(-1); + } + /* It isn't there yet, copy the file and put it in */ + for(i = 0; i < acl_cache[idx].acl->size; i++) { + if(acl_cache[idx].acl->tbl[i] != NULL + && strcmp(acl_cache[idx].acl->tbl[i], canon)) { + fputs(acl_cache[idx].acl->tbl[i], new); + putc('\n', new); + } + } + return(acl_commit(acl, new)); +} + diff --git a/eBones/lib/libkadm/Makefile b/eBones/lib/libkadm/Makefile new file mode 100644 index 0000000000000..dc822b38fb1a7 --- /dev/null +++ b/eBones/lib/libkadm/Makefile @@ -0,0 +1,23 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.7 1995/09/14 19:52:28 gibbs Exp $ + +LIB= kadm + +SRCS= kadm_err.c kadm_stream.c kadm_supp.c kadm_cli_wrap.c +CFLAGS+= -I. -I${.CURDIR} -I${KRBOBJDIR} -DPOSIX + +beforeinstall: + -cd ${.CURDIR}; cmp -s kadm.h \ + ${DESTDIR}/usr/include/kerberosIV/kadm.h || \ + install -c -o ${BINOWN} -g ${BINGRP} -m 444 kadm.h \ + ${DESTDIR}/usr/include/kerberosIV + -cd ${.OBJDIR}; cmp -s kadm_err.h \ + ${DESTDIR}/usr/include/kerberosIV/kadm_err.h || \ + install -c -o ${BINOWN} -g ${BINGRP} -m 444 kadm_err.h \ + ${DESTDIR}/usr/include/kerberosIV + +.include <bsd.lib.mk> + +kadm_err.c: ${KADMOBJDIR}/kadm_err.h + +kadm_cli_wrap.o: ${KRBOBJDIR}/krb_err.h diff --git a/eBones/lib/libkadm/kadm.h b/eBones/lib/libkadm/kadm.h new file mode 100644 index 0000000000000..21a23bb8f8d92 --- /dev/null +++ b/eBones/lib/libkadm/kadm.h @@ -0,0 +1,164 @@ +/* + * $Source: /usr/cvs/src/eBones/libkadm/kadm.h,v $ + * $Author: mark $ + * Header: /afs/athena.mit.edu/astaff/project/kerberos/src/include/RCS/kadm.h,v 4.2 89/09/26 09:15:20 jtkohl Exp + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Definitions for Kerberos administration server & client + */ + +#ifndef KADM_DEFS +#define KADM_DEFS + +/* + * kadm.h + * Header file for the fourth attempt at an admin server + * Doug Church, December 28, 1989, MIT Project Athena + */ + +/* for those broken Unixes without this defined... should be in sys/param.h */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#include <stdlib.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <krb.h> +#include <krb_db.h> +#include <des.h> + +/* The global structures for the client and server */ +typedef struct { + struct sockaddr_in admin_addr; + struct sockaddr_in my_addr; + int my_addr_len; + int admin_fd; /* file descriptor for link to admin server */ + char sname[ANAME_SZ]; /* the service name */ + char sinst[INST_SZ]; /* the services instance */ + char krbrlm[REALM_SZ]; +} Kadm_Client; + +typedef struct { /* status of the server, i.e the parameters */ + int inter; /* Space for command line flags */ + char *sysfile; /* filename of server */ +} admin_params; /* Well... it's the admin's parameters */ + +/* Largest password length to be supported */ +#define MAX_KPW_LEN 128 + +/* Largest packet the admin server will ever allow itself to return */ +#define KADM_RET_MAX 2048 + +/* That's right, versions are 8 byte strings */ +#define KADM_VERSTR "KADM0.0A" +#define KADM_ULOSE "KYOULOSE" /* sent back when server can't + decrypt client's msg */ +#define KADM_VERSIZE strlen(KADM_VERSTR) + +/* the lookups for the server instances */ +#define PWSERV_NAME "changepw" +#define KADM_SNAME "kerberos_master" +#define KADM_SINST "kerberos" + +/* Attributes fields constants and macros */ +#define ALLOC 2 +#define RESERVED 3 +#define DEALLOC 4 +#define DEACTIVATED 5 +#define ACTIVE 6 + +/* Kadm_vals structure for passing db fields into the server routines */ +#define FLDSZ 4 + +typedef struct { + u_char fields[FLDSZ]; /* The active fields in this struct */ + char name[ANAME_SZ]; + char instance[INST_SZ]; + unsigned long key_low; + unsigned long key_high; + unsigned long exp_date; + unsigned short attributes; + unsigned char max_life; +} Kadm_vals; /* The basic values structure in Kadm */ + +/* Kadm_vals structure for passing db fields into the server routines */ +#define FLDSZ 4 + +/* Need to define fields types here */ +#define KADM_NAME 31 +#define KADM_INST 30 +#define KADM_EXPDATE 29 +#define KADM_ATTR 28 +#define KADM_MAXLIFE 27 +#define KADM_DESKEY 26 + +/* To set a field entry f in a fields structure d */ +#define SET_FIELD(f,d) (d[3-(f/8)]|=(1<<(f%8))) + +/* To set a field entry f in a fields structure d */ +#define CLEAR_FIELD(f,d) (d[3-(f/8)]&=(~(1<<(f%8)))) + +/* Is field f in fields structure d */ +#define IS_FIELD(f,d) (d[3-(f/8)]&(1<<(f%8))) + +/* Various return codes */ +#define KADM_SUCCESS 0 + +#define WILDCARD_STR "*" + +enum acl_types { +ADDACL, +GETACL, +MODACL +}; + +/* Various opcodes for the admin server's functions */ +#define CHANGE_PW 2 +#define ADD_ENT 3 +#define MOD_ENT 4 +#define GET_ENT 5 + +/* XXX This doesn't belong here!!! */ +#ifdef POSIX +typedef void sigtype; +#else +typedef int sigtype; +#endif + +int vals_to_stream(Kadm_vals *dt_in, u_char **dt_out); +int stream_to_vals(u_char *dt_in, Kadm_vals *dt_out, int maxlen); + +int build_field_header(u_char *cont, u_char **st); +int check_field_header(u_char *st, u_char *cont, int maxlen); + +int stv_string(u_char *st, char *dat, int loc, int stlen, int maxlen); +int stv_short(u_char *st, u_short *dat, int loc, int maxlen); +int stv_long(u_char *st, u_long *dat, int loc, int maxlen); +int stv_char(u_char *st, u_char *dat, int loc, int maxlen); + +int vts_string(char *dat, u_char **st, int loc); +int vts_short(u_short dat, u_char **st, int loc); +int vts_long(u_long dat, u_char **st, int loc); +int vts_char(u_char dat, u_char **st, int loc); + +int kadm_cli_conn(void); +void kadm_cli_disconn(void); +int kadm_cli_send(u_char *st_dat, int st_siz, u_char **ret_dat, int *ret_siz); +int kadm_cli_out(u_char *dat, int dat_len, u_char **ret_dat, int *ret_siz); +int kadm_cli_keyd(des_cblock s_k, des_key_schedule s_s); + +int kadm_get(Kadm_vals *vals, u_char fl[4]); +int kadm_mod(Kadm_vals *vals1, Kadm_vals *vals2); +int kadm_add(Kadm_vals *vals); +int kadm_change_pw(des_cblock newkey); +int kadm_init_link(char n[], char i[], char r[]); +void prin_vals(Kadm_vals *vals); +void kadm_vals_to_prin(u_char fields[FLDSZ], Principal *new, Kadm_vals *old); +void kadm_prin_to_vals(u_char fields[FLDSZ], Kadm_vals *new, Principal *old); + +#endif KADM_DEFS diff --git a/eBones/lib/libkadm/kadm_cli_wrap.c b/eBones/lib/libkadm/kadm_cli_wrap.c new file mode 100644 index 0000000000000..e25439dbba2b3 --- /dev/null +++ b/eBones/lib/libkadm/kadm_cli_wrap.c @@ -0,0 +1,509 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Kerberos administration server client-side routines + */ + +#if 0 +#ifndef lint +static char rcsid_kadm_cli_wrap_c[] = +"from: Id: kadm_cli_wrap.c,v 4.6 89/12/30 20:09:45 qjb Exp"; +static const char rcsid[] = + "$Id: kadm_cli_wrap.c,v 1.1 1995/07/18 16:40:23 mark Exp $"; +#endif lint +#endif + +/* + * kadm_cli_wrap.c the client side wrapping of the calls to the admin server + */ + +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <errno.h> +#include <signal.h> +#include <netdb.h> +#include <sys/socket.h> +#include <kadm.h> +#include <kadm_err.h> +#include <krb_err.h> + +#ifndef NULL +#define NULL 0 +#endif + +static Kadm_Client client_parm; + +/* Macros for use in returning data... used in kadm_cli_send */ +#define RET_N_FREE(r) {clear_secrets(); free((char *)act_st); free((char *)priv_pak); return r;} + +/* Keys for use in the transactions */ +static des_cblock sess_key; /* to be filled in by kadm_cli_keyd */ +static Key_schedule sess_sched; + +static void +clear_secrets() +{ + bzero((char *)sess_key, sizeof(sess_key)); + bzero((char *)sess_sched, sizeof(sess_sched)); +} + +/* + * kadm_init_link + * receives : name, inst, realm + * + * initializes client parm, the Kadm_Client structure which holds the + * data about the connection between the server and client, the services + * used, the locations and other fun things + */ +int +kadm_init_link(n, i, r) +char n[]; +char i[]; +char r[]; +{ + struct servent *sep; /* service we will talk to */ + struct hostent *hop; /* host we will talk to */ + char adm_hostname[MAXHOSTNAMELEN]; + + (void) init_kadm_err_tbl(); + (void) init_krb_err_tbl(); + (void) strcpy(client_parm.sname, n); + (void) strcpy(client_parm.sinst, i); + (void) strcpy(client_parm.krbrlm, r); + client_parm.admin_fd = -1; + + /* set up the admin_addr - fetch name of admin host */ + if (krb_get_admhst(adm_hostname, client_parm.krbrlm, 1) != KSUCCESS) + return KADM_NO_HOST; + if ((hop = gethostbyname(adm_hostname)) == NULL) + return KADM_UNK_HOST; /* couldnt find the admin servers + * address */ + if ((sep = getservbyname(KADM_SNAME, "tcp")) == NULL) + return KADM_NO_SERV; /* couldnt find the admin service */ + bzero((char *) &client_parm.admin_addr, + sizeof(client_parm.admin_addr)); + client_parm.admin_addr.sin_family = hop->h_addrtype; + bcopy((char *) hop->h_addr, (char *) &client_parm.admin_addr.sin_addr, + hop->h_length); + client_parm.admin_addr.sin_port = sep->s_port; + + return KADM_SUCCESS; +} /* procedure kadm_init_link */ + +/* + * kadm_change_pw + * recieves : key + * + * Replaces the password (i.e. des key) of the caller with that specified in + * key. Returns no actual data from the master server, since this is called + * by a user + */ +int +kadm_change_pw(newkey) +des_cblock newkey; /* The DES form of the users key */ +{ + int stsize, retc; /* stream size and return code */ + u_char *send_st; /* send stream */ + u_char *ret_st; + int ret_sz; + u_long keytmp; + + if ((retc = kadm_cli_conn()) != KADM_SUCCESS) + return(retc); + /* possible problem with vts_long on a non-multiple of four boundary */ + + stsize = 0; /* start of our output packet */ + send_st = (u_char *) malloc(1);/* to make it reallocable */ + send_st[stsize++] = (u_char) CHANGE_PW; + + /* change key to stream */ + + bcopy((char *) (((long *) newkey) + 1), (char *) &keytmp, 4); + keytmp = htonl(keytmp); + stsize += vts_long(keytmp, &send_st, stsize); + + bcopy((char *) newkey, (char *) &keytmp, 4); + keytmp = htonl(keytmp); + stsize += vts_long(keytmp, &send_st, stsize); + + retc = kadm_cli_send(send_st, stsize, &ret_st, &ret_sz); + free((char *)send_st); + if (retc == KADM_SUCCESS) { + free((char *)ret_st); + } + kadm_cli_disconn(); + return(retc); +} + +/* + * kadm_add + * receives : vals + * returns : vals + * + * Adds and entry containing values to the database returns the values of the + * entry, so if you leave certain fields blank you will be able to determine + * the default values they are set to + */ +int +kadm_add(vals) +Kadm_vals *vals; +{ + u_char *st, *st2; /* st will hold the stream of values */ + int st_len; /* st2 the final stream with opcode */ + int retc; /* return code from call */ + u_char *ret_st; + int ret_sz; + + if ((retc = kadm_cli_conn()) != KADM_SUCCESS) + return(retc); + st_len = vals_to_stream(vals, &st); + st2 = (u_char *) malloc((unsigned)(1 + st_len)); + *st2 = (u_char) ADD_ENT; /* here's the opcode */ + bcopy((char *) st, (char *) st2 + 1, st_len); /* append st on */ + retc = kadm_cli_send(st2, st_len + 1, &ret_st, &ret_sz); + free((char *)st); + free((char *)st2); + if (retc == KADM_SUCCESS) { + /* ret_st has vals */ + if (stream_to_vals(ret_st, vals, ret_sz) < 0) + retc = KADM_LENGTH_ERROR; + free((char *)ret_st); + } + kadm_cli_disconn(); + return(retc); +} + +/* + * kadm_mod + * receives : KTEXT, {values, values} + * returns : CKSUM, RETCODE, {values} + * acl : su, sms (as register or dealloc) + * + * Modifies all entries corresponding to the first values so they match the + * second values. returns the values for the changed entries in vals2 + */ +int +kadm_mod(vals1, vals2) +Kadm_vals *vals1; +Kadm_vals *vals2; +{ + u_char *st, *st2; /* st will hold the stream of values */ + int st_len, nlen; /* st2 the final stream with opcode */ + u_char *ret_st; + int ret_sz; + + /* nlen is the length of second vals */ + int retc; /* return code from call */ + + if ((retc = kadm_cli_conn()) != KADM_SUCCESS) + return(retc); + + st_len = vals_to_stream(vals1, &st); + st2 = (u_char *) malloc((unsigned)(1 + st_len)); + *st2 = (u_char) MOD_ENT; /* here's the opcode */ + bcopy((char *) st, (char *) st2 + 1, st_len++); /* append st on */ + free((char *)st); + nlen = vals_to_stream(vals2, &st); + st2 = (u_char *) realloc((char *) st2, (unsigned)(st_len + nlen)); + bcopy((char *) st, (char *) st2 + st_len, nlen); /* append st on */ + retc = kadm_cli_send(st2, st_len + nlen, &ret_st, &ret_sz); + free((char *)st); + free((char *)st2); + if (retc == KADM_SUCCESS) { + /* ret_st has vals */ + if (stream_to_vals(ret_st, vals2, ret_sz) < 0) + retc = KADM_LENGTH_ERROR; + free((char *)ret_st); + } + kadm_cli_disconn(); + return(retc); +} + +/* + * kadm_get + * receives : KTEXT, {values, flags} + * returns : CKSUM, RETCODE, {count, values, values, values} + * acl : su + * + * gets the fields requested by flags from all entries matching values returns + * this data for each matching recipient, after a count of how many such + * matches there were + */ +int +kadm_get(vals, fl) +Kadm_vals *vals; +u_char fl[4]; + +{ + int loop; /* for copying the fields data */ + u_char *st, *st2; /* st will hold the stream of values */ + int st_len; /* st2 the final stream with opcode */ + int retc; /* return code from call */ + u_char *ret_st; + int ret_sz; + + if ((retc = kadm_cli_conn()) != KADM_SUCCESS) + return(retc); + st_len = vals_to_stream(vals, &st); + st2 = (u_char *) malloc((unsigned)(1 + st_len + FLDSZ)); + *st2 = (u_char) GET_ENT; /* here's the opcode */ + bcopy((char *) st, (char *) st2 + 1, st_len); /* append st on */ + for (loop = FLDSZ - 1; loop >= 0; loop--) + *(st2 + st_len + FLDSZ - loop) = fl[loop]; /* append the flags */ + retc = kadm_cli_send(st2, st_len + 1 + FLDSZ, &ret_st, &ret_sz); + free((char *)st); + free((char *)st2); + if (retc == KADM_SUCCESS) { + /* ret_st has vals */ + if (stream_to_vals(ret_st, vals, ret_sz) < 0) + retc = KADM_LENGTH_ERROR; + free((char *)ret_st); + } + kadm_cli_disconn(); + return(retc); +} + +/* + * kadm_cli_send + * recieves : opcode, packet, packet length, serv_name, serv_inst + * returns : return code from the packet build, the server, or + * something else + * + * It assembles a packet as follows: + * 8 bytes : VERSION STRING + * 4 bytes : LENGTH OF MESSAGE DATA and OPCODE + * : KTEXT + * : OPCODE \ + * : DATA > Encrypted (with make priv) + * : ...... / + * + * If it builds the packet and it is small enough, then it attempts to open the + * connection to the admin server. If the connection is succesfully open + * then it sends the data and waits for a reply. + */ +int +kadm_cli_send(st_dat, st_siz, ret_dat, ret_siz) +u_char *st_dat; /* the actual data */ +int st_siz; /* length of said data */ +u_char **ret_dat; /* to give return info */ +int *ret_siz; /* length of returned info */ +{ + int act_len, retdat; /* current offset into packet, return + * data */ + KTEXT_ST authent; /* the authenticator we will build */ + u_char *act_st; /* the pointer to the complete packet */ + u_char *priv_pak; /* private version of the packet */ + int priv_len; /* length of private packet */ + u_long cksum; /* checksum of the packet */ + MSG_DAT mdat; + u_char *return_dat; + + act_st = (u_char *) malloc(KADM_VERSIZE); /* verstr stored first */ + (void) strncpy((char *)act_st, KADM_VERSTR, KADM_VERSIZE); + act_len = KADM_VERSIZE; + + if ((retdat = kadm_cli_keyd(sess_key, sess_sched)) != KADM_SUCCESS) { + free((char *)act_st); + return retdat; /* couldnt get key working */ + } + priv_pak = (u_char *) malloc((unsigned)(st_siz + 200)); + /* 200 bytes for extra info case */ + if ((priv_len = krb_mk_priv(st_dat, priv_pak, (u_long)st_siz, + sess_sched, sess_key, &client_parm.my_addr, + &client_parm.admin_addr)) < 0) + RET_N_FREE(KADM_NO_ENCRYPT); /* whoops... we got a lose + * here */ + /* here is the length of priv data. receiver calcs + size of authenticator by subtracting vno size, priv size, and + sizeof(u_long) (for the size indication) from total size */ + + act_len += vts_long((u_long) priv_len, &act_st, act_len); +#ifdef NOENCRYPTION + cksum = 0; +#else + cksum = quad_cksum((des_cblock *)priv_pak, (des_cblock *)0, + (long)priv_len, 0, (des_cblock *)sess_key); +#endif + if ((retdat = krb_mk_req(&authent, client_parm.sname, client_parm.sinst, + client_parm.krbrlm, (long)cksum))) { + /* authenticator? */ + RET_N_FREE(retdat + krb_err_base); + } + + act_st = (u_char *) realloc((char *) act_st, + (unsigned) (act_len + authent.length + + priv_len)); + if (!act_st) { + clear_secrets(); + free((char *)priv_pak); + return(KADM_NOMEM); + } + bcopy((char *) authent.dat, (char *) act_st + act_len, authent.length); + bcopy((char *) priv_pak, (char *) act_st + act_len + authent.length, + priv_len); + free((char *)priv_pak); + if ((retdat = kadm_cli_out(act_st, + act_len + authent.length + priv_len, + ret_dat, ret_siz)) != KADM_SUCCESS) + RET_N_FREE(retdat); + free((char *)act_st); +#define RET_N_FREE2(r) {free((char *)*ret_dat); clear_secrets(); return(r);} + + /* first see if it's a YOULOUSE */ + if ((*ret_siz >= KADM_VERSIZE) && + !strncmp(KADM_ULOSE, (char *)*ret_dat, KADM_VERSIZE)) { + u_long errcode; + /* it's a youlose packet */ + if (*ret_siz < KADM_VERSIZE + sizeof(u_long)) + RET_N_FREE2(KADM_BAD_VER); + bcopy((char *)(*ret_dat) + KADM_VERSIZE, (char *)&errcode, + sizeof(u_long)); + retdat = (int) ntohl(errcode); + RET_N_FREE2(retdat); + } + /* need to decode the ret_dat */ + if ((retdat = krb_rd_priv(*ret_dat, (u_long)*ret_siz, sess_sched, + sess_key, &client_parm.admin_addr, + &client_parm.my_addr, &mdat))) + RET_N_FREE2(retdat+krb_err_base); + if (mdat.app_length < KADM_VERSIZE + 4) + /* too short! */ + RET_N_FREE2(KADM_BAD_VER); + if (strncmp((char *)mdat.app_data, KADM_VERSTR, KADM_VERSIZE)) + /* bad version */ + RET_N_FREE2(KADM_BAD_VER); + bcopy((char *)mdat.app_data+KADM_VERSIZE, + (char *)&retdat, sizeof(u_long)); + retdat = ntohl((u_long)retdat); + if (!(return_dat = (u_char *)malloc((unsigned)(mdat.app_length - + KADM_VERSIZE - sizeof(u_long))))) + RET_N_FREE2(KADM_NOMEM); + bcopy((char *) mdat.app_data + KADM_VERSIZE + sizeof(u_long), + (char *)return_dat, + (int)mdat.app_length - KADM_VERSIZE - sizeof(u_long)); + free((char *)*ret_dat); + clear_secrets(); + *ret_dat = return_dat; + *ret_siz = mdat.app_length - KADM_VERSIZE - sizeof(u_long); + return retdat; +} + +/* takes in the sess_key and key_schedule and sets them appropriately */ +int +kadm_cli_keyd(s_k, s_s) +des_cblock s_k; /* session key */ +des_key_schedule s_s; /* session key schedule */ +{ + CREDENTIALS cred; /* to get key data */ + int stat; + + /* want .sname and .sinst here.... */ + if ((stat = krb_get_cred(client_parm.sname, client_parm.sinst, + client_parm.krbrlm, &cred))) + return stat + krb_err_base; + bcopy((char *) cred.session, (char *) s_k, sizeof(des_cblock)); + bzero((char *) cred.session, sizeof(des_cblock)); +#ifdef NOENCRYPTION + bzero(s_s, sizeof(des_key_schedule)); +#else + if ((stat = key_sched((des_cblock *)s_k,s_s))) + return(stat+krb_err_base); +#endif + return KADM_SUCCESS; +} /* This code "works" */ + +static sigtype (*opipe)(); + +int +kadm_cli_conn() +{ /* this connects and sets my_addr */ + int on = 1; + + if ((client_parm.admin_fd = + socket(client_parm.admin_addr.sin_family, SOCK_STREAM,0)) < 0) + return KADM_NO_SOCK; /* couldnt create the socket */ + if (connect(client_parm.admin_fd, + (struct sockaddr *) & client_parm.admin_addr, + sizeof(client_parm.admin_addr))) { + (void) close(client_parm.admin_fd); + client_parm.admin_fd = -1; + return KADM_NO_CONN; /* couldnt get the connect */ + } + opipe = signal(SIGPIPE, SIG_IGN); + client_parm.my_addr_len = sizeof(client_parm.my_addr); + if (getsockname(client_parm.admin_fd, + (struct sockaddr *) & client_parm.my_addr, + &client_parm.my_addr_len) < 0) { + (void) close(client_parm.admin_fd); + client_parm.admin_fd = -1; + (void) signal(SIGPIPE, opipe); + return KADM_NO_HERE; /* couldnt find out who we are */ + } + if (setsockopt(client_parm.admin_fd, SOL_SOCKET, SO_KEEPALIVE, &on, + sizeof(on)) < 0) { + (void) close(client_parm.admin_fd); + client_parm.admin_fd = -1; + (void) signal(SIGPIPE, opipe); + return KADM_NO_CONN; /* XXX */ + } + return KADM_SUCCESS; +} + +void +kadm_cli_disconn() +{ + (void) close(client_parm.admin_fd); + (void) signal(SIGPIPE, opipe); +} + +int +kadm_cli_out(dat, dat_len, ret_dat, ret_siz) +u_char *dat; +int dat_len; +u_char **ret_dat; +int *ret_siz; +{ + extern int errno; + u_short dlen; + int retval; + + dlen = (u_short) dat_len; + + if (dat_len != (int)dlen) + return (KADM_NO_ROOM); + + dlen = htons(dlen); + if (krb_net_write(client_parm.admin_fd, (char *) &dlen, + sizeof(u_short)) < 0) + return (errno); /* XXX */ + + if (krb_net_write(client_parm.admin_fd, (char *) dat, dat_len) < 0) + return (errno); /* XXX */ + + if ((retval = krb_net_read(client_parm.admin_fd, (char *) &dlen, + sizeof(u_short)) != sizeof(u_short))) { + if (retval < 0) + return(errno); /* XXX */ + else + return(EPIPE); /* short read ! */ + } + + dlen = ntohs(dlen); + *ret_dat = (u_char *)malloc((unsigned)dlen); + if (!*ret_dat) + return(KADM_NOMEM); + + if ((retval = krb_net_read(client_parm.admin_fd, (char *) *ret_dat, + (int) dlen) != dlen)) { + if (retval < 0) + return(errno); /* XXX */ + else + return(EPIPE); /* short read ! */ + } + *ret_siz = (int) dlen; + return KADM_SUCCESS; +} diff --git a/eBones/lib/libkadm/kadm_err.et b/eBones/lib/libkadm/kadm_err.et new file mode 100644 index 0000000000000..e45a9c24cb7f6 --- /dev/null +++ b/eBones/lib/libkadm/kadm_err.et @@ -0,0 +1,53 @@ +# $Source: /usr/cvs/src/eBones/libkadm/kadm_err.et,v $ +# $Author: mark $ +# $Header: /usr/cvs/src/eBones/libkadm/kadm_err.et,v 1.1 1995/07/18 16:40:25 mark Exp $ +# Copyright 1988 by the Massachusetts Institute of Technology. +# +# For copying and distribution information, please see the file +# <mit-copyright.h>. +# +# Kerberos administration server error table +# + et kadm + +# KADM_SUCCESS, as all success codes should be, is zero + +ec KADM_RCSID, "$Header: /usr/cvs/src/eBones/libkadm/kadm_err.et,v 1.1 1995/07/18 16:40:25 mark Exp $" +# /* Building and unbuilding the packet errors */ +ec KADM_NO_REALM, "Cannot fetch local realm" +ec KADM_NO_CRED, "Unable to fetch credentials" +ec KADM_BAD_KEY, "Bad key supplied" +ec KADM_NO_ENCRYPT, "Can't encrypt data" +ec KADM_NO_AUTH, "Cannot encode/decode authentication info" +ec KADM_WRONG_REALM, "Principal attemping change is in wrong realm" +ec KADM_NO_ROOM, "Packet is too large" +ec KADM_BAD_VER, "Version number is incorrect" +ec KADM_BAD_CHK, "Checksum does not match" +ec KADM_NO_READ, "Unsealing private data failed" +ec KADM_NO_OPCODE, "Unsupported operation" +ec KADM_NO_HOST, "Could not find administrating host" +ec KADM_UNK_HOST, "Administrating host name is unknown" +ec KADM_NO_SERV, "Could not find service name in services database" +ec KADM_NO_SOCK, "Could not create socket" +ec KADM_NO_CONN, "Could not connect to server" +ec KADM_NO_HERE, "Could not fetch local socket address" +ec KADM_NO_MAST, "Could not fetch master key" +ec KADM_NO_VERI, "Could not verify master key" + +# /* From the server side routines */ +ec KADM_INUSE, "Entry already exists in database" +ec KADM_UK_SERROR, "Database store error" +ec KADM_UK_RERROR, "Database read error" +ec KADM_UNAUTH, "Insufficient access to perform requested operation" +# KADM_DATA isn't really an error, but... +ec KADM_DATA, "Data is available for return to client" +ec KADM_NOENTRY, "No such entry in the database" + +ec KADM_NOMEM, "Memory exhausted" +ec KADM_NO_HOSTNAME, "Could not fetch system hostname" +ec KADM_NO_BIND, "Could not bind port" +ec KADM_LENGTH_ERROR, "Length mismatch problem" +ec KADM_ILL_WILDCARD, "Illegal use of wildcard" + +ec KADM_DB_INUSE, "Database is locked or in use--try again later" +end diff --git a/eBones/lib/libkadm/kadm_stream.c b/eBones/lib/libkadm/kadm_stream.c new file mode 100644 index 0000000000000..58a625a464b1d --- /dev/null +++ b/eBones/lib/libkadm/kadm_stream.c @@ -0,0 +1,286 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Stream conversion functions for Kerberos administration server + */ + +#if 0 +#ifndef lint +static char rcsid_kadm_stream_c[] = +"Header: /afs/athena.mit.edu/astaff/project/kerberos/src/lib/kadm/RCS/kadm_stream.c,v 4.2 89/09/26 09:20:48 jtkohl Exp "; +static const char rcsid[] = + "$Id: kadm_stream.c,v 1.1 1995/07/18 16:40:27 mark Exp $"; +#endif lint +#endif + +/* + kadm_stream.c + this holds the stream support routines for the kerberos administration server + + vals_to_stream: converts a vals struct to a stream for transmission + internals build_field_header, vts_[string, char, long, short] + stream_to_vals: converts a stream to a vals struct + internals check_field_header, stv_[string, char, long, short] + error: prints out a kadm error message, returns + fatal: prints out a kadm fatal error message, exits +*/ + +#include <string.h> +#include <kadm.h> + +#define min(a,b) (((a) < (b)) ? (a) : (b)) + +/* +vals_to_stream + recieves : kadm_vals *, u_char * + returns : a realloced and filled in u_char * + +this function creates a byte-stream representation of the kadm_vals structure +*/ + +int +vals_to_stream(dt_in, dt_out) +Kadm_vals *dt_in; +u_char **dt_out; +{ + int vsloop, stsize; /* loop counter, stream size */ + + stsize = build_field_header(dt_in->fields, dt_out); + for (vsloop=31; vsloop>=0; vsloop--) + if (IS_FIELD(vsloop,dt_in->fields)) { + switch (vsloop) { + case KADM_NAME: + stsize+=vts_string(dt_in->name, dt_out, stsize); + break; + case KADM_INST: + stsize+=vts_string(dt_in->instance, dt_out, stsize); + break; + case KADM_EXPDATE: + stsize+=vts_long(dt_in->exp_date, dt_out, stsize); + break; + case KADM_ATTR: + stsize+=vts_short(dt_in->attributes, dt_out, stsize); + break; + case KADM_MAXLIFE: + stsize+=vts_char(dt_in->max_life, dt_out, stsize); + break; + case KADM_DESKEY: + stsize+=vts_long(dt_in->key_high, dt_out, stsize); + stsize+=vts_long(dt_in->key_low, dt_out, stsize); + break; + default: + break; + } +} + return(stsize); +} + +int +build_field_header(cont, st) +u_char *cont; /* container for fields data */ +u_char **st; /* stream */ +{ + *st = (u_char *) malloc (4); + bcopy((char *) cont, (char *) *st, 4); + return 4; /* return pointer to current stream location */ +} + +int +vts_string(dat, st, loc) +char *dat; /* a string to put on the stream */ +u_char **st; /* base pointer to the stream */ +int loc; /* offset into the stream for current data */ +{ + *st = (u_char *) realloc ((char *)*st, (unsigned) (loc + strlen(dat) + 1)); + bcopy(dat, (char *)(*st + loc), strlen(dat)+1); + return strlen(dat)+1; +} + +int +vts_short(dat, st, loc) +u_short dat; /* the attributes field */ +u_char **st; /* a base pointer to the stream */ +int loc; /* offset into the stream for current data */ +{ + u_short temp; /* to hold the net order short */ + + temp = htons(dat); /* convert to network order */ + *st = (u_char *) realloc ((char *)*st, (unsigned)(loc + sizeof(u_short))); + bcopy((char *) &temp, (char *)(*st + loc), sizeof(u_short)); + return sizeof(u_short); +} + +int +vts_long(dat, st, loc) +u_long dat; /* the attributes field */ +u_char **st; /* a base pointer to the stream */ +int loc; /* offset into the stream for current data */ +{ + u_long temp; /* to hold the net order short */ + + temp = htonl(dat); /* convert to network order */ + *st = (u_char *) realloc ((char *)*st, (unsigned)(loc + sizeof(u_long))); + bcopy((char *) &temp, (char *)(*st + loc), sizeof(u_long)); + return sizeof(u_long); +} + +int +vts_char(dat, st, loc) +u_char dat; /* the attributes field */ +u_char **st; /* a base pointer to the stream */ +int loc; /* offset into the stream for current data */ +{ + *st = (u_char *) realloc ((char *)*st, (unsigned)(loc + sizeof(u_char))); + (*st)[loc] = (u_char) dat; + return 1; +} + +/* +stream_to_vals + recieves : u_char *, kadm_vals * + returns : a kadm_vals filled in according to u_char * + +this decodes a byte stream represntation of a vals struct into kadm_vals +*/ +int +stream_to_vals(dt_in, dt_out, maxlen) +u_char *dt_in; +Kadm_vals *dt_out; +int maxlen; /* max length to use */ +{ + register int vsloop, stsize; /* loop counter, stream size */ + register int status; + + bzero((char *) dt_out, sizeof(*dt_out)); + + stsize = check_field_header(dt_in, dt_out->fields, maxlen); + if (stsize < 0) + return(-1); + for (vsloop=31; vsloop>=0; vsloop--) + if (IS_FIELD(vsloop,dt_out->fields)) + switch (vsloop) { + case KADM_NAME: + if ((status = stv_string(dt_in, dt_out->name, stsize, + sizeof(dt_out->name), maxlen)) < 0) + return(-1); + stsize += status; + break; + case KADM_INST: + if ((status = stv_string(dt_in, dt_out->instance, stsize, + sizeof(dt_out->instance), maxlen)) < 0) + return(-1); + stsize += status; + break; + case KADM_EXPDATE: + if ((status = stv_long(dt_in, &dt_out->exp_date, stsize, + maxlen)) < 0) + return(-1); + stsize += status; + break; + case KADM_ATTR: + if ((status = stv_short(dt_in, &dt_out->attributes, stsize, + maxlen)) < 0) + return(-1); + stsize += status; + break; + case KADM_MAXLIFE: + if ((status = stv_char(dt_in, &dt_out->max_life, stsize, + maxlen)) < 0) + return(-1); + stsize += status; + break; + case KADM_DESKEY: + if ((status = stv_long(dt_in, &dt_out->key_high, stsize, + maxlen)) < 0) + return(-1); + stsize += status; + if ((status = stv_long(dt_in, &dt_out->key_low, stsize, + maxlen)) < 0) + return(-1); + stsize += status; + break; + default: + break; + } + return stsize; +} + +int +check_field_header(st, cont, maxlen) +u_char *st; /* stream */ +u_char *cont; /* container for fields data */ +int maxlen; +{ + if (4 > maxlen) + return(-1); + bcopy((char *) st, (char *) cont, 4); + return 4; /* return pointer to current stream location */ +} + +int +stv_string(st, dat, loc, stlen, maxlen) +register u_char *st; /* base pointer to the stream */ +char *dat; /* a string to read from the stream */ +register int loc; /* offset into the stream for current data */ +int stlen; /* max length of string to copy in */ +int maxlen; /* max length of input stream */ +{ + int maxcount; /* max count of chars to copy */ + + maxcount = min(maxlen - loc, stlen); + + (void) strncpy(dat, (char *)st + loc, maxcount); + + if (dat[maxcount-1]) /* not null-term --> not enuf room */ + return(-1); + return strlen(dat)+1; +} + +int +stv_short(st, dat, loc, maxlen) +u_char *st; /* a base pointer to the stream */ +u_short *dat; /* the attributes field */ +int loc; /* offset into the stream for current data */ +int maxlen; +{ + u_short temp; /* to hold the net order short */ + + if (loc + sizeof(u_short) > maxlen) + return(-1); + bcopy((char *)((u_long)st+(u_long)loc), (char *) &temp, sizeof(u_short)); + *dat = ntohs(temp); /* convert to network order */ + return sizeof(u_short); +} + +int +stv_long(st, dat, loc, maxlen) +u_char *st; /* a base pointer to the stream */ +u_long *dat; /* the attributes field */ +int loc; /* offset into the stream for current data */ +int maxlen; /* maximum length of st */ +{ + u_long temp; /* to hold the net order short */ + + if (loc + sizeof(u_long) > maxlen) + return(-1); + bcopy((char *)((u_long)st+(u_long)loc), (char *) &temp, sizeof(u_long)); + *dat = ntohl(temp); /* convert to network order */ + return sizeof(u_long); +} + +int +stv_char(st, dat, loc, maxlen) +u_char *st; /* a base pointer to the stream */ +u_char *dat; /* the attributes field */ +int loc; /* offset into the stream for current data */ +int maxlen; +{ + if (loc + 1 > maxlen) + return(-1); + *dat = *(st + loc); + return 1; +} + diff --git a/eBones/lib/libkadm/kadm_supp.c b/eBones/lib/libkadm/kadm_supp.c new file mode 100644 index 0000000000000..353fed0ed9b33 --- /dev/null +++ b/eBones/lib/libkadm/kadm_supp.c @@ -0,0 +1,118 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Support functions for Kerberos administration server & clients + */ + +#if 0 +#ifndef lint +static char rcsid_kadm_supp_c[] = +"Header: /afs/athena.mit.edu/astaff/project/kerberos/src/lib/kadm/RCS/kadm_supp.c,v 4.1 89/09/26 09:21:07 jtkohl Exp "; +static const char rcsid[] = + "$Id: kadm_supp.c,v 1.1 1995/07/18 16:40:28 mark Exp $"; +#endif lint +#endif + +/* + kadm_supp.c + this holds the support routines for the kerberos administration server + + error: prints out a kadm error message, returns + fatal: prints out a kadm fatal error message, exits + prin_vals: prints out data associated with a Principal in the vals + structure +*/ + +#include <string.h> +#include <time.h> +#include <kadm.h> +#include <krb_db.h> + +/* +prin_vals: + recieves : a vals structure +*/ +void +prin_vals(vals) +Kadm_vals *vals; +{ + printf("Info in Database for %s.%s:\n", vals->name, vals->instance); + printf(" Max Life: %d Exp Date: %s\n",vals->max_life, + asctime(localtime((long *)&vals->exp_date))); + printf(" Attribs: %.2x key: %lu %lu\n",vals->attributes, + vals->key_low, vals->key_high); +} + +#ifdef notdef +nierror(s) +int s; +{ + printf("Kerberos admin server loses..... %s\n",error_message(s)); + return(s); +} +#endif + +/* kadm_prin_to_vals takes a fields arguments, a Kadm_vals and a Principal, + it copies the fields in Principal specified by fields into Kadm_vals, + i.e from old to new */ + +void +kadm_prin_to_vals(fields, new, old) +u_char fields[FLDSZ]; +Kadm_vals *new; +Principal *old; +{ + bzero((char *)new, sizeof(*new)); + if (IS_FIELD(KADM_NAME,fields)) { + (void) strncpy(new->name, old->name, ANAME_SZ); + SET_FIELD(KADM_NAME, new->fields); + } + if (IS_FIELD(KADM_INST,fields)) { + (void) strncpy(new->instance, old->instance, INST_SZ); + SET_FIELD(KADM_INST, new->fields); + } + if (IS_FIELD(KADM_EXPDATE,fields)) { + new->exp_date = old->exp_date; + SET_FIELD(KADM_EXPDATE, new->fields); + } + if (IS_FIELD(KADM_ATTR,fields)) { + new->attributes = old->attributes; + SET_FIELD(KADM_MAXLIFE, new->fields); + } + if (IS_FIELD(KADM_MAXLIFE,fields)) { + new->max_life = old->max_life; + SET_FIELD(KADM_MAXLIFE, new->fields); + } + if (IS_FIELD(KADM_DESKEY,fields)) { + new->key_low = old->key_low; + new->key_high = old->key_high; + SET_FIELD(KADM_DESKEY, new->fields); + } +} + +void +kadm_vals_to_prin(fields, new, old) +u_char fields[FLDSZ]; +Principal *new; +Kadm_vals *old; +{ + + bzero((char *)new, sizeof(*new)); + if (IS_FIELD(KADM_NAME,fields)) + (void) strncpy(new->name, old->name, ANAME_SZ); + if (IS_FIELD(KADM_INST,fields)) + (void) strncpy(new->instance, old->instance, INST_SZ); + if (IS_FIELD(KADM_EXPDATE,fields)) + new->exp_date = old->exp_date; + if (IS_FIELD(KADM_ATTR,fields)) + new->attributes = old->attributes; + if (IS_FIELD(KADM_MAXLIFE,fields)) + new->max_life = old->max_life; + if (IS_FIELD(KADM_DESKEY,fields)) { + new->key_low = old->key_low; + new->key_high = old->key_high; + } +} diff --git a/eBones/lib/libkdb/Makefile b/eBones/lib/libkdb/Makefile new file mode 100644 index 0000000000000..29beb2401b309 --- /dev/null +++ b/eBones/lib/libkdb/Makefile @@ -0,0 +1,8 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1995/09/13 17:23:53 markm Exp $ + +LIB= kdb +CFLAGS+=-DKERBEROS -DDEBUG +SRCS= krb_cache.c krb_dbm.c krb_kdb_utils.c krb_lib.c print_princ.c + +.include <bsd.lib.mk> diff --git a/eBones/lib/libkdb/krb_cache.c b/eBones/lib/libkdb/krb_cache.c new file mode 100644 index 0000000000000..1c7c9ce3d7f27 --- /dev/null +++ b/eBones/lib/libkdb/krb_cache.c @@ -0,0 +1,181 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * This is where a cache would be implemented, if it were necessary. + * + * from: krb_cache.c,v 4.5 89/01/24 18:12:34 jon Exp $ + * $Id: krb_cache.c,v 1.3 1995/07/18 16:37:12 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: krb_cache.c,v 1.3 1995/07/18 16:37:12 mark Exp $"; +#endif lint +#endif + +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/uio.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <strings.h> +#include <des.h> +#include <krb.h> +#include <krb_db.h> + +#ifdef DEBUG +extern int debug; +extern long kerb_debug; +#endif +static init = 0; + +/* + * initialization routine for cache + */ + +int +kerb_cache_init() +{ + init = 1; + return (0); +} + +/* + * look up a principal in the cache returns number of principals found + */ + +int +kerb_cache_get_principal(serv, inst, principal, max) + char *serv; /* could have wild card */ + char *inst; /* could have wild card */ + Principal *principal; + unsigned int max; /* max number of name structs to return */ + +{ + int found = 0; + + if (!init) + kerb_cache_init(); +#ifdef DEBUG + if (kerb_debug & 2) { + fprintf(stderr, "cache_get_principal for %s %s max = %d\n", + serv, inst, max); + if (found) { + fprintf(stderr, "cache get %s %s found %s %s\n", + serv, inst, principal->name, principal->instance); + } else { + fprintf(stderr, "cache %s %s not found\n", serv, + inst); + } + } +#endif + return (found); +} + +/* + * insert/replace a principal in the cache returns number of principals + * inserted + */ + +int +kerb_cache_put_principal(principal, max) + Principal *principal; + unsigned int max; /* max number of principal structs to + * insert */ + +{ + u_long i; + int count = 0; + + if (!init) + kerb_cache_init(); + +#ifdef DEBUG + if (kerb_debug & 2) { + fprintf(stderr, "kerb_cache_put_principal max = %d", + max); + } +#endif + + for (i = 0; i < max; i++) { +#ifdef DEBUG + if (kerb_debug & 2) + fprintf(stderr, "\n %s %s", + principal->name, principal->instance); +#endif + /* DO IT */ + count++; + principal++; + } + return count; +} + +/* + * look up a dba in the cache returns number of dbas found + */ + +int +kerb_cache_get_dba(serv, inst, dba, max) + char *serv; /* could have wild card */ + char *inst; /* could have wild card */ + Dba *dba; + unsigned int max; /* max number of name structs to return */ + +{ + int found = 0; + + if (!init) + kerb_cache_init(); + +#ifdef DEBUG + if (kerb_debug & 2) { + fprintf(stderr, "cache_get_dba for %s %s max = %d\n", + serv, inst, max); + if (found) { + fprintf(stderr, "cache get %s %s found %s %s\n", + serv, inst, dba->name, dba->instance); + } else { + fprintf(stderr, "cache %s %s not found\n", serv, inst); + } + } +#endif + return (found); +} + +/* + * insert/replace a dba in the cache returns number of dbas inserted + */ + +int +kerb_cache_put_dba(dba, max) + Dba *dba; + unsigned int max; /* max number of dba structs to insert */ + +{ + u_long i; + int count = 0; + + if (!init) + kerb_cache_init(); +#ifdef DEBUG + if (kerb_debug & 2) { + fprintf(stderr, "kerb_cache_put_dba max = %d", max); + } +#endif + for (i = 0; i < max; i++) { +#ifdef DEBUG + if (kerb_debug & 2) + fprintf(stderr, "\n %s %s", + dba->name, dba->instance); +#endif + /* DO IT */ + count++; + dba++; + } + return count; +} + diff --git a/eBones/lib/libkdb/krb_dbm.c b/eBones/lib/libkdb/krb_dbm.c new file mode 100644 index 0000000000000..760bd6f6bd37d --- /dev/null +++ b/eBones/lib/libkdb/krb_dbm.c @@ -0,0 +1,789 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: krb_dbm.c,v 4.9 89/04/18 16:15:13 wesommer Exp $ + * $Id: krb_dbm.c,v 1.4 1995/08/03 17:15:42 mark Exp $ +*/ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: krb_dbm.c,v 1.4 1995/08/03 17:15:42 mark Exp $"; +#endif lint +#endif + +#if defined(__FreeBSD__) || defined(__NetBSD__) +#define _NDBM_ +#endif + +#if defined(__FreeBSD__) || defined(__NetBSD__) +#define _DBM_ +#endif + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/uio.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <sys/resource.h> +#include <sys/errno.h> +#include <strings.h> +#include <des.h> +#include <sys/file.h> +#ifdef _NDBM_ +#include <ndbm.h> +#else /*_NDBM_*/ +#include <dbm.h> +#endif /*_NDBM_*/ +/* before krb_db.h */ +#include <krb.h> +#include <krb_db.h> + +#ifdef dbm_pagfno +#define DB +#endif + +#define KERB_DB_MAX_RETRY 5 + +#ifdef DEBUG +extern int debug; +extern long kerb_debug; +extern char *progname; +#endif + +static init = 0; +static char default_db_name[] = DBM_FILE; +static char *current_db_name = default_db_name; +static void encode_princ_key(datum *key, char *name, char *instance); +static void decode_princ_key(datum *key, char *name, char *instance); +static void encode_princ_contents(datum *contents, Principal *principal); +static void decode_princ_contents(datum *contents, Principal *principal); +static void kerb_dbl_fini(void); +static int kerb_dbl_lock(int mode); +static void kerb_dbl_unlock(void); +static long kerb_start_update(char *db_name); +static long kerb_end_update(char *db_name, long age); + +static struct timeval timestamp;/* current time of request */ +static int non_blocking = 0; + +/* + * This module contains all of the code which directly interfaces to + * the underlying representation of the Kerberos database; this + * implementation uses a DBM or NDBM indexed "file" (actually + * implemented as two separate files) to store the relations, plus a + * third file as a semaphore to allow the database to be replaced out + * from underneath the KDC server. + */ + +/* + * Locking: + * + * There are two distinct locking protocols used. One is designed to + * lock against processes (the admin_server, for one) which make + * incremental changes to the database; the other is designed to lock + * against utilities (kdb_util, kpropd) which replace the entire + * database in one fell swoop. + * + * The first locking protocol is implemented using flock() in the + * krb_dbl_lock() and krb_dbl_unlock routines. + * + * The second locking protocol is necessary because DBM "files" are + * actually implemented as two separate files, and it is impossible to + * atomically rename two files simultaneously. It assumes that the + * database is replaced only very infrequently in comparison to the time + * needed to do a database read operation. + * + * A third file is used as a "version" semaphore; the modification + * time of this file is the "version number" of the database. + * At the start of a read operation, the reader checks the version + * number; at the end of the read operation, it checks again. If the + * version number changed, or if the semaphore was nonexistant at + * either time, the reader sleeps for a second to let things + * stabilize, and then tries again; if it does not succeed after + * KERB_DB_MAX_RETRY attempts, it gives up. + * + * On update, the semaphore file is deleted (if it exists) before any + * update takes place; at the end of the update, it is replaced, with + * a version number strictly greater than the version number which + * existed at the start of the update. + * + * If the system crashes in the middle of an update, the semaphore + * file is not automatically created on reboot; this is a feature, not + * a bug, since the database may be inconsistant. Note that the + * absence of a semaphore file does not prevent another _update_ from + * taking place later. Database replacements take place automatically + * only on slave servers; a crash in the middle of an update will be + * fixed by the next slave propagation. A crash in the middle of an + * update on the master would be somewhat more serious, but this would + * likely be noticed by an administrator, who could fix the problem and + * retry the operation. + */ + +/* Macros to convert ndbm names to dbm names. + * Note that dbm_nextkey() cannot be simply converted using a macro, since + * it is invoked giving the database, and nextkey() needs the previous key. + * + * Instead, all routines call "dbm_next" instead. + */ + +#ifndef _NDBM_ +typedef char DBM; + +#define dbm_open(file, flags, mode) ((dbminit(file) == 0)?"":((char *)0)) +#define dbm_fetch(db, key) fetch(key) +#define dbm_store(db, key, content, flag) store(key, content) +#define dbm_firstkey(db) firstkey() +#define dbm_next(db,key) nextkey(key) +#define dbm_close(db) dbmclose() +#else +#define dbm_next(db,key) dbm_nextkey(db) +#endif + +/* + * Utility routine: generate name of database file. + */ + +static char *gen_dbsuffix(db_name, sfx) + char *db_name; + char *sfx; +{ + char *dbsuffix; + + if (sfx == NULL) + sfx = ".ok"; + + dbsuffix = malloc (strlen(db_name) + strlen(sfx) + 1); + strcpy(dbsuffix, db_name); + strcat(dbsuffix, sfx); + return dbsuffix; +} + +/* + * initialization for data base routines. + */ + +int +kerb_db_init() +{ + init = 1; + return (0); +} + +/* + * gracefully shut down database--must be called by ANY program that does + * a kerb_db_init + */ + +void +kerb_db_fini() +{ +} + +/* + * Set the "name" of the current database to some alternate value. + * + * Passing a null pointer as "name" will set back to the default. + * If the alternate database doesn't exist, nothing is changed. + */ + +int +kerb_db_set_name(name) + char *name; +{ + DBM *db; + + if (name == NULL) + name = default_db_name; + db = dbm_open(name, 0, 0); + if (db == NULL) + return errno; + dbm_close(db); + kerb_dbl_fini(); + current_db_name = name; + return 0; +} + +/* + * Return the last modification time of the database. + */ + +long +kerb_get_db_age() +{ + struct stat st; + char *okname; + long age; + + okname = gen_dbsuffix(current_db_name, ".ok"); + + if (stat (okname, &st) < 0) + age = 0; + else + age = st.st_mtime; + + free (okname); + return age; +} + +/* + * Remove the semaphore file; indicates that database is currently + * under renovation. + * + * This is only for use when moving the database out from underneath + * the server (for example, during slave updates). + */ + +static long +kerb_start_update(db_name) + char *db_name; +{ + char *okname = gen_dbsuffix(db_name, ".ok"); + long age = kerb_get_db_age(); + + if (unlink(okname) < 0 + && errno != ENOENT) { + age = -1; + } + free (okname); + return age; +} + +static long +kerb_end_update(db_name, age) + char *db_name; + long age; +{ + int fd; + int retval = 0; + char *new_okname = gen_dbsuffix(db_name, ".ok#"); + char *okname = gen_dbsuffix(db_name, ".ok"); + + fd = open (new_okname, O_CREAT|O_RDWR|O_TRUNC, 0600); + if (fd < 0) + retval = errno; + else { + struct stat st; + struct timeval tv[2]; + /* make sure that semaphore is "after" previous value. */ + if (fstat (fd, &st) == 0 + && st.st_mtime <= age) { + tv[0].tv_sec = st.st_atime; + tv[0].tv_usec = 0; + tv[1].tv_sec = age; + tv[1].tv_usec = 0; + /* set times.. */ + utimes (new_okname, tv); + fsync(fd); + } + close(fd); + if (rename (new_okname, okname) < 0) + retval = errno; + } + + free (new_okname); + free (okname); + + return retval; +} + +static long +kerb_start_read() +{ + return kerb_get_db_age(); +} + +static long +kerb_end_read(age) + u_long age; +{ + if (kerb_get_db_age() != age || age == -1) { + return -1; + } + return 0; +} + +/* + * Create the database, assuming it's not there. + */ + +int +kerb_db_create(db_name) + char *db_name; +{ + char *okname = gen_dbsuffix(db_name, ".ok"); + int fd; + register int ret = 0; +#ifdef _NDBM_ + DBM *db; + + db = dbm_open(db_name, O_RDWR|O_CREAT|O_EXCL, 0600); + if (db == NULL) + ret = errno; + else + dbm_close(db); +#else + char *dirname = gen_dbsuffix(db_name, ".dir"); + char *pagname = gen_dbsuffix(db_name, ".pag"); + + fd = open(dirname, O_RDWR|O_CREAT|O_EXCL, 0600); + if (fd < 0) + ret = errno; + else { + close(fd); + fd = open (pagname, O_RDWR|O_CREAT|O_EXCL, 0600); + if (fd < 0) + ret = errno; + else + close(fd); + } + if (dbminit(db_name) < 0) + ret = errno; +#endif + if (ret == 0) { + fd = open (okname, O_CREAT|O_RDWR|O_TRUNC, 0600); + if (fd < 0) + ret = errno; + close(fd); + } + return ret; +} + +/* + * "Atomically" rename the database in a way that locks out read + * access in the middle of the rename. + * + * Not perfect; if we crash in the middle of an update, we don't + * necessarily know to complete the transaction the rename, but... + */ + +int +kerb_db_rename(from, to) + char *from; + char *to; +{ +#ifdef _DBM_ + char *fromdb = gen_dbsuffix (from, ".db"); + char *todb = gen_dbsuffix (to, ".db"); +#else + char *fromdir = gen_dbsuffix (from, ".dir"); + char *todir = gen_dbsuffix (to, ".dir"); + char *frompag = gen_dbsuffix (from , ".pag"); + char *topag = gen_dbsuffix (to, ".pag"); +#endif + char *fromok = gen_dbsuffix(from, ".ok"); + long trans = kerb_start_update(to); + int ok = 0; + +#ifdef _DBM_ + if (rename (fromdb, todb) == 0) { +#else + if ((rename (fromdir, todir) == 0) + && (rename (frompag, topag) == 0)) { +#endif + (void) unlink (fromok); + ok = 1; + } + + free (fromok); +#ifdef _DBM_ + free (fromdb); + free (todb); +#else + free (fromdir); + free (todir); + free (frompag); + free (topag); +#endif + if (ok) + return kerb_end_update(to, trans); + else + return -1; +} + +/* + * look up a principal in the data base returns number of principals + * found , and whether there were more than requested. + */ + +int +kerb_db_get_principal(name, inst, principal, max, more) + char *name; /* could have wild card */ + char *inst; /* could have wild card */ + Principal *principal; + unsigned int max; /* max number of name structs to return */ + int *more; /* where there more than 'max' tuples? */ + +{ + int found = 0, code; + extern int errorproc(); + int wildp, wildi; + datum key, contents; + char testname[ANAME_SZ], testinst[INST_SZ]; + u_long trans; + int try; + DBM *db; + + if (!init) + kerb_db_init(); /* initialize database routines */ + + for (try = 0; try < KERB_DB_MAX_RETRY; try++) { + trans = kerb_start_read(); + + if ((code = kerb_dbl_lock(KERB_DBL_SHARED)) != 0) + return -1; + + db = dbm_open(current_db_name, O_RDONLY, 0600); + + *more = 0; + +#ifdef DEBUG + if (kerb_debug & 2) + fprintf(stderr, + "%s: db_get_principal for %s %s max = %d", + progname, name, inst, max); +#endif + + wildp = !strcmp(name, "*"); + wildi = !strcmp(inst, "*"); + + if (!wildi && !wildp) { /* nothing's wild */ + encode_princ_key(&key, name, inst); + contents = dbm_fetch(db, key); + if (contents.dptr == NULL) { + found = 0; + goto done; + } + decode_princ_contents(&contents, principal); +#ifdef DEBUG + if (kerb_debug & 1) { + fprintf(stderr, "\t found %s %s p_n length %d t_n length %d\n", + principal->name, principal->instance, + strlen(principal->name), + strlen(principal->instance)); + } +#endif + found = 1; + goto done; + } + /* process wild cards by looping through entire database */ + + for (key = dbm_firstkey(db); key.dptr != NULL; + key = dbm_next(db, key)) { + decode_princ_key(&key, testname, testinst); + if ((wildp || !strcmp(testname, name)) && + (wildi || !strcmp(testinst, inst))) { /* have a match */ + if (found >= max) { + *more = 1; + goto done; + } else { + found++; + contents = dbm_fetch(db, key); + decode_princ_contents(&contents, principal); +#ifdef DEBUG + if (kerb_debug & 1) { + fprintf(stderr, + "\tfound %s %s p_n length %d t_n length %d\n", + principal->name, principal->instance, + strlen(principal->name), + strlen(principal->instance)); + } +#endif + principal++; /* point to next */ + } + } + } + + done: + kerb_dbl_unlock(); /* unlock read lock */ + dbm_close(db); + if (kerb_end_read(trans) == 0) + break; + found = -1; + if (!non_blocking) + sleep(1); + } + return (found); +} + +/* + * Update a name in the data base. Returns number of names + * successfully updated. + */ + +int +kerb_db_put_principal(principal, max) + Principal *principal; + unsigned int max; /* number of principal structs to + * update */ + +{ + int found = 0, code; + u_long i; + extern int errorproc(); + datum key, contents; + DBM *db; + + gettimeofday(×tamp, NULL); + + if (!init) + kerb_db_init(); + + if ((code = kerb_dbl_lock(KERB_DBL_EXCLUSIVE)) != 0) + return -1; + + db = dbm_open(current_db_name, O_RDWR, 0600); + +#ifdef DEBUG + if (kerb_debug & 2) + fprintf(stderr, "%s: kerb_db_put_principal max = %d", + progname, max); +#endif + + /* for each one, stuff temps, and do replace/append */ + for (i = 0; i < max; i++) { + encode_princ_contents(&contents, principal); + encode_princ_key(&key, principal->name, principal->instance); + dbm_store(db, key, contents, DBM_REPLACE); +#ifdef DEBUG + if (kerb_debug & 1) { + fprintf(stderr, "\n put %s %s\n", + principal->name, principal->instance); + } +#endif + found++; + principal++; /* bump to next struct */ + } + + dbm_close(db); + kerb_dbl_unlock(); /* unlock database */ + return (found); +} + +static void +encode_princ_key(key, name, instance) + datum *key; + char *name, *instance; +{ + static char keystring[ANAME_SZ + INST_SZ]; + + bzero(keystring, ANAME_SZ + INST_SZ); + strncpy(keystring, name, ANAME_SZ); + strncpy(&keystring[ANAME_SZ], instance, INST_SZ); + key->dptr = keystring; + key->dsize = ANAME_SZ + INST_SZ; +} + +static void +decode_princ_key(key, name, instance) + datum *key; + char *name, *instance; +{ + strncpy(name, key->dptr, ANAME_SZ); + strncpy(instance, key->dptr + ANAME_SZ, INST_SZ); + name[ANAME_SZ - 1] = '\0'; + instance[INST_SZ - 1] = '\0'; +} + +static void +encode_princ_contents(contents, principal) + datum *contents; + Principal *principal; +{ + contents->dsize = sizeof(*principal); + contents->dptr = (char *) principal; +} + +static void +decode_princ_contents(contents, principal) + datum *contents; + Principal *principal; +{ + bcopy(contents->dptr, (char *) principal, sizeof(*principal)); +} + +void +kerb_db_get_stat(s) + DB_stat *s; +{ + gettimeofday(×tamp, NULL); + + + s->cpu = 0; + s->elapsed = 0; + s->dio = 0; + s->pfault = 0; + s->t_stamp = timestamp.tv_sec; + s->n_retrieve = 0; + s->n_replace = 0; + s->n_append = 0; + s->n_get_stat = 0; + s->n_put_stat = 0; + /* update local copy too */ +} + +void +kerb_db_put_stat(s) + DB_stat *s; +{ +} + +void +delta_stat(a, b, c) + DB_stat *a, *b, *c; +{ + /* c = a - b then b = a for the next time */ + + c->cpu = a->cpu - b->cpu; + c->elapsed = a->elapsed - b->elapsed; + c->dio = a->dio - b->dio; + c->pfault = a->pfault - b->pfault; + c->t_stamp = a->t_stamp - b->t_stamp; + c->n_retrieve = a->n_retrieve - b->n_retrieve; + c->n_replace = a->n_replace - b->n_replace; + c->n_append = a->n_append - b->n_append; + c->n_get_stat = a->n_get_stat - b->n_get_stat; + c->n_put_stat = a->n_put_stat - b->n_put_stat; + + bcopy(a, b, sizeof(DB_stat)); +} + +/* + * look up a dba in the data base returns number of dbas found , and + * whether there were more than requested. + */ + +int +kerb_db_get_dba(dba_name, dba_inst, dba, max, more) + char *dba_name; /* could have wild card */ + char *dba_inst; /* could have wild card */ + Dba *dba; + unsigned int max; /* max number of name structs to return */ + int *more; /* where there more than 'max' tuples? */ + +{ + *more = 0; + return (0); +} + +int +kerb_db_iterate (func, arg) + int (*func)(); + char *arg; /* void *, really */ +{ + datum key, contents; + Principal *principal; + int code; + DBM *db; + + kerb_db_init(); /* initialize and open the database */ + if ((code = kerb_dbl_lock(KERB_DBL_SHARED)) != 0) + return code; + + db = dbm_open(current_db_name, O_RDONLY, 0600); + + for (key = dbm_firstkey (db); key.dptr != NULL; key = dbm_next(db, key)) { + contents = dbm_fetch (db, key); + /* XXX may not be properly aligned */ + principal = (Principal *) contents.dptr; + if ((code = (*func)(arg, principal)) != 0) + return code; + } + dbm_close(db); + kerb_dbl_unlock(); + return 0; +} + +static int dblfd = -1; +static int mylock = 0; +static int inited = 0; + +static void +kerb_dbl_init() +{ + if (!inited) { + char *filename = gen_dbsuffix (current_db_name, ".ok"); + if ((dblfd = open(filename, 0)) < 0) { + fprintf(stderr, "kerb_dbl_init: couldn't open %s\n", filename); + fflush(stderr); + perror("open"); + exit(1); + } + free(filename); + inited++; + } +} + +static void +kerb_dbl_fini() +{ + close(dblfd); + dblfd = -1; + inited = 0; + mylock = 0; +} + +static int +kerb_dbl_lock(mode) + int mode; +{ + int flock_mode; + + if (!inited) + kerb_dbl_init(); + if (mylock) { /* Detect lock call when lock already + * locked */ + fprintf(stderr, "Kerberos locking error (mylock)\n"); + fflush(stderr); + exit(1); + } + switch (mode) { + case KERB_DBL_EXCLUSIVE: + flock_mode = LOCK_EX; + break; + case KERB_DBL_SHARED: + flock_mode = LOCK_SH; + break; + default: + fprintf(stderr, "invalid lock mode %d\n", mode); + abort(); + } + if (non_blocking) + flock_mode |= LOCK_NB; + + if (flock(dblfd, flock_mode) < 0) + return errno; + mylock++; + return 0; +} + +static void +kerb_dbl_unlock() +{ + if (!mylock) { /* lock already unlocked */ + fprintf(stderr, "Kerberos database lock not locked when unlocking.\n"); + fflush(stderr); + exit(1); + } + if (flock(dblfd, LOCK_UN) < 0) { + fprintf(stderr, "Kerberos database lock error. (unlocking)\n"); + fflush(stderr); + perror("flock"); + exit(1); + } + mylock = 0; +} + +int +kerb_db_set_lockmode(mode) + int mode; +{ + int old = non_blocking; + non_blocking = mode; + return old; +} diff --git a/eBones/lib/libkdb/krb_kdb_utils.c b/eBones/lib/libkdb/krb_kdb_utils.c new file mode 100644 index 0000000000000..0256348e2b77b --- /dev/null +++ b/eBones/lib/libkdb/krb_kdb_utils.c @@ -0,0 +1,148 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * Utility routines for Kerberos programs which directly access + * the database. This code was duplicated in too many places + * before I gathered it here. + * + * Jon Rochlis, MIT Telecom, March 1988 + * + * from: krb_kdb_utils.c,v 4.1 89/07/26 11:01:12 jtkohl Exp $ + * $Id: krb_kdb_utils.c,v 1.3 1995/07/18 16:37:15 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: krb_kdb_utils.c,v 1.3 1995/07/18 16:37:15 mark Exp $"; +#endif lint +#endif + +#include <des.h> +#include <krb.h> +#include <krb_db.h> +#include <kdc.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <sys/file.h> + +long +kdb_get_master_key(prompt, master_key, master_key_sched) + int prompt; + C_Block master_key; + Key_schedule master_key_sched; +{ + int kfile; + + if (prompt) { +#ifdef NOENCRYPTION + placebo_read_password(master_key, + "\nEnter Kerberos master key: ", 0); +#else + des_read_password((des_cblock *)master_key, + "\nEnter Kerberos master key: ", 0); +#endif + printf ("\n"); + } + else { + kfile = open(MKEYFILE, O_RDONLY, 0600); + if (kfile < 0) { + /* oh, for com_err_ */ + return (-1); + } + if (read(kfile, (char *) master_key, 8) != 8) { + return (-1); + } + close(kfile); + } + +#ifndef NOENCRYPTION + key_sched((des_cblock *)master_key,master_key_sched); +#endif + return (0); +} + +/* The caller is reasponsible for cleaning up the master key and sched, + even if we can't verify the master key */ + +/* Returns master key version if successful, otherwise -1 */ + +long +kdb_verify_master_key (master_key, master_key_sched, out) + C_Block master_key; + Key_schedule master_key_sched; + FILE *out; /* setting this to non-null be do output */ +{ + C_Block key_from_db; + Principal principal_data[1]; + int n, more = 0; + long master_key_version; + + /* lookup the master key version */ + n = kerb_get_principal(KERB_M_NAME, KERB_M_INST, principal_data, + 1 /* only one please */, &more); + if ((n != 1) || more) { + if (out != (FILE *) NULL) + fprintf(out, + "verify_master_key: %s, %d found.\n", + "Kerberos error on master key version lookup", + n); + return (-1); + } + + master_key_version = (long) principal_data[0].key_version; + + /* set up the master key */ + if (out != (FILE *) NULL) /* should we punt this? */ + fprintf(out, "Current Kerberos master key version is %d.\n", + principal_data[0].kdc_key_ver); + + /* + * now use the master key to decrypt the key in the db, had better + * be the same! + */ + bcopy(&principal_data[0].key_low, key_from_db, 4); + bcopy(&principal_data[0].key_high, ((long *) key_from_db) + 1, 4); + kdb_encrypt_key (key_from_db, key_from_db, + master_key, master_key_sched, DECRYPT); + + /* the decrypted database key had better equal the master key */ + n = bcmp((char *) master_key, (char *) key_from_db, + sizeof(master_key)); + /* this used to zero the master key here! */ + bzero(key_from_db, sizeof(key_from_db)); + bzero(principal_data, sizeof (principal_data)); + + if (n && (out != (FILE *) NULL)) { + fprintf(out, "\n\07\07verify_master_key: Invalid master key; "); + fprintf(out, "does not match database.\n"); + return (-1); + } + if (out != (FILE *) NULL) { + fprintf(out, "\nMaster key entered. BEWARE!\07\07\n"); + fflush(out); + } + + return (master_key_version); +} + +/* The old algorithm used the key schedule as the initial vector which + was byte order depedent ... */ + +void +kdb_encrypt_key (in, out, master_key, master_key_sched, e_d_flag) + C_Block in, out, master_key; + Key_schedule master_key_sched; + int e_d_flag; +{ + +#ifdef NOENCRYPTION + bcopy(in, out, sizeof(C_Block)); +#else + pcbc_encrypt((des_cblock*)in,(des_cblock*)out,(long)sizeof(C_Block), + master_key_sched,(des_cblock*)master_key,e_d_flag); +#endif +} diff --git a/eBones/lib/libkdb/krb_lib.c b/eBones/lib/libkdb/krb_lib.c new file mode 100644 index 0000000000000..2cf4fb8723d6e --- /dev/null +++ b/eBones/lib/libkdb/krb_lib.c @@ -0,0 +1,242 @@ +/* + * $Source: /usr/cvs/src/eBones/kdb/krb_lib.c,v $ + * $Author: mark $ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * <mit-copyright.h>. + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: krb_lib.c,v 1.3 1995/07/18 16:37:17 mark Exp $"; +#endif lint +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/uio.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <strings.h> +#include <des.h> +#include <krb.h> +#include <krb_db.h> + +#ifdef DEBUG +extern int debug; +extern char *progname; +long kerb_debug; +#endif + +static init = 0; + +/* + * initialization routine for data base + */ + +int +kerb_init() +{ +#ifdef DEBUG + if (!init) { + char *dbg = getenv("KERB_DBG"); + if (dbg) + sscanf(dbg, "%ld", &kerb_debug); + init = 1; + } +#endif + kerb_db_init(); + +#ifdef CACHE + kerb_cache_init(); +#endif + + /* successful init, return 0, else errcode */ + return (0); +} + +/* + * finalization routine for database -- NOTE: MUST be called by any + * program using kerb_init. ALSO will have to be modified to finalize + * caches, if they're ever really implemented. + */ + +void +kerb_fini() +{ + kerb_db_fini(); +} + +/* + * look up a principal in the cache or data base returns number of + * principals found + */ + +int +kerb_get_principal(name, inst, principal, max, more) + char *name; /* could have wild card */ + char *inst; /* could have wild card */ + Principal *principal; + unsigned int max; /* max number of name structs to return */ + int *more; /* more tuples than room for */ + +{ + int found = 0; +#ifdef CACHE + static int wild = 0; +#endif + if (!init) + kerb_init(); + +#ifdef DEBUG + if (kerb_debug & 1) + fprintf(stderr, "\n%s: kerb_get_principal for %s %s max = %d\n", + progname, name, inst, max); +#endif + + /* + * if this is a request including a wild card, have to go to db + * since the cache may not be exhaustive. + */ + + /* clear the principal area */ + bzero((char *) principal, max * sizeof(Principal)); + +#ifdef CACHE + /* + * so check to see if the name contains a wildcard "*" or "?", not + * preceeded by a backslash. + */ + wild = 0; + if (index(name, '*') || index(name, '?') || + index(inst, '*') || index(inst, '?')) + wild = 1; + + if (!wild) { + /* try the cache first */ + found = kerb_cache_get_principal(name, inst, principal, max, more); + if (found) + return (found); + } +#endif + /* If we didn't try cache, or it wasn't there, try db */ + found = kerb_db_get_principal(name, inst, principal, max, more); + /* try to insert principal(s) into cache if it was found */ +#ifdef CACHE + if (found) { + kerb_cache_put_principal(principal, found); + } +#endif + return (found); +} + +/* principals */ +int +kerb_put_principal(principal, n) + Principal *principal; + unsigned int n; /* number of principal structs to write */ +{ + long time(); + struct tm *tp, *localtime(); + + /* set mod date */ + principal->mod_date = time((long *)0); + /* and mod date string */ + + tp = localtime(&principal->mod_date); + (void) sprintf(principal->mod_date_txt, "%4d-%2d-%2d", + tp->tm_year > 1900 ? tp->tm_year : tp->tm_year + 1900, + tp->tm_mon + 1, tp->tm_mday); /* January is 0, not 1 */ +#ifdef DEBUG + if (kerb_debug & 1) { + int i; + fprintf(stderr, "\nkerb_put_principal..."); + for (i = 0; i < n; i++) { + krb_print_principal(&principal[i]); + } + } +#endif + /* write database */ + if (kerb_db_put_principal(principal, n) < 0) { +#ifdef DEBUG + if (kerb_debug & 1) + fprintf(stderr, "\n%s: kerb_db_put_principal err", progname); + /* watch out for cache */ +#endif + return -1; + } +#ifdef CACHE + /* write cache */ + if (!kerb_cache_put_principal(principal, n)) { +#ifdef DEBUG + if (kerb_debug & 1) + fprintf(stderr, "\n%s: kerb_cache_put_principal err", progname); +#endif + return -1; + } +#endif + return 0; +} + +int +kerb_get_dba(name, inst, dba, max, more) + char *name; /* could have wild card */ + char *inst; /* could have wild card */ + Dba *dba; + unsigned int max; /* max number of name structs to return */ + int *more; /* more tuples than room for */ + +{ + int found = 0; +#ifdef CACHE + static int wild = 0; +#endif + if (!init) + kerb_init(); + +#ifdef DEBUG + if (kerb_debug & 1) + fprintf(stderr, "\n%s: kerb_get_dba for %s %s max = %d\n", + progname, name, inst, max); +#endif + /* + * if this is a request including a wild card, have to go to db + * since the cache may not be exhaustive. + */ + + /* clear the dba area */ + bzero((char *) dba, max * sizeof(Dba)); + +#ifdef CACHE + /* + * so check to see if the name contains a wildcard "*" or "?", not + * preceeded by a backslash. + */ + + wild = 0; + if (index(name, '*') || index(name, '?') || + index(inst, '*') || index(inst, '?')) + wild = 1; + + if (!wild) { + /* try the cache first */ + found = kerb_cache_get_dba(name, inst, dba, max, more); + if (found) + return (found); + } +#endif + /* If we didn't try cache, or it wasn't there, try db */ + found = kerb_db_get_dba(name, inst, dba, max, more); +#ifdef CACHE + /* try to insert dba(s) into cache if it was found */ + if (found) { + kerb_cache_put_dba(dba, found); + } +#endif + return (found); +} diff --git a/eBones/lib/libkdb/print_princ.c b/eBones/lib/libkdb/print_princ.c new file mode 100644 index 0000000000000..64e910660e22c --- /dev/null +++ b/eBones/lib/libkdb/print_princ.c @@ -0,0 +1,51 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: $Header: /usr/cvs/src/eBones/kdb/print_princ.c,v 1.3 1995/07/18 16:37:19 mark Exp $ + * $Id: print_princ.c,v 1.3 1995/07/18 16:37:19 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: print_princ.c,v 1.3 1995/07/18 16:37:19 mark Exp $"; +#endif lint +#endif + +#include <stdio.h> +#include <time.h> +#include <sys/types.h> +#include <sys/time.h> +#include <strings.h> +#include <krb.h> +#include <krb_db.h> + +extern int debug; + +long kerb_debug; +static struct tm *time_p; + +void +krb_print_principal(a_n) + Principal *a_n; +{ + /* run-time database does not contain string versions */ + time_p = localtime(&(a_n->exp_date)); + + fprintf(stderr, + "\n%s %s expires %4d-%2d-%2d %2d:%2d, max_life %d*5 = %d min attr 0x%02x", + a_n->name, a_n->instance, + time_p->tm_year > 1900 ? time_p->tm_year : time_p->tm_year + 1900, + time_p->tm_mon + 1, time_p->tm_mday, + time_p->tm_hour, time_p->tm_min, + a_n->max_life, 5 * a_n->max_life, a_n->attributes); + + fprintf(stderr, + "\n\tkey_ver %d k_low 0x%08lx k_high 0x%08lx akv %d exists %d\n", + a_n->key_version, a_n->key_low, a_n->key_high, + a_n->kdc_key_ver, (int)a_n->old); + + fflush(stderr); +} diff --git a/eBones/lib/libkrb/Makefile b/eBones/lib/libkrb/Makefile new file mode 100644 index 0000000000000..eefe1a55d9b37 --- /dev/null +++ b/eBones/lib/libkrb/Makefile @@ -0,0 +1,53 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.8 1995/09/13 17:23:55 markm Exp $ + +LIB= krb +CFLAGS+=-DKERBEROS -DCRYPT -DDEBUG -DBSD42 +SRCS= krb_err.c 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 + +LDADD+= -lcom_err + +beforeinstall: + -cd ${.OBJDIR}; cmp -s krb_err.h \ + ${DESTDIR}/usr/include/kerberosIV/krb_err.h || \ + install -c -o ${BINOWN} -g ${BINGRP} -m 444 krb_err.h \ + ${DESTDIR}/usr/include/kerberosIV + +MAN3= krb.3 krb_realmofhost.3 krb_sendauth.3 krb_set_tkt_string.3 \ + kuserok.3 tf_util.3 + +MLINKS= krb.3 krb_mk_req.3 krb.3 krb_rd_req.3 krb.3 krb_kntoln.3 \ + krb.3 krb_set_key.3 krb.3 krb_get_cred.3 krb.3 krb_mk_priv.3 \ + krb.3 krb_rd_priv.3 krb.3 krb_mk_safe.3 krb.3 krb_rd_safe.3 \ + krb.3 krb_mk_err.3 krb.3 krb_rd_err.3 krb.3 krb_ck_repl.3 + +MLINKS+=krb_realmofhost.3 krb_get_phost.3 krb_realmofhost.3 krb_get_krbhst.3 \ + krb_realmofhost.3 krb_get_admhst.3 krb_realmofhost.3 krb_get_lrealm.3 + +MLINKS+=krb_realmofhost.3 realm.3 + +MLINKS+=krb_sendauth.3 krb_recvauth.3 krb_sendauth.3 krb_net_write.3 \ + krb_sendauth.3 krb_net_read.3 + +MLINKS+=krb_sendauth.3 ksend.3 + +MLINKS+=tf_util.3 tf_init.3 tf_util.3 tf_get_pname.3 \ + tf_util.3 tf_get_pinst.3 tf_util.3 tf_get_cred.3 \ + tf_util.3 tf_close.3 + +.include <bsd.lib.mk> + +krb_err.c: ${KRBOBJDIR}/krb_err.h + diff --git a/eBones/lib/libkrb/add_ticket.c b/eBones/lib/libkrb/add_ticket.c new file mode 100644 index 0000000000000..14ef47c46a0bd --- /dev/null +++ b/eBones/lib/libkrb/add_ticket.c @@ -0,0 +1,91 @@ +/* + * 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.3 1995/07/18 16:38:04 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: add_ticket.c,v 1.3 1995/07/18 16:38:04 mark Exp $"; +#endif /* lint */ +#endif + +#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 */ +int +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/lib/libkrb/create_auth_reply.c b/eBones/lib/libkrb/create_auth_reply.c new file mode 100644 index 0000000000000..e304b173628db --- /dev/null +++ b/eBones/lib/libkrb/create_auth_reply.c @@ -0,0 +1,118 @@ +/* + * 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.3 1995/07/18 16:38:06 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: create_auth_reply.c,v 1.3 1995/07/18 16:38:06 mark Exp $"; +#endif /* lint */ +#endif + +#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/lib/libkrb/create_ciph.c b/eBones/lib/libkrb/create_ciph.c new file mode 100644 index 0000000000000..7fb93e337d1c5 --- /dev/null +++ b/eBones/lib/libkrb/create_ciph.c @@ -0,0 +1,112 @@ +/* + * 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.3 1995/07/18 16:38:07 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: create_ciph.c,v 1.3 1995/07/18 16:38:07 mark Exp $"; +#endif /* lint */ +#endif + +#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 + * + */ + +int +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((C_Block *)key,key_s); + pcbc_encrypt((C_Block *)c->dat,(C_Block *)c->dat,(long) c->length,key_s, + (C_Block *)key,ENCRYPT); +#endif /* NOENCRYPTION */ + + return(KSUCCESS); +} diff --git a/eBones/lib/libkrb/create_death_packet.c b/eBones/lib/libkrb/create_death_packet.c new file mode 100644 index 0000000000000..bdc0e347bf15c --- /dev/null +++ b/eBones/lib/libkrb/create_death_packet.c @@ -0,0 +1,65 @@ +/* + * 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.3 1995/07/18 16:38:09 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: create_death_packet.c,v 1.3 1995/07/18 16:38:09 mark Exp $"; +#endif /* lint */ +#endif + +#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/lib/libkrb/create_ticket.c b/eBones/lib/libkrb/create_ticket.c new file mode 100644 index 0000000000000..e1d697419e1bc --- /dev/null +++ b/eBones/lib/libkrb/create_ticket.c @@ -0,0 +1,132 @@ +/* + * 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.3 1995/07/18 16:38:12 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: create_ticket.c,v 1.3 1995/07/18 16:38:12 mark Exp $"; +#endif /* lint */ +#endif + +#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((C_Block *)key,key_s); + pcbc_encrypt((C_Block *)tkt->dat,(C_Block *)tkt->dat,(long)tkt->length, + key_s,(C_Block *)key,ENCRYPT); +#endif + return 0; +} diff --git a/eBones/lib/libkrb/debug_decl.c b/eBones/lib/libkrb/debug_decl.c new file mode 100644 index 0000000000000..f548e2a0bfa97 --- /dev/null +++ b/eBones/lib/libkrb/debug_decl.c @@ -0,0 +1,20 @@ +/* + * 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.3 1995/07/18 16:38:14 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: debug_decl.c,v 1.3 1995/07/18 16:38:14 mark Exp $"; +#endif lint +#endif + +/* Declare global debugging variables. */ + +int krb_ap_req_debug = 0; +int krb_debug = 0; diff --git a/eBones/lib/libkrb/decomp_ticket.c b/eBones/lib/libkrb/decomp_ticket.c new file mode 100644 index 0000000000000..04316ad405770 --- /dev/null +++ b/eBones/lib/libkrb/decomp_ticket.c @@ -0,0 +1,126 @@ +/* + * 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.3 1995/07/18 16:38:15 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: decomp_ticket.c,v 1.3 1995/07/18 16:38:15 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +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,(C_Block *)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/lib/libkrb/des_rw.c b/eBones/lib/libkrb/des_rw.c new file mode 100644 index 0000000000000..5b339ee3238e3 --- /dev/null +++ b/eBones/lib/libkrb/des_rw.c @@ -0,0 +1,262 @@ +/* + * 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.6 1995/07/18 16:38:17 mark 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 <des.h> +#include <krb.h> + +static des_cblock des_key; +static des_key_schedule key_schedule; + +/* + * 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. + */ + +int +des_set_key(inkey, insched) + des_cblock *inkey; + des_key_schedule insched; +{ + bcopy(inkey, des_key, sizeof(des_cblock)); + bcopy(insched, &key_schedule, sizeof(des_key_schedule)); + return 0; +} + +/* + * 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_schedule, 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, (char *)&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_schedule, (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 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_schedule, (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/lib/libkrb/dest_tkt.c b/eBones/lib/libkrb/dest_tkt.c new file mode 100644 index 0000000000000..df04be0d08bd5 --- /dev/null +++ b/eBones/lib/libkrb/dest_tkt.c @@ -0,0 +1,92 @@ +/* + * 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.3 1995/07/18 16:38:19 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: dest_tkt.c,v 1.3 1995/07/18 16:38:19 mark Exp $"; +#endif /* lint */ +#endif + +#include <unistd.h> +#include <stdio.h> +#include <string.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". + */ + +int +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/lib/libkrb/extract_ticket.c b/eBones/lib/libkrb/extract_ticket.c new file mode 100644 index 0000000000000..8ad3097ee9292 --- /dev/null +++ b/eBones/lib/libkrb/extract_ticket.c @@ -0,0 +1,61 @@ +/* + * 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.3 1995/07/18 16:38:21 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: extract_ticket.c,v 1.3 1995/07/18 16:38:21 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +void +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/lib/libkrb/fgetst.c b/eBones/lib/libkrb/fgetst.c new file mode 100644 index 0000000000000..796caca7ff746 --- /dev/null +++ b/eBones/lib/libkrb/fgetst.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: fgetst.c,v 4.0 89/01/23 10:08:31 jtkohl Exp $ + * $Id: fgetst.c,v 1.3 1995/07/18 16:38:23 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: fgetst.c,v 1.3 1995/07/18 16:38:23 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +fgetst(f, s, n) + FILE *f; + register char *s; + int n; +{ + register int 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/lib/libkrb/get_ad_tkt.c b/eBones/lib/libkrb/get_ad_tkt.c new file mode 100644 index 0000000000000..f96644a0a8179 --- /dev/null +++ b/eBones/lib/libkrb/get_ad_tkt.c @@ -0,0 +1,237 @@ +/* + * 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.3 1995/07/18 16:38:25 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: get_ad_tkt.c,v 1.3 1995/07/18 16:38:25 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +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((C_Block *)cr.session,key_s); + pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat,(long)cip->length, + key_s,(C_Block *)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/lib/libkrb/get_admhst.c b/eBones/lib/libkrb/get_admhst.c new file mode 100644 index 0000000000000..a01a40ff3ea5d --- /dev/null +++ b/eBones/lib/libkrb/get_admhst.c @@ -0,0 +1,82 @@ +/* + * 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.3 1995/07/18 16:38:27 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: get_admhst.c,v 1.3 1995/07/18 16:38:27 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +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/lib/libkrb/get_cred.c b/eBones/lib/libkrb/get_cred.c new file mode 100644 index 0000000000000..60233867ebd5e --- /dev/null +++ b/eBones/lib/libkrb/get_cred.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: get_cred.c,v 4.10 89/05/31 17:46:22 jtkohl Exp $ + * $Id: get_cred.c,v 1.3 1995/07/18 16:38:28 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: get_cred.c,v 1.3 1995/07/18 16:38:28 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +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/lib/libkrb/get_in_tkt.c b/eBones/lib/libkrb/get_in_tkt.c new file mode 100644 index 0000000000000..b95f073280487 --- /dev/null +++ b/eBones/lib/libkrb/get_in_tkt.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: get_in_tkt.c,v 4.12 89/07/18 16:32:56 jtkohl Exp $ + * $Id: get_in_tkt.c,v 1.3 1995/07/18 16:38:30 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: get_in_tkt.c,v 1.3 1995/07/18 16:38:30 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +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: /usr/cvs/src/eBones/krb/get_in_tkt.c,v $ + * $Author: mark $ + * + * 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. + */ + +#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/lib/libkrb/get_krbhst.c b/eBones/lib/libkrb/get_krbhst.c new file mode 100644 index 0000000000000..cfc6e1cb70727 --- /dev/null +++ b/eBones/lib/libkrb/get_krbhst.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: get_krbhst.c,v 4.8 89/01/22 20:00:29 rfrench Exp $ + * $Id: get_krbhst.c,v 1.3 1995/07/18 16:38:32 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: get_krbhst.c,v 1.3 1995/07/18 16:38:32 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +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/lib/libkrb/get_krbrlm.c b/eBones/lib/libkrb/get_krbrlm.c new file mode 100644 index 0000000000000..a4803e5a20179 --- /dev/null +++ b/eBones/lib/libkrb/get_krbrlm.c @@ -0,0 +1,62 @@ +/* + * 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.3 1995/07/18 16:38:34 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: get_krbrlm.c,v 1.3 1995/07/18 16:38:34 mark Exp $"; +#endif /* lint */ +#endif + +#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(). + */ + +int +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/lib/libkrb/get_phost.c b/eBones/lib/libkrb/get_phost.c new file mode 100644 index 0000000000000..cd83b2d2a1202 --- /dev/null +++ b/eBones/lib/libkrb/get_phost.c @@ -0,0 +1,55 @@ +/* + * 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.3 1995/07/18 16:38:35 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: get_phost.c,v 1.3 1995/07/18 16:38:35 mark Exp $"; +#endif /* lint */ +#endif + +#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/lib/libkrb/get_pw_tkt.c b/eBones/lib/libkrb/get_pw_tkt.c new file mode 100644 index 0000000000000..48b6126432f74 --- /dev/null +++ b/eBones/lib/libkrb/get_pw_tkt.c @@ -0,0 +1,75 @@ +/* + * 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.3 1995/07/18 16:38:37 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: get_pw_tkt.c,v 1.3 1995/07/18 16:38:37 mark Exp $"; +#endif /* lint */ +#endif + + +#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. + */ + +int +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/lib/libkrb/get_request.c b/eBones/lib/libkrb/get_request.c new file mode 100644 index 0000000000000..c4982bf3283ce --- /dev/null +++ b/eBones/lib/libkrb/get_request.c @@ -0,0 +1,55 @@ +/* + * 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.3 1995/07/18 16:38:39 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: get_request.c,v 1.3 1995/07/18 16:38:39 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +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/lib/libkrb/get_svc_in_tkt.c b/eBones/lib/libkrb/get_svc_in_tkt.c new file mode 100644 index 0000000000000..f5680db91d8b3 --- /dev/null +++ b/eBones/lib/libkrb/get_svc_in_tkt.c @@ -0,0 +1,77 @@ +/* + * 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.3 1995/07/18 16:38:41 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: get_svc_in_tkt.c,v 1.3 1995/07/18 16:38:41 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +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/lib/libkrb/get_tf_fullname.c b/eBones/lib/libkrb/get_tf_fullname.c new file mode 100644 index 0000000000000..8d7639992e890 --- /dev/null +++ b/eBones/lib/libkrb/get_tf_fullname.c @@ -0,0 +1,69 @@ +/* + * 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.3 1995/07/18 16:38:42 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: get_tf_fullname.c,v 1.3 1995/07/18 16:38:42 mark Exp $"; +#endif /* lint */ +#endif + +#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(). + */ + +int +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/lib/libkrb/get_tf_realm.c b/eBones/lib/libkrb/get_tf_realm.c new file mode 100644 index 0000000000000..8d75a9df82951 --- /dev/null +++ b/eBones/lib/libkrb/get_tf_realm.c @@ -0,0 +1,37 @@ +/* + * 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.3 1995/07/18 16:38:44 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: get_tf_realm.c,v 1.3 1995/07/18 16:38:44 mark Exp $"; +#endif /* lint */ +#endif + +#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. + * + */ + +int +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/lib/libkrb/getrealm.c b/eBones/lib/libkrb/getrealm.c new file mode 100644 index 0000000000000..dcd4d28a91990 --- /dev/null +++ b/eBones/lib/libkrb/getrealm.c @@ -0,0 +1,106 @@ +/* + * 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.3 1995/07/18 16:38:46 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: getrealm.c,v 1.3 1995/07/18 16:38:46 mark Exp $"; +#endif lint +#endif + +#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/lib/libkrb/getst.c b/eBones/lib/libkrb/getst.c new file mode 100644 index 0000000000000..e50e4bb51e19b --- /dev/null +++ b/eBones/lib/libkrb/getst.c @@ -0,0 +1,41 @@ +/* + * 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.3 1995/07/18 16:38:47 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: getst.c,v 1.3 1995/07/18 16:38:47 mark Exp $"; +#endif /* lint */ +#endif + +#include <unistd.h> + +/* + * 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. + */ + +int +getst(fd, s, n) + int fd; + register char *s; + int n; +{ + 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/lib/libkrb/in_tkt.c b/eBones/lib/libkrb/in_tkt.c new file mode 100644 index 0000000000000..1f6ee8aa60783 --- /dev/null +++ b/eBones/lib/libkrb/in_tkt.c @@ -0,0 +1,146 @@ +/* + * 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.6 1995/07/18 16:38:49 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: in_tkt.c,v 1.6 1995/07/18 16:38:49 mark Exp $"; +#endif /* lint */ +#endif + +#include <unistd.h> +#include <string.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. + */ + +int +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 %ld and %ld\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 %ld and %ld\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/lib/libkrb/k_gethostname.c b/eBones/lib/libkrb/k_gethostname.c new file mode 100644 index 0000000000000..cfb4f922a6df7 --- /dev/null +++ b/eBones/lib/libkrb/k_gethostname.c @@ -0,0 +1,71 @@ +/* + * 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.3 1995/07/18 16:38:51 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: k_gethostname.c,v 1.3 1995/07/18 16:38:51 mark Exp $"; +#endif /* lint */ +#endif + +#include <unistd.h> + +#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. + */ + +int +k_gethostname(name, namelen) + char *name; + int namelen; +{ +#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/lib/libkrb/klog.c b/eBones/lib/libkrb/klog.c new file mode 100644 index 0000000000000..7fdc774af3d5e --- /dev/null +++ b/eBones/lib/libkrb/klog.c @@ -0,0 +1,110 @@ +/* + * 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.3 1995/07/18 16:38:52 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: klog.c,v 1.3 1995/07/18 16:38:52 mark Exp $"; +#endif /* lint */ +#endif + +#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; + long now; + 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". + */ + +void +kset_logfile(filename) + char *filename; +{ + log_name = filename; + is_open = 0; +} diff --git a/eBones/lib/libkrb/kname_parse.c b/eBones/lib/libkrb/kname_parse.c new file mode 100644 index 0000000000000..da7ec9393c6b8 --- /dev/null +++ b/eBones/lib/libkrb/kname_parse.c @@ -0,0 +1,239 @@ +/* + * 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.3 1995/07/18 16:38:54 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: kname_parse.c,v 1.3 1995/07/18 16:38:54 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +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. + */ + +int +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. + */ + +int +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. + */ + +int +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/lib/libkrb/kntoln.c b/eBones/lib/libkrb/kntoln.c new file mode 100644 index 0000000000000..388704c09ff39 --- /dev/null +++ b/eBones/lib/libkrb/kntoln.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: kntoln.c,v 4.7 89/01/23 09:25:15 jtkohl Exp $ + * $Id: kntoln.c,v 1.3 1995/07/18 16:38:56 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: kntoln.c,v 1.3 1995/07/18 16:38:56 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +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/lib/libkrb/kparse.c b/eBones/lib/libkrb/kparse.c new file mode 100644 index 0000000000000..5b25ac7264362 --- /dev/null +++ b/eBones/lib/libkrb/kparse.c @@ -0,0 +1,776 @@ +/* + * 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.3 1995/07/18 16:38:58 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: kparse.c,v 1.3 1995/07/18 16:38:58 mark Exp $"; +#endif lint +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <ctype.h> +#include <kparse.h> + +#ifndef FALSE +#define FALSE 0 +#define TRUE 1 +#endif + +#define MAXKEY 80 +#define MAXVALUE 80 + +int fUngetChar(int ch, FILE *fp); +int fGetChar(FILE *fp); +int fGetLiteral(FILE *fp); + +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*/ + return(0); /*just to shut up -Wall MRVM*/ +} + +/* + * 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). + */ +int +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. + */ +int +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. + */ +int +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/lib/libkrb/krb.3 b/eBones/lib/libkrb/krb.3 new file mode 100644 index 0000000000000..10e20e9480772 --- /dev/null +++ b/eBones/lib/libkrb/krb.3 @@ -0,0 +1,462 @@ +.\" $Source: /usr/cvs/src/eBones/krb/krb.3,v $ +.\" $Author: mark $ +.\" $Header: /usr/cvs/src/eBones/krb/krb.3,v 1.2 1995/07/18 16:40:57 mark Exp $ +.\" Copyright 1989 by the Massachusetts Institute of Technology. +.\" +.\" For copying and distribution information, +.\" please see the file <mit-copyright.h>. +.\" +.TH KERBEROS 3 "Kerberos Version 4.0" "MIT Project Athena" +.SH NAME +krb_mk_req, krb_rd_req, krb_kntoln, krb_set_key, krb_get_cred, +krb_mk_priv, krb_rd_priv, krb_mk_safe, krb_rd_safe, krb_mk_err, +krb_rd_err, krb_ck_repl \- Kerberos authentication library +.SH SYNOPSIS +.nf +.nj +.ft B +#include <des.h> +#include <kerberosIV/krb.h> +.PP +.ft B +extern char *krb_err_txt[]; +.PP +.ft B +int krb_mk_req(authent,service,instance,realm,checksum) +KTEXT authent; +char *service; +char *instance; +char *realm; +u_long checksum; +.PP +.ft B +int krb_rd_req(authent,service,instance,from_addr,ad,fn) +KTEXT authent; +char *service; +char *instance; +u_long from_addr; +AUTH_DAT *ad; +char *fn; +.PP +.ft B +int krb_kntoln(ad,lname) +AUTH_DAT *ad; +char *lname; +.PP +.ft B +int krb_set_key(key,cvt) +char *key; +int cvt; +.PP +.ft B +int krb_get_cred(service,instance,realm,c) +char *service; +char *instance; +char *realm; +CREDENTIALS *c; +.PP +.ft B +long krb_mk_priv(in,out,in_length,schedule,key,sender,receiver) +u_char *in; +u_char *out; +u_long in_length; +des_cblock key; +des_key_schedule schedule; +struct sockaddr_in *sender; +struct sockaddr_in *receiver; +.PP +.ft B +long krb_rd_priv(in,in_length,schedule,key,sender,receiver,msg_data) +u_char *in; +u_long in_length; +Key_schedule schedule; +des_cblock key; +struct sockaddr_in *sender; +struct sockaddr_in *receiver; +MSG_DAT *msg_data; +.PP +.ft B +long krb_mk_safe(in,out,in_length,key,sender,receiver) +u_char *in; +u_char *out; +u_long in_length; +des_cblock key; +struct sockaddr_in *sender; +struct sockaddr_in *receiver; +.PP +.ft B +long krb_rd_safe(in,length,key,sender,receiver,msg_data) +u_char *in; +u_long length; +des_cblock key; +struct sockaddr_in *sender; +struct sockaddr_in *receiver; +MSG_DAT *msg_data; +.PP +.ft B +long krb_mk_err(out,code,string) +u_char *out; +long code; +char *string; +.PP +.ft B +long krb_rd_err(in,length,code,msg_data) +u_char *in; +u_long length; +long code; +MSG_DAT *msg_data; +.fi +.ft R +.SH DESCRIPTION +This library supports network authentication and various related +operations. The library contains many routines beyond those described +in this man page, but they are not intended to be used directly. +Instead, they are called by the routines that are described, the +authentication server and the login program. +.PP +.I krb_err_txt[] +contains text string descriptions of various Kerberos error codes returned +by some of the routines below. +.PP +.I krb_mk_req +takes a pointer to a text structure in which an authenticator is to be +built. It also takes the name, instance, and realm of the service to be +used and an optional checksum. It is up to the application to decide +how to generate the checksum. +.I krb_mk_req +then retrieves a ticket for the desired service and creates an +authenticator. The authenticator is built in +.I authent +and is accessible +to the calling procedure. +.PP +It is up to the application to get the authenticator to the service +where it will be read by +.I krb_rd_req. +Unless an attacker posesses the session key contained in the ticket, it +will be unable to modify the authenticator. Thus, the checksum can be +used to verify the authenticity of the other data that will pass through +a connection. +.PP +.I krb_rd_req +takes an authenticator of type +.B KTEXT, +a service name, an instance, the address of the +host originating the request, and a pointer to a structure of type +.B AUTH_DAT +which is filled in with information obtained from the authenticator. +It also optionally takes the name of the file in which it will find the +secret key(s) for the service. +If the supplied +.I instance +contains "*", then the first service key with the same service name +found in the service key file will be used, and the +.I instance +argument will be filled in with the chosen instance. This means that +the caller must provide space for such an instance name. +.PP +It is used to find out information about the principal when a request +has been made to a service. It is up to the application protocol to get +the authenticator from the client to the service. The authenticator is +then passed to +.I krb_rd_req +to extract the desired information. +.PP +.I krb_rd_req +returns zero (RD_AP_OK) upon successful authentication. If a packet was +forged, modified, or replayed, authentication will fail. If the +authentication fails, a non-zero value is returned indicating the +particular problem encountered. See +.I krb.h +for the list of error codes. +.PP +If the last argument is the null string (""), krb_rd_req will use the +file /etc/kerberosIV/srvtab to find its keys. If the last argument is +NULL, it will assume that the key has been set by +.I krb_set_key +and will not bother looking further. +.PP +.I krb_kntoln +converts a Kerberos name to a local name. It takes a structure +of type AUTH_DAT and uses the name and instance to look in the database +/etc/kerberosIV/aname to find the corresponding local name. The local name is +returned and can be used by an application to change uids, directories, +or other parameters. It is not an integral part of Kerberos, but is +instead provided to support the use of Kerberos in existing utilities. +.PP +.I krb_set_key +takes as an argument a des key. It then creates +a key schedule from it and saves the original key to be used as an +initialization vector. +It is used to set the server's key which +must be used to decrypt tickets. +.PP +If called with a non-zero second argument, +.I krb_set_key +will first convert the input from a string of arbitrary length to a DES +key by encrypting it with a one-way function. +.PP +In most cases it should not be necessary to call +.I krb_set_key. +The necessary keys will usually be obtained and set inside +.I krb_rd_req. krb_set_key +is provided for those applications that do not wish to place the +application keys on disk. +.PP +.I krb_get_cred +searches the caller's ticket file for a ticket for the given service, instance, +and realm; and, if a ticket is found, fills in the given CREDENTIALS structure +with the ticket information. +.PP +If the ticket was found, +.I krb_get_cred +returns GC_OK. +If the ticket file can't be found, can't be read, doesn't belong to +the user (other than root), isn't a regular file, or is in the wrong +mode, the error GC_TKFIL is returned. +.PP +.I krb_mk_priv +creates an encrypted, authenticated +message from any arbitrary application data, pointed to by +.I in +and +.I in_length +bytes long. +The private session key, pointed to by +.I key +and the key schedule, +.I schedule, +are used to encrypt the data and some header information using +.I pcbc_encrypt. +.I sender +and +.I receiver +point to the Internet address of the two parties. +In addition to providing privacy, this protocol message protects +against modifications, insertions or replays. The encapsulated message and +header are placed in the area pointed to by +.I out +and the routine returns the length of the output, or -1 indicating +an error. +.PP +.I krb_rd_priv +decrypts and authenticates a received +.I krb_mk_priv +message. +.I in +points to the beginning of the received message, whose length +is specified in +.I in_length. +The private session key, pointed to by +.I key, +and the key schedule, +.I schedule, +are used to decrypt and verify the received message. +.I msg_data +is a pointer to a +.I MSG_DAT +struct, defined in +.I krb.h. +The routine fills in the +.I app_data +field with a pointer to the decrypted application data, +.I app_length +with the length of the +.I app_data +field, +.I time_sec +and +.I time_5ms +with the timestamps in the message, and +.I swap +with a 1 if the byte order of the receiver is different than that of +the sender. (The application must still determine if it is appropriate +to byte-swap application data; the Kerberos protocol fields are already taken +care of). The +.I hash +field returns a value useful as input to the +.I krb_ck_repl +routine. + +The routine returns zero if ok, or a Kerberos error code. Modified messages +and old messages cause errors, but it is up to the caller to +check the time sequence of messages, and to check against recently replayed +messages using +.I krb_ck_repl +if so desired. +.PP +.I krb_mk_safe +creates an authenticated, but unencrypted message from any arbitrary +application data, +pointed to by +.I in +and +.I in_length +bytes long. +The private session key, pointed to by +.I key, +is used to seed the +.I quad_cksum() +checksum algorithm used as part of the authentication. +.I sender +and +.I receiver +point to the Internet address of the two parties. +This message does not provide privacy, but does protect (via detection) +against modifications, insertions or replays. The encapsulated message and +header are placed in the area pointed to by +.I out +and the routine returns the length of the output, or -1 indicating +an error. +The authentication provided by this routine is not as strong as that +provided by +.I krb_mk_priv +or by computing the checksum using +.I cbc_cksum +instead, both of which authenticate via DES. +.PP + +.I krb_rd_safe +authenticates a received +.I krb_mk_safe +message. +.I in +points to the beginning of the received message, whose length +is specified in +.I in_length. +The private session key, pointed to by +.I key, +is used to seed the quad_cksum() routine as part of the authentication. +.I msg_data +is a pointer to a +.I MSG_DAT +struct, defined in +.I krb.h . +The routine fills in these +.I MSG_DAT +fields: +the +.I app_data +field with a pointer to the application data, +.I app_length +with the length of the +.I app_data +field, +.I time_sec +and +.I time_5ms +with the timestamps in the message, and +.I swap +with a 1 if the byte order of the receiver is different than that of +the sender. +(The application must still determine if it is appropriate +to byte-swap application data; the Kerberos protocol fields are already taken +care of). The +.I hash +field returns a value useful as input to the +.I krb_ck_repl +routine. + +The routine returns zero if ok, or a Kerberos error code. Modified messages +and old messages cause errors, but it is up to the caller to +check the time sequence of messages, and to check against recently replayed +messages using +.I krb_ck_repl +if so desired. +.PP +.I krb_mk_err +constructs an application level error message that may be used along +with +.I krb_mk_priv +or +.I krb_mk_safe. +.I out +is a pointer to the output buffer, +.I code +is an application specific error code, and +.I string +is an application specific error string. + +.PP +.I krb_rd_err +unpacks a received +.I krb_mk_err +message. +.I in +points to the beginning of the received message, whose length +is specified in +.I in_length. +.I code +is a pointer to a value to be filled in with the error +value provided by the application. +.I msg_data +is a pointer to a +.I MSG_DAT +struct, defined in +.I krb.h . +The routine fills in these +.I MSG_DAT +fields: the +.I app_data +field with a pointer to the application error text, +.I app_length +with the length of the +.I app_data +field, and +.I swap +with a 1 if the byte order of the receiver is different than that of +the sender. (The application must still determine if it is appropriate +to byte-swap application data; the Kerberos protocol fields are already taken +care of). + +The routine returns zero if the error message has been successfully received, +or a Kerberos error code. +.PP +The +.I KTEXT +structure is used to pass around text of varying lengths. It consists +of a buffer for the data, and a length. krb_rd_req takes an argument of this +type containing the authenticator, and krb_mk_req returns the +authenticator in a structure of this type. KTEXT itself is really a +pointer to the structure. The actual structure is of type KTEXT_ST. +.PP +The +.I AUTH_DAT +structure is filled in by krb_rd_req. It must be allocated before +calling krb_rd_req, and a pointer to it is passed. The structure is +filled in with data obtained from Kerberos. +.I MSG_DAT +structure is filled in by either krb_rd_priv, krb_rd_safe, or +krb_rd_err. It must be allocated before the call and a pointer to it +is passed. The structure is +filled in with data obtained from Kerberos. +.PP +.SH FILES +/usr/include/kerberosIV/krb.h +.br +/usr/lib/libkrb.a +.br +/usr/include/des.h +.br +/usr/lib/libdes.a +.br +/etc/kerberosIV/aname +.br +/etc/kerberosIV/srvtab +.br +/tmp/tkt[uid] +.SH "SEE ALSO" +kerberos(1), des_crypt(3) +.SH DIAGNOSTICS +.SH BUGS +The caller of +.I krb_rd_req, krb_rd_priv, and krb_rd_safe +must check time order and for replay attempts. +.I krb_ck_repl +is not implemented yet. +.SH AUTHORS +Clifford Neuman, MIT Project Athena +.br +Steve Miller, MIT Project Athena/Digital Equipment Corporation +.SH RESTRICTIONS +COPYRIGHT 1985,1986,1989 Massachusetts Institute of Technology diff --git a/eBones/lib/libkrb/krb_err.et b/eBones/lib/libkrb/krb_err.et new file mode 100644 index 0000000000000..7d2baef473454 --- /dev/null +++ b/eBones/lib/libkrb/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.3 1995/07/18 16:39:00 mark 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/lib/libkrb/krb_err_txt.c b/eBones/lib/libkrb/krb_err_txt.c new file mode 100644 index 0000000000000..2c8c0cacbe201 --- /dev/null +++ b/eBones/lib/libkrb/krb_err_txt.c @@ -0,0 +1,280 @@ +/* + * 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.3 1995/07/18 16:39:02 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: krb_err_txt.c,v 1.3 1995/07/18 16:39:02 mark Exp $"; +#endif lint +#endif + +/* + * 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/lib/libkrb/krb_get_in_tkt.c b/eBones/lib/libkrb/krb_get_in_tkt.c new file mode 100644 index 0000000000000..b6ff308a77c01 --- /dev/null +++ b/eBones/lib/libkrb/krb_get_in_tkt.c @@ -0,0 +1,301 @@ +/* + * 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.3 1995/07/18 16:39:04 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: krb_get_in_tkt.c,v 1.3 1995/07/18 16:39:04 mark Exp $"; +#endif /* lint */ +#endif + +#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,(C_Block *)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 + */ + +int +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/lib/libkrb/krb_realmofhost.3 b/eBones/lib/libkrb/krb_realmofhost.3 new file mode 100644 index 0000000000000..c3b14cc457882 --- /dev/null +++ b/eBones/lib/libkrb/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.3 1995/07/18 16:41:02 mark 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 <kerberosIV/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/kerberosIV/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/kerberosIV/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/kerberosIV/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/kerberosIV/krb.realms +translation file for host-to-realm mapping. +.TP +/etc/kerberosIV/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/lib/libkrb/krb_sendauth.3 b/eBones/lib/libkrb/krb_sendauth.3 new file mode 100644 index 0000000000000..5608255009d9d --- /dev/null +++ b/eBones/lib/libkrb/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.3 1995/07/18 16:41:03 mark 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 <kerberosIV/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/kerberosIV/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 <Copyright.h>. diff --git a/eBones/lib/libkrb/krbglue.c b/eBones/lib/libkrb/krbglue.c new file mode 100644 index 0000000000000..f82cf70399f3c --- /dev/null +++ b/eBones/lib/libkrb/krbglue.c @@ -0,0 +1,258 @@ +/* + * 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.3 1995/07/18 16:39:05 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +$Id: krbglue.c,v 1.3 1995/07/18 16:39:05 mark Exp $"; +#endif lint +#endif + +#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 +#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 +#endif +*/ + + +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/lib/libkrb/kuserok.c b/eBones/lib/libkrb/kuserok.c new file mode 100644 index 0000000000000..8e5d18ab1e317 --- /dev/null +++ b/eBones/lib/libkrb/kuserok.c @@ -0,0 +1,199 @@ +/* + * 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.3 1995/07/18 16:39:07 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: kuserok.c,v 1.3 1995/07/18 16:39:07 mark Exp $"; +#endif lint +#endif + +#include <krb.h> +#include <stdio.h> +#include <unistd.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 + +int +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/lib/libkrb/log.c b/eBones/lib/libkrb/log.c new file mode 100644 index 0000000000000..e33477f5cf54f --- /dev/null +++ b/eBones/lib/libkrb/log.c @@ -0,0 +1,125 @@ +/* + * 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.3 1995/07/18 16:39:09 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: log.c,v 1.3 1995/07/18 16:39:09 mark Exp $"; +#endif /* lint */ +#endif + +#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". + */ + +void +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. + */ + +int +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/lib/libkrb/mk_err.c b/eBones/lib/libkrb/mk_err.c new file mode 100644 index 0000000000000..86002403bccf9 --- /dev/null +++ b/eBones/lib/libkrb/mk_err.c @@ -0,0 +1,65 @@ +/* + * 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.3 1995/07/18 16:39:11 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: mk_err.c,v 1.3 1995/07/18 16:39:11 mark Exp $"; +#endif /* lint */ +#endif + +#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/lib/libkrb/mk_priv.c b/eBones/lib/libkrb/mk_priv.c new file mode 100644 index 0000000000000..d45d734c6f170 --- /dev/null +++ b/eBones/lib/libkrb/mk_priv.c @@ -0,0 +1,207 @@ +/* + * 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.3 1995/07/18 16:39:13 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: mk_priv.c,v 1.3 1995/07/18 16:39:13 mark Exp $"; +#endif /* lint */ +#endif + +/* system include files */ +#include <stdio.h> +#include <string.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,(C_Block *)key, + ENCRYPT); +#endif /* NOENCRYPTION */ + + return (q - out + c_length); /* resulting size */ +} diff --git a/eBones/lib/libkrb/mk_req.c b/eBones/lib/libkrb/mk_req.c new file mode 100644 index 0000000000000..a27c1c0d556b6 --- /dev/null +++ b/eBones/lib/libkrb/mk_req.c @@ -0,0 +1,198 @@ +/* + * 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.3 1995/07/18 16:39:15 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: mk_req.c,v 1.3 1995/07/18 16:39:15 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +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: %ld\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((C_Block *)cr.session,key_s); + pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat, + (long)req_id->length,key_s,(C_Block *)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/lib/libkrb/mk_safe.c b/eBones/lib/libkrb/mk_safe.c new file mode 100644 index 0000000000000..e5490bcd2e9be --- /dev/null +++ b/eBones/lib/libkrb/mk_safe.c @@ -0,0 +1,171 @@ +/* + * 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.3 1995/07/18 16:39:17 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: mk_safe.c,v 1.3 1995/07/18 16:39:17 mark Exp $"; +#endif /* lint */ +#endif + +/* system include files */ +#include <stdio.h> +#include <string.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((C_Block *)q,big_cksum,p-q,2,key); +#endif + if (krb_debug) + printf("\ncksum = %lu",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/lib/libkrb/month_sname.c b/eBones/lib/libkrb/month_sname.c new file mode 100644 index 0000000000000..f4ef33994bc9a --- /dev/null +++ b/eBones/lib/libkrb/month_sname.c @@ -0,0 +1,33 @@ +/* + * 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.3 1995/07/18 16:39:19 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: month_sname.c,v 1.3 1995/07/18 16:39:19 mark Exp $"; +#endif /* lint */ +#endif + + +/* + * 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/lib/libkrb/netread.c b/eBones/lib/libkrb/netread.c new file mode 100644 index 0000000000000..628004e251853 --- /dev/null +++ b/eBones/lib/libkrb/netread.c @@ -0,0 +1,50 @@ +/* + * 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.3 1995/07/18 16:39:20 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: netread.c,v 1.3 1995/07/18 16:39:20 mark Exp $"; +#endif lint +#endif + +#include <unistd.h> + +/* + * 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/lib/libkrb/netwrite.c b/eBones/lib/libkrb/netwrite.c new file mode 100644 index 0000000000000..f85f7ba5efd77 --- /dev/null +++ b/eBones/lib/libkrb/netwrite.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: netwrite.c,v 4.1 88/11/15 16:48:58 jtkohl Exp $"; + * $Id: netwrite.c,v 1.3 1995/07/18 16:39:22 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: netwrite.c,v 1.3 1995/07/18 16:39:22 mark Exp $"; +#endif lint +#endif + +#include <unistd.h> + +/* + * 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/lib/libkrb/one.c b/eBones/lib/libkrb/one.c new file mode 100644 index 0000000000000..ef02ae1c878a9 --- /dev/null +++ b/eBones/lib/libkrb/one.c @@ -0,0 +1,22 @@ +/* + * 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.3 1995/07/18 16:39:24 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: one.c,v 1.3 1995/07/18 16:39:24 mark Exp $"; +#endif lint +#endif + +/* + * definition of variable set to 1. + * used in krb_conf.h to determine host byte order. + */ + +int krbONE = 1; diff --git a/eBones/lib/libkrb/pkt_cipher.c b/eBones/lib/libkrb/pkt_cipher.c new file mode 100644 index 0000000000000..9c32b72b0fe96 --- /dev/null +++ b/eBones/lib/libkrb/pkt_cipher.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: pkt_cipher.c,v 4.8 89/01/13 17:46:14 steiner Exp $ + * $Id: pkt_cipher.c,v 1.3 1995/07/18 16:39:25 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: pkt_cipher.c,v 1.3 1995/07/18 16:39:25 mark Exp $"; +#endif /* lint */ +#endif + +#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/lib/libkrb/pkt_clen.c b/eBones/lib/libkrb/pkt_clen.c new file mode 100644 index 0000000000000..f8dacae34faa2 --- /dev/null +++ b/eBones/lib/libkrb/pkt_clen.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: pkt_clen.c,v 4.7 88/11/15 16:56:36 jtkohl Exp $ + * $Id: pkt_clen.c,v 1.3 1995/07/18 16:39:27 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: pkt_clen.c,v 1.3 1995/07/18 16:39:27 mark Exp $"; +#endif /* lint */ +#endif + +#include <string.h> + +#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. + */ + +int +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/lib/libkrb/rd_err.c b/eBones/lib/libkrb/rd_err.c new file mode 100644 index 0000000000000..e46dc6678f0db --- /dev/null +++ b/eBones/lib/libkrb/rd_err.c @@ -0,0 +1,82 @@ +/* + * 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.3 1995/07/18 16:39:29 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: rd_err.c,v 1.3 1995/07/18 16:39:29 mark Exp $"; +#endif /* lint */ +#endif + +/* system include files */ +#include <string.h> +#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/lib/libkrb/rd_priv.c b/eBones/lib/libkrb/rd_priv.c new file mode 100644 index 0000000000000..0c21a1d463b11 --- /dev/null +++ b/eBones/lib/libkrb/rd_priv.c @@ -0,0 +1,207 @@ +/* + * 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.3 1995/07/18 16:39:31 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[]= +"$Id: rd_priv.c,v 1.3 1995/07/18 16:39:31 mark Exp $"; +#endif /* lint */ +#endif + +/* system include files */ +#include <string.h> +#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 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, + (C_Block *)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 = %ld",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/lib/libkrb/rd_req.c b/eBones/lib/libkrb/rd_req.c new file mode 100644 index 0000000000000..60ee9483d30c7 --- /dev/null +++ b/eBones/lib/libkrb/rd_req.c @@ -0,0 +1,331 @@ +/* + * 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.3 1995/07/18 16:39:33 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: rd_req.c,v 1.3 1995/07/18 16:39:33 mark Exp $"; +#endif /* lint */ +#endif + +#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,(C_Block *)ky); + else + bcopy(key,(char *)ky,8); + return(des_key_sched((C_Block *)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. + */ + +int +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((C_Block *)ad->session,seskey_sched); + pcbc_encrypt((C_Block *)req_id->dat,(C_Block *)req_id->dat, + (long)req_id->length,seskey_sched,(C_Block *)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/lib/libkrb/rd_safe.c b/eBones/lib/libkrb/rd_safe.c new file mode 100644 index 0000000000000..4d3e8d6735aeb --- /dev/null +++ b/eBones/lib/libkrb/rd_safe.c @@ -0,0 +1,183 @@ +/* + * 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.3 1995/07/18 16:39:34 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: rd_safe.c,v 1.3 1995/07/18 16:39:34 mark Exp $"; +#endif /* lint */ +#endif + +/* system include files */ +#include <stdio.h> +#include <string.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((C_Block *)q,calc_cksum,p-q,2,key); +#endif + + if (krb_debug) + printf("\ncalc_cksum = %lu, received cksum = %lu", + (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/lib/libkrb/read_service_key.c b/eBones/lib/libkrb/read_service_key.c new file mode 100644 index 0000000000000..6064292d96cfd --- /dev/null +++ b/eBones/lib/libkrb/read_service_key.c @@ -0,0 +1,124 @@ +/* + * 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.3 1995/07/18 16:39:36 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: read_service_key.c,v 1.3 1995/07/18 16:39:36 mark Exp $"; +#endif /* lint */ +#endif + +#include <krb.h> +#include <stdio.h> +#include <unistd.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 */ +int +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/lib/libkrb/recvauth.c b/eBones/lib/libkrb/recvauth.c new file mode 100644 index 0000000000000..45d68ee750799 --- /dev/null +++ b/eBones/lib/libkrb/recvauth.c @@ -0,0 +1,290 @@ +/* + * 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.3 1995/07/18 16:39:38 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: recvauth.c,v 1.3 1995/07/18 16:39:38 mark Exp $"; +#endif lint +#endif + +#include <krb.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <syslog.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.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((C_Block *)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/lib/libkrb/save_credentials.c b/eBones/lib/libkrb/save_credentials.c new file mode 100644 index 0000000000000..268bb77a1c4da --- /dev/null +++ b/eBones/lib/libkrb/save_credentials.c @@ -0,0 +1,56 @@ +/* + * 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.3 1995/07/18 16:39:40 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: save_credentials.c,v 1.3 1995/07/18 16:39:40 mark Exp $"; +#endif /* lint */ +#endif + +#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. + */ + +int +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/lib/libkrb/send_to_kdc.c b/eBones/lib/libkrb/send_to_kdc.c new file mode 100644 index 0000000000000..eae06d575ac8b --- /dev/null +++ b/eBones/lib/libkrb/send_to_kdc.c @@ -0,0 +1,391 @@ +/* + * 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.7 1995/09/07 21:38:31 markm Exp $ + */ + +#if 0 +#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 */ +#endif + +#include <krb.h> +#include <prot.h> + +#include <unistd.h> +#include <stdlib.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 <arpa/inet.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 + */ + +int +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; + int addr_count; + struct sockaddr_in to; + struct hostent *host, *hostlist; + 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 addresses to check against later + */ + hostlist = (struct hostent *) + realloc((char *)hostlist, + (unsigned) + sizeof(struct hostent)*(n_hosts+1)); + if (!hostlist) { + fprintf(stderr, "Could not grow hostlist\n"); + return /*errno */SKDC_CANT; + } + bcopy((char *)host, (char *)&hostlist[n_hosts-1], + sizeof(struct hostent)); + host = &hostlist[n_hosts-1]; +/* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2 + (or worse) only return one address ... */ +#if (defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) + { + char *cp = malloc((unsigned)host->h_length); + if (!cp) { + retval = /*errno */SKDC_CANT; + goto rtn; + } + bcopy((char *)host->h_addr, cp, host->h_length); + host->h_addr = cp; + } +#else /* !(ULTRIX022 || (SunOS < 40)) */ + /* + * Make a copy of the entire h_addr_list. + */ + { + char *addr; + char **old_addr_list; + addr_count = 0; + old_addr_list = host->h_addr_list; + while(old_addr_list[addr_count++]) + ; + host->h_addr_list = (char **)malloc(addr_count+1 * sizeof(char *)); + if (host->h_addr_list == NULL) { + fprintf(stderr, "Could not allocate host->h_addr_list\n"); + retval = SKDC_CANT; + goto rtn; + } + if (krb_debug) { + printf("h_length = %d\n", host->h_length); + printf("Number of addresses = %d\n", addr_count); + } + for (addr_count = 0; old_addr_list[addr_count]; addr_count++) { + if (krb_debug) + printf ("addr[%d] = %s\n", addr_count, + inet_ntoa(*(struct in_addr *)old_addr_list[addr_count])); + addr = (char *)malloc(host->h_length); + if (addr == NULL) { + fprintf(stderr, "Could not allocate address\n"); + retval = SKDC_CANT; + goto rtn; + } + bcopy(old_addr_list[addr_count], addr, host->h_length); + host->h_addr_list[addr_count] = addr; + } + host->h_addr_list[addr_count] = NULL; + } +#endif /* !(ULTRIX022 || (SunOS < 40)) */ + + 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. Some addresses may be unreachable + * from where we are, so loop through them as well. + */ + for (retry = 0; retry < CLIENT_KRB_RETRY; ++retry) { + for (host = hostlist; host->h_name != (char *)NULL; host++) { +#if (defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) + to.sin_family = host->h_addrtype; + bcopy(host->h_addr_list[addr_count], (char *)&to.sin_addr, + host->h_length); + if (send_recv(pkt, rpkt, f, &to, hostlist)) { + retval = KSUCCESS; + goto rtn; + } +#else /* !(ULTRIX022 || (SunOS < 40)) */ + for (addr_count = 0; host->h_addr_list[addr_count]; addr_count++) { + to.sin_family = host->h_addrtype; + bcopy(host->h_addr_list[addr_count], (char *)&to.sin_addr, + host->h_length); + if (send_recv(pkt, rpkt, f, &to, hostlist)) { + retval = KSUCCESS; + goto rtn; + } + } +#endif /* !(ULTRIX022 || (SunOS < 40)) */ + } + } + retval = SKDC_RETRY; +rtn: + (void) close(f); + if (hostlist) { + if(!no_host) { + 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 int +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; + int addr_count; + + 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); + } +/* At least Sun OS version 3.2 (or worse) and Ultrix version 2.2 + (or worse) only return one address ... */ +#if (defined(ULTRIX022) || (defined(SunOS) && SunOS < 40)) + 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 %s\n", + inet_ntoa(*(struct in_addr *)hp->h_addr)); + } +#else /* !(ULTRIX022 || (SunOS < 40)) */ + for (hp = addrs; hp->h_name != (char *)NULL; hp++) { + for (addr_count = 0; hp->h_addr_list[addr_count]; addr_count++) { + if (!bcmp(hp->h_addr_list[addr_count], + (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 %s\n", + inet_ntoa(*(struct in_addr *)hp->h_addr_list[addr_count])); + } + } +#endif /* !(ULTRIX022 || (SunOS < 40)) */ + if (krb_debug) + fprintf(stderr, "%s: received packet from wrong host! (%ls)\n", + "send_to_kdc(send_rcv)", inet_ntoa(from.sin_addr)); + return 0; +} diff --git a/eBones/lib/libkrb/sendauth.c b/eBones/lib/libkrb/sendauth.c new file mode 100644 index 0000000000000..a1d79e772bc06 --- /dev/null +++ b/eBones/lib/libkrb/sendauth.c @@ -0,0 +1,259 @@ +/* + * 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.3 1995/07/18 16:39:44 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: sendauth.c,v 1.3 1995/07/18 16:39:44 mark Exp $"; +#endif lint +#endif + +#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((C_Block *)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/lib/libkrb/stime.c b/eBones/lib/libkrb/stime.c new file mode 100644 index 0000000000000..2da246319eb73 --- /dev/null +++ b/eBones/lib/libkrb/stime.c @@ -0,0 +1,43 @@ +/* + * 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.3 1995/07/18 16:39:46 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: stime.c,v 1.3 1995/07/18 16:39:46 mark Exp $"; +#endif /* lint */ +#endif + +#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/lib/libkrb/tf_shm.c b/eBones/lib/libkrb/tf_shm.c new file mode 100644 index 0000000000000..31894cb83983a --- /dev/null +++ b/eBones/lib/libkrb/tf_shm.c @@ -0,0 +1,176 @@ +/* + * 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.3 1995/07/18 16:39:48 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: tf_shm.c,v 1.3 1995/07/18 16:39:48 mark Exp $"; +#endif lint +#endif + +#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/lib/libkrb/tf_util.c b/eBones/lib/libkrb/tf_util.c new file mode 100644 index 0000000000000..e939c38e9da86 --- /dev/null +++ b/eBones/lib/libkrb/tf_util.c @@ -0,0 +1,581 @@ +/* + * 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.3 1995/07/18 16:39:50 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: tf_util.c,v 1.3 1995/07/18 16:39:50 mark Exp $"; +#endif /* lint */ +#endif + +#include <unistd.h> +#include <string.h> +#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 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}; + +#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 int tf_read(char *s, int n); +static int tf_gets(char *s, int n); + +/* + * 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 + */ + +int +tf_init(tf_name, rw) + char *tf_name; + int rw; +{ + 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. + */ + +int +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. + */ + +int +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 + */ + +int +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. + */ + +void +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 int +tf_gets(s, n) + register char *s; + int n; +{ + 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 int +tf_read(s, n) + register char *s; + register int 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; +} + +/* + * 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. + */ + +int +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/lib/libkrb/tkt_string.c b/eBones/lib/libkrb/tkt_string.c new file mode 100644 index 0000000000000..d944833a33aa6 --- /dev/null +++ b/eBones/lib/libkrb/tkt_string.c @@ -0,0 +1,80 @@ +/* + * 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.3 1995/07/18 16:39:52 mark Exp $ + */ + +#if 0 +#ifndef lint +static char *rcsid = +"$Id: tkt_string.c,v 1.3 1995/07/18 16:39:52 mark Exp $"; +#endif /* lint */ +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <krb.h> +#include <string.h> +#include <sys/param.h> + +/* + * 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%ld",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/lib/libkrb/util.c b/eBones/lib/libkrb/util.c new file mode 100644 index 0000000000000..68c0dbc1eb4b8 --- /dev/null +++ b/eBones/lib/libkrb/util.c @@ -0,0 +1,75 @@ +/* + * 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.3 1995/07/18 16:39:54 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: util.c,v 1.3 1995/07/18 16:39:54 mark Exp $"; +#endif lint +#endif + +#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 + */ + +void +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%lX\n\ttkt_tm 0x%lX 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((C_Block *)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 diff --git a/eBones/lib/librkinit/Makefile b/eBones/lib/librkinit/Makefile new file mode 100644 index 0000000000000..7d4b4ca246b27 --- /dev/null +++ b/eBones/lib/librkinit/Makefile @@ -0,0 +1,19 @@ +# @(#)Makefile 8.1 (Berkeley) 6/4/93 + +LIB= rkinit +CFLAGS+=-DKERBEROS -DCRYPT -DDEBUG -I${RKINITOBJDIR} +SRCS= rkinit_err.c rk_lib.c rk_rpc.c rk_util.c rk_krb.c rkinit_err.c + +LDADD+= -lcom_err + +beforeinstall: + -cd ${.OBJDIR}; cmp -s rkinit_err.h \ + ${DESTDIR}/usr/include/kerberosIV/rkinit_err.h || \ + install -c -o ${BINOWN} -g ${BINGRP} -m 444 rkinit_err.h \ + ${DESTDIR}/usr/include/kerberosIV + +MAN3= rkinit.3 + +.include <bsd.lib.mk> + +rkinit_err.c: ${RKINITOBJDIR}/rkinit_err.h diff --git a/eBones/lib/librkinit/rk_krb.c b/eBones/lib/librkinit/rk_krb.c new file mode 100644 index 0000000000000..ad8a6537b2d45 --- /dev/null +++ b/eBones/lib/librkinit/rk_krb.c @@ -0,0 +1,316 @@ +/* + * $Id: rk_krb.c,v 1.1 1993/12/10 19:36:09 dglo Exp gibbs $ + * $Source: /usr/src/eBones/librkinit/RCS/rk_krb.c,v $ + * $Author: dglo $ + * + * This file contains the kerberos parts of the rkinit library. + * See the comment at the top of rk_lib.c for a description of the naming + * conventions used within the rkinit library. + */ + +#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS) +static char *rcsid = "$Id: rk_krb.c,v 1.1 1993/12/10 19:36:09 dglo Exp gibbs $"; +#endif /* lint || SABER || LOCORE || RCS_HDRS */ + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <krb.h> +#include <des.h> + +#include <signal.h> +#include <setjmp.h> + +#ifdef POSIX +#include <termios.h> +#else +#include <sgtty.h> +#endif + +#include <rkinit.h> +#include <rkinit_err.h> +#include <rkinit_private.h> + +static jmp_buf env; +static void sig_restore(); +static void push_signals(); +static void pop_signals(); + +/* Information to be passed around within client get_in_tkt */ +typedef struct { + KTEXT scip; /* Server KDC packet */ + char *username; + char *host; +} rkinit_intkt_info; + +static char errbuf[BUFSIZ]; + +/* The compiler complains if this is declared static. */ +#ifdef __STDC__ +int rki_key_proc(char *user, char *instance, char *realm, char *arg, + des_cblock *key) +#else +int rki_key_proc(user, instance, realm, arg, key) + char *user; + char *instance; + char *realm; + char *arg; + des_cblock *key; +#endif /* __STDC__ */ + +{ + rkinit_intkt_info *rii = (rkinit_intkt_info *)arg; + char password[BUFSIZ]; + int ok = 0; +#ifdef POSIX + struct termios ttyb; +#else + struct sgttyb ttyb; /* For turning off echo */ +#endif + + SBCLEAR(ttyb); + BCLEAR(password); + + /* + * If the username does not match the aname in the ticket, + * we will print that too. Otherwise, we won't. + */ + + printf("Kerberos initialization (%s)", rii->host); + if (strcmp(rii->username, user)) + printf(": tickets will be owned by %s", rii->username); + + printf("\nPassword for %s%s%s@%s: ", user, + (instance[0]) ? "." : "", instance, realm); + + fflush(stdout); + + push_signals(); + if (setjmp(env)) { + ok = -1; + goto lose; + } + +#ifndef POSIX + ioctl(0, TIOCGETP, &ttyb); + ttyb.sg_flags &= ~ECHO; + ioctl(0, TIOCSETP, &ttyb); +#else + (void) tcgetattr(0, &ttyb); + ttyb.c_lflag &= ~ECHO; + (void) tcsetattr(0, TCSAFLUSH, &ttyb); +#endif + + bzero(password, sizeof(password)); + if (read(0, password, sizeof(password)) == -1) { + perror("read"); + ok = -1; + goto lose; + } + + if (password[strlen(password)-1] == '\n') + password[strlen(password)-1] = 0; + + /* Generate the key from the password and destroy the password */ + + des_string_to_key(password, key); + +lose: + BCLEAR(password); + +#ifndef POSIX + ttyb.sg_flags |= ECHO; + ioctl(0, TIOCSETP, &ttyb); +#else + ttyb.c_lflag |= ECHO; + (void) tcsetattr(0, TCSAFLUSH, &ttyb); +#endif + + pop_signals(); + printf("\n"); + + return(ok); +} + +#ifdef __STDC__ +static int rki_decrypt_tkt(char *user, char *instance, char *realm, + char *arg, int (*key_proc)(), KTEXT *cipp) +#else +static int rki_decrypt_tkt(user, instance, realm, arg, key_proc, cipp) + char *user; + char *instance; + char *realm; + char *arg; + int (*key_proc)(); + KTEXT *cipp; +#endif /* __STDC__ */ +{ + KTEXT cip = *cipp; + C_Block key; /* Key for decrypting cipher */ + Key_schedule key_s; + KTEXT scip = 0; /* cipher from rkinit server */ + + rkinit_intkt_info *rii = (rkinit_intkt_info *)arg; + + /* generate a key */ + { + register int rc; + rc = (*key_proc)(user, instance, realm, arg, key); + if (rc) + return(rc); + } + + des_key_sched(&key, key_s); + + /* Decrypt information from KDC */ + des_pcbc_encrypt((C_Block *)cip->dat,(C_Block *)cip->dat, + (long) cip->length, key_s, &key, 0); + + /* DescrYPT rkinit server's information from KDC */ + scip = rii->scip; + des_pcbc_encrypt((C_Block *)scip->dat,(C_Block *)scip->dat, + (long) scip->length, key_s, &key, 0); + + /* Get rid of all traces of key */ + bzero((char *)key, sizeof(key)); + bzero((char *)key_s, sizeof(key_s)); + + return(0); +} + +#ifdef __STDC__ +int rki_get_tickets(int version, char *host, char *r_krealm, rkinit_info *info) +#else +int rki_get_tickets(version, host, r_krealm, info) + int version; + char *host; + char *r_krealm; + rkinit_info *info; +#endif /* __STDC__ */ +{ + int status = RKINIT_SUCCESS; + KTEXT_ST auth; + char phost[MAXHOSTNAMELEN]; + KTEXT_ST scip; /* server's KDC packet */ + des_cblock key; + des_key_schedule sched; + struct sockaddr_in caddr; + struct sockaddr_in saddr; + CREDENTIALS cred; + MSG_DAT msg_data; + u_char enc_data[MAX_KTXT_LEN]; + + rkinit_intkt_info rii; + + SBCLEAR(auth); + BCLEAR(phost); + SBCLEAR(rii); + SBCLEAR(scip); + SBCLEAR(caddr); + SBCLEAR(saddr); + SBCLEAR(cred); + SBCLEAR(msg_data); + BCLEAR(enc_data); + + if ((status = rki_send_rkinit_info(version, info)) != RKINIT_SUCCESS) + return(status); + + if ((status = rki_rpc_get_skdc(&scip)) != RKINIT_SUCCESS) + return(status); + + rii.scip = &scip; + rii.host = host; + rii.username = info->username; + + if ((status = krb_get_in_tkt(info->aname, info->inst, info->realm, + "krbtgt", info->realm, 1, + rki_key_proc, rki_decrypt_tkt, (char *)&rii))) { + strcpy(errbuf, krb_err_txt[status]); + rkinit_errmsg(errbuf); + return(RKINIT_KERBEROS); + } + + /* Create an authenticator */ + strcpy(phost, krb_get_phost(host)); + if ((status = krb_mk_req(&auth, KEY, phost, r_krealm, 0))) { + sprintf(errbuf, "krb_mk_req: %s", krb_err_txt[status]); + rkinit_errmsg(errbuf); + return(RKINIT_KERBEROS); + } + + /* Re-encrypt server KDC packet in session key */ + /* Get credentials from ticket file */ + if ((status = krb_get_cred(KEY, phost, r_krealm, &cred))) { + sprintf(errbuf, "krb_get_cred: %s", krb_err_txt[status]); + rkinit_errmsg(errbuf); + return(RKINIT_KERBEROS); + } + + /* Exctract the session key and make the schedule */ + bcopy(cred.session, key, sizeof(key)); + if ((status = des_key_sched(&key, sched))) { + sprintf(errbuf, "des_key_sched: %s", krb_err_txt[status]); + rkinit_errmsg(errbuf); + return(RKINIT_DES); + } + + /* Get client and server addresses */ + if ((status = rki_get_csaddr(&caddr, &saddr)) != RKINIT_SUCCESS) + return(status); + + /* + * scip was passed to krb_get_in_tkt, where it was decrypted. + * Now re-encrypt in the session key. + */ + + msg_data.app_data = enc_data; + if ((msg_data.app_length = + krb_mk_priv(scip.dat, msg_data.app_data, scip.length, sched, key, + &caddr, &saddr)) == -1) { + sprintf(errbuf, "krb_mk_priv failed."); + rkinit_errmsg(errbuf); + return(RKINIT_KERBEROS); + } + + /* Destroy tickets, which we no longer need */ + dest_tkt(); + + if ((status = rki_rpc_send_ckdc(&msg_data)) != RKINIT_SUCCESS) + return(status); + + if ((status = rki_rpc_sendauth(&auth)) != RKINIT_SUCCESS) + return(status); + + if ((status = rki_rpc_get_status())) + return(status); + + return(RKINIT_SUCCESS); +} + + +static void (*old_sigfunc[NSIG])(int); + +static void push_signals() +{ + register i; + for (i = 0; i < NSIG; i++) + old_sigfunc[i] = signal(i,sig_restore); +} + +static void 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); +} diff --git a/eBones/lib/librkinit/rk_lib.c b/eBones/lib/librkinit/rk_lib.c new file mode 100644 index 0000000000000..06b8f392e0d6f --- /dev/null +++ b/eBones/lib/librkinit/rk_lib.c @@ -0,0 +1,100 @@ +/* + * $Id: rk_lib.c,v 1.1 1993/12/10 19:32:01 dglo Exp gibbs $ + * $Source: /usr/src/eBones/librkinit/RCS/rk_lib.c,v $ + * $Author: dglo $ + * + * This file contains the non-rpc top-level rkinit library routines. + * The routines in the rkinit library that should be called from clients + * are exactly those defined in this file. + * + * The naming convetions used within the rkinit library are as follows: + * Functions intended for general client use start with rkinit_ + * Functions intended for use only inside the library or server start with + * rki_ + * Functions that do network communcation start with rki_rpc_ + * Static functions can be named in any fashion. + */ + +#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS) +static char *rcsid = "$Id: rk_lib.c,v 1.1 1993/12/10 19:32:01 dglo Exp gibbs $"; +#endif /* lint || SABER || LOCORE || RCS_HDRS */ + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <setjmp.h> +#include <krb.h> + +#include <rkinit.h> +#include <rkinit_private.h> +#include <rkinit_err.h> + +#ifdef __STDC__ +char *rkinit_errmsg(char *string) +#else +char *rkinit_errmsg(string) + char *string; +#endif /* __STDC__ */ +{ + static char errmsg[BUFSIZ]; + + if (string) { + BCLEAR(errmsg); + strncpy(errmsg, string, sizeof(errmsg) - 1); + } + + return(errmsg); +} + +#ifdef __STDC__ +int rkinit(char *host, char *r_krealm, rkinit_info *info, int timeout) +#else +int rkinit(host, r_krealm, info, timeout) + char *host; + char *r_krealm; + rkinit_info *info; + int timeout; +#endif /* __STDC__ */ +{ + int status = RKINIT_SUCCESS; + int version = 0; + char phost[MAXHOSTNAMELEN]; + jmp_buf timeout_env; + void (*old_alrm)(int) = NULL; + char origtktfilename[MAXPATHLEN]; /* original ticket file name */ + char tktfilename[MAXPATHLEN]; /* temporary client ticket file */ + + BCLEAR(phost); + BCLEAR(origtktfilename); + BCLEAR(tktfilename); + BCLEAR(timeout_env); + + init_rkin_err_tbl(); + + if ((status = rki_setup_rpc(host))) + return(status); + + if (timeout) + old_alrm = rki_setup_timer(timeout_env); + + /* The alarm handler longjmps us to here. */ + if ((status = setjmp(timeout_env)) == 0) { + + strcpy(origtktfilename, tkt_string()); + sprintf(tktfilename, "/tmp/tkt_rkinit.%ld", getpid()); + krb_set_tkt_string(tktfilename); + + if ((status = rki_choose_version(&version)) == RKINIT_SUCCESS) + status = rki_get_tickets(version, host, r_krealm, info); + } + + if (timeout) + rki_restore_timer(old_alrm); + + dest_tkt(); + krb_set_tkt_string(origtktfilename); + + rki_cleanup_rpc(); + + return(status); +} diff --git a/eBones/lib/librkinit/rk_rpc.c b/eBones/lib/librkinit/rk_rpc.c new file mode 100644 index 0000000000000..dd6132779461c --- /dev/null +++ b/eBones/lib/librkinit/rk_rpc.c @@ -0,0 +1,387 @@ +/* + * $Id: rk_rpc.c,v 1.1 1993/12/10 19:36:09 dglo Exp gibbs $ + * $Source: /usr/src/eBones/librkinit/RCS/rk_rpc.c,v $ + * $Author: dglo $ + * + * This file contains functions that are used for network communication. + * See the comment at the top of rk_lib.c for a description of the naming + * conventions used within the rkinit library. + */ + +#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS) +static char *rcsid = "$Id: rk_rpc.c,v 1.1 1993/12/10 19:36:09 dglo Exp gibbs $"; +#endif /* lint || SABER || LOCORE || RCS_HDRS */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <sys/uio.h> +#include <unistd.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <errno.h> + +#include <rkinit.h> +#include <rkinit_err.h> +#include <rkinit_private.h> + +extern int errno; + +static int sock; +struct sockaddr_in saddr; + +static char errbuf[BUFSIZ]; + +char *calloc(); + +#ifdef __STDC__ +int rki_send_packet(int sock, char type, u_int32_t length, const char *data) +#else +int rki_send_packet(sock, type, length, data) + int sock; + char type; + u_int32_t length; + const char *data; +#endif /* __STDC__ */ +{ + int len; + u_char *packet; + u_int32_t pkt_len; + u_int32_t net_pkt_len; + + pkt_len = length + PKT_DATA; + + if ((packet = (u_char *)calloc(pkt_len, sizeof(u_char))) == NULL) { + sprintf(errbuf, "rki_send_packet: failure allocating %d bytes", + pkt_len * sizeof(u_char)); + rkinit_errmsg(errbuf); + return(RKINIT_MEMORY); + } + + net_pkt_len = htonl(pkt_len); + + packet[PKT_TYPE] = type; + bcopy((char *)&net_pkt_len, packet + PKT_LEN, sizeof(u_int32_t)); + bcopy(data, packet + PKT_DATA, length); + + if ((len = write(sock, packet, pkt_len)) != pkt_len) { + if (len == -1) + sprintf(errbuf, "write: %s", sys_errlist[errno]); + else + sprintf(errbuf, "write: %d bytes written; %d bytes actually sent", + pkt_len, len); + rkinit_errmsg(errbuf); + free(packet); + return(RKINIT_WRITE); + } + + free(packet); + return(RKINIT_SUCCESS); +} + +#ifdef __STDC__ +int rki_get_packet(int sock, u_char type, u_int32_t *length, char *data) +#else +int rki_get_packet(sock, type, length, data) + int sock; + u_char type; + u_int32_t *length; + char *data; +#endif /* __STDC__ */ +{ + int len; + int len_sofar = 0; + u_int32_t expected_length = 0; + int got_full_packet = FALSE; + int tries = 0; + u_char *packet; + + u_int32_t max_pkt_len; + + max_pkt_len = *length + PKT_DATA; + + if ((packet = (u_char *)calloc(max_pkt_len, sizeof(u_char))) == NULL) { + sprintf(errbuf, "rki_get_packet: failure allocating %d bytes", + max_pkt_len * sizeof(u_char)); + rkinit_errmsg(errbuf); + return(RKINIT_MEMORY); + } + + /* Read the packet type and length */ + while ((len_sofar < PKT_DATA) && (tries < RETRIES)) { + if ((len = read(sock, packet + len_sofar, PKT_DATA - len_sofar)) < 0) { + sprintf(errbuf, "read: %s", sys_errlist[errno]); + rkinit_errmsg(errbuf); + return(RKINIT_READ); + } + len_sofar += len; + tries++; + } + if (len_sofar < PKT_DATA) { + sprintf(errbuf, + "read: expected to receive at least %d bytes; received %d", + PKT_DATA, len_sofar); + rkinit_errmsg(errbuf); + return(RKINIT_PACKET); + } + bcopy(packet + PKT_LEN, (char *)&expected_length, sizeof(u_int32_t)); + expected_length = ntohl(expected_length); + if (expected_length > max_pkt_len) { + sprintf(errbuf, "%s %d %s %d", + "rki_get_packet: incoming message of size", + expected_length, + "is larger than message buffer of size", + max_pkt_len); + rkinit_errmsg(errbuf); + return(RKINIT_PACKET); + } + tries = 0; + while (!got_full_packet && (tries < RETRIES)) { + if ((len = read(sock, packet + len_sofar, + expected_length - len_sofar)) < 0) { + sprintf(errbuf, "read: %s", sys_errlist[errno]); + rkinit_errmsg(errbuf); + return(RKINIT_READ); + } + len_sofar += len; + if (expected_length == len_sofar) + got_full_packet = TRUE; + } + if (len_sofar < expected_length) { + sprintf(errbuf, + "read: expected to receive at least %d bytes; received %d", + expected_length, len_sofar); + rkinit_errmsg(errbuf); + return(RKINIT_PACKET); + } + if (packet[PKT_TYPE] == MT_DROP) { + BCLEAR(errbuf); + rkinit_errmsg(errbuf); + return(RKINIT_DROPPED); + } + + if (packet[PKT_TYPE] != type) { + sprintf(errbuf, "Expected packet type of %s; got %s", + rki_mt_to_string(type), + rki_mt_to_string(packet[PKT_TYPE])); + rkinit_errmsg(errbuf); + return(RKINIT_PACKET); + } + + *length = len_sofar - PKT_DATA; + bcopy(packet + PKT_DATA, data, *length); + + free(packet); + + return(RKINIT_SUCCESS); +} + +#ifdef __STDC__ +int rki_setup_rpc(char *host) +#else +int rki_setup_rpc(host) + char *host; +#endif /* __STDC__ */ +{ + struct hostent *hp; + struct servent *sp; + int port; + + SBCLEAR(saddr); + SBCLEAR(hp); + SBCLEAR(sp); + + if ((hp = gethostbyname(host)) == NULL) { + sprintf(errbuf, "%s: unknown host.", host); + rkinit_errmsg(errbuf); + return(RKINIT_HOST); + } + + if ((sp = getservbyname(SERVENT, "tcp"))) + port = sp->s_port; + else + /* Fall back on known port number */ + port = htons(PORT); + + saddr.sin_family = hp->h_addrtype; + bcopy(hp->h_addr, (char *)&saddr.sin_addr, hp->h_length); + saddr.sin_port = port; + + if ((sock = socket(hp->h_addrtype, SOCK_STREAM, IPPROTO_IP)) < 0) { + sprintf(errbuf, "socket: %s", sys_errlist[errno]); + rkinit_errmsg(errbuf); + return(RKINIT_SOCKET); + } + + if (connect(sock, (struct sockaddr *)&saddr, sizeof (saddr)) < 0) { + sprintf(errbuf, "connect: %s", sys_errlist[errno]); + rkinit_errmsg(errbuf); + close(sock); + return(RKINIT_CONNECT); + } + + return(RKINIT_SUCCESS); +} + +#ifdef __STDC__ +int rki_rpc_exchange_version_info(int c_lversion, int c_hversion, + int *s_lversion, int *s_hversion) +#else +int rki_rpc_exchange_version_info(c_lversion, c_hversion, + s_lversion, s_hversion) + int c_lversion; + int c_hversion; + int *s_lversion; + int *s_hversion; +#endif /* __STDC__ */ +{ + int status = RKINIT_SUCCESS; + u_char version_info[VERSION_INFO_SIZE]; + u_int32_t length = sizeof(version_info); + + version_info[0] = (u_char) c_lversion; + version_info[1] = (u_char) c_hversion; + + if ((status = rki_send_packet(sock, MT_CVERSION, length, + (char *)version_info)) != RKINIT_SUCCESS) + return(status); + + if ((status = rki_get_packet(sock, MT_SVERSION, &length, + (char *)version_info)) != RKINIT_SUCCESS) + return(status); + + *s_lversion = (int) version_info[0]; + *s_hversion = (int) version_info[1]; + + return(RKINIT_SUCCESS); +} + +#ifdef __STDC__ +int rki_rpc_send_rkinit_info(rkinit_info *info) +#else +int rki_rpc_send_rkinit_info(info) + rkinit_info *info; +#endif /* __STDC__ */ +{ + rkinit_info info_copy; + + bcopy(info, &info_copy, sizeof(rkinit_info)); + info_copy.lifetime = htonl(info_copy.lifetime); + return(rki_send_packet(sock, MT_RKINIT_INFO, sizeof(rkinit_info), + (char *)&info_copy)); +} + +#ifdef __STDC__ +int rki_rpc_get_status(void) +#else +int rki_rpc_get_status() +#endif /* __STDC__ */ +{ + char msg[BUFSIZ]; + int status = RKINIT_SUCCESS; + u_int32_t length = sizeof(msg); + + if ((status = rki_get_packet(sock, MT_STATUS, &length, msg))) + return(status); + + if (length == 0) + return(RKINIT_SUCCESS); + else { + rkinit_errmsg(msg); + return(RKINIT_DAEMON); + } +} + +#ifdef __STDC__ +int rki_rpc_get_ktext(int sock, KTEXT auth, u_char type) +#else +int rki_rpc_get_ktext(sock, auth, type) + int sock; + KTEXT auth; + u_char type; +#endif /* __STDC__ */ +{ + int status = RKINIT_SUCCESS; + u_int32_t length = MAX_KTXT_LEN; + + if ((status = rki_get_packet(sock, type, &length, (char *)auth->dat))) + return(status); + + auth->length = length; + + return(RKINIT_SUCCESS); +} + +#ifdef __STDC__ +int rki_rpc_sendauth(KTEXT auth) +#else +int rki_rpc_sendauth(auth) + KTEXT auth; +#endif /* __STDC__ */ +{ + return(rki_send_packet(sock, MT_AUTH, auth->length, (char *)auth->dat)); +} + + +#ifdef __STDC__ +int rki_rpc_get_skdc(KTEXT scip) +#else +int rki_rpc_get_skdc(scip) + KTEXT scip; +#endif /* __STDC__ */ +{ + return(rki_rpc_get_ktext(sock, scip, MT_SKDC)); +} + +#ifdef __STDC__ +int rki_rpc_send_ckdc(MSG_DAT *scip) +#else +int rki_rpc_send_ckdc(scip) + MSG_DAT *scip; +#endif /* __STDC__ */ +{ + return(rki_send_packet(sock, MT_CKDC, scip->app_length, + (char *)scip->app_data)); +} + +#ifdef __STDC__ +int rki_get_csaddr(struct sockaddr_in *caddrp, struct sockaddr_in *saddrp) +#else +int rki_get_csaddr(caddrp, saddrp) + struct sockaddr_in *caddrp; + struct sockaddr_in *saddrp; +#endif /* __STDC__ */ +{ + int addrlen = sizeof(struct sockaddr_in); + + bcopy((char *)&saddr, (char *)saddrp, addrlen); + + if (getsockname(sock, (struct sockaddr *)caddrp, &addrlen) < 0) { + sprintf(errbuf, "getsockname: %s", sys_errlist[errno]); + rkinit_errmsg(errbuf); + return(RKINIT_GETSOCK); + } + + return(RKINIT_SUCCESS); +} + +#ifdef __STDC__ +void rki_drop_server(void) +#else +void rki_drop_server() +#endif /* __STDC__ */ +{ + (void) rki_send_packet(sock, MT_DROP, 0, ""); +} + +#ifdef __STDC__ +void rki_cleanup_rpc(void) +#else +void rki_cleanup_rpc() +#endif /* __STDC__ */ +{ + rki_drop_server(); + (void) close(sock); +} diff --git a/eBones/lib/librkinit/rk_util.c b/eBones/lib/librkinit/rk_util.c new file mode 100644 index 0000000000000..4333d38d306f9 --- /dev/null +++ b/eBones/lib/librkinit/rk_util.c @@ -0,0 +1,214 @@ +/* + * $Id: rk_util.c,v 1.1 1993/12/10 19:36:09 dglo Exp gibbs $ + * $Source: /usr/src/eBones/librkinit/RCS/rk_util.c,v $ + * $Author: dglo $ + * + * This file contains internal routines for general use by the rkinit + * library and server. + * + * See the comment at the top of rk_lib.c for a description of the naming + * conventions used within the rkinit library. + */ + +#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS) +static char *rcsid = "$Id: rk_util.c,v 1.1 1993/12/10 19:36:09 dglo Exp gibbs $"; +#endif /* lint || SABER || LOCORE || RCS_HDRS */ + +#include <stdio.h> +#include <sys/types.h> +#include <string.h> +#include <setjmp.h> +#include <signal.h> +#include <sys/time.h> + +#ifdef DEBUG +#include <syslog.h> +#endif /* DEBUG */ + +#include <rkinit.h> +#include <rkinit_private.h> +#include <rkinit_err.h> + +#define RKINIT_TIMEOUTVAL 60 + +static char errbuf[BUFSIZ]; +static jmp_buf timeout_env; + +#ifdef DEBUG +static int _rkinit_server_ = FALSE; + +#ifdef __STDC__ +void rki_dmsg(char *string) +#else +void rki_dmsg(string) + char *string; +#endif /* __STDC__ */ +{ + if (_rkinit_server_) + syslog(LOG_NOTICE, string); + else + printf("%s\n", string); +} + +#ifdef __STDC__ +void rki_i_am_server(void) +#else +void rki_i_am_server() +#endif /* __STDC__ */ +{ + _rkinit_server_ = TRUE; +} +#else /* DEBUG */ +#ifdef __STDC__ +void rki_dmsg(char *string) +#else +void rki_dmsg(string) + char *string; +#endif /* __STDC__ */ +{ + return; +} + +#endif /* DEBUG */ + +#ifdef __STDC__ +const char *rki_mt_to_string(int mt) +#else +const char *rki_mt_to_string(mt) + int mt; +#endif /* __STDC__ */ +{ + char *string = 0; + + switch(mt) { + case MT_STATUS: + string = "Status message"; + break; + case MT_CVERSION: + string = "Client version"; + break; + case MT_SVERSION: + string = "Server version"; + break; + case MT_RKINIT_INFO: + string = "Rkinit information"; + break; + case MT_SKDC: + string = "Server kdc packet"; + break; + case MT_CKDC: + string = "Client kdc packet"; + break; + case MT_AUTH: + string = "Authenticator"; + break; + case MT_DROP: + string = "Drop server"; + break; + default: + string = "Unknown message type"; + break; + } + + return(string); +} + +#ifdef __STDC__ +int rki_choose_version(int *version) +#else +int rki_choose_version(version) + int *version; +#endif /* __STDC__ */ +{ + int s_lversion; /* lowest version number server supports */ + int s_hversion; /* highest version number server supports */ + int status = RKINIT_SUCCESS; + + if ((status = + rki_rpc_exchange_version_info(RKINIT_LVERSION, RKINIT_HVERSION, + &s_lversion, + &s_hversion)) != RKINIT_SUCCESS) + return(status); + + *version = min(RKINIT_HVERSION, s_hversion); + if (*version < max(RKINIT_LVERSION, s_lversion)) { + sprintf(errbuf, + "Can't run version %d client against version %d server.", + RKINIT_HVERSION, s_hversion); + rkinit_errmsg(errbuf); + status = RKINIT_VERSION; + } + + return(status); +} + +#ifdef __STDC__ +int rki_send_rkinit_info(int version, rkinit_info *info) +#else +int rki_send_rkinit_info(version, info) + int version; + rkinit_info *info; +#endif /* __STDC__ */ +{ + int status = 0; + + if ((status = rki_rpc_send_rkinit_info(info)) != RKINIT_SUCCESS) + return(status); + + return(rki_rpc_get_status()); +} + +#ifdef __STDC__ +static void rki_timeout(int signal) +#else +static void rki_timeout(signal) + int signal; +#endif /* __STDC__ */ +{ + sprintf(errbuf, "%d seconds exceeded.", RKINIT_TIMEOUTVAL); + rkinit_errmsg(errbuf); + longjmp(timeout_env, RKINIT_TIMEOUT); + return; +} + +#ifdef __STDC__ +static void set_timer(int secs) +#else +static void set_timer(secs) + int secs; +#endif /* __STDC__ */ +{ + struct itimerval timer; /* Time structure for timeout */ + + /* Set up an itimer structure to send an alarm signal after TIMEOUT + seconds. */ + timer.it_interval.tv_sec = secs; + timer.it_interval.tv_usec = 0; + timer.it_value = timer.it_interval; + + (void) setitimer (ITIMER_REAL, &timer, (struct itimerval *)0); +} + + +#ifdef __STDC__ +void (*rki_setup_timer(jmp_buf env))(int) +#else +void (*rki_setup_timer(env))(int) + jmp_buf env; +#endif /* __STDC__ */ +{ + bcopy((char *)env, (char *)timeout_env, sizeof(jmp_buf)); + set_timer(RKINIT_TIMEOUTVAL); + return(signal(SIGALRM, rki_timeout)); +} + +#ifdef __STDC__ +void rki_restore_timer(void (*old_alrm)(int)) +#else +void rki_restore_timer(old_alrm) + void (*old_alrm)(int); +#endif /* __STDC__ */ +{ + set_timer(0); + (void) signal(SIGALRM, old_alrm); +} diff --git a/eBones/lib/librkinit/rkinit.3 b/eBones/lib/librkinit/rkinit.3 new file mode 100644 index 0000000000000..fe6bdf7a1fb65 --- /dev/null +++ b/eBones/lib/librkinit/rkinit.3 @@ -0,0 +1,167 @@ +.\" +.\" $Header: /local/cvsfiles/kerberos/src/appl/rkinit/man/rkinit.3,v 1.1 1991/12/03 23:21:29 eichin Exp $ +.\" $Source: /local/cvsfiles/kerberos/src/appl/rkinit/man/rkinit.3,v $ +.\" $Author: eichin $ +.\" +.\" +.TH RKINIT 3 "November 12, 1989" +.SH NAME +rkinit, rkinit_errmsg +.SH SYNOPSIS +.nf +.nj +.ft B +#include <rkinit.h> +#include <rkinit_err.h> +.PP +.ft B +int rkinit(host, r_krealm, info, timeout) + char *host; + char *r_krealm; + rkinit_info *info; + int timeout; +.PP +.ft B +char *rkinit_errmsg(string) + char *string; +.fi +.ft R +.SH DESCRIPTION +This library contains the calls necessary to interface with the +.I rkinit +system of remote ticket establishment. See +.IR rkinit (1) +for more information on +.I rkinit +.PP +.I rkinit.h +is the header file that contains information that all clients +will need to use. +.PP +.I rkinit_err.h +is the +.I com_err +error table header file. See +.IR com_err (3) +for more information about +.I com_err. +.PP +.IR rkinit () +takes as arguments the name of the host on which you wish to +establish tickets, the kerberos realm of the remote host, a +fully initialized rkinit_info structure, and a boolean value +telling +whether or not +.IR rkinit () +should time out if the transaction +fails to complete after a certain about of time. +This call does not know about about default values, so +something must be filled in for everything except for the ticket +filename in the rkinit_info structure described below. + +.nf +.nj +.ft B +This is the rkinit_info type: + +typedef struct { + char aname[ANAME_SZ + 1]; + char inst[INST_SZ + 1]; + char realm[REALM_SZ + 1]; + char sname[ANAME_SZ + 1]; + char sinst[INST_SZ + 1]; + char username[9]; /* max local name length + 1 */ + char tktfilename[MAXPATHLEN + 1]; + long lifetime; +} rkinit_info; +.fi +.ft R + +.I aname +is the name part of the kerberos principal for which tickets are +being requested. + +.I inst +is the instance part. + +.I realm +is the realm part. + +.I sname +is the service name of the key that will appear in the remote +initial ticket (for example, "krbtgt"). + +.I sname +is the service instance. + +.I username +is the name of the local user on the remote host who will own +the ticket file. + +.I tktfilename +is the name of the file on the remote host in which the +tickets will be stored. This is the only field in the structure +for which a blank value is filled in. If this value is left +blank, the server will figure out what to call the ticket file +by using the kerberos library default as determined by +.I TKT_FILE +as defined in +.IR krb.h . + +.I lifetime +is the lifetime of the tickets in the usual five minute +intervals. It is possible with this routine, as with +.IR krb_get_in_tkt (3) +to request tickets with zero lifetime. + +.IR rkinit (), +while it is running, opens a socket, changes the name +of the default kerberos ticket file, and changes the signal +handler for the ALRM signal (if timeout != 0). rkinit() +restores all these values when it exits whether it exits with +an error or not, so clients using the rkinit library need not +worry about this information. + +.IR rkinit_errmsg () +takes a string as its only argument. Passing +other than NULL to this routine should be done +by only the rkinit library and server. +Doing this sets the current rkinit +error message. Calling +.IR rkinit_errmsg () +with NULL as the argument returns the current rkinit error +message. +Although the rkinit library uses +.IR com_err (3) +for error handling, the error messages returned by +.IR com_err () +may not be specific enough. A client could report the error +message returned by rkinit as follows: + + +.nf +.nj +.ft B +if (status = rkinit(host, r_krealm, &info, timeout)) { + com_err(argv[0], status, "while obtaining remote tickets:"); + fprintf(stderr, "%s\\n", rkinit_errmsg(0)); + exit(1); +} +.fi +.ft R + +.SH SEE ALSO +kerberos(1), kerberos(3), rkinit(1), rkinitd(8) + +.SH DIAGNOSTICS +.IR rkinit () +is usually good about reporting error messages to the client. +It will probably not handle uninitialized variables well, +however. Make sure that things like the realm of the remote +host and the lifetime of the tickets have been properly +initialized before calling +.IR rkinit (). + + +.SH AUTHOR +Emanuel Jay Berkenbilt (MIT-Project Athena) diff --git a/eBones/lib/librkinit/rkinit_err.et b/eBones/lib/librkinit/rkinit_err.et new file mode 100644 index 0000000000000..d0ade5ba11cbc --- /dev/null +++ b/eBones/lib/librkinit/rkinit_err.et @@ -0,0 +1,32 @@ +# +# $Header: /local/cvsfiles/kerberos/src/appl/rkinit/lib/rkinit_err.et,v 1.1 1991/12/03 23:20:58 eichin Exp $ +# $Source: /local/cvsfiles/kerberos/src/appl/rkinit/lib/rkinit_err.et,v $ +# $Author: eichin $ +# +# These error messages will probably not be printed by com_err. +# Instead, a better error message (with specific information) +# will be obtained by a call to rkinit_errmsg(). +# + +et rkin + +ec RKINIT_RCSID, "$Header: /local/cvsfiles/kerberos/src/appl/rkinit/lib/rkinit_err.et,v 1.1 1991/12/03 23:20:58 eichin Exp $" +ec RKINIT_VERSION, "Version mismatch" +ec RKINIT_HOST, "Failure getting host information" +ec RKINIT_SERV, "Failure getting service information (/etc/services)" +ec RKINIT_SOCKET, "Failure setting up socket" +ec RKINIT_CONNECT, "Failure connecting" +ec RKINIT_PACKET, "Bad packet type" +ec RKINIT_WRITE, "Failure writing" +ec RKINIT_READ, "Failure reading" +ec RKINIT_DAEMON, "Error reported by rkinitd" +ec RKINIT_KERBEROS, "Kerberos error" +ec RKINIT_DES, "Des error" +ec RKINIT_GETPEER, "Failure in getpeername" +ec RKINIT_GETSOCK, "Failure in getsockname" +ec RKINIT_MEMORY, "Out of memory" +ec RKINIT_TIMEOUT, "Timed out" +ec RKINIT_DROPPED, "Connection dropped" + +ec RKINIT_LAST, "Last error message" +end diff --git a/eBones/libexec/Makefile b/eBones/libexec/Makefile new file mode 100644 index 0000000000000..b7193e672228e --- /dev/null +++ b/eBones/libexec/Makefile @@ -0,0 +1,6 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.1 1995/09/13 17:23:59 markm Exp $ + +SUBDIR= kpropd registerd rkinitd + +.include <bsd.subdir.mk> diff --git a/eBones/libexec/Makefile.inc b/eBones/libexec/Makefile.inc new file mode 100644 index 0000000000000..d694f9b03653d --- /dev/null +++ b/eBones/libexec/Makefile.inc @@ -0,0 +1,5 @@ +# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93 + +BINDIR?= /usr/libexec + +.include "../Makefile.inc" diff --git a/eBones/libexec/kpropd/Makefile b/eBones/libexec/kpropd/Makefile new file mode 100644 index 0000000000000..0f1f420eda8b2 --- /dev/null +++ b/eBones/libexec/kpropd/Makefile @@ -0,0 +1,10 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1995/09/13 17:24:02 markm Exp $ + +PROG= kpropd +CFLAGS+=-I${.CURDIR}/../../usr.sbin/kprop +DPADD+= ${LIBKRB} ${LIBDES} +LDADD= -lkrb -ldes +NOMAN= noman + +.include <bsd.prog.mk> diff --git a/eBones/libexec/kpropd/kpropd.c b/eBones/libexec/kpropd/kpropd.c new file mode 100644 index 0000000000000..1b232dfc0ded5 --- /dev/null +++ b/eBones/libexec/kpropd/kpropd.c @@ -0,0 +1,453 @@ +/* + * Copyright 1987 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * MIT.Copyright. + * + * kprop/kpropd have been abandonded by Project Athena (for good reason) + * however they still form the basis for one of the better ways for + * distributing kerberos databases. This version of kpropd has been + * adapted from the MIT distribution to work properly in a 4.4BSD + * environment. + * + * $Revision: 1.1.1.1 $ $Date: 1995/08/03 07:37:19 $ $State: Exp $ + * $Source: /usr/cvs/src/eBones/kpropd/kpropd.c,v $ + * + * Log: kpropd.c,v + * Revision 4.5 92/10/23 15:45:46 tytso Make it possible + * to specify the location of the kdb_util program. + * + * Revision 4.4 91/06/15 03:20:51 probe Fixed <sys/types.h> inclusion + * + * Revision 4.3 89/05/16 15:06:04 wesommer Fix operator precedence stuff. + * Programmer: John Kohl. + * + * Revision 4.2 89/03/23 10:24:00 jtkohl NOENCRYPTION changes + * + * Revision 4.1 89/01/24 20:33:48 root name change + * + * Revision 4.0 89/01/24 18:45:06 wesommer Original version; programmer: + * wesommer auditor: jon + * + * Revision 4.5 88/01/08 18:07:46 jon formatting and rcs header changes */ + +/* + * This program is run on slave servers, to catch updates "pushed" from the + * master kerberos server in a realm. + */ + +#if 0 +#ifndef lint +static char rcsid_kpropd_c[] = +"$Header: /usr/cvs/src/eBones/kpropd/kpropd.c,v 1.1.1.1 1995/08/03 07:37:19 mark Exp $"; +#endif /* lint */ +#endif + +#include <errno.h> +#include <unistd.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <syslog.h> +#include <krb.h> +#include <krb_db.h> + +#include "kprop.h" + +static char kprop_version[KPROP_PROT_VERSION_LEN] = KPROP_PROT_VERSION; + +int debug = 0; + +int pause_int = 300; /* 5 minutes in seconds */ +unsigned long get_data_checksum(int fd, Key_schedule key_sched); +void recv_auth(int in, int out, int private, + struct sockaddr_in *remote, struct sockaddr_in *local, + AUTH_DAT *ad); +static void SlowDeath(void); +void recv_clear(int in, int out); + /* leave room for private msg overhead */ +static char buf[KPROP_BUFSIZ + 64]; + +static void +usage() +{ + fprintf(stderr, "\nUsage: kpropd [-r realm] [-s srvtab] [-P kdb_util] fname\n"); + exit(2); +} + +void +main(argc, argv) + int argc; + char **argv; +{ + struct sockaddr_in from; + struct sockaddr_in sin; + int s2, fd, n, fdlock; + int from_len; + char local_file[256]; + char local_temp[256]; + struct hostent *hp; + char hostname[256]; + char from_str[128]; + long kerror; + AUTH_DAT auth_dat; + KTEXT_ST ticket; + char my_instance[INST_SZ]; + char my_realm[REALM_SZ]; + char cmd[1024]; + short net_transfer_mode, transfer_mode; + Key_schedule session_sched; + char version[9]; + int c; + extern char *optarg; + extern int optind; + int rflag = 0; + char *srvtab = ""; + char *local_db = DBM_FILE; + char *kdb_util = KPROP_KDB_UTIL; + + if (argv[argc - 1][0] == 'k' && isdigit(argv[argc - 1][1])) { + argc--; /* ttys file hack */ + } + while ((c = getopt(argc, argv, "r:s:d:P:")) != EOF) { + switch (c) { + case 'r': + rflag++; + strcpy(my_realm, optarg); + break; + case 's': + srvtab = optarg; + break; + case 'd': + local_db = optarg; + break; + case 'P': + kdb_util = optarg; + break; + default: + usage(); + break; + } + } + if (optind != argc - 1) + usage(); + + openlog("kpropd", LOG_PID, LOG_AUTH); + + strcpy(local_file, argv[optind]); + strcat(strcpy(local_temp, argv[optind]), ".tmp"); + +#ifdef STANDALONE + + if ((sp = getservbyname("krb_prop", "tcp")) == NULL) { + syslog(LOG_ERR, "tcp/krb_prop: unknown service."); + SlowDeath(); + } + bzero(&sin, sizeof sin); + sin.sin_port = sp->s_port; + sin.sin_family = AF_INET; + + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + syslog(LOG_ERR, "socket: %m"); + SlowDeath(); + } + if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) { + syslog(LOG_ERR, "bind: %m"); + SlowDeath(); + } + +#endif /* STANDALONE */ + + if (!rflag) { + kerror = krb_get_lrealm(my_realm, 1); + if (kerror != KSUCCESS) { + syslog(LOG_ERR, "can't get local realm. %s", + krb_err_txt[kerror]); + SlowDeath(); + } + } + if (gethostname(my_instance, sizeof(my_instance)) != 0) { + syslog(LOG_ERR, "gethostname: %m"); + SlowDeath(); + } + +#ifdef STANDALONE + listen(s, 5); + for (;;) { + from_len = sizeof from; + if ((s2 = accept(s, (struct sockaddr *)&from, &from_len)) < 0) { + syslog(LOG_ERR, "accept: %m"); + continue; + } +#else /* !STANDALONE */ + + s2 = 0; + from_len = sizeof from; + if (getpeername(0, (struct sockaddr *)&from, &from_len) < 0) { + syslog(LOG_ERR, "getpeername: %m"); + SlowDeath(); + } + +#endif /* !STANDALONE */ + + strcpy(from_str, inet_ntoa(from.sin_addr)); + + if ((hp = gethostbyaddr((char *) &(from.sin_addr.s_addr), + from_len, AF_INET)) == NULL) { + strcpy(hostname, "UNKNOWN"); + } else { + strcpy(hostname, hp->h_name); + } + + syslog(LOG_INFO, "connection from %s, %s", hostname, from_str); + + /* for krb_rd_{priv, safe} */ + n = sizeof sin; + if (getsockname(s2, (struct sockaddr *)&sin, &n) != 0) { + syslog(LOG_ERR, "can't get socketname: %m"); + SlowDeath(); + } + if (n != sizeof(sin)) { + syslog(LOG_ERR, "can't get socketname (length)"); + SlowDeath(); + } + if ((fdlock = open(local_temp, O_WRONLY | O_CREAT, 0600)) < 0) { + syslog(LOG_ERR, "open: %m"); + SlowDeath(); + } + if (flock(fdlock, LOCK_EX | LOCK_NB)) { + syslog(LOG_ERR, "flock: %m"); + SlowDeath(); + } + if ((fd = creat(local_temp, 0600)) < 0) { + syslog(LOG_ERR, "creat: %m"); + SlowDeath(); + } + if ((n = read(s2, buf, sizeof(kprop_version))) + != sizeof(kprop_version)) { + syslog(LOG_ERR, + "can't read protocol version (%d bytes)", n); + SlowDeath(); + } + if (strncmp(buf, kprop_version, sizeof(kprop_version)) != 0) { + syslog(LOG_ERR, "unsupported version %s", buf); + SlowDeath(); + } + if ((n = read(s2, &net_transfer_mode, + sizeof(net_transfer_mode))) + != sizeof(net_transfer_mode)) { + syslog(LOG_ERR, "can't read transfer mode"); + SlowDeath(); + } + transfer_mode = ntohs(net_transfer_mode); + kerror = krb_recvauth(KOPT_DO_MUTUAL, s2, &ticket, + KPROP_SERVICE_NAME, + my_instance, + &from, + &sin, + &auth_dat, + srvtab, + session_sched, + version); + if (kerror != KSUCCESS) { + syslog(LOG_ERR, "%s calling getkdata", + krb_err_txt[kerror]); + SlowDeath(); + } + syslog(LOG_INFO, "connection from %s.%s@%s", + auth_dat.pname, auth_dat.pinst, auth_dat.prealm); + + /* + * AUTHORIZATION is done here. We might want to expand this + * to read an acl file at some point, but allowing for now + * KPROP_SERVICE_NAME.KRB_MASTER@local-realm is fine ... + */ + + if ((strcmp(KPROP_SERVICE_NAME, auth_dat.pname) != 0) || + (strcmp(KRB_MASTER, auth_dat.pinst) != 0) || + (strcmp(my_realm, auth_dat.prealm) != 0)) { + syslog(LOG_NOTICE, "authorization denied"); + SlowDeath(); + } + switch (transfer_mode) { + case KPROP_TRANSFER_PRIVATE: + recv_auth(s2, fd, 1 /* private */ , &from, &sin, &auth_dat); + break; + case KPROP_TRANSFER_SAFE: + recv_auth(s2, fd, 0 /* safe */ , &from, &sin, &auth_dat); + break; + case KPROP_TRANSFER_CLEAR: + recv_clear(s2, fd); + break; + default: + syslog(LOG_ERR, "bad transfer mode %d", transfer_mode); + SlowDeath(); + } + + if (transfer_mode != KPROP_TRANSFER_PRIVATE) { + syslog(LOG_ERR, "non-private transfers not supported\n"); + SlowDeath(); +#ifdef doesnt_work_yet + lseek(fd, (long) 0, L_SET); + if (auth_dat.checksum != get_data_checksum(fd, session_sched)) { + syslog(LOG_ERR, "checksum doesn't match"); + SlowDeath(); + } +#endif + } else { + struct stat st; + fstat(fd, &st); + if (st.st_size != auth_dat.checksum) { + syslog(LOG_ERR, "length doesn't match"); + SlowDeath(); + } + } + close(fd); + close(s2); + + if (rename(local_temp, local_file) < 0) { + syslog(LOG_ERR, "rename: %m"); + SlowDeath(); + } + + if (flock(fdlock, LOCK_UN)) { + syslog(LOG_ERR, "flock (unlock): %m"); + SlowDeath(); + } + close(fdlock); + sprintf(cmd, "%s load %s %s\n", kdb_util, local_file, local_db); + if (system(cmd) != 0) { + syslog(LOG_ERR, "couldn't load database"); + SlowDeath(); + } + +#ifdef STANDALONE + } +#endif + +} + +void +recv_auth(in, out, private, remote, local, ad) + int in, out; + int private; + struct sockaddr_in *remote, *local; + AUTH_DAT *ad; +{ + u_long length; + long kerror; + int n; + MSG_DAT msg_data; + Key_schedule session_sched; + + if (private) +#ifdef NOENCRYPTION + bzero((char *) session_sched, sizeof(session_sched)); +#else + if (key_sched((C_Block *)ad->session, session_sched)) { + syslog(LOG_ERR, "can't make key schedule"); + SlowDeath(); + } +#endif + + while (1) { + n = krb_net_read(in, (char *)&length, sizeof length); + if (n == 0) + break; + if (n < 0) { + syslog(LOG_ERR, "read: %m"); + SlowDeath(); + } + length = ntohl(length); + if (length > sizeof buf) { + syslog(LOG_ERR, "read length %d, bigger than buf %d", + length, sizeof buf); + SlowDeath(); + } + n = krb_net_read(in, buf, length); + if (n < 0) { + syslog(LOG_ERR, "kpropd: read: %m"); + SlowDeath(); + } + if (private) + kerror = krb_rd_priv(buf, n, session_sched, ad->session, + remote, local, &msg_data); + else + kerror = krb_rd_safe(buf, n, (C_Block *)ad->session, + remote, local, &msg_data); + if (kerror != KSUCCESS) { + syslog(LOG_ERR, "%s: %s", + private ? "krb_rd_priv" : "krb_rd_safe", + krb_err_txt[kerror]); + SlowDeath(); + } + if (write(out, msg_data.app_data, msg_data.app_length) != + msg_data.app_length) { + syslog(LOG_ERR, "write: %m"); + SlowDeath(); + } + } +} + +void +recv_clear(in, out) + int in, out; +{ + int n; + + while (1) { + n = read(in, buf, sizeof buf); + if (n == 0) + break; + if (n < 0) { + syslog(LOG_ERR, "read: %m"); + SlowDeath(); + } + if (write(out, buf, n) != n) { + syslog(LOG_ERR, "write: %m"); + SlowDeath(); + } + } +} + +static void +SlowDeath() +{ +#ifdef STANDALONE + sleep(pause_int); +#endif + exit(1); +} + +#ifdef doesnt_work_yet +unsigned long +get_data_checksum(fd, key_sched) + int fd; + Key_schedule key_sched; +{ + unsigned long cksum = 0; + unsigned long cbc_cksum(); + int n; + char buf[BUFSIZ]; + char obuf[8]; + + while (n = read(fd, buf, sizeof buf)) { + if (n < 0) { + syslog(LOG_ERR, "read (in checksum test): %m"); + SlowDeath(); + } +#ifndef NOENCRYPTION + cksum += cbc_cksum(buf, obuf, n, key_sched, key_sched); +#endif + } + return cksum; +} +#endif diff --git a/eBones/libexec/registerd/Makefile b/eBones/libexec/registerd/Makefile new file mode 100644 index 0000000000000..af9e2cab5ef7a --- /dev/null +++ b/eBones/libexec/registerd/Makefile @@ -0,0 +1,18 @@ +# +# Copyright (c) 1990 The Regents of the University of California. +# All rights reserved. +# +# %sccs.include.redist.sh +# +# @(#)Makefile 8.1 (Berkeley) 6/1/93 +# +# $Id: Makefile,v 1.4 1995/09/13 17:24:03 markm Exp $ + +PROG= registerd +SRCS= registerd.c +CFLAGS+=-DCRYPT -DKERBEROS -I${.CURDIR}/../../usr.bin/register +DPADD+= ${LIBKDB} ${LIBKRB} ${LIBDES} +LDADD= -lkdb -lkrb -ldes +MAN8= registerd.8 + +.include <bsd.prog.mk> diff --git a/eBones/libexec/registerd/registerd.c b/eBones/libexec/registerd/registerd.c new file mode 100644 index 0000000000000..36c7a742ac467 --- /dev/null +++ b/eBones/libexec/registerd/registerd.c @@ -0,0 +1,355 @@ +/*- + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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 above copyright + * notice, this list of conditions and the following disclaimer. + * 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 the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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. + */ + +#if 0 +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1990, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +static char sccsid[] = "@(#)registerd.c 8.1 (Berkeley) 6/1/93"; +#endif /* not lint */ +#endif + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/signal.h> +#include <sys/resource.h> +#include <sys/param.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <syslog.h> +#include <des.h> +#include <krb.h> +#include <krb_db.h> +#include <string.h> +#include <stdio.h> +#include <unistd.h> +#include "register_proto.h" +#include "pathnames.h" + +#define KBUFSIZ (sizeof(struct keyfile_data)) +#define RCRYPT 0x00 +#define CLEAR 0x01 + +char *progname, msgbuf[BUFSIZ]; + +void cleanup(void); +void die(int); +void send_packet(char *msg, int flag); +int net_get_principal(char *pname, char *iname, C_Block *keyp); +int do_append(struct sockaddr_in *sinp); + +void +main(argc, argv) + int argc; + char **argv; +{ + static Key_schedule schedule; + static struct rlimit rl = { 0, 0 }; + struct keyfile_data *kfile; + u_char code; + int kf, retval, sval; + struct sockaddr_in sin; + char keyfile[MAXPATHLEN], keybuf[KBUFSIZ]; + + progname = argv[0]; /* for the library routines */ + + openlog("registerd", LOG_PID, LOG_AUTH); + + signal(SIGHUP, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGTSTP, SIG_IGN); + signal(SIGPIPE, die); + + if (setrlimit(RLIMIT_CORE, &rl) < 0) { + syslog(LOG_ERR, "setrlimit: %m"); + exit(1); + } + + + /* figure out who we are talking to */ + + sval = sizeof(sin); + if (getpeername(0, (struct sockaddr *) &sin, &sval) < 0) { + syslog(LOG_ERR, "getpeername: %m"); + exit(1); + } + + /* get encryption key */ + + (void) sprintf(keyfile, "%s/%s%s", + SERVER_KEYDIR, + KEYFILE_BASE, + inet_ntoa(sin.sin_addr)); + + if ((kf = open(keyfile, O_RDONLY)) < 0) { + syslog(LOG_ERR, + "error opening Kerberos update keyfile (%s): %m", keyfile); + sprintf(msgbuf, + "couldn't open session keyfile for your host"); + send_packet(msgbuf, CLEAR); + exit(1); + } + + if (read(kf, keybuf, KBUFSIZ) != KBUFSIZ) { + syslog(LOG_ERR, "wrong read size of Kerberos update keyfile"); + sprintf(msgbuf, + "couldn't read session key from your host's keyfile"); + send_packet(msgbuf, CLEAR); + exit(1); + } + sprintf(msgbuf, GOTKEY_MSG); + send_packet(msgbuf, CLEAR); + kfile = (struct keyfile_data *) keybuf; + key_sched((C_Block *)kfile->kf_key, schedule); + des_set_key((des_cblock *)kfile->kf_key, schedule); + + /* read the command code byte */ + + if (des_read(0, &code, 1) == 1) { + + switch(code) { + case APPEND_DB: + retval = do_append(&sin); + break; + case ABORT: + cleanup(); + close(0); + exit(0); + default: + retval = KFAILURE; + syslog(LOG_NOTICE, + "invalid command code on db update (0x%x)", + code); + } + + } else { + retval = KFAILURE; + syslog(LOG_ERR, + "couldn't read command code on Kerberos update"); + } + + code = (u_char) retval; + if (code != KSUCCESS) { + sprintf(msgbuf, "%s", krb_err_txt[code]); + send_packet(msgbuf, RCRYPT); + } else { + sprintf(msgbuf, "Update complete."); + send_packet(msgbuf, RCRYPT); + } + cleanup(); + close(0); + exit(0); +} + +#define MAX_PRINCIPAL 10 +static Principal principal_data[MAX_PRINCIPAL]; +static C_Block key, master_key; +static Key_schedule master_key_schedule; + +int +do_append(sinp) + struct sockaddr_in *sinp; +{ + Principal default_princ; + char input_name[ANAME_SZ]; + char input_instance[INST_SZ]; + int j,n, more; + long mkeyversion; + + + + /* get master key from MKEYFILE */ + if (kdb_get_master_key(0, master_key, master_key_schedule) != 0) { + syslog(LOG_ERR, "couldn't get master key"); + return(KFAILURE); + } + + mkeyversion = kdb_verify_master_key(master_key, master_key_schedule, NULL); + if (mkeyversion < 0) { + syslog(LOG_ERR, "couldn't validate master key"); + return(KFAILURE); + } + + n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST, + &default_princ, 1, &more); + + if (n != 1) { + syslog(LOG_ERR, "couldn't get default principal"); + return(KFAILURE); + } + + /* + * get principal name, instance, and password from network. + * convert password to key and store it + */ + + if (net_get_principal(input_name, input_instance, (C_Block *)key) != 0) { + return(KFAILURE); + } + + + j = kerb_get_principal( + input_name, + input_instance, + principal_data, + MAX_PRINCIPAL, + &more + ); + + if (j != 0) { + /* already in database, no update */ + syslog(LOG_NOTICE, + "attempt to add duplicate entry for principal %s.%s", + input_name, input_instance); + return(KDC_PR_N_UNIQUE); + } + + /* + * set up principal's name, instance + */ + + strcpy(principal_data[0].name, input_name); + strcpy(principal_data[0].instance, input_instance); + principal_data[0].old = NULL; + + + /* and the expiration date and version #s */ + + principal_data[0].exp_date = default_princ.exp_date; + strcpy(principal_data[0].exp_date_txt, default_princ.exp_date_txt); + principal_data[0].max_life = default_princ.max_life; + principal_data[0].attributes = default_princ.attributes; + principal_data[0].kdc_key_ver = default_princ.kdc_key_ver; + + + /* and the key */ + + kdb_encrypt_key(key, key, master_key, master_key_schedule, + ENCRYPT); + bcopy(key, &principal_data[0].key_low, 4); + bcopy(((long *) key) + 1, &principal_data[0].key_high,4); + bzero(key, sizeof(key)); + + principal_data[0].key_version = 1; /* 1st entry */ + + /* and write it to the database */ + + if (kerb_put_principal(&principal_data[0], 1)) { + syslog(LOG_INFO, "Kerberos update failure: put_principal failed"); + return(KFAILURE); + } + + syslog(LOG_NOTICE, "Kerberos update: wrote new record for %s.%s from %s", + principal_data[0].name, + principal_data[0].instance, + inet_ntoa(sinp->sin_addr) + ); + + return(KSUCCESS); + +} + +void +send_packet(msg,flag) + char *msg; + int flag; +{ + int len = strlen(msg); + msg[len++] = '\n'; + msg[len] = '\0'; + if (len > sizeof(msgbuf)) { + syslog(LOG_ERR, "send_packet: invalid msg size"); + return; + } + if (flag == RCRYPT) { + if (des_write(0, msg, len) != len) + syslog(LOG_ERR, "couldn't write reply message"); + } else if (flag == CLEAR) { + if (write(0, msg, len) != len) + syslog(LOG_ERR, "couldn't write reply message"); + } else + syslog(LOG_ERR, "send_packet: invalid flag (%d)", flag); + +} + +int +net_get_principal(pname, iname, keyp) + char *pname, *iname; + C_Block *keyp; +{ + int cc; + static char password[255]; + + cc = des_read(0, pname, ANAME_SZ); + if (cc != ANAME_SZ) { + syslog(LOG_ERR, "couldn't get principal name"); + return(-1); + } + + cc = des_read(0, iname, INST_SZ); + if (cc != INST_SZ) { + syslog(LOG_ERR, "couldn't get instance name"); + return(-1); + } + + cc = des_read(0, password, 255); + if (cc != 255) { + syslog(LOG_ERR, "couldn't get password"); + bzero(password, 255); + return(-1); + } + + string_to_key(password, (des_cblock *)*keyp); + bzero(password, 255); + return(0); +} + +void +cleanup() +{ + bzero(master_key, sizeof(master_key)); + bzero(key, sizeof(key)); + bzero(master_key_schedule, sizeof(master_key_schedule)); +} + +void +die(sig) + int sig; +{ + syslog(LOG_ERR, "remote end died (SIGPIPE)"); + cleanup(); + exit(1); +} diff --git a/eBones/libexec/rkinitd/Makefile b/eBones/libexec/rkinitd/Makefile new file mode 100644 index 0000000000000..3872644163897 --- /dev/null +++ b/eBones/libexec/rkinitd/Makefile @@ -0,0 +1,12 @@ +# @(#)Makefile 8.1 (Berkeley) 6/4/93 + +PROG= rkinitd +SRCS= ${RKINITOBJDIR}/rkinit_err.h rkinitd.c util.c rpc.c krb.c +CFLAGS+=-I${KRBOBJDIR} -I${RKINITOBJDIR} +DPADD= ${LIBKRB} ${LIBDES} +LDADD= -L${RKINITOBJDIR} -lrkinit -L${KRBOBJDIR} -lkrb \ + -L${DESOBJDIR} -ldes + +MAN8= rkinitd.8 + +.include <bsd.prog.mk> diff --git a/eBones/libexec/rkinitd/krb.c b/eBones/libexec/rkinitd/krb.c new file mode 100644 index 0000000000000..23734db4307d4 --- /dev/null +++ b/eBones/libexec/rkinitd/krb.c @@ -0,0 +1,388 @@ +/* + * $Id: krb.c,v 1.1 1993/07/29 22:45:19 dglo Exp gibbs $ + * $Source: /usr/src/eBones/rkinitd/RCS/krb.c,v $ + * $Author: dglo $ + * + * This file contains all of the kerberos part of rkinitd. + */ + +#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS) +static char *rcsid = "$Id: krb.c,v 1.1 1993/07/29 22:45:19 dglo Exp gibbs $"; +#endif /* lint || SABER || LOCORE || RCS_HDRS */ + +#include <stdio.h> +#include <sys/types.h> +#include <errno.h> +#include <syslog.h> +#include <netinet/in.h> +#include <setjmp.h> +#include <string.h> +#include <unistd.h> +#include <pwd.h> +#include <krb.h> +#include <des.h> + +#include <rkinit.h> +#include <rkinit_private.h> +#include <rkinit_err.h> + +#include "rkinitd.h" + +#define FAILURE (!RKINIT_SUCCESS) + +extern int errno; + +static char errbuf[BUFSIZ]; + +typedef struct { + jmp_buf env; +} rkinitd_intkt_info; + + +#if defined(_AIX) && defined(_IBMR2) + +#include <sys/id.h> + +/* + * The RIOS has bizzarre ideas about changing uids around. They are + * such that the seteuid and setruid calls here fail. For this reason + * we are replacing the seteuid and setruid calls. + * + * The bizzarre ideas are as follows: + * + * The effective ID may be changed only to the current real or + * saved IDs. + * + * The saved uid may be set only if the real and effective + * uids are being set to the same value. + * + * The real uid may be set only if the effective + * uid is being set to the same value. + */ + +#ifdef __STDC__ +static int setruid(uid_t ruid) +#else +static int setruid(ruid) + uid_t ruid; +#endif /* __STDC__ */ +{ + uid_t euid; + + euid = geteuid(); + + if (setuidx(ID_REAL | ID_EFFECTIVE, ruid) == -1) + return (-1); + + return (setuidx(ID_EFFECTIVE, euid)); +} + + +#ifdef __STDC__ +static int seteuid(uid_t euid) +#else +static int seteuid(euid) + uid_t euid; +#endif /* __STDC__ */ +{ + uid_t ruid; + + ruid = getuid(); + + if (setuidx(ID_SAVED | ID_REAL | ID_EFFECTIVE, euid) == -1) + return (-1); + + return (setruid(ruid)); +} + + +#ifdef __STDC__ +static int setreuid(uid_t ruid, uid_t euid) +#else +static int setreuid(ruid, euid) + uid_t ruid; + uid_t euid; +#endif /* __STDC__ */ +{ + if (seteuid(euid) == -1) + return (-1); + + return (setruid(ruid)); +} + + +#ifdef __STDC__ +static int setuid(uid_t uid) +#else +static int setuid(uid) + uid_t uid; +#endif /* __STDC__ */ +{ + return (setreuid(uid, uid)); +} + +#endif /* RIOS */ + + +#ifdef __STDC__ +static void this_phost(char *host, int hostlen) +#else +static void this_phost(host, hostlen) + char *host; + int hostlen; +#endif /* __STDC__ */ +{ + char this_host[MAXHOSTNAMELEN + 1]; + + BCLEAR(this_host); + + if (gethostname(this_host, sizeof(this_host)) < 0) { + sprintf(errbuf, "gethostname: %s", sys_errlist[errno]); + rkinit_errmsg(errbuf); + error(); + exit(1); + } + + strncpy(host, krb_get_phost(this_host), hostlen - 1); +} + +#ifdef __STDC__ +static int decrypt_tkt(char *user, char *instance, char *realm, char *arg, + int (*key_proc)(), KTEXT *cipp) +#else +static int decrypt_tkt(user, instance, realm, arg, key_proc, cipp) + char *user; + char *instance; + char *realm; + char *arg; + int (*key_proc)(); + KTEXT *cipp; +#endif /* __STDC__ */ +{ + MSG_DAT msg_data; /* Message data containing decrypted data */ + KTEXT_ST auth; /* Authenticator */ + AUTH_DAT auth_dat; /* Authentication data */ + KTEXT cip = *cipp; + MSG_DAT scip; + int status = 0; + des_cblock key; + des_key_schedule sched; + char phost[MAXHOSTNAMELEN + 1]; + struct sockaddr_in caddr; /* client internet address */ + struct sockaddr_in saddr; /* server internet address */ + + rkinitd_intkt_info *rii = (rkinitd_intkt_info *)arg; + + u_char enc_data[MAX_KTXT_LEN]; + + SBCLEAR(auth); + SBCLEAR(auth_dat); + SBCLEAR(scip); + BCLEAR(enc_data); + + scip.app_data = enc_data; + + /* + * Exchange with the client our response from the KDC (ticket encrypted + * in user's private key) for the same ticket encrypted in our + * (not yet known) session key. + */ + + rpc_exchange_tkt(cip, &scip); + + /* + * Get the authenticator + */ + + SBCLEAR(auth); + + rpc_getauth(&auth, &caddr, &saddr); + + /* + * Decode authenticator and extract session key. The first zero + * means we don't care what host this comes from. This needs to + * be done with euid of root so that /etc/srvtab can be read. + */ + + BCLEAR(phost); + this_phost(phost, sizeof(phost)); + + /* + * This function has to use longjmp to return to the caller + * because the kerberos library routine that calls it doesn't + * pay attention to the return value it gives. That means that + * if any of these routines failed, the error returned to the client + * would be "password incorrect". + */ + + if ((status = krb_rd_req(&auth, KEY, phost, caddr.sin_addr.s_addr, + &auth_dat, KEYFILE))) { + sprintf(errbuf, "krb_rd_req: %s", krb_err_txt[status]); + rkinit_errmsg(errbuf); + longjmp(rii->env, status); + } + + bcopy(auth_dat.session, key, sizeof(key)); + if (des_key_sched(&key, sched)) { + sprintf(errbuf, "Error in des_key_sched"); + rkinit_errmsg(errbuf); + longjmp(rii->env, RKINIT_DES); + } + + /* Decrypt the data. */ + if ((status = + krb_rd_priv((u_char *)scip.app_data, scip.app_length, + sched, key, &caddr, &saddr, &msg_data)) == KSUCCESS) { + cip->length = msg_data.app_length; + bcopy(msg_data.app_data, cip->dat, msg_data.app_length); + cip->dat[cip->length] = 0; + } + else { + sprintf(errbuf, "krb_rd_priv: %s", krb_err_txt[status]); + rkinit_errmsg(errbuf); + longjmp(rii->env, status); + } + + return(status); +} + +#ifdef __STDC__ +static int validate_user(char *aname, char *inst, char *realm, + char *username, char *errmsg) +#else +static int validate_user(aname, inst, realm, username, errmsg) + char *aname; + char *inst; + char *realm; + char *username; + char *errmsg; +#endif /* __STDC__ */ +{ + struct passwd *pwnam; /* For access_check and uid */ + AUTH_DAT auth_dat; + int kstatus = KSUCCESS; + + SBCLEAR(auth_dat); + + if ((pwnam = getpwnam(username)) == NULL) { + sprintf(errmsg, "%s does not exist on the remote host.", username); + return(FAILURE); + } + + strcpy(auth_dat.pname, aname); + strcpy(auth_dat.pinst, inst); + strcpy(auth_dat.prealm, realm); + + if (seteuid(pwnam->pw_uid) < 0) { + sprintf(errmsg, "Failure setting euid to %d: %s\n", pwnam->pw_uid, + sys_errlist[errno]); + strcpy(errbuf, errmsg); + error(); + return(FAILURE); + } + kstatus = kuserok(&auth_dat, username); + if (seteuid(0) < 0) { + sprintf(errmsg, "Failure setting euid to 0: %s\n", + sys_errlist[errno]); + strcpy(errbuf, errmsg); + error(); + return(FAILURE); + } + + if (kstatus != KSUCCESS) { + sprintf(errmsg, "%s has not allowed you to log in with", username); + if (strlen(auth_dat.pinst)) + sprintf(errmsg, "%s %s.%s", errmsg, auth_dat.pname, + auth_dat.pinst); + else + sprintf(errmsg, "%s %s", errmsg, auth_dat.pname); + sprintf(errmsg, "%s@%s tickets.", errmsg, auth_dat.prealm); + return(FAILURE); + } + + /* + * Set real uid to owner of ticket file. The library takes care + * of making the appropriate change. + */ + if (setruid(pwnam->pw_uid) < 0) { + sprintf(errmsg, "Failure setting ruid to %d: %s\n", pwnam->pw_uid, + sys_errlist[errno]); + strcpy(errbuf, errmsg); + error(); + return(FAILURE); + } + + return(RKINIT_SUCCESS); +} + +#ifdef __STDC__ +int get_tickets(int version) +#else +int get_tickets(version) + int version; +#endif /* __STDC__ */ +{ + rkinit_info info; + AUTH_DAT auth_dat; + + int status; + char errmsg[BUFSIZ]; /* error message for client */ + + rkinitd_intkt_info rii; + + SBCLEAR(info); + SBCLEAR(auth_dat); + BCLEAR(errmsg); + SBCLEAR(rii); + + rpc_get_rkinit_info(&info); + + /* + * The validate_user routine makes sure that the principal in question + * is allowed to log in as username, and if so, does a setuid(localuid). + * If there is an access violation or an error in setting the uid, + * an error is returned and the string errmsg is initialized with + * an error message that will be sent back to the client. + */ + if ((status = validate_user(info.aname, info.inst, info.realm, + info.username, errmsg)) != RKINIT_SUCCESS) { + rpc_send_error(errmsg); + exit(0); + } + else + rpc_send_success(); + + /* + * If the name of a ticket file was specified, set it; otherwise, + * just use the default. + */ + if (strlen(info.tktfilename)) + krb_set_tkt_string(info.tktfilename); + + /* + * Call internal kerberos library routine so that we can supply + * our own ticket decryption routine. + */ + + /* + * We need a setjmp here because krb_get_in_tkt ignores the + * return value of decrypt_tkt. Thus if we want any of its + * return values to reach the client, we have to jump out of + * the routine. + */ + + if (setjmp(rii.env) == 0) { + if ((status = krb_get_in_tkt(info.aname, info.inst, info.realm, + info.sname, info.sinst, info.lifetime, + NULL, decrypt_tkt, (char *)&rii))) { + strcpy(errmsg, krb_err_txt[status]); + rpc_send_error(errmsg); + } + else + rpc_send_success(); + } + else + rpc_send_error(errbuf); + + return(RKINIT_SUCCESS); +} diff --git a/eBones/libexec/rkinitd/rkinitd.8 b/eBones/libexec/rkinitd/rkinitd.8 new file mode 100644 index 0000000000000..cce921e90866f --- /dev/null +++ b/eBones/libexec/rkinitd/rkinitd.8 @@ -0,0 +1,42 @@ +.\" +.\" $Header: /local/cvsfiles/kerberos/src/appl/rkinit/man/rkinitd.8,v 1.1 1991/12/03 23:21:32 eichin Exp $ +.\" $Source: /local/cvsfiles/kerberos/src/appl/rkinit/man/rkinitd.8,v $ +.\" $Author: eichin $ +.\" +.\" +.TH RKINITD 8 "November 12, 1989" +.UC 4 +.SH NAME +rkinitd \- server for +.I rkinit, +a remote kerberos ticket establishment utility +.SH SYNOPSIS +.B rkinitd +.SH DESCRIPTION +.I rkinitd +is the server for +.I rkinit. +See +.IR rkinit (1) +for information about +.I rkinit. +.I rkinitd +is started from inetd and must be run as root or be installed +setuid(root) as it needs to be able to read /etc/athena/srvtab and +change its uid to create tickets. + +.I rkinitd +times out in 60 seconds if the transaction is not completed. + +.I rkinitd +must be running on a machine that is registered for rlogin +service; that is, the host must have a srvtab containing an rcmd.<host> +key where <host> is the value returned by the +.IR krb_get_phost (3) +kerberos library call. + +.SH SEE ALSO +rkinit(1), inetd(8), kerberos(1), kerberos(3) + +.SH AUTHOR +Emanuel Jay Berkenbilt (MIT-Project Athena) diff --git a/eBones/libexec/rkinitd/rkinitd.c b/eBones/libexec/rkinitd/rkinitd.c new file mode 100644 index 0000000000000..724414977c24f --- /dev/null +++ b/eBones/libexec/rkinitd/rkinitd.c @@ -0,0 +1,137 @@ +/* + * $Id: rkinitd.c,v 1.1 1993/12/10 18:54:19 dglo Exp gibbs $ + * $Source: /usr/src/eBones/rkinitd/RCS/rkinitd.c,v $ + * $Author: dglo $ + * + * This is the main source file for rkinit + */ + +#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS) +static char *rcsid = "$Id: rkinitd.c,v 1.1 1993/12/10 18:54:19 dglo Exp gibbs $"; +#endif /* lint || SABER || LOCORE || RCS_HDRS */ + +#include <stdio.h> +#include <ctype.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <strings.h> +#include <signal.h> +#include <sys/time.h> +#include <pwd.h> +#include <unistd.h> +#include <krb.h> +#include <des.h> +#include <syslog.h> + +#include <rkinit.h> +#include <rkinit_err.h> +#include <rkinit_private.h> + +#include "rkinitd.h" + +extern int errno; + +static int inetd = TRUE; /* True if we were started by inetd */ + +#ifdef __STDC__ +static void usage(void) +#else +static void usage() +#endif /* __STDC__ */ +{ + syslog(LOG_ERR, "rkinitd usage: rkinitd [-notimeout]\n"); + exit(1); +} + +#ifdef __STDC__ +void error(void) +#else +void error() +#endif /* __STDC__ */ +{ + char errbuf[BUFSIZ]; + + strcpy(errbuf, rkinit_errmsg(0)); + if (strlen(errbuf)) { + if (inetd) + syslog(LOG_ERR, "rkinitd: %s", errbuf); + else + fprintf(stderr, "rkinitd: %s\n", errbuf); + } +} + +int +#ifdef __STDC__ +main(int argc, char *argv[]) +#else +main(argc, argv) + int argc; + char *argv[]; +#endif /* __STDC__ */ +{ + int version; /* Version of the transaction */ + + int notimeout = FALSE; /* Should we not timeout? */ + + static char *envinit[1]; /* Empty environment */ + extern char **environ; /* This process's environment */ + + int status = 0; /* General error code */ + + /* + * Clear the environment so that this process does not inherit + * kerberos ticket variable information from the person who started + * the process (if a person started it...). + */ + environ = envinit; + + /* Initialize com_err error table */ + init_rkin_err_tbl(); + +#ifdef DEBUG + /* This only works if the library was compiled with DEBUG defined */ + rki_i_am_server(); +#endif /* DEBUG */ + + /* + * Make sure that we are running as root or can arrange to be + * running as root. We need both to be able to read /etc/srvtab + * and to be able to change uid to create tickets. + */ + + (void) setuid(0); + if (getuid() != 0) { + syslog(LOG_ERR, "rkinitd: not running as root.\n"); + exit(1); + } + + /* Determine whether to time out */ + if (argc == 2) { + if (strcmp(argv[1], "-notimeout")) + usage(); + else + notimeout = TRUE; + } + else if (argc != 1) + usage(); + + inetd = setup_rpc(notimeout); + + if ((status = choose_version(&version) != RKINIT_SUCCESS)) { + error(); + exit(1); + } + + if ((status = get_tickets(version) != RKINIT_SUCCESS)) { + error(); + exit(1); + } + + exit(0); +} + + diff --git a/eBones/libexec/rkinitd/rkinitd.h b/eBones/libexec/rkinitd/rkinitd.h new file mode 100644 index 0000000000000..1a65cba24ae36 --- /dev/null +++ b/eBones/libexec/rkinitd/rkinitd.h @@ -0,0 +1,34 @@ +/* + * $Id: rkinitd.h,v 1.1 1993/12/10 19:02:10 dglo Exp gibbs $ + * $Source: /usr/src/eBones/rkinitd/RCS/rkinitd.h,v $ + * $Author: dglo $ + * + * This header file contains function declarations for use for rkinitd + */ + +#ifndef __RKINITD_H__ +#define __RKINITD_H__ + +#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS) +static char *rcsid_rkinitd_h = "$Id: rkinitd.h,v 1.1 1993/12/10 19:02:10 dglo Exp gibbs $"; +#endif /* lint || SABER || LOCORE || RCS_HDRS */ + +#ifdef __STDC__ +#define RK_PROTO(x) x +#else +#define RK_PROTO(x) () +#endif /* __STDC__ */ + +int get_tickets RK_PROTO((int)); +void error RK_PROTO((void)); +int setup_rpc RK_PROTO((int)) ; +void rpc_exchange_version_info RK_PROTO((int *, int *, int, int)); +void rpc_get_rkinit_info RK_PROTO((rkinit_info *)); +void rpc_send_error RK_PROTO((char *)); +void rpc_send_success RK_PROTO((void)); +void rpc_exchange_tkt RK_PROTO((KTEXT, MSG_DAT *)); +void rpc_getauth RK_PROTO((KTEXT, struct sockaddr_in *, struct sockaddr_in *)); +int choose_version RK_PROTO((int *)); + + +#endif /* __RKINITD_H__ */ diff --git a/eBones/libexec/rkinitd/rpc.c b/eBones/libexec/rkinitd/rpc.c new file mode 100644 index 0000000000000..97d4f9f85c4e4 --- /dev/null +++ b/eBones/libexec/rkinitd/rpc.c @@ -0,0 +1,222 @@ +/* + * $Id: rpc.c,v 1.1 1993/12/10 18:59:29 dglo Exp gibbs $ + * $Source: /usr/src/eBones/rkinitd/RCS/rpc.c,v $ + * $Author: dglo $ + * + * This file contains the network parts of the rkinit server. + */ + +#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS) +static char *rcsid = "$Id: rpc.c,v 1.1 1993/12/10 18:59:29 dglo Exp gibbs $"; +#endif /* lint || SABER || LOCORE || RCS_HDRS */ + +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <syslog.h> +#include <signal.h> +#include <errno.h> +#include <string.h> + +#include <rkinit.h> +#include <rkinit_err.h> +#include <rkinit_private.h> + +#include "rkinitd.h" + +#define RKINITD_TIMEOUT 60 + +extern int errno; + +static int in; /* sockets */ +static int out; + +static char errbuf[BUFSIZ]; + +void error(); + +#ifdef __STDC__ +static void timeout(int signal) +#else +static void timeout(signal) + int signal; +#endif /* __STDC__ */ +{ + syslog(LOG_WARNING, "rkinitd timed out.\n"); + exit(1); + + return; +} + +/* + * This function does all the network setup for rkinitd. + * It returns true if we were started from inetd, or false if + * we were started from the commandline. + * It causes the program to exit if there is an error. + */ +#ifdef __STDC__ +int setup_rpc(int notimeout) +#else +int setup_rpc(notimeout) + int notimeout; /* True if we should not timeout */ +#endif /* __STDC__ */ +{ + struct itimerval timer; /* Time structure for timeout */ + + /* For now, support only inetd. */ + in = 0; + out = 1; + + if (! notimeout) { + SBCLEAR(timer); + + /* Set up an itimer structure to send an alarm signal after timeout + seconds. */ + timer.it_interval.tv_sec = RKINITD_TIMEOUT; + timer.it_interval.tv_usec = 0; + timer.it_value = timer.it_interval; + + /* Start the timer. */ + if (setitimer (ITIMER_REAL, &timer, (struct itimerval *)0) < 0) { + sprintf(errbuf, "setitimer: %s", sys_errlist[errno]); + rkinit_errmsg(errbuf); + error(); + exit(1); + } + + signal(SIGALRM, timeout); + } + + return(TRUE); +} + +#ifdef __STDC__ +void rpc_exchange_version_info(int *c_lversion, int *c_hversion, + int s_lversion, int s_hversion) +#else +void rpc_exchange_version_info(c_lversion, c_hversion, s_lversion, s_hversion) + int *c_lversion; + int *c_hversion; + int s_lversion; + int s_hversion; +#endif /* __STDC__ */ +{ + u_char version_info[VERSION_INFO_SIZE]; + u_int32_t length = sizeof(version_info); + + if (rki_get_packet(in, MT_CVERSION, &length, (char *)version_info) != + RKINIT_SUCCESS) { + error(); + exit(1); + } + + *c_lversion = version_info[0]; + *c_hversion = version_info[1]; + + version_info[0] = s_lversion; + version_info[1] = s_hversion; + + if (rki_send_packet(out, MT_SVERSION, length, (char *)version_info) != + RKINIT_SUCCESS) { + error(); + exit(1); + } +} + +#ifdef __STDC__ +void rpc_get_rkinit_info(rkinit_info *info) +#else +void rpc_get_rkinit_info(info) + rkinit_info *info; +#endif /* __STDC__ */ +{ + u_int32_t length = sizeof(rkinit_info); + + if (rki_get_packet(in, MT_RKINIT_INFO, &length, (char *)info)) { + error(); + exit(1); + } + + info->lifetime = ntohl(info->lifetime); +} + +#ifdef __STDC__ +void rpc_send_error(char *errmsg) +#else +void rpc_send_error(errmsg) + char *errmsg; +#endif /* __STDC__ */ +{ + if (rki_send_packet(out, MT_STATUS, strlen(errmsg), errmsg)) { + error(); + exit(1); + } +} + +#ifdef __STDC__ +void rpc_send_success(void) +#else +void rpc_send_success() +#endif /* __STDC__ */ +{ + if (rki_send_packet(out, MT_STATUS, 0, "")) { + error(); + exit(1); + } +} + +#ifdef __STDC__ +void rpc_exchange_tkt(KTEXT cip, MSG_DAT *scip) +#else +void rpc_exchange_tkt(cip, scip) + KTEXT cip; + MSG_DAT *scip; +#endif /* __STDC__ */ +{ + u_int32_t length = MAX_KTXT_LEN; + + if (rki_send_packet(out, MT_SKDC, cip->length, (char *)cip->dat)) { + error(); + exit(1); + } + + if (rki_get_packet(in, MT_CKDC, &length, (char *)scip->app_data)) { + error(); + exit(1); + } + scip->app_length = length; +} + +#ifdef __STDC__ +void rpc_getauth(KTEXT auth, struct sockaddr_in *caddr, + struct sockaddr_in *saddr) +#else +void rpc_getauth(auth, caddr, saddr) + KTEXT auth; + struct sockaddr_in *caddr; + struct sockaddr_in *saddr; +#endif /* __STDC__ */ +{ + int addrlen = sizeof(struct sockaddr_in); + + if (rki_rpc_get_ktext(in, auth, MT_AUTH)) { + error(); + exit(1); + } + + if (getpeername(in, (struct sockaddr *)caddr, &addrlen) < 0) { + sprintf(errbuf, "getpeername: %s", sys_errlist[errno]); + rkinit_errmsg(errbuf); + error(); + exit(1); + } + + if (getsockname(out, (struct sockaddr *)saddr, &addrlen) < 0) { + sprintf(errbuf, "getsockname: %s", sys_errlist[errno]); + rkinit_errmsg(errbuf); + error(); + exit(1); + } +} diff --git a/eBones/libexec/rkinitd/util.c b/eBones/libexec/rkinitd/util.c new file mode 100644 index 0000000000000..20812051dc48f --- /dev/null +++ b/eBones/libexec/rkinitd/util.c @@ -0,0 +1,49 @@ +/* + * $Id: util.c,v 1.1 1993/12/10 18:59:29 dglo Exp gibbs $ + * $Source: /usr/src/eBones/rkinitd/RCS/util.c,v $ + * $Author: dglo $ + * + * This file contains general rkinit server utilities. + */ + +#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS) +static char *rcsid = "$Id: util.c,v 1.1 1993/12/10 18:59:29 dglo Exp gibbs $"; +#endif /* lint || SABER || LOCORE || RCS_HDRS */ + +#include <stdio.h> +#include <rkinit.h> +#include <rkinit_err.h> +#include <rkinit_private.h> + +#include "rkinitd.h" + +static char errbuf[BUFSIZ]; + +void rpc_exchange_version_info(); +void error(); + +#ifdef __STDC__ +int choose_version(int *version) +#else +int choose_version(version) + int *version; +#endif /* __STDC__ */ +{ + int c_lversion; /* lowest version number client supports */ + int c_hversion; /* highest version number client supports */ + int status = RKINIT_SUCCESS; + + rpc_exchange_version_info(&c_lversion, &c_hversion, + RKINIT_LVERSION, RKINIT_HVERSION); + + *version = min(RKINIT_HVERSION, c_hversion); + if (*version < max(RKINIT_LVERSION, c_lversion)) { + sprintf(errbuf, + "Can't run version %d client against version %d server.", + c_hversion, RKINIT_HVERSION); + rkinit_errmsg(errbuf); + return(RKINIT_VERSION); + } + + return(status); +} diff --git a/eBones/man/Makefile b/eBones/man/Makefile new file mode 100644 index 0000000000000..526ca8ef76de4 --- /dev/null +++ b/eBones/man/Makefile @@ -0,0 +1,10 @@ +# from: @(#)Makefile 5.4 (Berkeley) 7/25/90 +# $Id: Makefile,v 1.3 1995/07/18 16:40:32 mark Exp $ + +MAN1= kerberos.1 +MAN3= des_crypt.3 +MAN5= krb.conf.5 krb.realms.5 + +MLINKS+=des_crypt.3 des.3 + +.include <bsd.prog.mk> diff --git a/eBones/usr.bin/Makefile b/eBones/usr.bin/Makefile new file mode 100644 index 0000000000000..fa796caeb8f59 --- /dev/null +++ b/eBones/usr.bin/Makefile @@ -0,0 +1,6 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.1 1995/09/13 17:24:05 markm Exp $ + +SUBDIR= kadmin kdestroy kinit klist ksrvtgt register rkinit + +.include <bsd.subdir.mk> diff --git a/eBones/usr.bin/Makefile.inc b/eBones/usr.bin/Makefile.inc new file mode 100644 index 0000000000000..5506596ac57e0 --- /dev/null +++ b/eBones/usr.bin/Makefile.inc @@ -0,0 +1,5 @@ +# @(#)Makefile.inc 8.1 (Berkeley) 6/6/93 + +BINDIR?= /usr/bin + +.include "../Makefile.inc" diff --git a/eBones/usr.bin/kadmin/Makefile b/eBones/usr.bin/kadmin/Makefile new file mode 100644 index 0000000000000..7660270bb3c41 --- /dev/null +++ b/eBones/usr.bin/kadmin/Makefile @@ -0,0 +1,16 @@ +# $Id: Makefile,v 1.6 1995/09/14 04:05:59 gibbs Exp $ + +PROG= kadmin +SRCS= ${KRBOBJDIR}/krb_err.h kadmin.c kadmin_cmds.c +CLEANFILES+= kadmin_cmds.c krb_err.c +CFLAGS+= -DPOSIX -I${.CURDIR}/../../lib/libkadm +DPADD= ${LIBKRB} ${LIBDES} +LDADD+= -lkadm -lkrb -ldes +LDADD+= -lss -lcom_err +MAN8= kadmin.8 + +kadmin_cmds.c: kadmin_cmds.ct + test -e kadmin_cmds.ct || ln -s ${.CURDIR}/kadmin_cmds.ct . + mk_cmds kadmin_cmds.ct + +.include <bsd.prog.mk> diff --git a/eBones/usr.bin/kadmin/kadmin.c b/eBones/usr.bin/kadmin/kadmin.c new file mode 100644 index 0000000000000..67e0e1fb2b41c --- /dev/null +++ b/eBones/usr.bin/kadmin/kadmin.c @@ -0,0 +1,636 @@ +/* + * $Source: /usr/cvs/src/eBones/kadmin/kadmin.c,v $ + * $Author: mark $ + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Kerberos database administrator's tool. + * + * The default behavior of kadmin is if the -m option is given + * on the commandline, multiple requests are allowed to be given + * with one entry of the admin password (until the tickets expire). + * If you do not want this to be an available option, compile with + * NO_MULTIPLE defined. + */ + +#if 0 +#ifndef lint +static char rcsid_kadmin_c[] = +"BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadmin.c,v 4.5 89/09/26 14:17:54 qjb Exp "; +#endif lint +#endif + +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <sys/param.h> +#include <pwd.h> +#include <ss/ss.h> +#include <com_err.h> +#include <kerberosIV/krb_err.h> +#include <kadm.h> + +#define BAD_PW 1 +#define GOOD_PW 0 +#define FUDGE_VALUE 15 /* for ticket expiration time */ +#define PE_NO 0 +#define PE_YES 1 +#define PE_UNSURE 2 + +/* for get_password, whether it should do the swapping...necessary for + using vals structure, unnecessary for change_pw requests */ +#define DONTSWAP 0 +#define SWAP 1 + +static void do_init(int argc, char *argv[]); +void clean_up(void); +int get_password(unsigned long *low, unsigned long *high, char *prompt, + int byteswap); +int get_admin_password(void); +int princ_exists(char *name, char *instance, char *realm); + +extern ss_request_table admin_cmds; + +static char myname[ANAME_SZ]; +static char default_realm[REALM_SZ]; /* default kerberos realm */ +static char krbrlm[REALM_SZ]; /* current realm being administered */ +#ifndef NO_MULTIPLE +static int multiple = 0; /* Allow multiple requests per ticket */ +#endif + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int sci_idx; + int code; + char tktstring[MAXPATHLEN]; + + void quit(); + + sci_idx = ss_create_invocation("admin", "2.0", (char *) NULL, + &admin_cmds, &code); + if (code) { + ss_perror(sci_idx, code, "creating invocation"); + exit(1); + } + (void) sprintf(tktstring, "/tmp/tkt_adm_%d",getpid()); + krb_set_tkt_string(tktstring); + + do_init(argc, argv); + + printf("Welcome to the Kerberos Administration Program, version 2\n"); + printf("Type \"help\" if you need it.\n"); + ss_listen(sci_idx, &code); + printf("\n"); + quit(); + exit(0); +} + +int +setvals(vals, string) + Kadm_vals *vals; + char *string; +{ + char realm[REALM_SZ]; + int status = KADM_SUCCESS; + + bzero(vals, sizeof(*vals)); + bzero(realm, sizeof(realm)); + + SET_FIELD(KADM_NAME,vals->fields); + SET_FIELD(KADM_INST,vals->fields); + if ((status = kname_parse(vals->name, vals->instance, realm, string))) { + printf("kerberos error: %s\n", krb_err_txt[status]); + return status; + } + if (!realm[0]) + strcpy(realm, default_realm); + if (strcmp(realm, krbrlm)) { + strcpy(krbrlm, realm); + if ((status = kadm_init_link(PWSERV_NAME, KRB_MASTER, krbrlm)) + != KADM_SUCCESS) + printf("kadm error for realm %s: %s\n", + krbrlm, error_message(status)); + } + if (status) + return 1; + else + return KADM_SUCCESS; +} + +void +change_password(argc, argv) + int argc; + char *argv[]; +{ + Kadm_vals old, new; + int status; + char pw_prompt[BUFSIZ]; + + if (argc != 2) { + printf("Usage: change_password loginname\n"); + return; + } + + if (setvals(&old, argv[1]) != KADM_SUCCESS) + return; + + new = old; + + SET_FIELD(KADM_DESKEY,new.fields); + + if (princ_exists(old.name, old.instance, krbrlm) != PE_NO) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + /* get the new password */ + (void) sprintf(pw_prompt, "New password for %s:", argv[1]); + + if (get_password(&new.key_low, &new.key_high, + pw_prompt, SWAP) == GOOD_PW) { + status = kadm_mod(&old, &new); + if (status == KADM_SUCCESS) { + printf("Password changed for %s.\n", argv[1]); + } else { + printf("kadmin: %s\nwhile changing password for %s", + error_message(status), argv[1]); + } + } else + printf("Error reading password; password unchanged\n"); + bzero((char *)&new, sizeof(new)); +#ifndef NO_MULTIPLE + if (!multiple) + clean_up(); +#endif + } + else + printf("kadmin: Principal does not exist.\n"); + return; +} + +/*ARGSUSED*/ +void +change_admin_password(argc, argv) + int argc; + char *argv[]; +{ + des_cblock newkey; + unsigned long low, high; + int status; + char prompt_pw[BUFSIZ]; + + if (argc != 1) { + printf("Usage: change_admin_password\n"); + return; + } + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + (void) sprintf(prompt_pw, "New password for %s.admin:",myname); + if (get_password(&low, &high, prompt_pw, DONTSWAP) == GOOD_PW) { + bcopy((char *)&low,(char *) newkey,4); + bcopy((char *)&high, (char *)(((long *) newkey) + 1),4); + low = high = 0L; + if ((status = kadm_change_pw(newkey)) == KADM_SUCCESS) + printf("Admin password changed\n"); + else + printf("kadm error: %s\n",error_message(status)); + bzero((char *)newkey, sizeof(newkey)); + } else + printf("Error reading password; password unchanged\n"); +#ifndef NO_MULTIPLE + if (!multiple) + clean_up(); +#endif + return; +} + +void +add_new_key(argc, argv) + int argc; + char *argv[]; +{ + Kadm_vals new; + char pw_prompt[BUFSIZ]; + int status; + + if (argc != 2) { + printf("Usage: add_new_key user_name.\n"); + return; + } + if (setvals(&new, argv[1]) != KADM_SUCCESS) + return; + + SET_FIELD(KADM_DESKEY,new.fields); + + if (princ_exists(new.name, new.instance, krbrlm) != PE_YES) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + /* get the new password */ + (void) sprintf(pw_prompt, "Password for %s:", argv[1]); + + if (get_password(&new.key_low, &new.key_high, + pw_prompt, SWAP) == GOOD_PW) { + status = kadm_add(&new); + if (status == KADM_SUCCESS) { + printf("%s added to database.\n", argv[1]); + } else { + printf("kadm error: %s\n",error_message(status)); + } + } else + printf("Error reading password; %s not added\n",argv[1]); + bzero((char *)&new, sizeof(new)); +#ifndef NO_MULTIPLE + if (!multiple) + clean_up(); +#endif + } + else + printf("kadmin: Principal already exists.\n"); + return; +} + +void +get_entry(argc, argv) + int argc; + char *argv[]; +{ + int status; + u_char fields[4]; + Kadm_vals vals; + + if (argc != 2) { + printf("Usage: get_entry username\n"); + return; + } + + bzero(fields, sizeof(fields)); + + SET_FIELD(KADM_NAME,fields); + SET_FIELD(KADM_INST,fields); + SET_FIELD(KADM_EXPDATE,fields); + SET_FIELD(KADM_ATTR,fields); + SET_FIELD(KADM_MAXLIFE,fields); + + if (setvals(&vals, argv[1]) != KADM_SUCCESS) + return; + + + if (princ_exists(vals.name, vals.instance, krbrlm) != PE_NO) { + /* get the admin's password */ + if (get_admin_password() != GOOD_PW) + return; + + if ((status = kadm_get(&vals, fields)) == KADM_SUCCESS) + prin_vals(&vals); + else + printf("kadm error: %s\n",error_message(status)); + +#ifndef NO_MULTIPLE + if (!multiple) + clean_up(); +#endif + } + else + printf("kadmin: Principal does not exist.\n"); + return; +} + + +void +help(argc, argv) + int argc; + char *argv[]; +{ + if (argc == 1) { + printf("Welcome to the Kerberos administration program."); + printf("Type \"?\" to get\n"); + printf("a list of requests that are available. You can"); + printf(" get help on each of\n"); + printf("the commands by typing \"help command_name\"."); + printf(" Some functions of this\n"); + printf("program will require an \"admin\" password"); + printf(" from you. This is a password\n"); + printf("private to you, that is used to authenticate"); + printf(" requests from this\n"); + printf("program. You can change this password with"); + printf(" the \"change_admin_password\"\n"); + printf("(or short form \"cap\") command. Good Luck! \n"); + } else if (!strcmp(argv[1], "change_password") || + !strcmp(argv[1], "cpw")) { + printf("Usage: change_password user_name.\n"); + printf("\n"); + printf("user_name is the name of the user whose password"); + printf(" you wish to change. \n"); + printf("His/her password is changed in the kerberos database\n"); + printf("When this command is issued, first the \"Admin\""); + printf(" password will be prompted\n"); + printf("for and if correct the user's new password will"); + printf(" be prompted for (twice with\n"); + printf("appropriate comparison). Note: No minimum password"); + printf(" length restrictions apply, but\n"); + printf("longer passwords are more secure.\n"); + } else if (!strcmp(argv[1], "change_admin_password") || + !strcmp(argv[1], "cap")) { + printf("Usage: change_admin_password.\n"); + printf("\n"); + printf("This command takes no arguments and is used"); + printf(" to change your private\n"); + printf("\"Admin\" password. It will first prompt for"); + printf(" the (current) \"Admin\"\n"); + printf("password and then ask for the new password"); + printf(" by prompting:\n"); + printf("\n"); + printf("New password for <Your User Name>.admin:\n"); + printf("\n"); + printf("Enter the new admin password that you desire"); + printf(" (it will be asked for\n"); + printf("twice to avoid errors).\n"); + } else if (!strcmp(argv[1], "add_new_key") || + !strcmp(argv[1], "ank")) { + printf("Usage: add_new_key user_name.\n"); + printf("\n"); + printf("user_name is the name of a new user to put"); + printf(" in the kerberos database. Your\n"); + printf("\"Admin\" password and the user's password"); + printf(" are prompted for. The user's\n"); + printf("password will be asked for"); + printf(" twice to avoid errors.\n"); + } else if (!strcmp(argv[1], "get_entry") || + !strcmp(argv[1], "get")) { + printf("Usage: get_entry user_name.\n"); + printf("\n"); + printf("user_name is the name of a user whose"); + printf(" entry you wish to review. Your\n"); + printf("\"Admin\" password is prompted for. "); + printf(" The key field is not filled in, for\n"); + printf("security reasons.\n"); + } else if (!strcmp(argv[1], "destroy_tickets") || + !strcmp(argv[1], "dest")) { + printf("Usage: destroy_tickets\n"); + printf("\n"); + printf("Destroy your admin tickets. This will"); + printf(" cause you to be prompted for your\n"); + printf("admin password on your next request.\n"); + } else if (!strcmp(argv[1], "list_requests") || + !strcmp(argv[1], "lr") || + !strcmp(argv[1], "?")) { + printf("Usage: list_requests\n"); + printf("\n"); + printf("This command lists what other commands are"); + printf(" currently available.\n"); + } else if (!strcmp(argv[1], "exit") || + !strcmp(argv[1], "quit") || + !strcmp(argv[1], "q")) { + printf("Usage: quit\n"); + printf("\n"); + printf("This command exits this program.\n"); + } else { + printf("Sorry there is no such command as %s.", argv[1]); + printf(" Type \"help\" for more information. \n"); + } + return; +} + +void +go_home(str,x) +char *str; +int x; +{ + fprintf(stderr, "%s: %s\n", str, error_message(x)); + clean_up(); + exit(1); +} + +static int inited = 0; + +void +usage() +{ + fprintf(stderr, "Usage: kadmin [-u admin_name] [-r default_realm]"); +#ifndef NO_MULTIPLE + fprintf(stderr, " [-m]"); +#endif + fprintf(stderr, "\n"); +#ifndef NO_MULTIPLE + fprintf(stderr, " -m allows multiple admin requests to be "); + fprintf(stderr, "serviced with one entry of admin\n"); + fprintf(stderr, " password.\n"); +#endif + exit(1); +} + +static void +do_init(argc, argv) + int argc; + char *argv[]; +{ + struct passwd *pw; + extern char *optarg; + extern int optind; + int c; +#ifndef NO_MULTIPLE +#define OPTION_STRING "u:r:m" +#else +#define OPTION_STRING "u:r:" +#endif + + bzero(myname, sizeof(myname)); + + if (!inited) { + /* + * This is only as a default/initial realm; we don't care + * about failure. + */ + if (krb_get_lrealm(default_realm, 1) != KSUCCESS) + strcpy(default_realm, KRB_REALM); + + /* + * If we can reach the local realm, initialize to it. Otherwise, + * don't initialize. + */ + if (kadm_init_link(PWSERV_NAME, KRB_MASTER, krbrlm) != KADM_SUCCESS) + bzero(krbrlm, sizeof(krbrlm)); + else + strcpy(krbrlm, default_realm); + + while ((c = getopt(argc, argv, OPTION_STRING)) != EOF) + switch (c) { + case 'u': + strncpy(myname, optarg, sizeof(myname) - 1); + break; + case 'r': + bzero(default_realm, sizeof(default_realm)); + strncpy(default_realm, optarg, sizeof(default_realm) - 1); + break; +#ifndef NO_MULTIPLE + case 'm': + multiple++; + break; +#endif + default: + usage(); + break; + } + if (optind < argc) + usage(); + if (!myname[0]) { + pw = getpwuid((int) getuid()); + if (!pw) { + fprintf(stderr, + "You aren't in the password file. Who are you?\n"); + exit(1); + } + (void) strcpy(myname, pw->pw_name); + } + inited = 1; + } +} + +#ifdef NOENCRYPTION +#define read_long_pw_string placebo_read_pw_string +#else +#define read_long_pw_string des_read_pw_string +#endif +extern int read_long_pw_string(); + +int +get_admin_password() +{ + int status; + char admin_passwd[MAX_KPW_LEN]; /* Admin's password */ + int ticket_life = 1; /* minimum ticket lifetime */ +#ifndef NO_MULTIPLE + CREDENTIALS c; + + if (multiple) { + /* If admin tickets exist and are valid, just exit. */ + bzero(&c, sizeof(c)); + if (krb_get_cred(PWSERV_NAME, KADM_SINST, krbrlm, &c) == KSUCCESS) + /* + * If time is less than lifetime - FUDGE_VALUE after issue date, + * tickets will probably last long enough for the next + * transaction. + */ + if (time(0) < (c.issue_date + (5 * 60 * c.lifetime) - FUDGE_VALUE)) + return(KADM_SUCCESS); + ticket_life = DEFAULT_TKT_LIFE; + } +#endif + + if (princ_exists(myname, "admin", krbrlm) != PE_NO) { + if (read_long_pw_string(admin_passwd, sizeof(admin_passwd)-1, + "Admin password:", 0)) { + fprintf(stderr, "Error reading admin password.\n"); + goto bad; + } + status = krb_get_pw_in_tkt(myname, "admin", krbrlm, PWSERV_NAME, + KADM_SINST, ticket_life, admin_passwd); + bzero(admin_passwd, sizeof(admin_passwd)); + } + else + status = KDC_PR_UNKNOWN; + + switch(status) { + case GT_PW_OK: + return(GOOD_PW); + case KDC_PR_UNKNOWN: + printf("Principal %s.admin@%s does not exist.\n", myname, krbrlm); + goto bad; + case GT_PW_BADPW: + printf("Incorrect admin password.\n"); + goto bad; + default: + com_err("kadmin", status+krb_err_base, + "while getting password tickets"); + goto bad; + } + + bad: + bzero(admin_passwd, sizeof(admin_passwd)); + (void) dest_tkt(); + return(BAD_PW); +} + +void +clean_up() +{ + (void) dest_tkt(); + return; +} + +void +quit() +{ + printf("Cleaning up and exiting.\n"); + clean_up(); + exit(0); +} + +int +princ_exists(name, instance, realm) + char *name; + char *instance; + char *realm; +{ + int status; + + status = krb_get_pw_in_tkt(name, instance, realm, "krbtgt", realm, 1, ""); + + if ((status == KSUCCESS) || (status == INTK_BADPW)) + return(PE_YES); + else if (status == KDC_PR_UNKNOWN) + return(PE_NO); + else + return(PE_UNSURE); +} + +int +get_password(low, high, prompt, byteswap) +unsigned long *low, *high; +char *prompt; +int byteswap; +{ + char new_passwd[MAX_KPW_LEN]; /* new password */ + des_cblock newkey; + + do { + if (read_long_pw_string(new_passwd, sizeof(new_passwd)-1, prompt, 1)) + return(BAD_PW); + if (strlen(new_passwd) == 0) + printf("Null passwords are not allowed; try again.\n"); + } while (strlen(new_passwd) == 0); + +#ifdef NOENCRYPTION + bzero((char *) newkey, sizeof(newkey)); +#else + des_string_to_key(new_passwd, &newkey); +#endif + bzero(new_passwd, sizeof(new_passwd)); + + bcopy((char *) newkey,(char *)low,4); + bcopy((char *)(((long *) newkey) + 1), (char *)high,4); + + bzero((char *) newkey, sizeof(newkey)); + +#ifdef NOENCRYPTION + *low = 1; +#endif + + if (byteswap != DONTSWAP) { + *low = htonl(*low); + *high = htonl(*high); + } + return(GOOD_PW); +} diff --git a/eBones/usr.bin/kadmin/kadmin_cmds.ct b/eBones/usr.bin/kadmin/kadmin_cmds.ct new file mode 100644 index 0000000000000..141ac154e1f13 --- /dev/null +++ b/eBones/usr.bin/kadmin/kadmin_cmds.ct @@ -0,0 +1,41 @@ +# $Source: /usr/cvs/src/eBones/kadmin/kadmin_cmds.ct,v $ +# $Author: mark $ +# $Header: /usr/cvs/src/eBones/kadmin/kadmin_cmds.ct,v 1.1 1995/07/18 16:36:56 mark Exp $ +# +# Copyright 1988 by the Massachusetts Institute of Technology. +# +# For copying and distribution information, please see the file +# <mit-copyright.h>. +# +# Command table for Kerberos administration tool +# + command_table admin_cmds; + + request change_password, + "Change a user's password", + change_password, cpw; + + request change_admin_password, "Change your admin password", + change_admin_password, cap; + + request add_new_key, "Add new user to kerberos database", + add_new_key, ank; + + request get_entry, "Get entry from kerberos database", + get_entry, get; + + request clean_up, "Destroy admin tickets", + destroy_tickets, dest; + + request help,"Request help with this program", + help; + +# list_requests is generic -- unrelated to Kerberos + + request ss_list_requests, "List available requests.", + list_requests, lr, "?"; + + request quit, "Exit program.", + quit, exit, q; + + end; diff --git a/eBones/usr.bin/kdestroy/Makefile b/eBones/usr.bin/kdestroy/Makefile new file mode 100644 index 0000000000000..19a157a1fb3ae --- /dev/null +++ b/eBones/usr.bin/kdestroy/Makefile @@ -0,0 +1,10 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1995/09/13 17:24:09 markm Exp $ + +PROG= kdestroy +CFLAGS+=-DKERBEROS -DDEBUG -DBSD42 +DPADD= ${LIBKRB} ${LIBDES} +LDADD= -lkrb -ldes +MAN1= kdestroy.1 + +.include <bsd.prog.mk> diff --git a/eBones/usr.bin/kdestroy/kdestroy.c b/eBones/usr.bin/kdestroy/kdestroy.c new file mode 100644 index 0000000000000..926eea52da956 --- /dev/null +++ b/eBones/usr.bin/kdestroy/kdestroy.c @@ -0,0 +1,83 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * This program causes Kerberos tickets to be destroyed. + * Options are: + * + * -q[uiet] - no bell even if tickets not destroyed + * -f[orce] - no message printed at all + * + * from: kdestroy.c,v 4.5 88/03/18 15:16:02 steiner Exp $ + * $Id: kdestroy.c,v 1.3 1995/07/18 16:37:44 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: kdestroy.c,v 1.3 1995/07/18 16:37:44 mark Exp $"; +#endif lint +#endif + +#include <stdio.h> +#include <krb.h> +#ifdef BSD42 +#include <strings.h> +#endif BSD42 + + +static char *pname; + +static void +usage() +{ + fprintf(stderr, "Usage: %s [-f] [-q]\n", pname); + exit(1); +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int fflag=0, qflag=0, k_errno; + register char *cp; + + cp = rindex (argv[0], '/'); + if (cp == NULL) + pname = argv[0]; + else + pname = cp+1; + + if (argc > 2) + usage(); + else if (argc == 2) { + if (!strcmp(argv[1], "-f")) + ++fflag; + else if (!strcmp(argv[1], "-q")) + ++qflag; + else usage(); + } + + k_errno = dest_tkt(); + + if (fflag) { + if (k_errno != 0 && k_errno != RET_TKFIL) + exit(1); + else + exit(0); + } else { + if (k_errno == 0) + printf("Tickets destroyed.\n"); + else if (k_errno == RET_TKFIL) + fprintf(stderr, "No tickets to destroy.\n"); + else { + fprintf(stderr, "Tickets NOT destroyed.\n"); + if (!qflag) + fprintf(stderr, "\007"); + exit(1); + } + } + exit(0); +} diff --git a/eBones/usr.bin/kinit/Makefile b/eBones/usr.bin/kinit/Makefile new file mode 100644 index 0000000000000..f17237c8e39d4 --- /dev/null +++ b/eBones/usr.bin/kinit/Makefile @@ -0,0 +1,10 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1995/09/13 17:24:10 markm Exp $ + +PROG= kinit +CFLAGS+=-DKERBEROS -DDEBUG -DBSD42 +DPADD= ${LIBKRB} ${LIBDES} +LDADD= -lkrb -ldes +MAN1= kinit.1 + +.include <bsd.prog.mk> diff --git a/eBones/usr.bin/kinit/kinit.c b/eBones/usr.bin/kinit/kinit.c new file mode 100644 index 0000000000000..3b47c7cfb6bb4 --- /dev/null +++ b/eBones/usr.bin/kinit/kinit.c @@ -0,0 +1,224 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * Routine to initialize user to Kerberos. Prompts optionally for + * user, instance and realm. Authenticates user and gets a ticket + * for the Kerberos ticket-granting service for future use. + * + * Options are: + * + * -i[instance] + * -r[realm] + * -v[erbose] + * -l[ifetime] + * + * from: kinit.c,v 4.12 90/03/20 16:11:15 jon Exp $ + * $Id: kinit.c,v 1.4 1995/08/03 17:16:00 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: kinit.c,v 1.4 1995/08/03 17:16:00 mark Exp $"; +#endif lint +#endif + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <pwd.h> +#include <krb.h> + +#ifndef ORGANIZATION +#define ORGANIZATION "MIT Project Athena" +#endif /*ORGANIZATION*/ + +#ifdef PC +#define LEN 64 /* just guessing */ +#endif PC + +#if defined(BSD42) || defined(__FreeBSD__) || defined(__NetBSD__) +#include <strings.h> +#include <sys/param.h> +#if defined(ultrix) || defined(sun) +#define LEN 64 +#else +#define LEN MAXHOSTNAMELEN +#endif /* defined(ultrix) || defined(sun) */ +#endif /* BSD42 */ + +#define LIFE 96 /* lifetime of ticket in 5-minute units */ + +char *progname; + +void usage(void); + +void +get_input(s, size, stream) +char *s; +int size; +FILE *stream; +{ + char *p; + + if (fgets(s, size, stream) == NULL) + exit(1); + if ((p = index(s, '\n')) != NULL) + *p = '\0'; +} + +int +main(argc, argv) + int argc; + char *argv[]; +{ + char aname[ANAME_SZ]; + char inst[INST_SZ]; + char realm[REALM_SZ]; + char buf[LEN]; + char *username = NULL; + int iflag, rflag, vflag, lflag, lifetime, k_errno; + register char *cp; + register i; + + *inst = *realm = '\0'; + iflag = rflag = vflag = lflag = 0; + lifetime = LIFE; + progname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv; + + while (--argc) { + if ((*++argv)[0] != '-') { + if (username) + usage(); + username = *argv; + continue; + } + for (i = 1; (*argv)[i] != '\0'; i++) + switch ((*argv)[i]) { + case 'i': /* Instance */ + ++iflag; + continue; + case 'r': /* Realm */ + ++rflag; + continue; + case 'v': /* Verbose */ + ++vflag; + continue; + case 'l': + ++lflag; + continue; + default: + usage(); + exit(1); + } + } + if (username && + (k_errno = kname_parse(aname, inst, realm, username)) + != KSUCCESS) { + fprintf(stderr, "%s: %s\n", progname, krb_err_txt[k_errno]); + iflag = rflag = 1; + username = NULL; + } + if (k_gethostname(buf, LEN)) { + fprintf(stderr, "%s: k_gethostname failed\n", progname); + exit(1); + } + printf("%s (%s)\n", ORGANIZATION, buf); + if (username) { + printf("Kerberos Initialization for \"%s", aname); + if (*inst) + printf(".%s", inst); + if (*realm) + printf("@%s", realm); + printf("\"\n"); + } else { + if (iflag) { + printf("Kerberos Initialization\n"); + printf("Kerberos name: "); + get_input(aname, sizeof(aname), stdin); + } else { + int uid = getuid(); + char *getenv(); + struct passwd *pwd; + + /* default to current user name unless running as root */ + if (uid == 0 && (username = getenv("USER")) && + strcmp(username, "root") != 0) { + strncpy(aname, username, sizeof(aname)); + strncpy(inst, "root", sizeof(inst)); + } else { + pwd = getpwuid(uid); + + if (pwd == (struct passwd *) NULL) { + fprintf(stderr, "Unknown name for your uid\n"); + printf("Kerberos name: "); + gets(aname); + } else + strncpy(aname, pwd->pw_name, sizeof(aname)); + } + } + + if (!*aname) + exit(0); + if (!k_isname(aname)) { + fprintf(stderr, "%s: bad Kerberos name format\n", + progname); + exit(1); + } + } + /* optional instance */ + if (iflag) { + printf("Kerberos instance: "); + get_input(inst, sizeof(inst), stdin); + if (!k_isinst(inst)) { + fprintf(stderr, "%s: bad Kerberos instance format\n", + progname); + exit(1); + } + } + if (rflag) { + printf("Kerberos realm: "); + get_input(realm, sizeof(realm), stdin); + if (!k_isrealm(realm)) { + fprintf(stderr, "%s: bad Kerberos realm format\n", + progname); + exit(1); + } + } + if (lflag) { + printf("Kerberos ticket lifetime (minutes): "); + get_input(buf, sizeof(buf), stdin); + lifetime = atoi(buf); + if (lifetime < 5) + lifetime = 1; + else + lifetime /= 5; + /* This should be changed if the maximum ticket lifetime */ + /* changes */ + if (lifetime > 255) + lifetime = 255; + } + if (!*realm && krb_get_lrealm(realm, 1)) { + fprintf(stderr, "%s: krb_get_lrealm failed\n", progname); + exit(1); + } + k_errno = krb_get_pw_in_tkt(aname, inst, realm, "krbtgt", realm, + lifetime, 0); + if (vflag) { + printf("Kerberos realm %s:\n", realm); + printf("%s\n", krb_err_txt[k_errno]); + } else if (k_errno) { + fprintf(stderr, "%s: %s\n", progname, krb_err_txt[k_errno]); + exit(1); + } + return 0; +} + +void +usage() +{ + fprintf(stderr, "Usage: %s [-irvl] [name]\n", progname); + exit(1); +} diff --git a/eBones/usr.bin/klist/Makefile b/eBones/usr.bin/klist/Makefile new file mode 100644 index 0000000000000..f77bf20af818e --- /dev/null +++ b/eBones/usr.bin/klist/Makefile @@ -0,0 +1,10 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1995/09/13 17:24:11 markm Exp $ + +PROG= klist +CFLAGS+=-DKERBEROS -DDEBUG +DPADD= ${LIBKRB} ${LIBDES} +LDADD= -lkrb -ldes +MAN1= klist.1 + +.include <bsd.prog.mk> diff --git a/eBones/usr.bin/klist/klist.c b/eBones/usr.bin/klist/klist.c new file mode 100644 index 0000000000000..0927dcb7f58f2 --- /dev/null +++ b/eBones/usr.bin/klist/klist.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>. + * + * Lists your current Kerberos tickets. + * Written by Bill Sommerfeld, MIT Project Athena. + * + * from: klist.c,v 4.15 89/08/30 11:19:16 jtkohl Exp $ + * $Id: klist.c,v 1.3 1995/07/18 16:37:59 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: klist.c,v 1.3 1995/07/18 16:37:59 mark Exp $"; +#endif lint +#endif + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <sys/file.h> +#include <krb.h> +#include <prot.h> +#include <time.h> + +int ok_getst(int fd, char *s, int n); +void display_srvtab(char *file); +char *short_date(long *dp); +void usage(void); +void display_tktfile(char *file, int tgt_test, int long_form); + +char *whoami; /* What was I invoked as?? */ + +extern char *krb_err_txt[]; + +/* ARGSUSED */ +int +main(argc, argv) + int argc; + char **argv; +{ + int long_form = 1; + int tgt_test = 0; + int do_srvtab = 0; + char *tkt_file = NULL; + char *cp; + + whoami = (cp = rindex(*argv, '/')) ? cp + 1 : *argv; + + while (*(++argv)) { + if (!strcmp(*argv, "-s")) { + long_form = 0; + continue; + } + if (!strcmp(*argv, "-t")) { + tgt_test = 1; + long_form = 0; + continue; + } + if (!strcmp(*argv, "-l")) { /* now default */ + continue; + } + if (!strcmp(*argv, "-file")) { + if (*(++argv)) { + tkt_file = *argv; + continue; + } else + usage(); + } + if (!strcmp(*argv, "-srvtab")) { + if (tkt_file == NULL) /* if no other file spec'ed, + set file to default srvtab */ + tkt_file = KEYFILE; + do_srvtab = 1; + continue; + } + usage(); + } + + if (do_srvtab) + display_srvtab(tkt_file); + else + display_tktfile(tkt_file, tgt_test, long_form); + exit(0); +} + +void +display_tktfile(file, tgt_test, long_form) +char *file; +int tgt_test, long_form; +{ + char pname[ANAME_SZ]; + char pinst[INST_SZ]; + char prealm[REALM_SZ]; + char buf1[20], buf2[20]; + int k_errno; + CREDENTIALS c; + int header = 1; + + if ((file == NULL) && ((file = getenv("KRBTKFILE")) == NULL)) + file = TKT_FILE; + + if (long_form) + printf("Ticket file: %s\n", file); + + /* + * Since krb_get_tf_realm will return a ticket_file error, + * we will call tf_init and tf_close first to filter out + * things like no ticket file. Otherwise, the error that + * the user would see would be + * klist: can't find realm of ticket file: No ticket file (tf_util) + * instead of + * klist: No ticket file (tf_util) + */ + + /* Open ticket file */ + if ((k_errno = tf_init(file, R_TKT_FIL))) { + if (!tgt_test) + fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]); + exit(1); + } + /* Close ticket file */ + (void) tf_close(); + + /* + * We must find the realm of the ticket file here before calling + * tf_init because since the realm of the ticket file is not + * really stored in the principal section of the file, the + * routine we use must itself call tf_init and tf_close. + */ + if ((k_errno = krb_get_tf_realm(file, prealm)) != KSUCCESS) { + if (!tgt_test) + fprintf(stderr, "%s: can't find realm of ticket file: %s\n", + whoami, krb_err_txt[k_errno]); + exit(1); + } + + /* Open ticket file */ + if ((k_errno = tf_init(file, R_TKT_FIL))) { + if (!tgt_test) + fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]); + exit(1); + } + /* Get principal name and instance */ + if ((k_errno = tf_get_pname(pname)) || + (k_errno = tf_get_pinst(pinst))) { + if (!tgt_test) + fprintf(stderr, "%s: %s\n", whoami, krb_err_txt[k_errno]); + exit(1); + } + + /* + * You may think that this is the obvious place to get the + * realm of the ticket file, but it can't be done here as the + * routine to do this must open the ticket file. This is why + * it was done before tf_init. + */ + + if (!tgt_test && long_form) + printf("Principal:\t%s%s%s%s%s\n\n", pname, + (pinst[0] ? "." : ""), pinst, + (prealm[0] ? "@" : ""), prealm); + while ((k_errno = tf_get_cred(&c)) == KSUCCESS) { + if (!tgt_test && long_form && header) { + printf("%-15s %-15s %s\n", + " Issued", " Expires", " Principal"); + header = 0; + } + if (tgt_test) { + c.issue_date += ((unsigned char) c.lifetime) * 5 * 60; + if (!strcmp(c.service, TICKET_GRANTING_TICKET) && + !strcmp(c.instance, prealm)) { + if (time(0) < c.issue_date) + exit(0); /* tgt hasn't expired */ + else + exit(1); /* has expired */ + } + continue; /* not a tgt */ + } + if (long_form) { + (void) strcpy(buf1, short_date(&c.issue_date)); + c.issue_date += ((unsigned char) c.lifetime) * 5 * 60; + (void) strcpy(buf2, short_date(&c.issue_date)); + printf("%s %s ", buf1, buf2); + } + printf("%s%s%s%s%s\n", + c.service, (c.instance[0] ? "." : ""), c.instance, + (c.realm[0] ? "@" : ""), c.realm); + } + if (tgt_test) + exit(1); /* no tgt found */ + if (header && long_form && k_errno == EOF) { + printf("No tickets in file.\n"); + } +} + +char * +short_date(dp) + long *dp; +{ + register char *cp; + extern char *ctime(); + cp = ctime(dp) + 4; + cp[15] = '\0'; + return (cp); +} + +void +usage() +{ + fprintf(stderr, + "Usage: %s [ -s | -t ] [ -file filename ] [ -srvtab ]\n", whoami); + exit(1); +} + +void +display_srvtab(file) +char *file; +{ + int stab; + char serv[SNAME_SZ]; + char inst[INST_SZ]; + char rlm[REALM_SZ]; + unsigned char key[8]; + unsigned char vno; + int count; + + printf("Server key file: %s\n", file); + + if ((stab = open(file, O_RDONLY, 0400)) < 0) { + perror(file); + exit(1); + } + printf("%-15s %-15s %-10s %s\n","Service","Instance","Realm", + "Key Version"); + printf("------------------------------------------------------\n"); + + /* argh. getst doesn't return error codes, it silently fails */ + while (((count = ok_getst(stab, serv, SNAME_SZ)) > 0) + && ((count = ok_getst(stab, inst, INST_SZ)) > 0) + && ((count = ok_getst(stab, rlm, REALM_SZ)) > 0)) { + if (((count = read(stab,(char *) &vno,1)) != 1) || + ((count = read(stab,(char *) key,8)) != 8)) { + if (count < 0) + perror("reading from key file"); + else + fprintf(stderr, "key file truncated\n"); + exit(1); + } + printf("%-15s %-15s %-15s %d\n",serv,inst,rlm,vno); + } + if (count < 0) + perror(file); + (void) close(stab); +} + +/* adapted from getst() in librkb */ +/* + * ok_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. ok_getst() returns the number of characters read, including + * the null terminator. + * + * If there is a read error, it returns -1 (like the read(2) system call) + */ + +int +ok_getst(fd, s, n) + int fd; + register char *s; + int n; +{ + register count = n; + int err; + while ((err = read(fd, s, 1)) > 0 && --count) + if (*s++ == '\0') + return (n - count); + if (err < 0) + return(-1); + *s = '\0'; + return (n - count); +} diff --git a/eBones/usr.bin/ksrvtgt/Makefile b/eBones/usr.bin/ksrvtgt/Makefile new file mode 100644 index 0000000000000..0fc63fd71ba55 --- /dev/null +++ b/eBones/usr.bin/ksrvtgt/Makefile @@ -0,0 +1,10 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1995/09/13 17:24:12 markm Exp $ + +PROG= ksrvtgt +CFLAGS+=-DKERBEROS -DDEBUG +DPADD= ${LIBKRB} ${LIBDES} +LDADD= -lkrb -ldes +MAN1= ksrvtgt.1 + +.include <bsd.prog.mk> diff --git a/eBones/usr.bin/ksrvtgt/ksrvtgt.c b/eBones/usr.bin/ksrvtgt/ksrvtgt.c new file mode 100644 index 0000000000000..0f92394b6bbd3 --- /dev/null +++ b/eBones/usr.bin/ksrvtgt/ksrvtgt.c @@ -0,0 +1,62 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * Get a ticket-granting-ticket given a service key file (srvtab) + * The lifetime is the shortest allowed [1 five-minute interval] + * + * from: ksrvtgt.c,v 4.3 89/07/28 10:17:28 jtkohl Exp $ + * $Id: ksrvtgt.c,v 1.3 1995/07/18 16:40:07 mark Exp $ + */ + +#ifndef lint +const char rcsid[] = +"$Id: ksrvtgt.c,v 1.3 1995/07/18 16:40:07 mark Exp $"; +#endif /* lint */ + +#include <stdio.h> +#include <string.h> +#include <sys/param.h> +#include <krb.h> +#include <conf.h> + +int +main(argc,argv) + int argc; + char **argv; +{ + char realm[REALM_SZ + 1]; + register int code; + char srvtab[MAXPATHLEN + 1]; + + bzero(realm, sizeof(realm)); + bzero(srvtab, sizeof(srvtab)); + + if (argc < 3 || argc > 5) { + fprintf(stderr, "Usage: %s name instance [[realm] srvtab]\n", + argv[0]); + exit(1); + } + + if (argc == 4) + (void) strncpy(srvtab, argv[3], sizeof(srvtab) -1); + + if (argc == 5) { + (void) strncpy(realm, argv[3], sizeof(realm) - 1); + (void) strncpy(srvtab, argv[4], sizeof(srvtab) -1); + } + + if (srvtab[0] == 0) + (void) strcpy(srvtab, KEYFILE); + + if (realm[0] == 0) + if (krb_get_lrealm(realm, 1) != KSUCCESS) + (void) strcpy(realm, KRB_REALM); + + code = krb_get_svc_in_tkt(argv[1], argv[2], realm, + "krbtgt", realm, 1, srvtab); + if (code) + fprintf(stderr, "%s\n", krb_err_txt[code]); + exit(code); +} diff --git a/eBones/usr.bin/passwd/kpasswd.c b/eBones/usr.bin/passwd/kpasswd.c new file mode 100644 index 0000000000000..56e76a3d762f7 --- /dev/null +++ b/eBones/usr.bin/passwd/kpasswd.c @@ -0,0 +1,223 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * change your password with kerberos + */ + +#ifndef lint +#if 0 +static char rcsid_kpasswd_c[] = + "BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kpasswd.c,v 4.3 89/09/26 09:33:02 jtkohl Exp "; +#endif +static const char rcsid[] = + "$Id: kpasswd.c,v 1.1 1995/07/18 16:41:20 mark Exp $"; +#endif lint + +/* + * kpasswd + * change your password with kerberos + */ + +#include <stdio.h> +#include <sys/types.h> +#include <sys/param.h> +#include <pwd.h> +#include "kadm.h" + +#include "extern.h" + +extern void krb_set_tkt_string(); +static void go_home(char *, int); + + +int krb_passwd(char *uname, char *iflag, char *rflag, char *uflag) +{ + char name[ANAME_SZ]; /* name of user */ + char inst[INST_SZ]; /* instance of user */ + char realm[REALM_SZ]; /* realm of user */ + char default_name[ANAME_SZ]; + char default_inst[INST_SZ]; + char default_realm[REALM_SZ]; + int realm_given = 0; /* True if realm was give on cmdline */ + int use_default = 1; /* True if we should use default name */ + struct passwd *pw; + int status; /* return code */ + des_cblock new_key; + int c; + extern char *optarg; + extern int optind; + char tktstring[MAXPATHLEN]; + + void get_pw_new_key(); + +#ifdef NOENCRYPTION +#define read_long_pw_string placebo_read_pw_string +#else +#define read_long_pw_string des_read_pw_string +#endif + int read_long_pw_string(); + + bzero(name, sizeof(name)); + bzero(inst, sizeof(inst)); + bzero(realm, sizeof(realm)); + + if (krb_get_tf_fullname(TKT_FILE, default_name, default_inst, + default_realm) != KSUCCESS) { + pw = getpwuid((int) getuid()); + if (pw) { + strcpy(default_name, pw->pw_name); + } else { + /* seems like a null name is kinda silly */ + strcpy(default_name, ""); + } + strcpy(default_inst, ""); + if (krb_get_lrealm(default_realm, 1) != KSUCCESS) + strcpy(default_realm, KRB_REALM); + } + + if(uflag) { + if (status = kname_parse(name, inst, realm, uflag)) { + errx(2, "Kerberos error: %s", krb_err_txt[status]); + } + if (realm[0]) + realm_given++; + else + if (krb_get_lrealm(realm, 1) != KSUCCESS) + strcpy(realm, KRB_REALM); + } + + if(uname) { + if (k_isname(uname)) { + strncpy(name, uname, sizeof(name) - 1); + } else { + errx(1, "bad name: %s", uname); + } + } + + if(iflag) { + if (k_isinst(iflag)) { + strncpy(inst, iflag, sizeof(inst) - 1); + } else { + errx(1, "bad instance: %s", iflag); + } + } + + if(rflag) { + if (k_isrealm(rflag)) { + strncpy(realm, rflag, sizeof(realm) - 1); + realm_given++; + } else { + errx(1, "bad realm: %s", rflag); + } + } + + if(uname || iflag || rflag || uflag) use_default = 0; + + if (use_default) { + strcpy(name, default_name); + strcpy(inst, default_inst); + strcpy(realm, default_realm); + } else { + if (!name[0]) + strcpy(name, default_name); + if (!realm[0]) + strcpy(realm, default_realm); + } + + (void) sprintf(tktstring, "/tmp/tkt_cpw_%d",getpid()); + krb_set_tkt_string(tktstring); + + get_pw_new_key(new_key, name, inst, realm, realm_given); + + if ((status = kadm_init_link("changepw", KRB_MASTER, realm)) + != KADM_SUCCESS) + com_err("kpasswd", status, "while initializing"); + else if ((status = kadm_change_pw(new_key)) != KADM_SUCCESS) + com_err("kpasswd", status, " attempting to change password."); + + if (status != KADM_SUCCESS) + fprintf(stderr,"Password NOT changed.\n"); + else + printf("Password changed.\n"); + + (void) dest_tkt(); + if (status) + exit(2); + else + exit(0); +} + +void get_pw_new_key(new_key, name, inst, realm, print_realm) + des_cblock new_key; + char *name; + char *inst; + char *realm; + int print_realm; /* True if realm was give on cmdline */ +{ + char ppromp[40+ANAME_SZ+INST_SZ+REALM_SZ]; /* for the password prompt */ + char pword[MAX_KPW_LEN]; /* storage for the password */ + char npromp[40+ANAME_SZ+INST_SZ+REALM_SZ]; /* for the password prompt */ + + char local_realm[REALM_SZ]; + int status; + + /* + * We don't care about failure; this is to determine whether or + * not to print the realm in the prompt for a new password. + */ + (void) krb_get_lrealm(local_realm, 1); + + if (strcmp(local_realm, realm)) + print_realm++; + + (void) sprintf(ppromp,"Old password for %s%s%s%s%s:", + name, *inst ? "." : "", inst, + print_realm ? "@" : "", print_realm ? realm : ""); + if (read_long_pw_string(pword, sizeof(pword)-1, ppromp, 0)) { + fprintf(stderr, "Error reading old password.\n"); + exit(1); + } + + if ((status = krb_get_pw_in_tkt(name, inst, realm, PWSERV_NAME, + KADM_SINST, 1, pword)) != KSUCCESS) { + if (status == INTK_BADPW) { + printf("Incorrect old password.\n"); + exit(0); + } + else { + fprintf(stderr, "Kerberos error: %s\n", krb_err_txt[status]); + exit(1); + } + } + bzero(pword, sizeof(pword)); + do { + (void) sprintf(npromp,"New Password for %s%s%s%s%s:", + name, *inst ? "." : "", inst, + print_realm ? "@" : "", print_realm ? realm : ""); + if (read_long_pw_string(pword, sizeof(pword)-1, npromp, 1)) + go_home("Error reading new password, password unchanged.\n",0); + if (strlen(pword) == 0) + printf("Null passwords are not allowed; try again.\n"); + } while (strlen(pword) == 0); + +#ifdef NOENCRYPTION + bzero((char *) new_key, sizeof(des_cblock)); + new_key[0] = (unsigned char) 1; +#else + (void) des_string_to_key(pword, new_key); +#endif + bzero(pword, sizeof(pword)); +} + +static void +go_home(str,x) + char *str; + int x; +{ + fprintf(stderr, str, x); + (void) dest_tkt(); + exit(1); +} diff --git a/eBones/usr.bin/register/Makefile b/eBones/usr.bin/register/Makefile new file mode 100644 index 0000000000000..82a411cfc31a4 --- /dev/null +++ b/eBones/usr.bin/register/Makefile @@ -0,0 +1,11 @@ +# @(#)Makefile 8.1 (Berkeley) 6/1/93 +# $Id: Makefile,v 1.4 1995/09/13 17:24:14 markm Exp $ + +PROG= register +CFLAGS+=-DCRYPT -DDEBUG -DKERBEROS +DPADD= ${LIBKRB} ${LIBDES} ${LIBCRYPT} +LDADD= -lkrb -ldes -lcrypt +BINOWN= root +BINMODE=4555 + +.include <bsd.prog.mk> diff --git a/eBones/usr.bin/register/register.c b/eBones/usr.bin/register/register.c new file mode 100644 index 0000000000000..7050cca1284b6 --- /dev/null +++ b/eBones/usr.bin/register/register.c @@ -0,0 +1,316 @@ +/*- + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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 above copyright + * notice, this list of conditions and the following disclaimer. + * 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 the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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. + */ + +#if 0 +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1989, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +static char sccsid[] = "@(#)register.c 8.1 (Berkeley) 6/1/93"; +#endif /* not lint */ +#endif + +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/resource.h> +#include <sys/socket.h> +#include <sys/file.h> +#include <sys/signal.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <pwd.h> +#include <stdio.h> +#include <netdb.h> +#include <des.h> +#include <krb.h> +#include "pathnames.h" +#include "register_proto.h" + +#define SERVICE "krbupdate" /* service to add to KDC's database */ +#define PROTOCOL "tcp" + +void die(int); +void type_info(void); +void setup_key(struct sockaddr_in local); +void cleanup(void); +int get_user_info(void); + +char realm[REALM_SZ]; +char krbhst[MAX_HSTNM]; + +static char pname[ANAME_SZ]; +static char iname[INST_SZ]; +static char password[_PASSWORD_LEN]; + +void +main(argc, argv) + int argc; + char **argv; +{ + struct servent *se; + struct hostent *host; + struct sockaddr_in sin, local; + int rval; + int sock, llen; + u_char code; + static struct rlimit rl = { 0, 0 }; + + signal(SIGPIPE, die); + + if (setrlimit(RLIMIT_CORE, &rl) < 0) { + perror("rlimit"); + exit(1); + } + + if ((se = getservbyname(SERVICE, PROTOCOL)) == NULL) { + fprintf(stderr, "couldn't find entry for service %s\n", + SERVICE); + exit(1); + } + if ((rval = krb_get_lrealm(realm,0)) != KSUCCESS) { + fprintf(stderr, "couldn't get local Kerberos realm: %s\n", + krb_err_txt[rval]); + exit(1); + } + + if ((rval = krb_get_krbhst(krbhst, realm, 1)) != KSUCCESS) { + fprintf(stderr, "couldn't get Kerberos host: %s\n", + krb_err_txt[rval]); + exit(1); + } + + if ((host = gethostbyname(krbhst)) == NULL) { + fprintf(stderr, "couldn't get host entry for host %s\n", + krbhst); + exit(1); + } + + sin.sin_family = host->h_addrtype; + (void)bcopy(host->h_addr, (char *) &sin.sin_addr, host->h_length); + sin.sin_port = se->s_port; + + if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + perror("socket"); + exit(1); + } + + if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { + perror("connect"); + (void)close(sock); + exit(1); + } + + llen = sizeof(local); + if (getsockname(sock, (struct sockaddr *) &local, &llen) < 0) { + perror("getsockname"); + (void)close(sock); + exit(1); + } + + setup_key(local); + + type_info(); + + if (!get_user_info()) { + code = ABORT; + (void)des_write(sock, &code, 1); + cleanup(); + exit(1); + } + + code = APPEND_DB; + if (des_write(sock, &code, 1) != 1) { + perror("write 1"); + cleanup(); + exit(1); + } + + if (des_write(sock, pname, ANAME_SZ) != ANAME_SZ) { + perror("write principal name"); + cleanup(); + exit(1); + } + + if (des_write(sock, iname, INST_SZ) != INST_SZ) { + perror("write instance name"); + cleanup(); + exit(1); + } + + if (des_write(sock, password, 255) != 255) { + perror("write password"); + cleanup(); + exit(1); + } + + /* get return message */ + + { + int cc; + char msgbuf[BUFSIZ]; + + cc = read(sock, msgbuf, BUFSIZ); + if (cc <= 0) { + fprintf(stderr, "protocol error during key verification\n"); + cleanup(); + exit(1); + } + if (strncmp(msgbuf, GOTKEY_MSG, 6) != 0) { + fprintf(stderr, "%s: %s", krbhst, msgbuf); + cleanup(); + exit(1); + } + + cc = des_read(sock, msgbuf, BUFSIZ); + if (cc <= 0) { + fprintf(stderr, "protocol error during read\n"); + cleanup(); + exit(1); + } else { + printf("%s: %s", krbhst, msgbuf); + } + } + + cleanup(); + close(sock); +} + +void +cleanup() +{ + bzero(password, 255); +} + +extern char *crypt(); +extern char *getpass(); + +int +get_user_info() +{ + int uid = getuid(); + int valid = 0, i; + struct passwd *pw; + char *pas, *namep; + + /* NB: we must run setuid-root to get at the real pw file */ + + if ((pw = getpwuid(uid)) == NULL) { + fprintf(stderr, "Who are you?\n"); + return(0); + } + (void)seteuid(uid); + (void)strcpy(pname, pw->pw_name); /* principal name */ + + for (i = 1; i < 3; i++) { + pas = getpass("login password:"); + namep = crypt(pas, pw->pw_passwd); + if (strcmp(namep, pw->pw_passwd)) { + fprintf(stderr, "Password incorrect\n"); + continue; + } else { + valid = 1; + break; + } + } + if (!valid) + return(0); + pas = getpass("Kerberos password (may be the same):"); + while (*pas == NULL) { + printf("<NULL> password not allowed\n"); + pas = getpass("Kerberos password (may be the same):"); + } + (void)strcpy(password, pas); /* password */ + pas = getpass("Retype Kerberos password:"); + if (strcmp(password, pas)) { + fprintf(stderr, "Password mismatch -- aborted\n"); + return(0); + } + + iname[0] = NULL; /* null instance name */ + return(1); +} + +void +setup_key(local) + struct sockaddr_in local; +{ + static struct keyfile_data kdata; + static Key_schedule schedule; + int fd; + char namebuf[MAXPATHLEN]; + + (void) sprintf(namebuf, "%s%s", + CLIENT_KEYFILE, + inet_ntoa(local.sin_addr)); + + fd = open(namebuf, O_RDONLY); + if (fd < 0) { + fprintf(stderr, "couldn't open key file %s for local host: ", + namebuf); + perror(""); + exit(1); + } + + if (read(fd, (char *)&kdata, sizeof(kdata)) != sizeof(kdata)) { + fprintf(stderr,"size error reading key file for local host %s\n", + inet_ntoa(local.sin_addr)); + exit(1); + } + key_sched((des_cblock *)kdata.kf_key, schedule); + des_set_key((des_cblock *)kdata.kf_key, schedule); + return; +} + +void +type_info() +{ + printf("Kerberos user registration (realm %s)\n\n", realm); + printf("Please enter your login password followed by your new Kerberos password.\n"); + printf("The Kerberos password you enter now will be used in the future\n"); + printf("as your Kerberos password for all machines in the %s realm.\n", realm); + printf("You will only be allowed to perform this operation once, although you may run\n"); + printf("the %s program from now on to change your Kerberos password.\n\n", _PATH_KPASSWD); +} + +void +die(sig) + int sig; +{ + fprintf(stderr, "\nServer no longer listening\n"); + fflush(stderr); + cleanup(); + exit(1); +} diff --git a/eBones/usr.bin/rkinit/Makefile b/eBones/usr.bin/rkinit/Makefile new file mode 100644 index 0000000000000..b910742fe1b05 --- /dev/null +++ b/eBones/usr.bin/rkinit/Makefile @@ -0,0 +1,11 @@ +# Makefile,v 1.2 1995/01/20 22:08:14 wollman Exp + +PROG= rkinit +SRCS= ${RKINITOBJDIR}/rkinit_err.h rkinit.c +CFLAGS+= -I${KRBOBJDIR} -I${RKINITOBJDIR} +LDADD+= -L${RKINITOBJDIR} -lrkinit -L${KRBOBJDIR} -lkrb -L${DESOBJDIR} -ldes +LDADD+= -lss -lcom_err + +MAN1= rkinit.1 + +.include <bsd.prog.mk> diff --git a/eBones/usr.bin/rkinit/rkinit.1 b/eBones/usr.bin/rkinit/rkinit.1 new file mode 100644 index 0000000000000..5634d2b7483c9 --- /dev/null +++ b/eBones/usr.bin/rkinit/rkinit.1 @@ -0,0 +1,206 @@ +.\" +.\" $Header: /local/cvsfiles/kerberos/src/appl/rkinit/man/rkinit.1,v 1.1 1991/12/03 23:21:25 eichin Exp $ +.\" $Source: /local/cvsfiles/kerberos/src/appl/rkinit/man/rkinit.1,v $ +.\" $Author: eichin $ +.\" +.\" +.TH RKINIT 1 "November 12, 1989" +.UC 4 +.SH NAME +rkinit \- establish kerberos tickets safely on a remote host +.SH SYNOPSIS +.B rkinit [ host ] +[ -p +.B principal +] [ -l +.B username +] [ -k +.B kerberos_realm +] [ -f +.B ticket_file +] [ -h +.B remote_host +] [ -t +.B ticket_lifetime +] [ +.B \-notimeout +] + +A host name must be specified either as the first command line +argument or following a \-h flag. If redundant command line +arguments are given, the last one to appear takes precedence. + +.SH DESCRIPTION +.I rkinit +is a program that allows a user to establish kerberos tickets on +a remote host registered for +rlogin service. This can be done without the user's kerberos +password ever leaving the client machine. + +In order to establish tickets remotely +without the use of something like +.I rkinit, +one would have to log in to the +remote host and run +.IR kinit (1). +.I rkinit +followed by +.I rlogin +can be thought of as a safe substitute for +.I rlogin +followed +.I kinit. + +.I rkinit +uses the same access checking mechanism as +.I rlogin. +That means that +.I rkinit +can be used to create any tickets for user +.I A +on remote host +.I B +if and only if +.IR A 's +tickets would entitle a login to +.I B. +This means that one can create remote tickets for himself or for +another user if he is in that user's .klogin file. + +.I rkinit +understands the following command line options: + +.TP 4 +.B \-p \fIprincipal\fR +If +.I principal, +in the format +.I name[.inst][@realm] +is specified, the tickets created on the remote host will be the +tickets indicated by the +.I principal +field. If this option is not given, the following defaults are +used: If the user running +.I rkinit +does not have tickets on the client machine, +.I rkinit +will prompt for a password and behave effectively as if the user +had invoked +.I kinit +on the specified +remote host; i.e., +the tickets established will be owned on the remote host +by the user who invoked +.I rkinit +and will be for the local realm of the +remote host. +If the user running +.I rkinit +already has tickets, +.I rkinit +will prompt for a password and create tickets whose principal +matches that of the +tickets that the user already has. + + +.TP +.B \-l \fIusername\fR +If +.I username +is specified, the ticket file on the remote host will be owned by the +user +.I username. +If it is not specified, the tickets will be owned by +the remote user whose login name matches that of the user invoking +.I rkinit. + +.TP +.B \-r \fIrealm\fR +.I realm +is used to tell +.I rkinit +what realm the remote host is in. This +option should not usually have to be used since +.I rkinit +uses +.IR krb_realmofhost (3) +to determine the remote host's kerberos realm. Note that this +is distinct from realm as specified in +.I principal, +which refers to the realm of the remote tickets. + +.TP +.B \-f \fIticket_file\fR +This option is used to specify the name of the ticket file that +should be used on the remote host. Note that if you +specify a location for the ticket file that is other +than the default, you will have to set the environment variable +KRBTKFILE to that filename once you get to the remote host in +order for you to use the tickets. +If a ticket file is not specified, the tickets will +be placed in the +default location as specified by +.IR tkt_file (3). +On a UNIX host, this is /tmp/tkt<uid>, where +<uid> is the user id of the person who owns the remote ticket file. + +.TP +.B \-h \fIremote_host\fR +.I remote host +is the host on which remote tickets are being obtained. This +option can be used in place of specifying the host as the first +command line argument. + +.TP +.B \-t \fIticket_lifetime\fR +.I ticket lifetime +is the lifetime in minutes of the remote tickets. If it is not +specified, the default ticket life time (as defined in krb.h) is +used. + +.TP +.B \-notimeout +prevents the client from timing out. This is mainly useful only +for debugging since the rkinit server also times out. + +.SH EXAMPLES + +In the following examples, +.B tabetha +and +.B soup +are machines in the +.B ATHENA.MIT.EDU +kerberos realm and +.B local +is a user who can log in +to +.B soup +and has +.B qjb.root@ATHENA.MIT.EDU +in his .klogin file. + + +% rkinit tabetha +.br +Kerberos initialization (tabetha) +.br +Password for qjb@ATHENA.MIT.EDU: +.br +% +.br + +.br +% rkinit soup -p qjb.root -l local +.br +Kerberos initialization (soup): tickets will be owned by local +.br +Password for qjb.root@ATHENA.MIT.EDU: +.br +% + +.SH SEE ALSO +rkinitd(8), kerberos(1), kerberos(3), kinit(1) + +.SH AUTHOR +Emanuel Jay Berkenbilt (MIT-Project Athena) diff --git a/eBones/usr.bin/rkinit/rkinit.c b/eBones/usr.bin/rkinit/rkinit.c new file mode 100644 index 0000000000000..35a0eebfaa101 --- /dev/null +++ b/eBones/usr.bin/rkinit/rkinit.c @@ -0,0 +1,216 @@ +/* + * $Id: rkinit.c,v 1.1 1993/12/10 18:41:00 dglo Exp gibbs $ + * $Source: /usr/src/eBones/rkinit/RCS/rkinit.c,v $ + * $Author: dglo $ + * + * This is an rkinit client + */ + +#if !defined(lint) && !defined(SABER) && !defined(LOCORE) && defined(RCS_HDRS) +static char *rcsid = "$Id: rkinit.c,v 1.1 1993/12/10 18:41:00 dglo Exp gibbs $"; +#endif /* lint || SABER || LOCORE || RCS_HDRS */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <netdb.h> +#include <pwd.h> +#include <krb.h> +#include <des.h> +#include <com_err.h> + +#include <rkinit.h> +#include <rkinit_err.h> + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifdef __STDC__ +static void usage(void) +#else +static void usage() +#endif /* __STDC__ */ +{ + fprintf(stderr,"Usage: rkinit [host] options\n"); + fprintf(stderr, + "Options: [-l username] [-k krb_realm] [-p principal] [-f tktfile]\n"); + fprintf(stderr, " [-t lifetime] [-h host] [-notimeout]\n"); + fprintf(stderr, "A host must be specified either with the -h option "); + fprintf(stderr, "or as the first argument.\n"); + + exit(1); +} + +int +#ifdef __STDC__ +main(int argc, char *argv[]) +#else +main(argc, argv) + int argc; + char *argv[]; +#endif /* __STDC__ */ +{ + char *whoami; /* Name of this program */ + + char principal[MAX_K_NAME_SZ]; /* Principal for which to get tickets */ + char *host = NULL; /* Remote host */ + char *username = 0; /* Username of owner of ticket */ + char r_krealm[REALM_SZ]; /* Kerberos realm of remote host */ + char aname[ANAME_SZ]; /* Aname of remote ticket file */ + char inst[INST_SZ]; /* Instance of remote ticket file */ + char realm[REALM_SZ]; /* Realm of remote ticket file */ + char *tktfilename = NULL; /* Name of ticket file on remote host */ + u_long lifetime = DEFAULT_TKT_LIFE; /* Lifetime of remote tickets */ + int timeout = TRUE; /* Should we time out? */ + rkinit_info info; /* Information needed by rkinit */ + + struct passwd *localid; /* To determine local id */ + + int status = 0; /* general error number */ + + int i; + + bzero(r_krealm, sizeof(r_krealm)); + bzero(principal, sizeof(principal)); + bzero(aname, sizeof(aname)); + bzero(inst, sizeof(inst)); + bzero(realm, sizeof(realm)); + + /* Parse commandline arguements. */ + if ((whoami = rindex(argv[0], '/')) == 0) + whoami = argv[0]; + else + whoami++; + + if (argc < 2) usage(); + + if (argv[1][0] != '-') { + host = argv[1]; + i = 2; + } + else + i = 1; + + for (/* i initialized above */; i < argc; i++) { + if (strcmp(argv[i], "-h") == NULL) { + if (++i >= argc) + usage(); + else + host = argv[i]; + } + else if (strcmp(argv[i], "-l") == NULL) { + if (++i >= argc) + usage(); + else + username = argv[i]; + } + else if (strcmp(argv[i], "-k") == NULL) { + if (++i >= argc) + usage(); + else + strncpy(r_krealm, argv[i], sizeof(r_krealm) - 1); + } + else if (strcmp(argv[i], "-p") == NULL) { + if (++i >= argc) + usage(); + else + strncpy(principal, argv[i], sizeof(principal) - 1); + } + else if (strcmp(argv[i], "-f") == NULL) { + if (++i >= argc) + usage(); + else + tktfilename = argv[i]; + } + else if (strcmp(argv[i], "-t") == NULL) { + if (++i >= argc) + usage(); + else { + lifetime = atoi(argv[i])/5; + if (lifetime == 0) + lifetime = 1; + else if (lifetime > 255) + lifetime = 255; + } + } + else if (strcmp(argv[i], "-notimeout") == NULL) + timeout = FALSE; + else + usage(); + } + + if (host == NULL) + usage(); + + /* Initialize the realm of the remote host if necessary */ + if (r_krealm[0] == 0) { + /* + * Try to figure out the realm of the remote host. If the + * remote host is unknown, don't worry about it; the library + * will handle the error better and print a good error message. + */ + struct hostent *hp; + if ((hp = gethostbyname(host))) + strcpy(r_krealm, krb_realmofhost(hp->h_name)); + } + + /* If no username was specified, use local id on client host */ + if (username == 0) { + if ((localid = getpwuid(getuid())) == 0) { + fprintf(stderr, "You can not be found in the password file.\n"); + exit(1); + } + username = localid->pw_name; + } + + /* Find out who will go in the ticket file */ + if (! principal[0]) { + if ((status = krb_get_tf_fullname(TKT_FILE, aname, inst, realm)) + != KSUCCESS) { + /* + * If user has no ticket file and principal was not specified, + * we will try to get tickets for username@remote_realm + */ + strcpy(aname, username); + strcpy(realm, r_krealm); + } + } + else { + if ((status = kname_parse(aname, inst, realm, principal)) + != KSUCCESS) { + fprintf(stderr, "%s\n", krb_err_txt[status]); + exit(1); + } + if (strlen(realm) == 0) { + if (krb_get_lrealm(realm, 1) != KSUCCESS) + strcpy(realm, KRB_REALM); + } + } + + bzero((char *)&info, sizeof(info)); + + strcpy(info.aname, aname); + strcpy(info.inst, inst); + strcpy(info.realm, realm); + strcpy(info.sname, "krbtgt"); + strcpy(info.sinst, realm); + strncpy(info.username, username, sizeof(info.username) - 1); + if (tktfilename) + strncpy(info.tktfilename, tktfilename, sizeof(info.tktfilename) - 1); + info.lifetime = lifetime; + + if ((status = rkinit(host, r_krealm, &info, timeout))) { + com_err(whoami, status, "while obtaining remote tickets:"); + fprintf(stderr, "%s\n", rkinit_errmsg(0)); + exit(1); + } + + exit(0); +} diff --git a/eBones/usr.sbin/Makefile b/eBones/usr.sbin/Makefile new file mode 100644 index 0000000000000..4d583fc0282fa --- /dev/null +++ b/eBones/usr.sbin/Makefile @@ -0,0 +1,7 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id$ + +SUBDIR= ext_srvtab kadmind kdb_destroy kdb_edit kdb_init kdb_util \ + kerberos kprop ksrvutil kstash make_keypair + +.include <bsd.subdir.mk> diff --git a/eBones/usr.sbin/Makefile.inc b/eBones/usr.sbin/Makefile.inc new file mode 100644 index 0000000000000..a3ace61925937 --- /dev/null +++ b/eBones/usr.sbin/Makefile.inc @@ -0,0 +1,5 @@ +# @(#)Makefile.inc 8.1 (Berkeley) 6/6/93 + +BINDIR?= /usr/sbin + +.include "../Makefile.inc" diff --git a/eBones/usr.sbin/ext_srvtab/Makefile b/eBones/usr.sbin/ext_srvtab/Makefile new file mode 100644 index 0000000000000..e1ee1d512eb33 --- /dev/null +++ b/eBones/usr.sbin/ext_srvtab/Makefile @@ -0,0 +1,10 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1995/09/13 17:24:16 markm Exp $ + +PROG= ext_srvtab +CFLAGS+=-DKERBEROS +DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES} +LDADD+= -lkdb -lkrb -ldes +MAN8= ext_srvtab.8 + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/ext_srvtab/ext_srvtab.c b/eBones/usr.sbin/ext_srvtab/ext_srvtab.c new file mode 100644 index 0000000000000..6f250138cf940 --- /dev/null +++ b/eBones/usr.sbin/ext_srvtab/ext_srvtab.c @@ -0,0 +1,176 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * + * from: ext_srvtab.c,v 4.1 89/07/18 16:49:30 jtkohl Exp $ + * $Id: ext_srvtab.c,v 1.3 1995/07/18 16:35:55 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: ext_srvtab.c,v 1.3 1995/07/18 16:35:55 mark Exp $"; +#endif lint +#endif + +#include <stdio.h> +#include <string.h> +#include <sys/file.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <signal.h> +#include <des.h> +#include <krb.h> +#include <krb_db.h> + +#define TRUE 1 +#define FALSE 0 + +static C_Block master_key; +static C_Block session_key; +static Key_schedule master_key_schedule; +char progname[] = "ext_srvtab"; +char realm[REALM_SZ]; + +void FWrite(char *p, int size, int n, FILE *f); +void StampOutSecrets(void); +void usage(void); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + FILE *fout; + char fname[1024]; + int fopen_errs = 0; + int arg; + Principal princs[40]; + int more; + int prompt = TRUE; + register int n, i; + + bzero(realm, sizeof(realm)); + + /* Parse commandline arguments */ + if (argc < 2) + usage(); + else { + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-n") == 0) + prompt = FALSE; + else if (strcmp(argv[i], "-r") == 0) { + if (++i >= argc) + usage(); + else { + strcpy(realm, argv[i]); + /* + * This is to humor the broken way commandline + * argument parsing is done. Later, this + * program ignores everything that starts with -. + */ + argv[i][0] = '-'; + } + } + else if (argv[i][0] == '-') + usage(); + else + if (!k_isinst(argv[i])) { + fprintf(stderr, "%s: bad instance name: %s\n", + progname, argv[i]); + usage(); + } + } + } + + if (kdb_get_master_key (prompt, master_key, master_key_schedule) != 0) { + fprintf (stderr, "Couldn't read master key.\n"); + fflush (stderr); + exit(1); + } + + if (kdb_verify_master_key (master_key, master_key_schedule, stderr) < 0) { + exit(1); + } + + /* For each arg, search for instances of arg, and produce */ + /* srvtab file */ + if (!realm[0]) + if (krb_get_lrealm(realm, 1) != KSUCCESS) { + fprintf(stderr, "%s: couldn't get local realm\n", progname); + exit(1); + } + (void) umask(077); + + for (arg = 1; arg < argc; arg++) { + if (argv[arg][0] == '-') + continue; + sprintf(fname, "%s-new-srvtab", argv[arg]); + if ((fout = fopen(fname, "w")) == NULL) { + fprintf(stderr, "Couldn't create file '%s'.\n", fname); + fopen_errs++; + continue; + } + printf("Generating '%s'....\n", fname); + n = kerb_get_principal("*", argv[arg], &princs[0], 40, &more); + if (more) + fprintf(stderr, "More than 40 found...\n"); + for (i = 0; i < n; i++) { + FWrite(princs[i].name, strlen(princs[i].name) + 1, 1, fout); + FWrite(princs[i].instance, strlen(princs[i].instance) + 1, + 1, fout); + FWrite(realm, strlen(realm) + 1, 1, fout); + FWrite(&princs[i].key_version, + sizeof(princs[i].key_version), 1, fout); + bcopy(&princs[i].key_low, session_key, sizeof(long)); + bcopy(&princs[i].key_high, session_key + sizeof(long), + sizeof(long)); + kdb_encrypt_key (session_key, session_key, + master_key, master_key_schedule, DES_DECRYPT); + FWrite(session_key, sizeof session_key, 1, fout); + } + fclose(fout); + } + + StampOutSecrets(); + + exit(fopen_errs); /* 0 errors if successful */ + +} + +void +Die() +{ + StampOutSecrets(); + exit(1); +} + +void +FWrite(p, size, n, f) + char *p; + int size; + int n; + FILE *f; +{ + if (fwrite(p, size, n, f) != n) { + printf("Error writing output file. Terminating.\n"); + Die(); + } +} + +void +StampOutSecrets() +{ + bzero(master_key, sizeof master_key); + bzero(session_key, sizeof session_key); + bzero(master_key_schedule, sizeof master_key_schedule); +} + +void +usage() +{ + fprintf(stderr, + "Usage: %s [-n] [-r realm] instance [instance ...]\n", progname); + exit(1); +} diff --git a/eBones/usr.sbin/kadmind/Makefile b/eBones/usr.sbin/kadmind/Makefile new file mode 100644 index 0000000000000..37222ef002500 --- /dev/null +++ b/eBones/usr.sbin/kadmind/Makefile @@ -0,0 +1,10 @@ +# $Id: Makefile,v 1.4 1995/09/13 17:24:18 markm Exp $ + +PROG= kadmind +SRCS= admin_server.c kadm_funcs.c kadm_ser_wrap.c kadm_server.c +CFLAGS+=-DPOSIX -I${.CURDIR}/../../lib/libkadm +DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES} +LDADD+= -lkadm -lkdb -lkrb -ldes -lacl -lcom_err +MAN8= kadmind.8 + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/kadmind/admin_server.c b/eBones/usr.sbin/kadmind/admin_server.c new file mode 100644 index 0000000000000..6f8c7f78b2675 --- /dev/null +++ b/eBones/usr.sbin/kadmind/admin_server.c @@ -0,0 +1,474 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Top-level loop of the kerberos Administration server + */ + +#if 0 +#ifndef lint +static char rcsid_admin_server_c[] = +"Id: admin_server.c,v 4.8 90/01/02 13:50:38 jtkohl Exp "; +static const char rcsid[] = + "$Id"; +#endif lint +#endif + +/* + admin_server.c + this holds the main loop and initialization and cleanup code for the server +*/ + +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <signal.h> +#ifndef sigmask +#define sigmask(m) (1 <<((m)-1)) +#endif +#include <sys/wait.h> +#include <errno.h> +#include <sys/socket.h> +#include <syslog.h> +#include <com_err.h> +#include <kadm.h> +#include <kerberosIV/kadm_err.h> +#include <krb_db.h> +#include "kadm_server.h" + +/* Almost all procs and such need this, so it is global */ +admin_params prm; /* The command line parameters struct */ + +char prog[32]; /* WHY IS THIS NEEDED??????? */ +char *progname = prog; +char *acldir = DEFAULT_ACL_DIR; +char krbrlm[REALM_SZ]; +extern Kadm_Server server_parm; + +void cleanexit(int val); +void process_client(int fd, struct sockaddr_in *who); +void kill_children(void); +static void clear_secrets(void); +void byebye(void); +void close_syslog(void); +int kadm_listen(void); + +/* +** Main does the logical thing, it sets up the database and RPC interface, +** as well as handling the creation and maintenance of the syslog file... +*/ +void +main(argc, argv) /* admin_server main routine */ +int argc; +char *argv[]; +{ + int errval; + int c; + extern char *optarg; + + prog[sizeof(prog)-1]='\0'; /* Terminate... */ + (void) strncpy(prog, argv[0], sizeof(prog)-1); + + /* initialize the admin_params structure */ + prm.sysfile = KADM_SYSLOG; /* default file name */ + prm.inter = 1; + + bzero(krbrlm, sizeof(krbrlm)); + + while ((c = getopt(argc, argv, "f:hnd:a:r:")) != EOF) + switch(c) { + case 'f': /* Syslog file name change */ + prm.sysfile = optarg; + break; + case 'n': + prm.inter = 0; + break; + case 'a': /* new acl directory */ + acldir = optarg; + break; + case 'd': + /* put code to deal with alt database place */ + if ((errval = kerb_db_set_name(optarg))) { + fprintf(stderr, "opening database %s: %s", + optarg, error_message(errval)); + exit(1); + } + break; + case 'r': + (void) strncpy(krbrlm, optarg, sizeof(krbrlm) - 1); + break; + case 'h': /* get help on using admin_server */ + default: + printf("Usage: admin_server [-h] [-n] [-r realm] [-d dbname] [-f filename] [-a acldir]\n"); + exit(-1); /* failure */ + } + + if (krbrlm[0] == 0) + if (krb_get_lrealm(krbrlm, 0) != KSUCCESS) { + fprintf(stderr, + "Unable to get local realm. Fix krb.conf or use -r.\n"); + exit(1); + } + + printf("KADM Server %s initializing\n",KADM_VERSTR); + printf("Please do not use 'kill -9' to kill this job, use a\n"); + printf("regular kill instead\n\n"); + + set_logfile(prm.sysfile); + log("Admin server starting"); + + (void) kerb_db_set_lockmode(KERB_DBL_NONBLOCKING); + errval = kerb_init(); /* Open the Kerberos database */ + if (errval) { + fprintf(stderr, "error: kerb_init() failed"); + close_syslog(); + byebye(); + } + /* set up the server_parm struct */ + if ((errval = kadm_ser_init(prm.inter, krbrlm))==KADM_SUCCESS) { + kerb_fini(); /* Close the Kerberos database-- + will re-open later */ + errval = kadm_listen(); /* listen for calls to server from + clients */ + } + if (errval != KADM_SUCCESS) { + fprintf(stderr,"error: %s\n",error_message(errval)); + kerb_fini(); /* Close if error */ + } + close_syslog(); /* Close syslog file, print + closing note */ + byebye(); /* Say bye bye on the terminal + in use */ +} /* procedure main */ + + +/* close the system log file */ +void +close_syslog() +{ + log("Shutting down admin server"); +} + +void +byebye() /* say goodnight gracie */ +{ + printf("Admin Server (kadm server) has completed operation.\n"); +} + +static void +clear_secrets() +{ + bzero((char *)server_parm.master_key, sizeof(server_parm.master_key)); + bzero((char *)server_parm.master_key_schedule, + sizeof(server_parm.master_key_schedule)); + server_parm.master_key_version = 0L; +} + +static exit_now = 0; + +sigtype +doexit() +{ + exit_now = 1; +#ifdef POSIX + return; +#else /* !POSIX */ + return(0); +#endif /* POSIX */ +} + +unsigned pidarraysize = 0; +int *pidarray = (int *)0; + +/* +kadm_listen +listen on the admin servers port for a request +*/ +int +kadm_listen() +{ + extern int errno; + int found; + int admin_fd; + int peer_fd; + fd_set mask, readfds; + struct sockaddr_in peer; + int addrlen; + int pid; + sigtype do_child(); + + (void) signal(SIGINT, doexit); + (void) signal(SIGTERM, doexit); + (void) signal(SIGHUP, doexit); + (void) signal(SIGQUIT, doexit); + (void) signal(SIGPIPE, SIG_IGN); /* get errors on write() */ + (void) signal(SIGALRM, doexit); + (void) signal(SIGCHLD, do_child); + + if ((admin_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + return KADM_NO_SOCK; + if (bind(admin_fd, (struct sockaddr *)&server_parm.admin_addr, + sizeof(struct sockaddr_in)) < 0) + return KADM_NO_BIND; + (void) listen(admin_fd, 1); + FD_ZERO(&mask); + FD_SET(admin_fd, &mask); + + for (;;) { /* loop nearly forever */ + if (exit_now) { + clear_secrets(); + kill_children(); + return(0); + } + readfds = mask; + if ((found = select(admin_fd+1,&readfds,(fd_set *)0, + (fd_set *)0, (struct timeval *)0)) == 0) + continue; /* no things read */ + if (found < 0) { + if (errno != EINTR) + log("select: %s",error_message(errno)); + continue; + } + if (FD_ISSET(admin_fd, &readfds)) { + /* accept the conn */ + addrlen = sizeof(peer); + if ((peer_fd = accept(admin_fd, (struct sockaddr *)&peer, + &addrlen)) < 0) { + log("accept: %s",error_message(errno)); + continue; + } + addrlen = sizeof(server_parm.admin_addr); + if (getsockname(peer_fd, (struct sockaddr *)&server_parm.admin_addr, + &addrlen)) { + log("getsockname: %s",error_message(errno)); + continue; + } +#ifdef DEBUG + printf("Connection recieved on %s\n", + inet_ntoa(server_parm.admin_addr.sin_addr)); +#endif /* DEBUG */ +#ifndef DEBUG + /* if you want a sep daemon for each server */ + if ((pid = fork())) { + /* parent */ + if (pid < 0) { + log("fork: %s",error_message(errno)); + (void) close(peer_fd); + continue; + } + /* fork succeded: keep tabs on child */ + (void) close(peer_fd); + if (pidarray) { + pidarray = (int *)realloc((char *)pidarray, ++pidarraysize); + pidarray[pidarraysize-1] = pid; + } else { + pidarray = (int *)malloc(pidarraysize = 1); + pidarray[0] = pid; + } + } else { + /* child */ + (void) close(admin_fd); +#endif /* DEBUG */ + /* do stuff */ + process_client (peer_fd, &peer); +#ifndef DEBUG + } +#endif + } else { + log("something else woke me up!"); + return(0); + } + } + /*NOTREACHED*/ + return(0); /* Shut -Wall up - markm */ +} + +#ifdef DEBUG +#define cleanexit(code) {kerb_fini(); return;} +#endif + +void +process_client(fd, who) +int fd; +struct sockaddr_in *who; +{ + u_char *dat; + int dat_len; + u_short dlen; + int retval; + int on = 1; + Principal service; + des_cblock skey; + int more; + int status; + + if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on)) < 0) + log("setsockopt keepalive: %d",errno); + + server_parm.recv_addr = *who; + + if (kerb_init()) { /* Open as client */ + log("can't open krb db"); + cleanexit(1); + } + /* need to set service key to changepw.KRB_MASTER */ + + status = kerb_get_principal(server_parm.sname, server_parm.sinst, &service, + 1, &more); + if (status == -1) { + /* db locked */ + u_long retcode = KADM_DB_INUSE; + char *pdat; + + dat_len = KADM_VERSIZE + sizeof(u_long); + dat = (u_char *) malloc((unsigned)dat_len); + pdat = (char *) dat; + retcode = htonl((u_long) KADM_DB_INUSE); + (void) strncpy(pdat, KADM_ULOSE, KADM_VERSIZE); + bcopy((char *)&retcode, &pdat[KADM_VERSIZE], sizeof(u_long)); + goto out; + } else if (!status) { + log("no service %s.%s",server_parm.sname, server_parm.sinst); + cleanexit(2); + } + + bcopy((char *)&service.key_low, (char *)skey, 4); + bcopy((char *)&service.key_high, (char *)(((long *) skey) + 1), 4); + bzero((char *)&service, sizeof(service)); + kdb_encrypt_key (skey, skey, server_parm.master_key, + server_parm.master_key_schedule, DECRYPT); + (void) krb_set_key((char *)skey, 0); /* if error, will show up when + rd_req fails */ + bzero((char *)skey, sizeof(skey)); + + while (1) { + if ((retval = krb_net_read(fd, (char *)&dlen, sizeof(u_short))) != + sizeof(u_short)) { + if (retval < 0) + log("dlen read: %s",error_message(errno)); + else if (retval) + log("short dlen read: %d",retval); + (void) close(fd); + cleanexit(retval ? 3 : 0); + } + if (exit_now) { + cleanexit(0); + } + dat_len = (int) ntohs(dlen); + dat = (u_char *) malloc((unsigned)dat_len); + if (!dat) { + log("malloc: No memory"); + (void) close(fd); + cleanexit(4); + } + if ((retval = krb_net_read(fd, (char *)dat, dat_len)) != dat_len) { + if (retval < 0) + log("data read: %s",error_message(errno)); + else + log("short read: %d vs. %d", dat_len, retval); + (void) close(fd); + cleanexit(5); + } + if (exit_now) { + cleanexit(0); + } + if ((retval = kadm_ser_in(&dat,&dat_len)) != KADM_SUCCESS) + log("processing request: %s", error_message(retval)); + + /* kadm_ser_in did the processing and returned stuff in + dat & dat_len , return the appropriate data */ + + out: + dlen = (u_short) dat_len; + + if (dat_len != (int)dlen) { + clear_secrets(); + abort(); /* XXX */ + } + dlen = htons(dlen); + + if (krb_net_write(fd, (char *)&dlen, sizeof(u_short)) < 0) { + log("writing dlen to client: %s",error_message(errno)); + (void) close(fd); + cleanexit(6); + } + + if (krb_net_write(fd, (char *)dat, dat_len) < 0) { + log(LOG_ERR, "writing to client: %s",error_message(errno)); + (void) close(fd); + cleanexit(7); + } + free((char *)dat); + } + /*NOTREACHED*/ +} + +sigtype +do_child() +{ + /* SIGCHLD brings us here */ + int pid; + register int i, j; + +#ifdef POSIX + int status; +#else + union wait status; +#endif + + pid = wait(&status); + + for (i = 0; i < pidarraysize; i++) + if (pidarray[i] == pid) { + /* found it */ + for (j = i; j < pidarraysize-1; j++) + /* copy others down */ + pidarray[j] = pidarray[j+1]; + pidarraysize--; + if (WEXITSTATUS(status) || WCOREDUMP(status) || WIFSIGNALED(status)) + log("child %d: termsig %d, coredump %d, retcode %d", pid, + WTERMSIG(status), WCOREDUMP(status), WEXITSTATUS(status)); +#ifdef POSIX + return; +#else /* !POSIX */ + return(0); +#endif /* POSIX */ + } + log("child %d not in list: termsig %d, coredump %d, retcode %d", pid, + WTERMSIG(status), WCOREDUMP(status), WEXITSTATUS(status)); +#ifdef POSIX + return; +#else /* !POSIX */ + return(0); +#endif /* POSIX */ +} + +#ifndef DEBUG +void +cleanexit(val) + int val; +{ + kerb_fini(); + clear_secrets(); + exit(val); +} +#endif + +void +kill_children() +{ + register int i; + int osigmask; + + osigmask = sigblock(sigmask(SIGCHLD)); + + for (i = 0; i < pidarraysize; i++) { + kill(pidarray[i], SIGINT); + log("killing child %d", pidarray[i]); + } + sigsetmask(osigmask); + return; +} diff --git a/eBones/usr.sbin/kadmind/kadm_funcs.c b/eBones/usr.sbin/kadmind/kadm_funcs.c new file mode 100644 index 0000000000000..b20a5666ac6be --- /dev/null +++ b/eBones/usr.sbin/kadmind/kadm_funcs.c @@ -0,0 +1,381 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT + * + * Kerberos administration server-side database manipulation routines + */ + +#if 0 +#ifndef lint +static char rcsid_kadm_funcs_c[] = +"Id: kadm_funcs.c,v 4.3 90/03/20 01:39:51 jon Exp "; +static const char rcsid[] = + "$Id: kadm_funcs.c,v 1.2 1995/09/07 20:50:48 mark Exp $"; +#endif lint +#endif + +/* +kadm_funcs.c +the actual database manipulation code +*/ + +#include <stdio.h> +#include <string.h> +#include <com_err.h> +#include <sys/param.h> +#include <kadm.h> +#include <kerberosIV/kadm_err.h> +#include <krb_db.h> +#include "kadm_server.h" + +extern Kadm_Server server_parm; + +int +check_access(pname, pinst, prealm, acltype) +char *pname; +char *pinst; +char *prealm; +enum acl_types acltype; +{ + char checkname[MAX_K_NAME_SZ]; + char filename[MAXPATHLEN]; + extern char *acldir; + + sprintf(checkname, "%s.%s@%s", pname, pinst, prealm); + + switch (acltype) { + case ADDACL: + sprintf(filename, "%s%s", acldir, ADD_ACL_FILE); + break; + case GETACL: + sprintf(filename, "%s%s", acldir, GET_ACL_FILE); + break; + case MODACL: + sprintf(filename, "%s%s", acldir, MOD_ACL_FILE); + break; + } + return(acl_check(filename, checkname)); +} + +int +wildcard(str) +char *str; +{ + if (!strcmp(str, WILDCARD_STR)) + return(1); + return(0); +} + +#define failadd(code) { (void) log("FAILED addding '%s.%s' (%s)", valsin->name, valsin->instance, error_message(code)); return code; } + +int +kadm_add_entry (rname, rinstance, rrealm, valsin, valsout) +char *rname; /* requestors name */ +char *rinstance; /* requestors instance */ +char *rrealm; /* requestors realm */ +Kadm_vals *valsin; +Kadm_vals *valsout; +{ + long numfound; /* check how many we get written */ + int more; /* pointer to more grabbed records */ + Principal data_i, data_o; /* temporary principal */ + u_char flags[4]; + des_cblock newpw; + Principal default_princ; + + if (!check_access(rname, rinstance, rrealm, ADDACL)) { + (void) log("WARNING: '%s.%s@%s' tried to add an entry for '%s.%s'", + rname, rinstance, rrealm, valsin->name, valsin->instance); + return KADM_UNAUTH; + } + + /* Need to check here for "legal" name and instance */ + if (wildcard(valsin->name) || wildcard(valsin->instance)) { + failadd(KADM_ILL_WILDCARD); + } + + (void) log("request to add an entry for '%s.%s' from '%s.%s@%s'", + valsin->name, valsin->instance, rname, rinstance, rrealm); + + numfound = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST, + &default_princ, 1, &more); + if (numfound == -1) { + failadd(KADM_DB_INUSE); + } else if (numfound != 1) { + failadd(KADM_UK_RERROR); + } + + kadm_vals_to_prin(valsin->fields, &data_i, valsin); + (void) strncpy(data_i.name, valsin->name, ANAME_SZ); + (void) strncpy(data_i.instance, valsin->instance, INST_SZ); + + if (!IS_FIELD(KADM_EXPDATE,valsin->fields)) + data_i.exp_date = default_princ.exp_date; + if (!IS_FIELD(KADM_ATTR,valsin->fields)) + data_i.attributes = default_princ.attributes; + if (!IS_FIELD(KADM_MAXLIFE,valsin->fields)) + data_i.max_life = default_princ.max_life; + + bzero((char *)&default_princ, sizeof(default_princ)); + + /* convert to host order */ + data_i.key_low = ntohl(data_i.key_low); + data_i.key_high = ntohl(data_i.key_high); + + + bcopy(&data_i.key_low,newpw,4); + bcopy(&data_i.key_high,(char *)(((long *) newpw) + 1),4); + + /* encrypt new key in master key */ + kdb_encrypt_key (newpw, newpw, server_parm.master_key, + server_parm.master_key_schedule, ENCRYPT); + bcopy(newpw,&data_i.key_low,4); + bcopy((char *)(((long *) newpw) + 1), &data_i.key_high,4); + bzero((char *)newpw, sizeof(newpw)); + + data_o = data_i; + numfound = kerb_get_principal(valsin->name, valsin->instance, + &data_o, 1, &more); + if (numfound == -1) { + failadd(KADM_DB_INUSE); + } else if (numfound) { + failadd(KADM_INUSE); + } else { + data_i.key_version++; + data_i.kdc_key_ver = server_parm.master_key_version; + (void) strncpy(data_i.mod_name, rname, sizeof(data_i.mod_name)-1); + (void) strncpy(data_i.mod_instance, rinstance, + sizeof(data_i.mod_instance)-1); + + numfound = kerb_put_principal(&data_i, 1); + if (numfound == -1) { + failadd(KADM_DB_INUSE); + } else if (numfound) { + failadd(KADM_UK_SERROR); + } else { + numfound = kerb_get_principal(valsin->name, valsin->instance, + &data_o, 1, &more); + if ((numfound!=1) || (more!=0)) { + failadd(KADM_UK_RERROR); + } + bzero((char *)flags, sizeof(flags)); + SET_FIELD(KADM_NAME,flags); + SET_FIELD(KADM_INST,flags); + SET_FIELD(KADM_EXPDATE,flags); + SET_FIELD(KADM_ATTR,flags); + SET_FIELD(KADM_MAXLIFE,flags); + kadm_prin_to_vals(flags, valsout, &data_o); + (void) log("'%s.%s' added.", valsin->name, valsin->instance); + return KADM_DATA; /* Set all the appropriate fields */ + } + } +} +#undef failadd + +#define failget(code) { (void) log("FAILED retrieving '%s.%s' (%s)", valsin->name, valsin->instance, error_message(code)); return code; } + +int +kadm_get_entry (rname, rinstance, rrealm, valsin, flags, valsout) +char *rname; /* requestors name */ +char *rinstance; /* requestors instance */ +char *rrealm; /* requestors realm */ +Kadm_vals *valsin; /* what they wannt to get */ +u_char *flags; /* which fields we want */ +Kadm_vals *valsout; /* what data is there */ +{ + long numfound; /* check how many were returned */ + int more; /* To point to more name.instances */ + Principal data_o; /* Data object to hold Principal */ + + + if (!check_access(rname, rinstance, rrealm, GETACL)) { + (void) log("WARNING: '%s.%s@%s' tried to get '%s.%s's entry", + rname, rinstance, rrealm, valsin->name, valsin->instance); + return KADM_UNAUTH; + } + + if (wildcard(valsin->name) || wildcard(valsin->instance)) { + failget(KADM_ILL_WILDCARD); + } + + (void) log("retrieve '%s.%s's entry for '%s.%s@%s'", + valsin->name, valsin->instance, rname, rinstance, rrealm); + + /* Look up the record in the database */ + numfound = kerb_get_principal(valsin->name, valsin->instance, + &data_o, 1, &more); + if (numfound == -1) { + failget(KADM_DB_INUSE); + } else if (numfound) { /* We got the record, let's return it */ + kadm_prin_to_vals(flags, valsout, &data_o); + (void) log("'%s.%s' retrieved.", valsin->name, valsin->instance); + return KADM_DATA; /* Set all the appropriate fields */ + } else { + failget(KADM_NOENTRY); /* Else whimper and moan */ + } +} +#undef failget + +#define failmod(code) { (void) log("FAILED modifying '%s.%s' (%s)", valsin1->name, valsin1->instance, error_message(code)); return code; } + +int +kadm_mod_entry (rname, rinstance, rrealm, valsin1, valsin2, valsout) +char *rname; /* requestors name */ +char *rinstance; /* requestors instance */ +char *rrealm; /* requestors realm */ +Kadm_vals *valsin1, *valsin2; /* holds the parameters being + passed in */ +Kadm_vals *valsout; /* the actual record which is returned */ +{ + long numfound; + int more; + Principal data_o, temp_key; + u_char fields[4]; + des_cblock newpw; + + if (wildcard(valsin1->name) || wildcard(valsin1->instance)) { + failmod(KADM_ILL_WILDCARD); + } + + if (!check_access(rname, rinstance, rrealm, MODACL)) { + (void) log("WARNING: '%s.%s@%s' tried to change '%s.%s's entry", + rname, rinstance, rrealm, valsin1->name, valsin1->instance); + return KADM_UNAUTH; + } + + (void) log("request to modify '%s.%s's entry from '%s.%s@%s' ", + valsin1->name, valsin1->instance, rname, rinstance, rrealm); + + numfound = kerb_get_principal(valsin1->name, valsin1->instance, + &data_o, 1, &more); + if (numfound == -1) { + failmod(KADM_DB_INUSE); + } else if (numfound) { + kadm_vals_to_prin(valsin2->fields, &temp_key, valsin2); + (void) strncpy(data_o.name, valsin1->name, ANAME_SZ); + (void) strncpy(data_o.instance, valsin1->instance, INST_SZ); + if (IS_FIELD(KADM_EXPDATE,valsin2->fields)) + data_o.exp_date = temp_key.exp_date; + if (IS_FIELD(KADM_ATTR,valsin2->fields)) + data_o.attributes = temp_key.attributes; + if (IS_FIELD(KADM_MAXLIFE,valsin2->fields)) + data_o.max_life = temp_key.max_life; + if (IS_FIELD(KADM_DESKEY,valsin2->fields)) { + data_o.key_version++; + data_o.kdc_key_ver = server_parm.master_key_version; + + + /* convert to host order */ + temp_key.key_low = ntohl(temp_key.key_low); + temp_key.key_high = ntohl(temp_key.key_high); + + + bcopy(&temp_key.key_low,newpw,4); + bcopy(&temp_key.key_high,(char *)(((long *) newpw) + 1),4); + + /* encrypt new key in master key */ + kdb_encrypt_key (newpw, newpw, server_parm.master_key, + server_parm.master_key_schedule, ENCRYPT); + bcopy(newpw,&data_o.key_low,4); + bcopy((char *)(((long *) newpw) + 1), &data_o.key_high,4); + bzero((char *)newpw, sizeof(newpw)); + } + bzero((char *)&temp_key, sizeof(temp_key)); + + (void) strncpy(data_o.mod_name, rname, sizeof(data_o.mod_name)-1); + (void) strncpy(data_o.mod_instance, rinstance, + sizeof(data_o.mod_instance)-1); + more = kerb_put_principal(&data_o, 1); + + bzero((char *)&data_o, sizeof(data_o)); + + if (more == -1) { + failmod(KADM_DB_INUSE); + } else if (more) { + failmod(KADM_UK_SERROR); + } else { + numfound = kerb_get_principal(valsin1->name, valsin1->instance, + &data_o, 1, &more); + if ((more!=0)||(numfound!=1)) { + failmod(KADM_UK_RERROR); + } + bzero((char *) fields, sizeof(fields)); + SET_FIELD(KADM_NAME,fields); + SET_FIELD(KADM_INST,fields); + SET_FIELD(KADM_EXPDATE,fields); + SET_FIELD(KADM_ATTR,fields); + SET_FIELD(KADM_MAXLIFE,fields); + kadm_prin_to_vals(fields, valsout, &data_o); + (void) log("'%s.%s' modified.", valsin1->name, valsin1->instance); + return KADM_DATA; /* Set all the appropriate fields */ + } + } + else { + failmod(KADM_NOENTRY); + } +} +#undef failmod + +#define failchange(code) { (void) log("FAILED changing key for '%s.%s@%s' (%s)", rname, rinstance, rrealm, error_message(code)); return code; } + +int +kadm_change (rname, rinstance, rrealm, newpw) +char *rname; +char *rinstance; +char *rrealm; +des_cblock newpw; +{ + long numfound; + int more; + Principal data_o; + des_cblock local_pw; + + if (strcmp(server_parm.krbrlm, rrealm)) { + (void) log("change key request from wrong realm, '%s.%s@%s'!\n", + rname, rinstance, rrealm); + return(KADM_WRONG_REALM); + } + + if (wildcard(rname) || wildcard(rinstance)) { + failchange(KADM_ILL_WILDCARD); + } + (void) log("'%s.%s@%s' wants to change its password", + rname, rinstance, rrealm); + + bcopy(newpw, local_pw, sizeof(local_pw)); + + /* encrypt new key in master key */ + kdb_encrypt_key (local_pw, local_pw, server_parm.master_key, + server_parm.master_key_schedule, ENCRYPT); + + numfound = kerb_get_principal(rname, rinstance, + &data_o, 1, &more); + if (numfound == -1) { + failchange(KADM_DB_INUSE); + } else if (numfound) { + bcopy(local_pw,&data_o.key_low,4); + bcopy((char *)(((long *) local_pw) + 1), &data_o.key_high,4); + data_o.key_version++; + data_o.kdc_key_ver = server_parm.master_key_version; + (void) strncpy(data_o.mod_name, rname, sizeof(data_o.mod_name)-1); + (void) strncpy(data_o.mod_instance, rinstance, + sizeof(data_o.mod_instance)-1); + more = kerb_put_principal(&data_o, 1); + bzero((char *) local_pw, sizeof(local_pw)); + bzero((char *) &data_o, sizeof(data_o)); + if (more == -1) { + failchange(KADM_DB_INUSE); + } else if (more) { + failchange(KADM_UK_SERROR); + } else { + (void) log("'%s.%s@%s' password changed.", rname, rinstance, rrealm); + return KADM_SUCCESS; + } + } + else { + failchange(KADM_NOENTRY); + } +} +#undef failchange diff --git a/eBones/usr.sbin/kadmind/kadm_ser_wrap.c b/eBones/usr.sbin/kadmind/kadm_ser_wrap.c new file mode 100644 index 0000000000000..b6f47827b53eb --- /dev/null +++ b/eBones/usr.sbin/kadmind/kadm_ser_wrap.c @@ -0,0 +1,213 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Kerberos administration server-side support functions + */ + +#if 0 +#ifndef lint +static char rcsid_module_c[] = +"BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_ser_wrap.c,v 4.4 89/09/26 09:29:36 jtkohl Exp "; +#endif lint +#endif + +/* +kadm_ser_wrap.c +unwraps wrapped packets and calls the appropriate server subroutine +*/ + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <netdb.h> +#include <sys/socket.h> +#include <kadm.h> +#include <kerberosIV/kadm_err.h> +#include <kerberosIV/krb_err.h> +#include "kadm_server.h" + +Kadm_Server server_parm; + +/* +kadm_ser_init +set up the server_parm structure +*/ +int +kadm_ser_init(inter, realm) +int inter; /* interactive or from file */ +char realm[]; +{ + struct servent *sep; + struct hostent *hp; + char hostname[MAXHOSTNAMELEN]; + + init_kadm_err_tbl(); + init_krb_err_tbl(); + if (gethostname(hostname, sizeof(hostname))) + return KADM_NO_HOSTNAME; + + strcpy(server_parm.sname, PWSERV_NAME); + strcpy(server_parm.sinst, KRB_MASTER); + strcpy(server_parm.krbrlm, realm); + + server_parm.admin_fd = -1; + /* setting up the addrs */ + if ((sep = getservbyname(KADM_SNAME, "tcp")) == NULL) + return KADM_NO_SERV; + bzero((char *)&server_parm.admin_addr,sizeof(server_parm.admin_addr)); + server_parm.admin_addr.sin_family = AF_INET; + if ((hp = gethostbyname(hostname)) == NULL) + return KADM_NO_HOSTNAME; + server_parm.admin_addr.sin_addr.s_addr = INADDR_ANY; + server_parm.admin_addr.sin_port = sep->s_port; + /* setting up the database */ + if (kdb_get_master_key((inter==1),server_parm.master_key, + server_parm.master_key_schedule) != 0) + return KADM_NO_MAST; + if ((server_parm.master_key_version = + kdb_verify_master_key(server_parm.master_key, + server_parm.master_key_schedule,stderr))<0) + return KADM_NO_VERI; + return KADM_SUCCESS; +} + +static void +errpkt(dat, dat_len, code) +u_char **dat; +int *dat_len; +int code; +{ + u_long retcode; + char *pdat; + + free((char *)*dat); /* free up req */ + *dat_len = KADM_VERSIZE + sizeof(u_long); + *dat = (u_char *) malloc((unsigned)*dat_len); + pdat = (char *) *dat; + retcode = htonl((u_long) code); + (void) strncpy(pdat, KADM_ULOSE, KADM_VERSIZE); + bcopy((char *)&retcode, &pdat[KADM_VERSIZE], sizeof(u_long)); + return; +} + +/* +kadm_ser_in +unwrap the data stored in dat, process, and return it. +*/ +int +kadm_ser_in(dat,dat_len) +u_char **dat; +int *dat_len; +{ + u_char *in_st; /* pointer into the sent packet */ + int in_len,retc; /* where in packet we are, for + returns */ + u_long r_len; /* length of the actual packet */ + KTEXT_ST authent; /* the authenticator */ + AUTH_DAT ad; /* who is this, klink */ + u_long ncksum; /* checksum of encrypted data */ + des_key_schedule sess_sched; /* our schedule */ + MSG_DAT msg_st; + u_char *retdat, *tmpdat; + int retval, retlen; + + if (strncmp(KADM_VERSTR, (char *)*dat, KADM_VERSIZE)) { + errpkt(dat, dat_len, KADM_BAD_VER); + return KADM_BAD_VER; + } + in_len = KADM_VERSIZE; + /* get the length */ + if ((retc = stv_long(*dat, &r_len, in_len, *dat_len)) < 0) + return KADM_LENGTH_ERROR; + in_len += retc; + authent.length = *dat_len - r_len - KADM_VERSIZE - sizeof(u_long); + bcopy((char *)(*dat) + in_len, (char *)authent.dat, authent.length); + authent.mbz = 0; + /* service key should be set before here */ + if ((retc = krb_rd_req(&authent, server_parm.sname, server_parm.sinst, + server_parm.recv_addr.sin_addr.s_addr, &ad, (char *)0))) + { + errpkt(dat, dat_len,retc + krb_err_base); + return retc + krb_err_base; + } + +#define clr_cli_secrets() {bzero((char *)sess_sched, sizeof(sess_sched)); bzero((char *)ad.session, sizeof(ad.session));} + + in_st = *dat + *dat_len - r_len; +#ifdef NOENCRYPTION + ncksum = 0; +#else + ncksum = quad_cksum((des_cblock *)in_st, (des_cblock *)0, (long) r_len, + 0, (des_cblock *)ad.session); +#endif + if (ncksum!=ad.checksum) { /* yow, are we correct yet */ + clr_cli_secrets(); + errpkt(dat, dat_len,KADM_BAD_CHK); + return KADM_BAD_CHK; + } +#ifdef NOENCRYPTION + bzero(sess_sched, sizeof(sess_sched)); +#else + des_key_sched((des_cblock *)ad.session, sess_sched); +#endif + if ((retc = (int) krb_rd_priv(in_st, r_len, sess_sched, ad.session, + &server_parm.recv_addr, + &server_parm.admin_addr, &msg_st))) { + clr_cli_secrets(); + errpkt(dat, dat_len,retc + krb_err_base); + return retc + krb_err_base; + } + switch (msg_st.app_data[0]) { + case CHANGE_PW: + retval = kadm_ser_cpw(msg_st.app_data+1,(int) msg_st.app_length,&ad, + &retdat, &retlen); + break; + case ADD_ENT: + retval = kadm_ser_add(msg_st.app_data+1,(int) msg_st.app_length,&ad, + &retdat, &retlen); + break; + case GET_ENT: + retval = kadm_ser_get(msg_st.app_data+1,(int) msg_st.app_length,&ad, + &retdat, &retlen); + break; + case MOD_ENT: + retval = kadm_ser_mod(msg_st.app_data+1,(int) msg_st.app_length,&ad, + &retdat, &retlen); + break; + default: + clr_cli_secrets(); + errpkt(dat, dat_len, KADM_NO_OPCODE); + return KADM_NO_OPCODE; + } + /* Now seal the response back into a priv msg */ + free((char *)*dat); + tmpdat = (u_char *) malloc((unsigned)(retlen + KADM_VERSIZE + + sizeof(u_long))); + (void) strncpy((char *)tmpdat, KADM_VERSTR, KADM_VERSIZE); + retval = htonl((u_long)retval); + bcopy((char *)&retval, (char *)tmpdat + KADM_VERSIZE, sizeof(u_long)); + if (retlen) { + bcopy((char *)retdat, (char *)tmpdat + KADM_VERSIZE + sizeof(u_long), + retlen); + free((char *)retdat); + } + /* slop for mk_priv stuff */ + *dat = (u_char *) malloc((unsigned) (retlen + KADM_VERSIZE + + sizeof(u_long) + 200)); + if ((*dat_len = krb_mk_priv(tmpdat, *dat, + (u_long) (retlen + KADM_VERSIZE + + sizeof(u_long)), + sess_sched, + ad.session, &server_parm.admin_addr, + &server_parm.recv_addr)) < 0) { + clr_cli_secrets(); + errpkt(dat, dat_len, KADM_NO_ENCRYPT); + return KADM_NO_ENCRYPT; + } + clr_cli_secrets(); + return KADM_SUCCESS; +} diff --git a/eBones/usr.sbin/kadmind/kadm_server.c b/eBones/usr.sbin/kadmind/kadm_server.c new file mode 100644 index 0000000000000..c53af7b883368 --- /dev/null +++ b/eBones/usr.sbin/kadmind/kadm_server.c @@ -0,0 +1,167 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Kerberos administration server-side subroutines + */ + +#if 0 +#ifndef lint +static char rcsid_kadm_server_c[] = +"Header: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.c,v 4.2 89/09/26 09:30:23 jtkohl Exp "; +#endif lint +#endif + +#include <string.h> +#include <kadm.h> +#include <kerberosIV/kadm_err.h> +#include "kadm_server.h" + +/* +kadm_ser_cpw - the server side of the change_password routine + recieves : KTEXT, {key} + returns : CKSUM, RETCODE + acl : caller can change only own password + +Replaces the password (i.e. des key) of the caller with that specified in key. +Returns no actual data from the master server, since this is called by a user +*/ +int +kadm_ser_cpw(dat, len, ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + unsigned long keylow, keyhigh; + des_cblock newkey; + int stvlen; + + /* take key off the stream, and change the database */ + + if ((stvlen = stv_long(dat, &keyhigh, 0, len)) < 0) + return(KADM_LENGTH_ERROR); + if (stv_long(dat, &keylow, stvlen, len) < 0) + return(KADM_LENGTH_ERROR); + + keylow = ntohl(keylow); + keyhigh = ntohl(keyhigh); + bcopy((char *)&keyhigh, (char *)(((long *)newkey) + 1), 4); + bcopy((char *)&keylow, (char *)newkey, 4); + *datout = 0; + *outlen = 0; + + return(kadm_change(ad->pname, ad->pinst, ad->prealm, newkey)); +} + +/* +kadm_ser_add - the server side of the add_entry routine + recieves : KTEXT, {values} + returns : CKSUM, RETCODE, {values} + acl : su, sms (as alloc) + +Adds and entry containing values to the database +returns the values of the entry, so if you leave certain fields blank you will + be able to determine the default values they are set to +*/ +int +kadm_ser_add(dat,len,ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + Kadm_vals values, retvals; + int status; + + if ((status = stream_to_vals(dat, &values, len)) < 0) + return(KADM_LENGTH_ERROR); + if ((status = kadm_add_entry(ad->pname, ad->pinst, ad->prealm, + &values, &retvals)) == KADM_DATA) { + *outlen = vals_to_stream(&retvals,datout); + return KADM_SUCCESS; + } else { + *outlen = 0; + return status; + } +} + +/* +kadm_ser_mod - the server side of the mod_entry routine + recieves : KTEXT, {values, values} + returns : CKSUM, RETCODE, {values} + acl : su, sms (as register or dealloc) + +Modifies all entries corresponding to the first values so they match the + second values. +returns the values for the changed entries +*/ +int +kadm_ser_mod(dat,len,ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + Kadm_vals vals1, vals2, retvals; + int wh; + int status; + + if ((wh = stream_to_vals(dat, &vals1, len)) < 0) + return KADM_LENGTH_ERROR; + if ((status = stream_to_vals(dat+wh,&vals2, len-wh)) < 0) + return KADM_LENGTH_ERROR; + if ((status = kadm_mod_entry(ad->pname, ad->pinst, ad->prealm, &vals1, + &vals2, &retvals)) == KADM_DATA) { + *outlen = vals_to_stream(&retvals,datout); + return KADM_SUCCESS; + } else { + *outlen = 0; + return status; + } +} + +/* +kadm_ser_get + recieves : KTEXT, {values, flags} + returns : CKSUM, RETCODE, {count, values, values, values} + acl : su + +gets the fields requested by flags from all entries matching values +returns this data for each matching recipient, after a count of how many such + matches there were +*/ +int +kadm_ser_get(dat,len,ad, datout, outlen) +u_char *dat; +int len; +AUTH_DAT *ad; +u_char **datout; +int *outlen; +{ + Kadm_vals values, retvals; + u_char fl[FLDSZ]; + int loop,wh; + int status; + + if ((wh = stream_to_vals(dat, &values, len)) < 0) + return KADM_LENGTH_ERROR; + if (wh + FLDSZ > len) + return KADM_LENGTH_ERROR; + for (loop=FLDSZ-1; loop>=0; loop--) + fl[loop] = dat[wh++]; + if ((status = kadm_get_entry(ad->pname, ad->pinst, ad->prealm, + &values, fl, &retvals)) == KADM_DATA) { + *outlen = vals_to_stream(&retvals,datout); + return KADM_SUCCESS; + } else { + *outlen = 0; + return status; + } +} + diff --git a/eBones/usr.sbin/kadmind/kadm_server.h b/eBones/usr.sbin/kadmind/kadm_server.h new file mode 100644 index 0000000000000..1708107029a83 --- /dev/null +++ b/eBones/usr.sbin/kadmind/kadm_server.h @@ -0,0 +1,70 @@ +/* + * $Source: /usr/cvs/src/eBones/kadmind/kadm_server.h,v $ + * $Author: mark $ + * Header: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/kadm_server.h,v 4.1 89/12/21 17:46:51 jtkohl Exp + * + * Copyright 1988 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * Definitions for Kerberos administration server & client + */ + +#ifndef KADM_SERVER_DEFS +#define KADM_SERVER_DEFS + +/* + * kadm_server.h + * Header file for the fourth attempt at an admin server + * Doug Church, December 28, 1989, MIT Project Athena + * ps. Yes that means this code belongs to athena etc... + * as part of our ongoing attempt to copyright all greek names + */ + +#include <sys/types.h> +#include <krb.h> +#include <des.h> + +typedef struct { + struct sockaddr_in admin_addr; + struct sockaddr_in recv_addr; + int recv_addr_len; + int admin_fd; /* our link to clients */ + char sname[ANAME_SZ]; + char sinst[INST_SZ]; + char krbrlm[REALM_SZ]; + C_Block master_key; + C_Block session_key; + Key_schedule master_key_schedule; + long master_key_version; +} Kadm_Server; + +/* the default syslog file */ +#define KADM_SYSLOG "/var/log/kadmind.syslog" + +#define DEFAULT_ACL_DIR "/etc/kerberosIV" +#define ADD_ACL_FILE "/admin_acl.add" +#define GET_ACL_FILE "/admin_acl.get" +#define MOD_ACL_FILE "/admin_acl.mod" + +int kadm_ser_in(unsigned char **dat, int *dat_len); +int kadm_ser_init(int inter, char realm[]); +int kadm_ser_cpw(u_char *dat, int len, AUTH_DAT *ad, u_char **datout, + int *outlen); +int kadm_ser_add(u_char *dat, int len, AUTH_DAT *ad, u_char **datout, + int *outlen); +int kadm_ser_mod(u_char *dat, int len, AUTH_DAT *ad, u_char **datout, + int *outlen); +int kadm_ser_get(u_char *dat, int len, AUTH_DAT *ad, u_char **datout, + int *outlen); +int kadm_change (char *rname, char *rinstance, char *rrealm, + des_cblock newpw); +int kadm_add_entry(char *rname, char *rinstance, char *rrealm, + Kadm_vals *valsin, Kadm_vals *valsout); +int kadm_mod_entry(char *rname, char *rinstance, char *rrealm, + Kadm_vals *valsin1, Kadm_vals *valsin2, Kadm_vals *valsout); +int kadm_get_entry(char *rname, char *rinstance, char *rrealm, + Kadm_vals *valsin, u_char *flags, Kadm_vals *valsout); + +#endif KADM_SERVER_DEFS diff --git a/eBones/usr.sbin/kdb_destroy/Makefile b/eBones/usr.sbin/kdb_destroy/Makefile new file mode 100644 index 0000000000000..f92eb0e2b8e10 --- /dev/null +++ b/eBones/usr.sbin/kdb_destroy/Makefile @@ -0,0 +1,8 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1995/09/13 17:24:23 markm Exp $ + +PROG= kdb_destroy +CFLAGS+=-DKERBEROS -DDEBUG +MAN8= kdb_destroy.8 + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/kdb_destroy/kdb_destroy.c b/eBones/usr.sbin/kdb_destroy/kdb_destroy.c new file mode 100644 index 0000000000000..57e1a80a6b9c9 --- /dev/null +++ b/eBones/usr.sbin/kdb_destroy/kdb_destroy.c @@ -0,0 +1,66 @@ +/* + * Copyright 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: kdb_destroy.c,v 4.0 89/01/24 21:49:02 jtkohl Exp $ + * $Id: kdb_destroy.c,v 1.5 1995/08/04 06:35:45 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: kdb_destroy.c,v 1.5 1995/08/04 06:35:45 mark Exp $"; +#endif lint +#endif + +#include <unistd.h> +#include <strings.h> +#include <stdio.h> +#include <krb.h> +#include <krb_db.h> + +#if defined(__FreeBSD__) || defined(__NetBSD__) +#define _DBM_ +#endif + +void +main() +{ + char answer[10]; /* user input */ +#ifdef _DBM_ + char dbm[256]; /* database path and name */ + char *file; /* database file names */ +#else + char dbm[256]; /* database path and name */ + char dbm1[256]; /* database path and name */ + char *file1, *file2; /* database file names */ +#endif + + strcpy(dbm, DBM_FILE); +#ifdef _DBM_ + file = strcat(dbm, ".db"); +#else + strcpy(dbm1, DBM_FILE); + file1 = strcat(dbm, ".dir"); + file2 = strcat(dbm1, ".pag"); +#endif + + printf("You are about to destroy the Kerberos database "); + printf("on this machine.\n"); + printf("Are you sure you want to do this (y/n)? "); + fgets(answer, sizeof(answer), stdin); + + if (answer[0] == 'y' || answer[0] == 'Y') { +#ifdef _DBM_ + if (unlink(file) == 0) +#else + if (unlink(file1) == 0 && unlink(file2) == 0) +#endif + fprintf(stderr, "Database deleted at %s\n", DBM_FILE); + else + fprintf(stderr, "Database cannot be deleted at %s\n", + DBM_FILE); + } else + fprintf(stderr, "Database not deleted.\n"); +} diff --git a/eBones/usr.sbin/kdb_edit/Makefile b/eBones/usr.sbin/kdb_edit/Makefile new file mode 100644 index 0000000000000..7a05577c4a8af --- /dev/null +++ b/eBones/usr.sbin/kdb_edit/Makefile @@ -0,0 +1,11 @@ +# From: @(#)Makefile 5.2 (Berkeley) 2/14/91 +# $Id: Makefile,v 1.4 1995/09/13 17:24:24 markm Exp $ + +PROG= kdb_edit +CFLAGS+=-DKERBEROS -DDEBUG -I. +SRCS= kdb_edit.c maketime.c +DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES} +LDADD= -lkdb -lkrb -ldes +MAN8= kdb_edit.8 + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/kdb_edit/kdb_edit.c b/eBones/usr.sbin/kdb_edit/kdb_edit.c new file mode 100644 index 0000000000000..82bf9a4e99722 --- /dev/null +++ b/eBones/usr.sbin/kdb_edit/kdb_edit.c @@ -0,0 +1,477 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * This routine changes the Kerberos encryption keys for principals, + * i.e., users or services. + * + * from: kdb_edit.c,v 4.2 90/01/09 16:05:09 raeburn Exp $ + * $Id: kdb_edit.c,v 1.5 1995/08/03 17:15:54 mark Exp $ + */ + +/* + * exit returns 0 ==> success -1 ==> error + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: kdb_edit.c,v 1.5 1995/08/03 17:15:54 mark Exp $"; +#endif lint +#endif + +#include <stdio.h> +#include <signal.h> +#include <errno.h> +#include <strings.h> +#include <sys/ioctl.h> +#include <sys/file.h> +#include "time.h" +#include <des.h> +#include <krb.h> +#include <krb_db.h> +/* MKEYFILE is now defined in kdc.h */ +#include <kdc.h> + +void Usage(void); +void cleanup(void); +void sig_exit(int sig, int code, struct sigcontext *scp); +void no_core_dumps(void); +int change_principal(void); + +#define zaptime(foo) bzero((char *)(foo), sizeof(*(foo))) + +char prog[32]; +char *progname = prog; +int nflag = 0; +int cflag; +int lflag; +int uflag; +int debug; +extern kerb_debug; + +Key_schedule KS; +C_Block new_key; +unsigned char *input; + +unsigned char *ivec; +int i, j; +int more; + +char *in_ptr; +char input_name[ANAME_SZ]; +char input_instance[INST_SZ]; +char input_string[ANAME_SZ]; + +#define MAX_PRINCIPAL 10 +Principal principal_data[MAX_PRINCIPAL]; + +static Principal old_principal; +static Principal default_princ; + +static C_Block master_key; +static C_Block session_key; +static Key_schedule master_key_schedule; +static char pw_str[255]; +static long master_key_version; + +/* + * gets replacement + */ +static char * s_gets(char * str, int len) +{ + int i; + char *s; + + if((s = fgets(str, len, stdin)) == NULL) + return(s); + if(str[i = (strlen(str)-1)] == '\n') + str[i] = '\0'; + return(s); +} + +int +main(argc, argv) + int argc; + char *argv[]; + +{ + /* Local Declarations */ + + long n; + + prog[sizeof prog - 1] = '\0'; /* make sure terminated */ + strncpy(prog, argv[0], sizeof prog - 1); /* salt away invoking + * program */ + + /* Assume a long is four bytes */ + if (sizeof(long) != 4) { + fprintf(stdout, "%s: size of long is %d.\n", prog, sizeof(long)); + exit(-1); + } + /* Assume <=32 signals */ + if (NSIG > 32) { + fprintf(stderr, "%s: more than 32 signals defined.\n", prog); + exit(-1); + } + while (--argc > 0 && (*++argv)[0] == '-') + for (i = 1; argv[0][i] != '\0'; i++) { + switch (argv[0][i]) { + + /* debug flag */ + case 'd': + debug = 1; + continue; + + /* debug flag */ + case 'l': + kerb_debug |= 1; + continue; + + case 'n': /* read MKEYFILE for master key */ + nflag = 1; + continue; + + default: + fprintf(stderr, "%s: illegal flag \"%c\"\n", + progname, argv[0][i]); + Usage(); /* Give message and die */ + } + }; + + fprintf(stdout, "Opening database...\n"); + fflush(stdout); + kerb_init(); + if (argc > 0) { + if (kerb_db_set_name(*argv) != 0) { + fprintf(stderr, "Could not open altername database name\n"); + exit(1); + } + } + +#ifdef notdef + no_core_dumps(); /* diddle signals to avoid core dumps! */ + + /* ignore whatever is reasonable */ + signal(SIGHUP, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGTSTP, SIG_IGN); + +#endif + + if (kdb_get_master_key ((nflag == 0), + master_key, master_key_schedule) != 0) { + fprintf (stdout, "Couldn't read master key.\n"); + fflush (stdout); + exit (-1); + } + + if ((master_key_version = kdb_verify_master_key(master_key, + master_key_schedule, + stdout)) < 0) + exit (-1); + + /* lookup the default values */ + n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST, + &default_princ, 1, &more); + if (n != 1) { + fprintf(stderr, + "%s: Kerberos error on default value lookup, %ld found.\n", + progname, n); + exit(-1); + } + fprintf(stdout, "Previous or default values are in [brackets] ,\n"); + fprintf(stdout, "enter return to leave the same, or new value.\n"); + + while (change_principal()) { + } + + cleanup(); + return(0); /* make -Wall shut up - MRVM */ +} + +int +change_principal() +{ + static char temp[255]; + int creating = 0; + int editpw = 0; + int changed = 0; + long temp_long; + int n; + struct tm *tp, edate, *localtime(); + long maketime(); + + fprintf(stdout, "\nPrincipal name: "); + fflush(stdout); + if (!s_gets(input_name, ANAME_SZ-1) || *input_name == '\0') + return 0; + fprintf(stdout, "Instance: "); + fflush(stdout); + /* instance can be null */ + s_gets(input_instance, INST_SZ-1); + j = kerb_get_principal(input_name, input_instance, principal_data, + MAX_PRINCIPAL, &more); + if (!j) { + fprintf(stdout, "\n\07\07<Not found>, Create [y] ? "); + s_gets(temp, sizeof(temp)-1); /* Default case should work, it didn't */ + if (temp[0] != 'y' && temp[0] != 'Y' && temp[0] != '\0') + return -1; + /* make a new principal, fill in defaults */ + j = 1; + creating = 1; + strcpy(principal_data[0].name, input_name); + strcpy(principal_data[0].instance, input_instance); + principal_data[0].old = NULL; + principal_data[0].exp_date = default_princ.exp_date; + principal_data[0].max_life = default_princ.max_life; + principal_data[0].attributes = default_princ.attributes; + principal_data[0].kdc_key_ver = (unsigned char) master_key_version; + principal_data[0].key_version = 0; /* bumped up later */ + } + tp = localtime(&principal_data[0].exp_date); + (void) sprintf(principal_data[0].exp_date_txt, "%4d-%02d-%02d", + tp->tm_year > 1900 ? tp->tm_year : tp->tm_year + 1900, + tp->tm_mon + 1, tp->tm_mday); /* January is 0, not 1 */ + for (i = 0; i < j; i++) { + for (;;) { + fprintf(stdout, + "\nPrincipal: %s, Instance: %s, kdc_key_ver: %d", + principal_data[i].name, principal_data[i].instance, + principal_data[i].kdc_key_ver); + editpw = 1; + changed = 0; + if (!creating) { + /* + * copy the existing data so we can use the old values + * for the qualifier clause of the replace + */ + principal_data[i].old = (char *) &old_principal; + bcopy(&principal_data[i], &old_principal, + sizeof(old_principal)); + printf("\nChange password [n] ? "); + s_gets(temp, sizeof(temp)-1); + if (strcmp("y", temp) && strcmp("Y", temp)) + editpw = 0; + } + /* password */ + if (editpw) { +#ifdef NOENCRYPTION + placebo_read_pw_string(pw_str, sizeof pw_str, + "\nNew Password: ", TRUE); +#else + des_read_pw_string(pw_str, sizeof pw_str, + "\nNew Password: ", TRUE); +#endif + if (pw_str[0] == '\0' || !strcmp(pw_str, "RANDOM")) { + printf("\nRandom password [y] ? "); + s_gets(temp, sizeof(temp)-1); + if (!strcmp("n", temp) || !strcmp("N", temp)) { + /* no, use literal */ +#ifdef NOENCRYPTION + bzero(new_key, sizeof(C_Block)); + new_key[0] = 127; +#else + string_to_key(pw_str, &new_key); +#endif + bzero(pw_str, sizeof pw_str); /* "RANDOM" */ + } else { +#ifdef NOENCRYPTION + bzero(new_key, sizeof(C_Block)); + new_key[0] = 127; +#else + random_key(new_key); +#endif + bzero(pw_str, sizeof pw_str); + } + } else if (!strcmp(pw_str, "NULL")) { + printf("\nNull Key [y] ? "); + s_gets(temp, sizeof(temp)-1); + if (!strcmp("n", temp) || !strcmp("N", temp)) { + /* no, use literal */ +#ifdef NOENCRYPTION + bzero(new_key, sizeof(C_Block)); + new_key[0] = 127; +#else + string_to_key(pw_str, &new_key); +#endif + bzero(pw_str, sizeof pw_str); /* "NULL" */ + } else { + + principal_data[i].key_low = 0; + principal_data[i].key_high = 0; + goto null_key; + } + } else { +#ifdef NOENCRYPTION + bzero(new_key, sizeof(C_Block)); + new_key[0] = 127; +#else + string_to_key(pw_str, &new_key); +#endif + bzero(pw_str, sizeof pw_str); + } + + /* seal it under the kerberos master key */ + kdb_encrypt_key (new_key, new_key, + master_key, master_key_schedule, + ENCRYPT); + bcopy(new_key, &principal_data[i].key_low, 4); + bcopy(((long *) new_key) + 1, + &principal_data[i].key_high, 4); + bzero(new_key, sizeof(new_key)); + null_key: + /* set master key version */ + principal_data[i].kdc_key_ver = + (unsigned char) master_key_version; + /* bump key version # */ + principal_data[i].key_version++; + fprintf(stdout, + "\nPrincipal's new key version = %d\n", + principal_data[i].key_version); + fflush(stdout); + changed = 1; + } + /* expiration date */ + fprintf(stdout, "Expiration date (enter yyyy-mm-dd) [ %s ] ? ", + principal_data[i].exp_date_txt); + zaptime(&edate); + while (s_gets(temp, sizeof(temp)-1) && ((n = strlen(temp)) > + sizeof(principal_data[0].exp_date_txt))) { + bad_date: + fprintf(stdout, "\07\07Date Invalid\n"); + fprintf(stdout, + "Expiration date (enter yyyy-mm-dd) [ %s ] ? ", + principal_data[i].exp_date_txt); + zaptime(&edate); + } + + if (*temp) { + if (sscanf(temp, "%d-%d-%d", &edate.tm_year, + &edate.tm_mon, &edate.tm_mday) != 3) + goto bad_date; + (void) strcpy(principal_data[i].exp_date_txt, temp); + edate.tm_mon--; /* January is 0, not 1 */ + edate.tm_hour = 23; /* nearly midnight at the end of the */ + edate.tm_min = 59; /* specified day */ + if (!(principal_data[i].exp_date = maketime(&edate, 1))) + goto bad_date; + changed = 1; + } + + /* maximum lifetime */ + fprintf(stdout, "Max ticket lifetime (*5 minutes) [ %d ] ? ", + principal_data[i].max_life); + while (s_gets(temp, sizeof(temp)-1) && *temp) { + if (sscanf(temp, "%ld", &temp_long) != 1) + goto bad_life; + if (temp_long > 255 || (temp_long < 0)) { + bad_life: + fprintf(stdout, "\07\07Invalid, choose 0-255\n"); + fprintf(stdout, + "Max ticket lifetime (*5 minutes) [ %d ] ? ", + principal_data[i].max_life); + continue; + } + changed = 1; + /* dont clobber */ + principal_data[i].max_life = (unsigned short) temp_long; + break; + } + + /* attributes */ + fprintf(stdout, "Attributes [ %d ] ? ", + principal_data[i].attributes); + while (s_gets(temp, sizeof(temp)-1) && *temp) { + if (sscanf(temp, "%ld", &temp_long) != 1) + goto bad_att; + if (temp_long > 65535 || (temp_long < 0)) { + bad_att: + fprintf(stdout, "\07\07Invalid, choose 0-65535\n"); + fprintf(stdout, "Attributes [ %d ] ? ", + principal_data[i].attributes); + continue; + } + changed = 1; + /* dont clobber */ + principal_data[i].attributes = + (unsigned short) temp_long; + break; + } + + /* + * remaining fields -- key versions and mod info, should + * not be directly manipulated + */ + if (changed) { + if (kerb_put_principal(&principal_data[i], 1)) { + fprintf(stdout, + "\nError updating Kerberos database"); + } else { + fprintf(stdout, "Edit O.K."); + } + } else { + fprintf(stdout, "Unchanged"); + } + + + bzero(&principal_data[i].key_low, 4); + bzero(&principal_data[i].key_high, 4); + fflush(stdout); + break; + } + } + if (more) { + fprintf(stdout, "\nThere were more tuples found "); + fprintf(stdout, "than there were space for"); + } + return 1; +} + +void +no_core_dumps() +{ + + signal(SIGQUIT, (sig_t)sig_exit); + signal(SIGILL, (sig_t)sig_exit); + signal(SIGTRAP, (sig_t)sig_exit); + signal(SIGIOT, (sig_t)sig_exit); + signal(SIGEMT, (sig_t)sig_exit); + signal(SIGFPE, (sig_t)sig_exit); + signal(SIGBUS, (sig_t)sig_exit); + signal(SIGSEGV, (sig_t)sig_exit); + signal(SIGSYS, (sig_t)sig_exit); +} + +void +sig_exit(sig, code, scp) + int sig, code; + struct sigcontext *scp; +{ + cleanup(); + fprintf(stderr, + "\nSignal caught, sig = %d code = %d old pc = 0x%X \nexiting", + sig, code, scp->sc_pc); + exit(-1); +} + +void +cleanup() +{ + + bzero(master_key, sizeof(master_key)); + bzero(session_key, sizeof(session_key)); + bzero(master_key_schedule, sizeof(master_key_schedule)); + bzero(principal_data, sizeof(principal_data)); + bzero(new_key, sizeof(new_key)); + bzero(pw_str, sizeof(pw_str)); +} + +void +Usage() +{ + fprintf(stderr, "Usage: %s [-n]\n", progname); + exit(1); +} diff --git a/eBones/usr.sbin/kdb_edit/maketime.c b/eBones/usr.sbin/kdb_edit/maketime.c new file mode 100644 index 0000000000000..5e0ee00ee0e4a --- /dev/null +++ b/eBones/usr.sbin/kdb_edit/maketime.c @@ -0,0 +1,85 @@ +/* + * Copyright 1990 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * Convert a struct tm * to a UNIX time. + * + * from: maketime.c,v 4.2 90/01/09 15:54:51 raeburn Exp $ + * $Id: maketime.c,v 1.3 1995/07/18 16:37:29 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: maketime.c,v 1.1 1994/03/21 16:23:54 piero Exp "; +#endif lint +#endif + +#include <sys/time.h> + +#define daysinyear(y) (((y) % 4) ? 365 : (((y) % 100) ? 366 : (((y) % 400) ? 365 : 366))) + +#define SECSPERDAY 24*60*60 +#define SECSPERHOUR 60*60 +#define SECSPERMIN 60 + +static int cumdays[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, + 365}; + +static int leapyear[] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; +static int nonleapyear[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + +long +maketime(tp, local) +register struct tm *tp; +int local; +{ + register long retval; + int foo; + int *marray; + + if (tp->tm_mon < 0 || tp->tm_mon > 11 || + tp->tm_hour < 0 || tp->tm_hour > 23 || + tp->tm_min < 0 || tp->tm_min > 59 || + tp->tm_sec < 0 || tp->tm_sec > 59) /* out of range */ + return 0; + + retval = 0; + if (tp->tm_year < 1900) + foo = tp->tm_year + 1900; + else + foo = tp->tm_year; + + if (foo < 1901 || foo > 2038) /* year is too small/large */ + return 0; + + if (daysinyear(foo) == 366) { + if (tp->tm_mon > 1) + retval+= SECSPERDAY; /* add leap day */ + marray = leapyear; + } else + marray = nonleapyear; + + if (tp->tm_mday < 0 || tp->tm_mday > marray[tp->tm_mon]) + return 0; /* out of range */ + + while (--foo >= 1970) + retval += daysinyear(foo) * SECSPERDAY; + + retval += cumdays[tp->tm_mon] * SECSPERDAY; + retval += (tp->tm_mday-1) * SECSPERDAY; + retval += tp->tm_hour * SECSPERHOUR + tp->tm_min * SECSPERMIN + tp->tm_sec; + + if (local) { + /* need to use local time, so we retrieve timezone info */ + struct timezone tz; + struct timeval tv; + if (gettimeofday(&tv, &tz) < 0) { + /* some error--give up? */ + return(retval); + } + retval += tz.tz_minuteswest * SECSPERMIN; + } + return(retval); +} diff --git a/eBones/usr.sbin/kdb_init/Makefile b/eBones/usr.sbin/kdb_init/Makefile new file mode 100644 index 0000000000000..cc1b778013f13 --- /dev/null +++ b/eBones/usr.sbin/kdb_init/Makefile @@ -0,0 +1,10 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1995/09/13 17:24:25 markm Exp $ + +PROG= kdb_init +CFLAGS+=-DKERBEROS -DDEBUG +DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES} +LDADD= -lkdb -lkrb -ldes +MAN8= kdb_init.8 + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/kdb_init/kdb_init.c b/eBones/usr.sbin/kdb_init/kdb_init.c new file mode 100644 index 0000000000000..de99181d5c3ba --- /dev/null +++ b/eBones/usr.sbin/kdb_init/kdb_init.c @@ -0,0 +1,180 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * program to initialize the database, reports error if database file + * already exists. + * + * from: kdb_init.c,v 4.0 89/01/24 21:50:45 jtkohl Exp $ + * $Id: kdb_init.c,v 1.4 1995/07/18 16:37:35 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: kdb_init.c,v 1.4 1995/07/18 16:37:35 mark Exp $"; +#endif lint +#endif + +#include <stdio.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/time.h> +#include <des.h> +#include <krb.h> +#include <krb_db.h> +#include <string.h> + +#define TRUE 1 + +enum ap_op { + NULL_KEY, /* setup null keys */ + MASTER_KEY, /* use master key as new key */ + RANDOM_KEY, /* choose a random key */ +}; + +int add_principal(char *name, char *instance, enum ap_op aap_op); + +int debug = 0; +char *progname; +C_Block master_key; +Key_schedule master_key_schedule; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + char realm[REALM_SZ]; + char *cp; + int code; + char *database; + + progname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv; + + if (argc > 3) { + fprintf(stderr, "Usage: %s [realm-name] [database-name]\n", argv[0]); + exit(1); + } + if (argc == 3) { + database = argv[2]; + --argc; + } else + database = DBM_FILE; + + /* Do this first, it'll fail if the database exists */ + if ((code = kerb_db_create(database)) != 0) { + fprintf(stderr, "Couldn't create database: %s\n", + sys_errlist[code]); + exit(1); + } + kerb_db_set_name(database); + + if (argc == 2) + strncpy(realm, argv[1], REALM_SZ); + else { + fprintf(stderr, "Realm name [default %s ]: ", KRB_REALM); + if (fgets(realm, sizeof(realm), stdin) == NULL) { + fprintf(stderr, "\nEOF reading realm\n"); + exit(1); + } + if ((cp = index(realm, '\n'))) + *cp = '\0'; + if (!*realm) /* no realm given */ + strcpy(realm, KRB_REALM); + } + if (!k_isrealm(realm)) { + fprintf(stderr, "%s: Bad kerberos realm name \"%s\"\n", + progname, realm); + exit(1); + } + printf("You will be prompted for the database Master Password.\n"); + printf("It is important that you NOT FORGET this password.\n"); + fflush(stdout); + + if (kdb_get_master_key (TRUE, master_key, master_key_schedule) != 0) { + fprintf (stderr, "Couldn't read master key.\n"); + exit (-1); + } + + if ( + add_principal(KERB_M_NAME, KERB_M_INST, MASTER_KEY) || + add_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST, NULL_KEY) || + add_principal("krbtgt", realm, RANDOM_KEY) || + add_principal("changepw", KRB_MASTER, RANDOM_KEY) + ) { + fprintf(stderr, "\n%s: couldn't initialize database.\n", + progname); + exit(1); + } + + /* play it safe */ + bzero (master_key, sizeof (C_Block)); + bzero (master_key_schedule, sizeof (Key_schedule)); + exit(0); +} + +/* use a return code to indicate success or failure. check the return */ +/* values of the routines called by this routine. */ + +int +add_principal(name, instance, aap_op) + char *name, *instance; + enum ap_op aap_op; +{ + Principal principal; + struct tm *tm; + C_Block new_key; + + bzero(&principal, sizeof(principal)); + strncpy(principal.name, name, ANAME_SZ); + strncpy(principal.instance, instance, INST_SZ); + switch (aap_op) { + case NULL_KEY: + principal.key_low = 0; + principal.key_high = 0; + break; + case RANDOM_KEY: +#ifdef NOENCRYPTION + bzero(new_key, sizeof(C_Block)); + new_key[0] = 127; +#else + random_key(new_key); +#endif + kdb_encrypt_key (new_key, new_key, master_key, master_key_schedule, + ENCRYPT); + bcopy(new_key, &principal.key_low, 4); + bcopy(((long *) new_key) + 1, &principal.key_high, 4); + break; + case MASTER_KEY: + bcopy (master_key, new_key, sizeof (C_Block)); + kdb_encrypt_key (new_key, new_key, master_key, master_key_schedule, + ENCRYPT); + bcopy(new_key, &principal.key_low, 4); + bcopy(((long *) new_key) + 1, &principal.key_high, 4); + break; + } + principal.exp_date = 946702799; /* Happy new century */ + strncpy(principal.exp_date_txt, "12/31/99", DATE_SZ); + principal.mod_date = time(0); + + tm = localtime(&principal.mod_date); + principal.attributes = 0; + principal.max_life = 255; + + principal.kdc_key_ver = 1; + principal.key_version = 1; + + strncpy(principal.mod_name, "db_creation", ANAME_SZ); + strncpy(principal.mod_instance, "", INST_SZ); + principal.old = 0; + + kerb_db_put_principal(&principal, 1); + + /* let's play it safe */ + bzero (new_key, sizeof (C_Block)); + bzero (&principal.key_low, 4); + bzero (&principal.key_high, 4); + return 0; +} diff --git a/eBones/usr.sbin/kdb_util/Makefile b/eBones/usr.sbin/kdb_util/Makefile new file mode 100644 index 0000000000000..1f211a134843b --- /dev/null +++ b/eBones/usr.sbin/kdb_util/Makefile @@ -0,0 +1,12 @@ +# From: @(#)Makefile 5.2 (Berkeley) 2/14/91 +# $Id: Makefile,v 1.4 1995/09/13 17:24:27 markm Exp $ + +PROG= kdb_util +CFLAGS+=-DKERBEROS -DDEBUG -I${.CURDIR}/../../kdb_edit +SRCS= kdb_util.c maketime.c +.PATH: ${.CURDIR}/../kdb_edit +DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES} +LDADD= -lkdb -lkrb -ldes +MAN8= kdb_util.8 + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/kdb_util/kdb_util.c b/eBones/usr.sbin/kdb_util/kdb_util.c new file mode 100644 index 0000000000000..5dbe509e1afe2 --- /dev/null +++ b/eBones/usr.sbin/kdb_util/kdb_util.c @@ -0,0 +1,523 @@ +/* + * Copyright 1987, 1988 by the Massachusetts Institute of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * Kerberos database manipulation utility. This program allows you to + * dump a kerberos database to an ascii readable file and load this + * file into the database. Read locking of the database is done during a + * dump operation. NO LOCKING is done during a load operation. Loads + * should happen with other processes shutdown. + * + * Written July 9, 1987 by Jeffrey I. Schiller + * + * from: kdb_util.c,v 4.4 90/01/09 15:57:20 raeburn Exp $ + * $Id: kdb_util.c,v 1.5 1995/08/03 17:15:57 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: kdb_util.c,v 1.5 1995/08/03 17:15:57 mark Exp $"; +#endif lint +#endif + +#include <errno.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <time.h> +#include <strings.h> +#include <des.h> +#include <krb.h> +#include <sys/file.h> +#include <krb_db.h> + +#define TRUE 1 + +Principal aprinc; + +static des_cblock master_key, new_master_key; +static des_key_schedule master_key_schedule, new_master_key_schedule; + +#define zaptime(foo) bzero((char *)(foo), sizeof(*(foo))) + +char * progname; + +void convert_old_format_db (char *db_file, FILE *out); +void convert_new_master_key (char *db_file, FILE *out); +void update_ok_file (char *file_name); +void print_time(FILE *file, unsigned long timeval); +void load_db (char *db_file, FILE *input_file); +int dump_db (char *db_file, FILE *output_file, void (*cv_key)()); + +int +main(argc, argv) + int argc; + char **argv; +{ + FILE *file; + enum { + OP_LOAD, + OP_DUMP, + OP_SLAVE_DUMP, + OP_NEW_MASTER, + OP_CONVERT_OLD_DB, + } op; + char *file_name; + char *prog = argv[0]; + char *db_name; + + progname = prog; + + if (argc != 3 && argc != 4) { + fprintf(stderr, "Usage: %s operation file-name [database name].\n", + argv[0]); + exit(1); + } + if (argc == 3) + db_name = DBM_FILE; + else + db_name = argv[3]; + + if (kerb_db_set_name (db_name) != 0) { + perror("Can't open database"); + exit(1); + } + + if (!strcmp(argv[1], "load")) + op = OP_LOAD; + else if (!strcmp(argv[1], "dump")) + op = OP_DUMP; + else if (!strcmp(argv[1], "slave_dump")) + op = OP_SLAVE_DUMP; + else if (!strcmp(argv[1], "new_master_key")) + op = OP_NEW_MASTER; + else if (!strcmp(argv[1], "convert_old_db")) + op = OP_CONVERT_OLD_DB; + else { + fprintf(stderr, + "%s: %s is an invalid operation.\n", prog, argv[1]); + fprintf(stderr, + "%s: Valid operations are \"dump\", \"slave_dump\",", argv[0]); + fprintf(stderr, + "\"load\", \"new_master_key\", and \"convert_old_db\".\n"); + exit(1); + } + + file_name = argv[2]; + file = fopen(file_name, op == OP_LOAD ? "r" : "w"); + if (file == NULL) { + fprintf(stderr, "%s: Unable to open %s\n", prog, argv[2]); + (void) fflush(stderr); + perror("open"); + exit(1); + } + + switch (op) { + case OP_DUMP: + if ((dump_db (db_name, file, (void (*)()) 0) == EOF) || + (fclose(file) == EOF)) { + fprintf(stderr, "error on file %s:", file_name); + perror(""); + exit(1); + } + break; + case OP_SLAVE_DUMP: + if ((dump_db (db_name, file, (void (*)()) 0) == EOF) || + (fclose(file) == EOF)) { + fprintf(stderr, "error on file %s:", file_name); + perror(""); + exit(1); + } + update_ok_file (file_name); + break; + case OP_LOAD: + load_db (db_name, file); + break; + case OP_NEW_MASTER: + convert_new_master_key (db_name, file); + printf("Don't forget to do a `kdb_util load %s' to reload the database!\n", file_name); + break; + case OP_CONVERT_OLD_DB: + convert_old_format_db (db_name, file); + printf("Don't forget to do a `kdb_util load %s' to reload the database!\n", file_name); + break; + } + exit(0); + } + +void +clear_secrets () +{ + bzero((char *)master_key, sizeof (des_cblock)); + bzero((char *)master_key_schedule, sizeof (Key_schedule)); + bzero((char *)new_master_key, sizeof (des_cblock)); + bzero((char *)new_master_key_schedule, sizeof (Key_schedule)); +} + +/* cv_key is a procedure which takes a principle and changes its key, + either for a new method of encrypting the keys, or a new master key. + if cv_key is null no transformation of key is done (other than net byte + order). */ + +struct callback_args { + void (*cv_key)(); + FILE *output_file; +}; + +static int dump_db_1(arg, principal) + char *arg; + Principal *principal; +{ /* replace null strings with "*" */ + struct callback_args *a = (struct callback_args *)arg; + + if (principal->instance[0] == '\0') { + principal->instance[0] = '*'; + principal->instance[1] = '\0'; + } + if (principal->mod_name[0] == '\0') { + principal->mod_name[0] = '*'; + principal->mod_name[1] = '\0'; + } + if (principal->mod_instance[0] == '\0') { + principal->mod_instance[0] = '*'; + principal->mod_instance[1] = '\0'; + } + if (a->cv_key != NULL) { + (*a->cv_key) (principal); + } + fprintf(a->output_file, "%s %s %d %d %d %d %lx %lx", + principal->name, + principal->instance, + principal->max_life, + principal->kdc_key_ver, + principal->key_version, + principal->attributes, + htonl (principal->key_low), + htonl (principal->key_high)); + print_time(a->output_file, principal->exp_date); + print_time(a->output_file, principal->mod_date); + fprintf(a->output_file, " %s %s\n", + principal->mod_name, + principal->mod_instance); + return 0; +} + +int +dump_db (db_file, output_file, cv_key) + char *db_file; + FILE *output_file; + void (*cv_key)(); +{ + struct callback_args a; + + a.cv_key = cv_key; + a.output_file = output_file; + + kerb_db_iterate (dump_db_1, (char *)&a); + return fflush(output_file); +} + +void +load_db (db_file, input_file) + char *db_file; + FILE *input_file; +{ + char exp_date_str[50]; + char mod_date_str[50]; + int temp1, temp2, temp3; + long time_explode(); + int code; + char *temp_db_file; + temp1 = strlen(db_file)+2; + temp_db_file = malloc (temp1); + strcpy(temp_db_file, db_file); + strcat(temp_db_file, "~"); + + /* Create the database */ + if ((code = kerb_db_create(temp_db_file)) != 0) { + fprintf(stderr, "Couldn't create temp database %s: %s\n", + temp_db_file, sys_errlist[code]); + exit(1); + } + kerb_db_set_name(temp_db_file); + for (;;) { /* explicit break on eof from fscanf */ + bzero((char *)&aprinc, sizeof(aprinc)); + if (fscanf(input_file, + "%s %s %d %d %d %hd %lx %lx %s %s %s %s\n", + aprinc.name, + aprinc.instance, + &temp1, + &temp2, + &temp3, + &aprinc.attributes, + &aprinc.key_low, + &aprinc.key_high, + exp_date_str, + mod_date_str, + aprinc.mod_name, + aprinc.mod_instance) == EOF) + break; + aprinc.key_low = ntohl (aprinc.key_low); + aprinc.key_high = ntohl (aprinc.key_high); + aprinc.max_life = (unsigned char) temp1; + aprinc.kdc_key_ver = (unsigned char) temp2; + aprinc.key_version = (unsigned char) temp3; + aprinc.exp_date = time_explode(exp_date_str); + aprinc.mod_date = time_explode(mod_date_str); + if (aprinc.instance[0] == '*') + aprinc.instance[0] = '\0'; + if (aprinc.mod_name[0] == '*') + aprinc.mod_name[0] = '\0'; + if (aprinc.mod_instance[0] == '*') + aprinc.mod_instance[0] = '\0'; + if (kerb_db_put_principal(&aprinc, 1) != 1) { + fprintf(stderr, "Couldn't store %s.%s: %s; load aborted\n", + aprinc.name, aprinc.instance, + sys_errlist[errno]); + exit(1); + }; + } + if ((code = kerb_db_rename(temp_db_file, db_file)) != 0) + perror("database rename failed"); + (void) fclose(input_file); + free(temp_db_file); +} + +void +print_time(file, timeval) + FILE *file; + unsigned long timeval; +{ + struct tm *tm; + struct tm *gmtime(); + tm = gmtime((long *)&timeval); + fprintf(file, " %04d%02d%02d%02d%02d", + tm->tm_year < 1900 ? tm->tm_year + 1900: tm->tm_year, + tm->tm_mon + 1, + tm->tm_mday, + tm->tm_hour, + tm->tm_min); +} + +/*ARGSUSED*/ +void +update_ok_file (file_name) + char *file_name; +{ + /* handle slave locking/failure stuff */ + char *file_ok; + int fd; + static char ok[]=".dump_ok"; + + if ((file_ok = (char *)malloc(strlen(file_name) + strlen(ok) + 1)) + == NULL) { + fprintf(stderr, "kdb_util: out of memory.\n"); + (void) fflush (stderr); + perror ("malloc"); + exit (1); + } + strcpy(file_ok, file_name); + strcat(file_ok, ok); + if ((fd = open(file_ok, O_WRONLY|O_CREAT|O_TRUNC, 0400)) < 0) { + fprintf(stderr, "Error creating 'ok' file, '%s'", file_ok); + perror(""); + (void) fflush (stderr); + exit (1); + } + free(file_ok); + close(fd); +} + +void +convert_key_new_master (p) + Principal *p; +{ + des_cblock key; + + /* leave null keys alone */ + if ((p->key_low == 0) && (p->key_high == 0)) return; + + /* move current key to des_cblock for encryption, special case master key + since that's changing */ + if ((strncmp (p->name, KERB_M_NAME, ANAME_SZ) == 0) && + (strncmp (p->instance, KERB_M_INST, INST_SZ) == 0)) { + bcopy((char *)new_master_key, (char *) key, sizeof (des_cblock)); + (p->key_version)++; + } else { + bcopy((char *)&(p->key_low), (char *)key, 4); + bcopy((char *)&(p->key_high), (char *) (((long *) key) + 1), 4); + kdb_encrypt_key (key, key, master_key, master_key_schedule, DECRYPT); + } + + kdb_encrypt_key (key, key, new_master_key, new_master_key_schedule, ENCRYPT); + + bcopy((char *)key, (char *)&(p->key_low), 4); + bcopy((char *)(((long *) key) + 1), (char *)&(p->key_high), 4); + bzero((char *)key, sizeof (key)); /* a little paranoia ... */ + + (p->kdc_key_ver)++; +} + +void +convert_new_master_key (db_file, out) + char *db_file; + FILE *out; +{ + + printf ("\n\nEnter the CURRENT master key."); + if (kdb_get_master_key (TRUE, master_key, master_key_schedule) != 0) { + fprintf (stderr, "get_master_key: Couldn't get master key.\n"); + clear_secrets (); + exit (-1); + } + + if (kdb_verify_master_key (master_key, master_key_schedule, stderr) < 0) { + clear_secrets (); + exit (-1); + } + + printf ("\n\nNow enter the NEW master key. Do not forget it!!"); + if (kdb_get_master_key (TRUE, new_master_key, new_master_key_schedule) != 0) { + fprintf (stderr, "get_master_key: Couldn't get new master key.\n"); + clear_secrets (); + exit (-1); + } + + dump_db (db_file, out, convert_key_new_master); +} + +void +convert_key_old_db (p) + Principal *p; +{ + des_cblock key; + + /* leave null keys alone */ + if ((p->key_low == 0) && (p->key_high == 0)) return; + + bcopy((char *)&(p->key_low), (char *)key, 4); + bcopy((char *)&(p->key_high), (char *)(((long *) key) + 1), 4); + +#ifndef NOENCRYPTION + des_pcbc_encrypt((des_cblock *)key,(des_cblock *)key, + (long)sizeof(des_cblock),master_key_schedule, + (des_cblock *)master_key_schedule,DECRYPT); +#endif + + /* make new key, new style */ + kdb_encrypt_key (key, key, master_key, master_key_schedule, ENCRYPT); + + bcopy((char *)key, (char *)&(p->key_low), 4); + bcopy((char *)(((long *) key) + 1), (char *)&(p->key_high), 4); + bzero((char *)key, sizeof (key)); /* a little paranoia ... */ +} + +void +convert_old_format_db (db_file, out) + char *db_file; + FILE *out; +{ + des_cblock key_from_db; + Principal principal_data[1]; + int n, more; + + if (kdb_get_master_key (TRUE, master_key, master_key_schedule) != 0L) { + fprintf (stderr, "verify_master_key: Couldn't get master key.\n"); + clear_secrets(); + exit (-1); + } + + /* can't call kdb_verify_master_key because this is an old style db */ + /* lookup the master key version */ + n = kerb_get_principal(KERB_M_NAME, KERB_M_INST, principal_data, + 1 /* only one please */, &more); + if ((n != 1) || more) { + fprintf(stderr, "verify_master_key: " + "Kerberos error on master key lookup, %d found.\n", + n); + exit (-1); + } + + /* set up the master key */ + fprintf(stderr, "Current Kerberos master key version is %d.\n", + principal_data[0].kdc_key_ver); + + /* + * now use the master key to decrypt (old style) the key in the db, had better + * be the same! + */ + bcopy((char *)&principal_data[0].key_low, (char *)key_from_db, 4); + bcopy((char *)&principal_data[0].key_high, + (char *)(((long *) key_from_db) + 1), 4); +#ifndef NOENCRYPTION + des_pcbc_encrypt((des_cblock *)key_from_db,(des_cblock *)key_from_db, + (long)sizeof(key_from_db),master_key_schedule, + (des_cblock *)master_key_schedule,DECRYPT); +#endif + /* the decrypted database key had better equal the master key */ + n = bcmp((char *) master_key, (char *) key_from_db, + sizeof(master_key)); + bzero((char *)key_from_db, sizeof(key_from_db)); + + if (n) { + fprintf(stderr, "\n\07\07verify_master_key: Invalid master key, "); + fprintf(stderr, "does not match database.\n"); + exit (-1); + } + + fprintf(stderr, "Master key verified.\n"); + (void) fflush(stderr); + + dump_db (db_file, out, convert_key_old_db); +} + +long +time_explode(cp) +register char *cp; +{ + char wbuf[5]; + struct tm tp; + long maketime(); + int local; + + zaptime(&tp); /* clear out the struct */ + + if (strlen(cp) > 10) { /* new format */ + (void) strncpy(wbuf, cp, 4); + wbuf[4] = 0; + tp.tm_year = atoi(wbuf); + cp += 4; /* step over the year */ + local = 0; /* GMT */ + } else { /* old format: local time, + year is 2 digits, assuming 19xx */ + wbuf[0] = *cp++; + wbuf[1] = *cp++; + wbuf[2] = 0; + tp.tm_year = 1900 + atoi(wbuf); + local = 1; /* local */ + } + + wbuf[0] = *cp++; + wbuf[1] = *cp++; + wbuf[2] = 0; + tp.tm_mon = atoi(wbuf)-1; + + wbuf[0] = *cp++; + wbuf[1] = *cp++; + tp.tm_mday = atoi(wbuf); + + wbuf[0] = *cp++; + wbuf[1] = *cp++; + tp.tm_hour = atoi(wbuf); + + wbuf[0] = *cp++; + wbuf[1] = *cp++; + tp.tm_min = atoi(wbuf); + + + return(maketime(&tp, local)); +} diff --git a/eBones/usr.sbin/kerberos/Makefile b/eBones/usr.sbin/kerberos/Makefile new file mode 100644 index 0000000000000..224b3350fdb45 --- /dev/null +++ b/eBones/usr.sbin/kerberos/Makefile @@ -0,0 +1,11 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.5 1995/09/13 17:24:28 markm Exp $ + +PROG= kerberos +SRCS= kerberos.c cr_err_reply.c +CFLAGS+=-DKERBEROS -DDEBUG +DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES} +LDADD= -lkdb -lkrb -ldes +NOMAN= noman + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/kerberos/cr_err_reply.c b/eBones/usr.sbin/kerberos/cr_err_reply.c new file mode 100644 index 0000000000000..89ee5f6cbfdba --- /dev/null +++ b/eBones/usr.sbin/kerberos/cr_err_reply.c @@ -0,0 +1,97 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: cr_err_reply.c,v 4.10 89/01/10 11:34:42 steiner Exp $ + * $Id: cr_err_reply.c,v 1.2 1995/07/18 16:37:49 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: cr_err_reply.c,v 1.2 1995/07/18 16:37:49 mark Exp $"; +#endif /* lint */ +#endif + +#include <sys/types.h> +#include <krb.h> +#include <prot.h> +#include <strings.h> + +extern int req_act_vno; /* this is defined in the kerberos + * server code */ + +/* + * This routine is used by the Kerberos authentication server to + * create an error reply packet to send back to its client. + * + * It takes a pointer to the packet to be built, the name, instance, + * and realm of the principal, the client's timestamp, an error code + * and an error string as arguments. Its return value is undefined. + * + * The packet is built in the following format: + * + * type variable data + * or constant + * ---- ----------- ---- + * + * unsigned char req_ack_vno protocol version number + * + * unsigned char AUTH_MSG_ERR_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 long e error code + * + * string e_string error text + */ + +void +cr_err_reply(pkt,pname,pinst,prealm,time_ws,e,e_string) + KTEXT pkt; + char *pname; /* Principal's name */ + char *pinst; /* Principal's instance */ + char *prealm; /* Principal's authentication domain */ + u_long time_ws; /* Workstation time */ + u_long e; /* Error code */ + char *e_string; /* Text of error */ +{ + u_char *v = (u_char *) pkt->dat; /* Prot vers number */ + u_char *t = (u_char *)(pkt->dat+1); /* Prot message type */ + + /* Create fixed part of packet */ + *v = (unsigned char) req_act_vno; /* KRB_PROT_VERSION; */ + *t = (unsigned char) AUTH_MSG_ERR_REPLY; + *t |= HOST_BYTE_ORDER; + + /* 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); + /* ws timestamp */ + bcopy((char *) &time_ws,(char *)(pkt->dat+pkt->length),4); + pkt->length += 4; + /* err code */ + bcopy((char *) &e,(char *)(pkt->dat+pkt->length),4); + pkt->length += 4; + /* err text */ + (void) strcpy((char *)(pkt->dat+pkt->length),e_string); + pkt->length += 1 + strlen(e_string); + + /* And return */ + return; +} diff --git a/eBones/usr.sbin/kerberos/kerberos.c b/eBones/usr.sbin/kerberos/kerberos.c new file mode 100644 index 0000000000000..236bbbdc116d8 --- /dev/null +++ b/eBones/usr.sbin/kerberos/kerberos.c @@ -0,0 +1,816 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology. + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: kerberos.c,v 4.19 89/11/01 17:18:07 qjb Exp $ + * $Id: kerberos.c,v 1.4 1995/07/18 16:37:51 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: kerberos.c,v 1.4 1995/07/18 16:37:51 mark Exp $"; +#endif lint +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#include <signal.h> +#include <sgtty.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/file.h> +#include <ctype.h> + +#include <krb.h> +#include <des.h> +#include <klog.h> +#include <prot.h> +#include <krb_db.h> +#include <kdc.h> + +void cr_err_reply(KTEXT pkt, char *pname, char *pinst, char *prealm, + u_long time_ws, u_long e, char *e_string); +void kerb_err_reply(struct sockaddr_in *client, KTEXT pkt, long err, + char *string); +void setup_disc(void); +void kerberos(struct sockaddr_in *client, KTEXT pkt); +int check_princ(char *p_name, char *instance, unsigned lifetime, Principal *p); +int set_tgtkey(char *r); + +struct sockaddr_in s_in = {AF_INET}; +int f; + +/* XXX several files in libkdb know about this */ +char *progname; + +static Key_schedule master_key_schedule; +static C_Block master_key; + +static struct timeval kerb_time; +static Principal a_name_data; /* for requesting user */ +static Principal s_name_data; /* for services requested */ +static C_Block session_key; +static u_char master_key_version; +static char k_instance[INST_SZ]; +static char *lt; +static int more; + +static int mflag; /* Are we invoked manually? */ +static int lflag; /* Have we set an alterate log file? */ +static char *log_file; /* name of alt. log file */ +static int nflag; /* don't check max age */ +static int rflag; /* alternate realm specified */ + +/* fields within the received request packet */ +static u_char req_msg_type; +static u_char req_version; +static char *req_name_ptr; +static char *req_inst_ptr; +static char *req_realm_ptr; +static u_long req_time_ws; + +int req_act_vno = KRB_PROT_VERSION; /* Temporary for version skew */ + +static char local_realm[REALM_SZ]; + +/* statistics */ +static long q_bytes; /* current bytes remaining in queue */ +static long q_n; /* how many consecutive non-zero + * q_bytes */ +static long max_q_bytes; +static long max_q_n; +static long n_auth_req; +static long n_appl_req; +static long n_packets; + +static long max_age = -1; +static long pause_int = -1; + +static void check_db_age(); +static void hang(); + +/* + * Print usage message and exit. + */ +static void usage() +{ + fprintf(stderr, "Usage: %s [-s] [-m] [-n] [-p pause_seconds]%s%s\n", progname, + " [-a max_age] [-l log_file] [-r realm]" + ," [database_pathname]" + ); + exit(1); +} + + +int +main(argc, argv) + int argc; + char **argv; +{ + struct sockaddr_in from; + register int n; + int on = 1; + int child; + struct servent *sp; + int fromlen; + static KTEXT_ST pkt_st; + KTEXT pkt = &pkt_st; + int kerror; + int c; + extern char *optarg; + extern int optind; + + progname = argv[0]; + + while ((c = getopt(argc, argv, "snmp:a:l:r:")) != EOF) { + switch(c) { + case 's': + /* + * Set parameters to slave server defaults. + */ + if (max_age == -1 && !nflag) + max_age = ONE_DAY; /* 24 hours */ + if (pause_int == -1) + pause_int = FIVE_MINUTES; /* 5 minutes */ + if (lflag == 0) { + log_file = KRBSLAVELOG; + lflag++; + } + break; + case 'n': + max_age = -1; /* don't check max age. */ + nflag++; + break; + case 'm': + mflag++; /* running manually; prompt for master key */ + break; + case 'p': + /* Set pause interval. */ + if (!isdigit(optarg[0])) + usage(); + pause_int = atoi(optarg); + if ((pause_int < 5) || (pause_int > ONE_HOUR)) { + fprintf(stderr, "pause_int must be between 5 and 3600 seconds.\n"); + usage(); + } + break; + case 'a': + /* Set max age. */ + if (!isdigit(optarg[0])) + usage(); + max_age = atoi(optarg); + if ((max_age < ONE_HOUR) || (max_age > THREE_DAYS)) { + fprintf(stderr, "max_age must be between one hour and three days, in seconds\n"); + usage(); + } + break; + case 'l': + /* Set alternate log file */ + lflag++; + log_file = optarg; + break; + case 'r': + /* Set realm name */ + rflag++; + strcpy(local_realm, optarg); + break; + default: + usage(); + break; + } + } + + if (optind == (argc-1)) { + if (kerb_db_set_name(argv[optind]) != 0) { + fprintf(stderr, "Could not set alternate database name\n"); + exit(1); + } + optind++; + } + + if (optind != argc) + usage(); + + printf("Kerberos server starting\n"); + + if ((!nflag) && (max_age != -1)) + printf("\tMaximum database age: %ld seconds\n", max_age); + if (pause_int != -1) + printf("\tSleep for %ld seconds on error\n", pause_int); + else + printf("\tSleep forever on error\n"); + if (mflag) + printf("\tMaster key will be entered manually\n"); + + printf("\tLog file is %s\n", lflag ? log_file : KRBLOG); + + if (lflag) + kset_logfile(log_file); + + /* find our hostname, and use it as the instance */ + if (gethostname(k_instance, INST_SZ)) { + fprintf(stderr, "%s: gethostname error\n", progname); + exit(1); + } + + if ((sp = getservbyname("kerberos", "udp")) == 0) { + fprintf(stderr, "%s: udp/kerberos unknown service\n", progname); + exit(1); + } + s_in.sin_port = sp->s_port; + + if ((f = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + fprintf(stderr, "%s: Can't open socket\n", progname); + exit(1); + } + if (setsockopt(f, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) + fprintf(stderr, "%s: setsockopt (SO_REUSEADDR)\n", progname); + + if (bind(f, (struct sockaddr *) &s_in, S_AD_SZ) < 0) { + fprintf(stderr, "%s: Can't bind socket\n", progname); + exit(1); + } + /* do all the database and cache inits */ + if ((n = kerb_init())) { + if (mflag) { + printf("Kerberos db and cache init "); + printf("failed = %d ...exiting\n", n); + exit(-1); + } else { + klog(L_KRB_PERR, + "Kerberos db and cache init failed = %d ...exiting", n); + hang(); + } + } + + /* Make sure database isn't stale */ + check_db_age(); + + /* setup master key */ + if (kdb_get_master_key (mflag, master_key, master_key_schedule) != 0) { + klog (L_KRB_PERR, "kerberos: couldn't get master key.\n"); + exit (-1); + } + kerror = kdb_verify_master_key (master_key, master_key_schedule, stdout); + if (kerror < 0) { + klog (L_KRB_PERR, "Can't verify master key."); + bzero (master_key, sizeof (master_key)); + bzero (master_key_schedule, sizeof (master_key_schedule)); + exit (-1); + } + + master_key_version = (u_char) kerror; + + fprintf(stdout, "\nCurrent Kerberos master key version is %d\n", + master_key_version); + + if (!rflag) { + /* Look up our local realm */ + krb_get_lrealm(local_realm, 1); + } + fprintf(stdout, "Local realm: %s\n", local_realm); + fflush(stdout); + + if (set_tgtkey(local_realm)) { + /* Ticket granting service unknown */ + klog(L_KRB_PERR, "Ticket granting ticket service unknown"); + fprintf(stderr, "Ticket granting ticket service unknown\n"); + exit(1); + } + if (mflag) { + if ((child = fork()) != 0) { + printf("Kerberos started, PID=%d\n", child); + exit(0); + } + setup_disc(); + } + /* receive loop */ + for (;;) { + fromlen = S_AD_SZ; + n = recvfrom(f, pkt->dat, MAX_PKT_LEN, 0, (struct sockaddr *) &from, + &fromlen); + if (n > 0) { + pkt->length = n; + pkt->mbz = 0; /* force zeros to catch runaway strings */ + /* see what is left in the input queue */ + ioctl(f, FIONREAD, &q_bytes); + gettimeofday(&kerb_time, NULL); + q_n++; + max_q_n = max(max_q_n, q_n); + n_packets++; + klog(L_NET_INFO, + "q_byt %d, q_n %d, rd_byt %d, mx_q_b %d, mx_q_n %d, n_pkt %d", + q_bytes, q_n, n, max_q_bytes, max_q_n, n_packets, 0); + max_q_bytes = max(max_q_bytes, q_bytes); + if (!q_bytes) + q_n = 0; /* reset consecutive packets */ + kerberos(&from, pkt); + } else + klog(L_NET_ERR, + "%s: bad recvfrom n = %d errno = %d", progname, n, errno, 0); + } +} + +void +kerberos(client, pkt) + struct sockaddr_in *client; + KTEXT pkt; +{ + static KTEXT_ST rpkt_st; + KTEXT rpkt = &rpkt_st; + static KTEXT_ST ciph_st; + KTEXT ciph = &ciph_st; + static KTEXT_ST tk_st; + KTEXT tk = &tk_st; + static KTEXT_ST auth_st; + KTEXT auth = &auth_st; + AUTH_DAT ad_st; + AUTH_DAT *ad = &ad_st; + + + static struct in_addr client_host; + static int msg_byte_order; + static int swap_bytes; + static u_char k_flags; + u_long lifetime; + int i; + C_Block key; + Key_schedule key_s; + char *ptr; + + + + ciph->length = 0; + + client_host = client->sin_addr; + + /* eval macros and correct the byte order and alignment as needed */ + req_version = pkt_version(pkt); /* 1 byte, version */ + req_msg_type = pkt_msg_type(pkt); /* 1 byte, Kerberos msg type */ + + req_act_vno = req_version; + + /* check packet version */ + if (req_version != KRB_PROT_VERSION) { + lt = klog(L_KRB_PERR, + "KRB prot version mismatch: KRB =%d request = %d", + KRB_PROT_VERSION, req_version, 0); + /* send an error reply */ + kerb_err_reply(client, pkt, KERB_ERR_PKT_VER, lt); + return; + } + msg_byte_order = req_msg_type & 1; + + swap_bytes = 0; + if (msg_byte_order != HOST_BYTE_ORDER) { + swap_bytes++; + } + klog(L_KRB_PINFO, + "Prot version: %d, Byte order: %d, Message type: %d", + req_version, msg_byte_order, req_msg_type); + + switch (req_msg_type & ~1) { + + case AUTH_MSG_KDC_REQUEST: + { + u_long req_life; /* Requested liftime */ + char *service; /* Service name */ + char *instance; /* Service instance */ + n_auth_req++; + tk->length = 0; + k_flags = 0; /* various kerberos flags */ + + + /* set up and correct for byte order and alignment */ + req_name_ptr = (char *) pkt_a_name(pkt); + req_inst_ptr = (char *) pkt_a_inst(pkt); + req_realm_ptr = (char *) pkt_a_realm(pkt); + bcopy(pkt_time_ws(pkt), &req_time_ws, sizeof(req_time_ws)); + /* time has to be diddled */ + if (swap_bytes) { + swap_u_long(req_time_ws); + } + ptr = (char *) pkt_time_ws(pkt) + 4; + + req_life = (u_long) (*ptr++); + + service = ptr; + instance = ptr + strlen(service) + 1; + + rpkt = &rpkt_st; + klog(L_INI_REQ, + "Initial ticket request Host: %s User: \"%s\" \"%s\"", + inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0); + + if ((i = check_princ(req_name_ptr, req_inst_ptr, 0, + &a_name_data))) { + kerb_err_reply(client, pkt, i, lt); + return; + } + tk->length = 0; /* init */ + if (strcmp(service, "krbtgt")) + klog(L_NTGT_INTK, + "INITIAL request from %s.%s for %s.%s", + req_name_ptr, req_inst_ptr, service, instance, 0); + /* this does all the checking */ + if ((i = check_princ(service, instance, lifetime, + &s_name_data))) { + kerb_err_reply(client, pkt, i, lt); + return; + } + /* Bound requested lifetime with service and user */ + lifetime = min(req_life, ((u_long) s_name_data.max_life)); + lifetime = min(lifetime, ((u_long) a_name_data.max_life)); + +#ifdef NOENCRYPTION + bzero(session_key, sizeof(C_Block)); +#else + random_key(session_key); +#endif + /* unseal server's key from master key */ + bcopy(&s_name_data.key_low, key, 4); + bcopy(&s_name_data.key_high, ((long *) key) + 1, 4); + kdb_encrypt_key(key, key, master_key, + master_key_schedule, DECRYPT); + /* construct and seal the ticket */ + krb_create_ticket(tk, k_flags, a_name_data.name, + a_name_data.instance, local_realm, + client_host.s_addr, session_key, lifetime, kerb_time.tv_sec, + s_name_data.name, s_name_data.instance, key); + bzero(key, sizeof(key)); + bzero(key_s, sizeof(key_s)); + + /* + * get the user's key, unseal it from the server's key, and + * use it to seal the cipher + */ + + /* a_name_data.key_low a_name_data.key_high */ + bcopy(&a_name_data.key_low, key, 4); + bcopy(&a_name_data.key_high, ((long *) key) + 1, 4); + + /* unseal the a_name key from the master key */ + kdb_encrypt_key(key, key, master_key, + master_key_schedule, DECRYPT); + + create_ciph(ciph, session_key, s_name_data.name, + s_name_data.instance, local_realm, lifetime, + s_name_data.key_version, tk, kerb_time.tv_sec, key); + + /* clear session key */ + bzero(session_key, sizeof(session_key)); + + bzero(key, sizeof(key)); + + + + /* always send a reply packet */ + rpkt = create_auth_reply(req_name_ptr, req_inst_ptr, + req_realm_ptr, req_time_ws, 0, a_name_data.exp_date, + a_name_data.key_version, ciph); + sendto(f, rpkt->dat, rpkt->length, 0, (struct sockaddr *) client, + S_AD_SZ); + bzero(&a_name_data, sizeof(a_name_data)); + bzero(&s_name_data, sizeof(s_name_data)); + break; + } + case AUTH_MSG_APPL_REQUEST: + { + u_long time_ws; /* Workstation time */ + u_long req_life; /* Requested liftime */ + char *service; /* Service name */ + char *instance; /* Service instance */ + int kerno; /* Kerberos error number */ + char tktrlm[REALM_SZ]; + + n_appl_req++; + tk->length = 0; + k_flags = 0; /* various kerberos flags */ + + auth->length = 4 + strlen(pkt->dat + 3); + auth->length += (int) *(pkt->dat + auth->length) + + (int) *(pkt->dat + auth->length + 1) + 2; + + bcopy(pkt->dat, auth->dat, auth->length); + + strncpy(tktrlm, auth->dat + 3, REALM_SZ); + if (set_tgtkey(tktrlm)) { + lt = klog(L_ERR_UNK, + "FAILED realm %s unknown. Host: %s ", + tktrlm, inet_ntoa(client_host)); + kerb_err_reply(client, pkt, kerno, lt); + return; + } + kerno = krb_rd_req(auth, "ktbtgt", tktrlm, client_host.s_addr, + ad, 0); + + if (kerno) { + klog(L_ERR_UNK, "FAILED krb_rd_req from %s: %s", + inet_ntoa(client_host), krb_err_txt[kerno]); + kerb_err_reply(client, pkt, kerno, "krb_rd_req failed"); + return; + } + ptr = (char *) pkt->dat + auth->length; + + bcopy(ptr, &time_ws, 4); + ptr += 4; + + req_life = (u_long) (*ptr++); + + service = ptr; + instance = ptr + strlen(service) + 1; + + klog(L_APPL_REQ, "APPL Request %s.%s@%s on %s for %s.%s", + ad->pname, ad->pinst, ad->prealm, inet_ntoa(client_host), + service, instance, 0); + + if (strcmp(ad->prealm, tktrlm)) { + kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN, + "Can't hop realms"); + return; + } + if (!strcmp(service, "changepw")) { + kerb_err_reply(client, pkt, KERB_ERR_PRINCIPAL_UNKNOWN, + "Can't authorize password changed based on TGT"); + return; + } + kerno = check_princ(service, instance, req_life, + &s_name_data); + if (kerno) { + kerb_err_reply(client, pkt, kerno, lt); + return; + } + /* Bound requested lifetime with service and user */ + lifetime = min(req_life, + (ad->life - ((kerb_time.tv_sec - ad->time_sec) / 300))); + lifetime = min(lifetime, ((u_long) s_name_data.max_life)); + + /* unseal server's key from master key */ + bcopy(&s_name_data.key_low, key, 4); + bcopy(&s_name_data.key_high, ((long *) key) + 1, 4); + kdb_encrypt_key(key, key, master_key, + master_key_schedule, DECRYPT); + /* construct and seal the ticket */ + +#ifdef NOENCRYPTION + bzero(session_key, sizeof(C_Block)); +#else + random_key(session_key); +#endif + + krb_create_ticket(tk, k_flags, ad->pname, ad->pinst, + ad->prealm, client_host.s_addr, + session_key, lifetime, kerb_time.tv_sec, + s_name_data.name, s_name_data.instance, + key); + bzero(key, sizeof(key)); + bzero(key_s, sizeof(key_s)); + + create_ciph(ciph, session_key, service, instance, + local_realm, + lifetime, s_name_data.key_version, tk, + kerb_time.tv_sec, ad->session); + + /* clear session key */ + bzero(session_key, sizeof(session_key)); + + bzero(ad->session, sizeof(ad->session)); + + rpkt = create_auth_reply(ad->pname, ad->pinst, + ad->prealm, time_ws, + 0, 0, 0, ciph); + sendto(f, rpkt->dat, rpkt->length, 0, (struct sockaddr *) client, + S_AD_SZ); + bzero(&s_name_data, sizeof(s_name_data)); + break; + } + + +#ifdef notdef_DIE + case AUTH_MSG_DIE: + { + lt = klog(L_DEATH_REQ, + "Host: %s User: \"%s\" \"%s\" Kerberos killed", + inet_ntoa(client_host), req_name_ptr, req_inst_ptr, 0); + exit(0); + } +#endif notdef_DIE + + default: + { + lt = klog(L_KRB_PERR, + "Unknown message type: %d from %s port %u", + req_msg_type, inet_ntoa(client_host), + ntohs(client->sin_port)); + break; + } + } +} + + +/* + * setup_disc + * + * disconnect all descriptors, remove ourself from the process + * group that spawned us. + */ + +void +setup_disc() +{ + + int s; + + for (s = 0; s < 3; s++) { + (void) close(s); + } + + (void) open("/dev/null", 0); + (void) dup2(0, 1); + (void) dup2(0, 2); + + s = open("/dev/tty", 2); + + if (s >= 0) { + ioctl(s, TIOCNOTTY, (struct sgttyb *) 0); + (void) close(s); + } + (void) chdir("/tmp"); +} + + +/* + * kerb_er_reply creates an error reply packet and sends it to the + * client. + */ + +void +kerb_err_reply(client, pkt, err, string) + struct sockaddr_in *client; + KTEXT pkt; + long err; + char *string; + +{ + static KTEXT_ST e_pkt_st; + KTEXT e_pkt = &e_pkt_st; + static char e_msg[128]; + + strcpy(e_msg, "\nKerberos error -- "); + strcat(e_msg, string); + cr_err_reply(e_pkt, req_name_ptr, req_inst_ptr, req_realm_ptr, + req_time_ws, err, e_msg); + sendto(f, e_pkt->dat, e_pkt->length, 0, (struct sockaddr *) client, + S_AD_SZ); + +} + +/* + * Make sure that database isn't stale. + * + * Exit if it is; we don't want to tell lies. + */ + +static void check_db_age() +{ + long age; + + if (max_age != -1) { + /* Requires existance of kerb_get_db_age() */ + gettimeofday(&kerb_time, 0); + age = kerb_get_db_age(); + if (age == 0) { + klog(L_KRB_PERR, "Database currently being updated!"); + hang(); + } + if ((age + max_age) < kerb_time.tv_sec) { + klog(L_KRB_PERR, "Database out of date!"); + hang(); + /* NOTREACHED */ + } + } +} + +int +check_princ(p_name, instance, lifetime, p) + char *p_name; + char *instance; + unsigned lifetime; + + Principal *p; +{ + static int n; + static int more; + + n = kerb_get_principal(p_name, instance, p, 1, &more); + klog(L_ALL_REQ, + "Principal: \"%s\", Instance: \"%s\" Lifetime = %d n = %d", + p_name, instance, lifetime, n, 0); + + if (n < 0) { + lt = klog(L_KRB_PERR, "Database unavailable!"); + hang(); + } + + /* + * if more than one p_name, pick one, randomly create a session key, + * compute maximum lifetime, lookup authorizations if applicable, + * and stuff into cipher. + */ + if (n == 0) { + /* service unknown, log error, skip to next request */ + lt = klog(L_ERR_UNK, "UNKNOWN \"%s\" \"%s\"", p_name, + instance, 0); + return KERB_ERR_PRINCIPAL_UNKNOWN; + } + if (more) { + /* not unique, log error */ + lt = klog(L_ERR_NUN, "Principal NOT UNIQUE \"%s\" \"%s\"", + p_name, instance, 0); + return KERB_ERR_PRINCIPAL_NOT_UNIQUE; + } + /* If the user's key is null, we want to return an error */ + if ((p->key_low == 0) && (p->key_high == 0)) { + /* User has a null key */ + lt = klog(L_ERR_NKY, "Null key \"%s\" \"%s\"", p_name, + instance, 0); + return KERB_ERR_NULL_KEY; + } + if (master_key_version != p->kdc_key_ver) { + /* log error reply */ + lt = klog(L_ERR_MKV, + "Key vers incorrect, KRB = %d, \"%s\" \"%s\" = %d", + master_key_version, p->name, p->instance, p->kdc_key_ver, + 0); + return KERB_ERR_NAME_MAST_KEY_VER; + } + /* make sure the service hasn't expired */ + if ((u_long) p->exp_date < (u_long) kerb_time.tv_sec) { + /* service did expire, log it */ + lt = klog(L_ERR_SEXP, + "EXPIRED \"%s\" \"%s\" %s", p->name, p->instance, + stime(&(p->exp_date)), 0); + return KERB_ERR_NAME_EXP; + } + /* ok is zero */ + return 0; +} + + +/* Set the key for krb_rd_req so we can check tgt */ +int +set_tgtkey(r) + char *r; /* Realm for desired key */ +{ + int n; + static char lastrealm[REALM_SZ]; + Principal p_st; + Principal *p = &p_st; + C_Block key; + + if (!strcmp(lastrealm, r)) + return (KSUCCESS); + + log("Getting key for %s", r); + + n = kerb_get_principal("krbtgt", r, p, 1, &more); + if (n == 0) + return (KFAILURE); + + /* unseal tgt key from master key */ + bcopy(&p->key_low, key, 4); + bcopy(&p->key_high, ((long *) key) + 1, 4); + kdb_encrypt_key(key, key, master_key, + master_key_schedule, DECRYPT); + krb_set_key(key, 0); + strcpy(lastrealm, r); + return (KSUCCESS); +} + +static void +hang() +{ + if (pause_int == -1) { + klog(L_KRB_PERR, "Kerberos will pause so as not to loop init"); + for (;;) + pause(); + } else { + char buf[256]; + sprintf(buf, "Kerberos will wait %ld seconds before dying so as not to loop init", pause_int); + klog(L_KRB_PERR, buf); + sleep(pause_int); + klog(L_KRB_PERR, "Do svedania....\n"); + exit(1); + } +} diff --git a/eBones/usr.sbin/kprop/Makefile b/eBones/usr.sbin/kprop/Makefile new file mode 100644 index 0000000000000..d6063a6b08379 --- /dev/null +++ b/eBones/usr.sbin/kprop/Makefile @@ -0,0 +1,9 @@ +# From: @(#)Makefile 5.1 (Berkeley) 6/25/90 +# $Id: Makefile,v 1.4 1995/09/13 17:24:29 markm Exp $ + +PROG= kprop +DPADD= ${LIBKRB} ${LIBDES} +LDADD= -lkrb -ldes +NOMAN= noman + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/kprop/kprop.c b/eBones/usr.sbin/kprop/kprop.c new file mode 100644 index 0000000000000..23bb893d2703a --- /dev/null +++ b/eBones/usr.sbin/kprop/kprop.c @@ -0,0 +1,637 @@ +/* + * + * Copyright 1987 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, + * please see the file <mit-copyright.h>. + * + * $Revision: 1.1.1.1 $ + * $Date: 1995/08/03 07:36:18 $ + * $State: Exp $ + * $Source: /usr/cvs/src/eBones/kprop/kprop.c,v $ + * $Author: mark $ + * $Locker: $ + * + * $Log: kprop.c,v $ + * Revision 1.1.1.1 1995/08/03 07:36:18 mark + * Import an updated revision of the MIT kprop program for distributing + * kerberos databases to slave servers. + * + * NOTE: This method was abandoned by MIT long ago, this code is close to + * garbage, but it is slightly more secure than using rdist. + * There is no documentation available on how to use it, and + * it should -not- be built by default. + * + * Obtained from: MIT Project Athena + * + * Revision 1.1.1.1 1995/08/02 22:11:44 pst + * Import an updated revision of the MIT kprop program for distributing + * kerberos databases to slave servers. + * + * NOTE: This method was abandoned by MIT long ago, this code is close to + * garbage, but it is slightly more secure than using rdist. + * There is no documentation available on how to use it, and + * it should -not- be built by default. + * + * Obtained from: MIT Project Athena + * + * Revision 4.7 92/11/10 23:01:06 tytso + * Removed incompatible #include + * + * Revision 4.6 91/02/28 22:49:34 probe + * Fixed header file inclusion + * + * Revision 4.5 90/03/20 15:37:57 jon + * Stop kpropd port number from being bashed (static buffers) + * Programmer: jtkohl + * Auditor: jon + * + * Revision 4.4 90/01/02 13:42:40 jtkohl + * add back in accidentally deleted $ in rcsid string + * + * Revision 4.3 89/12/30 21:22:27 qjb + * Added #define MAXHOSTNAMELEN if not already defined for the benifit + * of Unixes that don't have this variable in sys/param.h. + * + * Revision 4.2 89/03/23 10:23:43 jtkohl + * fix misuse of mkstemp to use mktemp + * NOENCRYPTION changes + * + * Revision 4.1 89/01/24 20:35:17 root + * name change + * + * Revision 4.0 89/01/24 18:44:38 wesommer + * Original version; programmer: wesommer + * auditor: jon. + * + * Revision 4.4 88/01/08 18:05:21 jon + * formating changes and rcs header info + * + * + */ + +#if 0 +#ifndef lint +static char rcsid_kprop_c[] = +"$Id: kprop.c,v 1.1.1.1 1995/08/03 07:36:18 mark Exp $"; +#endif lint +#endif + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <sys/types.h> +#include <sys/file.h> +#include <signal.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/param.h> +#include <netdb.h> +#include <krb.h> +#include <des.h> + +#include "kprop.h" + +/* for those broken Unixes without this defined... should be in sys/param.h */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +static char kprop_version[KPROP_PROT_VERSION_LEN] = KPROP_PROT_VERSION; + +int debug = 0; + +char my_realm[REALM_SZ]; +int princ_data_size = 3 * sizeof(long) + 3 * sizeof(unsigned char); +short transfer_mode, net_transfer_mode; +int force_flag; +static char ok[] = ".dump_ok"; + +extern char *krb_get_phost(char *); + +struct slave_host { + u_long net_addr; + char *name; + char *instance; + char *realm; + int not_time_yet; + int succeeded; + struct slave_host *next; +}; + +void Death(char *s); +int get_slaves(struct slave_host **psl, char *file, time_t ok_mtime); +int prop_to_slaves(struct slave_host *sl, int fd, char *fslv); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + int fd, i; + char *floc, *floc_ok; + char *fslv; + struct stat stbuf, stbuf_ok; + long l_init, l_final; + char *pc; + int l_diff; + static struct slave_host *slave_host_list = NULL; + struct slave_host *sh; + + transfer_mode = KPROP_TRANSFER_PRIVATE; + + time(&l_init); + pc = ctime(&l_init); + pc[strlen(pc) - 1] = '\0'; + printf("\nStart slave propagation: %s\n", pc); + + floc = (char *) NULL; + fslv = (char *) NULL; + + if (krb_get_lrealm(my_realm,1) != KSUCCESS) + Death ("Getting my kerberos realm. Check krb.conf"); + + for (i = 1; i < argc; i++) + switch (argv[i][0]) { + case '-': + if (strcmp (argv[i], "-private") == 0) + transfer_mode = KPROP_TRANSFER_PRIVATE; +#ifdef not_safe_yet + else if (strcmp (argv[i], "-safe") == 0) + transfer_mode = KPROP_TRANSFER_SAFE; + else if (strcmp (argv[i], "-clear") == 0) + transfer_mode = KPROP_TRANSFER_CLEAR; +#endif + else if (strcmp (argv[i], "-realm") == 0) { + i++; + if (i < argc) + strcpy(my_realm, argv[i]); + else + goto usage; + } else if (strcmp (argv[i], "-force") == 0) + force_flag++; + else { + fprintf (stderr, "kprop: unknown control argument %s.\n", + argv[i]); + exit (1); + } + break; + default: + /* positional arguments are marginal at best ... */ + if (floc == (char *) NULL) + floc = argv[i]; + else { + if (fslv == (char *) NULL) + fslv = argv[i]; + else { + usage: + /* already got floc and fslv, what is this? */ + fprintf(stderr, + "\nUsage: kprop [-force] [-realm realm] [-private|-safe|-clear] data_file slaves_file\n\n"); + exit(1); + } + } + } + if ((floc == (char *)NULL) || (fslv == (char *)NULL)) + goto usage; + + if ((floc_ok = (char *) malloc(strlen(floc) + strlen(ok) + 1)) + == NULL) { + Death(floc); + } + strcat(strcpy(floc_ok, floc), ok); + + if ((fd = open(floc, O_RDONLY)) < 0) { + Death(floc); + } + if (flock(fd, LOCK_EX | LOCK_NB)) { + Death(floc); + } + if (stat(floc, &stbuf)) { + Death(floc); + } + if (stat(floc_ok, &stbuf_ok)) { + Death(floc_ok); + } + if (stbuf.st_mtime > stbuf_ok.st_mtime) { + fprintf(stderr, "kprop: '%s' more recent than '%s'.\n", + floc, floc_ok); + exit(1); + } + if (!get_slaves(&slave_host_list, fslv, stbuf_ok.st_mtime)) { + fprintf(stderr, + "kprop: can't read slave host file '%s'.\n", fslv); + exit(1); + } +#ifdef KPROP_DBG + { + struct slave_host *sh; + int i; + fprintf(stderr, "\n\n"); + fflush(stderr); + for (sh = slave_host_list; sh; sh = sh->next) { + fprintf(stderr, "slave %d: %s, %s", i++, sh->name, + inet_ntoa(sh->net_addr)); + fflush(stderr); + } + } +#endif /* KPROP_DBG */ + + if (!prop_to_slaves(slave_host_list, fd, fslv)) { + fprintf(stderr, + "kprop: propagation failed.\n"); + exit(1); + } + if (flock(fd, LOCK_UN)) { + Death(floc); + } + fprintf(stderr, "\n\n"); + for (sh = slave_host_list; sh; sh = sh->next) { + fprintf(stderr, "%s:\t\t%s\n", sh->name, + (sh->not_time_yet? "Not time yet" : (sh->succeeded ? "Succeeded" : "FAILED"))); + } + + time(&l_final); + l_diff = l_final - l_init; + printf("propagation finished, %d:%02d:%02d elapsed\n", + l_diff / 3600, (l_diff % 3600) / 60, l_diff % 60); + + exit(0); +} + +void +Death(s) + char *s; +{ + fprintf(stderr, "kprop: "); + perror(s); + exit(1); +} + +/* The master -> slave protocol looks like this: + 1) 8 byte version string + 2) 2 bytes of "transfer mode" (net byte order of course) + 3) ticket/authentication send by sendauth + 4) 4 bytes of "block" length (u_long) + 5) data + + 4 and 5 repeat til EOF ... +*/ + +int +prop_to_slaves(sl, fd, fslv) + struct slave_host *sl; + int fd; + char *fslv; +{ + char buf[KPROP_BUFSIZ]; + char obuf[KPROP_BUFSIZ + 64 /* leave room for private msg overhead */ ]; + struct servent *sp; + struct sockaddr_in sin, my_sin; + int i, n, s; + struct slave_host *cs; /* current slave */ + char path[256], my_host_name[MAXHOSTNAMELEN], *p_my_host_name; + char kprop_service_instance[INST_SZ]; + char *pc; + u_long cksum, get_data_checksum(); + u_long length, nlength; + long kerror; + KTEXT_ST ticket; + CREDENTIALS cred; + MSG_DAT msg_dat; + static char tkstring[] = "/tmp/kproptktXXXXXX"; + + Key_schedule session_sched; + + (void) mktemp(tkstring); + krb_set_tkt_string(tkstring); + + if ((sp = getservbyname("krb_prop", "tcp")) == 0) { + fprintf(stderr, "tcp/krb_prop: service unknown.\n"); + exit(1); + } + + bzero(&sin, sizeof sin); + sin.sin_family = AF_INET; + sin.sin_port = sp->s_port; + + strcpy(path, fslv); + if ((pc = rindex(path, '/'))) { + pc += 1; + } else { + pc = path; + } + + for (i = 0; i < 5; i++) { /* try each slave five times max */ + for (cs = sl; cs; cs = cs->next) { + if (!cs->succeeded) { + if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0) { + perror("kprop: socket"); + exit(1); + } + bcopy(&cs->net_addr, &sin.sin_addr, + sizeof cs->net_addr); + + if (connect(s, (struct sockaddr *) &sin, sizeof sin) < 0) { + fprintf(stderr, "%s: ", cs->name); + perror("connect"); + close(s); + continue; /*** NEXT SLAVE ***/ + } + + /* for krb_mk_{priv, safe} */ + bzero (&my_sin, sizeof my_sin); + n = sizeof my_sin; + if (getsockname (s, (struct sockaddr *) &my_sin, &n) != 0) { + fprintf (stderr, "kprop: can't get socketname."); + perror ("getsockname"); + close (s); + continue; /*** NEXT SLAVE ***/ + } + if (n != sizeof (my_sin)) { + fprintf (stderr, "kprop: can't get socketname. len"); + close (s); + continue; /*** NEXT SLAVE ***/ + } + + /* Get ticket */ + kerror = krb_mk_req (&ticket, KPROP_SERVICE_NAME, + cs->instance, cs->realm, (u_long) 0); + /* if ticket has expired try to get a new one, but + * first get a TGT ... + */ + if (kerror != MK_AP_OK) { + if (gethostname (my_host_name, sizeof(my_host_name)) != 0) { + fprintf (stderr, "%s:", cs->name); + perror ("getting my hostname"); + close (s); + break; /* next one can't work either! */ + } + /* get canonical kerberos service instance name */ + p_my_host_name = krb_get_phost (my_host_name); + /* copy it to make sure gethostbyname static doesn't + * screw us. */ + strcpy (kprop_service_instance, p_my_host_name); + kerror = krb_get_svc_in_tkt (KPROP_SERVICE_NAME, +#if 0 + kprop_service_instance, +#else + KRB_MASTER, +#endif + my_realm, + TGT_SERVICE_NAME, + my_realm, + 96, + KPROP_SRVTAB); + if (kerror != INTK_OK) { + fprintf (stderr, + "%s: %s. While getting initial ticket\n", + cs->name, krb_err_txt[kerror]); + close (s); + goto punt; + } + kerror = krb_mk_req (&ticket, KPROP_SERVICE_NAME, + cs->instance, cs->realm, (u_long) 0); + } + if (kerror != MK_AP_OK) { + fprintf (stderr, "%s: %s. Calling krb_mk_req.", + cs->name, krb_err_txt[kerror]); + close (s); + continue; /*** NEXT SLAVE ***/ + } + + if (write(s, kprop_version, sizeof(kprop_version)) + != sizeof(kprop_version)) { + fprintf (stderr, "%s: ", cs->name); + perror ("write (version) error"); + close (s); + continue; /*** NEXT SLAVE ***/ + } + + net_transfer_mode = htons (transfer_mode); + if (write(s, &net_transfer_mode, sizeof(net_transfer_mode)) + != sizeof(net_transfer_mode)) { + fprintf (stderr, "%s: ", cs->name); + perror ("write (transfer_mode) error"); + close (s); + continue; /*** NEXT SLAVE ***/ + } + + kerror = krb_get_cred (KPROP_SERVICE_NAME, cs->instance, + cs->realm, &cred); + if (kerror != KSUCCESS) { + fprintf (stderr, "%s: %s. Getting session key.", + cs->name, krb_err_txt[kerror]); + close (s); + continue; /*** NEXT SLAVE ***/ + } +#ifdef NOENCRYPTION + bzero((char *)session_sched, sizeof(session_sched)); +#else + if (key_sched ((C_Block *)cred.session, session_sched)) { + fprintf (stderr, "%s: can't make key schedule.", + cs->name); + close (s); + continue; /*** NEXT SLAVE ***/ + } +#endif + /* SAFE (quad_cksum) and CLEAR are just not good enough */ + cksum = 0; +#ifdef not_working_yet + if (transfer_mode != KPROP_TRANSFER_PRIVATE) { + cksum = get_data_checksum(fd, session_sched); + lseek(fd, 0L, 0); + } + else +#endif + { + struct stat st; + fstat (fd, &st); + cksum = st.st_size; + } + kerror = krb_sendauth(KOPT_DO_MUTUAL, + s, + &ticket, + KPROP_SERVICE_NAME, + cs->instance, + cs->realm, + cksum, + &msg_dat, + &cred, + session_sched, + &my_sin, + &sin, + KPROP_PROT_VERSION); + if (kerror != KSUCCESS) { + fprintf (stderr, "%s: %s. Calling krb_sendauth.", + cs->name, krb_err_txt[kerror]); + close (s); + continue; /*** NEXT SLAVE ***/ + } + + while ((n = read(fd, buf, sizeof buf))) { + if (n < 0) { + perror("input file read error"); + exit(1); + } + switch (transfer_mode) { + case KPROP_TRANSFER_PRIVATE: + case KPROP_TRANSFER_SAFE: + if (transfer_mode == KPROP_TRANSFER_PRIVATE) + length = krb_mk_priv (buf, obuf, n, + session_sched, cred.session, + &my_sin, &sin); + else + length = krb_mk_safe (buf, obuf, n, + (C_Block *)cred.session, + &my_sin, &sin); + if (length == -1) { + fprintf (stderr, "%s: %s failed.", + cs->name, + (transfer_mode == KPROP_TRANSFER_PRIVATE) + ? "krb_rd_priv" : "krb_rd_safe"); + close (s); + continue; /*** NEXT SLAVE ***/ + } + nlength = htonl(length); + if (write(s, &nlength, sizeof nlength) + != sizeof nlength) { + fprintf (stderr, "%s: ", cs->name); + perror ("write error"); + close (s); + continue; /*** NEXT SLAVE ***/ + } + if (write(s, obuf, length) != length) { + fprintf(stderr, "%s: ", cs->name); + perror("write error"); + close(s); + continue; /*** NEXT SLAVE ***/ + } + break; + case KPROP_TRANSFER_CLEAR: + if (write(s, buf, n) != n) { + fprintf(stderr, "%s: ", cs->name); + perror("write error"); + close(s); + continue; /*** NEXT SLAVE ***/ + } + break; + } + } + close(s); + cs->succeeded = 1; + fprintf(stderr, "%s: success.\n", cs->name); + strcat(strcpy(pc, cs->name), "-last-prop"); + close(creat(path, 0600)); + } + } + } +punt: + + dest_tkt(); + for (cs = sl; cs; cs = cs->next) { + if (!cs->succeeded) + return (0); /* didn't get this slave */ + } + return (1); +} + +int +get_slaves(psl, file, ok_mtime) + struct slave_host **psl; + char *file; + time_t ok_mtime; +{ + FILE *fin; + char namebuf[128], *inst; + char *pc; + struct hostent *host; + struct slave_host **th; + char path[256]; + char *ppath; + struct stat stbuf; + + if ((fin = fopen(file, "r")) == NULL) { + fprintf(stderr, "Can't open slave host file, '%s'.\n", file); + exit(-1); + } + strcpy(path, file); + if ((ppath = rindex(path, '/'))) { + ppath += 1; + } else { + ppath = path; + } + for (th = psl; fgets(namebuf, sizeof namebuf, fin); th = &(*th)->next) { + if ((pc = index(namebuf, '\n'))) { + *pc = '\0'; + } else { + fprintf(stderr, "Host name too long (>= %d chars) in '%s'.\n", + sizeof namebuf, file); + exit(-1); + } + host = gethostbyname(namebuf); + if (host == NULL) { + fprintf(stderr, "Unknown host '%s' in '%s'.\n", namebuf, file); + exit(-1); + } + (*th) = (struct slave_host *) malloc(sizeof(struct slave_host)); + if (!*th) { + fprintf(stderr, "No memory reading host list from '%s'.\n", + file); + exit(-1); + } + (*th)->name = malloc(strlen(namebuf) + 1); + if (!(*th)->name) { + fprintf(stderr, "No memory reading host list from '%s'.\n", + file); + exit(-1); + } + /* get kerberos cannonical instance name */ + strcpy((*th)->name, namebuf); + inst = krb_get_phost ((*th)->name); + (*th)->instance = malloc(strlen(inst) + 1); + if (!(*th)->instance) { + fprintf(stderr, "No memory reading host list from '%s'.\n", + file); + exit(-1); + } + strcpy((*th)->instance, inst); + /* what a concept, slave servers in different realms! */ + (*th)->realm = my_realm; + (*th)->net_addr = *(u_long *) host->h_addr; + (*th)->succeeded = 0; + (*th)->next = NULL; + strcat(strcpy(ppath, (*th)->name), "-last-prop"); + if (!force_flag && !stat(path, &stbuf) && stbuf.st_mtime > ok_mtime) { + (*th)->not_time_yet = 1; + (*th)->succeeded = 1; /* no change since last success */ + } + } + fclose(fin); + return (1); +} + +#ifdef doesnt_work_yet +u_long get_data_checksum(fd, key_sched) + int fd; + Key_schedule key_sched; +{ + unsigned long cksum = 0; + unsigned long cbc_cksum(); + int n; + char buf[BUFSIZ]; + long obuf[2]; + + while (n = read(fd, buf, sizeof buf)) { + if (n < 0) { + fprintf(stderr, "Input data file read error: "); + perror("read"); + exit(1); + } + cksum = cbc_cksum(buf, obuf, n, key_sched, key_sched); + } + return cksum; +} +#endif diff --git a/eBones/usr.sbin/kprop/kprop.h b/eBones/usr.sbin/kprop/kprop.h new file mode 100644 index 0000000000000..5197276fc0d76 --- /dev/null +++ b/eBones/usr.sbin/kprop/kprop.h @@ -0,0 +1,55 @@ +/* + * Copyright 1987 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, + * please see the file <mit-copyright.h>. + * + * $Revision: 1.1.1.1 $ + * $Date: 1995/08/03 07:36:18 $ + * $State: Exp $ + * $Source: /usr/cvs/src/eBones/kprop/kprop.h,v $ + * $Author: mark $ + * $Locker: $ + * + * $Log: kprop.h,v $ + * Revision 1.1.1.1 1995/08/03 07:36:18 mark + * Import an updated revision of the MIT kprop program for distributing + * kerberos databases to slave servers. + * + * NOTE: This method was abandoned by MIT long ago, this code is close to + * garbage, but it is slightly more secure than using rdist. + * There is no documentation available on how to use it, and + * it should -not- be built by default. + * + * Obtained from: MIT Project Athena + * + * Revision 1.1.1.1 1995/08/02 22:11:44 pst + * Import an updated revision of the MIT kprop program for distributing + * kerberos databases to slave servers. + * + * NOTE: This method was abandoned by MIT long ago, this code is close to + * garbage, but it is slightly more secure than using rdist. + * There is no documentation available on how to use it, and + * it should -not- be built by default. + * + * Obtained from: MIT Project Athena + * + * Revision 4.1 92/10/23 15:45:13 tytso + * Change the location of KPROP_KDBUTIL to be /kerberos/bin/kdb_util. + * + * Revision 4.0 89/01/24 18:44:46 wesommer + * Original version; programmer: wesommer + * auditor: jon + * + */ + +#define KPROP_SERVICE_NAME "rcmd" +#define KPROP_SRVTAB "/etc/kerberosIV/srvtab" +#define TGT_SERVICE_NAME "krbtgt" +#define KPROP_PROT_VERSION_LEN 8 +#define KPROP_PROT_VERSION "kprop01" +#define KPROP_TRANSFER_PRIVATE 1 +#define KPROP_TRANSFER_SAFE 2 +#define KPROP_TRANSFER_CLEAR 3 +#define KPROP_BUFSIZ 32768 +#define KPROP_KDB_UTIL "/usr/sbin/kdb_util" diff --git a/eBones/usr.sbin/ksrvutil/Makefile b/eBones/usr.sbin/ksrvutil/Makefile new file mode 100644 index 0000000000000..199cf48b02db1 --- /dev/null +++ b/eBones/usr.sbin/ksrvutil/Makefile @@ -0,0 +1,10 @@ +# $Id: Makefile,v 1.4 1995/09/13 17:24:34 markm Exp $ + +PROG= ksrvutil +SRCS= ksrvutil.c +CFLAGS+= -I${.CURDIR}/../../lib/libkadm +DPADD= ${LIBKRB} ${LIBDES} +LDADD+= -lkadm -lkrb -ldes -lcom_err +MAN8= ksrvutil.8 + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/ksrvutil/ksrvutil.c b/eBones/usr.sbin/ksrvutil/ksrvutil.c new file mode 100644 index 0000000000000..1062ea5cc9380 --- /dev/null +++ b/eBones/usr.sbin/ksrvutil/ksrvutil.c @@ -0,0 +1,582 @@ +/* + * Copyright 1989 by the Massachusetts Institute of Technology. + * + * For copying and distribution information, please see the file + * Copyright.MIT. + * + * list and update contents of srvtab files + */ + +#if 0 +#ifndef lint +static char rcsid_ksrvutil_c[] = +"BonesHeader: /afs/athena.mit.edu/astaff/project/kerberos/src/kadmin/RCS/ksrvutil.c,v 4.1 89/09/26 09:33:49 jtkohl Exp "; +static const char rcsid[] = + "$Id: ksrvutil.c,v 1.1 1995/07/18 16:40:11 mark Exp $"; +#endif lint +#endif + +/* + * ksrvutil + * list and update the contents of srvtab files + */ + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/file.h> +#include <sys/param.h> +#include <stdio.h> +#include <sys/stat.h> +#include <errno.h> +#include <kadm.h> +#include <err.h> +#include <com_err.h> + +#ifdef NOENCRYPTION +#define read_long_pw_string placebo_read_pw_string +#else /* NOENCRYPTION */ +#define read_long_pw_string des_read_pw_string +#endif /* NOENCRYPTION */ +int read_long_pw_string(); + +#define SRVTAB_MODE 0600 /* rw------- */ +#define PAD " " +#define VNO_HEADER "Version" +#define VNO_FORMAT "%4d " +#define KEY_HEADER " Key " /* 17 characters long */ +#define PRINC_HEADER " Principal\n" +#define PRINC_FORMAT "%s" + +void usage(void); +void leave(char *str, int x); +void get_key_from_password(des_cblock key); +void print_name(char *name, char *inst, char *realm); +void print_key(des_cblock key); +unsigned short get_mode(char *filename); +int get_svc_new_key(des_cblock new_key, char *sname, char *sinst, + char *srealm, char *keyfile); + +void +copy_keyfile(progname, keyfile, backup_keyfile) + char *progname; + char *keyfile; + char *backup_keyfile; +{ + int keyfile_fd; + int backup_keyfile_fd; + int keyfile_mode; + char buf[BUFSIZ]; /* for copying keyfiles */ + int rcount; /* for copying keyfiles */ + int try_again; + + bzero((char *)buf, sizeof(buf)); + + do { + try_again = FALSE; + if ((keyfile_fd = open(keyfile, O_RDONLY, 0)) < 0) { + if (errno != ENOENT) { + err(1, "unable to read %s", keyfile); + } + else { + try_again = TRUE; + if ((keyfile_fd = + open(keyfile, + O_WRONLY | O_TRUNC | O_CREAT, SRVTAB_MODE)) < 0) { + err(1, "unable to create %s", keyfile); + } + else + if (close(keyfile_fd) < 0) { + err(1, "failure closing %s", keyfile); + } + } + } + } while(try_again); + + keyfile_mode = get_mode(keyfile); + + if ((backup_keyfile_fd = + open(backup_keyfile, O_WRONLY | O_TRUNC | O_CREAT, + keyfile_mode)) < 0) { + err(1, "unable to write %s", backup_keyfile); + } + do { + if ((rcount = read(keyfile_fd, (char *)buf, sizeof(buf))) < 0) { + err(1, "error reading %s", keyfile); + } + if (rcount && (write(backup_keyfile_fd, buf, rcount) != rcount)) { + err(1, "error writing %s", backup_keyfile); + } + } while (rcount); + if (close(backup_keyfile_fd) < 0) { + err(1, "error closing %s", backup_keyfile); + } + if (close(keyfile_fd) < 0) { + err(1, "error closing %s", keyfile); + } +} + +void +safe_read_stdin(prompt, buf, size) + char *prompt; + char *buf; + int size; +{ + printf(prompt); + fflush(stdout); + bzero(buf, size); + if (read(0, buf, size - 1) < 0) { + warn("failure reading from stdin"); + leave((char *)NULL, 1); + } + fflush(stdin); + buf[strlen(buf)-1] = 0; +} + + +void +safe_write(progname, filename, fd, buf, len) + char *progname; + char *filename; + int fd; + char *buf; + int len; +{ + if (write(fd, buf, len) != len) { + warn("failure writing %s", filename); + close(fd); + leave("In progress srvtab in this file.", 1); + } +} + +int +yn(string) + char *string; +{ + char ynbuf[5]; + + printf("%s (y,n) [y] ", string); + for (;;) { + safe_read_stdin("", ynbuf, sizeof(ynbuf)); + + if ((ynbuf[0] == 'n') || (ynbuf[0] == 'N')) + return(0); + else if ((ynbuf[0] == 'y') || (ynbuf[0] == 'Y') || (ynbuf[0] == 0)) + return(1); + else { + printf("Please enter 'y' or 'n': "); + fflush(stdout); + } + } +} + +void +append_srvtab(progname, filename, fd, sname, sinst, + srealm, key_vno, key) + char *progname; + char *filename; + int fd; + char *sname; + char *sinst; + char *srealm; + unsigned char key_vno; + des_cblock key; +{ + /* Add one to append null */ + safe_write(progname, filename, fd, sname, strlen(sname) + 1); + safe_write(progname, filename, fd, sinst, strlen(sinst) + 1); + safe_write(progname, filename, fd, srealm, strlen(srealm) + 1); + safe_write(progname, filename, fd, (char *)&key_vno, 1); + safe_write(progname, filename, fd, (char *)key, sizeof(des_cblock)); + fsync(fd); +} + +unsigned short +get_mode(filename) + char *filename; +{ + struct stat statbuf; + unsigned short mode; + + bzero((char *)&statbuf, sizeof(statbuf)); + + if (stat(filename, &statbuf) < 0) + mode = SRVTAB_MODE; + else + mode = statbuf.st_mode; + + return(mode); +} + +int +main(argc,argv) + int argc; + char *argv[]; +{ + char sname[ANAME_SZ]; /* name of service */ + char sinst[INST_SZ]; /* instance of service */ + char srealm[REALM_SZ]; /* realm of service */ + unsigned char key_vno; /* key version number */ + int status; /* general purpose error status */ + des_cblock new_key; + des_cblock old_key; + char change_tkt[MAXPATHLEN]; /* Ticket to use for key change */ + char keyfile[MAXPATHLEN]; /* Original keyfile */ + char work_keyfile[MAXPATHLEN]; /* Working copy of keyfile */ + char backup_keyfile[MAXPATHLEN]; /* Backup copy of keyfile */ + unsigned short keyfile_mode; /* Protections on keyfile */ + int work_keyfile_fd = -1; /* Initialize so that */ + int backup_keyfile_fd = -1; /* compiler doesn't complain */ + char local_realm[REALM_SZ]; /* local kerberos realm */ + int i; + int interactive = FALSE; + int list = FALSE; + int change = FALSE; + int add = FALSE; + int key = FALSE; /* do we show keys? */ + int arg_entered = FALSE; + int change_this_key = FALSE; + char databuf[BUFSIZ]; + int first_printed = FALSE; /* have we printed the first item? */ + + bzero((char *)sname, sizeof(sname)); + bzero((char *)sinst, sizeof(sinst)); + bzero((char *)srealm, sizeof(srealm)); + + bzero((char *)change_tkt, sizeof(change_tkt)); + bzero((char *)keyfile, sizeof(keyfile)); + bzero((char *)work_keyfile, sizeof(work_keyfile)); + bzero((char *)backup_keyfile, sizeof(backup_keyfile)); + bzero((char *)local_realm, sizeof(local_realm)); + + sprintf(change_tkt, "/tmp/tkt_ksrvutil.%d", getpid()); + krb_set_tkt_string(change_tkt); + + /* This is used only as a default for adding keys */ + if (krb_get_lrealm(local_realm, 1) != KSUCCESS) + strcpy(local_realm, KRB_REALM); + + for (i = 1; i < argc; i++) { + if (strcmp(argv[i], "-i") == 0) + interactive++; + else if (strcmp(argv[i], "-k") == 0) + key++; + else if (strcmp(argv[i], "list") == 0) { + if (arg_entered) + usage(); + else { + arg_entered++; + list++; + } + } + else if (strcmp(argv[i], "change") == 0) { + if (arg_entered) + usage(); + else { + arg_entered++; + change++; + } + } + else if (strcmp(argv[i], "add") == 0) { + if (arg_entered) + usage(); + else { + arg_entered++; + add++; + } + } + else if (strcmp(argv[i], "-f") == 0) { + if (++i == argc) + usage(); + else + strcpy(keyfile, argv[i]); + } + else + usage(); + } + + if (!arg_entered) + usage(); + + if (!keyfile[0]) + strcpy(keyfile, KEYFILE); + + strcpy(work_keyfile, keyfile); + strcpy(backup_keyfile, keyfile); + + if (change || add) { + strcat(work_keyfile, ".work"); + strcat(backup_keyfile, ".old"); + + copy_keyfile(argv[0], keyfile, backup_keyfile); + } + + if (add) + copy_keyfile(argv[0], backup_keyfile, work_keyfile); + + keyfile_mode = get_mode(keyfile); + + if (change || list) { + if ((backup_keyfile_fd = open(backup_keyfile, O_RDONLY, 0)) < 0) { + err(1, "unable to read %s", backup_keyfile); + } + } + + if (change) { + if ((work_keyfile_fd = + open(work_keyfile, O_WRONLY | O_CREAT | O_TRUNC, + SRVTAB_MODE)) < 0) { + err(1, "unable to write %s", work_keyfile); + } + } + else if (add) { + if ((work_keyfile_fd = + open(work_keyfile, O_APPEND | O_WRONLY, SRVTAB_MODE)) < 0) { + err(1, "unable to append to %s", work_keyfile); + } + } + + if (change || list) { + while ((getst(backup_keyfile_fd, sname, SNAME_SZ) > 0) && + (getst(backup_keyfile_fd, sinst, INST_SZ) > 0) && + (getst(backup_keyfile_fd, srealm, REALM_SZ) > 0) && + (read(backup_keyfile_fd, &key_vno, 1) > 0) && + (read(backup_keyfile_fd,(char *)old_key,sizeof(old_key)) > 0)) { + if (list) { + if (!first_printed) { + printf(VNO_HEADER); + printf(PAD); + if (key) { + printf(KEY_HEADER); + printf(PAD); + } + printf(PRINC_HEADER); + first_printed = 1; + } + printf(VNO_FORMAT, key_vno); + printf(PAD); + if (key) { + print_key(old_key); + printf(PAD); + } + print_name(sname, sinst, srealm); + printf("\n"); + } + else if (change) { + printf("\nPrincipal: "); + print_name(sname, sinst, srealm); + printf("; version %d\n", key_vno); + if (interactive) + change_this_key = yn("Change this key?"); + else if (change) + change_this_key = 1; + else + change_this_key = 0; + + if (change_this_key) + printf("Changing to version %d.\n", key_vno + 1); + else if (change) + printf("Not changing this key.\n"); + + if (change_this_key) { + /* + * Pick a new key and determine whether or not + * it is safe to change + */ + if ((status = + get_svc_new_key(new_key, sname, sinst, + srealm, keyfile)) == KADM_SUCCESS) + key_vno++; + else { + bcopy(old_key, new_key, sizeof(new_key)); + com_err(argv[0], status, ": key NOT changed"); + change_this_key = FALSE; + } + } + else + bcopy(old_key, new_key, sizeof(new_key)); + append_srvtab(argv[0], work_keyfile, work_keyfile_fd, + sname, sinst, srealm, key_vno, new_key); + if (key && change_this_key) { + printf("Old key: "); + print_key(old_key); + printf("; new key: "); + print_key(new_key); + printf("\n"); + } + if (change_this_key) { + if ((status = kadm_change_pw(new_key)) == KADM_SUCCESS) { + printf("Key changed.\n"); + dest_tkt(); + } + else { + com_err(argv[0], status, + " attempting to change password."); + dest_tkt(); + /* XXX This knows the format of a keyfile */ + if (lseek(work_keyfile_fd, -9, L_INCR) >= 0) { + key_vno--; + safe_write(argv[0], work_keyfile, + work_keyfile_fd, (char *)&key_vno, 1); + safe_write(argv[0], work_keyfile, work_keyfile_fd, + (char *)old_key, sizeof(des_cblock)); + fsync(work_keyfile_fd); + fprintf(stderr,"Key NOT changed.\n"); + } + else { + warn("unable to revert keyfile"); + leave("", 1); + } + } + } + } + bzero((char *)old_key, sizeof(des_cblock)); + bzero((char *)new_key, sizeof(des_cblock)); + } + } + else if (add) { + do { + do { + safe_read_stdin("Name: ", databuf, sizeof(databuf)); + strncpy(sname, databuf, sizeof(sname) - 1); + safe_read_stdin("Instance: ", databuf, sizeof(databuf)); + strncpy(sinst, databuf, sizeof(sinst) - 1); + safe_read_stdin("Realm: ", databuf, sizeof(databuf)); + strncpy(srealm, databuf, sizeof(srealm) - 1); + safe_read_stdin("Version number: ", databuf, sizeof(databuf)); + key_vno = atoi(databuf); + if (!srealm[0]) + strcpy(srealm, local_realm); + printf("New principal: "); + print_name(sname, sinst, srealm); + printf("; version %d\n", key_vno); + } while (!yn("Is this correct?")); + get_key_from_password(new_key); + if (key) { + printf("Key: "); + print_key(new_key); + printf("\n"); + } + append_srvtab(argv[0], work_keyfile, work_keyfile_fd, + sname, sinst, srealm, key_vno, new_key); + printf("Key successfully added.\n"); + } while (yn("Would you like to add another key?")); + } + + if (change || list) + if (close(backup_keyfile_fd) < 0) { + warn("failure closing %s, continuing", backup_keyfile); + } + + if (change || add) { + if (close(work_keyfile_fd) < 0) { + err(1, "failure closing %s", work_keyfile); + } + if (rename(work_keyfile, keyfile) < 0) { + err(1, "failure renaming %s to %s", work_keyfile, keyfile); + } + chmod(backup_keyfile, keyfile_mode); + chmod(keyfile, keyfile_mode); + printf("Old keyfile in %s.\n", backup_keyfile); + } + + exit(0); +} + +void +print_key(key) + des_cblock key; +{ + int i; + + for (i = 0; i < 4; i++) + printf("%02x", key[i]); + printf(" "); + for (i = 4; i < 8; i++) + printf("%02x", key[i]); +} + +void +print_name(name, inst, realm) + char *name; + char *inst; + char *realm; +{ + printf("%s%s%s%s%s", name, inst[0] ? "." : "", inst, + realm[0] ? "@" : "", realm); +} + +int +get_svc_new_key(new_key, sname, sinst, srealm, keyfile) + des_cblock new_key; + char *sname; + char *sinst; + char *srealm; + char *keyfile; +{ + int status = KADM_SUCCESS; + + if (((status = krb_get_svc_in_tkt(sname, sinst, srealm, PWSERV_NAME, + KADM_SINST, 1, keyfile)) == KSUCCESS) && + ((status = kadm_init_link("changepw", KRB_MASTER, srealm)) == + KADM_SUCCESS)) { +#ifdef NOENCRYPTION + bzero((char *) new_key, sizeof(des_cblock)); + new_key[0] = (unsigned char) 1; +#else /* NOENCRYPTION */ + des_random_key(new_key); +#endif /* NOENCRYPTION */ + return(KADM_SUCCESS); + } + + return(status); +} + +void +get_key_from_password(key) + des_cblock key; +{ + char password[MAX_KPW_LEN]; /* storage for the password */ + + if (read_long_pw_string(password, sizeof(password)-1, "Password: ", 1)) + leave("Error reading password.", 1); + +#ifdef NOENCRYPTION + bzero((char *) key, sizeof(des_cblock)); + key[0] = (unsigned char) 1; +#else /* NOENCRYPTION */ + des_string_to_key(password, (des_cblock *)key); +#endif /* NOENCRYPTION */ + bzero((char *)password, sizeof(password)); +} + +void +usage() +{ + fprintf(stderr, "Usage: ksrvutil [-f keyfile] [-i] [-k] "); + fprintf(stderr, "{list | change | add}\n"); + fprintf(stderr, " -i causes the program to ask for "); + fprintf(stderr, "confirmation before changing keys.\n"); + fprintf(stderr, " -k causes the key to printed for list or "); + fprintf(stderr, "change.\n"); + exit(1); +} + +void +leave(str,x) +char *str; +int x; +{ + if (str) + fprintf(stderr, "%s\n", str); + dest_tkt(); + exit(x); +} diff --git a/eBones/usr.sbin/kstash/Makefile b/eBones/usr.sbin/kstash/Makefile new file mode 100644 index 0000000000000..cf97f8cedabd4 --- /dev/null +++ b/eBones/usr.sbin/kstash/Makefile @@ -0,0 +1,10 @@ +# From: @(#)Makefile 5.2 (Berkeley) 3/5/91 +# $Id: Makefile,v 1.5 1995/09/13 17:24:35 markm Exp $ + +PROG= kstash +CFLAGS+=-DKERBEROS -DDEBUG +DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES} +LDADD= -lkdb -lkrb -ldes +MAN8= kstash.8 + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/kstash/kstash.c b/eBones/usr.sbin/kstash/kstash.c new file mode 100644 index 0000000000000..ce26a1db34e0a --- /dev/null +++ b/eBones/usr.sbin/kstash/kstash.c @@ -0,0 +1,94 @@ +/* + * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute + * of Technology + * For copying and distribution information, please see the file + * <Copyright.MIT>. + * + * from: kstash.c,v 4.0 89/01/23 09:45:43 jtkohl Exp $ + * $Id: kstash.c,v 1.3 1995/07/18 16:40:16 mark Exp $ + */ + +#if 0 +#ifndef lint +static char rcsid[] = +"$Id: kstash.c,v 1.3 1995/07/18 16:40:16 mark Exp $"; +#endif lint +#endif + +#include <unistd.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> +#include <signal.h> +#include <sgtty.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/file.h> + +#include <krb.h> +#include <des.h> +#include <klog.h> +#include <prot.h> +#include <krb_db.h> +#include <kdc.h> + +/* change this later, but krblib_dbm needs it for now */ +char *progname; + +static C_Block master_key; +static Key_schedule master_key_schedule; +int debug; +static int kfile; +static void clear_secrets(); + +int +main(argc, argv) + int argc; + char **argv; +{ + long n; + if ((n = kerb_init())) { + fprintf(stderr, "Kerberos db and cache init failed = %ld\n", n); + exit(1); + } + + if (kdb_get_master_key (TRUE, master_key, master_key_schedule) != 0) { + fprintf (stderr, "%s: Couldn't read master key.\n", argv[0]); + fflush (stderr); + clear_secrets(); + exit (-1); + } + + if (kdb_verify_master_key (master_key, master_key_schedule, stderr) < 0) { + clear_secrets(); + exit (-1); + } + + kfile = open(MKEYFILE, O_TRUNC | O_RDWR | O_CREAT, 0600); + if (kfile < 0) { + clear_secrets(); + fprintf(stderr, "\n\07\07%s: Unable to open master key file\n", + argv[0]); + exit(1); + } + if (write(kfile, (char *) master_key, 8) < 0) { + clear_secrets(); + fprintf(stderr, "\n%s: Write I/O error on master key file\n", + argv[0]); + exit(1); + } + (void) close(kfile); + clear_secrets(); + return(0); +} + +static void +clear_secrets() +{ + bzero(master_key_schedule, sizeof(master_key_schedule)); + bzero(master_key, sizeof(master_key)); +} diff --git a/eBones/usr.sbin/make_keypair/Makefile b/eBones/usr.sbin/make_keypair/Makefile new file mode 100644 index 0000000000000..f100cdcb8ddf6 --- /dev/null +++ b/eBones/usr.sbin/make_keypair/Makefile @@ -0,0 +1,10 @@ +# @(#)Makefile 8.1 (Berkeley) 6/1/93 +# $id$ + +PROG= make_keypair +MAN8= make_keypair.8 +CFLAGS+=-DKERBEROS -I${.CURDIR}/../../usr.bin/register +DPADD= ${LIBKDB} ${LIBKRB} ${LIBDES} +LDADD= -lkdb -lkrb -ldes + +.include <bsd.prog.mk> diff --git a/eBones/usr.sbin/make_keypair/make_keypair.c b/eBones/usr.sbin/make_keypair/make_keypair.c new file mode 100644 index 0000000000000..deb67ac60e1fa --- /dev/null +++ b/eBones/usr.sbin/make_keypair/make_keypair.c @@ -0,0 +1,134 @@ +/*- + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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 above copyright + * notice, this list of conditions and the following disclaimer. + * 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 the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 THE REGENTS OR CONTRIBUTORS 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. + */ + +#if 0 +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1988, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +static char sccsid[] = "@(#)make_keypair.c 8.1 (Berkeley) 6/1/93"; +#endif /* not lint */ +#endif + +#include <sys/types.h> +#include <sys/file.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <netdb.h> +#include <des.h> +#include <krb.h> +#include "pathnames.h" +#include "register_proto.h" + +void usage(char *name); +void make_key(struct in_addr addr); + +char * progname; + +void +main(argc, argv) + int argc; + char **argv; +{ + struct hostent *hp; + char *addr; + int i; + struct sockaddr_in sin; + + progname = *argv; /* argv[0] */ + + if (argc != 2) { + usage(argv[0]); + exit(1); + } + + if ((hp = gethostbyname(argv[1])) == NULL) { + herror(argv[1]); + exit(1); + } + + for (i = 0; (addr = hp->h_addr_list[i]); i++) { + addr = hp->h_addr_list[i]; + bcopy(addr, &sin.sin_addr, hp->h_length); + + printf("Making key for host %s (%s)\n", + argv[1], inet_ntoa(sin.sin_addr)); + make_key(sin.sin_addr); + } + printf("==========\n"); + printf("One copy of the each key should be put in %s on the\n", + SERVER_KEYDIR); + printf("Kerberos server machine (mode 600, owner root).\n"); + printf("Another copy of each key should be put on the named\n"); + printf("client as %sXXX.XXX.XXX.XXX (same modes as above),\n", + CLIENT_KEYFILE); + printf("where the X's refer to digits of the host's inet address.\n"); + (void)fflush(stdout); + exit(0); +} + +void +make_key(addr) + struct in_addr addr; +{ + struct keyfile_data kfile; + char namebuf[255]; + int fd; + + (void)sprintf(namebuf, "%s%s", + CLIENT_KEYFILE, + inet_ntoa(addr)); + fd = open(namebuf, O_WRONLY|O_CREAT, 0600); + if (fd < 0) { + perror("open"); + exit(1); + } + random_key(kfile.kf_key); + printf("writing to file -> %s ...", namebuf); + if (write(fd, &kfile, sizeof(kfile)) != sizeof(kfile)) { + fprintf(stderr, "error writing file %s\n", namebuf); + } + printf("done.\n"); + (void)close(fd); + return; +} + +void +usage(name) + char *name; +{ + fprintf(stderr, "usage: %s host\n", name); +} diff --git a/share/doc/FAQ/Makefile b/share/doc/FAQ/Makefile new file mode 100644 index 0000000000000..40ecc8aa77906 --- /dev/null +++ b/share/doc/FAQ/Makefile @@ -0,0 +1,6 @@ +# $Id$ + +DOC= freebsd-faq +SRCS= freebsd-faq.sgml + +.include <bsd.sgml.mk> diff --git a/share/doc/handbook/Makefile b/share/doc/handbook/Makefile new file mode 100644 index 0000000000000..7bf538d5ff81c --- /dev/null +++ b/share/doc/handbook/Makefile @@ -0,0 +1,12 @@ +# $Id$ + +SRCS= authors.sgml basics.sgml bibliography.sgml boothelp.sgml +SRCS+= booting.sgml contrib.sgml ctm.sgml current.sgml dialup.sgml +SRCS+= diskless.sgml eresources.sgml glossary.sgml handbook.sgml +SRCS+= history.sgml hw.sgml install.sgml kerberos.sgml kerneldebug.sgml +SRCS+= memoryuse.sgml mirrors.sgml nfs.sgml nutshell.sgml porting.sgml +SRCS+= ports.sgml ppp.sgml relnotes.sgml scsi.sgml sections.sgml +SRCS+= slipc.sgml slips.sgml submitters.sgml sup.sgml +SRCS+= troubleshooting.sgml userppp.sgml + +.include <bsd.sgml.mk> diff --git a/share/doc/handbook/boothelp.sgml b/share/doc/handbook/boothelp.sgml new file mode 100644 index 0000000000000..fbda261aa6693 --- /dev/null +++ b/share/doc/handbook/boothelp.sgml @@ -0,0 +1,50 @@ +<!-- $Id$ --> +<!-- The FreeBSD Documentation Project --> + +<!DOCTYPE linuxdoc PUBLIC "-//FreeBSD//DTD linuxdoc//EN" [ + +<!-- Conditional flags for this version of the document --> +<!ENTITY % boothelp.only "INCLUDE"> +<!ENTITY % handbook.only "IGNORE"> + +<!-- Entity shorthand for authors' names and email addresses --> +<!ENTITY % authors SYSTEM "authors.sgml"> +%authors; + +<!-- Entity definitions for all the parts --> +<!ENTITY % sections SYSTEM "sections.sgml"> +%sections; + +]> + +<linuxdoc> + <book> + + <title>FreeBSD Installation + <author> + <name></name> + </author> + + <abstract>Welcome to FreeBSD! This guide describes the + FreeBSD installation process. To navigate through the + sections in this guide using the <bf>up</bf> and + <bf>down</bf> arrow keys to select a section you wish to + read. Then use the <bf>right arrow</bf> or the <bf>enter + key</bf> to view the section. You can backtrack through + sections you have read by using the <bf>left arrow</bf>. + </abstract> + + <chapt><heading>General information</heading> + &nutshell; + &history; + &relnotes; + + &install; + &troubleshooting; + &bibliography; + &eresources; + &hw; + &contrib; + + </book> +</linuxdoc> diff --git a/share/doc/handbook/contrib.sgml b/share/doc/handbook/contrib.sgml new file mode 100644 index 0000000000000..b3bd245e4a680 --- /dev/null +++ b/share/doc/handbook/contrib.sgml @@ -0,0 +1,300 @@ +<!-- $Id: contrib.sgml,v 1.14 1995/08/31 15:15:17 jkh Exp $ --> +<!-- The FreeBSD Documentation Project --> + +<chapt><heading>FreeBSD contributor list<label id="contrib"></heading> + + <sect><heading>Derived software contributors</heading> + + <p>This software was originally derived from William + F. Jolitz's 386BSD release 0.1, though almost none of the + original 386BSD specific code remains. This software has + been essentially reimplemented from the 4.4 BSD Lite + release provided by the Computer Science Research Group + (CSRG) at the University of California, Berkeley and + associated academic contributors. + + There are also portions of NetBSD that have been integrated + into FreeBSD as well, and we would therefore like to thank + all the contributors to NetBSD for their work. Despite + some occasionally rocky moments in relations between the + two groups, we both want essentially the same thing: More + BSD based operating systems on people's computers! We wish + the NetBSD group every success in their endevors. + + <sect><heading>Hardware contributors</heading> + + <p>A special thank-you to Walnut Creek CDROM for providing + the Pentium P5-90 and 486/DX2-66 EISA/VL systems that are + being used for our development work, to say nothing of the + network access and other donations of hardware resources. + It would have been impossible to do this release without + their support. + + TRW Financial Systems, Inc. provided 130 PCs, three 68 GB + fileservers, twelve ethernets, two routers and an ATM + switch for debugging the diskless code. They also keep a + couple of FreeBSD hackers alive and busy. Thanks! + + Thanks also to Dermot McDonnell for his donation of a + Toshiba XM3401B CDROM drive. It's been most useful! + + Thanks to Chuck Robey <chuckr@eng.umd.edu> who's been + contributing his floppy tape streamer for experimental + work. + + <sect><heading>The FreeBSD core team<label id="contrib:core"></heading> + + <p>(in alphabetical order by first name): + + <itemize> + <item>Andrey A. Chernov <ache@FreeBSD.org> + <item>Bruce Evans <bde@FreeBSD.org> + <item>David Greenman <davidg@FreeBSD.org> + <item>Garrett A. Wollman <wollman@FreeBSD.org> + <item>Gary Palmer <gpalmer@FreeBSD.org> + <item>Jörg Wunsch <joerg@FreeBSD.org> + <item>John Dyson <dyson@FreeBSD.org> + <item>Jordan K. Hubbard <jkh@FreeBSD.org> + <item>Justin Gibbs <gibbs@FreeBSD.org> + <item>Poul-Henning Kamp <phk@FreeBSD.org> + <item>Rich Murphey <rich@FreeBSD.org> + <item>Rodney W. Grimes <rgrimes@FreeBSD.org> + <item>Satoshi Asami <asami@FreeBSD.org> + <item>Søren Schmidt <sos@FreeBSD.org> + </itemize> + + <sect><heading>Who is responsible for what</heading> + + <p><descrip> + <tag/President/ Jordan K. Hubbard <jkh@FreeBSD.org> + <tag/Principle Architect/ David Greenman <davidg@FreeBSD.org> + <tag/Documentation/ John Fieber <jfieber@FreeBSD.org> + <tag/Internationalization/ Andrey A. Chernov <ache@FreeBSD.org> + <tag/Networking/ Garrett A. Wollman <wollman@FreeBSD.org> + <tag/Postmaster/ Jonathan M. Bresler <jmb@FreeBSD.org> + <tag/Public Relations/ Jordan Hubbard <jkh@FreeBSD.org> + <tag/Release Coordinator/ Jordan Hubbard <jkh@FreeBSD.org> + <tag/System Administration/ Gary Palmer <gpalmer@FreeBSD.org> + <tag/Webmasters/ John Fieber <jfieber@FreeBSD.org> and + James L. Robinson <jlrobin@FreeBSD.org> + <tag/XFree86 Project, Inc. Liason/ Rich Murphey + <rich@FreeBSD.org> + </descrip> + + <sect><heading>Additional FreeBSD contributors</heading> + + <p>(in alphabetical order by first name): + + <itemize> + <item>Adam David <adam@veda.is> + <item>Adam Glass <glass@postgres.berkeley.edu> + <item>Akito Fujita <fujita@zoo.ncl.omron.co.jp> + <item>Alain Kalker <alain@Wit401402.student.utwente.nl> + <item>Andras Olah <olah@cs.utwente.nl> + <item>Andreas Klemm <andreas@knobel.GUN.de> + <item>Andrew Herbert <andrew@werple.apana.org.au> + <item>Andrew Moore <alm@FreeBSD.org> + <item>Anthony Yee-Hang Chan <yeehang@netcom.com> + <item>Atsushi Murai <amurai@spec.co.jp> + <item>Bill Fenner <fenner@parc.xerox.com> + <item>Bill Paul <wpaul@FreeBSD.org> + <item>Bob Wilcox <bob@obiwan.uucp> + <item>Brian Tao <taob@gate.sinica.edu.tw> + <item>Charles Hannum <mycroft@ai.mit.edu> + <item>Chris G. Demetriou <cgd@postgres.berkeley.edu> + <item>Chris Provenzano <proven@athena.mit.edu> + <item>Chris Stenton <jacs@gnome.co.uk> + <item>Chris Torek <torek@ee.lbl.gov> + <item>Christian Gusenbauer <cg@fimp01.fim.uni-linz.ac.at> + <item>Christoph Robitschko <chmr@edvz.tu-graz.ac.at> + <item>Chuck Robey <chuckr@Glue.umd.edu> + <item>Cornelis van der Laan <nils@guru.ims.uni-stuttgart.de> + <item>Craig Struble <cstruble@vt.edu> + <item>Curt Mayer <curt@toad.com> + <item>Danny J. Zerkel <dzerkel@feephi.phofarm.com> + <item>Dave Burgess <burgess@hrd769.brooks.af.mil> + <item>Dave Chapeskie <dchapes@zeus.leitch.com> + <item>Dave Rivers <rivers@ponds.uucp> + <item>David Dawes <dawes@physics.su.OZ.AU> + <item>Dean Huxley <dean@fsa.ca> + <item>Don Whiteside <dwhite@anshar.shadow.net> + <item>Eric L. Hernes <erich@lodgenet.com> + <item>Frank Durda IV <bsdmail@nemesis.lonestar.org> + <item>Frank Maclachlan <fpm@crash.cts.com> + <item>Frank Nobis <fn@trinity.radio-do.de> + <item>Gary A. Browning <gab10@griffcd.amdahl.com> + <item>Gary Clark II <gclarkii@FreeBSD.ORG> + <item>Gary Jennejohn <gj%pcs.dec.com@inet-gw-1.pa.dec.com> + <item>Gene Stark <stark@cs.sunysb.edu> + <item>Guido van Rooij <guido@gvr.win.tue.nl> + <item>Havard Eidnes <Havard.Eidnes@runit.sintef.no> + <item>Holger Veit <Holger.Veit@gmd.de> + <item>Ishii Masahiro, R. Kym Horsell + <item>J.T. Conklin <jtc@winsey.com> + <item>James Clark <jjc@jclark.com> + <item>James da Silva <jds@cs.umd.edu> et al + <item>Janusz Kokot <janek@gaja.ipan.lublin.pl> + <item>Javier Martin Rueda <jmrueda@diatel.upm.es> + <item>Jim Wilson <wilson@moria.cygnus.com> + <item>Jonathan Bresler < jmb@FreeBSD.ORG> + <item>Josh MacDonald <jmacd@uclink.berkeley.edu> + <item>Julian Elischer <julian@dialix.oz.au> + <item>Julian Stacey <stacey@guug.de> + (fallback: <julian@meepmeep.pcs.com>) + <item>Keith Bostic <bostic@toe.CS.Berkeley.EDU> + <item>Keith Moore <?> + <item>Kirk McKusick <mckusick@mckusick.com> + <item>Kurt Olsen <kurto@tiny.mcs.usu.edu> + <item>L Jonas Olsson <ljo@po.cwru.edu> + <item>Lars Fredriksen <fredriks@mcs.com> + <item>Lucas James <Lucas.James@ldjpc.apana.org.au> + <item>Marc Frajola <marc@dev.com> + <item>Marc Ramirez <mrami@mramirez.sy.yale.edu + <item>Marc van Kempen <wmbfmk@urc.tue.nl> + <item>Mark Murray <mark@grondar.za> + <item>Mark Tinguely <tinguely@plains.nodak.edu> + <tinguely@hookie.cs.ndsu.NoDak.edu> + <item>Martin Birgmeier + <item>Martin Renters <martin@innovus.com> + <item>Matt Thomas <thomas@lkg.dec.com> + <item>Michael Smith <msmith@atrad.adelaide.edu.au> + <item>Mike Pritchard <mpp@mpp.minn.net> + <item>NIIMI Satoshi <sa2c@and.or.jp> + <item>Nate Williams <nate@FreeBSD.org> + <item>Nobuhiro Yasutomi <nobu@psrc.isac.co.jp> + <item>Nobuyuki Koganemaru <kogane@kces.koganemaru.co.jp> + <item>Ollivier Robert <roberto@FreeBSD.org> + <item>Paul Kranenburg <pk@cs.few.eur.nl> + <item>Paul Mackerras <paulus@cs.anu.edu.au> + <item>Paul Richards <paul@FreeBSD.org> + <item>Paul Traina <pst@cisco.com> + <item>Peter Dufault <dufault@hda.com> + <item>Peter Wemm <peter@haywire.DIALix.COM> + <item>Philippe Charnier <charnier@lirmm.fr> + <item>Richard Stallman <rms@gnu.ai.mit.edu> + <item>Rob Shady <rls@id.net> + <item>Rob Snow <rsnow@txdirect.net> + <item>Sascha Wildner <swildner@channelz.GUN.de> + <item>Scott Mace <smace@FreeBSD.org> + <item>Sean Eric Fagan <sef@kithrup.com> + <item>Serge V. Vakulenko <vak@zebub.msk.su> + <item>Stefan Esser <se@MI.Uni-Koeln.DE> + <item>Stephen McKay <syssgm@devetir.qld.gov.au> + <item>Steve Gerakines <steve2@genesis.tiac.net> + <item>Steven Wallace <swallace@ece.uci.edu> + <item>Tatsumi Hosokawa <hosokawa@mt.cs.keio.ac.jp> + <item>Terry Lee <terry@uivlsi.csl.uiuc.edu> + <item>Theo Deraadt <deraadt@fsa.ca> + <item>Thomas Gellekum <thomas@ghpc8.ihf.rwth-aachen.de> + <item>Tom Samplonius <tom@misery.sdf.com> + <item>Torbjorn Granlund <tege@matematik.su.se> + <item>Torsten Blum <torstenb@FreeBSD.ORG> + <item>Ugen J.S.Antsilevich <ugen@NetVision.net.il> + <item>Werner Griessl <werner@btp1da.phy.uni-bayreuth.de> + <item>Wolfgang Stanglmeier <wolf@kintaro.cologne.de> + <item>Wolfram Schneider <wosch@cs.tu-berlin.de> + <item>Yuval Yarom <yval@cs.huji.ac.il> + <item>Yves Fonk <yves@cpcoup5.tn.tudelft.nl> + </itemize> + + <sect><heading>386BSD Patch kit patch contributors</heading> + + <p>(in alphabetical order by first name): + + <itemize> + <item>Adam Glass <glass@postgres.berkeley.edu> + <item>Adrian Hall <adrian@ibmpcug.co.uk> + <item>Andrey A. Chernov <ache@astral.msk.su> + <item>Andrew Herbert <andrew@werple.apana.org.au> + <item>Andrew Moore <alm@netcom.com> + <item>Andy Valencia <ajv@csd.mot.com> <jtk@netcom.com> + <item>Arne Henrik Juul <arnej@Lise.Unit.NO> + <item>Bakul Shah <bvs@bitblocks.com> + <item>Barry Lustig <barry@ictv.com> + <item>Bob Wilcox <bob@obiwan.uucp> + <item>Branko Lankester + <item>Brett Lymn <blymn@mulga.awadi.com.AU> + <item>Charles Hannum <mycroft@ai.mit.edu> + <item>Chris G. Demetriou <cgd@postgres.berkeley.edu> + <item>Chris Torek <torek@ee.lbl.gov> + <item>Christoph Robitschko <chmr@edvz.tu-graz.ac.at> + <item>Daniel Poirot <poirot@aio.jsc.nasa.gov> + <item>Dave Burgess <burgess@hrd769.brooks.af.mil> + <item>Dave Rivers <rivers@ponds.uucp> + <item>David Dawes <dawes@physics.su.OZ.AU> + <item>David Greenman <davidg@Root.COM> + <item>Eric J. Haug <ejh@slustl.slu.edu> + <item>Felix Gaehtgens <felix@escape.vsse.in-berlin.de> + <item>Frank Maclachlan <fpm@crash.cts.com> + <item>Gary A. Browning <gab10@griffcd.amdahl.com> + <item>Geoff Rehmet <csgr@alpha.ru.ac.za> + <item>Goran Hammarback <goran@astro.uu.se> + <item>Guido van Rooij <guido@gvr.win.tue.nl> + <item>Guy Harris <guy@auspex.com> + <item>Havard Eidnes <Havard.Eidnes@runit.sintef.no> + <item>Herb Peyerl <hpeyerl@novatel.cuc.ab.ca + <item>Holger Veit <Holger.Veit@gmd.de> + <item>Ishii Masahiro, R. Kym Horsell + <item>J.T. Conklin <jtc@winsey.com> + <item>Jagane D Sundar < jagane@netcom.com > + <item>James Clark <jjc@jclark.com> + <item>James Jegers <jimj@miller.cs.uwm.edu> + <item>James W. Dolter + <item>James da Silva <jds@cs.umd.edu> et al + <item>Jay Fenlason <hack@datacube.com> + <item>Jim Wilson <wilson@moria.cygnus.com> + <item>Joerg Lohse <lohse@tech7.informatik.uni-hamburg.de> + <item>Jörg Wunsch <joerg_wunsch@uriah.heep.sax.de> + <item>John Dyson - <formerly dyson@ref.tfs.com> + <item>John Woods <jfw@eddie.mit.edu> + <item>Jordan K. Hubbard <jkh@whisker.hubbard.ie> + <item>Julian Elischer <julian@dialix.oz.au> + <item>Julian Stacey <stacey@guug.de> + (fallback: <julian@meepmeep.pcs.com>) + <item>Karl Lehenbauer <karl@NeoSoft.com> + <karl@one.neosoft.com> + <item>Keith Bostic <bostic@toe.CS.Berkeley.EDU> + <item>Ken Hughes + <item>Kent Talarico <kent@shipwreck.tsoft.net> + <item>Kevin Lahey <kml%rokkaku.UUCP@mathcs.emory.edu> + <kml@mosquito.cis.ufl.edu> + <item>Marc Frajola <marc@dev.com> + <item>Mark Tinguely <tinguely@plains.nodak.edu> + <tinguely@hookie.cs.ndsu.NoDak.edu> + <item>Martin Renters <martin@innovus.com> + <item>Michael Galassi <nerd@percival.rain.com> + <item>Mike Durkin <mdurkin@tsoft.sf-bay.org> + <item>Nate Williams <nate@bsd.coe.montana.edu> + <item>Nick Handel <nhandel@NeoSoft.com> + <nick@madhouse.neosoft.com> + <item>Pace Willisson <pace@blitz.com> + <item>Paul Kranenburg <pk@cs.few.eur.nl> + <item>Paul Mackerras <paulus@cs.anu.edu.au> + <item>Paul Popelka <paulp@uts.amdahl.com> + <item>Peter da Silva <peter@NeoSoft.com> + <item>Phil Sutherland <philsuth@mycroft.dialix.oz.au> + <item>Ralf Friedl <friedl@informatik.uni-kl.de> + <item>Rick Macklem <root@snowhite.cis.uoguelph.ca> + <item>Robert D. Thrush <rd@phoenix.aii.com> + <item>Rodney W. Grimes <rgrimes@cdrom.com> + <item>Rog Egge <?> + <item>Sascha Wildner <swildner@channelz.GUN.de> + <item>Scott Burris <scott@pita.cns.ucla.edu> + <item>Scott Reynolds <scott@clmqt.marquette.mi.us> + <item>Sean Eric Fagan <sef@kithrup.com> + <item>Simon J Gerraty <sjg@melb.bull.oz.au> + <sjg@zen.void.oz.au> + <item>Stephen McKay <syssgm@devetir.qld.gov.au> + <item>Terry Lambert <terry@icarus.weber.edu> + <item>Terry Lee <terry@uivlsi.csl.uiuc.edu> + <item>Warren Toomey <wkt@csadfa.cs.adfa.oz.au> + <item>Wiljo Heinen <wiljo@freeside.ki.open.de> + <item>William Jolitz <withheld> + <item>Wolfgang Solfrank <ws@tools.de> + <item>Wolfgang Stanglmeier <wolf@dentaro.GUN.de> + <item>Yuval Yarom <yval@cs.huji.ac.il> + </itemize> + + Last, but not least, the release engineer would like to + thank: His Wife, for chocolate chip cookies, and some other + things. The DGB project @ TFS, for patience and tolerance. diff --git a/share/doc/handbook/hw.sgml b/share/doc/handbook/hw.sgml new file mode 100644 index 0000000000000..372997456200f --- /dev/null +++ b/share/doc/handbook/hw.sgml @@ -0,0 +1,319 @@ +<!-- $Id: hw.sgml,v 1.5 1995/08/29 01:42:37 jfieber Exp $ --> +<!-- The FreeBSD Documentation Project --> + +<!-- +<!DOCTYPE linuxdoc PUBLIC "-//FreeBSD//DTD linuxdoc//EN"> +--> + +<chapt><heading>PC Hardware compatibility<label id="hw"></heading> + + <p>Issues of hardware compatibility are among the most + troublesome in the computer industry today and FreeBSD is by + no means immune to trouble. In this respect, FreeBSD's + advantage of being able to run on inexpensive commidity PC + hardware is also its liability when it comes to support for + the amazing variety of components on the market. While it + would be impossible to provide a exhaustive listing of + hardware that FreeBSD supports, this section serves as a + catalog of the device drivers included with FreeBSD and the + hardware each drivers supports. Where possible and + appropriate, notes about specific products are included. + + As FreeBSD is a volunteer project without a funded testing + department, we depend on you, the user, for much of the + information contained in this catalog. If you have direct + experience of hardware that does or does not work with + FreeBSD, please let us know by sending email to + <tt>doc@freebsd.org</tt>. Questions about supported hardware + should be directed to <tt>questions@freebsd.org</tt> (see + <ref id="eresources:mail" name="Mailing Lists"> for more + information). When submitting information or asking a + question, please remember to specify exactly what version of + FreeBSD you are using and include as many details of your + hardware as possible. + +<sect><heading>Core/Processing<label id="hw:core"></heading> + +<sect1><heading>Motherboards, busses, and chipsets</heading> + <sect2><heading>* ISA</heading> + <sect2><heading>* EISA</heading> + <sect2><heading>* VLB</heading> + <sect2><heading>PCI</heading> + + <p><em>Contributed by &a.rgrimes;.<newline>25 April 1995.</em></p> + + <p>Of the Intel PCI chip sets the following is a list + of brokenness from worst to best and a short + description of brokenness.</p> + + <p><descrip> + + <tag>Mercury:</tag> Cache coherency problems, + especially if there are ISA bus masters behind + the ISA to PCI bridge chip. Hardware flaw, only + known work around is to turn the cache + off. + + <tag>Saturn-I <em>(ie, 82424ZX at rev 0, 1 or + 2)</em>:</tag> write back cache coherency + problems. Hardware flaw, only known work around + is to set the external cache to write-through + mode. Upgrade to Saturn-II. + + <tag>Saturn-II <em>(ie, 82424ZX at rev 3 or + 4)</em>:</tag> Works fine, but many MB + manufactures leave out the external dirty bit + SRAM needed for write back operation. Work + arounds are either run it in write through mode, + or get the dirty bit SRAM installed. (I have + these for the ASUS PCI/I-486SP3G rev 1.6 and + later boards). + + <tag>Neptune:</tag> Can not run more than 2 bus + master devices. Admitted Intel design flaw. + Workarounds include do not run more than 2 bus + masters, special hardware design to replace the + PCI bus arbiter (appears on Intel Altair board + and several other Intel server group MB's). And + of course Intel's official answer, move to the + Triton chip set, we ``fixed it there''. + + <tag>Triton:</tag> No known cache coherency or bus + master problems, chip set does not implement + parity checking. Workaround for parity issue. + Wait for Triton-II. + + <tag>Triton-II:</tag> Unknown, not yet shipping. + + </descrip> + </p> + +<sect1><heading>* CPUs/FPUs</heading> +<sect1><heading>* Memory</heading> +<sect1><heading>* BIOS</heading> + +<sect><heading>Input/Output Devices<label id="hw:io"></heading> + +<sect1><heading>* Video cards</heading> +<sect1><heading>* Sound cards</heading> +<sect1><heading>Serial ports and multiport cards</heading> + + <p>The <tt>sio</tt> driver provides support for NS8250-, + NS16450-, NS16550 and NS16550A-based EIA RS-232C (CCITT + V.24) communications interfaces. Several multiport + cards are supported as well. See the <tt>sio(4)</tt> + manual page for detailed technical documentation. + +<sect2><heading>Digiboard PC/8</heading> + + <p><em>Contributed by &a.awebster;.<newline>26 August + 1995.</em> + + Here is a config snippet from a machine with + digiboard PC/8 with 16550. It has 8 modems connected + to these 8 lines, and they work just great. Do not + forget to add <tt>options "COM_MULTIPORT"</tt> or it + will not work very well! + +<tscreen><verb> +device sio4 at isa? port 0x100 tty flags 0xb05 +device sio5 at isa? port 0x108 tty flags 0xb05 +device sio6 at isa? port 0x110 tty flags 0xb05 +device sio7 at isa? port 0x118 tty flags 0xb05 +device sio8 at isa? port 0x120 tty flags 0xb05 +device sio9 at isa? port 0x128 tty flags 0xb05 +device sio10 at isa? port 0x130 tty flags 0xb05 +device sio11 at isa? port 0x138 tty flags 0xb05 irq 9 vector siointr +</verb></tscreen> + + The trick in setting this up is that the MSB of the + flags represent the last SIO port, in this case 11 so + flags are 0xb05. + +<sect2><heading>Boca 16</heading> + + <p><em>Contributed by &a.whiteside;.<newline>26 August + 1995.</em> + + The procedures to make a Boca 16 pord board with + FreeBSD are pretty straighforward, but you will need + a couple things to make it work: + + <enum> + <item>You either need the kernel sources installed + so you can recompile the necessary options or + you will need someone else to compile it for you. + The 2.0.5 default kernel does <bf>not</bf> come with + multiport support enabled and you will need to add + a device entry for each port anyways. + </item> + <item>Two, you will need to know the interrupt and IO + setting for your Boca Board so you can set these + options properly in the kernel.</item> + </enum> + + One important note - the actual UART chips for the + Boca 16 are in the connector box, not on the internal + board itself. So if you have it unplugged, probes of + those ports will fail. I have never tested booting with + the box unplugged and plugging it back in, and I + suggest you do not either. + + If you do not already have a custom kernel + configuration file set up, refer to <ref + id="kernelconfig" name="Kernel Configuration"> for + general procedurs. The following are the specifics + for the Boca 16 board and assume you are using the + kernel name MYKERNEL and editing with vi. + + <enum> + <item>Add the line +<tscreen><verb> +options "COM_MULTIPORT" +</verb></tscreen> +to the config file. +</item> + + <item>Where the current <tt>device sio + <em>xxx</em></tt> lines are, you will need to add + 16 more devices. <em>Only the last device + includes the interrupt vector for the + board</em>. (See the <tt>sio(4)</tt> manual page + for detail as to why.) + + The following example is for a Boca Board with an + interrupt of 3, and a base IO address 100h. The + IO address for Each port is +8 hexidecimal from + the previous port, thus the 100h, 108h, 110h... + addresses. + +<tscreen><verb> +device sio1 at isa? port 0x100 tty flags 0x1005 +device sio2 at isa? port 0x108 tty flags 0x1005 +device sio3 at isa? port 0x110 tty flags 0x1005 +device sio4 at isa? port 0x118 tty flags 0x1005 +... +device sio15 at isa? port 0x170 tty flags 0x1005 +device sio16 at isa? port 0x178 tty flags 0x1005 irq 3 vector siointr +</verb></tscreen> + + The flags entry <em>must</em> be changed from + this example unless you are using the exact same + sio assignments. Flags are set according to + 0x<em>MYY</em> where <em>M</em> indicates the + minor number of the master port (the last port on + a Boca 16) and <em>YY</em> indicates if FIFO is + enabled or disabled(enabled), IRQ sharing is + used(yes) and if there is an AST/4 compatible IRQ + control register(no). + + In this example, +<tscreen><verb> +flags 0x1005 +</verb></tscreen> + + indicates that the master port is sio16. If I + added another board and assigned sio17 through + sio28, the flags for all 16 ports on + <em>that</em> board would be 0x1C05, where 1C + indicates the minor number of the master port. + Do not change the 05 setting.</item> + + <item>Save and complete the kernel configuration, + recompile, install and reboot. + + Presuming you have successfully installed the + recompiled kernel and have it set to the correct + address and IRQ, your boot message should + indicate the successful probe of the Boca ports + as follows: (obviously the sio numbers, IO and + IRQ could be different) + +<tscreen><verb> +sio1 at 0x100-0x107 flags 0x1005 on isa +sio1: type 16550A (multiport) +sio2 at 0x108-0x10f flags 0x1005 on isa +sio2: type 16550A (multiport) +sio3 at 0x110-0x117 flags 0x1005 on isa +sio3: type 16550A (multiport) +sio4 at 0x118-0x11f flags 0x1005 on isa +sio4: type 16550A (multiport) +sio5 at 0x120-0x127 flags 0x1005 on isa +sio5: type 16550A (multiport) +sio6 at 0x128-0x12f flags 0x1005 on isa +sio6: type 16550A (multiport) +sio7 at 0x130-0x137 flags 0x1005 on isa +sio7: type 16550A (multiport) +sio8 at 0x138-0x13f flags 0x1005 on isa +sio8: type 16550A (multiport) +sio9 at 0x140-0x147 flags 0x1005 on isa +sio9: type 16550A (multiport) +sio10 at 0x148-0x14f flags 0x1005 on isa +sio10: type 16550A (multiport) +sio11 at 0x150-0x157 flags 0x1005 on isa +sio11: type 16550A (multiport) +sio12 at 0x158-0x15f flags 0x1005 on isa +sio12: type 16550A (multiport) +sio13 at 0x160-0x167 flags 0x1005 on isa +sio13: type 16550A (multiport) +sio14 at 0x168-0x16f flags 0x1005 on isa +sio14: type 16550A (multiport) +sio15 at 0x170-0x177 flags 0x1005 on isa +sio15: type 16550A (multiport) +sio16 at 0x178-0x17f irq 3 flags 0x1005 on isa +sio16: type 16550A (multiport master) +</verb></tscreen> + + If the messages go by too fast to see, <tt>dmesg + > more</tt> will show you the boot + messages.</item> + + <item>Next, apprepriate entries in <tt>/dev</tt> for the devices + must be made using the <tt>/dev/MAKEDEV</tt> + script. After becoming root: +<tscreen> +cd /dev<newline> +./MAKEDEV tty1<newline> +./MAKEDEV cua1<newline> +<em>.. (everything inbetween)</em><newline> +./MAKEDEV ttyg<newline> +./MAKEDEV cuag +</tscreen> + + If you do not want or need callout devices for some + reason, you can dispense with making the <tt>cua*</tt> + devices.</item> + + <item>If you want a quick and sloppy way to make + sure the devices are working, you can simply plug + a modem into each port and (as root) <tt>echo at + > ttyd*</tt> for each device you have + made. You <em>should</em> see the RX lights flash + for each working port.</item> + </enum> + + +<sect1><heading>* Parallel ports</heading> +<sect1><heading>* Modems</heading> +<sect1><heading>* Network cards</heading> +<sect1><heading>* Keyboards</heading> +<sect1><heading>* Mice</heading> +<sect1><heading>* Other</heading> + +<sect><heading>* Storage Devices<label id="hw:storage"></heading> + +<sect1><heading>* Disk/tape controllers</heading> + <sect2><heading>* SCSI</heading> + <sect2><heading>* IDE</heading> + <sect2><heading>* Floppy</heading> +<sect1><heading>* Hard drives</heading> +<sect1><heading>* Tape drives</heading> +<sect1><heading>* CD-ROM drives</heading> +<sect1><heading>* Other</heading> + +<sect><heading>* Other<label id="hw:other"></heading> + +<sect1><heading>* PCMCIA</heading> + + + diff --git a/share/doc/handbook/mirrors.sgml b/share/doc/handbook/mirrors.sgml new file mode 100644 index 0000000000000..bc6cefbfb7702 --- /dev/null +++ b/share/doc/handbook/mirrors.sgml @@ -0,0 +1,410 @@ +<!-- $Id:$ --> +<!-- The FreeBSD Documentation Project --> + +<!-- +<!doctype linuxdoc public "-//FreeBSD//DTD linuxdoc//EN"> +--> + +<chapt><heading>Obtaining FreeBSD<label id="mirrors"></heading> + +<p>The official sources for FreeBSD available via anonymous FTP from: +<quote> +<htmlurl url="ftp://ftp.freebsd.org/pub/FreeBSD" +name="ftp://ftp.FreeBSD.org/pub/FreeBSD"> +</quote> +and on CD-ROM from Walnut Creek CDROM: +<quote> + Walnut Creek CDROM<newline> + 1547 Palos Verdes Mall, Suite 260<newline> + Walnut Creek CA 94596 USA<newline> + Phone: +1 510 647-0783<newline> + Fax: +1 510 647-0821<newline> + Email: <htmlurl url="mailto:info@cdrom.com" name="info@cdrom.com"><newline> + WWW: <htmlurl url="http://www.cdrom.com/" name="http://www.cdrom.com/"> +</quote> + +<p>Additionally, FreeBSD is available via anonymous FTP from the + following mirror sites. If you choose to obtain FreeBSD via + anonymous FTP, please try to use a site near you. + +<descrip> +<tag>Australia</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.physics.usyd.edu.au/FreeBSD" + name="ftp://ftp.physics.usyd.edu.au/FreeBSD"><newline> + Contact: <htmlurl url="mailto:dawes@xfree86.org" + name="dawes@xfree86.org">. + +<item> +<htmlurl url="ftp://minnie.cs.adfa.oz.au/FreeBSD" + name="ftp://minnie.cs.adfa.oz.au/FreeBSD"><newline> + Contact: <htmlurl url="mailto:wkt@dolphin.cs.adfa.oz.au" + name="wkt@dolphin.cs.adfa.oz.au">. + +</itemize> + +<tag>Canada</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.synapse.net/contrib/FreeBSD" + name="ftp://ftp.synapse.net/contrib/FreeBSD"><newline> + Contact: <htmlurl url="mailto:evanc@synapse.net" + name="evanc@synapse.net">. + +</itemize> + +<tag>Finland</tag> + +<itemize> + +<item> +<htmlurl url="ftp://nic.funet.fi/pub/unix/FreeBSD" + name="ftp://nic.funet.fi/pub/unix/FreeBSD"><newline> + Contact: <htmlurl url="mailto:count@nic.funet.fi" + name="count@nic.funet.fi">. + +</itemize> + +<tag>France</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.ibp.fr/pub/FreeBSD" + name="ftp://ftp.ibp.fr/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:Remy.Card@ibp.fr" + name="Remy.Card@ibp.fr">. + +</itemize> + +<tag>Germany</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.fb9dv.uni-duisburg.de/pub/unix/FreeBSD" + name="ftp://ftp.fb9dv.uni-duisburg.de/pub/unix/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ftp@ftp.fb9dv.uni-duisburg.de" + name="ftp@ftp.fb9dv.uni-duisburg.de">. + +<item> +<htmlurl url="ftp://gil.physik.rwth-aachen.de/pub/FreeBSD" + name="ftp://gil.physik.rwth-aachen.de/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:kuku@gil.physik.rwth-aachen.de" + name="kuku@gil.physik.rwth-aachen.de">. + +<item> +<htmlurl url="ftp://ftp.uni-paderborn.de/freebsd" + name="ftp://ftp.uni-paderborn.de/freebsd"><newline> + Contact: <htmlurl url="mailto:ftp@uni-paderborn.de" + name="ftp@uni-paderborn.de">. + +<item> +<htmlurl url="ftp://ftp.leo.org/pub/comp/os/bsd/FreeBSD" + name="ftp://ftp.leo.org/pub/comp/os/bsd/FreeBSD"><newline> + Contact: <htmlurl url="mailto:bsd@leo.org" + name="bsd@leo.org">. + +<item> +<htmlurl url="ftp://ftp.tu-dresden.de/pub/soft/unix/bsd/FreeBSD" + name="ftp://ftp.tu-dresden.de/pub/soft/unix/bsd/FreeBSD"><newline> + Contact: <htmlurl url="mailto:pdsowner@rcs1.urz.tu-dresden.de" + name="pdsowner@rcs1.urz.tu-dresden.de">. + +</itemize> + +<tag>Ireland</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.internet-eireann.ie/pub/FreeBSD" + name="ftp://ftp.internet-eireann.ie/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ftpadmin@internet-eireann.ie" + name="ftpadmin@internet-eireann.ie">. + +</itemize> + +<tag>Israel</tag> + +<itemize> + +<item> +<htmlurl url="ftp://orgchem.weizmann.ac.il/pub/FreeBSD" + name="ftp://orgchem.weizmann.ac.il/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:serg@klara.weizmann.ac.il" + name="serg@klara.weizmann.ac.il">. + +</itemize> + +<tag>Hong Kong</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.hk.super.net/pub/FreeBSD" + name="g ftp://ftp.hk.super.net/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ftp-admin@HK.Super.NET" + name="ftp-admin@HK.Super.NET">. + +</itemize> + +<tag>Korea</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.cau.ac.kr/pub/FreeBSD" + name="ftp://ftp.cau.ac.kr/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ftpadm@ftp.cau.ac.kr" + name="ftpadm@ftp.cau.ac.kr">. + +</itemize> + +<tag>Netherlands</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.nl.net/pub/os/FreeBSD" + name="ftp://ftp.nl.net/pub/os/FreeBSD"><newline> + Contact: <htmlurl url="mailto:archive@nl.net" + name="archive@nl.net">. + +</itemize> + +<tag>Russia</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.kiae.su/FreeBSD" + name="ftp://ftp.kiae.su/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ftp@ftp.kiae.su" + name="ftp@ftp.kiae.su">. + +</itemize> + +<tag>Sweden</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.luth.se/pub/FreeBSD" + name="ftp://ftp.luth.se/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ragge@ludd.luth.se" + name="ragge@ludd.luth.se">. + +</itemize> + +<tag>Taiwan</tag> + +<itemize> + +<item> +<htmlurl url="ftp://NCTUCCCA.edu.tw/Operating-Systems/FreeBSD" + name="ftp://NCTUCCCA.edu.tw/Operating-Systems/FreeBSD"><newline> + Contact: <htmlurl url="mailto:freebsd@NCTUCCCA.edu.tw" + name="freebsd@NCTUCCCA.edu.tw">. + +<item> +<htmlurl url="ftp://netbsd.csie.nctu.edu.tw/pub/FreeBSD" + name="ftp://netbsd.csie.nctu.edu.tw/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ftp@netbsd.csie.nctu.edu.tw" + name="ftp@netbsd.csie.nctu.edu.tw">. + +</itemize> + +<tag>Thailand</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.nectec.or.th/pub/FreeBSD" + name="ftp://ftp.nectec.or.th/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ftpadmin@ftp.nectec.or.th" + name="ftpadmin@ftp.nectec.or.th">. + +</itemize> + +<tag>USA</tag> + +<itemize> + +<item> +<htmlurl url="ftp://gatekeeper.dec.com/pub/BSD/FreeBSD" + name="ftp://gatekeeper.dec.com/pub/BSD/FreeBSD"><newline> + Contact: <htmlurl url="mailto:hubbard@gatekeeper.dec.com" + name="hubbard@gatekeeper.dec.com">. + +<item> +<htmlurl url="ftp://ftp.cybernetics.net/pub/FreeBSD" + name="ftp://ftp.cybernetics.net/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:michael@Cybernetics.NET" + name="michael@Cybernetics.NET">. + +<item> +<htmlurl url="ftp://ftp.neosoft.com/systems/FreeBSD" + name="ftp://ftp.neosoft.com/systems/FreeBSD"><newline> + Contact: <htmlurl url="mailto:smace@NeoSoft.COM" + name="smace@NeoSoft.COM">. + +<item> +<htmlurl url="ftp://kryten.atinc.com/pub/FreeBSD" + name="ftp://kryten.atinc.com/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:jmb@kryten.atinc.com" + name="jmb@kryten.atinc.com">. + +<item> +<htmlurl url="ftp://ftp.dataplex.net/pub/FreeBSD" + name="ftp://ftp.dataplex.net/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:rkw@dataplex.net" + name="rkw@dataplex.net">. + +<item> +<htmlurl url="ftp://ftp.cps.cmich.edu/pub/ftp.freebsd.org" + name="ftp://ftp.cps.cmich.edu/pub/ftp.freebsd.org"><newline> + Contact: <htmlurl url="mailto:ftpadmin@cps.cmich.edu" + name="ftpadmin@cps.cmich.edu">. + +<item> +<htmlurl url="ftp://ftp.cslab.vt.edu/pub/FreeBSD" + name="ftp://ftp.cslab.vt.edu/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ftp@ftp.cslab.vt.edu" + name="ftp@ftp.cslab.vt.edu">. + +</itemize> + +<tag>Japan</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.tokyonet.ad.jp/pub/FreeBSD" + name="ftp://ftp.tokyonet.ad.jp/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ftpadmin@TokyoNet.AD.JP" + name="ftpadmin@TokyoNet.AD.JP">. + +<item> +<htmlurl url="ftp://ftp.tut.ac.jp/FreeBSD" + name="ftp://ftp.tut.ac.jp/FreeBSD"><newline> + Contact: <htmlurl url="mailto:<ashida@ftp.tut.ac.jp" + name="ashida@ftp.tut.ac.jp">. + +<item> +<htmlurl url="ftp://ftp.sra.co.jp/pub/os/FreeBSD" + name="ftp://ftp.sra.co.jp/pub/os/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ftp-admin@sra.co.jp" + name="ftp-admin@sra.co.jp">. + +<item> +<htmlurl url="ftp://ftp.ee.uec.ac.jp/pub/os/mirror/ftp.freebsd.org" + name="ftp://ftp.ee.uec.ac.jp/pub/os/mirror/ftp.freebsd.org"><newline> + Contact: <htmlurl url="mailto:ftp-admin@ftp.ee.uec.ac.jp" + name="ftp-admin@ftp.ee.uec.ac.jp">. + +<item> +<htmlurl url="ftp://ftp.mei.co.jp/free/PC-UNIX/FreeBSD" + name="ftp://ftp.mei.co.jp/free/PC-UNIX/FreeBSD"><newline> + Contact: <htmlurl url="mailto:tanig@isl.mei.co.jp" + name="tanig@isl.mei.co.jp">. + +<item> +<htmlurl url="ftp://ftp.waseda.ac.jp/pub/FreeBSD" + name="ftp://ftp.waseda.ac.jp/pub/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ftp-admin@waseda.ac.jp" + name="ftp-admin@waseda.ac.jp">. + +<item> +<htmlurl url="ftp://ftp.pu-toyama.ac.jp/pub/FreeBSD" + name="ftp://ftp.pu-toyama.ac.jp/pub/FreeBSD"><newline> + Contact: Yoshihiko USUI <htmlurl url="mailto:usui@pu-toyama.ac.jp" + name="usui@pu-toyama.ac.jp">. + +<item> +<htmlurl url="ftp://ftpsv1.u-aizu.ac.jp/pub/os/FreeBSD" + name="ftp://ftpsv1.u-aizu.ac.jp/pub/os/FreeBSD"><newline> + Contact: <htmlurl url="mailto:ftp-admin@u-aizu.ac.jp" + name="ftp-admin@u-aizu.ac.jp">. + +</itemize> + +<tag>UK</tag> + +<itemize> + +<item> +<htmlurl url="ftp://src.doc.ic.ac.uk/packages/unix/FreeBSD" + name="ftp://src.doc.ic.ac.uk/packages/unix/FreeBSD"><newline> + Contact: <htmlurl url="mailto:wizards@doc.ic.ac.uk" + name="wizards@doc.ic.ac.uk">. + +<item> +<htmlurl url="ftp://unix.hensa.ac.uk/pub/walnut.creek/FreeBSD" + name="ftp://unix.hensa.ac.uk/pub/walnut.creek/FreeBSD"><newline> + Contact: <htmlurl url="mailto:archive-admin@unix.hensa.ac.uk" + name="archive-admin@unix.hensa.ac.uk">. + +<item> +<htmlurl url="ftp://ftp.demon.co.uk/pub/BSD/FreeBSD" + name="ftp://ftp.demon.co.uk/pub/BSD/FreeBSD"><newline> + Contact: <htmlurl url="mailto:uploads@demon.net" + name="uploads@demon.net">. + +</itemize> +</descrip> + +The latest versions of export-restricted code for FreeBSD (2.0C or later) +(eBones and secure) are being made available at the following locations. +If you are outside the U.S. or Canada, please get secure (DES) and +eBones (Kerberos) from one of the following foreign distribution sites: + +<descrip> + +<tag>SouthAfrica</tag> + +<itemize> + +<item> +<htmlurl url="ftp://skeleton.mikom.csir.co.za/pub/FreeBSD" + name="ftp://skeleton.mikom.csir.co.za/pub/FreeBSD"><newline> + Contact: Mark Murray <htmlurl url="mailto:mark@grondar.za" + name="mark@grondar.za">. + +<item> +<htmlurl url="ftp://storm.sea.uct.ac.za/pub/FreeBSD" + name="ftp://storm.sea.uct.ac.za/pub/FreeBSD"><newline> + Contact: Shaun Courtney <htmlurl url="mailto:ftp@storm.sea.uct.ac.za" + name="ftp@storm.sea.uct.ac.za">. + +</itemize> + +<tag>Brazil</tag> + +<itemize> + +<item> +<htmlurl url="ftp://ftp.iqm.unicamp.br/pub/FreeBSD" + name="ftp://ftp.iqm.unicamp.br/pub/FreeBSD"><newline> + Contact: Pedro A M Vazquez <htmlurl url="mailto:vazquez@iqm.unicamp.br" + name="vazquez@iqm.unicamp.br">. + +</itemize> + +<tag>Finland</tag> + +<itemize> + +<item> +<htmlurl url="ftp://nic.funet.fi/pub/unix/FreeBSD/eurocrypt" + name="ftp://nic.funet.fi/pub/unix/FreeBSD/eurocrypt"><newline> + Contact: <htmlurl url="mailto:count@nic.funet.fi" + name="count@nic.funet.fi">. + +</itemize> +</descrip>
\ No newline at end of file diff --git a/share/doc/handbook/sections.sgml b/share/doc/handbook/sections.sgml new file mode 100644 index 0000000000000..0c8a2b1b42835 --- /dev/null +++ b/share/doc/handbook/sections.sgml @@ -0,0 +1,38 @@ +<!-- $Id$ --> +<!-- The FreeBSD Documentation Project --> + +<!-- Entities containing all the pieces of the handbook are --> +<!-- defined here --> + +<!ENTITY bibliography SYSTEM "bibliography.sgml"> +<!ENTITY basics SYSTEM "basics.sgml"> +<!ENTITY booting SYSTEM "booting.sgml"> +<!ENTITY contrib SYSTEM "contrib.sgml"> +<!ENTITY ctm SYSTEM "ctm.sgml"> +<!ENTITY current SYSTEM "current.sgml"> +<!ENTITY dialup SYSTEM "dialup.sgml"> +<!ENTITY diskless SYSTEM "diskless.sgml"> +<!ENTITY eresources SYSTEM "eresources.sgml"> +<!ENTITY glossary SYSTEM "glossary.sgml"> +<!ENTITY history SYSTEM "history.sgml"> +<!ENTITY hw SYSTEM "hw.sgml"> +<!ENTITY install SYSTEM "install.sgml"> +<!ENTITY kerberos SYSTEM "kerberos.sgml"> +<!ENTITY kernelconfig SYSTEM "kernelconfig.sgml"> +<!ENTITY kerneldebug SYSTEM "kerneldebug.sgml"> +<!ENTITY memoryuse SYSTEM "memoryuse.sgml"> +<!ENTITY mirrors SYSTEM "mirrors.sgml"> +<!ENTITY nfs SYSTEM "nfs.sgml"> +<!ENTITY nutshell SYSTEM "nutshell.sgml"> +<!ENTITY porting SYSTEM "porting.sgml"> +<!ENTITY ports SYSTEM "ports.sgml"> +<!ENTITY ppp SYSTEM "ppp.sgml"> +<!ENTITY relnotes SYSTEM "relnotes.sgml"> +<!ENTITY scsi SYSTEM "scsi.sgml"> +<!ENTITY slipc SYSTEM "slipc.sgml"> +<!ENTITY slips SYSTEM "slips.sgml"> +<!ENTITY submitters SYSTEM "submitters.sgml"> +<!ENTITY sup SYSTEM "sup.sgml"> +<!ENTITY troubleshooting SYSTEM "troubleshooting.sgml"> +<!ENTITY userppp SYSTEM "userppp.sgml"> + diff --git a/share/examples/startslip/sldown.sh b/share/examples/startslip/sldown.sh new file mode 100755 index 0000000000000..1f342a47b0c9c --- /dev/null +++ b/share/examples/startslip/sldown.sh @@ -0,0 +1,3 @@ +#!/bin/sh +/sbin/ifconfig $1 $2 +/sbin/route delete default diff --git a/share/examples/startslip/slip.sh b/share/examples/startslip/slip.sh new file mode 100755 index 0000000000000..1a0c1ad7f831b --- /dev/null +++ b/share/examples/startslip/slip.sh @@ -0,0 +1,4 @@ +#!/bin/sh +startslip -b 57600 -U ./slup.sh -D ./sldown.sh \ + -s atd<phone1> -s atd<phone2> -s atd<phone3> \ + -h -t 60 -w 2 -W 20 /dev/cuaa1 <login> <password> diff --git a/share/examples/startslip/slup.sh b/share/examples/startslip/slup.sh new file mode 100755 index 0000000000000..79cded3395585 --- /dev/null +++ b/share/examples/startslip/slup.sh @@ -0,0 +1,16 @@ +#!/bin/sh +myname=<my.ip.address> +gateway=<gateway.ip.address> +netmask=255.255.255.248 +tune1="link0 -link2" # force headers compression +tune2="mtu 296" # for FreeBSD 1.x host + +case $LINE in + 0) tune=$tune1;; # 1st phone connected + 1) tune=$tune2;; # 2nd phone connected + *) tune=;; # others +esac + +/sbin/ifconfig $1 $2 $tune +/sbin/ifconfig $1 inet $myname $gateway netmask $netmask +/sbin/route add default $gateway diff --git a/share/man/man4/man4.i386/asc.4 b/share/man/man4/man4.i386/asc.4 new file mode 100644 index 0000000000000..fc187f306bb13 --- /dev/null +++ b/share/man/man4/man4.i386/asc.4 @@ -0,0 +1,179 @@ +.\" asc(4) - manual page for the scanner device driver `asc' +.\" +.\" +.\" Copyright (c) 1995 Gunther Schadow, Luigi Rizzo. All rights reserved. +.\" +.\" 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 above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 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 acknowledgements: +.\" This product includes software developed by Gunther Schadow. +.\" This product includes software developed by Luigi Rizzo. +.\" 4. The name of the author may not be used to endorse or promote products +.\" derived from this software without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. +.TH ASC 4 "January 6, 1995" FreeBSD "FreeBSD Programmer's Manual" +.SH NAME +\fBasc\fP - a device driver for a handy scanner +.SH SYNOPSIS +.TP +\fB#include <machine/asc_ioctl.h>\fP +.TP +\fBMinor number bits:\fP \fIuu d g p ...\fP +\fIuu\fP - unit asc0 .. asc3 +\fI d\fP - selects logging of \fIdebug\fP messages +\fI g\fP - selects \fIbitmap\fP vs. \fIgraymap\fP output +\fI p\fP - selects \fIraw\fP vs. portable \fIpnm\fP output +.TP +\fBdd if=/dev/asc0 of=rawfile bs=(width/8) count=(height) +.TP +\fBcat /dev/asc0p > pbmfile\fP +.PB +.SH DESCRIPTION +The \fBasc\fP character device driver currently handles the +GI1904-based hand scanner (e.g. Trust Amiscan Grey). +It uses DMA and interrupts. Input data from the scanner are +buffered, up to 50 scanlines are buffered in the driver. +.PP +The device can operate at four different \fIresolutions\fP: 100, 200, +300 and 400dpi. It produces a simple bitmap with the most significant bit +at the left side. The driver can optionally output the famous and +likely simple portable bitmap file format pbm(5) by Jef +Poskanzer. Thus the scans can easily processed by any graphic package +around (xpaint, xv, xli only to name some of them ...). +.PP +The \fIwidth\fP of the output bitmap is fixed as given by the +resolution value. However, the \fIheight\fP of the bitmap must be +supplied in \fIpnm\fP mode since the driver must know at what time the +'end-of-file' shall be reached. The default is to produce a +square image, i.e. \fIheight=width\fP. With this feature you are able to +directly copy the scanner output into a pbm file whith cat(1). Of +course you can obtain a similar effect by using dd(1) with the driver +in \fIraw\fP mode. +.PP +The \fIgraymap\fP output mode is not yet implemented into the driver. +It is even questionable if external programs would not do this job +better thereby not counting to the size of the kernel. Even though, I +do not know of tools which produce a graymap from a halftone bitmap. +.SH IOCTL REQUESTS +The ioctl requests that are served by \fBasc\fP are listed below. +There is a utility, called sasc(1), that provides access to these +requests from within shell. +.TP +ASC_GRES int +Get current resolution in dots per inch (dpi). +.TP +ASC_GWIDTH int +Get current width of the bitmap in pixels. +.TP +ASC_SHEIGHT int +Set the \fIheight\fP of the bitmap in \fIpnm\fP mode. This is actually +a limit on the amount of lines scannable after the first read +operation. When the limit is reached read will return 0. However, the +device is turned off only when a close is performed (either +explicitely or implicitely on exit of the calling process). +.TP +ASC_GHEIGHT int +Get the current height of the bitmap. +.TP +ASC_SBLEN int +Set the length of the buffer used internally to do the DMA transfer. +The buffer length is supplied in lines of the bitmap. Since the buffer +size limit is (currently) 0x3000 bytes the maximum number of lines +allowed will vary with the width of each line. This upper limit is +checked before it overwrites the current value and pases an ENOMEM in +the \fBerrno\fP variable. However, since the bitmap width can change +after a buffer length was selected a read request may fail with ENOMEM +if the buffer length turns out too high. It is generally wise to +choose long buffers rather than go save in order to obtain better +output. +.TP +ASC_GBLEN int +Get the current buffer length in lines. +.TP +ASC_SBTIME int +Set the timeout for the completion of reading one buffer. Since a +handy scanner is a human/computer interface timeout values are usually +higher than those of a flat scanner. Default is 15 seconds. After +timeout is reached the read operation will fail with EBUSY. Note that +the timeout timer starts anew for each buffer to be read and thus does +not cause you to scan faster for longer images. BLEN/BTIME is similar +as MIN/TIME in termios(4). +.TP +ASC_GBTIME int +Get the current buffer timeout. +.PP +All ioctl requests that modify a parameter except ASC_SBTIME do not +have an effect on an ongoing scan process, i.e. after the first read +request that follows open. You must close the device and open it again +for the new selections to take effect. Consequently, the selections +are not reset when you close or open the device. +.PP +Similarily, requests that read a value do not report the value that is +used for the ongoing scan process. The values needed during the scan +process are saved when it starts and thus are not accessed by ioctl +requests. +.PP +The BTIME value does, however, have an immediate effect on the ongoing +scan. Thus the timeout can for example be set to long until the user +starts scanning. It can then be set to a short amount to react +(nearly) immediately when the user stops. Note that the user should be +left time to at least fill one buffer without having to haste. +.PP +Note that the \fIpbm\fP versus \fIraw\fP mode selection is done by the +minor number not by ioctl requests. In \fIraw\fP mode the selected +height of the bitmap will have no effect. +.SH FILES +.TP 15 +.BI /dev/asc0 +device node for \fIraw\fP output, has minor number 0. +.TP +.BI /dev/asc0d +device node for \fIraw\fP output emiting \fIdebug\fP messages if the +ASCDEBUG option was given at compile time, has minor number 32. +.TP +.BI /dev/asc0p +device node for output in \fIpbm\fP file format, has minor number 8. +.TP +.BI /dev/asc0pd +device node for \fIpbm\fP and \fIdebug\fP mode, has minor number 40. +.PB +.SH DIAGNOSTICS +.TP +\fBASCDEBUG\fP +When you define this name as an `option' in the kernel configuration +you can get debug output if you access the driver with a minor number +whose debug bit (i.e. bit 5 out of 7) is set. +.SH SEE ALSO +.nh +open(2), +ioctl(2), +intro(2), +read(2), +close(2), +cat(1), +dd(1), +pbm(5), +pnm(1), +termios(4). +.hy +.SH BUGS +Ioctl support is not working yet. +.SH AUTHOR +Luigi Rizzo <luigi.rizzo@iet.unipi.it> diff --git a/share/man/man4/man4.i386/meteor.4 b/share/man/man4/man4.i386/meteor.4 new file mode 100644 index 0000000000000..c4c26185e2071 --- /dev/null +++ b/share/man/man4/man4.i386/meteor.4 @@ -0,0 +1,771 @@ +.Dd August 15, 1995 +.br +.in +0.5i +.Dt METEOR 4 +.Os FreeBSD +.Sh NAME +.Nm meteor +.Nd video capture driver +.Sh SYNOPSIS +.Nm video meteor +.Sh DESCRIPTION +The +.Xr meteor +driver provides support for a PCI +.Em video +capture. It allows the capture of 24 bit RGB, 16 bit RGB and 16 bit YUV +output formats. + +.Pp +.Sh Meteor Driver Installation +To use the Matrox Meteor card in your system, you need a computer +that support the PCI (preferably the Type 2 or better) interface bus. +It is recommended that the system has as more than 16 MB of RAM since this +capture card directly deposits the image to system RAM. +.Pp +The files required for Matrox Meteor card are: +.br +.in +0.5i +/sys/pci/meteor.c +.br +/sys/i386/include/ioctl_meteor.h (also known as: +.br +/usr/include/machine/ioctl_meteor.h) +.br +.in -0.5i +For FreeBSD release versions 2.1 and earlier, the following patch files are also required: +.br +.in +0.5i +meteor/usr/sys/i386/i386/conf.patch +.br +meteor/usr/sys/conf/files.patch +.br +meteor/sys/i386/conf/LINT.patch +.br +These files are available for anonymous ftp at: +.br +.in +0.5i +ftp://joy.cs.ndsu.nodak.edu/pub/meteor.tgz +.br +.in -1.0i +.Pp +1) In the configuration file, add the line (as shown in +meteor/usr/sys/i386/conf/LINT.patch): +.Pp +.Em device meteor0 +.Pp +2) There is also a couple of optional parameters you may use +.Pp +.Em options "METEOR_ALLOC_PAGES=xxx" +specifies the number of contiguous pages to allocate when successfully +probed. The default number of pages allocated by the kernel is 151. +This means that there are (151*4096) bytes available for use. +.Pp +.Em options METEOR_DEALLOC_PAGES +deallocate all pages when closing the device. Note, the chance of +contiguously re-allocating new pages are very small. The default +behavior is to not deallocate pages. +.Pp +.Em options "METEOR_DEALLOC_ABOVE=xxx" +deallocate all pages above the specified number. The default action is +to not deallocate above any pages. +.Pp +3) Make and install the kernel. +.Pp +4) Make the special file name: +.Pp +.Em mknod /dev/meteor0 c <major> 0 +The major number is determined by the placement of the device in conf.c. +The patch supplied with the driver will make the major number 67. +.Pp +.Sh Meteor Capture Modes +The Meteor capture driver has three modes of capture operation. +.Pp +1) Conventional read(2) interface. +.in +0.5i +.Pp +This mode is the easiest and slowest to use. This mode is great for +capturing a single field at little programming cost. +.Pp +In this mode, the user opens the device, set the capture mode +and size (See: METEORSETGEO ioctl call), and uses the read system +call to load the data into a buffer. +.Pp +meteor_read.c; read 400x300 RGB24 into a viewable PPM file +.Pp +.in -0.5i +.nf +#include <sys/fcntl.h> +#include <machine/ioctl_meteor.h> + +extern int errno; +#define ROWS 300 +#define COLS 400 +#define SIZE (ROWS * COLS * 4) +main() +{ + struct meteor_geomet geo; + char buf[SIZE],b[4],header[16],*p; + int i,o,c; + + if ((i = open("/dev/meteor0", O_RDONLY)) < 0) { + printf("open failed: %d\n", errno); + exit(1); + } + /* set up the capture type and size */ + geo.rows = ROWS; + geo.columns = COLS; + geo.frames = 1; + geo.oformat = METEOR_GEO_RGB24 ; + + if (ioctl(i, METEORSETGEO, &geo) < 0) { + printf("ioctl failed: %d\n", errno); + exit(1); + } + + c = METEOR_FMT_NTSC; + + if (ioctl(i, METEORSFMT, &c) < 0) { + printf("ioctl failed: %d\n", errno); + exit(1); + } + + c = METEOR_INPUT_DEV0; + + if (ioctl(i, METEORSINPUT, &c) < 0) { + printf("ioctl failed: %d\n", errno); + exit(1); + } + + if ((c=read(i, &buf[0], SIZE)) < SIZE) { + printf("read failed %d %d %d\n", c, i, errno); + close(i); + exit(1); + } + close(i); + + if ((o = open("rgb24.ppm", O_WRONLY | O_CREAT, 0644)) < 0) { + printf("ppm open failed: %d\n", errno); + exit(1); + } + + /* make PPM header and save to file */ + strcpy(&header[0], "P6 400 300 255 "); + header[2] = header[6] = header[10] = header[14] = '\n'; + write (o, &header[0], 15); + /* save the RGB data to PPM file */ + for (p = &buf[0]; p < &buf[SIZE]; ) { + b[2] = *p++; /* blue */ + b[1] = *p++; /* green */ + b[0] = *p++; /* red */ + *p++; /* NULL byte */ + write(o,&b[0], 3); /* not very efficient */ + } + close(o); + exit(0); +} +.if +.Pp + 2) Memory mapped single capture or unsynchronized continuous capture. +.in +0.5i +.Pp +The single capture mode is designed for conferencing tools such as nv. +These tools need to control the starting of the image capture and also +need several frames a second. The continuous capture mode is designed +for applications that want free-running data. +.Pp +In this mode, the user opens the device, set the capture mode +and size (See: METEORSETGEO ioctl call), memory maps the frame buffer +memory into the user process space, and issues either the +single-capture or the continuous capture call (See: METEORCAPTUR ioctl +call) to load the data into the memory mapped buffer. +.Pp +As explained in the METEORCAPTUR ioctl call, the single frame capture +ioctl will block until the capture is complete, the continuous capture +will return immediately. +.in -0.5i +.Pp + meteor_mmap_single_continuous.c +.Pp +.nf +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/fcntl.h> +#include <machine/ioctl_meteor.h> + +extern int errno; +#define ROWS 480 +#define COLS 640 +#define SIZE (ROW * COLS * 2) +main() +{ + struct meteor_geomet geo; + char buf[SIZE]; + char *mmbuf; + int i,c; + + if ((i = open("/dev/meteor0", O_RDONLY)) < 0) { + printf("open failed\n"); + exit(1); + } + + geo.rows = ROWS; + geo.columns = COLS; + geo.frames = 1; + geo.oformat = METEOR_GEO_RGB16 ; + + if (ioctl(i, METEORSETGEO, &geo) < 0) { + printf("ioctl failed: %d\n", errno); + exit(1); + } + + c = METEOR_FMT_NTSC; + + if (ioctl(i, METEORSFMT, &c) < 0) { + printf("ioctl failed: %d\n", errno); + exit(1); + } + + c = METEOR_INPUT_DEV0; + + if (ioctl(i, METEORSINPUT, &c) < 0) { + printf("ioctl failed: %d\n", errno); + exit(1); + } + + mmbuf=(char *)mmap((caddr_t)0, SIZE, PROT_READ, 0, i, (off_t)0); + +#ifdef SINGLE_MODE + /* single frame capture */ + c = METEOR_CAP_SINGLE ; + ioctl(i, METEORCAPTUR, &c); /* wait for the frame */ + + /* directly access the frame buffer array data in mmbuf */ +#else + /* continuous frame capture */ + c = METEOR_CAP_CONTINOUS ; + ioctl(i, METEORCAPTUR, &c); /* returns immediately */ + + /* directly access the frame buffer array data in mmbuf */ + + c = METEOR_CAP_STOP_CONT ; + ioctl(i, METEORCAPTUR, &c); /* close will also stop capture */ +#endif + + close(i); + exit(0); +} +.if +.Pp + 3) Memory mapped, multi-frame ring buffer synchronize capture. +.Pp +.in +0.5i +This continuous capture mode is synchronized with the application that +processes up to 32 frames. This gives the advantages of both single and +continuous capture modes. +.Pp +The kernel notifies the application of a new data by raising an +application defined signal. The driver also shares a structure with +the application that allows them to communicate which frame has been +written by the kernel and which frame has been read by the application. +.Pp +The shared structure starts on the first page after your data. The +structure address can be found by calculation: +.in +0.5i +.Pp +(number_rows * number_columns * pixel_depth + 4095) & 0xfffff000 +.in -0.5i +.Pp + or +.in +0.5i +.Pp +((number_rows * number_columns * pixel_depth + 4095)/4096) * 4096 +.in -0.5i +.Pp +The shared structure is of type struct meteor_mem. The two most +important fields are called active and num_active_buf. active +is a bitmap of frames written by the kernel. num_active_bufs is +a count of frames marked in the active field. When a frame is read +in by the driver, the num_active_bufs count is tested, if this +count is below the threshold of number of active frames (value +in meteor_mem's hiwat variable), the bit representing frame +number in the buffer is stored in the active variable, the +num_active_bufs is incremented, the kernel then raises the specified +signal to activate the user application. The user application's +responsibility when getting the signal is to check the active bitmap +to determine the lowest active frame, use the data as the application +desires, clear the bitmap entry for that frame, and decrement the +num_active_bufs. If the threshold of number of active frames (hiwat) +has been exceeded, no new frames or signal from the kernel will occur +until the num_active_bufs is less than or equal to lowat. +.Pp +The driver loads the frames in a round-robin fashion. it is expected +that the user removes them in the same order. The driver does not +check to see if the frame is already active. +.Pp +The frame_size and number of frames in the buffer are also provided +to the meteor_mem structure, but changing these fields in the +application will not change the operation of the driver. +.Pp +In programming for this mode, the user opens the device, sets the +geometry, mmaps the data/common control structure, then starts the +continuous capture mode. A special signal catcher is required to +process the frames as they are read by the kernel. +.Pp +When specifying the geometry (See: ioctl METEORSETGEO), it +is important that the number of frames is set greater than 1. +.in -0.5i +.Pp + skeleton_capture_n.c +.Pp +.nf +#include <sys/types.h> +#include <sys/mman.h> +#include <sys/fcntl.h> +#include <sys/signal.h> +#include <machine/ioctl_meteor.h> + +int video; /* made global if you wish to stop capture in signal handler */ +caddr_t data_frames; +struct meteor_mem *common_mem; +extern int errno; + +#define FRAME_MAX + +void +usr2_catcher() +{ +#ifdef SIGNAL_STOP + struct meteor_capframe capframe; /* for ioctl */ +#endif + char *frame; + + /* find frame */ + frame = (char *) (data_frames + sig_cnt * common_mem->frame_size) ; + + /* add frame processing here */ + /* deactivate frame */ + common_mem->active &= ~(1 << (sig_cnt % 16)); + common_mem->num_active_bufs--; + + /* process next frame on next interrupt */ + sig_cnt = ((sig_cnt+1) % FRAME_MAX); + +#ifdef SIGNAL_STOP + if (some_condition_requiring_stopping) { + capframe.command=METEOR_CAP_STOP_FRAMES; + + if (ioctl(i, METEORCAPFRM, &capframe) < 0) { + printf("METEORCAPFRM failed %d\n", errno); + exit(1); + } + } +#endif +} + +main() +{ + struct meteor_geomet geo; + int height, width, depth, frames, size; + struct meteor_capframe capframe; + + if ((i = open("/dev/meteor0", O_RDONLY)) < 0) { + printf("open failed\n"); + exit(1); + } + printf("test %d %d\n", errno, i); + + height = geo.rows = 120; + width= geo.columns = 320; + frames = geo.frames = FRAME_MAX; + depth = 2; /* 2 bytes per pixel for RGB*/ + + + geo.oformat = METEOR_GEO_RGB16; + + if (ioctl(i, METEORSETGEO, &geo) < 0) { + printf("METEORSETGEO failed %d\n", errno); + exit(1); + } + + c = METEOR_FMT_NTSC; + + if (ioctl(i, METEORSFMT, &c) < 0) { + printf("ioctl failed: %d\n", errno); + exit(1); + } + + c = METEOR_INPUT_DEV0; + + if (ioctl(i, METEORSINPUT, &c) < 0) { + printf("ioctl failed: %d\n", errno); + exit(1); + } + + size = ((width*height*depth*frames+4095)/4096)*4096; + /* add one page after data for meteor_mem */ + data_frames = mmap((caddr_t)0, size + 4096, PROT_READ | PROT_WRITE, + 0, i, (off_t)0); + + if (data_frames == (caddr_t) -1) return (0); + + /* common_mem is located at page following data */ + common_mem = (struct meteor_mem *) (y + size); + + signal(SIGUSR2, usr2_catcher); /* catch new frame message */ + + capframe.command=METEOR_CAP_N_FRAMES; + capframe.signal=SIGUSR2; + capframe.lowat=12; /* must be < hiwat */ + capframe.hiwat=14; /* must be < FRAME_MAX */ + + /* start the sync capture */ + if (ioctl(i, METEORCAPFRM, &capframe) < 0) { + printf("METEORCAPFRM failed %d\n", errno); + exit(1); + } + + /* this is the background working area, or you can sleep */ + + + /* to stop capture */ + capframe.command=METEOR_CAP_STOP_FRAMES; + + if (ioctl(i, METEORCAPFRM, &capframe) < 0) { + printf("METEORCAPFRM failed %d\n", errno); + exit(1); + } +} +.if +.Pp +.Sh Meteor IOCTL Call and Parameters +.Pp +The Meteor capture driver has ioctl requests for capturing, reading card +status, for setting and reading the geometry, and for setting and reading the +attributes. +.Pp +IT IS VERY IMPORTANT TO CHECK FOR ERRORS ON THESE RETURNING IOCTLs. +Errors indicate that something is very wrong with the ioctl and the +application should not attempt to proceed further with capturing. The +meteor capture driver still makes attempts to stop the next capture step if +an error occurred in a previous step but was ignored by the application +programmer. +.Pp +1) ioctl requests METEORSETGEO and METEORGETGEO +.in +0.5i +METEORSETGEO and METEORGETGEO are used to set and read the input +size, input device, and output format for frame capture. +.Pp +These ioctl routines use the meteor_geomet structure that has the +following entries: +.Pp +.Bl -tag -width columns +.It Dv rows +number of rows (lines high) in output image +.It Dv columns +number of pixels in a row (width) in output image +.It Dv frames +number of frames in buffer. Should be 1, unless using +the multi-framed synchronous capture mode (METEORCAPFRM) +which REQUIRES frames to be larger than 1. +.Pp +Note: if rows, columns or frames is not changed, then +the existing values are used. The system defaults +is 640x480x1. +.It Dv oformat +you may choose one of the following output format: +.Bl -tag -width METEOR_GEO_YUV_PACKED +.It Dv METEOR_GEO_RGB16 +RGB 16 bits xrrrrrgg gggbbbbb default) +.It Dv METEOR_GEO_RGB24 +(RBG 24 bits packed in 32 bits: +00000000 rrrrrrrr gggggggg bbbbbbbb) +.It Dv METEOR_GEO_YUV_PACKED +(4-2-2 YUV 16 bits packed. byte format: +u0 y0 v0 y1 u1 y2 v1 y3 ...) +.It Dv METEOR_GEO_YUV_PLANER +(4-2-2 YUV 16 bits planer format: +rows * columns bytes of y +rows * column / 4 bytes of even u +rows * column / 4 bytes of even v +rows * column / 4 bytes of odd u +rows * column / 4 bytes of odd v) +.El +.El +.Pp +The METEORSETGEO ioctl will fail if more than one entry from a category +is selected. It is highly recommended that a METEORSETGEO is done +before capturing data because you cannot guarantee the initial mode +the card. +.Pp +The METEORSETGEO will also attempt to reallocate a new contiguous +kernel buffer if the new geometry exceeds the old geometry. On +other hand, if the new geometry will fit in the existing buffer, +the existing buffer is used. +.Pp +If METEORSETGEO fails the ioctl() will return a value of -1 and the +external variable errno will be set to: +.Pp +.Bl -tag -width EINVAL +.It Dv EINVAL +invalid meteor_geomet structure pointer, rows, columns, +frames were invalid. +.It Dv ENOMEM +could not allocate the contigous block. +.El +.in -0.5i +.Pp +2) ioctl requests METEORSFMT and METEORGFMT +.in +0.5i +.Pp +METEORSFMT and METEORGFMT are used to set and read the camera input +standard format. +.Pp +Possible formats are: +.Bl -tag -width METEOR_FMT_AUTOMODE +.It Dv METEOR_FMT_NTSC +NTSC (default mode) +.It Dv METEOR_FMT_PAL +PAL +.It Dv METEOR_FMT_SECAM +SECAM +.It Dv METEOR_FMT_AUTOMODE +Autodetect. +.El +.in -0.5i +.Pp +3) ioctl requests METEORSINPUT and METEORGINPUT +.in +0.5i +.Pp +METEORSINPUT and METEORGINPUT are used to set and read the camera +input device. Using the DB9 connector on the Meteor card, 4 input +devices can be connected and an input camera can be selected with this +ioctl. +.Pp +Possible formats are: +.Bl -tag -width METEOR_INPUT_DEV_SVIDEO +.It Dv METEOR_INPUT_DEV0 +(default if none specified) +.It Dv METEOR_INPUT_DEV_RCA +(same as METEOR_INPUT_DEV0) +.It Dv METEOR_INPUT_DEV1 +.It Dv METEOR_INPUT_DEV2 +.It Dv METEOR_INPUT_DEV_SVIDEO +(same as METEOR_INPUT_DEV2) +.El +.in -0.5i +.Pp +4) ioctl request METEORSTATUS +.in +0.5i +.Pp +METEORSTATUS is used to read the status of the Meteor capture card +and returns the following information: +.Pp +.Bl -tag -width METEOR_STATUS_ID_MASK +.It Dv METEOR_STATUS_ID_MASK +4 bit ID of the SAA7196 scaler chip. +.It Dv METEOR_STATUS_DIR +0 = scaler uses internal source. +.br +1 = scaler uses external data of expansion bus. +.It Dv METEOR_STATUS_OEF +0 = even field detected. +.br +1 = odd field detected. +.It Dv METEOR_STATUS_SVP +VRAM Port state: +.br +0 = inputs HFL and INCADDR inactive. +.br +1 = inputs HFL and INCADDR active. +.It Dv METEOR_STATUS_STTC +0 = TV horizontal time constant (slow). +.br +1 = VCR horizontal time constant (fast). +.It Dv METEOR_STATUS_HCLK +0 = Horizontal Phase Lock Loop locked. +.br +1 = Horizontal Phase Lock Loop unlocked. +.It Dv METEOR_STATUS_FIDT +0 = 50 Hz Field detected. +.br +1 = 60 Hz Field detected. +.It Dv METEOR_STATUS_ALTD +0 = no line alternating color burst detected. +.br +1 = line alternating color burst detected +(PAL/SECAM). +.It Dv METEOR_STATUS_CODE +0 = no color information detected. +.br +1 = color information detected. +.El +.in -0.5i +.Pp +5) ioctl request METEORCAPTUR +.in +0.5i +.Pp +METEORCAPTUR is used to single frame capture or unsynchronized +continuous capture. +.Pp +The single frame capture ioctl request will return only after a +frame has been captured and transfered to the frame buffer. +.Pp +The unsynchronized continuous capture will return immediately and +data is directly deposited into the buffer when it is available. +Since this is unsynchronized, it is possible the data is being +written by the kernel while being read by the application. +.Pp +These ioctl routines use the following settings: +following entries: +.Pp +.Bl -tag -width METEOR_CAP_CONTINOUS +.It Dv METEOR_CAP_SINGLE +capture one frame +.It Dv METEOR_CAP_CONTINOUS +unsynchronized continuous capture +.It Dv METEOR_CAP_STOP_CONT +stop the unsynchronized continuous +capture +.El +.Pp +If METEORCAPTUR fails the ioctl() will return a value of -1 and the +external variable errno will be set to: +.Pp +.Bl -tag -width EINVAL +.It Dv EINVAL +invalid capture command value +.It Dv ENXIO +there is not internal buffer to hold the frame. +this indicates the previous set geometry ioctl failed. +.It Dv EIO +card is already capturing. +.El +.in -0.5i +.Pp +6) ioctl request METEORCAPFRM +.in +0.5i +.Pp +METEORCAPFRM is used for synchronous capture of multiple frames. +.Pp +This ioctl routines use the meteor_capture structure that has the +following entries: +.Pp +.Bl -tag -width command +.It Dv command +possible values for command are: +.Bl -tag -width METEOR_CAP_STOP_FRAMES +.It Dv METEOR_CAP_STOP_FRAMES stop the capture does not use the +other variable in structure. +.It Dv METEOR_CAP_N_FRAMES start the capture using the other +variables in the structure as inputs +.El +.It Dv signal +signal to send to application when a new +frame has been captured. This signal will +only be raised if the captured frame is saved. +.It Dv lowat +see below +.It Dv hiwat +see below +.El +.Pp +When a new frame is completed, the driver checks the current unread +frame count stored in shared variable (the shared variable are stored +in the meteor_mem structure) num_active_buf, if the count is larger +than hiwat, the driver will not store any new frames and will not +send capture signal to the user application until the num_active_buf +is lower than lowat. +.Pp +If METEORCAPFRM fails the ioctl() will return a value of -1 and the +external variable errno will be set to: +.Pp +.Bl -tag -width EINVAL +.It Dv EINVAL +invalid meteor_geomet structure pointer or bad command. +.It Dv ENXIO +there is not internal buffer to hold the frame. +this indicates the previous set geometry ioctl failed. +.It Dv EIO +card is already capturing. +.El +.in -0.5i +.Pp +7) ioctl requests METEORSCHCV and METEORGCHCV +.in +0.5i +.Pp +METEORSCHCV and METEORGCHCV are used to set and get the chrominance +gain control and effects the UV output amplitude. +.Pp +If METEORSCHCV or METEORGCHCV fails the ioctl() will return a value +of -1 and the external variable errno will be set to: +.Pp +.Bl -tag -width EINVAL +.It Dv EINVAL +EINVAL +invalid unsigned char pointer. +.El +.in -0.5i +.Pp +8) ioctl requests METEORGHUE and METEORSHUE +.in +0.5i +.Pp +METEORGHUE and METEORSHUE are used to get and set the hue. The +signed character has legal values are from +127 which represent ++178.6 degrees to -128 which represents -180 degrees. +.Pp +If METEORGHUE or METEORSHUE fails the ioctl() will return a value of +-1 and the external variable errno will be set to: +.Pp +.Bl -tag -width EINVAL +.It Dv EINVAL +invalid signed char pointer. +.El +.in -0.5i +.Pp +9) ioctl requests METEORSCOUNT and METEORGCOUNT +.in +0.5i +.Pp +METEORGCOUNT is used to get the count of frame errors, DMA errors and +count of the number of frames captured that have occurred since +the device was opened. METEORSCOUNT can be used to reinitialize the +counters. +.Pp +This ioctl routines use the meteor_counts structure that has the +following entries: +.Pp +.Bl -tag -width frame_count +.It Dv fifo_errors +number of FIFO errors since device was opened. +.It Dv dma_errors number of DMA errors since device was opened. + +.It Dv frame_count number of frames captured since device was opened. +.El +.Pp +If METEORSCOUNT or METEORGCOUNT fails the ioctl() will return a value +of -1 and the external variable errno will be set to: +.Bl -tag -width EINVAL +.It Dv EINVAL +invalid meteor_counts structure pointer. +.El +.in -0.5i +.Pp +.Sh Known Bugs: +.in +0.5i +.Pp +1) IIC register is difficult to set. We got around that by adding a long +wait at each IIC register write. +.Pp +2) We had difficulties getting the Meteor capture card to work on systems +that used NCR chipset SCSI cards. It is possible that the Meteor and NCR SCSI +could work together using the newer TRITON motherboards. +.in -0.5i +.Pp +.Sh Authors: +.Pp +.Bl -tag -width Mark_Tinguely +.It Dv Jim Lowe +(james@miller.cs.uwm.edu) +.It Dv Mark Tinguely +(tinguely@plains.nodak.edu) +.El diff --git a/share/mk/bsd.sgml.mk b/share/mk/bsd.sgml.mk new file mode 100644 index 0000000000000..799dfdb0c5535 --- /dev/null +++ b/share/mk/bsd.sgml.mk @@ -0,0 +1,151 @@ +# bsd.sgml.mk - 8 Sep 1995 John Fieber +# This file is in the public domain. +# +# $Id: bsd.sgml.mk,v 1.1 1995/09/08 19:23:19 jfieber Exp $ + +.if exists(${.CURDIR}/../Makefile.inc) +.include "${.CURDIR}/../Makefile.inc" +.endif + +# FORMATS indicates which output formats will be generated. See +# the sgmlfmt(1) man page for a list of valid formats. +# If FORMATS is empty, nothing will be built or installed. +# Use SGMLOPTS to pass extra flags to sgmlfmt(1). + +FORMATS?= ascii html +SGMLFLAGS+= ${SGMLOPTS} + +VOLUME?= ${.CURDIR:T} +DOC?= ${.CURDIR:T} +BINDIR?= /usr/share/doc +SRCDIR?= ${.CURDIR} +DISTRIBUTION?= doc +SGMLFMT?= sgmlfmt +LPR?= lpr + +DOCS= ${FORMATS:S/^/${DOC}./g} + +.MAIN: all +all: ${DOCS} + +# If FORMATS is empty, do nothing +.if empty(FORMATS) +${DOC}. install- print- clean-: +.endif + +.if !target(obj) +.if defined(NOOBJ) +obj: +.else +obj: + @cd ${.CURDIR}; rm -f obj; \ + here=`pwd`; dest=/usr/obj`echo $$here | sed 's,^/usr/src,,'`; \ + ${ECHO} "$$here -> $$dest"; ln -s $$dest obj; \ + if test -d /usr/obj -a ! -d $$dest; then \ + mkdir -p $$dest; \ + else \ + true; \ + fi; +.endif +.endif + +clean: ${FORMATS:S/^/clean-/g} + rm -f [eE]rrs mklog + +cleandir: clean + cd ${.CURDIR}; rm -rf obj + +install: beforeinstall realinstall afterinstall + +.if !target(beforeinstall) +beforeinstall: + +.endif +.if !target(afterinstall) +afterinstall: + +.endif +.if !target(maninstall) +maninstall: + +.endif + +realinstall: ${FORMATS:S/^/install-/g} + +.if !target(print) +print: ${FORMATS:S/^/print-/g} + +.endif + +spell: ${SRCS} + (cd ${.CURDIR}; spell ${SRCS} ) | sort | \ + comm -23 - ${.CURDIR}/spell.ok > ${DOC}.spell + +.if !target(distribute) +distribute: + cd ${.CURDIR} ; $(MAKE) install DESTDIR=${DISTDIR}/${DISTRIBUTION} SHARED=copies +.endif + +.if !target(depend) +depend: + +.endif + + +# For each FORMATS type, define a build, install, clean and print target. +# Note that there is special case handling for html targets +# because the number of files generated is generally not possible +# to predict outside of sgmlfmt(1). + +.for _XFORMAT in ${FORMATS} + +# XXX This doesn't work: +# .if ${_FORMAT} == "foobar" +# but defining another variable does: (?!?!) + +_FORMAT = ${_XFORMAT} + +.if !target(print-${_FORMAT}) +.if ${_FORMAT} == "html" +print-${_FORMAT}: + +.else +print-${_FORMAT}: ${DOC}.${_FORMAT} + ${LPR} -P${.TARGET:S/print-//} ${DOC}.${_FORMAT} + +.endif +.endif + +.if !target(install-${_FORMAT}) +.if ${_FORMAT} == "html" +install-${_FORMAT}: ${DOC}.${_FORMAT} + ${INSTALL} ${COPY} -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} \ + *.${.TARGET:S/install-//} ${DESTDIR}${BINDIR}/${VOLUME} + +.else +install-${_FORMAT}: ${DOC}.${_FORMAT} + ${INSTALL} ${COPY} -o ${MANOWN} -g ${MANGRP} -m ${MANMODE} \ + ${DOC}.${.TARGET:S/install-//} ${DESTDIR}${BINDIR}/${VOLUME} + +.endif +.endif + +.if !target(${DOC}.${_FORMAT}) +${DOC}.${_FORMAT}: ${SRCS} + ${SGMLFMT} -f ${.TARGET:S/${DOC}.//} ${SGMLFLAGS} ${.CURDIR}/${DOC}.sgml + +.endif + +.if !target(clean-${_FORMAT}) +.if ${_FORMAT} == "html" +clean-${_FORMAT}: + rm -f *.${.TARGET:S/clean-//} + +.else +clean-${_FORMAT}: + rm -f ${DOC}.${.TARGET:S/clean-//} + +.endif +.endif + +.endfor diff --git a/sys/gnu/i386/isa/dgb.c b/sys/gnu/i386/isa/dgb.c new file mode 100644 index 0000000000000..3d227355ca821 --- /dev/null +++ b/sys/gnu/i386/isa/dgb.c @@ -0,0 +1,2076 @@ +/*- + * dgb.c $Id: dgb.c,v 1.1 1995/09/03 19:52:52 jkh Exp $ + * + * Copyright (C) 1995 by Serge Babkin <babkin@hq.icb.chel.su> + * + * Digiboard driver. + * + * Stage 1. "Better than nothing". + * + * Based on sio driver by Bruce Evans and on Linux driver by Troy + * De Jongh <troyd@digibd.com> or <troyd@skypoint.com> + * which is under GNU General Public License version 2 so this driver + * is forced to be under GPL 2 too. + * + * Serge Babkin does not guarantee that this file is totally correct + * for any given task and users of this file must accept responsibility + * for any damage that occurs from the application of this file. + * + * Written by Serge Babkin, + * Joint Stock Commercial Bank "Chelindbank" + * (Chelyabinsk, Russia) + * babkin@hq.icb.chel.su + */ + +#include "dgb.h" + +#if NDGB > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/reboot.h> +#include <sys/ioctl.h> +#define TTYDEFCHARS /* XXX TK2.0 */ +#include <sys/tty.h> +#undef TTYDEFCHARS +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/conf.h> +#include <sys/dkstat.h> +#include <sys/file.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/syslog.h> +#include <sys/devconf.h> +#include <sys/types.h> + +#include <machine/clock.h> + +#include <i386/isa/icu.h> /* XXX just to get at `imen' */ +#include <i386/isa/isa.h> +#include <i386/isa/isa_device.h> + +#include <vm/vm.h> + +#include "dgreg.h" +#include "dgbios.h" +#include "dgfep.h" + +/* + * XXX temporary kludges for 2.0 (XXX TK2.0). + */ +#if defined (__FreeBSD__) && __FreeBSD__ < 2 +#define TS_RTS_IFLOW 0 +#define TSA_CARR_ON(tp) ((void *)&(tp)->t_rawq) +#define TSA_OCOMPLETE(tp) ((void *)&(tp)->t_outq) +#define TSA_OLOWAT(tp) ((void *)&(tp)->t_outq) + +#define TTY_BI TTY_FE /* XXX */ +#define TTY_OE TTY_PE /* XXX */ +#endif + +#define CALLOUT_MASK 0x80 +#define CONTROL_MASK 0x60 +#define CONTROL_INIT_STATE 0x20 +#define CONTROL_LOCK_STATE 0x40 +#define UNIT_MASK 0x30000 +#define PORT_MASK 0xF +#define DEV_TO_UNIT(dev) (MINOR_TO_UNIT(minor(dev))) +#define MINOR_MAGIC_MASK (CALLOUT_MASK | CONTROL_MASK) +#define MINOR_TO_UNIT(mynor) (((mynor) & UNIT_MASK)>>16) +#define MINOR_TO_PORT(mynor) ((mynor) & 0xF) + +/* + * Input buffer watermarks. + * The external device is asked to stop sending when the buffer exactly reaches + * high water, or when the high level requests it. + * The high level is notified immediately (rather than at a later clock tick) + * when this watermark is reached. + * The buffer size is chosen so the watermark should almost never be reached. + * The low watermark is invisibly 0 since the buffer is always emptied all at + * once. + */ +#define RS_IHIGHWATER (3 * RS_IBUFSIZE / 4) + +/* + * com state bits. + * (CS_BUSY | CS_TTGO) and (CS_BUSY | CS_TTGO | CS_ODEVREADY) must be higher + * than the other bits so that they can be tested as a group without masking + * off the low bits. + * + * The following com and tty flags correspond closely: + * CS_BUSY = TS_BUSY (maintained by comstart() and comflush()) + * CS_TTGO = ~TS_TTSTOP (maintained by comstart() and siostop()) + * CS_CTS_OFLOW = CCTS_OFLOW (maintained by comparam()) + * CS_RTS_IFLOW = CRTS_IFLOW (maintained by comparam()) + * TS_FLUSH is not used. + * XXX I think TIOCSETA doesn't clear TS_TTSTOP when it clears IXON. + * XXX CS_*FLOW should be CF_*FLOW in com->flags (control flags not state). + */ +#define CS_BUSY 0x80 /* output in progress */ +#define CS_TTGO 0x40 /* output not stopped by XOFF */ +#define CS_ODEVREADY 0x20 /* external device h/w ready (CTS) */ +#define CS_CHECKMSR 1 /* check of MSR scheduled */ +#define CS_CTS_OFLOW 2 /* use CTS output flow control */ +#define CS_DTR_OFF 0x10 /* DTR held off */ +#define CS_ODONE 4 /* output completed */ +#define CS_RTS_IFLOW 8 /* use RTS input flow control */ + +static char const * const error_desc[] = { +#define CE_OVERRUN 0 + "silo overflow", +#define CE_INTERRUPT_BUF_OVERFLOW 1 + "interrupt-level buffer overflow", +#define CE_TTY_BUF_OVERFLOW 2 + "tty-level buffer overflow", +}; + +#define CE_NTYPES 3 +#define CE_RECORD(com, errnum) (++(com)->delta_error_counts[errnum]) + +/* types. XXX - should be elsewhere */ +typedef u_int Port_t; /* hardware port */ +typedef u_char bool_t; /* boolean */ + +/* digiboard port structure */ +struct dgb_p { + bool_t status; + + u_char unit; /* board unit number */ + u_char pnum; /* port number */ + u_char omodem; /* FEP output modem status */ + u_char imodem; /* FEP input modem status */ + u_char modemfake; /* Modem values to be forced */ + u_char modem; /* Force values */ + u_char hflow; + u_char dsr; + u_char dcd; + u_char stopc; + u_char startc; + u_char stopca; + u_char startca; + u_char fepstopc; + u_char fepstartc; + u_char fepstopca; + u_char fepstartca; + u_char txwin; + u_char rxwin; + ushort fepiflag; + ushort fepcflag; + ushort fepoflag; + ushort txbufhead; + ushort txbufsize; + ushort rxbufhead; + ushort rxbufsize; + int close_delay; + int count; + int blocked_open; + int event; + int asyncflags; + u_long statusflags; + u_char *txptr; + u_char *rxptr; + struct board_chan *brdchan; + struct tty *tty; + + bool_t active_out; /* nonzero if the callout device is open */ + int dtr_wait; /* time to hold DTR down on close (* 1/hz) */ + u_int wopeners; /* # processes waiting for DCD in open() */ + + /* + * The high level of the driver never reads status registers directly + * because there would be too many side effects to handle conveniently. + * Instead, it reads copies of the registers stored here by the + * interrupt handler. + */ + u_char last_modem_status; /* last MSR read by intr handler */ + u_char prev_modem_status; /* last MSR handled by high level */ + + struct tty *tp; /* cross reference */ + + /* Initial state. */ + struct termios it_in; /* should be in struct tty */ + struct termios it_out; + + /* Lock state. */ + struct termios lt_in; /* should be in struct tty */ + struct termios lt_out; + + /* flags of state, are used in sleep() too */ + u_char closing; /* port is being closed now */ + u_char draining; /* port is being drained now */ + u_char used; /* port is being used now */ + u_char mustdrain; /* data must be waited to drain in dgbparam() */ +}; + +/* Digiboard per-board structure */ +struct dgb_softc { + /* struct board_info */ + u_char status; /* status: DISABLED/ENABLED */ + u_char unit; /* unit number */ + u_char type; /* type of card: PCXE, PCXI, PCXEVE */ + u_char altpin; /* do we need alternate pin setting ? */ + ushort numports; /* number of ports on card */ + ushort port; /* I/O port */ + u_char *vmem; /* virtual memory address */ + long pmem; /* physical memory address */ + int mem_seg; /* internal memory segment */ + struct dgb_p *ports; /* pointer to array of port descriptors */ + struct tty *ttys; /* pointer to array of TTY structures */ + volatile struct global_data *mailbox; + }; + + +struct dgb_softc dgb_softc[NDGB]; + +/* + * The public functions in the com module ought to be declared in a com-driver + * system header. + */ + +/* Interrupt handling entry points. */ +void dgbintr __P((int unit)); +void dgbpoll __P((void *unit_c)); + +/* Device switch entry points. */ +int dgbopen __P((dev_t dev, int oflags, int devtype, + struct proc *p)); +int dgbclose __P((dev_t dev, int fflag, int devtype, + struct proc *p)); +int dgbread __P((dev_t dev, struct uio *uio, int ioflag)); +int dgbwrite __P((dev_t dev, struct uio *uio, int ioflag)); +int dgbioctl __P((dev_t dev, int cmd, caddr_t data, + int fflag, struct proc *p)); +void dgbstop __P((struct tty *tp, int rw)); +#define dgbreset noreset +int dgbselect __P((dev_t dev, int rw, struct proc *p)); +#define dgbmmap nommap +#define dgbstrategy nostrategy + +static int dgbattach __P((struct isa_device *dev)); +static int dgbprobe __P((struct isa_device *dev)); + +static void fepcmd(struct dgb_p *port, int cmd, int op1, int op2, + int ncmds, int bytecmd); + +static void dgbstart __P((struct tty *tp)); +static int dgbparam __P((struct tty *tp, struct termios *t)); +static void dgbhardclose __P((struct dgb_p *port)); +static void dgb_drain_or_flush __P((struct dgb_p *port)); +static int dgbdrain __P((struct dgb_p *port)); +static void dgb_pause __P((void *chan)); + + +struct isa_driver dgbdriver = { + dgbprobe, dgbattach, "dgb",0 +}; + +static speed_t dgbdefaultrate = TTYDEF_SPEED; +static u_int dgb_events; /* input chars + weighted output completions */ +static int dgbmajor; + +static struct speedtab dgbspeedtab[] = { + 0, 0, /* old (sysV-like) Bx codes */ + 50, 1, + 75, 2, + 110, 3, + 134, 4, + 150, 5, + 200, 6, + 300, 7, + 600, 8, + 1200, 9, + 1800, 10, + 2400, 11, + 4800, 12, + 9600, 13, + 19200, 14, + 38400, 15, + 57600, (02000 | 1), /* B50 & fast baud table */ + 115200, (02000 | 2), /* B100 & fast baud table */ + -1, -1 +}; + +#ifdef DEBUG + int dgbdebug=1; +#else + int dgbdebug=0; +#endif + +static int polltimeout=0; + +static int setwin(struct dgb_softc *sc, unsigned addr); +static int setinitwin(struct dgb_softc *sc, unsigned addr); +static void hidewin(struct dgb_softc *sc); + +static inline int +setwin(sc,addr) + struct dgb_softc *sc; + unsigned int addr; +{ + if(sc->type==PCXEVE) { + outb(sc->port+1, FEPWIN|(addr>>13)); + DPRINT3("dgb%d: switched to window 0x%x\n",sc->unit,addr>>13); + return (addr & 0x1FFF); + } else { + outb(sc->port,FEPMEM); + return addr; + } +} + +static inline int +setinitwin(sc,addr) + struct dgb_softc *sc; + unsigned int addr; +{ + if(sc->type==PCXEVE) { + outb(sc->port+1, FEPWIN|(addr>>13)); + DPRINT3("dgb%d: switched to window 0x%x\n",sc->unit,addr>>13); + return (addr & 0x1FFF); + } else { + outb(sc->port,inb(sc->port)|FEPMEM); + return addr; + } +} + +static inline void +hidewin(sc) + struct dgb_softc *sc; +{ + if(sc->type==PCXEVE) + outb(sc->port+1, 0); + else + outb(sc->port,0); +} + +static inline void +towin(sc,win) + struct dgb_softc *sc; + int win; +{ + if(sc->type==PCXEVE) { + outb(sc->port+1, win); + } else { + outb(sc->port,FEPMEM); + } +} + +static int +dgbprobe(dev) + struct isa_device *dev; +{ + struct dgb_softc *sc= &dgb_softc[dev->id_unit]; + int i, v, t; + u_long win_size; /* size of vizible memory window */ + u_char *mem; + int addr; + int unit=dev->id_unit; + + sc->unit=dev->id_unit; + sc->port=dev->id_iobase; + + if(dev->id_flags & DGBFLAG_ALTPIN) + sc->altpin=1; + else + sc->altpin=0; + + /* left 24 bits only (ISA address) */ + sc->pmem=((long)dev->id_maddr & 0xFFFFFF); + + DPRINT4("dgb%d: port 0x%x mem 0x%x\n",unit,sc->port,sc->pmem); + + outb(sc->port, FEPRST); + sc->status=DISABLED; + + for(i=0; i< 1000; i++) { + DELAY(1); + if( (inb(sc->port) & FEPMASK) == FEPRST ) { + sc->status=ENABLED; + DPRINT3("dgb%d: got reset after %d us\n",unit,i); + break; + } + } + + if(sc->status!=ENABLED) { + DPRINT2("dgb%d: failed to respond\n",dev->id_unit); + return 0; + } + + /* check type of card and get internal memory characteristics */ + + v=inb(sc->port); + + if( v & 0x1 ) { + switch( v&0x30 ) { + case 0: + sc->mem_seg=0xF000; + win_size=0x10000; + printf("dgb%d: PC/Xi 64K\n",dev->id_unit); + break; + case 0x10: + sc->mem_seg=0xE000; + win_size=0x20000; + printf("dgb%d: PC/Xi 128K\n",dev->id_unit); + break; + case 0x20: + sc->mem_seg=0xC000; + win_size=0x40000; + printf("dgb%d: PC/Xi 256K\n",dev->id_unit); + break; + default: /* case 0x30: */ + sc->mem_seg=0x8000; + win_size=0x80000; + printf("dgb%d: PC/Xi 512K\n",dev->id_unit); + break; + } + sc->type=PCXI; + } else { + outb(sc->port, 1); + v=inb(sc->port); + + if( v & 0x1 ) { + printf("dgb%d: PC/Xm isn't supported\n",dev->id_unit); + sc->status=DISABLED; + return 0; + } + + sc->mem_seg=0xF000; + + if(dev->id_flags==DGBFLAG_NOWIN || ( v&0xC0 )==0) { + win_size=0x10000; + printf("dgb%d: PC/Xe 64K\n",dev->id_unit); + sc->type=PCXE; + } else { + win_size=0x2000; + printf("dgb%d: PC/Xe 64/8K (windowed)\n",dev->id_unit); + sc->type=PCXEVE; + if((u_long)sc->pmem & ~0xFFE000) { + printf("dgb%d: warning: address 0x%x truncated to 0x%x\n", + dev->id_unit, sc->pmem, + (long)sc->pmem & 0xFFE000); + + dev->id_maddr= (u_char *)( (long)sc->pmem & 0xFFE000 ); + } + } + } + + /* save size of vizible memory segment */ + dev->id_msize=win_size; + + /* map memory */ + dev->id_maddr=sc->vmem=pmap_mapdev(sc->pmem,dev->id_msize); + + outb(sc->port, FEPCLR); /* drop RESET */ + + return 4; /* we need I/O space of 4 ports */ +} + +static struct kern_devconf kdc_dgb[NDGB] = { { + 0, 0, 0, /* filled in by dev_attach */ + "dgb", 0, { MDDT_ISA, 0, "tty" }, + isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, + &kdc_isa0, /* parent */ + 0, /* parentdata */ + DC_UNCONFIGURED, + "DigiBoard multiport card" +} }; + +static void +dgbregisterdev(id) + struct isa_device *id; +{ + int unit; + + unit = id->id_unit; + if (unit != 0) + kdc_dgb[unit] = kdc_dgb[0]; + kdc_dgb[unit].kdc_unit = unit; + kdc_dgb[unit].kdc_isa = id; + + /* now we assume that multiport is always 'open' for simplicity */ + kdc_dgb[unit].kdc_state = DC_BUSY; + dev_attach(&kdc_dgb[unit]); +} + + +static int +dgbattach(dev) + struct isa_device *dev; +{ + int unit=dev->id_unit; + struct dgb_softc *sc= &dgb_softc[dev->id_unit]; + int i, t; + u_char *mem; + u_char *ptr; + int addr; + struct dgb_p *port; + struct board_chan *bc; + struct global_data *gd; + int shrinkmem; + int nfails; + ushort *pstat; + int lowwater; + + if(sc->status!=ENABLED) { + DPRINT2("dbg%d: try to attach a disabled card\n",unit); + return 0; + } + + mem=sc->vmem; + + DPRINT3("dgb%d: internal memory segment 0x%x\n",unit,sc->mem_seg); + + outb(sc->port, FEPRST); DELAY(1); + + for(i=0; (inb(sc->port) & FEPMASK) != FEPRST ; i++) { + if(i>10000) { + printf("dgb%d: 1st reset failed\n",dev->id_unit); + sc->status=DISABLED; + hidewin(sc); + return 0; + } + DELAY(1); + } + + DPRINT3("dgb%d: got reset after %d us\n",unit,i); + + /* for PCXEVE set up interrupt and base address */ + + if(sc->type==PCXEVE) { + t=(((u_long)sc->pmem>>8) & 0xFFE0) | 0x10 /* enable windowing */; + + /* IRQ isn't used */ +#if 0 + switch(dev->id_irq) { + case IRQ3: + t|=0x1; + break; + case IRQ5: + t|=2; + break; + case IRQ7: + t|=3; + break; + case IRQ10: + t|=4; + break; + case IRQ11: + t|=5; + break; + case IRQ12: + t|=6; + break; + case IRQ15: + t|=7; + break; + default: + printf("dgb%d: wrong IRQ mask 0x%x\n",dev->id_unit,dev->id_irq); + sc->status=DISABLED; + return 0; + } +#endif + + outb(sc->port+2,t & 0xFF); + outb(sc->port+3,t>>8); + } else if(sc->type==PCXE) { + t=(((u_long)sc->pmem>>8) & 0xFFE0) /* disable windowing */; + outb(sc->port+2,t & 0xFF); + outb(sc->port+3,t>>8); + } + + + if(sc->type==PCXI || sc->type==PCXE) { + outb(sc->port, FEPRST|FEPMEM); DELAY(1); + + for(i=0; (inb(sc->port) & FEPMASK) != (FEPRST|FEPMEM) ; i++) { + if(i>10000) { + printf("dgb%d: 2nd reset failed\n",dev->id_unit); + sc->status=DISABLED; + hidewin(sc); + return 0; + } + DELAY(1); + } + + DPRINT3("dgb%d: got memory after %d us\n",unit,i); + } + + mem=sc->vmem; + + /* very short memory test */ + + addr=setinitwin(sc,BOTWIN); + *(u_long *)(mem+addr) = 0xA55A3CC3; + if(*(u_long *)(mem+addr)!=0xA55A3CC3) { + printf("dgb%d: 1st memory test failed\n",dev->id_unit); + sc->status=DISABLED; + hidewin(sc); + return 0; + } + + addr=setinitwin(sc,TOPWIN); + *(u_long *)(mem+addr) = 0x5AA5C33C; + if(*(u_long *)(mem+addr)!=0x5AA5C33C) { + printf("dgb%d: 2nd memory test failed\n",dev->id_unit); + sc->status=DISABLED; + hidewin(sc); + return 0; + } + + addr=setinitwin(sc,BIOSCODE+((0xF000-sc->mem_seg)<<4)); + *(u_long *)(mem+addr) = 0x5AA5C33C; + if(*(u_long *)(mem+addr)!=0x5AA5C33C) { + printf("dgb%d: 3rd (BIOS) memory test failed\n",dev->id_unit); + } + + addr=setinitwin(sc,MISCGLOBAL); + for(i=0; i<16; i++) { + mem[addr+i]=0; + } + + if(sc->type==PCXI || sc->type==PCXE) { + + addr=BIOSCODE+((0xF000-sc->mem_seg)<<4); + + DPRINT3("dgb%d: BIOS local address=0x%x\n",unit,addr); + + ptr= mem+addr; + + for(i=0; i<pcxx_nbios; i++, ptr++) + *ptr = pcxx_bios[i]; + + ptr= mem+addr; + + nfails=0; + for(i=0; i<pcxx_nbios; i++, ptr++) + if( *ptr != pcxx_bios[i] ) { + DPRINT5("dgb%d: wrong code in BIOS at addr 0x%x : \ +0x%x instead of 0x%x\n", unit, ptr-(mem+addr), *ptr, pcxx_bios[i] ); + + if(++nfails>=5) { + printf("dgb%d: 4th memory test (BIOS load) fails\n",unit); + break; + } + } + + outb(sc->port,FEPMEM); + + for(i=0; (inb(sc->port) & FEPMASK) != FEPMEM ; i++) { + if(i>10000) { + printf("dgb%d: BIOS start failed\n",dev->id_unit); + sc->status=DISABLED; + hidewin(sc); + return 0; + } + DELAY(1); + } + + DPRINT3("dgb%d: reset dropped after %d us\n",unit,i); + + for(i=0; i<200000; i++) { + if( *((ushort *)(mem+MISCGLOBAL)) == *((ushort *)"GD") ) + goto load_fep; + DELAY(1); + } + printf("dgb%d: BIOS download failed\n",dev->id_unit); + DPRINT4("dgb%d: code=0x%x must be 0x%x\n", + dev->id_unit, + *((ushort *)(mem+MISCGLOBAL)), + *((ushort *)"GD")); + + sc->status=DISABLED; + hidewin(sc); + return 0; + } + + if(sc->type==PCXEVE) { + /* set window 7 */ + outb(sc->port+1,0xFF); + + ptr= mem+(BIOSCODE & 0x1FFF); + + for(i=0; i<pcxx_nbios; i++) + *ptr++ = pcxx_bios[i]; + + ptr= mem+(BIOSCODE & 0x1FFF); + + nfails=0; + for(i=0; i<pcxx_nbios; i++, ptr++) + if( *ptr != pcxx_bios[i] ) { + DPRINT5("dgb%d: wrong code in BIOS at addr 0x%x : \ +0x%x instead of 0x%x\n", unit, ptr-(mem+addr), *ptr, pcxx_bios[i] ); + + if(++nfails>=5) { + printf("dgb%d: 4th memory test (BIOS load) fails\n",unit); + break; + } + } + + outb(sc->port,FEPCLR); + + setwin(sc,0); + + for(i=0; (inb(sc->port) & FEPMASK) != FEPCLR ; i++) { + if(i>10000) { + printf("dgb%d: BIOS start failed\n",dev->id_unit); + sc->status=DISABLED; + hidewin(sc); + return 0; + } + DELAY(1); + } + + DPRINT3("dgb%d: reset dropped after %d us\n",unit,i); + + addr=setwin(sc,MISCGLOBAL); + + for(i=0; i<200000; i++) { + if(*(ushort *)(mem+addr)== *(ushort *)"GD") + goto load_fep; + DELAY(1); + } + printf("dgb%d: BIOS download failed\n",dev->id_unit); + DPRINT5("dgb%d: Error#(0x%x,0x%x) code=0x%x\n", + dev->id_unit, + *(ushort *)(mem+0xC12), + *(ushort *)(mem+0xC14), + *(ushort *)(mem+MISCGLOBAL)); + + sc->status=DISABLED; + hidewin(sc); + return 0; + } + +load_fep: + DPRINT2("dgb%d: BIOS loaded\n",dev->id_unit); + + addr=setwin(sc,FEPCODE); + + ptr= mem+addr; + + for(i=0; i<pcxx_ncook; i++) + *ptr++ = pcxx_cook[i]; + + addr=setwin(sc,MBOX); + *(ushort *)(mem+addr+ 0)=2; + *(ushort *)(mem+addr+ 2)=sc->mem_seg+FEPCODESEG; + *(ushort *)(mem+addr+ 4)=0; + *(ushort *)(mem+addr+ 6)=FEPCODESEG; + *(ushort *)(mem+addr+ 8)=0; + *(ushort *)(mem+addr+10)=pcxx_ncook; + + outb(sc->port,FEPMEM|FEPINT); /* send interrupt to BIOS */ + outb(sc->port,FEPMEM); + + for(i=0; *(ushort *)(mem+addr)!=0; i++) { + if(i>200000) { + printf("dgb%d: FEP code download failed\n",unit); + DPRINT3("dgb%d: code=0x%x must be 0\n", unit, + *(ushort *)(mem+addr)); + sc->status=DISABLED; + hidewin(sc); + return 0; + } + } + + DPRINT2("dgb%d: FEP code loaded\n",unit); + + *(ushort *)(mem+setwin(sc,FEPSTAT))=0; + addr=setwin(sc,MBOX); + *(ushort *)(mem+addr+0)=1; + *(ushort *)(mem+addr+2)=FEPCODESEG; + *(ushort *)(mem+addr+4)=0x4; + + outb(sc->port,FEPINT); /* send interrupt to BIOS */ + outb(sc->port,FEPCLR); + + addr=setwin(sc,FEPSTAT); + for(i=0; *(ushort *)(mem+addr)!= *(ushort *)"OS"; i++) { + if(i>200000) { + printf("dgb%d: FEP/OS start failed\n",dev->id_unit); + sc->status=DISABLED; + hidewin(sc); + return 0; + } + } + + DPRINT2("dgb%d: FEP/OS started\n",dev->id_unit); + + sc->numports= *(ushort *)(mem+setwin(sc,NPORT)); + + printf("dgb%d: %d ports\n",unit,sc->numports); + + if(sc->numports > MAX_DGB_PORTS) { + printf("dgb%d: too many ports\n",unit); + sc->status=DISABLED; + hidewin(sc); + return 0; + } + + addr=setwin(sc,PORTBASE); + pstat=(ushort *)(mem+addr); + + for(i=0; i<32 && pstat[i]; i++); + + if(i!=sc->numports) { + printf("dgb%d: %d ports are shown as valid ones\n",unit,i); + if(i<sc->numports) + sc->numports=i; + printf("dgb%d: %d ports will be used\n",unit,sc->numports); + } + + MALLOC(sc->ports, struct dgb_p *, sizeof(struct dgb_p)*sc->numports, + M_TTYS, M_NOWAIT); + + if(sc->ports==0) { + printf("dgb%d: unable to malloc the per port structures\n",unit); + sc->status=DISABLED; + hidewin(sc); + return 0; + } + + bzero(sc->ports, sizeof(struct dgb_p)*sc->numports); + + MALLOC(sc->ttys, struct tty *, sizeof(struct tty)*sc->numports, + M_TTYS, M_NOWAIT); + + if(sc->ttys==0) { + printf("dgb%d: unable to malloc the tty structures\n",unit); + FREE(sc->ttys, M_TTYS); + sc->status=DISABLED; + hidewin(sc); + return 0; + } + + bzero(sc->ttys, sizeof(struct tty)*sc->numports); + + /* We should now init per-port structures */ + bc=(struct board_chan *)(mem + CHANSTRUCT); + sc->mailbox=(struct global_data *)(mem + FEP_GLOBAL); + + if(sc->numports<3) + shrinkmem=1; + else + shrinkmem=0; + + + for(i=0; i<sc->numports; i++, bc++) { + port= &sc->ports[i]; + + port->status=ENABLED; + + port->tty=&sc->ttys[i]; + port->unit=unit; + + port->brdchan=bc; + + if(sc->altpin) { + port->dsr=CD; + port->dcd=DSR; + } else { + port->dcd=CD; + port->dsr=DSR; + } + + port->pnum=i; + + if(shrinkmem) { + DPRINT2("dgb%d: shrinking memory\n",unit); + fepcmd(port, SETBUFFER, 32, 0, 0, 0); + shrinkmem=0; + } + + if(sc->type!=PCXEVE) { + port->txptr=mem+((bc->tseg-sc->mem_seg)<<4); + port->rxptr=mem+((bc->rseg-sc->mem_seg)<<4); + port->txwin=port->rxwin=0; + } else { + port->txptr=mem+( ((bc->tseg-sc->mem_seg)<<4) & 0x1FFF ); + port->rxptr=mem+( ((bc->rseg-sc->mem_seg)<<4) & 0x1FFF ); + port->txwin=FEPWIN | ((bc->tseg-sc->mem_seg)>>9); + port->rxwin=FEPWIN | ((bc->rseg-sc->mem_seg)>>9); + } + + port->txbufhead=0; + port->rxbufhead=0; + port->txbufsize=bc->tmax+1; + port->rxbufsize=bc->rmax+1; + + lowwater= (port->txbufsize>=2000) ? 1024 : (port->txbufsize/2); + fepcmd(port, STXLWATER, lowwater, 0, 10, 0); + fepcmd(port, SRXLWATER, port->rxbufsize/4, 0, 10, 0); + fepcmd(port, SRXHWATER, 3*port->rxbufsize/4, 0, 10, 0); + + bc->edelay=100; + bc->idata=1; + + port->startc=bc->startc; + port->startca=bc->startca; + port->stopc=bc->stopc; + port->stopca=bc->stopca; + + port->close_delay=50; + + /* + * We don't use all the flags from <sys/ttydefaults.h> since they + * are only relevant for logins. It's important to have echo off + * initially so that the line doesn't start blathering before the + * echo flag can be turned off. + */ + port->it_in.c_iflag = TTYDEF_IFLAG; + port->it_in.c_oflag = TTYDEF_OFLAG; + port->it_in.c_cflag = TTYDEF_CFLAG; + port->it_in.c_lflag = TTYDEF_LFLAG; + termioschars(&port->it_in); + port->it_in.c_ispeed = port->it_in.c_ospeed = dgbdefaultrate; + port->it_out = port->it_in; + } + + hidewin(sc); + + /* register the polling function */ + timeout(dgbpoll, (void *)unit, hz/25); + + return 1; +} + +/* ARGSUSED */ +int +dgbopen(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + struct dgb_softc *sc; + struct tty *tp; + int unit; + int mynor; + int pnum; + struct dgb_p *port; + int s; + int error; + struct board_chan *bc; + + error=0; + + mynor=minor(dev); + unit=MINOR_TO_UNIT(mynor); + pnum=MINOR_TO_PORT(mynor); + + if(unit >= NDGB) { + DPRINT2("dgb%d: try to open a nonexisting card\n",unit); + return ENXIO; + } + + sc=&dgb_softc[unit]; + + if(sc->status!=ENABLED) { + DPRINT2("dgb%d: try to open a disabled card\n",unit); + return ENXIO; + } + + if(pnum>=sc->numports) { + DPRINT3("dgb%d: try to open non-existing port %d\n",unit,pnum); + return ENXIO; + } + + if(mynor & CONTROL_MASK) + return 0; + + tp=&sc->ttys[pnum]; + port=&sc->ports[pnum]; + bc=port->brdchan; + +open_top: + + s=spltty(); + + while(port->closing) { + error=tsleep(&port->closing, TTOPRI|PCATCH, "dgocl", 0); + + if(error) { + DPRINT4("dgb%d: port %d: tsleep(dgocl) error=%d\n",unit,pnum,error); + goto out; + } + } + + if (tp->t_state & TS_ISOPEN) { + /* + * The device is open, so everything has been initialized. + * Handle conflicts. + */ + if (mynor & CALLOUT_MASK) { + if (!port->active_out) { + error = EBUSY; + DPRINT4("dgb%d: port %d: BUSY error=%d\n",unit,pnum,error); + goto out; + } + } else { + if (port->active_out) { + if (flag & O_NONBLOCK) { + error = EBUSY; + DPRINT4("dgb%d: port %d: BUSY error=%d\n",unit,pnum,error); + goto out; + } + error = tsleep(&port->active_out, + TTIPRI | PCATCH, "dgbi", 0); + if (error != 0) { + DPRINT4("dgb%d: port %d: tsleep(dgbi) error=%d\n", + unit,pnum,error); + goto out; + } + splx(s); + goto open_top; + } + } + if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0) { + error = EBUSY; + goto out; + } + } else { + /* + * The device isn't open, so there are no conflicts. + * Initialize it. Initialization is done twice in many + * cases: to preempt sleeping callin opens if we are + * callout, and to complete a callin open after DCD rises. + */ + tp->t_oproc=dgbstart; + tp->t_param=dgbparam; + tp->t_dev=dev; + tp->t_termios= (mynor & CALLOUT_MASK) ? + port->it_out : + port->it_in; + + setwin(sc,0); + port->imodem=bc->mstat; + bc->rout=bc->rin; /* clear input queue */ + bc->idata=1; + + hidewin(sc); + + port->wopeners++; + error=dgbparam(tp, &tp->t_termios); + port->wopeners--; + + if(error!=0) { + DPRINT4("dgb%d: port %d: dgbparam error=%d\n",unit,pnum,error); + goto out; + } + + ttsetwater(tp); + + /* handle fake DCD for callout devices */ + /* and initial DCD */ + + if( (port->imodem & port->dcd) || mynor & CALLOUT_MASK ) + linesw[tp->t_line].l_modem(tp,1); + + } + + /* + * Wait for DCD if necessary. + */ + if (!(tp->t_state & TS_CARR_ON) && !(mynor & CALLOUT_MASK) + && !(tp->t_cflag & CLOCAL) && !(flag & O_NONBLOCK)) { + ++port->wopeners; + error = tsleep(TSA_CARR_ON(tp), TTIPRI | PCATCH, "dgdcd", 0); + --port->wopeners; + if (error != 0) { + DPRINT4("dgb%d: port %d: tsleep(dgdcd) error=%d\n",unit,pnum,error); + goto out; + } + splx(s); + goto open_top; + } + error = linesw[tp->t_line].l_open(dev, tp); + DPRINT4("dgb%d: port %d: l_open error=%d\n",unit,pnum,error); + + if (tp->t_state & TS_ISOPEN && mynor & CALLOUT_MASK) + port->active_out = TRUE; + + port->used=1; + +out: + splx(s); + + if( !(tp->t_state & TS_ISOPEN) && port->wopeners==0 ) + dgbhardclose(port); + + DPRINT4("dgb%d: port %d: open() returns %d\n",unit,pnum,error); + + return error; +} + +/*ARGSUSED*/ +int +dgbclose(dev, flag, mode, p) + dev_t dev; + int flag; + int mode; + struct proc *p; +{ + int mynor; + struct tty *tp; + int unit, pnum; + struct dgb_softc *sc; + struct dgb_p *port; + int s; + + mynor=minor(dev); + unit=MINOR_TO_UNIT(mynor); + pnum=MINOR_TO_PORT(mynor); + + sc=&dgb_softc[unit]; + tp=&sc->ttys[pnum]; + port=sc->ports+pnum; + + if(mynor & CONTROL_MASK) + return 0; + + DPRINT3("dgb%d: port %d: closing\n",unit,pnum); + + s=spltty(); + + port->closing=1; + linesw[tp->t_line].l_close(tp,flag); + dgb_drain_or_flush(port); + dgbhardclose(port); + ttyclose(tp); + port->closing=0; wakeup(&port->closing); + port->used=0; + + splx(s); + + wakeup(TSA_CARR_ON(tp)); + wakeup(&port->active_out); + port->active_out=0; + + return 0; +} + +static void +dgbhardclose(port) + struct dgb_p *port; +{ + struct dgb_softc *sc=&dgb_softc[port->unit]; + struct board_chan *bc=port->brdchan; + int s; + + setwin(sc,0); + + bc->idata=0; bc->iempty=0; bc->ilow=0; + if(port->tty->t_cflag & HUPCL) { + port->omodem &= ~(RTS|DTR); + fepcmd(port, SETMODEM, 0, DTR|RTS, 0, 1); + } + + hidewin(sc); + + timeout(dgb_pause, &port->brdchan, hz/2); + tsleep(&port->brdchan, TTIPRI | PCATCH, "dgclo", 0); +} + +static void +dgb_pause(chan) + void *chan; +{ +wakeup((caddr_t)chan); +} + + +int +dgbread(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + int mynor; + struct tty *tp; + int error, unit, pnum; + + mynor=minor(dev); + if (mynor & CONTROL_MASK) + return (ENODEV); + unit=MINOR_TO_UNIT(mynor); + pnum=MINOR_TO_PORT(mynor); + + tp=&dgb_softc[unit].ttys[pnum]; + + error=linesw[tp->t_line].l_read(tp, uio, flag); + DPRINT4("dgb%d: port %d: read() returns %d\n",unit,pnum,error); + + return error; +} + +int +dgbwrite(dev, uio, flag) + dev_t dev; + struct uio *uio; + int flag; +{ + int mynor; + struct tty *tp; + int error, unit, pnum; + + mynor=minor(dev); + if (mynor & CONTROL_MASK) + return (ENODEV); + + unit=MINOR_TO_UNIT(mynor); + pnum=MINOR_TO_PORT(mynor); + + tp=&dgb_softc[unit].ttys[pnum]; + + error=linesw[tp->t_line].l_write(tp, uio, flag); + DPRINT4("dgb%d: port %d: write() returns %d\n",unit,pnum,error); + + return error; +} + +void dgbpoll(unit_c) + void *unit_c; +{ + int unit=(int)unit_c; + int pnum; + struct dgb_p *port; + struct dgb_softc *sc=&dgb_softc[unit]; + int head, tail; + u_char *eventbuf; + int event, mstat, lstat; + struct board_chan *bc; + struct tty *tp; + int rhead, rtail; + int whead, wtail; + int wrapmask; + int size; + int c=0; + u_char *ptr; + int ocount; + + if(sc->status==DISABLED) { + printf("dgb%d: polling of disabled board stopped\n",unit); + return; + } + + setwin(sc,0); + + head=sc->mailbox->ein; + tail=sc->mailbox->eout; + + while(head!=tail) { + if(head >= FEP_IMAX-FEP_ISTART + || tail >= FEP_IMAX-FEP_ISTART + || (head|tail) & 03 ) { + printf("dgb%d: event queue's head or tail is wrong!\n", unit); + break; + } + + eventbuf=sc->vmem+tail+FEP_ISTART; + pnum=eventbuf[0]; + event=eventbuf[1]; + mstat=eventbuf[2]; + lstat=eventbuf[3]; + + port=&sc->ports[pnum]; + bc=port->brdchan; + tp=&sc->ttys[pnum]; + + if(pnum>=sc->numports || port->status==DISABLED) { + printf("dgb%d: port %d: got event on nonexisting port\n",unit,pnum); + } else if(port->used || port->wopeners>0 ) { + + if( !(event & ALL_IND) ) + printf("dgb%d: port%d: ? event 0x%x mstat 0x%x lstat 0x%x\n", + unit, pnum, event, mstat, lstat); + + if(event & DATA_IND) { + DPRINT3("dgb%d: port %d: DATA_IND\n",unit,pnum); + + wrapmask=port->rxbufsize-1; + + rhead=bc->rin & wrapmask; + rtail=bc->rout & wrapmask; + + if( !(tp->t_cflag & CREAD) || !port->used ) { + bc->rout=rhead; + goto end_of_data; + } + + if(bc->orun) { + printf("dgb%d: port%d: overrun\n", unit, pnum); + bc->orun=0; + } + + while(rhead!=rtail) { + DPRINT5("dgb%d: port %d: p rx head=%d tail=%d\n", + unit,pnum,rhead,rtail); + + if(rhead>rtail) + size=rhead-rtail; + else + size=port->rxbufsize-rtail; + + ptr=port->rxptr+rtail; + + for(c=0; c<size; c++) { + int chr; + + towin(sc,port->rxwin); + chr= *ptr++; + +#if 0 + if(chr>=' ' && chr<127) + DPRINT4("dgb%d: port %d: got char '%c'\n", + unit,pnum,chr); + else + DPRINT4("dgb%d: port %d: got char 0x%x\n", + unit,pnum,chr); +#endif + + hidewin(sc); + linesw[tp->t_line].l_rint(chr, tp); + } + + setwin(sc,0); + rtail= (rtail + size) & wrapmask; + bc->rout=rtail; + rhead=bc->rin & wrapmask; + } + + end_of_data: + } + + if(event & MODEMCHG_IND) { + DPRINT3("dgb%d: port %d: MODEMCHG_IND\n",unit,pnum); + port->imodem=mstat; + if(mstat & port->dcd) { + hidewin(sc); + linesw[tp->t_line].l_modem(tp,1); + setwin(sc,0); + wakeup(TSA_CARR_ON(tp)); + } else { + hidewin(sc); + linesw[tp->t_line].l_modem(tp,0); + setwin(sc,0); + if( port->draining) { + port->draining=0; + wakeup(&port->draining); + } + } + } + + if(event & BREAK_IND) { + DPRINT3("dgb%d: port %d: BREAK_IND\n",unit,pnum); + hidewin(sc); + linesw[tp->t_line].l_rint(TTY_BI, tp); + setwin(sc,0); + } + + if(event & (LOWTX_IND | EMPTYTX_IND) ) { + DPRINT3("dgb%d: port %d: LOWTX_IND or EMPTYTX_IND\n",unit,pnum); + + if( (event & EMPTYTX_IND ) && tp->t_outq.c_cc==0 + && port->draining) { + port->draining=0; + wakeup(&port->draining); + bc->ilow=0; bc->iempty=0; + } + + wrapmask=port->txbufsize; + + while( tp->t_outq.c_cc!=0 ) { +#ifndef TS_ASLEEP /* post 2.0.5 FreeBSD */ + ttwwakeup(tp); +#else + if(tp->t_outq.c_cc <= tp->t_lowat) { + if(tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup(TSA_OLOWAT(tp)); + } + selwakeup(&tp->t_wsel); + } +#endif + setwin(sc,0); + + whead=bc->tin & wrapmask; + wtail=bc->tout & wrapmask; + + DPRINT5("dgb%d: port%d: p tx head=%d tail=%d\n", + unit,pnum,whead,wtail); + + if(whead<wtail) + size=wtail-whead-1; + else { + size=port->txbufsize-whead; + if(wtail==0) + size--; + } + + if(size==0) { + bc->iempty=1; bc->ilow=1; + goto end_of_buffer; + } + + towin(sc,port->txwin); + + ocount=q_to_b(&tp->t_outq, port->txptr+whead, size); + whead+=ocount; + + setwin(sc,0); + bc->tin=whead; + } +#ifndef TS_ASLEEP /* post 2.0.5 FreeBSD */ + ttwwakeup(tp); +#else + if(tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup(TSA_OLOWAT(tp)); + } + tp->t_state &= ~TS_BUSY; +#endif + end_of_buffer: + } + } else { + DPRINT4("dgb%d: port %d: got event 0x%x on closed port\n", + unit,pnum,event); + bc->rout=bc->rin; + bc->idata=bc->iempty=bc->ilow=0; + } + + bc->idata=1; + + tail= (tail+4) & (FEP_IMAX-FEP_ISTART-4); + } + + sc->mailbox->eout=tail; + hidewin(sc); + + timeout(dgbpoll, unit_c, hz/25); +} + +void +dgbintr(unit) + int unit; +{ +} + +int +dgbioctl(dev, cmd, data, flag, p) + dev_t dev; + int cmd; + caddr_t data; + int flag; + struct proc *p; +{ + struct dgb_softc *sc; + int unit, pnum; + struct dgb_p *port; + int mynor; + struct tty *tp; + struct board_chan *bc; + int error; + int s; + int tiocm_xxx; + + mynor=minor(dev); + unit=MINOR_TO_UNIT(mynor); + pnum=MINOR_TO_PORT(mynor); + + sc=&dgb_softc[unit]; + port=&sc->ports[pnum]; + tp=&sc->ttys[pnum]; + bc=port->brdchan; + + if (mynor & CONTROL_MASK) { + struct termios *ct; + + switch (mynor & CONTROL_MASK) { + case CONTROL_INIT_STATE: + ct = mynor & CALLOUT_MASK ? &port->it_out : &port->it_in; + break; + case CONTROL_LOCK_STATE: + ct = mynor & CALLOUT_MASK ? &port->lt_out : &port->lt_in; + break; + default: + return (ENODEV); /* /dev/nodev */ + } + switch (cmd) { + case TIOCSETA: + error = suser(p->p_ucred, &p->p_acflag); + if (error != 0) + return (error); + *ct = *(struct termios *)data; + return (0); + case TIOCGETA: + *(struct termios *)data = *ct; + return (0); + case TIOCGETD: + *(int *)data = TTYDISC; + return (0); + case TIOCGWINSZ: + bzero(data, sizeof(struct winsize)); + return (0); + default: + return (ENOTTY); + } + } + + if (cmd == TIOCSETA || cmd == TIOCSETAW || cmd == TIOCSETAF) { + int cc; + struct termios *dt = (struct termios *)data; + struct termios *lt = mynor & CALLOUT_MASK + ? &port->lt_out : &port->lt_in; + + dt->c_iflag = (tp->t_iflag & lt->c_iflag) + | (dt->c_iflag & ~lt->c_iflag); + dt->c_oflag = (tp->t_oflag & lt->c_oflag) + | (dt->c_oflag & ~lt->c_oflag); + dt->c_cflag = (tp->t_cflag & lt->c_cflag) + | (dt->c_cflag & ~lt->c_cflag); + dt->c_lflag = (tp->t_lflag & lt->c_lflag) + | (dt->c_lflag & ~lt->c_lflag); + for (cc = 0; cc < NCCS; ++cc) + if (lt->c_cc[cc] != 0) + dt->c_cc[cc] = tp->t_cc[cc]; + if (lt->c_ispeed != 0) + dt->c_ispeed = tp->t_ispeed; + if (lt->c_ospeed != 0) + dt->c_ospeed = tp->t_ospeed; + } + + if(cmd==TIOCSTOP) { + setwin(sc,0); + fepcmd(port, PAUSETX, 0, 0, 0, 0); + hidewin(sc); + return 0; + } else if(cmd==TIOCSTART) { + setwin(sc,0); + fepcmd(port, RESUMETX, 0, 0, 0, 0); + hidewin(sc); + return 0; + } + + if(cmd==TIOCSETAW || cmd==TIOCSETAF) + port->mustdrain=1; + + error = linesw[tp->t_line].l_ioctl(tp, cmd, data, flag, p); + + if (error >= 0) + return error; + error = ttioctl(tp, cmd, data, flag); + + port->mustdrain=0; + + if (error >= 0) + return error; + s = spltty(); + switch (cmd) { + case TIOCSBRK: + error=dgbdrain(port); + + if(error!=0) { + splx(s); + return error; + } + + setwin(sc,0); + + /* now it sends 250 millisecond break because I don't know */ + /* how to send an infinite break */ + + fepcmd(port, SENDBREAK, 250, 0, 10, 0); + hidewin(sc); + break; + case TIOCCBRK: + /* now it's empty */ + break; + case TIOCSDTR: + DPRINT3("dgb%d: port %d: set DTR\n",unit,pnum); + port->omodem |= DTR; + setwin(sc,0); + fepcmd(port, SETMODEM, port->omodem, RTS, 0, 1); + + if( !(bc->mstat & DTR) ) { + DPRINT3("dgb%d: port %d: DTR is off\n",unit,pnum); + } + + hidewin(sc); + break; + case TIOCCDTR: + DPRINT3("dgb%d: port %d: reset DTR\n",unit,pnum); + port->omodem &= ~DTR; + setwin(sc,0); + fepcmd(port, SETMODEM, port->omodem, RTS|DTR, 0, 1); + + if( bc->mstat & DTR ) { + DPRINT3("dgb%d: port %d: DTR is on\n",unit,pnum); + } + + hidewin(sc); + break; + case TIOCMSET: + if(*(int *)data & TIOCM_DTR) + port->omodem |=DTR; + else + port->omodem &=~DTR; + + if(*(int *)data & TIOCM_RTS) + port->omodem |=RTS; + else + port->omodem &=~RTS; + + setwin(sc,0); + fepcmd(port, SETMODEM, port->omodem, RTS|DTR, 0, 1); + hidewin(sc); + break; + case TIOCMBIS: + if(*(int *)data & TIOCM_DTR) + port->omodem |=DTR; + + if(*(int *)data & TIOCM_RTS) + port->omodem |=RTS; + + setwin(sc,0); + fepcmd(port, SETMODEM, port->omodem, RTS|DTR, 0, 1); + hidewin(sc); + break; + case TIOCMBIC: + if(*(int *)data & TIOCM_DTR) + port->omodem &=~DTR; + + if(*(int *)data & TIOCM_RTS) + port->omodem &=~RTS; + + setwin(sc,0); + fepcmd(port, SETMODEM, port->omodem, RTS|DTR, 0, 1); + hidewin(sc); + break; + case TIOCMGET: + setwin(sc,0); + port->imodem=bc->mstat; + hidewin(sc); + + tiocm_xxx = TIOCM_LE; /* XXX - always enabled while open */ + + DPRINT3("dgb%d: port %d: modem stat -- ",unit,pnum); + + if (port->imodem & DTR) { + DPRINT1("DTR "); + tiocm_xxx |= TIOCM_DTR; + } + if (port->imodem & RTS) { + DPRINT1("RTS "); + tiocm_xxx |= TIOCM_RTS; + } + if (port->imodem & CTS) { + DPRINT1("CTS "); + tiocm_xxx |= TIOCM_CTS; + } + if (port->imodem & port->dcd) { + DPRINT1("DCD "); + tiocm_xxx |= TIOCM_CD; + } + if (port->imodem & port->dsr) { + DPRINT1("DSR "); + tiocm_xxx |= TIOCM_DSR; + } + if (port->imodem & RI) { + DPRINT1("RI "); + tiocm_xxx |= TIOCM_RI; + } + *(int *)data = tiocm_xxx; + DPRINT1("--\n"); + break; + default: + splx(s); + return ENOTTY; + } + splx(s); + return 0; +} + +static void +wakeflush(p) + void *p; +{ + struct dgb_p *port=p; + + wakeup(&port->draining); +} + +/* wait for the output to drain */ + +static int +dgbdrain(port) + struct dgb_p *port; +{ + struct tty *tp=port->tty; + struct dgb_softc *sc=&dgb_softc[port->unit]; + struct board_chan *bc=port->brdchan; + int error; + int head, tail; + + setwin(sc,0); + + bc->iempty=1; + tail=bc->tout; + head=bc->tin; + + while(tail!=head) { + DPRINT5("dgb%d: port %d: drain: head=%d tail=%d\n", + port->unit, port->pnum, head, tail); + + hidewin(sc); + port->draining=1; + timeout(wakeflush,port, hz); + error=tsleep(&port->draining, TTIPRI | PCATCH, "dgdrn", 0); + port->draining=0; + setwin(sc,0); + + if (error != 0) { + DPRINT4("dgb%d: port %d: tsleep(dgdrn) error=%d\n", + port->unit,port->pnum,error); + + bc->iempty=0; + hidewin(sc); + return error; + } + + tail=bc->tout; + head=bc->tin; + } + DPRINT5("dgb%d: port %d: drain: head=%d tail=%d\n", + port->unit, port->pnum, head, tail); + + return 0; +} + +/* wait for the output to drain */ +/* or simply clear the buffer it it's stopped */ + +static void +dgb_drain_or_flush(port) + struct dgb_p *port; +{ + struct tty *tp=port->tty; + struct dgb_softc *sc=&dgb_softc[port->unit]; + struct board_chan *bc=port->brdchan; + int error; + int lasttail; + int head, tail; + + setwin(sc,0); + + lasttail=-1; + bc->iempty=1; + tail=bc->tout; + head=bc->tin; + + while(tail!=head /* && tail!=lasttail */ ) { + DPRINT5("dgb%d: port %d: flush: head=%d tail=%d\n", + port->unit, port->pnum, head, tail); + + /* if there is no carrier simply clean the buffer */ + if( !(tp->t_state & TS_CARR_ON) ) { + bc->tout=bc->tin=0; + bc->iempty=0; + hidewin(sc); + return; + } + + hidewin(sc); + port->draining=1; + timeout(wakeflush,port, hz); + error=tsleep(&port->draining, TTIPRI | PCATCH, "dgfls", 0); + port->draining=0; + setwin(sc,0); + + if (error != 0) { + DPRINT4("dgb%d: port %d: tsleep(dgfls) error=%d\n", + port->unit,port->pnum,error); + + /* silently clean the buffer */ + + bc->tout=bc->tin=0; + bc->iempty=0; + hidewin(sc); + return; + } + + lasttail=tail; + tail=bc->tout; + head=bc->tin; + } + DPRINT5("dgb%d: port %d: flush: head=%d tail=%d\n", + port->unit, port->pnum, head, tail); +} + +static int +dgbparam(tp, t) + struct tty *tp; + struct termios *t; +{ + int dev=tp->t_dev; + int mynor=minor(dev); + int unit=MINOR_TO_UNIT(dev); + int pnum=MINOR_TO_PORT(dev); + struct dgb_softc *sc=&dgb_softc[unit]; + struct dgb_p *port=&sc->ports[pnum]; + struct board_chan *bc=port->brdchan; + int cflag; + int head; + int mval; + int iflag; + int hflow; + int s; + + DPRINT3("dgb%d: port%d: setting parameters\n",unit,pnum); + + if(port->mustdrain) { + DPRINT3("dgb%d: port%d: must call dgbdrain()\n",unit,pnum); + dgbdrain(port); + } + + cflag=ttspeedtab(t->c_ospeed, dgbspeedtab); + + if (t->c_ispeed == 0) + t->c_ispeed = t->c_ospeed; + + if (cflag < 0 || cflag > 0 && t->c_ispeed != t->c_ospeed) + return (EINVAL); + + s=spltty(); + + setwin(sc,0); + + if(cflag==0) { /* hangup */ + DPRINT3("dgb%d: port%d: hangup\n",unit,pnum); + head=bc->rin; + bc->rout=head; + head=bc->tin; + fepcmd(port, STOUT, head, 0, 0, 0); + mval= port->omodem & ~(DTR|RTS); + } else { + DPRINT4("dgb%d: port%d: CBAUD=%d\n",unit,pnum,cflag); + + /* convert flags to sysV-style values */ + if(t->c_cflag & PARODD) + cflag|=01000; + if(t->c_cflag & PARENB) + cflag|=00400; + if(t->c_cflag & CSTOPB) + cflag|=00100; + + cflag|= (t->c_cflag & CSIZE) >> 4; + DPRINT4("dgb%d: port%d: CFLAG=0x%x\n",unit,pnum,cflag); + + if(cflag!=port->fepcflag) { + DPRINT3("dgb%d: port%d: set cflag\n",unit,pnum); + port->fepcflag=cflag; + fepcmd(port, SETCTRLFLAGS, (unsigned)cflag, 0, 0, 0); + } + mval= port->omodem | (DTR|RTS) ; + } + + iflag=t->c_iflag & (IGNBRK|BRKINT|IGNPAR|PARMRK|INPCK|ISTRIP); + if(t->c_cflag & IXON) + cflag|=002000; + if(t->c_cflag & IXANY) + cflag|=004000; + if(t->c_cflag & IXOFF) + cflag|=010000; + + if(iflag!=port->fepiflag) { + DPRINT3("dgb%d: port%d: set iflag\n",unit,pnum); + port->fepiflag=iflag; + fepcmd(port, SETIFLAGS, (unsigned)iflag, 0, 0, 0); + } + + bc->mint=port->dcd; + + if(t->c_cflag & CRTSCTS) + hflow=(CTS|RTS); + else + hflow=0; + + if(hflow!=port->hflow) { + DPRINT3("dgb%d: port%d: set hflow\n",unit,pnum); + port->hflow=hflow; + fepcmd(port, SETHFLOW, (unsigned)hflow, 0xff, 0, 1); + } + + if(port->omodem != mval) { + DPRINT4("dgb%d: port %d: setting modem parameters 0x%x\n", + unit,pnum,mval); + port->omodem=mval; + fepcmd(port, SETMODEM, (unsigned)mval, RTS|DTR, 0, 1); + } + + if(port->fepstartc!=t->c_cc[VSTART] || port->fepstopc!=t->c_cc[VSTOP]) { + DPRINT3("dgb%d: port%d: set startc, stopc\n",unit,pnum); + port->fepstartc=t->c_cc[VSTART]; + port->fepstopc=t->c_cc[VSTOP]; + fepcmd(port, SONOFFC, port->fepstartc, port->fepstopc, 0, 1); + } + + hidewin(sc); + splx(s); + + return 0; + +} + +static void +dgbstart(tp) + struct tty *tp; +{ + int unit; + int pnum; + struct dgb_p *port; + struct dgb_softc *sc; + struct board_chan *bc; + int head, tail; + int size, ocount; + int s; + int wmask; + + unit=MINOR_TO_UNIT(minor(tp->t_dev)); + pnum=MINOR_TO_PORT(minor(tp->t_dev)); + sc=&dgb_softc[unit]; + port=&sc->ports[pnum]; + bc=port->brdchan; + + wmask=port->txbufsize-1; + + s=spltty(); + + while( tp->t_outq.c_cc!=0 ) { +#ifndef TS_ASLEEP /* post 2.0.5 FreeBSD */ + ttwwakeup(tp); +#else + if(tp->t_outq.c_cc <= tp->t_lowat) { + if(tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup(TSA_OLOWAT(tp)); + } + selwakeup(&tp->t_wsel); + } +#endif + setwin(sc,0); + + head=bc->tin & wmask; + tail=bc->tout & wmask; + + DPRINT5("dgb%d: port%d: s tx head=%d tail=%d\n",unit,pnum,head,tail); + + if(tail>head) + size=tail-head-1; + else { + size=port->txbufsize-head; + if(tail==0) + size--; + } + + if(size==0) { + bc->iempty=1; bc->ilow=1; + hidewin(sc); + tp->t_state|=TS_BUSY; + splx(s); + return; + } + + towin(sc,port->txwin); + + ocount=q_to_b(&tp->t_outq, port->txptr+head, size); + head+=ocount; + + setwin(sc,0); + bc->tin=head; + } + +#ifndef TS_ASLEEP /* post 2.0.5 FreeBSD */ + ttwwakeup(tp); +#else + if(tp->t_state & TS_ASLEEP) { + tp->t_state &= ~TS_ASLEEP; + wakeup(TSA_OLOWAT(tp)); + } + tp->t_state&=~TS_BUSY; +#endif + hidewin(sc); + splx(s); +} + +void +dgbstop(tp, rw) + struct tty *tp; + int rw; +{ +} + +int +dgbselect(dev, rw, p) + dev_t dev; + int rw; + struct proc *p; +{ + if (minor(dev) & CONTROL_MASK) + return (ENODEV); + return (ttselect(dev & ~MINOR_MAGIC_MASK, rw, p)); +} + +static void +fepcmd(port, cmd, op1, op2, ncmds, bytecmd) + struct dgb_p *port; + int cmd, op1, op2, ncmds, bytecmd; +{ + struct dgb_softc *sc=&dgb_softc[port->unit]; + u_char *mem=sc->vmem; + unsigned tail, head; + int count, n; + + if(port->status==DISABLED) { + printf("dgb%d(%d): FEP command on disabled port\n", + port->unit, port->pnum); + return; + } + + setwin(sc,0); + head=sc->mailbox->cin; + + if(head>=(FEP_CMAX-FEP_CSTART) || (head & 3)) { + printf("dgb%d(%d): wrong pointer head of command queue : 0x%x\n", + port->unit, port->pnum, head); + return; + } + + if(bytecmd) { + mem[head+FEP_CSTART+0]=cmd; + mem[head+FEP_CSTART+1]=port->pnum; + mem[head+FEP_CSTART+2]=op1; + mem[head+FEP_CSTART+3]=op2; + } else { + mem[head+FEP_CSTART+0]=cmd; + mem[head+FEP_CSTART+1]=port->pnum; + *(ushort *)(mem+head+FEP_CSTART+2)=op1; + } + + head=(head+4) & (FEP_CMAX-FEP_CSTART-4); + sc->mailbox->cin=head; + + for(count=FEPTIMEOUT; count>0; count--) { + head=sc->mailbox->cin; + tail=sc->mailbox->cout; + n=(head-tail) & (FEP_CMAX-FEP_CSTART-4); + + if(n <= ncmds * 4) + return; + } + + printf("dgb%d(%d): timeout on FEP command\n", + port->unit, port->pnum); +} + +#endif /* NDGB > 0 */ diff --git a/sys/gnu/i386/isa/dgbios.h b/sys/gnu/i386/isa/dgbios.h new file mode 100644 index 0000000000000..b6e916e583810 --- /dev/null +++ b/sys/gnu/i386/isa/dgbios.h @@ -0,0 +1,175 @@ +static unsigned char pcxx_bios[] = { + 0x28,0x43,0x29,0x20,0x43,0x6F,0x70,0x79,0x72,0x69,0x67,0x68, + 0x74,0x20,0x31,0x39,0x39,0x34,0x2C,0x20,0x44,0x69,0x67,0x69, + 0x42,0x6F,0x61,0x72,0x64,0x20,0x49,0x6E,0x63,0x2E,0x00,0x00, + 0x8A,0xF8,0x8A,0xF8,0x15,0xF9,0x8A,0xF8,0x8A,0xF8,0x8A,0xF8, + 0x8A,0xF8,0x8A,0xF8,0xBC,0xF8,0x8A,0xF8,0x96,0xF8,0x96,0xF8, + 0x96,0xF8,0x96,0xF8,0x96,0xF8,0x96,0xF8,0x8A,0xF8,0x8A,0xF8, + 0x96,0xF8,0x96,0xF8,0x8A,0xF8,0xAD,0xF8,0xB0,0xF8,0x8A,0xF8, + 0x8A,0xF8,0x8A,0xF8,0x8A,0xF8,0x8A,0xF8,0x8A,0xF8,0x8A,0xF8, + 0x8A,0xF8,0x8A,0xF8,0x8A,0xF8,0x04,0x02,0x00,0x02,0x14,0x02, + 0x10,0x02,0x24,0x02,0x20,0x02,0x34,0x02,0x30,0x02,0x44,0x02, + 0x40,0x02,0x54,0x02,0x50,0x02,0x64,0x02,0x60,0x02,0x74,0x02, + 0x70,0x02,0x04,0x01,0x00,0x01,0x1E,0x2E,0x8E,0x1E,0x22,0xF8, + 0xFE,0x06,0x70,0x00,0x1F,0xCF,0x1E,0x50,0x52,0x2E,0x8E,0x1E, + 0x22,0xF8,0xFE,0x06,0x71,0x00,0xB8,0x00,0x80,0xBA,0x22,0xFF, + 0xEF,0x5A,0x58,0x1F,0xCF,0xB4,0x80,0xCF,0x1E,0x2E,0x8E,0x1E, + 0x22,0xF8,0xFE,0x06,0x2B,0x00,0x1F,0xCF,0x1E,0x52,0x50,0x2E, + 0x8E,0x1E,0x22,0xF8,0xCD,0x16,0xFE,0x06,0x2A,0x00,0x80,0x3E, + 0x2A,0x00,0x12,0x72,0x39,0xC6,0x06,0x2A,0x00,0x00,0xFE,0x06, + 0x29,0x00,0x80,0x3E,0x29,0x00,0x3C,0x72,0x29,0xC6,0x06,0x29, + 0x00,0x00,0xFE,0x06,0x28,0x00,0x80,0x3E,0x28,0x00,0x3C,0x72, + 0x19,0xC6,0x06,0x28,0x00,0x00,0xFE,0x06,0x27,0x00,0x80,0x3E, + 0x27,0x00,0x18,0x72,0x09,0xC6,0x06,0x27,0x00,0x00,0xFF,0x06, + 0x25,0x00,0xBA,0x22,0xFF,0xB8,0x00,0x80,0xEF,0x58,0x5A,0x1F, + 0xCF,0x60,0x1E,0x06,0xFC,0x2E,0x8E,0x06,0x22,0xF8,0x2E,0x8E, + 0x1E,0x22,0xF8,0x8D,0x36,0x40,0x00,0xAD,0x3C,0x3F,0x7F,0x22, + 0x3C,0x1F,0x7F,0x22,0x32,0xE4,0xD1,0xE0,0x3D,0x16,0x00,0x90, + 0x73,0x14,0xBB,0x56,0xF9,0x03,0xD8,0x2E,0xFF,0x17,0x8D,0x36, + 0x40,0x00,0xB0,0x00,0x89,0x04,0x07,0x1F,0x61,0xCF,0xB4,0x80, + 0xEB,0xF0,0xCD,0x15,0xEB,0xEC,0x6C,0xF9,0x79,0xF9,0xB9,0xF9, + 0xD3,0xF9,0xD8,0xF9,0xE1,0xF9,0xE9,0xF9,0xF2,0xF9,0xFA,0xF9, + 0xFD,0xF9,0x2A,0xFA,0xE4,0x00,0x24,0xF7,0xE6,0x00,0x0C,0x08, + 0xE6,0x00,0xB4,0x00,0xC3,0x1E,0xAD,0x8B,0xD8,0xAD,0x8E,0xDB, + 0x8B,0xF0,0x33,0xDB,0x8B,0x07,0x3D,0x4F,0x53,0x75,0x2A,0x8A, + 0x47,0x02,0x32,0xE4,0x86,0xC4,0x8B,0xC8,0x32,0xC0,0x02,0x07, + 0x43,0xE2,0xFB,0x0A,0xC0,0x75,0x16,0x8C,0xD9,0x1F,0x89,0x0E, + 0x2E,0x00,0x89,0x36,0x2C,0x00,0x8D,0x1E,0x02,0x00,0xC7,0x07, + 0x45,0x4D,0x32,0xE4,0xC3,0x1F,0xB4,0x80,0xC3,0xAD,0x8B,0xD8, + 0xAD,0x8B,0xD0,0xAD,0x8E,0xC0,0xAD,0x8B,0xF8,0xAD,0x8B,0xC8, + 0x8B,0xF2,0x1E,0x8E,0xDB,0xF3,0xA4,0x1F,0x32,0xE4,0xC3,0xEA, + 0xF0,0xFF,0x00,0xF0,0xAD,0x8B,0xD0,0xEC,0x88,0x04,0x32,0xE4, + 0xC3,0xAD,0x8B,0xD0,0xAC,0xEE,0x32,0xE4,0xC3,0xAD,0x8B,0xD0, + 0xED,0x89,0x04,0x32,0xE4,0xC3,0xAD,0x8B,0xD0,0xAD,0xEF,0x32, + 0xE4,0xC3,0xB4,0x80,0xC3,0xAC,0x3C,0x12,0x7F,0x25,0xFE,0xC8, + 0x32,0xE4,0xD1,0xE0,0x8D,0x1E,0x66,0xF8,0x03,0xD8,0x2E,0x8B, + 0x17,0xEC,0xAC,0x3C,0x0F,0x7F,0x10,0x3C,0x00,0x74,0x03,0xEE, + 0x90,0x90,0xEC,0x8B,0xFE,0x1E,0x07,0xAA,0x32,0xE4,0xC3,0xB4, + 0x80,0xC3,0xAC,0x3C,0x12,0x7F,0x1F,0xFE,0xC8,0x32,0xE4,0xD1, + 0xE0,0x8D,0x1E,0x66,0xF8,0x03,0xD8,0x2E,0x8B,0x17,0xEC,0xAC, + 0x3C,0x0F,0x7F,0x0A,0x3C,0x00,0x74,0x01,0xEE,0xAC,0xEE,0x32, + 0xE4,0xC3,0xB4,0x80,0xC3,0xFC,0x8E,0xC0,0xB8,0xFF,0xFF,0x8B, + 0xCB,0x33,0xFF,0xF3,0xAB,0x8B,0xCB,0x33,0xFF,0xF3,0xAF,0xE3, + 0x01,0xC3,0x8B,0xCB,0xBF,0x00,0x00,0x26,0x89,0x3D,0x83,0xC7, + 0x02,0xE2,0xF8,0xBE,0x00,0x00,0x8B,0xCB,0x26,0x8B,0x3C,0x3B, + 0xFE,0x74,0x01,0xC3,0x83,0xC6,0x02,0x83,0xC7,0x02,0xE2,0xF0, + 0x33,0xC0,0x8B,0xCB,0x33,0xFF,0xF3,0xAB,0x8B,0xCB,0x33,0xFF, + 0xF3,0xAF,0xC3,0x32,0xC0,0x26,0x80,0x3E,0x23,0x00,0x00,0x74, + 0x02,0x0C,0x01,0x26,0xF7,0x06,0x20,0x00,0x0F,0x00,0x74,0x02, + 0x0C,0x02,0x26,0xF7,0x06,0x20,0x00,0xF0,0x00,0x74,0x02,0x0C, + 0x04,0x26,0xF7,0x06,0x20,0x00,0x00,0xFF,0x74,0x02,0x0C,0x08, + 0x26,0xA2,0x24,0x00,0xB8,0x00,0x40,0xBA,0x5E,0xFF,0xEF,0xBA, + 0x66,0xFF,0xEF,0xBA,0x52,0xFF,0xB8,0x63,0x0E,0xEF,0xBA,0x56, + 0xFF,0xB8,0x05,0xE0,0xEF,0xBA,0x28,0xFF,0xB8,0xFC,0x00,0xEF, + 0xB8,0x00,0x02,0x26,0xA3,0x2E,0x00,0xB8,0x04,0x00,0x26,0xA3, + 0x2C,0x00,0xB0,0xC3,0xE6,0x08,0x8A,0xD8,0xE4,0x08,0x3A,0xC3, + 0x75,0x06,0x26,0xC6,0x06,0xB4,0x00,0x01,0xFC,0x8D,0x3E,0x00, + 0x00,0xB8,0x47,0x44,0xAB,0xB8,0xFF,0xFF,0xAB,0xAB,0xAB,0xB8, + 0x42,0x49,0xAB,0xB8,0x4F,0x53,0xAB,0xB8,0x58,0x69,0x26,0x80, + 0x3E,0x10,0x00,0x04,0x74,0x0E,0xB8,0x58,0x65,0x26,0x80,0x3E, + 0x10,0x00,0x03,0x74,0x03,0xB8,0x58,0x74,0xAB,0x8D,0x36,0xFE, + 0xFF,0x8A,0x04,0x8D,0x36,0xFF,0xFF,0x8A,0x24,0xAB,0xFB,0x26, + 0x81,0x0E,0x12,0x00,0x00,0x08,0x06,0x1F,0xA1,0x00,0x00,0x8B, + 0x1E,0x02,0x00,0x3D,0x44,0x47,0x75,0x0B,0x26,0x81,0x0E,0x12, + 0x00,0x00,0x10,0xFF,0x2E,0x2C,0x00,0x81,0xFB,0x45,0x4D,0x75, + 0xE3,0x26,0x81,0x0E,0x12,0x00,0x00,0x20,0xFF,0x2E,0x2C,0x00, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0xFA,0xBA,0xA8,0xFF,0xB8,0xBA,0x81,0xEF, + 0xBA,0xA4,0xFF,0xB8,0x3A,0x00,0xEF,0x90,0xE4,0x00,0xA8,0x60, + 0x75,0x0C,0x24,0x06,0x74,0x14,0x3C,0x02,0x74,0x1C,0x3C,0x04, + 0x74,0x24,0xBB,0x38,0xC0,0xBE,0xF8,0x81,0xBF,0xBA,0xA0,0xEB, + 0x22,0x90,0xBB,0x38,0xF0,0xBE,0xF8,0x41,0xBF,0xBA,0x81,0xEB, + 0x16,0x90,0xBB,0x38,0xF0,0xBE,0xF8,0xE1,0xBF,0xBA,0x88,0xEB, + 0x0A,0x90,0xBB,0x38,0xC0,0xBE,0xF8,0x41,0xBF,0xBA,0x81,0xBA, + 0xA0,0xFF,0x8B,0xC3,0xEF,0xBA,0xA2,0xFF,0xB8,0xF8,0x0F,0xEF, + 0xBA,0xA6,0xFF,0x8B,0xC6,0xEF,0xBA,0xA8,0xFF,0x8B,0xC7,0xEF, + 0x8C,0xC8,0x8E,0xD8,0xE4,0x00,0x24,0x06,0x74,0x17,0xBB,0x00, + 0x80,0xBD,0xC0,0xE0,0x3C,0x02,0x74,0x5A,0xBD,0xC0,0xC0,0x3C, + 0x04,0x74,0x53,0xBD,0xC0,0x80,0xEB,0x4E,0x90,0xB9,0x08,0x00, + 0xB8,0x00,0x80,0x8E,0xC0,0x26,0xA3,0x00,0x00,0x05,0x00,0x10, + 0xE2,0xF5,0xBD,0xC0,0xF0,0xBB,0x00,0x7C,0xB8,0x00,0xE0,0x8E, + 0xC0,0x26,0x8B,0x0E,0x00,0x00,0x3B,0xC8,0x75,0x28,0xBB,0x00, + 0x80,0xBD,0xC0,0xE0,0xB8,0x00,0xC0,0x8E,0xC0,0x26,0x8B,0x0E, + 0x00,0x00,0x3B,0xC8,0x75,0x14,0xBD,0xC0,0xC0,0xB8,0x00,0x80, + 0x8E,0xC0,0x26,0x8B,0x0E,0x00,0x00,0x3B,0xC8,0x75,0x03,0xBD, + 0xC0,0x80,0x8C,0xC8,0x8E,0xD0,0xBC,0xED,0xFC,0x8B,0xC5,0x25, + 0x00,0xF0,0xE9,0x6C,0xFD,0xB4,0x00,0x74,0x06,0xB4,0xFF,0xEB, + 0x02,0xE5,0xFC,0x8E,0xC5,0x2E,0x89,0x2E,0x22,0xF8,0xE4,0x00, + 0x24,0x16,0x26,0xA2,0x11,0x00,0x26,0x83,0x0E,0x12,0x00,0x01, + 0x80,0xFC,0x00,0x74,0x06,0x26,0x83,0x0E,0x14,0x00,0x01,0x26, + 0xC7,0x06,0x18,0x00,0x40,0x00,0x26,0xC6,0x06,0x10,0x00,0x03, + 0xA8,0x10,0x74,0x06,0x26,0xC6,0x06,0x10,0x00,0x04,0xB8,0x00, + 0x00,0x8E,0xC0,0xB8,0xAA,0x55,0x26,0xA3,0x00,0x00,0x26,0xC7, + 0x06,0x02,0x00,0x00,0x00,0x26,0xC7,0x06,0x04,0x00,0x00,0x00, + 0x8B,0xCD,0x81,0xE1,0x00,0xF0,0x8E,0xC1,0x26,0x8B,0x1E,0x00, + 0x00,0x3B,0xC3,0x75,0x13,0x8E,0xC5,0x26,0xC6,0x06,0x10,0x00, + 0x05,0xB8,0x40,0x00,0x8E,0xD0,0xBC,0x00,0x04,0xE9,0x99,0x00, + 0x8C,0xC8,0x8E,0xD0,0xBC,0x7C,0xFD,0xB8,0x00,0x00,0xBB,0x00, + 0x20,0xE9,0xDD,0xFC,0xB4,0x00,0x74,0x06,0xB4,0xFF,0xEB,0x02, + 0x74,0xFD,0x8E,0xC5,0x80,0xFC,0x00,0x74,0x08,0x26,0x83,0x0E, + 0x14,0x00,0x02,0xEB,0x0D,0x26,0xC7,0x06,0x16,0x00,0x10,0x00, + 0x26,0x83,0x0E,0x12,0x00,0x02,0xB8,0x40,0x00,0x8E,0xD0,0xBC, + 0x00,0x04,0xE4,0x00,0xA8,0x60,0x75,0x07,0xBA,0xA2,0xFF,0xB8, + 0xFC,0x0F,0xEF,0xB8,0x00,0x04,0x8E,0xC0,0xB8,0xAA,0x55,0x26, + 0xA3,0x00,0x00,0x26,0xC7,0x06,0x02,0x00,0x00,0x00,0x26,0xC7, + 0x06,0x04,0x00,0x00,0x00,0xB9,0x00,0x00,0x8E,0xC1,0x26,0x8B, + 0x1E,0x00,0x00,0x3B,0xC3,0x75,0x02,0xEB,0x24,0x8E,0xC5,0x26, + 0x83,0x0E,0x12,0x00,0x04,0xB8,0x00,0x04,0xBB,0x00,0x60,0x06, + 0xE8,0x66,0xFC,0x07,0x75,0x09,0x26,0xC7,0x06,0x16,0x00,0x40, + 0x00,0xEB,0x06,0x26,0x83,0x0E,0x14,0x00,0x04,0x8E,0xC5,0x8C, + 0xC0,0x3D,0xC0,0xF0,0x75,0x03,0xE9,0x9F,0x00,0x3D,0xC0,0x80, + 0x74,0x62,0x3D,0xC0,0xC0,0x74,0x23,0x26,0x83,0x0E,0x12,0x00, + 0x08,0xB8,0x00,0xF0,0xBB,0x00,0x7C,0x06,0xE8,0x2E,0xFC,0x07, + 0x75,0x08,0x26,0x83,0x06,0x18,0x00,0x40,0xEB,0x06,0x26,0x83, + 0x0E,0x14,0x00,0x08,0xEB,0x72,0xB9,0x03,0x00,0xB8,0x00,0xD0, + 0xBA,0x08,0x00,0xBB,0x00,0x80,0x3D,0x00,0xF0,0x75,0x03,0xBB, + 0x00,0x7C,0x26,0x09,0x16,0x12,0x00,0x06,0x50,0x51,0xE8,0xFC, + 0xFB,0x59,0x58,0x07,0x75,0x0F,0x26,0x83,0x06,0x18,0x00,0x40, + 0xD1,0xE2,0x05,0x00,0x10,0xE2,0xD8,0xEB,0x05,0x26,0x09,0x16, + 0x14,0x00,0xEB,0x38,0xB9,0x07,0x00,0xB8,0x00,0x90,0xBA,0x08, + 0x00,0xBB,0x00,0x80,0x3D,0x00,0xF0,0x75,0x03,0xBB,0x00,0x7C, + 0x26,0x09,0x16,0x12,0x00,0x06,0x50,0x51,0xE8,0xC2,0xFB,0x59, + 0x58,0x07,0x75,0x0F,0x26,0x83,0x06,0x18,0x00,0x40,0xD1,0xE2, + 0x05,0x00,0x10,0xE2,0xD8,0xEB,0x05,0x26,0x09,0x16,0x14,0x00, + 0x26,0xA1,0x18,0x00,0x2D,0x10,0x00,0x26,0xA3,0x1A,0x00,0x06, + 0xFC,0x33,0xFF,0x8E,0xC7,0xB9,0x00,0x02,0xB8,0x00,0xF0,0xF3, + 0xAB,0x33,0xFF,0xBE,0x24,0xF8,0xB9,0x20,0x00,0xA5,0x47,0x47, + 0xE2,0xFB,0xBE,0x64,0xF8,0xB9,0xE0,0x00,0x8B,0x1C,0x26,0x89, + 0x1D,0x83,0xC7,0x04,0xE2,0xF8,0x07,0xBA,0x28,0xFF,0xB8,0xFD, + 0x00,0xEF,0xBA,0x32,0xFF,0xB8,0x0D,0x00,0xEF,0xBA,0x34,0xFF, + 0xB8,0x0F,0x00,0xEF,0xBA,0x36,0xFF,0xB8,0x0E,0x00,0xEF,0xBA, + 0x38,0xFF,0xB8,0x19,0x00,0xEF,0xBA,0x3A,0xFF,0xB8,0x18,0x00, + 0xEF,0xBA,0x3C,0xFF,0xB8,0x0B,0x00,0xEF,0xBA,0x3E,0xFF,0xB8, + 0x1A,0x00,0xEF,0x8D,0x3E,0x90,0x00,0x8D,0x36,0x66,0xF8,0xB9, + 0x10,0x00,0xF3,0xA5,0x8D,0x3E,0xB0,0x00,0x8D,0x36,0x86,0xF8, + 0xB9,0x02,0x00,0xF3,0xA5,0xB9,0x10,0x00,0x8D,0x36,0x90,0x00, + 0x83,0xC6,0x1E,0x26,0x8B,0x14,0xB3,0x10,0x32,0xC0,0xEC,0xB0, + 0x0C,0xEE,0x8A,0xC3,0x8A,0xC3,0xEE,0x83,0xEE,0x02,0x26,0x8B, + 0x14,0xFE,0xCB,0xE2,0xEB,0xB9,0x10,0x00,0x8D,0x36,0x90,0x00, + 0x26,0x8B,0x14,0xB3,0x01,0xBF,0x00,0x80,0xB0,0x0C,0xEE,0xF6, + 0xE8,0xEC,0x3A,0xC3,0x75,0x0E,0xD1,0xC7,0x26,0x09,0x3E,0x20, + 0x00,0x26,0xFE,0x06,0x22,0x00,0xEB,0x07,0x33,0xC0,0x26,0x89, + 0x04,0xD1,0xC7,0x83,0xC6,0x02,0x26,0x8B,0x14,0xFE,0xC3,0xE2, + 0xD7,0x26,0xC6,0x06,0x23,0x00,0x01,0x8D,0x36,0xB0,0x00,0x26, + 0x8B,0x14,0x32,0xC0,0xEE,0xB0,0x0C,0xEE,0xB0,0x5A,0xEE,0xB0, + 0x0C,0xEE,0xF6,0xE8,0xEC,0x3C,0x5A,0x74,0x14,0x26,0xC7,0x06, + 0xB0,0x00,0x00,0x00,0x26,0xC7,0x06,0xB2,0x00,0x00,0x00,0x26, + 0xC6,0x06,0x23,0x00,0x00,0xE9,0xD3,0xFA,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0xEA,0x00,0xFC,0x00,0xF0,0x4D,0x2F,0x50, + 0x43,0x2F,0x58,0x2A,0x39,0x34,0x34,0x30 +}; + +static unsigned pcxx_nbios=sizeof(pcxx_bios); diff --git a/sys/gnu/i386/isa/dgfep.h b/sys/gnu/i386/isa/dgfep.h new file mode 100644 index 0000000000000..c60c66afec902 --- /dev/null +++ b/sys/gnu/i386/isa/dgfep.h @@ -0,0 +1,516 @@ +static unsigned char pcxx_cook[] = { + 0x4F,0x53,0x18,0x85,0xE9,0xBF,0x15,0x00,0x40,0x28,0x23,0x29, + 0x46,0x45,0x50,0x4F,0x53,0x20,0x37,0x2E,0x30,0x37,0x20,0x31, + 0x2F,0x31,0x30,0x2F,0x39,0x35,0x00,0x40,0x28,0x23,0x29,0x28, + 0x43,0x29,0x43,0x6F,0x70,0x79,0x72,0x69,0x67,0x68,0x74,0x20, + 0x31,0x39,0x38,0x39,0x2D,0x31,0x39,0x39,0x35,0x20,0x44,0x69, + 0x67,0x69,0x42,0x6F,0x61,0x72,0x64,0x20,0x49,0x6E,0x63,0x2E, + 0x00,0xCB,0x0C,0xCB,0x0C,0xE2,0x0C,0xCB,0x0C,0xCB,0x0C,0xCB, + 0x0C,0xCB,0x0C,0xCB,0x0C,0x57,0x0C,0xCB,0x0C,0xCB,0x0C,0xCB, + 0x0C,0x53,0x0B,0xCB,0x0C,0xCB,0x0C,0x42,0x0B,0xCB,0x0C,0xCB, + 0x0C,0x12,0x0D,0xCB,0x0C,0xCB,0x0C,0xCB,0x0C,0xCB,0x0C,0xCB, + 0x0C,0xCB,0x0C,0xCB,0x0C,0xCB,0x0C,0xCB,0x0C,0xCB,0x0C,0xCB, + 0x0C,0xCB,0x0C,0xCB,0x0C,0x00,0x10,0x80,0x10,0x00,0x11,0x80, + 0x11,0x00,0x12,0x80,0x12,0x00,0x13,0x80,0x13,0x00,0x14,0x80, + 0x14,0x00,0x15,0x80,0x15,0x00,0x16,0x80,0x16,0x00,0x17,0x80, + 0x17,0x78,0x0B,0xB9,0x0B,0x50,0x0C,0xB9,0x0B,0x8D,0x0B,0x8D, + 0x0B,0x8D,0x0B,0x8D,0x0B,0xC0,0x0B,0xC0,0x0B,0xC0,0x0B,0xC0, + 0x0B,0x8D,0x0B,0x8D,0x0B,0x8D,0x0B,0x8D,0x0B,0x50,0x0C,0xB9, + 0x0B,0x50,0x0C,0xB9,0x0B,0x8D,0x0B,0x8D,0x0B,0x8D,0x0B,0x8D, + 0x0B,0xC0,0x0B,0xC0,0x0B,0xC0,0x0B,0xC0,0x0B,0x8D,0x0B,0x8D, + 0x0B,0x8D,0x0B,0x8D,0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94, + 0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94, + 0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94, + 0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94, + 0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94, + 0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x94,0x0B,0x16,0x00,0xFE, + 0x11,0xFE,0x0B,0x2C,0x08,0xB5,0x06,0xFE,0x05,0x7E,0x04,0xFE, + 0x02,0x7E,0x01,0xBE,0x00,0x7E,0x00,0x5E,0x00,0x2E,0x00,0x16, + 0x00,0x0A,0x00,0x04,0x00,0x16,0x00,0x02,0x00,0x01,0x00,0x00, + 0x00,0x0E,0x00,0x06,0x00,0x7E,0x04,0xFE,0x02,0x7E,0x01,0xBE, + 0x00,0x7E,0x00,0x5E,0x00,0x2E,0x00,0x16,0x00,0x0A,0x00,0x04, + 0x00,0x18,0x00,0x86,0x13,0x03,0x0D,0xDF,0x08,0x41,0x07,0x81, + 0x06,0xE0,0x04,0x3F,0x03,0x9F,0x01,0xCE,0x00,0x89,0x00,0x66, + 0x00,0x32,0x00,0x18,0x00,0x0B,0x00,0x0B,0x00,0x18,0x00,0x0B, + 0x00,0x0B,0x00,0x0B,0x00,0x41,0x07,0x81,0x06,0xE0,0x04,0x3F, + 0x03,0x9F,0x01,0xCE,0x00,0x89,0x00,0x66,0x00,0x32,0x00,0x18, + 0x00,0x0B,0x00,0x0B,0x00,0x00,0x80,0x40,0xC0,0x1F,0x3F,0x7F, + 0xFF,0x00,0x04,0x02,0x06,0x08,0x0C,0x0A,0x0E,0x00,0x04,0x02, + 0x06,0x08,0x0C,0x0A,0x0E,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0, + 0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0x1E,0x06,0x3E, + 0x06,0xEF,0x06,0xF8,0x05,0x0E,0x06,0x55,0x07,0xA0,0x08,0xA0, + 0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0, + 0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0, + 0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0xA1,0x05,0xA1,0x05,0xA1,0x05,0xA1,0x05,0xA1, + 0x05,0xA1,0x05,0xA1,0x05,0xA1,0x05,0xA1,0x05,0xA1,0x05,0xA1, + 0x05,0xA1,0x05,0xA1,0x05,0xA1,0x05,0xA1,0x05,0xA1,0x05,0xA1, + 0x05,0xA1,0x05,0xA1,0x05,0xA1,0x05,0xA1,0x05,0xA1,0x05,0xA1, + 0x05,0xA1,0x05,0xA1,0x05,0xA1,0x05,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x5B,0x05,0xEA,0x05,0xEA,0x05,0xEA, + 0x05,0xEA,0x05,0xEA,0x05,0xEA,0x05,0xEA,0x05,0xEA,0x05,0xEA, + 0x05,0xEA,0x05,0xEA,0x05,0xEA,0x05,0xEA,0x05,0xEA,0x05,0xEA, + 0x05,0xEA,0x05,0xEA,0x05,0xEA,0x05,0xEA,0x05,0xEA,0x05,0xEA, + 0x05,0xEA,0x05,0xEA,0x05,0xEA,0x05,0xEA,0x05,0xEA,0x05,0x69, + 0x05,0x77,0x05,0x85,0x05,0x93,0x05,0xA0,0x08,0xA0,0x08,0xA0, + 0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0, + 0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0, + 0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0, + 0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0, + 0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0,0x08,0xA0, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D,0x08,0x9D, + 0x08,0x00,0x00,0xFA,0x8A,0x5C,0x50,0xF6,0xC3,0x0E,0x75,0x3C, + 0xF6,0xC3,0x40,0x75,0x16,0xF6,0xC3,0x10,0x74,0x26,0xF6,0xC3, + 0x01,0x75,0x13,0xF6,0xC3,0x20,0x75,0x15,0xC7,0x04,0xB6,0x04, + 0xE9,0xCF,0x00,0x8B,0x44,0x02,0x89,0x04,0xFF,0xE0,0xC7,0x04, + 0x03,0x05,0xE9,0x0E,0x01,0xC7,0x04,0x66,0x08,0xE9,0x6A,0x04, + 0xF6,0xC3,0x20,0x74,0x1A,0xC7,0x04,0xB3,0x08,0xE9,0xAB,0x04, + 0x8B,0x54,0x20,0xEC,0x8A,0xC8,0xF6,0xC3,0x02,0x75,0x42,0xF6, + 0xC3,0x08,0x75,0x0E,0xEB,0x69,0x90,0xC7,0x04,0x20,0x04,0xFB, + 0x81,0xC6,0x80,0x00,0xFF,0x24,0xF6,0xC1,0x04,0x74,0x27,0x80, + 0x64,0x50,0xF7,0xF6,0x44,0x51,0x02,0x74,0x13,0xF6,0x44,0x29, + 0x10,0x74,0x0D,0x8A,0x44,0x5D,0x83,0xC2,0x02,0xEE,0x83,0xEA, + 0x02,0xE9,0x49,0x04,0x8A,0x44,0x5C,0x83,0xC2,0x02,0xEE,0x83, + 0xEA,0x02,0xE9,0x3C,0x04,0xF6,0x44,0x50,0x04,0x75,0x28,0x83, + 0x7C,0x24,0xFF,0x74,0x1F,0xA1,0x00,0x0E,0x2B,0x44,0x26,0x3D, + 0x64,0x00,0x77,0x14,0xB0,0x05,0xEE,0x8A,0x44,0x75,0x24,0xEF, + 0x88,0x44,0x75,0xEE,0x80,0x64,0x50,0xFD,0x80,0x64,0x4B,0xFD, + 0xE9,0x0E,0x04,0xB0,0x01,0xEE,0x90,0x90,0x90,0xEC,0xA8,0x01, + 0x74,0x25,0xB0,0x05,0xEE,0x8A,0x44,0x75,0x0C,0x10,0x88,0x44, + 0x75,0xEE,0xA1,0x00,0x0E,0x03,0x44,0x24,0x89,0x44,0x26,0x80, + 0x64,0x50,0xFB,0x80,0x64,0x4B,0xFB,0x80,0x4C,0x50,0x02,0x80, + 0x4C,0x4B,0x02,0xE9,0xDB,0x03,0xFA,0x8B,0x54,0x20,0xEC,0x8A, + 0xC8,0x22,0x44,0x52,0x3A,0x44,0x53,0x75,0x19,0x8B,0x7C,0x0C, + 0x3B,0x7C,0x0A,0x74,0x18,0x8E,0x44,0x08,0x26,0x8A,0x05,0x47, + 0x23,0x7C,0x0E,0x89,0x7C,0x0C,0x83,0xC2,0x02,0xEE,0xFB,0x81, + 0xC6,0x80,0x00,0xFF,0x24,0xB0,0x01,0xEE,0x90,0x90,0x90,0xEC, + 0xA8,0x01,0x74,0x0C,0x80,0x64,0x50,0xEF,0x80,0x64,0x4B,0xEF, + 0xC7,0x04,0xC3,0x03,0xFB,0x81,0xC6,0x80,0x00,0xFF,0x24,0xFA, + 0x8B,0x54,0x20,0xEC,0x8A,0xC8,0x22,0x44,0x52,0x3A,0x44,0x53, + 0x75,0x3A,0x8B,0x7C,0x0C,0x3B,0x7C,0x0A,0x74,0x1B,0x8E,0x44, + 0x08,0x26,0x8A,0x05,0x47,0x23,0x7C,0x0E,0x89,0x7C,0x0C,0x8A, + 0xD8,0x22,0x5C,0x62,0x32,0xFF,0x03,0xDB,0x2E,0xFF,0xA7,0xC1, + 0x01,0xB0,0x01,0xEE,0x90,0x90,0x90,0xEC,0xA8,0x01,0x74,0x0C, + 0x80,0x64,0x50,0xEF,0x80,0x64,0x4B,0xEF,0xC7,0x04,0xC3,0x03, + 0xF6,0xC1,0x01,0x75,0x07,0xFB,0x81,0xC6,0x80,0x00,0xFF,0x24, + 0xE9,0x61,0x03,0xF6,0x44,0x2A,0x01,0x75,0x03,0xE9,0x39,0x03, + 0xB0,0x27,0xEB,0x42,0x90,0xF6,0x44,0x2A,0x01,0x75,0x03,0xE9, + 0x2B,0x03,0xB0,0x28,0xEB,0x34,0x90,0xF6,0x44,0x2A,0x01,0x75, + 0x03,0xE9,0x1D,0x03,0xB0,0x21,0xEB,0x26,0x90,0xF6,0x44,0x2A, + 0x01,0x75,0x03,0xE9,0x0F,0x03,0xB0,0x29,0xEB,0x18,0x90,0xF6, + 0x44,0x2A,0x01,0x75,0x03,0xE9,0x01,0x03,0xB0,0x5E,0xEB,0x0A, + 0x90,0xF6,0x44,0x2A,0x01,0x75,0x03,0xE9,0xF3,0x02,0x88,0x44, + 0x61,0xB0,0x5C,0x83,0xC2,0x02,0xEE,0x83,0xEA,0x02,0x80,0x4C, + 0x50,0x40,0xC7,0x04,0xC6,0x05,0xC7,0x44,0x02,0xC6,0x05,0xE9, + 0xCB,0x02,0xFA,0x8B,0x54,0x20,0xEC,0x8A,0xC8,0x22,0x44,0x52, + 0x3A,0x44,0x53,0x75,0x12,0x80,0x64,0x50,0xBF,0xC7,0x04,0x03, + 0x05,0x83,0x44,0x30,0x02,0x8A,0x44,0x61,0xE9,0xB9,0x02,0xE9, + 0xA7,0x02,0xF6,0x44,0x2A,0x02,0x75,0x03,0xE9,0xAA,0x02,0x2C, + 0x20,0xE9,0xA5,0x02,0x83,0xC2,0x02,0xEE,0x83,0xEA,0x02,0xF6, + 0x44,0x2B,0x40,0x75,0x03,0xE9,0x89,0x02,0xB8,0x7F,0x00,0xE9, + 0x9B,0x01,0x83,0xC2,0x02,0xEE,0x83,0xEA,0x02,0xF6,0x44,0x2B, + 0x80,0x75,0xED,0xE9,0x73,0x02,0x83,0xC2,0x02,0xEE,0x83,0xEA, + 0x02,0xF7,0x44,0x30,0xFF,0xFF,0x74,0x03,0xFF,0x4C,0x30,0xF6, + 0x44,0x2B,0x20,0x75,0x03,0xE9,0x59,0x02,0xB8,0x02,0x00,0xE9, + 0x6B,0x01,0xB3,0x18,0x22,0x5C,0x2B,0x75,0x16,0x83,0xC2,0x02, + 0xEE,0x83,0xEA,0x02,0x8B,0x44,0x30,0x05,0x08,0x00,0x25,0xF8, + 0xFF,0x89,0x44,0x30,0xE9,0x36,0x02,0x80,0xFB,0x18,0x75,0x57, + 0xB0,0x20,0x83,0xC2,0x02,0xEE,0x83,0xEA,0x02,0x8B,0x44,0x30, + 0x8B,0xD8,0x05,0x08,0x00,0x25,0xF8,0xFF,0x89,0x44,0x30,0x2B, + 0xC3,0x48,0x74,0x38,0x89,0x44,0x32,0x80,0x4C,0x50,0x40,0xC7, + 0x44,0x02,0x8F,0x06,0xC7,0x04,0x8F,0x06,0xE9,0x02,0x02,0xFA, + 0x8B,0x54,0x20,0xEC,0x8A,0xC8,0x22,0x44,0x52,0x3A,0x44,0x53, + 0x75,0x16,0xB0,0x20,0x83,0xC2,0x02,0xEE,0x83,0xEA,0x02,0xFF, + 0x4C,0x32,0x75,0x08,0x80,0x64,0x50,0xBF,0xC7,0x04,0x03,0x05, + 0xE9,0xDA,0x01,0x83,0xC2,0x02,0xEE,0x83,0xEA,0x02,0x80,0xFB, + 0x08,0x75,0x18,0x8B,0x44,0x30,0x8B,0xD8,0x05,0x08,0x00,0x25, + 0xF8,0xFF,0x89,0x44,0x30,0x2B,0xC3,0x3D,0x05,0x00,0x7C,0xDC, + 0xE9,0xCE,0x00,0x8B,0x44,0x30,0x8B,0xD8,0x05,0x08,0x00,0x25, + 0xF8,0xFF,0x89,0x44,0x30,0xB8,0x02,0x00,0xE9,0xBA,0x00,0xF6, + 0x44,0x2A,0x20,0x75,0x43,0xF6,0x44,0x2A,0x04,0x74,0x42,0xF6, + 0x44,0x2A,0x10,0x74,0x07,0xF7,0x44,0x30,0xFF,0xFF,0x74,0x30, + 0xB0,0x0D,0x83,0xC2,0x02,0xEE,0x83,0xEA,0x02,0x80,0x4C,0x50, + 0x40,0xC7,0x04,0x21,0x07,0xC7,0x44,0x02,0x21,0x07,0xE9,0x70, + 0x01,0xFA,0x8B,0x54,0x20,0xEC,0x8A,0xC8,0x22,0x44,0x52,0x3A, + 0x44,0x53,0x75,0x1C,0x80,0x64,0x50,0xBF,0xC7,0x04,0x03,0x05, + 0xB0,0x0A,0xEB,0x2B,0x90,0xB0,0x0A,0x83,0xC2,0x02,0xEE,0x83, + 0xEA,0x02,0xF6,0x44,0x2B,0x01,0x75,0x03,0xE9,0x42,0x01,0xB8, + 0x05,0x00,0xEB,0x55,0x90,0xF6,0x44,0x2A,0x08,0x75,0xE2,0xF6, + 0x44,0x2A,0x10,0x74,0x06,0x83,0x7C,0x30,0x00,0x74,0x13,0x83, + 0xC2,0x02,0xEE,0x83,0xEA,0x02,0xB3,0x06,0x22,0x5C,0x2B,0x75, + 0x08,0xC7,0x44,0x30,0x00,0x00,0xE9,0x14,0x01,0x80,0xFB,0x02, + 0x75,0x14,0x8B,0x44,0x30,0xC1,0xE8,0x04,0x05,0x03,0x00,0x3D, + 0x06,0x00,0x72,0x14,0xB8,0x06,0x00,0xEB,0x0F,0x90,0x80,0xFB, + 0x04,0x75,0x06,0xB8,0x05,0x00,0xEB,0x04,0x90,0xB8,0x09,0x00, + 0xC7,0x44,0x30,0x00,0x00,0xF6,0x44,0x2A,0x40,0x74,0x45,0x3D, + 0x20,0x00,0x77,0x40,0xBB,0x01,0x00,0x3D,0x03,0x00,0x7E,0x03, + 0xBB,0x02,0x00,0x89,0x5C,0x32,0x80,0x4C,0x50,0x40,0xC7,0x44, + 0x02,0xD2,0x07,0xC7,0x04,0xD2,0x07,0xE9,0xBF,0x00,0xFA,0x8B, + 0x54,0x20,0xEC,0x8A,0xC8,0x22,0x44,0x52,0x3A,0x44,0x53,0x75, + 0x10,0x8A,0x44,0x60,0x83,0xC2,0x02,0xEE,0x83,0xEA,0x02,0x83, + 0x6C,0x32,0x01,0x7E,0x50,0xE9,0x9D,0x00,0x05,0x06,0x00,0x03, + 0xC0,0x89,0x44,0x32,0x80,0x4C,0x50,0x40,0xC7,0x44,0x02,0x0C, + 0x08,0xC7,0x04,0x0C,0x08,0xE9,0x85,0x00,0xFA,0x8B,0x54,0x20, + 0xEC,0x8A,0xC8,0xB0,0x01,0xEE,0x90,0x90,0x90,0xEC,0xA8,0x01, + 0x74,0x0F,0xA1,0x00,0x0E,0x01,0x44,0x32,0xC7,0x44,0x02,0x30, + 0x08,0xC7,0x04,0x30,0x08,0xEB,0x62,0x90,0x8B,0x54,0x20,0xEC, + 0x8A,0xC8,0xA1,0x00,0x0E,0x2B,0x44,0x32,0x3D,0xE8,0x03,0x77, + 0xEC,0x80,0x64,0x50,0xBF,0xC7,0x04,0x03,0x05,0xEB,0x46,0x90, + 0xB0,0x01,0xEE,0x90,0x90,0x90,0xEC,0xA8,0x01,0x74,0x3A,0x80, + 0x64,0x50,0xEF,0x80,0x64,0x4B,0xEF,0xC7,0x04,0xB3,0x08,0xEB, + 0x2C,0x90,0xFA,0x8B,0x54,0x20,0xEC,0x8A,0xC8,0x22,0x44,0x52, + 0x3A,0x44,0x53,0x75,0x1C,0x8B,0x7C,0x0C,0x3B,0x7C,0x0A,0x74, + 0xCF,0x8E,0x44,0x08,0x26,0x8A,0x05,0x47,0x23,0x7C,0x0E,0x89, + 0x7C,0x0C,0x83,0xC2,0x02,0xEE,0x83,0xEA,0x02,0xF6,0xC1,0x01, + 0x75,0x26,0xFB,0x81,0xC6,0x80,0x00,0xFF,0x24,0xFF,0x44,0x30, + 0x83,0xC2,0x02,0xEE,0x83,0xEA,0x02,0xF6,0xC1,0x01,0x75,0x10, + 0xFB,0x81,0xC6,0x80,0x00,0xFF,0x24,0xFA,0x8B,0x54,0x20,0xEC, + 0xA8,0x01,0x74,0xDA,0xC6,0x44,0x49,0x02,0x8B,0x7C,0x12,0x8E, + 0x44,0x10,0xB0,0x01,0xEE,0x90,0x90,0x90,0xEC,0x8A,0xE0,0x90, + 0xB0,0x30,0xEE,0x83,0xC2,0x02,0x90,0xEC,0x83,0xEA,0x02,0x23, + 0x44,0x34,0xFF,0x64,0x06,0xB3,0x1C,0x22,0x5C,0x51,0x75,0x1A, + 0xF6,0x44,0x29,0x04,0x74,0x21,0xF6,0x44,0x29,0x20,0x75,0x2B, + 0x80,0x7C,0x5E,0x00,0x75,0x1D,0xC7,0x44,0x06,0x58,0x0A,0xE9, + 0x56,0x01,0xF6,0xC3,0x10,0x75,0x2E,0xF6,0xC3,0x04,0x75,0x74, + 0xEB,0x6B,0x90,0xC7,0x44,0x06,0x62,0x0A,0xE9,0x4B,0x01,0xC7, + 0x44,0x06,0x53,0x0A,0xE9,0x34,0x01,0x80,0x7C,0x5E,0x00,0x75, + 0x08,0xC7,0x44,0x06,0xCA,0x09,0xE9,0x9D,0x00,0xC7,0x44,0x06, + 0xC5,0x09,0xE9,0x90,0x00,0x0A,0xC0,0x74,0x2A,0xFE,0x4C,0x63, + 0x74,0x1A,0x80,0xE3,0xEF,0x75,0xC4,0xF6,0x44,0x29,0x04,0x74, + 0x21,0xF6,0x44,0x29,0x20,0x75,0x21,0x80,0x7C,0x5E,0x00,0x75, + 0x18,0xE9,0x00,0x01,0x80,0x64,0x51,0xEF,0x80,0xE3,0xEF,0x75, + 0xA6,0xEB,0x85,0x80,0x64,0x51,0xEF,0xE9,0x06,0x01,0xE9,0xF5, + 0x00,0xE9,0xE3,0x00,0x80,0x7C,0x5E,0x00,0x75,0x4F,0xEB,0x52, + 0x90,0x80,0x64,0x51,0xF7,0xE9,0xE2,0x00,0x80,0x64,0x53,0x3F, + 0x80,0x64,0x54,0xFE,0x80,0x4C,0x58,0x01,0x80,0x64,0x51,0xFB, + 0xF6,0x44,0x29,0x40,0x75,0x2C,0x3A,0x44,0x5D,0x74,0x27,0x3A, + 0x44,0x5C,0x74,0x22,0xF6,0x44,0x29,0x20,0x74,0x0A,0x3A,0x44, + 0x5A,0x74,0x17,0x3A,0x44,0x5B,0x74,0x12,0xF6,0x44,0x5E,0xFF, + 0x74,0x09,0x3A,0x44,0x5E,0x75,0x04,0x80,0x4C,0x51,0x08,0xE9, + 0xA0,0x00,0xE9,0xAB,0x00,0x3A,0x44,0x5E,0x74,0x7D,0x3A,0x44, + 0x5C,0x74,0x3D,0x3A,0x44,0x5D,0x74,0x55,0x3A,0x44,0x5A,0x74, + 0x08,0x3A,0x44,0x5B,0x74,0x18,0xE9,0x81,0x00,0xF6,0x44,0x53, + 0x40,0x74,0x07,0x80,0x64,0x53,0xBF,0xE9,0x82,0x00,0x3A,0x44, + 0x5B,0x74,0x03,0xEB,0x7B,0x90,0x80,0x4C,0x53,0x40,0xF6,0x44, + 0x29,0x08,0x74,0x70,0x80,0x4C,0x51,0x04,0xC7,0x44,0x06,0xE1, + 0x08,0xEB,0x65,0x90,0xF6,0x44,0x53,0x80,0x74,0x0F,0x80,0x64, + 0x53,0x7F,0x80,0x64,0x54,0xFE,0x80,0x4C,0x58,0x01,0xEB,0x50, + 0x90,0x3A,0x44,0x5D,0x74,0x03,0xEB,0x48,0x90,0x80,0x4C,0x53, + 0x80,0x80,0x4C,0x54,0x01,0x80,0x4C,0x58,0x01,0xF6,0x44,0x29, + 0x08,0x74,0x35,0x80,0x4C,0x51,0x04,0xC7,0x44,0x06,0xE1,0x08, + 0xEB,0x2A,0x90,0x80,0x4C,0x51,0x08,0xC7,0x44,0x06,0xE1,0x08, + 0xEB,0x10,0x90,0x3A,0x44,0x5E,0x74,0xEF,0x3A,0x44,0x5C,0x74, + 0xAF,0x3A,0x44,0x5D,0x74,0xC7,0x3D,0xFF,0x00,0x73,0x26,0xAA, + 0x23,0x7C,0x16,0x3B,0x7C,0x14,0x74,0x4F,0xEC,0xA8,0x01,0x74, + 0x03,0xE9,0x4E,0xFE,0x89,0x7C,0x12,0x2B,0x7C,0x14,0x23,0x7C, + 0x16,0x3B,0x7C,0x1C,0x73,0x46,0xFB,0x81,0xC6,0x80,0x00,0xFF, + 0x24,0x0A,0xE4,0x75,0x1E,0xB3,0x0C,0x22,0x5C,0x28,0x80,0xFB, + 0x08,0x75,0xCC,0xAA,0x23,0x7C,0x16,0x3B,0x7C,0x14,0x74,0x1B, + 0xAA,0x23,0x7C,0x16,0x3B,0x7C,0x14,0x74,0x12,0xEB,0xC1,0xF6, + 0x44,0x28,0x04,0x75,0xBB,0xF6,0x44,0x28,0x08,0x75,0x50,0x32, + 0xC0,0xEB,0xA8,0x4F,0x23,0x7C,0x16,0x89,0x7C,0x12,0xC6,0x44, + 0x59,0x01,0xEB,0xA4,0xF6,0x44,0x51,0x02,0x74,0x07,0xFB,0x81, + 0xC6,0x80,0x00,0xFF,0x24,0x80,0x4C,0x51,0x02,0xB0,0x05,0xEE, + 0xB0,0x82,0x22,0x44,0x5F,0xF6,0xD0,0x22,0x44,0x75,0x88,0x44, + 0x75,0xEE,0xF6,0x44,0x29,0x10,0x74,0x10,0x80,0x4C,0x54,0x04, + 0x80,0x4C,0x58,0x04,0x80,0x74,0x50,0x08,0xC7,0x04,0xC3,0x03, + 0xFB,0x81,0xC6,0x80,0x00,0xFF,0x24,0x26,0xC6,0x05,0xFF,0x47, + 0x23,0x7C,0x16,0x3B,0x7C,0x14,0x74,0xA7,0x32,0xFF,0xF6,0x44, + 0x29,0x80,0x74,0x0A,0x8A,0xDC,0xC0,0xEB,0x04,0x2E,0x8A,0xBF, + 0xB1,0x01,0x26,0x88,0x3D,0x47,0x23,0x7C,0x16,0x3B,0x7C,0x14, + 0x74,0x89,0xAA,0x23,0x7C,0x16,0x3B,0x7C,0x14,0x74,0x80,0xE9, + 0x2E,0xFF,0x1E,0x2E,0x8E,0x1E,0xC1,0x03,0xFF,0x06,0x1C,0x0E, + 0x60,0xBE,0x00,0x14,0xEB,0x0F,0x90,0x1E,0x2E,0x8E,0x1E,0xC1, + 0x03,0xFF,0x06,0x1A,0x0E,0x60,0xBE,0x00,0x10,0xB9,0x08,0x00, + 0x8B,0x54,0x20,0xB0,0x03,0xEE,0x90,0x90,0x32,0xFF,0xEC,0x8A, + 0xD8,0x02,0xD8,0x2E,0xFF,0xA7,0xA9,0x00,0x81,0xC6,0x00,0x01, + 0x8B,0x54,0x20,0x0B,0xD2,0xE0,0xE4,0xB8,0x00,0x80,0xBA,0x22, + 0xFF,0xEF,0x61,0x1F,0xCF,0x81,0xCE,0x80,0x00,0x8B,0x54,0x20, + 0xFF,0x06,0x20,0x0E,0xB0,0x01,0xEE,0x8A,0x44,0x71,0x24,0xE7, + 0x88,0x44,0x71,0xEE,0xC6,0x44,0x49,0x02,0x80,0x4C,0x50,0x20, + 0xC7,0x04,0xC3,0x03,0x81,0xE6,0x7F,0xFF,0x8B,0x54,0x20,0xEB, + 0xAE,0x81,0xCE,0x80,0x00,0x8B,0x54,0x20,0xFF,0x06,0x22,0x0E, + 0xEC,0x0A,0xC0,0x79,0x7A,0x80,0x4C,0x51,0x10,0xC7,0x44,0x06, + 0xE1,0x08,0xC6,0x44,0x63,0x04,0xF6,0x44,0x51,0x04,0x74,0x08, + 0x80,0x64,0x51,0xFB,0x80,0x64,0x53,0x3F,0xF6,0x44,0x28,0x01, + 0x75,0x59,0xF6,0x44,0x28,0x02,0x75,0x4F,0x8B,0x7C,0x12,0x8C, + 0xC3,0x8E,0x44,0x10,0xF6,0x44,0x28,0x08,0x74,0x1E,0xB0,0xFF, + 0xAA,0x23,0x7C,0x16,0x3B,0x7C,0x14,0x74,0x26,0x32,0xC0,0xF6, + 0x44,0x29,0x80,0x74,0x02,0xB0,0x10,0xAA,0x23,0x7C,0x16,0x3B, + 0x7C,0x14,0x74,0x13,0x32,0xC0,0xAA,0x23,0x7C,0x16,0x3B,0x7C, + 0x14,0x74,0x08,0x8E,0xC3,0x89,0x7C,0x12,0xEB,0x15,0x90,0x8E, + 0xC3,0x4F,0x23,0x7C,0x16,0x89,0x7C,0x12,0xC6,0x44,0x59,0x01, + 0xEB,0x05,0x90,0x80,0x4C,0x4F,0x01,0xB0,0x10,0xEE,0x81,0xE6, + 0x7F,0xFF,0x8B,0x54,0x20,0xE9,0x17,0xFF,0xFF,0x06,0x1E,0x0E, + 0xE9,0x10,0xFF,0x1E,0x2E,0x8E,0x1E,0xC1,0x03,0x50,0x52,0x55, + 0x8B,0xEC,0x8B,0x46,0x08,0xA3,0x12,0x0E,0x32,0xE4,0xA0,0x22, + 0x0C,0xA3,0x10,0x0E,0xFF,0x06,0x00,0x0E,0x83,0x06,0x0E,0x0E, + 0x0A,0x83,0x3E,0x04,0x0E,0x00,0x74,0x31,0x8B,0x16,0x00,0x0E, + 0x2B,0x16,0x02,0x0E,0x3B,0x16,0x04,0x0E,0x72,0x23,0x8B,0x16, + 0x00,0x0E,0x89,0x16,0x02,0x0E,0x8B,0x16,0x18,0x0D,0x3B,0x16, + 0x1A,0x0D,0x74,0x11,0x80,0x3E,0x10,0x0C,0x01,0x74,0x16,0xB0, + 0x00,0x90,0xE6,0x00,0x0C,0x08,0x90,0xE6,0x00,0xB8,0x00,0x80, + 0xBA,0x22,0xFF,0xEF,0x5D,0x5A,0x58,0x1F,0xCF,0xB0,0x80,0xE6, + 0x00,0xA0,0x11,0x0C,0x0C,0x10,0xA2,0x11,0x0C,0xEB,0xE6,0x1E, + 0x2E,0x8E,0x1E,0xC1,0x03,0xFF,0x06,0x28,0x0E,0x55,0x8B,0xEC, + 0x8B,0x6E,0x02,0x89,0x2E,0x16,0x0E,0x5D,0x1F,0xCF,0x1E,0x2E, + 0x8E,0x1E,0xC1,0x03,0xFF,0x06,0x24,0x0E,0x55,0x8B,0xEC,0x8B, + 0x6E,0x02,0x89,0x2E,0x14,0x0E,0x5D,0x80,0x3E,0x10,0x0C,0x01, + 0x75,0x12,0x50,0xA0,0x11,0x0C,0x0C,0x01,0xA2,0x11,0x0C,0xE4, + 0x00,0x90,0x90,0x24,0x7F,0xE6,0x00,0x58,0x1F,0xCF,0x1E,0x06, + 0x60,0xB8,0x00,0x80,0xBA,0x22,0xFF,0xEF,0x2E,0x8E,0x1E,0xC1, + 0x03,0x2E,0x8E,0x06,0xC1,0x03,0x2E,0xFF,0x06,0x30,0x0D,0xFC, + 0xFF,0x26,0x2E,0x0E,0x00,0x00,0xFB,0x40,0x43,0x41,0x42,0x46, + 0x47,0x45,0xEB,0xF6,0xC3,0x00,0x00,0x8F,0x06,0x2E,0x0E,0x2E, + 0xFF,0x06,0x3D,0x0D,0xB8,0x00,0x00,0xBA,0x58,0xFF,0xEF,0xB8, + 0x00,0xE0,0xBA,0x5E,0xFF,0xEF,0x61,0x07,0x1F,0xCF,0xC2,0xFE, + 0xFF,0x8B,0x7C,0x0A,0x2B,0x7C,0x0C,0x23,0x7C,0x0E,0x3B,0x7C, + 0x18,0x77,0x2E,0xC6,0x44,0x4D,0x00,0x80,0x4C,0x4F,0x02,0xEB, + 0x5A,0x90,0x8B,0x7C,0x0A,0x3B,0x7C,0x0C,0x75,0x1B,0x8B,0x3E, + 0x10,0x0D,0x3B,0x3E,0x12,0x0D,0x75,0x53,0xF6,0x44,0x4B,0xFF, + 0x75,0x4D,0xC6,0x44,0x4C,0x00,0x80,0x4C,0x4F,0x04,0xEB,0x43, + 0x90,0xF6,0x44,0x50,0x10,0x75,0x3C,0xEB,0x09,0x90,0x8B,0x7C, + 0x0A,0x2B,0x7C,0x0C,0x74,0x31,0x80,0x4C,0x50,0x10,0x80,0x4C, + 0x4B,0x10,0xC7,0x04,0xC3,0x03,0xEB,0x23,0x90,0xFA,0x8B,0x36, + 0x08,0x0E,0x8B,0x54,0x20,0xEC,0x8A,0xF8,0x8A,0x5C,0x54,0x32, + 0xFB,0xF6,0x44,0x4D,0xFF,0x75,0x8E,0xF6,0x44,0x4C,0xFF,0x75, + 0xA1,0xF6,0x44,0x50,0x10,0x74,0xC7,0xEC,0x32,0xC3,0x22,0xF8, + 0x83,0x2E,0x10,0x0E,0x01,0x78,0x05,0xD0,0x6C,0x49,0x72,0x45, + 0x8B,0x7C,0x12,0x2B,0x7C,0x14,0x74,0x22,0x80,0x7C,0x4E,0x00, + 0x74,0x1C,0x23,0x7C,0x16,0x03,0xFF,0x3B,0x7C,0x16,0x73,0x43, + 0x8B,0x0E,0x0E,0x0E,0x2B,0x4C,0x6E,0x3B,0x4C,0x22,0x73,0x37, + 0x80,0x7C,0x49,0x00,0x74,0x31,0xF6,0x44,0x51,0x02,0x75,0x3C, + 0xEC,0x32,0xC3,0x22,0xF8,0x80,0xE7,0x38,0xFB,0x89,0x1E,0x30, + 0x0E,0xBE,0x00,0x10,0xFF,0x14,0xEB,0x61,0x90,0xB0,0x01,0xEE, + 0x8A,0x44,0x71,0x0C,0x10,0x88,0x44,0x71,0xEE,0x80,0x64,0x50, + 0xDF,0xC7,0x04,0xC3,0x03,0xEB,0xA5,0xC6,0x44,0x4E,0x00,0x8B, + 0x0E,0x0E,0x0E,0x89,0x4C,0x6E,0x80,0x4C,0x4F,0x08,0xEB,0xBE, + 0x8B,0x7C,0x12,0x2B,0x7C,0x14,0x23,0x7C,0x16,0x3B,0x7C,0x1A, + 0x73,0xB6,0x80,0x64,0x51,0xFD,0xF6,0x44,0x29,0x10,0x74,0x10, + 0x80,0x64,0x54,0xFB,0x80,0x4C,0x58,0x04,0x80,0x74,0x50,0x08, + 0xC7,0x04,0xC3,0x03,0xB0,0x05,0xEE,0xB0,0x82,0x22,0x44,0x5F, + 0x0A,0x44,0x75,0x88,0x44,0x75,0xEE,0xEB,0x8B,0xFA,0x8B,0x36, + 0x08,0x0E,0x8B,0x1E,0x30,0x0E,0x8A,0xCB,0xE5,0x80,0x23,0x44, + 0x2E,0x74,0x02,0xF6,0xD1,0x80,0xE1,0x40,0x0A,0xF9,0x8A,0xDF, + 0x22,0x5C,0x55,0x30,0x5C,0x54,0x32,0xFB,0x88,0x7C,0x55,0x0A, + 0x5C,0x58,0x88,0x5C,0x58,0x22,0x5C,0x56,0x75,0x24,0x80,0x7C, + 0x4F,0x00,0x75,0x22,0xFB,0x03,0x74,0x1E,0x89,0x36,0x08,0x0E, + 0xFF,0x06,0x26,0x0E,0x8B,0x3E,0x12,0x0D,0x3B,0x3E,0x10,0x0D, + 0x75,0x46,0xBE,0x00,0x10,0xFF,0x14,0xE9,0xD3,0xFE,0x80,0x4C, + 0x4F,0x20,0x8B,0x3E,0x18,0x0D,0x8A,0x44,0x48,0x8A,0x64,0x4F, + 0x89,0x85,0x00,0x08,0x8A,0x44,0x54,0x8A,0x64,0x57,0x89,0x85, + 0x02,0x08,0x83,0xC7,0x04,0x81,0xE7,0xFC,0x03,0x3B,0x3E,0x1A, + 0x0D,0x74,0x13,0x88,0x44,0x57,0xC6,0x44,0x4F,0x00,0x8A,0x44, + 0x56,0xF6,0xD0,0x20,0x44,0x58,0x89,0x3E,0x18,0x0D,0xEB,0xA4, + 0xFF,0x06,0x2C,0x0E,0xBE,0x00,0x10,0xFF,0x14,0xFA,0x8B,0x3E, + 0x12,0x0D,0x81,0xC7,0x00,0x04,0x8A,0x5D,0x01,0x83,0xE3,0x0F, + 0x03,0xDB,0x2E,0x8B,0xB7,0x89,0x00,0x8B,0x54,0x20,0x0B,0xD2, + 0x74,0x0D,0x8A,0x1D,0x83,0xE3,0x1F,0x03,0xDB,0xFA,0x2E,0xFF, + 0xA7,0x9C,0x0F,0xFF,0x06,0x2A,0x0E,0x8B,0x3E,0x12,0x0D,0x8B, + 0x36,0x18,0x0D,0x8B,0x9D,0x00,0x04,0x89,0x9C,0x00,0x08,0x8B, + 0x9D,0x02,0x04,0x89,0x9C,0x02,0x08,0x83,0xC6,0x04,0x81,0xE6, + 0xFC,0x03,0x3B,0x36,0x1A,0x0D,0x74,0x04,0x89,0x36,0x18,0x0D, + 0xFB,0x8B,0x3E,0x12,0x0D,0x83,0xC7,0x04,0x81,0xE7,0xFC,0x03, + 0x89,0x3E,0x12,0x0D,0xBE,0x00,0x10,0xFF,0x14,0xE9,0x1D,0xFE, + 0xDC,0x0F,0xE4,0x0F,0xEC,0x0F,0x0D,0x10,0x1C,0x10,0x57,0x0F, + 0x2F,0x10,0x57,0x0F,0x3B,0x10,0x54,0x10,0x83,0x10,0xCF,0x10, + 0xDB,0x10,0xE4,0x10,0xEB,0x10,0x35,0x11,0x7D,0x11,0x83,0x11, + 0xA1,0x11,0xB9,0x11,0xF2,0x11,0x38,0x12,0x03,0x13,0x0C,0x13, + 0x57,0x0F,0x57,0x0F,0x57,0x0F,0x57,0x0F,0x57,0x0F,0x57,0x0F, + 0x57,0x0F,0x57,0x0F,0x8B,0x45,0x02,0x89,0x44,0x1A,0xEB,0xA0, + 0x8B,0x45,0x02,0x89,0x44,0x1C,0xEB,0x98,0x8B,0x45,0x02,0x8B, + 0x5C,0x0A,0x2B,0x5C,0x0C,0x23,0x5C,0x0E,0x8B,0x4C,0x0A,0x2B, + 0xC8,0x23,0x4C,0x0E,0x3B,0xD9,0x76,0x06,0x23,0x44,0x0E,0x89, + 0x44,0x0C,0xE9,0x77,0xFF,0x80,0x4C,0x53,0x80,0x80,0x4C,0x54, + 0x01,0x80,0x4C,0x58,0x01,0xE9,0x68,0xFF,0x80,0x64,0x53,0x3F, + 0x80,0x64,0x54,0xFE,0x80,0x4C,0x58,0x01,0x80,0x64,0x51,0xFB, + 0xE9,0x55,0xFF,0x8B,0x45,0x02,0x88,0x44,0x5A,0x88,0x64,0x5B, + 0xE9,0x49,0xFF,0x8B,0x45,0x02,0x0B,0xC0,0x74,0x03,0x89,0x44, + 0x24,0x80,0x4C,0x50,0x04,0x80,0x4C,0x4B,0x04,0xC7,0x04,0xC3, + 0x03,0xE9,0x30,0xFF,0x8B,0x5D,0x02,0xF6,0xD7,0x22,0x7C,0x54, + 0x0A,0xDF,0x8A,0x44,0x54,0x32,0xC3,0x24,0x82,0x30,0x44,0x54, + 0xB0,0x05,0xEE,0x8A,0x44,0x75,0x32,0xD8,0x8A,0x7C,0x5F,0xF6, + 0xD7,0x22,0xDF,0x80,0xE3,0x82,0x32,0xC3,0x88,0x44,0x75,0xEE, + 0xE9,0x01,0xFF,0x8B,0x5D,0x02,0xF6,0xC7,0x04,0x75,0x08,0x80, + 0x64,0x53,0x3F,0x80,0x64,0x51,0xFB,0x8A,0x44,0x29,0x32,0xC7, + 0xA8,0x10,0x74,0x0E,0xF6,0x44,0x51,0x02,0x74,0x08,0x80,0x74, + 0x50,0x08,0xC7,0x04,0xC3,0x03,0x88,0x5C,0x28,0x88,0x7C,0x29, + 0xB4,0x60,0xF6,0xC3,0x10,0x74,0x03,0x80,0xCC,0x10,0x8A,0x44, + 0x62,0xF6,0xC3,0x20,0x74,0x02,0x24,0x7F,0x89,0x44,0x34,0xC7, + 0x44,0x06,0xE1,0x08,0xE9,0xB5,0xFE,0x8B,0x45,0x02,0x88,0x44, + 0x5C,0x88,0x64,0x5D,0xE9,0xA9,0xFE,0x8B,0x45,0x02,0x89,0x44, + 0x18,0xE9,0xA0,0xFE,0xFF,0x1E,0x24,0x0D,0xE9,0x99,0xFE,0xF6, + 0x44,0x51,0x02,0x75,0x41,0x8B,0x44,0x12,0x2B,0x44,0x14,0x23, + 0x44,0x16,0x3B,0x44,0x1A,0x72,0x33,0x80,0x4C,0x51,0x02,0xF6, + 0x44,0x29,0x10,0x74,0x10,0x80,0x4C,0x54,0x04,0x80,0x4C,0x58, + 0x04,0x80,0x74,0x50,0x08,0xC7,0x04,0xC3,0x03,0xF6,0x44,0x5F, + 0x82,0x74,0x13,0xB0,0x05,0xEE,0x8A,0x44,0x75,0xB4,0x82,0x22, + 0x64,0x5F,0xF6,0xD4,0x22,0xC4,0x88,0x44,0x75,0xEE,0xE9,0x4F, + 0xFE,0xF6,0x44,0x51,0x02,0x74,0x3F,0x8B,0x44,0x12,0x2B,0x44, + 0x14,0x23,0x44,0x16,0x3B,0x44,0x1C,0x73,0xE9,0x80,0x64,0x51, + 0xFD,0xF6,0x44,0x29,0x10,0x74,0x10,0x80,0x64,0x54,0xFB,0x80, + 0x4C,0x58,0x04,0x80,0x74,0x50,0x08,0xC7,0x04,0xC3,0x03,0xF6, + 0x44,0x5F,0x02,0x74,0x11,0xB0,0x05,0xEE,0x8A,0x44,0x75,0xB4, + 0x82,0x22,0x64,0x5F,0x0A,0xC4,0x88,0x44,0x75,0xEE,0xE9,0x07, + 0xFE,0xE8,0x8A,0x02,0xE9,0x01,0xFE,0x8B,0x45,0x02,0xBB,0x10, + 0x27,0xF7,0xE3,0xBB,0x0F,0x00,0xF7,0xF3,0xA3,0x06,0x0E,0xBA, + 0x52,0xFF,0xEF,0xBA,0x50,0xFF,0xB8,0x00,0x00,0xEF,0xE9,0xE3, + 0xFD,0x8B,0x45,0x02,0x3A,0x06,0x22,0x0C,0x72,0x0C,0x3B,0x06, + 0x1A,0x0C,0x77,0x06,0xE8,0xAB,0x01,0xE9,0xCE,0xFD,0xE9,0x9E, + 0xFD,0x8B,0x45,0x02,0x88,0x44,0x2A,0x88,0x64,0x2B,0x0B,0xC0, + 0x75,0x07,0x80,0x64,0x50,0xFE,0xEB,0x10,0x90,0xF6,0x44,0x50, + 0x01,0x75,0x09,0x80,0x4C,0x50,0x01,0xC7,0x44,0x30,0x00,0x00, + 0xA8,0x80,0x75,0x07,0xC6,0x44,0x60,0x00,0xEB,0x05,0x90,0xC6, + 0x44,0x60,0x7F,0xC7,0x04,0xC3,0x03,0xE9,0x92,0xFD,0x8B,0x5D, + 0x02,0xF6,0xD7,0x22,0x7C,0x5F,0x0A,0xDF,0x8A,0xFB,0x88,0x5C, + 0x5F,0x8A,0x44,0x52,0x8A,0x64,0x53,0x8B,0xCB,0x33,0xC8,0x81, + 0xE1,0x38,0x38,0x33,0xC1,0x88,0x44,0x52,0x88,0x64,0x53,0xB0, + 0x05,0xEE,0xF6,0xD3,0x22,0x5C,0x54,0xF6,0x44,0x51,0x02,0x75, + 0x02,0x0A,0xDF,0x8A,0x44,0x75,0x32,0xD8,0x80,0xE3,0x82,0x32, + 0xC3,0x88,0x44,0x75,0xEE,0xE9,0x4C,0xFD,0x8B,0x5D,0x02,0x88, + 0x5C,0x2C,0x88,0x7C,0x2D,0x8B,0xCB,0x83,0xE3,0x0F,0x03,0xDB, + 0x80,0x3E,0x10,0x0C,0x01,0x75,0x1F,0xA1,0x0E,0x0C,0x86,0xE0, + 0x3D,0x32,0x31,0x73,0x15,0xF6,0xC5,0x04,0x75,0x08,0x2E,0x8B, + 0x9F,0x69,0x01,0xEB,0x1B,0x90,0x2E,0x8B,0x9F,0x89,0x01,0xEB, + 0x13,0x90,0xF6,0xC5,0x04,0x75,0x08,0x2E,0x8B,0x9F,0x29,0x01, + 0xEB,0x06,0x90,0x2E,0x8B,0x9F,0x49,0x01,0xB0,0x0C,0xEE,0x8A, + 0xC3,0x88,0x44,0x7C,0xEE,0xB0,0x0D,0x90,0x90,0xEE,0x8A,0xC7, + 0x88,0x44,0x7D,0xEE,0xB0,0x04,0xEE,0xB0,0x44,0xF6,0xC1,0x40, + 0x74,0x0C,0xF6,0xC1,0x80,0x74,0x05,0x04,0x04,0xEB,0x03,0x90, + 0x0C,0x08,0xF6,0xC5,0x01,0x74,0x09,0x0C,0x01,0xF6,0xC5,0x02, + 0x75,0x02,0x0C,0x02,0x88,0x44,0x74,0xEE,0xB0,0x03,0x90,0x90, + 0xEE,0x8A,0xD9,0x80,0xE3,0x30,0xC0,0xEB,0x04,0x32,0xFF,0x2E, + 0x8A,0xA7,0xA9,0x01,0x8A,0x44,0x73,0x24,0x3F,0x0A,0xC4,0x88, + 0x44,0x73,0xEE,0x90,0x90,0xB0,0x05,0xEE,0xD0,0xEC,0x8A,0x44, + 0x75,0x24,0x9F,0x0A,0xC4,0x88,0x44,0x75,0xEE,0x2E,0x8A,0x87, + 0xAD,0x01,0x88,0x44,0x62,0xF6,0x44,0x28,0x20,0x74,0x02,0x24, + 0x7F,0x88,0x44,0x34,0xE9,0x81,0xFC,0x8A,0x45,0x02,0x88,0x44, + 0x5E,0xE9,0x78,0xFC,0x8B,0x45,0x02,0xBA,0x5A,0xFF,0xEF,0x9C, + 0xFF,0x36,0x26,0x0D,0xFF,0x36,0x24,0x0D,0x1E,0x06,0x60,0x8B, + 0x36,0x0A,0x0E,0xC7,0x04,0x3F,0x0D,0xE9,0x5A,0xFC,0xB8,0x00, + 0x00,0x8E,0xC0,0x8B,0xF0,0x8B,0xF8,0x2E,0x8B,0x9C,0x49,0x00, + 0x83,0xC6,0x02,0x26,0x89,0x1D,0x26,0x8C,0x4D,0x02,0x83,0xC7, + 0x04,0x81,0xFF,0x80,0x00,0x72,0xE8,0x26,0xC7,0x05,0xCB,0x0C, + 0x26,0x8C,0x4D,0x02,0x83,0xC7,0x04,0x81,0xFF,0x00,0x04,0x72, + 0xEE,0xC3,0xC1,0xE0,0x06,0x8B,0xD8,0x8C,0xDA,0x81,0xC2,0x00, + 0x04,0x8B,0xFA,0x8A,0x0E,0x22,0x0C,0xB5,0x00,0xBE,0x00,0x10, + 0x33,0xC0,0x89,0x44,0x0A,0x89,0x44,0x0C,0x89,0x44,0x12,0x89, + 0x44,0x14,0x81,0xC6,0x80,0x00,0xE2,0xEE,0x89,0x36,0x0A,0x0E, + 0xB8,0x01,0x00,0x8B,0xD0,0xB3,0x00,0x8A,0x0E,0x22,0x0C,0xB5, + 0x00,0xBE,0x00,0x10,0x2B,0xDA,0x72,0x29,0x89,0x44,0x16,0x81, + 0xC6,0x80,0x00,0xE2,0xF3,0x8A,0x0E,0x22,0x0C,0xB5,0x00,0xBE, + 0x00,0x10,0x2B,0xDA,0x72,0x13,0x89,0x44,0x0E,0x81,0xC6,0x80, + 0x00,0xE2,0xF3,0x8B,0xD0,0x03,0xC0,0x81,0xFA,0x00,0x02,0x72, + 0xCA,0x8A,0x0E,0x22,0x0C,0xB5,0x00,0xBE,0x00,0x10,0x89,0x7C, + 0x10,0x8B,0x44,0x16,0x03,0xF8,0x8B,0xD7,0xC1,0xE0,0x04,0x48, + 0x89,0x44,0x16,0x81,0xC6,0x80,0x00,0xE2,0xE9,0x8A,0x0E,0x22, + 0x0C,0xB5,0x00,0xBE,0x00,0x10,0x89,0x7C,0x08,0x8B,0x44,0x0E, + 0x03,0xF8,0x8B,0xD7,0xC1,0xE0,0x04,0x48,0x89,0x44,0x0E,0x81, + 0xC6,0x80,0x00,0xE2,0xE9,0xC3,0xC7,0x04,0x20,0x04,0xC7,0x44, + 0x06,0xE1,0x08,0x8B,0xC6,0x2D,0x00,0x10,0xB1,0x80,0xF6,0xF1, + 0x88,0x44,0x48,0xC7,0x44,0x0A,0x00,0x00,0xC7,0x44,0x0C,0x00, + 0x00,0xC7,0x44,0x12,0x00,0x00,0xC7,0x44,0x14,0x00,0x00,0xC7, + 0x44,0x18,0x00,0x00,0xC7,0x44,0x1A,0x00,0x00,0xC7,0x44,0x1C, + 0xFF,0xFF,0x8A,0x5C,0x48,0x83,0xE3,0x0F,0x03,0xDB,0x8B,0x97, + 0x90,0x0C,0x89,0x54,0x20,0xB8,0x01,0x00,0x8A,0x4C,0x48,0xD3, + 0xE0,0x89,0x44,0x2E,0xC7,0x44,0x24,0x19,0x00,0xC7,0x44,0x26, + 0x00,0x00,0xC6,0x44,0x4A,0x00,0xC7,0x44,0x30,0x00,0x00,0xC7, + 0x44,0x32,0x00,0x00,0xC6,0x44,0x4C,0x00,0xC6,0x44,0x4D,0x00, + 0xC6,0x44,0x4E,0x00,0xC6,0x44,0x4F,0x00,0xC6,0x44,0x50,0x00, + 0xC6,0x44,0x4B,0x00,0xC6,0x44,0x51,0x00,0xC6,0x44,0x28,0x00, + 0xC6,0x44,0x29,0x00,0xC6,0x44,0x2A,0x00,0xC6,0x44,0x2B,0x00, + 0xC6,0x44,0x54,0x00,0xC6,0x44,0x57,0x00,0xC6,0x44,0x55,0x00, + 0xC6,0x44,0x56,0x00,0xC6,0x44,0x58,0x00,0xC6,0x44,0x52,0x04, + 0xC6,0x44,0x53,0x04,0xC6,0x44,0x5F,0x00,0xC6,0x44,0x2C,0x3D, + 0xC6,0x44,0x2D,0x00,0xC7,0x44,0x34,0xFF,0x60,0xC6,0x44,0x62, + 0xFF,0xC6,0x44,0x5D,0x13,0xC6,0x44,0x5C,0x11,0xC6,0x44,0x5E, + 0x00,0xC6,0x44,0x60,0x23,0xC6,0x44,0x61,0x23,0x0B,0xD2,0x75, + 0x03,0xE9,0xD9,0x00,0xB0,0x09,0xEE,0x8A,0x4C,0x48,0xB0,0x80, + 0xD2,0xE8,0xEE,0xC6,0x44,0x70,0x00,0xB0,0x01,0xEE,0xB0,0x11, + 0x88,0x44,0x71,0xEE,0xB0,0x02,0x90,0x90,0xEE,0x8A,0x44,0x48, + 0xC0,0xE0,0x03,0x24,0xF0,0x88,0x44,0x72,0xEE,0xB0,0x03,0x90, + 0x90,0xEE,0xB0,0xC0,0x88,0x44,0x73,0xEE,0xB0,0x04,0x90,0x90, + 0xEE,0xB0,0x44,0x88,0x44,0x74,0xEE,0xB0,0x05,0x90,0xEE,0xB0, + 0x60,0x88,0x44,0x75,0xEE,0xC6,0x44,0x76,0x00,0xC6,0x44,0x77, + 0x00,0xC6,0x44,0x78,0x00,0xB0,0x09,0xEE,0xB0,0x09,0x88,0x44, + 0x79,0xEE,0xC6,0x44,0x7A,0x00,0xB0,0x0B,0xEE,0xB0,0x52,0x88, + 0x44,0x7B,0xEE,0x80,0x3E,0x10,0x0C,0x01,0x75,0x21,0xA1,0x0E, + 0x0C,0x86,0xE0,0x3D,0x32,0x31,0x73,0x17,0xB0,0x0C,0xEE,0xB0, + 0x18,0x88,0x44,0x7C,0xEE,0xB0,0x0D,0x90,0x90,0xEE,0xB0,0x00, + 0x88,0x44,0x7D,0xEE,0xEB,0x15,0x90,0xB0,0x0C,0xEE,0xB0,0x16, + 0x88,0x44,0x7C,0xEE,0xB0,0x0D,0x90,0x90,0xEE,0xB0,0x00,0x88, + 0x44,0x7D,0xEE,0xB0,0x0E,0x90,0x90,0xEE,0xB0,0x03,0x88,0x44, + 0x7E,0xEE,0xB0,0x0F,0x90,0x90,0xEE,0xB0,0x80,0x88,0x44,0x7F, + 0xEE,0xB0,0x03,0x90,0x90,0xEE,0x8A,0x44,0x73,0x0C,0x01,0x88, + 0x44,0x73,0xEE,0x90,0x90,0xB0,0x05,0xEE,0x8A,0x44,0x75,0x0C, + 0x08,0x88,0x44,0x75,0xEE,0xC3,0xFA,0x8C,0xD8,0x25,0x00,0xF0, + 0x8E,0xD0,0xBC,0xFE,0x1F,0x8C,0xD8,0x25,0x00,0xF0,0x8E,0xD8, + 0x80,0x3E,0x40,0x0D,0x01,0x75,0x51,0xA1,0x0E,0x0C,0x86,0xE0, + 0x3D,0x30,0x32,0x73,0x47,0x8B,0x1E,0x20,0x0C,0x8A,0x16,0x23, + 0x0C,0xC6,0x06,0x23,0x0C,0x00,0x83,0xFB,0x00,0x74,0x07,0xFE, + 0xCA,0xC6,0x06,0x23,0x0C,0x01,0x88,0x16,0x22,0x0C,0xBE,0x10, + 0x0C,0xBF,0x90,0x0C,0xB9,0x08,0x00,0x1E,0x07,0xFC,0xF3,0xA5, + 0xBF,0xA0,0x0C,0xB8,0x00,0x00,0xB9,0x08,0x00,0xF3,0xAB,0xC7, + 0x06,0x1A,0x0C,0x70,0x00,0xA0,0x40,0x0D,0xA2,0x10,0x0C,0xC6, + 0x06,0x11,0x0C,0x00,0x2E,0x8C,0x1E,0xC1,0x03,0xC7,0x06,0x18, + 0x0E,0x02,0x00,0xE8,0xEC,0xFC,0xC7,0x06,0x24,0x0D,0x5A,0x0D, + 0x8C,0x0E,0x26,0x0D,0xC7,0x06,0x18,0x0E,0x06,0x00,0xA1,0x1A, + 0x0C,0xE8,0x0A,0xFD,0xC7,0x06,0x18,0x0E,0x0A,0x00,0xBE,0x00, + 0x10,0xC7,0x44,0x1E,0x80,0x00,0xE8,0xA5,0xFD,0x81,0xC6,0x80, + 0x00,0x81,0xFE,0x00,0x18,0x72,0xEE,0xA0,0x22,0x0C,0xB4,0x80, + 0xF6,0xE4,0xBE,0x00,0x10,0x03,0xF0,0x89,0x36,0x0A,0x0E,0x29, + 0x44,0x9E,0xC7,0x06,0x00,0x0E,0x00,0x00,0xC7,0x06,0x02,0x0E, + 0x00,0x00,0xC7,0x06,0x04,0x0E,0x00,0x00,0xC7,0x06,0x06,0x0E, + 0x9A,0x02,0xBA,0x52,0xFF,0xA1,0x06,0x0E,0xEF,0xBA,0x50,0xFF, + 0xB8,0x00,0x00,0xEF,0xBA,0x56,0xFF,0xB8,0x05,0xE0,0xEF,0xBA, + 0x5E,0xFF,0xB8,0x00,0x40,0xEF,0xBA,0x66,0xFF,0xB8,0x00,0x40, + 0xEF,0xC7,0x06,0x10,0x0D,0x00,0x00,0xC7,0x06,0x12,0x0D,0x00, + 0x00,0xC7,0x06,0x14,0x0D,0x00,0x04,0xC7,0x06,0x16,0x0D,0xFC, + 0x03,0xC7,0x06,0x18,0x0D,0x00,0x00,0xC7,0x06,0x1A,0x0D,0x00, + 0x00,0xC7,0x06,0x1C,0x0D,0x00,0x08,0xC7,0x06,0x1E,0x0D,0xFC, + 0x03,0xB0,0x00,0x90,0xE6,0x00,0xC7,0x06,0x18,0x0E,0x32,0x00, + 0xBA,0x38,0xFF,0xB8,0x11,0x00,0xEF,0xBA,0x3A,0xFF,0xB8,0x08, + 0x00,0xEF,0xBA,0x3C,0xFF,0xB8,0x08,0x00,0xEF,0xBA,0x3E,0xFF, + 0xB8,0x08,0x00,0x80,0x3E,0x22,0x0C,0x08,0x76,0x03,0xB8,0x12, + 0x00,0xEF,0xBA,0x32,0xFF,0xB8,0x05,0x00,0xEF,0xBA,0x28,0xFF, + 0xB8,0x6C,0x00,0xEF,0xBA,0x22,0xFF,0xB8,0x00,0x80,0xEF,0xC7, + 0x06,0x18,0x0E,0x33,0x00,0xC7,0x06,0x20,0x0D,0x4F,0x00,0xC7, + 0x06,0x21,0x0D,0x53,0x00,0x8B,0x36,0x0A,0x0E,0xC7,0x04,0x3C, + 0x0D,0xC7,0x06,0x08,0x0E,0x00,0x10,0xE9,0x63,0xF6,0x40,0x28, + 0x23,0x29,0x20,0x24,0x49,0x64,0x3A,0x20,0x78,0x61,0x63,0x6F, + 0x6F,0x6B,0x2E,0x61,0x73,0x6D,0x2C,0x76,0x20,0x37,0x2E,0x32, + 0x35,0x20,0x31,0x39,0x39,0x35,0x2F,0x30,0x31,0x2F,0x31,0x32, + 0x20,0x32,0x30,0x3A,0x35,0x39,0x3A,0x32,0x31,0x20,0x6D,0x69, + 0x6C,0x74,0x20,0x45,0x78,0x70,0x20,0x24,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 +}; + +static unsigned pcxx_ncook=sizeof(pcxx_cook); diff --git a/sys/gnu/i386/isa/dgreg.h b/sys/gnu/i386/isa/dgreg.h new file mode 100644 index 0000000000000..3c322133d43ef --- /dev/null +++ b/sys/gnu/i386/isa/dgreg.h @@ -0,0 +1,366 @@ +/*- + * dgreg.h $Id: dgreg.h,v 1.4 1995/07/13 08:07:46 root Exp root $ + * + * Copyright (C) 1995 by Serge Babkin <babkin@hq.icb.chel.su> + * + * Digiboard driver. + * + * Stage 1. "Better than nothing". + * + * Based on sio driver by Bruce Evans and on Linux driver by Troy + * De Jongh <troyd@digibd.com> or <troyd@skypoint.com> + * which is under GNU General Public License version 2 so this driver + * is forced to be under GPL 2 too. + * + * Serge Babkin does not guarantee that this file is totally correct + * for any given task and users of this file must accept responsibility + * for any damage that occurs from the application of this file. + * + * Written by Serge Babkin, + * Joint Stock Commercial Bank "Chelindbank" + * (Chelyabinsk, Russia) + * babkin@hq.icb.chel.su + */ + +#define DEBUG + +#define MAX_DGB_PORTS 32 + +/* digi.h */ +/* Definitions for DigiBoard ditty(1) command. */ + +#if !defined(TIOCMODG) +#define TIOCMODG ('d'<<8) | 250 /* get modem ctrl state */ +#define TIOCMODS ('d'<<8) | 251 /* set modem ctrl state */ +#endif + +#if !defined(TIOCMSET) +#define TIOCMSET ('d'<<8) | 252 /* set modem ctrl state */ +#define TIOCMGET ('d'<<8) | 253 /* set modem ctrl state */ +#endif + +#if !defined(TIOCMBIC) +#define TIOCMBIC ('d'<<8) | 254 /* set modem ctrl state */ +#define TIOCMBIS ('d'<<8) | 255 /* set modem ctrl state */ +#endif + +#if !defined(TIOCSDTR) +#define TIOCSDTR ('e'<<8) | 0 /* set DTR */ +#define TIOCCDTR ('e'<<8) | 1 /* clear DTR */ +#endif + +/************************************************************************ + * Ioctl command arguments for DIGI parameters. + ************************************************************************/ +#define DIGI_GETA ('e'<<8) | 94 /* Read params */ + +#define DIGI_SETA ('e'<<8) | 95 /* Set params */ +#define DIGI_SETAW ('e'<<8) | 96 /* Drain & set params */ +#define DIGI_SETAF ('e'<<8) | 97 /* Drain, flush & set params */ + +#define DIGI_GETFLOW ('e'<<8) | 99 /* Get startc/stopc flow */ + /* control characters */ +#define DIGI_SETFLOW ('e'<<8) | 100 /* Set startc/stopc flow */ + /* control characters */ +#define DIGI_GETAFLOW ('e'<<8) | 101 /* Get Aux. startc/stopc */ + /* flow control chars */ +#define DIGI_SETAFLOW ('e'<<8) | 102 /* Set Aux. startc/stopc */ + /* flow control chars */ + +struct digiflow_struct { + unsigned char startc; /* flow cntl start char */ + unsigned char stopc; /* flow cntl stop char */ +}; + +typedef struct digiflow_struct digiflow_t; + + +/************************************************************************ + * Values for digi_flags + ************************************************************************/ +#define DIGI_IXON 0x0001 /* Handle IXON in the FEP */ +#define DIGI_FAST 0x0002 /* Fast baud rates */ +#define RTSPACE 0x0004 /* RTS input flow control */ +#define CTSPACE 0x0008 /* CTS output flow control */ +#define DSRPACE 0x0010 /* DSR output flow control */ +#define DCDPACE 0x0020 /* DCD output flow control */ +#define DTRPACE 0x0040 /* DTR input flow control */ +#define DIGI_FORCEDCD 0x0100 /* Force carrier */ +#define DIGI_ALTPIN 0x0200 /* Alternate RJ-45 pin config */ +#define DIGI_AIXON 0x0400 /* Aux flow control in fep */ + + +/************************************************************************ + * Structure used with ioctl commands for DIGI parameters. + ************************************************************************/ +struct digi_struct { + unsigned short digi_flags; /* Flags (see above) */ +}; + +typedef struct digi_struct digi_t; + +/* fep.h */ + +#define FEP_CSTART 0x400L +#define FEP_CMAX 0x800L +#define FEP_ISTART 0x800L +#define FEP_IMAX 0xC00L +#define FEP_CIN 0xD10L +#define FEP_GLOBAL 0xD10L +#define FEP_EIN 0xD18L +#define FEPSTAT 0xD20L +#define CHANSTRUCT 0x1000L +#define RXTXBUF 0x4000L + + +struct global_data { + volatile ushort cin; + volatile ushort cout; + volatile ushort cstart; + volatile ushort cmax; + volatile ushort ein; + volatile ushort eout; + volatile ushort istart; + volatile ushort imax; +}; + + +struct board_chan { + int filler1; + int filler2; + volatile ushort tseg; + volatile ushort tin; + volatile ushort tout; + volatile ushort tmax; + + volatile ushort rseg; + volatile ushort rin; + volatile ushort rout; + volatile ushort rmax; + + volatile ushort tlow; + volatile ushort rlow; + volatile ushort rhigh; + volatile ushort incr; + + volatile ushort etime; + volatile ushort edelay; + volatile u_char *dev; + + volatile ushort iflag; + volatile ushort oflag; + volatile ushort cflag; + volatile ushort gmask; + + volatile ushort col; + volatile ushort delay; + volatile ushort imask; + volatile ushort tflush; + + int filler3; + int filler4; + int filler5; + int filler6; + + volatile u_char num; + volatile u_char ract; + volatile u_char bstat; + volatile u_char tbusy; + volatile u_char iempty; + volatile u_char ilow; + volatile u_char idata; + volatile u_char eflag; + + volatile u_char tflag; + volatile u_char rflag; + volatile u_char xmask; + volatile u_char xval; + volatile u_char mstat; + volatile u_char mchange; + volatile u_char mint; + volatile u_char lstat; + + volatile u_char mtran; + volatile u_char orun; + volatile u_char startca; + volatile u_char stopca; + volatile u_char startc; + volatile u_char stopc; + volatile u_char vnext; + volatile u_char hflow; + + volatile u_char fillc; + volatile u_char ochar; + volatile u_char omask; + + u_char filler7; + u_char filler8[28]; +}; + + +#define SRXLWATER 0xE0 +#define SRXHWATER 0xE1 +#define STOUT 0xE2 +#define PAUSETX 0xE3 +#define RESUMETX 0xE4 +#define SAUXONOFFC 0xE6 +#define SENDBREAK 0xE8 +#define SETMODEM 0xE9 +#define SETIFLAGS 0xEA +#define SONOFFC 0xEB +#define STXLWATER 0xEC +#define PAUSERX 0xEE +#define RESUMERX 0xEF +#define SETBUFFER 0xF2 +#define SETCOOKED 0xF3 +#define SETHFLOW 0xF4 +#define SETCTRLFLAGS 0xF5 +#define SETVNEXT 0xF6 + + + +#define BREAK_IND 0x01 +#define LOWTX_IND 0x02 +#define EMPTYTX_IND 0x04 +#define DATA_IND 0x08 +#define MODEMCHG_IND 0x20 + +#define ALL_IND (BREAK_IND|LOWTX_IND|EMPTYTX_IND|DATA_IND|MODEMCHG_IND) + + +#define RTS 0x02 +#define CD 0x08 +#define DSR 0x10 +#define CTS 0x20 +#define RI 0x40 +#define DTR 0x80 + +/* pcxx.h */ + +#define FEPCODESEG 0x0200L +#define FEPCODE 0x2000L +#define BIOSCODE 0xf800L + +#define MISCGLOBAL 0x0C00L +#define NPORT 0x0C22L +#define MBOX 0x0C40L +#define PORTBASE 0x0C90L +#define BOTWIN 0x100L +#define TOPWIN 0xFF00L + +#define FEPCLR 0x00 +#define FEPMEM 0x02 +#define FEPRST 0x04 +#define FEPINT 0x08 +#define FEPMASK 0x0e +#define FEPWIN 0x80 + +#define PCXI 0 +#define PCXE 1 +#define PCXEVE 2 + +static char *board_desc[] = { + "PC/Xi (64K)", + "PC/Xe (64K)", + "PC/Xe (8K) ", +}; + +#define STARTC 021 +#define STOPC 023 +#define IAIXON 0x2000 + + +struct board_info { + u_char status; + u_char type; + u_char altpin; + ushort numports; + ushort port; + u_long membase; +}; + + +#define TXSTOPPED 0x1 +#define LOWWAIT 0x2 +#define EMPTYWAIT 0x4 + +#define DISABLED 0 +#define ENABLED 1 +#define OFF 0 +#define ON 1 + +#define FEPTIMEOUT 200000 +#define SERIAL_TYPE_NORMAL 1 +#define SERIAL_TYPE_CALLOUT 2 +#define PCXE_EVENT_HANGUP 1 + +struct channel { + u_char unit; /* board unit number */ + u_char omodem; /* FEP output modem status */ + u_char imodem; /* FEP input modem status */ + u_char modemfake; /* Modem values to be forced */ + u_char modem; /* Force values */ + u_char hflow; + u_char dsr; + u_char dcd; + u_char stopc; + u_char startc; + u_char stopca; + u_char startca; + u_char fepstopc; + u_char fepstartc; + u_char fepstopca; + u_char fepstartca; + u_char txwin; + u_char rxwin; + ushort fepiflag; + ushort fepcflag; + ushort fepoflag; + ushort txbufhead; + ushort txbufsize; + ushort rxbufhead; + ushort rxbufsize; + int close_delay; + int count; + int blocked_open; + int event; + int asyncflags; + uint dev; + long session; + long pgrp; + u_long statusflags; + u_long c_iflag; + u_long c_cflag; + u_long c_lflag; + u_long c_oflag; + u_char *txptr; + u_char *rxptr; + struct board_info *board; + struct board_chan *brdchan; + struct digi_struct digiext; + struct tty *tty; + struct termios normal_termios; + struct termios callout_termios; + volatile struct global_data *mailbox; +}; + +/* flags for configuring */ + +#define DGBFLAG_ALTPIN 0x0001 /* chande DCD and DCD */ +#define DGBFLAG_NOWIN 0x0002 /* use windowed PC/Xe as non-windowed */ + +/* debugging printout */ + +#ifdef DEBUG +# define DPRINT1(a1) (dgbdebug ? printf(a1) : 0) +# define DPRINT2(a1,a2) (dgbdebug ? printf(a1,a2) : 0) +# define DPRINT3(a1,a2,a3) (dgbdebug ? printf(a1,a2,a3) : 0) +# define DPRINT4(a1,a2,a3,a4) (dgbdebug ? printf(a1,a2,a3,a4) : 0) +# define DPRINT5(a1,a2,a3,a4,a5) (dgbdebug ? printf(a1,a2,a3,a4,a5) : 0) +#else +# define DPRINT1(a1) +# define DPRINT2(a1,a2) +# define DPRINT3(a1,a2,a3) +# define DPRINT4(a1,a2,a3,a4) +# define DPRINT5(a1,a2,a3,a4,a5) +#endif diff --git a/sys/i386/include/asc_ioctl.h b/sys/i386/include/asc_ioctl.h new file mode 100644 index 0000000000000..6d33429933301 --- /dev/null +++ b/sys/i386/include/asc_ioctl.h @@ -0,0 +1,52 @@ +/* asc.h - programming interface to the scanner device driver `asc' + * + * + * Copyright (c) 1995 Gunther Schadow. All rights reserved. + * + * 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 above copyright + * notice, this list of conditions and the following disclaimer. + * 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 Gunther Schadow. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. + */ + +#ifndef _I386_ASC_IOCTL_H_ +#define _I386_ASC_IOCTL_H_ + +#include <sys/types.h> +#include <sys/ioctl.h> + +#define ASC_GRES _IOR('S', 1, int) /* get resolution / dpi */ +#define ASC_SRES _IOW('S', 2, int) /* set resolution / dpi */ +#define ASC_GWIDTH _IOR('S', 3, int) /* get width / pixels */ +#define ASC_SWIDTH _IOW('S', 4, int) /* set width / pixels */ +#define ASC_GHEIGHT _IOR('S', 5, int) /* get height / pixels */ +#define ASC_SHEIGHT _IOW('S', 6, int) /* set height / pixels */ + +#define ASC_GBLEN _IOR('S', 7, int) /* get buffer length / lines */ +#define ASC_SBLEN _IOW('S', 8, int) /* set buffer length / lines */ +#define ASC_GBTIME _IOR('S', 9, int) /* get buffer timeout / s */ +#define ASC_SBTIME _IOW('S', 10, int) /* set buffer timeout / s */ + +#define ASC_SRESSW _IO('S', 11) /* set resolution by switch */ + +#endif diff --git a/sys/i386/include/si.h b/sys/i386/include/si.h new file mode 100644 index 0000000000000..9770fb63eb52e --- /dev/null +++ b/sys/i386/include/si.h @@ -0,0 +1,525 @@ +/* + * Device driver for Specialix range (SLXOS) of serial line multiplexors. + * 'C' definitions for Specialix serial multiplex driver. + * + * Copyright (C) 1990, 1992 Specialix International, + * Copyright (C) 1993, Andy Rutter <andy@acronym.co.uk> + * Copyright (C) 1995, Peter Wemm <peter@haywire.dialix.com> + * + * Derived from: SunOS 4.x version + * + * 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 above copyright + * notices, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notices, 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 Andy Rutter of + * Advanced Methods and Tools Ltd. based on original information + * from Specialix International. + * 4. Neither the name of Advanced Methods and Tools, nor Specialix + * International may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ``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 THE AUTHORS BE LIABLE. + * + * $Id: si.h,v 1.3 1995/08/22 00:42:07 peter Exp $ + */ + +/* + * Macro to turn a device number into various parameters, and test for + * CONTROL device. + * max of 4 controllers with up to 32 ports per controller. + * minor device allocation is: + * adapter port + * 0 0-31 + * 1 32-63 + * 2 64-95 + * 3 96-127 + */ +#define SI_MAXPORTPERCARD 32 +#define SI_MAXCONTROLLER 4 + + +/* + * breakup of minor device number: + * lowest 5 bits: port number on card 0x1f + * next 2 bits: card number 0x60 + * top bit: callout 0x80 + * next 8 bits is the major number + * next 2 bits select initial/lock states + * next 1 bit selects the master control device + */ + +#define SI_PORT_MASK 0x1f +#define SI_CARD_MASK 0x60 +#define SI_TTY_MASK 0x7f +#define SI_CALLOUT_MASK 0x80 +#define SI_INIT_STATE_MASK 0x10000 +#define SI_LOCK_STATE_MASK 0x20000 +#define SI_STATE_MASK 0x30000 +#define SI_CONTROLDEV_MASK 0x40000 +#define SI_SPECIAL_MASK 0x70000 + +#define SI_PORT(m) (m & SI_PORT_MASK) +#define SI_CARD(m) ((m & SI_CARD_MASK) >> 5) +#define SI_TTY(m) (m & SI_TTY_MASK) + +#define IS_CALLOUT(m) (m & SI_CALLOUT_MASK) +#define IS_STATE(m) (m & SI_STATE_MASK) +#define IS_CONTROLDEV(m) (m & SI_CONTROLDEV_MASK) +#define IS_SPECIAL(m) (m & SI_SPECIAL_MASK) + +#define MINOR2SC(m) (&si_softc[SI_CARD(m)]) +#define MINOR2PP(m) (MINOR2SC((m))->sc_ports + SI_PORT((m))) +#define MINOR2TP(m) (MINOR2PP((m))->sp_tty) +#define TP2PP(tp) (MINOR2PP(SI_TTY(minor((tp)->t_dev)))) + +/* Adapter types */ +#define SIEMPTY 0 +#define SIHOST 1 +#define SI2 2 +#define SIHOST2 3 +#define SIEISA 4 + +/* Buffer parameters */ +#define SLXOS_BUFFERSIZE 256 + +typedef unsigned char BYTE; /* Type cast for unsigned 8 bit */ +typedef unsigned short WORD; /* Type cast for unsigned 16 bit */ + + +/* + * Hardware `registers', stored in the shared memory. + * These are related to the firmware running on the Z280. + */ + +struct si_reg { + BYTE initstat; + BYTE memsize; + WORD int_count; + WORD revision; + BYTE rx_int_count; + BYTE spare; + WORD int_pending; + WORD int_counter; + BYTE int_scounter; + BYTE res[0x80 - 13]; +}; + +/* + * Per module control structure, stored in shared memory. + */ +struct si_module { + WORD sm_next; /* Next module */ + BYTE sm_type; /* Number of channels */ + BYTE sm_number; /* Module number on cable */ + BYTE sm_dsr; /* Private dsr copy */ + BYTE sm_res[0x80 - 5]; /* Reserve space to 128 bytes */ +}; + +/* + * The 'next' pointer & with 0x7fff + SI base addres give + * the address of the next module block if fitted. (else 0) + * Note that next points to the TX buffer so 0x60 must be + * subtracted to find the true base. + * + * Type is a bit field as follows: The bottom 5 bits are the + * number of channels on this module, the top 3 bits are + * as the module type thus: + * + * 000 2698 RS232 module (4 port or 8 port) + * 001 Reserved for 2698 RS422 module + * 010 Reserved for 8530 based sync module + * 011 Reserved for parallel printer module + * 100 Reserved for network module + * 101-111 Reserved for expansion. + * + * The number field is the cable position of the module. + */ +#define M232 0x00 +#define M422 0x20 /* not supported */ +#define MSYNC 0x40 /* this is the Telebit Netblazer module */ +#define MCENT 0x60 /* not supported */ +#define MNET 0x80 /* not supported */ +#define MMASK 0x1F + +/* + * Per channel(port) control structure, stored in shared memory. + */ +struct si_channel { + /* + * Generic stuff + */ + WORD next; /* Next Channel */ + WORD addr_uart; /* Uart address */ + WORD module; /* address of module struct */ + BYTE type; /* Uart type */ + BYTE fill; + /* + * Uart type specific stuff + */ + BYTE x_status; /* XON / XOFF status */ + BYTE c_status; /* cooking status */ + BYTE hi_rxipos; /* stuff into rx buff */ + BYTE hi_rxopos; /* stuff out of rx buffer */ + BYTE hi_txopos; /* Stuff into tx ptr */ + BYTE hi_txipos; /* ditto out */ + BYTE hi_stat; /* Command register */ + BYTE dsr_bit; /* Magic bit for DSR */ + BYTE txon; /* TX XON char */ + BYTE txoff; /* ditto XOFF */ + BYTE rxon; /* RX XON char */ + BYTE rxoff; /* ditto XOFF */ + BYTE hi_mr1; /* mode 1 image */ + BYTE hi_mr2; /* mode 2 image */ + BYTE hi_csr; /* clock register */ + BYTE hi_op; /* Op control */ + BYTE hi_ip; /* Input pins */ + BYTE hi_state; /* status */ + BYTE hi_prtcl; /* Protocol */ + BYTE hi_txon; /* host copy tx xon stuff */ + BYTE hi_txoff; + BYTE hi_rxon; + BYTE hi_rxoff; + BYTE close_prev; /* Was channel previously closed */ + BYTE hi_break; /* host copy break process */ + BYTE break_state; /* local copy ditto */ + BYTE hi_mask; /* Mask for CS7 etc. */ + BYTE mask_z280; /* Z280's copy */ + BYTE res[0x60 - 36]; + BYTE hi_txbuf[SLXOS_BUFFERSIZE]; + BYTE hi_rxbuf[SLXOS_BUFFERSIZE]; + BYTE res1[0xA0]; +}; + +/* + * Register definitions + */ + +/* + * Break input control register definitions + */ +#define BR_IGN 0x01 /* Ignore any received breaks */ +#define BR_INT 0x02 /* Interrupt on received break */ +#define BR_PARMRK 0x04 /* Enable parmrk parity error processing */ +#define BR_PARIGN 0x08 /* Ignore chars with parity errors */ + +/* + * Protocol register provided by host for XON/XOFF and cooking + */ +#define SP_TANY 0x01 /* Tx XON any char */ +#define SP_TXEN 0x02 /* Tx XON/XOFF enabled */ +#define SP_CEN 0x04 /* Cooking enabled */ +#define SP_RXEN 0x08 /* Rx XON/XOFF enabled */ +#define SP_DCEN 0x20 /* DCD / DTR check */ +#define SP_PAEN 0x80 /* Parity checking enabled */ + +/* + * HOST STATUS / COMMAND REGISTER + */ +#define IDLE_OPEN 0x00 /* Default mode, TX and RX polled + buffer updated etc */ +#define LOPEN 0x02 /* Local open command (no modem ctl */ +#define MOPEN 0x04 /* Open and monitor modem lines (blocks + for DCD */ +#define MPEND 0x06 /* Wating for DCD */ +#define CONFIG 0x08 /* Channel config has changed */ +#define CLOSE 0x0A /* Close channel */ +#define SBREAK 0x0C /* Start break */ +#define EBREAK 0x0E /* End break */ +#define IDLE_CLOSE 0x10 /* Closed channel */ +#define IDLE_BREAK 0x12 /* In a break */ +#define FCLOSE 0x14 /* Force a close */ +#define RESUME 0x16 /* Clear a pending xoff */ +#define WFLUSH 0x18 /* Flush output buffer */ +#define RFLUSH 0x1A /* Flush input buffer */ + +/* + * Host status register + */ +#define ST_BREAK 0x01 /* Break received (clear with config) */ + +/* + * OUTPUT PORT REGISTER + */ +#define OP_CTS 0x01 /* Enable CTS */ +#define OP_DSR 0x02 /* Enable DSR */ +/* + * INPUT PORT REGISTER + */ +#define IP_DCD 0x04 /* DCD High */ +#define IP_DTR 0x20 /* DTR High */ +#define IP_RTS 0x02 /* RTS High */ +#define IP_RI 0x40 /* RI High */ + +/* + * Mode register and uart specific stuff + */ +/* + * MODE REGISTER 1 + */ +#define MR1_5_BITS 0x00 +#define MR1_6_BITS 0x01 +#define MR1_7_BITS 0x02 +#define MR1_8_BITS 0x03 +/* + * Parity + */ +#define MR1_ODD 0x04 +#define MR1_EVEN 0x00 +/* + * Parity mode + */ +#define MR1_WITH 0x00 +#define MR1_FORCE 0x08 +#define MR1_NONE 0x10 +#define MR1_SPECIAL 0x18 +/* + * Error mode + */ +#define MR1_CHAR 0x00 +#define MR1_BLOCK 0x20 +/* + * Request to send line automatic control + */ +#define MR1_CTSCONT 0x80 + +/* + * MODE REGISTER 2 + */ +/* + * Number of stop bits + */ +#define MR2_1_STOP 0x07 +#define MR2_2_STOP 0x0F +/* + * Clear to send automatic testing before character sent + */ +#define MR2_RTSCONT 0x10 +/* + * Reset RTS automatically after sending character? + */ +#define MR2_CTSCONT 0x20 +/* + * Channel mode + */ +#define MR2_NORMAL 0x00 +#define MR2_AUTO 0x40 +#define MR2_LOCAL 0x80 +#define MR2_REMOTE 0xC0 + +/* + * CLOCK SELECT REGISTER - this and the code assumes ispeed == ospeed + */ +/* + * Clocking rates are in lower and upper nibbles.. R = upper, T = lower + */ +#define CLK75 0x0 +#define CLK110 0x1 /* 110 on XIO!! */ +#define CLK38400 0x2 /* out of sequence */ +#define CLK150 0x3 +#define CLK300 0x4 +#define CLK600 0x5 +#define CLK1200 0x6 +#define CLK2000 0x7 +#define CLK2400 0x8 +#define CLK4800 0x9 +#define CLK7200 0xa /* unchecked */ +#define CLK9600 0xb +#define CLK19200 0xc +#define CLK57600 0xd + +/* + * Per-port (channel) soft information structure, stored in the driver. + * This is visible via ioctl()'s. + */ +struct si_port { + volatile struct si_channel *sp_ccb; + struct tty *sp_tty; + int sp_pend; /* pending command */ + int sp_last_hi_ip; /* cached DCD */ + int sp_state; + int sp_active_out; /* callout is open */ + int sp_flags; + int sp_dtr_wait; /* DTR holddown in hz */ + u_int sp_wopeners; /* # procs waiting DCD */ + u_char sp_hotchar; /* ldisc specific ASAP char */ + /* Initial state. */ + struct termios sp_iin; + struct termios sp_iout; + /* Lock state. */ + struct termios sp_lin; + struct termios sp_lout; +#ifdef SI_DEBUG + int sp_debug; /* debug mask */ +#endif +}; + +/* sp_state */ +#define SS_CLOSED 0x0000 +#define SS_OPEN 0x0001 /* Port is active */ +/* 0x0002 -- */ +/* 0x0004 -- */ +/* 0x0008 -- */ +/* 0x0010 -- */ +/* 0x0020 -- */ +/* 0x0040 -- */ +/* 0x0080 -- */ +#define SS_LSTART 0x0100 /* lstart timeout pending */ +#define SS_INLSTART 0x0200 /* running an lstart induced t_oproc */ +#define SS_CLOSING 0x0400 /* in the middle of a siclose() */ +/* 0x0800 -- */ +#define SS_WAITWRITE 0x1000 +#define SS_BLOCKWRITE 0x2000 +#define SS_DTR_OFF 0x4000 /* DTR held off */ + +/* sp_flags */ +#define SPF_COOKMODE 0x0003 +#define SPFC_WELL 0 +#define SPFC_MEDIUM 1 +#define SPFC_RAW 2 +#define spfc_clear(pp) (pp)->sp_flags &= ~SPF_COOKMODE +#define SPF_COOK_WELL(pp) spfc_clear(pp) +#define SPF_COOK_MEDIUM(pp) {spfc_clear(pp);(pp)->sp_flags|=SPFC_MEDIUM;} +#define SPF_COOK_RAW(pp) {spfc_clear(pp);(pp)->sp_flags|=SPFC_RAW;} +#define SPF_SETCOOK(pp, c) {spfc_clear(pp);(pp)->sp_flags|=(c);} +#define SPF_ISCOOKWELL(pp) (((pp)->sp_flags & SPF_COOKMODE) == SPFC_WELL) +#define SPF_ISCOOKMEDIUM(pp) (((pp)->sp_flags & SPF_COOKMODE) == SPFC_MEDIUM) +#define SPF_ISCOOKRAW(pp) (((pp)->sp_flags & SPF_COOKMODE) == SPFC_RAW) +#define SPF_COOKWELL_ALWAYS 0x0004 /* always use line disc */ +/* 0x0008 */ +#define SPF_IXANY 0x0020 /* IXANY enable/disable flag */ +#define SPF_CTSOFLOW 0x0040 /* use CTS to handle o/p flow */ +#define SPF_RTSIFLOW 0x0080 /* use RTS to handle i/p flow */ +#define SPF_PPP 0x0100 /* special handling for upper + * level protocol code */ + +/* + * Command post flags + */ +#define SI_NOWAIT 0x00 /* Don't wait for command */ +#define SI_WAIT 0x01 /* Wait for complete */ + +/* + * Extensive debugging stuff - manipulated using siconfig(8) + */ +#define DBG_ENTRY 0x00000001 +#define DBG_DRAIN 0x00000002 +#define DBG_OPEN 0x00000004 +#define DBG_CLOSE 0x00000008 +#define DBG_READ 0x00000010 +#define DBG_WRITE 0x00000020 +#define DBG_PARAM 0x00000040 +#define DBG_INTR 0x00000080 +#define DBG_IOCTL 0x00000100 +/* 0x00000200 */ +#define DBG_SELECT 0x00000400 +#define DBG_OPTIM 0x00000800 +#define DBG_START 0x00001000 +#define DBG_EXIT 0x00002000 +#define DBG_FAIL 0x00004000 +#define DBG_STOP 0x00008000 +#define DBG_AUTOBOOT 0x00010000 +#define DBG_MODEM 0x00020000 +#define DBG_DOWNLOAD 0x00040000 +#define DBG_LSTART 0x00080000 +#define DBG_POLL 0x00100000 +#define DBG_ALL 0xffffffff + +/* + * SI ioctls + */ +/* + * struct for use by Specialix ioctls - used by siconfig(8) + */ +typedef struct { + unsigned char + sid_port:5, /* 0 - 31 ports per card */ + sid_card:2, /* 0 - 3 cards */ + sid_control:1; /* controlling device (all cards) */ +} sidev_t; +struct si_tcsi { + sidev_t tc_dev; + union { + int x_int; + int x_dbglvl; + } tc_action; +#define tc_card tc_dev.sid_card +#define tc_port tc_dev.sid_port +#define tc_int tc_action.x_int +#define tc_dbglvl tc_action.x_dbglvl +}; + +struct si_pstat { + sidev_t tc_dev; + union { + struct si_port x_siport; + struct si_channel x_ccb; + struct tty x_tty; + } tc_action; +#define tc_siport tc_action.x_siport +#define tc_ccb tc_action.x_ccb +#define tc_tty tc_action.x_tty +}; + +#define IOCTL_MIN 96 +#define TCSIDEBUG _IOW('S', 96, struct si_tcsi) /* Toggle debug */ +#define TCSIRXIT _IOW('S', 97, struct si_tcsi) /* RX int throttle */ +#define TCSIIT _IOW('S', 98, struct si_tcsi) /* TX int throttle */ + /* 99 defunct */ + /* 100 defunct */ + /* 101 defunct */ + /* 102 defunct */ + /* 103 defunct */ +#define TCSIIXANY _IOW('S', 103, struct si_tcsi) /* enable ixany */ + /* 104 defunct */ +#define TCSISTATE _IOWR('S', 105, struct si_tcsi) /* get current state of RTS + DCD and DTR pins */ + /* Set/reset/enquire cook mode, 1 = always use line disc + * -1 = enquire current setting */ +#define TCSICOOKMODE _IOWR('S', 106, struct si_tcsi) +#define TCSIPORTS _IOR('S', 107, int) /* Number of ports found */ +#define TCSISDBG_LEVEL _IOW('S', 108, struct si_tcsi) /* equivalent of TCSIDEBUG which sets a + * particular debug level (DBG_??? bit + * mask), default is 0xffff */ +#define TCSIGDBG_LEVEL _IOWR('S', 109, struct si_tcsi) +#define TCSIGRXIT _IOWR('S', 110, struct si_tcsi) +#define TCSIGIT _IOWR('S', 111, struct si_tcsi) + /* 112 defunct */ + /* 113 defunct */ + /* 114 defunct */ + /* 115 defunct */ + /* 116 defunct */ +#define TCSIMODEM _IOWR('S', 117, struct si_tcsi) /* set/clear/query the modem bit */ + +#define TCSISDBG_ALL _IOW('S', 118, int) /* set global debug level */ +#define TCSIGDBG_ALL _IOR('S', 119, int) /* get global debug level */ + +#define TCSIFLOW _IOWR('S', 120, struct si_tcsi) /* set/get h/w flow state */ + /* 121 defunct */ + /* 122 defunct */ + + +#define TCSIPPP _IOWR('S', 123, struct si_tcsi) /* set/get PPP flag bit */ +#define TCSIMODULES _IOR('S', 124, int) /* Number of modules found */ + +/* Various stats and monitoring hooks per tty device */ +#define TCSI_PORT _IOWR('S', 125, struct si_pstat) /* get si_port */ +#define TCSI_CCB _IOWR('S', 126, struct si_pstat) /* get si_ccb */ +#define TCSI_TTY _IOWR('S', 127, struct si_pstat) /* get tty struct */ + +#define IOCTL_MAX 127 + +#define IS_SI_IOCTL(cmd) ((u_int)((cmd)&0xff00) == ('S'<<8) && \ + (u_int)((cmd)&0xff) >= IOCTL_MIN && \ + (u_int)((cmd)&0xff) <= IOCTL_MAX) + +#define CONTROLDEV "/dev/si_control" diff --git a/sys/i386/isa/asc.c b/sys/i386/isa/asc.c new file mode 100644 index 0000000000000..4e994d9a98ffc --- /dev/null +++ b/sys/i386/isa/asc.c @@ -0,0 +1,862 @@ +/* asc.c - device driver for hand scanners + * + * Current version supports: + * + * - Trust AmiScan BW (GI1904 chipset) + * + * Copyright (c) 1995 Gunther Schadow. All rights reserved. + * Copyright (c) 1995 Luigi Rizzo. All rights reserved. + * + * 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 above copyright + * notice, this list of conditions and the following disclaimer. + * 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 Gunther Schadow + * and Luigi Rizzo. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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: asc.c,v 1.4 1995/09/08 18:30:33 julian Exp $ + */ + +#include "asc.h" +#if NASC > 0 +#ifdef FREEBSD_1_X +#include "param.h" +#include "systm.h" +#include "proc.h" +#include "user.h" +#include "buf.h" +#include "malloc.h" +#include "kernel.h" +#include "ioctl.h" +#include "tty.h" +#include "uio.h" +#include "syslog.h" + +#include "i386/isa/isa.h" +#include "i386/isa/isa_device.h" +#include "i386/isa/ascreg.h" + +#include "machine/asc_ioctl.h" +#else +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/user.h> +#include <sys/buf.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/uio.h> +#include <sys/syslog.h> + +#include <machine/asc_ioctl.h> + +#include <sys/devconf.h> +#include <i386/isa/isa.h> +#include <i386/isa/isa_device.h> +#include <i386/isa/ascreg.h> +#ifdef DEVFS +#include <sys/devfsext.h> + +extern d_open_t ascopen; +#endif + +#endif /* FREEBSD_1_X */ + +/*** + *** CONSTANTS & DEFINES + *** + ***/ + +#define PROBE_FAIL 0 +#define PROBE_SUCCESS 5 /* number of io ports... */ +#define SUCCESS 0 +#define FAIL -1 +#define INVALID FAIL + +#define DMA1_READY 0x08 +#define ASCDEBUG +#ifdef ASCDEBUG +# define lprintf if(scu->flags & DEBUG) printf +#else +# define lprintf (void) +#endif + +#define TIMEOUT (hz*15) /* timeout while reading a buffer - default value */ +#define ASCPRI PRIBIO /* priority while reading a buffer */ + +/*** + *** LAYOUT OF THE MINOR NUMBER + ***/ + +#define UNIT_MASK 0xc0 /* unit asc0 .. asc3 */ +#define UNIT(x) (x >> 6) +#define DBUG_MASK 0x20 +#define FRMT_MASK 0x18 /* output format */ +#define FRMT_RAW 0x00 /* output bits as read from scanner */ +#define FRMT_GRAY 0x10 /* output graymap (not implemented yet) */ +#define FRMT_PBM 0x08 /* output pbm format */ +#define FRMT_PGM 0x18 + +/*** + *** THE GEMOMETRY TABLE + ***/ + +static const struct asc_geom { + int dpi; /* dots per inch */ + int dpl; /* dots per line */ + int bpl; /* bytes per line */ + int g_res; /* get resolution value (ASC_STAT) */ +} geomtab[] = { + { 800, 3312, 414, ASC_RES_800}, + { 700, 2896, 362, ASC_RES_700}, + { 600, 2480, 310, ASC_RES_600}, + { 500, 1656, 258, ASC_RES_500}, + { 400, 1656, 207, ASC_RES_400}, + { 300, 1240, 155, ASC_RES_300}, + { 200, 832, 104, ASC_RES_200}, + { 100, 416, 52, ASC_RES_100}, + { INVALID, 416, 52, INVALID } /* terminator */ +}; + +/*** + *** THE TABLE OF UNITS + ***/ + +struct _sbuf { + size_t size; + size_t rptr; + size_t wptr; /* only changed in ascintr */ + size_t count; + char *base; +}; + +struct asc_unit { + int base; /* base address */ + int dma_num; /* dma number */ + char dma_byte; /* mask of byte for setting DMA value */ + char int_byte; /* mask of byte for setting int value */ + char cfg_byte; /* mirror of byte written to config reg (ASC_CFG). */ + char cmd_byte; /* mirror of byte written to cmd port (ASC_CMD)*/ + int flags; +#define ATTACHED 0x01 +#define OPEN 0x02 +#define READING 0x04 +#define DMA_ACTIVE 0x08 +#define SLEEPING 0x10 +#define SEL_COLL 0x20 +#define PBM_MODE 0x40 +#define DEBUG 0x80 + int geometry; /* resolution as geomtab index */ + int linesize; /* length of one scan line (from geom.table) */ + int blen; /* length of buffer in lines */ + int btime; /* timeout of buffer in seconds/hz */ + struct _sbuf sbuf; + long icnt; /* interrupt count XXX for debugging */ +#ifdef FREEBSD_1_X + pid_t selp; /* select pointer... */ +#else + struct selinfo selp; +#endif + int height; /* height, for pnm modes */ + size_t bcount; /* bytes to read, for pnm modes */ +} unittab[NASC]; + +/*** I could not find a reasonable buffer size limit other than by + *** experiments. MAXPHYS is obviously too much, while DEV_BSIZE and + *** PAGE_SIZE are really too small. There must be something wrong + *** with isa_dmastart/isa_dmarangecheck HELP!!! + ***/ +#define MAX_BUFSIZE 0x3000 +#define DEFAULT_BLEN 20 + +/*** + *** THE PER-DRIVER RECORD FOR ISA.C + ***/ +int ascprobe (struct isa_device *isdp); +int ascattach(struct isa_device *isdp); +struct isa_driver ascdriver = { ascprobe, ascattach, "asc" }; + +#ifndef FREEBSD_1_X +struct asc_softc { + struct isa_device *dev; +} asc_softc[NASC]; + +static struct kern_devconf kdc_asc[NASC] = { { + 0, 0, 0, /* filled in by dev_attach */ + "asc", 0, { MDDT_ISA, 0, "tty" }, + isa_generic_externalize, 0, 0, ISA_EXTERNALLEN, + &kdc_isa0, /* parent */ + 0, /* parentdata */ + DC_UNCONFIGURED, /* state */ + "GI1904 Hand scanner", + DC_CLS_MISC +} }; + +static inline void +asc_registerdev(struct isa_device *id) +{ + if(id->id_unit) + kdc_asc[id->id_unit] = kdc_asc[0]; + kdc_asc[id->id_unit].kdc_unit = id->id_unit; + kdc_asc[id->id_unit].kdc_isa = id; + dev_attach(&kdc_asc[id->id_unit]); +} +#endif /* ! FREEBSD_1_X */ + +/*** + *** LOCALLY USED SUBROUTINES + *** + ***/ + +/*** + *** get_resolution + *** read resolution from the scanner + ***/ +static void +get_resolution(struct asc_unit *scu) +{ + int res, i, delay; + + res=0; + scu->cmd_byte = ASC_STANDBY; + outb(ASC_CMD, scu->cmd_byte); + tsleep((caddr_t)scu, ASCPRI | PCATCH, "ascres", hz/10); + for(delay= 100; (res=inb(ASC_STAT)) & ASC_RDY_FLAG; delay--) + { + i = tsleep((caddr_t)scu, ASCPRI | PCATCH, "ascres0", 1); + if ( ( i == 0 ) || ( i == EWOULDBLOCK ) ) + i = SUCCESS; + else + break; + } + if (delay==0) { + lprintf("asc.get_resolution: timeout completing command\n"); + return /* -1 */; + } + /* ... actual read resolution... */ + res &= ASC_RES_MASK; + for (i=0; geomtab[i].dpi != INVALID; i++) { + if (geomtab[i].g_res == res) break; + } + if (geomtab[i].dpi==INVALID) { + scu->geometry= i; /* INVALID; */ + lprintf("asc.get_resolution: wrong resolution\n"); + } else { + lprintf("asc.get_resolution: %d dpi\n",geomtab[i].dpi); + scu->geometry = i; + } + scu->linesize = geomtab[scu->geometry].bpl; + scu->height = geomtab[scu->geometry].dpl; /* default... */ +} + +/*** + *** buffer_allocate + *** allocate/reallocate a buffer + ***/ + +static int +buffer_allocate(struct asc_unit *scu) +{ + size_t size, size1; + + size = scu->blen * scu->linesize; + + lprintf("asc.buffer_allocate: need 0x%x bytes\n", size); + + if ( size > MAX_BUFSIZE ) { + size1=size; + size= ( (MAX_BUFSIZE+scu->linesize-1) / scu->linesize)*scu->linesize; + lprintf("asc.buffer_allocate: 0x%x bytes are too much, try 0x%x\n", + size1, size); + /* return ENOMEM; */ + } + + if ( scu->sbuf.base != NULL ) + if ( scu->sbuf.size == size ) { + lprintf("asc.buffer_allocate: keep old buffer\n"); + return SUCCESS; + } else { + lprintf("asc.buffer_allocate: release old buffer\n"); + free( scu->sbuf.base, M_DEVBUF ); + } + + scu->sbuf.base = (char *)malloc(size, M_DEVBUF, M_WAITOK); + + if ( scu->sbuf.base == NULL ) { + lprintf("asc.buffer_allocate: " + "buffer allocatation failed for size = 0x%x\n", + scu->sbuf.size); + return ENOMEM; + } + + scu->sbuf.size = size; + scu->sbuf.rptr = 0; + scu->sbuf.wptr = 0; + scu->sbuf.count = 0; /* available data for reading */ + + lprintf("asc.buffer_allocate: ok\n"); + + return SUCCESS; +} + +/*** dma_restart + *** invoked locally to start dma. Must run in a critical section + ***/ +static void +dma_restart(struct asc_unit *scu) +{ + unsigned char al=scu->cmd_byte; + isa_dmastart(B_READ, scu->sbuf.base+scu->sbuf.wptr, + scu->linesize, scu->dma_num); + /*** this is done in sub_20, after dmastart ? ***/ +#if 0 + outb( ASC_CMD, al |= 4 ); + outb( ASC_CMD, al |= 8 ); /* ??? seems useless */ + outb( ASC_CMD, al &= 0xfb ); + scu->cmd_byte = al; +#else + outb( ASC_CMD, ASC_OPERATE); +#endif + scu->flags |= DMA_ACTIVE; +} + +/*** + *** the main functions + ***/ + +/*** asc_reset + *** resets the scanner and the config bytes... + ***/ +void +asc_reset(struct asc_unit *scu) +{ + scu->cfg_byte = 0 ; /* clear... */ + scu->cmd_byte = 0 ; /* clear... */ + + outb(ASC_CFG,scu->cfg_byte); /* for safety, do this here */ + outb(ASC_CMD,scu->cmd_byte); /* probably not needed */ + tsleep((caddr_t)scu, ASCPRI | PCATCH, "ascres", hz/10); /* sleep .1 sec */ + + scu->blen = DEFAULT_BLEN; + scu->btime = TIMEOUT; + scu->height = 0 ; /* don't know better... */ +} +/************************************************************************** + *** + *** ascprobe + *** read status port and check for proper configuration: + *** - if address group matches (status byte has reasonable value) + *** cannot check interrupt/dma, only clear the config byte. + ***/ +int +ascprobe (struct isa_device *isdp) +{ + int unit = isdp->id_unit; + struct asc_unit *scu = unittab + unit; + int stb; + + scu->base = isdp->id_iobase; /*** needed by the following macros ***/ + scu->flags = DEBUG; + + if ( isdp->id_iobase < 0 ) { + lprintf("asc%d.probe: no iobase given\n", unit); + return PROBE_FAIL; + } + + if ((stb=inb(ASC_PROBE)) != ASC_PROBE_VALUE) { + lprintf("asc%d.probe: failed, got 0x%02x instead of 0x%02x\n", + unit, stb, ASC_PROBE_VALUE); + return PROBE_FAIL; + } + + switch(ffs(isdp->id_irq) - 1) { + case 3: + scu->int_byte = ASC_CNF_IRQ3; + break; + case 5: + scu->int_byte = ASC_CNF_IRQ5; + break; + case 10: + scu->int_byte = ASC_CNF_IRQ10; + break; +#if 0 + case -1: + scu->int_byte = 0; + lprintf("asc%d.probe: warning - going interruptless\n", unit); + break; +#endif + default: + lprintf("asc%d.probe: unsupported INT %d (only 3, 5, 10)\n", + unit, isdp->id_irq); + return PROBE_FAIL; + } + scu->dma_num = isdp->id_drq; + switch(scu->dma_num) { + case 1: + scu->dma_byte = ASC_CNF_DMA1; + break; + case 3: + scu->dma_byte = ASC_CNF_DMA3; + break; + default: + lprintf("asc%d.probe: unsupported DMA %d (only 1 or 3)\n", scu->dma_num); + return PROBE_FAIL; + } + asc_reset(scu); +/* lprintf("asc%d.probe: ok\n", unit); */ + + scu->flags &= ~DEBUG; + scu->icnt = 0; + + return PROBE_SUCCESS; +} + +/************************************************************************** + *** + *** ascattach + *** finish initialization of unit structure, get geometry value (?) + ***/ + +int +ascattach(struct isa_device *isdp) +{ + int unit = isdp->id_unit; + struct asc_unit *scu = unittab + unit; +#ifdef DEVFS + char buf[32]; + void *x; +#endif + + scu->flags |= DEBUG; + printf("asc%d: [GI1904/Trust Ami-Scan Grey, type S2]\n", unit); + + /* initialize buffer structure */ + scu->sbuf.base = NULL; + scu->sbuf.size = INVALID; + scu->sbuf.rptr = INVALID; + + scu->flags |= ATTACHED; +/* lprintf("asc%d.attach: ok\n", unit); */ + scu->flags &= ~DEBUG; + +#ifdef FREEBSD_1_X + scu->selp = (pid_t)0; +#else + scu->selp.si_flags=0; + scu->selp.si_pid=(pid_t)0; + kdc_asc[isdp->id_unit].kdc_state = DC_BUSY; /* XXX don't know better */ + asc_registerdev(isdp); +#endif +#ifdef DEVFS + sprintf(buf,"asc%d",unit); +/* path name devsw minor type uid gid perm*/ + x=dev_add("/misc", buf, ascopen, unit<<6, DV_CHR, 0, 0, 0666); + sprintf(buf,"asc%dp",unit); + x=dev_add("/misc", buf, ascopen, ((unit<<6) + FRMT_PBM), + DV_CHR, 0, 0, 0666); + sprintf(buf,"asc%dd",unit); + x=dev_add("/misc", buf, ascopen, ((unit<<6) + DBUG_MASK), + DV_CHR, 0, 0, 0666); + sprintf(buf,"asc%dpd",unit); + x=dev_add("/misc", buf, ascopen, ((unit<<6) + DBUG_MASK + FRMT_PBM), + DV_CHR, 0, 0, 0666); +#endif /*DEVFS*/ + return 1; /* attach must not fail */ +} + +/************************************************************************** + *** + *** ascintr + *** the interrupt routine, at the end of DMA... + ***/ +void +ascintr(int unit) +{ + struct asc_unit *scu = unittab + unit; + int chan_bit = 0x01 << scu->dma_num; + + scu->icnt++; + /* ignore stray interrupts... */ + if ( scu->flags & (OPEN |READING) != (OPEN | READING) ) { + /* must be after closing... */ + scu->flags &= ~(OPEN | READING | DMA_ACTIVE | SLEEPING | SEL_COLL); + return; + } + if ( (scu->flags & DMA_ACTIVE) && (inb(DMA1_READY) & chan_bit) != 0) { + outb( ASC_CMD, ASC_STANDBY); + scu->flags &= ~DMA_ACTIVE; + /* bounce buffers... */ + isa_dmadone(B_READ, scu->sbuf.base+scu->sbuf.wptr, + scu->linesize, scu->dma_num); + scu->sbuf.wptr += scu->linesize; + if (scu->sbuf.wptr >= scu->sbuf.size) scu->sbuf.wptr=0; + scu->sbuf.count += scu->linesize; + if (scu->flags & SLEEPING) { + scu->flags &= ~SLEEPING; + wakeup((caddr_t)scu); + } + if (scu->sbuf.size - scu->sbuf.count >= scu->linesize) { + dma_restart(scu); + } +#ifdef FREEBSD_1_X + if (scu->selp) { + selwakeup(&scu->selp, scu->flags & SEL_COLL ); + scu->selp=(pid_t)0; + scu->flags &= ~SEL_COLL; + } +#else + if (scu->selp.si_pid) { + selwakeup(&scu->selp); + scu->selp.si_pid=(pid_t)0; + scu->selp.si_flags = 0; + } +#endif + } +} + +/************************************************************************** + *** + *** ascopen + *** set open flag, set modes according to minor number + *** FOR RELEASE: + *** don't switch scanner on, wait until first read or ioctls go before + ***/ + +int +ascopen(dev_t dev, int flags, int fmt, struct proc *p) +{ + int unit = UNIT(minor(dev)) & UNIT_MASK; + struct asc_unit *scu = unittab + unit; + + lprintf("asc%d.open: minor %d icnt %d\n", unit, minor(dev), scu->icnt); + + if ( unit >= NASC || !( scu->flags & ATTACHED ) ) { + lprintf("asc%d.open: unit was not attached successfully, flags 0x%04x\n", + unit, scu->flags); + return ENXIO; + } + + if ( scu->flags & OPEN ) { + lprintf("asc%d.open: already open", unit); + return EBUSY; + } + scu->flags = ATTACHED | OPEN; + + if ( minor(dev) & DBUG_MASK ) scu->flags |= DEBUG; + + switch(minor(dev) & FRMT_MASK) { + case FRMT_PBM: + scu->flags |= PBM_MODE; + lprintf("asc%d.open: pbm mode\n", unit); + break; + case FRMT_RAW: + lprintf("asc%d.open: raw mode\n", unit); + scu->flags &= ~PBM_MODE; + break; + default: + lprintf("asc%d.open: gray maps are not yet supported", unit); + return ENXIO; + } + + asc_reset(scu); + get_resolution(scu); + return SUCCESS; +} + +int +asc_startread(struct asc_unit *scu) +{ + /*** from here on, things can be delayed to the first read/ioctl ***/ + /*** this was done in sub_12... ***/ + scu->cfg_byte= scu->cmd_byte=0; /* init scanner */ + outb(ASC_CMD, scu->cmd_byte); + /*** this was done in sub_16, set scan len... ***/ + outb(ASC_BOH, 0 ); + scu->cmd_byte = 0x90 ; + outb(ASC_CMD, scu->cmd_byte); + outb(ASC_LEN_L, scu->linesize & 0xff /* len_low */); + outb(ASC_LEN_H, (scu->linesize >>8) & 0xff /* len_high */); + /*** this was done in sub_21, config DMA ... ***/ + scu->cfg_byte |= scu->dma_byte; + outb(ASC_CFG, scu->cfg_byte); + /*** sub_22: enable int on the scanner ***/ + scu->cfg_byte |= scu->int_byte; + outb(ASC_CFG, scu->cfg_byte); + /*** sub_28: light on etc...***/ + scu->cmd_byte = ASC_STANDBY; + outb(ASC_CMD, scu->cmd_byte); + tsleep((caddr_t)scu, ASCPRI | PCATCH, "ascstrd", hz/10); /* sleep .1 sec */ + return SUCCESS; +} + +/************************************************************************** + *** + *** ascclose + *** turn off scanner, release the buffer + *** should probably terminate dma ops, release int and dma. lr 12mar95 + ***/ + +int +ascclose(dev_t dev, int flags, int fmt, struct proc *p) +{ + int unit = UNIT(minor(dev)); + struct asc_unit *scu = unittab + unit; + + lprintf("asc%d.close: minor %d\n", + unit, minor(dev)); + + if ( unit >= NASC || !( scu->flags & ATTACHED ) ) { + lprintf("asc%d.close: unit was not attached successfully 0x%04x\n", + unit, scu->flags); + return ENXIO; + } + /* all this is in sub_29... */ + /* cli(); */ + outb(ASC_CFG, 0 ); /* don't save in CFG byte!!! */ + scu->cmd_byte &= ~ASC_LIGHT_ON; + outb(ASC_CMD, scu->cmd_byte);/* light off */ + tsleep((caddr_t)scu, ASCPRI | PCATCH, "ascclo", hz/2); /* sleep 1/2 sec */ + scu->cfg_byte &= ~ scu->dma_byte ; /* disable scanner dma */ + scu->cfg_byte &= ~ scu->int_byte ; /* disable scanner int */ + outb(ASC_CFG, scu->cfg_byte); + /* --- disable dma controller ? --- */ + /* --- disable interrupts on the controller (sub_24) --- */ + + if ( scu->sbuf.base != NULL ) free( scu->sbuf.base, M_DEVBUF ); + + scu->sbuf.base = NULL; + scu->sbuf.size = INVALID; + scu->sbuf.rptr = INVALID; + + scu->flags &= ~(DEBUG | OPEN | READING); + + return SUCCESS; +} + +static void +pbm_init(struct asc_unit *scu) +{ + int width = geomtab[scu->geometry].dpl; + int l= sprintf(scu->sbuf.base,"P4 %d %d\n", width, scu->height); + char *p; + + scu->bcount = scu->height * width / 8 + l; + + /* move header to end of sbuf */ + scu->sbuf.rptr=scu->sbuf.size-l; + bcopy(scu->sbuf.base, scu->sbuf.base+scu->sbuf.rptr,l); + scu->sbuf.count = l; + for(p = scu->sbuf.base + scu->sbuf.rptr; l; p++, l--) + *p = ~*p; +} +/************************************************************************** + *** + *** ascread + ***/ + +int +ascread(dev_t dev, struct uio *uio, int ioflag) +{ + int unit = UNIT(minor(dev)); + struct asc_unit *scu = unittab + unit; + size_t nbytes; + int sps, res; + unsigned char *p; + + lprintf("asc%d.read: minor %d icnt %d\n", unit, minor(dev), scu->icnt); + + if ( unit >= NASC || !( scu->flags & ATTACHED ) ) { + lprintf("asc%d.read: unit was not attached successfully 0x%04x\n", + unit, scu->flags); + return ENXIO; + } + + if ( !(scu->flags & READING) ) { /*** first read... ***/ + /* allocate a buffer for reading data and init things */ + if ( (res = buffer_allocate(scu)) == SUCCESS ) scu->flags |= READING; + else return res; + asc_startread(scu); + if ( scu->flags & PBM_MODE ) { /* initialize for pbm mode */ + pbm_init(scu); + } + } + + lprintf("asc%d.read(before): " + "sz 0x%x, rptr 0x%x, wptr 0x%x, cnt 0x%x bcnt 0x%x flags 0x%x icnt %d\n", + unit, scu->sbuf.size, scu->sbuf.rptr, + scu->sbuf.wptr, scu->sbuf.count, scu->bcount,scu->flags, + scu->icnt); + + sps=spltty(); + if ( scu->sbuf.count == 0 ) { /* no data avail., must wait */ + if (!(scu->flags & DMA_ACTIVE)) dma_restart(scu); + scu->flags |= SLEEPING; + res = tsleep((caddr_t)scu, ASCPRI | PCATCH, "ascread", 0); + scu->flags &= ~SLEEPING; + if ( res == 0 ) res = SUCCESS; + } + splx(sps); /* lower priority... */ + if (scu->flags & DEBUG) + tsleep((caddr_t)scu, ASCPRI | PCATCH, "ascdly",hz); + lprintf("asc%d.read(after): " + "sz 0x%x, rptr 0x%x, wptr 0x%x, cnt 0x%x bcnt 0x%x flags 0x%x icnt %d\n", + unit, scu->sbuf.size, scu->sbuf.rptr, + scu->sbuf.wptr, scu->sbuf.count, scu->bcount,scu->flags,scu->icnt); + + /* first, not more than available... */ + nbytes = min( uio->uio_resid, scu->sbuf.count ); + /* second, contiguous data... */ + nbytes = min( nbytes, (scu->sbuf.size - scu->sbuf.rptr) ); + /* third, one line (will remove this later, XXX) */ + nbytes = min( nbytes, scu->linesize ); + if ( (scu->flags & PBM_MODE) ) + nbytes = min( nbytes, scu->bcount ); + lprintf("asc%d.read: transferring 0x%x bytes\n", unit, nbytes); + + lprintf("asc%d.read: invert buffer\n",unit); + for(p = scu->sbuf.base + scu->sbuf.rptr, res=nbytes; res; p++, res--) + *p = ~*p; + res = uiomove(scu->sbuf.base + scu->sbuf.rptr, nbytes, uio); + if ( res != SUCCESS ) { + lprintf("asc%d.read: uiomove failed %d", unit, res); + return res; + } + + sps=spltty(); + scu->sbuf.rptr += nbytes; + if (scu->sbuf.rptr >= scu->sbuf.size) scu->sbuf.rptr=0; + scu->sbuf.count -= nbytes; + /* having moved some data, can read mode */ + if (!(scu->flags & DMA_ACTIVE)) dma_restart(scu); + splx(sps); /* lower priority... */ + if ( scu->flags & PBM_MODE ) scu->bcount -= nbytes; + + lprintf("asc%d.read: size 0x%x, pointer 0x%x, bcount 0x%x, ok\n", + unit, scu->sbuf.size, scu->sbuf.rptr, scu->bcount); + + return SUCCESS; +} + +/************************************************************************** + *** + *** ascioctl + ***/ + +int +ascioctl(dev_t dev, int cmd, caddr_t data, int flags, struct proc *p) +{ + int unit = UNIT(minor(dev)); + struct asc_unit *scu = unittab + unit; + + lprintf("asc%d.ioctl: minor %d\n", + unit, minor(dev)); + + if ( unit >= NASC || !( scu->flags & ATTACHED ) ) { + lprintf("asc%d.ioctl: unit was not attached successfully 0x04x\n", + unit, scu->flags); + return ENXIO; + } + switch(cmd) { + case ASC_GRES: + asc_reset(scu); + get_resolution(scu); + *(int *)data=geomtab[scu->geometry].dpi; + lprintf("asc%d.ioctl:ASC_GRES %ddpi\n", unit, *(int *)data); + return SUCCESS; + case ASC_GWIDTH: + *(int *)data=geomtab[scu->geometry].dpl; + lprintf("asc%d.ioctl:ASC_GWIDTH %d\n", unit, *(int *)data); + return SUCCESS; + case ASC_GHEIGHT: + *(int *)data=scu->height; + lprintf("asc%d.ioctl:ASC_GHEIGHT %d\n", unit, *(int *)data); + return SUCCESS; + case ASC_SHEIGHT: + lprintf("asc%d.ioctl:ASC_SHEIGHT %d\n", unit, *(int *)data); + if ( scu->flags & READING ) { + lprintf("asc%d:ioctl on already reading unit\n", unit); + return EBUSY; + } + scu->height=*(int *)data; + return SUCCESS; +#if 0 + case ASC_GBLEN: + *(int *)data=scu->blen; + lprintf("asc%d.ioctl:ASC_GBLEN %d\n", unit, *(int *)data); + return SUCCESS; + case ASC_SBLEN: + lprintf("asc%d.ioctl:ASC_SBLEN %d\n", unit, *(int *)data); + if (*(int *)data * geomtab[scu->geometry].dpl / 8 > MAX_BUFSIZE) + { + lprintf("asc%d:ioctl buffer size too high\n", unit); + return ENOMEM; + } + scu->blen=*(int *)data; + return SUCCESS; + case ASC_GBTIME: + *(int *)data = scu->btime / hz; + lprintf("asc%d.ioctl:ASC_GBTIME %d\n", unit, *(int *)data); + return SUCCESS; + case ASC_SBTIME: + scu->btime = *(int *)data * hz; + lprintf("asc%d.ioctl:ASC_SBTIME %d\n", unit, *(int *)data); + return SUCCESS; +#endif + default: return ENOTTY; + } + return SUCCESS; +} + +int +ascselect(dev_t dev, int rw, struct proc *p) +{ + int unit = UNIT(minor(dev)); + struct asc_unit *scu = unittab + unit; + int sps=spltty(); + struct proc *p1; + + if (scu->sbuf.count >0) { + splx(sps); + return 1; + } + if (!(scu->flags & DMA_ACTIVE)) dma_restart(scu); +#ifdef FREEBSD_1_X + if (scu->selp== (pid_t)0) { + scu->selp= p->p_pid; + } else { + scu->flags |= SEL_COLL; + } +#else + + if (scu->selp.si_pid && (p1=pfind(scu->selp.si_pid)) + && p1->p_wchan == (caddr_t)&selwait) + scu->selp.si_flags = SI_COLL; + else + scu->selp.si_pid = p->p_pid; +#endif + splx(sps); + return 0; +} +#endif /* NASC > 0 */ diff --git a/sys/i386/isa/ascreg.h b/sys/i386/isa/ascreg.h new file mode 100644 index 0000000000000..a1a7393de651a --- /dev/null +++ b/sys/i386/isa/ascreg.h @@ -0,0 +1,96 @@ +/* ascreg.h - port and bit definitions for the GI-1904 interface + * + * Copyright (c) 1995 Gunther Schadow. All rights reserved. + * Copyright (c) 1995 Luigi Rizzo. All rights reserved. + * + * 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 above copyright + * notice, this list of conditions and the following disclaimer. + * 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 Gunther Schadow. + * and Luigi Rizzo + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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:$ + */ + + /*** Registers (base=3EB): ************/ +#define ASC_CFG (scu->base) + /*** ASC_CFG 3EB: configuration register. Write only, mirror in RAM + *** 7 6 5 4 3 2 1 0 + *** - - I_5 I_3 I10 D_3 - D_1 + ***/ + /*** #define ASC_CNF_MASK 0x3D */ /* was 0x5a */ +#define ASC_CNF_DMA1 0x01 /* was (~0x02 & ASC_CNF_MASK) */ +#define ASC_CNF_DMA3 0x04 /* was (~0x08 & ASC_CNF_MASK) */ +#define ASC_CNF_IRQ3 0x10 /* was (~0x10 & ASC_CNF_MASK) */ +#define ASC_CNF_IRQ5 0x20 /* was (~0x40 & ASC_CNF_MASK) */ +#define ASC_CNF_IRQ10 0x08 /* was (~0x40 & ASC_CNF_MASK) */ + + /*** ASC_STAT 3EC: command/status; rw, mirror in ram + *** 7 6 5 4 3 2 1 0 + *** BSY - - - - - - - + *** [<-- Resolution -->] 13h,10h,0eh,0ch,09h, 07h, 04h, 02h + ***/ +#define ASC_STAT (scu->base + 1) + +#define ASC_RDY_FLAG 0x80 +#define ASC_RES_MASK 0x3f +#define ASC_RES_800 0x13 +#define ASC_RES_700 0x10 +#define ASC_RES_600 0x0e +#define ASC_RES_500 0x0c +#define ASC_RES_400 0x09 /* 0x00 */ +#define ASC_RES_300 0x07 /* 0x04 */ +#define ASC_RES_200 0x04 /* 0x20 */ +#define ASC_RES_100 0x02 /* 0x24 */ + + /*** ASC_CMD 3EC: command/status; rw, mirror in ram + *** W: 7 6 5 4 3 2 1 0 + *** . - - . . . . . + *** b0: 1: light on & get resolution, 0: light off + *** b1: 0: load scan len (sub_16, with b4=1, b7=1) + *** b2: 1/0 : dma stuff + *** b3: 0/1 : dma stuff + *** b4: 1 : load scan len (sub_16, with b1=0, b7=1) + *** b5: ? + *** b6: ? + *** b7: ? : set at beginning of sub_16 + ***/ +#define ASC_CMD (scu->base + 1) + +#define ASC_LIGHT_ON 0x01 +#define ASC_SET_B2 0x04 +#define ASC_OPERATE 0x91 /* from linux driver... */ +#define ASC_STANDBY 0x05 /* from linux driver... */ + + /*** ASC_LEN_L, ASC_LEN_H 3ED, 3EE: transfer length, lsb first ***/ +#define ASC_LEN_L ((scu->base)+2) +#define ASC_LEN_H ((scu->base)+3) + + /*** 3EE ASC_PROBE (must read ASC_PROBE_VALUE) ***/ +#define ASC_PROBE ((scu->base)+3) +#define ASC_PROBE_VALUE 0xA5 + + /*** ASC_BOH 3EF: always write 0 at the moment, read some values ? ***/ +#define ASC_BOH ((scu->base)+4) diff --git a/sys/pci/meteor.c b/sys/pci/meteor.c new file mode 100644 index 0000000000000..dac5eab12ce2d --- /dev/null +++ b/sys/pci/meteor.c @@ -0,0 +1,1245 @@ +/* + * Copyright (c) 1995 Mark Tinguely and Jim Lowe + * All rights reserved. + * + * 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 above copyright + * notice, this list of conditions and the following disclaimer. + * 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 Mark Tinguely and Jim Lowe + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 THE AUTHOR 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. + */ + +/* Change History: + 8/21/95 Release + 8/23/95 On advice from Stefan Esser, added volatile to PCI + memory pointers to remove PCI caching . + 8/29/95 Fixes suggested by Bruce Evans. + meteor_mmap should return -1 on error rather than 0. + unit # > NMETEOR should be unit # >= NMETEOR. +*/ + +#include "meteor.h" + +#if NMETEOR > 0 + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/protosw.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/errno.h> +#include <sys/malloc.h> +#include <sys/kernel.h> +#include <sys/proc.h> +#include <sys/signalvar.h> +#include <sys/devconf.h> +#include <sys/mman.h> +#include <machine/clock.h> + +#include <vm/vm.h> +#include <vm/vm_kern.h> +#include <vm/vm_param.h> + +#include <pci.h> +#if NPCI > 0 +#include <pci/pcivar.h> +#endif +#include <machine/ioctl_meteor.h> + + /* enough memory for 640x48 RGB16, or YUV (16 storage bits/pixel) or + 450x340 RGB24 (32 storage bits/pixel) + options "METEOR_ALLOC_PAGES=" + */ +#ifndef METEOR_ALLOC_PAGES +#define METEOR_ALLOC_PAGES 151 +#endif +#define METEOR_ALLOC (METEOR_ALLOC_PAGES * PAGE_SIZE) + +#define NUM_SAA7116_PCI_REGS 37 +#define NUM_SAA7196_I2C_REGS 49 + +typedef struct { + vm_offset_t virt_baseaddr; /* saa7116 register virtual address */ + vm_offset_t phys_baseaddr; /* saa7116 register physical address */ + vm_offset_t capt_cntrl; /* capture control register offset 0x40 */ + vm_offset_t stat_reg; /* status register offset 0x60 */ + vm_offset_t iic_virt_addr; /* ICC bus register offset 0x64 */ + pcici_t tag; /* PCI tag, for doing PCI commands */ + vm_offset_t bigbuf; /* buffer that holds the captured image */ + int alloc_pages; /* number of pages in bigbuf */ + struct proc *proc; /* process to receive raised signal */ + struct meteor_mem *mem; /* used to control sync. multi-frame output */ + u_long hiwat_cnt; /* mark and count frames lost due to hiwat */ + short ecurrent; /* even frame number in buffer (1-frames) */ + short ocurrent; /* odd frame number in buffer (1-frames) */ + short rows; /* number of rows in a frame */ + short cols; /* number of columns in a frame */ + short depth; /* number of byte per pixel */ + short frames; /* number of frames allocated */ + int frame_size; /* number of bytes in a frame */ + u_long fifo_errors; /* number of fifo capture errors since open */ + u_long dma_errors; /* number of DMA capture errors since open */ + u_long frames_captured;/* number of frames captured since open */ + unsigned flags; +#define METEOR_INITALIZED 0x00000001 +#define METEOR_OPEN 0x00000002 +#define METEOR_MMAP 0x00000004 +#define METEOR_INTR 0x00000008 +#define METEOR_READ 0x00000010 +#define METEOR_SINGLE 0x00000020 +#define METEOR_CONTIN 0x00000040 +#define METEOR_SYNCAP 0x00000080 +#define METEOR_CAP_MASK 0x000000f0 +#define METEOR_NTSC 0x00000100 +#define METEOR_PAL 0x00000200 +#define METEOR_SECAM 0x00000400 +#define METEOR_AUTOMODE 0x00000800 +#define METEOR_FORM_MASK 0x00000f00 +#define METEOR_DEV0 0x00001000 +#define METEOR_DEV1 0x00002000 +#define METEOR_DEV2 0x00004000 +#define METEOR_DEV3 0x00008000 +#define METEOR_DEV_MASK 0x0000f000 +#define METEOR_RGB16 0x00010000 +#define METEOR_RGB24 0x00020000 +#define METEOR_YUV_PACKED 0x00040000 +#define METEOR_YUV_PLANER 0x00080000 +#define METEOR_PRO_MASK 0x000f0000 +#define METEOR_SINGLE_EVEN 0x00100000 +#define METEOR_SINGLE_ODD 0x00200000 +#define METEOR_SINGLE_MASK 0x00300000 + u_char saa7196_i2c[NUM_SAA7196_I2C_REGS]; /* saa7196 register values */ +} meteor_reg_t; + +meteor_reg_t meteor[NMETEOR]; + +u_long read_intr_wait; +#define METPRI (PZERO+8)|PCATCH + +/*--------------------------------------------------------- +** +** Meteor PCI probe and initialization routines +** +**--------------------------------------------------------- +*/ + +static char* met_probe (pcici_t tag, pcidi_t type); +static void met_attach(pcici_t tag, int unit); +static u_long met_count; + +struct pci_device met_device = { + "meteor", + met_probe, + met_attach, + &met_count +}; + +DATA_SET (pcidevice_set, met_device); + +static u_long saa7116_pci_default[NUM_SAA7116_PCI_REGS] = { + /* PCI Memory registers */ + /* BITS Type Description */ +/* 0x00 */ 0x00000000, /* 31:1 e*RW DMA 1 (Even) + 0 RO 0x0 */ +/* 0x04 */ 0x00000000, /* 31:2 e*RW DMA 2 (Even) + 1:0 RO 0x0 */ +/* 0x08 */ 0x00000000, /* 31:2 e*RW DMA 3 (Even) + 1:0 RO 0x0 */ +/* 0x0c */ 0x00000000, /* 31:1 o*RW DMA 1 (Odd) + 0 RO 0x0 */ +/* 0x10 */ 0x00000000, /* 31:2 o*RW DMA 2 (Odd) + 1:0 RO 0x0 */ +/* 0x14 */ 0x00000000, /* 31:2 o*RW DMA 3 (Odd) + 1:0 RO 0x0 */ +/* 0x18 */ 0x00000500, /* 15:2 e*RW Stride 1 (Even) + 1:0 RO 0x0 */ +/* 0x1c */ 0x00000000, /* 15:2 e*RW Stride 2 (Even) + 1:0 RO 0x0 */ +/* 0x20 */ 0x00000000, /* 15:2 e*RW Stride 3 (Even) + 1:0 RO 0x0 */ +/* 0x24 */ 0x00000500, /* 15:2 o*RW Stride 1 (Odd) + 1:0 RO 0x0 */ +/* 0x28 */ 0x00000000, /* 15:2 o*RW Stride 2 (Odd) + 1:0 RO 0x0 */ +/* 0x2c */ 0x00000000, /* 15:2 o*RW Stride 3 (Odd) + 1:0 RO 0x0 */ +/* 0x30 */ 0xeeeeee01, /* 31:8 *RW Route (Even) + 7:0 *RW Mode (Even) */ +/* 0x34 */ 0xeeeeee01, /* 31:8 *RW Route (Odd) + 7:0 *RW Mode (Odd) */ +/* 0x38 */ 0x00200020, /* 22:16 *RW FIFO Trigger Planer Mode, + 6:0 *RW FIFO Trigger Packed Mode */ +/* 0x3c */ 0x00000103, /* 9:8 *RW Reserved (0x0) + 2 *RW Field Toggle + 1 *RW Reserved (0x1) + 0 *RW Reserved (0x1) */ +/* 0x40 */ 0x000000c0, /* 15 *RW Range Enable + 14 *RW Corrupt Disable + 11 *RR Address Error (Odd) + 10 *RR Address Error (Even) + 9 *RR Field Corrupt (Odd) + 8 *RR Field Corrupt (Even) + 7 *RW Fifo Enable + 6 *RW VRSTN# + 5 *RR Field Done (Odd) + 4 *RR Field Done (Even) + 3 *RS Single Field Capture (Odd) + 2 *RS Single Field Capture (Even) + 1 *RW Capture (ODD) Continous + 0 *RW Capture (Even) Continous */ + +/* 0x44 */ 0x00000000, /* 7:0 *RW Retry Wait Counter */ +/* 0x48 */ 0x00000307, /* 10 *RW Interrupt mask, start of field + 9 *RW Interrupt mask, end odd field + 8 *RW Interrupt mask, end even field + 2 *RR Interrupt status, start of field + 1 *RR Interrupt status, end of odd + 0 *RR Interrupt status, end of even */ +/* 0x4c */ 0x00000001, /* 31:0 *RW Field Mask (Even) continous */ +/* 0x50 */ 0x00000001, /* 31:0 *RW Field Mask (Odd) continous */ +/* 0x54 */ 0x00000000, /* 20:16 *RW Mask Length (Odd) + 4:0 *RW Mask Length (Even) */ +/* 0x58 */ 0x0005007c, /* 22:16 *RW FIFO almost empty + 6:0 *RW FIFO almost full */ +/* 0x5c */ 0x461e1e0f, /* 31:24 *RW I2C Phase 4 + 23:16 *RW I2C Phase 3 + 15:8 *RW I2C Phase 2 + 7:0 *RW I2C Phase 1 */ +/* 0x60 */ 0x00000300, /* 31:24 *RO I2C Read Data + 23:16 **RW I2C Auto Address + 11 RO I2C SCL Input + 10 RO I2C SDA Input + 9 RR I2C Direct Abort + 8 RR I2C Auto Abort + 3 RW I2C SCL Output + 2 RW I2C SDA Output + 1 RW I2C Bypass + 0 RW I2C Auto Enable */ +/* 0x64 */ 0x00000000, /* 24 RS I2C New Cycle + 23:16 **RW I2C Direct Address + 15:8 **RW I2C Direct Sub-address + 7:0 **RW I2C Direct Write Address */ +/* 0x68 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 1 (Even) + 23:16 **RW I2C Auto Data 1 (Even) + 15:8 **RW I2C Auto Sub-address 0 (Even) + 7:0 **RW I2C Auto Data 0 (Even) */ +/* 0x6c */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 3 (Even) + 23:16 **RW I2C Auto Data 3 (Even) + 15:8 **RW I2C Auto Sub-address 2 (Even) + 7:0 **RW I2C Auto Data 2 (Even) */ +/* 0x70 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 5 (Even) + 23:16 **RW I2C Auto Data 5 (Even) + 15:8 **RW I2C Auto Sub-address 4 (Even) + 7:0 **RW I2C Auto Data 4 (Even) */ +/* 0x74 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 7 (Even) + 23:16 **RW I2C Auto Data 7 (Even) + 15:8 **RW I2C Auto Sub-address 6 (Even) + 7:0 **RW I2C Auto Data 6 (Even) */ +/* 0x78 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 1 (Odd) + 23:16 **RW I2C Auto Data 1 (Odd) + 15:8 **RW I2C Auto Sub-address 0 (Odd) + 7:0 **RW I2C Auto Data 0 (Odd) */ +/* 0x7c */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 3 (Odd) + 23:16 **RW I2C Auto Data 3 (Odd) + 15:8 **RW I2C Auto Sub-address 2 (Odd) + 7:0 **RW I2C Auto Data 2 (Odd) */ +/* 0x80 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 5 (Odd) + 23:16 **RW I2C Auto Data 5 (Odd) + 15:8 **RW I2C Auto Sub-address 4 (Odd) + 7:0 **RW I2C Auto Data 4 (Odd) */ +/* 0x84 */ 0x00000000, /* 31:24 **RW I2C Auto Sub-address 7 (Odd) + 23:16 **RW I2C Auto Data 7 (Odd) + 15:8 **RW I2C Auto Sub-address 6 (Odd) + 7:0 **RW I2C Auto Data 6 (Odd) */ +/* 0x88 */ 0x00000000, /* 23:16 **RW I2C Register Enable (Odd) + 7:0 **RW I2C Register Enable (Even) */ +/* 0x8c */ 0x00000000, /* 23:2 e*RW DMA End (Even) + 1:0 RO 0x0 */ +/* 0x90 */ 0x00000000 /* 23:2 e*RW DMA End (Odd) + 1:0 RO 0x0 */ +}; + +static u_char saa7196_i2c_default[NUM_SAA7196_I2C_REGS] = { + /* SAA7196 I2C bus control */ + /* BITS Function */ +/* 00 */ 0x50, /* 7:0 Increment Delay */ +/* 01 */ 0x7f, /* 7:0 Horizontal Sync Begin for 50hz */ +/* 02 */ 0x53, /* 7:0 Horizontal Sync Stop for 50hz */ +/* 03 */ 0x43, /* 7:0 Horizontal Sync Clamp Start for 50hz */ +/* 04 */ 0x19, /* 7:0 Horizontal Sync Clamp Stop for 50hz */ +/* 05 */ 0x00, /* 7:0 Horizontal Sync Start after PH1 for 50hz */ +/* 06 */ 0x46, /* 7 Input mode =0 CVBS, =1 S-Video + 6 Pre filter + 5:4 Aperture Bandpass characteristics + 3:2 Coring range for high freq + 1:0 Aperture bandpass filter weights */ +/* 07 */ 0x00, /* 7:0 Hue */ +/* 08 */ 0x7f, /* 7:3 Colour-killer threshold QAM (PAL, NTSC) */ +/* 09 */ 0x7f, /* 7:3 Colour-killer threshold SECAM */ +/* 0a */ 0x7f, /* 7:0 PAL switch sensitivity */ +/* 0b */ 0x7f, /* 7:0 SECAM switch sensitivity */ +/* 0c */ 0x40, /* 7 Colour-on bit + 6:5 AGC filter */ +/* 0d */ 0x84, /* 7 VTR/TV mode bit = 1->VTR mode + 3 Realtime output mode select bit + 2 HREF position select + 1 Status byte select + 0 SECAM mode bit */ +/* 0e */ 0x38, /* 7 Horizontal clock PLL + 5 Select interal/external clock source + 4 Output enable of Horizontal/Vertical sync + 3 Data output YUV enable + 2 S-VHS bit + 1 GPSW2 + 0 GPSW1 */ +/* 0f */ 0x50, /* 7 Automatic Field detection + 6 Field Select 0 = 50hz, 1=60hz + 5 SECAM cross-colour reduction + 4 Enable sync and clamping pulse + 3:1 Luminance delay compensation */ +/* 10 */ 0x00, /* 2 Select HREF Position + 1:0 Vertical noise reduction */ +/* 11 */ 0x2c, /* 7:0 Chrominance gain conrtol for QAM */ +/* 12 */ 0x40, /* 7:0 Chrominance saturation control for VRAM port */ +/* 13 */ 0x40, /* 7:0 Luminance contract control for VRAM port */ +/* 14 */ 0x34, /* 7:0 Horizontal sync begin for 60hz */ +/* 15 */ 0x0c, /* 7:0 Horizontal sync stop for 60hz */ +/* 16 */ 0xfb, /* 7:0 Horizontal clamp begin for 60hz */ +/* 17 */ 0xd4, /* 7:0 Horizontal clamp stop for 60hz */ +/* 18 */ 0xec, /* 7:0 Horizontal sync start after PH1 for 60hz */ +/* 19 */ 0x80, /* 7:0 Luminance brightness control for VRAM port */ +/* 1a */ 0x00, +/* 1b */ 0x00, +/* 1c */ 0x00, +/* 1d */ 0x00, +/* 1e */ 0x00, +/* 1f */ 0x00, +/* 20 */ 0x90, /* 7 ROM table bypass switch + 6:5 Set output field mode + 4 VRAM port outputs enable + 3:2 First pixel position in VRO data + 1:0 FIFO output register select */ +/* 21 */ 0x80, /* 7:0 [7:0] Pixel number per line on output */ +/* 22 */ 0x80, /* 7:0 [7:0] Pixel number per line on input */ +/* 23 */ 0x03, /* 7:0 [7:0] Horizontal start position of scaling win*/ +/* 24 */ 0x8a, /* 7:5 Horizontal decimation filter + 4 [8] Horizontal start position of scaling win + 3:2 [9:8] Pixel number per line on input + 1:0 [9:8] Pixel number per line on output */ +/* 25 */ 0xf0, /* 7:0 [7:0] Line number per output field */ +/* 26 */ 0xf0, /* 7:0 [7:0] Line number per input field */ +/* 27 */ 0x0f, /* 7:0 [7:0] Vertical start of scaling window */ +/* 28 */ 0x80, /* 7 Adaptive filter switch + 6:5 Vertical luminance data processing + 4 [8] Vertical start of scaling window + 3:2 [9:8] Line number per input field + 1:0 [9:8] Line number per output field */ +/* 29 */ 0x16, /* 7:0 [7:0] Vertical bypass start */ +/* 2a */ 0x00, /* 7:0 [7:0] Vertical bypass count */ +/* 2b */ 0x00, /* 4 [8] Vertical bypass start + 2 [8] Vertical bypass count + 0 Polarity, internally detected odd even flag */ +/* 2c */ 0x80, /* 7:0 Set lower limit V for colour-keying */ +/* 2d */ 0x7f, /* 7:0 Set upper limit V for colour-keying */ +/* 2e */ 0x80, /* 7:0 Set lower limit U for colour-keying */ +/* 2f */ 0x7f, /* 7:0 Set upper limit U for colour-keying */ +/* 30 */ 0xbf /* 7 VRAM bus output format + 6 Adaptive geometrical filter + 5 Luminance limiting value + 4 Monochrome and two's complement output data sel + 3 Line quailifier flag + 2 Pixel qualifier flag + 1 Transparent data transfer + 0 Extended formats enable bit */ +}; + +/* + * i2c_write: + * Returns 0 Succesful completion. + * Returns 1 If transfer aborted or timeout occured. + * + */ +#define SAA7196_I2C_ADDR 0x40 +#define I2C_WRITE 0x00 +#define I2C_READ 0x01 +#define SAA7116_IIC_NEW_CYCLE 0x1000000L +#define IIC_DIRECT_TRANSFER_ABORTED 0x0000200L + +#define SAA7196_WRITE(mtr, reg, data) \ + i2c_write(mtr, SAA7196_I2C_ADDR, I2C_WRITE, reg, data); \ + mtr->saa7196_i2c[reg] = data +#define SAA7196_REG(mtr, reg) mtr->saa7196_i2c[reg] +#define SAA7196_READ(mtr) \ + i2c_write(mtr, SAA7196_I2C_ADDR, I2C_READ, 0x0, 0x0) + +static int +i2c_write(meteor_reg_t * mtr, u_char slave, u_char rw, u_char reg, u_char data) +{ +register unsigned long wait_counter = 0x0001ffff; +register volatile u_long *iic_write_loc = (volatile u_long *)mtr->iic_virt_addr; +register int err = 0; + + /* Write the data the the i2c write register */ + *iic_write_loc = SAA7116_IIC_NEW_CYCLE | + (((u_long)slave|(u_long)rw) << 16) | + ((u_long)reg << 8) | (u_long)data; + + /* Wait until the i2c cycle is compeleted */ + while((*iic_write_loc & SAA7116_IIC_NEW_CYCLE)) { + if(!wait_counter) break; + wait_counter--; + } + +/*#ifdef notdef*/ + /* it seems the iic_write_loc is cached, until we can + figure out how to uncache the pci registers, then we + will just ignore the timeout. Hopefully 1ffff will + be enough delay time for the i2c cycle to complete */ + if(!wait_counter) { + printf("meteor: saa7116 i2c %s transfer timeout 0x%x", + rw ? "read" : "write", *iic_write_loc); + + err=1; + } +/*#endif*/ + + /* Check for error on direct write, clear if any */ + if((*((volatile u_long *)mtr->stat_reg)) & IIC_DIRECT_TRANSFER_ABORTED) { + printf("meteor: saa7116 i2c %s tranfer aborted", + rw ? "read" : "write" ); + err= 1; + } + + if(err) { + printf(" - reg=0x%x, value=0x%x.\n", reg, data); + } + + return err; +} + + +static char* +met_probe (pcici_t tag, pcidi_t type) +{ + switch (type) { + + case 0x12238086ul: /* meteor */ + return ("Matrox Meteor"); + + }; + return ((char*)0); +} + + /* interrupt handling routine + complete meteor_read() if using interrupts + */ +int +meteor_intr( void *arg) +{ + register meteor_reg_t *mtr = (meteor_reg_t *) arg; + + register volatile u_long *cap, *base, *status, cap_err; + struct meteor_mem *mm; + + base = (volatile u_long *) mtr->virt_baseaddr; + cap = (volatile u_long *) mtr->capt_cntrl; /* capture control ptr */ + status = base + 18; /* mtr->virt_base + 0x48 save a dereference */ + + /* the even field has to make the decision of whether the high water + has been reached. If hiwat has been reach do not advance the buffer. + continue to save frames on this buffer until we can advance again */ + if (*status & 0x1) { /* even field */ + if (mtr->flags & METEOR_SYNCAP) { + mm = mtr->mem; /* shared SYNCAP struct */ + if ((!mtr->hiwat_cnt && mm->num_active_bufs < mm->hiwat) || + (mm->num_active_bufs <= mm->lowat)) { + mtr->hiwat_cnt = 0; + if (++mtr->ecurrent > mtr->frames) { + *base = mtr->bigbuf; + mtr->ecurrent = 1; + } else { + *base = *base + mtr->frame_size; + } + } + else { + mtr->hiwat_cnt++; + } + } else if(mtr->flags & METEOR_SINGLE) { + *cap &= 0x0ffe; + mtr->flags &= ~METEOR_SINGLE_EVEN; + if(!(mtr->flags & METEOR_SINGLE_MASK)) { + mtr->frames_captured++ ; + wakeup((caddr_t) &read_intr_wait); + } + } + } else { /* odd field */ + if (mtr->flags & METEOR_SINGLE) { + *cap &= 0x0ffd; + mtr->flags &= ~ METEOR_SINGLE_ODD; + if(!(mtr->flags & METEOR_SINGLE_MASK)) { + mtr->frames_captured++ ; + wakeup((caddr_t) &read_intr_wait); + } + } else if (mtr->flags & METEOR_SYNCAP) { + mm = mtr->mem; /* shared SYNCAP struct */ + /* even field decided to advance or not, we + simply add stride to that decision */ + *(base+3) = *base + *(base + 6); + if (mtr->ecurrent != mtr->ocurrent) { + mm->active |= (1 << (mtr->ocurrent-1)); + mtr->ocurrent = mtr->ecurrent; + mm->num_active_bufs++; + if (mtr->proc && mm->signal) { + mtr->frames_captured++ ; + psignal(mtr->proc, mm->signal); + } + } + } + } + if (cap_err = (*cap & 0xf00)) { + if (cap_err & 0x3) + mtr->fifo_errors++ ; /* incrememnt fifo capture errors cnt */ + if (cap_err & 0xc) + mtr->dma_errors++ ; /* increment DMA capture errors cnt */ + } + + *cap |= 0xf30; /* clear error and field done */ + *status |= 0xf; /* clear interrupt status */ + + return(1); +} + +/* + * Initialize the capture card to NTSC RGB 16 640x480 + */ +static void +meteor_init ( meteor_reg_t *mtr ) +{ + volatile u_long *vbase_addr; + int i; + + *((volatile u_long *)(mtr->capt_cntrl)) = 0x00000040L; + + vbase_addr = (volatile u_long *) mtr->virt_baseaddr; + for (i= 0 ; i < NUM_SAA7116_PCI_REGS; i++) + *vbase_addr++ = saa7116_pci_default[i]; + + for (i = 0; i < NUM_SAA7196_I2C_REGS; i++) { + SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]); + } + +} + +static void met_attach(pcici_t tag, int unit) +{ +#ifdef METEOR_IRQ /* from the meteor.h file */ + u_long old_irq,new_irq; + +#endif METEOR_IRQ /* from the meteor.h file */ + meteor_reg_t *mtr; + vm_offset_t buf; + + if (unit >= NMETEOR) { + printf("meteor_attach: mx%d: invalid unit number\n"); + return ; + } + + mtr = &meteor[unit]; + pci_map_mem(tag, 0x10, &(mtr->virt_baseaddr), + &(mtr->phys_baseaddr)); + /* IIC addres at 0x64 offset bytes */ + mtr->capt_cntrl = mtr->virt_baseaddr + 0x40; + mtr->stat_reg = mtr->virt_baseaddr + 0x60; + mtr->iic_virt_addr = mtr->virt_baseaddr + 0x64; + +#ifdef METEOR_IRQ /* from the meteor.h file */ + old_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); + pci_conf_write(tag, PCI_INTERRUPT_REG, METEOR_IRQ); + new_irq = pci_conf_read(tag, PCI_INTERRUPT_REG); + printf("meteor_attach: irq changed from %d to %d\n", (old_irq & 0xff), + (new_irq & 0xff)); +#endif METEOR_IRQ + + meteor_init( mtr ); /* set up saa7116 and saa7196 chips */ + mtr->tag = tag; + /* setup the interrupt handling routine */ + pci_map_int (tag, meteor_intr, (void*) mtr, &net_imask); + + /* 640*240*3 round up to nearest pag e*/ + buf = vm_page_alloc_contig(METEOR_ALLOC, 0x100000, 0xffffffff, PAGE_SIZE); + if (buf == NULL) { + printf("meteor_attach: big buffer allocation failed\n"); + return; + } + mtr->bigbuf = buf; + mtr->alloc_pages = METEOR_ALLOC_PAGES; + + bzero((caddr_t) buf, METEOR_ALLOC); + + buf = vtophys(buf); + *((volatile u_long *) mtr->virt_baseaddr) = buf; + + /* 640x480 RGB 16 */ + *((volatile u_long *) mtr->virt_baseaddr + 3) = buf + 0x500; + + *((volatile u_long *) mtr->virt_baseaddr + 36) = + *((volatile u_long *) mtr->virt_baseaddr + 35) = buf + METEOR_ALLOC; + mtr->flags = METEOR_INITALIZED | METEOR_NTSC | METEOR_DEV0 | + METEOR_RGB16; + /* 1 frame of 640x480 RGB 16 */ + mtr->cols = 640; + mtr->rows = 480; + mtr->depth = 2; /* two bytes per pixel */ + mtr->frames = 1; /* one frame */ +} + +static void +meteor_reset(meteor_reg_t * const sc) +{ + +} + +/*--------------------------------------------------------- +** +** Meteor character device driver routines +** +**--------------------------------------------------------- +*/ + +#define UNIT(x) ((x) & 0x07) + +int +meteor_open(dev_t dev, int flags, int fmt, struct proc *p) +{ + meteor_reg_t *mtr; + int unit; + int i; + + unit = UNIT(minor(dev)); + if (unit >= NMETEOR) /* unit out of range */ + return(ENXIO); + + mtr = &(meteor[unit]); + + if (!(mtr->flags & METEOR_INITALIZED)) /* device not found */ + return(ENXIO); + + if (mtr->flags & METEOR_OPEN) /* device is busy */ + return(EBUSY); + + mtr->flags |= METEOR_OPEN; + /* + * Make sure that the i2c regs are set the same for each open. + */ + for(i=0; i< NUM_SAA7196_I2C_REGS; i++) { + SAA7196_WRITE(mtr, i, saa7196_i2c_default[i]); + } + + mtr->fifo_errors = 0; + mtr->dma_errors = 0; + mtr->frames_captured = 0; + + return(0); +} + +int +meteor_close(dev_t dev, int flags, int fmt, struct proc *p) +{ + meteor_reg_t *mtr; + int unit; + int temp; + + unit = UNIT(minor(dev)); + if (unit >= NMETEOR) /* unit out of range */ + return(ENXIO); + + mtr = &(meteor[unit]); + mtr->flags &= ~METEOR_OPEN; + + /* XXX stop any capture modes running */ + switch (mtr->flags & METEOR_CAP_MASK) { + case METEOR_SINGLE: /* this should not happen, the read capture + should have completed or in the very least + recieved a signal before close is called. */ + mtr->flags &= ~(METEOR_SINGLE|METEOR_SINGLE_MASK); + wakeup((caddr_t) &read_intr_wait); /* continue read */ + break; + + case METEOR_CONTIN: /* continous unsync-ed reading, we can + simply turn off the capture */ + mtr->flags &= ~METEOR_CONTIN; + *((volatile u_long *) mtr->capt_cntrl) = 0x0ff0; /* turn off capture */ + break; + case METEOR_SYNCAP: + mtr->flags &= ~METEOR_SYNCAP; + *((volatile u_long *) mtr->capt_cntrl) = 0x0ff0; /* turn off capture */ + mtr->proc = NULL; + mtr->mem = NULL; + mtr->ecurrent = mtr->ocurrent = 1; + /* re-initalize the even/odd DMA positions to top of buffer */ + *((volatile u_long *) mtr->virt_baseaddr) = mtr->bigbuf; + *((volatile u_long *) mtr->virt_baseaddr +3) = + *((volatile u_long *) mtr->virt_baseaddr) + + *((volatile u_long *) mtr->virt_baseaddr+6); + break; + case 0: + break; + default: + printf("meteor_close: bad capture state on close %d\n", + mtr->flags & METEOR_CAP_MASK); + } +#ifdef METEOR_DEALLOC_PAGES + if (mtr->bigbuf) { + kmem_free(kernel_map,mtr->bigbuf,(mtr->alloc_pages*PAGE_SIZE)); + mtr->bigbuf = NULL; + mtr->alloc_pages = 0; + } +#else +#ifdef METEOR_DEALLOC_ABOVE + if (mtr->bigbuf && mtr->alloc_pages > METEOR_DEALLOC_ABOVE) { + temp = METEOR_DEALLOC_ABOVE - mtr->alloc_pages; + kmem_free(kernel_map, + mtr->bigbuf+((mtr->alloc_pages - temp) * PAGE_SIZE), + (temp * PAGE_SIZE)); + mtr->alloc_pages = METEOR_DEALLOC_ABOVE; + } +#endif +#endif + return(0); +} + +int +meteor_read(dev_t dev, struct uio *uio, int ioflag) +{ + meteor_reg_t *mtr; + int unit; + int status; + int count; + + unit = UNIT(minor(dev)); + if (unit >= NMETEOR) /* unit out of range */ + return(ENXIO); + + mtr = &(meteor[unit]); + if (!mtr->bigbuf) /* no frame buffer allocated (ioctl failed) */ + return(ENXIO); + + if (mtr->flags & METEOR_CAP_MASK) + return(EIO); /* already capturing */ + + count = mtr->rows * mtr->cols * mtr->depth; + if (uio->uio_iov->iov_len < count) + return(EINVAL); + + mtr->flags |= METEOR_SINGLE | METEOR_SINGLE_MASK; + + *((volatile u_long *) mtr->capt_cntrl) = 0x0ff3; /* capture */ + + status = tsleep((caddr_t) &read_intr_wait, METPRI, "capturing", 0); + + if (!status) /* successful capture */ + status = uiomove((caddr_t)mtr->bigbuf, count, uio); + + else + printf ("meteor_read: bad tsleep\n"); + mtr->flags &= ~(METEOR_SINGLE | METEOR_SINGLE_MASK); + return(status); +} + +int +meteor_write(dev_t dev, struct uio *uio, int ioflag) +{ + return(0); +} + +int +meteor_ioctl(dev_t dev, int cmd, caddr_t arg, int flag, struct proc *pr) +{ + int error; + int unit; + int temp; + meteor_reg_t *mtr; + struct meteor_counts *cnt; + struct meteor_geomet *geo; + struct meteor_mem *mem; + struct meteor_capframe *frame; + volatile u_long *p; + vm_offset_t buf; + + error = 0; + + if (!arg) return(EINVAL); + unit = UNIT(minor(dev)); + if (unit >= NMETEOR) /* unit out of range */ + return(ENXIO); + + mtr = &(meteor[unit]); + + switch (cmd) { + case METEORSTATUS: /* get 7196 status */ + temp = 0; + SAA7196_WRITE(mtr, 0x0d, SAA7196_REG(mtr, 0x0d) | 0x02); + SAA7196_READ(mtr); + temp |= ((*((volatile u_long *)mtr->stat_reg)) & 0xff000000L) >> 24; + SAA7196_WRITE(mtr, 0x0d, SAA7196_REG(mtr, 0x0d) & 0x02); + SAA7196_READ(mtr); + temp |= ((*((volatile u_long *)mtr->stat_reg)) & 0xff000000L) >> 16; + *(u_short *)arg = temp; + break; + case METEORSHUE: /* set hue */ + SAA7196_WRITE(mtr, 0x07, *(char *)arg); + break; + case METEORGHUE: /* get hue */ + *(char *)arg = SAA7196_REG(mtr, 0x07); + break; + case METEORSCHCV: /* set chrominance gain */ + SAA7196_WRITE(mtr, 0x11, *(char *)arg); + break; + case METEORGCHCV: /* get chrominance gain */ + *(char *)arg = SAA7196_REG(mtr, 0x11); + break; + case METEORSINPUT: /* set input device */ + switch(*(unsigned long *)arg & METEOR_DEV_MASK) { + case 0: /* default */ + case METEOR_INPUT_DEV0: + mtr->flags = (mtr->flags & ~METEOR_DEV_MASK) + | METEOR_DEV0; + + SAA7196_WRITE(mtr, 0x0e, + (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x0); + break; + case METEOR_INPUT_DEV1: + mtr->flags = (mtr->flags & ~METEOR_DEV_MASK) + | METEOR_DEV1; + SAA7196_WRITE(mtr, 0x0e, + (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x1); + break; + case METEOR_INPUT_DEV2: + mtr->flags = (mtr->flags & ~METEOR_DEV_MASK) + | METEOR_DEV2; + SAA7196_WRITE(mtr, 0x0e, + (SAA7196_REG(mtr, 0x0e) & ~0x3) | 0x2); + break; + case METEOR_INPUT_DEV3: + mtr->flags = (mtr->flags & ~METEOR_DEV_MASK) + | METEOR_DEV3; + SAA7196_WRITE(mtr, 0x0e, + (SAA7196_REG(mtr, 0x0e) | 0x3)); + break; + default: + return EINVAL; + } + break; + case METEORGINPUT: /* get input device */ + *(u_long *)arg = mtr->flags & METEOR_DEV_MASK; + break; + case METEORSFMT: /* set input format */ + switch(*(unsigned long *)arg & METEOR_FORM_MASK ) { + case 0: /* default */ + case METEOR_FMT_NTSC: + mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) | + METEOR_NTSC; + SAA7196_WRITE(mtr, 0x0d, + (SAA7196_REG(mtr, 0x0d) & ~0x01)); + SAA7196_WRITE(mtr, 0x0f, + (SAA7196_REG(mtr, 0x0f) & ~0xc0) | 0x40); + SAA7196_WRITE(mtr, 0x22, 0x80); + SAA7196_WRITE(mtr, 0x24, + (SAA7196_REG(mtr, 0x24) & ~0x0c) | 0x08); + SAA7196_WRITE(mtr, 0x26, 0xf0); + SAA7196_WRITE(mtr, 0x28, + (SAA7196_REG(mtr, 0x28) & ~0x0c)) ; + break; + case METEOR_FMT_PAL: + mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) | + METEOR_PAL; + SAA7196_WRITE(mtr, 0x0d, + (SAA7196_REG(mtr, 0x0d) & ~0x01)); + SAA7196_WRITE(mtr, 0x0f, + (SAA7196_REG(mtr, 0x0f) & ~0xc0)); + SAA7196_WRITE(mtr, 0x22, 0x00); + SAA7196_WRITE(mtr, 0x24, + (SAA7196_REG(mtr, 0x24) | 0x0c)); + SAA7196_WRITE(mtr, 0x26, 0x20); + SAA7196_WRITE(mtr, 0x28, + (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x01) ; + break; + case METEOR_FMT_SECAM: + mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) | + METEOR_SECAM; + SAA7196_WRITE(mtr, 0x0d, + (SAA7196_REG(mtr, 0x0d) & ~0x01) | 0x1); + SAA7196_WRITE(mtr, 0x0f, + (SAA7196_REG(mtr, 0x0f) & ~0xe0) | 0xe0); + SAA7196_WRITE(mtr, 0x22, 0x00); + SAA7196_WRITE(mtr, 0x24, + (SAA7196_REG(mtr, 0x24) | 0x0c)); + SAA7196_WRITE(mtr, 0x26, 0x20); + SAA7196_WRITE(mtr, 0x28, + (SAA7196_REG(mtr, 0x28) & ~0x0c) | 0x01) ; + break; + case METEOR_FMT_AUTOMODE: + mtr->flags = (mtr->flags & ~METEOR_FORM_MASK) | + METEOR_AUTOMODE; + SAA7196_WRITE(mtr, 0x0d, + (SAA7196_REG(mtr, 0x0d) & ~0x01)); + SAA7196_WRITE(mtr, 0x0f, + (SAA7196_REG(mtr, 0x0f) & ~0xc0) | 0xc0); + break; + default: + return EINVAL; + } + break; + case METEORGFMT: /* get input format */ + *(u_long *)arg = mtr->flags & METEOR_FORM_MASK; + break; + case METEORCAPTUR: + switch (*(int *) arg) { + case METEOR_CAP_SINGLE: + if (!mtr->bigbuf) /* no frame buffer allocated */ + return(ENXIO); + + if (mtr->flags & METEOR_CAP_MASK) + return(EIO); /* already capturing */ + + mtr->flags |= METEOR_SINGLE | METEOR_SINGLE_MASK; + + *((volatile u_long *) mtr->capt_cntrl) = 0x0ff3; /* capture */ + + error = tsleep((caddr_t) &read_intr_wait, METPRI, + "capturing", 0); + mtr->flags &= ~(METEOR_SINGLE| METEOR_SINGLE_MASK); + break; + case METEOR_CAP_CONTINOUS: + if (!mtr->bigbuf) /* no frame buffer allocated */ + return(ENXIO); + + if (mtr->flags & METEOR_CAP_MASK) + return(EIO); /* already capturing */ + + mtr->flags |= METEOR_CONTIN; + + *((volatile u_long *) mtr->capt_cntrl) = 0x0ff3; /* capture */ + break; + case METEOR_CAP_STOP_CONT: + if (mtr->flags & METEOR_CONTIN) { + mtr->flags &= ~METEOR_CONTIN; + /* turn off capture */ + *((volatile u_long *) mtr->capt_cntrl) = 0x0ff0; + } + break; + + default: + error = EINVAL; + break; + } + break; + case METEORCAPFRM: + frame = (struct meteor_capframe *) arg; + if (!frame) + return(EINVAL); + switch (frame->command) { + case METEOR_CAP_N_FRAMES: + if (mtr->flags & METEOR_CAP_MASK) + return(EIO); + if (mtr->flags & METEOR_YUV_PLANER) + return(EINVAL); + if (!mtr->bigbuf) + return(ENOMEM); + if ((mtr->frames < 2) || + (frame->lowat < 1 || frame->lowat >= mtr->frames) || + (frame->hiwat < 1 || frame->hiwat >= mtr->frames)) + return(EINVAL); + mtr->flags |= METEOR_SYNCAP; + mtr->proc = pr; + /* meteor_mem structure is on the page after the data */ + mem = mtr->mem = (struct meteor_mem *) (mtr->bigbuf + + ((mtr->rows*mtr->cols * mtr->depth * + mtr->frames+PAGE_SIZE-1)/PAGE_SIZE)*PAGE_SIZE); + mtr->ecurrent = mtr->ocurrent = 1; + mem->signal = frame->signal; + mem->num_bufs = mtr->frames; + mem->frame_size= + mtr->frame_size = mtr->rows * mtr->cols * mtr->depth; + /* user and kernel change these */ + mem->lowat = frame->lowat; + mem->hiwat = frame->hiwat; + mem->active = 0; + mem->num_active_bufs = 0; + *((u_long *) mtr->capt_cntrl) = 0x0ff3; + break; + case METEOR_CAP_STOP_FRAMES: + if (mtr->flags & METEOR_SYNCAP) { + mtr->flags &= ~METEOR_SYNCAP; + /* turn off capture */ + *((u_long *) mtr->capt_cntrl) = 0x0ff0; + mtr->proc = NULL; + mtr->mem = NULL; + mtr->ecurrent = mtr->ocurrent = 0; + + /* re-initalize the even/odd DMA positions to top of buffer*/ + /* XXX if a capture is in progress, this may be trouble */ + + *((volatile u_long *) mtr->virt_baseaddr) = mtr->bigbuf; + *((volatile u_long *) mtr->virt_baseaddr +3) = + *((volatile u_long *) mtr->virt_baseaddr) + + *((volatile u_long *) mtr->virt_baseaddr+6); + } + break; + default: + error = EINVAL; + break; + } + break; + + case METEORSETGEO: + geo = (struct meteor_geomet *) arg; + /* can't change parameters while capturing */ + if (mtr->flags & METEOR_CAP_MASK) + return(EBUSY); + + if ((geo->columns & 0x3fe) != geo->columns) { + printf("meteor ioctl: column too large or not even\n"); + error = EINVAL; + } + if ((geo->rows & 0x7fe) != geo->rows) { + printf("meteor ioctl: rows too large or not even\n"); + error = EINVAL; + } + if (geo->frames > 32) { + printf("meteor ioctl: frames too large\n"); + error = EINVAL; + } + if (!error && (temp=geo->rows*geo->columns * geo->frames *2)) { + if (geo->oformat & METEOR_GEO_RGB24) + temp = temp * 2; + + /* meteor_mem structure for SYNC Capture */ + if (geo->frames > 1) + temp += PAGE_SIZE; + + temp = (temp + PAGE_SIZE -1)/PAGE_SIZE; + if (temp > mtr->alloc_pages) { + if (mtr->bigbuf) + kmem_free(kernel_map, mtr->bigbuf, + (mtr->alloc_pages * PAGE_SIZE)); + mtr->bigbuf = vm_page_alloc_contig((temp*PAGE_SIZE), + 0x100000, 0xffffffff, PAGE_SIZE); + mtr->alloc_pages = temp; + } + if (mtr->bigbuf) { + mtr->rows = geo->rows; + mtr->cols = geo->columns; + mtr->frames = geo->frames; + } + else { + mtr->alloc_pages = 0; + printf("meteor_ioctl: buffer allocation failed\n"); + error = ENOMEM; + } + } + + p = (volatile u_long *) mtr->virt_baseaddr; + if (mtr->bigbuf) + buf = vtophys(mtr->bigbuf); + else + buf = 0; + *p++ = buf; /* even y or even RGB */ + /* set end of buffer location */ + *(p+36) = *(p+35) = buf + mtr->alloc_pages * PAGE_SIZE; + + switch (geo->oformat & METEOR_PRO_MASK) { + case 0: /* default */ + case METEOR_GEO_RGB16: + mtr->depth = 2; + if (mtr->flags & METEOR_RGB16 == 0) { + mtr->flags = (mtr->flags & ~(METEOR_RGB24 | + METEOR_YUV_PACKED | + METEOR_YUV_PLANER)) + | METEOR_RGB16; + } + if (error == 0) { + /* recal stride and odd starting point */ + + *p++ = 0; + *p++ = 0; + *p++ = buf + mtr->cols * 2; + *p++ = 0; + *p++ = 0; + /* stride */ + *p = *(p+3) = mtr->cols * 2; + *(p+6) = *(p+7) = 0xeeeeee01; + /* set up the saa7196 */ + SAA7196_WRITE(mtr, 0x20, 0x90); + } + break; + case METEOR_GEO_RGB24: + mtr->depth = 4; + if (mtr->flags & METEOR_RGB24 == 0) { + mtr->flags = (mtr->flags & ~(METEOR_RGB16 | + METEOR_YUV_PACKED | + METEOR_YUV_PLANER)) + | METEOR_RGB24; + } + if (error == 0 ) { + /* recal stride and odd starting point */ + + *p++ = 0; + *p++ = 0; + *p++ = buf + mtr->cols * 4; + /* routes */ + *p++ = 0; + *p++ = 0; + /* stride */ + *p = *(p+3) = mtr->cols * 4; + /* routes */ + *(p+6) = *(p+7) = 0x39393900; + /* set up the saa7196 */ + SAA7196_WRITE(mtr, 0x20, 0x92); + } + break; + case METEOR_GEO_YUV_PLANER: + mtr->depth = 2; + if (mtr->flags & METEOR_YUV_PLANER == 0) { + mtr->flags = (mtr->flags & ~(METEOR_RGB16 | + METEOR_RGB24 | + METEOR_YUV_PACKED)) + | METEOR_YUV_PLANER; + } + if (error == 0 ) { + /* recal stride and odd starting point */ + + temp = mtr->rows * mtr->cols; + /* even u */ + *p++ = buf + temp; + /* even v */ + *p++ = buf + temp + (temp >> 2); + /* odd y */ + *p++ = buf + mtr->cols; + /* odd u */ + *p++ = buf + temp + (temp >> 1); + /* odd v */ + *p++ = buf + temp + (temp >> 1) + + (temp >> 2); + /* stride */ + *p = *(p+3) = mtr->cols; + /* routes */ + *(p+6) = *(p+7) = 0xaaaaffc1; + /* set up the saa7196 */ + SAA7196_WRITE(mtr, 0x20, 0x91); + } + break; + case METEOR_GEO_YUV_PACKED: + mtr->depth = 2; + if (mtr->flags & METEOR_YUV_PACKED == 0) { + mtr->flags = (mtr->flags & ~(METEOR_RGB16 | + METEOR_RGB24 | + METEOR_YUV_PLANER)) + | METEOR_YUV_PACKED; + } + if (error == 0 ) { + /* recal stride and odd starting point */ + + *p++ = 0; + *p++ = 0; + *p++ = buf + mtr->cols * 2; + *p++ = 0; + *p++ = 0; + /* stride */ + *p = *(p+3) = mtr->cols * 2; + /* routes */ + *(p+6) = *(p+7) = 0xeeeeee41; + /* set up the saa7196 */ + SAA7196_WRITE(mtr, 0x20, 0x91); + } + break; + default: + error = EINVAL; /* invalid arguement */ + printf("meteor_ioctl: invalid output format\n"); + break; + } + if (error == 0 ) { + /* set cols */ + SAA7196_WRITE(mtr, 0x21, mtr->cols & 0xff); + SAA7196_WRITE(mtr, 0x24, + ((SAA7196_REG(mtr, 0x24) & ~0x03) | + ((mtr->cols >> 8) & 0x03))); + /* set rows */ + SAA7196_WRITE(mtr, 0x25, ((mtr->rows >> 1) & 0xff)); + SAA7196_WRITE(mtr, 0x28, + ((SAA7196_REG(mtr, 0x28) & ~0x03) | + ((mtr->rows >> 9) & 0x03))); + } + break; + case METEORGETGEO: + geo = (struct meteor_geomet *) arg; + geo->rows = mtr->rows; + geo->columns = mtr->cols; + geo->frames = mtr->frames; + geo->oformat = mtr->flags & METEOR_PRO_MASK; + break; + case METEORSCOUNT: /* (re)set error counts */ + cnt = (struct meteor_counts *) arg; + mtr->fifo_errors = cnt->fifo_errors; + mtr->dma_errors = cnt->dma_errors; + mtr->frames_captured = cnt->frames_captured; + break; + case METEORGCOUNT: /* get error counts */ + cnt = (struct meteor_counts *) arg; + cnt->fifo_errors = mtr->fifo_errors; + cnt->dma_errors = mtr->dma_errors; + cnt->frames_captured = mtr->frames_captured; + break; + default: + printf("meteor_ioctl: invalid ioctl request\n"); + error = ENOTTY; + break; + } + return(error); +} + +int +meteor_mmap(dev_t dev, int offset, int nprot) +{ + + int unit; + meteor_reg_t *mtr; + + unit = UNIT(minor(dev)); + if (unit >= NMETEOR) + return(-1); + + mtr = &(meteor[unit]); + + + if(nprot & PROT_EXEC) + return -1; + + if(offset >= mtr->alloc_pages * PAGE_SIZE) + return -1; + + return i386_btop((vtophys(mtr->bigbuf) + offset)); +} + +#endif /* NMETEOR > 0 */ diff --git a/usr.bin/ee/nls/fr_FR.ISO_8859-1/ee.msg b/usr.bin/ee/nls/fr_FR.ISO_8859-1/ee.msg new file mode 100644 index 0000000000000..1901d8e8835da --- /dev/null +++ b/usr.bin/ee/nls/fr_FR.ISO_8859-1/ee.msg @@ -0,0 +1,170 @@ +$ This file contains the messages for ee ("easy editor"). See the file +$ ee.i18n.guide for more information +$ +$ For ee patchlevel 3 +$ +$ $Id$ +$ +$set 1 +$quote " +1 "menu de configuration " +2 "tabulation -> espaces " +3 "recherche sensible aux maj/min " +4 "respect des marges " +5 "formattage automatique des paragraphes" +6 "caractères 8 bits " +7 "fenêtre d'informations " +8 "marge de droite " +9 "menu de sortie" +10 "enregistrer les modifications" +11 "ne pas enregistrer" +12 "menu fichiers" +13 "lire un fichier" +14 "écrire un fichier" +15 "enregistrer un fichier" +16 "imprimer le contenu de l'éditeur" +17 "menu recherche" +18 "recherche de..." +19 "rechercher" +20 "menu correcteur orthographique" +21 "utiliser 'spell'" +22 "utiliser 'ispell'" +23 "menu divers" +24 "formatter le paragraphe" +25 "commande du shell" +26 "vérifier l'orthographe" +27 "menu principal" +28 "quitter l'éditeur" +29 "aide" +30 "opérations sur les fichiers" +31 "rafraîchir l'écran" +32 "configuration" +33 "recherche" +34 "divers" +35 "Contrôle + touche: " +36 "^a code ascii ^i tabulation ^r droite " +37 "^b fin du texte ^j nouvelle ligne ^t début du texte " +38 "^c commande ^k effacer caractère ^u haut " +39 "^d bas ^l gauche ^v annuler effacement mot " +40 "^e entrer recherche ^m nouvelle ligne ^w effacer un mot " +41 "^f annuler eff. caract. ^n page suivante ^x recherche " +42 "^g début de ligne ^o fin de ligne ^y effacer ligne " +43 "^h arrière ^p page précédente ^z annuler effacement ligne" +44 "^[ (échappement) menu " +45 " " +46 "Commandes: " +47 "aide : pour cet écran d'info fichier: donne le nom du fichier " +48 "lire : lire un fichier caract : code ascii d'un caractère" +49 "ecrire : créer un fichier minmaj : recherche sensible aux maj/Min" +50 "fin : quitter et enregistrer pasmin : recherche insensible aux maj/Min" +51 "quitter: quitter, ne pas enregistrer !cmd : exécute \"cmd\" par le shell" +52 "ligne : indique le nunéro de ligne 0-9 : aller à la ligne \"#\" " +53 "tabs : étendre les tabulations pastabs: ne pas étendre les tabulations" +54 " " +55 " ee [-i] [-e] [-h] [fichier(s)] " +56 " -i : pas de fenêtre d'info -e : ne pas étendre les tabs -h : pas de surbrillance" +57 "^[ (echap.) menu ^e rechercher... ^y efface ligne ^u haut ^p page préc." +58 "^a code ascii ^x rechercher ^z annul. eff. ligne ^d bas ^n page suiv." +59 "^b fin du texte ^g début de ligne ^w efface mot ^l gauche " +60 "^t début du texte ^o fin de ligne ^v annul. eff. mot ^r droite " +61 "^c commande ^k efface caract. ^f annul. eff. caract. " +62 "aide: fenêtre d'aide |fichier: nom du fichier |ligne: numéro de ligne" +63 "lire: lecture fichier|caract : code ascii du car. |0-9: aller ligne \"#\"" +64 "ecrire: crée un fich. |minmaj: rech. sensible min/maj|fin: quitte et sauve" +65 "!cmd: shell \"cmd\" |pasmin: rech. insens. min/maj |quitte: quitte sans sauver" +66 "tabs: étend les tabs |pastabs: n'étend pas les tabulations" +67 " presser sur Esc (^[) pour le menu" +68 "pas de fichier" +69 "code ascii: " +70 "le contenu du buffer est imprimé sur \"%s\" " +71 "commande: " +72 "nom du fichier à créer: " +73 "nom du fichier à lire: " +74 "caractère = %d" +75 "commande inconnue : \"%s\"" +76 "la commande tapée est ambiguë" +77 "ligne %d " +78 "longueur = %d" +79 "le fichier courant est \"%s\" " +80 "utilisation: %s [-i] [-e] [-h] [+numero_de_ligne] [fichier(s)]\n" +81 " -i supprime la fenêtre d'informations\n" +82 " -e ne convertit pas les tabs en espaces\n" +83 " -h n'utilise pas de surbrillance\n" +84 "le fichier \"%s\" est un répertoire" +85 "nouveau fichier \"%s\"" +86 "impossible de d'ouvrir \"%s\"" +87 "fichier \"%s\", %d lignes" +88 "le fichier \"%s\" a été lu" +89 "lecture du fichier \"%s\"" +90 ", lecture seule" +91 "fichier \"%s\", %d lignes" +92 "entrer un nom de fichier : " +93 "pas de nom de fichier donné : fichier non enregistré" +94 "des changements ont été effectués, êtes vous sûr ? (o/n [n]) " +95 "o" +96 "le fichier existe déjà, réécrire ? (o/n) [n] " +97 "impossible de créer le fichier \"%s\"" +98 "écriture du fichier \"%s\"" +99 "\"%s\" %d lignes, %d caractères" +100 " ...recherche" +101 "chaîne \"%s\" non trouvée" +102 "rechercher: " +103 "impossible d'exécuter %s\n" +104 "taper return pour continuer " +105 "presser sur echap pour annuler" +106 "menu trop grand pour la fenêtre" +107 "appuyer sur une touche pour continuer " +108 "commande du shell: " +109 "...formattage du paragraphe..." +110 "<!echo 'liste des mots non reconnus'; echo -=-=-=-=-=-" +111 "envoi du contenu du buffer à 'spell'" +112 "colonne de la marge de droite : " +113 "mode restreint: impossible d'effectuer l'opération demandée" +114 "OUI" +115 "NON" +116 "AIDE" +117 "ECRIRE" +118 "LIRE" +119 "LIGNE" +120 "FICHIER" +121 "CARACTERE" +122 "RAFRAICHIR" +23 "menu divers" +124 "AUTEUR" +125 "VERSION" +126 "MINMAJ" +127 "PASMINMAJ" +128 "TABS" +129 "PASTABS" +130 "FIN" +131 "QUITTE" +132 "INFO" +133 "PASINFO" +134 "MARGES" +135 "PASMARGES" +136 "AUTOFORMAT" +137 "PASAUTOFORMAT" +138 "ECHO" +139 "COMMANDEIMPRESSION" +140 "MARGEDROITE" +141 "SURBRILLANT" +142 "PASSURBRILLANT" +143 "8BIT" +144 "PAS8BIT" +145 "caractères de contrôle comme emacs " +146 "^a début de ligne ^i tabulation ^r annule effacement mot " +147 "^b arrière ^j annule eff. caract. ^t début du texte " +148 "^c commande ^k efface ligne ^u fin du texte " +149 "^d efface caractère ^l annule eff. ligne ^v page suivante " +150 "^e fin de ligne ^m nouvelle ligne ^w effacer un mot " +151 "^f caractère suivant ^n ligne suivante ^x recherche " +152 "^g page précédente ^o insère caract. ascii ^y rechercher... " +153 "^h efface en arrière ^p ligne précédente ^z mot suivant " +154 "^[ (escape) menu ^y rechercher... ^k efface ligne ^p ligne prec ^g page prec" +155 "^o code ascii ^x recherche ^l annul. eff.li ^n ligne suiv ^v page suiv" +156 "^u fin du fichier ^a début de ligne ^w efface mot ^b arrière " +157 "^t début du texte ^e fin de ligne ^r annul.eff.mot ^f avance 1 caractère " +158 "^c commande ^d efface caract. ^j annul.eff.car ^z mot suivant " +159 "EMACS" +160 "PASEMACS" +161 " +# positionne le curseur sur la ligne #\n" |