From 16f56ac4cd45685e9261760778b448e15ba8b27b Mon Sep 17 00:00:00 2001 From: Assar Westerlund Date: Sun, 13 Apr 1997 22:18:46 +0000 Subject: [PATCH] new files git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@1579 ec53bebd-3082-4978-b11e-865c3cabbd6b --- lib/des/md5.c | 305 +++++++++++ lib/des/md5.h | 88 ++++ lib/des/sha.c | 304 +++++++++++ lib/des/sha.h | 59 +++ lib/gssapi/Makefile.am | 18 + lib/gssapi/accept_sec_context.c | 132 +++++ lib/gssapi/add_oid_set_member.c | 21 + lib/gssapi/create_emtpy_oid_set.c | 17 + lib/gssapi/decapsulate.c | 36 ++ lib/gssapi/delete_sec_context.c | 24 + lib/gssapi/display_name.c | 32 ++ lib/gssapi/duplicate_name.c | 22 + lib/gssapi/encapsulate.c | 33 ++ lib/gssapi/external.c | 172 ++++++ lib/gssapi/get_mic.c | 58 +++ lib/gssapi/gssapi.h | 693 +++++++++++++++++++++++++ lib/gssapi/gssapi_locl.h | 30 ++ lib/gssapi/import_name.c | 36 ++ lib/gssapi/indicate_mechs.c | 22 + lib/gssapi/init.c | 15 + lib/gssapi/init_sec_context.c | 312 +++++++++++ lib/gssapi/inquire_context.c | 51 ++ lib/gssapi/krb5/Makefile.am | 18 + lib/gssapi/krb5/accept_sec_context.c | 132 +++++ lib/gssapi/krb5/add_oid_set_member.c | 21 + lib/gssapi/krb5/create_emtpy_oid_set.c | 17 + lib/gssapi/krb5/decapsulate.c | 36 ++ lib/gssapi/krb5/delete_sec_context.c | 24 + lib/gssapi/krb5/display_name.c | 32 ++ lib/gssapi/krb5/duplicate_name.c | 22 + lib/gssapi/krb5/encapsulate.c | 33 ++ lib/gssapi/krb5/external.c | 172 ++++++ lib/gssapi/krb5/get_mic.c | 58 +++ lib/gssapi/krb5/gssapi.h | 693 +++++++++++++++++++++++++ lib/gssapi/krb5/gssapi_locl.h | 30 ++ lib/gssapi/krb5/import_name.c | 36 ++ lib/gssapi/krb5/indicate_mechs.c | 22 + lib/gssapi/krb5/init.c | 15 + lib/gssapi/krb5/init_sec_context.c | 312 +++++++++++ lib/gssapi/krb5/inquire_context.c | 51 ++ lib/gssapi/krb5/release_buffer.c | 13 + lib/gssapi/krb5/release_oid_set.c | 13 + lib/gssapi/krb5/test_oid_set_member.c | 24 + lib/gssapi/krb5/unwrap.c | 69 +++ lib/gssapi/krb5/verify_mic.c | 59 +++ lib/gssapi/krb5/wrap.c | 63 +++ lib/gssapi/release_buffer.c | 13 + lib/gssapi/release_oid_set.c | 13 + lib/gssapi/test_oid_set_member.c | 24 + lib/gssapi/unwrap.c | 69 +++ lib/gssapi/verify_mic.c | 59 +++ lib/gssapi/wrap.c | 63 +++ 52 files changed, 4686 insertions(+) create mode 100644 lib/des/md5.c create mode 100644 lib/des/md5.h create mode 100644 lib/des/sha.c create mode 100644 lib/des/sha.h create mode 100644 lib/gssapi/Makefile.am create mode 100644 lib/gssapi/accept_sec_context.c create mode 100644 lib/gssapi/add_oid_set_member.c create mode 100644 lib/gssapi/create_emtpy_oid_set.c create mode 100644 lib/gssapi/decapsulate.c create mode 100644 lib/gssapi/delete_sec_context.c create mode 100644 lib/gssapi/display_name.c create mode 100644 lib/gssapi/duplicate_name.c create mode 100644 lib/gssapi/encapsulate.c create mode 100644 lib/gssapi/external.c create mode 100644 lib/gssapi/get_mic.c create mode 100644 lib/gssapi/gssapi.h create mode 100644 lib/gssapi/gssapi_locl.h create mode 100644 lib/gssapi/import_name.c create mode 100644 lib/gssapi/indicate_mechs.c create mode 100644 lib/gssapi/init.c create mode 100644 lib/gssapi/init_sec_context.c create mode 100644 lib/gssapi/inquire_context.c create mode 100644 lib/gssapi/krb5/Makefile.am create mode 100644 lib/gssapi/krb5/accept_sec_context.c create mode 100644 lib/gssapi/krb5/add_oid_set_member.c create mode 100644 lib/gssapi/krb5/create_emtpy_oid_set.c create mode 100644 lib/gssapi/krb5/decapsulate.c create mode 100644 lib/gssapi/krb5/delete_sec_context.c create mode 100644 lib/gssapi/krb5/display_name.c create mode 100644 lib/gssapi/krb5/duplicate_name.c create mode 100644 lib/gssapi/krb5/encapsulate.c create mode 100644 lib/gssapi/krb5/external.c create mode 100644 lib/gssapi/krb5/get_mic.c create mode 100644 lib/gssapi/krb5/gssapi.h create mode 100644 lib/gssapi/krb5/gssapi_locl.h create mode 100644 lib/gssapi/krb5/import_name.c create mode 100644 lib/gssapi/krb5/indicate_mechs.c create mode 100644 lib/gssapi/krb5/init.c create mode 100644 lib/gssapi/krb5/init_sec_context.c create mode 100644 lib/gssapi/krb5/inquire_context.c create mode 100644 lib/gssapi/krb5/release_buffer.c create mode 100644 lib/gssapi/krb5/release_oid_set.c create mode 100644 lib/gssapi/krb5/test_oid_set_member.c create mode 100644 lib/gssapi/krb5/unwrap.c create mode 100644 lib/gssapi/krb5/verify_mic.c create mode 100644 lib/gssapi/krb5/wrap.c create mode 100644 lib/gssapi/release_buffer.c create mode 100644 lib/gssapi/release_oid_set.c create mode 100644 lib/gssapi/test_oid_set_member.c create mode 100644 lib/gssapi/unwrap.c create mode 100644 lib/gssapi/verify_mic.c create mode 100644 lib/gssapi/wrap.c diff --git a/lib/des/md5.c b/lib/des/md5.c new file mode 100644 index 000000000..fece5cb0b --- /dev/null +++ b/lib/des/md5.c @@ -0,0 +1,305 @@ +/* + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" + +RCSID("$Id$"); +#endif + +#include +#include + +#include "md5.h" + +#ifndef min +#define min(a,b) (((a)>(b))?(b):(a)) +#endif + +#define A m->counter[0] +#define B m->counter[1] +#define C m->counter[2] +#define D m->counter[3] +#define X data + +void +md5_init (struct md5 *m) +{ + m->offset = 0; + m->sz = 0; + D = 0x10325476; + C = 0x98badcfe; + B = 0xefcdab89; + A = 0x67452301; +} + +static u_int32_t +cshift (u_int32_t x, unsigned n) +{ + return (x << n) | (x >> (32 - n)); +} + +#define F(x,y,z) ((x & y) | (~x & z)) +#define G(x,y,z) ((x & z) | (y & ~z)) +#define H(x,y,z) (x ^ y ^ z) +#define I(x,y,z) (y ^ (x | ~z)) + +#define DOIT(a,b,c,d,k,s,i,OP) \ +a = b + cshift(a + OP(b,c,d) + X[k] + (i), s) + +#define DO1(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,F) +#define DO2(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,G) +#define DO3(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,H) +#define DO4(a,b,c,d,k,s,i) DOIT(a,b,c,d,k,s,i,I) + +static void +calc (struct md5 *m, u_int32_t *data) +{ + u_int32_t AA, BB, CC, DD; + + AA = A; + BB = B; + CC = C; + DD = D; + + /* Round 1 */ + + DO1(A,B,C,D,0,7,0xd76aa478); + DO1(D,A,B,C,1,12,0xe8c7b756); + DO1(C,D,A,B,2,17,0x242070db); + DO1(B,C,D,A,3,22,0xc1bdceee); + + DO1(A,B,C,D,4,7,0xf57c0faf); + DO1(D,A,B,C,5,12,0x4787c62a); + DO1(C,D,A,B,6,17,0xa8304613); + DO1(B,C,D,A,7,22,0xfd469501); + + DO1(A,B,C,D,8,7,0x698098d8); + DO1(D,A,B,C,9,12,0x8b44f7af); + DO1(C,D,A,B,10,17,0xffff5bb1); + DO1(B,C,D,A,11,22,0x895cd7be); + + DO1(A,B,C,D,12,7,0x6b901122); + DO1(D,A,B,C,13,12,0xfd987193); + DO1(C,D,A,B,14,17,0xa679438e); + DO1(B,C,D,A,15,22,0x49b40821); + + /* Round 2 */ + + DO2(A,B,C,D,1,5,0xf61e2562); + DO2(D,A,B,C,6,9,0xc040b340); + DO2(C,D,A,B,11,14,0x265e5a51); + DO2(B,C,D,A,0,20,0xe9b6c7aa); + + DO2(A,B,C,D,5,5,0xd62f105d); + DO2(D,A,B,C,10,9,0x2441453); + DO2(C,D,A,B,15,14,0xd8a1e681); + DO2(B,C,D,A,4,20,0xe7d3fbc8); + + DO2(A,B,C,D,9,5,0x21e1cde6); + DO2(D,A,B,C,14,9,0xc33707d6); + DO2(C,D,A,B,3,14,0xf4d50d87); + DO2(B,C,D,A,8,20,0x455a14ed); + + DO2(A,B,C,D,13,5,0xa9e3e905); + DO2(D,A,B,C,2,9,0xfcefa3f8); + DO2(C,D,A,B,7,14,0x676f02d9); + DO2(B,C,D,A,12,20,0x8d2a4c8a); + + /* Round 3 */ + + DO3(A,B,C,D,5,4,0xfffa3942); + DO3(D,A,B,C,8,11,0x8771f681); + DO3(C,D,A,B,11,16,0x6d9d6122); + DO3(B,C,D,A,14,23,0xfde5380c); + + DO3(A,B,C,D,1,4,0xa4beea44); + DO3(D,A,B,C,4,11,0x4bdecfa9); + DO3(C,D,A,B,7,16,0xf6bb4b60); + DO3(B,C,D,A,10,23,0xbebfbc70); + + DO3(A,B,C,D,13,4,0x289b7ec6); + DO3(D,A,B,C,0,11,0xeaa127fa); + DO3(C,D,A,B,3,16,0xd4ef3085); + DO3(B,C,D,A,6,23,0x4881d05); + + DO3(A,B,C,D,9,4,0xd9d4d039); + DO3(D,A,B,C,12,11,0xe6db99e5); + DO3(C,D,A,B,15,16,0x1fa27cf8); + DO3(B,C,D,A,2,23,0xc4ac5665); + + /* Round 4 */ + + DO4(A,B,C,D,0,6,0xf4292244); + DO4(D,A,B,C,7,10,0x432aff97); + DO4(C,D,A,B,14,15,0xab9423a7); + DO4(B,C,D,A,5,21,0xfc93a039); + + DO4(A,B,C,D,12,6,0x655b59c3); + DO4(D,A,B,C,3,10,0x8f0ccc92); + DO4(C,D,A,B,10,15,0xffeff47d); + DO4(B,C,D,A,1,21,0x85845dd1); + + DO4(A,B,C,D,8,6,0x6fa87e4f); + DO4(D,A,B,C,15,10,0xfe2ce6e0); + DO4(C,D,A,B,6,15,0xa3014314); + DO4(B,C,D,A,13,21,0x4e0811a1); + + DO4(A,B,C,D,4,6,0xf7537e82); + DO4(D,A,B,C,11,10,0xbd3af235); + DO4(C,D,A,B,2,15,0x2ad7d2bb); + DO4(B,C,D,A,9,21,0xeb86d391); + + A += AA; + B += BB; + C += CC; + D += DD; +} + +/* + * From `Performance analysis of MD5' by Joseph D. Touch + */ + +static u_int32_t +swap_u_int32_t (u_int32_t t) +{ +#if defined(WORDS_BIGENDIAN) +#define ROL(x,n) ((x)<<(n))|((x)>>(32-(n))) + u_int32_t temp1, temp2; + + temp1 = ROL(t,16); + temp2 = temp1 >> 8; + temp1 &= 0x00ff00ff; + temp2 &= 0x00ff00ff; + temp1 <<= 8; + return temp1 | temp2; +#else + return t; +#endif +} + +void +md5_update (struct md5 *m, void *v, size_t len) +{ + u_char *p = (u_char *)v; + m->sz += len; + if (m->offset == 0 && len % 64 == 0) + while (len > 0) { +#if defined(WORDS_BIGENDIAN) + { + int i; + u_int32_t *u = (u_int32_t *)p; + + for (i = 0; i < 16; ++i) + m->current[i] = swap_u_int32_t (u[i]); + } + calc (m, m->current); +#else + calc (m, (u_int32_t *)p); +#endif + p += 64; + len -= 64; + } + else + while (len > 0) { + unsigned l; + + l = min(64 - m->offset, len); + memcpy ((char *)m->current + m->offset, p, l); + p += l; + len -= l; + m->offset += l; + if (m->offset == 64) { +#if defined(WORDS_BIGENDIAN) + int i; + + for (i = 0; i < 16; ++i) + m->current[i] = swap_u_int32_t (m->current[i]); +#endif + calc (m, m->current); + m->offset = 0; + } + } +} + +void +md5_finito (struct md5 *m, void *res) +{ + static u_char zeros[72]; + u_int32_t len; + unsigned dstart = (120 - m->offset - 1) % 64 + 1; + + *zeros = 0x80; + memset (zeros + 1, 0, sizeof(zeros) - 1); + len = 8 * m->sz; + len = swap_u_int32_t (len); + memcpy (zeros + dstart, &len, sizeof(len)); + md5_update (m, zeros, dstart + 8); + { + int i; + u_int32_t *r = (u_int32_t *)res; + + for (i = 0; i < 4; ++i) + r[i] = swap_u_int32_t (m->counter[i]); + } +} + +/* + * This is only for linkage compatibility! + */ +#undef MD5Init +#undef MD5Update +#undef MD5Final + +void +MD5Init (MD5_CTX *mdContext) +{ + md5_init(&mdContext->m.d5); +} + +void +MD5Update (MD5_CTX *mdContext, const unsigned char *inBuf, unsigned int inLen) +{ + md5_update(&mdContext->m.d5, (unsigned char *)inBuf, inLen); +} + +void +MD5Final (MD5_CTX *mdContext) +{ + md5_finito(&mdContext->m.d5, mdContext->digest); +} diff --git a/lib/des/md5.h b/lib/des/md5.h new file mode 100644 index 000000000..d618ab63d --- /dev/null +++ b/lib/des/md5.h @@ -0,0 +1,88 @@ +/* + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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$ */ + +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_BITYPES_H +#include +#endif +#include + +struct md5 { + unsigned offset; + unsigned sz; + u_int32_t counter[4]; + u_int32_t current[16]; +}; + +void md5_init (struct md5 *m); +void md5_update (struct md5 *m, void *p, size_t len); +void md5_finito (struct md5 *m, void *res); /* u_int32_t res[2] */ + +/* + * Functions for compatibility that have never been tested. + */ +typedef struct { + u_int32_t i[2]; /* number of _bits_ handled mod 2^64 */ + u_int32_t buf[4]; /* scratch buffer */ + unsigned char in[64]; /* input buffer */ +} MD5_CTX_PREAMBLE; + +typedef struct { + union { + MD5_CTX_PREAMBLE preamble_; + struct md5 d5; + } m; + unsigned char digest[16]; /* actual digest after MD5Final call */ +} MD5_CTX; + +void MD5Init (MD5_CTX *mdContext); +void MD5Update (MD5_CTX *mdContext, + const unsigned char *inBuf, + unsigned int inLen); +void MD5Final (MD5_CTX *mdContext); + +#ifndef NO_MD5_MACROS +#define MD5Init(mdContext) md5_init(&(mdContext)->m.d5) +#define MD5Update(mdCtx, inBuf, inLen) md5_update(&(mdCtx)->m.d5, inBuf, inLen) +#define MD5Final(mdCtx) md5_finito(&(mdCtx)->m.d5, (mdCtx)->digest) +#endif diff --git a/lib/des/sha.c b/lib/des/sha.c new file mode 100644 index 000000000..4bde7c05b --- /dev/null +++ b/lib/des/sha.c @@ -0,0 +1,304 @@ +/* + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" + +RCSID("$Id$"); +#endif + +#include +#include + +#include "sha.h" + +#ifndef min +#define min(a,b) (((a)>(b))?(b):(a)) +#endif + +#define A m->counter[0] +#define B m->counter[1] +#define C m->counter[2] +#define D m->counter[3] +#define E m->counter[4] +#define X data + +void +sha_init (struct sha *m) +{ + m->offset = 0; + m->sz = 0; + A = 0x67452301; + B = 0xefcdab89; + C = 0x98badcfe; + D = 0x10325476; + E = 0xc3d2e1f0; +} + +static u_int32_t +cshift (u_int32_t x, unsigned n) +{ + return (x << n) | (x >> (32 - n)); +} + +#define F0(x,y,z) ((x & y) | (~x & z)) +#define F1(x,y,z) (x ^ y ^ z) +#define F2(x,y,z) ((x & y) | (x & z) | (y & z)) +#define F3(x,y,z) F1(x,y,z) + +#define K0 0x5a827999 +#define K1 0x6ed9eba1 +#define K2 0x8f1bbcdc +#define K3 0xca62c1d6 + +#define DO(t,f,k) \ +do { \ + u_int32_t temp; \ + \ + temp = cshift(AA, 5) + f(BB,CC,DD) + EE + data[t] + k; \ + EE = DD; \ + DD = CC; \ + CC = cshift(BB, 30); \ + BB = AA; \ + AA = temp; \ +} while(0) + +static void +calc (struct sha *m, u_int32_t *in) +{ + u_int32_t AA, BB, CC, DD, EE; + u_int32_t data[80]; + int i; + + AA = A; + BB = B; + CC = C; + DD = D; + EE = E; + + for (i = 0; i < 16; ++i) + data[i] = in[i]; + for (i = 16; i < 80; ++i) + data[i] = cshift(data[i-3] ^ data[i-8] ^ data[i-14] ^ data[i-16], 1); + + /* t=[0,19] */ + + DO(0,F0,K0); + DO(1,F0,K0); + DO(2,F0,K0); + DO(3,F0,K0); + DO(4,F0,K0); + DO(5,F0,K0); + DO(6,F0,K0); + DO(7,F0,K0); + DO(8,F0,K0); + DO(9,F0,K0); + DO(10,F0,K0); + DO(11,F0,K0); + DO(12,F0,K0); + DO(13,F0,K0); + DO(14,F0,K0); + DO(15,F0,K0); + DO(16,F0,K0); + DO(17,F0,K0); + DO(18,F0,K0); + DO(19,F0,K0); + + /* t=[20,39] */ + + DO(20,F1,K1); + DO(21,F1,K1); + DO(22,F1,K1); + DO(23,F1,K1); + DO(24,F1,K1); + DO(25,F1,K1); + DO(26,F1,K1); + DO(27,F1,K1); + DO(28,F1,K1); + DO(29,F1,K1); + DO(30,F1,K1); + DO(31,F1,K1); + DO(32,F1,K1); + DO(33,F1,K1); + DO(34,F1,K1); + DO(35,F1,K1); + DO(36,F1,K1); + DO(37,F1,K1); + DO(38,F1,K1); + DO(39,F1,K1); + + /* t=[40,59] */ + + DO(40,F2,K2); + DO(41,F2,K2); + DO(42,F2,K2); + DO(43,F2,K2); + DO(44,F2,K2); + DO(45,F2,K2); + DO(46,F2,K2); + DO(47,F2,K2); + DO(48,F2,K2); + DO(49,F2,K2); + DO(50,F2,K2); + DO(51,F2,K2); + DO(52,F2,K2); + DO(53,F2,K2); + DO(54,F2,K2); + DO(55,F2,K2); + DO(56,F2,K2); + DO(57,F2,K2); + DO(58,F2,K2); + DO(59,F2,K2); + + /* t=[60,79] */ + + DO(60,F3,K3); + DO(61,F3,K3); + DO(62,F3,K3); + DO(63,F3,K3); + DO(64,F3,K3); + DO(65,F3,K3); + DO(66,F3,K3); + DO(67,F3,K3); + DO(68,F3,K3); + DO(69,F3,K3); + DO(70,F3,K3); + DO(71,F3,K3); + DO(72,F3,K3); + DO(73,F3,K3); + DO(74,F3,K3); + DO(75,F3,K3); + DO(76,F3,K3); + DO(77,F3,K3); + DO(78,F3,K3); + DO(79,F3,K3); + + A += AA; + B += BB; + C += CC; + D += DD; + E += EE; +} + +/* + * From `Performance analysis of SHA' by Joseph D. Touch + */ + +static u_int32_t +swap_u_int32_t (u_int32_t t) +{ +#if !defined(WORDS_BIGENDIAN) +#define ROL(x,n) ((x)<<(n))|((x)>>(32-(n))) + u_int32_t temp1, temp2; + + temp1 = ROL(t,16); + temp2 = temp1 >> 8; + temp1 &= 0x00ff00ff; + temp2 &= 0x00ff00ff; + temp1 <<= 8; + return temp1 | temp2; +#else + return t; +#endif +} + +void +sha_update (struct sha *m, void *v, size_t len) +{ + u_char *p = (u_char *)v; + m->sz += len; + if (m->offset == 0 && len % 64 == 0) + while (len > 0) { +#if !defined(WORDS_BIGENDIAN) + { + int i; + u_int32_t *u = (u_int32_t *)p; + + for (i = 0; i < 16; ++i) + m->current[i] = swap_u_int32_t (u[i]); + } + calc (m, m->current); +#else + calc (m, (u_int32_t *)p); +#endif + p += 64; + len -= 64; + } + else + while (len > 0) { + unsigned l; + + l = min(64 - m->offset, len); + memcpy ((char *)m->current + m->offset, p, l); + p += l; + len -= l; + m->offset += l; + if (m->offset == 64) { +#if !defined(WORDS_BIGENDIAN) + int i; + + for (i = 0; i < 16; ++i) + m->current[i] = swap_u_int32_t (m->current[i]); +#endif + calc (m, m->current); + m->offset = 0; + } + } +} + +void +sha_finito (struct sha *m, void *res) +{ + static unsigned char zeros[72]; + u_int32_t len; + unsigned dstart = (120 - m->offset - 1) % 64 + 1; + + *zeros = 0x80; + memset (zeros + 1, 0, sizeof(zeros) - 1); + len = 8 * m->sz; + len = swap_u_int32_t (len); + memcpy (zeros + dstart + 4, &len, sizeof(len)); + sha_update (m, zeros, dstart + 8); + { + int i; + u_int32_t *r = (u_int32_t *)res; + + for (i = 0; i < 5; ++i) + r[i] = swap_u_int32_t (m->counter[i]); + } +} diff --git a/lib/des/sha.h b/lib/des/sha.h new file mode 100644 index 000000000..45c9877df --- /dev/null +++ b/lib/des/sha.h @@ -0,0 +1,59 @@ +/* + * 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. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the Kungliga Tekniska + * Högskolan and its contributors. + * + * 4. 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$ */ + +#include +#ifdef HAVE_SYS_TYPES_H +#include +#endif +#ifdef HAVE_SYS_BITYPES_H +#include +#endif +#include + +struct sha { + unsigned offset; + u_int32_t counter[5]; + u_int32_t current[20]; + unsigned sz; +}; + +void sha_init (struct sha *m); +void sha_update (struct sha *m, void *v, size_t len); +void sha_finito (struct sha *m, void *res); diff --git a/lib/gssapi/Makefile.am b/lib/gssapi/Makefile.am new file mode 100644 index 000000000..294994d89 --- /dev/null +++ b/lib/gssapi/Makefile.am @@ -0,0 +1,18 @@ +# $Id$ + +AUTOMAKE_OPTIONS = no-dependencies + +INCLUDES = -I$(top_builddir)/include -I$(srcdir)/../krb5 + +lib_LIBRARIES = libgssapi.a + +libgssapi_a_SOURCES = \ + accept_sec_context.c add_oid_set_member.c \ + create_emtpy_oid_set.c decapsulate.c \ + delete_sec_context.c display_name.c \ + duplicate_name.c encapsulate.c external.c \ + get_mic.c import_name.c indicate_mechs.c \ + init.c init_sec_context.c inquire_context.c \ + release_buffer.c release_name.c release_oid_set.c \ + test_oid_set_member.c unwrap.c verify_mic.c \ + wrap.c \ diff --git a/lib/gssapi/accept_sec_context.c b/lib/gssapi/accept_sec_context.c new file mode 100644 index 000000000..736813a53 --- /dev/null +++ b/lib/gssapi/accept_sec_context.c @@ -0,0 +1,132 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_accept_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t * delegated_cred_handle + ) +{ + krb5_error_code kret; + OM_uint32 ret; + krb5_data indata; + krb5_flags ap_options; + OM_uint32 flags; + krb5_ticket *ticket; + + gssapi_krb5_init (); + + *context_handle = malloc(sizeof(**context_handle)); + if (*context_handle == NULL) + return GSS_S_FAILURE; + + (*context_handle)->auth_context = NULL; + (*context_handle)->source = NULL; + (*context_handle)->target = NULL; + (*context_handle)->flags = 0; + (*context_handle)->more_flags = 0; + + kret = krb5_auth_con_init (gssapi_krb5_context, + &(*context_handle)->auth_context); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + ret = gssapi_krb5_decapsulate (input_token_buffer, + &indata, + "\x01\x00"); + if (ret) + goto failure; + + kret = krb5_rd_req (gssapi_krb5_context, + &(*context_handle)->auth_context, + &indata, + /*server*/ NULL, /* XXX */ + NULL, + &ap_options, + &ticket); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_copy_principal (gssapi_krb5_context, + ticket->enc_part2.client, + &(*context_handle)->source); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + if (src_name) { + kret = krb5_copy_principal (gssapi_krb5_context, + ticket->enc_part2.client, + src_name); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + } + + flags = 0; + if (ap_options & AP_OPTS_MUTUAL_REQUIRED) + flags |= GSS_C_MUTUAL_FLAG; + flags |= GSS_C_CONF_FLAG; + flags |= GSS_C_INTEG_FLAG; + + if (ret_flags) + *ret_flags = flags; + (*context_handle)->flags = flags; + (*context_handle)->more_flags |= OPEN; + + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (time_rec) + *time_rec = GSS_C_INDEFINITE; + + if(flags & GSS_C_MUTUAL_FLAG) { + krb5_data outbuf; + + kret = krb5_mk_rep (gssapi_krb5_context, + &(*context_handle)->auth_context, + &outbuf); + if (kret) { + krb5_data_free (&outbuf); + ret = GSS_S_FAILURE; + goto failure; + } + ret = gssapi_krb5_encapsulate (&outbuf, + output_token, + "\x02\x00"); + if (ret) + goto failure; + } else { + output_token->length = 0; + } + + return GSS_S_COMPLETE; + +failure: + krb5_auth_con_free (gssapi_krb5_context, + (*context_handle)->auth_context); + if((*context_handle)->source) + krb5_free_principal (gssapi_krb5_context, + (*context_handle)->source); + if((*context_handle)->target) + krb5_free_principal (gssapi_krb5_context, + (*context_handle)->target); + free (*context_handle); + *context_handle = GSS_C_NO_CONTEXT; + return GSS_S_FAILURE; +} diff --git a/lib/gssapi/add_oid_set_member.c b/lib/gssapi/add_oid_set_member.c new file mode 100644 index 000000000..deb33cc12 --- /dev/null +++ b/lib/gssapi/add_oid_set_member.c @@ -0,0 +1,21 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_add_oid_set_member ( + OM_uint32 * minor_status, + const gss_OID member_oid, + gss_OID_set * oid_set + ) +{ + size_t n = (*oid_set)->count; + + (*oid_set)->elements = realloc ((*oid_set)->elements, + n * sizeof(gss_OID_desc)); + if ((*oid_set)->elements == NULL) { + return GSS_S_FAILURE; + } + (*oid_set)->count = n; + (*oid_set)->elements[n-1] = *member_oid; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/create_emtpy_oid_set.c b/lib/gssapi/create_emtpy_oid_set.c new file mode 100644 index 000000000..b67e4fe59 --- /dev/null +++ b/lib/gssapi/create_emtpy_oid_set.c @@ -0,0 +1,17 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_create_empty_oid_set ( + OM_uint32 * minor_status, + gss_OID_set * oid_set + ) +{ + *oid_set = malloc(sizeof(**oid_set)); + if (*oid_set == NULL) { + return GSS_S_FAILURE; + } + (*oid_set)->count = 0; + (*oid_set)->elements = NULL; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/decapsulate.c b/lib/gssapi/decapsulate.c new file mode 100644 index 000000000..3a5d97158 --- /dev/null +++ b/lib/gssapi/decapsulate.c @@ -0,0 +1,36 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +/* + * Remove the GSS-API wrapping from `in_token' giving `out_data. + * Does not copy data, so just free `in_token'. + */ + +OM_uint32 +gssapi_krb5_decapsulate( + gss_buffer_t input_token_buffer, + krb5_data *out_data, + u_char *type +) +{ + u_char *p; + size_t len; + + p = input_token_buffer->value; + len = GSS_KRB5_MECHANISM->length + 6; + if ( + input_token_buffer->length < len + || memcmp (p, "\x60\x07\x06\x05", 4) != 0 + || memcmp (p + 4, GSS_KRB5_MECHANISM->elements, + GSS_KRB5_MECHANISM->length) != 0) + return GSS_S_BAD_MECH; + if (memcmp (p + 4 + GSS_KRB5_MECHANISM->length, + type, 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + + out_data->length = input_token_buffer->length - len; + out_data->data = (u_char *)input_token_buffer->value + len; + + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/delete_sec_context.c b/lib/gssapi/delete_sec_context.c new file mode 100644 index 000000000..1381aaf57 --- /dev/null +++ b/lib/gssapi/delete_sec_context.c @@ -0,0 +1,24 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_delete_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token + ) +{ + gssapi_krb5_init (); + krb5_auth_con_free (gssapi_krb5_context, + (*context_handle)->auth_context); + if((*context_handle)->source) + krb5_free_principal (gssapi_krb5_context, + (*context_handle)->source); + if((*context_handle)->target) + krb5_free_principal (gssapi_krb5_context, + (*context_handle)->target); + free (*context_handle); + if (output_token) + output_token->length = 0; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/display_name.c b/lib/gssapi/display_name.c new file mode 100644 index 000000000..35b58c21a --- /dev/null +++ b/lib/gssapi/display_name.c @@ -0,0 +1,32 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_display_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID * output_name_type + ) +{ + krb5_error_code kret; + char *buf; + size_t len; + + gssapi_krb5_init (); + kret = krb5_unparse_name (gssapi_krb5_context, + input_name, + &buf); + if (kret) + return GSS_S_FAILURE; + len = strlen (buf); + output_name_buffer->length = len; + output_name_buffer->value = malloc(len); + if (output_name_buffer->value == NULL) { + free (buf); + return GSS_S_FAILURE; + } + memcpy (output_name_buffer->value, buf, len); + free (buf); + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/duplicate_name.c b/lib/gssapi/duplicate_name.c new file mode 100644 index 000000000..1134813d2 --- /dev/null +++ b/lib/gssapi/duplicate_name.c @@ -0,0 +1,22 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_duplicate_name ( + OM_uint32 * minor_status, + const gss_name_t src_name, + gss_name_t * dest_name + ) +{ + krb5_error_code kret; + + gssapi_krb5_init (); + + kret = krb5_copy_principal (gssapi_krb5_context, + src_name, + dest_name); + if (kret) + return GSS_S_FAILURE; + else + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/encapsulate.c b/lib/gssapi/encapsulate.c new file mode 100644 index 000000000..598167466 --- /dev/null +++ b/lib/gssapi/encapsulate.c @@ -0,0 +1,33 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +/* + * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings. + */ + +OM_uint32 +gssapi_krb5_encapsulate( + krb5_data *in_data, + gss_buffer_t output_token, + u_char *type +) +{ + u_char *p; + + output_token->length = in_data->length + GSS_KRB5_MECHANISM->length + 6; + output_token->value = malloc (output_token->length); + if (output_token->value == NULL) + return GSS_S_FAILURE; + + p = output_token->value; + memcpy (p, "\x60\x07\x06\x05", 4); + p += 4; + memcpy (p, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); + p += GSS_KRB5_MECHANISM->length; + memcpy (p, type, 2); + p += 2; + memcpy (p, in_data->data, in_data->length); + krb5_data_free (in_data); + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/external.c b/lib/gssapi/external.c new file mode 100644 index 000000000..cfa8fa61c --- /dev/null +++ b/lib/gssapi/external.c @@ -0,0 +1,172 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x01"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant + * GSS_C_NT_USER_NAME should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_user_name_oid_desc = +{10, (void *)"\x2a\x86\x48\x86\xf7\x12" + "\x01\x02\x01\x01"}; + +gss_OID GSS_C_NT_USER_NAME = &gss_c_nt_user_name_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x02"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. + * The constant GSS_C_NT_MACHINE_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_machine_uid_name_oid_desc = +{10, (void *)"\x2a\x86\x48\x86\xf7\x12" + "\x01\x02\x01\x02"}; + +gss_OID GSS_C_NT_MACHINE_UID_NAME = &gss_c_nt_machine_uid_name_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x03"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) string_uid_name(3)}. + * The constant GSS_C_NT_STRING_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_string_uid_name_oid_desc = +{10, (void *)"\x2a\x86\x48\x86\xf7\x12" + "\x01\x02\x01\x03"}; + +gss_OID GSS_C_NT_STRING_UID_NAME = &gss_c_nt_string_uid_name_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 2(gss-host-based-services)}. The constant + * GSS_C_NT_HOSTBASED_SERVICE should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_hostbased_service_oid_desc = +{6, (void *)"\x2b\x06\x01\x05\x06\x02"}; + +gss_OID GSS_C_NT_HOSTBASED_SERVICE = &gss_c_nt_hostbased_service_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, + * corresponding to an object identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 3(gss-anonymous-name)}. The constant + * and GSS_C_NT_ANONYMOUS should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_anonymous_oid_desc = +{6, (void *)"\x2b\x06\01\x05\x06\x03"}; + +gss_OID GSS_C_NT_ANONYMOUS = &gss_c_nt_anonymous_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 4(gss-api-exported-name)}. The constant + * GSS_C_NT_EXPORT_NAME should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_export_name_oid_desc = +{6, (void *)"\x2b\x06\x01\x05\x06\x04"}; + +gss_OID GSS_C_NT_EXPORT_NAME = &gss_c_nt_export_name_oid_desc; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5_name(1)}. The recommended symbolic name for this type + * is "GSS_KRB5_NT_PRINCIPAL_NAME". + */ + +static gss_OID_desc gss_krb5_nt_principal_name_oid_desc = +{10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01"}; + +gss_OID GSS_KRB5_NT_PRINCIPAL_NAME = &gss_krb5_nt_principal_name_oid_desc; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) user_name(1)}. The recommended symbolic name for this + * type is "GSS_KRB5_NT_USER_NAME". + */ + +gss_OID GSS_KRB5_NT_USER_NAME = &gss_c_nt_user_name_oid_desc; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) machine_uid_name(2)}. The recommended symbolic name for + * this type is "GSS_KRB5_NT_MACHINE_UID_NAME". + */ + +gss_OID GSS_KRB5_NT_MACHINE_UID_NAME = &gss_c_nt_machine_uid_name_oid_desc; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) string_uid_name(3)}. The recommended symbolic name for + * this type is "GSS_KRB5_NT_STRING_UID_NAME". + */ + +gss_OID GSS_KRB5_NT_STRING_UID_NAME = &gss_c_nt_string_uid_name_oid_desc; + +/* + * To support ongoing experimentation, testing, and evolution of the + * specification, the Kerberos V5 GSS-API mechanism as defined in this + * and any successor memos will be identified with the following Object + * Identifier, as defined in RFC-1510, until the specification is + * advanced to the level of Proposed Standard RFC: + * + * {iso(1), org(3), dod(5), internet(1), security(5), kerberosv5(2)} + * + * Upon advancement to the level of Proposed Standard RFC, the Kerberos + * V5 GSS-API mechanism will be identified by an Object Identifier + * having the value: + * + * {iso(1) member-body(2) United States(840) mit(113554) infosys(1) + * gssapi(2) krb5(2)} + */ + +static gss_OID_desc gss_krb5_mechanism_oid_desc = +{5, (void *)"\x2b\x05\x01\x05\x02"}; + +gss_OID GSS_KRB5_MECHANISM = &gss_krb5_mechanism_oid_desc; + +/* + * Context for krb5 calls. + */ + +krb5_context gssapi_krb5_context; diff --git a/lib/gssapi/get_mic.c b/lib/gssapi/get_mic.c new file mode 100644 index 000000000..57506c911 --- /dev/null +++ b/lib/gssapi/get_mic.c @@ -0,0 +1,58 @@ +#include "gssapi_locl.h" +#include +#include + +RCSID("$Id$"); + +OM_uint32 gss_get_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + u_char *p; + size_t len; + struct md5 md5; + u_char hash[16]; + des_key_schedule schedule; + des_cblock key; + des_cblock zero; + + len = 28 + GSS_KRB5_MECHANISM->length; + message_token->length = len; + message_token->value = malloc (len); + if (message_token->value == NULL) + return GSS_S_FAILURE; + + p = message_token->value; + memcpy (p, "\x60\x07\x06\x05", 4); + p += 4; + memcpy (p, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); + p += GSS_KRB5_MECHANISM->length; + memcpy (p, "\x01\x01", 2); + p += 2; + memcpy (p, "\x00\x00", 2); + p += 2; + memcpy (p, "\xff\xff\xff\xff", 4); + p += 4; + + memset (p, 0, 16); + p += 16; + + md5_init (&md5); + md5_update (&md5, p - 24, 8); + md5_update (&md5, message_buffer->value, + message_buffer->length); + md5_finito (&md5, hash); + + memset (&zero, 0, sizeof(zero)); + memcpy (&key, context_handle->auth_context->key.contents.data, + sizeof(key)); + des_set_key (&key, schedule); + des_cbc_cksum ((des_cblock *)hash, + (des_cblock *)hash, sizeof(hash), schedule, &zero); + memcpy (p - 8, hash, 8); + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/gssapi.h b/lib/gssapi/gssapi.h new file mode 100644 index 000000000..97441518d --- /dev/null +++ b/lib/gssapi/gssapi.h @@ -0,0 +1,693 @@ +/* $Id$ */ + +#ifndef GSSAPI_H_ +#define GSSAPI_H_ + +/* + * First, include stddef.h to get size_t defined. + */ +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#ifdef HAVE_SYS_BITYPES_H +#include +#endif + +#include + +#include + +/* + * Now define the three implementation-dependent types. + */ + +typedef u_int32_t OM_uint32; + +/* + * XXX - Should we really do it this way? + * I'm not entirely happy with exposing this match of the krb5 stuff + * here, and having to include the file as well. + */ + +typedef krb5_principal gss_name_t; + +typedef struct gss_ctx_id_t_desc_struct { + krb5_auth_context auth_context; + gss_name_t source, target; + OM_uint32 flags; + enum { LOCAL = 1, OPEN = 2} more_flags; +} gss_ctx_id_t_desc; + +typedef gss_ctx_id_t_desc *gss_ctx_id_t; +typedef int gss_cred_id_t; /* XXX */ + + +typedef struct gss_OID_desc_struct { + OM_uint32 length; + void *elements; +} gss_OID_desc, *gss_OID; + +typedef struct gss_OID_set_desc_struct { + size_t count; + gss_OID elements; +} gss_OID_set_desc, *gss_OID_set; + +typedef struct gss_buffer_desc_struct { + size_t length; + void *value; +} gss_buffer_desc, *gss_buffer_t; + +typedef struct gss_channel_bindings_struct { + OM_uint32 initiator_addrtype; + gss_buffer_desc initiator_address; + OM_uint32 acceptor_addrtype; + gss_buffer_desc acceptor_address; + gss_buffer_desc application_data; +} *gss_channel_bindings_t; + +/* + * For now, define a QOP-type as an OM_uint32 + */ +typedef OM_uint32 gss_qop_t; + +typedef int gss_cred_usage_t; + +/* + * Flag bits for context-level services. + */ +#define GSS_C_DELEG_FLAG 1 +#define GSS_C_MUTUAL_FLAG 2 +#define GSS_C_REPLAY_FLAG 4 +#define GSS_C_SEQUENCE_FLAG 8 +#define GSS_C_CONF_FLAG 16 +#define GSS_C_INTEG_FLAG 32 +#define GSS_C_ANON_FLAG 64 +#define GSS_C_PROT_READY_FLAG 128 +#define GSS_C_TRANS_FLAG 256 + +/* + * Credential usage options + */ +#define GSS_C_BOTH 0 +#define GSS_C_INITIATE 1 +#define GSS_C_ACCEPT 2 + +/* + * Status code types for gss_display_status + */ +#define GSS_C_GSS_CODE 1 +#define GSS_C_MECH_CODE 2 + +/* + * The constant definitions for channel-bindings address families + */ +#define GSS_C_AF_UNSPEC 0 +#define GSS_C_AF_LOCAL 1 +#define GSS_C_AF_INET 2 +#define GSS_C_AF_IMPLINK 3 +#define GSS_C_AF_PUP 4 +#define GSS_C_AF_CHAOS 5 +#define GSS_C_AF_NS 6 +#define GSS_C_AF_NBS 7 +#define GSS_C_AF_ECMA 8 +#define GSS_C_AF_DATAKIT 9 +#define GSS_C_AF_CCITT 10 +#define GSS_C_AF_SNA 11 +#define GSS_C_AF_DECnet 12 +#define GSS_C_AF_DLI 13 +#define GSS_C_AF_LAT 14 +#define GSS_C_AF_HYLINK 15 +#define GSS_C_AF_APPLETALK 16 +#define GSS_C_AF_BSC 17 +#define GSS_C_AF_DSS 18 +#define GSS_C_AF_OSI 19 +#define GSS_C_AF_X25 21 + +#define GSS_C_AF_NULLADDR 255 + +/* + * Various Null values + */ +#define GSS_C_NO_NAME ((gss_name_t) 0) +#define GSS_C_NO_BUFFER ((gss_buffer_t) 0) +#define GSS_C_NO_OID ((gss_OID) 0) +#define GSS_C_NO_OID_SET ((gss_OID_set) 0) +#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0) +#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0) +#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0) +#define GSS_C_EMPTY_BUFFER {0, NULL} + +/* + * Some alternate names for a couple of the above + * values. These are defined for V1 compatibility. + */ +#define GSS_C_NULL_OID GSS_C_NO_OID +#define GSS_C_NULL_OID_SET GSS_C_NO_OID_SET + +/* + * Define the default Quality of Protection for per-message + * services. Note that an implementation that offers multiple + * levels of QOP may define GSS_C_QOP_DEFAULT to be either zero + * (as done here) to mean "default protection", or to a specific + * explicit QOP value. However, a value of 0 should always be + * interpreted by a GSSAPI implementation as a request for the + * default protection level. + */ +#define GSS_C_QOP_DEFAULT 0 + +/* + * Expiration time of 2^32-1 seconds means infinite lifetime for a + * credential or security context + */ +#define GSS_C_INDEFINITE 0xfffffffful + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x01"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant + * GSS_C_NT_USER_NAME should be initialized to point + * to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_USER_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x02"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. + * The constant GSS_C_NT_MACHINE_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_MACHINE_UID_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x03"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) string_uid_name(3)}. + * The constant GSS_C_NT_STRING_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_STRING_UID_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 2(gss-host-based-services)}. The constant + * GSS_C_NT_HOSTBASED_SERVICE should be initialized to point + * to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_HOSTBASED_SERVICE; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, + * corresponding to an object identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 3(gss-anonymous-name)}. The constant + * and GSS_C_NT_ANONYMOUS should be initialized to point + * to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_ANONYMOUS; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 4(gss-api-exported-name)}. The constant + * GSS_C_NT_EXPORT_NAME should be initialized to point + * to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_EXPORT_NAME; + +/* + * This if for kerberos5 names. + */ + +extern gss_OID GSS_KRB5_NT_PRINCIPAL_NAME; +extern gss_OID GSS_KRB5_NT_PRINCIPAL_NAME; +extern gss_OID GSS_KRB5_NT_USER_NAME; +extern gss_OID GSS_KRB5_NT_MACHINE_UID_NAME; +extern gss_OID GSS_KRB5_NT_STRING_UID_NAME; + +extern gss_OID GSS_KRB5_MECHANISM; + +/* Major status codes */ + +#define GSS_S_COMPLETE 0 + +/* + * Some "helper" definitions to make the status code macros obvious. + */ +#define GSS_C_CALLING_ERROR_OFFSET 24 +#define GSS_C_ROUTINE_ERROR_OFFSET 16 +#define GSS_C_SUPPLEMENTARY_OFFSET 0 +#define GSS_C_CALLING_ERROR_MASK 0377ul +#define GSS_C_ROUTINE_ERROR_MASK 0377ul +#define GSS_C_SUPPLEMENTARY_MASK 0177777ul + +/* + * The macros that test status codes for error conditions. + * Note that the GSS_ERROR() macro has changed slightly from + * the V1 GSSAPI so that it now evaluates its argument + * only once. + */ +#define GSS_CALLING_ERROR(x) \ + (x & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET)) +#define GSS_ROUTINE_ERROR(x) \ + (x & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)) +#define GSS_SUPPLEMENTARY_INFO(x) \ + (x & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET)) +#define GSS_ERROR(x) \ + (x & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \ + (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))) + +/* + * Now the actual status code definitions + */ + +/* + * Calling errors: + */ +#define GSS_S_CALL_INACCESSIBLE_READ \ + (1ul << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_INACCESSIBLE_WRITE \ + (2ul << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_BAD_STRUCTURE \ + (3ul << GSS_C_CALLING_ERROR_OFFSET) + +/* + * Routine errors: + */ +#define GSS_S_BAD_MECH (1ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAME (2ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAMETYPE (3ul << GSS_C_ROUTINE_ERROR_OFFSET) + +#define GSS_S_BAD_BINDINGS (4ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_STATUS (5ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_SIG (6ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_MIC GSS_S_BAD_SIG +#define GSS_S_NO_CRED (7ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NO_CONTEXT (8ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_TOKEN (9ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_CREDENTIAL (10ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CREDENTIALS_EXPIRED (11ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CONTEXT_EXPIRED (12ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_FAILURE (13ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_QOP (14ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAUTHORIZED (15ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAVAILABLE (16ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DUPLICATE_ELEMENT (17ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NAME_NOT_MN (18ul << GSS_C_ROUTINE_ERROR_OFFSET) + +/* + * Supplementary info bits: + */ +#define GSS_S_CONTINUE_NEEDED (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 0)) +#define GSS_S_DUPLICATE_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 1)) +#define GSS_S_OLD_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 2)) +#define GSS_S_UNSEQ_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 3)) +#define GSS_S_GAP_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 4)) + +/* + * From RFC1964: + * + * 4.1.1. Non-Kerberos-specific codes + */ + +#define GSS_KRB5_S_G_BAD_SERVICE_NAME 1 + /* "No @ in SERVICE-NAME name string" */ +#define GSS_KRB5_S_G_BAD_STRING_UID 2 + /* "STRING-UID-NAME contains nondigits" */ +#define GSS_KRB5_S_G_NOUSER 3 + /* "UID does not resolve to username" */ +#define GSS_KRB5_S_G_VALIDATE_FAILED 4 + /* "Validation error" */ +#define GSS_KRB5_S_G_BUFFER_ALLOC 5 + /* "Couldn't allocate gss_buffer_t data" */ +#define GSS_KRB5_S_G_BAD_MSG_CTX 6 + /* "Message context invalid" */ +#define GSS_KRB5_S_G_WRONG_SIZE 7 + /* "Buffer is the wrong size" */ +#define GSS_KRB5_S_G_BAD_USAGE 8 + /* "Credential usage type is unknown" */ +#define GSS_KRB5_S_G_UNKNOWN_QOP 9 + /* "Unknown quality of protection specified" */ + + /* + * 4.1.2. Kerberos-specific-codes + */ + +#define GSS_KRB5_S_KG_CCACHE_NOMATCH 10 + /* "Principal in credential cache does not match desired name" */ +#define GSS_KRB5_S_KG_KEYTAB_NOMATCH 11 + /* "No principal in keytab matches desired name" */ +#define GSS_KRB5_S_KG_TGT_MISSING 12 + /* "Credential cache has no TGT" */ +#define GSS_KRB5_S_KG_NO_SUBKEY 13 + /* "Authenticator has no subkey" */ +#define GSS_KRB5_S_KG_CONTEXT_ESTABLISHED 14 + /* "Context is already fully established" */ +#define GSS_KRB5_S_KG_BAD_SIGN_TYPE 15 + /* "Unknown signature type in token" */ +#define GSS_KRB5_S_KG_BAD_LENGTH 16 + /* "Invalid field length in token" */ +#define GSS_KRB5_S_KG_CTX_INCOMPLETE 17 + /* "Attempt to use incomplete security context" */ + +/* + * Finally, function prototypes for the GSS-API routines. + */ + +OM_uint32 gss_acquire_cred + (OM_uint32 * minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * time_rec + ); + +OM_uint32 gss_release_cred + (OM_uint32 * minor_status, + gss_cred_id_t * cred_handle + ); + +OM_uint32 gss_init_sec_context + (OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ); + +OM_uint32 gss_accept_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t * delegated_cred_handle + ); + +OM_uint32 gss_process_context_token + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_buffer + ); + +OM_uint32 gss_delete_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token + ); + +OM_uint32 gss_context_time + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + OM_uint32 * time_rec + ); + +OM_uint32 gss_get_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ); + +OM_uint32 gss_verify_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state + ); + +OM_uint32 gss_wrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ); + +OM_uint32 gss_unwrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state + ); + +OM_uint32 gss_display_status + (OM_uint32 * minor_status, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 * message_context, + gss_buffer_t status_string + ); + +OM_uint32 gss_indicate_mechs + (OM_uint32 * minor_status, + gss_OID_set * mech_set + ); + +OM_uint32 gss_compare_name + (OM_uint32 * minor_status, + const gss_name_t name1, + const gss_name_t name2, + int * name_equal + ); + +OM_uint32 gss_display_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID * output_name_type + ); + +OM_uint32 gss_import_name + (OM_uint32 * minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t * output_name + ); + +OM_uint32 gss_export_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t exported_name + ); + +OM_uint32 gss_release_name + (OM_uint32 * minor_status, + gss_name_t * input_name + ); + +OM_uint32 gss_release_buffer + (OM_uint32 * minor_status, + gss_buffer_t buffer + ); + +OM_uint32 gss_release_oid_set + (OM_uint32 * minor_status, + gss_OID_set * set + ); + +OM_uint32 gss_inquire_cred + (OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + gss_name_t * name, + OM_uint32 * lifetime, + gss_cred_usage_t * cred_usage, + gss_OID_set * mechanisms + ); + +OM_uint32 gss_inquire_context ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_name_t * src_name, + gss_name_t * targ_name, + OM_uint32 * lifetime_rec, + gss_OID * mech_type, + OM_uint32 * ctx_flags, + int * locally_initiated, + int * open + ); + +OM_uint32 gss_wrap_size_limit ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 * max_input_size + ); + +OM_uint32 gss_add_cred ( + OM_uint32 * minor_status, + const gss_cred_id_t input_cred_handle, + const gss_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * initiator_time_rec, + OM_uint32 * acceptor_time_rec + ); + +OM_uint32 gss_inquire_cred_by_mech ( + OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + const gss_OID mech_type, + gss_name_t * name, + OM_uint32 * initiator_lifetime, + OM_uint32 * acceptor_lifetime, + gss_cred_usage_t * cred_usage + ); + +OM_uint32 gss_export_sec_context ( + OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t interprocess_token + ); + +OM_uint32 gss_import_sec_context ( + OM_uint32 * minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t * context_handle + ); + +OM_uint32 gss_create_empty_oid_set ( + OM_uint32 * minor_status, + gss_OID_set * oid_set + ); + +OM_uint32 gss_add_oid_set_member ( + OM_uint32 * minor_status, + const gss_OID member_oid, + gss_OID_set * oid_set + ); + +OM_uint32 gss_test_oid_set_member ( + OM_uint32 * minor_status, + const gss_OID member, + const gss_OID_set set, + int * present + ); + +OM_uint32 gss_inquire_names_for_mech ( + OM_uint32 * minor_status, + const gss_OID mechanism, + gss_OID_set * name_types + ); + +OM_uint32 gss_inquire_mechs_for_name ( + OM_uint32 * minor_status, + const gss_name_t input_name, + gss_OID_set * mech_types + ); + +OM_uint32 gss_canonicalize_name ( + OM_uint32 * minor_status, + const gss_name_t input_name, + const gss_OID mech_type, + gss_name_t * output_name + ); + +OM_uint32 gss_duplicate_name ( + OM_uint32 * minor_status, + const gss_name_t src_name, + gss_name_t * dest_name + ); + +/* + * The following routines are obsolete variants of gss_get_mic, + * gss_verify_mic, gss_wrap and gss_unwrap. They should be + * provided by GSSAPI V2 implementations for backwards + * compatibility with V1 applications. Distinct entrypoints + * (as opposed to #defines) should be provided, both to allow + * GSSAPI V1 applications to link against GSSAPI V2 implementations, + * and to retain the slight parameter type differences between the + * obsolete versions of these routines and their current forms. + */ + +OM_uint32 gss_sign + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int qop_req, + gss_buffer_t message_buffer, + gss_buffer_t message_token + ); + +OM_uint32 gss_verify + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t message_buffer, + gss_buffer_t token_buffer, + int * qop_state + ); + +OM_uint32 gss_seal + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + int qop_req, + gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ); + +OM_uint32 gss_unseal + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + int * qop_state + ); + +#endif /* GSSAPI_H_ */ diff --git a/lib/gssapi/gssapi_locl.h b/lib/gssapi/gssapi_locl.h new file mode 100644 index 000000000..759726199 --- /dev/null +++ b/lib/gssapi/gssapi_locl.h @@ -0,0 +1,30 @@ +/* $Id$ */ + +#ifndef GSSAPI_LOCL_H +#define GSSAPI_LOCL_H + +#include +#include + +#include + +#include +#include + +extern krb5_context gssapi_krb5_context; + +void gssapi_krb5_init (void); + +OM_uint32 +gssapi_krb5_encapsulate( + krb5_data *in_data, + gss_buffer_t output_token, + u_char *type); + +OM_uint32 +gssapi_krb5_decapsulate( + gss_buffer_t input_token_buffer, + krb5_data *out_data, + u_char *type); + +#endif diff --git a/lib/gssapi/import_name.c b/lib/gssapi/import_name.c new file mode 100644 index 000000000..aab0a0b6f --- /dev/null +++ b/lib/gssapi/import_name.c @@ -0,0 +1,36 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_import_name + (OM_uint32 * minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t * output_name + ) +{ + krb5_error_code kerr; + char *tmp; + + gssapi_krb5_init (); + + tmp = malloc (input_name_buffer->length + 1); + if (tmp == NULL) { + return GSS_S_FAILURE; + } + memcpy (tmp, + input_name_buffer->value, + input_name_buffer->length); + tmp[input_name_buffer->length] = '\0'; + + kerr = krb5_parse_name (gssapi_krb5_context, + tmp, + output_name); + free (tmp); + if (kerr == 0) + return GSS_S_COMPLETE; + else if (kerr = KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) + return GSS_S_BAD_NAME; + else + return GSS_S_FAILURE; +} diff --git a/lib/gssapi/indicate_mechs.c b/lib/gssapi/indicate_mechs.c new file mode 100644 index 000000000..d324f9a41 --- /dev/null +++ b/lib/gssapi/indicate_mechs.c @@ -0,0 +1,22 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_indicate_mechs + (OM_uint32 * minor_status, + gss_OID_set * mech_set + ) +{ + *mech_set = malloc(sizeof(**mech_set)); + if (*mech_set == NULL) { + return GSS_S_FAILURE; + } + (*mech_set)->count = 1; + (*mech_set)->elements = malloc((*mech_set)->count * sizeof(gss_OID_desc)); + if ((*mech_set)->elements == NULL) { + free (*mech_set); + return GSS_S_FAILURE; + } + (*mech_set)->elements[0] = *GSS_KRB5_MECHANISM; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/init.c b/lib/gssapi/init.c new file mode 100644 index 000000000..23ea03ede --- /dev/null +++ b/lib/gssapi/init.c @@ -0,0 +1,15 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +void +gssapi_krb5_init (void) +{ + static int donep = 0; + + if (donep) + return; + + krb5_init_context (&gssapi_krb5_context); + donep = 1; +} diff --git a/lib/gssapi/init_sec_context.c b/lib/gssapi/init_sec_context.c new file mode 100644 index 000000000..92c729df6 --- /dev/null +++ b/lib/gssapi/init_sec_context.c @@ -0,0 +1,312 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +static krb5_error_code +create_8003_checksum ( + const gss_channel_bindings_t input_chan_bindings, + OM_uint32 flags, + Checksum *result) +{ + u_char *p; + u_int32_t val; + + result->cksumtype = 0x8003; + result->checksum.length = 24; + result->checksum.data = malloc (result->checksum.length); + if (result->checksum.data == NULL) + return ENOMEM; + + p = result->checksum.data; + val = 16; + *p++ = (val >> 0) & 0xFF; + *p++ = (val >> 8) & 0xFF; + *p++ = (val >> 16) & 0xFF; + *p++ = (val >> 24) & 0xFF; + memset (p, 0, 16); + p += 16; + val = flags; + *p++ = (val >> 0) & 0xFF; + *p++ = (val >> 8) & 0xFF; + *p++ = (val >> 16) & 0xFF; + *p++ = (val >> 24) & 0xFF; + if (p - (u_char *)result->checksum.data != result->checksum.length) + abort (); + return 0; +} + +static OM_uint32 +init_auth + (OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_flags ap_options; + krb5_creds this_cred, *cred; + krb5_data outbuf; + krb5_ccache ccache; + u_int32_t flags; + Authenticator *auth; + krb5_data authenticator; + Checksum cksum; + + gssapi_krb5_init (); + + outbuf.length = 0; + outbuf.data = NULL; + + + + + *context_handle = malloc(sizeof(**context_handle)); + if (*context_handle == NULL) + return GSS_S_FAILURE; + + (*context_handle)->auth_context = NULL; + (*context_handle)->source = NULL; + (*context_handle)->target = NULL; + (*context_handle)->flags = 0; + (*context_handle)->more_flags = 0; + + kret = krb5_auth_con_init (gssapi_krb5_context, + &(*context_handle)->auth_context); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + if (actual_mech_type) + *actual_mech_type = GSS_KRB5_MECHANISM; + + flags = 0; + ap_options = 0; + if (req_flags & GSS_C_DELEG_FLAG) + ; /* XXX */ + if (req_flags & GSS_C_MUTUAL_FLAG) { + flags |= GSS_C_MUTUAL_FLAG; + ap_options |= AP_OPTS_MUTUAL_REQUIRED; + } + if (req_flags & GSS_C_REPLAY_FLAG) + ; /* XXX */ + if (req_flags & GSS_C_SEQUENCE_FLAG) + ; /* XXX */ + if (req_flags & GSS_C_ANON_FLAG) + ; /* XXX */ + flags |= GSS_C_CONF_FLAG; + flags |= GSS_C_INTEG_FLAG; + + if (ret_flags) + *ret_flags = flags; + (*context_handle)->flags = flags; + (*context_handle)->more_flags = LOCAL; + + kret = krb5_cc_default (gssapi_krb5_context, &ccache); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_cc_get_principal (gssapi_krb5_context, + ccache, + &(*context_handle)->source); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_copy_principal (gssapi_krb5_context, + target_name, + &(*context_handle)->target); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + this_cred.client = (*context_handle)->source; + this_cred.server = (*context_handle)->target; + this_cred.times.endtime = 0; + + kret = krb5_get_credentials (gssapi_krb5_context, + 0, + ccache, + &this_cred, + &cred); + + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + (*context_handle)->auth_context->key.keytype = cred->session.keytype; + krb5_data_copy (&(*context_handle)->auth_context->key.contents, + cred->session.contents.data, + cred->session.contents.length); + + kret = create_8003_checksum (input_chan_bindings, + flags, + &cksum); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_build_authenticator (gssapi_krb5_context, + (*context_handle)->auth_context, + cred, + &cksum, + &auth, + &authenticator); + + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_build_ap_req (gssapi_krb5_context, + cred, + ap_options, + authenticator, + &outbuf); + krb5_data_free (&authenticator); + + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + ret = gssapi_krb5_encapsulate (&outbuf, + output_token, + "\x01\x00"); + if (ret) + goto failure; + + if (flags & GSS_C_MUTUAL_FLAG) { + return GSS_S_CONTINUE_NEEDED; + } else { + (*context_handle)->more_flags |= OPEN; + return GSS_S_COMPLETE; + } + +failure: + krb5_auth_con_free (gssapi_krb5_context, + (*context_handle)->auth_context); + if((*context_handle)->source) + krb5_free_principal (gssapi_krb5_context, + (*context_handle)->source); + if((*context_handle)->target) + krb5_free_principal (gssapi_krb5_context, + (*context_handle)->target); + free (*context_handle); + krb5_data_free (&outbuf); + *context_handle = GSS_C_NO_CONTEXT; + return GSS_S_FAILURE; +} + +static OM_uint32 +repl_mutual + (OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_data indata; + krb5_ap_rep_enc_part *repl; + + ret = gssapi_krb5_decapsulate (input_token, + &indata, + "\x02\x00"); + if (ret) { + /* XXX - Handle AP_ERROR */ + return GSS_S_FAILURE; + } + + kret = krb5_rd_rep (gssapi_krb5_context, + (*context_handle)->auth_context, + &indata, + &repl); + if (kret) + return GSS_S_FAILURE; + krb5_free_ap_rep_enc_part (gssapi_krb5_context, + repl); + + (*context_handle)->more_flags |= OPEN; + + return GSS_S_COMPLETE; +} + +/* + * gss_init_sec_context + */ + +OM_uint32 gss_init_sec_context + (OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + gssapi_krb5_init (); + + if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) + return init_auth (minor_status, + initiator_cred_handle, + context_handle, + target_name, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + else + return repl_mutual(minor_status, + initiator_cred_handle, + context_handle, + target_name, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); +} diff --git a/lib/gssapi/inquire_context.c b/lib/gssapi/inquire_context.c new file mode 100644 index 000000000..3ab64db41 --- /dev/null +++ b/lib/gssapi/inquire_context.c @@ -0,0 +1,51 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_inquire_context ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_name_t * src_name, + gss_name_t * targ_name, + OM_uint32 * lifetime_rec, + gss_OID * mech_type, + OM_uint32 * ctx_flags, + int * locally_initiated, + int * open + ) +{ + OM_uint32 ret; + + if (src_name) { + ret = gss_duplicate_name (minor_status, + context_handle->source, + src_name); + if (ret) + return ret; + } + + if (targ_name) { + ret = gss_duplicate_name (minor_status, + context_handle->target, + targ_name); + if (ret) + return ret; + } + + if (lifetime_rec) + *lifetime_rec = GSS_C_INDEFINITE; + + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (ctx_flags) + *ctx_flags = context_handle->flags; + + if (locally_initiated) + *locally_initiated = context_handle->more_flags & LOCAL; + + if (open) + *open = context_handle->more_flags & OPEN; + + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/Makefile.am b/lib/gssapi/krb5/Makefile.am new file mode 100644 index 000000000..294994d89 --- /dev/null +++ b/lib/gssapi/krb5/Makefile.am @@ -0,0 +1,18 @@ +# $Id$ + +AUTOMAKE_OPTIONS = no-dependencies + +INCLUDES = -I$(top_builddir)/include -I$(srcdir)/../krb5 + +lib_LIBRARIES = libgssapi.a + +libgssapi_a_SOURCES = \ + accept_sec_context.c add_oid_set_member.c \ + create_emtpy_oid_set.c decapsulate.c \ + delete_sec_context.c display_name.c \ + duplicate_name.c encapsulate.c external.c \ + get_mic.c import_name.c indicate_mechs.c \ + init.c init_sec_context.c inquire_context.c \ + release_buffer.c release_name.c release_oid_set.c \ + test_oid_set_member.c unwrap.c verify_mic.c \ + wrap.c \ diff --git a/lib/gssapi/krb5/accept_sec_context.c b/lib/gssapi/krb5/accept_sec_context.c new file mode 100644 index 000000000..736813a53 --- /dev/null +++ b/lib/gssapi/krb5/accept_sec_context.c @@ -0,0 +1,132 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_accept_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t * delegated_cred_handle + ) +{ + krb5_error_code kret; + OM_uint32 ret; + krb5_data indata; + krb5_flags ap_options; + OM_uint32 flags; + krb5_ticket *ticket; + + gssapi_krb5_init (); + + *context_handle = malloc(sizeof(**context_handle)); + if (*context_handle == NULL) + return GSS_S_FAILURE; + + (*context_handle)->auth_context = NULL; + (*context_handle)->source = NULL; + (*context_handle)->target = NULL; + (*context_handle)->flags = 0; + (*context_handle)->more_flags = 0; + + kret = krb5_auth_con_init (gssapi_krb5_context, + &(*context_handle)->auth_context); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + ret = gssapi_krb5_decapsulate (input_token_buffer, + &indata, + "\x01\x00"); + if (ret) + goto failure; + + kret = krb5_rd_req (gssapi_krb5_context, + &(*context_handle)->auth_context, + &indata, + /*server*/ NULL, /* XXX */ + NULL, + &ap_options, + &ticket); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_copy_principal (gssapi_krb5_context, + ticket->enc_part2.client, + &(*context_handle)->source); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + if (src_name) { + kret = krb5_copy_principal (gssapi_krb5_context, + ticket->enc_part2.client, + src_name); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + } + + flags = 0; + if (ap_options & AP_OPTS_MUTUAL_REQUIRED) + flags |= GSS_C_MUTUAL_FLAG; + flags |= GSS_C_CONF_FLAG; + flags |= GSS_C_INTEG_FLAG; + + if (ret_flags) + *ret_flags = flags; + (*context_handle)->flags = flags; + (*context_handle)->more_flags |= OPEN; + + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (time_rec) + *time_rec = GSS_C_INDEFINITE; + + if(flags & GSS_C_MUTUAL_FLAG) { + krb5_data outbuf; + + kret = krb5_mk_rep (gssapi_krb5_context, + &(*context_handle)->auth_context, + &outbuf); + if (kret) { + krb5_data_free (&outbuf); + ret = GSS_S_FAILURE; + goto failure; + } + ret = gssapi_krb5_encapsulate (&outbuf, + output_token, + "\x02\x00"); + if (ret) + goto failure; + } else { + output_token->length = 0; + } + + return GSS_S_COMPLETE; + +failure: + krb5_auth_con_free (gssapi_krb5_context, + (*context_handle)->auth_context); + if((*context_handle)->source) + krb5_free_principal (gssapi_krb5_context, + (*context_handle)->source); + if((*context_handle)->target) + krb5_free_principal (gssapi_krb5_context, + (*context_handle)->target); + free (*context_handle); + *context_handle = GSS_C_NO_CONTEXT; + return GSS_S_FAILURE; +} diff --git a/lib/gssapi/krb5/add_oid_set_member.c b/lib/gssapi/krb5/add_oid_set_member.c new file mode 100644 index 000000000..deb33cc12 --- /dev/null +++ b/lib/gssapi/krb5/add_oid_set_member.c @@ -0,0 +1,21 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_add_oid_set_member ( + OM_uint32 * minor_status, + const gss_OID member_oid, + gss_OID_set * oid_set + ) +{ + size_t n = (*oid_set)->count; + + (*oid_set)->elements = realloc ((*oid_set)->elements, + n * sizeof(gss_OID_desc)); + if ((*oid_set)->elements == NULL) { + return GSS_S_FAILURE; + } + (*oid_set)->count = n; + (*oid_set)->elements[n-1] = *member_oid; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/create_emtpy_oid_set.c b/lib/gssapi/krb5/create_emtpy_oid_set.c new file mode 100644 index 000000000..b67e4fe59 --- /dev/null +++ b/lib/gssapi/krb5/create_emtpy_oid_set.c @@ -0,0 +1,17 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_create_empty_oid_set ( + OM_uint32 * minor_status, + gss_OID_set * oid_set + ) +{ + *oid_set = malloc(sizeof(**oid_set)); + if (*oid_set == NULL) { + return GSS_S_FAILURE; + } + (*oid_set)->count = 0; + (*oid_set)->elements = NULL; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/decapsulate.c b/lib/gssapi/krb5/decapsulate.c new file mode 100644 index 000000000..3a5d97158 --- /dev/null +++ b/lib/gssapi/krb5/decapsulate.c @@ -0,0 +1,36 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +/* + * Remove the GSS-API wrapping from `in_token' giving `out_data. + * Does not copy data, so just free `in_token'. + */ + +OM_uint32 +gssapi_krb5_decapsulate( + gss_buffer_t input_token_buffer, + krb5_data *out_data, + u_char *type +) +{ + u_char *p; + size_t len; + + p = input_token_buffer->value; + len = GSS_KRB5_MECHANISM->length + 6; + if ( + input_token_buffer->length < len + || memcmp (p, "\x60\x07\x06\x05", 4) != 0 + || memcmp (p + 4, GSS_KRB5_MECHANISM->elements, + GSS_KRB5_MECHANISM->length) != 0) + return GSS_S_BAD_MECH; + if (memcmp (p + 4 + GSS_KRB5_MECHANISM->length, + type, 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + + out_data->length = input_token_buffer->length - len; + out_data->data = (u_char *)input_token_buffer->value + len; + + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/delete_sec_context.c b/lib/gssapi/krb5/delete_sec_context.c new file mode 100644 index 000000000..1381aaf57 --- /dev/null +++ b/lib/gssapi/krb5/delete_sec_context.c @@ -0,0 +1,24 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_delete_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token + ) +{ + gssapi_krb5_init (); + krb5_auth_con_free (gssapi_krb5_context, + (*context_handle)->auth_context); + if((*context_handle)->source) + krb5_free_principal (gssapi_krb5_context, + (*context_handle)->source); + if((*context_handle)->target) + krb5_free_principal (gssapi_krb5_context, + (*context_handle)->target); + free (*context_handle); + if (output_token) + output_token->length = 0; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/display_name.c b/lib/gssapi/krb5/display_name.c new file mode 100644 index 000000000..35b58c21a --- /dev/null +++ b/lib/gssapi/krb5/display_name.c @@ -0,0 +1,32 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_display_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID * output_name_type + ) +{ + krb5_error_code kret; + char *buf; + size_t len; + + gssapi_krb5_init (); + kret = krb5_unparse_name (gssapi_krb5_context, + input_name, + &buf); + if (kret) + return GSS_S_FAILURE; + len = strlen (buf); + output_name_buffer->length = len; + output_name_buffer->value = malloc(len); + if (output_name_buffer->value == NULL) { + free (buf); + return GSS_S_FAILURE; + } + memcpy (output_name_buffer->value, buf, len); + free (buf); + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/duplicate_name.c b/lib/gssapi/krb5/duplicate_name.c new file mode 100644 index 000000000..1134813d2 --- /dev/null +++ b/lib/gssapi/krb5/duplicate_name.c @@ -0,0 +1,22 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_duplicate_name ( + OM_uint32 * minor_status, + const gss_name_t src_name, + gss_name_t * dest_name + ) +{ + krb5_error_code kret; + + gssapi_krb5_init (); + + kret = krb5_copy_principal (gssapi_krb5_context, + src_name, + dest_name); + if (kret) + return GSS_S_FAILURE; + else + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/encapsulate.c b/lib/gssapi/krb5/encapsulate.c new file mode 100644 index 000000000..598167466 --- /dev/null +++ b/lib/gssapi/krb5/encapsulate.c @@ -0,0 +1,33 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +/* + * Give it a krb5_data and it will encapsulate with extra GSS-API wrappings. + */ + +OM_uint32 +gssapi_krb5_encapsulate( + krb5_data *in_data, + gss_buffer_t output_token, + u_char *type +) +{ + u_char *p; + + output_token->length = in_data->length + GSS_KRB5_MECHANISM->length + 6; + output_token->value = malloc (output_token->length); + if (output_token->value == NULL) + return GSS_S_FAILURE; + + p = output_token->value; + memcpy (p, "\x60\x07\x06\x05", 4); + p += 4; + memcpy (p, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); + p += GSS_KRB5_MECHANISM->length; + memcpy (p, type, 2); + p += 2; + memcpy (p, in_data->data, in_data->length); + krb5_data_free (in_data); + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/external.c b/lib/gssapi/krb5/external.c new file mode 100644 index 000000000..cfa8fa61c --- /dev/null +++ b/lib/gssapi/krb5/external.c @@ -0,0 +1,172 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x01"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant + * GSS_C_NT_USER_NAME should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_user_name_oid_desc = +{10, (void *)"\x2a\x86\x48\x86\xf7\x12" + "\x01\x02\x01\x01"}; + +gss_OID GSS_C_NT_USER_NAME = &gss_c_nt_user_name_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x02"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. + * The constant GSS_C_NT_MACHINE_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_machine_uid_name_oid_desc = +{10, (void *)"\x2a\x86\x48\x86\xf7\x12" + "\x01\x02\x01\x02"}; + +gss_OID GSS_C_NT_MACHINE_UID_NAME = &gss_c_nt_machine_uid_name_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x03"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) string_uid_name(3)}. + * The constant GSS_C_NT_STRING_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_string_uid_name_oid_desc = +{10, (void *)"\x2a\x86\x48\x86\xf7\x12" + "\x01\x02\x01\x03"}; + +gss_OID GSS_C_NT_STRING_UID_NAME = &gss_c_nt_string_uid_name_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 2(gss-host-based-services)}. The constant + * GSS_C_NT_HOSTBASED_SERVICE should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_hostbased_service_oid_desc = +{6, (void *)"\x2b\x06\x01\x05\x06\x02"}; + +gss_OID GSS_C_NT_HOSTBASED_SERVICE = &gss_c_nt_hostbased_service_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, + * corresponding to an object identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 3(gss-anonymous-name)}. The constant + * and GSS_C_NT_ANONYMOUS should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_anonymous_oid_desc = +{6, (void *)"\x2b\x06\01\x05\x06\x03"}; + +gss_OID GSS_C_NT_ANONYMOUS = &gss_c_nt_anonymous_oid_desc; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 4(gss-api-exported-name)}. The constant + * GSS_C_NT_EXPORT_NAME should be initialized to point + * to that gss_OID_desc. + */ + +static gss_OID_desc gss_c_nt_export_name_oid_desc = +{6, (void *)"\x2b\x06\x01\x05\x06\x04"}; + +gss_OID GSS_C_NT_EXPORT_NAME = &gss_c_nt_export_name_oid_desc; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * krb5(2) krb5_name(1)}. The recommended symbolic name for this type + * is "GSS_KRB5_NT_PRINCIPAL_NAME". + */ + +static gss_OID_desc gss_krb5_nt_principal_name_oid_desc = +{10, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x01"}; + +gss_OID GSS_KRB5_NT_PRINCIPAL_NAME = &gss_krb5_nt_principal_name_oid_desc; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) user_name(1)}. The recommended symbolic name for this + * type is "GSS_KRB5_NT_USER_NAME". + */ + +gss_OID GSS_KRB5_NT_USER_NAME = &gss_c_nt_user_name_oid_desc; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) machine_uid_name(2)}. The recommended symbolic name for + * this type is "GSS_KRB5_NT_MACHINE_UID_NAME". + */ + +gss_OID GSS_KRB5_NT_MACHINE_UID_NAME = &gss_c_nt_machine_uid_name_oid_desc; + +/* + * This name form shall be represented by the Object Identifier {iso(1) + * member-body(2) United States(840) mit(113554) infosys(1) gssapi(2) + * generic(1) string_uid_name(3)}. The recommended symbolic name for + * this type is "GSS_KRB5_NT_STRING_UID_NAME". + */ + +gss_OID GSS_KRB5_NT_STRING_UID_NAME = &gss_c_nt_string_uid_name_oid_desc; + +/* + * To support ongoing experimentation, testing, and evolution of the + * specification, the Kerberos V5 GSS-API mechanism as defined in this + * and any successor memos will be identified with the following Object + * Identifier, as defined in RFC-1510, until the specification is + * advanced to the level of Proposed Standard RFC: + * + * {iso(1), org(3), dod(5), internet(1), security(5), kerberosv5(2)} + * + * Upon advancement to the level of Proposed Standard RFC, the Kerberos + * V5 GSS-API mechanism will be identified by an Object Identifier + * having the value: + * + * {iso(1) member-body(2) United States(840) mit(113554) infosys(1) + * gssapi(2) krb5(2)} + */ + +static gss_OID_desc gss_krb5_mechanism_oid_desc = +{5, (void *)"\x2b\x05\x01\x05\x02"}; + +gss_OID GSS_KRB5_MECHANISM = &gss_krb5_mechanism_oid_desc; + +/* + * Context for krb5 calls. + */ + +krb5_context gssapi_krb5_context; diff --git a/lib/gssapi/krb5/get_mic.c b/lib/gssapi/krb5/get_mic.c new file mode 100644 index 000000000..57506c911 --- /dev/null +++ b/lib/gssapi/krb5/get_mic.c @@ -0,0 +1,58 @@ +#include "gssapi_locl.h" +#include +#include + +RCSID("$Id$"); + +OM_uint32 gss_get_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ) +{ + u_char *p; + size_t len; + struct md5 md5; + u_char hash[16]; + des_key_schedule schedule; + des_cblock key; + des_cblock zero; + + len = 28 + GSS_KRB5_MECHANISM->length; + message_token->length = len; + message_token->value = malloc (len); + if (message_token->value == NULL) + return GSS_S_FAILURE; + + p = message_token->value; + memcpy (p, "\x60\x07\x06\x05", 4); + p += 4; + memcpy (p, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); + p += GSS_KRB5_MECHANISM->length; + memcpy (p, "\x01\x01", 2); + p += 2; + memcpy (p, "\x00\x00", 2); + p += 2; + memcpy (p, "\xff\xff\xff\xff", 4); + p += 4; + + memset (p, 0, 16); + p += 16; + + md5_init (&md5); + md5_update (&md5, p - 24, 8); + md5_update (&md5, message_buffer->value, + message_buffer->length); + md5_finito (&md5, hash); + + memset (&zero, 0, sizeof(zero)); + memcpy (&key, context_handle->auth_context->key.contents.data, + sizeof(key)); + des_set_key (&key, schedule); + des_cbc_cksum ((des_cblock *)hash, + (des_cblock *)hash, sizeof(hash), schedule, &zero); + memcpy (p - 8, hash, 8); + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/gssapi.h b/lib/gssapi/krb5/gssapi.h new file mode 100644 index 000000000..97441518d --- /dev/null +++ b/lib/gssapi/krb5/gssapi.h @@ -0,0 +1,693 @@ +/* $Id$ */ + +#ifndef GSSAPI_H_ +#define GSSAPI_H_ + +/* + * First, include stddef.h to get size_t defined. + */ +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#ifdef HAVE_SYS_BITYPES_H +#include +#endif + +#include + +#include + +/* + * Now define the three implementation-dependent types. + */ + +typedef u_int32_t OM_uint32; + +/* + * XXX - Should we really do it this way? + * I'm not entirely happy with exposing this match of the krb5 stuff + * here, and having to include the file as well. + */ + +typedef krb5_principal gss_name_t; + +typedef struct gss_ctx_id_t_desc_struct { + krb5_auth_context auth_context; + gss_name_t source, target; + OM_uint32 flags; + enum { LOCAL = 1, OPEN = 2} more_flags; +} gss_ctx_id_t_desc; + +typedef gss_ctx_id_t_desc *gss_ctx_id_t; +typedef int gss_cred_id_t; /* XXX */ + + +typedef struct gss_OID_desc_struct { + OM_uint32 length; + void *elements; +} gss_OID_desc, *gss_OID; + +typedef struct gss_OID_set_desc_struct { + size_t count; + gss_OID elements; +} gss_OID_set_desc, *gss_OID_set; + +typedef struct gss_buffer_desc_struct { + size_t length; + void *value; +} gss_buffer_desc, *gss_buffer_t; + +typedef struct gss_channel_bindings_struct { + OM_uint32 initiator_addrtype; + gss_buffer_desc initiator_address; + OM_uint32 acceptor_addrtype; + gss_buffer_desc acceptor_address; + gss_buffer_desc application_data; +} *gss_channel_bindings_t; + +/* + * For now, define a QOP-type as an OM_uint32 + */ +typedef OM_uint32 gss_qop_t; + +typedef int gss_cred_usage_t; + +/* + * Flag bits for context-level services. + */ +#define GSS_C_DELEG_FLAG 1 +#define GSS_C_MUTUAL_FLAG 2 +#define GSS_C_REPLAY_FLAG 4 +#define GSS_C_SEQUENCE_FLAG 8 +#define GSS_C_CONF_FLAG 16 +#define GSS_C_INTEG_FLAG 32 +#define GSS_C_ANON_FLAG 64 +#define GSS_C_PROT_READY_FLAG 128 +#define GSS_C_TRANS_FLAG 256 + +/* + * Credential usage options + */ +#define GSS_C_BOTH 0 +#define GSS_C_INITIATE 1 +#define GSS_C_ACCEPT 2 + +/* + * Status code types for gss_display_status + */ +#define GSS_C_GSS_CODE 1 +#define GSS_C_MECH_CODE 2 + +/* + * The constant definitions for channel-bindings address families + */ +#define GSS_C_AF_UNSPEC 0 +#define GSS_C_AF_LOCAL 1 +#define GSS_C_AF_INET 2 +#define GSS_C_AF_IMPLINK 3 +#define GSS_C_AF_PUP 4 +#define GSS_C_AF_CHAOS 5 +#define GSS_C_AF_NS 6 +#define GSS_C_AF_NBS 7 +#define GSS_C_AF_ECMA 8 +#define GSS_C_AF_DATAKIT 9 +#define GSS_C_AF_CCITT 10 +#define GSS_C_AF_SNA 11 +#define GSS_C_AF_DECnet 12 +#define GSS_C_AF_DLI 13 +#define GSS_C_AF_LAT 14 +#define GSS_C_AF_HYLINK 15 +#define GSS_C_AF_APPLETALK 16 +#define GSS_C_AF_BSC 17 +#define GSS_C_AF_DSS 18 +#define GSS_C_AF_OSI 19 +#define GSS_C_AF_X25 21 + +#define GSS_C_AF_NULLADDR 255 + +/* + * Various Null values + */ +#define GSS_C_NO_NAME ((gss_name_t) 0) +#define GSS_C_NO_BUFFER ((gss_buffer_t) 0) +#define GSS_C_NO_OID ((gss_OID) 0) +#define GSS_C_NO_OID_SET ((gss_OID_set) 0) +#define GSS_C_NO_CONTEXT ((gss_ctx_id_t) 0) +#define GSS_C_NO_CREDENTIAL ((gss_cred_id_t) 0) +#define GSS_C_NO_CHANNEL_BINDINGS ((gss_channel_bindings_t) 0) +#define GSS_C_EMPTY_BUFFER {0, NULL} + +/* + * Some alternate names for a couple of the above + * values. These are defined for V1 compatibility. + */ +#define GSS_C_NULL_OID GSS_C_NO_OID +#define GSS_C_NULL_OID_SET GSS_C_NO_OID_SET + +/* + * Define the default Quality of Protection for per-message + * services. Note that an implementation that offers multiple + * levels of QOP may define GSS_C_QOP_DEFAULT to be either zero + * (as done here) to mean "default protection", or to a specific + * explicit QOP value. However, a value of 0 should always be + * interpreted by a GSSAPI implementation as a request for the + * default protection level. + */ +#define GSS_C_QOP_DEFAULT 0 + +/* + * Expiration time of 2^32-1 seconds means infinite lifetime for a + * credential or security context + */ +#define GSS_C_INDEFINITE 0xfffffffful + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x01"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) user_name(1)}. The constant + * GSS_C_NT_USER_NAME should be initialized to point + * to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_USER_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x02"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) machine_uid_name(2)}. + * The constant GSS_C_NT_MACHINE_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_MACHINE_UID_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {10, (void *)"\x2a\x86\x48\x86\xf7\x12" + * "\x01\x02\x01\x03"}, + * corresponding to an object-identifier value of + * {iso(1) member-body(2) United States(840) mit(113554) + * infosys(1) gssapi(2) generic(1) string_uid_name(3)}. + * The constant GSS_C_NT_STRING_UID_NAME should be + * initialized to point to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_STRING_UID_NAME; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x02"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 2(gss-host-based-services)}. The constant + * GSS_C_NT_HOSTBASED_SERVICE should be initialized to point + * to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_HOSTBASED_SERVICE; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\01\x05\x06\x03"}, + * corresponding to an object identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 3(gss-anonymous-name)}. The constant + * and GSS_C_NT_ANONYMOUS should be initialized to point + * to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_ANONYMOUS; + +/* + * The implementation must reserve static storage for a + * gss_OID_desc object containing the value + * {6, (void *)"\x2b\x06\x01\x05\x06\x04"}, + * corresponding to an object-identifier value of + * {1(iso), 3(org), 6(dod), 1(internet), 5(security), + * 6(nametypes), 4(gss-api-exported-name)}. The constant + * GSS_C_NT_EXPORT_NAME should be initialized to point + * to that gss_OID_desc. + */ +extern gss_OID GSS_C_NT_EXPORT_NAME; + +/* + * This if for kerberos5 names. + */ + +extern gss_OID GSS_KRB5_NT_PRINCIPAL_NAME; +extern gss_OID GSS_KRB5_NT_PRINCIPAL_NAME; +extern gss_OID GSS_KRB5_NT_USER_NAME; +extern gss_OID GSS_KRB5_NT_MACHINE_UID_NAME; +extern gss_OID GSS_KRB5_NT_STRING_UID_NAME; + +extern gss_OID GSS_KRB5_MECHANISM; + +/* Major status codes */ + +#define GSS_S_COMPLETE 0 + +/* + * Some "helper" definitions to make the status code macros obvious. + */ +#define GSS_C_CALLING_ERROR_OFFSET 24 +#define GSS_C_ROUTINE_ERROR_OFFSET 16 +#define GSS_C_SUPPLEMENTARY_OFFSET 0 +#define GSS_C_CALLING_ERROR_MASK 0377ul +#define GSS_C_ROUTINE_ERROR_MASK 0377ul +#define GSS_C_SUPPLEMENTARY_MASK 0177777ul + +/* + * The macros that test status codes for error conditions. + * Note that the GSS_ERROR() macro has changed slightly from + * the V1 GSSAPI so that it now evaluates its argument + * only once. + */ +#define GSS_CALLING_ERROR(x) \ + (x & (GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET)) +#define GSS_ROUTINE_ERROR(x) \ + (x & (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET)) +#define GSS_SUPPLEMENTARY_INFO(x) \ + (x & (GSS_C_SUPPLEMENTARY_MASK << GSS_C_SUPPLEMENTARY_OFFSET)) +#define GSS_ERROR(x) \ + (x & ((GSS_C_CALLING_ERROR_MASK << GSS_C_CALLING_ERROR_OFFSET) | \ + (GSS_C_ROUTINE_ERROR_MASK << GSS_C_ROUTINE_ERROR_OFFSET))) + +/* + * Now the actual status code definitions + */ + +/* + * Calling errors: + */ +#define GSS_S_CALL_INACCESSIBLE_READ \ + (1ul << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_INACCESSIBLE_WRITE \ + (2ul << GSS_C_CALLING_ERROR_OFFSET) +#define GSS_S_CALL_BAD_STRUCTURE \ + (3ul << GSS_C_CALLING_ERROR_OFFSET) + +/* + * Routine errors: + */ +#define GSS_S_BAD_MECH (1ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAME (2ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_NAMETYPE (3ul << GSS_C_ROUTINE_ERROR_OFFSET) + +#define GSS_S_BAD_BINDINGS (4ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_STATUS (5ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_SIG (6ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_MIC GSS_S_BAD_SIG +#define GSS_S_NO_CRED (7ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NO_CONTEXT (8ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_TOKEN (9ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DEFECTIVE_CREDENTIAL (10ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CREDENTIALS_EXPIRED (11ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_CONTEXT_EXPIRED (12ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_FAILURE (13ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_BAD_QOP (14ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAUTHORIZED (15ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_UNAVAILABLE (16ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_DUPLICATE_ELEMENT (17ul << GSS_C_ROUTINE_ERROR_OFFSET) +#define GSS_S_NAME_NOT_MN (18ul << GSS_C_ROUTINE_ERROR_OFFSET) + +/* + * Supplementary info bits: + */ +#define GSS_S_CONTINUE_NEEDED (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 0)) +#define GSS_S_DUPLICATE_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 1)) +#define GSS_S_OLD_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 2)) +#define GSS_S_UNSEQ_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 3)) +#define GSS_S_GAP_TOKEN (1ul << (GSS_C_SUPPLEMENTARY_OFFSET + 4)) + +/* + * From RFC1964: + * + * 4.1.1. Non-Kerberos-specific codes + */ + +#define GSS_KRB5_S_G_BAD_SERVICE_NAME 1 + /* "No @ in SERVICE-NAME name string" */ +#define GSS_KRB5_S_G_BAD_STRING_UID 2 + /* "STRING-UID-NAME contains nondigits" */ +#define GSS_KRB5_S_G_NOUSER 3 + /* "UID does not resolve to username" */ +#define GSS_KRB5_S_G_VALIDATE_FAILED 4 + /* "Validation error" */ +#define GSS_KRB5_S_G_BUFFER_ALLOC 5 + /* "Couldn't allocate gss_buffer_t data" */ +#define GSS_KRB5_S_G_BAD_MSG_CTX 6 + /* "Message context invalid" */ +#define GSS_KRB5_S_G_WRONG_SIZE 7 + /* "Buffer is the wrong size" */ +#define GSS_KRB5_S_G_BAD_USAGE 8 + /* "Credential usage type is unknown" */ +#define GSS_KRB5_S_G_UNKNOWN_QOP 9 + /* "Unknown quality of protection specified" */ + + /* + * 4.1.2. Kerberos-specific-codes + */ + +#define GSS_KRB5_S_KG_CCACHE_NOMATCH 10 + /* "Principal in credential cache does not match desired name" */ +#define GSS_KRB5_S_KG_KEYTAB_NOMATCH 11 + /* "No principal in keytab matches desired name" */ +#define GSS_KRB5_S_KG_TGT_MISSING 12 + /* "Credential cache has no TGT" */ +#define GSS_KRB5_S_KG_NO_SUBKEY 13 + /* "Authenticator has no subkey" */ +#define GSS_KRB5_S_KG_CONTEXT_ESTABLISHED 14 + /* "Context is already fully established" */ +#define GSS_KRB5_S_KG_BAD_SIGN_TYPE 15 + /* "Unknown signature type in token" */ +#define GSS_KRB5_S_KG_BAD_LENGTH 16 + /* "Invalid field length in token" */ +#define GSS_KRB5_S_KG_CTX_INCOMPLETE 17 + /* "Attempt to use incomplete security context" */ + +/* + * Finally, function prototypes for the GSS-API routines. + */ + +OM_uint32 gss_acquire_cred + (OM_uint32 * minor_status, + const gss_name_t desired_name, + OM_uint32 time_req, + const gss_OID_set desired_mechs, + gss_cred_usage_t cred_usage, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * time_rec + ); + +OM_uint32 gss_release_cred + (OM_uint32 * minor_status, + gss_cred_id_t * cred_handle + ); + +OM_uint32 gss_init_sec_context + (OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ); + +OM_uint32 gss_accept_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + const gss_cred_id_t acceptor_cred_handle, + const gss_buffer_t input_token_buffer, + const gss_channel_bindings_t input_chan_bindings, + gss_name_t * src_name, + gss_OID * mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec, + gss_cred_id_t * delegated_cred_handle + ); + +OM_uint32 gss_process_context_token + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t token_buffer + ); + +OM_uint32 gss_delete_sec_context + (OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t output_token + ); + +OM_uint32 gss_context_time + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + OM_uint32 * time_rec + ); + +OM_uint32 gss_get_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_qop_t qop_req, + const gss_buffer_t message_buffer, + gss_buffer_t message_token + ); + +OM_uint32 gss_verify_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state + ); + +OM_uint32 gss_wrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ); + +OM_uint32 gss_unwrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state + ); + +OM_uint32 gss_display_status + (OM_uint32 * minor_status, + OM_uint32 status_value, + int status_type, + const gss_OID mech_type, + OM_uint32 * message_context, + gss_buffer_t status_string + ); + +OM_uint32 gss_indicate_mechs + (OM_uint32 * minor_status, + gss_OID_set * mech_set + ); + +OM_uint32 gss_compare_name + (OM_uint32 * minor_status, + const gss_name_t name1, + const gss_name_t name2, + int * name_equal + ); + +OM_uint32 gss_display_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t output_name_buffer, + gss_OID * output_name_type + ); + +OM_uint32 gss_import_name + (OM_uint32 * minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t * output_name + ); + +OM_uint32 gss_export_name + (OM_uint32 * minor_status, + const gss_name_t input_name, + gss_buffer_t exported_name + ); + +OM_uint32 gss_release_name + (OM_uint32 * minor_status, + gss_name_t * input_name + ); + +OM_uint32 gss_release_buffer + (OM_uint32 * minor_status, + gss_buffer_t buffer + ); + +OM_uint32 gss_release_oid_set + (OM_uint32 * minor_status, + gss_OID_set * set + ); + +OM_uint32 gss_inquire_cred + (OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + gss_name_t * name, + OM_uint32 * lifetime, + gss_cred_usage_t * cred_usage, + gss_OID_set * mechanisms + ); + +OM_uint32 gss_inquire_context ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_name_t * src_name, + gss_name_t * targ_name, + OM_uint32 * lifetime_rec, + gss_OID * mech_type, + OM_uint32 * ctx_flags, + int * locally_initiated, + int * open + ); + +OM_uint32 gss_wrap_size_limit ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + OM_uint32 req_output_size, + OM_uint32 * max_input_size + ); + +OM_uint32 gss_add_cred ( + OM_uint32 * minor_status, + const gss_cred_id_t input_cred_handle, + const gss_name_t desired_name, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + OM_uint32 initiator_time_req, + OM_uint32 acceptor_time_req, + gss_cred_id_t * output_cred_handle, + gss_OID_set * actual_mechs, + OM_uint32 * initiator_time_rec, + OM_uint32 * acceptor_time_rec + ); + +OM_uint32 gss_inquire_cred_by_mech ( + OM_uint32 * minor_status, + const gss_cred_id_t cred_handle, + const gss_OID mech_type, + gss_name_t * name, + OM_uint32 * initiator_lifetime, + OM_uint32 * acceptor_lifetime, + gss_cred_usage_t * cred_usage + ); + +OM_uint32 gss_export_sec_context ( + OM_uint32 * minor_status, + gss_ctx_id_t * context_handle, + gss_buffer_t interprocess_token + ); + +OM_uint32 gss_import_sec_context ( + OM_uint32 * minor_status, + const gss_buffer_t interprocess_token, + gss_ctx_id_t * context_handle + ); + +OM_uint32 gss_create_empty_oid_set ( + OM_uint32 * minor_status, + gss_OID_set * oid_set + ); + +OM_uint32 gss_add_oid_set_member ( + OM_uint32 * minor_status, + const gss_OID member_oid, + gss_OID_set * oid_set + ); + +OM_uint32 gss_test_oid_set_member ( + OM_uint32 * minor_status, + const gss_OID member, + const gss_OID_set set, + int * present + ); + +OM_uint32 gss_inquire_names_for_mech ( + OM_uint32 * minor_status, + const gss_OID mechanism, + gss_OID_set * name_types + ); + +OM_uint32 gss_inquire_mechs_for_name ( + OM_uint32 * minor_status, + const gss_name_t input_name, + gss_OID_set * mech_types + ); + +OM_uint32 gss_canonicalize_name ( + OM_uint32 * minor_status, + const gss_name_t input_name, + const gss_OID mech_type, + gss_name_t * output_name + ); + +OM_uint32 gss_duplicate_name ( + OM_uint32 * minor_status, + const gss_name_t src_name, + gss_name_t * dest_name + ); + +/* + * The following routines are obsolete variants of gss_get_mic, + * gss_verify_mic, gss_wrap and gss_unwrap. They should be + * provided by GSSAPI V2 implementations for backwards + * compatibility with V1 applications. Distinct entrypoints + * (as opposed to #defines) should be provided, both to allow + * GSSAPI V1 applications to link against GSSAPI V2 implementations, + * and to retain the slight parameter type differences between the + * obsolete versions of these routines and their current forms. + */ + +OM_uint32 gss_sign + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int qop_req, + gss_buffer_t message_buffer, + gss_buffer_t message_token + ); + +OM_uint32 gss_verify + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t message_buffer, + gss_buffer_t token_buffer, + int * qop_state + ); + +OM_uint32 gss_seal + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + int conf_req_flag, + int qop_req, + gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ); + +OM_uint32 gss_unseal + (OM_uint32 * minor_status, + gss_ctx_id_t context_handle, + gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + int * qop_state + ); + +#endif /* GSSAPI_H_ */ diff --git a/lib/gssapi/krb5/gssapi_locl.h b/lib/gssapi/krb5/gssapi_locl.h new file mode 100644 index 000000000..759726199 --- /dev/null +++ b/lib/gssapi/krb5/gssapi_locl.h @@ -0,0 +1,30 @@ +/* $Id$ */ + +#ifndef GSSAPI_LOCL_H +#define GSSAPI_LOCL_H + +#include +#include + +#include + +#include +#include + +extern krb5_context gssapi_krb5_context; + +void gssapi_krb5_init (void); + +OM_uint32 +gssapi_krb5_encapsulate( + krb5_data *in_data, + gss_buffer_t output_token, + u_char *type); + +OM_uint32 +gssapi_krb5_decapsulate( + gss_buffer_t input_token_buffer, + krb5_data *out_data, + u_char *type); + +#endif diff --git a/lib/gssapi/krb5/import_name.c b/lib/gssapi/krb5/import_name.c new file mode 100644 index 000000000..aab0a0b6f --- /dev/null +++ b/lib/gssapi/krb5/import_name.c @@ -0,0 +1,36 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_import_name + (OM_uint32 * minor_status, + const gss_buffer_t input_name_buffer, + const gss_OID input_name_type, + gss_name_t * output_name + ) +{ + krb5_error_code kerr; + char *tmp; + + gssapi_krb5_init (); + + tmp = malloc (input_name_buffer->length + 1); + if (tmp == NULL) { + return GSS_S_FAILURE; + } + memcpy (tmp, + input_name_buffer->value, + input_name_buffer->length); + tmp[input_name_buffer->length] = '\0'; + + kerr = krb5_parse_name (gssapi_krb5_context, + tmp, + output_name); + free (tmp); + if (kerr == 0) + return GSS_S_COMPLETE; + else if (kerr = KRB5_PARSE_ILLCHAR || kerr == KRB5_PARSE_MALFORMED) + return GSS_S_BAD_NAME; + else + return GSS_S_FAILURE; +} diff --git a/lib/gssapi/krb5/indicate_mechs.c b/lib/gssapi/krb5/indicate_mechs.c new file mode 100644 index 000000000..d324f9a41 --- /dev/null +++ b/lib/gssapi/krb5/indicate_mechs.c @@ -0,0 +1,22 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_indicate_mechs + (OM_uint32 * minor_status, + gss_OID_set * mech_set + ) +{ + *mech_set = malloc(sizeof(**mech_set)); + if (*mech_set == NULL) { + return GSS_S_FAILURE; + } + (*mech_set)->count = 1; + (*mech_set)->elements = malloc((*mech_set)->count * sizeof(gss_OID_desc)); + if ((*mech_set)->elements == NULL) { + free (*mech_set); + return GSS_S_FAILURE; + } + (*mech_set)->elements[0] = *GSS_KRB5_MECHANISM; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/init.c b/lib/gssapi/krb5/init.c new file mode 100644 index 000000000..23ea03ede --- /dev/null +++ b/lib/gssapi/krb5/init.c @@ -0,0 +1,15 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +void +gssapi_krb5_init (void) +{ + static int donep = 0; + + if (donep) + return; + + krb5_init_context (&gssapi_krb5_context); + donep = 1; +} diff --git a/lib/gssapi/krb5/init_sec_context.c b/lib/gssapi/krb5/init_sec_context.c new file mode 100644 index 000000000..92c729df6 --- /dev/null +++ b/lib/gssapi/krb5/init_sec_context.c @@ -0,0 +1,312 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +static krb5_error_code +create_8003_checksum ( + const gss_channel_bindings_t input_chan_bindings, + OM_uint32 flags, + Checksum *result) +{ + u_char *p; + u_int32_t val; + + result->cksumtype = 0x8003; + result->checksum.length = 24; + result->checksum.data = malloc (result->checksum.length); + if (result->checksum.data == NULL) + return ENOMEM; + + p = result->checksum.data; + val = 16; + *p++ = (val >> 0) & 0xFF; + *p++ = (val >> 8) & 0xFF; + *p++ = (val >> 16) & 0xFF; + *p++ = (val >> 24) & 0xFF; + memset (p, 0, 16); + p += 16; + val = flags; + *p++ = (val >> 0) & 0xFF; + *p++ = (val >> 8) & 0xFF; + *p++ = (val >> 16) & 0xFF; + *p++ = (val >> 24) & 0xFF; + if (p - (u_char *)result->checksum.data != result->checksum.length) + abort (); + return 0; +} + +static OM_uint32 +init_auth + (OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_flags ap_options; + krb5_creds this_cred, *cred; + krb5_data outbuf; + krb5_ccache ccache; + u_int32_t flags; + Authenticator *auth; + krb5_data authenticator; + Checksum cksum; + + gssapi_krb5_init (); + + outbuf.length = 0; + outbuf.data = NULL; + + + + + *context_handle = malloc(sizeof(**context_handle)); + if (*context_handle == NULL) + return GSS_S_FAILURE; + + (*context_handle)->auth_context = NULL; + (*context_handle)->source = NULL; + (*context_handle)->target = NULL; + (*context_handle)->flags = 0; + (*context_handle)->more_flags = 0; + + kret = krb5_auth_con_init (gssapi_krb5_context, + &(*context_handle)->auth_context); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + if (actual_mech_type) + *actual_mech_type = GSS_KRB5_MECHANISM; + + flags = 0; + ap_options = 0; + if (req_flags & GSS_C_DELEG_FLAG) + ; /* XXX */ + if (req_flags & GSS_C_MUTUAL_FLAG) { + flags |= GSS_C_MUTUAL_FLAG; + ap_options |= AP_OPTS_MUTUAL_REQUIRED; + } + if (req_flags & GSS_C_REPLAY_FLAG) + ; /* XXX */ + if (req_flags & GSS_C_SEQUENCE_FLAG) + ; /* XXX */ + if (req_flags & GSS_C_ANON_FLAG) + ; /* XXX */ + flags |= GSS_C_CONF_FLAG; + flags |= GSS_C_INTEG_FLAG; + + if (ret_flags) + *ret_flags = flags; + (*context_handle)->flags = flags; + (*context_handle)->more_flags = LOCAL; + + kret = krb5_cc_default (gssapi_krb5_context, &ccache); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_cc_get_principal (gssapi_krb5_context, + ccache, + &(*context_handle)->source); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_copy_principal (gssapi_krb5_context, + target_name, + &(*context_handle)->target); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + this_cred.client = (*context_handle)->source; + this_cred.server = (*context_handle)->target; + this_cred.times.endtime = 0; + + kret = krb5_get_credentials (gssapi_krb5_context, + 0, + ccache, + &this_cred, + &cred); + + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + (*context_handle)->auth_context->key.keytype = cred->session.keytype; + krb5_data_copy (&(*context_handle)->auth_context->key.contents, + cred->session.contents.data, + cred->session.contents.length); + + kret = create_8003_checksum (input_chan_bindings, + flags, + &cksum); + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_build_authenticator (gssapi_krb5_context, + (*context_handle)->auth_context, + cred, + &cksum, + &auth, + &authenticator); + + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + kret = krb5_build_ap_req (gssapi_krb5_context, + cred, + ap_options, + authenticator, + &outbuf); + krb5_data_free (&authenticator); + + if (kret) { + ret = GSS_S_FAILURE; + goto failure; + } + + ret = gssapi_krb5_encapsulate (&outbuf, + output_token, + "\x01\x00"); + if (ret) + goto failure; + + if (flags & GSS_C_MUTUAL_FLAG) { + return GSS_S_CONTINUE_NEEDED; + } else { + (*context_handle)->more_flags |= OPEN; + return GSS_S_COMPLETE; + } + +failure: + krb5_auth_con_free (gssapi_krb5_context, + (*context_handle)->auth_context); + if((*context_handle)->source) + krb5_free_principal (gssapi_krb5_context, + (*context_handle)->source); + if((*context_handle)->target) + krb5_free_principal (gssapi_krb5_context, + (*context_handle)->target); + free (*context_handle); + krb5_data_free (&outbuf); + *context_handle = GSS_C_NO_CONTEXT; + return GSS_S_FAILURE; +} + +static OM_uint32 +repl_mutual + (OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + OM_uint32 ret; + krb5_error_code kret; + krb5_data indata; + krb5_ap_rep_enc_part *repl; + + ret = gssapi_krb5_decapsulate (input_token, + &indata, + "\x02\x00"); + if (ret) { + /* XXX - Handle AP_ERROR */ + return GSS_S_FAILURE; + } + + kret = krb5_rd_rep (gssapi_krb5_context, + (*context_handle)->auth_context, + &indata, + &repl); + if (kret) + return GSS_S_FAILURE; + krb5_free_ap_rep_enc_part (gssapi_krb5_context, + repl); + + (*context_handle)->more_flags |= OPEN; + + return GSS_S_COMPLETE; +} + +/* + * gss_init_sec_context + */ + +OM_uint32 gss_init_sec_context + (OM_uint32 * minor_status, + const gss_cred_id_t initiator_cred_handle, + gss_ctx_id_t * context_handle, + const gss_name_t target_name, + const gss_OID mech_type, + OM_uint32 req_flags, + OM_uint32 time_req, + const gss_channel_bindings_t input_chan_bindings, + const gss_buffer_t input_token, + gss_OID * actual_mech_type, + gss_buffer_t output_token, + OM_uint32 * ret_flags, + OM_uint32 * time_rec + ) +{ + gssapi_krb5_init (); + + if (input_token == GSS_C_NO_BUFFER || input_token->length == 0) + return init_auth (minor_status, + initiator_cred_handle, + context_handle, + target_name, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); + else + return repl_mutual(minor_status, + initiator_cred_handle, + context_handle, + target_name, + mech_type, + req_flags, + time_req, + input_chan_bindings, + input_token, + actual_mech_type, + output_token, + ret_flags, + time_rec); +} diff --git a/lib/gssapi/krb5/inquire_context.c b/lib/gssapi/krb5/inquire_context.c new file mode 100644 index 000000000..3ab64db41 --- /dev/null +++ b/lib/gssapi/krb5/inquire_context.c @@ -0,0 +1,51 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_inquire_context ( + OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + gss_name_t * src_name, + gss_name_t * targ_name, + OM_uint32 * lifetime_rec, + gss_OID * mech_type, + OM_uint32 * ctx_flags, + int * locally_initiated, + int * open + ) +{ + OM_uint32 ret; + + if (src_name) { + ret = gss_duplicate_name (minor_status, + context_handle->source, + src_name); + if (ret) + return ret; + } + + if (targ_name) { + ret = gss_duplicate_name (minor_status, + context_handle->target, + targ_name); + if (ret) + return ret; + } + + if (lifetime_rec) + *lifetime_rec = GSS_C_INDEFINITE; + + if (mech_type) + *mech_type = GSS_KRB5_MECHANISM; + + if (ctx_flags) + *ctx_flags = context_handle->flags; + + if (locally_initiated) + *locally_initiated = context_handle->more_flags & LOCAL; + + if (open) + *open = context_handle->more_flags & OPEN; + + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/release_buffer.c b/lib/gssapi/krb5/release_buffer.c new file mode 100644 index 000000000..e339f50a4 --- /dev/null +++ b/lib/gssapi/krb5/release_buffer.c @@ -0,0 +1,13 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_release_buffer + (OM_uint32 * minor_status, + gss_buffer_t buffer + ) +{ + free (buffer->value); + buffer->length = 0; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/release_oid_set.c b/lib/gssapi/krb5/release_oid_set.c new file mode 100644 index 000000000..e374338a7 --- /dev/null +++ b/lib/gssapi/krb5/release_oid_set.c @@ -0,0 +1,13 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_release_oid_set + (OM_uint32 * minor_status, + gss_OID_set * set + ) +{ + free ((*set)->elements); + free (*set); + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/test_oid_set_member.c b/lib/gssapi/krb5/test_oid_set_member.c new file mode 100644 index 000000000..d67d46290 --- /dev/null +++ b/lib/gssapi/krb5/test_oid_set_member.c @@ -0,0 +1,24 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_test_oid_set_member ( + OM_uint32 * minor_status, + const gss_OID member, + const gss_OID_set set, + int * present + ) +{ + size_t i; + + *present = 0; + for (i = 0; i < set->count; ++i) + if (member->length = set->elements[i].length + && memcmp (member->elements, + set->elements[i].elements, + member->length) == 0) { + *present = 1; + break; + } + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/unwrap.c b/lib/gssapi/krb5/unwrap.c new file mode 100644 index 000000000..59c17125c --- /dev/null +++ b/lib/gssapi/krb5/unwrap.c @@ -0,0 +1,69 @@ +#include "gssapi_locl.h" +#include +#include + +RCSID("$Id$"); + +OM_uint32 gss_unwrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state + ) +{ + u_char *p; + size_t len; + struct md5 md5; + u_char hash[16]; + des_key_schedule schedule; + des_cblock key; + des_cblock zero; + + p = input_message_buffer->value; + len = GSS_KRB5_MECHANISM->length + 28; + + if ( + input_message_buffer->length < len + || memcmp (p, "\x60\x07\x06\x05", 4) != 0 + || memcmp (p + 4, GSS_KRB5_MECHANISM->elements, + GSS_KRB5_MECHANISM->length) != 0) + return GSS_S_BAD_MECH; + if (memcmp (p + 4 + GSS_KRB5_MECHANISM->length, "\x02\x01", 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + p += 6 + GSS_KRB5_MECHANISM->length; + if (memcmp (p, "\x00\x00", 2) != 0) + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\xff\xff", 2) != 0) + return GSS_S_BAD_MIC; + p += 2; + if (memcmp (p, "\xff\xff", 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + p += 2; + p += 16; + + md5_init (&md5); + md5_update (&md5, p - 24, 8); + md5_update (&md5, p, input_message_buffer->length - len); + md5_finito (&md5, hash); + + memset (&zero, 0, sizeof(zero)); + memcpy (&key, context_handle->auth_context->key.contents.data, + sizeof(key)); + des_set_key (&key, schedule); + des_cbc_cksum ((des_cblock *)hash, + (des_cblock *)hash, sizeof(hash), schedule, &zero); + if (memcmp (p - 8, hash, 8) != 0) + return GSS_S_BAD_MIC; + + output_message_buffer->length = input_message_buffer->length - len; + output_message_buffer->value = malloc(output_message_buffer->length); + if(output_message_buffer->value == NULL) + return GSS_S_FAILURE; + memcpy (output_message_buffer->value, + p, + output_message_buffer->length); + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/verify_mic.c b/lib/gssapi/krb5/verify_mic.c new file mode 100644 index 000000000..1cd19a635 --- /dev/null +++ b/lib/gssapi/krb5/verify_mic.c @@ -0,0 +1,59 @@ +#include "gssapi_locl.h" +#include +#include + +RCSID("$Id$"); + +OM_uint32 gss_verify_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state + ) +{ + u_char *p; + size_t len; + struct md5 md5; + u_char hash[16]; + des_key_schedule schedule; + des_cblock key; + des_cblock zero; + + p = token_buffer->value; + len = GSS_KRB5_MECHANISM->length + 28; + + if ( + token_buffer->length < len + || memcmp (p, "\x60\x07\x06\x05", 4) != 0 + || memcmp (p + 4, GSS_KRB5_MECHANISM->elements, + GSS_KRB5_MECHANISM->length) != 0) + return GSS_S_BAD_MECH; + if (memcmp (p + 4 + GSS_KRB5_MECHANISM->length, "\x01\x01", 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + p += 6 + GSS_KRB5_MECHANISM->length; + if (memcmp (p, "\x00\x00", 2) != 0) + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) + return GSS_S_BAD_MIC; + p += 4; + p += 16; + + md5_init (&md5); + md5_update (&md5, p - 24, 8); + md5_update (&md5, message_buffer->value, + message_buffer->length); + md5_finito (&md5, hash); + + memset (&zero, 0, sizeof(zero)); + memcpy (&key, context_handle->auth_context->key.contents.data, + sizeof(key)); + des_set_key (&key, schedule); + des_cbc_cksum ((des_cblock *)hash, + (des_cblock *)hash, sizeof(hash), schedule, &zero); + if (memcmp (p - 8, hash, 8) != 0) + return GSS_S_BAD_MIC; + + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/krb5/wrap.c b/lib/gssapi/krb5/wrap.c new file mode 100644 index 000000000..fa7a5d432 --- /dev/null +++ b/lib/gssapi/krb5/wrap.c @@ -0,0 +1,63 @@ +#include "gssapi_locl.h" +#include +#include + +RCSID("$Id$"); + +OM_uint32 gss_wrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ) +{ + u_char *p; + size_t len; + struct md5 md5; + u_char hash[16]; + des_key_schedule schedule; + des_cblock key; + des_cblock zero; + + len = input_message_buffer->length + 28 + GSS_KRB5_MECHANISM->length; + output_message_buffer->length = len; + output_message_buffer->value = malloc (len); + if (output_message_buffer->value == NULL) + return GSS_S_FAILURE; + + p = output_message_buffer->value; + memcpy (p, "\x60\x07\x06\x05", 4); + p += 4; + memcpy (p, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); + p += GSS_KRB5_MECHANISM->length; + memcpy (p, "\x02\x01", 2); + p += 2; + memcpy (p, "\x00\x00", 2); + p += 2; + memcpy (p, "\xff\xff", 2); + p += 2; + memcpy (p, "\xff\xff", 2); + p += 2; + + memset (p, 0, 16); + p += 16; + memcpy (p, input_message_buffer->value, + input_message_buffer->length); + + md5_init (&md5); + md5_update (&md5, p - 24, 8); + md5_update (&md5, p, input_message_buffer->length); + md5_finito (&md5, hash); + + memset (&zero, 0, sizeof(zero)); + memcpy (&key, context_handle->auth_context->key.contents.data, + sizeof(key)); + des_set_key (&key, schedule); + des_cbc_cksum ((des_cblock *)hash, + (des_cblock *)hash, sizeof(hash), schedule, &zero); + memcpy (p - 8, hash, 8); + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/release_buffer.c b/lib/gssapi/release_buffer.c new file mode 100644 index 000000000..e339f50a4 --- /dev/null +++ b/lib/gssapi/release_buffer.c @@ -0,0 +1,13 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_release_buffer + (OM_uint32 * minor_status, + gss_buffer_t buffer + ) +{ + free (buffer->value); + buffer->length = 0; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/release_oid_set.c b/lib/gssapi/release_oid_set.c new file mode 100644 index 000000000..e374338a7 --- /dev/null +++ b/lib/gssapi/release_oid_set.c @@ -0,0 +1,13 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_release_oid_set + (OM_uint32 * minor_status, + gss_OID_set * set + ) +{ + free ((*set)->elements); + free (*set); + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/test_oid_set_member.c b/lib/gssapi/test_oid_set_member.c new file mode 100644 index 000000000..d67d46290 --- /dev/null +++ b/lib/gssapi/test_oid_set_member.c @@ -0,0 +1,24 @@ +#include "gssapi_locl.h" + +RCSID("$Id$"); + +OM_uint32 gss_test_oid_set_member ( + OM_uint32 * minor_status, + const gss_OID member, + const gss_OID_set set, + int * present + ) +{ + size_t i; + + *present = 0; + for (i = 0; i < set->count; ++i) + if (member->length = set->elements[i].length + && memcmp (member->elements, + set->elements[i].elements, + member->length) == 0) { + *present = 1; + break; + } + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/unwrap.c b/lib/gssapi/unwrap.c new file mode 100644 index 000000000..59c17125c --- /dev/null +++ b/lib/gssapi/unwrap.c @@ -0,0 +1,69 @@ +#include "gssapi_locl.h" +#include +#include + +RCSID("$Id$"); + +OM_uint32 gss_unwrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t input_message_buffer, + gss_buffer_t output_message_buffer, + int * conf_state, + gss_qop_t * qop_state + ) +{ + u_char *p; + size_t len; + struct md5 md5; + u_char hash[16]; + des_key_schedule schedule; + des_cblock key; + des_cblock zero; + + p = input_message_buffer->value; + len = GSS_KRB5_MECHANISM->length + 28; + + if ( + input_message_buffer->length < len + || memcmp (p, "\x60\x07\x06\x05", 4) != 0 + || memcmp (p + 4, GSS_KRB5_MECHANISM->elements, + GSS_KRB5_MECHANISM->length) != 0) + return GSS_S_BAD_MECH; + if (memcmp (p + 4 + GSS_KRB5_MECHANISM->length, "\x02\x01", 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + p += 6 + GSS_KRB5_MECHANISM->length; + if (memcmp (p, "\x00\x00", 2) != 0) + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\xff\xff", 2) != 0) + return GSS_S_BAD_MIC; + p += 2; + if (memcmp (p, "\xff\xff", 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + p += 2; + p += 16; + + md5_init (&md5); + md5_update (&md5, p - 24, 8); + md5_update (&md5, p, input_message_buffer->length - len); + md5_finito (&md5, hash); + + memset (&zero, 0, sizeof(zero)); + memcpy (&key, context_handle->auth_context->key.contents.data, + sizeof(key)); + des_set_key (&key, schedule); + des_cbc_cksum ((des_cblock *)hash, + (des_cblock *)hash, sizeof(hash), schedule, &zero); + if (memcmp (p - 8, hash, 8) != 0) + return GSS_S_BAD_MIC; + + output_message_buffer->length = input_message_buffer->length - len; + output_message_buffer->value = malloc(output_message_buffer->length); + if(output_message_buffer->value == NULL) + return GSS_S_FAILURE; + memcpy (output_message_buffer->value, + p, + output_message_buffer->length); + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/verify_mic.c b/lib/gssapi/verify_mic.c new file mode 100644 index 000000000..1cd19a635 --- /dev/null +++ b/lib/gssapi/verify_mic.c @@ -0,0 +1,59 @@ +#include "gssapi_locl.h" +#include +#include + +RCSID("$Id$"); + +OM_uint32 gss_verify_mic + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + const gss_buffer_t message_buffer, + const gss_buffer_t token_buffer, + gss_qop_t * qop_state + ) +{ + u_char *p; + size_t len; + struct md5 md5; + u_char hash[16]; + des_key_schedule schedule; + des_cblock key; + des_cblock zero; + + p = token_buffer->value; + len = GSS_KRB5_MECHANISM->length + 28; + + if ( + token_buffer->length < len + || memcmp (p, "\x60\x07\x06\x05", 4) != 0 + || memcmp (p + 4, GSS_KRB5_MECHANISM->elements, + GSS_KRB5_MECHANISM->length) != 0) + return GSS_S_BAD_MECH; + if (memcmp (p + 4 + GSS_KRB5_MECHANISM->length, "\x01\x01", 2) != 0) + return GSS_S_DEFECTIVE_TOKEN; + p += 6 + GSS_KRB5_MECHANISM->length; + if (memcmp (p, "\x00\x00", 2) != 0) + return GSS_S_BAD_SIG; + p += 2; + if (memcmp (p, "\xff\xff\xff\xff", 4) != 0) + return GSS_S_BAD_MIC; + p += 4; + p += 16; + + md5_init (&md5); + md5_update (&md5, p - 24, 8); + md5_update (&md5, message_buffer->value, + message_buffer->length); + md5_finito (&md5, hash); + + memset (&zero, 0, sizeof(zero)); + memcpy (&key, context_handle->auth_context->key.contents.data, + sizeof(key)); + des_set_key (&key, schedule); + des_cbc_cksum ((des_cblock *)hash, + (des_cblock *)hash, sizeof(hash), schedule, &zero); + if (memcmp (p - 8, hash, 8) != 0) + return GSS_S_BAD_MIC; + + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/wrap.c b/lib/gssapi/wrap.c new file mode 100644 index 000000000..fa7a5d432 --- /dev/null +++ b/lib/gssapi/wrap.c @@ -0,0 +1,63 @@ +#include "gssapi_locl.h" +#include +#include + +RCSID("$Id$"); + +OM_uint32 gss_wrap + (OM_uint32 * minor_status, + const gss_ctx_id_t context_handle, + int conf_req_flag, + gss_qop_t qop_req, + const gss_buffer_t input_message_buffer, + int * conf_state, + gss_buffer_t output_message_buffer + ) +{ + u_char *p; + size_t len; + struct md5 md5; + u_char hash[16]; + des_key_schedule schedule; + des_cblock key; + des_cblock zero; + + len = input_message_buffer->length + 28 + GSS_KRB5_MECHANISM->length; + output_message_buffer->length = len; + output_message_buffer->value = malloc (len); + if (output_message_buffer->value == NULL) + return GSS_S_FAILURE; + + p = output_message_buffer->value; + memcpy (p, "\x60\x07\x06\x05", 4); + p += 4; + memcpy (p, GSS_KRB5_MECHANISM->elements, GSS_KRB5_MECHANISM->length); + p += GSS_KRB5_MECHANISM->length; + memcpy (p, "\x02\x01", 2); + p += 2; + memcpy (p, "\x00\x00", 2); + p += 2; + memcpy (p, "\xff\xff", 2); + p += 2; + memcpy (p, "\xff\xff", 2); + p += 2; + + memset (p, 0, 16); + p += 16; + memcpy (p, input_message_buffer->value, + input_message_buffer->length); + + md5_init (&md5); + md5_update (&md5, p - 24, 8); + md5_update (&md5, p, input_message_buffer->length); + md5_finito (&md5, hash); + + memset (&zero, 0, sizeof(zero)); + memcpy (&key, context_handle->auth_context->key.contents.data, + sizeof(key)); + des_set_key (&key, schedule); + des_cbc_cksum ((des_cblock *)hash, + (des_cblock *)hash, sizeof(hash), schedule, &zero); + memcpy (p - 8, hash, 8); + return GSS_S_COMPLETE; +}