diff options
author | Richard Levitte <levitte@openssl.org> | 2001-07-09 21:46:58 +0000 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2001-07-09 21:46:58 +0000 |
commit | 2a1ef754358e35c8e86df903e0a2f92c35a550d0 (patch) | |
tree | 6ac406a5043c584c2ce0912d35192c3c30376f67 /ssl/s3_clnt.c | |
parent | c148d7097811c18f277a8559753c770f4ff85771 (diff) |
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.
Diffstat (limited to 'ssl/s3_clnt.c')
-rw-r--r-- | ssl/s3_clnt.c | 146 |
1 files changed, 102 insertions, 44 deletions
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 |