diff options
author | Richard Levitte <levitte@openssl.org> | 2001-07-09 23:46:58 +0200 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2001-07-09 23:46:58 +0200 |
commit | 2a1ef754358e35c8e86df903e0a2f92c35a550d0 (patch) | |
tree | 6ac406a5043c584c2ce0912d35192c3c30376f67 | |
parent | A better compromise between encrypt and decrypt (but why isn't it as fast (diff) | |
download | openssl-2a1ef754358e35c8e86df903e0a2f92c35a550d0.tar.xz openssl-2a1ef754358e35c8e86df903e0a2f92c35a550d0.zip |
Patches from Vern Staats <staatsvr@asc.hpc.mil> to get Kerberos 5 in
SSL according to RFC 2712. His comment is:
This is a patch to openssl-SNAP-20010702 to support Kerberized SSL
authentication. I'm expecting to have the full kssl-0.5 kit up on
sourceforge by the end of the week. The full kit includes patches
for mod-ssl, apache, and a few text clients. The sourceforge URL
is http://sourceforge.net/projects/kssl/ .
Thanks to a note from Simon Wilkinson I've replaced my KRB5 AP_REQ
message with a real KerberosWrapper struct. I think this is fully
RFC 2712 compliant now, including support for the optional
authenticator field. I also added openssl-style ASN.1 macros for
a few Kerberos structs; see crypto/krb5/ if you're interested.
-rwxr-xr-x | Configure | 23 | ||||
-rw-r--r-- | Makefile.org | 4 | ||||
-rw-r--r-- | apps/s_server.c | 13 | ||||
-rw-r--r-- | crypto/asn1/asn1.h | 1 | ||||
-rw-r--r-- | crypto/asn1/tasn_typ.c | 3 | ||||
-rw-r--r-- | crypto/krb5/Makefile.ssl | 90 | ||||
-rw-r--r-- | crypto/krb5/krb5_asn.c | 164 | ||||
-rw-r--r-- | crypto/krb5/krb5_asn.h | 256 | ||||
-rw-r--r-- | ssl/kssl.c | 948 | ||||
-rw-r--r-- | ssl/kssl.h | 29 | ||||
-rw-r--r-- | ssl/s3_clnt.c | 146 | ||||
-rw-r--r-- | ssl/s3_srvr.c | 113 | ||||
-rw-r--r-- | ssl/ssl.h | 6 | ||||
-rw-r--r-- | ssl/ssl_err.c | 18 |
14 files changed, 1641 insertions, 173 deletions
@@ -723,6 +723,7 @@ if ($no_krb5 } else { + my ($lresolv, $lpath, $lext); if ($withargs{"krb5-flavor"} =~ /^[Hh]eimdal$/) { $withargs{"krb5-dir"} = "/usr/heimdal" @@ -732,7 +733,7 @@ else if $withargs{"krb5-lib"} eq ""; $cflags="-DKRB5_HEIMDAL $cflags"; } - if ($withargs{"krb5-flavor"} =~ /^[Mm][Ii][Tt]$/) + if ($withargs{"krb5-flavor"} =~ /^[Mm][Ii][Tt]/) { $withargs{"krb5-dir"} = "/usr/kerberos" if $withargs{"krb5-dir"} eq ""; @@ -740,9 +741,27 @@ else "/lib -lgssapi_krb5 -lkrb5 -lcom_err -lk5crypto" if $withargs{"krb5-lib"} eq ""; $cflags="-DKRB5_MIT $cflags"; + $withargs{"krb5-flavor"} =~ s/^[Mm][Ii][Tt][._-]*//; + if ($withargs{"krb5-flavor"} =~ /^1[._-]*[01]/) + { + $cflags="-DKRB5_MIT_OLD11 $cflags"; + } + } + LRESOLV: + foreach $lpath ("/lib", "/usr/lib") + { + foreach $lext ("a", "so") + { + $lresolv = "$lpath/libresolv.$lext"; + last LRESOLV if (-r "$lresolv"); + $lresolv = ""; + } } + $withargs{"krb5-lib"} .= " -lresolv" + if ("$lresolv"); $withargs{"krb5-include"} = "-I".$withargs{"krb5-dir"}."/include" - if $withargs{"krb5-include"} eq "" && $withargs{"krb5-dir"} ne ""; + if $withargs{"krb5-include"} eq "" && + $withargs{"krb5-dir"} ne ""; } # The DSO code currently always implements all functions so that no diff --git a/Makefile.org b/Makefile.org index a7353151d5..f3258d3048 100644 --- a/Makefile.org +++ b/Makefile.org @@ -168,7 +168,7 @@ SDIRS= \ des rc2 rc4 rc5 idea bf cast \ bn ec rsa dsa dh dso engine rijndael \ buffer bio stack lhash rand err objects \ - evp asn1 pem x509 x509v3 conf txt_db pkcs7 pkcs12 comp ocsp ui + evp asn1 pem x509 x509v3 conf txt_db pkcs7 pkcs12 comp ocsp ui krb5 # tests to perform. "alltests" is a special word indicating that all tests # should be performed. @@ -458,7 +458,7 @@ depend: do \ if [ -d "$$i" ]; then \ (cd $$i && echo "making dependencies $$i..." && \ - $(MAKE) SDIRS='${SDIRS}' DEPFLAG='${DEPFLAG}' MAKEDEPPROG='${MAKEDEPPROG}' depend ) || exit 1; \ + $(MAKE) SDIRS='${SDIRS}' DEPFLAG='${DEPFLAG}' MAKEDEPPROG='${MAKEDEPPROG}' KRB5_INCLUDES='${KRB5_INCLUDES}' depend ) || exit 1; \ fi; \ done; diff --git a/apps/s_server.c b/apps/s_server.c index 6ed23490f1..269b28dfd1 100644 --- a/apps/s_server.c +++ b/apps/s_server.c @@ -863,8 +863,10 @@ static int sv_body(char *hostname, int s, unsigned char *context) #ifndef OPENSSL_NO_KRB5 if ((con->kssl_ctx = kssl_ctx_new()) != NULL) { - kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVICE, KRB5SVC); - kssl_ctx_setstring(con->kssl_ctx, KSSL_KEYTAB, KRB5KEYTAB); + kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVICE, + KRB5SVC); + kssl_ctx_setstring(con->kssl_ctx, KSSL_KEYTAB, + KRB5KEYTAB); } #endif /* OPENSSL_NO_KRB5 */ if(context) @@ -1249,6 +1251,13 @@ static int www_body(char *hostname, int s, unsigned char *context) if (!BIO_set_write_buffer_size(io,bufsize)) goto err; if ((con=SSL_new(ctx)) == NULL) goto err; +#ifndef OPENSSL_NO_KRB5 + if ((con->kssl_ctx = kssl_ctx_new()) != NULL) + { + kssl_ctx_setstring(con->kssl_ctx, KSSL_SERVICE, KRB5SVC); + kssl_ctx_setstring(con->kssl_ctx, KSSL_KEYTAB, KRB5KEYTAB); + } +#endif /* OPENSSL_NO_KRB5 */ if(context) SSL_set_session_id_context(con, context, strlen((char *)context)); diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h index ae92ad9954..bd033f85ec 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -822,6 +822,7 @@ DECLARE_ASN1_FUNCTIONS_name(ASN1_STRING, DISPLAYTEXT) DECLARE_ASN1_FUNCTIONS(ASN1_PRINTABLESTRING) DECLARE_ASN1_FUNCTIONS(ASN1_T61STRING) DECLARE_ASN1_FUNCTIONS(ASN1_IA5STRING) +DECLARE_ASN1_FUNCTIONS(ASN1_GENERALSTRING) DECLARE_ASN1_FUNCTIONS(ASN1_UTCTIME) DECLARE_ASN1_FUNCTIONS(ASN1_GENERALIZEDTIME) DECLARE_ASN1_FUNCTIONS(ASN1_TIME) diff --git a/crypto/asn1/tasn_typ.c b/crypto/asn1/tasn_typ.c index 188311ccd9..804d2eeba2 100644 --- a/crypto/asn1/tasn_typ.c +++ b/crypto/asn1/tasn_typ.c @@ -91,6 +91,9 @@ IMPLEMENT_ASN1_FUNCTIONS(ASN1_T61STRING) IMPLEMENT_ASN1_TYPE(ASN1_IA5STRING) IMPLEMENT_ASN1_FUNCTIONS(ASN1_IA5STRING) +IMPLEMENT_ASN1_TYPE(ASN1_GENERALSTRING) +IMPLEMENT_ASN1_FUNCTIONS(ASN1_GENERALSTRING) + IMPLEMENT_ASN1_TYPE(ASN1_UTCTIME) IMPLEMENT_ASN1_FUNCTIONS(ASN1_UTCTIME) diff --git a/crypto/krb5/Makefile.ssl b/crypto/krb5/Makefile.ssl new file mode 100644 index 0000000000..8994b486a4 --- /dev/null +++ b/crypto/krb5/Makefile.ssl @@ -0,0 +1,90 @@ +# +# OpenSSL/krb5/Makefile.ssl +# + +DIR= krb5 +TOP= ../.. +CC= cc +INCLUDES= -I.. -I$(TOP) -I../../include +CFLAG=-g +INSTALL_PREFIX= +OPENSSLDIR= /usr/local/ssl +INSTALLTOP=/usr/local/ssl +MAKE= make -f Makefile.ssl +MAKEDEPPROG= makedepend +MAKEDEPEND= $(TOP)/util/domd $(TOP) -MD $(MAKEDEPPROG) +MAKEFILE= Makefile.ssl +AR= ar r + +CFLAGS= $(INCLUDES) $(CFLAG) + +GENERAL=Makefile README +TEST= +APPS= + +LIB=$(TOP)/libcrypto.a +LIBSRC= krb5_asn.c + +LIBOBJ= krb5_asn.o + +SRC= $(LIBSRC) + +EXHEADER= krb5_asn.h +HEADER= $(EXHEADER) + +ALL= $(GENERAL) $(SRC) $(HEADER) + +top: + (cd ../..; $(MAKE) DIRS=crypto SDIRS=$(DIR) sub_all) + +all: lib + +lib: $(LIBOBJ) + $(AR) $(LIB) $(LIBOBJ) + $(RANLIB) $(LIB) + @touch lib + +files: + perl $(TOP)/util/files.pl Makefile.ssl >> $(TOP)/MINFO + +links: + $(TOP)/util/point.sh Makefile.ssl Makefile ; + $(PERL) $(TOP)/util/mklink.pl ../../include/openssl $(EXHEADER) + $(PERL) $(TOP)/util/mklink.pl ../../test $(TEST) + $(PERL) $(TOP)/util/mklink.pl ../../apps $(APPS) + +install: + @for i in $(EXHEADER) ; \ + do \ + (cp $$i $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i; \ + chmod 644 $(INSTALL_PREFIX)$(INSTALLTOP)/include/openssl/$$i ); \ + done; + +tags: + ctags $(SRC) + +tests: + +lint: + lint -DLINT $(INCLUDES) $(SRC)>fluff + +depend: + $(MAKEDEPEND) $(INCLUDES) $(DEPFLAG) $(LIBSRC) + +dclean: + $(PERL) -pe 'if (/^# DO NOT DELETE THIS LINE/) {print; exit(0);}' $(MAKEFILE) >Makefile.new + mv -f Makefile.new $(MAKEFILE) + +clean: + rm -f *.o *.obj lib tags core .pure .nfs* *.old *.bak fluff + +# DO NOT DELETE THIS LINE -- make depend depends on it. + +krb5_asn.o: ../../include/openssl/asn1.h ../../include/openssl/asn1t.h +krb5_asn.o: ../../include/openssl/bio.h ../../include/openssl/bn.h +krb5_asn.o: ../../include/openssl/crypto.h ../../include/openssl/e_os2.h +krb5_asn.o: ../../include/openssl/krb5_asn.h +krb5_asn.o: ../../include/openssl/opensslconf.h +krb5_asn.o: ../../include/openssl/opensslv.h ../../include/openssl/safestack.h +krb5_asn.o: ../../include/openssl/stack.h ../../include/openssl/symhacks.h +krb5_asn.o: krb5_asn.c diff --git a/crypto/krb5/krb5_asn.c b/crypto/krb5/krb5_asn.c new file mode 100644 index 0000000000..08d169ba52 --- /dev/null +++ b/crypto/krb5/krb5_asn.c @@ -0,0 +1,164 @@ +/* krb5_asn.c */ +/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project, +** using ocsp/{*.h,*asn*.c} as a starting point +*/ +/* ==================================================================== + * Copyright (c) 2000 The OpenSSL Project. 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 acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * licensing@OpenSSL.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ +#include <openssl/asn1.h> +#include <openssl/asn1t.h> +#include <openssl/krb5_asn.h> + + +ASN1_SEQUENCE(KRB5_ENCDATA) = { + ASN1_EXP(KRB5_ENCDATA, etype, ASN1_INTEGER, 0), + ASN1_EXP_OPT(KRB5_ENCDATA, kvno, ASN1_INTEGER, 1), + ASN1_EXP(KRB5_ENCDATA, cipher, ASN1_OCTET_STRING,2) +} ASN1_SEQUENCE_END(KRB5_ENCDATA) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_ENCDATA) + + +ASN1_SEQUENCE(KRB5_PRINCNAME) = { + ASN1_EXP(KRB5_PRINCNAME, nametype, ASN1_INTEGER, 0), + ASN1_EXP_SEQUENCE_OF(KRB5_PRINCNAME, namestring, ASN1_GENERALSTRING, 1) +} ASN1_SEQUENCE_END(KRB5_PRINCNAME) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_PRINCNAME) + + +/* [APPLICATION 1] = 0x61 */ +ASN1_SEQUENCE(KRB5_TKTBODY) = { + ASN1_EXP(KRB5_TKTBODY, tktvno, ASN1_INTEGER, 0), + ASN1_EXP(KRB5_TKTBODY, realm, ASN1_GENERALSTRING, 1), + ASN1_EXP(KRB5_TKTBODY, sname, KRB5_PRINCNAME, 2), + ASN1_EXP(KRB5_TKTBODY, encdata, KRB5_ENCDATA, 3) +} ASN1_SEQUENCE_END(KRB5_TKTBODY) + +ASN1_ITEM_TEMPLATE(KRB5_TICKET) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_EXPTAG|ASN1_TFLG_APPLICATION, 1, + KRB5_TICKET, KRB5_TKTBODY) +ASN1_ITEM_TEMPLATE_END(KRB5_TICKET) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_TICKET) + + +/* [APPLICATION 14] = 0x6e */ +ASN1_SEQUENCE(KRB5_APREQBODY) = { + ASN1_EXP(KRB5_APREQBODY, pvno, ASN1_INTEGER, 0), + ASN1_EXP(KRB5_APREQBODY, msgtype, ASN1_INTEGER, 1), + ASN1_EXP(KRB5_APREQBODY, apoptions, ASN1_BIT_STRING, 2), + ASN1_EXP(KRB5_APREQBODY, ticket, KRB5_TICKET, 3), + ASN1_EXP(KRB5_APREQBODY, authenticator, KRB5_ENCDATA, 4), +} ASN1_SEQUENCE_END(KRB5_APREQBODY) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_APREQBODY) + +ASN1_ITEM_TEMPLATE(KRB5_APREQ) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_EXPTAG|ASN1_TFLG_APPLICATION, 14, + KRB5_APREQ, KRB5_APREQBODY) +ASN1_ITEM_TEMPLATE_END(KRB5_APREQ) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_APREQ) + + +/* Authenticator stuff */ + +ASN1_SEQUENCE(KRB5_CHECKSUM) = { + ASN1_EXP(KRB5_CHECKSUM, ctype, ASN1_INTEGER, 0), + ASN1_EXP(KRB5_CHECKSUM, checksum, ASN1_OCTET_STRING,1) +} ASN1_SEQUENCE_END(KRB5_CHECKSUM) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_CHECKSUM) + + +ASN1_SEQUENCE(KRB5_ENCKEY) = { + ASN1_EXP(KRB5_ENCKEY, ktype, ASN1_INTEGER, 0), + ASN1_EXP(KRB5_ENCKEY, keyvalue, ASN1_OCTET_STRING,1) +} ASN1_SEQUENCE_END(KRB5_ENCKEY) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_ENCKEY) + + +/* SEQ OF SEQ; see ASN1_EXP_SEQUENCE_OF_OPT() below */ +ASN1_SEQUENCE(KRB5_AUTHDATA) = { + ASN1_EXP(KRB5_AUTHDATA, adtype, ASN1_INTEGER, 0), + ASN1_EXP(KRB5_AUTHDATA, addata, ASN1_OCTET_STRING,1) +} ASN1_SEQUENCE_END(KRB5_AUTHDATA) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_AUTHDATA) + + +/* [APPLICATION 2] = 0x62 */ +ASN1_SEQUENCE(KRB5_AUTHENTBODY) = { + ASN1_EXP(KRB5_AUTHENTBODY, avno, ASN1_INTEGER, 0), + ASN1_EXP(KRB5_AUTHENTBODY, crealm, ASN1_GENERALSTRING, 1), + ASN1_EXP(KRB5_AUTHENTBODY, cname, KRB5_PRINCNAME, 2), + ASN1_EXP_OPT(KRB5_AUTHENTBODY, cksum, KRB5_CHECKSUM, 3), + ASN1_EXP(KRB5_AUTHENTBODY, cusec, ASN1_INTEGER, 4), + ASN1_EXP(KRB5_AUTHENTBODY, ctime, ASN1_GENERALIZEDTIME, 5), + ASN1_EXP_OPT(KRB5_AUTHENTBODY, subkey, KRB5_ENCKEY, 6), + ASN1_EXP_OPT(KRB5_AUTHENTBODY, seqnum, ASN1_INTEGER, 7), + ASN1_EXP_SEQUENCE_OF_OPT + (KRB5_AUTHENTBODY, authorization, KRB5_AUTHDATA, 8), +} ASN1_SEQUENCE_END(KRB5_AUTHENTBODY) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_AUTHENTBODY) + +ASN1_ITEM_TEMPLATE(KRB5_AUTHENT) = + ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_EXPTAG|ASN1_TFLG_APPLICATION, 2, + KRB5_AUTHENT, KRB5_AUTHENTBODY) +ASN1_ITEM_TEMPLATE_END(KRB5_AUTHENT) + +IMPLEMENT_ASN1_FUNCTIONS(KRB5_AUTHENT) + diff --git a/crypto/krb5/krb5_asn.h b/crypto/krb5/krb5_asn.h new file mode 100644 index 0000000000..c9f573cef7 --- /dev/null +++ b/crypto/krb5/krb5_asn.h @@ -0,0 +1,256 @@ +/* krb5_asn.h */ +/* Written by Vern Staats <staatsvr@asc.hpc.mil> for the OpenSSL project, +** using ocsp/{*.h,*asn*.c} as a starting point +*/ + +/* ==================================================================== + * Copyright (c) 1998-2000 The OpenSSL Project. 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 acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" + * + * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * openssl-core@openssl.org. + * + * 5. Products derived from this software may not be called "OpenSSL" + * nor may "OpenSSL" appear in their names without prior written + * permission of the OpenSSL Project. + * + * 6. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the OpenSSL Project + * for use in the OpenSSL Toolkit (http://www.openssl.org/)" + * + * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY + * EXPRESSED 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 OpenSSL PROJECT OR + * ITS 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. + * ==================================================================== + * + * This product includes cryptographic software written by Eric Young + * (eay@cryptsoft.com). This product includes software written by Tim + * Hudson (tjh@cryptsoft.com). + * + */ + +#ifndef HEADER_KRB5_ASN_H +#define HEADER_KRB5_ASN_H + +/* +#include <krb5.h> +*/ +#include <openssl/safestack.h> + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ASN.1 from Kerberos RFC 1510 +*/ + +/* EncryptedData ::= SEQUENCE { +** etype[0] INTEGER, -- EncryptionType +** kvno[1] INTEGER OPTIONAL, +** cipher[2] OCTET STRING -- ciphertext +** } +*/ +typedef struct krb5_encdata_st + { + ASN1_INTEGER *etype; + ASN1_INTEGER *kvno; + ASN1_OCTET_STRING *cipher; + } KRB5_ENCDATA; + +DECLARE_STACK_OF(KRB5_ENCDATA) + +/* PrincipalName ::= SEQUENCE { +** name-type[0] INTEGER, +** name-string[1] SEQUENCE OF GeneralString +** } +*/ +typedef struct krb5_princname_st + { + ASN1_INTEGER *nametype; + STACK_OF(ASN1_GENERALSTRING) *namestring; + } KRB5_PRINCNAME; + +DECLARE_STACK_OF(KRB5_PRINCNAME) + + +/* Ticket ::= [APPLICATION 1] SEQUENCE { +** tkt-vno[0] INTEGER, +** realm[1] Realm, +** sname[2] PrincipalName, +** enc-part[3] EncryptedData +** } +*/ +typedef struct krb5_tktbody_st + { + ASN1_INTEGER *tktvno; + ASN1_GENERALSTRING *realm; + KRB5_PRINCNAME *sname; + KRB5_ENCDATA *encdata; + } KRB5_TKTBODY; + +typedef STACK_OF(KRB5_TKTBODY) KRB5_TICKET; +DECLARE_STACK_OF(KRB5_TKTBODY) + + +/* AP-REQ ::= [APPLICATION 14] SEQUENCE { +** pvno[0] INTEGER, +** msg-type[1] INTEGER, +** ap-options[2] APOptions, +** ticket[3] Ticket, +** authenticator[4] EncryptedData +** } +** +** APOptions ::= BIT STRING { +** reserved(0), use-session-key(1), mutual-required(2) } +*/ +typedef struct krb5_ap_req_st + { + ASN1_INTEGER *pvno; + ASN1_INTEGER *msgtype; + ASN1_BIT_STRING *apoptions; + KRB5_TICKET *ticket; + KRB5_ENCDATA *authenticator; + } KRB5_APREQBODY; + +typedef STACK_OF(KRB5_APREQBODY) KRB5_APREQ; +DECLARE_STACK_OF(KRB5_APREQBODY) + + +/* Authenticator Stuff */ + + +/* Checksum ::= SEQUENCE { +** cksumtype[0] INTEGER, +** checksum[1] OCTET STRING +** } +*/ +typedef struct krb5_checksum_st + { + ASN1_INTEGER *ctype; + ASN1_OCTET_STRING *checksum; + } KRB5_CHECKSUM; + +DECLARE_STACK_OF(KRB5_CHECKSUM) + + +/* EncryptionKey ::= SEQUENCE { +** keytype[0] INTEGER, +** keyvalue[1] OCTET STRING +** } +*/ +typedef struct krb5_encryptionkey_st + { + ASN1_INTEGER *ktype; + ASN1_OCTET_STRING *keyvalue; + } KRB5_ENCKEY; + +DECLARE_STACK_OF(KRB5_ENCKEY) + + +/* AuthorizationData ::= SEQUENCE OF SEQUENCE { +** ad-type[0] INTEGER, +** ad-data[1] OCTET STRING +** } +*/ +typedef struct krb5_authorization_st + { + ASN1_INTEGER *adtype; + ASN1_OCTET_STRING *addata; + } KRB5_AUTHDATA; + +DECLARE_STACK_OF(KRB5_AUTHDATA); + + +/* -- Unencrypted authenticator +** Authenticator ::= [APPLICATION 2] SEQUENCE { +** authenticator-vno[0] INTEGER, +** crealm[1] Realm, +** cname[2] PrincipalName, +** cksum[3] Checksum OPTIONAL, +** cusec[4] INTEGER, +** ctime[5] KerberosTime, +** subkey[6] EncryptionKey OPTIONAL, +** seq-number[7] INTEGER OPTIONAL, +** authorization-data[8] AuthorizationData OPTIONAL +** } +*/ +typedef struct krb5_authenticator_st + { + ASN1_INTEGER *avno; + ASN1_GENERALSTRING *crealm; + KRB5_PRINCNAME *cname; + KRB5_CHECKSUM *cksum; + ASN1_INTEGER *cusec; + ASN1_GENERALIZEDTIME *ctime; + KRB5_ENCKEY *subkey; + ASN1_INTEGER *seqnum; + KRB5_AUTHDATA *authorization; + } KRB5_AUTHENTBODY; + +typedef STACK_OF(KRB5_AUTHENTBODY) KRB5_AUTHENT; +DECLARE_STACK_OF(KRB5_AUTHENTBODY) + + +/* DECLARE_ASN1_FUNCTIONS(type) = DECLARE_ASN1_FUNCTIONS_name(type, type) = +** type *name##_new(void); +** void name##_free(type *a); +** DECLARE_ASN1_ENCODE_FUNCTIONS(type, name, name) = +** DECLARE_ASN1_ENCODE_FUNCTIONS(type, itname, name) = +** type *d2i_##name(type **a, unsigned char **in, long len); +** int i2d_##name(type *a, unsigned char **out); +** DECLARE_ASN1_ITEM(itname) = OPENSSL_EXTERN const ASN1_ITEM itname##_it +*/ + +DECLARE_ASN1_FUNCTIONS(KRB5_ENCDATA) +DECLARE_ASN1_FUNCTIONS(KRB5_PRINCNAME) +DECLARE_ASN1_FUNCTIONS(KRB5_TKTBODY) +DECLARE_ASN1_FUNCTIONS(KRB5_APREQBODY) +DECLARE_ASN1_FUNCTIONS(KRB5_TICKET) +DECLARE_ASN1_FUNCTIONS(KRB5_APREQ) + +DECLARE_ASN1_FUNCTIONS(KRB5_CHECKSUM) +DECLARE_ASN1_FUNCTIONS(KRB5_ENCKEY) +DECLARE_ASN1_FUNCTIONS(KRB5_AUTHDATA) +DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENTBODY) +DECLARE_ASN1_FUNCTIONS(KRB5_AUTHENT) + + +/* BEGIN ERROR CODES */ +/* The following lines are auto generated by the script mkerr.pl. Any changes + * made after this point may be overwritten when the script is next run. + */ + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/ssl/kssl.c b/ssl/kssl.c index a8b7cc4cc8..a92c87273d 100644 --- a/ssl/kssl.c +++ b/ssl/kssl.c @@ -56,15 +56,26 @@ */ -/* ssl/kssl.c -- Routines to support (& debug) Kerberos5 auth for openssl +/* ssl/kssl.c -- Routines to support (& debug) Kerberos5 auth for openssl ** -** 19990701 VRS Started. +** 19990701 VRS Started. +** 200011?? Jeffrey Altman, Richard Levitte +** Generalized for Heimdal, Newer MIT, & Win32. +** Integrated into main OpenSSL 0.9.7 snapshots. +** 20010413 Simon Wilkinson, VRS +** Real RFC2712 KerberosWrapper replaces AP_REQ. */ #include <openssl/opensslconf.h> #ifndef OPENSSL_NO_KRB5 #include <string.h> +#define _XOPEN_SOURCE /* glibc2 needs this to declare strptime() */ +#include <time.h> + #include <openssl/ssl.h> +#include <openssl/evp.h> +#include <openssl/objects.h> +#include <openssl/krb5_asn.h> /* * When OpenSSL is built on Windows, we do not want to require that @@ -104,6 +115,15 @@ #define krb5_kt_resolve kssl_krb5_kt_resolve #define krb5_auth_con_init kssl_krb5_auth_con_init +#define krb5_principal_compare kssl_krb5_principal_compare +/* macro #define krb5_kt_get_entry kssl_krb5_kt_get_entry */ +#define krb5_decrypt_tkt_part kssl_krb5_decrypt_tkt_part +#define krb5_timeofday kssl_krb5_timeofday +#define krb5_rc_default kssl_krb5_rc_default +#define krb5_krb5_rc_initialize kssl_krb5_rc_initialize +#define krb5_krb5_rc_get_lifespan kssl_krb5_rc_get_lifespan +#define krb5_krb5_rc_destroy kssl_krb5_rc_destroy + /* Prototypes for built in stubs */ void kssl_krb5_free_data_contents(krb5_context, krb5_data *); void kssl_krb5_free_principal(krb5_context, krb5_principal ); @@ -117,6 +137,19 @@ krb5_error_code kssl_krb5_rd_req(krb5_context, krb5_auth_context *, krb5_const krb5_data *, krb5_const_principal, krb5_keytab, krb5_flags *,krb5_ticket **); + +krb5_boolean kssl_krb5_principal_compare(krb5_context, krb5_const_principal, + krb5_const_principal); +krb5_error_code krb5_decrypt_tkt_part(krb5_context, krb5_const krb5_keyblock *, + krb5_ticket *); +krb5_error_code krb5_timeofday(krb5_context context, krb5_int32 *timeret); +krb5_error_code krb5_rc_default(krb5_context context, krb5_rcache *rc); +krb5_error_code krb5_rc_initialize(krb5_context context, krb5_rcache rc, + krb5_deltat lifespan); +krb5_error_code krb5_rc_get_lifespan(krb5_context context, krb5_rcache rc, + krb5_deltat *lifespan); +krb5_error_code krb5_rc_destroy(krb5_context context, krb5_rcache rc); + krb5_error_code kssl_krb5_mk_req_extended(krb5_context, krb5_auth_context *, krb5_const krb5_flags, @@ -144,10 +177,12 @@ krb5_error_code kssl_krb5_cc_get_principal(krb5_context context, krb5_error_code kssl_krb5_auth_con_free(krb5_context,krb5_auth_context); /* Function pointers (almost all Kerberos functions are _stdcall) */ -static void (_stdcall *p_krb5_free_data_contents)(krb5_context, krb5_data *)=NULL; -static void (_stdcall *p_krb5_free_principal)(krb5_context, krb5_principal )=NULL; -static krb5_error_code(_stdcall *p_krb5_kt_resolve)(krb5_context, krb5_const char *, - krb5_keytab *)=NULL; +static void (_stdcall *p_krb5_free_data_contents)(krb5_context, krb5_data *) + =NULL; +static void (_stdcall *p_krb5_free_principal)(krb5_context, krb5_principal ) + =NULL; +static krb5_error_code(_stdcall *p_krb5_kt_resolve) + (krb5_context, krb5_const char *, krb5_keytab *)=NULL; static krb5_error_code (_stdcall *p_krb5_kt_default)(krb5_context, krb5_keytab *)=NULL; static krb5_error_code (_stdcall *p_krb5_free_ticket)(krb5_context, @@ -158,33 +193,27 @@ static krb5_error_code (_stdcall *p_krb5_rd_req)(krb5_context, krb5_const_principal, krb5_keytab, krb5_flags *, krb5_ticket **)=NULL; -static krb5_error_code (_stdcall *p_krb5_mk_req_extended) (krb5_context, - krb5_auth_context *, - krb5_const krb5_flags, - krb5_data *, - krb5_creds *, - krb5_data * )=NULL; +static krb5_error_code (_stdcall *p_krb5_mk_req_extended) + (krb5_context, krb5_auth_context *, + krb5_const krb5_flags, krb5_data *, krb5_creds *, + krb5_data * )=NULL; static krb5_error_code (_stdcall *p_krb5_init_context)(krb5_context *)=NULL; static void (_stdcall *p_krb5_free_context)(krb5_context)=NULL; static krb5_error_code (_stdcall *p_krb5_cc_default)(krb5_context, krb5_ccache *)=NULL; -static krb5_error_code (_stdcall *p_krb5_sname_to_principal)(krb5_context, - krb5_const char *, - krb5_const char *, - krb5_int32, - krb5_principal *)=NULL; -static krb5_error_code (_stdcall *p_krb5_get_credentials)(krb5_context, - krb5_const krb5_flags, - krb5_ccache, - krb5_creds *, - krb5_creds * *)=NULL; -static krb5_error_code (_stdcall *p_krb5_auth_con_init)(krb5_context, - krb5_auth_context *)=NULL; -static krb5_error_code (_stdcall *p_krb5_cc_get_principal)(krb5_context context, - krb5_ccache cache, - krb5_principal *principal)=NULL; -static krb5_error_code (_stdcall *p_krb5_auth_con_free)(krb5_context, - krb5_auth_context)=NULL; +static krb5_error_code (_stdcall *p_krb5_sname_to_principal) + (krb5_context, krb5_const char *, krb5_const char *, + krb5_int32, krb5_principal *)=NULL; +static krb5_error_code (_stdcall *p_krb5_get_credentials) + (krb5_context, krb5_const krb5_flags, krb5_ccache, + krb5_creds *, krb5_creds **)=NULL; +static krb5_error_code (_stdcall *p_krb5_auth_con_init) + (krb5_context, krb5_auth_context *)=NULL; +static krb5_error_code (_stdcall *p_krb5_cc_get_principal) + (krb5_context context, krb5_ccache cache, + krb5_principal *principal)=NULL; +static krb5_error_code (_stdcall *p_krb5_auth_con_free) + (krb5_context, krb5_auth_context)=NULL; static int krb5_loaded = 0; /* only attempt to initialize func ptrs once */ /* Function to Load the Kerberos 5 DLL and initialize function pointers */ @@ -222,6 +251,20 @@ load_krb5_dll(void) GetProcAddress( hKRB5_32, "krb5_free_ticket" ); (FARPROC) p_krb5_rd_req = GetProcAddress( hKRB5_32, "krb5_rd_req" ); + (FARPROC) p_krb5_principal_compare = + GetProcAddress( hKRB5_32, "krb5_principal_compare" ); + (FARPROC) p_krb5_decrypt_tkt_part = + GetProcAddress( hKRB5_32, "krb5_decrypt_tkt_part" ); + (FARPROC) p_krb5_timeofday = + GetProcAddress( hKRB5_32, "krb5_timeofday" ); + (FARPROC) p_krb5_rc_default = + GetProcAddress( hKRB5_32, "krb5_rc_default" ); + (FARPROC) p_krb5_rc_initialize = + GetProcAddress( hKRB5_32, "krb5_rc_initialize" ); + (FARPROC) p_krb5_rc_get_lifespan = + GetProcAddress( hKRB5_32, "krb5_rc_get_lifespan" ); + (FARPROC) p_krb5_rc_destroy = + GetProcAddress( hKRB5_32, "krb5_rc_destroy" ); (FARPROC) p_krb5_kt_default = GetProcAddress( hKRB5_32, "krb5_kt_default" ); (FARPROC) p_krb5_kt_resolve = @@ -412,6 +455,92 @@ kssl_krb5_rd_req(krb5_context con, krb5_auth_context * pacon, return KRB5KRB_ERR_GENERIC; } +krb5_boolean +krb5_principal_compare(krb5_context con, krb5_const_principal princ1, + krb5_const_principal princ2) + { + if (!krb5_loaded) + load_krb5_dll(); + + if ( p_krb5_principal_compare ) + return(p_krb5_principal_compare(con,princ1,princ2); + else + return KRB5KRB_ERR_GENERIC; + } + +krb5_error_code +krb5_decrypt_tkt_part(krb5_context con, krb5_const krb5_keyblock *keys, + krb5_ticket *ticket) + { + if (!krb5_loaded) + load_krb5_dll(); + + if ( p_krb5_decrypt_tkt_part ) + return(p_krb5_decrypt_tkt_part(con,keys,ticket); + else + return KRB5KRB_ERR_GENERIC; + } + +krb5_error_code +krb5_timeofday(krb5_context con, krb5_int32 *timeret) + { + if (!krb5_loaded) + load_krb5_dll(); + + if ( p_krb5_timeofday ) + return(p_krb5_timeofday(con,timeret); + else + return KRB5KRB_ERR_GENERIC; + } + +krb5_error_code +krb5_rc_default(krb5_context con, krb5_rcache *rc) + { + if (!krb5_loaded) + load_krb5_dll(); + + if ( p_krb5_rc_default ) + return(p_krb5_rc_default(con,rc); + else + return KRB5KRB_ERR_GENERIC; + } + +krb5_error_code +krb5_rc_initialize(krb5_context con, krb5_rcache rc, krb5_deltat lifespan) + { + if (!krb5_loaded) + load_krb5_dll(); + + if ( p_krb5_rc_initialize ) + return(p_krb5_rc_initialize(con, rc, lifespan); + else + return KRB5KRB_ERR_GENERIC; + } + +krb5_error_code +krb5_rc_get_lifespan(krb5_context con, krb5_rcache rc, krb5_deltat *lifespanp) + { + if (!krb5_loaded) + load_krb5_dll(); + + if ( p_krb5_rc_get_lifespan ) + return(p_krb5_rc_get_lifespan(con, rc, lifespanp); + else + return KRB5KRB_ERR_GENERIC; + } + +krb5_error_code +krb5_rc_destroy(krb5_context con, krb5_rcache rc) + { + if (!krb5_loaded) + load_krb5_dll(); + + if ( p_krb5_rc_destroy ) + return(p_krb5_rc_destroy(con, rc); + else + return KRB5KRB_ERR_GENERIC; + } + /* Structure definitions */ #ifndef NO_DEF_KRB5_CCACHE #ifndef krb5_x @@ -432,31 +561,37 @@ typedef struct _krb5_cc_ops { krb5_magic magic; char *prefix; - char * (KRB5_CALLCONV *get_name) KRB5_NPROTOTYPE((krb5_context, krb5_ccache)); - krb5_error_code (KRB5_CALLCONV *resolve) KRB5_NPROTOTYPE((krb5_context, krb5_ccache *, - const char *)); - krb5_error_code (KRB5_CALLCONV *gen_new) KRB5_NPROTOTYPE((krb5_context, krb5_ccache *)); - krb5_error_code (KRB5_CALLCONV *init) KRB5_NPROTOTYPE((krb5_context, krb5_ccache, - krb5_principal)); - krb5_error_code (KRB5_CALLCONV *destroy) KRB5_NPROTOTYPE((krb5_context, krb5_ccache)); - krb5_error_code (KRB5_CALLCONV *close) KRB5_NPROTOTYPE((krb5_context, krb5_ccache)); - krb5_error_code (KRB5_CALLCONV *store) KRB5_NPROTOTYPE((krb5_context, krb5_ccache, - krb5_creds *)); - krb5_error_code (KRB5_CALLCONV *retrieve) KRB5_NPROTOTYPE((krb5_context, krb5_ccache, - krb5_flags, krb5_creds *, - krb5_creds *)); - krb5_error_code (KRB5_CALLCONV *get_princ) KRB5_NPROTOTYPE((krb5_context, krb5_ccache, - krb5_principal *)); - krb5_error_code (KRB5_CALLCONV *get_first) KRB5_NPROTOTYPE((krb5_context, krb5_ccache, - krb5_cc_cursor *)); - krb5_error_code (KRB5_CALLCONV *get_next) KRB5_NPROTOTYPE((krb5_context, krb5_ccache, + char * (KRB5_CALLCONV *get_name) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache)); + krb5_error_code (KRB5_CALLCONV *resolve) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache *, const char *)); + krb5_error_code (KRB5_CALLCONV *gen_new) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache *)); + krb5_error_code (KRB5_CALLCONV *init) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_principal)); + krb5_error_code (KRB5_CALLCONV *destroy) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache)); + krb5_error_code (KRB5_CALLCONV *close) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache)); + krb5_error_code (KRB5_CALLCONV *store) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_creds *)); + krb5_error_code (KRB5_CALLCONV *retrieve) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache, + krb5_flags, krb5_creds *, krb5_creds *)); + krb5_error_code (KRB5_CALLCONV *get_princ) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_principal *)); + krb5_error_code (KRB5_CALLCONV *get_first) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_cc_cursor *)); + krb5_error_code (KRB5_CALLCONV *get_next) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_cc_cursor *, krb5_creds *)); - krb5_error_code (KRB5_CALLCONV *end_get) KRB5_NPROTOTYPE((krb5_context, krb5_ccache, - krb5_cc_cursor *)); - krb5_error_code (KRB5_CALLCONV *remove_cred) KRB5_NPROTOTYPE((krb5_context, krb5_ccache, + krb5_error_code (KRB5_CALLCONV *end_get) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_cc_cursor *)); + krb5_error_code (KRB5_CALLCONV *remove_cred) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_flags, krb5_creds *)); - krb5_error_code (KRB5_CALLCONV *set_flags) KRB5_NPROTOTYPE((krb5_context, krb5_ccache, - krb5_flags)); + krb5_error_code (KRB5_CALLCONV *set_flags) + KRB5_NPROTOTYPE((krb5_context, krb5_ccache, krb5_flags)); } krb5_cc_ops; #endif /* NO_DEF_KRB5_CCACHE */ @@ -468,8 +603,10 @@ kssl_krb5_cc_get_principal if ( p_krb5_cc_get_principal ) return(p_krb5_cc_get_principal(context,cache,principal)); else - return(krb5_x ((cache)->ops->get_princ,(context, cache, principal))); + return(krb5_x + ((cache)->ops->get_princ,(context, cache, principal))); } +#else #endif /* OPENSSL_SYS_WINDOWS || OPENSSL_SYS_WIN32 */ char @@ -498,6 +635,120 @@ char } +/* Given KRB5 enctype (basically DES or 3DES), return +*/ +EVP_CIPHER * +kssl_map_enc(krb5_enctype enctype) + { + switch (enctype) + { + case ENCTYPE_DES_CBC_CRC: + case ENCTYPE_DES_CBC_MD4: + case ENCTYPE_DES_CBC_MD5: + case ENCTYPE_DES_CBC_RAW: +#if ! defined(KRB5_MIT_OLD11) + case ENCTYPE_DES_HMAC_SHA1: +#endif + return (EVP_CIPHER *) EVP_des_cbc(); + break; + case ENCTYPE_DES3_CBC_SHA: + case ENCTYPE_DES3_CBC_RAW: +#if ! defined(KRB5_MIT_OLD11) + case ENCTYPE_DES3_CBC_SHA1: +#endif + return (EVP_CIPHER *) EVP_des_ede3_cbc(); + break; + default: return (EVP_CIPHER *) NULL; + break; + } + } + + +/* Return true:1 if p "looks like" the start of the real authenticator +** described in kssl_skip_confound() below. The ASN.1 pattern is +** "62 xx 30 yy" (APPLICATION-2, SEQUENCE), where xx-yy =~ 2, and +** xx and yy are possibly multi-byte length fields. +*/ +int kssl_test_confound(unsigned char *p) + { + int len = 2; + int xx = 0, yy = 0; + + if (*p++ != 0x62) return 0; + if (*p > 0x82) return 0; + switch(*p) { + case 0x82: p++; xx = (*p++ << 8); xx += *p++; break; + case 0x81: p++; xx = *p++; break; + case 0x80: return 0; + default: xx = *p++; break; + } + if (*p++ != 0x30) return 0; + if (*p > 0x82) return 0; + switch(*p) { + case 0x82: p++; len+=2; yy = (*p++ << 8); yy += *p++; break; + case 0x81: p++; len++; yy = *p++; break; + case 0x80: return 0; + default: yy = *p++; break; + } + + return (xx - len == yy)? 1: 0; + } + +/* Allocate, fill, and return cksumlens array of checksum lengths. +** This array holds just the unique elements from the krb5_cksumarray[]. +** array[n] == 0 signals end of data. +*/ +int *populate_cksumlens(void) + { + int i, j, n = krb5_max_cksum+1; + static int *cklens = NULL; + +#ifdef KRB5CHECKAUTH + if (!cklens && !(cklens = (int *) calloc(sizeof(int), n))) return NULL; + + for (i=0; i < krb5_max_cksum; i++) { + if (!krb5_cksumarray[i]) continue; /* array has holes */ + for (j=0; j < krb5_max_cksum; j++) { + if (cklens[j] == 0) { + cklens[j] = krb5_cksumarray[i]->checksum_length; + break; /* krb5 elem was new: add */ + } + if (cklens[j] == krb5_cksumarray[i]->checksum_length) { + break; /* ignore duplicate elements */ + } + } + } +#endif /* KRB5CHECKAUTH */ + + return cklens; + } + +/* Return pointer to start of real authenticator within authenticator, or +** return NULL on error. +** Decrypted authenticator looks like this: +** [0 or 8 byte confounder] [4-24 byte checksum] [real authent'r] +** This hackery wouldn't be necessary if MIT KRB5 1.0.6 had the +** krb5_auth_con_getcksumtype() function advertised in its krb5.h. +*/ +unsigned char *kssl_skip_confound(krb5_enctype etype, unsigned char *a) + { + int i, cklen, conlen; + static int *cksumlens = NULL; + unsigned char *test_auth; + + conlen = (etype)? 8: 0; + + if (!cksumlens && !(cksumlens = populate_cksumlens())) return NULL; + for (i=0; (cklen = cksumlens[i]) != 0; i++) + { + test_auth = a + conlen + cklen; + if (kssl_test_confound(test_auth)) return test_auth; + } + + return NULL; + } + + /* Set kssl_err error info when reason text is a simple string ** kssl_err = struct { int reason; char text[KSSL_ERR_MAX+1]; } */ @@ -522,10 +773,10 @@ print_krb5_data(char *label, krb5_data *kdata) printf("%s[%d] ", label, kdata->length); for (i=0; i < kdata->length; i++) { - if (isprint((int) kdata->data[i])) + if (0 && isprint((int) kdata->data[i])) printf( "%c ", kdata->data[i]); else - printf( "%02x", kdata->data[i]); + printf( "%02x ", (unsigned char) kdata->data[i]); } printf("\n"); } @@ -570,7 +821,8 @@ print_krb5_keyblock(char *label, krb5_keyblock *keyblk) return; } #ifdef KRB5_HEIMDAL - printf("%s\n\t[et%d:%d]: ", label, keyblk->keytype, keyblk->keyvalue->length); + printf("%s\n\t[et%d:%d]: ", label, keyblk->keytype, + keyblk->keyvalue->length); for (i=0; i < keyblk->keyvalue->length; i++) { printf("%02x",(unsigned char *)(keyblk->keyvalue->contents)[i]); @@ -587,21 +839,52 @@ print_krb5_keyblock(char *label, krb5_keyblock *keyblk) } +/* Display contents of krb5_principal_data struct, for debugging +** (krb5_principal is typedef'd == krb5_principal_data *) +*/ +void +print_krb5_princ(char *label, krb5_principal_data *princ) + { + int i, j; + + printf("%s principal Realm: ", label); + if (princ == NULL) return; + for (i=0; i < princ->realm.length; i++) putchar(princ->realm.data[i]); + printf(" (nametype %d) has %d strings:\n", princ->type,princ->length); + for (i=0; i < princ->length; i++) + { + printf("\t%d [%d]: ", i, princ->data[i].length); + for (j=0; j < princ->data[i].length; j++) { + putchar(princ->data[i].data[j]); + } + printf("\n"); + } + return; + } + + /* Given krb5 service (typically "kssl") and hostname in kssl_ctx, -** Create Kerberos AP_REQ message for SSL Client. +** Return encrypted Kerberos ticket for service @ hostname. +** If authenp is non-NULL, also return encrypted authenticator, +** whose data should be freed by caller. +** (Originally was: Create Kerberos AP_REQ message for SSL Client.) ** -** 19990628 VRS Started. +** 19990628 VRS Started; Returns Kerberos AP_REQ message. +** 20010409 VRS Modified for RFC2712; Returns enc tkt. +** 20010606 VRS May also return optional authenticator. */ krb5_error_code kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, - /* OUT */ krb5_data *krb5_app_req, KSSL_ERR *kssl_err) + /* OUT */ krb5_data **enc_ticketp, + /* UPDATE */ krb5_data *authenp, + /* OUT */ KSSL_ERR *kssl_err) { krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; krb5_context krb5context = NULL; krb5_auth_context krb5auth_context = NULL; krb5_ccache krb5ccdef = NULL; krb5_creds krb5creds, *krb5credsp = NULL; - krb5_data krb5in_data; + krb5_data krb5_app_req; kssl_err_set(kssl_err, 0, ""); memset((char *)&krb5creds, 0, sizeof(krb5creds)); @@ -635,7 +918,8 @@ kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, BIO_snprintf(kssl_err->text,KSSL_ERR_MAX, "krb5_sname_to_principal() fails for %s/%s\n", kssl_ctx->service_host, - (kssl_ctx->service_name)? kssl_ctx->service_name: KRB5SVC); + (kssl_ctx->service_name)? kssl_ctx->service_name: + KRB5SVC); kssl_err->reason = SSL_R_KRB5_C_INIT; goto err; } @@ -663,26 +947,65 @@ kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, goto err; } - krb5in_data.data = NULL; - krb5in_data.length = 0; + *enc_ticketp = &krb5credsp->ticket; +#ifdef KRB5_HEIMDAL + kssl_ctx->enctype = krb5credsp->session.keytype; +#else + kssl_ctx->enctype = krb5credsp->keyblock.enctype; +#endif krb5rc = KRB5KRB_ERR_GENERIC; /* caller should free data of krb5_app_req */ - if ((krb5rc = krb5_mk_req_extended(krb5context, &krb5auth_context, - 0, &krb5in_data, krb5credsp, krb5_app_req)) != 0) + /* 20010406 VRS deleted for real KerberosWrapper + ** 20010605 VRS reinstated to offer Authenticator to KerberosWrapper + */ + krb5_app_req.length = 0; + if (authenp) { - kssl_err_set(kssl_err, SSL_R_KRB5_C_MK_REQ, - "krb5_mk_req_extended() fails.\n"); - goto err; + krb5_data krb5in_data; + unsigned char *p; + long arlen; + KRB5_APREQBODY *ap_req; + + authenp->length = 0; + krb5in_data.data = NULL; + krb5in_data.length = 0; + if ((krb5rc = krb5_mk_req_extended(krb5context, + &krb5auth_context, 0, &krb5in_data, krb5credsp, + &krb5_app_req)) != 0) + { + kssl_err_set(kssl_err, SSL_R_KRB5_C_MK_REQ, + "krb5_mk_req_extended() fails.\n"); + goto err; + } + + arlen = krb5_app_req.length; + p = krb5_app_req.data; + ap_req = (KRB5_APREQBODY *) d2i_KRB5_APREQ(NULL, &p, arlen); + if (ap_req) + { + authenp->length = i2d_KRB5_ENCDATA( + ap_req->authenticator, NULL); + if (authenp->length && + (authenp->data = malloc(authenp->length))) + { + unsigned char *p = authenp->data; + authenp->length = i2d_KRB5_ENCDATA( + ap_req->authenticator, &p); + } + } + + if (ap_req) KRB5_APREQ_free((KRB5_APREQ *) ap_req); + if (krb5_app_req.length) krb5_xfree(krb5_app_req.data); } #ifdef KRB5_HEIMDAL - else if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session)) + if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->session)) { kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, "kssl_ctx_setkey() fails.\n"); } #else - else if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->keyblock)) + if (kssl_ctx_setkey(kssl_ctx, &krb5credsp->keyblock)) { kssl_err_set(kssl_err, SSL_R_KRB5_C_INIT, "kssl_ctx_setkey() fails.\n"); @@ -695,14 +1018,102 @@ kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, kssl_ctx_show(kssl_ctx); #endif /* KSSL_DEBUG */ - if (krb5creds.client) krb5_free_principal(krb5context, krb5creds.client); - if (krb5creds.server) krb5_free_principal(krb5context, krb5creds.server); - if (krb5auth_context) krb5_auth_con_free(krb5context, krb5auth_context); + if (krb5creds.client) krb5_free_principal(krb5context, + krb5creds.client); + if (krb5creds.server) krb5_free_principal(krb5context, + krb5creds.server); + if (krb5auth_context) krb5_auth_con_free(krb5context, + krb5auth_context); if (krb5context) krb5_free_context(krb5context); return (krb5rc); } +/* Given d2i_-decoded asn1ticket, allocate and return a new krb5_ticket. +** Return Kerberos error code and kssl_err struct on error. +** Allocates krb5_ticket and krb5_principal; caller should free these. +** +** 20010410 VRS Implemented krb5_decode_ticket() as +** old_krb5_decode_ticket(). Missing from MIT1.0.6. +** 20010615 VRS Re-cast as openssl/asn1 d2i_*() functions. +** Re-used some of the old krb5_decode_ticket() +** code here. This tkt should alloc/free just +** like the real thing. +*/ +krb5_error_code +kssl_TKT2tkt( /* IN */ krb5_context krb5context, + /* IN */ KRB5_TKTBODY *asn1ticket, + /* OUT */ krb5_ticket **krb5ticket, + /* OUT */ KSSL_ERR *kssl_err ) + { + krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; + krb5_ticket *new5ticket = NULL; + ASN1_GENERALSTRING *gstr_svc, *gstr_host; + + *krb5ticket = NULL; + + if (asn1ticket == NULL || asn1ticket->realm == NULL || + asn1ticket->sname == NULL || + asn1ticket->sname->namestring == NULL || + asn1ticket->sname->namestring->num < 2) + { + BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, + "Null field in asn1ticket.\n"); + kssl_err->reason = SSL_R_KRB5_S_RD_REQ; + return KRB5KRB_ERR_GENERIC; + } + + if ((new5ticket = (krb5_ticket *) calloc(1, sizeof(krb5_ticket)))==NULL) + { + BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, + "Unable to allocate new krb5_ticket.\n"); + kssl_err->reason = SSL_R_KRB5_S_RD_REQ; + return ENOMEM; /* or KRB5KRB_ERR_GENERIC; */ + } + + gstr_svc = (ASN1_GENERALSTRING*)asn1ticket->sname->namestring->data[0]; + gstr_host = (ASN1_GENERALSTRING*)asn1ticket->sname->namestring->data[1]; + + if ((krb5rc = kssl_build_principal_2(krb5context, + &new5ticket->server, + asn1ticket->realm->length, asn1ticket->realm->data, + gstr_svc->length, gstr_svc->data, + gstr_host->length, gstr_host->data)) != 0) + { + free(new5ticket); + BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, + "Error building ticket server principal.\n"); + kssl_err->reason = SSL_R_KRB5_S_RD_REQ; + return krb5rc; /* or KRB5KRB_ERR_GENERIC; */ + } + + krb5_princ_type(krb5context, new5ticket->server) = + asn1ticket->sname->nametype->data[0]; + new5ticket->enc_part.enctype = asn1ticket->encdata->etype->data[0]; + new5ticket->enc_part.kvno = asn1ticket->encdata->kvno->data[0]; + new5ticket->enc_part.ciphertext.length = + asn1ticket->encdata->cipher->length; + if ((new5ticket->enc_part.ciphertext.data = + calloc(1, asn1ticket->encdata->cipher->length)) == NULL) + { + free(new5ticket); + BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, + "Error allocating cipher in krb5ticket.\n"); + kssl_err->reason = SSL_R_KRB5_S_RD_REQ; + return KRB5KRB_ERR_GENERIC; + } + else + { + memcpy(new5ticket->enc_part.ciphertext.data, + asn1ticket->encdata->cipher->data, + asn1ticket->encdata->cipher->length); + } + + *krb5ticket = new5ticket; + return 0; + } + + /* Given krb5 service name in KSSL_CTX *kssl_ctx (typically "kssl"), ** and krb5 AP_REQ message & message length, ** Return Kerberos session key and client principle @@ -711,24 +1122,27 @@ kssl_cget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, ** 19990702 VRS Started. */ krb5_error_code -kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, - /* IN */ char *msg, int msglen, - /* OUT */ KSSL_ERR *kssl_err ) +kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, + /* IN */ krb5_data *indata, + /* OUT */ krb5_ticket_times *ttimes, + /* OUT */ KSSL_ERR *kssl_err ) { krb5_error_code krb5rc = KRB5KRB_ERR_GENERIC; static krb5_context krb5context = NULL; static krb5_auth_context krb5auth_context = NULL; krb5_ticket *krb5ticket = NULL; + KRB5_TKTBODY *asn1ticket = NULL; + unsigned char *p; krb5_keytab krb5keytab = NULL; + krb5_keytab_entry kt_entry; krb5_principal krb5server; - krb5_data krb5in_data; - krb5_flags ap_option; kssl_err_set(kssl_err, 0, ""); if (!kssl_ctx) { - kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, "No kssl_ctx defined.\n"); + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "No kssl_ctx defined.\n"); goto err; } @@ -792,21 +1206,89 @@ kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, } /* Actual Kerberos5 krb5_recvauth() has initial conversation here - ** o check KRB5_SENDAUTH_BADAUTHVERS unless KRB5_RECVAUTH_SKIP_VERSION + ** o check KRB5_SENDAUTH_BADAUTHVERS + ** unless KRB5_RECVAUTH_SKIP_VERSION ** o check KRB5_SENDAUTH_BADAPPLVERS ** o send "0" msg if all OK */ - krb5in_data.data = msg; - krb5in_data.length = msglen; - if ((krb5rc = krb5_rd_req(krb5context, &krb5auth_context, &krb5in_data, - krb5server, krb5keytab, &ap_option, &krb5ticket)) != 0) - { + /* 20010411 was using AP_REQ instead of true KerberosWrapper + ** + ** if ((krb5rc = krb5_rd_req(krb5context, &krb5auth_context, + ** &krb5in_data, krb5server, krb5keytab, + ** &ap_option, &krb5ticket)) != 0) { Error } + */ + + p = indata->data; + if ((asn1ticket = (KRB5_TKTBODY *) d2i_KRB5_TICKET(NULL, &p, + (long) indata->length)) == NULL) + { + BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, + "d2i_KRB5_TICKET() ASN.1 decode failure.\n"); + kssl_err->reason = SSL_R_KRB5_S_RD_REQ; + goto err; + } + + /* Was: krb5rc = krb5_decode_ticket(krb5in_data,&krb5ticket)) != 0) */ + if ((krb5rc = kssl_TKT2tkt(krb5context, asn1ticket, &krb5ticket, + kssl_err)) != 0) + { + BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, + "Error converting ASN.1 ticket to krb5_ticket.\n"); + kssl_err->reason = SSL_R_KRB5_S_RD_REQ; + goto err; + } + + if (! krb5_principal_compare(krb5context, krb5server, + krb5ticket->server)) { + krb5rc = KRB5_PRINC_NOMATCH; + BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, + "server principal != ticket principal\n"); + kssl_err->reason = SSL_R_KRB5_S_RD_REQ; + goto err; + } + if ((krb5rc = krb5_kt_get_entry(krb5context, krb5keytab, + krb5ticket->server, krb5ticket->enc_part.kvno, + krb5ticket->enc_part.enctype, &kt_entry)) != 0) { BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, - "krb5_rd_req() fails with %x.\n", krb5rc); + "krb5_kt_get_entry() fails with %x.\n", krb5rc); kssl_err->reason = SSL_R_KRB5_S_RD_REQ; goto err; } + if ((krb5rc = krb5_decrypt_tkt_part(krb5context, &kt_entry.key, + krb5ticket)) != 0) { + BIO_snprintf(kssl_err->text, KSSL_ERR_MAX, + "krb5_decrypt_tkt_part() failed.\n"); + kssl_err->reason = SSL_R_KRB5_S_RD_REQ; + goto err; + } + else { + krb5_kt_free_entry(krb5context, &kt_entry); +#ifdef KSSL_DEBUG + { + int i; krb5_address **paddr = krb5ticket->enc_part2->caddrs; + printf("Decrypted ticket fields:\n"); + printf("\tflags: %X, transit-type: %X", + krb5ticket->enc_part2->flags, + krb5ticket->enc_part2->transited.tr_type); + print_krb5_data("\ttransit-data: ", + &(krb5ticket->enc_part2->transited.tr_contents)); + printf("\tcaddrs: %p, authdata: %p\n", + krb5ticket->enc_part2->caddrs, + krb5ticket->enc_part2->authorization_data); + printf("\tcaddrs:\n"); + for (i=0; paddr[i] != NULL; i++) + { krb5_data d; + d.length=paddr[i]->length; d.data=paddr[i]->contents; + print_krb5_data("\t\tIP: ", &d); + } + printf("\tstart/auth/end times: %d / %d / %d\n", + krb5ticket->enc_part2->times.starttime, + krb5ticket->enc_part2->times.authtime, + krb5ticket->enc_part2->times.endtime); + } +#endif /* KSSL_DEBUG */ + } krb5rc = KRB5_NO_TKT_SUPPLIED; if (!krb5ticket || !krb5ticket->enc_part2 || @@ -829,13 +1311,26 @@ kssl_sget_tkt( /* UPDATE */ KSSL_CTX *kssl_ctx, kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, "kssl_ctx_setkey() fails.\n"); } + else if (krb5ticket->enc_part2->flags & TKT_FLG_INVALID) + { + krb5rc = KRB5KRB_AP_ERR_TKT_INVALID; + kssl_err_set(kssl_err, SSL_R_KRB5_S_BAD_TICKET, + "invalid ticket from krb5_rd_req.\n"); + } else krb5rc = 0; + kssl_ctx->enctype = krb5ticket->enc_part.enctype; + ttimes->authtime = krb5ticket->enc_part2->times.authtime; + ttimes->starttime = krb5ticket->enc_part2->times.starttime; + ttimes->endtime = krb5ticket->enc_part2->times.endtime; + ttimes->renew_till = krb5ticket->enc_part2->times.renew_till; + err: #ifdef KSSL_DEBUG kssl_ctx_show(kssl_ctx); #endif /* KSSL_DEBUG */ + if (asn1ticket) KRB5_TICKET_free((KRB5_TICKET *) asn1ticket); if (krb5keytab) krb5_kt_close(krb5context, krb5keytab); if (krb5ticket) krb5_free_ticket(krb5context, krb5ticket); if (krb5server) krb5_free_principal(krb5context, krb5server); @@ -860,7 +1355,8 @@ kssl_ctx_free(KSSL_CTX *kssl_ctx) { if (kssl_ctx == NULL) return kssl_ctx; - if (kssl_ctx->key) memset(kssl_ctx->key, 0, kssl_ctx->length); + if (kssl_ctx->key) memset(kssl_ctx->key, 0, + kssl_ctx->length); if (kssl_ctx->key) free(kssl_ctx->key); if (kssl_ctx->client_princ) free(kssl_ctx->client_princ); if (kssl_ctx->service_host) free(kssl_ctx->service_host); @@ -953,6 +1449,10 @@ kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text) krb5_error_code kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session) { + int length; + krb5_enctype enctype; + krb5_octet FAR *contents = NULL; + if (!kssl_ctx) return KSSL_CTX_ERR; if (kssl_ctx->key) @@ -963,8 +1463,18 @@ kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session) if (session) { - kssl_ctx->enctype = session->enctype; - kssl_ctx->length = session->length; + +#ifdef KRB5_HEIMDAL + length = session->keyvalue->length; + enctype = session->keytype; + contents = session->keyvalue->contents; +#else + length = session->length; + enctype = session->enctype; + contents = session->contents; +#endif + kssl_ctx->enctype = enctype; + kssl_ctx->length = length; } else { @@ -980,7 +1490,7 @@ kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session) return KSSL_CTX_ERR; } else - memcpy(kssl_ctx->key, session->contents, session->length); + memcpy(kssl_ctx->key, contents, length); return KSSL_CTX_OK; } @@ -1026,11 +1536,269 @@ void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data) #ifdef KRB5_HEIMDAL data->length = 0; free(data->if (data->data) data); +#elif defined(KRB5_MIT_OLD11) + if (data->data) { + krb5_xfree(data->data); + data->data = 0; + } #else krb5_free_data_contents(NULL, data); #endif } + +/* Helper function for kssl_validate_times(). +** We need context->clockskew, but krb5_context is an opaque struct. +** So we try to sneek the clockskew out through the replay cache. +** If that fails just return a likely default (300 seconds). +*/ +krb5_deltat get_rc_clockskew(krb5_context context) + { + krb5_rcache rc; + krb5_deltat clockskew; + + if (krb5_rc_default(context, &rc)) return KSSL_CLOCKSKEW; + if (krb5_rc_initialize(context, rc, 0)) return KSSL_CLOCKSKEW; + if (krb5_rc_get_lifespan(context, rc, &clockskew)) { + clockskew = KSSL_CLOCKSKEW; + } + (void) krb5_rc_destroy(context, rc); + return clockskew; + } + + +/* kssl_validate_times() combines (and more importantly exposes) +** the MIT KRB5 internal function krb5_validate_times() and the +** in_clock_skew() macro. The authenticator client time is checked +** to be within clockskew secs of the current time and the current +** time is checked to be within the ticket start and expire times. +** Either check may be omitted by supplying a NULL value. +** Returns 0 for valid times, SSL_R_KRB5* error codes otherwise. +** See Also: (Kerberos source)/krb5/lib/krb5/krb/valid_times.c +** 20010420 VRS +*/ +krb5_error_code kssl_validate_times( krb5_timestamp atime, + krb5_ticket_times *ttimes) + { + krb5_deltat skew; + krb5_timestamp start, now; + krb5_error_code rc; + krb5_context context; + + if ((rc = krb5_init_context(&context))) return SSL_R_KRB5_S_BAD_TICKET; + skew = get_rc_clockskew(context); + if ((rc = krb5_timeofday(context,&now))) return SSL_R_KRB5_S_BAD_TICKET; + krb5_free_context(context); + + if (atime && labs(atime - now) >= skew) return SSL_R_KRB5_S_TKT_SKEW; + + if (! ttimes) return 0; + + start = (ttimes->starttime != 0)? ttimes->starttime: ttimes->authtime; + if (start - now > skew) return SSL_R_KRB5_S_TKT_NYV; + if ((now - ttimes->endtime) > skew) return SSL_R_KRB5_S_TKT_EXPIRED; + +#ifdef KSSL_DEBUG + printf("kssl_validate_times: %d |<- | %d - %d | < %d ->| %d\n", + start, atime, now, skew, ttimes->endtime); +#endif /* KSSL_DEBUG */ + + return 0; + } + + +/* Decode and decrypt given DER-encoded authenticator, then pass +** authenticator ctime back in *atimep (or 0 if time unavailable). +** Returns krb5_error_code and kssl_err on error. A NULL +** authenticator (authentp->length == 0) is not considered an error. +** Note that kssl_check_authent() makes use of the KRB5 session key; +** you must call kssl_sget_tkt() to get the key before calling this routine. +*/ +krb5_error_code kssl_check_authent( + /* IN */ KSSL_CTX *kssl_ctx, + /* IN */ krb5_data *authentp, + /* OUT */ krb5_timestamp *atimep, + /* OUT */ KSSL_ERR *kssl_err ) + { + krb5_error_code krb5rc = 0; + KRB5_ENCDATA *dec_authent = NULL; + KRB5_AUTHENTBODY *auth = NULL; + krb5_enctype enctype; + EVP_CIPHER_CTX ciph_ctx; + EVP_CIPHER *enc = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char *p, *unenc_authent, *tbuf = NULL; + int padl, outl, unencbufsize; + struct tm tm_time, *tm_l, *tm_g; + time_t now, tl, tg, tz_offset; + + *atimep = 0; + kssl_err_set(kssl_err, 0, ""); + +#ifndef KRB5CHECKAUTH + authentp = NULL; +#else +#if KRB5CHECKAUTH == 0 + authentp = NULL; +#endif +#endif /* KRB5CHECKAUTH */ + + if (authentp == NULL || authentp->length == 0) return 0; + +#ifdef KSSL_DEBUG + printf("kssl_check_authent: authenticator[%d]:\n",authentp->length); + p = authentp->data; + for (padl=0; padl < authentp->length; padl++) printf("%02x ",p[padl]); + printf("\n"); +#endif /* KSSL_DEBUG */ + + unencbufsize = 2 * authentp->length; + if ((unenc_authent = calloc(1, unencbufsize)) == NULL) + { + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "Unable to allocate authenticator buffer.\n"); + krb5rc = KRB5KRB_ERR_GENERIC; + goto err; + } + + p = authentp->data; + if ((dec_authent = d2i_KRB5_ENCDATA(NULL, &p, + (long) authentp->length)) == NULL) + { + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "Error decoding authenticator.\n"); + krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto err; + } + + enctype = dec_authent->etype->data[0]; /* should = kssl_ctx->enctype */ + enc = kssl_map_enc(enctype); + memset(iv, 0, EVP_MAX_IV_LENGTH); /* per RFC 1510 */ + + EVP_DecryptInit(&ciph_ctx, enc, kssl_ctx->key, iv); + EVP_DecryptUpdate(&ciph_ctx, unenc_authent, &outl, + dec_authent->cipher->data, dec_authent->cipher->length); + if (outl > unencbufsize) + { + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "Buffer overflow decrypting authenticator.\n"); + krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto err; + } + EVP_DecryptFinal(&ciph_ctx, &(unenc_authent[outl]), &padl); + outl += padl; + if (outl > unencbufsize) + { + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "Buffer overflow decrypting authenticator.\n"); + krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto err; + } + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + +#ifdef KSSL_DEBUG + printf("kssl_check_authent: decrypted authenticator[%d] =\n", outl); + for (padl=0; padl < outl; padl++) printf("%02x ",unenc_authent[padl]); + printf("\n"); +#endif /* KSSL_DEBUG */ + + if ((p = kssl_skip_confound(enctype, unenc_authent)) == NULL) + { + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "confounded by authenticator.\n"); + krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto err; + } + outl -= p - unenc_authent; + + if ((auth = (KRB5_AUTHENTBODY *) d2i_KRB5_AUTHENT(NULL, &p, + (long) outl))==NULL) + { + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "Error decoding authenticator body.\n"); + krb5rc = KRB5KRB_AP_ERR_BAD_INTEGRITY; + goto err; + } + if ((tbuf = calloc(1, auth->ctime->length + 1)) == NULL) + { + kssl_err_set(kssl_err, SSL_R_KRB5_S_INIT, + "Unable to allocate atime buffer.\n"); + krb5rc = KRB5KRB_ERR_GENERIC; + goto err; + } + else strncpy(tbuf, auth->ctime->data, auth->ctime->length); + + if (strptime(tbuf, "%Y%m%d%H%M%S", &tm_time) != NULL) + { + now = time(&now); + tm_l = localtime(&now); tl = mktime(tm_l); + tm_g = gmtime(&now); tg = mktime(tm_g); + tz_offset = tg - tl; + + *atimep = mktime(&tm_time) - tz_offset; + } + +#ifdef KSSL_DEBUG + printf("kssl_check_authent: client time %s = %d\n", tbuf, *atimep); +#endif /* KSSL_DEBUG */ + + err: + if (tbuf) free(tbuf); + if (auth) KRB5_AUTHENT_free((KRB5_AUTHENT *) auth); + if (dec_authent) KRB5_ENCDATA_free(dec_authent); + if (unenc_authent) free(unenc_authent); + return krb5rc; + } + + +/* Replaces krb5_build_principal_ext(), with varargs length == 2 (svc, host), +** because I dont't know how to stub varargs. +** Returns krb5_error_code == ENOMEM on alloc error, otherwise +** passes back newly constructed principal, which should be freed by caller. +*/ +krb5_error_code kssl_build_principal_2( + /* UPDATE */ krb5_context context, + /* OUT */ krb5_principal *princ, + /* IN */ int rlen, const char *realm, + /* IN */ int slen, const char *svc, + /* IN */ int hlen, const char *host) + { + krb5_data *p_data = NULL; + krb5_principal new_p = NULL; + char *new_r = NULL; + + if ((p_data = (krb5_data *) calloc(2, sizeof(krb5_data))) == NULL || + (new_p = (krb5_principal) calloc(1, sizeof(krb5_principal_data))) + == NULL) goto err; + new_p->length = 2; + new_p->data = p_data; + + if ((new_r = calloc(1, rlen + 1)) == NULL) goto err; + memcpy(new_r, realm, rlen); + krb5_princ_set_realm_length(context, new_p, rlen); + krb5_princ_set_realm_data(context, new_p, new_r); + + if ((new_p->data[0].data = calloc(1, slen + 1)) == NULL) goto err; + memcpy(new_p->data[0].data, svc, slen); + new_p->data[0].length = slen; + + if ((new_p->data[1].data = calloc(1, hlen + 1)) == NULL) goto err; + memcpy(new_p->data[1].data, host, hlen); + new_p->data[1].length = hlen; + + krb5_princ_type(context, new_p) = KRB5_NT_UNKNOWN; + *princ = new_p; + return 0; + + err: + if (new_p && new_p[0].data) free(new_p[0].data); + if (new_p && new_p[1].data) free(new_p[1].data); + if (new_p) free(new_p); + if (new_r) free(new_r); + return ENOMEM; + } + + #else /* !OPENSSL_NO_KRB5 */ #if defined(PEDANTIC) || defined(OPENSSL_SYS_VMS) diff --git a/ssl/kssl.h b/ssl/kssl.h index ef0fc847b1..7319b3daf2 100644 --- a/ssl/kssl.h +++ b/ssl/kssl.h @@ -96,6 +96,17 @@ typedef unsigned char krb5_octet; #define KRB5KEYTAB "/etc/krb5.keytab" #endif +#ifndef KRB5SENDAUTH +#define KRB5SENDAUTH 1 +#endif + +#ifndef KRB5CHECKAUTH +#define KRB5CHECKAUTH 1 +#endif + +#ifndef KSSL_CLOCKSKEW +#define KSSL_CLOCKSKEW 300; +#endif #define KSSL_ERR_MAX 255 typedef struct kssl_err_st { @@ -139,6 +150,8 @@ void print_krb5_keyblock(char *label, krb5_keyblock *keyblk); char *kstring(char *string); char *knumber(int len, krb5_octet *contents); +EVP_CIPHER *kssl_map_enc(krb5_enctype enctype); + /* Public (for use by applications that use OpenSSL with Kerberos 5 support */ krb5_error_code kssl_ctx_setstring(KSSL_CTX *kssl_ctx, int which, char *text); @@ -147,13 +160,21 @@ KSSL_CTX *kssl_ctx_free(KSSL_CTX *kssl_ctx); void kssl_ctx_show(KSSL_CTX *kssl_ctx); krb5_error_code kssl_ctx_setprinc(KSSL_CTX *kssl_ctx, int which, krb5_data *realm, krb5_data *entity); -krb5_error_code kssl_cget_tkt(KSSL_CTX *kssl_ctx, krb5_data *ap_req, - KSSL_ERR *kssl_err); -krb5_error_code kssl_sget_tkt(KSSL_CTX *kssl_ctx, char *msg, int msglen, - KSSL_ERR *kssl_err); +krb5_error_code kssl_cget_tkt(KSSL_CTX *kssl_ctx, krb5_data **enc_tktp, + krb5_data *authenp, KSSL_ERR *kssl_err); +krb5_error_code kssl_sget_tkt(KSSL_CTX *kssl_ctx, krb5_data *indata, + krb5_ticket_times *ttimes, KSSL_ERR *kssl_err); krb5_error_code kssl_ctx_setkey(KSSL_CTX *kssl_ctx, krb5_keyblock *session); void kssl_err_set(KSSL_ERR *kssl_err, int reason, char *text); void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data); +krb5_error_code kssl_build_principal_2(krb5_context context, + krb5_principal *princ, int rlen, const char *realm, + int slen, const char *svc, int hlen, const char *host); +krb5_error_code kssl_validate_times(krb5_timestamp atime, + krb5_ticket_times *ttimes); +krb5_error_code kssl_check_authent(KSSL_CTX *kssl_ctx, krb5_data *authentp, + krb5_timestamp *atimep, KSSL_ERR *kssl_err); +unsigned char *kssl_skip_confound(krb5_enctype enctype, unsigned char *authn); #ifdef __cplusplus } diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c index a700c64417..93a87c4f12 100644 --- a/ssl/s3_clnt.c +++ b/ssl/s3_clnt.c @@ -785,13 +785,13 @@ static int ssl3_get_server_certificate(SSL *s) * certificate, which we don't include in s3_srvr.c */ x=sk_X509_value(sk,0); sk=NULL; - /* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end */ + /* VRS 19990621: possible memory leak; sk=null ==> !sk_pop_free() @end*/ pkey=X509_get_pubkey(x); /* VRS: allow null cert if auth == KRB5 */ - need_cert = - ((s->s3->tmp.new_cipher->algorithms & (SSL_MKEY_MASK|SSL_AUTH_MASK)) + need_cert = ((s->s3->tmp.new_cipher->algorithms + & (SSL_MKEY_MASK|SSL_AUTH_MASK)) == (SSL_aKRB5|SSL_kKRB5))? 0: 1; #ifdef KSSL_DEBUG @@ -801,11 +801,12 @@ static int ssl3_get_server_certificate(SSL *s) s->s3->tmp.new_cipher->algorithms, need_cert); #endif /* KSSL_DEBUG */ - if (need_cert && ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey))) + if (need_cert && ((pkey == NULL) || EVP_PKEY_missing_parameters(pkey))) { x=NULL; al=SSL3_AL_FATAL; - SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS); + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, + SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS); goto f_err; } @@ -814,7 +815,8 @@ static int ssl3_get_server_certificate(SSL *s) { x=NULL; al=SSL3_AL_FATAL; - SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE,SSL_R_UNKNOWN_CERTIFICATE_TYPE); + SSLerr(SSL_F_SSL3_GET_SERVER_CERTIFICATE, + SSL_R_UNKNOWN_CERTIFICATE_TYPE); goto f_err; } @@ -1427,65 +1429,121 @@ static int ssl3_send_client_key_exchange(SSL *s) { krb5_error_code krb5rc; KSSL_CTX *kssl_ctx = s->kssl_ctx; - krb5_data krb5_ap_req; + /* krb5_data krb5_ap_req; */ + krb5_data *enc_ticket; + krb5_data authenticator, *authp = NULL; + EVP_CIPHER_CTX ciph_ctx; + EVP_CIPHER *enc = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char tmp_buf[SSL_MAX_MASTER_KEY_LENGTH]; + unsigned char epms[SSL_MAX_MASTER_KEY_LENGTH + + EVP_MAX_IV_LENGTH]; + int padl, outl = sizeof(epms); #ifdef KSSL_DEBUG printf("ssl3_send_client_key_exchange(%lx & %lx)\n", l, SSL_kKRB5); #endif /* KSSL_DEBUG */ - /* - ** Tried to send random tmp_buf[] as PMS in Kerberos ticket - ** by passing krb5_mk_req_extended(ctx,authctx,opts, tmp_buf, ...) - ** but: I can't retrieve the PMS on the other side! There is - ** some indication in the krb5 source that this is only used - ** to generate a checksum. OTOH, the Tung book shows data - ** ("GET widget01.txt") being passed in krb5_mk_req_extended() - ** by way of krb5_sendauth(). I don't get it. - ** Until Kerberos goes 3DES, the big PMS secret would only be - ** encrypted in 1-DES anyway. So losing the PMS shouldn't be - ** a big deal. - */ - krb5rc = kssl_cget_tkt(kssl_ctx, &krb5_ap_req, - &kssl_err); + authp = NULL; +#ifdef KRB5SENDAUTH + if (KRB5SENDAUTH) authp = &authenticator; +#endif /* KRB5SENDAUTH */ + + krb5rc = kssl_cget_tkt(kssl_ctx, &enc_ticket, authp, + &kssl_err); + enc = kssl_map_enc(kssl_ctx->enctype); #ifdef KSSL_DEBUG { printf("kssl_cget_tkt rtn %d\n", krb5rc); - kssl_ctx_show(kssl_ctx); if (krb5rc && kssl_err.text) - printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text); + printf("kssl_cget_tkt kssl_err=%s\n", kssl_err.text); } #endif /* KSSL_DEBUG */ if (krb5rc) { - ssl3_send_alert(s,SSL3_AL_FATAL,SSL_AD_HANDSHAKE_FAILURE); - SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, kssl_err.reason); + ssl3_send_alert(s,SSL3_AL_FATAL, + SSL_AD_HANDSHAKE_FAILURE); + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + kssl_err.reason); goto err; } - /* Send ticket (copy to *p, set n = length) - */ - n = krb5_ap_req.length; - memcpy(p, krb5_ap_req.data, krb5_ap_req.length); - if (krb5_ap_req.data) - kssl_krb5_free_data_contents(NULL,&krb5_ap_req); - - /* 19991013 VRS - 3DES is kind of bogus here, - ** at least until Kerberos supports 3DES. The only - ** real secret is the 8-byte Kerberos session key; - ** the other key material ((s->) client_random, server_random) - ** could be sniffed. Mixing in these nonces should help - ** protect against replay attacks, however. - ** - ** Alternate code for Kerberos Purists: + /* 20010406 VRS - Earlier versions used KRB5 AP_REQ + ** in place of RFC 2712 KerberosWrapper, as in: + ** + ** Send ticket (copy to *p, set n = length) + ** n = krb5_ap_req.length; + ** memcpy(p, krb5_ap_req.data, krb5_ap_req.length); + ** if (krb5_ap_req.data) + ** kssl_krb5_free_data_contents(NULL,&krb5_ap_req); ** - ** memcpy(s->session->master_key, kssl_ctx->key, kssl_ctx->length); - ** s->session->master_key_length = kssl_ctx->length; - */ + ** Now using real RFC 2712 KerberosWrapper + ** (Thanks to Simon Wilkinson <sxw@sxw.org.uk>) + ** Note: 2712 "opaque" types are here replaced + ** with a 2-byte length followed by the value. + ** Example: + ** KerberosWrapper= xx xx asn1ticket 0 0 xx xx encpms + ** Where "xx xx" = length bytes. Shown here with + ** optional authenticator omitted. + */ + + /* KerberosWrapper.Ticket */ + s2n(enc_ticket->length,p); + memcpy(p, enc_ticket->data, enc_ticket->length); + p+= enc_ticket->length; + n = enc_ticket->length + 2; + + /* KerberosWrapper.Authenticator */ + if (authp && authp->length) + { + s2n(authp->length,p); + memcpy(p, authp->data, authp->length); + p+= authp->length; + n+= authp->length + 2; + + free(authp->data); + authp->data = NULL; + authp->length = 0; + } + else + { + s2n(0,p);/* null authenticator length */ + n+=2; + } + + if (RAND_bytes(tmp_buf,SSL_MAX_MASTER_KEY_LENGTH) <= 0) + goto err; + + /* 20010420 VRS. Tried it this way; failed. + ** EVP_EncryptInit(&ciph_ctx,enc, NULL,NULL); + ** EVP_CIPHER_CTX_set_key_length(&ciph_ctx, + ** kssl_ctx->length); + ** EVP_EncryptInit(&ciph_ctx,NULL, key,iv); + */ + + memset(iv, 0, EVP_MAX_IV_LENGTH); /* per RFC 1510 */ + EVP_EncryptInit(&ciph_ctx,enc, kssl_ctx->key,iv); + EVP_EncryptUpdate(&ciph_ctx,epms,&outl,tmp_buf, + SSL_MAX_MASTER_KEY_LENGTH); + EVP_EncryptFinal(&ciph_ctx,&(epms[outl]),&padl); + outl += padl; + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + + /* KerberosWrapper.EncryptedPreMasterSecret */ + s2n(outl,p); + memcpy(p, epms, outl); + p+=outl; + n+=outl + 2; + s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, - s->session->master_key, kssl_ctx->key,kssl_ctx->length); + s->session->master_key, + tmp_buf, SSL_MAX_MASTER_KEY_LENGTH); + + memset(tmp_buf, 0, SSL_MAX_MASTER_KEY_LENGTH); + memset(epms, 0, outl); } #endif #ifndef OPENSSL_NO_DH diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c index 09fcc59d00..9fcf8c0fdf 100644 --- a/ssl/s3_srvr.c +++ b/ssl/s3_srvr.c @@ -66,6 +66,7 @@ #include <openssl/objects.h> #include <openssl/evp.h> #include <openssl/x509.h> +#include <openssl/krb5_asn.h> #include "ssl_locl.h" #ifndef OPENSSL_NO_KRB5 @@ -1452,13 +1453,46 @@ static int ssl3_get_client_key_exchange(SSL *s) #ifndef OPENSSL_NO_KRB5 if (l & SSL_kKRB5) { - krb5_error_code krb5rc; - KSSL_CTX *kssl_ctx = s->kssl_ctx; + krb5_error_code krb5rc; + krb5_data enc_ticket; + krb5_data authenticator; + krb5_data enc_pms; + KSSL_CTX *kssl_ctx = s->kssl_ctx; + EVP_CIPHER_CTX ciph_ctx; + EVP_CIPHER *enc = NULL; + unsigned char iv[EVP_MAX_IV_LENGTH]; + unsigned char pms[SSL_MAX_MASTER_KEY_LENGTH]; + int padl, outl = sizeof(pms); + krb5_timestamp authtime = 0; + krb5_ticket_times ttimes; if (!kssl_ctx) kssl_ctx = kssl_ctx_new(); - if ((krb5rc = kssl_sget_tkt(kssl_ctx, - s->init_buf->data, s->init_buf->length, - &kssl_err)) != 0) + + n2s(p,i); + enc_ticket.length = i; + enc_ticket.data = p; + p+=enc_ticket.length; + + n2s(p,i); + authenticator.length = i; + authenticator.data = p; + p+=authenticator.length; + + n2s(p,i); + enc_pms.length = i; + enc_pms.data = p; + p+=enc_pms.length; + + if (n != enc_ticket.length + authenticator.length + + enc_pms.length + 6) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + + if ((krb5rc = kssl_sget_tkt(kssl_ctx, &enc_ticket, &ttimes, + &kssl_err)) != 0) { #ifdef KSSL_DEBUG printf("kssl_sget_tkt rtn %d [%d]\n", @@ -1471,34 +1505,71 @@ static int ssl3_get_client_key_exchange(SSL *s) goto err; } + /* Note: no authenticator is not considered an error, + ** but will return authtime == 0. + */ + if ((krb5rc = kssl_check_authent(kssl_ctx, &authenticator, + &authtime, &kssl_err)) != 0) + { +#ifdef KSSL_DEBUG + printf("kssl_check_authent rtn %d [%d]\n", + krb5rc, kssl_err.reason); + if (kssl_err.text) + printf("kssl_err text= %s\n", kssl_err.text); +#endif /* KSSL_DEBUG */ + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, + kssl_err.reason); + goto err; + } + + if ((krb5rc = kssl_validate_times(authtime, &ttimes)) != 0) + { + SSLerr(SSL_F_SSL3_SEND_CLIENT_KEY_EXCHANGE, krb5rc); + goto err; + } + #ifdef KSSL_DEBUG kssl_ctx_show(kssl_ctx); #endif /* KSSL_DEBUG */ - /* 19991013 VRS - 3DES is kind of bogus here, - ** at least until Kerberos supports 3DES. The only - ** real secret is the 8-byte Kerberos session key; - ** the other key material (client_random, server_random) - ** could be sniffed. Nonces may help against replays though. - ** - ** Alternate code for Kerberos Purists: - ** - ** memcpy(s->session->master_key, kssl_ctx->key, kssl_ctx->length); - ** s->session->master_key_length = kssl_ctx->length; - */ + enc = kssl_map_enc(kssl_ctx->enctype); + memset(iv, 0, EVP_MAX_IV_LENGTH); /* per RFC 1510 */ + + EVP_DecryptInit(&ciph_ctx,enc,kssl_ctx->key,iv); + EVP_DecryptUpdate(&ciph_ctx, pms,&outl, + enc_pms.data, enc_pms.length); + if (outl > SSL_MAX_MASTER_KEY_LENGTH) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + EVP_DecryptFinal(&ciph_ctx,&(pms[outl]),&padl); + outl += padl; + if (outl > SSL_MAX_MASTER_KEY_LENGTH) + { + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_DATA_LENGTH_TOO_LONG); + goto err; + } + EVP_CIPHER_CTX_cleanup(&ciph_ctx); + s->session->master_key_length= s->method->ssl3_enc->generate_master_secret(s, - s->session->master_key, kssl_ctx->key, kssl_ctx->length); - /* Was doing kssl_ctx_free() here, but it caused problems for apache. - ** kssl_ctx = kssl_ctx_free(kssl_ctx); - ** if (s->kssl_ctx) s->kssl_ctx = NULL; + s->session->master_key, pms, outl); + + /* Was doing kssl_ctx_free() here, + ** but it caused problems for apache. + ** kssl_ctx = kssl_ctx_free(kssl_ctx); + ** if (s->kssl_ctx) s->kssl_ctx = NULL; */ } else #endif /* OPENSSL_NO_KRB5 */ { al=SSL_AD_HANDSHAKE_FAILURE; - SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,SSL_R_UNKNOWN_CIPHER_TYPE); + SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE, + SSL_R_UNKNOWN_CIPHER_TYPE); goto f_err; } @@ -1459,13 +1459,17 @@ void ERR_load_SSL_strings(void); #define SSL_R_INVALID_COMMAND 280 #define SSL_R_INVALID_PURPOSE 278 #define SSL_R_INVALID_TRUST 279 +#define SSL_R_KRB5 1104 #define SSL_R_KRB5_C_CC_PRINC 1094 #define SSL_R_KRB5_C_GET_CRED 1095 #define SSL_R_KRB5_C_INIT 1096 #define SSL_R_KRB5_C_MK_REQ 1097 #define SSL_R_KRB5_S_BAD_TICKET 1098 #define SSL_R_KRB5_S_INIT 1099 -#define SSL_R_KRB5_S_RD_REQ 1100 +#define SSL_R_KRB5_S_RD_REQ 1108 +#define SSL_R_KRB5_S_TKT_EXPIRED 1105 +#define SSL_R_KRB5_S_TKT_NYV 1106 +#define SSL_R_KRB5_S_TKT_SKEW 1107 #define SSL_R_LENGTH_MISMATCH 159 #define SSL_R_LENGTH_TOO_SHORT 160 #define SSL_R_LIBRARY_BUG 274 diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c index 481481b666..26410b9b2a 100644 --- a/ssl/ssl_err.c +++ b/ssl/ssl_err.c @@ -273,13 +273,17 @@ static ERR_STRING_DATA SSL_str_reasons[]= {SSL_R_INVALID_COMMAND ,"invalid command"}, {SSL_R_INVALID_PURPOSE ,"invalid purpose"}, {SSL_R_INVALID_TRUST ,"invalid trust"}, -{SSL_R_KRB5_C_CC_PRINC ,"krb5 c cc princ"}, -{SSL_R_KRB5_C_GET_CRED ,"krb5 c get cred"}, -{SSL_R_KRB5_C_INIT ,"krb5 c init"}, -{SSL_R_KRB5_C_MK_REQ ,"krb5 c mk req"}, -{SSL_R_KRB5_S_BAD_TICKET ,"krb5 s bad ticket"}, -{SSL_R_KRB5_S_INIT ,"krb5 s init"}, -{SSL_R_KRB5_S_RD_REQ ,"krb5 s rd req"}, +{SSL_R_KRB5 ,"krb5"}, +{SSL_R_KRB5_C_CC_PRINC ,"krb5 client cc principal (no tkt?)"}, +{SSL_R_KRB5_C_GET_CRED ,"krb5 client get cred"}, +{SSL_R_KRB5_C_INIT ,"krb5 client init"}, +{SSL_R_KRB5_C_MK_REQ ,"krb5 client mk_req (expired tkt?)"}, +{SSL_R_KRB5_S_BAD_TICKET ,"krb5 server bad ticket"}, +{SSL_R_KRB5_S_INIT ,"krb5 server init"}, +{SSL_R_KRB5_S_RD_REQ ,"krb5 server rd_req (keytab perms?)"}, +{SSL_R_KRB5_S_TKT_EXPIRED ,"krb5 server tkt expired"}, +{SSL_R_KRB5_S_TKT_NYV ,"krb5 server tkt not yet valid"}, +{SSL_R_KRB5_S_TKT_SKEW ,"krb5 server tkt skew"}, {SSL_R_LENGTH_MISMATCH ,"length mismatch"}, {SSL_R_LENGTH_TOO_SHORT ,"length too short"}, {SSL_R_LIBRARY_BUG ,"library bug"}, |