gnutls_supplemental.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 Free Software Foundation
00003  *
00004  * Author: Simon Josefsson
00005  *
00006  * This file is part of GNUTLS.
00007  *
00008  * The GNUTLS library is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU Lesser General Public License
00010  * as published by the Free Software Foundation; either version 2.1 of
00011  * the License, or (at your option) any later version.
00012  *
00013  * This library is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * Lesser General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU Lesser General Public
00019  * License along with this library; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
00021  * USA
00022  *
00023  */
00024 
00025 /* This file contains support functions for 'TLS Handshake Message for
00026  * Supplemental Data' (RFC 4680).
00027  *
00028  * The idea here is simple.  MHD__gnutls_handshake() in gnuts_handshake.c
00029  * will call MHD__gnutls_gen_supplemental and MHD__gnutls_parse_supplemental
00030  * when some extension requested that supplemental data be sent or
00031  * received.  Extension request this by setting the flags
00032  * do_recv_supplemental or do_send_supplemental in the session.
00033  *
00034  * The functions in this file iterate through the MHD__gnutls_supplemental
00035  * array, and calls the send/recv functions for each respective data
00036  * type.
00037  *
00038  * The receive function of each data type is responsible for decoding
00039  * its own data.  If the extension did not expect to receive
00040  * supplemental data, it should return GNUTLS_E_UNEXPECTED_PACKET.
00041  * Otherwise, it just parse the data as normal.
00042  *
00043  * The send function needs to append the 2-byte data format type, and
00044  * append the 2-byte length of its data, and the data.  If it doesn't
00045  * want to send any data, it is fine to return without doing anything.
00046  */
00047 
00048 #include "gnutls_int.h"
00049 #include "gnutls_supplemental.h"
00050 #include "gnutls_errors.h"
00051 #include "gnutls_num.h"
00052 
00053 typedef int (*supp_recv_func) (MHD_gtls_session_t session,
00054                                const opaque * data, size_t data_size);
00055 typedef int (*supp_send_func) (MHD_gtls_session_t session,
00056                                MHD_gtls_buffer * buf);
00057 
00058 typedef struct
00059 {
00060   const char *name;
00061   MHD_gnutls_supplemental_data_format_type_t type;
00062   supp_recv_func supp_recv_func;
00063   supp_send_func supp_send_func;
00064 } MHD_gnutls_supplemental_entry;
00065 
00066 MHD_gnutls_supplemental_entry MHD__gnutls_supplemental[] = {
00067   {0, 0, 0, 0}
00068 };
00069 
00070 
00071 static supp_recv_func
00072 get_supp_func_recv (MHD_gnutls_supplemental_data_format_type_t type)
00073 {
00074   MHD_gnutls_supplemental_entry *p;
00075 
00076   for (p = MHD__gnutls_supplemental; p->name != NULL; p++)
00077     if (p->type == type)
00078       return p->supp_recv_func;
00079 
00080   return NULL;
00081 }
00082 
00083 int
00084 MHD__gnutls_gen_supplemental (MHD_gtls_session_t session,
00085                               MHD_gtls_buffer * buf)
00086 {
00087   MHD_gnutls_supplemental_entry *p;
00088   int ret;
00089 
00090   /* Make room for 3 byte length field. */
00091   ret = MHD_gtls_buffer_append (buf, "\0\0\0", 3);
00092   if (ret < 0)
00093     {
00094       MHD_gnutls_assert ();
00095       return ret;
00096     }
00097 
00098   for (p = MHD__gnutls_supplemental; p->name; p++)
00099     {
00100       supp_send_func supp_send = p->supp_send_func;
00101       size_t sizepos = buf->length;
00102       int ret;
00103 
00104       /* Make room for supplement type and length byte length field. */
00105       ret = MHD_gtls_buffer_append (buf, "\0\0\0\0", 4);
00106       if (ret < 0)
00107         {
00108           MHD_gnutls_assert ();
00109           return ret;
00110         }
00111 
00112       ret = supp_send (session, buf);
00113       if (ret < 0)
00114         {
00115           MHD_gnutls_assert ();
00116           return ret;
00117         }
00118 
00119       /* If data were added, store type+length, otherwise reset. */
00120       if (buf->length > sizepos + 4)
00121         {
00122           buf->data[sizepos] = 0;
00123           buf->data[sizepos + 1] = p->type;
00124           buf->data[sizepos + 2] = ((buf->length - sizepos - 4) >> 8) & 0xFF;
00125           buf->data[sizepos + 3] = (buf->length - sizepos - 4) & 0xFF;
00126         }
00127       else
00128         buf->length -= 4;
00129     }
00130 
00131   buf->data[0] = ((buf->length - 3) >> 16) & 0xFF;
00132   buf->data[1] = ((buf->length - 3) >> 8) & 0xFF;
00133   buf->data[2] = (buf->length - 3) & 0xFF;
00134 
00135   MHD__gnutls_debug_log ("EXT[%x]: Sending %d bytes of supplemental data\n",
00136                          session, buf->length);
00137 
00138   return buf->length;
00139 }
00140 
00141 int
00142 MHD__gnutls_parse_supplemental (MHD_gtls_session_t session,
00143                                 const uint8_t * data, int datalen)
00144 {
00145   const opaque *p = data;
00146   ssize_t dsize = datalen;
00147   size_t total_size;
00148 
00149   DECR_LEN (dsize, 3);
00150   total_size = MHD_gtls_read_uint24 (p);
00151   p += 3;
00152 
00153   if (dsize != total_size)
00154     {
00155       MHD_gnutls_assert ();
00156       return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
00157     }
00158 
00159   do
00160     {
00161       uint16_t supp_data_type;
00162       uint16_t supp_data_length;
00163       supp_recv_func recv_func;
00164 
00165       DECR_LEN (dsize, 2);
00166       supp_data_type = MHD_gtls_read_uint16 (p);
00167       p += 2;
00168 
00169       DECR_LEN (dsize, 2);
00170       supp_data_length = MHD_gtls_read_uint16 (p);
00171       p += 2;
00172 
00173       MHD__gnutls_debug_log
00174         ("EXT[%x]: Got supplemental type=%02x length=%d\n", session,
00175          supp_data_type, supp_data_length);
00176 
00177       recv_func = get_supp_func_recv (supp_data_type);
00178       if (recv_func)
00179         {
00180           int ret = recv_func (session, p, supp_data_length);
00181           if (ret < 0)
00182             {
00183               MHD_gnutls_assert ();
00184               return ret;
00185             }
00186         }
00187       else
00188         {
00189           MHD_gnutls_assert ();
00190           return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
00191         }
00192 
00193       DECR_LEN (dsize, supp_data_length);
00194       p += supp_data_length;
00195     }
00196   while (dsize > 0);
00197 
00198   return 0;
00199 }

Generated on Fri Feb 27 18:32:19 2009 for GNU libmicrohttpd by  doxygen 1.5.7.1