00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include "MHD_config.h"
00031 #include "gnutls_int.h"
00032 #include "gnutls_extensions.h"
00033 #include "gnutls_errors.h"
00034 #include "ext_max_record.h"
00035 #include <ext_cert_type.h>
00036 #include <ext_server_name.h>
00037 #include <gnutls_num.h>
00038
00039
00040 #define GNUTLS_EXTENSION_ENTRY(type, parse_type, ext_func_recv, ext_func_send) \
00041 { #type, type, parse_type, ext_func_recv, ext_func_send }
00042
00043
00044 #define MAX_EXT_SIZE 10
00045 const int MHD_gtls_extensions_size = MAX_EXT_SIZE;
00046
00047 MHD_gtls_extension_entry MHD_gtls_extensions[MAX_EXT_SIZE] = {
00048 GNUTLS_EXTENSION_ENTRY (GNUTLS_EXTENSION_MAX_RECORD_SIZE,
00049 EXTENSION_TLS,
00050 MHD_gtls_max_record_recv_params,
00051 MHD_gtls_max_record_send_params),
00052 GNUTLS_EXTENSION_ENTRY (GNUTLS_EXTENSION_CERT_TYPE,
00053 EXTENSION_TLS,
00054 MHD_gtls_cert_type_recv_params,
00055 MHD_gtls_cert_type_send_params),
00056 GNUTLS_EXTENSION_ENTRY (GNUTLS_EXTENSION_SERVER_NAME,
00057 EXTENSION_APPLICATION,
00058 MHD_gtls_server_name_recv_params,
00059 MHD_gtls_server_name_send_params),
00060 {0, 0, 0, 0}
00061 };
00062
00063 #define GNUTLS_EXTENSION_LOOP2(b) \
00064 MHD_gtls_extension_entry *p; \
00065 for(p = MHD_gtls_extensions; p->name != NULL; p++) { b ; }
00066
00067 #define GNUTLS_EXTENSION_LOOP(a) \
00068 GNUTLS_EXTENSION_LOOP2( if(p->type == type) { a; break; } )
00069
00070
00071
00072
00073 MHD_gtls_ext_recv_func
00074 MHD_gtls_ext_func_recv (uint16_t type, MHD_gtls_ext_parse_type_t parse_type)
00075 {
00076 MHD_gtls_ext_recv_func ret = NULL;
00077 GNUTLS_EXTENSION_LOOP (if
00078 (parse_type == EXTENSION_ANY
00079 || p->parse_type == parse_type) ret =
00080 p->MHD_gnutls_ext_func_recv);
00081 return ret;
00082
00083 }
00084
00085 MHD_gtls_ext_send_func
00086 MHD_gtls_ext_func_send (uint16_t type)
00087 {
00088 MHD_gtls_ext_send_func ret = NULL;
00089 GNUTLS_EXTENSION_LOOP (ret = p->MHD_gnutls_ext_func_send);
00090 return ret;
00091
00092 }
00093
00094 const char *
00095 MHD_gtls_extension_get_name (uint16_t type)
00096 {
00097 const char *ret = NULL;
00098
00099
00100 GNUTLS_EXTENSION_LOOP (ret = p->name + sizeof ("GNUTLS_EXTENSION_") - 1);
00101
00102 return ret;
00103 }
00104
00105
00106
00107
00108 static int
00109 MHD__gnutls_extension_list_check (MHD_gtls_session_t session, uint16_t type)
00110 {
00111 #if MHD_DEBUG_TLS
00112 if (session->security_parameters.entity == GNUTLS_CLIENT)
00113 {
00114 int i;
00115 for (i = 0; i < session->internals.extensions_sent_size; i++)
00116 {
00117 if (type == session->internals.extensions_sent[i])
00118 return 0;
00119 }
00120 return GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION;
00121 }
00122 #endif
00123 return 0;
00124 }
00125
00126 int
00127 MHD_gtls_parse_extensions (MHD_gtls_session_t session,
00128 MHD_gtls_ext_parse_type_t parse_type,
00129 const opaque * data, int data_size)
00130 {
00131 int next, ret;
00132 int pos = 0;
00133 uint16_t type;
00134 const opaque *sdata;
00135 MHD_gtls_ext_recv_func ext_recv;
00136 uint16_t size;
00137
00138 #if MHD_DEBUG_TLS
00139 int i;
00140 if (session->security_parameters.entity == GNUTLS_CLIENT)
00141 for (i = 0; i < session->internals.extensions_sent_size; i++)
00142 {
00143 MHD__gnutls_debug_log ("EXT[%d]: expecting extension '%s'\n",
00144 session,
00145 MHD_gtls_extension_get_name
00146 (session->internals.extensions_sent[i]));
00147 }
00148 #endif
00149
00150 DECR_LENGTH_RET (data_size, 2, 0);
00151 next = MHD_gtls_read_uint16 (data);
00152 pos += 2;
00153
00154 DECR_LENGTH_RET (data_size, next, 0);
00155
00156 do
00157 {
00158 DECR_LENGTH_RET (next, 2, 0);
00159 type = MHD_gtls_read_uint16 (&data[pos]);
00160 pos += 2;
00161
00162 MHD__gnutls_debug_log ("EXT[%x]: Received extension '%s/%d'\n", session,
00163 MHD_gtls_extension_get_name (type), type);
00164
00165 if ((ret = MHD__gnutls_extension_list_check (session, type)) < 0)
00166 {
00167 MHD_gnutls_assert ();
00168 return ret;
00169 }
00170
00171 DECR_LENGTH_RET (next, 2, 0);
00172 size = MHD_gtls_read_uint16 (&data[pos]);
00173 pos += 2;
00174
00175 DECR_LENGTH_RET (next, size, 0);
00176 sdata = &data[pos];
00177 pos += size;
00178
00179 ext_recv = MHD_gtls_ext_func_recv (type, parse_type);
00180 if (ext_recv == NULL)
00181 continue;
00182 if ((ret = ext_recv (session, sdata, size)) < 0)
00183 {
00184 MHD_gnutls_assert ();
00185 return ret;
00186 }
00187
00188 }
00189 while (next > 2);
00190
00191 return 0;
00192
00193 }
00194
00195
00196
00197
00198
00199 static void
00200 MHD__gnutls_extension_list_add (MHD_gtls_session_t session, uint16_t type)
00201 {
00202 #if MHD_DEBUG_TLS
00203 if (session->security_parameters.entity == GNUTLS_CLIENT)
00204 {
00205 if (session->internals.extensions_sent_size < MAX_EXT_TYPES)
00206 {
00207 session->internals.extensions_sent[session->internals.
00208 extensions_sent_size] = type;
00209 session->internals.extensions_sent_size++;
00210 }
00211 else
00212 {
00213 MHD__gnutls_debug_log ("extensions: Increase MAX_EXT_TYPES\n");
00214 }
00215 }
00216 #endif
00217 }
00218
00219 int
00220 MHD_gtls_gen_extensions (MHD_gtls_session_t session, opaque * data,
00221 size_t data_size)
00222 {
00223 int size;
00224 uint16_t pos = 0;
00225 opaque *sdata;
00226 int sdata_size;
00227 MHD_gtls_ext_send_func ext_send;
00228 MHD_gtls_extension_entry *p;
00229
00230 if (data_size < 2)
00231 {
00232 MHD_gnutls_assert ();
00233 return GNUTLS_E_INTERNAL_ERROR;
00234 }
00235
00236
00237
00238 sdata_size = data_size;
00239 sdata = MHD_gnutls_malloc (sdata_size);
00240 if (sdata == NULL)
00241 {
00242 MHD_gnutls_assert ();
00243 return GNUTLS_E_MEMORY_ERROR;
00244 }
00245
00246 pos += 2;
00247 for (p = MHD_gtls_extensions; p->name != NULL; p++)
00248 {
00249 ext_send = MHD_gtls_ext_func_send (p->type);
00250 if (ext_send == NULL)
00251 continue;
00252 size = ext_send (session, sdata, sdata_size);
00253 if (size > 0)
00254 {
00255 if (data_size < pos + (size_t) size + 4)
00256 {
00257 MHD_gnutls_assert ();
00258 MHD_gnutls_free (sdata);
00259 return GNUTLS_E_INTERNAL_ERROR;
00260 }
00261
00262
00263 MHD_gtls_write_uint16 (p->type, &data[pos]);
00264 pos += 2;
00265
00266
00267 MHD_gtls_write_uint16 (size, &data[pos]);
00268 pos += 2;
00269
00270 memcpy (&data[pos], sdata, size);
00271 pos += size;
00272
00273
00274
00275 MHD__gnutls_extension_list_add (session, p->type);
00276
00277 MHD__gnutls_debug_log ("EXT[%x]: Sending extension %s\n", session,
00278 MHD_gtls_extension_get_name (p->type));
00279 }
00280 else if (size < 0)
00281 {
00282 MHD_gnutls_assert ();
00283 MHD_gnutls_free (sdata);
00284 return size;
00285 }
00286 }
00287
00288 size = pos;
00289 pos -= 2;
00290
00291 MHD_gtls_write_uint16 (pos, data);
00292
00293 if (size == 2)
00294 {
00295 size = 0;
00296 }
00297
00298 MHD_gnutls_free (sdata);
00299 return size;
00300
00301 }