====================

This delta was composed from multiple commits as part of the CVS->Git migration.
The checkin message with each commit was inconsistent.
The following are the additional commit messages.
====================


Various improvements to make new rxkad build and pass the stress test:
- Removed rxi_Alloc and memcpy hacks not needed in openafs.
- Fixed build problems resulting from new prototyping work in the
  rest of openafs.
- Fixed a bug in tkt_CheckTimes (arla folks probably want this).
- Made rxkad_GetServerInfo actually return the kvno.

====================


Added -usetokens switch to make the rxkad stress test use existing tokens
instead of printing its own ticket.  This is useful for V5 and 2B testing.
Also changed the test realm name and key to facilitate testing.

====================


Some work integrating new rxkad into the tree.
Prototype cleanup for new rxkad.
More fixes to the rxkad stress test.

====================

Added missing rxkad.h that was inadvertently not committed.
Also removed the .cvsignore entry that caused me to miss it before.

====================

Committed missing rxkad.h; this time for sure
This commit is contained in:
Love Hörnquist-Åstrand 2002-08-27 20:19:37 +00:00 committed by Jeffrey Hutzleman
parent 8e66ec5e01
commit 00d5764eec
38 changed files with 9360 additions and 2129 deletions

View File

@ -80,8 +80,6 @@ RCSID("$Header$");
#ifdef AFS_KERBEROS_ENV
#include <fcntl.h>
#include <sys/file.h>
extern afs_uint32 life_to_time();
extern unsigned char time_to_life();
#include "cellconfig.h"
static char lcell[MAXCELLCHARS];

View File

@ -3,7 +3,6 @@ Makefile
crypt_conn.c
fcrypt.c
fcrypt.h
rxkad.h
rxkad_errs.c
sboxes.h
fc_test

View File

@ -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

View File

@ -1,2 +0,0 @@
NOTE: fc_cbc_encrypt now modifies its 5th argument, to permit chaining over
scatter/gather vectors.

21
src/rxkad/asn1-common.h Normal file
View File

@ -0,0 +1,21 @@
/* $Id$ */
#include <stddef.h>
#include <time.h>
#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

23
src/rxkad/asn1_err.h Normal file
View File

@ -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__ */

71
src/rxkad/crc.c Normal file
View File

@ -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;
}

152
src/rxkad/der.h Normal file
View File

@ -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 <time.h>
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__ */

54
src/rxkad/der_free.c Normal file
View File

@ -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);
}

478
src/rxkad/der_get.c Normal file
View File

@ -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 <version.h>
/*
* 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;
}

418
src/rxkad/der_put.c Normal file
View File

@ -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;
}

View File

@ -32,13 +32,10 @@
*/
#include <afs/param.h>
#include "rxkad.h"
#include "rxkad_locl.h"
#include <rx/rx.h>
#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");

View File

@ -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 */

View File

@ -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;
};
/* <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;
};
/* <ticketLen> bytes of ticket follow here */
#if RX_MAXCALLS != 4
The above structure requires that (RX_MAXCALLS == 4).
#endif
#endif /* RXKAD_PRIVATE_DATA_H */

330
src/rxkad/rxk_clnt.c Normal file
View File

@ -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;
}

775
src/rxkad/rxk_crpt.c Normal file
View File

@ -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 <sys/types.h>
# include <sys/param.h>
# 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)-1); \
lo = (lo >> n) | ((hi & ((1<<n)-1)) << (32-n)); \
hi = (hi >> n) | (t << (24-n)); }
/* Rotate one 64 bit number as a 56 bit number */
#define ROT56R64(k, n) { \
k = (k >> n) | ((k & ((1<<n) - 1)) << (56-n)); }
/*
* Generate a key schedule from key, the least significant bit in each
* key byte is parity and shall be ignored. This leaves 56 significant
* bits in the key to scatter over the 16 key schedules. For each
* schedule extract the low order 32 bits and use as schedule, then
* rotate right by 11 bits.
*
* Note that this fc_keysched() generates a schedule in natural byte
* order, the Transarc function does not. Therefore it's *not*
* possible to mix fc_keysched, fc_ecb_encrypt and fc_cbc_encrypt
* from different implementations. Keep them in the same module!
*/
int
fc_keysched(const void *key_,
afs_int32 sched[ROUNDS])
{
const unsigned char *key = key_;
/* Do we have 56 bit longs or even longer longs? */
#if ((1ul << 31) << 1) && defined(ULONG_MAX) && ((ULONG_MAX >> 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 <stdio.h>
#include <string.h>
#include <time.h>
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 */

69
src/rxkad/rxk_info.c Normal file
View File

@ -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;
}

272
src/rxkad/rxk_locl.c Normal file
View File

@ -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;
}

452
src/rxkad/rxk_serv.c Normal file
View File

@ -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 <krb5.h>
#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;
}

119
src/rxkad/rxkad.h Normal file
View File

@ -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 */

View File

@ -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 <pthread.h>
#include <assert.h>
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 */

View File

@ -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 <afsconfig.h>
#ifdef KERNEL
#include "../afs/param.h"
#else
#include <afs/param.h>
#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 <afs/stds.h>
#include <sys/types.h>
#include <time.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#else
#include <netinet/in.h>
#endif
#include <rx/rx.h>
#include <rx/xdr.h>
#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 <assert.h>
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<<RX_CIDSHIFT;
UNLOCK_CUID
return 0;
}
/* Allocate a new client security object. Called with the encryption level,
* the session key and the ticket for the other side obtained from the
* AuthServer. Refers to export control to determine level. */
struct rx_securityClass *rxkad_NewClientSecurityObject(
rxkad_level level, struct ktc_encryptionKey *sessionkey,
afs_int32 kvno, int ticketLen, char *ticket)
{ struct rx_securityClass *tsc;
struct rxkad_cprivate *tcp;
int code;
int size;
size = sizeof(struct rx_securityClass);
tsc = (struct rx_securityClass *) rxi_Alloc (size);
memset((void *)tsc, 0, size);
tsc->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; i<RX_MAXCALLS; i++) {
if (r_v2.encrypted.callNumbers[i] < 0) return RXKADINCONSISTENCY;
r_v2.encrypted.callNumbers[i] = htonl(r_v2.encrypted.callNumbers[i]);
}
r_v2.encrypted.incChallengeID = htonl(challengeID + 1);
r_v2.encrypted.level = htonl((afs_int32)tcp->level);
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
}

View File

@ -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 <afsconfig.h>
#ifdef KERNEL
#include "../afs/param.h"
#else
#include <afs/param.h>
#endif
#ifdef AFS_SUN59_ENV
#include <sys/time_impl.h>
#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 <afs/stds.h>
#include <sys/types.h>
#include <time.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#ifdef AFS_PTHREAD_ENV
#define RXKAD_STATS_DECLSPEC __declspec(dllexport)
#endif
#else
#include <netinet/in.h>
#endif
#include <rx/rx.h>
#include <rx/xdr.h>
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#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; i<sizeof(*v2r); i++)
cksum = (*cp++) + cksum * 0x10204081;
v2r->encrypted.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;
}

229
src/rxkad/rxkad_locl.h Normal file
View File

@ -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 <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/types.h>
#include <netinet/in.h>
#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 <des.h>
#undef RCSID
#include <rx/rx.h>
#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 */

View File

@ -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 */

View File

@ -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 <afsconfig.h>
#include <afs/param.h>
RCSID("$Header$");
#include <afs/stds.h>
#include <sys/types.h>
#include <time.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#else
#include <netinet/in.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#include <rx/rx.h>
#include <rx/xdr.h>
#include <des.h>
#include <afs/afsutil.h>
#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 <assert.h>
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; i<RX_MAXCALLS; i++) {
v2r.encrypted.callNumbers[i] = ntohl(v2r.encrypted.callNumbers[i]);
if (v2r.encrypted.callNumbers[i] < 0) return RXKADSEALEDINCON;
}
(void) rxi_SetCallNumberVector (aconn, v2r.encrypted.callNumbers);
incChallengeID = ntohl(v2r.encrypted.incChallengeID);
level = ntohl(v2r.encrypted.level);
} else {
/* expect old format response */
fc_ecb_encrypt(&oldr.encrypted, &oldr.encrypted,
sconn->keysched, 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;
}

View File

@ -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 \

View File

@ -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);

View File

@ -26,6 +26,7 @@ RCSID("$Header$");
#include <afs/com_err.h>
#include <afs/afsutil.h>
#include <rx/rxkad.h>
#include <afs/auth.h>
#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 */

View File

@ -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

View File

@ -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;

View File

@ -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 <afsconfig.h>
#if defined(UKERNEL)
#include "../afs/param.h"
#else
#include <afs/param.h>
#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 <afs/stds.h>
#include <sys/types.h>
#ifdef AFS_NT40_ENV
#include <winsock2.h>
#else
#include <netinet/in.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#else
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
#endif
#include <rx/xdr.h>
#include <rx/rx.h>
#include <des.h>
#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<TKTLIFENUMFIXED; i++)
if (tkt_lifetimes[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;
}

397
src/rxkad/v4.c Normal file
View File

@ -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<TKTLIFENUMFIXED; i++)
if (tkt_lifetimes[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);
}

355
src/rxkad/v5.c Normal file
View File

@ -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
* <bg@sics.se> 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 <errno.h>';
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 <version.h>' \
| 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 <krb5_asn1.h>' \
| grep -v 'include <der.h>' \
| grep -v 'include <parse_units.h>' \
| 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;
}

1168
src/rxkad/v5der.c Normal file

File diff suppressed because it is too large Load Diff

122
src/rxkad/v5gen-rewrite.h Normal file
View File

@ -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

2490
src/rxkad/v5gen.c Normal file

File diff suppressed because it is too large Load Diff

1257
src/rxkad/v5gen.h Normal file

File diff suppressed because it is too large Load Diff