gnutls_auth.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001, 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_errors.h"
00027 #include "gnutls_auth.h"
00028 #include "gnutls_auth_int.h"
00029 #include "gnutls_algorithms.h"
00030 #include "auth_cert.h"
00031 #include <gnutls_datum.h>
00032 
00033 /* The functions here are used in order for authentication algorithms
00034  * to be able to retrieve the needed credentials eg public and private
00035  * key etc.
00036  */
00037 
00045 void
00046 MHD__gnutls_credentials_clear (MHD_gtls_session_t session)
00047 {
00048   if (session->key && session->key->cred)
00049     {                           /* beginning of the list */
00050       auth_cred_st *ccred, *ncred;
00051       ccred = session->key->cred;
00052       while (ccred != NULL)
00053         {
00054           ncred = ccred->next;
00055           MHD_gnutls_free (ccred);
00056           ccred = ncred;
00057         }
00058       session->key->cred = NULL;
00059     }
00060 }
00061 
00062 /*
00063  * This creates a linked list of the form:
00064  * { algorithm, credentials, pointer to next }
00065  */
00088 int
00089 MHD__gnutls_credentials_set (MHD_gtls_session_t session,
00090                              enum MHD_GNUTLS_CredentialsType type, void *cred)
00091 {
00092   auth_cred_st *ccred = NULL, *pcred = NULL;
00093   int exists = 0;
00094 
00095   if (session->key->cred == NULL)
00096     {                           /* beginning of the list */
00097 
00098       session->key->cred = MHD_gnutls_malloc (sizeof (auth_cred_st));
00099       if (session->key->cred == NULL)
00100         return GNUTLS_E_MEMORY_ERROR;
00101 
00102       /* copy credentials locally */
00103       session->key->cred->credentials = cred;
00104 
00105       session->key->cred->next = NULL;
00106       session->key->cred->algorithm = type;
00107     }
00108   else
00109     {
00110       ccred = session->key->cred;
00111       while (ccred != NULL)
00112         {
00113           if (ccred->algorithm == type)
00114             {
00115               exists = 1;
00116               break;
00117             }
00118           pcred = ccred;
00119           ccred = ccred->next;
00120         }
00121       /* After this, pcred is not null.
00122        */
00123 
00124       if (exists == 0)
00125         {                       /* new entry */
00126           pcred->next = MHD_gnutls_malloc (sizeof (auth_cred_st));
00127           if (pcred->next == NULL)
00128             return GNUTLS_E_MEMORY_ERROR;
00129 
00130           ccred = pcred->next;
00131 
00132           /* copy credentials locally */
00133           ccred->credentials = cred;
00134 
00135           ccred->next = NULL;
00136           ccred->algorithm = type;
00137         }
00138       else
00139         {                       /* modify existing entry */
00140           MHD_gnutls_free (ccred->credentials);
00141           ccred->credentials = cred;
00142         }
00143     }
00144 
00145   return 0;
00146 }
00147 
00159 enum MHD_GNUTLS_CredentialsType
00160 MHD_gtls_auth_get_type (MHD_gtls_session_t session)
00161 {
00162 /* This is not the credentials we must set, but the authentication data
00163  * we get by the peer, so it should be reversed.
00164  */
00165   int server = session->security_parameters.entity == GNUTLS_SERVER ? 0 : 1;
00166 
00167   return
00168     MHD_gtls_map_kx_get_cred (MHD_gtls_cipher_suite_get_kx_algo
00169                               (&session->security_parameters.
00170                                current_cipher_suite), server);
00171 }
00172 
00173 /*
00174  * This returns a pointer to the linked list. Don't
00175  * free that!!!
00176  */
00177 const void *
00178 MHD_gtls_get_kx_cred (MHD_gtls_session_t session,
00179                       enum MHD_GNUTLS_KeyExchangeAlgorithm algo, int *err)
00180 {
00181   int server = session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0;
00182 
00183   return MHD_gtls_get_cred (session->key,
00184                             MHD_gtls_map_kx_get_cred (algo, server), err);
00185 }
00186 
00187 const void *
00188 MHD_gtls_get_cred (MHD_gtls_key_st key, enum MHD_GNUTLS_CredentialsType type,
00189                    int *err)
00190 {
00191   const void *retval = NULL;
00192   int _err = -1;
00193   auth_cred_st *ccred;
00194 
00195   if (key == NULL)
00196     goto out;
00197 
00198   ccred = key->cred;
00199   while (ccred != NULL)
00200     {
00201       if (ccred->algorithm == type)
00202         {
00203           break;
00204         }
00205       ccred = ccred->next;
00206     }
00207   if (ccred == NULL)
00208     goto out;
00209 
00210   _err = 0;
00211   retval = ccred->credentials;
00212 
00213 out:
00214   if (err != NULL)
00215     *err = _err;
00216   return retval;
00217 }
00218 
00219 /*-
00220   * MHD_gtls_get_auth_info - Returns a pointer to authentication information.
00221   * @session: is a #MHD_gtls_session_t structure.
00222   *
00223   * This function must be called after a succesful MHD__gnutls_handshake().
00224   * Returns a pointer to authentication information. That information
00225   * is data obtained by the handshake protocol, the key exchange algorithm,
00226   * and the TLS extensions messages.
00227   *
00228   * In case of GNUTLS_CRD_CERTIFICATE returns a type of &cert_auth_info_t;
00229   * In case of GNUTLS_CRD_SRP returns a type of &srp_(server/client)_auth_info_t;
00230   -*/
00231 void *
00232 MHD_gtls_get_auth_info (MHD_gtls_session_t session)
00233 {
00234   return session->key->auth_info;
00235 }
00236 
00237 /*-
00238   * MHD_gtls_free_auth_info - Frees the auth info structure
00239   * @session: is a #MHD_gtls_session_t structure.
00240   *
00241   * This function frees the auth info structure and sets it to
00242   * null. It must be called since some structures contain malloced
00243   * elements.
00244   -*/
00245 void
00246 MHD_gtls_free_auth_info (MHD_gtls_session_t session)
00247 {
00248   MHD_gtls_dh_info_st *dh_info;
00249   rsa_info_st *rsa_info;
00250 
00251   if (session == NULL || session->key == NULL)
00252     {
00253       MHD_gnutls_assert ();
00254       return;
00255     }
00256 
00257   switch (session->key->auth_info_type)
00258     {
00259     case MHD_GNUTLS_CRD_CERTIFICATE:
00260       {
00261         unsigned int i;
00262         cert_auth_info_t info = MHD_gtls_get_auth_info (session);
00263 
00264         if (info == NULL)
00265           break;
00266 
00267         dh_info = &info->dh;
00268         rsa_info = &info->rsa_export;
00269         for (i = 0; i < info->ncerts; i++)
00270           {
00271             MHD__gnutls_free_datum (&info->raw_certificate_list[i]);
00272           }
00273 
00274         MHD_gnutls_free (info->raw_certificate_list);
00275         info->raw_certificate_list = NULL;
00276         info->ncerts = 0;
00277 
00278         MHD_gtls_free_dh_info (dh_info);
00279         MHD_gtls_free_rsa_info (rsa_info);
00280       }
00281 
00282 
00283       break;
00284     default:
00285       return;
00286 
00287     }
00288 
00289   MHD_gnutls_free (session->key->auth_info);
00290   session->key->auth_info = NULL;
00291   session->key->auth_info_size = 0;
00292   session->key->auth_info_type = 0;
00293 
00294 }
00295 
00296 /* This function will set the auth info structure in the key
00297  * structure.
00298  * If allow change is !=0 then this will allow changing the auth
00299  * info structure to a different type.
00300  */
00301 int
00302 MHD_gtls_auth_info_set (MHD_gtls_session_t session,
00303                         enum MHD_GNUTLS_CredentialsType type, int size,
00304                         int allow_change)
00305 {
00306   if (session->key->auth_info == NULL)
00307     {
00308       session->key->auth_info = MHD_gnutls_calloc (1, size);
00309       if (session->key->auth_info == NULL)
00310         {
00311           MHD_gnutls_assert ();
00312           return GNUTLS_E_MEMORY_ERROR;
00313         }
00314       session->key->auth_info_type = type;
00315       session->key->auth_info_size = size;
00316     }
00317   else
00318     {
00319       if (allow_change == 0)
00320         {
00321           /* If the credentials for the current authentication scheme,
00322            * are not the one we want to set, then it's an error.
00323            * This may happen if a rehandshake is performed an the
00324            * ciphersuite which is negotiated has different authentication
00325            * schema.
00326            */
00327           if (MHD_gtls_auth_get_type (session) !=
00328               session->key->auth_info_type)
00329             {
00330               MHD_gnutls_assert ();
00331               return GNUTLS_E_INVALID_REQUEST;
00332             }
00333         }
00334       else
00335         {
00336           /* The new behaviour: Here we reallocate the auth info structure
00337            * in order to be able to negotiate different authentication
00338            * types. Ie. perform an auth_anon and then authenticate again using a
00339            * certificate (in order to prevent revealing the certificate's contents,
00340            * to passive eavesdropers.
00341            */
00342           if (MHD_gtls_auth_get_type (session) !=
00343               session->key->auth_info_type)
00344             {
00345 
00346               MHD_gtls_free_auth_info (session);
00347 
00348               session->key->auth_info = calloc (1, size);
00349               if (session->key->auth_info == NULL)
00350                 {
00351                   MHD_gnutls_assert ();
00352                   return GNUTLS_E_MEMORY_ERROR;
00353                 }
00354 
00355               session->key->auth_info_type = type;
00356               session->key->auth_info_size = size;
00357             }
00358         }
00359     }
00360   return 0;
00361 }
Generated by  doxygen 1.6.2-20100208