diff options
author | Theodore Tso <tytso@mit.edu> | 1993-06-03 19:29:40 +0000 |
---|---|---|
committer | Theodore Tso <tytso@mit.edu> | 1993-06-03 19:29:40 +0000 |
commit | 746386f12e01102acbe5637aac6f1259c74bb552 (patch) | |
tree | 715df6527f739854dc978c588047607e1907e9e9 /src/krb524 | |
parent | acbed92e113f54d33789d427e697a23a0f07ab64 (diff) | |
download | krb5-746386f12e01102acbe5637aac6f1259c74bb552.tar.gz krb5-746386f12e01102acbe5637aac6f1259c74bb552.tar.xz krb5-746386f12e01102acbe5637aac6f1259c74bb552.zip |
Initial revision
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@2611 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/krb524')
-rw-r--r-- | src/krb524/Makefile | 75 | ||||
-rw-r--r-- | src/krb524/README | 120 | ||||
-rw-r--r-- | src/krb524/RELEASE_NOTES | 17 | ||||
-rw-r--r-- | src/krb524/conv_creds.c | 112 | ||||
-rw-r--r-- | src/krb524/conv_princ.c | 42 | ||||
-rw-r--r-- | src/krb524/conv_tkt.c | 86 | ||||
-rw-r--r-- | src/krb524/conv_tkt_skey.c | 117 | ||||
-rw-r--r-- | src/krb524/encode.c | 119 | ||||
-rw-r--r-- | src/krb524/getcred.c | 68 | ||||
-rw-r--r-- | src/krb524/globals.c | 25 | ||||
-rw-r--r-- | src/krb524/k524init.c | 131 | ||||
-rw-r--r-- | src/krb524/krb524.h | 35 | ||||
-rw-r--r-- | src/krb524/krb524_err.et | 32 | ||||
-rw-r--r-- | src/krb524/krb524_prot | 11 | ||||
-rw-r--r-- | src/krb524/krb524d.c | 371 | ||||
-rw-r--r-- | src/krb524/misc.c | 32 | ||||
-rw-r--r-- | src/krb524/sendmsg.c | 156 | ||||
-rw-r--r-- | src/krb524/test.c | 298 |
18 files changed, 1847 insertions, 0 deletions
diff --git a/src/krb524/Makefile b/src/krb524/Makefile new file mode 100644 index 0000000000..6b4a4f162e --- /dev/null +++ b/src/krb524/Makefile @@ -0,0 +1,75 @@ +# Copyright 1993 by Geer Zolot Associates. All Rights Reserved. +# +# Export of this software from the United States of America is assumed +# to require a specific license from the United States Government. It +# is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of Geer Zolot Associates not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. Geer Zolot Associates makes no +# representations about the suitability of this software for any +# purpose. It is provided "as is" without express or implied warranty. +# +# $Id$ + +KRB5TOP = /ua/software/build/sun4/krb5.src.B2/src + +# Library sources +SRCS = conv_creds.c conv_princ.c conv_tkt.c conv_tkt_skey.c \ + encode.c misc.c globals.c sendmsg.c krb524_err.et +OBJS = conv_creds.o conv_princ.o conv_tkt.o conv_tkt_skey.o \ + encode.o misc.o globals.o sendmsg.o krb524_err.o + +GENS = krb524_err.c krb524_err.h + +# Server stuff. +LDFLAGS= -L. -L/usr/local/lib +LIBS = -lkrb524 -lkdb5 -lkrb5 -lkrb -lcrypto /usr/local/lib/libdes.a \ + -lisode -lcom_err + +CL_LIBS = -lkrb524 -lkrb5 -lcrypto -lisode -lkrb -lcom_err + +CC = gcc +CFLAGS = -g -DUSE_MASTER -I. -I/usr/local/include + +all: libkrb524.a krb524d test k524init + +libkrb524.a: $(OBJS) + ar cru libkrb524.a $(OBJS) + ranlib libkrb524.a + +test: libkrb524.a test.o + $(CC) -o test $(LDFLAGS) test.o $(LIBS) + +krb524d: libkrb524.a krb524d.o + $(CC) -o krb524d krb524d.o $(LDFLAGS) $(LIBS) + +k524init: libkrb524.a k524init.o + $(CC) -o k524init $(LDFLAGS) k524init.o $(CL_LIBS) + +krb524d.o: krb524d.c + $(CC) -c $(CFLAGS) -I$(KRB5TOP)/include $*.c + +test.o: test.c + $(CC) -c $(CFLAGS) -I$(KRB5TOP)/include $*.c + +depend: $(GENS) + makedepend -- $(CFLAGS) -I$(KRB5TOP)/include -- $(SRCS) \ + test.c krb524d.c + +clean: + -rm -f libkrb524.a $(OBJS) $(GENS) core *~ *.bak #* + -rm -f test krb524d k524init test.o krb524d.o k524init.o + +krb524_err.c krb524_err.h: krb524_err.et + compile_et krb524_err.et + +.SUFFIXES: .et + +# DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/src/krb524/README b/src/krb524/README new file mode 100644 index 0000000000..6f829313d8 --- /dev/null +++ b/src/krb524/README @@ -0,0 +1,120 @@ +Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + +Export of this software from the United States of America is assumed +to require a specific license from the United States Government. It +is the responsibility of any person or organization contemplating +export to obtain such a license before exporting. + +WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +distribute this software and its documentation for any purpose and +without fee is hereby granted, provided that the above copyright +notice appear in all copies and that both that copyright notice and +this permission notice appear in supporting documentation, and that +the name of Geer Zolot Associates not be used in advertising or +publicity pertaining to distribution of the software without specific, +written prior permission. Geer Zolot Associates makes no +representations about the suitability of this software for any +purpose. It is provided "as is" without express or implied warranty. + +$Id$ + +Kerberos V5 to Kerberos V4 Credentials Converting Service, ALPHA RELEASE +======================================================================== + +krb524 is a service that converts Kerberos V5 credentials into +Kerberos V4 credentials suitable for use with applications that for +whatever reason do not use V5 directly. The service consists of a +server that has access to the secret key of the Kerberos service for +which credentials will be converted, and a library for use by client +programs that wish to use the server. + +The protocol is simple. Suppose that a client C wishes to obtain V4 +credentials for a V5 service S by using the krb524 server. The +notation {C,S}_n represents a Vn service ticket for S for use by C. + +(1) C obtains V5 credentials, including a ticket {C,S}_5, for S by the +normal V5 means. + +(2) C transmits {C,S}_5 to KRB524. + +(3) KRB524 converts {C,S}_5 into {C,S}_4. + +(4) KRB524 transmits {C,S}_4 to C. + +(5) C creates a V4 credentials strucuture from the plaintext +information in the V5 credential and {C,S}_4. + +Steps (2) through (4) are encapsulated in a single function call in +the krb524 library. + +Obviously, not all V5 credentials can be completely converted to V4 +credentials, since the former is a superset of the latter. The +precise semantics of the conversion function are still undecided. +UTSL. + +Programs contained in this release +====================================================================== + +krb524d [-m[aster]] [-k[eytab]] + +The krb524 server. It accepts UDP requests on the krb524 service +port, specified in /etc/services, or on port 4444 by default. (A +request for an official port assignment is underway.) The -m argument +causes krb524d to access the KDC master database directly; the -k +argument causes krb524d to use the default keytab (and therefore only +be able to convert tickets for services in the keytab). Only one of +-m or -k can be specified. + +test -remote server client service + +A test program that obtains a V5 credential for {client,service}, +converts it to a V4 credential, and prints out the entire contents of +both versions. It prompts for service's secret key, which it needs to +decrypt both tickets in order to print them out. Enter it as an eight +digit ASCII hex number. + +k524init [-n] [-p principal] + +Convert a V5 credential into a V4 credential and store it in a V4 +ticket file. The client is 'principal', or krbtgt at the V5 ccache's +default principal's realm if not specified. The -n argument causes +the new ticket to be added to the existing ticket file; otherwise, the +ticket file is initialized. + +Using libkrb524.a +====================================================================== + +To use libkrb524.a, #include <krb524.h>, link against libkrb524.a, +call krb524_init_ets() at the beginning of your program, and call one +of the following two functions: + +int krb524_convert_creds_addr(krb5_creds *v5creds, CREDENTIALS *v4creds, + struct sockaddr *saddr) + +int krb524_convert_creds_kdc(krb5_creds *v5creds, CREDENTIALS *v4creds) + +Both convert the V5 credential in v5creds into a V4 credential in +v4creds. One assumes krb524d is running on the KDC, the other uses an +explicit host. You only need to specify the address for saddr; the +port is filled in automatically. + +Unresolved issues / Bugs +====================================================================== + +o krb524d requires access to the secret key of any service to be +converted. Should krb524d run on the KDC or on individual server +machines? The latter is more paranoid, since it prevents bugs in +krb524d from provided unauthorized access to the master database. +However, it also requires the client to provide the address of the +server to be used. The client will usually have this information +(since presumably it will be sending the converted V4 credentials to +the same server) but it may not be in a convenient form. It seems +"cleaner" to have krb524d run on the KDC. + +o Even if krb524d uses keytabs on server machines, it needs to be more +flexible. You only want to run one krb524d per host, so it has to be +able to scan multiple keytabs. This might get logistically messy. + +o This code is of alpha quality. Bugs, omissions, memory leaks, and +perhaps security holes still remain. Do not use it (yet) in a +production environment. diff --git a/src/krb524/RELEASE_NOTES b/src/krb524/RELEASE_NOTES new file mode 100644 index 0000000000..cd462b6fd3 --- /dev/null +++ b/src/krb524/RELEASE_NOTES @@ -0,0 +1,17 @@ +$Id$ + +Kerberos V5 to Kerberos V4 Credentials Converting Service, ALPHA RELEASE +======================================================================== + +This is the ALPHA RELEASE of krb524. Treat it accordingly. + +Soon, krb524 will be integrated into the standard MIT Kerberos 5 +distribution. krb524's existence as a distinct distribution is +temporary. + +If you have any questions, contact + +Barry Jaspan, bjaspan@gza.com +Geer Zolot Associates +(617) 374-3700 + diff --git a/src/krb524/conv_creds.c b/src/krb524/conv_creds.c new file mode 100644 index 0000000000..ce36f30c16 --- /dev/null +++ b/src/krb524/conv_creds.c @@ -0,0 +1,112 @@ +/* + * Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. It + * is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Geer Zolot Associates not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Geer Zolot Associates makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#if !defined(lint) && !defined(SABER) +static char rcs_id[] = "$Id$"; +#endif + +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <krb5/krb5.h> +#include <krb.h> + +#include "krb524.h" + +int krb524_convert_creds_addr(krb5_creds *v5creds, CREDENTIALS *v4creds, + struct sockaddr *saddr) +{ + int ret; + + if (ret = krb524_convert_creds_plain(v5creds, v4creds)) + return ret; + + return krb524_convert_tkt(v5creds->server, &v5creds->ticket, + &v4creds->ticket_st, + &v4creds->kvno, + saddr); +} + +int krb524_convert_creds_kdc(krb5_creds *v5creds, CREDENTIALS *v4creds) +{ + struct sockaddr_in *addrs; + int ret, naddrs; + + if (ret = krb5_locate_kdc(&v5creds->server->realm, &addrs, &naddrs)) + return ret; + if (naddrs == 0) + ret = KRB5_KDC_UNREACH; + else { + addrs[0].sin_port = 0; /* use krb524 default port */ + ret = krb524_convert_creds_addr(v5creds, v4creds, + (struct sockaddr *) &addrs[0]); + } + + free(addrs); + return ret; +} + +int krb524_convert_creds_plain(krb5_creds *v5creds, CREDENTIALS *v4creds) +{ + unsigned long addr; + krb5_data *comp; + int ret; + + bzero((char *) v4creds, sizeof(CREDENTIALS)); + + if (ret = krb524_convert_princs(v5creds->client, v5creds->server, + v4creds->pname, v4creds->pinst, + v4creds->realm, v4creds->service, + v4creds->instance)) + return ret; + + /* Check keytype too */ + if (v5creds->keyblock.length != sizeof(C_Block)) { + if (krb524_debug) + fprintf(stderr, "v5 session keyblock length %d != " + "C_Block size %d\n", v5creds->keyblock.length, + sizeof(C_Block)); + return KRB524_BADKEY; + } else + bcopy((char *) v5creds->keyblock.contents, v4creds->session, + sizeof(C_Block)); + + /* V4 has no concept of authtime or renew_till, so ignore them */ + /* V4 lifetime is 1 byte, in 5 minute increments */ + v4creds->lifetime = 0xff & + ((v5creds->times.endtime - v5creds->times.starttime) / 300); + v4creds->issue_date = v5creds->times.starttime; + + /* XXX perhaps we should use the addr of the client host if */ + /* v5creds contains more than one addr. Q: Does V4 support */ + /* non-INET addresses? */ + if (!v5creds->addresses || !v5creds->addresses[0] || + v5creds->addresses[0]->addrtype != ADDRTYPE_INET || + v5creds->addresses[0]->length != sizeof(addr)) { + if (krb524_debug) + fprintf(stderr, "Invalid v5creds address information.\n"); + return KRB524_BADADDR; + } else + bcopy(v5creds->addresses[0]->contents, (char *) &addr, + sizeof(addr)); + + return 0; +} diff --git a/src/krb524/conv_princ.c b/src/krb524/conv_princ.c new file mode 100644 index 0000000000..82d589b79e --- /dev/null +++ b/src/krb524/conv_princ.c @@ -0,0 +1,42 @@ +/* + * Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. It + * is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Geer Zolot Associates not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Geer Zolot Associates makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#if !defined(lint) && !defined(SABER) +static char rcs_id[] = "$Id$"; +#endif + +#include <stdio.h> +#include <krb5/krb5.h> +#include <krb.h> + +#include "krb524.h" + +int krb524_convert_princs(krb5_principal client, krb5_principal + server, char *pname, char *pinst, char + *prealm, char *sname, char *sinst) +{ + char dummy[REALM_SZ]; + int ret; + + if (ret = krb5_524_conv_principal(client, pname, pinst, prealm)) + return ret; + + return krb5_524_conv_principal(server, sname, sinst, dummy); +} diff --git a/src/krb524/conv_tkt.c b/src/krb524/conv_tkt.c new file mode 100644 index 0000000000..1332a23cdb --- /dev/null +++ b/src/krb524/conv_tkt.c @@ -0,0 +1,86 @@ +/* + * Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. It + * is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Geer Zolot Associates not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Geer Zolot Associates makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#if !defined(lint) && !defined(SABER) +static char rcs_id[] = "$Id$"; +#endif + +#include <stdio.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> + +#include <krb5/krb5.h> +#include <krb.h> + +#include "krb524.h" + +/* + * krb524_convert_tkt. Open a network connection to krb524d, send it + * the V5 ticket, receive the V4 ticket in response. + */ +int krb524_convert_tkt(krb5_principal server, krb5_data *v5tkt, + KTEXT_ST *v4tkt, + int *kvno, + struct sockaddr_in *saddr) +{ + char *p; + krb5_data reply; + struct servent *serv; + int ret, status; + + reply.data = NULL; + + if (saddr->sin_port == 0) { + serv = getservbyname(KRB524_SERVICE, "udp"); + if (serv) + saddr->sin_port = serv->s_port; + else + saddr->sin_port = htons(KRB524_PORT); + } + + if (ret = krb524_send_message(saddr, v5tkt, &reply)) + goto fail; + + p = reply.data; + status = ntohl(*((krb5_error_code *) p)); + p += sizeof(krb5_error_code); + reply.length -= sizeof(krb5_error_code); + if (status) { + ret = status; + goto fail; + } + *kvno = ntohl(*((krb5_error_code *) p)); + p += sizeof(int); + reply.length -= sizeof(int); + ret = decode_v4tkt(v4tkt, p, &reply.length); + +fail: + if (ret) { + if (reply.data) + free(reply.data); + reply.data = NULL; + reply.length = 0; + } + + return ret; +} + diff --git a/src/krb524/conv_tkt_skey.c b/src/krb524/conv_tkt_skey.c new file mode 100644 index 0000000000..ac6a1b9285 --- /dev/null +++ b/src/krb524/conv_tkt_skey.c @@ -0,0 +1,117 @@ +/* + * Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. It + * is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Geer Zolot Associates not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Geer Zolot Associates makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#if !defined(lint) && !defined(SABER) +static char rcs_id[] = "$Id$"; +#endif + +#include <stdio.h> +#include <krb5/krb5.h> +#include <krb.h> + +#include "krb524.h" + +/* + * Convert a v5 ticket for server to a v4 ticket, using service key + * skey for both. + */ +int krb524_convert_tkt_skey(krb5_ticket *v5tkt, KTEXT_ST *v4tkt, + krb5_keyblock *skey) +{ + char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ]; + char sname[ANAME_SZ], sinst[INST_SZ]; + krb5_enc_tkt_part *v5etkt; + krb5_data *comp; + int ret, lifetime; + + v5tkt->enc_part2 = NULL; + if (ret = krb5_decrypt_tkt_part(skey, v5tkt)) { + krb5_free_ticket(v5tkt); + return ret; + } + v5etkt = v5tkt->enc_part2; + + if (ret = krb524_convert_princs(v5etkt->client, v5tkt->server, + pname, pinst, prealm, sname, + sinst)) { + krb5_free_enc_tkt_part(v5etkt); + v5tkt->enc_part2 = NULL; + return ret; + } + + if (v5etkt->session->keytype != KEYTYPE_DES || + v5etkt->session->length != sizeof(C_Block)) { + if (krb524_debug) + fprintf(stderr, "v5 session keyblock type %d length %d != " + "C_Block size %d\n", v5etkt->session->keytype, + v5etkt->session->length, + sizeof(C_Block)); + krb5_free_enc_tkt_part(v5etkt); + v5tkt->enc_part2 = NULL; + return KRB524_BADKEY; + } + + /* V4 has no concept of authtime or renew_till, so ignore them */ + /* V4 lifetime is 1 byte, in 5 minute increments */ + if (v5etkt->times.starttime == 0) + v5etkt->times.starttime = v5etkt->times.authtime; + lifetime = 0xff & + ((v5etkt->times.endtime - v5etkt->times.authtime) / 300); + + /* XXX perhaps we should use the addr of the client host if */ + /* v5creds contains more than one addr. Q: Does V4 support */ + /* non-INET addresses? */ + if (!v5etkt->caddrs || !v5etkt->caddrs[0] || + v5etkt->caddrs[0]->addrtype != ADDRTYPE_INET) { + if (krb524_debug) + fprintf(stderr, "Invalid v5creds address information.\n"); + krb5_free_enc_tkt_part(v5etkt); + v5tkt->enc_part2 = NULL; + return KRB524_BADADDR; + } + + if (krb524_debug) + printf("startime = %ld, authtime = %ld, lifetime = %ld\n", + (long) v5etkt->times.starttime, + (long) v5etkt->times.authtime, + (long) lifetime); + + /* XXX are there V5 flags we should map to V4 equivalents? */ + ret = krb_create_ticket(v4tkt, + 0, /* flags */ + pname, + pinst, + krb5_princ_realm(v5etkt->client), + *((unsigned long *)v5etkt->caddrs[0]->contents), + v5etkt->session->contents, + lifetime, + /* issue_data */ + v5etkt->times.starttime, + sname, + sinst, + skey->contents); + + krb5_free_enc_tkt_part(v5etkt); + v5tkt->enc_part2 = NULL; + if (ret == KSUCCESS) + return 0; + else + return KRB524_V4ERR; +} diff --git a/src/krb524/encode.c b/src/krb524/encode.c new file mode 100644 index 0000000000..f14fa6d90a --- /dev/null +++ b/src/krb524/encode.c @@ -0,0 +1,119 @@ +/* + * Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. It + * is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Geer Zolot Associates not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Geer Zolot Associates makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#if !defined(lint) && !defined(SABER) +static char rcs_id[] = "$Id$"; +#endif + +#include <stdio.h> +#include <krb5/krb5.h> +#include <krb.h> + +#include "krb524.h" + +/* + * I'm sure that this is reinventing the wheel, but I don't know where + * the wheel is hidden. + */ + +int encode_v4tkt(KTEXT_ST *, char *, int *), + encode_ktext(char **, int *, KTEXT_ST *), + encode_bytes(char **, int *, char *, int), + encode_int32(char **, int *, krb5_int32 *); + +int decode_v4tkt(KTEXT_ST *, char *, int *), + decode_ktext(char **, int *, KTEXT_ST *), + decode_bytes(char **, int *, char *, int), + decode_int32(char **, int *, krb5_int32 *); + +int encode_bytes(char **out, int *outlen, char *in, int len) +{ + if (len > *outlen) + return KRB524_ENCFULL; + bcopy(in, *out, len); + *out += len; + *outlen -= len; + return 0; +} + +int encode_int32(char **out, int *outlen, krb5_int32 *v) +{ + int ret; + int nv; + + nv = htonl(*v); + return encode_bytes(out, outlen, (char *) &nv, sizeof(nv)); +} + +int encode_v4tkt(KTEXT_ST *v4tkt, char *buf, int *encoded_len) +{ + int buflen, ret; + + buflen = *encoded_len; + + if (ret = encode_int32(&buf, &buflen, &v4tkt->length)) + return ret; + if (ret = encode_bytes(&buf, &buflen, v4tkt->dat, MAX_KTXT_LEN)) + return ret; + if (ret = encode_int32(&buf, &buflen, &v4tkt->mbz)) + return ret; + + *encoded_len -= buflen; + return 0; +} + +/* decode functions */ + +int decode_bytes(char **out, int *outlen, char *in, int len) +{ + if (len > *outlen) + return KRB524_DECEMPTY; + bcopy(*out, in, len); + *out += len; + *outlen -= len; + return 0; +} + +int decode_int32(char **out, int *outlen, krb5_int32 *v) +{ + int ret; + int nv; + + if (ret = decode_bytes(out, outlen, (char *) &nv, sizeof(nv))) + return ret; + *v = ntohl(nv); + return 0; +} + +int decode_v4tkt(KTEXT_ST *v4tkt, char *buf, int *encoded_len) +{ + int buflen, ret; + + buflen = *encoded_len; + if (ret = decode_int32(&buf, &buflen, &v4tkt->length)) + return ret; + if (ret = decode_bytes(&buf, &buflen, v4tkt->dat, MAX_KTXT_LEN)) + return ret; + if (ret = decode_int32(&buf, &buflen, &v4tkt->mbz)) + return ret; + *encoded_len -= buflen; + return 0; +} + diff --git a/src/krb524/getcred.c b/src/krb524/getcred.c new file mode 100644 index 0000000000..e81ef25389 --- /dev/null +++ b/src/krb524/getcred.c @@ -0,0 +1,68 @@ +/* + * Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. It + * is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Geer Zolot Associates not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Geer Zolot Associates makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#if !defined(lint) && !defined(SABER) +static char rcs_id[] = "$Id$"; +#endif + +#include <stdio.h> +#include <krb5/krb5.h> +#include <krb.h> + +main(int argc, char **argv) +{ + krb5_principal client, server; + krb5_ccache cc; + krb5_creds v5creds; + CREDENTIALS v4creds; + int i, ret; + + krb524_init_ets(); + + if (ret = krb5_parse_name(argv[1], &client)) { + com_err("getcred", ret, "parsing client name"); + exit(1); + } + if (ret = krb5_parse_name(argv[2], &server)) { + com_err("getcred", ret, "parsing server name"); + exit(1); + } + if (ret = krb5_cc_default(&cc)) { + com_err("getcred", ret, "opening default credentials cache"); + exit(1); + } + + bzero((char *) &v5creds, sizeof(v5creds)); + v5creds.client = client; + v5creds.server = server; + v5creds.times.endtime = 0; + v5creds.keyblock.keytype = KEYTYPE_DES; + if (ret = krb5_get_credentials(0, cc, &v5creds)) { + com_err("getcred", ret, "getting V5 credentials"); + exit(1); + } + + if (ret = krb524_convert_creds_kdc(&v5creds, &v4creds)) { + com_err("getcred", ret, "converting to V4 credentials"); + exit(1); + } + + return 0; +} diff --git a/src/krb524/globals.c b/src/krb524/globals.c new file mode 100644 index 0000000000..eb7884a454 --- /dev/null +++ b/src/krb524/globals.c @@ -0,0 +1,25 @@ +/* + * Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. It + * is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Geer Zolot Associates not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Geer Zolot Associates makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#if !defined(lint) && !defined(SABER) +static char rcs_id[] = "$Id$"; +#endif + +int krb524_debug = 0; diff --git a/src/krb524/k524init.c b/src/krb524/k524init.c new file mode 100644 index 0000000000..39045e54e0 --- /dev/null +++ b/src/krb524/k524init.c @@ -0,0 +1,131 @@ +/* + * Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. It + * is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Geer Zolot Associates not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Geer Zolot Associates makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#if !defined(lint) && !defined(SABER) +static char rcs_id[] = "$Id$"; +#endif + +#include <stdio.h> +#include <krb5/krb5.h> +#include <krb.h> + +extern int optind; +extern char *optarg; + +#if !defined(lint) && !defined(SABER) +const char rcsid[] = "$Id$"; +#endif + +main(int argc, char **argv) +{ + krb5_principal client, server; + krb5_ccache cc; + krb5_creds v5creds; + CREDENTIALS v4creds; + int code; + int option; + char *princ = NULL; + int nodelete = 0; + int lose = 0; + + while((option = getopt(argc, argv, "p:n")) != EOF) { + switch(option) { + case 'p': + princ = optarg; + break; + case 'n': + nodelete++; + break; + default: + lose++; + break; + } + } + + if (lose || (argc - optind > 1)) { + fprintf(stderr, "Usage: k524init [-p principal]\n"); + exit(1); + } + + krb524_init_ets(); + + if (code = krb5_cc_default(&cc)) { + com_err("k524init", code, "opening default credentials cache"); + exit(1); + } + + if (code = krb5_cc_get_principal(cc, &client)) { + com_err("k524init", code, "while retrieving user principal name"); + exit(1); + } + + if (princ) { + if (code = krb5_parse_name(princ, &server)) { + com_err("k524init", code, "while parsing service principal name"); + exit(1); + } + } else { + if (code = krb5_build_principal(&server, + krb5_princ_realm(client)->length, + krb5_princ_realm(client)->data, + "krbtgt", + krb5_princ_realm(client)->data, + NULL)) { + com_err("k524init", code, "while creating service principal name"); + exit(1); + } + } + + bzero((char *) &v5creds, sizeof(v5creds)); + v5creds.client = client; + v5creds.server = server; + v5creds.times.endtime = 0; + v5creds.keyblock.keytype = KEYTYPE_DES; + if (code = krb5_get_credentials(0, cc, &v5creds)) { + com_err("k524init", code, "getting V5 credentials"); + exit(1); + } + + if (code = krb524_convert_creds_kdc(&v5creds, &v4creds)) { + com_err("k524init", code, "converting to V4 credentials"); + exit(1); + } + + /* this is stolen from the v4 kinit */ + + if (!nodelete) { + /* initialize ticket cache */ + if (code = in_tkt(v4creds.pname,v4creds.pinst) != KSUCCESS) { + com_err("k524init", code, "trying to create the V4 ticket file"); + exit(1); + } + } + + /* stash ticket, session key, etc. for future use */ + if (code = save_credentials(v4creds.service, v4creds.instance, + v4creds.realm, v4creds.session, + v4creds.lifetime, v4creds.kvno, + &(v4creds.ticket_st), v4creds.issue_date)) { + com_err("k524init", code, "trying to save the V4 ticket"); + exit(1); + } + + exit(0); +} diff --git a/src/krb524/krb524.h b/src/krb524/krb524.h new file mode 100644 index 0000000000..2b9a3b6f8b --- /dev/null +++ b/src/krb524/krb524.h @@ -0,0 +1,35 @@ +/* + * Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. It + * is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Geer Zolot Associates not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Geer Zolot Associates makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef __KRB524_H__ +#define __KRB524_H__ + +/* + * $Id$ + */ + +#define KRB524_SERVICE "krb524" +#define KRB524_PORT 4444 + +#include <krb524_err.h> + +extern int krb524_debug; + +#endif /* __KRB524_H__ */ diff --git a/src/krb524/krb524_err.et b/src/krb524/krb524_err.et new file mode 100644 index 0000000000..237d084ac9 --- /dev/null +++ b/src/krb524/krb524_err.et @@ -0,0 +1,32 @@ +# Copyright 1993 by Geer Zolot Associates. All Rights Reserved. +# +# Export of this software from the United States of America is assumed +# to require a specific license from the United States Government. It +# is the responsibility of any person or organization contemplating +# export to obtain such a license before exporting. +# +# WITHIN THAT CONSTRAINT, permission to use, copy, modify, and +# distribute this software and its documentation for any purpose and +# without fee is hereby granted, provided that the above copyright +# notice appear in all copies and that both that copyright notice and +# this permission notice appear in supporting documentation, and that +# the name of Geer Zolot Associates not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. Geer Zolot Associates makes no +# representations about the suitability of this software for any +# purpose. It is provided "as is" without express or implied warranty. +# +# $Id$ + +error_table k524 + +error_code KRB524_BADKEY, "Cannot convert V5 keyblock" +error_code KRB524_BADADDR, "Cannot convert V5 address information" +error_code KRB524_BADPRINC, "Cannot convert V5 principal" +error_code KRB524_BADREALM, "V5 realm name longer than V4 maximum" +error_code KRB524_V4ERR, "Kerberos V4 error" +error_code KRB524_ENCFULL, "Encoding too large" +error_code KRB524_DECEMPTY, "Decoding out of data" +error_code KRB524_NOTRESP, "Service not responding" + +end diff --git a/src/krb524/krb524_prot b/src/krb524/krb524_prot new file mode 100644 index 0000000000..f83854d77f --- /dev/null +++ b/src/krb524/krb524_prot @@ -0,0 +1,11 @@ +Protocol: + + -> ASN.1 encoded V5 ticket + <- int status_code, [int kvno, encode_v4tkt encoded KTEXT_ST] + +kvno and V4 ticket are only included if status_code is zero. + +The kvno for the converted ticket is sent explicitly because the field +is ASN.1 encoded in the krb5_creds structure; the client would have to +decode (but not decrypt) the entire krb5_ticket structure to get it, +which would be inefficient. diff --git a/src/krb524/krb524d.c b/src/krb524/krb524d.c new file mode 100644 index 0000000000..c681758ced --- /dev/null +++ b/src/krb524/krb524d.c @@ -0,0 +1,371 @@ +/* + * Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. It + * is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Geer Zolot Associates not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Geer Zolot Associates makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#if !defined(lint) && !defined(SABER) +static char rcs_id[] = "$Id$"; +#endif + +#include <stdio.h> +#include <string.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/signal.h> +#include <netinet/in.h> +#include <netdb.h> + +#include <krb5/krb5.h> +#include <krb5/asn1.h> +#include <krb5/kdb.h> +#include <krb5/kdb_dbm.h> +#ifdef PROVIDE_DES_CBC_CRC +#include <krb5/mit-des.h> +#endif +#include <krb.h> + +#include "krb524.h" + +#define TIMEOUT 60 +#define TKT_BUFSIZ 2048 +#define MSGSIZE 8192 + +char *whoami; +int signalled = 0; +static int debug = 0; + +int use_keytab; +char *keytab = NULL; +krb5_keytab kt; + +int use_master; +krb5_principal master_princ; +krb5_encrypt_block master_encblock; +krb5_keyblock master_keyblock; + +void init_keytab(), init_master(); +krb5_error_code do_connection(), lookup_service_key(), kdc_get_server_key(); + +void usage() +{ + fprintf(stderr, "Usage: %s [-m[aster]] [-k[eytab]]\n", whoami); + cleanup_and_exit(1); +} + +int request_exit() +{ + signalled = 1; +} + +int krb5_free_keyblock_contents(krb5_keyblock *key) +{ + memset(key->contents, 0, key->length); + xfree(key->contents); + return 0; +} + +main(int argc, char **argv) +{ + struct servent *serv; + struct sockaddr_in saddr; + struct timeval timeout; + int ret, s, conn; + fd_set rfds; + + krb5_init_ets(); + + whoami = ((whoami = strrchr(argv[0], '/')) ? whoami + 1 : argv[0]); + + argv++; argc--; + use_master = use_keytab = 0; + while (argc) { + if (strncmp(*argv, "-k", 2) == 0) + use_keytab = 1; + else if (strncmp(*argv, "-m", 2) == 0) + use_master = 1; + else + break; + argv++; argc--; + } + if (argc || use_keytab + use_master > 1 || + use_keytab + use_master == 0) + usage(); + + signal(SIGINT, request_exit); + signal(SIGHUP, request_exit); + signal(SIGTERM, request_exit); + + if (use_keytab) + init_keytab(); + if (use_master) + init_master(); + + bzero((char *) &saddr, sizeof(struct sockaddr_in)); + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = INADDR_ANY; + serv = getservbyname(KRB524_SERVICE, "udp"); + if (serv == NULL) { + com_err(whoami, 0, "service entry not found, using %d", KRB524_PORT); + saddr.sin_port = htons(KRB524_PORT); + } else + saddr.sin_port = serv->s_port; + + if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { + com_err(whoami, errno, "creating main socket"); + cleanup_and_exit(1); + } + if ((ret = bind(s, (struct sockaddr *) &saddr, + sizeof(struct sockaddr_in))) < 0) { + com_err(whoami, errno, "binding main socket"); + cleanup_and_exit(1); + } + + timeout.tv_sec = TIMEOUT; + timeout.tv_usec = 0; + while (1) { + FD_ZERO(&rfds); + FD_SET(s, &rfds); + + ret = select(s+1, &rfds, NULL, NULL, &timeout); + if (signalled) + cleanup_and_exit(0); + else if (ret == 0) { + if (use_master) { + ret = krb5_dbm_db_fini(); + if (ret && ret != KRB5_KDB_DBNOTINITED) { + com_err(whoami, ret, "closing kerberos database"); + cleanup_and_exit(1); + } + } + } else if (ret < 0 && errno != EINTR) { + com_err(whoami, errno, "in select"); + cleanup_and_exit(1); + } else if (FD_ISSET(s, &rfds)) { + if (debug) + printf("received packet\n"); + if (ret = do_connection(s)) { + com_err(whoami, ret, "handling packet"); + } + } else + com_err(whoami, 0, "impossible situation occurred!"); + } + + return cleanup_and_exit(0); +} + +int cleanup_and_exit(int ret) +{ + if (use_master) { + krb5_finish_key(&master_encblock); + memset((char *)&master_encblock, 0, sizeof(master_encblock)); + (void) krb5_db_fini(); + } + exit(ret); +} + +void init_keytab() +{ + int ret; + if (keytab == NULL) { + if (ret = krb5_kt_default(&kt)) { + com_err(whoami, ret, "while opening default keytab"); + cleanup_and_exit(1); + } + } else { + if (ret = krb5_kt_resolve(keytab, &kt)) { + com_err(whoami, ret, "while resolving keytab %s", + keytab); + cleanup_and_exit(1); + } + } +} + +void init_master() +{ + int ret; + char *realm; + + if (ret = krb5_get_default_realm(&realm)) { + com_err(whoami, ret, "getting default realm"); + cleanup_and_exit(1); + } + if (ret = krb5_db_setup_mkey_name(NULL, realm, (char **) 0, + &master_princ)) { + com_err(whoami, ret, "while setting up master key name"); + cleanup_and_exit(1); + } + +#ifdef PROVIDE_DES_CBC_CRC + master_encblock.crypto_entry = &mit_des_cryptosystem_entry; +#else + error(You gotta figure out what cryptosystem to use in the KDC); +#endif + + master_keyblock.keytype = KEYTYPE_DES; + if (ret = krb5_db_fetch_mkey(master_princ, &master_encblock, + FALSE, /* non-manual type-in */ + FALSE, /* irrelevant, given prev. arg */ + 0, &master_keyblock)) { + com_err(whoami, ret, "while fetching master key"); + cleanup_and_exit(1); + } + + if (ret = krb5_db_init()) { + com_err(whoami, ret, "while initializing master database"); + cleanup_and_exit(1); + } + if (ret = krb5_process_key(&master_encblock, &master_keyblock)) { + krb5_db_fini(); + com_err(whoami, ret, "while processing master key"); + cleanup_and_exit(1); + } +} + +krb5_error_code do_connection(int s) +{ + struct sockaddr saddr; + krb5_ticket *v5tkt; + KTEXT_ST v4tkt; + krb5_keyblock service_key; + krb5_data msgdata, tktdata; + char msgbuf[MSGSIZE], tktbuf[TKT_BUFSIZ], *p; + int n, ret, saddrlen; + + msgdata.data = msgbuf; + msgdata.length = MSGSIZE; + + saddrlen = sizeof(struct sockaddr); + ret = recvfrom(s, msgdata.data, msgdata.length, 0, &saddr, &saddrlen); + if (ret < 0) { + ret = errno; + goto error; + } + if (debug) + printf("message received\n"); + + if (ret = decode_krb5_ticket(&msgdata, &v5tkt)) + goto error; + if (debug) + printf("V5 ticket decoded\n"); + + if (ret = lookup_service_key(v5tkt->server, &service_key)) + goto error; + if (debug) + printf("service key retrieved\n"); + + ret = krb524_convert_tkt_skey(v5tkt, &v4tkt, &service_key); + if (ret) + goto error; + krb5_free_keyblock_contents(&service_key); + krb5_free_ticket(v5tkt); + if (debug) + printf("credentials converted\n"); + + tktdata.data = tktbuf; + tktdata.length = TKT_BUFSIZ; + ret = encode_v4tkt(&v4tkt, tktdata.data, &tktdata.length); + if (ret) + goto error; + if (debug) + printf("v4 credentials encoded\n"); + +error: + /* create the reply */ + p = msgdata.data; + msgdata.length = 0; + + n = htonl(ret); + memcpy(p, (char *) &n, sizeof(int)); + p += sizeof(int); + msgdata.length += sizeof(int); + + if (ret) + goto write_msg; + + n = htonl(v5tkt->enc_part.kvno); + memcpy(p, (char *) &n, sizeof(int)); + p += sizeof(int); + msgdata.length += sizeof(int); + + memcpy(p, tktdata.data, tktdata.length); + p += tktdata.length; + msgdata.length += tktdata.length; + +write_msg: + if (ret) + (void) sendto(s, msgdata.data, msgdata.length, 0, &saddr, saddrlen); + else + if (sendto(s, msgdata.data, msgdata.length, 0, &saddr, saddrlen)<0) + ret = errno; + if (debug) + printf("reply written\n"); + + return ret; +} + +krb5_error_code lookup_service_key(krb5_principal p, krb5_keyblock *key) +{ + int ret; + krb5_keytab_entry entry; + + if (use_keytab) { + if (ret = krb5_kt_get_entry(kt, p, 0, &entry)) + return ret; + bcopy((char *) &entry.key, key, sizeof(krb5_keyblock)); + return 0; + } else if (use_master) { + if (ret = krb5_dbm_db_init()) + return ret; + return kdc_get_server_key(p, key, NULL); + } +} + +/* taken from kdc/kdc_util.c, and modified somewhat */ +krb5_error_code kdc_get_server_key(service, key, kvno) + krb5_principal service; + krb5_keyblock *key; + krb5_kvno *kvno; +{ + krb5_error_code ret; + int nprincs; + krb5_db_entry server; + krb5_boolean more; + + nprincs = 1; + if (ret = krb5_db_get_principal(service, &server, &nprincs, &more)) + return(ret); + + if (more) { + krb5_db_free_principal(&server, nprincs); + return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE); + } else if (nprincs != 1) { + krb5_db_free_principal(&server, nprincs); + return(KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN); + } + + /* + * convert server.key into a real key (it is encrypted in the + * database) + */ + ret = KDB_CONVERT_KEY_OUTOF_DB(&server.key, key); + if (kvno) + *kvno = server.kvno; + krb5_db_free_principal(&server, nprincs); + return ret; +} diff --git a/src/krb524/misc.c b/src/krb524/misc.c new file mode 100644 index 0000000000..75a2755644 --- /dev/null +++ b/src/krb524/misc.c @@ -0,0 +1,32 @@ +/* + * Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. It + * is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Geer Zolot Associates not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Geer Zolot Associates makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#if !defined(lint) && !defined(SABER) +static char rcs_id[] = "$Id$"; +#endif + +#include <stdio.h> +#include "krb524.h" + +void krb524_init_ets() +{ + krb5_init_ets(); + initialize_k524_error_table(); +} diff --git a/src/krb524/sendmsg.c b/src/krb524/sendmsg.c new file mode 100644 index 0000000000..9b21082dca --- /dev/null +++ b/src/krb524/sendmsg.c @@ -0,0 +1,156 @@ +/* + * Copyright 1990,1991 by the Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + * + * Send a packet to a service and await a reply, using an exponential + * backoff retry algorithm. This is based on krb5_sendto_kdc. + */ + +#if !defined(lint) && !defined(SABER) +static char rcs_id[] = "$Id$"; +#endif /* !lint & !SABER */ + +#include <krb5/krb5.h> +#include <krb5/ext-proto.h> + +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> + +#include <krb5/los-proto.h> + +#ifdef _AIX +#include <sys/select.h> +#endif + +#include "krb524.h" + +/* + * Send the formatted request 'message' to the host/port specified in + * addr and return the response (if any) in 'reply'. + * + * If the message is sent and a response is received, 0 is returned, + * otherwise an error code is returned. + * + * The storage for 'reply' is allocated and should be freed by the caller + * when finished. + */ + +extern int krb5_max_dgram_size; +extern int krb5_max_skdc_timeout; +extern int krb5_skdc_timeout_shift; +extern int krb5_skdc_timeout_1; + +int krb524_send_message (DECLARG(const struct sock addr *, addr), + DECLARG(const krb5_data *, message), + DECLARG(krb5_data *, reply)) + OLDDECLARG(const struct sockaddr *, addr) + OLDDECLARG(const krb5_data *, message) + OLDDECLARG(krb5_data *, reply) +{ + register int timeout; + int nready, received; + krb5_error_code retval; + fd_set readable; + struct timeval waitlen; + int s, cc; + + if ((reply->data = malloc(krb5_max_dgram_size)) == NULL) + return ENOMEM; + reply->length = krb5_max_dgram_size; + + /* XXX 4.2/4.3BSD has PF_xxx = AF_xxx, so the */ + /* socket creation here will work properly... */ + s = socket(addr->sa_family, SOCK_DGRAM, 0); + if (s == -1) { + retval = errno; + goto out; + } + + /* + * On BSD systems, a connected UDP socket will get connection + * refused and net unreachable errors while an unconnected socket + * will time out, so use connect, send, recv instead of sendto, + * recvfrom. The connect here may return an error if the + * destination host is known to be unreachable. + */ + if (connect(s, addr, sizeof(struct sockaddr)) == -1) { + retval = errno; + goto out; + } + + /* + * Send the message, and wait for a reply, using an exponential + * backoff. Use the kdc timeout values, just for consistency. + */ + + received = 0; + for (timeout = krb5_skdc_timeout_1; + timeout < krb5_max_skdc_timeout; + timeout <<= krb5_skdc_timeout_shift) { + + if (send(s, message->data, message->length, 0) != message->length) { + retval = errno; + goto out; + } + + waitlen.tv_usec = 0; + waitlen.tv_sec = timeout; + FD_ZERO(&readable); + FD_SET(s, &readable); + nready = select(1 + s, &readable, 0, 0, &waitlen); + if (nready < 0) { + retval = errno; + goto out; + } else if (nready == 1) { + if ((cc = recv(s, reply->data, reply->length, 0)) == -1) { + retval = errno; + goto out; + } + + /* + * We might consider here verifying that the reply came + * from the host specified, but that check can be fouled + * by some implementations of some network types which + * might show a loopback return address, for example, if + * the server is on the same host as the client. + * + * Besides, reply addresses can be spoofed, and we don't + * want to provide a false sense of security. + */ + reply->length = cc; + retval = 0; + goto out; + } + /* else timeout, try again */ + } + + /* If the loop exits normally, the max timeout expired without */ + /* a reply having arrived. */ + retval = KRB524_NOTRESP; + +out: + (void) close(s); + if (retval) { + free(reply->data); + reply->data = 0; + reply->length = 0; + } + return retval; +} diff --git a/src/krb524/test.c b/src/krb524/test.c new file mode 100644 index 0000000000..56a675d9e9 --- /dev/null +++ b/src/krb524/test.c @@ -0,0 +1,298 @@ +/* + * Copyright 1993 by Geer Zolot Associates. All Rights Reserved. + * + * Export of this software from the United States of America is assumed + * to require a specific license from the United States Government. It + * is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of Geer Zolot Associates not be used in advertising or + * publicity pertaining to distribution of the software without specific, + * written prior permission. Geer Zolot Associates makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#if !defined(lint) && !defined(SABER) +static char rcs_id[] = "$Id$"; +#endif + +#include <stdio.h> +#include <time.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <netdb.h> + +#include <des.h> +#include <krb.h> +#include <krb5/krb5.h> +#include <krb5/asn1.h> + +#include "krb524.h" + +#define KEYSIZE 8 +#define CRED_BUFSIZ 2048 + +#define krb5_print_addrs + +void do_local(krb5_creds *, krb5_keyblock *), + do_remote(krb5_creds *, char *, krb5_keyblock *); + +void print_key(char *msg, char *key) +{ + printf("%s: ", msg); + C_Block_print(key); + printf("\n"); +} + +void print_time(char *msg, int t) +{ + printf("%s: %d, %s", msg, t, ctime(&t)); +} + +void krb5_print_times(char *msg, krb5_ticket_times *t) +{ + printf("%s: Start: %d, %s", msg, t->starttime, ctime(&t->starttime)); + printf("%s: End: %d, %s", msg, t->endtime, ctime(&t->endtime)); + printf("%s: Auth: %d, %s", msg, t->authtime, ctime(&t->authtime)); + printf("%s: Renew: %d, %s", msg, t->renew_till, ctime(&t->renew_till)); +} + +void krb5_print_keyblock(char *msg, krb5_keyblock *key) +{ + printf("%s: Keytype: %d\n", msg, key->keytype); + printf("%s: Length: %d\n", msg, key->length); + printf("%s: Key: ", msg); + C_Block_print(key->contents); + printf("\n"); +} + +void krb5_print_ticket(krb5_data *ticket_data, krb5_keyblock *key) +{ + char *p; + krb5_ticket *tkt; + int ret; + + if (ret = decode_krb5_ticket(ticket_data, &tkt)) { + com_err("test", ret, "decoding ticket"); + exit(1); + } + if (ret = krb5_decrypt_tkt_part(key, tkt)) { + com_err("test", ret, "decrypting V5 ticket for print"); + exit(1); + } + + krb5_unparse_name(tkt->server, &p); + printf("Ticket: Server: %s\n", p); + free(p); + printf("Ticket: EType: %d\n", tkt->enc_part.etype); + printf("Ticket: kvno: %d\n", tkt->enc_part.kvno); + printf("Ticket: Flags: 0x%08x\n", tkt->enc_part2->flags); + krb5_print_keyblock("Ticket: Session Keyblock", + tkt->enc_part2->session); + krb5_unparse_name(tkt->enc_part2->client, &p); + printf("Ticket: Client: %s\n", p); + free(p); + krb5_print_times("Ticket: Times", &tkt->enc_part2->times); + printf("Ticket: Address 0: %08x\n", + *((unsigned long *) tkt->enc_part2->caddrs[0]->contents)); + + krb5_free_ticket(tkt); +} + +void krb5_print_creds(krb5_creds *creds, krb5_keyblock *secret_key) +{ + char *p, buf[BUFSIZ]; + + krb5_unparse_name(creds->client, &p); + printf("Client: %s\n", p); + free(p); + krb5_unparse_name(creds->server, &p); + printf("Server: %s\n", p); + free(p); + krb5_print_keyblock("Session key", &creds->keyblock); + krb5_print_times("Times", &creds->times); + printf("is_skey: %s\n", creds->is_skey ? "True" : "False"); + printf("Flags: 0x%08x\n", creds->ticket_flags); + krb5_print_addrs(creds->addresses); + krb5_print_ticket(&creds->ticket, secret_key); + /* krb5_print_ticket(&creds->second_ticket, secret_key); */ +} + +void krb4_print_ticket(KTEXT ticket, krb5_keyblock *secret_key) +{ + char pname[ANAME_SZ], pinst[INST_SZ], prealm[REALM_SZ]; + char sname[ANAME_SZ], sinst[INST_SZ]; + unsigned char flags; + unsigned long addr, issue_time; + C_Block session_key; + int life; + Key_schedule keysched; + + int ret; + + if (des_key_sched(secret_key->contents, keysched)) { + fprintf(stderr, "Bug in DES key somewhere.\n"); + exit(1); + } + + ret = decomp_ticket(ticket, &flags, pname, pinst, prealm, &addr, + session_key, &life, &issue_time, sname, + sinst, secret_key->contents, keysched); + if (ret != KSUCCESS) { + fprintf(stderr, "krb4 decomp_ticket failed\n"); + exit(1); + } + printf("Ticket: Client: %s.%s@%s\n", pname, pinst, prealm); + printf("Ticket: Service: %s.%s%\n", sname, sinst); + printf("Ticket: Address: %08x\n", addr); + print_key("Ticket: Session Key", session_key); + printf("Ticket: Lifetime: %d\n", life); + printf("Ticket: Issue Date: %d, %s", issue_time, ctime(&issue_time)); +} + +void krb4_print_creds(CREDENTIALS *creds, krb5_keyblock *secret_key) +{ + printf("Client: %s.%s@%s\n", creds->pname, creds->pinst, + creds->realm); + printf("Service: %s.%s@%s\n", creds->service, creds->instance, + creds->realm); + print_key("Session key", creds->session); + printf("Lifetime: %d\n", creds->lifetime); + printf("Key Version: %d\n", creds->kvno); + print_time("Issue Date", creds->issue_date); + krb4_print_ticket(&creds->ticket_st, secret_key); +} + +usage() +{ + fprintf(stderr, "Usage: test [-remote server] client service\n"); + exit(1); +} + +main(int argc, char **argv) +{ + krb5_principal client, server; + krb5_ccache cc; + krb5_creds v5creds; + krb5_keyblock key; + char keybuf[KEYSIZE], buf[BUFSIZ]; + int i, ret, local; + char *remote; + + krb524_debug = 1; + + krb524_init_ets(); + + local = 0; + remote = NULL; + argc--; argv++; + while (argc) { + if (strcmp(*argv, "-local") == 0) + local++; + else if (strcmp(*argv, "-remote") == 0) { + argc--; argv++; + if (!argc) + usage(); + remote = *argv; + } + else + break; + argc--; argv++; + } + if (argc != 2) + usage(); + + if (ret = krb5_parse_name(argv[0], &client)) { + com_err("test", ret, "parsing client name"); + exit(1); + } + if (ret = krb5_parse_name(argv[1], &server)) { + com_err("test", ret, "parsing server name"); + exit(1); + } + if (ret = krb5_cc_default(&cc)) { + com_err("test", ret, "opening default credentials cache"); + exit(1); + } + + bzero((char *) &v5creds, sizeof(v5creds)); + v5creds.client = client; + v5creds.server = server; + v5creds.times.endtime = 0; + v5creds.keyblock.keytype = KEYTYPE_DES; + if (ret = krb5_get_credentials(0, cc, &v5creds)) { + com_err("test", ret, "getting V5 credentials"); + exit(1); + } + + /* We need the service key in order to locally decrypt both */ + /* tickets for testing */ + printf("Service's key: "); + fflush(stdout); + fgets(buf, BUFSIZ, stdin); + for (i = 0; i < 8; i++) { + unsigned char c; + c = buf[2*i]; + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'a' && c <= 'z') + c = c - 'a' + 0xa; + keybuf[i] = c << 4; + c = buf[2*i+1]; + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'a' && c <= 'z') + c = c - 'a' + 0xa; + keybuf[i] += c; + } + + key.keytype = KEYTYPE_DES; + key.length = KEYSIZE; /* presumably */ + key.contents = keybuf; + + do_remote(&v5creds, remote, &key); +} + +void do_remote(krb5_creds *v5creds, char *server, krb5_keyblock *key) +{ + struct sockaddr_in saddr; + struct hostent *hp; + CREDENTIALS v4creds; + int ret; + + printf("\nV5 credentials:\n"); + krb5_print_creds(v5creds, key); + + if (strcmp(server, "kdc") != 0) { + hp = gethostbyname(server); + if (hp == NULL) { + fprintf(stderr, "test: host %s does not exist.\n", server); + exit(1); + } + bzero((char *) &saddr, sizeof(struct sockaddr_in)); + saddr.sin_family = AF_INET; + bcopy(hp->h_addr, (char *) &saddr.sin_addr.s_addr, + sizeof(struct in_addr)); + + if (ret = krb524_convert_creds_addr(v5creds, &v4creds, &saddr)) { + com_err("test", ret, "converting credentials on %s", + server); + exit(1); + } + } else { + if (ret = krb524_convert_creds_kdc(v5creds, &v4creds)) { + com_err("test", ret, "converting credentials via kdc"); + exit(1); + } + } + + printf("\nV4 credentials:\n"); + krb4_print_creds(&v4creds, key); +} |