aboutsummaryrefslogtreecommitdiffstats
path: root/ssl/s3_srvr.c
diff options
context:
space:
mode:
Diffstat (limited to 'ssl/s3_srvr.c')
-rw-r--r--ssl/s3_srvr.c113
1 files changed, 92 insertions, 21 deletions
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;
}