*** empty log message ***
[gnutls.git] / lib / gnutls_extensions.c
blob2a85bd2837b21824ce0fdd0d3202c083f544fb68
1 /*
2 * Copyright (C) 2001 Nikos Mavroyanopoulos
4 * This file is part of GNUTLS.
6 * The GNUTLS library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "gnutls_int.h"
23 #include "gnutls_extensions.h"
24 #include "gnutls_errors.h"
25 #include "ext_max_record.h"
26 #include <ext_cert_type.h>
27 #include "gnutls_num.h"
29 /* Key Exchange Section */
30 #define GNUTLS_EXTENSION_ENTRY(type, ext_func_recv, ext_func_send) \
31 { #type, type, ext_func_recv, ext_func_send }
34 #define MAX_EXT_SIZE 10
35 const int _gnutls_extensions_size = MAX_EXT_SIZE;
37 gnutls_extension_entry _gnutls_extensions[MAX_EXT_SIZE] = {
38 GNUTLS_EXTENSION_ENTRY( GNUTLS_EXTENSION_MAX_RECORD_SIZE, _gnutls_max_record_recv_params, _gnutls_max_record_send_params),
39 GNUTLS_EXTENSION_ENTRY( GNUTLS_EXTENSION_CERT_TYPE, _gnutls_cert_type_recv_params, _gnutls_cert_type_send_params),
40 {0}
43 #define GNUTLS_EXTENSION_LOOP2(b) \
44 gnutls_extension_entry *p; \
45 for(p = _gnutls_extensions; p->name != NULL; p++) { b ; }
47 #define GNUTLS_EXTENSION_LOOP(a) \
48 GNUTLS_EXTENSION_LOOP2( if(p->type == type) { a; break; } )
51 /* EXTENSION functions */
53 void* _gnutls_ext_func_recv(uint16 type)
55 void* ret=NULL;
56 GNUTLS_EXTENSION_LOOP(ret = p->gnutls_ext_func_recv);
57 return ret;
60 void* _gnutls_ext_func_send(uint16 type)
62 void* ret=NULL;
63 GNUTLS_EXTENSION_LOOP(ret = p->gnutls_ext_func_send);
64 return ret;
68 const char *_gnutls_extension_get_name(uint16 type)
70 char *ret = NULL;
72 /* avoid prefix */
73 GNUTLS_EXTENSION_LOOP(ret = p->name + sizeof("EXTENSION_") - 1);
75 return ret;
78 /* Checks if the extension we just received is one of the
79 * requested ones. Otherwise it's a fatal error.
81 static int _gnutls_extension_list_check( GNUTLS_STATE state, uint8 type) {
82 int i;
83 if (state->security_parameters.entity==GNUTLS_CLIENT) {
84 for(i=0;i<state->gnutls_internals.extensions_sent_size;i++) {
85 if (type==state->gnutls_internals.extensions_sent[i])
86 return 0; /* ok found */
88 return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
91 return 0;
94 int _gnutls_parse_extensions( GNUTLS_STATE state, const opaque* data, int data_size) {
95 int next, ret;
96 int pos=0;
97 uint16 type;
98 const opaque* sdata;
99 int (*ext_func_recv)( GNUTLS_STATE, const opaque*, int);
100 uint16 size;
102 #ifdef DEBUG
103 int i;
105 if (state->security_parameters.entity==GNUTLS_CLIENT)
106 for (i=0;i<state->gnutls_internals.extensions_sent_size;i++) {
107 _gnutls_log("EXT: expecting extension %d\n", state->gnutls_internals.extensions_sent[i]);
109 #endif
111 DECR_LENGTH_RET( data_size, 2, 0);
112 next = _gnutls_read_uint16( data);
113 pos+=2;
115 DECR_LENGTH_RET( data_size, next, 0);
117 do {
118 DECR_LENGTH_RET( next, 1, 0);
119 type = _gnutls_read_uint16( &data[pos]);
120 pos+=2;
122 if ( (ret=_gnutls_extension_list_check( state, type)) < 0) {
123 gnutls_assert();
124 return ret;
127 DECR_LENGTH_RET( next, 2, 0);
128 size = _gnutls_read_uint16(&data[pos]);
129 pos+=2;
131 DECR_LENGTH_RET( next, size, 0);
132 sdata = &data[pos];
133 pos+=size;
135 ext_func_recv = _gnutls_ext_func_recv(type);
136 if (ext_func_recv == NULL) continue;
137 if ( (ret=ext_func_recv( state, sdata, size)) < 0) {
138 gnutls_assert();
139 return ret;
142 } while(next > 2);
144 return 0;
148 /* Adds the extension we want to send in the extensions list.
149 * This list is used to check whether the (later) received
150 * extensions are the ones we requested.
152 static void _gnutls_extension_list_add( GNUTLS_STATE state, uint8 type) {
154 if (state->security_parameters.entity==GNUTLS_CLIENT) {
155 if (state->gnutls_internals.extensions_sent_size <
156 sizeof(state->gnutls_internals.extensions_sent)) {
158 state->gnutls_internals.extensions_sent[state->gnutls_internals.extensions_sent_size] = type;
159 state->gnutls_internals.extensions_sent_size++;
160 } else {
161 #ifdef DEBUG
162 _gnutls_log("EXT: Increase MAX_EXT_TYPES\n");
163 #endif
167 return;
170 int _gnutls_gen_extensions( GNUTLS_STATE state, opaque** data) {
171 int next, size;
172 uint16 pos=0;
173 opaque sdata[1024];
174 int sdata_size = sizeof(sdata);
175 int (*ext_func_send)( GNUTLS_STATE, opaque*, int);
178 (*data) = gnutls_malloc(2); /* allocate size for size */
179 pos+=2;
181 if ((*data)==NULL) {
182 gnutls_assert();
183 return GNUTLS_E_MEMORY_ERROR;
186 next = MAX_EXT_TYPES; /* maximum supported extensions */
187 do {
188 next--;
189 ext_func_send = _gnutls_ext_func_send(next);
190 if (ext_func_send == NULL) continue;
191 size = ext_func_send( state, sdata, sdata_size);
193 if (size > 0) {
194 (*data) = gnutls_realloc( (*data), pos+size+4);
195 if ((*data)==NULL) {
196 gnutls_assert();
197 return GNUTLS_E_MEMORY_ERROR;
200 /* write extension type */
201 _gnutls_write_uint16( next, &(*data)[pos]);
202 pos+=2;
204 /* write size */
205 _gnutls_write_uint16( size, &(*data)[pos]);
206 pos+=2;
208 memcpy( &(*data)[pos], sdata, size);
209 pos+=size;
211 /* add this extension to the extension list
213 _gnutls_extension_list_add( state, next);
216 } while(next >= 0);
218 size = pos;
219 pos-=2; /* remove the size of the size header! */
221 _gnutls_write_uint16( pos, (*data));
223 if (size==2) { /* empty */
224 size = 0;
225 gnutls_free(*data);
226 (*data) = NULL;
228 return size;