ext_server_name.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation
00003  *
00004  * Author: Nikos Mavrogiannopoulos
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 #include "gnutls_int.h"
00026 #include "gnutls_auth_int.h"
00027 #include "gnutls_errors.h"
00028 #include "gnutls_num.h"
00029 #include <ext_server_name.h>
00030 
00031 /*
00032  * In case of a server: if a NAME_DNS extension type is received then it stores
00033  * into the session the value of NAME_DNS. The server may use MHD_gnutls_ext_get_server_name(),
00034  * in order to access it.
00035  *
00036  * In case of a client: If a proper NAME_DNS extension type is found in the session then
00037  * it sends the extension to the peer.
00038  *
00039  */
00040 
00041 int
00042 MHD_gtls_server_name_recv_params (MHD_gtls_session_t session,
00043                                   const opaque * data, size_t _data_size)
00044 {
00045   int i;
00046   const unsigned char *p;
00047   uint16_t len, type;
00048   ssize_t data_size = _data_size;
00049   int server_names = 0;
00050 
00051   DECR_LENGTH_RET (data_size, 2, 0);
00052   len = MHD_gtls_read_uint16 (data);
00053 
00054   if (len != data_size)
00055     {
00056       /* This is unexpected packet length, but
00057        * just ignore it, for now.
00058        */
00059       MHD_gnutls_assert ();
00060       return 0;
00061     }
00062 
00063   p = data + 2;
00064 
00065   /* Count all server_names in the packet. */
00066   while (data_size > 0)
00067     {
00068       DECR_LENGTH_RET (data_size, 1, 0);
00069       p++;
00070 
00071       DECR_LEN (data_size, 2);
00072       len = MHD_gtls_read_uint16 (p);
00073       p += 2;
00074 
00075       /* make sure supplied server name is not empty */
00076       if (len > 0)
00077         {
00078           DECR_LENGTH_RET (data_size, len, 0);
00079           server_names++;
00080           p += len;
00081         }
00082       else
00083         {
00084 #if HAVE_MESSAGES
00085           MHD__gnutls_handshake_log
00086             ("HSK[%x]: Received zero size server name (under attack?)\n",
00087              session);
00088 #endif
00089         }
00090     }
00091 
00092   /* we cannot accept more server names. */
00093   if (server_names > MAX_SERVER_NAME_EXTENSIONS)
00094     {
00095 #if HAVE_MESSAGES
00096       MHD__gnutls_handshake_log
00097         ("HSK[%x]: Too many server names received (under attack?)\n",
00098          session);
00099 #endif
00100       server_names = MAX_SERVER_NAME_EXTENSIONS;
00101     }
00102 
00103   session->security_parameters.extensions.server_names_size = server_names;
00104   if (server_names == 0)
00105     return 0;                   /* no names found */
00106 
00107   p = data + 2;
00108   for (i = 0; i < server_names; i++)
00109     {
00110       type = *p;
00111       p++;
00112 
00113       len = MHD_gtls_read_uint16 (p);
00114       p += 2;
00115 
00116       switch (type)
00117         {
00118         case 0:                /* NAME_DNS */
00119           if (len <= MAX_SERVER_NAME_SIZE)
00120             {
00121               memcpy (session->security_parameters.extensions.
00122                       server_names[i].name, p, len);
00123               session->security_parameters.extensions.server_names[i].
00124                 name_length = len;
00125               session->security_parameters.extensions.server_names[i].type =
00126                 GNUTLS_NAME_DNS;
00127               break;
00128             }
00129         }
00130 
00131       /* move to next record */
00132       p += len;
00133     }
00134   return 0;
00135 }
00136 
00137 /* returns data_size or a negative number on failure
00138  */
00139 int
00140 MHD_gtls_server_name_send_params (MHD_gtls_session_t session,
00141                                   opaque * data, size_t _data_size)
00142 {
00143   int total_size = 0;
00144 #if MHD_DEBUG_TLS
00145   uint16_t len;
00146   opaque *p;
00147   unsigned i;
00148   ssize_t data_size = _data_size;
00149 
00150   /* this function sends the client extension data (dnsname) */
00151   if (session->security_parameters.entity == GNUTLS_CLIENT)
00152     {
00153 
00154       if (session->security_parameters.extensions.server_names_size == 0)
00155         return 0;
00156 
00157       /* uint16_t
00158        */
00159       total_size = 2;
00160       for (i = 0;
00161            i < session->security_parameters.extensions.server_names_size; i++)
00162         {
00163           /* count the total size
00164            */
00165           len =
00166             session->security_parameters.extensions.server_names[i].
00167             name_length;
00168 
00169           /* uint8_t + uint16_t + size
00170            */
00171           total_size += 1 + 2 + len;
00172         }
00173 
00174       p = data;
00175 
00176       /* UINT16: write total size of all names
00177        */
00178       DECR_LENGTH_RET (data_size, 2, GNUTLS_E_SHORT_MEMORY_BUFFER);
00179       MHD_gtls_write_uint16 (total_size - 2, p);
00180       p += 2;
00181 
00182       for (i = 0;
00183            i < session->security_parameters.extensions.server_names_size; i++)
00184         {
00185 
00186           switch (session->security_parameters.extensions.
00187                   server_names[i].type)
00188             {
00189             case GNUTLS_NAME_DNS:
00190 
00191               len =
00192                 session->security_parameters.extensions.
00193                 server_names[i].name_length;
00194               if (len == 0)
00195                 break;
00196 
00197               /* UINT8: type of this extension
00198                * UINT16: size of the first name
00199                * LEN: the actual server name.
00200                */
00201               DECR_LENGTH_RET (data_size, len + 3,
00202                                GNUTLS_E_SHORT_MEMORY_BUFFER);
00203 
00204               *p = 0;           /* NAME_DNS type */
00205               p++;
00206 
00207               MHD_gtls_write_uint16 (len, p);
00208               p += 2;
00209 
00210               memcpy (p,
00211                       session->security_parameters.extensions.
00212                       server_names[0].name, len);
00213               p += len;
00214               break;
00215             default:
00216               MHD_gnutls_assert ();
00217               return GNUTLS_E_INTERNAL_ERROR;
00218             }
00219         }
00220     }
00221 #endif
00222   return total_size;
00223 }
Generated by  doxygen 1.6.2-20100208