Add DTLS support.
[openssl.git] / ssl / s3_srvr.c
index ca39d6b1c8e97374f0749ef8a58fb870095e05a0..ff2fd3082196cd9ca32257b5ad6e7de00eea96ab 100644 (file)
@@ -56,7 +56,7 @@
  * [including the GNU Public Licence.]
  */
 /* ====================================================================
- * Copyright (c) 1998-2003 The OpenSSL Project.  All rights reserved.
+ * Copyright (c) 1998-2005 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
 #include <openssl/objects.h>
 #include <openssl/evp.h>
 #include <openssl/x509.h>
+#include <openssl/dh.h>
+#include <openssl/bn.h>
+#ifndef OPENSSL_NO_KRB5
 #include <openssl/krb5_asn.h>
+#endif
 #include <openssl/md5.h>
-#include "cryptlib.h"
 
 static SSL_METHOD *ssl3_get_server_method(int ver);
-static int ssl3_get_client_hello(SSL *s);
-static int ssl3_check_client_hello(SSL *s);
-static int ssl3_send_server_hello(SSL *s);
-static int ssl3_send_server_key_exchange(SSL *s);
-static int ssl3_send_certificate_request(SSL *s);
-static int ssl3_send_server_done(SSL *s);
-static int ssl3_get_client_key_exchange(SSL *s);
-static int ssl3_get_client_certificate(SSL *s);
-static int ssl3_get_cert_verify(SSL *s);
-static int ssl3_send_hello_request(SSL *s);
 
 #ifndef OPENSSL_NO_ECDH
 static int nid2curve_id(int nid);
@@ -626,7 +619,7 @@ end:
        return(ret);
        }
 
-static int ssl3_send_hello_request(SSL *s)
+int ssl3_send_hello_request(SSL *s)
        {
        unsigned char *p;
 
@@ -648,14 +641,14 @@ static int ssl3_send_hello_request(SSL *s)
        return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
        }
 
-static int ssl3_check_client_hello(SSL *s)
+int ssl3_check_client_hello(SSL *s)
        {
        int ok;
        long n;
 
        /* this function is called when we really expect a Certificate message,
         * so permit appropriate message length */
-       n=ssl3_get_message(s,
+       n=s->method->ssl_get_message(s,
                SSL3_ST_SR_CERT_A,
                SSL3_ST_SR_CERT_B,
                -1,
@@ -681,9 +674,10 @@ static int ssl3_check_client_hello(SSL *s)
        return 1;
 }
 
-static int ssl3_get_client_hello(SSL *s)
+int ssl3_get_client_hello(SSL *s)
        {
        int i,j,ok,al,ret= -1;
+       int cookie_len;
        long n;
        unsigned long id;
        unsigned char *p,*d,*q;
@@ -702,7 +696,7 @@ static int ssl3_get_client_hello(SSL *s)
                s->first_packet=1;
                s->state=SSL3_ST_SR_CLNT_HELLO_B;
                }
-       n=ssl3_get_message(s,
+       n=s->method->ssl_get_message(s,
                SSL3_ST_SR_CLNT_HELLO_B,
                SSL3_ST_SR_CLNT_HELLO_C,
                SSL3_MT_CLIENT_HELLO,
@@ -767,6 +761,68 @@ static int ssl3_get_client_hello(SSL *s)
                }
 
        p+=j;
+
+       if (SSL_version(s) == DTLS1_VERSION)
+               {
+               /* cookie stuff */
+               cookie_len = *(p++);
+
+        if ( (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) &&
+            s->d1->send_cookie == 0)
+            {
+            /* HelloVerifyMessage has already been sent */
+            if ( cookie_len != s->d1->cookie_len)
+                {
+                al = SSL_AD_HANDSHAKE_FAILURE;
+                SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
+                goto f_err;
+                }
+            }
+
+        /* 
+         * The ClientHello may contain a cookie even if the
+         * HelloVerify message has not been sent--make sure that it
+         * does not cause an overflow.
+         */
+               if ( cookie_len > sizeof(s->d1->rcvd_cookie))
+                       {
+                       /* too much data */
+            al = SSL_AD_DECODE_ERROR;
+                       SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, SSL_R_COOKIE_MISMATCH);
+                       goto f_err;
+                       }
+
+        /* verify the cookie if appropriate option is set. */
+        if ( (SSL_get_options(s) & SSL_OP_COOKIE_EXCHANGE) &&
+            cookie_len > 0)
+            {
+            memcpy(s->d1->rcvd_cookie, p, cookie_len);
+
+            if ( s->ctx->app_verify_cookie_cb != NULL)
+                {
+                if ( s->ctx->app_verify_cookie_cb(s, s->d1->rcvd_cookie,
+                    cookie_len) == 0)
+                    {
+                    al=SSL_AD_HANDSHAKE_FAILURE;
+                    SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, 
+                        SSL_R_COOKIE_MISMATCH);
+                    goto f_err;
+                    }
+                /* else cookie verification succeeded */
+                }
+            else if ( memcmp(s->d1->rcvd_cookie, s->d1->cookie, 
+                          s->d1->cookie_len) != 0) /* default verification */
+                {
+                    al=SSL_AD_HANDSHAKE_FAILURE;
+                    SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO, 
+                        SSL_R_COOKIE_MISMATCH);
+                    goto f_err;
+                }
+            }
+
+        p += cookie_len;
+               }
+
        n2s(p,i);
        if ((i == 0) && (j != 0))
                {
@@ -980,7 +1036,7 @@ err:
        return(ret);
        }
 
-static int ssl3_send_server_hello(SSL *s)
+int ssl3_send_server_hello(SSL *s)
        {
        unsigned char *buf;
        unsigned char *p,*d;
@@ -993,7 +1049,7 @@ static int ssl3_send_server_hello(SSL *s)
                p=s->s3->server_random;
                Time=time(NULL);                        /* Time */
                l2n(Time,p);
-               RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-sizeof(Time));
+               RAND_pseudo_bytes(p,SSL3_RANDOM_SIZE-4);
                /* Do the message type and length last */
                d=p= &(buf[4]);
 
@@ -1016,7 +1072,7 @@ static int ssl3_send_server_hello(SSL *s)
                        s->session->session_id_length=0;
 
                sl=s->session->session_id_length;
-               if (sl > sizeof s->session->session_id)
+               if (sl > (int)sizeof(s->session->session_id))
                        {
                        SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO, ERR_R_INTERNAL_ERROR);
                        return -1;
@@ -1051,7 +1107,7 @@ static int ssl3_send_server_hello(SSL *s)
        return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
        }
 
-static int ssl3_send_server_done(SSL *s)
+int ssl3_send_server_done(SSL *s)
        {
        unsigned char *p;
 
@@ -1075,7 +1131,7 @@ static int ssl3_send_server_done(SSL *s)
        return(ssl3_do_write(s,SSL3_RT_HANDSHAKE));
        }
 
-static int ssl3_send_server_key_exchange(SSL *s)
+int ssl3_send_server_key_exchange(SSL *s)
        {
 #ifndef OPENSSL_NO_RSA
        unsigned char *q;
@@ -1494,7 +1550,7 @@ err:
        return(-1);
        }
 
-static int ssl3_send_certificate_request(SSL *s)
+int ssl3_send_certificate_request(SSL *s)
        {
        unsigned char *p,*d;
        int i,j,nl,off,n;
@@ -1574,6 +1630,7 @@ static int ssl3_send_certificate_request(SSL *s)
                s->init_num += 4;
 #endif
 
+               s->state = SSL3_ST_SW_CERT_REQ_B;
                }
 
        /* SSL3_ST_SW_CERT_REQ_B */
@@ -1584,18 +1641,20 @@ err:
 
 
 static const int KDF1_SHA1_len = 20;
-static void *KDF1_SHA1(void *in, size_t inlen, void *out, size_t outlen)
+static void *KDF1_SHA1(const void *in, size_t inlen, void *out, size_t *outlen)
        {
 #ifndef OPENSSL_NO_SHA
-       if (outlen != SHA_DIGEST_LENGTH)
+       if (*outlen < SHA_DIGEST_LENGTH)
                return NULL;
+       else
+               *outlen = SHA_DIGEST_LENGTH;
        return SHA1(in, inlen, out);
 #else
        return NULL;
 #endif
        }
 
-static int ssl3_get_client_key_exchange(SSL *s)
+int ssl3_get_client_key_exchange(SSL *s)
        {
        int i,al,ok;
        long n;
@@ -1620,7 +1679,7 @@ static int ssl3_get_client_key_exchange(SSL *s)
        BN_CTX *bn_ctx = NULL; 
 #endif
 
-       n=ssl3_get_message(s,
+       n=s->method->ssl_get_message(s,
                SSL3_ST_SR_KEY_EXCH_A,
                SSL3_ST_SR_KEY_EXCH_B,
                SSL3_MT_CLIENT_KEY_EXCHANGE,
@@ -1846,8 +1905,8 @@ static int ssl3_get_client_key_exchange(SSL *s)
                        goto err;
                        }
 
-               if (n != enc_ticket.length + authenticator.length +
-                                               enc_pms.length + 6)
+               if (n != (long)(enc_ticket.length + authenticator.length +
+                                               enc_pms.length + 6))
                        {
                        SSLerr(SSL_F_SSL3_GET_CLIENT_KEY_EXCHANGE,
                                SSL_R_DATA_LENGTH_TOO_LONG);
@@ -2132,7 +2191,7 @@ err:
        return(-1);
        }
 
-static int ssl3_get_cert_verify(SSL *s)
+int ssl3_get_cert_verify(SSL *s)
        {
        EVP_PKEY *pkey=NULL;
        unsigned char *p;
@@ -2141,7 +2200,7 @@ static int ssl3_get_cert_verify(SSL *s)
        int type=0,i,j;
        X509 *peer;
 
-       n=ssl3_get_message(s,
+       n=s->method->ssl_get_message(s,
                SSL3_ST_SR_CERT_VRFY_A,
                SSL3_ST_SR_CERT_VRFY_B,
                -1,
@@ -2287,15 +2346,16 @@ end:
        return(ret);
        }
 
-static int ssl3_get_client_certificate(SSL *s)
+int ssl3_get_client_certificate(SSL *s)
        {
        int i,ok,al,ret= -1;
        X509 *x=NULL;
        unsigned long l,nc,llen,n;
-       unsigned char *p,*d,*q;
+       const unsigned char *p,*q;
+       unsigned char *d;
        STACK_OF(X509) *sk=NULL;
 
-       n=ssl3_get_message(s,
+       n=s->method->ssl_get_message(s,
                SSL3_ST_SR_CERT_A,
                SSL3_ST_SR_CERT_B,
                -1,
@@ -2330,7 +2390,7 @@ static int ssl3_get_client_certificate(SSL *s)
                SSLerr(SSL_F_SSL3_GET_CLIENT_CERTIFICATE,SSL_R_WRONG_MESSAGE_TYPE);
                goto f_err;
                }
-       d=p=(unsigned char *)s->init_msg;
+       p=d=(unsigned char *)s->init_msg;
 
        if ((sk=sk_X509_new_null()) == NULL)
                {