diff --git a/src/auth/ktc.c b/src/auth/ktc.c index 7a3d6f5471..b304e5a217 100644 --- a/src/auth/ktc.c +++ b/src/auth/ktc.c @@ -80,8 +80,6 @@ RCSID("$Header$"); #ifdef AFS_KERBEROS_ENV #include #include -extern afs_uint32 life_to_time(); -extern unsigned char time_to_life(); #include "cellconfig.h" static char lcell[MAXCELLCHARS]; diff --git a/src/rxkad/.cvsignore b/src/rxkad/.cvsignore index afd6dabd7c..7a72943a87 100644 --- a/src/rxkad/.cvsignore +++ b/src/rxkad/.cvsignore @@ -3,7 +3,6 @@ Makefile crypt_conn.c fcrypt.c fcrypt.h -rxkad.h rxkad_errs.c sboxes.h fc_test diff --git a/src/rxkad/Makefile.in b/src/rxkad/Makefile.in index 279eeacc81..e3fe2c2572 100644 --- a/src/rxkad/Makefile.in +++ b/src/rxkad/Makefile.in @@ -9,12 +9,10 @@ srcdir=@srcdir@ include @TOP_OBJDIR@/src/config/Makefile.config CFLAGS=-I. -I${srcdir} ${OPTMZ} -I${TOP_OBJDIR}/src/config -I${TOP_INCDIR} ${XCFLAGS} -INCLS=${TOP_INCDIR}/rx/rx.h ${TOP_INCDIR}/rx/xdr.h \ - ${TOP_INCDIR}/rx/fcrypt.h \ - rxkad.h rxkad_prototypes.h fcrypt.h +INCLS=${TOP_INCDIR}/rx/rx.h ${TOP_INCDIR}/rx/xdr.h -OBJS=rxkad_client.o rxkad_server.o rxkad_common.o ticket.o rxkad_errs.o \ - fcrypt.o crypt_conn.o +OBJS=rxk_clnt.o rxk_crpt.o rxk_info.o rxk_locl.o rxk_serv.o \ + rxkad_errs.o v4.o v5.o crc.o fc_test_OBJS=fc_test.o @@ -24,23 +22,18 @@ fc_test_LIBS=\ ${TOP_LIBDIR}/liblwp.a \ ${TOP_LIBDIR}/libsys.a -all: kinstall ukinstall ${TOP_LIBDIR}/librxkad.a fc_test \ - ${TOP_INCDIR}/rx/rxkad.h ${TOP_INCDIR}/rx/rxkad_prototypes.h \ - ${TOP_INCDIR}/rx/fcrypt.h +all: kinstall ukinstall \ + ${TOP_INCDIR}/rx/rxkad.h ${TOP_INCDIR}/rx/rxkad_errs.h \ + ${TOP_LIBDIR}/librxkad.a fc_test + + +v5.o: v5.c v5gen.c v5der.c v5gen-rewrite.h # # Install targets # kinstall: \ - ${KERNELDIR}/afs/private_data.h \ - ${KERNELDIR}/afs/rxkad.h \ - ${KERNELDIR}/afs/rxkad_prototypes.h \ - ${KERNELDIR}/afs/sboxes.h \ - ${KERNELDIR}/afs/fcrypt.h \ - ${KERNELDIR}/afs/fcrypt.c \ - ${KERNELDIR}/afs/crypt_conn.c \ - ${KERNELDIR}/afs/rxkad_client.c \ - ${KERNELDIR}/afs/rxkad_common.c + ${KERNELDIR}/afs/rxkad.h ${KERNELDIR}/afs/rxkad_errs.h ${KERNELDIR}/afs/private_data.h: private_data.h ${INSTALL} $? $@ @@ -48,7 +41,7 @@ ${KERNELDIR}/afs/private_data.h: private_data.h ${KERNELDIR}/afs/rxkad.h: rxkad.h ${INSTALL} $? $@ -${KERNELDIR}/afs/rxkad_prototypes.h: rxkad_prototypes.h +${KERNELDIR}/afs/rxkad_errs.h: rxkad_errs.h ${INSTALL} $? $@ ${KERNELDIR}/afs/sboxes.h: sboxes.h @@ -69,26 +62,8 @@ ${KERNELDIR}/afs/rxkad_client.c: rxkad_client.c ${KERNELDIR}/afs/rxkad_common.c: rxkad_common.c ${INSTALL} $? $@ -ukinstall: \ - ${UKERNELDIR}/afs \ - ${UKERNELDIR}/rx \ - ${UKERNELDIR}/afs/private_data.h \ - ${UKERNELDIR}/afs/rxkad.h \ - ${UKERNELDIR}/afs/rxkad_prototypes.h \ - ${UKERNELDIR}/afs/fcrypt.h \ - ${UKERNELDIR}/rx/rxkad.h \ - ${UKERNELDIR}/rx/rxkad_prototypes.h \ - ${UKERNELDIR}/rx/fcrypt.h \ - ${UKERNELDIR}/afs/sboxes.h \ - ${UKERNELDIR}/afs/fcrypt.c \ - ${UKERNELDIR}/afs/crypt_conn.c \ - ${UKERNELDIR}/afs/rxkad_client.c \ - ${UKERNELDIR}/afs/rxkad_common.c \ - ${UKERNELDIR}/afs/ticket.c \ - ${UKERNELDIR}/afs/rxkad_server.c \ - ${UKERNELDIR}/afs/lifetimes.h \ - ${UKERNELDIR}/afs/rxkad_errs.c - +ukinstall: \ + ${UKERNELDIR}/afs/rxkad.h ${UKERNELDIR}/afs/rxkad_errs.h ${UKERNELDIR}/afs: mkdir -p $? @@ -102,22 +77,22 @@ ${UKERNELDIR}/afs/private_data.h: private_data.h ${UKERNELDIR}/afs/rxkad.h: rxkad.h ${INSTALL} $? $@ -${UKERNELDIR}/afs/rxkad_prototypes.h: rxkad_prototypes.h +${UKERNELDIR}/afs/rxkad_errs.h: rxkad_errs.h ${INSTALL} $? $@ -${UKERNELDIR}/afs/fcrypt.h: fcrypt.h +${UKERNELDIR}/rx/rxkad.h: rxkad.h ${INSTALL} $? $@ -${UKERNELDIR}/rx/rxkad_prototypes.h: rxkad_prototypes.h +${UKERNELDIR}/rx/rxkad_errs.h: rxkad_errs.h ${INSTALL} $? $@ ${UKERNELDIR}/afs/lifetimes.h: lifetimes.h ${INSTALL} $? $@ -${UKERNELDIR}/afs/ticket.c: ticket.c +${UKERNELDIR}/afs/sboxes.h: sboxes.h ${INSTALL} $? $@ -${UKERNELDIR}/afs/sboxes.h: sboxes.h +${UKERNELDIR}/afs/fcrypt.h: fcrypt.h ${INSTALL} $? $@ ${UKERNELDIR}/afs/fcrypt.c: fcrypt.c @@ -138,28 +113,15 @@ ${UKERNELDIR}/afs/rxkad_server.c: rxkad_server.c ${UKERNELDIR}/afs/rxkad_common.c: rxkad_common.c ${INSTALL} $? $@ -${UKERNELDIR}/rx/rxkad.h: rxkad.h - ${INSTALL} $? $@ - -${UKERNELDIR}/rx/fcrypt.h: fcrypt.h - ${INSTALL} $? $@ - -install: \ - ${DESTDIR}${libdir}/librxkad.a \ - ${DESTDIR}${includedir}/rx/fcrypt.h \ - ${DESTDIR}${includedir}/rx/rxkad.h \ - ${DESTDIR}${includedir}/rx/rxkad_prototypes.h +install: ${DESTDIR}${libdir}/librxkad.a ${DESTDIR}${includedir}/rx/rxkad.h ${DESTDIR}${includedir}/rx/rxkad_errs.h ${DEST}/lib/librxkad.a: librxkad.a ${INSTALL} $? $@ -${DEST}/include/rx/fcrypt.h: fcrypt.h - ${INSTALL} $? $@ - ${DEST}/include/rx/rxkad.h: rxkad.h ${INSTALL} $? $@ -${DEST}/include/rx/rxkad_prototypes.h: rxkad_prototypes.h +${DEST}/include/rx/rxkad_errs.h: rxkad_errs.h ${INSTALL} $? $@ # @@ -171,30 +133,6 @@ librxkad.a: ${OBJS} AFS_component_version_number.o $(AR) crv $@ ${OBJS} AFS_component_version_number.o $(RANLIB) $@ -crypt_conn.o: fcrypt.h private_data.h crypt_conn.c ${INCLS} - -rxkad_client.o: fcrypt.h private_data.h rxkad_client.c ${INCLS} - -rxkad_server.o: fcrypt.h private_data.h rxkad_server.c ${INCLS} - -rxkad_common.o: fcrypt.h private_data.h rxkad_common.c ${INCLS} - -rxkad_errs.o: rxkad_errs.c - -rxkad_errs.c rxkad.h: rxkad_errs.et rxkad.p.h - $(RM) -f rxkad.h rxkad_errs.c - ${COMPILE_ET} -p ${srcdir} rxkad_errs -h rxkad - -ticket.o: ticket.c lifetimes.h ${INCLS} - -fcrypt.o: fcrypt.c fcrypt.h sboxes.h rxkad.h rxkad_prototypes.h - ${CC} ${CFLAGS} -c fcrypt.c - -tcrypt: tcrypt.o librxkad.a - ${CC} -o tcrypt tcrypt.o librxkad.a - -tcrypt.o: tcrypt.c AFS_component_version_number.o - fc_test: ${fc_test_OBJS} ${CC} ${CFLAGS} -o fc_test ${fc_test_OBJS} ${fc_test_LIBS} ${XLIBS} @@ -205,7 +143,7 @@ fc_test.o: ${INCLS} # clean: - $(RM) -f *.o *.a tcrypt core rxkad_errs.c rxkad.h \ + $(RM) -f *.o *.a tcrypt core rxkad_errs.c \ AFS_component_version_number.c \ crypt_conn.c fcrypt.c fcrypt.h sboxes.h \ fc_test @@ -238,27 +176,20 @@ ${DESTDIR}${libdir}/librxkad.a: librxkad.a ${TOP_LIBDIR}/librxkad.a: librxkad.a ${INSTALL} $? $@ -${DESTDIR}${includedir}/rx/fcrypt.h: fcrypt.h - ${INSTALL} $? $@ - ${DESTDIR}${includedir}/rx/rxkad.h: rxkad.h ${INSTALL} $? $@ -${DESTDIR}${includedir}/rx/rxkad_prototypes.h: rxkad_prototypes.h - ${INSTALL} $? $@ - -${TOP_INCDIR}/rx/fcrypt.h: fcrypt.h +${DESTDIR}${includedir}/rx/rxkad_errs.h: rxkad_errs.h ${INSTALL} $? $@ ${TOP_INCDIR}/rx/rxkad.h: rxkad.h ${INSTALL} $? $@ -${TOP_INCDIR}/rx/rxkad_prototypes.h: rxkad_prototypes.h +${TOP_INCDIR}/rx/rxkad_errs.h: rxkad_errs.h ${INSTALL} $? $@ -dest: \ - ${DEST}/lib/librxkad.a \ - ${DEST}/include/rx/fcrypt.h \ - ${DEST}/include/rx/rxkad.h \ - ${DEST}/include/rx/rxkad_prototypes.h +dest: ${DEST}/lib/librxkad.a ${DEST}/include/rx/rxkad.h ${DEST}/include/rx/rxkad_errs.h +rxkad_errs.c rxkad_errs.h: rxkad_errs.et + $(RM) -f rxkad_errs.h rxkad_errs.c + ${COMPILE_ET} -p ${srcdir} rxkad_errs -h rxkad_errs diff --git a/src/rxkad/README b/src/rxkad/README deleted file mode 100644 index af39779ea7..0000000000 --- a/src/rxkad/README +++ /dev/null @@ -1,2 +0,0 @@ -NOTE: fc_cbc_encrypt now modifies its 5th argument, to permit chaining over -scatter/gather vectors. diff --git a/src/rxkad/asn1-common.h b/src/rxkad/asn1-common.h new file mode 100644 index 0000000000..6f470d795a --- /dev/null +++ b/src/rxkad/asn1-common.h @@ -0,0 +1,21 @@ +/* $Id$ */ + +#include +#include + +#ifndef __asn1_common_definitions__ +#define __asn1_common_definitions__ + +typedef struct octet_string { + size_t length; + void *data; +} octet_string; + +typedef char *general_string; + +typedef struct oid { + size_t length; + unsigned *components; +} oid; + +#endif diff --git a/src/rxkad/asn1_err.h b/src/rxkad/asn1_err.h new file mode 100644 index 0000000000..fe81da9602 --- /dev/null +++ b/src/rxkad/asn1_err.h @@ -0,0 +1,23 @@ +/* Generated from ../../../lib/asn1/asn1_err.et */ +/* $Id$ */ + +#ifndef __asn1_err_h__ +#define __asn1_err_h__ + +typedef enum asn1_error_number{ + ERROR_TABLE_BASE_asn1 = 1859794432, + asn1_err_base = 1859794432, + ASN1_BAD_TIMEFORMAT = 1859794432, + ASN1_MISSING_FIELD = 1859794433, + ASN1_MISPLACED_FIELD = 1859794434, + ASN1_TYPE_MISMATCH = 1859794435, + ASN1_OVERFLOW = 1859794436, + ASN1_OVERRUN = 1859794437, + ASN1_BAD_ID = 1859794438, + ASN1_BAD_LENGTH = 1859794439, + ASN1_BAD_FORMAT = 1859794440, + ASN1_PARSE_ERROR = 1859794441, + asn1_num_errors = 10 +} asn1_error_number; + +#endif /* __asn1_err_h__ */ diff --git a/src/rxkad/crc.c b/src/rxkad/crc.c new file mode 100644 index 0000000000..49deca102a --- /dev/null +++ b/src/rxkad/crc.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 1997 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +/* RCSID("$Heimdal: crc.c,v 1.9 2000/08/03 01:45:14 assar Exp $"); */ + +#include "rxkad_locl.h" + +static u_long table[256]; + +#define CRC_GEN 0xEDB88320L + +void +_rxkad_crc_init_table(void) +{ + static int flag = 0; + unsigned long crc, poly; + int i, j; + + if(flag) return; + poly = CRC_GEN; + for (i = 0; i < 256; i++) { + crc = i; + for (j = 8; j > 0; j--) { + if (crc & 1) { + crc = (crc >> 1) ^ poly; + } else { + crc >>= 1; + } + } + table[i] = crc; + } + flag = 1; +} + +afs_uint32 +_rxkad_crc_update (const char *p, size_t len, afs_uint32 res) +{ + while (len--) + res = table[(res ^ *p++) & 0xFF] ^ (res >> 8); + return res & 0xFFFFFFFF; +} diff --git a/src/rxkad/der.h b/src/rxkad/der.h new file mode 100644 index 0000000000..cd2a40a730 --- /dev/null +++ b/src/rxkad/der.h @@ -0,0 +1,152 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +/* $Id$ */ + +#ifndef __DER_H__ +#define __DER_H__ + +#include + +typedef enum {UNIV = 0, APPL = 1, CONTEXT = 2 , PRIVATE = 3} Der_class; + +typedef enum {PRIM = 0, CONS = 1} Der_type; + +/* Universal tags */ + +enum { + UT_Boolean = 1, + UT_Integer = 2, + UT_BitString = 3, + UT_OctetString = 4, + UT_Null = 5, + UT_OID = 6, + UT_Enumerated = 10, + UT_Sequence = 16, + UT_Set = 17, + UT_PrintableString = 19, + UT_IA5String = 22, + UT_UTCTime = 23, + UT_GeneralizedTime = 24, + UT_VisibleString = 26, + UT_GeneralString = 27 +}; + +#define ASN1_INDEFINITE 0xdce0deed + +#ifndef HAVE_TIMEGM +time_t timegm (struct tm *); +#endif + +int time2generalizedtime (time_t t, octet_string *s); + +int der_get_int (const unsigned char *p, size_t len, int *ret, size_t *size); +int der_get_length (const unsigned char *p, size_t len, + size_t *val, size_t *size); +int der_get_general_string (const unsigned char *p, size_t len, + general_string *str, size_t *size); +int der_get_octet_string (const unsigned char *p, size_t len, + octet_string *data, size_t *size); +int der_get_oid (const unsigned char *p, size_t len, + oid *data, size_t *size); +int der_get_tag (const unsigned char *p, size_t len, + Der_class *class, Der_type *type, + int *tag, size_t *size); + +int der_match_tag (const unsigned char *p, size_t len, + Der_class class, Der_type type, + int tag, size_t *size); +int der_match_tag_and_length (const unsigned char *p, size_t len, + Der_class class, Der_type type, int tag, + size_t *length_ret, size_t *size); + +int decode_integer (const unsigned char*, size_t, int*, size_t*); +int decode_unsigned (const unsigned char*, size_t, unsigned*, size_t*); +int decode_enumerated (const unsigned char*, size_t, unsigned*, size_t*); +int decode_general_string (const unsigned char*, size_t, + general_string*, size_t*); +int decode_oid (const unsigned char *p, size_t len, + oid *k, size_t *size); +int decode_octet_string (const unsigned char*, size_t, octet_string*, size_t*); +int decode_generalized_time (const unsigned char*, size_t, time_t*, size_t*); + +int der_put_int (unsigned char *p, size_t len, int val, size_t*); +int der_put_length (unsigned char *p, size_t len, size_t val, size_t*); +int der_put_general_string (unsigned char *p, size_t len, + const general_string *str, size_t*); +int der_put_octet_string (unsigned char *p, size_t len, + const octet_string *data, size_t*); +int der_put_oid (unsigned char *p, size_t len, + const oid *data, size_t *size); +int der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, + int tag, size_t*); +int der_put_length_and_tag (unsigned char*, size_t, size_t, + Der_class, Der_type, int, size_t*); + +int encode_integer (unsigned char *p, size_t len, + const int *data, size_t*); +int encode_unsigned (unsigned char *p, size_t len, + const unsigned *data, size_t*); +int encode_enumerated (unsigned char *p, size_t len, + const unsigned *data, size_t*); +int encode_general_string (unsigned char *p, size_t len, + const general_string *data, size_t*); +int encode_octet_string (unsigned char *p, size_t len, + const octet_string *k, size_t*); +int encode_oid (unsigned char *p, size_t len, + const oid *k, size_t*); +int encode_generalized_time (unsigned char *p, size_t len, + const time_t *t, size_t*); + +void free_integer (int *num); +void free_general_string (general_string *str); +void free_octet_string (octet_string *k); +void free_oid (oid *k); +void free_generalized_time (time_t *t); + +size_t length_len (size_t len); +size_t length_integer (const int *data); +size_t length_unsigned (const unsigned *data); +size_t length_enumerated (const unsigned *data); +size_t length_general_string (const general_string *data); +size_t length_octet_string (const octet_string *k); +size_t length_oid (const oid *k); +size_t length_generalized_time (const time_t *t); + +int copy_general_string (const general_string *from, general_string *to); +int copy_octet_string (const octet_string *from, octet_string *to); +int copy_oid (const oid *from, oid *to); + +int fix_dce(size_t reallen, size_t *len); + +#endif /* __DER_H__ */ diff --git a/src/rxkad/der_free.c b/src/rxkad/der_free.c new file mode 100644 index 0000000000..e0a3849ad2 --- /dev/null +++ b/src/rxkad/der_free.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +#include "der_locl.h" + +RCSID("$Id$"); + +void +free_general_string (general_string *str) +{ + free(*str); +} + +void +free_octet_string (octet_string *k) +{ + free(k->data); +} + +void +free_oid (oid *k) +{ + free(k->components); +} diff --git a/src/rxkad/der_get.c b/src/rxkad/der_get.c new file mode 100644 index 0000000000..7e2038ec51 --- /dev/null +++ b/src/rxkad/der_get.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +#include "der_locl.h" + +RCSID("$Id$"); + +#include + +/* + * All decoding functions take a pointer `p' to first position in + * which to read, from the left, `len' which means the maximum number + * of characters we are able to read, `ret' were the value will be + * returned and `size' where the number of used bytes is stored. + * Either 0 or an error code is returned. + */ + +static int +der_get_unsigned (const unsigned char *p, size_t len, + unsigned *ret, size_t *size) +{ + unsigned val = 0; + size_t oldlen = len; + + while (len--) + val = val * 256 + *p++; + *ret = val; + if(size) *size = oldlen; + return 0; +} + +int +der_get_int (const unsigned char *p, size_t len, + int *ret, size_t *size) +{ + int val = 0; + size_t oldlen = len; + + if (len--) + val = (signed char)*p++; + while (len--) + val = val * 256 + *p++; + *ret = val; + if(size) *size = oldlen; + return 0; +} + +int +der_get_length (const unsigned char *p, size_t len, + size_t *val, size_t *size) +{ + size_t v; + + if (len <= 0) + return ASN1_OVERRUN; + --len; + v = *p++; + if (v < 128) { + *val = v; + if(size) *size = 1; + } else { + int e; + size_t l; + unsigned tmp; + + if(v == 0x80){ + *val = ASN1_INDEFINITE; + if(size) *size = 1; + return 0; + } + v &= 0x7F; + if (len < v) + return ASN1_OVERRUN; + e = der_get_unsigned (p, v, &tmp, &l); + if(e) return e; + *val = tmp; + if(size) *size = l + 1; + } + return 0; +} + +int +der_get_general_string (const unsigned char *p, size_t len, + general_string *str, size_t *size) +{ + char *s; + + s = malloc (len + 1); + if (s == NULL) + return ENOMEM; + memcpy (s, p, len); + s[len] = '\0'; + *str = s; + if(size) *size = len; + return 0; +} + +int +der_get_octet_string (const unsigned char *p, size_t len, + octet_string *data, size_t *size) +{ + data->length = len; + data->data = malloc(len); + if (data->data == NULL && data->length != 0) + return ENOMEM; + memcpy (data->data, p, len); + if(size) *size = len; + return 0; +} + +int +der_get_oid (const unsigned char *p, size_t len, + oid *data, size_t *size) +{ + int n; + size_t oldlen = len; + + if (len < 1) + return ASN1_OVERRUN; + + data->components = malloc(len * sizeof(*data->components)); + if (data->components == NULL && len != 0) + return ENOMEM; + data->components[0] = (*p) / 40; + data->components[1] = (*p) % 40; + --len; + ++p; + for (n = 2; len > 0; ++n) { + unsigned u = 0; + + do { + --len; + u = u * 128 + (*p++ % 128); + } while (len > 0 && p[-1] & 0x80); + data->components[n] = u; + } + if (p[-1] & 0x80) { + free_oid (data); + return ASN1_OVERRUN; + } + data->length = n; + if (size) + *size = oldlen; + return 0; +} + +int +der_get_tag (const unsigned char *p, size_t len, + Der_class *class, Der_type *type, + int *tag, size_t *size) +{ + if (len < 1) + return ASN1_OVERRUN; + *class = (Der_class)(((*p) >> 6) & 0x03); + *type = (Der_type)(((*p) >> 5) & 0x01); + *tag = (*p) & 0x1F; + if(size) *size = 1; + return 0; +} + +int +der_match_tag (const unsigned char *p, size_t len, + Der_class class, Der_type type, + int tag, size_t *size) +{ + size_t l; + Der_class thisclass; + Der_type thistype; + int thistag; + int e; + + e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l); + if (e) return e; + if (class != thisclass || type != thistype) + return ASN1_BAD_ID; + if(tag > thistag) + return ASN1_MISPLACED_FIELD; + if(tag < thistag) + return ASN1_MISSING_FIELD; + if(size) *size = l; + return 0; +} + +int +der_match_tag_and_length (const unsigned char *p, size_t len, + Der_class class, Der_type type, int tag, + size_t *length_ret, size_t *size) +{ + size_t l, ret = 0; + int e; + + e = der_match_tag (p, len, class, type, tag, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_length (p, len, length_ret, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +int +decode_integer (const unsigned char *p, size_t len, + int *num, size_t *size) +{ + size_t ret = 0; + size_t l, reallen; + int e; + + e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_length (p, len, &reallen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_int (p, reallen, num, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +int +decode_unsigned (const unsigned char *p, size_t len, + unsigned *num, size_t *size) +{ + size_t ret = 0; + size_t l, reallen; + int e; + + e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_length (p, len, &reallen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_unsigned (p, reallen, num, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +int +decode_enumerated (const unsigned char *p, size_t len, + unsigned *num, size_t *size) +{ + size_t ret = 0; + size_t l, reallen; + int e; + + e = der_match_tag (p, len, UNIV, PRIM, UT_Enumerated, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_length (p, len, &reallen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_int (p, reallen, num, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +int +decode_general_string (const unsigned char *p, size_t len, + general_string *str, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + size_t slen; + + e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralString, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + + e = der_get_length (p, len, &slen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if (len < slen) + return ASN1_OVERRUN; + + e = der_get_general_string (p, slen, str, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +int +decode_octet_string (const unsigned char *p, size_t len, + octet_string *k, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + size_t slen; + + e = der_match_tag (p, len, UNIV, PRIM, UT_OctetString, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + + e = der_get_length (p, len, &slen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if (len < slen) + return ASN1_OVERRUN; + + e = der_get_octet_string (p, slen, k, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +int +decode_oid (const unsigned char *p, size_t len, + oid *k, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + size_t slen; + + e = der_match_tag (p, len, UNIV, PRIM, UT_OID, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + + e = der_get_length (p, len, &slen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if (len < slen) + return ASN1_OVERRUN; + + e = der_get_oid (p, slen, k, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +static void +generalizedtime2time (const char *s, time_t *t) +{ + struct tm tm; + + memset(&tm, 0, sizeof(tm)); + sscanf (s, "%04d%02d%02d%02d%02d%02dZ", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, + &tm.tm_min, &tm.tm_sec); + tm.tm_year -= 1900; + tm.tm_mon -= 1; + *t = timegm (&tm); +} + +int +decode_generalized_time (const unsigned char *p, size_t len, + time_t *t, size_t *size) +{ + octet_string k; + char *times; + size_t ret = 0; + size_t l; + int e; + size_t slen; + + e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralizedTime, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + + e = der_get_length (p, len, &slen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if (len < slen) + return ASN1_OVERRUN; + e = der_get_octet_string (p, slen, &k, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + times = realloc(k.data, k.length + 1); + if (times == NULL){ + free(k.data); + return ENOMEM; + } + times[k.length] = 0; + generalizedtime2time (times, t); + free (times); + if(size) *size = ret; + return 0; +} + + +int +fix_dce(size_t reallen, size_t *len) +{ + if(reallen == ASN1_INDEFINITE) + return 1; + if(*len < reallen) + return -1; + *len = reallen; + return 0; +} diff --git a/src/rxkad/der_put.c b/src/rxkad/der_put.c new file mode 100644 index 0000000000..aea6f59cf2 --- /dev/null +++ b/src/rxkad/der_put.c @@ -0,0 +1,418 @@ +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +#include "der_locl.h" + +RCSID("$Id$"); + +/* + * All encoding functions take a pointer `p' to first position in + * which to write, from the right, `len' which means the maximum + * number of characters we are able to write. The function returns + * the number of characters written in `size' (if non-NULL). + * The return value is 0 or an error. + */ + +static int +der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size) +{ + unsigned char *base = p; + + if (val) { + while (len > 0 && val) { + *p-- = val % 256; + val /= 256; + --len; + } + if (val != 0) + return ASN1_OVERFLOW; + else { + *size = base - p; + return 0; + } + } else if (len < 1) + return ASN1_OVERFLOW; + else { + *p = 0; + *size = 1; + return 0; + } +} + +int +der_put_int (unsigned char *p, size_t len, int val, size_t *size) +{ + unsigned char *base = p; + + if(val >= 0) { + do { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = val % 256; + len--; + val /= 256; + } while(val); + if(p[1] >= 128) { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = 0; + len--; + } + } else { + val = ~val; + do { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = ~(val % 256); + len--; + val /= 256; + } while(val); + if(p[1] < 128) { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = 0xff; + len--; + } + } + *size = base - p; + return 0; +} + + +int +der_put_length (unsigned char *p, size_t len, size_t val, size_t *size) +{ + if (len < 1) + return ASN1_OVERFLOW; + if (val < 128) { + *p = val; + *size = 1; + return 0; + } else { + size_t l; + int e; + + e = der_put_unsigned (p, len - 1, val, &l); + if (e) + return e; + p -= l; + *p = 0x80 | l; + *size = l + 1; + return 0; + } +} + +int +der_put_general_string (unsigned char *p, size_t len, + const general_string *str, size_t *size) +{ + size_t slen = strlen(*str); + + if (len < slen) + return ASN1_OVERFLOW; + p -= slen; + len -= slen; + memcpy (p+1, *str, slen); + *size = slen; + return 0; +} + +int +der_put_octet_string (unsigned char *p, size_t len, + const octet_string *data, size_t *size) +{ + if (len < data->length) + return ASN1_OVERFLOW; + p -= data->length; + len -= data->length; + memcpy (p+1, data->data, data->length); + *size = data->length; + return 0; +} + +int +der_put_oid (unsigned char *p, size_t len, + const oid *data, size_t *size) +{ + unsigned char *base = p; + int n; + + for (n = data->length - 1; n >= 2; --n) { + unsigned u = data->components[n]; + + if (len < 1) + return ASN1_OVERFLOW; + *p-- = u % 128; + u /= 128; + --len; + while (u > 0) { + if (len < 1) + return ASN1_OVERFLOW; + *p-- = 128 + u % 128; + u /= 128; + --len; + } + } + if (len < 1) + return ASN1_OVERFLOW; + *p-- = 40 * data->components[0] + data->components[1]; + *size = base - p; + return 0; +} + +int +der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, + int tag, size_t *size) +{ + if (len < 1) + return ASN1_OVERFLOW; + *p = (class << 6) | (type << 5) | tag; /* XXX */ + *size = 1; + return 0; +} + +int +der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, + Der_class class, Der_type type, int tag, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + + e = der_put_length (p, len, len_val, &l); + if(e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_tag (p, len, class, type, tag, &l); + if(e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +encode_integer (unsigned char *p, size_t len, const int *data, size_t *size) +{ + int num = *data; + size_t ret = 0; + size_t l; + int e; + + e = der_put_int (p, len, num, &l); + if(e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Integer, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +encode_unsigned (unsigned char *p, size_t len, const unsigned *data, + size_t *size) +{ + unsigned num = *data; + size_t ret = 0; + size_t l; + int e; + + e = der_put_unsigned (p, len, num, &l); + if(e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Integer, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +encode_enumerated (unsigned char *p, size_t len, const unsigned *data, + size_t *size) +{ + unsigned num = *data; + size_t ret = 0; + size_t l; + int e; + + e = der_put_int (p, len, num, &l); + if(e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Enumerated, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +encode_general_string (unsigned char *p, size_t len, + const general_string *data, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + + e = der_put_general_string (p, len, data, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_GeneralString, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +encode_octet_string (unsigned char *p, size_t len, + const octet_string *k, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + + e = der_put_octet_string (p, len, k, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_OctetString, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +encode_oid(unsigned char *p, size_t len, + const oid *k, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + + e = der_put_oid (p, len, k, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_OID, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +time2generalizedtime (time_t t, octet_string *s) +{ + struct tm *tm; + + s->data = malloc(16); + if (s->data == NULL) + return ENOMEM; + s->length = 15; + tm = gmtime (&t); + sprintf (s->data, "%04d%02d%02d%02d%02d%02dZ", tm->tm_year + 1900, + tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + return 0; +} + +int +encode_generalized_time (unsigned char *p, size_t len, + const time_t *t, size_t *size) +{ + size_t ret = 0; + size_t l; + octet_string k; + int e; + + e = time2generalizedtime (*t, &k); + if (e) + return e; + e = der_put_octet_string (p, len, &k, &l); + free (k.data); + if (e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, k.length, UNIV, PRIM, + UT_GeneralizedTime, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} diff --git a/src/rxkad/fc_test.c b/src/rxkad/fc_test.c index 81874a05ef..f246db4930 100644 --- a/src/rxkad/fc_test.c +++ b/src/rxkad/fc_test.c @@ -32,13 +32,10 @@ */ #include -#include "rxkad.h" +#include "rxkad_locl.h" #include -#include "private_data.h" #define ROUNDS 16 -#define ENCRYPT 1 -#define DECRYPT 0 typedef afs_int32 int32; typedef afs_uint32 u_int32; @@ -72,7 +69,8 @@ const char ciph2[] = { #define rxkad_EncryptPacket _afs_bpwQbdoghO #endif -int main(void) +int +main() { int32 sched[ROUNDS]; char ciph[100], clear[100]; @@ -80,13 +78,17 @@ int main(void) u_int32 iv[2]; struct rx_connection conn; struct rx_securityClass obj; +#if 0 struct rxkad_cprivate cpriv; +#endif struct rx_packet packet; int fail = 0; conn.securityObject = &obj; +#if 0 obj.privateData = (void *)&cpriv; cpriv.type = 0; +#endif if (sizeof(int32) != 4) { fprintf(stderr, "error: sizeof(int32) != 4\n"); diff --git a/src/rxkad/lifetimes.h b/src/rxkad/lifetimes.h deleted file mode 100644 index b67720be86..0000000000 --- a/src/rxkad/lifetimes.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2000, International Business Machines Corporation and others. - * All Rights Reserved. - * - * This software has been released under the terms of the IBM Public - * License. For details, see the LICENSE file in the top-level source - * directory or online at http://www.openafs.org/dl/license10.html - */ - -/* Ticket lifetime. This defines the table used to lookup lifetime for the - fixed part of rande of the one byte lifetime field. Values less than 0x80 - are intrpreted as the number of 5 minute intervals. Values from 0x80 to - 0xBF should be looked up in this table. The value of 0x80 is the same using - both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days. - The intervening values of have a fixed ratio of roughly 1.06914. The value - oxFF is defined to mean a ticket has no expiration time. This should be - used advisedly since individual servers may impose defacto upperbounds on - ticket lifetimes. */ - -#define TKTLIFENUMFIXED 64 -#define TKTLIFEMINFIXED 0x80 -#define TKTLIFEMAXFIXED 0xBF -#define TKTLIFENOEXPIRE 0xFF -#define MAXTKTLIFETIME (30*24*3600) /* 30 days */ - -static const int tkt_lifetimes[TKTLIFENUMFIXED] = { - 38400, /* 10.67 hours, 0.44 days */ - 41055, /* 11.40 hours, 0.48 days */ - 43894, /* 12.19 hours, 0.51 days */ - 46929, /* 13.04 hours, 0.54 days */ - 50174, /* 13.94 hours, 0.58 days */ - 53643, /* 14.90 hours, 0.62 days */ - 57352, /* 15.93 hours, 0.66 days */ - 61318, /* 17.03 hours, 0.71 days */ - 65558, /* 18.21 hours, 0.76 days */ - 70091, /* 19.47 hours, 0.81 days */ - 74937, /* 20.82 hours, 0.87 days */ - 80119, /* 22.26 hours, 0.93 days */ - 85658, /* 23.79 hours, 0.99 days */ - 91581, /* 25.44 hours, 1.06 days */ - 97914, /* 27.20 hours, 1.13 days */ - 104684, /* 29.08 hours, 1.21 days */ - 111922, /* 31.09 hours, 1.30 days */ - 119661, /* 33.24 hours, 1.38 days */ - 127935, /* 35.54 hours, 1.48 days */ - 136781, /* 37.99 hours, 1.58 days */ - 146239, /* 40.62 hours, 1.69 days */ - 156350, /* 43.43 hours, 1.81 days */ - 167161, /* 46.43 hours, 1.93 days */ - 178720, /* 49.64 hours, 2.07 days */ - 191077, /* 53.08 hours, 2.21 days */ - 204289, /* 56.75 hours, 2.36 days */ - 218415, /* 60.67 hours, 2.53 days */ - 233517, /* 64.87 hours, 2.70 days */ - 249664, /* 69.35 hours, 2.89 days */ - 266926, /* 74.15 hours, 3.09 days */ - 285383, /* 79.27 hours, 3.30 days */ - 305116, /* 84.75 hours, 3.53 days */ - 326213, /* 90.61 hours, 3.78 days */ - 348769, /* 96.88 hours, 4.04 days */ - 372885, /* 103.58 hours, 4.32 days */ - 398668, /* 110.74 hours, 4.61 days */ - 426234, /* 118.40 hours, 4.93 days */ - 455705, /* 126.58 hours, 5.27 days */ - 487215, /* 135.34 hours, 5.64 days */ - 520904, /* 144.70 hours, 6.03 days */ - 556921, /* 154.70 hours, 6.45 days */ - 595430, /* 165.40 hours, 6.89 days */ - 636601, /* 176.83 hours, 7.37 days */ - 680618, /* 189.06 hours, 7.88 days */ - 727680, /* 202.13 hours, 8.42 days */ - 777995, /* 216.11 hours, 9.00 days */ - 831789, /* 231.05 hours, 9.63 days */ - 889303, /* 247.03 hours, 10.29 days */ - 950794, /* 264.11 hours, 11.00 days */ - 1016537, /* 282.37 hours, 11.77 days */ - 1086825, /* 301.90 hours, 12.58 days */ - 1161973, /* 322.77 hours, 13.45 days */ - 1242318, /* 345.09 hours, 14.38 days */ - 1328218, /* 368.95 hours, 15.37 days */ - 1420057, /* 394.46 hours, 16.44 days */ - 1518247, /* 421.74 hours, 17.57 days */ - 1623226, /* 450.90 hours, 18.79 days */ - 1735464, /* 482.07 hours, 20.09 days */ - 1855462, /* 515.41 hours, 21.48 days */ - 1983758, /* 551.04 hours, 22.96 days */ - 2120925, /* 589.15 hours, 24.55 days */ - 2267576, /* 629.88 hours, 26.25 days */ - 2424367, /* 673.44 hours, 28.06 days */ - 2592000}; /* 720.00 hours, 30.00 days */ diff --git a/src/rxkad/private_data.h b/src/rxkad/private_data.h deleted file mode 100644 index 8dc0f4fbf1..0000000000 --- a/src/rxkad/private_data.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2000, International Business Machines Corporation and others. - * All Rights Reserved. - * - * This software has been released under the terms of the IBM Public - * License. For details, see the LICENSE file in the top-level source - * directory or online at http://www.openafs.org/dl/license10.html - */ - -/* Declarations of data structures associated with rxkad security objects. */ - -#ifndef RXKAD_PRIVATE_DATA_H -#define RXKAD_PRIVATE_DATA_H - -#include "rxkad.h" - - -#include "fcrypt.h" - -struct connStats { - afs_uint32 - bytesReceived, bytesSent, packetsReceived, packetsSent; -}; - -/* Private data structure representing an RX server end point for rxkad. - * This structure is encrypted in network byte order and transmitted as - * part of a challenge response. It is also used as part of the per-packet - * checksum sent on every packet, to ensure that the per-packet checksum - * is not used in the context of another end point. - * - * THIS STRUCTURE MUST BE A MULTIPLE OF 8 BYTES LONG SINCE IT IS - * ENCRYPTED IN PLACE! - */ -struct rxkad_endpoint { - afs_int32 cuid[2]; /* being used for connection routing */ - afs_uint32 cksum; /* cksum of challenge response */ - afs_int32 securityIndex; /* security index */ -}; - -/* structure used for generating connection IDs; must be encrypted in network - * byte order. Also must be a multiple of 8 bytes for encryption to work - * properly. - */ -struct rxkad_cidgen { - struct clock time; /* time now */ - afs_int32 random1; /* some implementation-specific random info */ - afs_int32 random2; /* more random info */ - afs_int32 counter; /* a counter */ - afs_int32 ipAddr; /* or an approximation to it */ -}; - -/* private data in client-side security object */ -struct rxkad_cprivate { - afs_int32 kvno; /* key version of ticket */ - afs_int32 ticketLen; /* length of ticket */ - fc_KeySchedule keysched; /* the session key */ - fc_InitializationVector ivec; /* initialization vector for cbc */ - char ticket[MAXKTCTICKETLEN]; /* the ticket for the server */ - rxkad_type type; /* always client */ - rxkad_level level; /* minimum security level of client */ -}; - -/* Per connection client-side info */ -struct rxkad_cconn { - fc_InitializationVector preSeq; /* used in computing checksum */ - struct connStats stats; - char cksumSeen; /* rx: header.spare is a checksum */ -}; - -/* private data in server-side security object */ -struct rxkad_sprivate { - char *get_key_rock; /* rock for get_key function */ - int (*get_key)(); /* func. of kvno and server key ptr */ - int (*user_ok)(); /* func called with new client name */ - rxkad_type type; /* always server */ - rxkad_level level; /* minimum security level of server */ -}; - -/* private data in server-side connection */ -struct rxkad_sconn { - rxkad_level level; /* security level of connection */ - char tried; /* did we ever try to auth this conn */ - char authenticated; /* connection is good */ - char cksumSeen; /* rx: header.spare is a checksum */ - afs_uint32 expirationTime; /* when the ticket expires */ - afs_int32 challengeID; /* unique challenge */ - struct connStats stats; /* per connection stats */ - fc_KeySchedule keysched; /* session key */ - fc_InitializationVector ivec; /* initialization vector for cbc */ - fc_InitializationVector preSeq; /* used in computing checksum */ - struct rxkad_serverinfo *rock; /* info about client if saved */ -}; - -struct rxkad_serverinfo { - int kvno; - struct ktc_principal client; -}; - -#define RXKAD_CHALLENGE_PROTOCOL_VERSION 2 - -/* An old style (any version predating 2) challenge packet */ -struct rxkad_oldChallenge { - afs_int32 challengeID; - afs_int32 level; /* minimum security level */ -}; - -/* A version 2 challenge */ -struct rxkad_v2Challenge { - afs_int32 version; - afs_int32 challengeID; - afs_int32 level; - afs_int32 spare; -}; - -/* An old challenge response packet */ -struct rxkad_oldChallengeResponse { - struct { /* encrypted with session key */ - afs_int32 incChallengeID; - afs_int32 level; - } encrypted; - afs_int32 kvno; - afs_int32 ticketLen; -}; -/* bytes of ticket follow here */ - -/* A version 2 challenge response also includes connection routing (Rx server - * end point) and client call number state as well as version and spare fields. - * The encrypted part probably doesn't need to start on an 8 byte boundary, but - * just in case we put in a spare. */ -struct rxkad_v2ChallengeResponse { - afs_int32 version; - afs_int32 spare; - struct { /* encrypted with session key */ - struct rxkad_endpoint endpoint; /* for connection routing */ - afs_int32 callNumbers[RX_MAXCALLS]; /* client call # state */ - afs_int32 incChallengeID; - afs_int32 level; - } encrypted; - afs_int32 kvno; - afs_int32 ticketLen; -}; -/* bytes of ticket follow here */ -#if RX_MAXCALLS != 4 - The above structure requires that (RX_MAXCALLS == 4). -#endif - -#endif /* RXKAD_PRIVATE_DATA_H */ diff --git a/src/rxkad/rxk_clnt.c b/src/rxkad/rxk_clnt.c new file mode 100644 index 0000000000..c4920c76f6 --- /dev/null +++ b/src/rxkad/rxk_clnt.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +#include "rxkad_locl.h" + +RCSID("$Id$"); + + +/* Security object specific client data */ +typedef struct rxkad_clnt_class { + struct rx_securityClass klass; + rxkad_level level; + key_stuff k; + afs_int32 kvno; + afs_int32 ticket_len; + char *ticket; +} rxkad_clnt_class; + +/* Per connection specific client data */ +typedef struct clnt_con_data { + end_stuff e; +} clnt_con_data; + +static +int +client_NewConnection(struct rx_securityClass *obj_, struct rx_connection *con) +{ + rxkad_clnt_class *obj = (rxkad_clnt_class *) obj_; + clnt_con_data *cdat; + + assert(con->securityData == 0); + obj->klass.refCount++; + cdat = (clnt_con_data *) rxi_Alloc(sizeof(clnt_con_data)); + cdat->e.bytesReceived = cdat->e.packetsReceived = 0; + cdat->e.bytesSent = cdat->e.packetsSent = 0; + + con->securityData = (char *) cdat; + rx_nextCid += RX_MAXCALLS; + con->epoch = rx_epoch; + con->cid = rx_nextCid; + /* We don't use trailers but the transarc implementation breaks when + * we don't set the trailer size, packets get to large */ + switch (obj->level) { + case rxkad_clear: + /* nichts */ + break; + case rxkad_auth: + rx_SetSecurityHeaderSize(con, 4); + rx_SetSecurityMaxTrailerSize(con, 4); + break; + case rxkad_crypt: + rx_SetSecurityHeaderSize(con, 8); + rx_SetSecurityMaxTrailerSize(con, 8); + break; + default: + assert(0); + } + rxkad_calc_header_iv(con, obj->k.keysched, + (const struct ktc_encryptionKey *)&obj->k.key, + cdat->e.header_iv); + return 0; +} + +static +int +client_Close(struct rx_securityClass *obj_) +{ + rxkad_clnt_class *obj = (rxkad_clnt_class *) obj_; + obj->klass.refCount--; + if (obj->klass.refCount <= 0) + { + rxi_Free(obj->ticket, obj->ticket_len); + rxi_Free(obj, sizeof(rxkad_clnt_class)); + } + return 0; +} + +static +int +client_DestroyConnection(struct rx_securityClass *obj, + struct rx_connection *con) +{ + clnt_con_data *cdat = (clnt_con_data *)con->securityData; + + if (cdat) + rxi_Free(cdat, sizeof(clnt_con_data)); + return client_Close(obj); +} + +/* + * Receive a challange and respond. + */ +static +int +client_GetResponse(const struct rx_securityClass *obj_, + const struct rx_connection *con, + struct rx_packet *pkt) +{ + rxkad_clnt_class *obj = (rxkad_clnt_class *) obj_; + rxkad_challenge c; + rxkad_response r; + + /* Get challenge */ + if (rx_SlowReadPacket(pkt, 0, sizeof(c), &c) != sizeof(c)) + return RXKADPACKETSHORT; + + if (ntohl(c.version) < RXKAD_VERSION) + return RXKADINCONSISTENCY; /* Don't know how to make vers 1 response. */ + /* Always make a vers 2 response. */ + + if (ntohl(c.min_level) > obj->level) + return RXKADLEVELFAIL; + + /* Make response */ + r.version = htonl(RXKAD_VERSION); + r.unused = 0; + r.encrypted.epoch = htonl(con->epoch); + r.encrypted.cid = htonl(con->cid & RX_CIDMASK); + r.encrypted.cksum = 0; + r.encrypted.security_index = htonl(con->securityIndex); + { + int i; + /* Get and fixup call number vector */ + rxi_GetCallNumberVector(con, r.encrypted.call_numbers); + for (i = 0; i < RX_MAXCALLS; i++) + { + if (r.encrypted.call_numbers[i] < 0) + return RXKADINCONSISTENCY; + r.encrypted.call_numbers[i] = htonl(r.encrypted.call_numbers[i]); + } + } + r.encrypted.inc_nonce = htonl(ntohl(c.nonce) + 1); + r.encrypted.level = htonl((afs_int32)obj->level); + r.kvno = htonl(obj->kvno); + r.ticket_len = htonl(obj->ticket_len); + /* Make checksum before we seal r.encrypted */ + r.encrypted.cksum = rxkad_cksum_response(&r); + /* Seal r.encrypted */ + fc_cbc_enc2(&r.encrypted, &r.encrypted, sizeof(r.encrypted), + obj->k.keysched, (afs_uint32*)&obj->k.key, ENCRYPT); + + /* Stuff response and kerberos ticket into packet */ + if (rx_SlowWritePacket(pkt, 0, sizeof(r), &r) != sizeof(r)) + return RXKADPACKETSHORT; + if (rx_SlowWritePacket(pkt, sizeof(r), obj->ticket_len, obj->ticket) != obj->ticket_len) + return RXKADPACKETSHORT; + rx_SetDataSize(pkt, sizeof(r) + obj->ticket_len); + return 0; +} + +/* + * Checksum and/or encrypt packet. + */ +static +int +client_PreparePacket(struct rx_securityClass *obj_, + struct rx_call *call, + struct rx_packet *pkt) +{ + rxkad_clnt_class *obj = (rxkad_clnt_class *) obj_; + key_stuff *k = &obj->k; + struct rx_connection *con = rx_ConnectionOf(call); + end_stuff *e = &((clnt_con_data *) con->securityData)->e; + + return rxkad_prepare_packet(pkt, con, obj->level, k, e); +} + +/* + * Verify checksums and/or decrypt packet. + */ +static +int +client_CheckPacket(struct rx_securityClass *obj_, + struct rx_call *call, + struct rx_packet *pkt) +{ + rxkad_clnt_class *obj = (rxkad_clnt_class *) obj_; + key_stuff *k = &obj->k; + struct rx_connection *con = rx_ConnectionOf(call); + end_stuff *e = &((clnt_con_data *) con->securityData)->e; + + return rxkad_check_packet(pkt, con, obj->level, k, e); +} + +static +int +client_GetStats(const struct rx_securityClass *obj, + const struct rx_connection *con, + struct rx_securityObjectStats *st) +{ + clnt_con_data *cdat = (clnt_con_data *) con->securityData; + + st->type = rxkad_disipline; + st->level = ((rxkad_clnt_class *)obj)->level; + st->flags = rxkad_checksummed; + if (cdat == 0) + st->flags |= rxkad_unallocated; + { + st->bytesReceived = cdat->e.bytesReceived; + st->packetsReceived = cdat->e.packetsReceived; + st->bytesSent = cdat->e.bytesSent; + st->packetsSent = cdat->e.packetsSent; + } + return 0; +} + +static +struct rx_securityOps client_ops = { + client_Close, + client_NewConnection, + client_PreparePacket, + 0, + 0, + 0, + 0, + client_GetResponse, + 0, + client_CheckPacket, + client_DestroyConnection, + client_GetStats, + 0, + 0, + 0, +}; + +int rxkad_EpochWasSet = 0; + +int rxkad_min_level = rxkad_clear; /* rxkad_{clear, auth, crypt} */ + +struct rx_securityClass * +rxkad_NewClientSecurityObject(rxkad_level level, + struct ktc_encryptionKey *sessionkey, + afs_int32 kvno, + int ticket_len, + char *ticket) +{ + rxkad_clnt_class *obj; + static int inited = 0; + + if (level < rxkad_min_level) + level = rxkad_min_level; /* Boost security level */ + + if (!inited) + { + /* Any good random numbers will do, no real need to use + * cryptographic techniques here */ + union { + afs_uint32 rnd[2]; + struct ktc_encryptionKey k; + } u; + afs_int32 sched[ROUNDS]; + u_long next_epoch; + + u.rnd[0] = rx_nextCid; + u.rnd[1] = rx_epoch; + fc_keysched(sessionkey, sched); + fc_ecb_encrypt(&u.k, &u.k, sched, ENCRYPT); + + /* Some paranoia so we won't reveal the key */ + /*des_set_odd_parity(&u.k);*/ + fc_keysched(&u.k, sched); + fc_ecb_encrypt(&u.k, &u.k, sched, ENCRYPT); + + /* Some paranoia so we won't reveal the key */ + /*des_set_odd_parity(&u.k);*/ + fc_keysched(&u.k, sched); + fc_ecb_encrypt(&u.k, &u.k, sched, ENCRYPT); + + /* Set new cid and epoch generator */ + rx_nextCid = u.rnd[0] << RX_CIDSHIFT; + next_epoch = u.rnd[0] ^ u.rnd[1]; + next_epoch &= 0x7FFFFFFF; + rx_SetEpoch(next_epoch); + rxkad_EpochWasSet = 1; + inited = 1; + } + +#if 0 + /* If we are passed a to large kerberos 5 ticket hope for the best */ + if (ticket_len > MAXKTCTICKETLEN) + ticket_len = MAXKTCTICKETLEN; +#endif + + obj = (rxkad_clnt_class *) rxi_Alloc(sizeof(rxkad_clnt_class)); + obj->klass.refCount = 1; + obj->klass.ops = &client_ops; + + obj->klass.privateData = (char *) obj; + + obj->level = level; + fc_keysched(sessionkey, obj->k.keysched); + memcpy(&obj->k.key, sessionkey, sizeof(struct ktc_encryptionKey)); + obj->kvno = kvno; + + obj->ticket_len = ticket_len; + obj->ticket = rxi_Alloc(ticket_len); + memcpy(obj->ticket, ticket, ticket_len); + + return &obj->klass; +} diff --git a/src/rxkad/rxk_crpt.c b/src/rxkad/rxk_crpt.c new file mode 100644 index 0000000000..b598c91e6d --- /dev/null +++ b/src/rxkad/rxk_crpt.c @@ -0,0 +1,775 @@ +/* + * Copyright (c) 1995 - 2000 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +#include "rxkad_locl.h" + + +/* + * this assumes that KRB_C_BIGENDIAN is used. + * if we can find out endianess at compile-time, do so, + * otherwise WORDS_BIGENDIAN should already have been defined + */ + +#if ENDIANESS_IN_SYS_PARAM_H +# undef WORDS_BIGENDIAN +# include +# include +# if BYTE_ORDER == BIG_ENDIAN +# define WORDS_BIGENDIAN 1 +# elif BYTE_ORDER == LITTLE_ENDIAN + /* ok */ +# else +# error where do you cut your eggs? +# endif +#endif + +RCSID("$Id$"); + +/* + * Unrolling of the inner loops helps the most on pentium chips + * (ca 18%). On risc machines only expect a modest improvement (ca 5%). + * The cost for this is rougly 4k bytes. + */ +#define UNROLL_LOOPS 1 +/* + * Inline assembler gives a boost only to fc_keysched. + * On the pentium expect ca 28%. + */ +/*#define GNU_ASM 1 (now autoconfed) */ + +#if !defined(inline) && !defined(__GNUC__) +#define inline +#endif + +#ifdef MANGLE_NAMES +#define fc_keysched _afs_QTKrFdpoFL +#define fc_ecb_encrypt _afs_sDLThwNLok +#define fc_cbc_encrypt _afs_fkyCWTvfRS +#define rxkad_DecryptPacket _afs_SRWEeqTXrS +#define rxkad_EncryptPacket _afs_bpwQbdoghO +#endif + + +/* Rotate 32 bit word left */ +#define ROT32L(x, n) ((((afs_uint32) x) << (n)) | (((afs_uint32) x) >> (32-(n)))) +#define bswap32(x) (((ROT32L(x, 16) & 0x00ff00ff)<<8) | ((ROT32L(x, 16)>>8) & 0x00ff00ff)) + +#if WORDS_BIGENDIAN +#define NTOH(x) (x) +#else +#define NTOH(x) bswap32(x) +#endif + +/* + * Try to use a good function for ntohl-ing. + * + * The choice is done by autoconf setting EFF_NTOHL to one of: + * CPU function + * i386 ntohl + * i[4-9]86 bswap + * alpha bswap32 + * all else ntohl + */ + +#define EFF_NTOHL bswap + +#if defined(__GNUC__) && (defined(i386) || defined(__i386__)) +static inline afs_uint32 +bswap(afs_uint32 x) +{ + asm("bswap %0" : "=r" (x) : "0" (x)); + return x; +} +#endif + +/* + * Sboxes for Feistel network derived from + * /afs/transarc.com/public/afsps/afs.rel31b.export-src/rxkad/sboxes.h + */ + +#undef Z +#define Z(x) NTOH(x << 3) +static const afs_uint32 sbox0[256] = { + Z(0xea), Z(0x7f), Z(0xb2), Z(0x64), Z(0x9d), Z(0xb0), Z(0xd9), Z(0x11), Z(0xcd), Z(0x86), Z(0x86), + Z(0x91), Z(0x0a), Z(0xb2), Z(0x93), Z(0x06), Z(0x0e), Z(0x06), Z(0xd2), Z(0x65), Z(0x73), Z(0xc5), + Z(0x28), Z(0x60), Z(0xf2), Z(0x20), Z(0xb5), Z(0x38), Z(0x7e), Z(0xda), Z(0x9f), Z(0xe3), Z(0xd2), + Z(0xcf), Z(0xc4), Z(0x3c), Z(0x61), Z(0xff), Z(0x4a), Z(0x4a), Z(0x35), Z(0xac), Z(0xaa), Z(0x5f), + Z(0x2b), Z(0xbb), Z(0xbc), Z(0x53), Z(0x4e), Z(0x9d), Z(0x78), Z(0xa3), Z(0xdc), Z(0x09), Z(0x32), + Z(0x10), Z(0xc6), Z(0x6f), Z(0x66), Z(0xd6), Z(0xab), Z(0xa9), Z(0xaf), Z(0xfd), Z(0x3b), Z(0x95), + Z(0xe8), Z(0x34), Z(0x9a), Z(0x81), Z(0x72), Z(0x80), Z(0x9c), Z(0xf3), Z(0xec), Z(0xda), Z(0x9f), + Z(0x26), Z(0x76), Z(0x15), Z(0x3e), Z(0x55), Z(0x4d), Z(0xde), Z(0x84), Z(0xee), Z(0xad), Z(0xc7), + Z(0xf1), Z(0x6b), Z(0x3d), Z(0xd3), Z(0x04), Z(0x49), Z(0xaa), Z(0x24), Z(0x0b), Z(0x8a), Z(0x83), + Z(0xba), Z(0xfa), Z(0x85), Z(0xa0), Z(0xa8), Z(0xb1), Z(0xd4), Z(0x01), Z(0xd8), Z(0x70), Z(0x64), + Z(0xf0), Z(0x51), Z(0xd2), Z(0xc3), Z(0xa7), Z(0x75), Z(0x8c), Z(0xa5), Z(0x64), Z(0xef), Z(0x10), + Z(0x4e), Z(0xb7), Z(0xc6), Z(0x61), Z(0x03), Z(0xeb), Z(0x44), Z(0x3d), Z(0xe5), Z(0xb3), Z(0x5b), + Z(0xae), Z(0xd5), Z(0xad), Z(0x1d), Z(0xfa), Z(0x5a), Z(0x1e), Z(0x33), Z(0xab), Z(0x93), Z(0xa2), + Z(0xb7), Z(0xe7), Z(0xa8), Z(0x45), Z(0xa4), Z(0xcd), Z(0x29), Z(0x63), Z(0x44), Z(0xb6), Z(0x69), + Z(0x7e), Z(0x2e), Z(0x62), Z(0x03), Z(0xc8), Z(0xe0), Z(0x17), Z(0xbb), Z(0xc7), Z(0xf3), Z(0x3f), + Z(0x36), Z(0xba), Z(0x71), Z(0x8e), Z(0x97), Z(0x65), Z(0x60), Z(0x69), Z(0xb6), Z(0xf6), Z(0xe6), + Z(0x6e), Z(0xe0), Z(0x81), Z(0x59), Z(0xe8), Z(0xaf), Z(0xdd), Z(0x95), Z(0x22), Z(0x99), Z(0xfd), + Z(0x63), Z(0x19), Z(0x74), Z(0x61), Z(0xb1), Z(0xb6), Z(0x5b), Z(0xae), Z(0x54), Z(0xb3), Z(0x70), + Z(0xff), Z(0xc6), Z(0x3b), Z(0x3e), Z(0xc1), Z(0xd7), Z(0xe1), Z(0x0e), Z(0x76), Z(0xe5), Z(0x36), + Z(0x4f), Z(0x59), Z(0xc7), Z(0x08), Z(0x6e), Z(0x82), Z(0xa6), Z(0x93), Z(0xc4), Z(0xaa), Z(0x26), + Z(0x49), Z(0xe0), Z(0x21), Z(0x64), Z(0x07), Z(0x9f), Z(0x64), Z(0x81), Z(0x9c), Z(0xbf), Z(0xf9), + Z(0xd1), Z(0x43), Z(0xf8), Z(0xb6), Z(0xb9), Z(0xf1), Z(0x24), Z(0x75), Z(0x03), Z(0xe4), Z(0xb0), + Z(0x99), Z(0x46), Z(0x3d), Z(0xf5), Z(0xd1), Z(0x39), Z(0x72), Z(0x12), Z(0xf6), Z(0xba), Z(0x0c), + Z(0x0d), Z(0x42), Z(0x2e)}; + +#undef Z +#define Z(x) NTOH((x << 27) | (x >> 5)) +static const afs_uint32 sbox1[256] = { + Z(0x77), Z(0x14), Z(0xa6), Z(0xfe), Z(0xb2), Z(0x5e), Z(0x8c), Z(0x3e), Z(0x67), Z(0x6c), Z(0xa1), + Z(0x0d), Z(0xc2), Z(0xa2), Z(0xc1), Z(0x85), Z(0x6c), Z(0x7b), Z(0x67), Z(0xc6), Z(0x23), Z(0xe3), + Z(0xf2), Z(0x89), Z(0x50), Z(0x9c), Z(0x03), Z(0xb7), Z(0x73), Z(0xe6), Z(0xe1), Z(0x39), Z(0x31), + Z(0x2c), Z(0x27), Z(0x9f), Z(0xa5), Z(0x69), Z(0x44), Z(0xd6), Z(0x23), Z(0x83), Z(0x98), Z(0x7d), + Z(0x3c), Z(0xb4), Z(0x2d), Z(0x99), Z(0x1c), Z(0x1f), Z(0x8c), Z(0x20), Z(0x03), Z(0x7c), Z(0x5f), + Z(0xad), Z(0xf4), Z(0xfa), Z(0x95), Z(0xca), Z(0x76), Z(0x44), Z(0xcd), Z(0xb6), Z(0xb8), Z(0xa1), + Z(0xa1), Z(0xbe), Z(0x9e), Z(0x54), Z(0x8f), Z(0x0b), Z(0x16), Z(0x74), Z(0x31), Z(0x8a), Z(0x23), + Z(0x17), Z(0x04), Z(0xfa), Z(0x79), Z(0x84), Z(0xb1), Z(0xf5), Z(0x13), Z(0xab), Z(0xb5), Z(0x2e), + Z(0xaa), Z(0x0c), Z(0x60), Z(0x6b), Z(0x5b), Z(0xc4), Z(0x4b), Z(0xbc), Z(0xe2), Z(0xaf), Z(0x45), + Z(0x73), Z(0xfa), Z(0xc9), Z(0x49), Z(0xcd), Z(0x00), Z(0x92), Z(0x7d), Z(0x97), Z(0x7a), Z(0x18), + Z(0x60), Z(0x3d), Z(0xcf), Z(0x5b), Z(0xde), Z(0xc6), Z(0xe2), Z(0xe6), Z(0xbb), Z(0x8b), Z(0x06), + Z(0xda), Z(0x08), Z(0x15), Z(0x1b), Z(0x88), Z(0x6a), Z(0x17), Z(0x89), Z(0xd0), Z(0xa9), Z(0xc1), + Z(0xc9), Z(0x70), Z(0x6b), Z(0xe5), Z(0x43), Z(0xf4), Z(0x68), Z(0xc8), Z(0xd3), Z(0x84), Z(0x28), + Z(0x0a), Z(0x52), Z(0x66), Z(0xa3), Z(0xca), Z(0xf2), Z(0xe3), Z(0x7f), Z(0x7a), Z(0x31), Z(0xf7), + Z(0x88), Z(0x94), Z(0x5e), Z(0x9c), Z(0x63), Z(0xd5), Z(0x24), Z(0x66), Z(0xfc), Z(0xb3), Z(0x57), + Z(0x25), Z(0xbe), Z(0x89), Z(0x44), Z(0xc4), Z(0xe0), Z(0x8f), Z(0x23), Z(0x3c), Z(0x12), Z(0x52), + Z(0xf5), Z(0x1e), Z(0xf4), Z(0xcb), Z(0x18), Z(0x33), Z(0x1f), Z(0xf8), Z(0x69), Z(0x10), Z(0x9d), + Z(0xd3), Z(0xf7), Z(0x28), Z(0xf8), Z(0x30), Z(0x05), Z(0x5e), Z(0x32), Z(0xc0), Z(0xd5), Z(0x19), + Z(0xbd), Z(0x45), Z(0x8b), Z(0x5b), Z(0xfd), Z(0xbc), Z(0xe2), Z(0x5c), Z(0xa9), Z(0x96), Z(0xef), + Z(0x70), Z(0xcf), Z(0xc2), Z(0x2a), Z(0xb3), Z(0x61), Z(0xad), Z(0x80), Z(0x48), Z(0x81), Z(0xb7), + Z(0x1d), Z(0x43), Z(0xd9), Z(0xd7), Z(0x45), Z(0xf0), Z(0xd8), Z(0x8a), Z(0x59), Z(0x7c), Z(0x57), + Z(0xc1), Z(0x79), Z(0xc7), Z(0x34), Z(0xd6), Z(0x43), Z(0xdf), Z(0xe4), Z(0x78), Z(0x16), Z(0x06), + Z(0xda), Z(0x92), Z(0x76), Z(0x51), Z(0xe1), Z(0xd4), Z(0x70), Z(0x03), Z(0xe0), Z(0x2f), Z(0x96), + Z(0x91), Z(0x82), Z(0x80)}; + +#undef Z +#define Z(x) NTOH(x << 11) +static const afs_uint32 sbox2[256] = { + Z(0xf0), Z(0x37), Z(0x24), Z(0x53), Z(0x2a), Z(0x03), Z(0x83), Z(0x86), Z(0xd1), Z(0xec), Z(0x50), + Z(0xf0), Z(0x42), Z(0x78), Z(0x2f), Z(0x6d), Z(0xbf), Z(0x80), Z(0x87), Z(0x27), Z(0x95), Z(0xe2), + Z(0xc5), Z(0x5d), Z(0xf9), Z(0x6f), Z(0xdb), Z(0xb4), Z(0x65), Z(0x6e), Z(0xe7), Z(0x24), Z(0xc8), + Z(0x1a), Z(0xbb), Z(0x49), Z(0xb5), Z(0x0a), Z(0x7d), Z(0xb9), Z(0xe8), Z(0xdc), Z(0xb7), Z(0xd9), + Z(0x45), Z(0x20), Z(0x1b), Z(0xce), Z(0x59), Z(0x9d), Z(0x6b), Z(0xbd), Z(0x0e), Z(0x8f), Z(0xa3), + Z(0xa9), Z(0xbc), Z(0x74), Z(0xa6), Z(0xf6), Z(0x7f), Z(0x5f), Z(0xb1), Z(0x68), Z(0x84), Z(0xbc), + Z(0xa9), Z(0xfd), Z(0x55), Z(0x50), Z(0xe9), Z(0xb6), Z(0x13), Z(0x5e), Z(0x07), Z(0xb8), Z(0x95), + Z(0x02), Z(0xc0), Z(0xd0), Z(0x6a), Z(0x1a), Z(0x85), Z(0xbd), Z(0xb6), Z(0xfd), Z(0xfe), Z(0x17), + Z(0x3f), Z(0x09), Z(0xa3), Z(0x8d), Z(0xfb), Z(0xed), Z(0xda), Z(0x1d), Z(0x6d), Z(0x1c), Z(0x6c), + Z(0x01), Z(0x5a), Z(0xe5), Z(0x71), Z(0x3e), Z(0x8b), Z(0x6b), Z(0xbe), Z(0x29), Z(0xeb), Z(0x12), + Z(0x19), Z(0x34), Z(0xcd), Z(0xb3), Z(0xbd), Z(0x35), Z(0xea), Z(0x4b), Z(0xd5), Z(0xae), Z(0x2a), + Z(0x79), Z(0x5a), Z(0xa5), Z(0x32), Z(0x12), Z(0x7b), Z(0xdc), Z(0x2c), Z(0xd0), Z(0x22), Z(0x4b), + Z(0xb1), Z(0x85), Z(0x59), Z(0x80), Z(0xc0), Z(0x30), Z(0x9f), Z(0x73), Z(0xd3), Z(0x14), Z(0x48), + Z(0x40), Z(0x07), Z(0x2d), Z(0x8f), Z(0x80), Z(0x0f), Z(0xce), Z(0x0b), Z(0x5e), Z(0xb7), Z(0x5e), + Z(0xac), Z(0x24), Z(0x94), Z(0x4a), Z(0x18), Z(0x15), Z(0x05), Z(0xe8), Z(0x02), Z(0x77), Z(0xa9), + Z(0xc7), Z(0x40), Z(0x45), Z(0x89), Z(0xd1), Z(0xea), Z(0xde), Z(0x0c), Z(0x79), Z(0x2a), Z(0x99), + Z(0x6c), Z(0x3e), Z(0x95), Z(0xdd), Z(0x8c), Z(0x7d), Z(0xad), Z(0x6f), Z(0xdc), Z(0xff), Z(0xfd), + Z(0x62), Z(0x47), Z(0xb3), Z(0x21), Z(0x8a), Z(0xec), Z(0x8e), Z(0x19), Z(0x18), Z(0xb4), Z(0x6e), + Z(0x3d), Z(0xfd), Z(0x74), Z(0x54), Z(0x1e), Z(0x04), Z(0x85), Z(0xd8), Z(0xbc), Z(0x1f), Z(0x56), + Z(0xe7), Z(0x3a), Z(0x56), Z(0x67), Z(0xd6), Z(0xc8), Z(0xa5), Z(0xf3), Z(0x8e), Z(0xde), Z(0xae), + Z(0x37), Z(0x49), Z(0xb7), Z(0xfa), Z(0xc8), Z(0xf4), Z(0x1f), Z(0xe0), Z(0x2a), Z(0x9b), Z(0x15), + Z(0xd1), Z(0x34), Z(0x0e), Z(0xb5), Z(0xe0), Z(0x44), Z(0x78), Z(0x84), Z(0x59), Z(0x56), Z(0x68), + Z(0x77), Z(0xa5), Z(0x14), Z(0x06), Z(0xf5), Z(0x2f), Z(0x8c), Z(0x8a), Z(0x73), Z(0x80), Z(0x76), + Z(0xb4), Z(0x10), Z(0x86)}; + +#undef Z +#define Z(x) NTOH(x << 19) +static const afs_uint32 sbox3[256] = { + Z(0xa9), Z(0x2a), Z(0x48), Z(0x51), Z(0x84), Z(0x7e), Z(0x49), Z(0xe2), Z(0xb5), Z(0xb7), Z(0x42), + Z(0x33), Z(0x7d), Z(0x5d), Z(0xa6), Z(0x12), Z(0x44), Z(0x48), Z(0x6d), Z(0x28), Z(0xaa), Z(0x20), + Z(0x6d), Z(0x57), Z(0xd6), Z(0x6b), Z(0x5d), Z(0x72), Z(0xf0), Z(0x92), Z(0x5a), Z(0x1b), Z(0x53), + Z(0x80), Z(0x24), Z(0x70), Z(0x9a), Z(0xcc), Z(0xa7), Z(0x66), Z(0xa1), Z(0x01), Z(0xa5), Z(0x41), + Z(0x97), Z(0x41), Z(0x31), Z(0x82), Z(0xf1), Z(0x14), Z(0xcf), Z(0x53), Z(0x0d), Z(0xa0), Z(0x10), + Z(0xcc), Z(0x2a), Z(0x7d), Z(0xd2), Z(0xbf), Z(0x4b), Z(0x1a), Z(0xdb), Z(0x16), Z(0x47), Z(0xf6), + Z(0x51), Z(0x36), Z(0xed), Z(0xf3), Z(0xb9), Z(0x1a), Z(0xa7), Z(0xdf), Z(0x29), Z(0x43), Z(0x01), + Z(0x54), Z(0x70), Z(0xa4), Z(0xbf), Z(0xd4), Z(0x0b), Z(0x53), Z(0x44), Z(0x60), Z(0x9e), Z(0x23), + Z(0xa1), Z(0x18), Z(0x68), Z(0x4f), Z(0xf0), Z(0x2f), Z(0x82), Z(0xc2), Z(0x2a), Z(0x41), Z(0xb2), + Z(0x42), Z(0x0c), Z(0xed), Z(0x0c), Z(0x1d), Z(0x13), Z(0x3a), Z(0x3c), Z(0x6e), Z(0x35), Z(0xdc), + Z(0x60), Z(0x65), Z(0x85), Z(0xe9), Z(0x64), Z(0x02), Z(0x9a), Z(0x3f), Z(0x9f), Z(0x87), Z(0x96), + Z(0xdf), Z(0xbe), Z(0xf2), Z(0xcb), Z(0xe5), Z(0x6c), Z(0xd4), Z(0x5a), Z(0x83), Z(0xbf), Z(0x92), + Z(0x1b), Z(0x94), Z(0x00), Z(0x42), Z(0xcf), Z(0x4b), Z(0x00), Z(0x75), Z(0xba), Z(0x8f), Z(0x76), + Z(0x5f), Z(0x5d), Z(0x3a), Z(0x4d), Z(0x09), Z(0x12), Z(0x08), Z(0x38), Z(0x95), Z(0x17), Z(0xe4), + Z(0x01), Z(0x1d), Z(0x4c), Z(0xa9), Z(0xcc), Z(0x85), Z(0x82), Z(0x4c), Z(0x9d), Z(0x2f), Z(0x3b), + Z(0x66), Z(0xa1), Z(0x34), Z(0x10), Z(0xcd), Z(0x59), Z(0x89), Z(0xa5), Z(0x31), Z(0xcf), Z(0x05), + Z(0xc8), Z(0x84), Z(0xfa), Z(0xc7), Z(0xba), Z(0x4e), Z(0x8b), Z(0x1a), Z(0x19), Z(0xf1), Z(0xa1), + Z(0x3b), Z(0x18), Z(0x12), Z(0x17), Z(0xb0), Z(0x98), Z(0x8d), Z(0x0b), Z(0x23), Z(0xc3), Z(0x3a), + Z(0x2d), Z(0x20), Z(0xdf), Z(0x13), Z(0xa0), Z(0xa8), Z(0x4c), Z(0x0d), Z(0x6c), Z(0x2f), Z(0x47), + Z(0x13), Z(0x13), Z(0x52), Z(0x1f), Z(0x2d), Z(0xf5), Z(0x79), Z(0x3d), Z(0xa2), Z(0x54), Z(0xbd), + Z(0x69), Z(0xc8), Z(0x6b), Z(0xf3), Z(0x05), Z(0x28), Z(0xf1), Z(0x16), Z(0x46), Z(0x40), Z(0xb0), + Z(0x11), Z(0xd3), Z(0xb7), Z(0x95), Z(0x49), Z(0xcf), Z(0xc3), Z(0x1d), Z(0x8f), Z(0xd8), Z(0xe1), + Z(0x73), Z(0xdb), Z(0xad), Z(0xc8), Z(0xc9), Z(0xa9), Z(0xa1), Z(0xc2), Z(0xc5), Z(0xe3), Z(0xba), + Z(0xfc), Z(0x0e), Z(0x25)}; + +/* + * This is a 16 round Feistel network with permutation F_ENCRYPT + */ + +#define F_ENCRYPT(R, L, sched) { \ + union lc4 { afs_uint32 l; unsigned char c[4]; } u; \ + u.l = sched ^ R; \ + L ^= sbox0[u.c[0]] ^ sbox1[u.c[1]] ^ sbox2[u.c[2]] ^ sbox3[u.c[3]]; } + +#ifndef WORDS_BIGENDIAN +/* BEWARE: this code is endian dependent. + * This should really be inline assembler on the x86. + */ +#undef F_ENCRYPT +#define FF(y, shiftN) (((y) >> shiftN) & 0xFF) +#define F_ENCRYPT(R, L, sched) { \ + afs_uint32 u; \ + u = sched ^ R; \ + L ^= sbox0[FF(u, 0)] ^ sbox1[FF(u, 8)] ^ sbox2[FF(u, 16)] ^ sbox3[FF(u, 24)];} +#endif + +static inline +void +fc_ecb_enc(afs_uint32 l, + afs_uint32 r, + afs_uint32 out[2], + const afs_int32 sched[ROUNDS]) +{ +#if !defined(UNROLL_LOOPS) + { + int i; + for (i = 0; i < (ROUNDS/4); i++) + { + F_ENCRYPT(r, l, *sched++); + F_ENCRYPT(l, r, *sched++); + F_ENCRYPT(r, l, *sched++); + F_ENCRYPT(l, r, *sched++); + } + } +#else + F_ENCRYPT(r, l, *sched++); + F_ENCRYPT(l, r, *sched++); + F_ENCRYPT(r, l, *sched++); + F_ENCRYPT(l, r, *sched++); + F_ENCRYPT(r, l, *sched++); + F_ENCRYPT(l, r, *sched++); + F_ENCRYPT(r, l, *sched++); + F_ENCRYPT(l, r, *sched++); + F_ENCRYPT(r, l, *sched++); + F_ENCRYPT(l, r, *sched++); + F_ENCRYPT(r, l, *sched++); + F_ENCRYPT(l, r, *sched++); + F_ENCRYPT(r, l, *sched++); + F_ENCRYPT(l, r, *sched++); + F_ENCRYPT(r, l, *sched++); + F_ENCRYPT(l, r, *sched++); +#endif /* UNROLL_LOOPS */ + + out[0] = l; + out[1] = r; +} + +static inline +void +fc_ecb_dec(afs_uint32 l, + afs_uint32 r, + afs_uint32 out[2], + const afs_int32 sched[ROUNDS]) +{ + sched = &sched[ROUNDS-1]; + +#if !defined(UNROLL_LOOPS) + { + int i; + for (i = 0; i < (ROUNDS/4); i++) + { + F_ENCRYPT(l, r, *sched--); + F_ENCRYPT(r, l, *sched--); + F_ENCRYPT(l, r, *sched--); + F_ENCRYPT(r, l, *sched--); + } + } +#else + F_ENCRYPT(l, r, *sched--); + F_ENCRYPT(r, l, *sched--); + F_ENCRYPT(l, r, *sched--); + F_ENCRYPT(r, l, *sched--); + F_ENCRYPT(l, r, *sched--); + F_ENCRYPT(r, l, *sched--); + F_ENCRYPT(l, r, *sched--); + F_ENCRYPT(r, l, *sched--); + F_ENCRYPT(l, r, *sched--); + F_ENCRYPT(r, l, *sched--); + F_ENCRYPT(l, r, *sched--); + F_ENCRYPT(r, l, *sched--); + F_ENCRYPT(l, r, *sched--); + F_ENCRYPT(r, l, *sched--); + F_ENCRYPT(l, r, *sched--); + F_ENCRYPT(r, l, *sched--); +#endif /* UNROLL_LOOPS */ + + out[0] = l; + out[1] = r; +} + +static inline +void +fc_cbc_enc(const afs_uint32 *in, + afs_uint32 *out, + afs_int32 length, + const afs_int32 sched[ROUNDS], + afs_uint32 iv[2]) +{ + afs_int32 xor0 = iv[0], xor1 = iv[1]; + + for (; length > 0; length -= 8) + { + afs_uint32 b8[2]; + /* If length < 8 we read to much, usally ok */ + xor0 ^= in[0]; + xor1 ^= in[1]; + fc_ecb_enc(xor0, xor1, b8, sched); + xor0 = in[0] ^ b8[0]; + xor1 = in[1] ^ b8[1]; + + /* Out is always a multiple of 8 */ + memcpy(out, b8, 8); + out += 2; + in += 2; + } + iv[0] = xor0; + iv[1] = xor1; +} + +static inline +void +fc_cbc_dec(const afs_uint32 *in, + afs_uint32 *out, + afs_int32 length, + const afs_int32 sched[ROUNDS], + afs_uint32 iv[2]) +{ + afs_int32 xor0 = iv[0], xor1 = iv[1]; + + for (; length > 0; length -= 8) + { + afs_uint32 b8[2]; + /* In is always a multiple of 8 */ + fc_ecb_dec(in[0], in[1], b8, sched); + b8[0] ^= xor0; + b8[1] ^= xor1; + xor0 = in[0] ^ b8[0]; + xor1 = in[1] ^ b8[1]; + +#if 0 + if (length >= 8) + memcpy(out, b8, 8); + else + memcpy(out, b8, length); /* Don't write to much when length < 8 */ +#else + /* If length < 8 we write to much, this is not always ok */ + memcpy(out, b8, 8); +#endif + out += 2; + in += 2; + } + iv[0] = xor0; + iv[1] = xor1; +} + +int +fc_ecb_encrypt(const void *in_, + void *out_, + const afs_int32 sched[ROUNDS], + int encrypt) +{ + const afs_uint32 *in = in_; /* In must be afs_uint32 aligned */ + afs_uint32 *out = out_; /* Out must be afs_uint32 aligned */ + if (encrypt) + fc_ecb_enc(in[0], in[1], out, sched); + else + fc_ecb_dec(in[0], in[1], out, sched); + return 0; +} + +int +fc_cbc_encrypt(const void *in_, + void *out_, + afs_int32 length, + const afs_int32 sched[ROUNDS], + afs_uint32 iv[2], + int encrypt) +{ + const afs_uint32 *in = in_; /* In must be afs_uint32 aligned */ + afs_uint32 *out = out_; /* Out must be afs_uint32 aligned */ + if (encrypt) + fc_cbc_enc(in, out, length, sched, iv); + else + fc_cbc_dec(in, out, length, sched, iv); + return 0; +} + +/* Rotate two 32 bit numbers as a 56 bit number */ +#define ROT56R(hi, lo, n) { \ + afs_uint32 t = lo & ((1<> n) | ((hi & ((1<> n) | (t << (24-n)); } + +/* Rotate one 64 bit number as a 56 bit number */ +#define ROT56R64(k, n) { \ + k = (k >> n) | ((k & ((1<> 55) != 0) && ((1ul << 55) != 0) + unsigned long k; /* k holds all 56 non parity bits */ + + /* Compress out parity bits */ + k = (*key++) >> 1; + k <<= 7; + k |= (*key++) >> 1; + k <<= 7; + k |= (*key++) >> 1; + k <<= 7; + k |= (*key++) >> 1; + k <<= 7; + k |= (*key++) >> 1; + k <<= 7; + k |= (*key++) >> 1; + k <<= 7; + k |= (*key++) >> 1; + k <<= 7; + k |= (*key) >> 1; + + /* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */ + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + *sched++ = EFF_NTOHL((afs_uint32)k); + ROT56R64(k, 11); + *sched++ = EFF_NTOHL((afs_uint32)k); + return 0; +#else + afs_uint32 hi, lo; /* hi is upper 24 bits and lo lower 32, total 56 */ + + /* Compress out parity bits */ + lo = (*key++) >> 1; + lo <<= 7; + lo |= (*key++) >> 1; + lo <<= 7; + lo |= (*key++) >> 1; + lo <<= 7; + lo |= (*key++) >> 1; + hi = lo >> 4; + lo &= 0xf; + lo <<= 7; + lo |= (*key++) >> 1; + lo <<= 7; + lo |= (*key++) >> 1; + lo <<= 7; + lo |= (*key++) >> 1; + lo <<= 7; + lo |= (*key) >> 1; + + /* Use lower 32 bits for schedule, rotate by 11 each round (16 times) */ + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + *sched++ = EFF_NTOHL(lo); + ROT56R(hi, lo, 11); + *sched++ = EFF_NTOHL(lo); + return 0; +#endif +} + +/* + * Encryption/decryption of Rx packets is pretty straight forward. Run + * fc_cbc_encrypt over the packet fragments until len bytes have been + * processed. Skip the Rx packet header but not the security header. + */ +int +rxkad_EncryptPacket(const void *rx_connection_not_used, + const afs_int32 sched[ROUNDS], + const afs_uint32 iv[2], + int len, + struct rx_packet *packet) +{ + afs_uint32 ivec[2]; + struct iovec *frag; + + { + /* What is this good for? + * It turns out that the security header for auth_enc is of + * size 8 bytes and the last 4 bytes are defined to be 0! + */ + afs_uint32 *t = (afs_uint32 *)packet->wirevec[1].iov_base; + t[1] = 0; + } + + memcpy(ivec, iv, sizeof(ivec)); /* Must use copy of iv */ + for (frag = &packet->wirevec[1]; len; frag++) + { + int iov_len = frag->iov_len; + afs_uint32 *iov_bas = (afs_uint32 *) frag->iov_base; + if (iov_len == 0) + return RXKADDATALEN; /* Length mismatch */ + if (len < iov_len) + iov_len = len; /* Don't process to much data */ + fc_cbc_enc(iov_bas, iov_bas, iov_len, sched, ivec); + len -= iov_len; + } + return 0; +} + +int +rxkad_DecryptPacket(const void *rx_connection_not_used, + const afs_int32 sched[ROUNDS], + const afs_uint32 iv[2], + int len, + struct rx_packet *packet) +{ + afs_uint32 ivec[2]; + struct iovec *frag; + + memcpy(ivec, iv, sizeof(ivec)); /* Must use copy of iv */ + for (frag = &packet->wirevec[1]; len > 0; frag++) + { + int iov_len = frag->iov_len; + afs_uint32 *iov_bas = (afs_uint32 *) frag->iov_base; + if (iov_len == 0) + return RXKADDATALEN; /* Length mismatch */ + if (len < iov_len) + iov_len = len; /* Don't process to much data */ + fc_cbc_dec(iov_bas, iov_bas, iov_len, sched, ivec); + len -= iov_len; + } + return 0; +} + +#if defined(TEST) || defined(TEST_KERNEL) +/* + * It is possible to link with the client kernel libafs.a to verify + * the test case. Use TEST_KERNEL to get the mangled names. + */ + +#include +#include + +#include + +const char the_quick[] = "The quick brown fox jumps over the lazy dogs.\0\0"; + +const unsigned char key1[8]={0xf0,0xe1,0xd2,0xc3,0xb4,0xa5,0x96,0x87}; +const char ciph1[] = { + 0x00, 0xf0, 0xe, 0x11, 0x75, 0xe6, 0x23, 0x82, 0xee, 0xac, 0x98, 0x62, + 0x44, 0x51, 0xe4, 0x84, 0xc3, 0x59, 0xd8, 0xaa, 0x64, 0x60, 0xae, 0xf7, + 0xd2, 0xd9, 0x13, 0x79, 0x72, 0xa3, 0x45, 0x03, 0x23, 0xb5, 0x62, 0xd7, + 0xc, 0xf5, 0x27, 0xd1, 0xf8, 0x91, 0x3c, 0xac, 0x44, 0x22, 0x92, 0xef }; + +const unsigned char key2[8]={0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10}; +const char ciph2[] = { + 0xca, 0x90, 0xf5, 0x9d, 0xcb, 0xd4, 0xd2, 0x3c, 0x01, 0x88, 0x7f, 0x3e, + 0x31, 0x6e, 0x62, 0x9d, 0xd8, 0xe0, 0x57, 0xa3, 0x06, 0x3a, 0x42, 0x58, + 0x2a, 0x28, 0xfe, 0x72, 0x52, 0x2f, 0xdd, 0xe0, 0x19, 0x89, 0x09, 0x1c, + 0x2a, 0x8e, 0x8c, 0x94, 0xfc, 0xc7, 0x68, 0xe4, 0x88, 0xaa, 0xde, 0x0f }; + +#ifdef TEST_KERNEL +#define fc_keysched _afs_QTKrFdpoFL +#define fc_ecb_encrypt _afs_sDLThwNLok +#define fc_cbc_encrypt _afs_fkyCWTvfRS +#define rxkad_DecryptPacket _afs_SRWEeqTXrS +#define rxkad_EncryptPacket _afs_bpwQbdoghO +#endif + +int rx_SlowPutInt32() { abort(); } + +int +main() +{ + afs_int32 sched[ROUNDS]; + char ciph[100], clear[100], tmp[100]; + afs_uint32 data[2]; + afs_uint32 iv[2]; + struct rx_packet packet; + + if (sizeof(afs_int32) != 4) + fprintf(stderr, "error: sizeof(afs_int32) != 4\n"); + if (sizeof(afs_uint32) != 4) + fprintf(stderr, "error: sizeof(afs_uint32) != 4\n"); + + /* + * Use key1 and key2 as iv */ + fc_keysched(key1, sched); + memcpy(iv, key2, sizeof(iv)); + fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv, ENCRYPT); + if (memcmp(ciph1, ciph, sizeof(ciph1)) != 0) + fprintf(stderr, "encrypt FAILED\n"); + memcpy(iv, key2, sizeof(iv)); + fc_cbc_encrypt(ciph, clear, sizeof(the_quick), sched, iv, DECRYPT); + if (strcmp(the_quick, clear) != 0) + fprintf(stderr, "crypt decrypt FAILED\n"); + + /* + * Use key2 and key1 as iv + */ + fc_keysched(key2, sched); + memcpy(iv, key1, sizeof(iv)); + fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv, ENCRYPT); + if (memcmp(ciph2, ciph, sizeof(ciph2)) != 0) + fprintf(stderr, "encrypt FAILED\n"); + memcpy(iv, key1, sizeof(iv)); + fc_cbc_encrypt(ciph, clear, sizeof(the_quick), sched, iv, DECRYPT); + if (strcmp(the_quick, clear) != 0) + fprintf(stderr, "crypt decrypt FAILED\n"); + + /* + * Test Encrypt- and Decrypt-Packet, use key1 and key2 as iv + */ + fc_keysched(key1, sched); + memcpy(iv, key2, sizeof(iv)); + strcpy(clear, the_quick); + packet.wirevec[1].iov_base = clear; + packet.wirevec[1].iov_len = sizeof(the_quick); + packet.wirevec[2].iov_len = 0; + + /* For unknown reasons bytes 4-7 are zeroed in rxkad_EncryptPacket */ + rxkad_EncryptPacket(tmp, sched, iv, sizeof(the_quick), &packet); + rxkad_DecryptPacket(tmp, sched, iv, sizeof(the_quick), &packet); + clear[4] ^= 'q'; + clear[5] ^= 'u'; + clear[6] ^= 'i'; + clear[7] ^= 'c'; + if (strcmp(the_quick, clear) != 0) + fprintf(stderr, "rxkad_EncryptPacket/rxkad_DecryptPacket FAILED\n"); + + { + struct timeval start, stop; + int i; + + fc_keysched(key1, sched); + gettimeofday(&start, 0); + for (i = 0; i < 1000000; i++) + fc_keysched(key1, sched); + gettimeofday(&stop, 0); + printf("fc_keysched = %2.2f us\n", + (stop.tv_sec - start.tv_sec + + (stop.tv_usec - start.tv_usec)/1e6)*1); + + fc_ecb_encrypt(data, data, sched, ENCRYPT); + gettimeofday(&start, 0); + for (i = 0; i < 1000000; i++) + fc_ecb_encrypt(data, data, sched, ENCRYPT); + gettimeofday(&stop, 0); + printf("fc_ecb_encrypt = %2.2f us\n", + (stop.tv_sec - start.tv_sec + + (stop.tv_usec - start.tv_usec)/1e6)*1); + + fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv, ENCRYPT); + gettimeofday(&start, 0); + for (i = 0; i < 100000; i++) + fc_cbc_encrypt(the_quick, ciph, sizeof(the_quick), sched, iv, ENCRYPT); + gettimeofday(&stop, 0); + printf("fc_cbc_encrypt = %2.2f us\n", + (stop.tv_sec - start.tv_sec + + (stop.tv_usec - start.tv_usec)/1e6)*10); + + } + + exit(0); +} +#endif /* TEST */ diff --git a/src/rxkad/rxk_info.c b/src/rxkad/rxk_info.c new file mode 100644 index 0000000000..4b7ea1b53d --- /dev/null +++ b/src/rxkad/rxk_info.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +#include "rxkad_locl.h" + +RCSID("$Id$"); + +afs_int32 +rxkad_GetServerInfo(struct rx_connection *con, + rxkad_level *level, + afs_uint32 *expiration, + char *name, + char *instance, + char *cell, + afs_int32 *kvno) +{ + serv_con_data *cdat = (serv_con_data *) con->securityData; + + if (cdat && cdat->authenticated + && (time(0) < cdat->expires) + && cdat->user) + { + if (level) + *level = cdat->cur_level; + if (expiration) + *expiration = cdat->expires; + if (name) + strcpy(name, cdat->user->name); + if (instance) + strcpy(instance, cdat->user->instance); + if (cell) + strcpy(cell, cdat->user->cell); + if (kvno) + *kvno = cdat->kvno; + return 0; + } + else + return RXKADNOAUTH; +} diff --git a/src/rxkad/rxk_locl.c b/src/rxkad/rxk_locl.c new file mode 100644 index 0000000000..6f13b928bf --- /dev/null +++ b/src/rxkad/rxk_locl.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +#include "rxkad_locl.h" + +RCSID("$Id$"); + +/* The header checksum is the last 16 bits of this struct after + * encryption. Note that only the last 8 bytes change per packet. */ +#if 0 +struct header_data { + struct const_header_data c; /* 16 bytes */ + struct variable_header_data v; /* 8 bytes */ +}; +#endif + +struct const_header_data { + /* Data that is constant per connection */ + afs_uint32 epoch; + afs_uint32 cid; + afs_uint32 zero; + afs_uint32 security_index; +}; + +struct variable_header_data { + /* Data that changes per packet */ + afs_uint32 call_number; + afs_uint32 channel_and_seq; +}; + +/* To create a 16 bit packet header checksum we first create an iv + * dependent on the epoch, the connection ID and the security index. + */ +void +rxkad_calc_header_iv(const struct rx_connection *conn, + const afs_int32 *sched, + const struct ktc_encryptionKey *in_iv, + afs_uint32 *out_iv) +{ + struct const_header_data h; + afs_uint32 *t; + + h.epoch = htonl(conn->epoch); + h.cid = htonl(conn->cid & RX_CIDMASK); + h.zero = 0; + h.security_index = htonl(conn->securityIndex); + + t = (afs_uint32 *)in_iv; /* memcpy(out_iv, in_iv, 8); */ + out_iv[0] = t[0]; + out_iv[1] = t[1]; + fc_cbc_encrypt(&h, &h, sizeof(h), sched, out_iv, ENCRYPT); + /* Extract last 8 bytes as iv */ + assert(out_iv[0] == h.zero); + /* out_iv[0] = h.zero; */ + out_iv[1] = h.security_index; +} + +/* Make a 16 bit header checksum dependent on call number, channel + * number and packet sequence number. In addition, the checksum is + * indirectly dependent (via the iv) on epoch, connection ID and + * security index. + */ +static +u_short +rxkad_cksum_header(const struct rx_packet *packet, + const afs_int32 *sched, + const afs_uint32 *iv) +{ + struct variable_header_data h; + afs_uint32 t; + + /* Collect selected packet fields */ + h.call_number = htonl(packet->header.callNumber); + t = ((packet->header.cid & RX_CHANNELMASK) << (32 - RX_CIDSHIFT)) + | ((packet->header.seq & 0x3fffffff)); + h.channel_and_seq = htonl(t); + + /* Encrypt selected fields (this is hand rolled CBC mode) */ + h.call_number ^= iv[0]; + h.channel_and_seq ^= iv[1]; + fc_ecb_encrypt(&h, &h, sched, ENCRYPT); + + /* Select 16 bits that are now dependent on all selected packet fields */ + t = (ntohl(h.channel_and_seq) >> 16) & 0xffff; + if (t != 0) + return t; + else + return 1; /* No checksum is 0 */ +} + +/* Checksum a rxkad_response, this checksum is buried within the + * encrypted part of the response but covers the entire response. */ +afs_uint32 +rxkad_cksum_response(rxkad_response *r) +{ + u_char *t; + afs_uint32 cksum = 1000003; + + for (t = (u_char *)r; t < (u_char*)(r + 1); t++) + cksum = *t + cksum * 0x10204081; + + return htonl(cksum); +} + +int +rxkad_prepare_packet(struct rx_packet *pkt, + struct rx_connection *con, + int level, + key_stuff *k, + end_stuff *e) +{ + u_int len = rx_GetDataSize(pkt); + + /* Checksum header */ + rx_SetPacketCksum(pkt, rxkad_cksum_header(pkt, k->keysched, e->header_iv)); + + e->packetsSent++; + e->bytesSent += len; + + if (level != rxkad_clear) + { + afs_uint32 *data = (afs_uint32 *) rx_DataOf(pkt); + afs_uint32 t; + afs_int32 code = 0; + + assert(pkt->wirevec[1].iov_len >= 4); + + /* First 4 bytes of security header, includes encrypted length */ + t = pkt->header.seq ^ pkt->header.callNumber; + t <<= 16; + t |= len; /* Extracted on receiving side */ + data[0] = htonl(t); + + switch (level) { + case rxkad_auth: + len += rx_GetSecurityHeaderSize(con); /* Extended pkt len */ + /* Extend packet length so that we can encrypt the first 8 bytes */ + if (pkt->wirevec[1].iov_len < 8) + { + int diff = 8 - pkt->wirevec[1].iov_len; + pkt->wirevec[1].iov_len += diff; + len += diff; + } + rx_SetDataSize(pkt, len); /* Set extended packet length */ + + /* Encrypt security header (4 bytes) and the next 4 bytes */ + assert(pkt->wirevec[1].iov_len >= 8); + fc_ecb_encrypt(data, data, k->keysched, ENCRYPT); + break; + + case rxkad_crypt: + len += rx_GetSecurityHeaderSize(con); /* Extended pkt len */ + /* Round up to 8 byte boundary for encryption to work */ + if (len % 8) + { + int diff = 8 - (len % 8); + rxi_RoundUpPacket(pkt, diff); + len += diff; + } + rx_SetDataSize(pkt, len); /* Set extended packet length */ + + assert((len % 8) == 0); + code = rxkad_EncryptPacket(con, k->keysched, + (afs_uint32*)&k->key, len, pkt); + break; + + default: + assert(0); + } + + return code; + } + return 0; +} + +int +rxkad_check_packet(struct rx_packet *pkt, + struct rx_connection *con, + int level, + key_stuff *k, + end_stuff *e) +{ + u_int xlen = rx_GetDataSize(pkt); /* Extended packet length */ + + if (rx_GetPacketCksum(pkt) + != rxkad_cksum_header(pkt, k->keysched, e->header_iv)) + return RXKADSEALEDINCON; + + e->packetsReceived++; + + if (level == rxkad_clear) + { + e->bytesReceived += xlen; /* Same as real length */ + } + else + { + u_int len; /* Real packet length */ + afs_uint32 *data = (afs_uint32 *) rx_DataOf(pkt); + afs_uint32 t; + afs_int32 code; + + switch (level) { + case rxkad_auth: + assert(rx_Contiguous(pkt) >= 8); + fc_ecb_encrypt(data, data, k->keysched, DECRYPT); + break; + + case rxkad_crypt: + code = rxkad_DecryptPacket(con, k->keysched,(afs_uint32*)&k->key, + xlen, pkt); + if (code) + return code; + break; + + default: + assert(0); + } + + assert(rx_Contiguous(pkt) >= 4); + + t = ntohl(data[0]); + len = t & 0xffff; /* Extract real length */ + t >>= 16; + if (t != ((pkt->header.seq ^ pkt->header.callNumber) & 0xffff)) + return RXKADSEALEDINCON; + +#define TBYTES 15 + /* The packet is extended with 0 - 7 bytes to a chipher block + * boundary. This is however not true with the Transarc + * implementation, for unknown reasons it sometimes extendeds + * the packet with anything up to TBYTES. */ + if (len > xlen) + return RXKADSEALEDINCON; + if (xlen > len + TBYTES) + return RXKADSEALEDINCON; + + e->bytesReceived += len; + rx_SetDataSize(pkt, len); /* Set real packet length */ + return 0; + } + return 0; +} diff --git a/src/rxkad/rxk_serv.c b/src/rxkad/rxk_serv.c new file mode 100644 index 0000000000..b4778897f1 --- /dev/null +++ b/src/rxkad/rxk_serv.c @@ -0,0 +1,452 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +#include "rxkad_locl.h" + +#if defined(KRB5) +#include +#endif + +RCSID("$Id$"); + +/* Security object specific server data */ +typedef struct rxkad_serv_class { + struct rx_securityClass klass; + rxkad_level min_level; + void *appl_data; + int (*get_key)(void *appl_data, int kvno, struct ktc_encryptionKey *key); + int (*user_ok)(char *name, char *inst, char *realm, int kvno); +} rxkad_serv_class; + +static +int +server_NewConnection(struct rx_securityClass *obj, struct rx_connection *con) +{ + assert(con->securityData == 0); + obj->refCount++; + con->securityData = (char *) rxi_Alloc(sizeof(serv_con_data)); + memset(con->securityData, 0x0, sizeof(serv_con_data)); + return 0; +} + +static +int +server_Close(struct rx_securityClass *obj) +{ + obj->refCount--; + if (obj->refCount <= 0) + rxi_Free(obj, sizeof(rxkad_serv_class)); + return 0; +} + +static +int +server_DestroyConnection(struct rx_securityClass *obj, + struct rx_connection *con) +{ + serv_con_data *cdat = (serv_con_data *)con->securityData; + + if (cdat) + { + if (cdat->user) + rxi_Free(cdat->user, sizeof(struct ktc_principal)); + rxi_Free(cdat, sizeof(serv_con_data)); + } + return server_Close(obj); +} + +/* + * Check whether a connection authenticated properly. + * Zero is good (authentication succeeded). + */ +static +int +server_CheckAuthentication(struct rx_securityClass *obj, + struct rx_connection *con) +{ + serv_con_data *cdat = (serv_con_data *) con->securityData; + + if (cdat) + return !cdat->authenticated; + else + return RXKADNOAUTH; +} + +/* + * Select a nonce for later use. + */ +static +int +server_CreateChallenge(struct rx_securityClass *obj_, + struct rx_connection *con) +{ + rxkad_serv_class *obj = (rxkad_serv_class *) obj_; + serv_con_data *cdat = (serv_con_data *) con->securityData; + union { + afs_uint32 rnd[2]; + struct ktc_encryptionKey k; + } u; + + /* Any good random numbers will do, no real need to use + * cryptographic techniques here */ + /* XXX openafs !!! */ + des_random_key(&u.k); + cdat->nonce = u.rnd[0] ^ u.rnd[1]; + cdat->authenticated = 0; + cdat->cur_level = obj->min_level; + return 0; +} + +/* + * Wrap the nonce in a challenge packet. + */ +static +int +server_GetChallenge(const struct rx_securityClass *obj, + const struct rx_connection *con, + struct rx_packet *pkt) +{ + serv_con_data *cdat = (serv_con_data *) con->securityData; + rxkad_challenge c; + + /* Make challenge */ + c.version = htonl(RXKAD_VERSION); + c.nonce = htonl(cdat->nonce); + c.min_level = htonl((afs_int32)cdat->cur_level); + c.unused = 0; /* Use this to hint client we understand krb5 tickets??? */ + + /* Stuff into packet */ + if (rx_SlowWritePacket(pkt, 0, sizeof(c), &c) != sizeof(c)) + return RXKADPACKETSHORT; + rx_SetDataSize(pkt, sizeof(c)); + return 0; +} + +int +rxkad_decode_krb5_ticket(int (*get_key)(void *appl_data, + int kvno, + struct ktc_encryptionKey *key), + void *appl_data, + int serv_kvno, + char *ticket, + afs_int32 ticket_len, + /* OUT parms */ + struct ktc_encryptionKey *session_key, + afs_uint32 *expires, + struct ktc_principal *p, + afs_int32 *real_kvno); + + +static +int +decode_krb5_ticket(rxkad_serv_class *obj, + int serv_kvno, + char *ticket, + afs_int32 ticket_len, + /* OUT parms */ + struct ktc_encryptionKey *session_key, + afs_uint32 *expires, + struct ktc_principal *p, + afs_int32 *real_kvno) +{ + return rxkad_decode_krb5_ticket(obj->get_key, + obj->appl_data, + serv_kvno, + ticket, + ticket_len, + session_key, + expires, + p, + real_kvno); +} + +static +int +decode_krb4_ticket(rxkad_serv_class *obj, + int serv_kvno, + char *ticket, + afs_int32 ticket_len, + /* OUT parms */ + struct ktc_encryptionKey *session_key, + afs_uint32 *expires, + struct ktc_principal *p) +{ + afs_uint32 start; + afs_uint32 paddress; + struct ktc_encryptionKey serv_key; /* Service's secret key */ + des_key_schedule serv_sched; /* Service's schedule */ + + /* First get service key */ + int code = (*obj->get_key)(obj->appl_data, serv_kvno, &serv_key); + if (code) + return RXKADUNKNOWNKEY; + + code = decomp_ticket(ticket, ticket_len, + p->name, p->instance, p->cell, &paddress, + (char *)session_key, &start, expires, + &serv_key, serv_sched); + if (code != 0) + return RXKADBADTICKET; + +#if 0 + if (paddress != ntohl(con->peer->host)) + return RXKADBADTICKET; +#endif + + if (tkt_CheckTimes (start, *expires, time(0)) < -1) + return RXKADBADTICKET; + + return 0; /* Success */ +} + +/* + * Process a response to a challange. + */ +static +int +server_CheckResponse(struct rx_securityClass *obj_, + struct rx_connection *con, + struct rx_packet *pkt) +{ + rxkad_serv_class *obj = (rxkad_serv_class *) obj_; + serv_con_data *cdat = (serv_con_data *) con->securityData; + + int serv_kvno; /* Service's kvno we used */ + afs_int32 ticket_len; + char ticket[MAXKTCTICKETLEN]; + int code; + rxkad_response r; + struct ktc_principal p; + afs_uint32 cksum; + + if (rx_SlowReadPacket(pkt, 0, sizeof(r), &r) != sizeof(r)) + return RXKADPACKETSHORT; + + serv_kvno = ntohl(r.kvno); + ticket_len = ntohl(r.ticket_len); + + if (ticket_len > MAXKTCTICKETLEN) + return RXKADTICKETLEN; + + if (rx_SlowReadPacket(pkt, sizeof(r), ticket_len, ticket) != ticket_len) + return RXKADPACKETSHORT; + + /* Disassemble kerberos ticket */ + if (serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5 || + serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY) { + code = decode_krb5_ticket(obj, serv_kvno, ticket, ticket_len, + &cdat->k.key, &cdat->expires, &p, &cdat->kvno); + } else { + code = decode_krb4_ticket(obj, serv_kvno, ticket, ticket_len, + &cdat->k.key, &cdat->expires, &p); + cdat->kvno = serv_kvno; + } + + if (code != 0) + return code; + + fc_keysched(&cdat->k.key, cdat->k.keysched); + + /* Unseal r.encrypted */ + fc_cbc_enc2(&r.encrypted, &r.encrypted, sizeof(r.encrypted), + cdat->k.keysched, (afs_uint32*)&cdat->k.key, DECRYPT); + + /* Verify response integrity */ + cksum = r.encrypted.cksum; + r.encrypted.cksum = 0; + if (r.encrypted.epoch != ntohl(con->epoch) + || r.encrypted.cid != ntohl(con->cid & RX_CIDMASK) + || r.encrypted.security_index != ntohl(con->securityIndex) + || cksum != rxkad_cksum_response(&r)) + return RXKADSEALEDINCON; + { + int i; + for (i = 0; i < RX_MAXCALLS; i++) + { + r.encrypted.call_numbers[i] = ntohl(r.encrypted.call_numbers[i]); + if (r.encrypted.call_numbers[i] < 0) + return RXKADSEALEDINCON; + } + } + + if (ntohl(r.encrypted.inc_nonce) != cdat->nonce+1) + return RXKADOUTOFSEQUENCE; + + { + int level = ntohl(r.encrypted.level); + if ((level < cdat->cur_level) || (level > rxkad_crypt)) + return RXKADLEVELFAIL; + cdat->cur_level = level; + /* We don't use trailers but the transarc implementation breaks if + * we don't set the trailer size, packets get to large */ + if (level == rxkad_auth) + { + rx_SetSecurityHeaderSize(con, 4); + rx_SetSecurityMaxTrailerSize(con, 4); + } + else if (level == rxkad_crypt) + { + rx_SetSecurityHeaderSize(con, 8); + rx_SetSecurityMaxTrailerSize(con, 8); + } + } + + rxi_SetCallNumberVector(con, r.encrypted.call_numbers); + + rxkad_calc_header_iv(con, cdat->k.keysched, + (const struct ktc_encryptionKey *)&cdat->k.key, + cdat->e.header_iv); + cdat->authenticated = 1; + + if (obj->user_ok) + { + code = obj->user_ok(p.name, p.instance, p.cell, serv_kvno); + if (code) + return RXKADNOAUTH; + } + else + { + struct ktc_principal *user = (struct ktc_principal *) rxi_Alloc(sizeof(struct ktc_principal)); + *user = p; + cdat->user = user; + } + return 0; +} + +/* + * Checksum and/or encrypt packet + */ +static +int +server_PreparePacket(struct rx_securityClass *obj_, + struct rx_call *call, + struct rx_packet *pkt) +{ + struct rx_connection *con = rx_ConnectionOf(call); + serv_con_data *cdat = (serv_con_data *) con->securityData; + key_stuff *k = &cdat->k; + end_stuff *e = &cdat->e; + + return rxkad_prepare_packet(pkt, con, cdat->cur_level, k, e); +} + +/* + * Verify checksum and/or decrypt packet. + */ +static +int +server_CheckPacket(struct rx_securityClass *obj_, + struct rx_call *call, + struct rx_packet *pkt) +{ + struct rx_connection *con = rx_ConnectionOf(call); + serv_con_data *cdat = (serv_con_data *) con->securityData; + key_stuff *k = &cdat->k; + end_stuff *e = &cdat->e; + + if (time(0) > cdat->expires) /* Use fast time package instead??? */ + return RXKADEXPIRED; + + return rxkad_check_packet(pkt, con, cdat->cur_level, k, e); +} + +static +int +server_GetStats(const struct rx_securityClass *obj_, + const struct rx_connection *con, + struct rx_securityObjectStats *st) +{ + rxkad_serv_class *obj = (rxkad_serv_class *) obj_; + serv_con_data *cdat = (serv_con_data *) con->securityData; + + st->type = rxkad_disipline; + st->level = obj->min_level; + st->flags = rxkad_checksummed; + if (cdat == 0) + st->flags |= rxkad_unallocated; + { + st->bytesReceived = cdat->e.bytesReceived; + st->packetsReceived = cdat->e.packetsReceived; + st->bytesSent = cdat->e.bytesSent; + st->packetsSent = cdat->e.packetsSent; + st->expires = cdat->expires; + st->level = cdat->cur_level; + if (cdat->authenticated) + st->flags |= rxkad_authenticated; + } + return 0; +} + +static struct rx_securityOps server_ops = { + server_Close, + server_NewConnection, + server_PreparePacket, + 0, + server_CheckAuthentication, + server_CreateChallenge, + server_GetChallenge, + 0, + server_CheckResponse, + server_CheckPacket, + server_DestroyConnection, + server_GetStats, +}; + +struct rx_securityClass * +rxkad_NewServerSecurityObject(rxkad_level min_level, + void *appl_data, + int (*get_key)(void *appl_data, + int kvno, + struct ktc_encryptionKey *key), + int (*user_ok)(char *name, + char *inst, + char *realm, + int kvno)) +{ + rxkad_serv_class *obj; + + if (!get_key) + return 0; + + obj = (rxkad_serv_class *) rxi_Alloc(sizeof(rxkad_serv_class)); + obj->klass.refCount = 1; + obj->klass.ops = &server_ops; + obj->klass.privateData = (char *) obj; + + obj->min_level = min_level; + obj->appl_data = appl_data; + obj->get_key = get_key; + obj->user_ok = user_ok; + + return &obj->klass; +} diff --git a/src/rxkad/rxkad.h b/src/rxkad/rxkad.h new file mode 100644 index 0000000000..616cd67ed3 --- /dev/null +++ b/src/rxkad/rxkad.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 1995 - 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +#ifndef AFS_SRC_RXKAD_H +#define AFS_SRC_RXKAD_H + +#define MAXKTCTICKETLIFETIME (30*24*60*60) +#define MINKTCTICKETLEN (32) +#define MAXKTCTICKETLEN (1024) +#define MAXKTCNAMELEN (64) +#define MAXKTCREALMLEN (64) +#define KTC_TIME_UNCERTAINTY (60*15) + +#define MAXRANDOMNAMELEN 16 /* length of random generated + usernames used by afslog for high + security must be < MAXKTCNAMELEN */ + +#define LOGON_OPTION_INTEGRATED 1 +#define LOGON_OPTION_HIGHSECURITY 2 + +/* + * Define ticket types. For Kerberos V4 tickets, this is overloaded as + * the server key version number, so class numbers 0 through 255 are reserved + * for V4 tickets. For other types, the kvno field passed to/from + * ktc_[SG]etToken is used to carry the ticket type. + */ + +/* For Kerberos V5, tickets have an in-the-clear portion containing the + * server key version. + */ +#define RXKAD_TKT_TYPE_KERBEROS_V5 256 + +/* + * rxkad krb5 "proposal 2B": + * Make a special ticket that will fit inside the token buffers of old + * versions that use a value of 344 for MAXKTCTICKETLEN. This is done + * by using only the encrypted part of a Kerberos V5 ticket. This type + * stomps insides the v4 kvno space. This is bad but necessary in order + * to allow these tokens to be used in old clients and to allow them + * to be carried over the krb524 protocol. + */ +#define RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY 213 + +/* + * The AFS/DFS translator may also make use of additional ticket types in + * the range 257 through 511. DO NOT USE THESE FOR ANY OTHER PURPOSE. + */ +#define RXKAD_TKT_TYPE_ADAPT_RESERVED_MIN 257 +#define RXKAD_TKT_TYPE_ADAPT_RESERVED_MAX 511 + + +struct ktc_encryptionKey { + char data[8]; +}; + +struct ktc_principal { + char name[MAXKTCNAMELEN]; + char instance[MAXKTCNAMELEN]; + char cell[MAXKTCREALMLEN]; +#ifdef AFS_NT40_ENV + char smbname[MAXRANDOMNAMELEN]; +#endif +}; + +typedef char rxkad_level; +extern int rxkad_min_level; /* enforce min level at client end */ +#define rxkad_clear 0 /* checksum some selected header fields */ +#define rxkad_auth 1 /* rxkad_clear + protected packet length */ +#define rxkad_crypt 2 /* rxkad_crypt + encrypt packet payload */ + +extern int rxkad_EpochWasSet; + +/* XXX rxkad stats */ + + +/* + * Misc stuff that shouldn't be exported + */ + +#define round_up_to_ebs(v) (((v) + 7) & (~7)) + +#ifdef KERNEL +#include "../afs/rxkad_prototypes.h" +#else +#include "rxkad_prototypes.h" +#endif +#include "rxkad_errs.h" + +#endif /* AFS_SRC_RXKAD_H */ diff --git a/src/rxkad/rxkad.p.h b/src/rxkad/rxkad.p.h deleted file mode 100644 index e27ad77299..0000000000 --- a/src/rxkad/rxkad.p.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2000, International Business Machines Corporation and others. - * All Rights Reserved. - * - * This software has been released under the terms of the IBM Public - * License. For details, see the LICENSE file in the top-level source - * directory or online at http://www.openafs.org/dl/license10.html - */ - -/* The Kerberos Authenticated DES security object. */ - - -#ifndef TRANSARC_RXKAD_RXKAD_H -#define TRANSARC_RXKAD_RXKAD_H - - /* no ticket good for longer than 30 days */ -#define MAXKTCTICKETLIFETIME (30*24*3600) -#define MINKTCTICKETLEN 32 -#define MAXKTCTICKETLEN 344 -#define MAXKTCNAMELEN 64 /* name & inst should be 256 */ -#define MAXKTCREALMLEN 64 /* should be 256 */ -#define KTC_TIME_UNCERTAINTY (15*60) /* max skew bet. machines' clocks */ - -#define MAXRANDOMNAMELEN 16 /* length of random generated - usernames used by afslog for high - security must be < MAXKTCNAMELEN */ -#define LOGON_OPTION_INTEGRATED 1 -#define LOGON_OPTION_HIGHSECURITY 2 - -/* - * Define ticket types. For Kerberos V4 tickets, this is overloaded as - * the server key version number, so class numbers 0 through 255 are reserved - * for V4 tickets. For Kerberos V5, tickets have an in-the-clear portion - * containing the server key version, so we only use a single type number to - * identify those tickets. The ticket type is carried in the kvno field - * passed to/from ktc_[SG]etToken. - */ -#define RXKAD_TKT_TYPE_KERBEROS_V5 256 - -/* - * The AFS/DFS translator may also make use of additional ticket types in - * the range 257 through 511. DO NOT USE THESE FOR ANY OTHER PURPOSE. - */ -#define RXKAD_TKT_TYPE_ADAPT_RESERVED_MIN 257 -#define RXKAD_TKT_TYPE_ADAPT_RESERVED_MAX 511 - -struct ktc_encryptionKey { - char data[8]; -}; - -struct ktc_principal { - char name[MAXKTCNAMELEN]; - char instance[MAXKTCNAMELEN]; - char cell[MAXKTCREALMLEN]; -#ifdef AFS_NT40_ENV - char smbname[MAXRANDOMNAMELEN]; -#endif -}; - -#ifndef NEVERDATE -#define NEVERDATE 0xffffffff -#endif - -/* this function round a length to the correct encryption block size */ -#define round_up_to_ebs(v) (((v) + 7) & (~7)) - -typedef char rxkad_type; -#define rxkad_client 1 /* bits definitions */ -#define rxkad_server 2 - -typedef char rxkad_level; -#define rxkad_clear 0 /* send packets in the clear */ -#define rxkad_auth 1 /* send encrypted sequence numbers */ -#define rxkad_crypt 2 /* encrypt packet data */ - -/* many stats are kept per type and per level. These are encoded into an index - * from 0 to 5 by the StatIndex macro. */ - -#define rxkad_StatIndex(type,level) \ - (((((type) == 1) || ((type) == 2)) && ((level) >= 0) && ((level) <= 2)) \ - ? (((level)<<1)+(type)-1) : 0) -#define rxkad_LevelIndex(level) \ - ((((level) >= 0) && ((level) <= 2)) ? (level) : 0) -#define rxkad_TypeIndex(type) \ - ((((type) == 1) || ((type) == 2)) ? (type) : 0) - -struct rxkad_stats { - afs_uint32 connections[3]; /* client side only */ - afs_uint32 destroyObject; /* client security objects */ - afs_uint32 destroyClient; /* client connections */ - afs_uint32 destroyUnused; /* unused server conn */ - afs_uint32 destroyUnauth; /* unauthenticated server conn */ - afs_uint32 destroyConn[3]; /* server conn per level */ - afs_uint32 expired; /* server packets rejected */ - afs_uint32 challengesSent; /* server challenges sent */ - afs_uint32 challenges[3]; /* challenges seen by client */ - afs_uint32 responses[3]; /* responses seen by server */ - afs_uint32 preparePackets[6]; - afs_uint32 checkPackets[6]; - afs_uint32 bytesEncrypted[2]; /* index just by type */ - afs_uint32 bytesDecrypted[2]; - afs_uint32 fc_encrypts[2]; /* DECRYPT==0, ENCRYPT==1 */ - afs_uint32 fc_key_scheds; /* key schedule creations */ - afs_uint32 des_encrypts[2]; /* DECRYPT==0, ENCRYPT==1 */ - afs_uint32 des_key_scheds; /* key schedule creations */ - afs_uint32 des_randoms; /* random blocks generated */ - long spares[10]; -}; - -#if defined(AFS_NT40_ENV) && defined(AFS_PTHREAD_ENV) -#ifndef RXKAD_STATS_DECLSPEC -#define RXKAD_STATS_DECLSPEC __declspec(dllimport) extern -#endif -#else -#define RXKAD_STATS_DECLSPEC extern -#endif -RXKAD_STATS_DECLSPEC struct rxkad_stats rxkad_stats; -#ifdef AFS_PTHREAD_ENV -#include -#include -extern pthread_mutex_t rxkad_stats_mutex; -#define LOCK_RXKAD_STATS assert(pthread_mutex_lock(&rxkad_stats_mutex)==0); -#define UNLOCK_RXKAD_STATS assert(pthread_mutex_unlock(&rxkad_stats_mutex)==0); -#else -#define LOCK_RXKAD_STATS -#define UNLOCK_RXKAD_STATS -#endif - - -/* gak! using up spares already! */ -#define rxkad_stats_clientObjects (rxkad_stats.spares[0]) -#define rxkad_stats_serverObjects (rxkad_stats.spares[1]) - -extern int rxkad_EpochWasSet; /* TRUE => we called rx_SetEpoch */ - -#ifdef KERNEL -#include "../afs/rxkad_prototypes.h" -#else -#include "rxkad_prototypes.h" -#endif - -#endif /* TRANSARC_RXKAD_RXKAD_H */ diff --git a/src/rxkad/rxkad_client.c b/src/rxkad/rxkad_client.c deleted file mode 100644 index 042e091db0..0000000000 --- a/src/rxkad/rxkad_client.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright 2000, International Business Machines Corporation and others. - * All Rights Reserved. - * - * This software has been released under the terms of the IBM Public - * License. For details, see the LICENSE file in the top-level source - * directory or online at http://www.openafs.org/dl/license10.html - */ - -/* The rxkad security object. Authentication using a DES-encrypted - * Kerberos-style ticket. These are the client-only routines. They do not - * make any use of DES. */ - -#include -#ifdef KERNEL -#include "../afs/param.h" -#else -#include -#endif - -RCSID("$Header$"); - -#ifdef KERNEL -#include "../afs/stds.h" -#ifndef UKERNEL -#include "../h/types.h" -#include "../h/time.h" -#ifdef AFS_LINUX20_ENV -#include "../h/socket.h" -#endif -#include "../netinet/in.h" -#else /* !UKERNEL */ -#include "../afs/sysincludes.h" -#endif /* !UKERNEL */ -#ifndef AFS_LINUX22_ENV -#include "../rpc/types.h" -#include "../rx/xdr.h" -#endif -#include "../rx/rx.h" -#else /* ! KERNEL */ -#include -#include -#include -#ifdef HAVE_STRING_H -#include -#else -#ifdef HAVE_STRINGS_H -#include -#endif -#endif -#ifdef AFS_NT40_ENV -#include -#else -#include -#endif -#include -#include -#ifdef AFS_PTHREAD_ENV -#include "../rxkad/rxkad.h" -#endif /* AFS_PTHREAD_ENV */ -#endif /* KERNEL */ - -#include "private_data.h" -#define XPRT_RXKAD_CLIENT - -char *rxi_Alloc(); - -#ifndef max -#define max(a,b) ((a) < (b)? (b) : (a)) -#endif /* max */ - -static struct rx_securityOps rxkad_client_ops = { - rxkad_Close, - rxkad_NewConnection, /* every new connection */ - rxkad_PreparePacket, /* once per packet creation */ - 0, /* send packet (once per retrans.) */ - 0, - 0, - 0, - rxkad_GetResponse, /* respond to challenge packet */ - 0, - rxkad_CheckPacket, /* check data packet */ - rxkad_DestroyConnection, - rxkad_GetStats, - 0, - 0, - 0, -}; - -/* To minimize changes to epoch, we set this Cuid once, and everyone (including - * rxnull) uses it after that. This means that the Ksession of the first - * authencticated connection should be a good one. */ - -#ifdef AFS_PTHREAD_ENV -/* - * This mutex protects the following global variables: - * Cuid - * counter - * rxkad_EpochWasSet - */ -#include -pthread_mutex_t rxkad_client_uid_mutex; -#define LOCK_CUID assert(pthread_mutex_lock(&rxkad_client_uid_mutex)==0); -#define UNLOCK_CUID assert(pthread_mutex_unlock(&rxkad_client_uid_mutex)==0); -#else -#define LOCK_CUID -#define UNLOCK_CUID -#endif /* AFS_PTHREAD_ENV */ - -static afs_int32 Cuid[2]; /* set once and shared by all */ -int rxkad_EpochWasSet = 0; /* TRUE => we called rx_SetEpoch */ - -/* allocate a new connetion ID in place */ -int rxkad_AllocCID(struct rx_securityClass *aobj, struct rx_connection *aconn) -{ - struct rxkad_cprivate *tcp; - struct rxkad_cidgen tgen; - static afs_int32 counter = 0; /* not used anymore */ - - LOCK_CUID - if (Cuid[0] == 0) { - afs_uint32 xor[2]; - tgen.ipAddr = rxi_getaddr(); /* comes back in net order */ - clock_GetTime(&tgen.time); /* changes time1 and time2 */ - tgen.time.sec = htonl(tgen.time.sec); - tgen.time.usec = htonl(tgen.time.usec); - tgen.counter = htonl(counter); - counter++; -#ifdef KERNEL - tgen.random1 = afs_random() & 0x7fffffff; /* was "80000" */ - tgen.random2 = afs_random() & 0x7fffffff; /* was "htonl(100)" */ -#else - tgen.random1 = htonl(getpid()); - tgen.random2 = htonl(100); -#endif - if (aobj) { - /* block is ready for encryption with session key, let's go for it. */ - tcp = (struct rxkad_cprivate *) aobj->privateData; - memcpy((void *)xor, (void *)tcp->ivec, 2*sizeof(afs_int32)); - fc_cbc_encrypt((char *) &tgen, (char *) &tgen, sizeof(tgen), - tcp->keysched, xor, ENCRYPT); - } else { - /* Create a session key so that we can encrypt it */ - - } - memcpy((void *)Cuid, ((char *)&tgen) + sizeof(tgen) - ENCRYPTIONBLOCKSIZE, ENCRYPTIONBLOCKSIZE); - Cuid[0] = (Cuid[0] & ~0x40000000) | 0x80000000; - Cuid[1] &= RX_CIDMASK; - rx_SetEpoch (Cuid[0]); /* for future rxnull connections */ - rxkad_EpochWasSet++; - } - - if (!aconn) { - UNLOCK_CUID - return 0; - } - aconn->epoch = Cuid[0]; - aconn->cid = Cuid[1]; - Cuid[1] += 1<refCount = 1; /* caller gets one for free */ - tsc->ops = &rxkad_client_ops; - - size = sizeof(struct rxkad_cprivate); - tcp = (struct rxkad_cprivate *) rxi_Alloc (size); - memset((void *)tcp, 0, size); - tsc->privateData = (char *) tcp; - tcp->type |= rxkad_client; - tcp->level = level; - code = fc_keysched (sessionkey, tcp->keysched); - if (code) return 0; /* bad key */ - memcpy((void *)tcp->ivec, (void *)sessionkey, sizeof(tcp->ivec)); - tcp->kvno = kvno; /* key version number */ - tcp->ticketLen = ticketLen; /* length of ticket */ - memcpy(tcp->ticket, ticket, ticketLen); - - LOCK_RXKAD_STATS - rxkad_stats_clientObjects++; - UNLOCK_RXKAD_STATS - return tsc; -} - -/* client: respond to a challenge packet */ - -int rxkad_GetResponse(struct rx_securityClass *aobj, - struct rx_connection *aconn, struct rx_packet *apacket) -{ struct rxkad_cprivate *tcp; - char *tp; - int v2; /* whether server is old style or v2 */ - afs_int32 challengeID; - rxkad_level level; - char *response; - int responseSize, missing; - struct rxkad_v2ChallengeResponse r_v2; - struct rxkad_oldChallengeResponse r_old; - - tcp = (struct rxkad_cprivate *) aobj->privateData; - - if (!(tcp->type & rxkad_client)) return RXKADINCONSISTENCY; - - v2 = (rx_Contiguous(apacket) > sizeof(struct rxkad_oldChallenge)); - tp = rx_DataOf(apacket); - - if (v2) { /* v2 challenge */ - struct rxkad_v2Challenge *c_v2; - if (rx_GetDataSize(apacket) < sizeof(struct rxkad_v2Challenge)) - return RXKADPACKETSHORT; - c_v2 = (struct rxkad_v2Challenge *)tp; - challengeID = ntohl(c_v2->challengeID); - level = ntohl(c_v2->level); - } else { /* old format challenge */ - struct rxkad_oldChallenge *c_old; - if (rx_GetDataSize(apacket) < sizeof(struct rxkad_oldChallenge)) - return RXKADPACKETSHORT; - c_old = (struct rxkad_oldChallenge *)tp; - challengeID = ntohl(c_old->challengeID); - level = ntohl(c_old->level); - } - - if (level > tcp->level) return RXKADLEVELFAIL; - LOCK_RXKAD_STATS - rxkad_stats.challenges[rxkad_LevelIndex(tcp->level)]++; - UNLOCK_RXKAD_STATS - - if (v2) { - int i; - afs_uint32 xor[2]; - memset((void *)&r_v2, 0, sizeof(r_v2)); - r_v2.version = htonl(RXKAD_CHALLENGE_PROTOCOL_VERSION); - r_v2.spare = 0; - (void) rxkad_SetupEndpoint (aconn, &r_v2.encrypted.endpoint); - (void) rxi_GetCallNumberVector (aconn, r_v2.encrypted.callNumbers); - for (i=0; ilevel); - r_v2.kvno = htonl(tcp->kvno); - r_v2.ticketLen = htonl(tcp->ticketLen); - r_v2.encrypted.endpoint.cksum = rxkad_CksumChallengeResponse (&r_v2); - memcpy((void *)xor, (void *)tcp->ivec, 2*sizeof(afs_int32)); - fc_cbc_encrypt (&r_v2.encrypted, &r_v2.encrypted, - sizeof(r_v2.encrypted), tcp->keysched, xor, ENCRYPT); - response = (char *)&r_v2; - responseSize = sizeof(r_v2); - } else { - memset((void *)&r_old, 0, sizeof(r_old)); - r_old.encrypted.incChallengeID = htonl(challengeID + 1); - r_old.encrypted.level = htonl((afs_int32)tcp->level); - r_old.kvno = htonl(tcp->kvno); - r_old.ticketLen = htonl(tcp->ticketLen); - fc_ecb_encrypt (&r_old.encrypted, &r_old.encrypted, tcp->keysched, ENCRYPT); - response = (char *)&r_old; - responseSize = sizeof(r_old); - } - - if (RX_MAX_PACKET_DATA_SIZE < responseSize + tcp->ticketLen) - return RXKADPACKETSHORT; /* not enough space */ - - rx_computelen(apacket, missing); - missing = responseSize + tcp->ticketLen - missing; - if (missing > 0) - if (rxi_AllocDataBuf(apacket, missing, RX_PACKET_CLASS_SEND) > 0) - return RXKADPACKETSHORT; /* not enough space */ - - /* copy response and ticket into packet */ - rx_packetwrite(apacket, 0, responseSize, response); - rx_packetwrite(apacket, responseSize, tcp->ticketLen, tcp->ticket); - - rx_SetDataSize (apacket, responseSize + tcp->ticketLen); - return 0; -} - -void rxkad_ResetState(void) -{ - LOCK_CUID - Cuid[0] = 0; - rxkad_EpochWasSet=0; - UNLOCK_CUID -} diff --git a/src/rxkad/rxkad_common.c b/src/rxkad/rxkad_common.c deleted file mode 100644 index 0aaeadc3fa..0000000000 --- a/src/rxkad/rxkad_common.c +++ /dev/null @@ -1,515 +0,0 @@ -/* - * Copyright 2000, International Business Machines Corporation and others. - * All Rights Reserved. - * - * This software has been released under the terms of the IBM Public - * License. For details, see the LICENSE file in the top-level source - * directory or online at http://www.openafs.org/dl/license10.html - */ - -/* The rxkad security object. Routines used by both client and servers. */ - -#include -#ifdef KERNEL -#include "../afs/param.h" -#else -#include -#endif - -#ifdef AFS_SUN59_ENV -#include -#endif - -#define INCLUDE_RXKAD_PRIVATE_DECLS - -RCSID("$Header$"); - -#ifdef KERNEL -#ifndef UKERNEL -#include "../afs/stds.h" -#include "../afs/afs_osi.h" -#ifdef AFS_AIX_ENV -#include "../h/systm.h" -#endif -#ifdef AFS_DARWIN60_ENV -#include "../h/kernel.h" -#endif -#include "../h/types.h" -#include "../h/time.h" -#ifndef AFS_LINUX22_ENV -#include "../rpc/types.h" -#include "../rx/xdr.h" -#endif /* AFS_LINUX22_ENV */ -#else /* !UKERNEL */ -#include "../afs/sysincludes.h" -#include "../afs/afsincludes.h" -#endif /* !UKERNEL */ -#include "../rx/rx.h" - -#else /* KERNEL */ -#include -#include -#include -#ifdef AFS_NT40_ENV -#include -#ifdef AFS_PTHREAD_ENV -#define RXKAD_STATS_DECLSPEC __declspec(dllexport) -#endif -#else -#include -#endif -#include -#include -#ifdef HAVE_STRING_H -#include -#else -#ifdef HAVE_STRINGS_H -#include -#endif -#endif - -#endif /* KERNEL */ - -#include "private_data.h" -#define XPRT_RXKAD_COMMON - -char *rxi_Alloc(); - -#ifndef afs_max -#define afs_max(a,b) ((a) < (b)? (b) : (a)) -#endif /* afs_max */ - -#ifndef KERNEL -#define osi_Time() time(0) -#endif -struct rxkad_stats rxkad_stats = {0}; - -/* static prototypes */ -static afs_int32 ComputeSum(struct rx_packet *apacket, - fc_KeySchedule *aschedule, afs_int32 *aivec); -static afs_int32 FreeObject(struct rx_securityClass *aobj); - -/* this call sets up an endpoint structure, leaving it in *network* byte - * order so that it can be used quickly for encryption. - */ -int rxkad_SetupEndpoint(struct rx_connection *aconnp, - struct rxkad_endpoint *aendpointp) -{ - register afs_int32 i; - - aendpointp->cuid[0] = htonl(aconnp->epoch); - i = aconnp->cid & RX_CIDMASK; - aendpointp->cuid[1] = htonl(i); - aendpointp->cksum = 0; /* used as cksum only in chal resp. */ - aendpointp->securityIndex = htonl(aconnp->securityIndex); - return 0; -} - -/* setup xor information based on session key */ -int rxkad_DeriveXORInfo(struct rx_connection *aconnp, - fc_KeySchedule *aschedule, char *aivec, char *aresult) -{ - struct rxkad_endpoint tendpoint; - afs_uint32 xor[2]; - - rxkad_SetupEndpoint(aconnp, &tendpoint); - memcpy((void *)xor, aivec, 2*sizeof(afs_int32)); - fc_cbc_encrypt(&tendpoint, &tendpoint, sizeof(tendpoint), - aschedule, xor, ENCRYPT); - memcpy(aresult, ((char *)&tendpoint) + sizeof(tendpoint) - ENCRYPTIONBLOCKSIZE, ENCRYPTIONBLOCKSIZE); - return 0; -} - -/* rxkad_CksumChallengeResponse - computes a checksum of the components of a - * challenge response packet (which must be unencrypted and in network order). - * The endpoint.cksum field is omitted and treated as zero. The cksum is - * returned in network order. */ - -afs_uint32 rxkad_CksumChallengeResponse(struct rxkad_v2ChallengeResponse *v2r) -{ - int i; - afs_uint32 cksum; - u_char *cp = (u_char *)v2r; - afs_uint32 savedCksum = v2r->encrypted.endpoint.cksum; - - v2r->encrypted.endpoint.cksum = 0; - - /* this function captured from budb/db_hash.c */ - cksum = 1000003; - for (i=0; iencrypted.endpoint.cksum = savedCksum; - return htonl(cksum); -} - -void rxkad_SetLevel(struct rx_connection *conn, rxkad_level level) -{ - if (level == rxkad_auth) { - rx_SetSecurityHeaderSize (conn, 4); - rx_SetSecurityMaxTrailerSize (conn, 4); - } - else if (level == rxkad_crypt) { - rx_SetSecurityHeaderSize (conn, 8); - rx_SetSecurityMaxTrailerSize (conn, 8); /* XXX was 7, but why screw with - unaligned accesses? */ - } -} - -/* returns a short integer in host byte order representing a good checksum of - * the packet header. - */ -static afs_int32 ComputeSum(struct rx_packet *apacket, - fc_KeySchedule *aschedule, afs_int32 *aivec) -{ - afs_uint32 word[2]; - register afs_uint32 t; - - t = apacket->header.callNumber; - word[0] = htonl(t); - /* note that word [1] includes the channel # */ - t = ((apacket->header.cid & 0x3) << 30) - | ((apacket->header.seq & 0x3fffffff)); - word[1] = htonl(t); - /* XOR in the ivec from the per-endpoint encryption */ - word[0] ^= aivec[0]; - word[1] ^= aivec[1]; - /* encrypts word as if it were a character string */ - fc_ecb_encrypt(word, word, aschedule, ENCRYPT); - t = ntohl(word[1]); - t = (t >> 16) & 0xffff; - if (t == 0) t = 1; /* so that 0 means don't care */ - return t; -} - - -static afs_int32 FreeObject(struct rx_securityClass *aobj) -{ struct rxkad_cprivate *tcp; /* both structs start w/ type field */ - - if (aobj->refCount > 0) return 0; /* still in use */ - tcp = (struct rxkad_cprivate *)aobj->privateData; - rxi_Free(aobj, sizeof(struct rx_securityClass)); - if (tcp->type & rxkad_client) { - rxi_Free(tcp, sizeof(struct rxkad_cprivate)); - } - else if (tcp->type & rxkad_server) { - rxi_Free(tcp, sizeof(struct rxkad_sprivate)); - } - else { return RXKADINCONSISTENCY; } /* unknown type */ - LOCK_RXKAD_STATS - rxkad_stats.destroyObject++; - UNLOCK_RXKAD_STATS - return 0; -} - -/* rxkad_Close - called by rx with the security class object as a parameter - * when a security object is to be discarded */ - -int rxkad_Close(struct rx_securityClass *aobj) -{ - afs_int32 code; - aobj->refCount--; - code = FreeObject (aobj); - return code; -} - -/* either: called to (re)create a new connection. */ - -int rxkad_NewConnection(struct rx_securityClass *aobj, - struct rx_connection *aconn) -{ - if (aconn->securityData) - return RXKADINCONSISTENCY; /* already allocated??? */ - - if (rx_IsServerConn(aconn)) { - int size = sizeof(struct rxkad_sconn); - aconn->securityData = (char *) rxi_Alloc (size); - memset(aconn->securityData, 0, size); /* initialize it conveniently */ - } - else { /* client */ - struct rxkad_cprivate *tcp; - struct rxkad_cconn *tccp; - int size = sizeof(struct rxkad_cconn); - tccp = (struct rxkad_cconn *) rxi_Alloc (size); - aconn->securityData = (char *) tccp; - memset(aconn->securityData, 0, size); /* initialize it conveniently */ - tcp = (struct rxkad_cprivate *) aobj->privateData; - if (!(tcp->type & rxkad_client)) return RXKADINCONSISTENCY; - rxkad_SetLevel(aconn, tcp->level); /* set header and trailer sizes */ - rxkad_AllocCID(aobj, aconn); /* CHANGES cid AND epoch!!!! */ - rxkad_DeriveXORInfo(aconn, tcp->keysched, tcp->ivec, tccp->preSeq); - LOCK_RXKAD_STATS - rxkad_stats.connections[rxkad_LevelIndex(tcp->level)]++; - UNLOCK_RXKAD_STATS - } - - aobj->refCount++; /* attached connection */ - return 0; -} - -/* either: called to destroy a connection. */ - -int rxkad_DestroyConnection(struct rx_securityClass *aobj, - struct rx_connection *aconn) -{ - if (rx_IsServerConn(aconn)) { - struct rxkad_sconn *sconn; - struct rxkad_serverinfo *rock; - sconn = (struct rxkad_sconn *)aconn->securityData; - if (sconn) { - aconn->securityData = 0; - LOCK_RXKAD_STATS - if (sconn->authenticated) - rxkad_stats.destroyConn[rxkad_LevelIndex(sconn->level)]++; - else rxkad_stats.destroyUnauth++; - UNLOCK_RXKAD_STATS - rock = sconn->rock; - if (rock) rxi_Free (rock, sizeof(struct rxkad_serverinfo)); - rxi_Free (sconn, sizeof(struct rxkad_sconn)); - } - else { - LOCK_RXKAD_STATS - rxkad_stats.destroyUnused++; - UNLOCK_RXKAD_STATS - } - } - else { /* client */ - struct rxkad_cconn *cconn; - struct rxkad_cprivate *tcp; - cconn = (struct rxkad_cconn *)aconn->securityData; - tcp = (struct rxkad_cprivate *) aobj->privateData; - if (!(tcp->type & rxkad_client)) return RXKADINCONSISTENCY; - if (cconn) { - aconn->securityData = 0; - rxi_Free (cconn, sizeof(struct rxkad_cconn)); - } - LOCK_RXKAD_STATS - rxkad_stats.destroyClient++; - UNLOCK_RXKAD_STATS - } - aobj->refCount--; /* decrement connection counter */ - if (aobj->refCount <= 0) { - afs_int32 code; - code = FreeObject (aobj); - if (code) return code; - } - return 0; -} - -/* either: decode packet */ - -int rxkad_CheckPacket(struct rx_securityClass *aobj, - struct rx_call *acall, struct rx_packet *apacket) -{ struct rx_connection *tconn; - rxkad_level level; - fc_KeySchedule *schedule; - fc_InitializationVector *ivec; - int len; - int nlen; - u_int word; /* so we get unsigned right-shift */ - int checkCksum; - afs_int32 *preSeq; - afs_int32 code; - - tconn = rx_ConnectionOf(acall); - len = rx_GetDataSize (apacket); - checkCksum = 0; /* init */ - if (rx_IsServerConn(tconn)) { - struct rxkad_sconn *sconn; - sconn = (struct rxkad_sconn *) tconn->securityData; - if (rx_GetPacketCksum(apacket) != 0) sconn->cksumSeen = 1; - checkCksum = sconn->cksumSeen; - if (sconn && sconn->authenticated && - (osi_Time() < sconn->expirationTime)) { - level = sconn->level; - LOCK_RXKAD_STATS - rxkad_stats.checkPackets[rxkad_StatIndex(rxkad_server, level)]++; - UNLOCK_RXKAD_STATS - sconn->stats.packetsReceived++; - sconn->stats.bytesReceived += len; - schedule = (fc_KeySchedule *)sconn->keysched; - ivec = (fc_InitializationVector *)sconn->ivec; - } - else { - LOCK_RXKAD_STATS - rxkad_stats.expired++; - UNLOCK_RXKAD_STATS - return RXKADEXPIRED; - } - preSeq = sconn->preSeq; - } - else { /* client connection */ - struct rxkad_cconn *cconn; - struct rxkad_cprivate *tcp; - cconn = (struct rxkad_cconn *) tconn->securityData; - if (rx_GetPacketCksum(apacket) != 0) cconn->cksumSeen = 1; - checkCksum = cconn->cksumSeen; - tcp = (struct rxkad_cprivate *) aobj->privateData; - if (!(tcp->type & rxkad_client)) return RXKADINCONSISTENCY; - level = tcp->level; - LOCK_RXKAD_STATS - rxkad_stats.checkPackets[rxkad_StatIndex(rxkad_client, level)]++; - UNLOCK_RXKAD_STATS - cconn->stats.packetsReceived++; - cconn->stats.bytesReceived += len; - preSeq = cconn->preSeq; - schedule = (fc_KeySchedule *)tcp->keysched; - ivec = (fc_InitializationVector *)tcp->ivec; - } - - if (checkCksum) { - code = ComputeSum(apacket, schedule, preSeq); - if (code != rx_GetPacketCksum(apacket)) - return RXKADSEALEDINCON; - } - - switch (level) { - case rxkad_clear: return 0; /* shouldn't happen */ - case rxkad_auth: - rx_Pullup(apacket, 8); /* the following encrypts 8 bytes only */ - fc_ecb_encrypt (rx_DataOf(apacket), rx_DataOf(apacket), - schedule, DECRYPT); - break; - case rxkad_crypt: - code = rxkad_DecryptPacket (tconn, schedule, ivec, len, apacket); - if (code) return code; - break; - } - word = ntohl(rx_GetInt32(apacket,0)); /* get first sealed word */ - if ((word >> 16) != - ((apacket->header.seq ^ apacket->header.callNumber) & 0xffff)) - return RXKADSEALEDINCON; - nlen = word & 0xffff; /* get real user data length */ - - /* The sealed length should be no larger than the initial length, since the - * reverse (round-up) occurs in ...PreparePacket */ - if (nlen > len) - return RXKADDATALEN; - rx_SetDataSize (apacket, nlen); - return 0; -} - -/* either: encode packet */ - -int rxkad_PreparePacket(struct rx_securityClass *aobj, - struct rx_call *acall, struct rx_packet *apacket) -{ - struct rx_connection *tconn; - rxkad_level level; - fc_KeySchedule *schedule; - fc_InitializationVector *ivec; - int len; - int nlen; - int word; - afs_int32 code; - afs_int32 *preSeq; - - tconn = rx_ConnectionOf(acall); - len = rx_GetDataSize (apacket); - if (rx_IsServerConn(tconn)) { - struct rxkad_sconn *sconn; - sconn = (struct rxkad_sconn *) tconn->securityData; - if (sconn && sconn->authenticated && - (osi_Time() < sconn->expirationTime)) { - level = sconn->level; - LOCK_RXKAD_STATS - rxkad_stats.preparePackets[rxkad_StatIndex(rxkad_server, level)]++; - UNLOCK_RXKAD_STATS - sconn->stats.packetsSent++; - sconn->stats.bytesSent += len; - schedule = (fc_KeySchedule *)sconn->keysched; - ivec = (fc_InitializationVector *)sconn->ivec; - } - else { - LOCK_RXKAD_STATS - rxkad_stats.expired++; /* this is a pretty unlikely path... */ - UNLOCK_RXKAD_STATS - return RXKADEXPIRED; - } - preSeq = sconn->preSeq; - } - else { /* client connection */ - struct rxkad_cconn *cconn; - struct rxkad_cprivate *tcp; - cconn = (struct rxkad_cconn *) tconn->securityData; - tcp = (struct rxkad_cprivate *) aobj->privateData; - if (!(tcp->type & rxkad_client)) return RXKADINCONSISTENCY; - level = tcp->level; - LOCK_RXKAD_STATS - rxkad_stats.preparePackets[rxkad_StatIndex(rxkad_client, level)]++; - UNLOCK_RXKAD_STATS - cconn->stats.packetsSent++; - cconn->stats.bytesSent += len; - preSeq = cconn->preSeq; - schedule = (fc_KeySchedule *)tcp->keysched; - ivec = (fc_InitializationVector *)tcp->ivec; - } - - /* compute upward compatible checksum */ - rx_SetPacketCksum(apacket, ComputeSum(apacket, schedule, preSeq)); - if (level == rxkad_clear) return 0; - - len = rx_GetDataSize (apacket); - word = (((apacket->header.seq ^ apacket->header.callNumber) - & 0xffff) << 16) | (len & 0xffff); - rx_PutInt32(apacket,0, htonl(word)); - - switch (level) { - case rxkad_clear: return 0; /* shouldn't happen */ - case rxkad_auth: - nlen = afs_max (ENCRYPTIONBLOCKSIZE, - len + rx_GetSecurityHeaderSize(tconn)); - if (nlen > (len + rx_GetSecurityHeaderSize(tconn))) { - rxi_RoundUpPacket(apacket, nlen - (len + rx_GetSecurityHeaderSize(tconn))); - } - rx_Pullup(apacket, 8); /* the following encrypts 8 bytes only */ - fc_ecb_encrypt (rx_DataOf(apacket), rx_DataOf(apacket), - schedule, ENCRYPT); - break; - case rxkad_crypt: - nlen = round_up_to_ebs(len + rx_GetSecurityHeaderSize(tconn)); - if (nlen > (len + rx_GetSecurityHeaderSize(tconn))) { - rxi_RoundUpPacket(apacket, nlen - (len + rx_GetSecurityHeaderSize(tconn))); - } - code = rxkad_EncryptPacket (tconn, schedule, ivec, nlen, apacket); - if (code) return code; - break; - } - rx_SetDataSize (apacket, nlen); - return 0; -} - -/* either: return connection stats */ - -int rxkad_GetStats(struct rx_securityClass *aobj, - struct rx_connection *aconn, struct rx_securityObjectStats *astats) -{ - astats->type = 3; - astats->level = ((struct rxkad_cprivate *)aobj->privateData)->level; - if (!aconn->securityData) { - astats->flags |= 1; - return 0; - } - if (rx_IsServerConn(aconn)) { - struct rxkad_sconn *sconn; - sconn = (struct rxkad_sconn *) aconn->securityData; - astats->level = sconn->level; - if (sconn->authenticated) astats->flags |= 2; - if (sconn->cksumSeen) astats->flags |= 8; - astats->expires = sconn->expirationTime; - astats->bytesReceived = sconn->stats.bytesReceived; - astats->packetsReceived = sconn->stats.packetsReceived; - astats->bytesSent = sconn->stats.bytesSent; - astats->packetsSent = sconn->stats.packetsSent; - } - else { /* client connection */ - struct rxkad_cconn *cconn; - cconn = (struct rxkad_cconn *) aconn->securityData; - if (cconn->cksumSeen) astats->flags |= 8; - astats->bytesReceived = cconn->stats.bytesReceived; - astats->packetsReceived = cconn->stats.packetsReceived; - astats->bytesSent = cconn->stats.bytesSent; - astats->packetsSent = cconn->stats.packetsSent; - } - return 0; -} diff --git a/src/rxkad/rxkad_locl.h b/src/rxkad/rxkad_locl.h new file mode 100644 index 0000000000..b463511b46 --- /dev/null +++ b/src/rxkad/rxkad_locl.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 1995, 1996, 1997 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +/* @(#)$Id$ */ + +#ifndef __RXKAD_LOCL_H +#define __RXKAD_LOCL_H + +/* $Id$ */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include + +#include +#include + +#ifdef NDEBUG +#ifndef assert +#define assert(e) ((void)0) +#endif +#else +#ifndef assert +#define assert(e) ((e) ? (void)0 : (void)osi_Panic("assert(%s) failed: file %s, line %d\n", #e, __FILE__, __LINE__, #e)) +#endif +#endif + +#include + +#undef RCSID +#include +#undef RCSID +#define RCSID(msg) \ +static /**/const char *const rcsid[] = { (char *)rcsid, "\100(#)" msg } + +extern int rx_epoch, rx_nextCid; + +#include "rxkad.h" +#include "rxkad_errs.h" + +#define rxkad_disipline 3 + +#define rxkad_unallocated 1 +#define rxkad_authenticated 2 +#define rxkad_expired 4 +#define rxkad_checksummed 8 + +#define ROUNDS 16 + +#define ROUNDS 16 +typedef afs_int32 fc_KeySchedule[ROUNDS]; + +int fc_keysched(const void *key_, afs_int32 sched[ROUNDS]); + +/* In_ and out_ MUST be afs_uint32 aligned */ +int fc_ecb_encrypt(const void *in_, void *out_, + const afs_int32 sched[ROUNDS], int encrypt); + +/* In_ and out_ MUST be afs_uint32 aligned */ +int fc_cbc_encrypt(const void *in_, void *out_, afs_int32 length, + const afs_int32 sched[ROUNDS], afs_uint32 iv[2], + int encrypt); + +int rxkad_EncryptPacket(const void *rx_connection_not_used, + const afs_int32 sched[ROUNDS], const afs_uint32 iv[2], + int len, struct rx_packet *packet); + +int rxkad_DecryptPacket(const void *rx_connection_not_used, + const afs_int32 sched[ROUNDS], const afs_uint32 iv[2], + int len, struct rx_packet *packet); + +#ifdef __GNUC__ +static inline +void +fc_cbc_enc2(const void *in, void *out, afs_int32 length, const afs_int32 sched[ROUNDS], + const afs_uint32 iv_[2], int encrypt) +{ + afs_uint32 iv[2]; + iv[0] = iv_[0]; + iv[1] = iv_[1]; + fc_cbc_encrypt(in, out, length, sched, iv, encrypt); +} +#else +#define fc_cbc_enc2(in, out, length, sched, iv_, encrypt) \ +{ afs_uint32 _iv_[2]; afs_uint32 *_tmp_ = (iv_); \ + memcpy(_iv_, _tmp_, 8); \ + fc_cbc_encrypt((in), (out), (length), (sched), (_iv_), (encrypt)); } +#endif + +#define RXKAD_VERSION 2 + +/* Version 2 challenge format */ +typedef struct rxkad_challenge { + afs_int32 version; + afs_int32 nonce; + afs_int32 min_level; + afs_int32 unused; +} rxkad_challenge; + +/* To protect the client from being used as an oracle the response + * contains connection specific information. */ +typedef struct rxkad_response { + afs_int32 version; + afs_int32 unused; + struct { + afs_int32 epoch; + afs_int32 cid; + afs_uint32 cksum; /* Cksum of this response */ + afs_int32 security_index; + afs_int32 call_numbers[RX_MAXCALLS]; + afs_int32 inc_nonce; + afs_int32 level; + } encrypted; + afs_int32 kvno; + afs_int32 ticket_len; + /* u_char the_ticket[ticket_len]; */ +} rxkad_response; + +typedef struct key_stuff { + afs_int32 keysched[ROUNDS]; + struct ktc_encryptionKey key; +} key_stuff; + +typedef struct end_stuff { + afs_uint32 header_iv[2]; + afs_uint32 bytesReceived, packetsReceived, bytesSent, packetsSent; +} end_stuff; + +afs_uint32 +rxkad_cksum_response(rxkad_response *r); + +void +rxkad_calc_header_iv(const struct rx_connection *conn, + const afs_int32 sched[ROUNDS], + const struct ktc_encryptionKey *in_iv, + afs_uint32 out_iv[2]); + +int +rxkad_prepare_packet(struct rx_packet *pkt, struct rx_connection *con, + int level, key_stuff *k, end_stuff *e); + +int +rxkad_check_packet(struct rx_packet *pkt, struct rx_connection *con, + int level, key_stuff *k, end_stuff *e); + +/* Per connection specific server data */ +typedef struct serv_con_data { + end_stuff e; + key_stuff k; + afs_uint32 expires; + afs_int32 nonce; + struct ktc_principal *user; + afs_int32 kvno; + rxkad_level cur_level; /* Starts at min_level and can only increase */ + char authenticated; +} serv_con_data; + + +int +decomp_ticket(char *data, + int length, + char *pname, + char *pinstance, + char *prealm, + afs_int32 *paddress, + unsigned char *session, + afs_int32 *life, + afs_int32 *time_sec, + struct ktc_encryptionKey *key, + des_key_schedule schedule); + + +int +rxkad_decode_krb5_ticket(int (*get_key)(void *appl_data, + int kvno, + struct ktc_encryptionKey *key), + void *appl_data, + int serv_kvno, + char *ticket, + afs_int32 ticket_len, + /* OUT parms */ + struct ktc_encryptionKey *session_key, + afs_uint32 *expires, + struct ktc_principal *p, + afs_int32 *real_kvno); + + +void +_rxkad_crc_init_table(void); + +afs_uint32 +_rxkad_crc_update (const char *p, size_t len, afs_uint32 res); + + +#endif /* __RXKAD_LOCL_H */ diff --git a/src/rxkad/rxkad_prototypes.h b/src/rxkad/rxkad_prototypes.h index 1c339ff940..57e867740d 100644 --- a/src/rxkad/rxkad_prototypes.h +++ b/src/rxkad/rxkad_prototypes.h @@ -7,99 +7,47 @@ * directory or online at http://www.openafs.org/dl/license10.html */ -#ifndef _RXKAD_PROTOTYPES_H -#define _RXKAD_PROTOTYPES_H +#ifndef AFS_SRC_RXKAD_PROTO_H +#define AFS_SRC_RXKAD_PROTO_H -/* till the typedefs are moved elsewhere */ -#ifdef KERNEL -#include "../afs/fcrypt.h" -#else -#include "rx/fcrypt.h" -#endif #include "../rx/rx.h" -/* domestic/crypt_conn.c */ -extern afs_int32 rxkad_DecryptPacket (const struct rx_connection *conn, - const fc_KeySchedule *schedule, const fc_InitializationVector *ivec, - const int len, struct rx_packet *packet); -extern afs_int32 rxkad_EncryptPacket (const struct rx_connection *conn, - const fc_KeySchedule *schedule, const fc_InitializationVector *ivec, - const int len, struct rx_packet *packet); +/* rxk_clnt.c */ +extern struct rx_securityClass * +rxkad_NewClientSecurityObject(rxkad_level level, + struct ktc_encryptionKey *sessionkey, + afs_int32 kvno, + int ticket_len, + char *ticket); - -/* domestic/fcrypt.c */ -extern int fc_keysched (struct ktc_encryptionKey *key, - fc_KeySchedule schedule); -extern afs_int32 fc_ecb_encrypt(afs_uint32 *clear, afs_uint32 *cipher, - fc_KeySchedule schedule, int encrypt); -extern afs_int32 fc_cbc_encrypt (char *input, char *output, afs_int32 length, - fc_KeySchedule key, afs_uint32 *xor, int encrypt); - -/* rxkad_client.c */ -extern int rxkad_AllocCID(struct rx_securityClass *aobj, struct rx_connection *aconn); -extern struct rx_securityClass *rxkad_NewClientSecurityObject( - rxkad_level level, struct ktc_encryptionKey *sessionkey, - afs_int32 kvno, int ticketLen, char *ticket); -extern int rxkad_GetResponse(struct rx_securityClass *aobj, - struct rx_connection *aconn, struct rx_packet *apacket); -extern void rxkad_ResetState(void); - -/* rxkad_common.c */ -#if 0 -/* can't prototype these due to types */ -extern int rxkad_SetupEndpoint(struct rx_connection *aconnp, - struct rxkad_endpoint *aendpointp); -extern afs_uint32 rxkad_CksumChallengeResponse(struct rxkad_v2ChallengeResponse *v2r); -#endif -extern int rxkad_DeriveXORInfo(struct rx_connection *aconnp, - fc_KeySchedule *aschedule, char *aivec, char *aresult); -extern void rxkad_SetLevel(struct rx_connection *conn, rxkad_level level); -extern int rxkad_Close(struct rx_securityClass *aobj); -extern int rxkad_NewConnection(struct rx_securityClass *aobj, - struct rx_connection *aconn); -extern int rxkad_DestroyConnection(struct rx_securityClass *aobj, - struct rx_connection *aconn); -extern int rxkad_CheckPacket(struct rx_securityClass *aobj, - struct rx_call *acall, struct rx_packet *apacket); -extern int rxkad_PreparePacket(struct rx_securityClass *aobj, - struct rx_call *acall, struct rx_packet *apacket); -extern int rxkad_GetStats(struct rx_securityClass *aobj, - struct rx_connection *aconn, struct rx_securityObjectStats *astats); - - -/* rxkad_errs.c */ - -/* rxkad_server.c */ -extern struct rx_securityClass *rxkad_NewServerSecurityObject ( - rxkad_level level, char *get_key_rock, - int (*get_key)(char *get_key_rock, int kvno, struct ktc_encryptionKey *serverKey), - int (*user_ok)(char *name, char *instance, char *cell, afs_int32 kvno)); -extern int rxkad_CheckAuthentication (struct rx_securityClass *aobj, - struct rx_connection *aconn); -extern int rxkad_CreateChallenge(struct rx_securityClass *aobj, - struct rx_connection *aconn); -extern int rxkad_GetChallenge (struct rx_securityClass *aobj, - struct rx_connection *aconn, struct rx_packet *apacket); -extern int rxkad_CheckResponse (struct rx_securityClass *aobj, - struct rx_connection *aconn, struct rx_packet *apacket); +/* rxk_info.c */ extern afs_int32 rxkad_GetServerInfo (struct rx_connection *aconn, rxkad_level *level, afs_uint32 *expiration, char *name, char *instance, char *cell, afs_int32 *kvno); +/* rxk_serv.c */ +extern struct rx_securityClass *rxkad_NewServerSecurityObject ( + rxkad_level min_level, void *appl_data, + int (*get_key)(void *appl_data, + int kvno, + struct ktc_encryptionKey *serverKey), + int (*user_ok)(char *name, + char *inst, + char *realm, + int kvno)); - -/* ticket.c */ -extern int tkt_DecodeTicket (char *asecret, afs_int32 ticketLen, - struct ktc_encryptionKey *key, char *name, char *inst, char *cell, - char *sessionKey, afs_int32 *host, afs_int32 *start, afs_int32 *end); +/* v4.c */ +extern afs_uint32 life_to_time (afs_uint32 start, int life_); +extern int time_to_life (afs_uint32 start, afs_uint32 end); +extern int tkt_CheckTimes (afs_uint32 start, afs_uint32 end, afs_uint32 now); extern int tkt_MakeTicket (char *ticket, int *ticketLen, struct ktc_encryptionKey *key, char *name, char *inst, char *cell, afs_uint32 start, afs_uint32 end, struct ktc_encryptionKey *sessionKey, afs_uint32 host, char *sname, char *sinst); -extern int tkt_CheckTimes (afs_uint32 start, afs_uint32 end, afs_uint32 now); +extern int tkt_DecodeTicket (char *ticket, afs_int32 ticketLen, + struct ktc_encryptionKey *key, char *name, char *inst, char *cell, + char *sessionKey, afs_int32 *host, afs_int32 *start, afs_int32 *end); extern afs_int32 ktohl (char flags, afs_int32 l); -extern afs_uint32 life_to_time (afs_uint32 start, unsigned char life); -extern unsigned char time_to_life (afs_uint32 start, afs_uint32 end); -#endif +#endif /* AFS_SRC_RXKAD_PROTO_H */ diff --git a/src/rxkad/rxkad_server.c b/src/rxkad/rxkad_server.c deleted file mode 100644 index 11d6948799..0000000000 --- a/src/rxkad/rxkad_server.c +++ /dev/null @@ -1,406 +0,0 @@ -/* - * Copyright 2000, International Business Machines Corporation and others. - * All Rights Reserved. - * - * This software has been released under the terms of the IBM Public - * License. For details, see the LICENSE file in the top-level source - * directory or online at http://www.openafs.org/dl/license10.html - */ - -/* The rxkad security object. Authentication using a DES-encrypted - * Kerberos-style ticket. These are the server-only routines. */ - - -#include -#include - -RCSID("$Header$"); - -#include -#include -#include -#ifdef AFS_NT40_ENV -#include -#else -#include -#endif -#ifdef HAVE_STRING_H -#include -#else -#ifdef HAVE_STRINGS_H -#include -#endif -#endif -#include -#include -#include -#include -#include "private_data.h" -#define XPRT_RXKAD_SERVER - -/* - * This can be set to allow alternate ticket decoding. - * Currently only used by the AFS/DFS protocol translator to recognize - * Kerberos V5 tickets. The actual code to do that is provided externally. - */ -afs_int32 (*rxkad_AlternateTicketDecoder)(); - -static struct rx_securityOps rxkad_server_ops = { - rxkad_Close, - rxkad_NewConnection, - rxkad_PreparePacket, /* once per packet creation */ - 0, /* send packet (once per retrans) */ - rxkad_CheckAuthentication, - rxkad_CreateChallenge, - rxkad_GetChallenge, - 0, - rxkad_CheckResponse, - rxkad_CheckPacket, /* check data packet */ - rxkad_DestroyConnection, - rxkad_GetStats, -}; -extern afs_uint32 rx_MyMaxSendSize; - -/* Miscellaneous random number routines that use the fcrypt module and the - * timeofday. */ - -static fc_KeySchedule random_int32_schedule; - -#ifdef AFS_PTHREAD_ENV -/* - * This mutex protects the following global variables: - * random_int32_schedule - * seed - */ - -#include -pthread_mutex_t rxkad_random_mutex; -#define LOCK_RM assert(pthread_mutex_lock(&rxkad_random_mutex)==0); -#define UNLOCK_RM assert(pthread_mutex_unlock(&rxkad_random_mutex)==0); -#else -#define LOCK_RM -#define UNLOCK_RM -#endif /* AFS_PTHREAD_ENV */ - -static void init_random_int32 (void) -{ struct timeval key; - - gettimeofday (&key, NULL); - LOCK_RM - fc_keysched (&key, random_int32_schedule); - UNLOCK_RM -} - -static afs_int32 get_random_int32 (void) -{ static struct timeval seed; - afs_int32 rc; - - LOCK_RM - fc_ecb_encrypt (&seed, &seed, random_int32_schedule, ENCRYPT); - rc = seed.tv_sec; - UNLOCK_RM - return rc; -} - -/* Called with four parameters. The first is the level of encryption, as - defined in the rxkad.h file. The second and third are a rock and a - procedure that is called with the key version number that accompanies the - ticket and returns a pointer to the server's decryption key. The fourth - argument, if not NULL, is a pointer to a function that will be called for - every new connection with the name, instance and cell of the client. The - routine should return zero if the user is NOT acceptible to the server. If - this routine is not supplied, the server can call rxkad_GetServerInfo with - the rx connection pointer passed to the RPC routine to obtain information - about the client. */ - -/* - rxkad_level level; * minimum level * - char *get_key_rock; * rock for get_key implementor * - int (*get_key)(); * passed kvno & addr(key) to fill * - int (*user_ok)(); * passed name, inst, cell => bool * -*/ - -struct rx_securityClass *rxkad_NewServerSecurityObject ( - rxkad_level level, char *get_key_rock, - int (*get_key)(char *get_key_rock, int kvno, struct ktc_encryptionKey *serverKey), - int (*user_ok)(char *name, char *instance, char *cell, afs_int32 kvno)) -{ struct rx_securityClass *tsc; - struct rxkad_sprivate *tsp; - int size; - - if (!get_key) return 0; - - size = sizeof(struct rx_securityClass); - tsc = (struct rx_securityClass *) osi_Alloc (size); - memset(tsc, 0, size); - tsc->refCount = 1; /* caller has one reference */ - tsc->ops = &rxkad_server_ops; - size = sizeof(struct rxkad_sprivate); - tsp = (struct rxkad_sprivate *) osi_Alloc (size); - memset(tsp, 0, size); - tsc->privateData = (char *) tsp; - - tsp->type |= rxkad_server; /* so can identify later */ - tsp->level = level; /* level of encryption */ - tsp->get_key_rock = get_key_rock; - tsp->get_key = get_key; /* to get server ticket */ - tsp->user_ok = user_ok; /* to inform server of client id. */ - init_random_int32 (); - - LOCK_RXKAD_STATS - rxkad_stats_serverObjects++; - UNLOCK_RXKAD_STATS - return tsc; -} - -/* server: called to tell if a connection authenticated properly */ - -int rxkad_CheckAuthentication (struct rx_securityClass *aobj, - struct rx_connection *aconn) -{ struct rxkad_sconn *sconn; - - /* first make sure the object exists */ - if (!aconn->securityData) return RXKADINCONSISTENCY; - - sconn = (struct rxkad_sconn *) aconn->securityData; - return !sconn->authenticated; -} - -/* server: put the current challenge in the connection structure for later use - by packet sender */ - -int rxkad_CreateChallenge(struct rx_securityClass *aobj, - struct rx_connection *aconn) -{ struct rxkad_sconn *sconn; - struct rxkad_sprivate *tsp; - - sconn = (struct rxkad_sconn *) aconn->securityData; - sconn->challengeID = get_random_int32 (); - sconn->authenticated = 0; /* conn unauth. 'til we hear back */ - /* initialize level from object's minimum acceptable level */ - tsp = (struct rxkad_sprivate *)aobj->privateData; - sconn->level = tsp->level; - return 0; -} - -/* server: fill in a challenge in the packet */ - -int rxkad_GetChallenge (struct rx_securityClass *aobj, - struct rx_connection *aconn, struct rx_packet *apacket) -{ struct rxkad_sconn *sconn; - char *challenge; - int challengeSize; - struct rxkad_v2Challenge c_v2; /* version 2 */ - struct rxkad_oldChallenge c_old; /* old style */ - - sconn = (struct rxkad_sconn *) aconn->securityData; - if (rx_IsUsingPktCksum(aconn)) sconn->cksumSeen = 1; - - if (sconn->cksumSeen) { - memset(&c_v2, 0, sizeof(c_v2)); - c_v2.version = htonl(RXKAD_CHALLENGE_PROTOCOL_VERSION); - c_v2.challengeID = htonl(sconn->challengeID); - c_v2.level = htonl((afs_int32)sconn->level); - c_v2.spare = 0; - challenge = (char *)&c_v2; - challengeSize = sizeof(c_v2); - } else { - memset(&c_old, 0, sizeof(c_old)); - c_old.challengeID = htonl(sconn->challengeID); - c_old.level = htonl((afs_int32)sconn->level); - challenge = (char *)&c_old; - challengeSize = sizeof(c_old); - } - if (rx_MyMaxSendSize < challengeSize) - return RXKADPACKETSHORT; /* not enough space */ - - rx_packetwrite(apacket, 0, challengeSize, challenge); - rx_SetDataSize (apacket, challengeSize); - sconn->tried = 1; - LOCK_RXKAD_STATS - rxkad_stats.challengesSent++; - UNLOCK_RXKAD_STATS - return 0; -} - -/* server: process a response to a challenge packet */ -/* XXX this does some copying of data in and out of the packet, but I'll bet it - * could just do it in place, especially if I used rx_Pullup... - */ -int rxkad_CheckResponse (struct rx_securityClass *aobj, - struct rx_connection *aconn, struct rx_packet *apacket) -{ struct rxkad_sconn *sconn; - struct rxkad_sprivate *tsp; - struct ktc_encryptionKey serverKey; - struct rxkad_oldChallengeResponse oldr; /* response format */ - struct rxkad_v2ChallengeResponse v2r; - afs_int32 tlen; /* ticket len */ - afs_int32 kvno; /* key version of ticket */ - char tix[MAXKTCTICKETLEN]; - afs_int32 incChallengeID; - rxkad_level level; - int code; - /* ticket contents */ - struct ktc_principal client; - struct ktc_encryptionKey sessionkey; - afs_int32 host; - afs_uint32 start; - afs_uint32 end; - unsigned int pos; - struct rxkad_serverinfo *rock; - - sconn = (struct rxkad_sconn *) aconn->securityData; - tsp = (struct rxkad_sprivate *) aobj->privateData; - - if (sconn->cksumSeen) { - /* expect v2 response, leave fields in v2r in network order for cksum - * computation which follows decryption. */ - if (rx_GetDataSize(apacket) < sizeof(v2r)) - return RXKADPACKETSHORT; - rx_packetread(apacket, 0, sizeof(v2r), &v2r); - pos = sizeof(v2r); - /* version == 2 */ - /* ignore spare */ - kvno = ntohl (v2r.kvno); - tlen = ntohl(v2r.ticketLen); - if (rx_GetDataSize(apacket) < sizeof(v2r) + tlen) - return RXKADPACKETSHORT; - } else { - /* expect old format response */ - if (rx_GetDataSize(apacket) < sizeof(oldr)) return RXKADPACKETSHORT; - rx_packetread(apacket, 0, sizeof(oldr), &oldr); - pos = sizeof(oldr); - - kvno = ntohl (oldr.kvno); - tlen = ntohl(oldr.ticketLen); - if (rx_GetDataSize(apacket) != sizeof(oldr) + tlen) - return RXKADPACKETSHORT; - } - if ((tlen < MINKTCTICKETLEN) || (tlen > MAXKTCTICKETLEN)) - return RXKADTICKETLEN; - - rx_packetread(apacket, pos, tlen, tix); /* get ticket */ - - /* - * We allow the ticket to be optionally decoded by an alternate - * ticket decoder, if the function variable - * rxkad_AlternateTicketDecoder is set. That function should - * return a code of -1 if it wants the ticket to be decoded by - * the standard decoder. - */ - if (rxkad_AlternateTicketDecoder) { - code = rxkad_AlternateTicketDecoder - (kvno, tix, tlen, client.name, client.instance, client.cell, - &sessionkey, &host, &start, &end); - if (code && code != -1) { - return code; - } - } else { - code = -1; /* No alternate ticket decoder present */ - } - - /* - * If the alternate decoder is not present, or returns -1, then - * assume the ticket is of the default style. - */ - if (code == -1) { - /* get ticket's key */ - code = (*tsp->get_key)(tsp->get_key_rock, kvno, &serverKey); - if (code) return RXKADUNKNOWNKEY; /* invalid kvno */ - code = tkt_DecodeTicket (tix, tlen, &serverKey, - client.name, client.instance, client.cell, - &sessionkey, &host, &start, &end); - if (code) return RXKADBADTICKET; - } - code = tkt_CheckTimes (start, end, time(0)); - if (code == -1) return RXKADEXPIRED; - else if (code <= 0) return RXKADNOAUTH; - - code = fc_keysched (&sessionkey, sconn->keysched); - if (code) return RXKADBADKEY; - memcpy(sconn->ivec, &sessionkey, sizeof(sconn->ivec)); - - if (sconn->cksumSeen) { - /* using v2 response */ - afs_uint32 cksum; /* observed cksum */ - struct rxkad_endpoint endpoint; /* connections endpoint */ - int i; - afs_uint32 xor[2]; - - memcpy(xor, sconn->ivec, 2*sizeof(afs_int32)); - fc_cbc_encrypt (&v2r.encrypted, &v2r.encrypted, sizeof(v2r.encrypted), - sconn->keysched, xor, DECRYPT); - cksum = rxkad_CksumChallengeResponse (&v2r); - if (cksum != v2r.encrypted.endpoint.cksum) - return RXKADSEALEDINCON; - (void) rxkad_SetupEndpoint (aconn, &endpoint); - v2r.encrypted.endpoint.cksum = 0; - if (memcmp (&endpoint, &v2r.encrypted.endpoint, sizeof(endpoint)) != 0) - return RXKADSEALEDINCON; - for (i=0; ikeysched, DECRYPT); - incChallengeID = ntohl(oldr.encrypted.incChallengeID); - level = ntohl(oldr.encrypted.level); - } - if (incChallengeID != sconn->challengeID+1) - return RXKADOUTOFSEQUENCE; /* replay attempt */ - if ((level < sconn->level) || (level > rxkad_crypt)) return RXKADLEVELFAIL; - sconn->level = level; - rxkad_SetLevel (aconn, sconn->level); - LOCK_RXKAD_STATS - rxkad_stats.responses[rxkad_LevelIndex(sconn->level)]++; - UNLOCK_RXKAD_STATS - - /* now compute endpoint-specific info used for computing 16 bit checksum */ - rxkad_DeriveXORInfo(aconn, sconn->keysched, sconn->ivec, sconn->preSeq); - - /* otherwise things are ok */ - sconn->expirationTime = end; - sconn->authenticated = 1; - - if (tsp->user_ok) { - code = tsp->user_ok (client.name, client.instance, client.cell, kvno); - if (code) return RXKADNOAUTH; - } - else { /* save the info for later retreival */ - int size = sizeof(struct rxkad_serverinfo); - rock = (struct rxkad_serverinfo *) osi_Alloc (size); - memset(rock, 0, size); - rock->kvno = kvno; - memcpy(&rock->client, &client, sizeof(rock->client)); - sconn->rock = rock; - } - return 0; -} - -/* return useful authentication info about a server-side connection */ - -afs_int32 rxkad_GetServerInfo (struct rx_connection *aconn, - rxkad_level *level, afs_uint32 *expiration, char *name, char *instance, - char *cell, afs_int32 *kvno) -{ - struct rxkad_sconn *sconn; - - sconn = (struct rxkad_sconn *) aconn->securityData; - if (sconn && sconn->authenticated && sconn->rock && - (time(0) < sconn->expirationTime)) { - if (level) *level = sconn->level; - if (expiration) *expiration = sconn->expirationTime; - if (name) strcpy (name, sconn->rock->client.name); - if (instance) strcpy (instance, sconn->rock->client.instance); - if (cell) strcpy (cell, sconn->rock->client.cell); - if (kvno) *kvno = sconn->rock->kvno; - return 0; - } - else return RXKADNOAUTH; -} diff --git a/src/rxkad/test/Makefile.in b/src/rxkad/test/Makefile.in index faca0a8ab4..34e8290af0 100644 --- a/src/rxkad/test/Makefile.in +++ b/src/rxkad/test/Makefile.in @@ -13,8 +13,10 @@ CFLAGS=-g -I. -I${srcdir} -I${TOP_OBJDIR}/src/config -I${TOP_INCDIR} ${XCFLAGS} HEADERS = ../rxkad.h stress.h stress_internal.h stress_errs.h -LIBS=${TOP_LIBDIR}/librx.a \ +LIBS=${TOP_LIBDIR}/libauth.a \ + ${TOP_LIBDIR}/librx.a \ ${TOP_LIBDIR}/liblwp.a \ + ${TOP_LIBDIR}/libsys.a \ ${TOP_LIBDIR}/libcmd.a \ ${TOP_LIBDIR}/librxkad.a \ ${TOP_LIBDIR}/libdes.a \ diff --git a/src/rxkad/test/stress.c b/src/rxkad/test/stress.c index c11fa3e799..1a0a311bc3 100644 --- a/src/rxkad/test/stress.c +++ b/src/rxkad/test/stress.c @@ -89,6 +89,7 @@ static int StringToAuth (authname) #define aRECLAIM 21 #define a2DCHOICE 22 #define aMAXSKEW 23 +#define aUSETOKENS 24 static int CommandProc (as, arock) char *arock; @@ -122,6 +123,7 @@ static int CommandProc (as, arock) cParms->callTest = (as->parms[aCALLTEST].items != 0); cParms->hijackTest = (as->parms[aHIJACKTEST].items != 0); cParms->stopServer = (as->parms[aSTOPSERVER].items != 0); + cParms->useTokens = (as->parms[aUSETOKENS].items != 0); if (as->parms[aMELT1b].items) meltdown_1pkt = 0; @@ -268,6 +270,7 @@ void main (argc, argv) initialize_RXK_error_table(); initialize_RKS_error_table(); initialize_CMD_error_table(); + initialize_KTC_error_table(); code = rx_Init (0); rx_SetRxDeadTime(120); @@ -308,6 +311,7 @@ void main (argc, argv) cmd_AddParm (ts, "-noreclaim", CMD_FLAG, CMD_OPTIONAL, "dont aggressively reclaim packets"); cmd_AddParm (ts, "-no2dchoice", CMD_FLAG, CMD_OPTIONAL, "disable rx_getcall 2d choice code"); cmd_AddParm (ts, "-maxskew", CMD_SINGLE, CMD_OPTIONAL, "max client server skew in seconds"); + cmd_AddParm (ts, "-usetokens", CMD_FLAG, CMD_OPTIONAL, "use existing tokens"); code = cmd_Dispatch (argc, argv); exit (code!=0); diff --git a/src/rxkad/test/stress_c.c b/src/rxkad/test/stress_c.c index aac253651b..278c08be38 100644 --- a/src/rxkad/test/stress_c.c +++ b/src/rxkad/test/stress_c.c @@ -26,6 +26,7 @@ RCSID("$Header$"); #include #include #include +#include #include "stress.h" #include "stress_internal.h" #ifdef AFS_PTHREAD_ENV @@ -52,6 +53,29 @@ static long GetServer(aname) return addr; } +static long GetToken (versionP, session, ticketLenP, ticket) + OUT long *versionP; + OUT struct ktc_encryptionKey *session; + OUT int *ticketLenP; + OUT char *ticket; +{ + struct ktc_principal sname; + struct ktc_token ttoken; + long code; + + strcpy(sname.cell, "heimdal.mit.edu"); + sname.instance[0] = 0; + strcpy(sname.name, "afs"); + code = ktc_GetToken(&sname, &ttoken, sizeof(ttoken), NULL); + if (code) return code; + + *versionP = ttoken.kvno; + *ticketLenP = ttoken.ticketLen; + memcpy(ticket, ttoken.ticket, ttoken.ticketLen); + memcpy(session, &ttoken.sessionKey, sizeof(struct ktc_encryptionKey)); + return 0; +} + static long GetTicket (versionP, session, ticketLenP, ticket) OUT long *versionP; OUT struct ktc_encryptionKey *session; @@ -68,7 +92,7 @@ static long GetTicket (versionP, session, ticketLenP, ticket) /* now create the actual ticket */ *ticketLenP = 0; code = tkt_MakeTicket(ticket, ticketLenP, &serviceKey, - RXKST_CLIENT_NAME, RXKST_CLIENT_INST, "", + RXKST_CLIENT_NAME, RXKST_CLIENT_INST, RXKST_CLIENT_CELL, /*start,end*/0, 0xffffffff, session, /*host*/0, RXKST_SERVER_NAME, RXKST_SERVER_NAME); /* parms were buffer, ticketlen, key to seal ticket with, principal name, @@ -1142,7 +1166,10 @@ long rxkst_StartClient (parms) int ticketLen; struct ktc_encryptionKey Ksession; - code = GetTicket (&kvno, &Ksession, &ticketLen, ticket); + if (parms->useTokens) + code = GetToken (&kvno, &Ksession, &ticketLen, ticket); + else + code = GetTicket (&kvno, &Ksession, &ticketLen, ticket); if (code) return code; /* next, we have ticket, kvno and session key, authenticate the conn */ diff --git a/src/rxkad/test/stress_internal.h b/src/rxkad/test/stress_internal.h index efc5394719..3917cb5dc6 100644 --- a/src/rxkad/test/stress_internal.h +++ b/src/rxkad/test/stress_internal.h @@ -19,6 +19,7 @@ extern long serviceKeyVersion; #define RXKST_SERVER_INST "" #define RXKST_CLIENT_NAME "rxkad_stress_test_client" #define RXKST_CLIENT_INST "" +#define RXKST_CLIENT_CELL "HEIMDAL.MIT.EDU" extern int errno; @@ -44,6 +45,7 @@ struct clientParms { int hijackTest; /* check hijack prevention measures */ int stopServer; /* send stop server RPC */ int authentication; /* type of authentication to use */ + int useTokens; /* use user's existing tokens */ u_long repeatInterval; /* secs between load test activity */ u_long repeatCount; /* times load test activity repeated */ }; @@ -51,11 +53,6 @@ struct clientParms { long rxkst_StartClient(INOUT struct clientParms *parms); long rxkst_StartServer(INOUT struct serverParms *parms); -long RXKST_Fast(); -long RXKST_Slow(); -long RXKST_Copious(); -long RXKST_Kill(); - /* For backward compatibility with AFS3.0 release. */ #ifndef assert diff --git a/src/rxkad/test/stress_s.c b/src/rxkad/test/stress_s.c index ceb7789b38..5b9b11ab13 100644 --- a/src/rxkad/test/stress_s.c +++ b/src/rxkad/test/stress_s.c @@ -33,8 +33,8 @@ RCSID("$Header$"); extern RXKST_ExecuteRequest(); struct ktc_encryptionKey serviceKey = - {0x45, 0xe3, 0x3d, 0x16, 0x29, 0x64, 0x8a, 0x8f}; -long serviceKeyVersion = 7; + {0x0b, 0x20, 0xbc, 0x1a, 0x08, 0x61, 0x20, 0x3d}; +long serviceKeyVersion = 3; static long GetKey (rock, kvno, key) IN char *rock; @@ -108,13 +108,14 @@ static long CheckAuth (call) if (kvno != serviceKeyVersion) return RXKST_BADKVNO; if (strcmp (name, RXKST_CLIENT_NAME) || strcmp (inst, RXKST_CLIENT_INST) || - cell[0]) return RXKST_BADCLIENT; + strcmp (cell, RXKST_CLIENT_CELL)) + return RXKST_BADCLIENT; return 0; } /* Stop the server. There isn't a graceful way to do this so just exit. */ -long SRXKST_Kill (call) +afs_int32 SRXKST_Kill (call) IN struct rx_call *call; { long code; @@ -131,7 +132,7 @@ long SRXKST_Kill (call) return 0; } -long SRXKST_Fast (call, n, inc_nP) +afs_int32 SRXKST_Fast (call, n, inc_nP) IN struct rx_call *call; IN u_long n; OUT u_long *inc_nP; @@ -140,7 +141,7 @@ long SRXKST_Fast (call, n, inc_nP) return 0; } -long SRXKST_Slow (call, tag, nowP) +afs_int32 SRXKST_Slow (call, tag, nowP) IN struct rx_call *call; IN u_long tag; OUT u_long *nowP; @@ -184,7 +185,7 @@ static void PutBuffer(b) buflist = bl; } -long SRXKST_Copious (call, inlen, insum, outlen, outsum) +afs_int32 SRXKST_Copious (call, inlen, insum, outlen, outsum) IN struct rx_call *call; IN u_long inlen; IN u_long insum; diff --git a/src/rxkad/ticket.c b/src/rxkad/ticket.c deleted file mode 100644 index bfeb763d52..0000000000 --- a/src/rxkad/ticket.c +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright 2000, International Business Machines Corporation and others. - * All Rights Reserved. - * - * This software has been released under the terms of the IBM Public - * License. For details, see the LICENSE file in the top-level source - * directory or online at http://www.openafs.org/dl/license10.html - */ - -#include -#if defined(UKERNEL) -#include "../afs/param.h" -#else -#include -#endif - -RCSID("$Header$"); - -#if defined(UKERNEL) -#include "../afs/sysincludes.h" -#include "../afs/afsincludes.h" -#include "../afs/stds.h" -#include "../rx/xdr.h" -#include "../rx/rx.h" -#include "../des/des.h" -#include "../afs/lifetimes.h" -#include "../afs/rxkad.h" -#else /* defined(UKERNEL) */ -#include -#include -#ifdef AFS_NT40_ENV -#include -#else -#include -#endif -#ifdef HAVE_STRING_H -#include -#else -#ifdef HAVE_STRINGS_H -#include -#endif -#endif -#include -#include -#include -#include "lifetimes.h" -#include "rxkad.h" -#endif /* defined(UKERNEL) */ - -/* static prototypes */ -static int decode_athena_ticket (char *ticket, int ticketLen, char *name, - char *inst, char *realm, afs_int32 *host, struct ktc_encryptionKey *sessionKey, - afs_uint32 *start, afs_uint32 *end); -static int assemble_athena_ticket (char *ticket, int *ticketLen, char *name, - char *inst, char *realm, afs_int32 host, struct ktc_encryptionKey *sessionKey, - afs_uint32 start, afs_uint32 end, char *sname, char *sinst); - -#define ANDREWFLAGSVALUE (0x80) -#define TICKET_LABEL "TicketEnd" - -/* This is called to interpret a ticket. It is assumed that the necessary keys - have been added so that the key version number in the ticket will indicate a - valid key for decrypting the ticket. The various fields inside the ticket - are copied into the return arguments. An error code indicate some problem - interpreting the ticket and the values of the output parameters are - undefined. */ - -int tkt_DecodeTicket (char *asecret, afs_int32 ticketLen, - struct ktc_encryptionKey *key, char *name, char *inst, char *cell, - char *sessionKey, afs_int32 *host, afs_int32 *start, afs_int32 *end) -{ char clear_ticket[MAXKTCTICKETLEN]; - char *ticket; - Key_schedule schedule; - /* unsigned char flags; */ - int code; - - if (ticketLen == 0) return RXKADBADTICKET; /* no ticket */ - if ((ticketLen < MINKTCTICKETLEN) || /* minimum legal ticket size */ - ((ticketLen) % 8 != 0)) /* enc. part must be (0 mod 8) bytes */ - return RXKADBADTICKET; - - if (key_sched (key, schedule)) return RXKADBADKEY; - - ticket = clear_ticket; - pcbc_encrypt (asecret, ticket, ticketLen, schedule, key, DECRYPT); - - /* flags = *ticket; */ /* get the first byte: the flags */ -#if 0 - if (flags == ANDREWFLAGSVALUE) { - code = decode_andrew_ticket (ticket, ticketLen, name, inst, cell, - host, sessionKey, start, end); - if (code) { - code = decode_athena_ticket (ticket, ticketLen, name, inst, cell, - host, sessionKey, start, end); - flags = 0; - } - } - else { - code = decode_athena_ticket (ticket, ticketLen, name, inst, cell, - host, sessionKey, start, end); - if (code) { - code = decode_andrew_ticket (ticket, ticketLen, name, inst, cell, - host, sessionKey, start, end); - flags = ANDREWFLAGSVALUE; - } - } -#else - code = decode_athena_ticket - (ticket, ticketLen, name, inst, cell, host, sessionKey, start, end); - /* flags = 0; */ - -#endif - if (code) return RXKADBADTICKET; - if (tkt_CheckTimes (*start, *end, time(0)) < -1) return RXKADBADTICKET; - - return 0; -} - -/* This makes a Kerberos ticket */ -/* - char *ticket; * ticket is constructed here * - int *ticketLen; * output length of finished ticket * - struct ktc_encryptionKey *key; * key ticket should be sealed with * - char *name; * user of this ticket * - char *inst; - char *cell; * cell of authentication * - afs_uint32 start,end; * life of ticket * - struct ktc_encryptionKey *sessionKey; * session key invented for ticket * - afs_uint32 host; * caller's host address * - char *sname; * server * - char *sinst; -*/ - -int tkt_MakeTicket (char *ticket, int *ticketLen, - struct ktc_encryptionKey *key, char *name, char *inst, char *cell, - afs_uint32 start, afs_uint32 end, struct ktc_encryptionKey *sessionKey, - afs_uint32 host, char *sname, char *sinst) -{ int code; - Key_schedule schedule; - - *ticketLen = 0; /* in case we return early */ - code = assemble_athena_ticket (ticket, ticketLen, name, inst, cell, - host, sessionKey, start, end, sname, sinst); - *ticketLen = round_up_to_ebs(*ticketLen); /* round up */ - if (code) return -1; - - /* encrypt ticket */ - if ((code = key_sched (key, schedule))) { - printf ("In tkt_MakeTicket: key_sched returned %d\n", code); - return RXKADBADKEY; - } - pcbc_encrypt (ticket, ticket, *ticketLen, schedule, key, ENCRYPT); - return 0; -} - -#define getstr(name,min) \ - slen = strlen(ticket); \ - if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \ - strcpy (name, ticket); \ - ticket += slen+1 - -static int decode_athena_ticket (char *ticket, int ticketLen, char *name, - char *inst, char *realm, afs_int32 *host, struct ktc_encryptionKey *sessionKey, - afs_uint32 *start, afs_uint32 *end) -{ char *ticketBeg = ticket; - char flags; - int slen; - int tlen; - unsigned char lifetime; - char sname[MAXKTCNAMELEN]; /* these aren't used, */ - char sinst[MAXKTCNAMELEN]; /* but are in the ticket */ - - flags = *ticket++; - getstr (name, 1); - getstr (inst, 0); - getstr (realm, 0); - - memcpy(host, ticket, sizeof (*host)); - ticket += sizeof(*host); - *host = ktohl (flags, *host); - - memcpy(sessionKey, ticket, sizeof (struct ktc_encryptionKey)); - ticket += sizeof (struct ktc_encryptionKey); - - lifetime = *ticket++; - memcpy(start, ticket, sizeof (*start)); - ticket += sizeof(*start); - *start = ktohl (flags, *start); - *end = life_to_time (*start, lifetime); - - getstr (sname, 1); - getstr (sinst, 0); - - tlen = ticket - ticketBeg; - if ((round_up_to_ebs(tlen) != ticketLen) && (ticketLen != 56)) return -1; - return 0; -} - -#define putstr(name,min) \ - slen = strlen(name); \ - if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \ - strcpy (ticket, name); \ - ticket += slen+1 -#define putint(num) num = htonl(num);\ - memcpy(ticket, &num, sizeof(num));\ - ticket += sizeof(num) - -static int assemble_athena_ticket (char *ticket, int *ticketLen, char *name, - char *inst, char *realm, afs_int32 host, struct ktc_encryptionKey *sessionKey, - afs_uint32 start, afs_uint32 end, char *sname, char *sinst) -{ char *ticketBeg = ticket; - int slen; - unsigned char life; - - *ticket++ = 0; /* flags, always send net-byte-order */ - putstr (name, 1); - putstr (inst, 0); - putstr (realm, 0); - putint (host); - - memcpy(ticket, sessionKey, sizeof(struct ktc_encryptionKey)); - ticket += sizeof(struct ktc_encryptionKey); - - life = time_to_life (start, end); - if (life == 0) return -1; - *ticket++ = life; - - putint (start); - putstr (sname, 1); - putstr (sinst, 0); - - *ticketLen = ticket - ticketBeg; - return 0; -} - -/* This is just a routine that checks the consistency of ticket lifetimes. It - returns three values: */ -/* -2 means the times are inconsistent or ticket has expired - -1 means the ticket has recently expired. - 0 means the times are consistent but start time is in the (near) future. - 1 means the start time is in the past and the end time is infinity. - 2 means the start time is past and the end time is in the future - and the lifetime is within the legal limit. - */ - -int tkt_CheckTimes (afs_uint32 start, afs_uint32 end, afs_uint32 now) -{ int active; - - if (start >= end) return -2; /* zero or negative lifetime */ - if (start > now+KTC_TIME_UNCERTAINTY+MAXKTCTICKETLIFETIME) - return -2; /* starts too far in the future? */ - if ((start != 0) && (end != NEVERDATE) && - (end-start > MAXKTCTICKETLIFETIME)) return -2; /* too long a life */ - if ((end != NEVERDATE) && (end+KTC_TIME_UNCERTAINTY < now)) { /* expired */ - if ((start != 0) && (now - start > MAXKTCTICKETLIFETIME + 24*60*60)) - return -2; - else return -1; /* expired only recently */ - } - if ((start == 0) || (start-KTC_TIME_UNCERTAINTY <= now)) active = 1; - else active = 0; /* start time not yet arrived */ - - if ((start == 0) || (end == NEVERDATE)) - return active; /* no expiration time */ - return active*2; /* ticket valid */ -} - -afs_int32 ktohl (char flags, afs_int32 l) -{ - if (flags & 1) { - unsigned char *lp = (unsigned char *)&l; - afs_int32 hl; - hl = *lp + (*(lp+1) << 8) + (*(lp+2) << 16) + (*(lp+3) << 24); - return hl; - } - return ntohl(l); -} - -/* life_to_time - takes a start time and a Kerberos standard lifetime char and - * returns the corresponding end time. There are four simple cases to be - * handled. The first is a life of 0xff, meaning no expiration, and results in - * an end time of 0xffffffff. The second is when life is less than the values - * covered by the table. In this case, the end time is the start time plus the - * number of 5 minute intervals specified by life. The third case returns - * start plus the MAXTKTLIFETIME if life is greater than TKTLIFEMAXFIXED. The - * last case, uses the life value (minus TKTLIFEMINFIXED) as an index into the - * table to extract the lifetime in seconds, which is added to start to produce - * the end time. */ - -afs_uint32 life_to_time (afs_uint32 start, unsigned char life) -{ int realLife; - - if (life == TKTLIFENOEXPIRE) return NEVERDATE; - if (life < TKTLIFEMINFIXED) return start + life*5*60; - if (life > TKTLIFEMAXFIXED) return start + MAXTKTLIFETIME; - realLife = tkt_lifetimes[life - TKTLIFEMINFIXED]; - return start + realLife; -} - -/* time_to_life - takes start and end times for the ticket and returns a - * Kerberos standard lifetime char possibily using the tkt_lifetimes table for - * lifetimes above 127*5minutes. First, the special case of (end == - * 0xffffffff) is handled to mean no expiration. Then negative lifetimes and - * those greater than the maximum ticket lifetime are rejected. Then lifetimes - * less than the first table entry are handled by rounding the requested - * lifetime *up* to the next 5 minute interval. The final step is to search - * the table for the smallest entry *greater than or equal* to the requested - * entry. The actual code is prepared to handle the case where the table is - * unordered but that it an unnecessary frill. */ - -unsigned char time_to_life (afs_uint32 start, afs_uint32 end) -{ int lifetime = end-start; - int best, best_i; - int i; - - if (end == NEVERDATE) return TKTLIFENOEXPIRE; - if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0)) return 0; - if (lifetime < tkt_lifetimes[0]) return (lifetime + 5*60-1) / (5*60); - best_i = -1; - best = MAXKTCTICKETLIFETIME; - for (i=0; i= lifetime) { - int diff = tkt_lifetimes[i]-lifetime; - if (diff < best) { - best = diff; - best_i = i; - }} - if (best_i < 0) return 0; - return best_i+TKTLIFEMINFIXED; -} diff --git a/src/rxkad/v4.c b/src/rxkad/v4.c new file mode 100644 index 0000000000..11fdc10296 --- /dev/null +++ b/src/rxkad/v4.c @@ -0,0 +1,397 @@ +/* + * Copyright 2000, International Business Machines Corporation and others. + * All Rights Reserved. + * + * This software has been released under the terms of the IBM Public + * License. For details, see the LICENSE file in the top-level source + * directory or online at http://www.openafs.org/dl/license10.html + */ + +#include "rxkad_locl.h" + +/* RCSID("$Id$"); */ + +/* Ticket lifetime. This defines the table used to lookup lifetime for the + fixed part of rande of the one byte lifetime field. Values less than 0x80 + are intrpreted as the number of 5 minute intervals. Values from 0x80 to + 0xBF should be looked up in this table. The value of 0x80 is the same using + both methods: 10 and two-thirds hours . The lifetime of 0xBF is 30 days. + The intervening values of have a fixed ratio of roughly 1.06914. The value + oxFF is defined to mean a ticket has no expiration time. This should be + used advisedly since individual servers may impose defacto upperbounds on + ticket lifetimes. */ + +#define TKTLIFENUMFIXED 64 +#define TKTLIFEMINFIXED 0x80 +#define TKTLIFEMAXFIXED 0xBF +#define TKTLIFENOEXPIRE 0xFF +#define MAXTKTLIFETIME (30*24*3600) /* 30 days */ + +static const int tkt_lifetimes[TKTLIFENUMFIXED] = { + 38400, /* 10.67 hours, 0.44 days */ + 41055, /* 11.40 hours, 0.48 days */ + 43894, /* 12.19 hours, 0.51 days */ + 46929, /* 13.04 hours, 0.54 days */ + 50174, /* 13.94 hours, 0.58 days */ + 53643, /* 14.90 hours, 0.62 days */ + 57352, /* 15.93 hours, 0.66 days */ + 61318, /* 17.03 hours, 0.71 days */ + 65558, /* 18.21 hours, 0.76 days */ + 70091, /* 19.47 hours, 0.81 days */ + 74937, /* 20.82 hours, 0.87 days */ + 80119, /* 22.26 hours, 0.93 days */ + 85658, /* 23.79 hours, 0.99 days */ + 91581, /* 25.44 hours, 1.06 days */ + 97914, /* 27.20 hours, 1.13 days */ + 104684, /* 29.08 hours, 1.21 days */ + 111922, /* 31.09 hours, 1.30 days */ + 119661, /* 33.24 hours, 1.38 days */ + 127935, /* 35.54 hours, 1.48 days */ + 136781, /* 37.99 hours, 1.58 days */ + 146239, /* 40.62 hours, 1.69 days */ + 156350, /* 43.43 hours, 1.81 days */ + 167161, /* 46.43 hours, 1.93 days */ + 178720, /* 49.64 hours, 2.07 days */ + 191077, /* 53.08 hours, 2.21 days */ + 204289, /* 56.75 hours, 2.36 days */ + 218415, /* 60.67 hours, 2.53 days */ + 233517, /* 64.87 hours, 2.70 days */ + 249664, /* 69.35 hours, 2.89 days */ + 266926, /* 74.15 hours, 3.09 days */ + 285383, /* 79.27 hours, 3.30 days */ + 305116, /* 84.75 hours, 3.53 days */ + 326213, /* 90.61 hours, 3.78 days */ + 348769, /* 96.88 hours, 4.04 days */ + 372885, /* 103.58 hours, 4.32 days */ + 398668, /* 110.74 hours, 4.61 days */ + 426234, /* 118.40 hours, 4.93 days */ + 455705, /* 126.58 hours, 5.27 days */ + 487215, /* 135.34 hours, 5.64 days */ + 520904, /* 144.70 hours, 6.03 days */ + 556921, /* 154.70 hours, 6.45 days */ + 595430, /* 165.40 hours, 6.89 days */ + 636601, /* 176.83 hours, 7.37 days */ + 680618, /* 189.06 hours, 7.88 days */ + 727680, /* 202.13 hours, 8.42 days */ + 777995, /* 216.11 hours, 9.00 days */ + 831789, /* 231.05 hours, 9.63 days */ + 889303, /* 247.03 hours, 10.29 days */ + 950794, /* 264.11 hours, 11.00 days */ + 1016537, /* 282.37 hours, 11.77 days */ + 1086825, /* 301.90 hours, 12.58 days */ + 1161973, /* 322.77 hours, 13.45 days */ + 1242318, /* 345.09 hours, 14.38 days */ + 1328218, /* 368.95 hours, 15.37 days */ + 1420057, /* 394.46 hours, 16.44 days */ + 1518247, /* 421.74 hours, 17.57 days */ + 1623226, /* 450.90 hours, 18.79 days */ + 1735464, /* 482.07 hours, 20.09 days */ + 1855462, /* 515.41 hours, 21.48 days */ + 1983758, /* 551.04 hours, 22.96 days */ + 2120925, /* 589.15 hours, 24.55 days */ + 2267576, /* 629.88 hours, 26.25 days */ + 2424367, /* 673.44 hours, 28.06 days */ + 2592000}; /* 720.00 hours, 30.00 days */ + + +#ifndef NEVERDATE +#define NEVERDATE 0xffffffff +#endif + + +afs_uint32 +life_to_time(afs_uint32 start, int life_) +{ + int realLife; + + if (life_ == TKTLIFENOEXPIRE) return NEVERDATE; + if (life_ < TKTLIFEMINFIXED) return start + life_*5*60; + if (life_ > TKTLIFEMAXFIXED) return start + MAXTKTLIFETIME; + realLife = tkt_lifetimes[life_ - TKTLIFEMINFIXED]; + return start + realLife; +} + +int +time_to_life(afs_uint32 start, afs_uint32 end) +{ + int lifetime = end-start; + int best, best_i; + int i; + + if (end == NEVERDATE) return TKTLIFENOEXPIRE; + if ((lifetime > MAXKTCTICKETLIFETIME) || (lifetime <= 0)) return 0; + if (lifetime < tkt_lifetimes[0]) return (lifetime + 5*60-1) / (5*60); + best_i = -1; + best = MAXKTCTICKETLIFETIME; + for (i=0; i= lifetime) { + int diff = tkt_lifetimes[i]-lifetime; + if (diff < best) { + best = diff; + best_i = i; + }} + if (best_i < 0) return 0; + return best_i+TKTLIFEMINFIXED; +} + +/* function returns: + * + * -2 if zero or negative lifetime, or start time is more than now plus time + * uncertainty plus max ticket lifetime, or if there is an end time, it's + * before now minus uncertainty, the start time is non-zero, and now minus + * the start time is greater than the max ticket lifetime plus 24 hours + * + * -1 if there is an end time, it's before now minus uncertainty, and the + * start time is not non-zero or now minus the start time is not greater + * than the max ticket lifetime plus 24 hours + * + * 0 if the times are consistent (not covered by above) but start time is + * less than now plus uncertainty + * + * 1 if the start time is in the past and the end time is infinity. + * + * 2 if the start time is past and the end time is in the future + * and the lifetime is within the legal limit. + */ + +int +tkt_CheckTimes(afs_uint32 begin, afs_uint32 end, afs_uint32 now) +{ + if (end <= begin + || begin > now + KTC_TIME_UNCERTAINTY + MAXKTCTICKETLIFETIME + || (end + && end < now - KTC_TIME_UNCERTAINTY + && now - begin > MAXKTCTICKETLIFETIME + MAXKTCTICKETLIFETIME)) + return -2; + if (end + && end < now - KTC_TIME_UNCERTAINTY + && (begin == 0 || now - begin <= 2 * MAXKTCTICKETLIFETIME)) + return -1; + if (begin < now + KTC_TIME_UNCERTAINTY) + return 0; + if (begin < now && end == 0) + return 1; + if (begin < now + && end > now + && (end - begin) < MAXKTCTICKETLIFETIME) + return 2; + return 2; +} + +#define getstr(name,min) \ + slen = strlen(ticket); \ + if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \ + strcpy (name, ticket); \ + ticket += slen+1 + + +static int +decode_athena_ticket (ticket, ticketLen, name, inst, realm, + host, sessionKey, start, end) + char *ticket; + int ticketLen; + char *name; + char *inst; + char *realm; + afs_int32 *host; + struct ktc_encryptionKey *sessionKey; + afs_uint32 *start; + afs_uint32 *end; +{ + char *ticketBeg = ticket; + char flags; + int slen; + int tlen; + unsigned char lifetime; + char sname[MAXKTCNAMELEN]; /* these aren't used, */ + char sinst[MAXKTCNAMELEN]; /* but are in the ticket */ + + flags = *ticket++; + getstr (name, 1); + getstr (inst, 0); + getstr (realm, 0); + + memcpy(host, ticket, sizeof (*host)); + ticket += sizeof(*host); + *host = ktohl (flags, *host); + + memcpy(sessionKey, ticket, sizeof (struct ktc_encryptionKey)); + ticket += sizeof (struct ktc_encryptionKey); + + lifetime = *ticket++; + memcpy(start, ticket, sizeof (*start)); + ticket += sizeof(*start); + *start = ktohl (flags, *start); + *end = life_to_time (*start, lifetime); + + /* XXX check sname, sinst */ + getstr (sname, 1); + getstr (sinst, 0); + + tlen = ticket - ticketBeg; + + if ((round_up_to_ebs(tlen) != ticketLen) && (ticketLen != 56)) + return -1; + return 0; +} + +int +decomp_ticket(char *data, + int length, + char *pname, + char *pinstance, + char *prealm, + afs_int32 *paddress, + unsigned char *session, + afs_int32 *start, + afs_int32 *end, + struct ktc_encryptionKey *key, + des_key_schedule schedule) +{ + int ret; + char clear_ticket[MAXKTCTICKETLEN], *ticket; + + if (length > MAXKTCTICKETLEN) + length = MAXKTCTICKETLEN; + + if (key_sched (key, schedule)) + return RXKADBADKEY; + ticket = clear_ticket; + + pcbc_encrypt (data, ticket, length, schedule, key, DECRYPT); + + ret = decode_athena_ticket (ticket, length, pname, pinstance, + prealm, paddress, session, + start, end); + + return ret; +} + +#define putstr(name,min) \ + slen = strlen(name); \ + if ((slen < min) || (slen >= MAXKTCNAMELEN)) return -1; \ + strcpy (ticket, name); \ + ticket += slen+1 +#define putint(num) num = htonl(num);\ + memcpy(ticket, &num, sizeof(num));\ + ticket += sizeof(num) + +static int +assemble_athena_ticket(ticket, ticketLen, name, inst, realm, + host, sessionKey, start, end, sname, sinst) + char *ticket; + int *ticketLen; + char *name; + char *inst; + char *realm; + afs_int32 host; + struct ktc_encryptionKey *sessionKey; + afs_uint32 start; + afs_uint32 end; + char *sname; + char *sinst; +{ char *ticketBeg = ticket; + int slen; + unsigned char life; + + *ticket++ = 0; /* flags, always send net-byte-order */ + putstr (name, 1); + putstr (inst, 0); + putstr (realm, 0); + putint (host); + + memcpy(ticket, sessionKey, sizeof(struct ktc_encryptionKey)); + ticket += sizeof(struct ktc_encryptionKey); + + life = time_to_life (start, end); + if (life == 0) return -1; + *ticket++ = life; + + putint (start); + putstr (sname, 1); + putstr (sinst, 0); + + *ticketLen = ticket - ticketBeg; + return 0; +} + +int tkt_MakeTicket (ticket, ticketLen, key, name, inst, cell, + start, end, sessionKey, host, sname, sinst) + char *ticket; /* ticket is constructed here */ + int *ticketLen; /* output length of finished ticket */ + struct ktc_encryptionKey *key; /* key ticket should be sealed with */ + char *name; /* user of this ticket */ + char *inst; + char *cell; /* cell of authentication */ + afs_uint32 start,end; /* life of ticket */ + struct ktc_encryptionKey *sessionKey; /* session key invented for ticket */ + afs_uint32 host; /* caller's host address */ + char *sname; /* server */ + char *sinst; +{ + int code; + des_key_schedule schedule; + + *ticketLen = 0; /* in case we return early */ + + code = assemble_athena_ticket (ticket, ticketLen, name, inst, cell, + host, sessionKey, start, end, sname, sinst); + + *ticketLen = round_up_to_ebs(*ticketLen); /* round up */ + if (code) + return -1; + + /* encrypt ticket */ + if (code = key_sched (key, schedule)) + return RXKADBADKEY; + + pcbc_encrypt (ticket, ticket, *ticketLen, schedule, key, ENCRYPT); + return 0; +} + +int +tkt_DecodeTicket (ticket, ticketLen, key, + name, inst, cell, sessionKey, host, start, end) + char *ticket; + afs_int32 ticketLen; + struct ktc_encryptionKey *key; + char *name; + char *inst; + char *cell; + char *sessionKey; + afs_int32 *host; + afs_int32 *start; + afs_int32 *end; +{ + des_key_schedule schedule; + int code; + + if (ticketLen == 0) + return RXKADBADTICKET; /* no ticket */ + if ((ticketLen < MINKTCTICKETLEN) || /* minimum legal ticket size */ + ((ticketLen) % 8 != 0)) /* enc. part must be (0 mod 8) bytes */ + return RXKADBADTICKET; + + code = decomp_ticket(ticket, ticketLen, name, inst, cell, + host, sessionKey, start, end, key, schedule); + + if (code) + return RXKADBADTICKET; + + if (tkt_CheckTimes (*start, *end, time(0)) < -1) + return RXKADBADTICKET; + + return 0; +} + +afs_int32 +ktohl(char flags, afs_int32 l) +{ + if (flags & 1) { + unsigned char *lp = (unsigned char *)&l; + afs_int32 hl; + hl = *lp + (*(lp+1) << 8) + (*(lp+2) << 16) + (*(lp+3) << 24); + return hl; + } + return ntohl(l); +} diff --git a/src/rxkad/v5.c b/src/rxkad/v5.c new file mode 100644 index 0000000000..8b2a6671f5 --- /dev/null +++ b/src/rxkad/v5.c @@ -0,0 +1,355 @@ +/* + * Copyright (c) 1995, 1996, 1997, 2002 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + +#include "rxkad_locl.h" +/* RCSID("$Id$"); */ + +/* + * This code depends on heimdal's asn1_compile generated krb5 decoding + * stuff. The code is orignally from rxkad that Björn Grönvall + * for kth-krb and was included in Arla. + * + * The first file, v5der.c are part for of support functions + * that all generated files depends on. + * + * The second file (v5gen.h) is the headerfile that is generated for + * the decoding functions. + * + * The third file (v5gen.c) is the subset of the genrated functions we + * need to decode the authenticator. + * + * All files are modified to build within OpenAFS enviroment without + * any external dependencies. Below is the shellscript that is used to + * import the code into the four files. + * + * All internal symbols are rewritten to _rxkad_v5_. + */ + +#if 0 + +(cd /home/lha/src/cvs/heimdal-spnego2/lib/asn1 ; \ + echo '#include "asn1_err.h"'; + echo '#include '; + cat der_get.c \ + der_put.c \ + der_free.c \ + der_length.c \ + der_copy.c \ + ) \ +| grep -v 'include "der_locl.h"' \ +| grep -v 'include ' \ +| sed 's!\(RCSID.*\)!/* \1 */!' \ +| sed 's!$Id$Heimdal:!' \ +| cat > /sources/afs/openafs-krb5/src/rxkad/v5der.c + +grep -v 'struct units' \ + /home/lha/src/cvs/heimdal-spnego2/obj/lib/asn1/krb5_asn1.h \ + > /sources/afs/openafs-krb5/src/rxkad/v5gen.h + +(cd /home/lha/src/cvs/heimdal-spnego2/obj/lib/asn1 ; \ + cat asn1_Ticket.c \ + asn1_EncryptedData.c \ + asn1_PrincipalName.c \ + asn1_HostAddresses.c \ + asn1_HostAddress.c \ + asn1_AuthorizationData.c \ + asn1_EncTicketPart.c \ + asn1_KerberosTime.c \ + asn1_TransitedEncoding.c \ + asn1_EncryptionKey.c \ + asn1_TicketFlags.c \ + asn1_Realm.c \ + asn1_ENCTYPE.c \ + asn1_NAME_TYPE.c \ + ) \ + | grep -v 'include ' \ + | grep -v 'include ' \ + | grep -v 'include ' \ + | perl \ + -e '$f=0; while(<>){$f=1 if(/struct units/);print if($f eq 0);$f=0 if(/^};/);}' \ + | cat > /sources/afs/openafs-krb5/src/rxkad/v5gen.c + +( \ + perl -p -e 's/^(encode_|decode_|free_|copy_|length_)([^(]*)\([^)]*\)\n$/#define $1$2 _rxkad_v5_$1$2\n/' /sources/afs/openafs-krb5/src/rxkad/v5gen.c ; \ + perl -p -e 's/^(der_|copy_|encode_|decode_|len_|length_|free_|fix_dce|time2generalizedtime)([^(]*).*/#define $1$2 _rxkad_v5_$1$2/' /sources/afs/openafs-krb5/src/rxkad/v5der.c ; \ + echo '#define TicketFlags2int _rxkad_v5_TicketFlags2int' ; \ + echo '#define int2TicketFlags _rxkad_v5_int2TicketFlags' ) \ + | grep _rxkad_v5 > /sources/afs/openafs-krb5/src/rxkad/v5gen-rewrite.h + + +: lha@nutcracker ; nm v5.o | grep T | grep -v _rxkad_v5 +00008924 T rxkad_decode_krb5_ticket + +#endif + +#include "v5gen-rewrite.h" +#include "asn1-common.h" +#include "der.h" +#include "v5gen.h" +#include "v5der.c" +#include "v5gen.c" + +static int +krb5_des_decrypt(struct ktc_encryptionKey *, + int, void *, size_t, void *, size_t *); + + +int +rxkad_decode_krb5_ticket(int (*get_key)(void *appl_data, + int kvno, + struct ktc_encryptionKey *key), + void *appl_data, + int serv_kvno, + char *ticket, + afs_int32 ticket_len, + /* OUT parms */ + struct ktc_encryptionKey *session_key, + afs_uint32 *expires, + struct ktc_principal *p, + afs_int32 *real_kvno) +{ + struct ktc_encryptionKey serv_key; /* Service's secret key */ + Ticket t5; /* Must free */ + EncTicketPart decr_part; /* Must free */ + char plain[MAXKTCTICKETLEN]; + int code; + size_t siz, plainsiz; + int v5_serv_kvno; + + assert(serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5 || + serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5_ENCPART_ONLY); + + memset(&t5, 0, sizeof(t5)); + memset(&decr_part, 0, sizeof(decr_part)); + + if (serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5) { + code = decode_Ticket(ticket, ticket_len, &t5, &siz); + if (code != 0) + goto cleanup; + + if (t5.tkt_vno != 5) + goto bad_ticket; + } else { + code = decode_EncryptedData(ticket, ticket_len, &t5.enc_part, &siz); + if (code != 0) + goto cleanup; + } + + /* Find the real service key version number */ + if (t5.enc_part.kvno == NULL) + goto bad_ticket; + v5_serv_kvno = *t5.enc_part.kvno; + if (real_kvno) *real_kvno = v5_serv_kvno; + + /* Check that the key type really fit into 8 bytes */ + switch (t5.enc_part.etype) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + break; + default: + goto unknown_key; + } + + /* Get the service key. We have to assume that the key type is of + * size 8 bytes or else we can't store service keys for both krb4 + * and krb5 in the same way in /usr/afs/etc/KeyFile. + */ + code = (*get_key)(appl_data, v5_serv_kvno, &serv_key); + if (code) + goto unknown_key; + + /* check ticket */ + if (t5.enc_part.cipher.length > sizeof(plain) || + t5.enc_part.cipher.length % 8 != 0) + goto bad_ticket; + + /* Decrypt data here, save in plain, assume it will shrink */ + code = krb5_des_decrypt(&serv_key, + t5.enc_part.etype, + t5.enc_part.cipher.data, + t5.enc_part.cipher.length, + plain, + &plainsiz); + if (code != 0) + goto bad_ticket; + + /* Decode ticket */ + code = decode_EncTicketPart(plain, plainsiz, &decr_part, &siz); + if (code != 0) + goto bad_ticket; + + /* Extract realm and principal */ + memset(p, 0x0, sizeof(*p)); + strncpy(p->cell, decr_part.crealm, MAXKTCNAMELEN - 1); + switch (decr_part.cname.name_string.len) { + case 2: + strncpy(p->instance, decr_part.cname.name_string.val[1], + MAXKTCNAMELEN - 1); + case 1: + strncpy(p->name, decr_part.cname.name_string.val[0], + MAXKTCNAMELEN - 1); + break; + default: + goto bad_ticket; + } + + /* Verify that decr_part.key is of right type */ + switch (decr_part.key.keytype) { + case ETYPE_DES_CBC_CRC: + case ETYPE_DES_CBC_MD4: + case ETYPE_DES_CBC_MD5: + break; + default: + goto bad_ticket; + } + + /* Extract session key */ + memcpy(session_key, decr_part.key.keyvalue.data, 8); + + /* Check lifetimes and host addresses, flags etc */ + { + time_t now = time(0); /* Use fast time package instead??? */ + time_t start = decr_part.authtime; + if (decr_part.starttime) + start = *decr_part.starttime; + if (start - now > KTC_TIME_UNCERTAINTY || decr_part.flags.invalid) + goto no_auth; + if (now > decr_part.endtime) + goto tkt_expired; + *expires = decr_part.endtime; + } + + cleanup: + if (serv_kvno == RXKAD_TKT_TYPE_KERBEROS_V5) + free_Ticket(&t5); + else + free_EncryptedData(&t5.enc_part); + free_EncTicketPart(&decr_part); + return code; + + unknown_key: + code = RXKADUNKNOWNKEY; + goto cleanup; + no_auth: + code = RXKADNOAUTH; + goto cleanup; + tkt_expired: + code = RXKADEXPIRED; + goto cleanup; + bad_ticket: + code = RXKADBADTICKET; + goto cleanup; + +} + +static int +verify_checksum_crc(void *data, size_t len, + void *cksum, size_t cksumsz, + struct ktc_encryptionKey *key) +{ + afs_uint32 crc; + char r[4]; + + assert(cksumsz == 4); + + _rxkad_crc_init_table (); + crc = _rxkad_crc_update (data, len, 0); + r[0] = crc & 0xff; + r[1] = (crc >> 8) & 0xff; + r[2] = (crc >> 16) & 0xff; + r[3] = (crc >> 24) & 0xff; + + if (memcmp(cksum, r, 4) != 0) + return 1; + return 0; +} + + +static int +krb5_des_decrypt(struct ktc_encryptionKey *key, + int etype, + void *in, size_t insz, + void *out, size_t *outsz) +{ + int (*cksum_func)(void *,size_t,void *,size_t,struct ktc_encryptionKey *); + des_cblock ivec; + des_key_schedule s; + char cksum[24]; + size_t cksumsz; + int ret; + + cksum_func = NULL; + + assert(insz % 8 == 0); + + des_key_sched(key, &s); + +#define CONFOUNDERSZ 8 + + switch (etype) { + case ETYPE_DES_CBC_CRC: + memcpy(&ivec, key, sizeof(ivec)); + cksumsz = 4; + cksum_func = verify_checksum_crc; + break; + case ETYPE_DES_CBC_MD4: + memset(&ivec, 0, sizeof(ivec)); + cksumsz = 16; + /* FIXME: cksum_func = verify_checksum_md4 */; + break; + case ETYPE_DES_CBC_MD5: + memset(&ivec, 0, sizeof(ivec)); + cksumsz = 16; + /* FIXME: cksum_func = verify_checksum_md5 */; + break; + default: + abort(); + } + assert(cksumsz <= sizeof(cksum)); + + ret = des_cbc_encrypt(in, out, insz, s, &ivec, 0); + if (ret) + return ret; + + memcpy(cksum, (char *)out + CONFOUNDERSZ, cksumsz); + memset((char *)out + CONFOUNDERSZ, 0, cksumsz); + + if (cksum_func) + ret = (*cksum_func)(out, insz, cksum, cksumsz, key); + + *outsz = insz - CONFOUNDERSZ - cksumsz; + memmove(out, (char *)out + CONFOUNDERSZ + cksumsz, *outsz); + + return ret; +} diff --git a/src/rxkad/v5der.c b/src/rxkad/v5der.c new file mode 100644 index 0000000000..5060259b2b --- /dev/null +++ b/src/rxkad/v5der.c @@ -0,0 +1,1168 @@ +#include "asn1_err.h" +#include +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + + +/* RCSID("$Heimdal: der_get.c,v 1.31 2001/09/28 22:53:24 assar Exp $"); */ + + +/* + * All decoding functions take a pointer `p' to first position in + * which to read, from the left, `len' which means the maximum number + * of characters we are able to read, `ret' were the value will be + * returned and `size' where the number of used bytes is stored. + * Either 0 or an error code is returned. + */ + +static int +der_get_unsigned (const unsigned char *p, size_t len, + unsigned *ret, size_t *size) +{ + unsigned val = 0; + size_t oldlen = len; + + while (len--) + val = val * 256 + *p++; + *ret = val; + if(size) *size = oldlen; + return 0; +} + +int +der_get_int (const unsigned char *p, size_t len, + int *ret, size_t *size) +{ + int val = 0; + size_t oldlen = len; + + if (len--) + val = (signed char)*p++; + while (len--) + val = val * 256 + *p++; + *ret = val; + if(size) *size = oldlen; + return 0; +} + +int +der_get_length (const unsigned char *p, size_t len, + size_t *val, size_t *size) +{ + size_t v; + + if (len <= 0) + return ASN1_OVERRUN; + --len; + v = *p++; + if (v < 128) { + *val = v; + if(size) *size = 1; + } else { + int e; + size_t l; + unsigned tmp; + + if(v == 0x80){ + *val = ASN1_INDEFINITE; + if(size) *size = 1; + return 0; + } + v &= 0x7F; + if (len < v) + return ASN1_OVERRUN; + e = der_get_unsigned (p, v, &tmp, &l); + if(e) return e; + *val = tmp; + if(size) *size = l + 1; + } + return 0; +} + +int +der_get_general_string (const unsigned char *p, size_t len, + general_string *str, size_t *size) +{ + char *s; + + s = malloc (len + 1); + if (s == NULL) + return ENOMEM; + memcpy (s, p, len); + s[len] = '\0'; + *str = s; + if(size) *size = len; + return 0; +} + +int +der_get_octet_string (const unsigned char *p, size_t len, + octet_string *data, size_t *size) +{ + data->length = len; + data->data = malloc(len); + if (data->data == NULL && data->length != 0) + return ENOMEM; + memcpy (data->data, p, len); + if(size) *size = len; + return 0; +} + +int +der_get_oid (const unsigned char *p, size_t len, + oid *data, size_t *size) +{ + int n; + size_t oldlen = len; + + if (len < 1) + return ASN1_OVERRUN; + + data->components = malloc(len * sizeof(*data->components)); + if (data->components == NULL && len != 0) + return ENOMEM; + data->components[0] = (*p) / 40; + data->components[1] = (*p) % 40; + --len; + ++p; + for (n = 2; len > 0; ++n) { + unsigned u = 0; + + do { + --len; + u = u * 128 + (*p++ % 128); + } while (len > 0 && p[-1] & 0x80); + data->components[n] = u; + } + if (p[-1] & 0x80) { + free_oid (data); + return ASN1_OVERRUN; + } + data->length = n; + if (size) + *size = oldlen; + return 0; +} + +int +der_get_tag (const unsigned char *p, size_t len, + Der_class *class, Der_type *type, + int *tag, size_t *size) +{ + if (len < 1) + return ASN1_OVERRUN; + *class = (Der_class)(((*p) >> 6) & 0x03); + *type = (Der_type)(((*p) >> 5) & 0x01); + *tag = (*p) & 0x1F; + if(size) *size = 1; + return 0; +} + +int +der_match_tag (const unsigned char *p, size_t len, + Der_class class, Der_type type, + int tag, size_t *size) +{ + size_t l; + Der_class thisclass; + Der_type thistype; + int thistag; + int e; + + e = der_get_tag (p, len, &thisclass, &thistype, &thistag, &l); + if (e) return e; + if (class != thisclass || type != thistype) + return ASN1_BAD_ID; + if(tag > thistag) + return ASN1_MISPLACED_FIELD; + if(tag < thistag) + return ASN1_MISSING_FIELD; + if(size) *size = l; + return 0; +} + +int +der_match_tag_and_length (const unsigned char *p, size_t len, + Der_class class, Der_type type, int tag, + size_t *length_ret, size_t *size) +{ + size_t l, ret = 0; + int e; + + e = der_match_tag (p, len, class, type, tag, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_length (p, len, length_ret, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +int +decode_integer (const unsigned char *p, size_t len, + int *num, size_t *size) +{ + size_t ret = 0; + size_t l, reallen; + int e; + + e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_length (p, len, &reallen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_int (p, reallen, num, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +int +decode_unsigned (const unsigned char *p, size_t len, + unsigned *num, size_t *size) +{ + size_t ret = 0; + size_t l, reallen; + int e; + + e = der_match_tag (p, len, UNIV, PRIM, UT_Integer, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_length (p, len, &reallen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_unsigned (p, reallen, num, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +int +decode_enumerated (const unsigned char *p, size_t len, + unsigned *num, size_t *size) +{ + size_t ret = 0; + size_t l, reallen; + int e; + + e = der_match_tag (p, len, UNIV, PRIM, UT_Enumerated, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_length (p, len, &reallen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + e = der_get_int (p, reallen, num, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +int +decode_general_string (const unsigned char *p, size_t len, + general_string *str, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + size_t slen; + + e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralString, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + + e = der_get_length (p, len, &slen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if (len < slen) + return ASN1_OVERRUN; + + e = der_get_general_string (p, slen, str, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +int +decode_octet_string (const unsigned char *p, size_t len, + octet_string *k, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + size_t slen; + + e = der_match_tag (p, len, UNIV, PRIM, UT_OctetString, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + + e = der_get_length (p, len, &slen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if (len < slen) + return ASN1_OVERRUN; + + e = der_get_octet_string (p, slen, k, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +int +decode_oid (const unsigned char *p, size_t len, + oid *k, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + size_t slen; + + e = der_match_tag (p, len, UNIV, PRIM, UT_OID, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + + e = der_get_length (p, len, &slen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if (len < slen) + return ASN1_OVERRUN; + + e = der_get_oid (p, slen, k, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if(size) *size = ret; + return 0; +} + +static void +generalizedtime2time (const char *s, time_t *t) +{ + struct tm tm; + + memset(&tm, 0, sizeof(tm)); + sscanf (s, "%04d%02d%02d%02d%02d%02dZ", + &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, + &tm.tm_min, &tm.tm_sec); + tm.tm_year -= 1900; + tm.tm_mon -= 1; + *t = timegm (&tm); +} + +int +decode_generalized_time (const unsigned char *p, size_t len, + time_t *t, size_t *size) +{ + octet_string k; + char *times; + size_t ret = 0; + size_t l; + int e; + size_t slen; + + e = der_match_tag (p, len, UNIV, PRIM, UT_GeneralizedTime, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + + e = der_get_length (p, len, &slen, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + if (len < slen) + return ASN1_OVERRUN; + e = der_get_octet_string (p, slen, &k, &l); + if (e) return e; + p += l; + len -= l; + ret += l; + times = realloc(k.data, k.length + 1); + if (times == NULL){ + free(k.data); + return ENOMEM; + } + times[k.length] = 0; + generalizedtime2time (times, t); + free (times); + if(size) *size = ret; + return 0; +} + + +int +fix_dce(size_t reallen, size_t *len) +{ + if(reallen == ASN1_INDEFINITE) + return 1; + if(*len < reallen) + return -1; + *len = reallen; + return 0; +} +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + + +/* RCSID("$Heimdal: der_put.c,v 1.27 2001/09/25 23:37:25 assar Exp $"); */ + +/* + * All encoding functions take a pointer `p' to first position in + * which to write, from the right, `len' which means the maximum + * number of characters we are able to write. The function returns + * the number of characters written in `size' (if non-NULL). + * The return value is 0 or an error. + */ + +static int +der_put_unsigned (unsigned char *p, size_t len, unsigned val, size_t *size) +{ + unsigned char *base = p; + + if (val) { + while (len > 0 && val) { + *p-- = val % 256; + val /= 256; + --len; + } + if (val != 0) + return ASN1_OVERFLOW; + else { + *size = base - p; + return 0; + } + } else if (len < 1) + return ASN1_OVERFLOW; + else { + *p = 0; + *size = 1; + return 0; + } +} + +int +der_put_int (unsigned char *p, size_t len, int val, size_t *size) +{ + unsigned char *base = p; + + if(val >= 0) { + do { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = val % 256; + len--; + val /= 256; + } while(val); + if(p[1] >= 128) { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = 0; + len--; + } + } else { + val = ~val; + do { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = ~(val % 256); + len--; + val /= 256; + } while(val); + if(p[1] < 128) { + if(len < 1) + return ASN1_OVERFLOW; + *p-- = 0xff; + len--; + } + } + *size = base - p; + return 0; +} + + +int +der_put_length (unsigned char *p, size_t len, size_t val, size_t *size) +{ + if (len < 1) + return ASN1_OVERFLOW; + if (val < 128) { + *p = val; + *size = 1; + return 0; + } else { + size_t l; + int e; + + e = der_put_unsigned (p, len - 1, val, &l); + if (e) + return e; + p -= l; + *p = 0x80 | l; + *size = l + 1; + return 0; + } +} + +int +der_put_general_string (unsigned char *p, size_t len, + const general_string *str, size_t *size) +{ + size_t slen = strlen(*str); + + if (len < slen) + return ASN1_OVERFLOW; + p -= slen; + len -= slen; + memcpy (p+1, *str, slen); + *size = slen; + return 0; +} + +int +der_put_octet_string (unsigned char *p, size_t len, + const octet_string *data, size_t *size) +{ + if (len < data->length) + return ASN1_OVERFLOW; + p -= data->length; + len -= data->length; + memcpy (p+1, data->data, data->length); + *size = data->length; + return 0; +} + +int +der_put_oid (unsigned char *p, size_t len, + const oid *data, size_t *size) +{ + unsigned char *base = p; + int n; + + for (n = data->length - 1; n >= 2; --n) { + unsigned u = data->components[n]; + + if (len < 1) + return ASN1_OVERFLOW; + *p-- = u % 128; + u /= 128; + --len; + while (u > 0) { + if (len < 1) + return ASN1_OVERFLOW; + *p-- = 128 + u % 128; + u /= 128; + --len; + } + } + if (len < 1) + return ASN1_OVERFLOW; + *p-- = 40 * data->components[0] + data->components[1]; + *size = base - p; + return 0; +} + +int +der_put_tag (unsigned char *p, size_t len, Der_class class, Der_type type, + int tag, size_t *size) +{ + if (len < 1) + return ASN1_OVERFLOW; + *p = (class << 6) | (type << 5) | tag; /* XXX */ + *size = 1; + return 0; +} + +int +der_put_length_and_tag (unsigned char *p, size_t len, size_t len_val, + Der_class class, Der_type type, int tag, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + + e = der_put_length (p, len, len_val, &l); + if(e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_tag (p, len, class, type, tag, &l); + if(e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +encode_integer (unsigned char *p, size_t len, const int *data, size_t *size) +{ + int num = *data; + size_t ret = 0; + size_t l; + int e; + + e = der_put_int (p, len, num, &l); + if(e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Integer, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +encode_unsigned (unsigned char *p, size_t len, const unsigned *data, + size_t *size) +{ + unsigned num = *data; + size_t ret = 0; + size_t l; + int e; + + e = der_put_unsigned (p, len, num, &l); + if(e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Integer, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +encode_enumerated (unsigned char *p, size_t len, const unsigned *data, + size_t *size) +{ + unsigned num = *data; + size_t ret = 0; + size_t l; + int e; + + e = der_put_int (p, len, num, &l); + if(e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_Enumerated, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +encode_general_string (unsigned char *p, size_t len, + const general_string *data, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + + e = der_put_general_string (p, len, data, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_GeneralString, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +encode_octet_string (unsigned char *p, size_t len, + const octet_string *k, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + + e = der_put_octet_string (p, len, k, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_OctetString, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +encode_oid(unsigned char *p, size_t len, + const oid *k, size_t *size) +{ + size_t ret = 0; + size_t l; + int e; + + e = der_put_oid (p, len, k, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, l, UNIV, PRIM, UT_OID, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} + +int +time2generalizedtime (time_t t, octet_string *s) +{ + struct tm *tm; + + s->data = malloc(16); + if (s->data == NULL) + return ENOMEM; + s->length = 15; + tm = gmtime (&t); + sprintf (s->data, "%04d%02d%02d%02d%02d%02dZ", tm->tm_year + 1900, + tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, + tm->tm_sec); + return 0; +} + +int +encode_generalized_time (unsigned char *p, size_t len, + const time_t *t, size_t *size) +{ + size_t ret = 0; + size_t l; + octet_string k; + int e; + + e = time2generalizedtime (*t, &k); + if (e) + return e; + e = der_put_octet_string (p, len, &k, &l); + free (k.data); + if (e) + return e; + p -= l; + len -= l; + ret += l; + e = der_put_length_and_tag (p, len, k.length, UNIV, PRIM, + UT_GeneralizedTime, &l); + if (e) + return e; + p -= l; + len -= l; + ret += l; + *size = ret; + return 0; +} +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + + +/* RCSID("$Heimdal: der_free.c,v 1.8 2001/09/25 13:39:26 assar Exp $"); */ + +void +free_general_string (general_string *str) +{ + free(*str); +} + +void +free_octet_string (octet_string *k) +{ + free(k->data); +} + +void +free_oid (oid *k) +{ + free(k->components); +} +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + + +/* RCSID("$Heimdal: der_length.c,v 1.12 2001/09/25 13:39:26 assar Exp $"); */ + +static size_t +len_unsigned (unsigned val) +{ + size_t ret = 0; + + do { + ++ret; + val /= 256; + } while (val); + return ret; +} + +static size_t +len_int (int val) +{ + size_t ret = 0; + + if (val == 0) + return 1; + while (val > 255 || val < -255) { + ++ret; + val /= 256; + } + if (val != 0) { + ++ret; + if ((signed char)val != val) + ++ret; + val /= 256; + } + return ret; +} + +static size_t +len_oid (const oid *oid) +{ + size_t ret = 1; + int n; + + for (n = 2; n < oid->length; ++n) { + unsigned u = oid->components[n]; + + ++ret; + u /= 128; + while (u > 0) { + ++ret; + u /= 128; + } + } + return ret; +} + +size_t +length_len (size_t len) +{ + if (len < 128) + return 1; + else + return len_unsigned (len) + 1; +} + +size_t +length_integer (const int *data) +{ + size_t len = len_int (*data); + + return 1 + length_len(len) + len; +} + +size_t +length_unsigned (const unsigned *data) +{ + size_t len = len_unsigned (*data); + + return 1 + length_len(len) + len; +} + +size_t +length_enumerated (const unsigned *data) +{ + size_t len = len_int (*data); + + return 1 + length_len(len) + len; +} + +size_t +length_general_string (const general_string *data) +{ + char *str = *data; + size_t len = strlen(str); + return 1 + length_len(len) + len; +} + +size_t +length_octet_string (const octet_string *k) +{ + return 1 + length_len(k->length) + k->length; +} + +size_t +length_oid (const oid *k) +{ + size_t len = len_oid (k); + + return 1 + length_len(len) + len; +} + +size_t +length_generalized_time (const time_t *t) +{ + octet_string k; + size_t ret; + + time2generalizedtime (*t, &k); + ret = 1 + length_len(k.length) + k.length; + free (k.data); + return ret; +} +/* + * Copyright (c) 1997 - 2001 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * 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. Neither the name of the Institute 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 INSTITUTE 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 INSTITUTE 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. + */ + + +/* RCSID("$Heimdal: der_copy.c,v 1.9 2001/09/25 13:39:25 assar Exp $"); */ + +int +copy_general_string (const general_string *from, general_string *to) +{ + *to = malloc(strlen(*from) + 1); + if(*to == NULL) + return ENOMEM; + strcpy(*to, *from); + return 0; +} + +int +copy_octet_string (const octet_string *from, octet_string *to) +{ + to->length = from->length; + to->data = malloc(to->length); + if(to->length != 0 && to->data == NULL) + return ENOMEM; + memcpy(to->data, from->data, to->length); + return 0; +} + +int +copy_oid (const oid *from, oid *to) +{ + to->length = from->length; + to->components = malloc(to->length * sizeof(*to->components)); + if (to->length != 0 && to->components == NULL) + return ENOMEM; + memcpy(to->components, from->components, to->length); + return 0; +} diff --git a/src/rxkad/v5gen-rewrite.h b/src/rxkad/v5gen-rewrite.h new file mode 100644 index 0000000000..97ad9707fa --- /dev/null +++ b/src/rxkad/v5gen-rewrite.h @@ -0,0 +1,122 @@ +#define encode_Ticket _rxkad_v5_encode_Ticket +#define decode_Ticket _rxkad_v5_decode_Ticket +#define free_Ticket _rxkad_v5_free_Ticket +#define length_Ticket _rxkad_v5_length_Ticket +#define copy_Ticket _rxkad_v5_copy_Ticket +#define encode_EncryptedData _rxkad_v5_encode_EncryptedData +#define decode_EncryptedData _rxkad_v5_decode_EncryptedData +#define free_EncryptedData _rxkad_v5_free_EncryptedData +#define length_EncryptedData _rxkad_v5_length_EncryptedData +#define copy_EncryptedData _rxkad_v5_copy_EncryptedData +#define encode_PrincipalName _rxkad_v5_encode_PrincipalName +#define decode_PrincipalName _rxkad_v5_decode_PrincipalName +#define free_PrincipalName _rxkad_v5_free_PrincipalName +#define length_PrincipalName _rxkad_v5_length_PrincipalName +#define copy_PrincipalName _rxkad_v5_copy_PrincipalName +#define encode_HostAddresses _rxkad_v5_encode_HostAddresses +#define decode_HostAddresses _rxkad_v5_decode_HostAddresses +#define free_HostAddresses _rxkad_v5_free_HostAddresses +#define length_HostAddresses _rxkad_v5_length_HostAddresses +#define copy_HostAddresses _rxkad_v5_copy_HostAddresses +#define encode_HostAddress _rxkad_v5_encode_HostAddress +#define decode_HostAddress _rxkad_v5_decode_HostAddress +#define free_HostAddress _rxkad_v5_free_HostAddress +#define length_HostAddress _rxkad_v5_length_HostAddress +#define copy_HostAddress _rxkad_v5_copy_HostAddress +#define encode_AuthorizationData _rxkad_v5_encode_AuthorizationData +#define decode_AuthorizationData _rxkad_v5_decode_AuthorizationData +#define free_AuthorizationData _rxkad_v5_free_AuthorizationData +#define length_AuthorizationData _rxkad_v5_length_AuthorizationData +#define copy_AuthorizationData _rxkad_v5_copy_AuthorizationData +#define encode_EncTicketPart _rxkad_v5_encode_EncTicketPart +#define decode_EncTicketPart _rxkad_v5_decode_EncTicketPart +#define free_EncTicketPart _rxkad_v5_free_EncTicketPart +#define length_EncTicketPart _rxkad_v5_length_EncTicketPart +#define copy_EncTicketPart _rxkad_v5_copy_EncTicketPart +#define encode_KerberosTime _rxkad_v5_encode_KerberosTime +#define decode_KerberosTime _rxkad_v5_decode_KerberosTime +#define free_KerberosTime _rxkad_v5_free_KerberosTime +#define length_KerberosTime _rxkad_v5_length_KerberosTime +#define copy_KerberosTime _rxkad_v5_copy_KerberosTime +#define encode_TransitedEncoding _rxkad_v5_encode_TransitedEncoding +#define decode_TransitedEncoding _rxkad_v5_decode_TransitedEncoding +#define free_TransitedEncoding _rxkad_v5_free_TransitedEncoding +#define length_TransitedEncoding _rxkad_v5_length_TransitedEncoding +#define copy_TransitedEncoding _rxkad_v5_copy_TransitedEncoding +#define encode_EncryptionKey _rxkad_v5_encode_EncryptionKey +#define decode_EncryptionKey _rxkad_v5_decode_EncryptionKey +#define free_EncryptionKey _rxkad_v5_free_EncryptionKey +#define length_EncryptionKey _rxkad_v5_length_EncryptionKey +#define copy_EncryptionKey _rxkad_v5_copy_EncryptionKey +#define encode_TicketFlags _rxkad_v5_encode_TicketFlags +#define decode_TicketFlags _rxkad_v5_decode_TicketFlags +#define free_TicketFlags _rxkad_v5_free_TicketFlags +#define length_TicketFlags _rxkad_v5_length_TicketFlags +#define copy_TicketFlags _rxkad_v5_copy_TicketFlags +#define encode_Realm _rxkad_v5_encode_Realm +#define decode_Realm _rxkad_v5_decode_Realm +#define free_Realm _rxkad_v5_free_Realm +#define length_Realm _rxkad_v5_length_Realm +#define copy_Realm _rxkad_v5_copy_Realm +#define encode_ENCTYPE _rxkad_v5_encode_ENCTYPE +#define decode_ENCTYPE _rxkad_v5_decode_ENCTYPE +#define free_ENCTYPE _rxkad_v5_free_ENCTYPE +#define length_ENCTYPE _rxkad_v5_length_ENCTYPE +#define copy_ENCTYPE _rxkad_v5_copy_ENCTYPE +#define encode_NAME_TYPE _rxkad_v5_encode_NAME_TYPE +#define decode_NAME_TYPE _rxkad_v5_decode_NAME_TYPE +#define free_NAME_TYPE _rxkad_v5_free_NAME_TYPE +#define length_NAME_TYPE _rxkad_v5_length_NAME_TYPE +#define copy_NAME_TYPE _rxkad_v5_copy_NAME_TYPE +#define der_get_unsigned _rxkad_v5_der_get_unsigned +#define der_get_int _rxkad_v5_der_get_int +#define der_get_length _rxkad_v5_der_get_length +#define der_get_general_string _rxkad_v5_der_get_general_string +#define der_get_octet_string _rxkad_v5_der_get_octet_string +#define der_get_oid _rxkad_v5_der_get_oid +#define der_get_tag _rxkad_v5_der_get_tag +#define der_match_tag _rxkad_v5_der_match_tag +#define der_match_tag_and_length _rxkad_v5_der_match_tag_and_length +#define decode_integer _rxkad_v5_decode_integer +#define decode_unsigned _rxkad_v5_decode_unsigned +#define decode_enumerated _rxkad_v5_decode_enumerated +#define decode_general_string _rxkad_v5_decode_general_string +#define decode_octet_string _rxkad_v5_decode_octet_string +#define decode_oid _rxkad_v5_decode_oid +#define decode_generalized_time _rxkad_v5_decode_generalized_time +#define fix_dce _rxkad_v5_fix_dce +#define der_put_unsigned _rxkad_v5_der_put_unsigned +#define der_put_int _rxkad_v5_der_put_int +#define der_put_length _rxkad_v5_der_put_length +#define der_put_general_string _rxkad_v5_der_put_general_string +#define der_put_octet_string _rxkad_v5_der_put_octet_string +#define der_put_oid _rxkad_v5_der_put_oid +#define der_put_tag _rxkad_v5_der_put_tag +#define der_put_length_and_tag _rxkad_v5_der_put_length_and_tag +#define encode_integer _rxkad_v5_encode_integer +#define encode_unsigned _rxkad_v5_encode_unsigned +#define encode_enumerated _rxkad_v5_encode_enumerated +#define encode_general_string _rxkad_v5_encode_general_string +#define encode_octet_string _rxkad_v5_encode_octet_string +#define encode_oid _rxkad_v5_encode_oid +#define time2generalizedtime _rxkad_v5_time2generalizedtime +#define encode_generalized_time _rxkad_v5_encode_generalized_time +#define free_general_string _rxkad_v5_free_general_string +#define free_octet_string _rxkad_v5_free_octet_string +#define free_oid _rxkad_v5_free_oid +#define len_unsigned _rxkad_v5_len_unsigned +#define len_int _rxkad_v5_len_int +#define len_oid _rxkad_v5_len_oid +#define length_len _rxkad_v5_length_len +#define length_integer _rxkad_v5_length_integer +#define length_unsigned _rxkad_v5_length_unsigned +#define length_enumerated _rxkad_v5_length_enumerated +#define length_general_string _rxkad_v5_length_general_string +#define length_octet_string _rxkad_v5_length_octet_string +#define length_oid _rxkad_v5_length_oid +#define length_generalized_time _rxkad_v5_length_generalized_time +#define copy_general_string _rxkad_v5_copy_general_string +#define copy_octet_string _rxkad_v5_copy_octet_string +#define copy_oid _rxkad_v5_copy_oid +#define TicketFlags2int _rxkad_v5_TicketFlags2int +#define int2TicketFlags _rxkad_v5_int2TicketFlags diff --git a/src/rxkad/v5gen.c b/src/rxkad/v5gen.c new file mode 100644 index 0000000000..d6ae3a2901 --- /dev/null +++ b/src/rxkad/v5gen.c @@ -0,0 +1,2490 @@ +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_Ticket(unsigned char *p, size_t len, const Ticket *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +{ +int oldret = ret; +ret = 0; +e = encode_EncryptedData(p, len, &(data)->enc_part, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 3, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_PrincipalName(p, len, &(data)->sname, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 2, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_Realm(p, len, &(data)->realm, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 1, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_integer(p, len, &(data)->tkt_vno, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 0, &l); +BACK; +ret += oldret; +} +e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, APPL, CONS, 1, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_Ticket(const unsigned char *p, size_t len, Ticket *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = der_match_tag_and_length (p, len, APPL, CONS, 1, &reallen, &l); +FORW; +{ +int dce_fix; +if((dce_fix = fix_dce(reallen, &len)) < 0) +return ASN1_BAD_FORMAT; +e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,&reallen, &l); +FORW; +{ +int dce_fix; +if((dce_fix = fix_dce(reallen, &len)) < 0) +return ASN1_BAD_FORMAT; +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 0, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_integer(p, len, &(data)->tkt_vno, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 1, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_Realm(p, len, &(data)->realm, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 2, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_PrincipalName(p, len, &(data)->sname, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 3, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_EncryptedData(p, len, &(data)->enc_part, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +} +} +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +} +} +if(size) *size = ret; +return 0; +fail: +free_Ticket(data); +return e; +} + +void +free_Ticket(Ticket *data) +{ +free_Realm(&(data)->realm); +free_PrincipalName(&(data)->sname); +free_EncryptedData(&(data)->enc_part); +} + +size_t +length_Ticket(const Ticket *data) +{ +size_t ret = 0; +{ +int oldret = ret; +ret = 0; +ret += length_integer(&(data)->tkt_vno); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_Realm(&(data)->realm); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_PrincipalName(&(data)->sname); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_EncryptedData(&(data)->enc_part); +ret += 1 + length_len(ret) + oldret; +} +ret += 1 + length_len(ret); +ret += 1 + length_len (ret); +return ret; +} + +int +copy_Ticket(const Ticket *from, Ticket *to) +{ +*(&(to)->tkt_vno) = *(&(from)->tkt_vno); +if(copy_Realm(&(from)->realm, &(to)->realm)) return ENOMEM; +if(copy_PrincipalName(&(from)->sname, &(to)->sname)) return ENOMEM; +if(copy_EncryptedData(&(from)->enc_part, &(to)->enc_part)) return ENOMEM; +return 0; +} + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_EncryptedData(unsigned char *p, size_t len, const EncryptedData *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +{ +int oldret = ret; +ret = 0; +e = encode_octet_string(p, len, &(data)->cipher, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 2, &l); +BACK; +ret += oldret; +} +if((data)->kvno) +{ +int oldret = ret; +ret = 0; +e = encode_integer(p, len, (data)->kvno, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 1, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_ENCTYPE(p, len, &(data)->etype, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 0, &l); +BACK; +ret += oldret; +} +e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_EncryptedData(const unsigned char *p, size_t len, EncryptedData *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,&reallen, &l); +FORW; +{ +int dce_fix; +if((dce_fix = fix_dce(reallen, &len)) < 0) +return ASN1_BAD_FORMAT; +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 0, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_ENCTYPE(p, len, &(data)->etype, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 1, &l); +if (e) +(data)->kvno = NULL; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +(data)->kvno = malloc(sizeof(*(data)->kvno)); +if((data)->kvno == NULL) return ENOMEM; +e = decode_integer(p, len, (data)->kvno, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 2, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_octet_string(p, len, &(data)->cipher, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +} +} +if(size) *size = ret; +return 0; +fail: +free_EncryptedData(data); +return e; +} + +void +free_EncryptedData(EncryptedData *data) +{ +free_ENCTYPE(&(data)->etype); +if((data)->kvno) { +free((data)->kvno); +} +free_octet_string(&(data)->cipher); +} + +size_t +length_EncryptedData(const EncryptedData *data) +{ +size_t ret = 0; +{ +int oldret = ret; +ret = 0; +ret += length_ENCTYPE(&(data)->etype); +ret += 1 + length_len(ret) + oldret; +} +if((data)->kvno){ +int oldret = ret; +ret = 0; +ret += length_integer((data)->kvno); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_octet_string(&(data)->cipher); +ret += 1 + length_len(ret) + oldret; +} +ret += 1 + length_len(ret); +return ret; +} + +int +copy_EncryptedData(const EncryptedData *from, EncryptedData *to) +{ +if(copy_ENCTYPE(&(from)->etype, &(to)->etype)) return ENOMEM; +if((from)->kvno) { +(to)->kvno = malloc(sizeof(*(to)->kvno)); +if((to)->kvno == NULL) return ENOMEM; +*((to)->kvno) = *((from)->kvno); +}else +(to)->kvno = NULL; +if(copy_octet_string(&(from)->cipher, &(to)->cipher)) return ENOMEM; +return 0; +} + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_PrincipalName(unsigned char *p, size_t len, const PrincipalName *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +{ +int oldret = ret; +ret = 0; +for(i = (&(data)->name_string)->len - 1; i >= 0; --i) { +int oldret = ret; +ret = 0; +e = encode_general_string(p, len, &(&(data)->name_string)->val[i], &l); +BACK; +ret += oldret; +} +e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 1, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_NAME_TYPE(p, len, &(data)->name_type, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 0, &l); +BACK; +ret += oldret; +} +e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_PrincipalName(const unsigned char *p, size_t len, PrincipalName *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,&reallen, &l); +FORW; +{ +int dce_fix; +if((dce_fix = fix_dce(reallen, &len)) < 0) +return ASN1_BAD_FORMAT; +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 0, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_NAME_TYPE(p, len, &(data)->name_type, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 1, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,&reallen, &l); +FORW; +if(len < reallen) +return ASN1_OVERRUN; +len = reallen; +{ +size_t origlen = len; +int oldret = ret; +ret = 0; +(&(data)->name_string)->len = 0; +(&(data)->name_string)->val = NULL; +while(ret < origlen) { +(&(data)->name_string)->len++; +(&(data)->name_string)->val = realloc((&(data)->name_string)->val, sizeof(*((&(data)->name_string)->val)) * (&(data)->name_string)->len); +e = decode_general_string(p, len, &(&(data)->name_string)->val[(&(data)->name_string)->len-1], &l); +FORW; +len = origlen - ret; +} +ret += oldret; +} +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +} +} +if(size) *size = ret; +return 0; +fail: +free_PrincipalName(data); +return e; +} + +void +free_PrincipalName(PrincipalName *data) +{ +free_NAME_TYPE(&(data)->name_type); +while((&(data)->name_string)->len){ +free_general_string(&(&(data)->name_string)->val[(&(data)->name_string)->len-1]); +(&(data)->name_string)->len--; +} +free((&(data)->name_string)->val); +} + +size_t +length_PrincipalName(const PrincipalName *data) +{ +size_t ret = 0; +{ +int oldret = ret; +ret = 0; +ret += length_NAME_TYPE(&(data)->name_type); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +{ +int oldret = ret; +int i; +ret = 0; +for(i = (&(data)->name_string)->len - 1; i >= 0; --i){ +ret += length_general_string(&(&(data)->name_string)->val[i]); +} +ret += 1 + length_len(ret) + oldret; +} +ret += 1 + length_len(ret) + oldret; +} +ret += 1 + length_len(ret); +return ret; +} + +int +copy_PrincipalName(const PrincipalName *from, PrincipalName *to) +{ +if(copy_NAME_TYPE(&(from)->name_type, &(to)->name_type)) return ENOMEM; +if(((&(to)->name_string)->val = malloc((&(from)->name_string)->len * sizeof(*(&(to)->name_string)->val))) == NULL && (&(from)->name_string)->len != 0) +return ENOMEM; +for((&(to)->name_string)->len = 0; (&(to)->name_string)->len < (&(from)->name_string)->len; (&(to)->name_string)->len++){ +if(copy_general_string(&(&(from)->name_string)->val[(&(to)->name_string)->len], &(&(to)->name_string)->val[(&(to)->name_string)->len])) return ENOMEM; +} +return 0; +} + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_HostAddresses(unsigned char *p, size_t len, const HostAddresses *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +for(i = (data)->len - 1; i >= 0; --i) { +int oldret = ret; +ret = 0; +e = encode_HostAddress(p, len, &(data)->val[i], &l); +BACK; +ret += oldret; +} +e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_HostAddresses(const unsigned char *p, size_t len, HostAddresses *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,&reallen, &l); +FORW; +if(len < reallen) +return ASN1_OVERRUN; +len = reallen; +{ +size_t origlen = len; +int oldret = ret; +ret = 0; +(data)->len = 0; +(data)->val = NULL; +while(ret < origlen) { +(data)->len++; +(data)->val = realloc((data)->val, sizeof(*((data)->val)) * (data)->len); +e = decode_HostAddress(p, len, &(data)->val[(data)->len-1], &l); +FORW; +len = origlen - ret; +} +ret += oldret; +} +if(size) *size = ret; +return 0; +fail: +free_HostAddresses(data); +return e; +} + +void +free_HostAddresses(HostAddresses *data) +{ +while((data)->len){ +free_HostAddress(&(data)->val[(data)->len-1]); +(data)->len--; +} +free((data)->val); +} + +size_t +length_HostAddresses(const HostAddresses *data) +{ +size_t ret = 0; +{ +int oldret = ret; +int i; +ret = 0; +for(i = (data)->len - 1; i >= 0; --i){ +ret += length_HostAddress(&(data)->val[i]); +} +ret += 1 + length_len(ret) + oldret; +} +return ret; +} + +int +copy_HostAddresses(const HostAddresses *from, HostAddresses *to) +{ +if(((to)->val = malloc((from)->len * sizeof(*(to)->val))) == NULL && (from)->len != 0) +return ENOMEM; +for((to)->len = 0; (to)->len < (from)->len; (to)->len++){ +if(copy_HostAddress(&(from)->val[(to)->len], &(to)->val[(to)->len])) return ENOMEM; +} +return 0; +} + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_HostAddress(unsigned char *p, size_t len, const HostAddress *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +{ +int oldret = ret; +ret = 0; +e = encode_octet_string(p, len, &(data)->address, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 1, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_integer(p, len, &(data)->addr_type, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 0, &l); +BACK; +ret += oldret; +} +e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_HostAddress(const unsigned char *p, size_t len, HostAddress *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,&reallen, &l); +FORW; +{ +int dce_fix; +if((dce_fix = fix_dce(reallen, &len)) < 0) +return ASN1_BAD_FORMAT; +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 0, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_integer(p, len, &(data)->addr_type, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 1, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_octet_string(p, len, &(data)->address, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +} +} +if(size) *size = ret; +return 0; +fail: +free_HostAddress(data); +return e; +} + +void +free_HostAddress(HostAddress *data) +{ +free_octet_string(&(data)->address); +} + +size_t +length_HostAddress(const HostAddress *data) +{ +size_t ret = 0; +{ +int oldret = ret; +ret = 0; +ret += length_integer(&(data)->addr_type); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_octet_string(&(data)->address); +ret += 1 + length_len(ret) + oldret; +} +ret += 1 + length_len(ret); +return ret; +} + +int +copy_HostAddress(const HostAddress *from, HostAddress *to) +{ +*(&(to)->addr_type) = *(&(from)->addr_type); +if(copy_octet_string(&(from)->address, &(to)->address)) return ENOMEM; +return 0; +} + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_AuthorizationData(unsigned char *p, size_t len, const AuthorizationData *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +for(i = (data)->len - 1; i >= 0; --i) { +int oldret = ret; +ret = 0; +{ +int oldret = ret; +ret = 0; +e = encode_octet_string(p, len, &(&(data)->val[i])->ad_data, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 1, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_integer(p, len, &(&(data)->val[i])->ad_type, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 0, &l); +BACK; +ret += oldret; +} +e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l); +BACK; +ret += oldret; +} +e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_AuthorizationData(const unsigned char *p, size_t len, AuthorizationData *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,&reallen, &l); +FORW; +if(len < reallen) +return ASN1_OVERRUN; +len = reallen; +{ +size_t origlen = len; +int oldret = ret; +ret = 0; +(data)->len = 0; +(data)->val = NULL; +while(ret < origlen) { +(data)->len++; +(data)->val = realloc((data)->val, sizeof(*((data)->val)) * (data)->len); +e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,&reallen, &l); +FORW; +{ +int dce_fix; +if((dce_fix = fix_dce(reallen, &len)) < 0) +return ASN1_BAD_FORMAT; +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 0, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_integer(p, len, &(&(data)->val[(data)->len-1])->ad_type, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 1, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_octet_string(p, len, &(&(data)->val[(data)->len-1])->ad_data, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +} +} +len = origlen - ret; +} +ret += oldret; +} +if(size) *size = ret; +return 0; +fail: +free_AuthorizationData(data); +return e; +} + +void +free_AuthorizationData(AuthorizationData *data) +{ +while((data)->len){ +free_octet_string(&(&(data)->val[(data)->len-1])->ad_data); +(data)->len--; +} +free((data)->val); +} + +size_t +length_AuthorizationData(const AuthorizationData *data) +{ +size_t ret = 0; +{ +int oldret = ret; +int i; +ret = 0; +for(i = (data)->len - 1; i >= 0; --i){ +{ +int oldret = ret; +ret = 0; +ret += length_integer(&(&(data)->val[i])->ad_type); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_octet_string(&(&(data)->val[i])->ad_data); +ret += 1 + length_len(ret) + oldret; +} +ret += 1 + length_len(ret); +} +ret += 1 + length_len(ret) + oldret; +} +return ret; +} + +int +copy_AuthorizationData(const AuthorizationData *from, AuthorizationData *to) +{ +if(((to)->val = malloc((from)->len * sizeof(*(to)->val))) == NULL && (from)->len != 0) +return ENOMEM; +for((to)->len = 0; (to)->len < (from)->len; (to)->len++){ +*(&(&(to)->val[(to)->len])->ad_type) = *(&(&(from)->val[(to)->len])->ad_type); +if(copy_octet_string(&(&(from)->val[(to)->len])->ad_data, &(&(to)->val[(to)->len])->ad_data)) return ENOMEM; +} +return 0; +} + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_EncTicketPart(unsigned char *p, size_t len, const EncTicketPart *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +if((data)->authorization_data) +{ +int oldret = ret; +ret = 0; +e = encode_AuthorizationData(p, len, (data)->authorization_data, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 10, &l); +BACK; +ret += oldret; +} +if((data)->caddr) +{ +int oldret = ret; +ret = 0; +e = encode_HostAddresses(p, len, (data)->caddr, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 9, &l); +BACK; +ret += oldret; +} +if((data)->renew_till) +{ +int oldret = ret; +ret = 0; +e = encode_KerberosTime(p, len, (data)->renew_till, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 8, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_KerberosTime(p, len, &(data)->endtime, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 7, &l); +BACK; +ret += oldret; +} +if((data)->starttime) +{ +int oldret = ret; +ret = 0; +e = encode_KerberosTime(p, len, (data)->starttime, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 6, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_KerberosTime(p, len, &(data)->authtime, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 5, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_TransitedEncoding(p, len, &(data)->transited, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 4, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_PrincipalName(p, len, &(data)->cname, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 3, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_Realm(p, len, &(data)->crealm, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 2, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_EncryptionKey(p, len, &(data)->key, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 1, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_TicketFlags(p, len, &(data)->flags, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 0, &l); +BACK; +ret += oldret; +} +e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, APPL, CONS, 3, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_EncTicketPart(const unsigned char *p, size_t len, EncTicketPart *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = der_match_tag_and_length (p, len, APPL, CONS, 3, &reallen, &l); +FORW; +{ +int dce_fix; +if((dce_fix = fix_dce(reallen, &len)) < 0) +return ASN1_BAD_FORMAT; +e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,&reallen, &l); +FORW; +{ +int dce_fix; +if((dce_fix = fix_dce(reallen, &len)) < 0) +return ASN1_BAD_FORMAT; +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 0, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_TicketFlags(p, len, &(data)->flags, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 1, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_EncryptionKey(p, len, &(data)->key, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 2, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_Realm(p, len, &(data)->crealm, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 3, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_PrincipalName(p, len, &(data)->cname, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 4, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_TransitedEncoding(p, len, &(data)->transited, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 5, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_KerberosTime(p, len, &(data)->authtime, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 6, &l); +if (e) +(data)->starttime = NULL; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +(data)->starttime = malloc(sizeof(*(data)->starttime)); +if((data)->starttime == NULL) return ENOMEM; +e = decode_KerberosTime(p, len, (data)->starttime, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 7, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_KerberosTime(p, len, &(data)->endtime, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 8, &l); +if (e) +(data)->renew_till = NULL; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +(data)->renew_till = malloc(sizeof(*(data)->renew_till)); +if((data)->renew_till == NULL) return ENOMEM; +e = decode_KerberosTime(p, len, (data)->renew_till, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 9, &l); +if (e) +(data)->caddr = NULL; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +(data)->caddr = malloc(sizeof(*(data)->caddr)); +if((data)->caddr == NULL) return ENOMEM; +e = decode_HostAddresses(p, len, (data)->caddr, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 10, &l); +if (e) +(data)->authorization_data = NULL; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +(data)->authorization_data = malloc(sizeof(*(data)->authorization_data)); +if((data)->authorization_data == NULL) return ENOMEM; +e = decode_AuthorizationData(p, len, (data)->authorization_data, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +} +} +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +} +} +if(size) *size = ret; +return 0; +fail: +free_EncTicketPart(data); +return e; +} + +void +free_EncTicketPart(EncTicketPart *data) +{ +free_TicketFlags(&(data)->flags); +free_EncryptionKey(&(data)->key); +free_Realm(&(data)->crealm); +free_PrincipalName(&(data)->cname); +free_TransitedEncoding(&(data)->transited); +free_KerberosTime(&(data)->authtime); +if((data)->starttime) { +free_KerberosTime((data)->starttime); +free((data)->starttime); +} +free_KerberosTime(&(data)->endtime); +if((data)->renew_till) { +free_KerberosTime((data)->renew_till); +free((data)->renew_till); +} +if((data)->caddr) { +free_HostAddresses((data)->caddr); +free((data)->caddr); +} +if((data)->authorization_data) { +free_AuthorizationData((data)->authorization_data); +free((data)->authorization_data); +} +} + +size_t +length_EncTicketPart(const EncTicketPart *data) +{ +size_t ret = 0; +{ +int oldret = ret; +ret = 0; +ret += length_TicketFlags(&(data)->flags); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_EncryptionKey(&(data)->key); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_Realm(&(data)->crealm); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_PrincipalName(&(data)->cname); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_TransitedEncoding(&(data)->transited); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_KerberosTime(&(data)->authtime); +ret += 1 + length_len(ret) + oldret; +} +if((data)->starttime){ +int oldret = ret; +ret = 0; +ret += length_KerberosTime((data)->starttime); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_KerberosTime(&(data)->endtime); +ret += 1 + length_len(ret) + oldret; +} +if((data)->renew_till){ +int oldret = ret; +ret = 0; +ret += length_KerberosTime((data)->renew_till); +ret += 1 + length_len(ret) + oldret; +} +if((data)->caddr){ +int oldret = ret; +ret = 0; +ret += length_HostAddresses((data)->caddr); +ret += 1 + length_len(ret) + oldret; +} +if((data)->authorization_data){ +int oldret = ret; +ret = 0; +ret += length_AuthorizationData((data)->authorization_data); +ret += 1 + length_len(ret) + oldret; +} +ret += 1 + length_len(ret); +ret += 1 + length_len (ret); +return ret; +} + +int +copy_EncTicketPart(const EncTicketPart *from, EncTicketPart *to) +{ +if(copy_TicketFlags(&(from)->flags, &(to)->flags)) return ENOMEM; +if(copy_EncryptionKey(&(from)->key, &(to)->key)) return ENOMEM; +if(copy_Realm(&(from)->crealm, &(to)->crealm)) return ENOMEM; +if(copy_PrincipalName(&(from)->cname, &(to)->cname)) return ENOMEM; +if(copy_TransitedEncoding(&(from)->transited, &(to)->transited)) return ENOMEM; +if(copy_KerberosTime(&(from)->authtime, &(to)->authtime)) return ENOMEM; +if((from)->starttime) { +(to)->starttime = malloc(sizeof(*(to)->starttime)); +if((to)->starttime == NULL) return ENOMEM; +if(copy_KerberosTime((from)->starttime, (to)->starttime)) return ENOMEM; +}else +(to)->starttime = NULL; +if(copy_KerberosTime(&(from)->endtime, &(to)->endtime)) return ENOMEM; +if((from)->renew_till) { +(to)->renew_till = malloc(sizeof(*(to)->renew_till)); +if((to)->renew_till == NULL) return ENOMEM; +if(copy_KerberosTime((from)->renew_till, (to)->renew_till)) return ENOMEM; +}else +(to)->renew_till = NULL; +if((from)->caddr) { +(to)->caddr = malloc(sizeof(*(to)->caddr)); +if((to)->caddr == NULL) return ENOMEM; +if(copy_HostAddresses((from)->caddr, (to)->caddr)) return ENOMEM; +}else +(to)->caddr = NULL; +if((from)->authorization_data) { +(to)->authorization_data = malloc(sizeof(*(to)->authorization_data)); +if((to)->authorization_data == NULL) return ENOMEM; +if(copy_AuthorizationData((from)->authorization_data, (to)->authorization_data)) return ENOMEM; +}else +(to)->authorization_data = NULL; +return 0; +} + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_KerberosTime(unsigned char *p, size_t len, const KerberosTime *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +e = encode_generalized_time(p, len, data, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_KerberosTime(const unsigned char *p, size_t len, KerberosTime *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = decode_generalized_time(p, len, data, &l); +FORW; +if(size) *size = ret; +return 0; +fail: +free_KerberosTime(data); +return e; +} + +void +free_KerberosTime(KerberosTime *data) +{ +} + +size_t +length_KerberosTime(const KerberosTime *data) +{ +size_t ret = 0; +ret += length_generalized_time(data); +return ret; +} + +int +copy_KerberosTime(const KerberosTime *from, KerberosTime *to) +{ +*(to) = *(from); +return 0; +} + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_TransitedEncoding(unsigned char *p, size_t len, const TransitedEncoding *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +{ +int oldret = ret; +ret = 0; +e = encode_octet_string(p, len, &(data)->contents, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 1, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_integer(p, len, &(data)->tr_type, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 0, &l); +BACK; +ret += oldret; +} +e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_TransitedEncoding(const unsigned char *p, size_t len, TransitedEncoding *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,&reallen, &l); +FORW; +{ +int dce_fix; +if((dce_fix = fix_dce(reallen, &len)) < 0) +return ASN1_BAD_FORMAT; +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 0, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_integer(p, len, &(data)->tr_type, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 1, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_octet_string(p, len, &(data)->contents, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +} +} +if(size) *size = ret; +return 0; +fail: +free_TransitedEncoding(data); +return e; +} + +void +free_TransitedEncoding(TransitedEncoding *data) +{ +free_octet_string(&(data)->contents); +} + +size_t +length_TransitedEncoding(const TransitedEncoding *data) +{ +size_t ret = 0; +{ +int oldret = ret; +ret = 0; +ret += length_integer(&(data)->tr_type); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_octet_string(&(data)->contents); +ret += 1 + length_len(ret) + oldret; +} +ret += 1 + length_len(ret); +return ret; +} + +int +copy_TransitedEncoding(const TransitedEncoding *from, TransitedEncoding *to) +{ +*(&(to)->tr_type) = *(&(from)->tr_type); +if(copy_octet_string(&(from)->contents, &(to)->contents)) return ENOMEM; +return 0; +} + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_EncryptionKey(unsigned char *p, size_t len, const EncryptionKey *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +{ +int oldret = ret; +ret = 0; +e = encode_octet_string(p, len, &(data)->keyvalue, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 1, &l); +BACK; +ret += oldret; +} +{ +int oldret = ret; +ret = 0; +e = encode_integer(p, len, &(data)->keytype, &l); +BACK; +e = der_put_length_and_tag (p, len, ret, CONTEXT, CONS, 0, &l); +BACK; +ret += oldret; +} +e = der_put_length_and_tag (p, len, ret, UNIV, CONS, UT_Sequence, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_EncryptionKey(const unsigned char *p, size_t len, EncryptionKey *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = der_match_tag_and_length (p, len, UNIV, CONS, UT_Sequence,&reallen, &l); +FORW; +{ +int dce_fix; +if((dce_fix = fix_dce(reallen, &len)) < 0) +return ASN1_BAD_FORMAT; +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 0, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_integer(p, len, &(data)->keytype, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +{ +size_t newlen, oldlen; + +e = der_match_tag (p, len, CONTEXT, CONS, 1, &l); +if (e) +return e; +else { +p += l; +len -= l; +ret += l; +e = der_get_length (p, len, &newlen, &l); +FORW; +{ +int dce_fix; +oldlen = len; +if((dce_fix = fix_dce(newlen, &len)) < 0)return ASN1_BAD_FORMAT; +e = decode_octet_string(p, len, &(data)->keyvalue, &l); +FORW; +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +}else +len = oldlen - newlen; +} +} +} +if(dce_fix){ +e = der_match_tag_and_length (p, len, (Der_class)0, (Der_type)0, 0, &reallen, &l); +FORW; +} +} +if(size) *size = ret; +return 0; +fail: +free_EncryptionKey(data); +return e; +} + +void +free_EncryptionKey(EncryptionKey *data) +{ +free_octet_string(&(data)->keyvalue); +} + +size_t +length_EncryptionKey(const EncryptionKey *data) +{ +size_t ret = 0; +{ +int oldret = ret; +ret = 0; +ret += length_integer(&(data)->keytype); +ret += 1 + length_len(ret) + oldret; +} +{ +int oldret = ret; +ret = 0; +ret += length_octet_string(&(data)->keyvalue); +ret += 1 + length_len(ret) + oldret; +} +ret += 1 + length_len(ret); +return ret; +} + +int +copy_EncryptionKey(const EncryptionKey *from, EncryptionKey *to) +{ +*(&(to)->keytype) = *(&(from)->keytype); +if(copy_octet_string(&(from)->keyvalue, &(to)->keyvalue)) return ENOMEM; +return 0; +} + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_TicketFlags(unsigned char *p, size_t len, const TicketFlags *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +{ +unsigned char c = 0; +*p-- = c; len--; ret++; +c = 0; +*p-- = c; len--; ret++; +c = 0; +if(data->anonymous) c |= 1<<1; +if(data->ok_as_delegate) c |= 1<<2; +if(data->transited_policy_checked) c |= 1<<3; +if(data->hw_authent) c |= 1<<4; +if(data->pre_authent) c |= 1<<5; +if(data->initial) c |= 1<<6; +if(data->renewable) c |= 1<<7; +*p-- = c; len--; ret++; +c = 0; +if(data->invalid) c |= 1<<0; +if(data->postdated) c |= 1<<1; +if(data->may_postdate) c |= 1<<2; +if(data->proxy) c |= 1<<3; +if(data->proxiable) c |= 1<<4; +if(data->forwarded) c |= 1<<5; +if(data->forwardable) c |= 1<<6; +if(data->reserved) c |= 1<<7; +*p-- = c; +*p-- = 0; +len -= 2; +ret += 2; +} + +e = der_put_length_and_tag (p, len, ret, UNIV, PRIM,UT_BitString, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_TicketFlags(const unsigned char *p, size_t len, TicketFlags *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = der_match_tag_and_length (p, len, UNIV, PRIM, UT_BitString,&reallen, &l); +FORW; +if(len < reallen) +return ASN1_OVERRUN; +p++; +len--; +reallen--; +ret++; +data->reserved = (*p >> 7) & 1; +data->forwardable = (*p >> 6) & 1; +data->forwarded = (*p >> 5) & 1; +data->proxiable = (*p >> 4) & 1; +data->proxy = (*p >> 3) & 1; +data->may_postdate = (*p >> 2) & 1; +data->postdated = (*p >> 1) & 1; +data->invalid = (*p >> 0) & 1; +p++; len--; reallen--; ret++; +data->renewable = (*p >> 7) & 1; +data->initial = (*p >> 6) & 1; +data->pre_authent = (*p >> 5) & 1; +data->hw_authent = (*p >> 4) & 1; +data->transited_policy_checked = (*p >> 3) & 1; +data->ok_as_delegate = (*p >> 2) & 1; +data->anonymous = (*p >> 1) & 1; +p += reallen; len -= reallen; ret += reallen; +if(size) *size = ret; +return 0; +fail: +free_TicketFlags(data); +return e; +} + +void +free_TicketFlags(TicketFlags *data) +{ +} + +size_t +length_TicketFlags(const TicketFlags *data) +{ +size_t ret = 0; +ret += 7; +return ret; +} + +int +copy_TicketFlags(const TicketFlags *from, TicketFlags *to) +{ +*(to) = *(from); +return 0; +} + +unsigned TicketFlags2int(TicketFlags f) +{ +unsigned r = 0; +if(f.reserved) r |= (1U << 0); +if(f.forwardable) r |= (1U << 1); +if(f.forwarded) r |= (1U << 2); +if(f.proxiable) r |= (1U << 3); +if(f.proxy) r |= (1U << 4); +if(f.may_postdate) r |= (1U << 5); +if(f.postdated) r |= (1U << 6); +if(f.invalid) r |= (1U << 7); +if(f.renewable) r |= (1U << 8); +if(f.initial) r |= (1U << 9); +if(f.pre_authent) r |= (1U << 10); +if(f.hw_authent) r |= (1U << 11); +if(f.transited_policy_checked) r |= (1U << 12); +if(f.ok_as_delegate) r |= (1U << 13); +if(f.anonymous) r |= (1U << 14); +return r; +} + +TicketFlags int2TicketFlags(unsigned n) +{ + TicketFlags flags; + + flags.reserved = (n >> 0) & 1; + flags.forwardable = (n >> 1) & 1; + flags.forwarded = (n >> 2) & 1; + flags.proxiable = (n >> 3) & 1; + flags.proxy = (n >> 4) & 1; + flags.may_postdate = (n >> 5) & 1; + flags.postdated = (n >> 6) & 1; + flags.invalid = (n >> 7) & 1; + flags.renewable = (n >> 8) & 1; + flags.initial = (n >> 9) & 1; + flags.pre_authent = (n >> 10) & 1; + flags.hw_authent = (n >> 11) & 1; + flags.transited_policy_checked = (n >> 12) & 1; + flags.ok_as_delegate = (n >> 13) & 1; + flags.anonymous = (n >> 14) & 1; + return flags; +} + + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_Realm(unsigned char *p, size_t len, const Realm *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +e = encode_general_string(p, len, data, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_Realm(const unsigned char *p, size_t len, Realm *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = decode_general_string(p, len, data, &l); +FORW; +if(size) *size = ret; +return 0; +fail: +free_Realm(data); +return e; +} + +void +free_Realm(Realm *data) +{ +free_general_string(data); +} + +size_t +length_Realm(const Realm *data) +{ +size_t ret = 0; +ret += length_general_string(data); +return ret; +} + +int +copy_Realm(const Realm *from, Realm *to) +{ +if(copy_general_string(from, to)) return ENOMEM; +return 0; +} + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_ENCTYPE(unsigned char *p, size_t len, const ENCTYPE *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +e = encode_integer(p, len, (const int*)data, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_ENCTYPE(const unsigned char *p, size_t len, ENCTYPE *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = decode_integer(p, len, (int*)data, &l); +FORW; +if(size) *size = ret; +return 0; +fail: +free_ENCTYPE(data); +return e; +} + +void +free_ENCTYPE(ENCTYPE *data) +{ +} + +size_t +length_ENCTYPE(const ENCTYPE *data) +{ +size_t ret = 0; +ret += length_integer((const int*)data); +return ret; +} + +int +copy_ENCTYPE(const ENCTYPE *from, ENCTYPE *to) +{ +*(to) = *(from); +return 0; +} + +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#include +#include +#include +#include +#include + +#define BACK if (e) return e; p -= l; len -= l; ret += l + +int +encode_NAME_TYPE(unsigned char *p, size_t len, const NAME_TYPE *data, size_t *size) +{ +size_t ret = 0; +size_t l; +int i, e; + +i = 0; +e = encode_integer(p, len, (const int*)data, &l); +BACK; +*size = ret; +return 0; +} + +#define FORW if(e) goto fail; p += l; len -= l; ret += l + +int +decode_NAME_TYPE(const unsigned char *p, size_t len, NAME_TYPE *data, size_t *size) +{ +size_t ret = 0, reallen; +size_t l; +int i, e; + +memset(data, 0, sizeof(*data)); +i = 0; +reallen = 0; +e = decode_integer(p, len, (int*)data, &l); +FORW; +if(size) *size = ret; +return 0; +fail: +free_NAME_TYPE(data); +return e; +} + +void +free_NAME_TYPE(NAME_TYPE *data) +{ +} + +size_t +length_NAME_TYPE(const NAME_TYPE *data) +{ +size_t ret = 0; +ret += length_integer((const int*)data); +return ret; +} + +int +copy_NAME_TYPE(const NAME_TYPE *from, NAME_TYPE *to) +{ +*(to) = *(from); +return 0; +} + diff --git a/src/rxkad/v5gen.h b/src/rxkad/v5gen.h new file mode 100644 index 0000000000..5cb9d64f78 --- /dev/null +++ b/src/rxkad/v5gen.h @@ -0,0 +1,1257 @@ +/* Generated from ../../../lib/asn1/k5.asn1 */ +/* Do not edit */ + +#ifndef __krb5_asn1_h__ +#define __krb5_asn1_h__ + +#include +#include + +#ifndef __asn1_common_definitions__ +#define __asn1_common_definitions__ + +typedef struct octet_string { + size_t length; + void *data; +} octet_string; + +typedef char *general_string; + +typedef struct oid { + size_t length; + unsigned *components; +} oid; + +#endif + +/* +NAME-TYPE ::= INTEGER +*/ + +typedef enum NAME_TYPE { + KRB5_NT_UNKNOWN = 0, + KRB5_NT_PRINCIPAL = 1, + KRB5_NT_SRV_INST = 2, + KRB5_NT_SRV_HST = 3, + KRB5_NT_SRV_XHST = 4, + KRB5_NT_UID = 5, + KRB5_NT_X500_PRINCIPAL = 6 +} NAME_TYPE; + +int encode_NAME_TYPE(unsigned char *, size_t, const NAME_TYPE *, size_t *); +int decode_NAME_TYPE(const unsigned char *, size_t, NAME_TYPE *, size_t *); +void free_NAME_TYPE (NAME_TYPE *); +size_t length_NAME_TYPE(const NAME_TYPE *); +int copy_NAME_TYPE (const NAME_TYPE *, NAME_TYPE *); + + +/* +MESSAGE-TYPE ::= INTEGER +*/ + +typedef enum MESSAGE_TYPE { + krb_as_req = 10, + krb_as_rep = 11, + krb_tgs_req = 12, + krb_tgs_rep = 13, + krb_ap_req = 14, + krb_ap_rep = 15, + krb_safe = 20, + krb_priv = 21, + krb_cred = 22, + krb_error = 30 +} MESSAGE_TYPE; + +int encode_MESSAGE_TYPE(unsigned char *, size_t, const MESSAGE_TYPE *, size_t *); +int decode_MESSAGE_TYPE(const unsigned char *, size_t, MESSAGE_TYPE *, size_t *); +void free_MESSAGE_TYPE (MESSAGE_TYPE *); +size_t length_MESSAGE_TYPE(const MESSAGE_TYPE *); +int copy_MESSAGE_TYPE (const MESSAGE_TYPE *, MESSAGE_TYPE *); + + +/* +PADATA-TYPE ::= INTEGER +*/ + +typedef enum PADATA_TYPE { + KRB5_PADATA_NONE = 0, + KRB5_PADATA_TGS_REQ = 1, + KRB5_PADATA_AP_REQ = 1, + KRB5_PADATA_ENC_TIMESTAMP = 2, + KRB5_PADATA_PW_SALT = 3, + KRB5_PADATA_ENC_UNIX_TIME = 5, + KRB5_PADATA_SANDIA_SECUREID = 6, + KRB5_PADATA_SESAME = 7, + KRB5_PADATA_OSF_DCE = 8, + KRB5_PADATA_CYBERSAFE_SECUREID = 9, + KRB5_PADATA_AFS3_SALT = 10, + KRB5_PADATA_ETYPE_INFO = 11, + KRB5_PADATA_SAM_CHALLENGE = 12, + KRB5_PADATA_SAM_RESPONSE = 13, + KRB5_PADATA_PK_AS_REQ = 14, + KRB5_PADATA_PK_AS_REP = 15, + KRB5_PADATA_PK_AS_SIGN = 16, + KRB5_PADATA_PK_KEY_REQ = 17, + KRB5_PADATA_PK_KEY_REP = 18, + KRB5_PADATA_USE_SPECIFIED_KVNO = 20, + KRB5_PADATA_SAM_REDIRECT = 21, + KRB5_PADATA_GET_FROM_TYPED_DATA = 22, + KRB5_PADATA_SAM_ETYPE_INFO = 23 +} PADATA_TYPE; + +int encode_PADATA_TYPE(unsigned char *, size_t, const PADATA_TYPE *, size_t *); +int decode_PADATA_TYPE(const unsigned char *, size_t, PADATA_TYPE *, size_t *); +void free_PADATA_TYPE (PADATA_TYPE *); +size_t length_PADATA_TYPE(const PADATA_TYPE *); +int copy_PADATA_TYPE (const PADATA_TYPE *, PADATA_TYPE *); + + +/* +CKSUMTYPE ::= INTEGER +*/ + +typedef enum CKSUMTYPE { + CKSUMTYPE_NONE = 0, + CKSUMTYPE_CRC32 = 1, + CKSUMTYPE_RSA_MD4 = 2, + CKSUMTYPE_RSA_MD4_DES = 3, + CKSUMTYPE_DES_MAC = 4, + CKSUMTYPE_DES_MAC_K = 5, + CKSUMTYPE_RSA_MD4_DES_K = 6, + CKSUMTYPE_RSA_MD5 = 7, + CKSUMTYPE_RSA_MD5_DES = 8, + CKSUMTYPE_RSA_MD5_DES3 = 9, + CKSUMTYPE_HMAC_SHA1_DES3 = 12, + CKSUMTYPE_SHA1 = 1000, + CKSUMTYPE_GSSAPI = 32771, + CKSUMTYPE_HMAC_MD5 = -138, + CKSUMTYPE_HMAC_MD5_ENC = -1138 +} CKSUMTYPE; + +int encode_CKSUMTYPE(unsigned char *, size_t, const CKSUMTYPE *, size_t *); +int decode_CKSUMTYPE(const unsigned char *, size_t, CKSUMTYPE *, size_t *); +void free_CKSUMTYPE (CKSUMTYPE *); +size_t length_CKSUMTYPE(const CKSUMTYPE *); +int copy_CKSUMTYPE (const CKSUMTYPE *, CKSUMTYPE *); + + +/* +ENCTYPE ::= INTEGER +*/ + +typedef enum ENCTYPE { + ETYPE_NULL = 0, + ETYPE_DES_CBC_CRC = 1, + ETYPE_DES_CBC_MD4 = 2, + ETYPE_DES_CBC_MD5 = 3, + ETYPE_DES3_CBC_MD5 = 5, + ETYPE_OLD_DES3_CBC_SHA1 = 7, + ETYPE_SIGN_DSA_GENERATE = 8, + ETYPE_ENCRYPT_RSA_PRIV = 9, + ETYPE_ENCRYPT_RSA_PUB = 10, + ETYPE_DES3_CBC_SHA1 = 16, + ETYPE_ARCFOUR_HMAC_MD5 = 23, + ETYPE_ARCFOUR_HMAC_MD5_56 = 24, + ETYPE_ENCTYPE_PK_CROSS = 48, + ETYPE_DES_CBC_NONE = -4096, + ETYPE_DES3_CBC_NONE = -4097, + ETYPE_DES_CFB64_NONE = -4098, + ETYPE_DES_PCBC_NONE = -4099, + ETYPE_DES3_CBC_NONE_IVEC = -4100 +} ENCTYPE; + +int encode_ENCTYPE(unsigned char *, size_t, const ENCTYPE *, size_t *); +int decode_ENCTYPE(const unsigned char *, size_t, ENCTYPE *, size_t *); +void free_ENCTYPE (ENCTYPE *); +size_t length_ENCTYPE(const ENCTYPE *); +int copy_ENCTYPE (const ENCTYPE *, ENCTYPE *); + + +/* +UNSIGNED ::= UNSIGNED INTEGER +*/ + +typedef unsigned int UNSIGNED; + +int encode_UNSIGNED(unsigned char *, size_t, const UNSIGNED *, size_t *); +int decode_UNSIGNED(const unsigned char *, size_t, UNSIGNED *, size_t *); +void free_UNSIGNED (UNSIGNED *); +size_t length_UNSIGNED(const UNSIGNED *); +int copy_UNSIGNED (const UNSIGNED *, UNSIGNED *); + + +/* +Realm ::= GeneralString +*/ + +typedef general_string Realm; + +int encode_Realm(unsigned char *, size_t, const Realm *, size_t *); +int decode_Realm(const unsigned char *, size_t, Realm *, size_t *); +void free_Realm (Realm *); +size_t length_Realm(const Realm *); +int copy_Realm (const Realm *, Realm *); + + +/* +PrincipalName ::= SEQUENCE { + name-type[0] NAME-TYPE, + name-string[1] SEQUENCE OF GeneralString +} +*/ + +typedef struct PrincipalName { + NAME_TYPE name_type; + struct { + unsigned int len; + general_string *val; + } name_string; +} PrincipalName; + +int encode_PrincipalName(unsigned char *, size_t, const PrincipalName *, size_t *); +int decode_PrincipalName(const unsigned char *, size_t, PrincipalName *, size_t *); +void free_PrincipalName (PrincipalName *); +size_t length_PrincipalName(const PrincipalName *); +int copy_PrincipalName (const PrincipalName *, PrincipalName *); + + +/* +Principal ::= SEQUENCE { + name[0] PrincipalName, + realm[1] Realm +} +*/ + +typedef struct Principal { + PrincipalName name; + Realm realm; +} Principal; + +int encode_Principal(unsigned char *, size_t, const Principal *, size_t *); +int decode_Principal(const unsigned char *, size_t, Principal *, size_t *); +void free_Principal (Principal *); +size_t length_Principal(const Principal *); +int copy_Principal (const Principal *, Principal *); + + +/* +HostAddress ::= SEQUENCE { + addr-type[0] INTEGER, + address[1] OCTET STRING +} +*/ + +typedef struct HostAddress { + int addr_type; + octet_string address; +} HostAddress; + +int encode_HostAddress(unsigned char *, size_t, const HostAddress *, size_t *); +int decode_HostAddress(const unsigned char *, size_t, HostAddress *, size_t *); +void free_HostAddress (HostAddress *); +size_t length_HostAddress(const HostAddress *); +int copy_HostAddress (const HostAddress *, HostAddress *); + + +/* +HostAddresses ::= SEQUENCE OF HostAddress +*/ + +typedef struct HostAddresses { + unsigned int len; + HostAddress *val; +} HostAddresses; + +int encode_HostAddresses(unsigned char *, size_t, const HostAddresses *, size_t *); +int decode_HostAddresses(const unsigned char *, size_t, HostAddresses *, size_t *); +void free_HostAddresses (HostAddresses *); +size_t length_HostAddresses(const HostAddresses *); +int copy_HostAddresses (const HostAddresses *, HostAddresses *); + + +/* +KerberosTime ::= GeneralizedTime +*/ + +typedef time_t KerberosTime; + +int encode_KerberosTime(unsigned char *, size_t, const KerberosTime *, size_t *); +int decode_KerberosTime(const unsigned char *, size_t, KerberosTime *, size_t *); +void free_KerberosTime (KerberosTime *); +size_t length_KerberosTime(const KerberosTime *); +int copy_KerberosTime (const KerberosTime *, KerberosTime *); + + +/* +AuthorizationData ::= SEQUENCE OF SEQUENCE { + ad-type[0] INTEGER, + ad-data[1] OCTET STRING +} +*/ + +typedef struct AuthorizationData { + unsigned int len; + struct { + int ad_type; + octet_string ad_data; + } *val; +} AuthorizationData; + +int encode_AuthorizationData(unsigned char *, size_t, const AuthorizationData *, size_t *); +int decode_AuthorizationData(const unsigned char *, size_t, AuthorizationData *, size_t *); +void free_AuthorizationData (AuthorizationData *); +size_t length_AuthorizationData(const AuthorizationData *); +int copy_AuthorizationData (const AuthorizationData *, AuthorizationData *); + + +/* +APOptions ::= BIT STRING { + reserved(0), + use-session-key(1), + mutual-required(2) +} +*/ + +typedef struct APOptions { + unsigned int reserved:1; + unsigned int use_session_key:1; + unsigned int mutual_required:1; +} APOptions; + + +int encode_APOptions(unsigned char *, size_t, const APOptions *, size_t *); +int decode_APOptions(const unsigned char *, size_t, APOptions *, size_t *); +void free_APOptions (APOptions *); +size_t length_APOptions(const APOptions *); +int copy_APOptions (const APOptions *, APOptions *); +unsigned APOptions2int(APOptions); +APOptions int2APOptions(unsigned); + +/* +TicketFlags ::= BIT STRING { + reserved(0), + forwardable(1), + forwarded(2), + proxiable(3), + proxy(4), + may-postdate(5), + postdated(6), + invalid(7), + renewable(8), + initial(9), + pre-authent(10), + hw-authent(11), + transited-policy-checked(12), + ok-as-delegate(13), + anonymous(14) +} +*/ + +typedef struct TicketFlags { + unsigned int reserved:1; + unsigned int forwardable:1; + unsigned int forwarded:1; + unsigned int proxiable:1; + unsigned int proxy:1; + unsigned int may_postdate:1; + unsigned int postdated:1; + unsigned int invalid:1; + unsigned int renewable:1; + unsigned int initial:1; + unsigned int pre_authent:1; + unsigned int hw_authent:1; + unsigned int transited_policy_checked:1; + unsigned int ok_as_delegate:1; + unsigned int anonymous:1; +} TicketFlags; + + +int encode_TicketFlags(unsigned char *, size_t, const TicketFlags *, size_t *); +int decode_TicketFlags(const unsigned char *, size_t, TicketFlags *, size_t *); +void free_TicketFlags (TicketFlags *); +size_t length_TicketFlags(const TicketFlags *); +int copy_TicketFlags (const TicketFlags *, TicketFlags *); +unsigned TicketFlags2int(TicketFlags); +TicketFlags int2TicketFlags(unsigned); + +/* +KDCOptions ::= BIT STRING { + reserved(0), + forwardable(1), + forwarded(2), + proxiable(3), + proxy(4), + allow-postdate(5), + postdated(6), + unused7(7), + renewable(8), + unused9(9), + unused10(10), + unused11(11), + request-anonymous(14), + canonicalize(15), + disable-transited-check(26), + renewable-ok(27), + enc-tkt-in-skey(28), + renew(30), + validate(31) +} +*/ + +typedef struct KDCOptions { + unsigned int reserved:1; + unsigned int forwardable:1; + unsigned int forwarded:1; + unsigned int proxiable:1; + unsigned int proxy:1; + unsigned int allow_postdate:1; + unsigned int postdated:1; + unsigned int unused7:1; + unsigned int renewable:1; + unsigned int unused9:1; + unsigned int unused10:1; + unsigned int unused11:1; + unsigned int request_anonymous:1; + unsigned int canonicalize:1; + unsigned int disable_transited_check:1; + unsigned int renewable_ok:1; + unsigned int enc_tkt_in_skey:1; + unsigned int renew:1; + unsigned int validate:1; +} KDCOptions; + + +int encode_KDCOptions(unsigned char *, size_t, const KDCOptions *, size_t *); +int decode_KDCOptions(const unsigned char *, size_t, KDCOptions *, size_t *); +void free_KDCOptions (KDCOptions *); +size_t length_KDCOptions(const KDCOptions *); +int copy_KDCOptions (const KDCOptions *, KDCOptions *); +unsigned KDCOptions2int(KDCOptions); +KDCOptions int2KDCOptions(unsigned); + +/* +LR-TYPE ::= INTEGER +*/ + +typedef enum LR_TYPE { + LR_NONE = 0, + LR_INITIAL_TGT = 1, + LR_INITIAL = 2, + LR_ISSUE_USE_TGT = 3, + LR_RENEWAL = 4, + LR_REQUEST = 5, + LR_PW_EXPTIME = 6, + LR_ACCT_EXPTIME = 7 +} LR_TYPE; + +int encode_LR_TYPE(unsigned char *, size_t, const LR_TYPE *, size_t *); +int decode_LR_TYPE(const unsigned char *, size_t, LR_TYPE *, size_t *); +void free_LR_TYPE (LR_TYPE *); +size_t length_LR_TYPE(const LR_TYPE *); +int copy_LR_TYPE (const LR_TYPE *, LR_TYPE *); + + +/* +LastReq ::= SEQUENCE OF SEQUENCE { + lr-type[0] LR-TYPE, + lr-value[1] KerberosTime +} +*/ + +typedef struct LastReq { + unsigned int len; + struct { + LR_TYPE lr_type; + KerberosTime lr_value; + } *val; +} LastReq; + +int encode_LastReq(unsigned char *, size_t, const LastReq *, size_t *); +int decode_LastReq(const unsigned char *, size_t, LastReq *, size_t *); +void free_LastReq (LastReq *); +size_t length_LastReq(const LastReq *); +int copy_LastReq (const LastReq *, LastReq *); + + +/* +EncryptedData ::= SEQUENCE { + etype[0] ENCTYPE, + kvno[1] INTEGER OPTIONAL, + cipher[2] OCTET STRING +} +*/ + +typedef struct EncryptedData { + ENCTYPE etype; + int *kvno; + octet_string cipher; +} EncryptedData; + +int encode_EncryptedData(unsigned char *, size_t, const EncryptedData *, size_t *); +int decode_EncryptedData(const unsigned char *, size_t, EncryptedData *, size_t *); +void free_EncryptedData (EncryptedData *); +size_t length_EncryptedData(const EncryptedData *); +int copy_EncryptedData (const EncryptedData *, EncryptedData *); + + +/* +EncryptionKey ::= SEQUENCE { + keytype[0] INTEGER, + keyvalue[1] OCTET STRING +} +*/ + +typedef struct EncryptionKey { + int keytype; + octet_string keyvalue; +} EncryptionKey; + +int encode_EncryptionKey(unsigned char *, size_t, const EncryptionKey *, size_t *); +int decode_EncryptionKey(const unsigned char *, size_t, EncryptionKey *, size_t *); +void free_EncryptionKey (EncryptionKey *); +size_t length_EncryptionKey(const EncryptionKey *); +int copy_EncryptionKey (const EncryptionKey *, EncryptionKey *); + + +/* +TransitedEncoding ::= SEQUENCE { + tr-type[0] INTEGER, + contents[1] OCTET STRING +} +*/ + +typedef struct TransitedEncoding { + int tr_type; + octet_string contents; +} TransitedEncoding; + +int encode_TransitedEncoding(unsigned char *, size_t, const TransitedEncoding *, size_t *); +int decode_TransitedEncoding(const unsigned char *, size_t, TransitedEncoding *, size_t *); +void free_TransitedEncoding (TransitedEncoding *); +size_t length_TransitedEncoding(const TransitedEncoding *); +int copy_TransitedEncoding (const TransitedEncoding *, TransitedEncoding *); + + +/* +Ticket ::= [APPLICATION 1] SEQUENCE { + tkt-vno[0] INTEGER, + realm[1] Realm, + sname[2] PrincipalName, + enc-part[3] EncryptedData +} +*/ + +typedef struct { + int tkt_vno; + Realm realm; + PrincipalName sname; + EncryptedData enc_part; +} Ticket; + +int encode_Ticket(unsigned char *, size_t, const Ticket *, size_t *); +int decode_Ticket(const unsigned char *, size_t, Ticket *, size_t *); +void free_Ticket (Ticket *); +size_t length_Ticket(const Ticket *); +int copy_Ticket (const Ticket *, Ticket *); + + +/* +EncTicketPart ::= [APPLICATION 3] SEQUENCE { + flags[0] TicketFlags, + key[1] EncryptionKey, + crealm[2] Realm, + cname[3] PrincipalName, + transited[4] TransitedEncoding, + authtime[5] KerberosTime, + starttime[6] KerberosTime OPTIONAL, + endtime[7] KerberosTime, + renew-till[8] KerberosTime OPTIONAL, + caddr[9] HostAddresses OPTIONAL, + authorization-data[10] AuthorizationData OPTIONAL +} +*/ + +typedef struct { + TicketFlags flags; + EncryptionKey key; + Realm crealm; + PrincipalName cname; + TransitedEncoding transited; + KerberosTime authtime; + KerberosTime *starttime; + KerberosTime endtime; + KerberosTime *renew_till; + HostAddresses *caddr; + AuthorizationData *authorization_data; +} EncTicketPart; + +int encode_EncTicketPart(unsigned char *, size_t, const EncTicketPart *, size_t *); +int decode_EncTicketPart(const unsigned char *, size_t, EncTicketPart *, size_t *); +void free_EncTicketPart (EncTicketPart *); +size_t length_EncTicketPart(const EncTicketPart *); +int copy_EncTicketPart (const EncTicketPart *, EncTicketPart *); + + +/* +Checksum ::= SEQUENCE { + cksumtype[0] CKSUMTYPE, + checksum[1] OCTET STRING +} +*/ + +typedef struct Checksum { + CKSUMTYPE cksumtype; + octet_string checksum; +} Checksum; + +int encode_Checksum(unsigned char *, size_t, const Checksum *, size_t *); +int decode_Checksum(const unsigned char *, size_t, Checksum *, size_t *); +void free_Checksum (Checksum *); +size_t length_Checksum(const Checksum *); +int copy_Checksum (const Checksum *, Checksum *); + + +/* +Authenticator ::= [APPLICATION 2] SEQUENCE { + authenticator-vno[0] INTEGER, + crealm[1] Realm, + cname[2] PrincipalName, + cksum[3] Checksum OPTIONAL, + cusec[4] INTEGER, + ctime[5] KerberosTime, + subkey[6] EncryptionKey OPTIONAL, + seq-number[7] UNSIGNED OPTIONAL, + authorization-data[8] AuthorizationData OPTIONAL +} +*/ + +typedef struct { + int authenticator_vno; + Realm crealm; + PrincipalName cname; + Checksum *cksum; + int cusec; + KerberosTime ctime; + EncryptionKey *subkey; + UNSIGNED *seq_number; + AuthorizationData *authorization_data; +} Authenticator; + +int encode_Authenticator(unsigned char *, size_t, const Authenticator *, size_t *); +int decode_Authenticator(const unsigned char *, size_t, Authenticator *, size_t *); +void free_Authenticator (Authenticator *); +size_t length_Authenticator(const Authenticator *); +int copy_Authenticator (const Authenticator *, Authenticator *); + + +/* +PA-DATA ::= SEQUENCE { + padata-type[1] PADATA-TYPE, + padata-value[2] OCTET STRING +} +*/ + +typedef struct PA_DATA { + PADATA_TYPE padata_type; + octet_string padata_value; +} PA_DATA; + +int encode_PA_DATA(unsigned char *, size_t, const PA_DATA *, size_t *); +int decode_PA_DATA(const unsigned char *, size_t, PA_DATA *, size_t *); +void free_PA_DATA (PA_DATA *); +size_t length_PA_DATA(const PA_DATA *); +int copy_PA_DATA (const PA_DATA *, PA_DATA *); + + +/* +ETYPE-INFO-ENTRY ::= SEQUENCE { + etype[0] ENCTYPE, + salt[1] OCTET STRING OPTIONAL, + salttype[2] INTEGER OPTIONAL +} +*/ + +typedef struct ETYPE_INFO_ENTRY { + ENCTYPE etype; + octet_string *salt; + int *salttype; +} ETYPE_INFO_ENTRY; + +int encode_ETYPE_INFO_ENTRY(unsigned char *, size_t, const ETYPE_INFO_ENTRY *, size_t *); +int decode_ETYPE_INFO_ENTRY(const unsigned char *, size_t, ETYPE_INFO_ENTRY *, size_t *); +void free_ETYPE_INFO_ENTRY (ETYPE_INFO_ENTRY *); +size_t length_ETYPE_INFO_ENTRY(const ETYPE_INFO_ENTRY *); +int copy_ETYPE_INFO_ENTRY (const ETYPE_INFO_ENTRY *, ETYPE_INFO_ENTRY *); + + +/* +ETYPE-INFO ::= SEQUENCE OF ETYPE-INFO-ENTRY +*/ + +typedef struct ETYPE_INFO { + unsigned int len; + ETYPE_INFO_ENTRY *val; +} ETYPE_INFO; + +int encode_ETYPE_INFO(unsigned char *, size_t, const ETYPE_INFO *, size_t *); +int decode_ETYPE_INFO(const unsigned char *, size_t, ETYPE_INFO *, size_t *); +void free_ETYPE_INFO (ETYPE_INFO *); +size_t length_ETYPE_INFO(const ETYPE_INFO *); +int copy_ETYPE_INFO (const ETYPE_INFO *, ETYPE_INFO *); + + +/* +METHOD-DATA ::= SEQUENCE OF PA-DATA +*/ + +typedef struct METHOD_DATA { + unsigned int len; + PA_DATA *val; +} METHOD_DATA; + +int encode_METHOD_DATA(unsigned char *, size_t, const METHOD_DATA *, size_t *); +int decode_METHOD_DATA(const unsigned char *, size_t, METHOD_DATA *, size_t *); +void free_METHOD_DATA (METHOD_DATA *); +size_t length_METHOD_DATA(const METHOD_DATA *); +int copy_METHOD_DATA (const METHOD_DATA *, METHOD_DATA *); + + +/* +KDC-REQ-BODY ::= SEQUENCE { + kdc-options[0] KDCOptions, + cname[1] PrincipalName OPTIONAL, + realm[2] Realm, + sname[3] PrincipalName OPTIONAL, + from[4] KerberosTime OPTIONAL, + till[5] KerberosTime OPTIONAL, + rtime[6] KerberosTime OPTIONAL, + nonce[7] INTEGER, + etype[8] SEQUENCE OF ENCTYPE, + addresses[9] HostAddresses OPTIONAL, + enc-authorization-data[10] EncryptedData OPTIONAL, + additional-tickets[11] SEQUENCE OF Ticket OPTIONAL +} +*/ + +typedef struct KDC_REQ_BODY { + KDCOptions kdc_options; + PrincipalName *cname; + Realm realm; + PrincipalName *sname; + KerberosTime *from; + KerberosTime *till; + KerberosTime *rtime; + int nonce; + struct { + unsigned int len; + ENCTYPE *val; + } etype; + HostAddresses *addresses; + EncryptedData *enc_authorization_data; + struct { + unsigned int len; + Ticket *val; + } *additional_tickets; +} KDC_REQ_BODY; + +int encode_KDC_REQ_BODY(unsigned char *, size_t, const KDC_REQ_BODY *, size_t *); +int decode_KDC_REQ_BODY(const unsigned char *, size_t, KDC_REQ_BODY *, size_t *); +void free_KDC_REQ_BODY (KDC_REQ_BODY *); +size_t length_KDC_REQ_BODY(const KDC_REQ_BODY *); +int copy_KDC_REQ_BODY (const KDC_REQ_BODY *, KDC_REQ_BODY *); + + +/* +KDC-REQ ::= SEQUENCE { + pvno[1] INTEGER, + msg-type[2] MESSAGE-TYPE, + padata[3] METHOD-DATA OPTIONAL, + req-body[4] KDC-REQ-BODY +} +*/ + +typedef struct KDC_REQ { + int pvno; + MESSAGE_TYPE msg_type; + METHOD_DATA *padata; + KDC_REQ_BODY req_body; +} KDC_REQ; + +int encode_KDC_REQ(unsigned char *, size_t, const KDC_REQ *, size_t *); +int decode_KDC_REQ(const unsigned char *, size_t, KDC_REQ *, size_t *); +void free_KDC_REQ (KDC_REQ *); +size_t length_KDC_REQ(const KDC_REQ *); +int copy_KDC_REQ (const KDC_REQ *, KDC_REQ *); + + +/* +AS-REQ ::= [APPLICATION 10] KDC-REQ +*/ + +typedef KDC_REQ AS_REQ; + +int encode_AS_REQ(unsigned char *, size_t, const AS_REQ *, size_t *); +int decode_AS_REQ(const unsigned char *, size_t, AS_REQ *, size_t *); +void free_AS_REQ (AS_REQ *); +size_t length_AS_REQ(const AS_REQ *); +int copy_AS_REQ (const AS_REQ *, AS_REQ *); + + +/* +TGS-REQ ::= [APPLICATION 12] KDC-REQ +*/ + +typedef KDC_REQ TGS_REQ; + +int encode_TGS_REQ(unsigned char *, size_t, const TGS_REQ *, size_t *); +int decode_TGS_REQ(const unsigned char *, size_t, TGS_REQ *, size_t *); +void free_TGS_REQ (TGS_REQ *); +size_t length_TGS_REQ(const TGS_REQ *); +int copy_TGS_REQ (const TGS_REQ *, TGS_REQ *); + + +/* +PA-ENC-TS-ENC ::= SEQUENCE { + patimestamp[0] KerberosTime, + pausec[1] INTEGER OPTIONAL +} +*/ + +typedef struct PA_ENC_TS_ENC { + KerberosTime patimestamp; + int *pausec; +} PA_ENC_TS_ENC; + +int encode_PA_ENC_TS_ENC(unsigned char *, size_t, const PA_ENC_TS_ENC *, size_t *); +int decode_PA_ENC_TS_ENC(const unsigned char *, size_t, PA_ENC_TS_ENC *, size_t *); +void free_PA_ENC_TS_ENC (PA_ENC_TS_ENC *); +size_t length_PA_ENC_TS_ENC(const PA_ENC_TS_ENC *); +int copy_PA_ENC_TS_ENC (const PA_ENC_TS_ENC *, PA_ENC_TS_ENC *); + + +/* +KDC-REP ::= SEQUENCE { + pvno[0] INTEGER, + msg-type[1] MESSAGE-TYPE, + padata[2] METHOD-DATA OPTIONAL, + crealm[3] Realm, + cname[4] PrincipalName, + ticket[5] Ticket, + enc-part[6] EncryptedData +} +*/ + +typedef struct KDC_REP { + int pvno; + MESSAGE_TYPE msg_type; + METHOD_DATA *padata; + Realm crealm; + PrincipalName cname; + Ticket ticket; + EncryptedData enc_part; +} KDC_REP; + +int encode_KDC_REP(unsigned char *, size_t, const KDC_REP *, size_t *); +int decode_KDC_REP(const unsigned char *, size_t, KDC_REP *, size_t *); +void free_KDC_REP (KDC_REP *); +size_t length_KDC_REP(const KDC_REP *); +int copy_KDC_REP (const KDC_REP *, KDC_REP *); + + +/* +AS-REP ::= [APPLICATION 11] KDC-REP +*/ + +typedef KDC_REP AS_REP; + +int encode_AS_REP(unsigned char *, size_t, const AS_REP *, size_t *); +int decode_AS_REP(const unsigned char *, size_t, AS_REP *, size_t *); +void free_AS_REP (AS_REP *); +size_t length_AS_REP(const AS_REP *); +int copy_AS_REP (const AS_REP *, AS_REP *); + + +/* +TGS-REP ::= [APPLICATION 13] KDC-REP +*/ + +typedef KDC_REP TGS_REP; + +int encode_TGS_REP(unsigned char *, size_t, const TGS_REP *, size_t *); +int decode_TGS_REP(const unsigned char *, size_t, TGS_REP *, size_t *); +void free_TGS_REP (TGS_REP *); +size_t length_TGS_REP(const TGS_REP *); +int copy_TGS_REP (const TGS_REP *, TGS_REP *); + + +/* +EncKDCRepPart ::= SEQUENCE { + key[0] EncryptionKey, + last-req[1] LastReq, + nonce[2] INTEGER, + key-expiration[3] KerberosTime OPTIONAL, + flags[4] TicketFlags, + authtime[5] KerberosTime, + starttime[6] KerberosTime OPTIONAL, + endtime[7] KerberosTime, + renew-till[8] KerberosTime OPTIONAL, + srealm[9] Realm, + sname[10] PrincipalName, + caddr[11] HostAddresses OPTIONAL +} +*/ + +typedef struct EncKDCRepPart { + EncryptionKey key; + LastReq last_req; + int nonce; + KerberosTime *key_expiration; + TicketFlags flags; + KerberosTime authtime; + KerberosTime *starttime; + KerberosTime endtime; + KerberosTime *renew_till; + Realm srealm; + PrincipalName sname; + HostAddresses *caddr; +} EncKDCRepPart; + +int encode_EncKDCRepPart(unsigned char *, size_t, const EncKDCRepPart *, size_t *); +int decode_EncKDCRepPart(const unsigned char *, size_t, EncKDCRepPart *, size_t *); +void free_EncKDCRepPart (EncKDCRepPart *); +size_t length_EncKDCRepPart(const EncKDCRepPart *); +int copy_EncKDCRepPart (const EncKDCRepPart *, EncKDCRepPart *); + + +/* +EncASRepPart ::= [APPLICATION 25] EncKDCRepPart +*/ + +typedef EncKDCRepPart EncASRepPart; + +int encode_EncASRepPart(unsigned char *, size_t, const EncASRepPart *, size_t *); +int decode_EncASRepPart(const unsigned char *, size_t, EncASRepPart *, size_t *); +void free_EncASRepPart (EncASRepPart *); +size_t length_EncASRepPart(const EncASRepPart *); +int copy_EncASRepPart (const EncASRepPart *, EncASRepPart *); + + +/* +EncTGSRepPart ::= [APPLICATION 26] EncKDCRepPart +*/ + +typedef EncKDCRepPart EncTGSRepPart; + +int encode_EncTGSRepPart(unsigned char *, size_t, const EncTGSRepPart *, size_t *); +int decode_EncTGSRepPart(const unsigned char *, size_t, EncTGSRepPart *, size_t *); +void free_EncTGSRepPart (EncTGSRepPart *); +size_t length_EncTGSRepPart(const EncTGSRepPart *); +int copy_EncTGSRepPart (const EncTGSRepPart *, EncTGSRepPart *); + + +/* +AP-REQ ::= [APPLICATION 14] SEQUENCE { + pvno[0] INTEGER, + msg-type[1] MESSAGE-TYPE, + ap-options[2] APOptions, + ticket[3] Ticket, + authenticator[4] EncryptedData +} +*/ + +typedef struct { + int pvno; + MESSAGE_TYPE msg_type; + APOptions ap_options; + Ticket ticket; + EncryptedData authenticator; +} AP_REQ; + +int encode_AP_REQ(unsigned char *, size_t, const AP_REQ *, size_t *); +int decode_AP_REQ(const unsigned char *, size_t, AP_REQ *, size_t *); +void free_AP_REQ (AP_REQ *); +size_t length_AP_REQ(const AP_REQ *); +int copy_AP_REQ (const AP_REQ *, AP_REQ *); + + +/* +AP-REP ::= [APPLICATION 15] SEQUENCE { + pvno[0] INTEGER, + msg-type[1] MESSAGE-TYPE, + enc-part[2] EncryptedData +} +*/ + +typedef struct { + int pvno; + MESSAGE_TYPE msg_type; + EncryptedData enc_part; +} AP_REP; + +int encode_AP_REP(unsigned char *, size_t, const AP_REP *, size_t *); +int decode_AP_REP(const unsigned char *, size_t, AP_REP *, size_t *); +void free_AP_REP (AP_REP *); +size_t length_AP_REP(const AP_REP *); +int copy_AP_REP (const AP_REP *, AP_REP *); + + +/* +EncAPRepPart ::= [APPLICATION 27] SEQUENCE { + ctime[0] KerberosTime, + cusec[1] INTEGER, + subkey[2] EncryptionKey OPTIONAL, + seq-number[3] UNSIGNED OPTIONAL +} +*/ + +typedef struct { + KerberosTime ctime; + int cusec; + EncryptionKey *subkey; + UNSIGNED *seq_number; +} EncAPRepPart; + +int encode_EncAPRepPart(unsigned char *, size_t, const EncAPRepPart *, size_t *); +int decode_EncAPRepPart(const unsigned char *, size_t, EncAPRepPart *, size_t *); +void free_EncAPRepPart (EncAPRepPart *); +size_t length_EncAPRepPart(const EncAPRepPart *); +int copy_EncAPRepPart (const EncAPRepPart *, EncAPRepPart *); + + +/* +KRB-SAFE-BODY ::= SEQUENCE { + user-data[0] OCTET STRING, + timestamp[1] KerberosTime OPTIONAL, + usec[2] INTEGER OPTIONAL, + seq-number[3] UNSIGNED OPTIONAL, + s-address[4] HostAddress OPTIONAL, + r-address[5] HostAddress OPTIONAL +} +*/ + +typedef struct KRB_SAFE_BODY { + octet_string user_data; + KerberosTime *timestamp; + int *usec; + UNSIGNED *seq_number; + HostAddress *s_address; + HostAddress *r_address; +} KRB_SAFE_BODY; + +int encode_KRB_SAFE_BODY(unsigned char *, size_t, const KRB_SAFE_BODY *, size_t *); +int decode_KRB_SAFE_BODY(const unsigned char *, size_t, KRB_SAFE_BODY *, size_t *); +void free_KRB_SAFE_BODY (KRB_SAFE_BODY *); +size_t length_KRB_SAFE_BODY(const KRB_SAFE_BODY *); +int copy_KRB_SAFE_BODY (const KRB_SAFE_BODY *, KRB_SAFE_BODY *); + + +/* +KRB-SAFE ::= [APPLICATION 20] SEQUENCE { + pvno[0] INTEGER, + msg-type[1] MESSAGE-TYPE, + safe-body[2] KRB-SAFE-BODY, + cksum[3] Checksum +} +*/ + +typedef struct { + int pvno; + MESSAGE_TYPE msg_type; + KRB_SAFE_BODY safe_body; + Checksum cksum; +} KRB_SAFE; + +int encode_KRB_SAFE(unsigned char *, size_t, const KRB_SAFE *, size_t *); +int decode_KRB_SAFE(const unsigned char *, size_t, KRB_SAFE *, size_t *); +void free_KRB_SAFE (KRB_SAFE *); +size_t length_KRB_SAFE(const KRB_SAFE *); +int copy_KRB_SAFE (const KRB_SAFE *, KRB_SAFE *); + + +/* +KRB-PRIV ::= [APPLICATION 21] SEQUENCE { + pvno[0] INTEGER, + msg-type[1] MESSAGE-TYPE, + enc-part[3] EncryptedData +} +*/ + +typedef struct { + int pvno; + MESSAGE_TYPE msg_type; + EncryptedData enc_part; +} KRB_PRIV; + +int encode_KRB_PRIV(unsigned char *, size_t, const KRB_PRIV *, size_t *); +int decode_KRB_PRIV(const unsigned char *, size_t, KRB_PRIV *, size_t *); +void free_KRB_PRIV (KRB_PRIV *); +size_t length_KRB_PRIV(const KRB_PRIV *); +int copy_KRB_PRIV (const KRB_PRIV *, KRB_PRIV *); + + +/* +EncKrbPrivPart ::= [APPLICATION 28] SEQUENCE { + user-data[0] OCTET STRING, + timestamp[1] KerberosTime OPTIONAL, + usec[2] INTEGER OPTIONAL, + seq-number[3] UNSIGNED OPTIONAL, + s-address[4] HostAddress OPTIONAL, + r-address[5] HostAddress OPTIONAL +} +*/ + +typedef struct { + octet_string user_data; + KerberosTime *timestamp; + int *usec; + UNSIGNED *seq_number; + HostAddress *s_address; + HostAddress *r_address; +} EncKrbPrivPart; + +int encode_EncKrbPrivPart(unsigned char *, size_t, const EncKrbPrivPart *, size_t *); +int decode_EncKrbPrivPart(const unsigned char *, size_t, EncKrbPrivPart *, size_t *); +void free_EncKrbPrivPart (EncKrbPrivPart *); +size_t length_EncKrbPrivPart(const EncKrbPrivPart *); +int copy_EncKrbPrivPart (const EncKrbPrivPart *, EncKrbPrivPart *); + + +/* +KRB-CRED ::= [APPLICATION 22] SEQUENCE { + pvno[0] INTEGER, + msg-type[1] MESSAGE-TYPE, + tickets[2] SEQUENCE OF Ticket, + enc-part[3] EncryptedData +} +*/ + +typedef struct { + int pvno; + MESSAGE_TYPE msg_type; + struct { + unsigned int len; + Ticket *val; + } tickets; + EncryptedData enc_part; +} KRB_CRED; + +int encode_KRB_CRED(unsigned char *, size_t, const KRB_CRED *, size_t *); +int decode_KRB_CRED(const unsigned char *, size_t, KRB_CRED *, size_t *); +void free_KRB_CRED (KRB_CRED *); +size_t length_KRB_CRED(const KRB_CRED *); +int copy_KRB_CRED (const KRB_CRED *, KRB_CRED *); + + +/* +KrbCredInfo ::= SEQUENCE { + key[0] EncryptionKey, + prealm[1] Realm OPTIONAL, + pname[2] PrincipalName OPTIONAL, + flags[3] TicketFlags OPTIONAL, + authtime[4] KerberosTime OPTIONAL, + starttime[5] KerberosTime OPTIONAL, + endtime[6] KerberosTime OPTIONAL, + renew-till[7] KerberosTime OPTIONAL, + srealm[8] Realm OPTIONAL, + sname[9] PrincipalName OPTIONAL, + caddr[10] HostAddresses OPTIONAL +} +*/ + +typedef struct KrbCredInfo { + EncryptionKey key; + Realm *prealm; + PrincipalName *pname; + TicketFlags *flags; + KerberosTime *authtime; + KerberosTime *starttime; + KerberosTime *endtime; + KerberosTime *renew_till; + Realm *srealm; + PrincipalName *sname; + HostAddresses *caddr; +} KrbCredInfo; + +int encode_KrbCredInfo(unsigned char *, size_t, const KrbCredInfo *, size_t *); +int decode_KrbCredInfo(const unsigned char *, size_t, KrbCredInfo *, size_t *); +void free_KrbCredInfo (KrbCredInfo *); +size_t length_KrbCredInfo(const KrbCredInfo *); +int copy_KrbCredInfo (const KrbCredInfo *, KrbCredInfo *); + + +/* +EncKrbCredPart ::= [APPLICATION 29] SEQUENCE { + ticket-info[0] SEQUENCE OF KrbCredInfo, + nonce[1] INTEGER OPTIONAL, + timestamp[2] KerberosTime OPTIONAL, + usec[3] INTEGER OPTIONAL, + s-address[4] HostAddress OPTIONAL, + r-address[5] HostAddress OPTIONAL +} +*/ + +typedef struct { + struct { + unsigned int len; + KrbCredInfo *val; + } ticket_info; + int *nonce; + KerberosTime *timestamp; + int *usec; + HostAddress *s_address; + HostAddress *r_address; +} EncKrbCredPart; + +int encode_EncKrbCredPart(unsigned char *, size_t, const EncKrbCredPart *, size_t *); +int decode_EncKrbCredPart(const unsigned char *, size_t, EncKrbCredPart *, size_t *); +void free_EncKrbCredPart (EncKrbCredPart *); +size_t length_EncKrbCredPart(const EncKrbCredPart *); +int copy_EncKrbCredPart (const EncKrbCredPart *, EncKrbCredPart *); + + +/* +KRB-ERROR ::= [APPLICATION 30] SEQUENCE { + pvno[0] INTEGER, + msg-type[1] MESSAGE-TYPE, + ctime[2] KerberosTime OPTIONAL, + cusec[3] INTEGER OPTIONAL, + stime[4] KerberosTime, + susec[5] INTEGER, + error-code[6] INTEGER, + crealm[7] Realm OPTIONAL, + cname[8] PrincipalName OPTIONAL, + realm[9] Realm, + sname[10] PrincipalName, + e-text[11] GeneralString OPTIONAL, + e-data[12] OCTET STRING OPTIONAL +} +*/ + +typedef struct { + int pvno; + MESSAGE_TYPE msg_type; + KerberosTime *ctime; + int *cusec; + KerberosTime stime; + int susec; + int error_code; + Realm *crealm; + PrincipalName *cname; + Realm realm; + PrincipalName sname; + general_string *e_text; + octet_string *e_data; +} KRB_ERROR; + +int encode_KRB_ERROR(unsigned char *, size_t, const KRB_ERROR *, size_t *); +int decode_KRB_ERROR(const unsigned char *, size_t, KRB_ERROR *, size_t *); +void free_KRB_ERROR (KRB_ERROR *); +size_t length_KRB_ERROR(const KRB_ERROR *); +int copy_KRB_ERROR (const KRB_ERROR *, KRB_ERROR *); + + +enum { pvno = 5 }; + +enum { DOMAIN_X500_COMPRESS = 1 }; + +#endif /* __krb5_asn1_h__ */