PR: 2739
[openssl.git] / ssl / t1_lib.c
index 01e8fc9c6802afb7d87bbd01ad412d604aa3a99e..57d1107e4034564e22d71c73cd3125d14143efc4 100644 (file)
@@ -432,25 +432,29 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *p, unsigned cha
         }
 
 #ifndef OPENSSL_NO_SRP
-#define MIN(x,y) (((x)<(y))?(x):(y))
-       /* we add SRP username the first time only if we have one! */
+       /* Add SRP username if there is one */
        if (s->srp_ctx.login != NULL)
-               {/* Add TLS extension SRP username to the Client Hello message */
-               int login_len = MIN(strlen(s->srp_ctx.login) + 1, 255);
-               long lenmax; 
+               { /* Add TLS extension SRP username to the Client Hello message */
 
-               if ((lenmax = limit - ret - 5) < 0) return NULL; 
-               if (login_len > lenmax) return NULL;
-               if (login_len > 255)
+               int login_len = strlen(s->srp_ctx.login);       
+               if (login_len > 255 || login_len == 0)
                        {
                        SSLerr(SSL_F_SSL_ADD_CLIENTHELLO_TLSEXT, ERR_R_INTERNAL_ERROR);
                        return NULL;
-                       }
+                       } 
+
+               /* check for enough space.
+                  4 for the srp type type and entension length
+                  1 for the srp user identity
+                  + srp user identity length 
+               */
+               if ((limit - ret - 5 - login_len) < 0) return NULL; 
+
+               /* fill in the extension */
                s2n(TLSEXT_TYPE_srp,ret);
                s2n(login_len+1,ret);
-
-               (*ret++) = (unsigned char) MIN(strlen(s->srp_ctx.login), 254);
-               memcpy(ret, s->srp_ctx.login, MIN(strlen(s->srp_ctx.login), 254));
+               (*ret++) = (unsigned char) login_len;
+               memcpy(ret, s->srp_ctx.login, login_len);
                ret+=login_len;
                }
 #endif
@@ -812,17 +816,21 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *p, unsigned cha
                }
 
 #ifndef OPENSSL_NO_HEARTBEATS
-       /* Add Heartbeat extension */
-       s2n(TLSEXT_TYPE_heartbeat,ret);
-       s2n(1,ret);
-       /* Set mode:
-        * 1: peer may send requests
-        * 2: peer not allowed to send requests
-        */
-       if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS)
-               *(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
-       else
-               *(ret++) = SSL_TLSEXT_HB_ENABLED;
+       /* Add Heartbeat extension if we've received one */
+       if (s->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED)
+               {
+               s2n(TLSEXT_TYPE_heartbeat,ret);
+               s2n(1,ret);
+               /* Set mode:
+                * 1: peer may send requests
+                * 2: peer not allowed to send requests
+                */
+               if (s->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_RECV_REQUESTS)
+                       *(ret++) = SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
+               else
+                       *(ret++) = SSL_TLSEXT_HB_ENABLED;
+
+               }
 #endif
 
 #ifndef OPENSSL_NO_NEXTPROTONEG
@@ -1003,13 +1011,25 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
 #ifndef OPENSSL_NO_SRP
                else if (type == TLSEXT_TYPE_srp)
                        {
-                       if (size > 0)
+                       if (size <= 0 || ((len = data[0])) != (size -1))
                                {
-                               len = data[0];
-                               if ((s->srp_ctx.login = OPENSSL_malloc(len+1)) == NULL)
-                                       return -1;
-                               memcpy(s->srp_ctx.login, &data[1], len);
-                               s->srp_ctx.login[len]='\0';  
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
+                               }
+                       if (s->srp_ctx.login != NULL)
+                               {
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
+                               }
+                       if ((s->srp_ctx.login = OPENSSL_malloc(len+1)) == NULL)
+                               return -1;
+                       memcpy(s->srp_ctx.login, &data[1], len);
+                       s->srp_ctx.login[len]='\0';
+  
+                       if (strlen(s->srp_ctx.login) != len) 
+                               {
+                               *al = SSL_AD_DECODE_ERROR;
+                               return 0;
                                }
                        }
 #endif
@@ -1244,6 +1264,12 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                                sdata = data;
                                if (dsize > 0)
                                        {
+                                       if (s->tlsext_ocsp_exts)
+                                               {
+                                               sk_X509_EXTENSION_pop_free(s->tlsext_ocsp_exts,
+                                                                          X509_EXTENSION_free);
+                                               }
+
                                        s->tlsext_ocsp_exts =
                                                d2i_X509_EXTENSIONS(NULL,
                                                        &sdata, dsize);
@@ -1273,6 +1299,8 @@ int ssl_parse_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                                                        s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
                                                        s->tlsext_heartbeat |= SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
                                                        break;
+                               default:        *al = SSL_AD_ILLEGAL_PARAMETER;
+                                                       return 0;
                                }
                        }
 #endif
@@ -1544,6 +1572,8 @@ int ssl_parse_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char *d, in
                                                        s->tlsext_heartbeat |= SSL_TLSEXT_HB_ENABLED;
                                                        s->tlsext_heartbeat |= SSL_TLSEXT_HB_DONT_SEND_REQUESTS;
                                                        break;
+                               default:        *al = SSL_AD_ILLEGAL_PARAMETER;
+                                                       return 0;
                                }
                        }
 #endif
@@ -2231,7 +2261,7 @@ static tls12_lookup tls12_sig[] = {
 #ifndef OPENSSL_NO_RSA
        {EVP_PKEY_RSA, TLSEXT_signature_rsa},
 #endif
-#ifndef OPENSSL_NO_RSA
+#ifndef OPENSSL_NO_DSA
        {EVP_PKEY_DSA, TLSEXT_signature_dsa},
 #endif
 #ifndef OPENSSL_NO_ECDSA
@@ -2265,6 +2295,8 @@ static int tls12_find_nid(int id, tls12_lookup *table, size_t tlen)
 int tls12_get_sigandhash(unsigned char *p, const EVP_PKEY *pk, const EVP_MD *md)
        {
        int sig_id, md_id;
+       if (!md)
+               return 0;
        md_id = tls12_find_id(EVP_MD_type(md), tls12_md,
                                sizeof(tls12_md)/sizeof(tls12_lookup));
        if (md_id == -1)
@@ -2435,7 +2467,10 @@ tls1_process_heartbeat(SSL *s)
                *bp++ = TLS1_HB_RESPONSE;
                s2n(payload, bp);
                memcpy(bp, pl, payload);
-               
+               bp += payload;
+               /* Random padding */
+               RAND_pseudo_bytes(bp, padding);
+
                r = ssl3_write_bytes(s, TLS1_RT_HEARTBEAT, buffer, 3 + payload + padding);
 
                if (r >= 0 && s->msg_callback)