Support TLS extensions (specifically, HostName)
[openssl.git] / ssl / t1_lib.c
1 /* ssl/t1_lib.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  * 
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  * 
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  * 
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from 
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  * 
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  * 
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include <openssl/objects.h>
61 #include "ssl_locl.h"
62
63 const char *tls1_version_str="TLSv1" OPENSSL_VERSION_PTEXT;
64
65 SSL3_ENC_METHOD TLSv1_enc_data={
66         tls1_enc,
67         tls1_mac,
68         tls1_setup_key_block,
69         tls1_generate_master_secret,
70         tls1_change_cipher_state,
71         tls1_final_finish_mac,
72         TLS1_FINISH_MAC_LENGTH,
73         tls1_cert_verify_mac,
74         TLS_MD_CLIENT_FINISH_CONST,TLS_MD_CLIENT_FINISH_CONST_SIZE,
75         TLS_MD_SERVER_FINISH_CONST,TLS_MD_SERVER_FINISH_CONST_SIZE,
76         tls1_alert_code,
77         };
78
79 long tls1_default_timeout(void)
80         {
81         /* 2 hours, the 24 hours mentioned in the TLSv1 spec
82          * is way too long for http, the cache would over fill */
83         return(60*60*2);
84         }
85
86 int tls1_new(SSL *s)
87         {
88         if (!ssl3_new(s)) return(0);
89         s->method->ssl_clear(s);
90         return(1);
91         }
92
93 void tls1_free(SSL *s)
94         {
95         ssl3_free(s);
96         }
97
98 void tls1_clear(SSL *s)
99         {
100         ssl3_clear(s);
101         s->version=TLS1_VERSION;
102         }
103
104 #ifndef OPENSSL_NO_TLSEXT
105 unsigned char *ssl_add_ClientHello_TLS_extensions(SSL *s, unsigned char *p, unsigned char *limit) {
106         int extdatalen=0;
107         unsigned char *ret = p;
108
109         ret+=2;
110
111         if (ret>=limit) return NULL; /* this really never occurs, but ... */
112         if (s->servername_done == 0 && s->tlsext_hostname != NULL) { 
113                 /* Add TLS extension servername to the Client Hello message */
114                 unsigned long size_str;
115                 long lenmax; 
116
117                 if ((lenmax = limit - p - 7) < 0) return NULL; 
118                 if ((size_str = strlen(s->tlsext_hostname)) > (unsigned long)lenmax) return NULL;
119
120                 s2n(TLSEXT_TYPE_server_name,ret);
121                 s2n(size_str+3,ret);
122                 *(ret++) = (unsigned char) TLSEXT_TYPE_SERVER_host;
123                 s2n(size_str,ret);
124         
125                 memcpy(ret, s->tlsext_hostname, size_str);
126                 ret+=size_str;
127         }
128
129         
130         if ((extdatalen = ret-p-2)== 0) 
131                 return p;
132
133         s2n(extdatalen,p);
134         return ret;
135
136 }
137
138 unsigned char *ssl_add_ServerHello_TLS_extensions(SSL *s, unsigned char *p, unsigned char *limit) {
139         int extdatalen=0;
140         unsigned char *ret = p;
141         if (s->hit || s->servername_done == 2)
142                 return p;
143         ret+=2;
144         if (s->servername_done == 1)  
145                 s->servername_done = 2;
146
147         if (ret>=limit) return NULL; /* this really never occurs, but ... */
148
149         if (s->session->tlsext_hostname != NULL) { 
150
151                 if (limit - p - 4 < 0) return NULL; 
152
153                 s2n(TLSEXT_TYPE_server_name,ret);
154                 s2n(0,ret);
155         }
156
157         
158         if ((extdatalen = ret-p-2)== 0) 
159                 return p;
160
161         s2n(extdatalen,p);
162         return ret;
163
164 }
165
166 int ssl_parse_ClientHello_TLS_extensions(SSL *s, unsigned char **p, unsigned char *d, int n) {
167         unsigned short type;
168         unsigned short size;
169         unsigned short len;
170         unsigned char * data = *p;
171
172         if (data >= (d+n-2))
173            return SSL_ERROR_NONE;
174         n2s(data,len);
175
176         if (data > (d+n-len)) 
177            return SSL_ERROR_NONE;
178
179         while(data <= (d+n-4)){
180                 n2s(data,type);
181                 n2s(data,size);
182
183                 if (data+size > (d+n))
184                         return SSL_ERROR_SSL;
185
186                 if (type == TLSEXT_TYPE_server_name) {
187                         unsigned char *sdata = data;
188                         int servname_type;
189                         int dsize = size-3 ;
190                         
191                         if (dsize > 0 ) {
192                                 servname_type = *(sdata++); 
193                                 n2s(sdata,len);
194                                 if (len != dsize) 
195                                         return SSL_ERROR_SSL;
196
197                                 switch (servname_type) {
198                                 case TLSEXT_TYPE_SERVER_host:
199                                         if (s->session->tlsext_hostname == NULL) {
200                                                 if (len > 255 || 
201                                                         ((s->session->tlsext_hostname = OPENSSL_malloc(len+1)) == NULL))
202                                                         return SSL_ERROR_SSL;
203                                                 memcpy(s->session->tlsext_hostname, sdata, len);
204                                                 s->session->tlsext_hostname[len]='\0'; 
205                                         }
206                                         break;
207                                 default:
208                                         break;
209                                 }
210                                  
211                         }
212                 }
213
214                 data+=size;             
215         }
216         *p = data;
217
218         return SSL_ERROR_NONE;
219 }
220 int ssl_parse_ServerHello_TLS_extensions(SSL *s, unsigned char **p, unsigned char *d, int n) {
221         unsigned short type;
222         unsigned short size;
223         unsigned short len;  
224         unsigned char *data = *p;
225
226         int tlsext_servername = 0;
227
228         if (data >= (d+n-2))
229            return SSL_ERROR_NONE;
230
231
232         n2s(data,len);
233
234         while(data <= (d+n-4)){
235                 n2s(data,type);
236                 n2s(data,size);
237
238                 if (data+size > (d+n))
239                         return SSL_ERROR_SSL;
240
241                 if (type == TLSEXT_TYPE_server_name) {
242                         if ( s->tlsext_hostname == NULL || size > 0 ) {
243                                 return SSL_ERROR_SSL;
244                         }
245                         tlsext_servername = 1;   
246                 } 
247
248                 data+=size;             
249         }
250
251         
252
253         if (data != d+n)
254                 return SSL_ERROR_SSL;
255
256         if (!s->hit && tlsext_servername == 1) {
257                 if (s->tlsext_hostname) {
258                         if (s->session->tlsext_hostname == NULL) {
259                                 s->session->tlsext_hostname = BUF_strdup(s->tlsext_hostname);   
260                                 if (!s->session->tlsext_hostname)
261                                         return SSL_ERROR_SSL;
262                         }
263                 } else 
264                         return SSL_ERROR_SSL;
265         }
266         *p = data;
267
268         return SSL_ERROR_NONE;
269 }
270
271 int ssl_check_Hello_TLS_extensions(SSL *s,int *ad)
272 {
273         int ret = SSL_ERROR_NONE;
274
275         *ad = SSL_AD_UNRECOGNIZED_NAME;
276         if (s->servername_done == 0 && (s->ctx != NULL && s->ctx->tlsext_servername_callback != NULL) 
277                 && ((ret = s->ctx->tlsext_servername_callback(s, ad, s->ctx->tlsext_servername_arg))!= SSL_ERROR_NONE)) 
278                 return ret;
279
280         else if (s->servername_done == 1)       
281                 s->servername_done = 2;
282
283         return ret;
284 }
285 #endif
286