Support TLS extensions (specifically, HostName)
Submitted by: Peter Sylvester
This commit is contained in:
@@ -349,6 +349,10 @@ static int ssl23_client_hello(SSL *s)
|
||||
p+=i;
|
||||
|
||||
/* COMPRESSION */
|
||||
#ifdef OPENSSL_NO_COMP
|
||||
*(p++)=1;
|
||||
#else
|
||||
|
||||
if ((s->options & SSL_OP_NO_COMPRESSION)
|
||||
|| !s->ctx->comp_methods)
|
||||
j=0;
|
||||
@@ -360,7 +364,15 @@ static int ssl23_client_hello(SSL *s)
|
||||
comp=sk_SSL_COMP_value(s->ctx->comp_methods,i);
|
||||
*(p++)=comp->id;
|
||||
}
|
||||
#endif
|
||||
*(p++)=0; /* Add the NULL method */
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
if ((p = ssl_add_ClientHello_TLS_extensions(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
|
||||
{
|
||||
SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
l = p-d;
|
||||
*p = 42;
|
||||
|
||||
@@ -140,7 +140,7 @@ IMPLEMENT_ssl23_meth_func(SSLv23_server_method,
|
||||
int ssl23_accept(SSL *s)
|
||||
{
|
||||
BUF_MEM *buf;
|
||||
unsigned long Time=(unsigned long)time(NULL);
|
||||
unsigned long Time=time(NULL);
|
||||
void (*cb)(const SSL *ssl,int type,int val)=NULL;
|
||||
int ret= -1;
|
||||
int new_state,state;
|
||||
@@ -416,7 +416,7 @@ int ssl23_get_client_hello(SSL *s)
|
||||
n2s(p,sil);
|
||||
n2s(p,cl);
|
||||
d=(unsigned char *)s->init_buf->data;
|
||||
if ((csl+sil+cl+11) != s->packet_length)
|
||||
if ((csl+sil+cl+11) > s->packet_length)
|
||||
{
|
||||
SSLerr(SSL_F_SSL23_GET_CLIENT_HELLO,SSL_R_RECORD_LENGTH_MISMATCH);
|
||||
goto err;
|
||||
@@ -459,6 +459,12 @@ int ssl23_get_client_hello(SSL *s)
|
||||
*(d++)=1;
|
||||
*(d++)=0;
|
||||
|
||||
/* copy any remaining data with may be extensions */
|
||||
p = p+csl+sil+cl ;
|
||||
while (p < s->packet+s->packet_length) {
|
||||
*(d++)=*(p++);
|
||||
}
|
||||
|
||||
i = (d-(unsigned char *)s->init_buf->data) - 4;
|
||||
l2n3((long)i, d_len);
|
||||
|
||||
|
||||
@@ -255,6 +255,16 @@ int ssl3_connect(SSL *s)
|
||||
case SSL3_ST_CR_SRVR_HELLO_B:
|
||||
ret=ssl3_get_server_hello(s);
|
||||
if (ret <= 0) goto end;
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
{
|
||||
int extension_error = 0,al;
|
||||
if ((al = ssl_check_Hello_TLS_extensions(s,&extension_error)) != SSL_ERROR_NONE){
|
||||
ret = -1;
|
||||
SSLerr(SSL_F_SSL3_CONNECT,SSL_R_SERVERHELLO_TLS_EXT);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (s->hit)
|
||||
s->state=SSL3_ST_CR_FINISHED_A;
|
||||
else
|
||||
@@ -602,6 +612,13 @@ int ssl3_client_hello(SSL *s)
|
||||
}
|
||||
#endif
|
||||
*(p++)=0; /* Add the NULL method */
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
if ((p = ssl_add_ClientHello_TLS_extensions(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
|
||||
{
|
||||
SSLerr(SSL_F_SSL3_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
l=(p-d);
|
||||
d=buf;
|
||||
@@ -786,6 +803,16 @@ int ssl3_get_server_hello(SSL *s)
|
||||
s->s3->tmp.new_compression=comp;
|
||||
}
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
/* TLS extensions*/
|
||||
if (s->version > SSL3_VERSION)
|
||||
{
|
||||
if ((al = ssl_parse_ServerHello_TLS_extensions(s,&p,d,n)) != SSL_ERROR_NONE){
|
||||
SSLerr(SSL_F_SSL3_GET_SERVER_HELLO,SSL_R_PARSE_TLS_EXT);
|
||||
goto f_err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (p != (d+n))
|
||||
{
|
||||
|
||||
47
ssl/s3_lib.c
47
ssl/s3_lib.c
@@ -1643,6 +1643,43 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
|
||||
}
|
||||
break;
|
||||
#endif /* !OPENSSL_NO_ECDH */
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
case SSL_CTRL_GET_TLSEXT_HOSTNAME:
|
||||
if (larg != TLSEXT_TYPE_SERVER_host)
|
||||
{
|
||||
SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE);
|
||||
return(0);
|
||||
}
|
||||
*((char **) parg) = s->session&&s->session->tlsext_hostname?s->session->tlsext_hostname:s->tlsext_hostname;
|
||||
ret = 1;
|
||||
break;
|
||||
case SSL_CTRL_SET_TLSEXT_HOSTNAME:
|
||||
if (larg == TLSEXT_TYPE_SERVER_host) {
|
||||
if (s->tlsext_hostname != NULL)
|
||||
OPENSSL_free(s->tlsext_hostname);
|
||||
s->tlsext_hostname = NULL;
|
||||
|
||||
ret = 1;
|
||||
if (parg == NULL)
|
||||
break;
|
||||
if (strlen((char *)parg) > 255) {
|
||||
SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME);
|
||||
return 0;
|
||||
}
|
||||
if ((s->tlsext_hostname = BUF_strdup((char *)parg)) == NULL) {
|
||||
SSLerr(SSL_F_SSL3_CTRL, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE);
|
||||
return 0;
|
||||
}
|
||||
s->options |= SSL_OP_NO_SSLv2;
|
||||
break;
|
||||
case SSL_CTRL_SET_TLSEXT_SERVERNAME_DONE:
|
||||
s->servername_done = larg;
|
||||
break;
|
||||
#endif /* !OPENSSL_NO_TLSEXT */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -1827,6 +1864,11 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
|
||||
}
|
||||
break;
|
||||
#endif /* !OPENSSL_NO_ECDH */
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG:
|
||||
ctx->tlsext_servername_arg=parg;
|
||||
break;
|
||||
#endif /* !OPENSSL_NO_TLSEXT */
|
||||
/* A Thawte special :-) */
|
||||
case SSL_CTRL_EXTRA_CHAIN_CERT:
|
||||
if (ctx->extra_certs == NULL)
|
||||
@@ -1871,6 +1913,11 @@ long ssl3_ctx_callback_ctrl(SSL_CTX *ctx, int cmd, void (*fp)(void))
|
||||
cert->ecdh_tmp_cb = (EC_KEY *(*)(SSL *, int, int))fp;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
case SSL_CTRL_SET_TLSEXT_SERVERNAME_CB:
|
||||
ctx->tlsext_servername_callback=(int (*)(SSL *,int *,void *))fp;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return(0);
|
||||
|
||||
@@ -281,6 +281,17 @@ int ssl3_accept(SSL *s)
|
||||
s->shutdown=0;
|
||||
ret=ssl3_get_client_hello(s);
|
||||
if (ret <= 0) goto end;
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
{
|
||||
int extension_error = 0,al;
|
||||
if ((al = ssl_check_Hello_TLS_extensions(s,&extension_error)) != SSL_ERROR_NONE){
|
||||
ret = -1;
|
||||
SSLerr(SSL_F_SSL3_ACCEPT,SSL_R_CLIENTHELLO_TLS_EXT);
|
||||
ssl3_send_alert(s,al,extension_error);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
s->new_session = 2;
|
||||
s->state=SSL3_ST_SW_SRVR_HELLO_A;
|
||||
s->init_num=0;
|
||||
@@ -942,6 +953,17 @@ int ssl3_get_client_hello(SSL *s)
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
/* TLS extensions*/
|
||||
if (s->version > SSL3_VERSION)
|
||||
{
|
||||
if ((al = ssl_parse_ClientHello_TLS_extensions(s,&p,d,n)) != SSL_ERROR_NONE){
|
||||
SSLerr(SSL_F_SSL3_GET_CLIENT_HELLO,SSL_R_PARSE_TLS_EXT);
|
||||
ssl3_send_alert(s,SSL3_AL_WARNING,al);
|
||||
return (ret = al);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Given s->session->ciphers and SSL_get_ciphers, we must
|
||||
* pick a cipher */
|
||||
@@ -1086,6 +1108,13 @@ int ssl3_send_server_hello(SSL *s)
|
||||
else
|
||||
*(p++)=s->s3->tmp.new_compression->id;
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
if ((p = ssl_add_ServerHello_TLS_extensions(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
|
||||
{
|
||||
SSLerr(SSL_F_SSL3_SEND_SERVER_HELLO,ERR_R_INTERNAL_ERROR);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* do the header */
|
||||
l=(p-d);
|
||||
|
||||
32
ssl/ssl.h
32
ssl/ssl.h
@@ -172,6 +172,11 @@
|
||||
|
||||
#include <openssl/e_os2.h>
|
||||
|
||||
#ifdef OPENSSL_NO_TLS1
|
||||
# ifndef OPENSSL_NO_TLSEXT
|
||||
# define OPENSSL_NO_TLSEXT
|
||||
# endif
|
||||
#endif
|
||||
#ifndef OPENSSL_NO_COMP
|
||||
#include <openssl/comp.h>
|
||||
#endif
|
||||
@@ -439,6 +444,9 @@ typedef struct ssl_session_st
|
||||
unsigned int krb5_client_princ_len;
|
||||
unsigned char krb5_client_princ[SSL_MAX_KRB5_PRINCIPAL_LENGTH];
|
||||
#endif /* OPENSSL_NO_KRB5 */
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
char *tlsext_hostname;
|
||||
#endif
|
||||
|
||||
int not_resumable;
|
||||
|
||||
@@ -755,6 +763,13 @@ struct ssl_ctx_st
|
||||
* padding and MAC overheads.
|
||||
*/
|
||||
unsigned int max_send_fragment;
|
||||
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
/* TLS extensions servername callback */
|
||||
int (*tlsext_servername_callback)(SSL*, int *, void *);
|
||||
void *tlsext_servername_arg;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#define SSL_SESS_CACHE_OFF 0x0000
|
||||
@@ -977,6 +992,14 @@ struct ssl_st
|
||||
int client_version; /* what was passed, used for
|
||||
* SSLv3/TLS rollback check */
|
||||
unsigned int max_send_fragment;
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
char *tlsext_hostname;
|
||||
int servername_done; /* no further mod of servername
|
||||
0 : call the servername extension callback.
|
||||
1 : prepare 2, allow last ack just after in server callback.
|
||||
2 : don't call servername callback, no ack in server hello
|
||||
*/
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -1122,6 +1145,9 @@ size_t SSL_get_peer_finished(const SSL *s, void *buf, size_t count);
|
||||
#define SSL_AD_INTERNAL_ERROR TLS1_AD_INTERNAL_ERROR /* fatal */
|
||||
#define SSL_AD_USER_CANCELLED TLS1_AD_USER_CANCELLED
|
||||
#define SSL_AD_NO_RENEGOTIATION TLS1_AD_NO_RENEGOTIATION
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
#define SSL_AD_UNRECOGNIZED_NAME TLS1_AD_UNRECOGNIZED_NAME
|
||||
#endif
|
||||
|
||||
#define SSL_ERROR_NONE 0
|
||||
#define SSL_ERROR_SSL 1
|
||||
@@ -1454,6 +1480,7 @@ int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile,
|
||||
SSL_SESSION *SSL_get_session(const SSL *ssl);
|
||||
SSL_SESSION *SSL_get1_session(SSL *ssl); /* obtain a reference count */
|
||||
SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl);
|
||||
SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx);
|
||||
void SSL_set_info_callback(SSL *ssl,
|
||||
void (*cb)(const SSL *ssl,int type,int val));
|
||||
void (*SSL_get_info_callback(const SSL *ssl))(const SSL *ssl,int type,int val);
|
||||
@@ -1777,6 +1804,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_R_CIPHER_CODE_WRONG_LENGTH 137
|
||||
#define SSL_R_CIPHER_OR_HASH_UNAVAILABLE 138
|
||||
#define SSL_R_CIPHER_TABLE_SRC_ERROR 139
|
||||
#define SSL_R_CLIENTHELLO_TLS_EXT 2003
|
||||
#define SSL_R_COMPRESSED_LENGTH_TOO_LONG 140
|
||||
#define SSL_R_COMPRESSION_FAILURE 141
|
||||
#define SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE 1120
|
||||
@@ -1861,6 +1889,7 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_R_NULL_SSL_METHOD_PASSED 196
|
||||
#define SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED 197
|
||||
#define SSL_R_PACKET_LENGTH_TOO_LONG 198
|
||||
#define SSL_R_PARSE_TLS_EXT 2004
|
||||
#define SSL_R_PATH_TOO_LONG 270
|
||||
#define SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE 199
|
||||
#define SSL_R_PEER_ERROR 200
|
||||
@@ -1884,11 +1913,14 @@ void ERR_load_SSL_strings(void);
|
||||
#define SSL_R_REUSE_CERT_LENGTH_NOT_ZERO 216
|
||||
#define SSL_R_REUSE_CERT_TYPE_NOT_ZERO 217
|
||||
#define SSL_R_REUSE_CIPHER_LIST_NOT_ZERO 218
|
||||
#define SSL_R_SERVERHELLO_TLS_EXT 2005
|
||||
#define SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED 277
|
||||
#define SSL_R_SHORT_READ 219
|
||||
#define SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE 220
|
||||
#define SSL_R_SSL23_DOING_SESSION_ID_REUSE 221
|
||||
#define SSL_R_SSL2_CONNECTION_ID_TOO_LONG 1114
|
||||
#define SSL_R_SSL3_EXT_INVALID_SERVERNAME 2006
|
||||
#define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 2007
|
||||
#define SSL_R_SSL3_SESSION_ID_TOO_LONG 1113
|
||||
#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 222
|
||||
#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042
|
||||
|
||||
@@ -78,12 +78,15 @@ typedef struct ssl_session_asn1_st
|
||||
ASN1_INTEGER time;
|
||||
ASN1_INTEGER timeout;
|
||||
ASN1_INTEGER verify_result;
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
ASN1_OCTET_STRING tlsext_hostname;
|
||||
#endif /* OPENSSL_NO_TLSEXT */
|
||||
} SSL_SESSION_ASN1;
|
||||
|
||||
int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
|
||||
{
|
||||
#define LSIZE2 (sizeof(long)*2)
|
||||
int v1=0,v2=0,v3=0,v4=0,v5=0;
|
||||
int v1=0,v2=0,v3=0,v4=0,v5=0,v6=0;
|
||||
unsigned char buf[4],ibuf1[LSIZE2],ibuf2[LSIZE2];
|
||||
unsigned char ibuf3[LSIZE2],ibuf4[LSIZE2],ibuf5[LSIZE2];
|
||||
long l;
|
||||
@@ -178,6 +181,14 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
|
||||
ASN1_INTEGER_set(&a.verify_result,in->verify_result);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
if (in->tlsext_hostname)
|
||||
{
|
||||
a.tlsext_hostname.length=strlen(in->tlsext_hostname);
|
||||
a.tlsext_hostname.type=V_ASN1_OCTET_STRING;
|
||||
a.tlsext_hostname.data=in->tlsext_hostname;
|
||||
}
|
||||
#endif /* OPENSSL_NO_TLSEXT */
|
||||
|
||||
M_ASN1_I2D_len(&(a.version), i2d_ASN1_INTEGER);
|
||||
M_ASN1_I2D_len(&(a.ssl_version), i2d_ASN1_INTEGER);
|
||||
@@ -200,6 +211,10 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
|
||||
if (in->verify_result != X509_V_OK)
|
||||
M_ASN1_I2D_len_EXP_opt(&(a.verify_result),i2d_ASN1_INTEGER,5,v5);
|
||||
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
if (in->tlsext_hostname)
|
||||
M_ASN1_I2D_len_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6);
|
||||
#endif /* OPENSSL_NO_TLSEXT */
|
||||
M_ASN1_I2D_seq_total();
|
||||
|
||||
M_ASN1_I2D_put(&(a.version), i2d_ASN1_INTEGER);
|
||||
@@ -223,6 +238,10 @@ int i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp)
|
||||
v4);
|
||||
if (in->verify_result != X509_V_OK)
|
||||
M_ASN1_I2D_put_EXP_opt(&a.verify_result,i2d_ASN1_INTEGER,5,v5);
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
if (in->tlsext_hostname)
|
||||
M_ASN1_I2D_put_EXP_opt(&(a.tlsext_hostname), i2d_ASN1_OCTET_STRING,6,v6);
|
||||
#endif /* OPENSSL_NO_TLSEXT */
|
||||
M_ASN1_I2D_finish();
|
||||
}
|
||||
|
||||
@@ -394,5 +413,21 @@ SSL_SESSION *d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp,
|
||||
else
|
||||
ret->verify_result=X509_V_OK;
|
||||
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
os.length=0;
|
||||
os.data=NULL;
|
||||
M_ASN1_D2I_get_EXP_opt(osp,d2i_ASN1_OCTET_STRING,6);
|
||||
if (os.data)
|
||||
{
|
||||
ret->tlsext_hostname = BUF_strndup(os.data, os.length);
|
||||
OPENSSL_free(os.data);
|
||||
os.data = NULL;
|
||||
os.length = 0;
|
||||
}
|
||||
else
|
||||
ret->tlsext_hostname=NULL;
|
||||
|
||||
#endif /* OPENSSL_NO_TLSEXT */
|
||||
|
||||
M_ASN1_D2I_Finish(a,SSL_SESSION_free,SSL_F_D2I_SSL_SESSION);
|
||||
}
|
||||
|
||||
@@ -292,6 +292,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
|
||||
{ERR_REASON(SSL_R_CIPHER_CODE_WRONG_LENGTH),"cipher code wrong length"},
|
||||
{ERR_REASON(SSL_R_CIPHER_OR_HASH_UNAVAILABLE),"cipher or hash unavailable"},
|
||||
{ERR_REASON(SSL_R_CIPHER_TABLE_SRC_ERROR),"cipher table src error"},
|
||||
{ERR_REASON(SSL_R_CLIENTHELLO_TLS_EXT) ,"clienthello tls ext"},
|
||||
{ERR_REASON(SSL_R_COMPRESSED_LENGTH_TOO_LONG),"compressed length too long"},
|
||||
{ERR_REASON(SSL_R_COMPRESSION_FAILURE) ,"compression failure"},
|
||||
{ERR_REASON(SSL_R_COMPRESSION_ID_NOT_WITHIN_PRIVATE_RANGE),"compression id not within private range"},
|
||||
@@ -376,6 +377,7 @@ static ERR_STRING_DATA SSL_str_reasons[]=
|
||||
{ERR_REASON(SSL_R_NULL_SSL_METHOD_PASSED),"null ssl method passed"},
|
||||
{ERR_REASON(SSL_R_OLD_SESSION_CIPHER_NOT_RETURNED),"old session cipher not returned"},
|
||||
{ERR_REASON(SSL_R_PACKET_LENGTH_TOO_LONG),"packet length too long"},
|
||||
{ERR_REASON(SSL_R_PARSE_TLS_EXT) ,"parse tls ext"},
|
||||
{ERR_REASON(SSL_R_PATH_TOO_LONG) ,"path too long"},
|
||||
{ERR_REASON(SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE),"peer did not return a certificate"},
|
||||
{ERR_REASON(SSL_R_PEER_ERROR) ,"peer error"},
|
||||
@@ -399,11 +401,14 @@ static ERR_STRING_DATA SSL_str_reasons[]=
|
||||
{ERR_REASON(SSL_R_REUSE_CERT_LENGTH_NOT_ZERO),"reuse cert length not zero"},
|
||||
{ERR_REASON(SSL_R_REUSE_CERT_TYPE_NOT_ZERO),"reuse cert type not zero"},
|
||||
{ERR_REASON(SSL_R_REUSE_CIPHER_LIST_NOT_ZERO),"reuse cipher list not zero"},
|
||||
{ERR_REASON(SSL_R_SERVERHELLO_TLS_EXT) ,"serverhello tls ext"},
|
||||
{ERR_REASON(SSL_R_SESSION_ID_CONTEXT_UNINITIALIZED),"session id context uninitialized"},
|
||||
{ERR_REASON(SSL_R_SHORT_READ) ,"short read"},
|
||||
{ERR_REASON(SSL_R_SIGNATURE_FOR_NON_SIGNING_CERTIFICATE),"signature for non signing certificate"},
|
||||
{ERR_REASON(SSL_R_SSL23_DOING_SESSION_ID_REUSE),"ssl23 doing session id reuse"},
|
||||
{ERR_REASON(SSL_R_SSL2_CONNECTION_ID_TOO_LONG),"ssl2 connection id too long"},
|
||||
{ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME),"ssl3 ext invalid servername"},
|
||||
{ERR_REASON(SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE),"ssl3 ext invalid servername type"},
|
||||
{ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_LONG),"ssl3 session id too long"},
|
||||
{ERR_REASON(SSL_R_SSL3_SESSION_ID_TOO_SHORT),"ssl3 session id too short"},
|
||||
{ERR_REASON(SSL_R_SSLV3_ALERT_BAD_CERTIFICATE),"sslv3 alert bad certificate"},
|
||||
|
||||
@@ -1315,6 +1315,27 @@ err:
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_TLSEXT
|
||||
/** return a servername extension value if provided in CLIENT HELLO
|
||||
* or NULL.
|
||||
* For the moment, only hostname types are supported.
|
||||
*/
|
||||
|
||||
const char *SSL_get_servername(const SSL *s, const int type) {
|
||||
|
||||
if (type != TLSEXT_TYPE_SERVER_host)
|
||||
return NULL;
|
||||
return s->session /*&&s->session->tlsext_hostname*/?s->session->tlsext_hostname:s->tlsext_hostname;
|
||||
}
|
||||
|
||||
int SSL_get_servername_type(const SSL *s) {
|
||||
|
||||
if (s->session &&s->session->tlsext_hostname ?s->session->tlsext_hostname:s->tlsext_hostname)
|
||||
return TLSEXT_TYPE_SERVER_host;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
unsigned long SSL_SESSION_hash(const SSL_SESSION *a)
|
||||
{
|
||||
unsigned long l;
|
||||
@@ -1466,6 +1487,10 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
|
||||
|
||||
ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;
|
||||
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
ret->tlsext_servername_callback = NULL;
|
||||
ret->tlsext_servername_arg = NULL;
|
||||
#endif
|
||||
return(ret);
|
||||
err:
|
||||
SSLerr(SSL_F_SSL_CTX_NEW,ERR_R_MALLOC_FAILURE);
|
||||
@@ -2415,6 +2440,19 @@ SSL_CTX *SSL_get_SSL_CTX(const SSL *ssl)
|
||||
return(ssl->ctx);
|
||||
}
|
||||
|
||||
SSL_CTX *SSL_set_SSL_CTX(SSL *ssl, SSL_CTX* ctx)
|
||||
{
|
||||
|
||||
if (ssl->cert != NULL)
|
||||
ssl_cert_free(ssl->cert);
|
||||
ssl->cert = ssl_cert_dup(ctx->cert);
|
||||
CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
|
||||
if (ssl->ctx != NULL)
|
||||
SSL_CTX_free(ssl->ctx); /* decrement reference count */
|
||||
ssl->ctx = ctx;
|
||||
return(ssl->ctx);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_STDIO
|
||||
int SSL_CTX_set_default_verify_paths(SSL_CTX *ctx)
|
||||
{
|
||||
|
||||
@@ -940,5 +940,11 @@ int check_srvr_ecc_cert_and_alg(X509 *x, SSL_CIPHER *cs);
|
||||
|
||||
SSL_COMP *ssl3_comp_find(STACK_OF(SSL_COMP) *sk, int n);
|
||||
|
||||
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
unsigned char *ssl_add_ClientHello_TLS_extensions(SSL *s, unsigned char *p, unsigned char *limit);
|
||||
unsigned char *ssl_add_ServerHello_TLS_extensions(SSL *s, unsigned char *p, unsigned char *limit);
|
||||
int ssl_parse_ClientHello_TLS_extensions(SSL *s, unsigned char **data, unsigned char *d, int n);
|
||||
int ssl_parse_ServerHello_TLS_extensions(SSL *s, unsigned char **data, unsigned char *d, int n);
|
||||
int ssl_check_Hello_TLS_extensions(SSL *s,int *ad);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -122,6 +122,9 @@ SSL_SESSION *SSL_SESSION_new(void)
|
||||
ss->prev=NULL;
|
||||
ss->next=NULL;
|
||||
ss->compress_meth=0;
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
ss->tlsext_hostname = NULL;
|
||||
#endif
|
||||
CRYPTO_new_ex_data(CRYPTO_EX_INDEX_SSL_SESSION, ss, &ss->ex_data);
|
||||
return(ss);
|
||||
}
|
||||
@@ -546,6 +549,10 @@ void SSL_SESSION_free(SSL_SESSION *ss)
|
||||
if (ss->sess_cert != NULL) ssl_sess_cert_free(ss->sess_cert);
|
||||
if (ss->peer != NULL) X509_free(ss->peer);
|
||||
if (ss->ciphers != NULL) sk_SSL_CIPHER_free(ss->ciphers);
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
if (ss->tlsext_hostname != NULL)
|
||||
OPENSSL_free(ss->tlsext_hostname);
|
||||
#endif
|
||||
OPENSSL_cleanse(ss,sizeof(*ss));
|
||||
OPENSSL_free(ss);
|
||||
}
|
||||
|
||||
186
ssl/t1_lib.c
186
ssl/t1_lib.c
@@ -101,14 +101,186 @@ void tls1_clear(SSL *s)
|
||||
s->version=TLS1_VERSION;
|
||||
}
|
||||
|
||||
#if 0
|
||||
long tls1_ctrl(SSL *s, int cmd, long larg, char *parg)
|
||||
{
|
||||
return(0);
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
unsigned char *ssl_add_ClientHello_TLS_extensions(SSL *s, unsigned char *p, unsigned char *limit) {
|
||||
int extdatalen=0;
|
||||
unsigned char *ret = p;
|
||||
|
||||
ret+=2;
|
||||
|
||||
if (ret>=limit) return NULL; /* this really never occurs, but ... */
|
||||
if (s->servername_done == 0 && s->tlsext_hostname != NULL) {
|
||||
/* Add TLS extension servername to the Client Hello message */
|
||||
unsigned long size_str;
|
||||
long lenmax;
|
||||
|
||||
if ((lenmax = limit - p - 7) < 0) return NULL;
|
||||
if ((size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) return NULL;
|
||||
|
||||
s2n(TLSEXT_TYPE_server_name,ret);
|
||||
s2n(size_str+3,ret);
|
||||
*(ret++) = (unsigned char) TLSEXT_TYPE_SERVER_host;
|
||||
s2n(size_str,ret);
|
||||
|
||||
memcpy(ret, s->tlsext_hostname, size_str);
|
||||
ret+=size_str;
|
||||
}
|
||||
|
||||
long tls1_callback_ctrl(SSL *s, int cmd, void *(*fp)())
|
||||
{
|
||||
return(0);
|
||||
|
||||
if ((extdatalen = ret-p-2)== 0)
|
||||
return p;
|
||||
|
||||
s2n(extdatalen,p);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
unsigned char *ssl_add_ServerHello_TLS_extensions(SSL *s, unsigned char *p, unsigned char *limit) {
|
||||
int extdatalen=0;
|
||||
unsigned char *ret = p;
|
||||
if (s->hit || s->servername_done == 2)
|
||||
return p;
|
||||
ret+=2;
|
||||
if (s->servername_done == 1)
|
||||
s->servername_done = 2;
|
||||
|
||||
if (ret>=limit) return NULL; /* this really never occurs, but ... */
|
||||
|
||||
if (s->session->tlsext_hostname != NULL) {
|
||||
|
||||
if (limit - p - 4 < 0) return NULL;
|
||||
|
||||
s2n(TLSEXT_TYPE_server_name,ret);
|
||||
s2n(0,ret);
|
||||
}
|
||||
|
||||
|
||||
if ((extdatalen = ret-p-2)== 0)
|
||||
return p;
|
||||
|
||||
s2n(extdatalen,p);
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int ssl_parse_ClientHello_TLS_extensions(SSL *s, unsigned char **p, unsigned char *d, int n) {
|
||||
unsigned short type;
|
||||
unsigned short size;
|
||||
unsigned short len;
|
||||
unsigned char * data = *p;
|
||||
|
||||
if (data >= (d+n-2))
|
||||
return SSL_ERROR_NONE;
|
||||
n2s(data,len);
|
||||
|
||||
if (data > (d+n-len))
|
||||
return SSL_ERROR_NONE;
|
||||
|
||||
while(data <= (d+n-4)){
|
||||
n2s(data,type);
|
||||
n2s(data,size);
|
||||
|
||||
if (data+size > (d+n))
|
||||
return SSL_ERROR_SSL;
|
||||
|
||||
if (type == TLSEXT_TYPE_server_name) {
|
||||
unsigned char *sdata = data;
|
||||
int servname_type;
|
||||
int dsize = size-3 ;
|
||||
|
||||
if (dsize > 0 ) {
|
||||
servname_type = *(sdata++);
|
||||
n2s(sdata,len);
|
||||
if (len != dsize)
|
||||
return SSL_ERROR_SSL;
|
||||
|
||||
switch (servname_type) {
|
||||
case TLSEXT_TYPE_SERVER_host:
|
||||
if (s->session->tlsext_hostname == NULL) {
|
||||
if (len > 255 ||
|
||||
((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL))
|
||||
return SSL_ERROR_SSL;
|
||||
memcpy(s->session->tlsext_hostname, sdata, len);
|
||||
s->session->tlsext_hostname[len]='\0';
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
data+=size;
|
||||
}
|
||||
*p = data;
|
||||
|
||||
return SSL_ERROR_NONE;
|
||||
}
|
||||
int ssl_parse_ServerHello_TLS_extensions(SSL *s, unsigned char **p, unsigned char *d, int n) {
|
||||
unsigned short type;
|
||||
unsigned short size;
|
||||
unsigned short len;
|
||||
unsigned char *data = *p;
|
||||
|
||||
int tlsext_servername = 0;
|
||||
|
||||
if (data >= (d+n-2))
|
||||
return SSL_ERROR_NONE;
|
||||
|
||||
|
||||
n2s(data,len);
|
||||
|
||||
while(data <= (d+n-4)){
|
||||
n2s(data,type);
|
||||
n2s(data,size);
|
||||
|
||||
if (data+size > (d+n))
|
||||
return SSL_ERROR_SSL;
|
||||
|
||||
if (type == TLSEXT_TYPE_server_name) {
|
||||
if ( s->tlsext_hostname == NULL || size > 0 ) {
|
||||
return SSL_ERROR_SSL;
|
||||
}
|
||||
tlsext_servername = 1;
|
||||
}
|
||||
|
||||
data+=size;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (data != d+n)
|
||||
return SSL_ERROR_SSL;
|
||||
|
||||
if (!s->hit && tlsext_servername == 1) {
|
||||
if (s->tlsext_hostname) {
|
||||
if (s->session->tlsext_hostname == NULL) {
|
||||
s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);
|
||||
if (!s->session->tlsext_hostname)
|
||||
return SSL_ERROR_SSL;
|
||||
}
|
||||
} else
|
||||
return SSL_ERROR_SSL;
|
||||
}
|
||||
*p = data;
|
||||
|
||||
return SSL_ERROR_NONE;
|
||||
}
|
||||
|
||||
int ssl_check_Hello_TLS_extensions(SSL *s,int *ad)
|
||||
{
|
||||
int ret = SSL_ERROR_NONE;
|
||||
|
||||
*ad = SSL_AD_UNRECOGNIZED_NAME;
|
||||
if (s->servername_done == 0 && (s->ctx != NULL && s->ctx->tlsext_servername_callback != NULL)
|
||||
&& ((ret = s->ctx->tlsext_servername_callback(s, ad, s->ctx->tlsext_servername_arg))!= SSL_ERROR_NONE))
|
||||
return ret;
|
||||
|
||||
else if (s->servername_done == 1)
|
||||
s->servername_done = 2;
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
47
ssl/tls1.h
47
ssl/tls1.h
@@ -97,6 +97,53 @@ extern "C" {
|
||||
#define TLS1_AD_USER_CANCELLED 90
|
||||
#define TLS1_AD_NO_RENEGOTIATION 100
|
||||
|
||||
#ifndef OPENSSL_NO_TLSEXT
|
||||
#define TLS1_AD_UNRECOGNIZED_NAME 122
|
||||
|
||||
#define TLSEXT_TYPE_server_name 0
|
||||
#define TLSEXT_TYPE_max_fragment_length 1
|
||||
#define TLSEXT_TYPE_client_certificate_url 2
|
||||
#define TLSEXT_TYPE_trusted_ca_keys 3
|
||||
#define TLSEXT_TYPE_truncated_hmac 4
|
||||
#define TLSEXT_TYPE_status_request 5
|
||||
#define TLSEXT_TYPE_srp 6
|
||||
|
||||
#define TLSEXT_TYPE_SERVER_host 0
|
||||
|
||||
#define SSL_CTX_set_tlsext_hostname(ctx,name) \
|
||||
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_TYPE_SERVER_host,(char *)name)
|
||||
#define SSL_set_tlsext_hostname(s,name) \
|
||||
SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_TYPE_SERVER_host,(char *)name)
|
||||
|
||||
#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
|
||||
SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb)
|
||||
#define SSL_CTX_set_tlsext_servername_arg(ctx, arg) \
|
||||
SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG,0, (void *)arg)
|
||||
|
||||
|
||||
const char *SSL_get_servername(const SSL *s, const int type) ;
|
||||
int SSL_get_servername_type(const SSL *s) ;
|
||||
|
||||
#if 0
|
||||
#define SSL_get_tlsext_hostname(s,psn) \
|
||||
SSL_ctrl(s,SSL_CTRL_GET_TLSEXT_HOSTNAME,TLSEXT_TYPE_SERVER_host, (void *)psn)
|
||||
#else
|
||||
#define SSL_get_tlsext_hostname(s,psn) \
|
||||
(*psn = SSL_get_servername(s, TLSEXT_TYPE_SERVER_host),*psn != NULL)
|
||||
#endif
|
||||
#define SSL_set_tlsext_servername_done(s,t) \
|
||||
SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_SERVERNAME_DONE,t, NULL)
|
||||
|
||||
void SSL_set_ctx(SSL *s, SSL_CTX *ctx) ;
|
||||
|
||||
#define SSL_CTRL_SET_TLSEXT_SERVERNAME_CB 53
|
||||
#define SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG 54
|
||||
#define SSL_CTRL_SET_TLSEXT_HOSTNAME 55
|
||||
#define SSL_CTRL_GET_TLSEXT_HOSTNAME 56
|
||||
#define SSL_CTRL_SET_TLSEXT_SERVERNAME_DONE 57
|
||||
|
||||
#endif
|
||||
|
||||
/* Additional TLS ciphersuites from expired Internet Draft
|
||||
* draft-ietf-tls-56-bit-ciphersuites-01.txt
|
||||
* (available if TLS1_ALLOW_EXPERIMENTAL_CIPHERSUITES is defined, see
|
||||
|
||||
Reference in New Issue
Block a user