Back to index

courier  0.68.2
Classes | Defines | Functions | Variables
libcouriergnutls.c File Reference
#include "config.h"
#include "argparse.h"
#include "spipe.h"
#include "libcouriertls.h"
#include "tlscache.h"
#include "soxwrap/soxwrap.h"
#include <gnutls/gnutls.h>
#include <gnutls/extra.h>
#include <gnutls/x509.h>
#include <gnutls/openpgp.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <netdb.h>
#include <errno.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/time.h>

Go to the source code of this file.

Classes

struct  oid_name
struct  intmap
struct  ssl_context_t
struct  ssl_handle_t
struct  cert_buf_ptr
struct  db_retrieve_s

Defines

#define dirent   direct
#define NAMLEN(dirent)   (dirent)->d_namlen

Functions

static void nonsslerror (struct tls_info *info, const char *pfix)
static const char * safe_getenv (ssl_context context, const char *n, const char *def)
static char ** splitwords (const char *var, size_t *nwords)
static void splitwords_free (char **words)
static void addremove (int *cipher_list_out, int removeit, int n)
static void parse_map (const struct intmap *mapptr, char **tokens, int *tokens_out, int is_ciphers)
ssl_context tls_create (int isserver, const struct tls_info *info)
void tls_destroy (ssl_context p)
int tls_certificate_verified (ssl_handle ssl)
static int read_cert_dir (const char *cert_dir, int(*cb_func)(const char *filename, struct stat *stat_buf, void *arg), void *arg)
static int cnt_cert_size (const char *filename, struct stat *stat_buf, void *arg)
static int save_cert_to_buf (const char *filename, struct stat *stat_buf, void *arg)
static int add_certificates (gnutls_certificate_credentials_t xcred, const char *certfile)
static void tls_free_session_keys (ssl_handle ssl)
static void tls_free_session (ssl_handle ssl)
static int chk_error (int rc, ssl_handle ssl, int fd, fd_set *r, fd_set *w, int *result_rc)
static int verify_client (ssl_handle ssl, int fd)
static int dohandshake (ssl_handle ssl, int fd, fd_set *r, fd_set *w)
static char * check_cert (const char *filename, gnutls_certificate_type_t cert_type, const char *req_dn, int isvirtual)
static int read_file (const char *file, gnutls_datum *filebuf)
static void release_file (gnutls_datum *filebuf)
static int set_cert (ssl_handle ssl, gnutls_session_t session, gnutls_retr_st *st, const char *certfilename)
static int get_server_cert (gnutls_session_t session, gnutls_retr_st *st)
static int pick_client_cert (gnutls_session_t session, const gnutls_datum_t *req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t *sign_algos, int sign_algos_length, gnutls_retr_st *st)
static int get_client_cert (gnutls_session_t session, const gnutls_datum_t *req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t *sign_algos, int sign_algos_length, gnutls_retr_st *st)
static int read_dh_params (gnutls_dh_params_t dhparams, const char *filename)
static int db_store_func (void *dummy, gnutls_datum_t key, gnutls_datum_t data)
static int do_cache_remove (void *rec, size_t recsize, int *doupdate, void *arg)
static int db_remove_func (void *dummy, gnutls_datum_t key)
static int do_cache_retrieve (void *rec, size_t recsize, int *doupdate, void *arg)
static gnutls_datum_t db_retrieve_func (void *dummy, gnutls_datum_t key)
ssl_handle tls_connect (ssl_context ctx, int fd)
void tls_disconnect (ssl_handle ssl, int fd)
int tls_transfer (struct tls_transfer_info *t, ssl_handle ssl, int fd, fd_set *r, fd_set *w)
int tls_connecting (ssl_handle ssl)
static const char * dump_dn (gnutls_x509_crt_t cert, int(*get_dn_func)(gnutls_x509_crt_t cert, int indx, void *oid, size_t *sizeof_oid), int(*get_dnval_func)(gnutls_x509_crt_t cert, const char *oid, int indx, unsigned int raw_flag, void *buf, size_t *sizeof_buf), void(*dump_func)(const char *, int cnt, void *), void *dump_arg)
static void print_time (const char *name, time_t t, void(*dump_func)(const char *, int cnt, void *), void *dump_arg)
static void tls_dump_connection_info_x509 (ssl_handle ssl, int server, void(*dump_func)(const char *, int cnt, void *), void *dump_arg)
static void dump_cipher_name (gnutls_session_t session, void(*dump_func)(const char *, int cnt, void *), void *dump_arg)
void tls_dump_connection_info (ssl_handle ssl, int server, void(*dump_func)(const char *, int cnt, void *), void *dump_arg)
static void gen_encryption_desc (gnutls_session_t session, void(*dump_func)(const char *, int cnt, void *), void *dump_arg)
static void cnt_desc_size (const char *str, int s, void *ptr)
static void save_desc (const char *str, int s, void *ptr)
char * tls_get_encryption_desc (ssl_handle ssl)
int tls_validate_pem_cert (const char *buf, size_t buf_size)
char * tls_cert_name (const char *buf, size_t buf_size)

Variables

static struct oid_name []
static struct intmap all_ciphers []
static struct intmap all_kxs []
static struct intmap all_comps []
static struct intmap all_certs []

Class Documentation

struct oid_name

Definition at line 54 of file libcouriergnutls.c.

Class Members
const char * name
const char * oid
struct intmap

Definition at line 121 of file libcouriergnutls.c.

Class Members
int algo
const char * name
struct ssl_context_t

Definition at line 158 of file libcouriergnutls.c.

Class Members
int cert_list
char * certfile
int certfiledh
int cipher_list
int comp_list
int fail_if_no_cert
int isserver
int kx_list
int * protocol_list
char * trustcerts
int verify_cert
struct ssl_handle_t

Definition at line 176 of file libcouriergnutls.c.

Collaboration diagram for ssl_handle_t:
Class Members
gnutls_anon_client_credentials_t anonclientcred
gnutls_anon_server_credentials_t anonservercred
ssl_context ctx
gnutls_dh_params_t dhparams
gnutls_openpgp_key_t pgp_crt
gnutls_openpgp_privkey_t pgp_key
gnutls_session_t session
gnutls_x509_privkey x509_key
gnutls_certificate_credentials_t xcred
struct cert_buf_ptr

Definition at line 646 of file libcouriergnutls.c.

Class Members
size_t cnt
char * ptr
struct db_retrieve_s

Definition at line 1522 of file libcouriergnutls.c.

Class Members
gnutls_datum_t * key
gnutls_datum_t ret

Define Documentation

#define dirent   direct

Definition at line 24 of file libcouriergnutls.c.

#define NAMLEN (   dirent)    (dirent)->d_namlen

Definition at line 25 of file libcouriergnutls.c.


Function Documentation

static int add_certificates ( gnutls_certificate_credentials_t  xcred,
const char *  certfile 
) [static]

Definition at line 679 of file libcouriergnutls.c.

{
       struct stat stat_buf;
       struct cert_buf_ptr ptr;
       gnutls_datum_t datum_ptr;

       if (!certfile || !*certfile || stat(certfile, &stat_buf) < 0)
              return 0;

       if (S_ISREG(stat_buf.st_mode))
       {
              return gnutls_certificate_set_x509_trust_file(xcred, certfile,
                                                       GNUTLS_X509_FMT_PEM);
       }

       if (!S_ISDIR(stat_buf.st_mode))
              return 0;

       ptr.cnt=0;

       if (read_cert_dir(certfile, cnt_cert_size, &ptr.cnt))
              return 0;

       datum_ptr.data=malloc(ptr.cnt+1);
       datum_ptr.size=ptr.cnt;

       if (!datum_ptr.data)
              return 0;

       ptr.ptr=(char *)datum_ptr.data;

       if (read_cert_dir(certfile, save_cert_to_buf, &ptr) ||
           ptr.cnt)
       {
              free(datum_ptr.data);
              return 0;
       }
       *ptr.ptr=0;

       gnutls_certificate_set_x509_trust_mem(xcred, &datum_ptr,
                                         GNUTLS_X509_FMT_PEM);
       free(datum_ptr.data);

       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void addremove ( int *  cipher_list_out,
int  removeit,
int  n 
) [static]

Definition at line 272 of file libcouriergnutls.c.

{
       if (removeit)
       {
              int *p=cipher_list_out;

              while (*cipher_list_out)
              {
                     if (*cipher_list_out != n)
                            *p++ = *cipher_list_out;
                     ++cipher_list_out;
              }
              *p=0;
              return;
       }

       while (*cipher_list_out)
       {
              if (*cipher_list_out == n)
                     return;
              ++cipher_list_out;
       }

       *cipher_list_out++ =n;
       *cipher_list_out=0;
}

Here is the caller graph for this function:

static char* check_cert ( const char *  filename,
gnutls_certificate_type_t  cert_type,
const char *  req_dn,
int  isvirtual 
) [static]

Definition at line 1052 of file libcouriergnutls.c.

{
       if (!filename || !*filename)
              return NULL;

       while (*req_dn)
       {
              char *p=malloc(strlen(filename)+strlen(req_dn)+10);

              if (!p)
                     return NULL;

              strcat(strcat(strcpy(p, filename), "."), req_dn);

              if (cert_type == GNUTLS_CRT_OPENPGP)
                     strcat(p, ".pgp");

              if (access(p, R_OK) == 0)
                     return p;

              free(p);

              if (!isvirtual)
                     break;

              if ((req_dn=strchr(req_dn, '.')) == NULL)
                     break;
              ++req_dn;
       }

       {
              char *p=malloc(strlen(filename)+10);

              if (!p)
                     return NULL;

              strcpy(p, filename);

              if (cert_type == GNUTLS_CRT_OPENPGP)
                     strcat(p, ".pgp");

              if (access(p, R_OK) == 0)
                     return p;

              free(p);
       }
       return NULL;
}

Here is the caller graph for this function:

static int chk_error ( int  rc,
ssl_handle  ssl,
int  fd,
fd_set *  r,
fd_set *  w,
int *  result_rc 
) [static]

Definition at line 754 of file libcouriergnutls.c.

{
       if (rc == GNUTLS_E_SUCCESS)
       {
              if (result_rc)
                     *result_rc=0;
              return 0;
       }

       if (rc == GNUTLS_E_WARNING_ALERT_RECEIVED)
              return 1;

       if (rc == GNUTLS_E_FATAL_ALERT_RECEIVED)
       {
              const char *alert=
                     gnutls_alert_get_name(gnutls_alert_get(ssl->session));
              (*ssl->info_cpy.tls_err_msg)(alert, ssl->info_cpy.app_data);

              if (result_rc)
                     *result_rc= -1;
              return 0;
       }

       if (rc == GNUTLS_E_AGAIN || rc == GNUTLS_E_INTERRUPTED)
       {
              fd_set *p=gnutls_record_get_direction(ssl->session)
                     ? w:r;

              if (p)
                     FD_SET(fd, p);

              if (result_rc)
                     *result_rc=1;
              return 0;
       }

       if (result_rc)
       {
              (*ssl->info_cpy.tls_err_msg)(gnutls_strerror(rc),
                                        ssl->info_cpy.app_data);
              *result_rc= -1;
       }
       return 0;
}

Here is the caller graph for this function:

static int cnt_cert_size ( const char *  filename,
struct stat stat_buf,
void *  arg 
) [static]

Definition at line 638 of file libcouriergnutls.c.

{
       *(size_t *)arg += stat_buf->st_size;
       return 0;
}

Here is the caller graph for this function:

static void cnt_desc_size ( const char *  str,
int  s,
void *  ptr 
) [static]

Definition at line 2210 of file libcouriergnutls.c.

{
       if (s < 0)
              s=strlen(str);

       *(size_t *)ptr += s;
}

Here is the caller graph for this function:

static int db_remove_func ( void *  dummy,
gnutls_datum_t  key 
) [static]

Definition at line 1515 of file libcouriergnutls.c.

{
       tls_cache_walk(((ssl_handle)dummy)->info_cpy.tlscache,
                     do_cache_remove, &key);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static gnutls_datum_t db_retrieve_func ( void *  dummy,
gnutls_datum_t  key 
) [static]

Definition at line 1562 of file libcouriergnutls.c.

{
       struct db_retrieve_s drs;

       drs.ret.data=NULL;
       drs.ret.size=0;
       drs.key= &key;

       tls_cache_walk(((ssl_handle)dummy)->info_cpy.tlscache,
                     do_cache_retrieve, &drs);
       return drs.ret;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int db_store_func ( void *  dummy,
gnutls_datum_t  key,
gnutls_datum_t  data 
) [static]

Definition at line 1473 of file libcouriergnutls.c.

{
       char *p=malloc(key.size + data.size + sizeof(int));

       if (!p)
              return -1;

       memcpy(p, &key.size, sizeof(key.size));
       memcpy(p+sizeof(key.size), key.data, key.size);
       memcpy(p+sizeof(key.size)+key.size, data.data, data.size);

       tls_cache_add(((ssl_handle)dummy)->info_cpy.tlscache, p,
                    key.size + data.size + sizeof(int));
       free(p);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int do_cache_remove ( void *  rec,
size_t  recsize,
int *  doupdate,
void *  arg 
) [static]

Definition at line 1491 of file libcouriergnutls.c.

{
       char *recptr=rec;
       gnutls_datum_t *key=(gnutls_datum_t *)arg;

       if (recsize >= key->size + sizeof(key->size))
       {
              gnutls_datum_t dummy;

              memcpy(&dummy.size, recptr, sizeof(dummy.size));

              if (dummy.size == key->size &&
                  memcmp(recptr + sizeof(key->size),
                        key->data, key->size) == 0)
              {
                     dummy.size= -1;
                     memcpy(recptr, &dummy.size, sizeof(dummy.size));
                     *doupdate=1;
                     return 1;
              }
       }
       return 0;
}

Here is the caller graph for this function:

static int do_cache_retrieve ( void *  rec,
size_t  recsize,
int *  doupdate,
void *  arg 
) [static]

Definition at line 1527 of file libcouriergnutls.c.

{
       char *recptr=rec;
       struct db_retrieve_s *ret=(struct db_retrieve_s *)arg;

       if (recsize >= ret->key->size + sizeof(ret->key->size))
       {
              gnutls_datum_t dummy;

              memcpy(&dummy.size, recptr, sizeof(dummy.size));

              if (dummy.size == ret->key->size &&
                  memcmp(recptr+sizeof(dummy.size),
                        ret->key->data,
                        ret->key->size) == 0)
              {
                     ret->ret.size=recsize-sizeof(dummy.size)-ret->key->size;

                     ret->ret.data=gnutls_malloc(ret->ret.size);

                     if (ret->ret.data)
                            memcpy(ret->ret.data,
                                   (void *)(recptr+sizeof(dummy.size)
                                          +ret->key->size),
                                   ret->ret.size);
                     else
                            ret->ret.size=0;

                     return 1;
              }
       }
       return 0;
}

Here is the caller graph for this function:

static int dohandshake ( ssl_handle  ssl,
int  fd,
fd_set *  r,
fd_set *  w 
) [static]

Definition at line 1028 of file libcouriergnutls.c.

{
       int rc;

       while (chk_error(gnutls_handshake(ssl->session),
                      ssl, fd, r, w, &rc))
              ;

       if (rc == 0)
       {
              ssl->info_cpy.connect_interrupted=0;

              
              if (verify_client(ssl, fd))
                     return -1;

              if (ssl->info_cpy.connect_callback != NULL &&
                  !(*ssl->info_cpy.connect_callback)(ssl,
                                                 ssl->info_cpy.app_data))
                     return (-1);
       }
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void dump_cipher_name ( gnutls_session_t  session,
void(*)(const char *, int cnt, void *)  dump_func,
void *  dump_arg 
) [static]

Definition at line 2095 of file libcouriergnutls.c.

{
       gnutls_kx_algorithm_t kx_algo;
       gnutls_cipher_algorithm_t cipher_algo;
       gnutls_mac_algorithm_t mac_algo;
       const char *cipher_name;

       kx_algo=gnutls_kx_get(session);
       cipher_algo=gnutls_cipher_get(session);
       mac_algo=gnutls_mac_get(session);
       cipher_name=gnutls_cipher_suite_get_name(kx_algo, cipher_algo,
                                           mac_algo);

       if (cipher_name)
              (*dump_func)(cipher_name, -1, dump_arg);
       else
       {
              gnutls_compression_method_t comp;

              (*dump_func)(gnutls_kx_get_name(kx_algo), -1, dump_arg);
              
              (*dump_func)("-", 1, dump_arg);
              (*dump_func)(gnutls_certificate_type_get_name(gnutls_certificate_type_get(session)),
                          -1, dump_arg);

              (*dump_func)("-", 1, dump_arg);
              (*dump_func)(gnutls_cipher_get_name(cipher_algo), -1,
                          dump_arg);

              if ((comp=gnutls_compression_get(session))
                  != GNUTLS_COMP_NULL)
              {
                     (*dump_func)("/", 1, dump_arg);
                     (*dump_func)(gnutls_compression_get_name(comp),
                                 -1, dump_arg);
              }

              (*dump_func)("-", 1, dump_arg);
              (*dump_func)(gnutls_mac_get_name(gnutls_mac_get(session)),
                          -1, dump_arg);
       }
}

Here is the caller graph for this function:

static const char* dump_dn ( gnutls_x509_crt_t  cert,
int(*)(gnutls_x509_crt_t cert, int indx, void *oid, size_t *sizeof_oid)  get_dn_func,
int(*)(gnutls_x509_crt_t cert, const char *oid, int indx, unsigned int raw_flag, void *buf, size_t *sizeof_buf)  get_dnval_func,
void(*)(const char *, int cnt, void *)  dump_func,
void *  dump_arg 
) [static]

Definition at line 1917 of file libcouriergnutls.c.

{
       int idx;
       size_t bufsiz;
       size_t maxnamesize;
       size_t maxvalsize;
       char *oidname;
       char *oidval;
       int oidcnt;

       maxnamesize=0;
       maxvalsize=0;

       oidcnt=0;

       while (bufsiz=0, (*get_dn_func)(cert, oidcnt, NULL, &bufsiz)
              == GNUTLS_E_SHORT_MEMORY_BUFFER)
       {
              if (bufsiz > maxnamesize)
                     maxnamesize=bufsiz;
              ++oidcnt;
       }

       oidname=malloc(maxnamesize);

       if (!oidname)
              return strerror(errno);

       for (idx=0; idx<oidcnt; ++idx)
       {
              int vidx;
              int rc;

              bufsiz=maxnamesize;

              if ((rc=(*get_dn_func)(cert, idx, oidname, &bufsiz)) < 0)
              {
                     free(oidname);
                     return gnutls_strerror(rc);
              }
       
              vidx=0;

              while (bufsiz=0,
                     (*get_dnval_func)(cert, oidname, vidx, 0,
                                    NULL, &bufsiz)
                     == GNUTLS_E_SHORT_MEMORY_BUFFER)
              {
                     if (bufsiz > maxvalsize)
                            maxvalsize=bufsiz;
                     ++vidx;
              }
       }

       oidval=malloc(maxvalsize);

       if (!oidval)
       {
              free(oidname);
              return strerror(errno);
       }

       for (idx=0; idx<oidcnt; ++idx)
       {
              int vidx;
              int rc;
              size_t i;
              const char *oidname_str;

              bufsiz=maxnamesize;

              if ((rc=(*get_dn_func)(cert, idx, oidname, &bufsiz)) < 0)
              {
                     free(oidval);
                     free(oidname);
                     return gnutls_strerror(rc);
              }

              oidname_str=oidname;

              for (i=0; i<sizeof(oid_name_list)/sizeof(oid_name_list[0]);
                   ++i)
              {
                     if (strcmp(oid_name_list[i].oid, oidname) == 0)
                     {
                            oidname_str=oid_name_list[i].name;
                            break;
                     }
              }

              vidx=0;

              while (bufsiz=maxvalsize,
                     (*get_dnval_func)(cert, oidname, vidx, 0,
                                    oidval, &bufsiz) >= 0)
              {
                     (*dump_func)("   ", -1, dump_arg);
                     (*dump_func)(oidname_str, -1, dump_arg);
                     (*dump_func)("=", -1, dump_arg);
                     (*dump_func)(oidval, -1, dump_arg);
                     (*dump_func)("\n", -1, dump_arg);
                     ++vidx;
              }
       }
       
       free(oidval);
       free(oidname);
       return NULL;
}

Here is the caller graph for this function:

static void gen_encryption_desc ( gnutls_session_t  session,
void(*)(const char *, int cnt, void *)  dump_func,
void *  dump_arg 
) [static]

Definition at line 2245 of file libcouriergnutls.c.

{
       char buf[10];

       (*dump_func)(gnutls_protocol_get_name(gnutls_protocol_get_version(session)),
                   -1, dump_arg);
       (*dump_func)(",", 1, dump_arg);
       snprintf(buf, sizeof(buf), "%d",
               (int)gnutls_cipher_get_key_size(gnutls_cipher_get(session))
               *8);
       buf[sizeof(buf)-1]=0;
       (*dump_func)(buf, -1, dump_arg);
       (*dump_func)("bits,", -1, dump_arg);
       dump_cipher_name(session, dump_func, dump_arg);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_client_cert ( gnutls_session_t  session,
const gnutls_datum_t *  req_ca_rdn,
int  nreqs,
const gnutls_pk_algorithm_t *  sign_algos,
int  sign_algos_length,
gnutls_retr_st *  st 
) [static]

Definition at line 1420 of file libcouriergnutls.c.

{
       ssl_handle ssl=(ssl_handle)gnutls_session_get_ptr(session);
       int rc;
       char *certfilename=NULL;

       rc= 0;
       st->type=gnutls_certificate_type_get(session);

       if (ssl->ctx->certfile)
              certfilename=check_cert(ssl->ctx->certfile,
                                   st->type, "", 0);

       st->ncerts=0;
       st->deinit_all=0;

       if (certfilename)
       {
              rc=set_cert(ssl, session, st, certfilename);
              free(certfilename);
       }
       else
       {
              rc=pick_client_cert(session, req_ca_rdn, nreqs, sign_algos,
                                sign_algos_length, st);
              if (rc > 0)
                     rc=0;
       }
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int get_server_cert ( gnutls_session_t  session,
gnutls_retr_st *  st 
) [static]

Definition at line 1218 of file libcouriergnutls.c.

{
       ssl_handle ssl=(ssl_handle)gnutls_session_get_ptr(session);
       int vhost_idx;
       char *vhost_buf;
       size_t vhost_max_size=0;
       size_t vhost_size;
       unsigned int type=GNUTLS_NAME_DNS;
       char *certfilename=NULL;
       int rc;

       st->type=gnutls_certificate_type_get(session);

       for (vhost_idx=0; vhost_size=0,
                   gnutls_server_name_get(session, NULL, &vhost_size, &type,
                                       vhost_idx) ==
                   GNUTLS_E_SHORT_MEMORY_BUFFER; ++vhost_idx)
       {
              if (++vhost_size > vhost_max_size)
                     vhost_max_size=vhost_size;
       }

       vhost_buf=malloc(vhost_size);

       if (!vhost_buf)
              return GNUTLS_E_MEMORY_ERROR;

       for (vhost_idx=0; vhost_size=vhost_max_size,
                   gnutls_server_name_get(session, vhost_buf, &vhost_size,
                                       &type,
                                       vhost_idx) == GNUTLS_E_SUCCESS;
            ++vhost_idx)
       {
              if (ssl->ctx->certfile)
                     certfilename=check_cert(ssl->ctx->certfile,
                                          st->type,
                                          vhost_buf, 1);

              if (certfilename)
                     break;
       }

       if (!certfilename)
       {
              if (ssl->ctx->certfile)
                     certfilename=check_cert(ssl->ctx->certfile,
                                          st->type,
                                          safe_getenv(ssl->ctx,
                                                     "TCPLOCALIP", ""),
                                          0);
       }

       if (!certfilename)
              return 0;

       rc=set_cert(ssl, session, st, certfilename);
       free(certfilename);
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void nonsslerror ( struct tls_info info,
const char *  pfix 
) [static]

Definition at line 191 of file libcouriergnutls.c.

{
        char errmsg[256];

        strcpy(errmsg, "couriertls: ");
        strncat(errmsg, pfix, 200);
        strcat(errmsg, ": ");
        strncat(errmsg, strerror(errno), 255 - strlen(errmsg));

        (*info->tls_err_msg)(errmsg, info->app_data);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void parse_map ( const struct intmap mapptr,
char **  tokens,
int *  tokens_out,
int  is_ciphers 
) [static]

Definition at line 301 of file libcouriergnutls.c.

{
       size_t i;

       *tokens_out=0;

       for (i=0; tokens[i]; i++)
       {
              size_t j;
              int removeit=0;
              const char *name=tokens[i];

              if (*name == '-')
              {
                     ++name;
                     removeit=1;
              }

              for (j=0; mapptr[j].name; j++)
              {
                     if (strcmp(name, mapptr[j].name) == 0)
                     {
                            addremove(tokens_out, removeit,
                                     mapptr[j].algo);
                            continue;
                     }

                     if (is_ciphers && strcmp(name, "HIGH") == 0 &&
                         gnutls_cipher_get_key_size(mapptr[j].algo)
                                > 128 / 8)
                     {
                            addremove(tokens_out, removeit,
                                     mapptr[j].algo);
                            continue;
                     }

                     if (is_ciphers && strcmp(name, "MEDIUM") == 0 &&
                         gnutls_cipher_get_key_size(mapptr[j].algo)
                                == 128 / 8)
                     {
                            addremove(tokens_out, removeit,
                                     mapptr[j].algo);
                            continue;
                     }

                     if (is_ciphers && strcmp(name, "LOW") == 0 &&
                         gnutls_cipher_get_key_size(mapptr[j].algo)
                                < 128 / 8 &&
                         gnutls_cipher_get_key_size(mapptr[j].algo)
                         > 0)
                     {
                            addremove(tokens_out, removeit,
                                     mapptr[j].algo);
                            continue;
                     }

                     if (strcmp(name, "ALL") == 0 &&
                         (!is_ciphers ||
                          gnutls_cipher_get_key_size(mapptr[j].algo)
                          > 0))
                     {
                            addremove(tokens_out, removeit,
                                     mapptr[j].algo);
                            continue;
                     }
              }
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int pick_client_cert ( gnutls_session_t  session,
const gnutls_datum_t *  req_ca_rdn,
int  nreqs,
const gnutls_pk_algorithm_t *  sign_algos,
int  sign_algos_length,
gnutls_retr_st *  st 
) [static]

Definition at line 1280 of file libcouriergnutls.c.

{
       ssl_handle ssl=(ssl_handle)gnutls_session_get_ptr(session);
       int i, j;
       const char *cert_array;
       size_t cert_array_size;
       int rc=0;

       if (ssl->info_cpy.getpemclientcert4ca == NULL)
              return 0;

       if (st->type != GNUTLS_CRT_X509)
              return 0;

       if (ssl->info_cpy.loadpemclientcert4ca)
              (*ssl->info_cpy.loadpemclientcert4ca)(ssl->info_cpy.app_data);

       for (j=0; (*ssl->info_cpy.getpemclientcert4ca)(j, &cert_array,
                                                 &cert_array_size,
                                                 ssl->info_cpy.app_data);
            ++j)
       {
              gnutls_datum_t data;
              unsigned int cert_cnt=0;
              gnutls_x509_crt_t *certbuf;
              size_t issuer_buf_size=0;
              char *issuer_rdn;
              gnutls_x509_privkey pk;

              data.data=(unsigned char *)cert_array;
              data.size=cert_array_size;
              gnutls_x509_privkey_init(&pk);
              if (gnutls_x509_privkey_import(pk, &data,
                                          GNUTLS_X509_FMT_PEM)
                  != GNUTLS_E_SUCCESS)
              {
                     gnutls_x509_privkey_deinit(pk);
                     continue;
              }

              data.data=(void *)cert_array;
              data.size=cert_array_size;;

              gnutls_x509_crt_list_import(NULL, &cert_cnt, &data,
                                       GNUTLS_X509_FMT_PEM,
                                       GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);
              if (cert_cnt == 0)
              {
                     gnutls_x509_privkey_deinit(pk);
                     continue;
              }

              certbuf=gnutls_malloc(sizeof(*certbuf)*cert_cnt);

              if (!certbuf)
              {
                     gnutls_x509_privkey_deinit(pk);
                     continue;
              }

              if (gnutls_x509_crt_list_import(certbuf, &cert_cnt, &data,
                                          GNUTLS_X509_FMT_PEM,
                                          GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED) < 0)
              {
                     free(certbuf);
                     gnutls_x509_privkey_deinit(pk);
                     continue;
              }


              gnutls_x509_crt_get_issuer_dn(certbuf[0], NULL,
                                         &issuer_buf_size);

              ++issuer_buf_size;

              issuer_rdn=gnutls_malloc(issuer_buf_size+1);

              if (gnutls_x509_crt_get_issuer_dn(certbuf[0], issuer_rdn,
                                            &issuer_buf_size)
                  != GNUTLS_E_SUCCESS)
              {
                     gnutls_free(issuer_rdn);
                     issuer_rdn=0;
              }
              else
                     issuer_rdn[issuer_buf_size]=0;

              for (i=0; issuer_rdn && i<nreqs; i++)
              {
                     size_t buf_size=0;
                     char *ca_rdn;

                     gnutls_x509_rdn_get(&req_ca_rdn[i], NULL, &buf_size);

                     ++buf_size;

                     ca_rdn=gnutls_malloc(buf_size+1);

                     if (gnutls_x509_rdn_get(&req_ca_rdn[i], ca_rdn, &buf_size) !=
                         GNUTLS_E_SUCCESS)
                     {
                            gnutls_free(ca_rdn);
                            continue;
                     }

                     ca_rdn[buf_size]=0;

                     if (strcmp(ca_rdn, issuer_rdn) == 0)
                            break;
                     gnutls_free(ca_rdn);
              }

              st->ncerts=0;
              if (issuer_rdn && i < nreqs)
              {
                     st->cert.x509=certbuf;
                     st->ncerts=cert_cnt;
                     st->deinit_all=1;
                     st->key.x509=pk;
                     cert_cnt=0;
                     rc=1;
              }
              else
              {
                     gnutls_x509_privkey_deinit(pk);
                     while (cert_cnt)
                            gnutls_x509_crt_deinit(certbuf[--cert_cnt]);
                     gnutls_free(certbuf);
              }
              gnutls_free(issuer_rdn);
              if (rc)
                     break;
       }

       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void print_time ( const char *  name,
time_t  t,
void(*)(const char *, int cnt, void *)  dump_func,
void *  dump_arg 
) [static]

Definition at line 2035 of file libcouriergnutls.c.

{
       struct tm *tmptr=gmtime(&t);
       char buf[256];

       strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", tmptr);

       (*dump_func)(name, -1, dump_arg);
       (*dump_func)(": ", 2, dump_arg);
       (*dump_func)(buf, -1, dump_arg);
       (*dump_func)("\n", 1, dump_arg);
}

Here is the caller graph for this function:

static int read_cert_dir ( const char *  cert_dir,
int(*)(const char *filename, struct stat *stat_buf, void *arg)  cb_func,
void *  arg 
) [static]

Definition at line 595 of file libcouriergnutls.c.

{
       DIR *dirp;
       struct dirent *de;
       int rc=0;

       if ((dirp=opendir(cert_dir)) == NULL)
              return 0;

       while ((de=readdir(dirp)) != NULL)
       {
              char *buf;
              struct stat stat_buf;

              if (de->d_name[0] == '.')
                     continue;

              buf=malloc(strlen(cert_dir)+strlen(de->d_name)+2);

              if (!buf)
                     continue;

              strcat(strcat(strcpy(buf, cert_dir), "/"), de->d_name);

              if (lstat(buf, &stat_buf) < 0 || !S_ISREG(stat_buf.st_mode))
              {
                     free(buf);
                     continue;
              }

              rc=(*cb_func)(buf, &stat_buf, arg);
              free(buf);
              if (rc)
                     break;
       }
       closedir(dirp);
       return rc;
}

Here is the caller graph for this function:

static int read_dh_params ( gnutls_dh_params_t  dhparams,
const char *  filename 
) [static]

Definition at line 1455 of file libcouriergnutls.c.

{
       int rc;

       gnutls_datum_t filebuf;

       rc=read_file(filename, &filebuf);

       if (rc == 0)
       {
              rc=gnutls_dh_params_import_pkcs3(dhparams, &filebuf,
                                           GNUTLS_X509_FMT_PEM);
              release_file(&filebuf);
       }
       return rc;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int read_file ( const char *  file,
gnutls_datum *  filebuf 
) [static]

Definition at line 1104 of file libcouriergnutls.c.

{
       FILE *fp;
       struct stat stat_buf;

       filebuf->data=NULL;

       if ((fp=fopen(file, "r")) == NULL ||
           fstat(fileno(fp), &stat_buf) < 0)
       {
              if (fp)
                     fclose(fp);
              return GNUTLS_E_FILE_ERROR;
       }

       if ((filebuf->data=malloc(stat_buf.st_size)) == NULL)
       {
              fclose(fp);
              return GNUTLS_E_MEMORY_ERROR;
       }

       if (fread(filebuf->data, filebuf->size=stat_buf.st_size, 1, fp) != 1)
       {
              if (fp)
                     fclose(fp);
              return GNUTLS_E_FILE_ERROR;
       }
       return 0;
}

Here is the caller graph for this function:

static void release_file ( gnutls_datum *  filebuf) [static]

Definition at line 1135 of file libcouriergnutls.c.

{
       if (filebuf->data)
              free(filebuf->data);
       filebuf->data=NULL;
}

Here is the caller graph for this function:

static const char* safe_getenv ( ssl_context  context,
const char *  n,
const char *  def 
) [static]

Definition at line 203 of file libcouriergnutls.c.

{
       const char *v=(*context->info_cpy.getconfigvar)
              (n, context->info_cpy.app_data);

       if (!v)       v="";

       if (!*v)
              v=def;
       return (v);
}

Here is the caller graph for this function:

static int save_cert_to_buf ( const char *  filename,
struct stat stat_buf,
void *  arg 
) [static]

Definition at line 651 of file libcouriergnutls.c.

{
       struct cert_buf_ptr *p=(struct cert_buf_ptr *)arg;
       FILE *fp;

       if (p->cnt < stat_buf->st_size)
              return 1;

       fp=fopen(filename, "r");

       if (fp)
       {
              if (stat_buf->st_size &&
                  fread(p->ptr, stat_buf->st_size, 1, fp) != 1)
              {
                     fclose(fp);
                     return 1;
              }
              fclose(fp);
       }
       p->ptr += stat_buf->st_size;
       p->cnt -= stat_buf->st_size;
       return 0;
}

Here is the caller graph for this function:

static void save_desc ( const char *  str,
int  s,
void *  ptr 
) [static]

Definition at line 2218 of file libcouriergnutls.c.

{
       if (s < 0)
              s=strlen(str);

       memcpy(*(char **)ptr, str, s);
       *(char **)ptr += s;
}

Here is the caller graph for this function:

static int set_cert ( ssl_handle  ssl,
gnutls_session_t  session,
gnutls_retr_st *  st,
const char *  certfilename 
) [static]

Definition at line 1142 of file libcouriergnutls.c.

{
       int rc;
       gnutls_datum filebuf;
       unsigned int cert_cnt;

       st->ncerts=0;
       st->deinit_all=0;
       tls_free_session_keys(ssl);

       if ((rc=read_file(certfilename, &filebuf)) < 0)
              return rc;

       switch (st->type) {
       case GNUTLS_CRT_X509:

              cert_cnt=0;

              if ((rc=gnutls_x509_privkey_init(&ssl->x509_key)) < 0 ||
                  (rc=gnutls_x509_privkey_import(ssl->x509_key, &filebuf,
                                             GNUTLS_X509_FMT_PEM)) < 0)
                     break;

              rc=gnutls_x509_crt_list_import(NULL, &cert_cnt,
                                          &filebuf,
                                          GNUTLS_X509_FMT_PEM,
                                          GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);

              if (rc != GNUTLS_E_SHORT_MEMORY_BUFFER)
                     break;

              st->ncerts=cert_cnt+1;
              st->cert.x509=gnutls_malloc(st->ncerts*sizeof(*st->cert.x509));

              rc=gnutls_x509_crt_list_import(st->cert.x509, &st->ncerts,
                                          &filebuf,
                                          GNUTLS_X509_FMT_PEM, 0);

              if (rc < 0)
              {
                     st->ncerts=0;
                     gnutls_free(st->cert.x509);
                     st->cert.x509=0;
                     break;
              }
              st->ncerts=rc;
              st->key.x509=ssl->x509_key;
              ssl->x509_key=0;
              st->deinit_all=1;

              break;
       case GNUTLS_CRT_OPENPGP:
              if ((rc=gnutls_openpgp_key_init(&ssl->pgp_crt)) < 0 ||
                  (rc=gnutls_openpgp_privkey_init(&ssl->pgp_key)) < 0 ||
                  (rc=gnutls_openpgp_key_import(ssl->pgp_crt, &filebuf,
                                            GNUTLS_OPENPGP_FMT_BASE64))
                  < 0 ||
                  (rc=gnutls_openpgp_privkey_import(ssl->pgp_key, &filebuf,
                                                GNUTLS_OPENPGP_FMT_BASE64,
                                                NULL, 0)) < 0)
                     break;
              st->cert.pgp=ssl->pgp_crt;
              st->ncerts=1;
              st->key.pgp=ssl->pgp_key;
              break;
       default:
              break;
       }

       release_file(&filebuf);
       return 0;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static char** splitwords ( const char *  var,
size_t *  nwords 
) [static]

Definition at line 216 of file libcouriergnutls.c.

{
       char *buf=strdup(var);
       char **ptrbuf;

       char *p;
       size_t cnt;

       char *saveptr;

       if (!buf)
              return NULL;

       cnt=1;

       for (p=buf; (p=strtok_r(p, ":", &saveptr)) != NULL; p=NULL)
              ++cnt;

       ptrbuf=malloc(cnt*sizeof(char *));

       if (!ptrbuf)
       {
              free(buf);
              return NULL;
       }

       cnt=0;
       strcpy(buf, var);

       for (p=buf; (p=strtok_r(p, ":", &saveptr)) != NULL; p=NULL)
       {
              ptrbuf[cnt++]=p;

              while (*p)
              {
                     if (*p == '-')
                            *p=' ';
                     ++p;
              }
       }

       ptrbuf[cnt]=0;
       if (cnt == 0)
              free(buf);
       *nwords=cnt;

       return ptrbuf;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void splitwords_free ( char **  words) [static]

Definition at line 265 of file libcouriergnutls.c.

{
       if (words[0])
              free(words[0]);
       free(words);
}

Here is the caller graph for this function:

char* tls_cert_name ( const char *  buf,
size_t  buf_size 
)

Definition at line 2298 of file libcouriergnutls.c.

{
       gnutls_datum_t dat;
       unsigned int cert_cnt=0;
       gnutls_x509_crt_t *certbuf;
       char *p=0;
       size_t p_size;


       dat.data=(void *)buf;
       dat.size=buf_size;

       gnutls_x509_crt_list_import(NULL, &cert_cnt, &dat,
                                GNUTLS_X509_FMT_PEM,
                                GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);

       if (cert_cnt == 0)
              return 0;
       certbuf=malloc(sizeof(*certbuf)*cert_cnt);

       if (!certbuf)
              return 0;

       if (gnutls_x509_crt_list_import(certbuf, &cert_cnt, &dat,
                                   GNUTLS_X509_FMT_PEM,
                                   GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED) < 0)
              return 0;

       p_size=0;
       gnutls_x509_crt_get_dn(certbuf[0], NULL, &p_size);
       ++p_size;
       p=malloc(p_size+1);

       if (p)
       {
              if (gnutls_x509_crt_get_dn(certbuf[0], p, &p_size)
                  != GNUTLS_E_SUCCESS)
              {
                     free(p);
                     p=0;
              }
              else p[p_size]=0;
       }

       while (cert_cnt)
              gnutls_x509_crt_deinit(certbuf[--cert_cnt]);
       free(certbuf);
       return p;
}

Definition at line 590 of file libcouriergnutls.c.

{
       return ssl->info_cpy.certificate_verified;
}

Here is the caller graph for this function:

ssl_handle tls_connect ( ssl_context  ctx,
int  fd 
)

Definition at line 1575 of file libcouriergnutls.c.

{
       ssl_handle ssl=malloc(sizeof(struct ssl_handle_t));

       if (!ssl)
              return NULL;

       memset(ssl, 0, sizeof(*ssl));

       ssl->info_cpy=ctx->info_cpy;
       ssl->ctx=ctx;

       if (ctx->info_cpy.peer_verify_domain && !*ctx->trustcerts)
       {
              errno=ENOENT;
              (*ctx->info_cpy.tls_err_msg)( "TLS_TRUSTCERTS not set",
                                         ctx->info_cpy.app_data);
              free(ssl);
              return NULL;
       }

        if (fcntl(fd, F_SETFL, O_NONBLOCK))
        {
                nonsslerror(&ctx->info_cpy, "fcntl");
                return (NULL);
        }

#ifdef  SO_KEEPALIVE

        {
        int     dummy;

                dummy=1;

                if (setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE,
                        (const char *)&dummy, sizeof(dummy)) < 0)
                {
                        nonsslerror(&ctx->info_cpy, "setsockopt");
                        return (NULL);
                }
        }
#endif

#ifdef  SO_LINGER
        {
        struct linger l;

                l.l_onoff=0;
                l.l_linger=0;

                if (setsockopt(fd, SOL_SOCKET, SO_LINGER,
                        (const char *)&l, sizeof(l)) < 0)
                {
                        nonsslerror(&ctx->info_cpy, "setsockopt");
                        return (NULL);
                }
        }
#endif

       if (gnutls_anon_allocate_client_credentials(&ssl->anonclientcred) < 0)
       {
              free(ssl);
              return NULL;
       }

       if (gnutls_anon_allocate_server_credentials(&ssl->anonservercred) < 0)
       {
              gnutls_anon_free_client_credentials(ssl->anonclientcred);
              free(ssl);
              return NULL;
       }

       if (gnutls_certificate_allocate_credentials(&ssl->xcred) < 0)
       {
              gnutls_anon_free_server_credentials(ssl->anonservercred);
              gnutls_anon_free_client_credentials(ssl->anonclientcred);
              free(ssl);
              return NULL;
       }

       if (gnutls_dh_params_init(&ssl->dhparams) < 0)
       {
              gnutls_certificate_free_credentials(ssl->xcred);
              gnutls_anon_free_server_credentials(ssl->anonservercred);
              gnutls_anon_free_client_credentials(ssl->anonclientcred);
              free(ssl);
              return NULL;
       }

       if (gnutls_init (&ssl->session,
                      ctx->isserver ? GNUTLS_SERVER:GNUTLS_CLIENT) < 0)
       {
              gnutls_certificate_free_credentials(ssl->xcred);
              gnutls_anon_free_server_credentials(ssl->anonservercred);
              gnutls_anon_free_client_credentials(ssl->anonclientcred);
              free(ssl);
              return NULL;
       }

       {
              const char *p=getenv("TLS_MIN_DH_BITS");
              unsigned int n=atoi(p ? p:"0");

              if (n)
                     gnutls_dh_set_prime_bits(ssl->session, n);
       }

       gnutls_session_set_ptr(ssl->session, ssl);

        gnutls_handshake_set_private_extensions(ssl->session, 1);
        gnutls_certificate_set_verify_flags(ssl->xcred, 
                                            GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT |
                                            
                                            /*
                                            GNUTLS_VERIFY_DO_NOT_ALLOW_SAME |
                                            GNUTLS_VERIFY_ALLOW_ANY_X509_V1_CA_C
RT |

                                            GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD2 |
                                            GNUTLS_VERIFY_ALLOW_SIGN_RSA_MD5 |*/
                                            0);

        gnutls_certificate_set_verify_limits(ssl->xcred, 16384, 10);

       if (gnutls_set_default_priority (ssl->session) < 0 ||
           gnutls_kx_set_priority (ssl->session, ctx->kx_list) < 0 ||
           gnutls_cipher_set_priority(ssl->session, ctx->cipher_list) < 0 ||
           gnutls_compression_set_priority(ssl->session, ctx->comp_list) < 0 ||
           gnutls_protocol_set_priority(ssl->session, ctx->protocol_list) < 0||
           (ctx->certfiledh && read_dh_params(ssl->dhparams,
                                          ctx->certfile) < 0) ||
           add_certificates(ssl->xcred, ctx->trustcerts) < 0 ||
#if 0
           add_certificates(ssl->xcred, ctx->certfile) < 0 ||
           add_certificates(ssl->xcred, ctx->dhcertfile) < 0 ||
#endif
           gnutls_credentials_set(ssl->session, GNUTLS_CRD_ANON,
                               ctx->isserver
                               ? (void *)ssl->anonservercred
                               : (void *)ssl->anonclientcred)
           < 0 ||
           gnutls_credentials_set(ssl->session, GNUTLS_CRD_CERTIFICATE,
                               ssl->xcred) < 0 ||

           gnutls_certificate_type_set_priority(ssl->session,
                                           ctx->cert_list) < 0 ||
           (ctx->info_cpy.peer_verify_domain &&
            gnutls_server_name_set(ssl->session, GNUTLS_NAME_DNS,
                                ctx->info_cpy.peer_verify_domain,
                                strlen(ctx->info_cpy.peer_verify_domain))
            < 0)
           )
       {
              tls_free_session(ssl);
              return NULL;
       }

       if (ctx->certfiledh)
       {
              gnutls_certificate_set_dh_params(ssl->xcred, ssl->dhparams);

              gnutls_anon_set_server_dh_params(ssl->anonservercred,
                                           ssl->dhparams);
       }

       if (ctx->isserver)
       {
              if (ctx->verify_cert)
                     gnutls_certificate_server_set_request(ssl->session,
                                                       ctx->fail_if_no_cert ?
                                                       GNUTLS_CERT_REQUIRE:
                                                       GNUTLS_CERT_REQUEST);
              gnutls_certificate_server_set_retrieve_function(ssl->xcred,
                                                        get_server_cert
                                                        );
       }
       else gnutls_certificate_client_set_retrieve_function(ssl->xcred,
                                                      get_client_cert);

       gnutls_transport_set_ptr(ssl->session,(gnutls_transport_ptr_t)
                             GNUTLS_CAST_PTR_T fd);

       if (ssl->ctx->info_cpy.tlscache)
       {
              gnutls_db_set_ptr(ssl->session, ssl);

              gnutls_db_set_cache_expiration(ssl->session, 3600);

              gnutls_db_set_remove_function(ssl->session,
                                         db_remove_func);
              gnutls_db_set_retrieve_function(ssl->session,
                                          db_retrieve_func);
              gnutls_db_set_store_function(ssl->session,
                                        db_store_func);
       }

       ssl->info_cpy.connect_interrupted=1;

       if (dohandshake(ssl, fd, NULL, NULL) < 0)
       {
              tls_disconnect(ssl, fd);
              return NULL;
       }

       return ssl;
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tls_connecting ( ssl_handle  ssl)

Definition at line 1912 of file libcouriergnutls.c.

{
       return ssl->info_cpy.connect_interrupted;
}

Here is the caller graph for this function:

ssl_context tls_create ( int  isserver,
const struct tls_info info 
)

Definition at line 373 of file libcouriergnutls.c.

{
       static int first=1;

       char **words;
       size_t n, i;
       ssl_context p=malloc(sizeof(struct ssl_context_t));
       char *certfile=NULL, *dhcertfile=NULL;

       if (!p)
              return NULL;

       memset(p, 0, sizeof(*p));

       p->isserver=isserver;
       p->info_cpy=*info;
       p->info_cpy.certificate_verified=0;

       if (first)
       {
              if (gnutls_check_version(LIBGNUTLS_VERSION) == NULL)
              {
                     fprintf(stderr, "GnuTLS version mismatch\n");
                     free(p);
                     errno=EINVAL;
                     return (NULL);
              }

              first=0;

              if (gnutls_global_init() < 0)
              {
                     fprintf(stderr, "gnutls_global_init() failed\n");
                     free(p);
                     errno=EINVAL;
                     return (NULL);
              }

              if (gnutls_global_init_extra() < 0)
              {
                     gnutls_global_deinit();
                     fprintf(stderr, "gnutls_global_init() failed\n");
                     free(p);
                     errno=EINVAL;
                     return (NULL);
              }
       }

       if (!(words=splitwords(safe_getenv(p, "TLS_PROTOCOL",
                                      "TLS1_1:TLS1:SSL3"), &n)))
       {
              tls_destroy(p);
              return NULL;
       }

       if ((p->protocol_list=malloc((n+1)*sizeof(int))) == NULL)
       {
              splitwords_free(words);

              tls_destroy(p);
              return NULL;
       }

       for (n=i=0; words[i]; ++i)
       {
              if (strcmp(words[i], "SSL3") == 0)
              {
                     p->protocol_list[n++]=GNUTLS_SSL3;
              }
              else if (strcmp(words[i], "TLS1") == 0)
              {
                     p->protocol_list[n++]=GNUTLS_TLS1_0;
              }
              else if (strcmp(words[i], "TLS1_1") == 0)
              {
                     p->protocol_list[n++]=GNUTLS_TLS1_1;
              }
       }
       p->protocol_list[n]=0;

       splitwords_free(words);

       if (!(words=splitwords(safe_getenv(p, "TLS_CIPHER_LIST",
                                      "HIGH:MEDIUM"), &n)))
       {
              tls_destroy(p);
              return NULL;
       }

       parse_map(all_ciphers, words, p->cipher_list, 1);
       splitwords_free(words);

       if (!(words=splitwords(safe_getenv(p, "TLS_KX_LIST", "ALL"), &n)))
       {
              tls_destroy(p);
              return NULL;
       }

       parse_map(all_kxs, words, p->kx_list, 0);
       splitwords_free(words);

       if (!(words=splitwords(safe_getenv(p, "TLS_COMPRESSION", "ALL"), &n)))
       {
              tls_destroy(p);
              return NULL;
       }

       parse_map(all_comps, words, p->comp_list, 0);
       splitwords_free(words);

       if (!(words=splitwords(safe_getenv(p, "TLS_CERTS", "X509"), &n)))
       {
              tls_destroy(p);
              return NULL;
       }

       parse_map(all_certs, words, p->cert_list, 0);
       splitwords_free(words);


       if ((certfile=strdup(safe_getenv(p, "TLS_CERTFILE", ""))) == NULL ||
           (dhcertfile=strdup(safe_getenv(p, "TLS_DHCERTFILE", "")))
           == NULL ||
           (p->trustcerts=strdup(safe_getenv(p, "TLS_TRUSTCERTS", "")))
           == NULL)
       {
              if (certfile)
                     free(certfile);
              if (dhcertfile)
                     free(dhcertfile);
              tls_destroy(p);
              return NULL;
       }

       if (*dhcertfile)
       {
              p->certfile=dhcertfile;
              p->certfiledh=1;
              dhcertfile=NULL;
       }
       else if (*certfile)
       {
              p->certfile=certfile;
              p->certfiledh=0;
              certfile=NULL;
       }

       if (certfile)
              free(certfile);
       if (dhcertfile)
              free(dhcertfile);

       switch (*safe_getenv(p, "TLS_VERIFYPEER", "P")) {
       case 'n':
       case 'N':
              p->verify_cert=0;
              p->fail_if_no_cert=0;
              break;
       case 'p':
       case 'P':            /* PEER */
              p->verify_cert=1;
              p->fail_if_no_cert=0;
              break;
       case 'r':
       case 'R':            /* REQUIREPEER */
              p->verify_cert=1;
              p->fail_if_no_cert=1;
              break;
       }

       if (info->peer_verify_domain)
              p->verify_cert=p->fail_if_no_cert=1;

       {
              const char *filename=safe_getenv(p, "TLS_CACHEFILE", "");
              const char *cachesize=safe_getenv(p, "TLS_CACHESIZE", "");
              off_t cachesize_l;

              if (filename && *filename)
              {
                     cachesize_l= cachesize ? (off_t)atol(cachesize):0;

                     if (cachesize_l <= 0)
                            cachesize_l=512L * 1024;
                     if ((p->info_cpy.tlscache=tls_cache_open(filename,
                                                         cachesize_l))
                         == NULL)
                     {
                            nonsslerror(&p->info_cpy, filename);
                            tls_destroy(p);
                            return NULL;
                     }
              }
       }

#if 0
       int session_timeout=atoi(safe_getenv(ctx, "TLS_TIMEOUT"));
#endif
       return p;
}

Here is the caller graph for this function:

void tls_destroy ( ssl_context  p)

Definition at line 574 of file libcouriergnutls.c.

{
       if (p->protocol_list)
              free(p->protocol_list);

       if (p->certfile)
              free(p->certfile);

       if (p->trustcerts)
              free(p->trustcerts);

       if (p->info_cpy.tlscache)
              tls_cache_close(p->info_cpy.tlscache);
       free(p);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tls_disconnect ( ssl_handle  ssl,
int  fd 
)

Definition at line 1782 of file libcouriergnutls.c.

{
       fcntl(fd, F_SETFL, 0);
       gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR);
       tls_free_session(ssl);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void tls_dump_connection_info ( ssl_handle  ssl,
int  server,
void(*)(const char *, int cnt, void *)  dump_func,
void *  dump_arg 
)

Definition at line 2061 of file libcouriergnutls.c.

{
       if (gnutls_certificate_type_get (ssl->session) == GNUTLS_CRT_X509)
              tls_dump_connection_info_x509(ssl, server, dump_func,
                                         dump_arg);

       (*dump_func)("Version: ", -1, dump_arg);
       (*dump_func)
              (gnutls_protocol_get_name(gnutls_protocol_get_version(ssl->session)),
               -1, dump_arg);
       (*dump_func)("\n", 1, dump_arg);

       {
              char buf[10];

              (*dump_func)("Bits: ", -1, dump_arg);

              snprintf(buf, sizeof(buf), "%d", (int)
                      gnutls_cipher_get_key_size(gnutls_cipher_get(ssl->session))
                      *8);
              buf[sizeof(buf)-1]=0;

              (*dump_func)(buf, -1, dump_arg);
              (*dump_func)("\n", 1, dump_arg);
       }

       (*dump_func)("Cipher: ", -1, dump_arg);
       dump_cipher_name(ssl->session, dump_func, dump_arg);
       (*dump_func)("\n", 1, dump_arg);
}

Here is the caller graph for this function:

static void tls_dump_connection_info_x509 ( ssl_handle  ssl,
int  server,
void(*)(const char *, int cnt, void *)  dump_func,
void *  dump_arg 
) [static]

Definition at line 2141 of file libcouriergnutls.c.

{
       const gnutls_datum_t *cert_list;
       unsigned int cert_list_size;
       gnutls_x509_crt_t *cert;

       cert_list=gnutls_certificate_get_peers(ssl->session, &cert_list_size);

       if (cert_list)
       {
              unsigned int i;

              cert=malloc(sizeof (*cert) * cert_list_size);

              for (i = 0; i<cert_list_size; i++)
              {
                     gnutls_x509_crt_init(&cert[i]);
                     gnutls_x509_crt_import(cert[i],
                                          &cert_list[i],
                                          GNUTLS_X509_FMT_DER);
              }

              for (i = 0; i < cert_list_size; i++)
              {
                     time_t notbefore;
                     time_t notafter;

                     (*dump_func)("Subject:\n", -1, dump_arg);

                     dump_dn(cert[i],
                            gnutls_x509_crt_get_dn_oid,
                            gnutls_x509_crt_get_dn_by_oid,
                            dump_func, dump_arg);
                     (*dump_func)("\n", 1, dump_arg);


#if 0
                     (*dump_func)("Issuer:\n", -1, dump_arg);

                     dump_dn(cert[i],
                            gnutls_x509_crt_get_issuer_dn_oid,
                            gnutls_x509_crt_get_issuer_dn_by_oid,
                            dump_func, dump_arg);
                     (*dump_func)("\n", 1, dump_arg);
#endif

                     notbefore=gnutls_x509_crt_get_activation_time(cert[i]);
                     notafter=gnutls_x509_crt_get_expiration_time(cert[i]);
                     print_time("Not-Before", notbefore,
                               dump_func, dump_arg);
                     print_time("Not-After",  notafter,
                               dump_func, dump_arg);
              }

              for (i = 0; i < cert_list_size; i++)
                     gnutls_x509_crt_deinit(cert[i]);
              free(cert);
       }
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void tls_free_session ( ssl_handle  ssl) [static]

Definition at line 743 of file libcouriergnutls.c.

{
       gnutls_deinit(ssl->session);
       gnutls_certificate_free_credentials(ssl->xcred);
       gnutls_anon_free_client_credentials(ssl->anonclientcred);
       gnutls_anon_free_server_credentials(ssl->anonservercred);
       gnutls_dh_params_deinit(ssl->dhparams);
       tls_free_session_keys(ssl);
       free(ssl);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void tls_free_session_keys ( ssl_handle  ssl) [static]

Definition at line 726 of file libcouriergnutls.c.

{
       if (ssl->x509_key)
              gnutls_x509_privkey_deinit(ssl->x509_key);

       if (ssl->pgp_crt)
              gnutls_openpgp_key_deinit(ssl->pgp_crt);

       if (ssl->pgp_key)
              gnutls_openpgp_privkey_deinit(ssl->pgp_key);

       ssl->x509_key=NULL;
       ssl->pgp_crt=NULL;
       ssl->pgp_key=NULL;

}

Here is the caller graph for this function:

Definition at line 2227 of file libcouriergnutls.c.

{
       size_t n=1;
       char *buf;

       gen_encryption_desc(ssl->session, cnt_desc_size, &n);

       buf=malloc(n);

       if (buf)
       {
              char *ptr=buf;
              gen_encryption_desc(ssl->session, save_desc, &ptr);
              *ptr=0;
       }
       return buf;
}

Here is the caller graph for this function:

int tls_transfer ( struct tls_transfer_info t,
ssl_handle  ssl,
int  fd,
fd_set *  r,
fd_set *  w 
)

Definition at line 1789 of file libcouriergnutls.c.

{
       if (ssl->info_cpy.connect_interrupted)
       {
              if (dohandshake(ssl, fd, r, w) < 0)
                     return -1;

              return 0;
       }

       if (t->shutdown)
              return -1;

       if (t->shutdown_interrupted)
       {
              while (chk_error(gnutls_bye(ssl->session, GNUTLS_SHUT_RDWR),
                             ssl, fd, r, w, NULL))
                     ;

              if ((r && FD_ISSET(fd, r)) ||
                  (w && FD_ISSET(fd, w)))
              {
                     return 1;
              }

                     
              t->shutdown_interrupted=0;
              t->shutdown= -1;
              return -1;
       }

       if(0) printf("readleft=%d writeleft=%d\nread_interrupted=%d read_interrupted=%d\n",
                  (int)t->readleft,(int)t->writeleft,
                  t->read_interrupted,t->write_interrupted);

       if (!t->write_interrupted && t->readleft > 0 && t->writeleft == 0)
       {
              int rc;
              ssize_t n;

              do
              {
                     n=gnutls_record_recv(ssl->session, t->readptr,
                                        t->readleft);

                     if (n >= 0)
                     {
                            if (n == 0)
                            {
                                   t->shutdown=1;
                                   return -1;
                            }

                            t->readptr += n;
                            t->readleft -= n;
                            return 0;
                     }

                     if ((int)n == GNUTLS_E_REHANDSHAKE)
                     {
                            ssl->info_cpy.connect_interrupted=1;

                            return tls_transfer(t, ssl, fd, r, w);
                     }

              } while (chk_error((int)n, ssl, fd, r, w, &rc));

              if (rc < 0)
              {
                     t->shutdown_interrupted=1;
                     return tls_transfer(t, ssl, fd, r, w);
              }
       } else if (t->writeleft > 0)
       {
              int rc;
              ssize_t n;

              t->write_interrupted=0;

              do
              {
                     n=gnutls_record_send(ssl->session, (void *)t->writeptr,
                                        t->writeleft);

                     if (n >= 0)
                     {
                            if (n == 0)
                            {
                                   t->shutdown=1;
                                   return -1;
                            }

                            t->writeptr += n;
                            t->writeleft -= n;
                            return 0;
                     }

                     if ((int)n == GNUTLS_E_REHANDSHAKE)
                     {
                            t->write_interrupted=1;
                            ssl->info_cpy.connect_interrupted=1;

                            return tls_transfer(t, ssl, fd, r, w);
                     }

              } while (chk_error((int)n, ssl, fd, r, w, &rc));

              if (rc < 0)
              {
                     t->shutdown=1;
                     return -1;
              }
              t->write_interrupted=1;
       }
       else
       {
              FD_SET(fd, r);
              FD_SET(fd, w);
       }
       return (1);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int tls_validate_pem_cert ( const char *  buf,
size_t  buf_size 
)

Definition at line 2267 of file libcouriergnutls.c.

{
       gnutls_datum_t dat;
       unsigned int cert_cnt=0;
       gnutls_x509_crt_t *certbuf;

       dat.data=(void *)buf;
       dat.size=buf_size;

       gnutls_x509_crt_list_import(NULL, &cert_cnt, &dat,
                                GNUTLS_X509_FMT_PEM,
                                GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED);

       if (cert_cnt == 0)
              return 0;
       certbuf=malloc(sizeof(*certbuf)*cert_cnt);

       if (!certbuf)
              return 0;

       if (gnutls_x509_crt_list_import(certbuf, &cert_cnt, &dat,
                                   GNUTLS_X509_FMT_PEM,
                                   GNUTLS_X509_CRT_LIST_IMPORT_FAIL_IF_EXCEED) < 0)
              return 0;

       while (cert_cnt)
              gnutls_x509_crt_deinit(certbuf[--cert_cnt]);
       free(certbuf);
       return (1);
}
static int verify_client ( ssl_handle  ssl,
int  fd 
) [static]

Definition at line 800 of file libcouriergnutls.c.

{
       unsigned int status;
       int rc;
       const gnutls_datum_t *cert_list;
       unsigned int cert_list_size;

       if (!ssl->ctx->verify_cert)
              return 0;

       cert_list = gnutls_certificate_get_peers(ssl->session, &cert_list_size);
       if (cert_list == NULL || cert_list_size == 0)
       {
              if (ssl->ctx->fail_if_no_cert)
              {
                     (*ssl->info_cpy.tls_err_msg)
                            ("No certificate supplied by peer",
                             ssl->info_cpy.app_data);
                     return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
              }
              return 0;
       }

       status=0;
       rc=gnutls_certificate_verify_peers2(ssl->session, &status);

       if (rc)
       {
              (*ssl->info_cpy.tls_err_msg)
                     ("Peer certificate verification failed",
                      ssl->info_cpy.app_data);
              return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
       }

       if (status)
       {
              (*ssl->info_cpy.tls_err_msg)
                     (status & GNUTLS_CERT_REVOKED ?
                      "Peer's certificate is revoked":
                      status & GNUTLS_CERT_SIGNER_NOT_FOUND ?
                      "Peer's certificate not signed by a trusted authority":
                      status & GNUTLS_CERT_SIGNER_NOT_CA ?
                      "Invalid peer certificate authority":
                      status & GNUTLS_CERT_INSECURE_ALGORITHM ?
                      "Peer's certificate does not use a secure checksum":
                      "Invalid peer certificate",
                      ssl->info_cpy.app_data);
              return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
       }

       if (gnutls_certificate_type_get(ssl->session) == GNUTLS_CRT_X509)
       {
              gnutls_x509_crt_t cert;

              if (gnutls_x509_crt_init(&cert) < 0)
              {
                     (*ssl->info_cpy.tls_err_msg)
                            ("Error initializing certificate",
                             ssl->info_cpy.app_data);
                     return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
              }

              if (gnutls_x509_crt_import(cert, &cert_list[0],
                                      GNUTLS_X509_FMT_DER) < 0)
              {
                     (*ssl->info_cpy.tls_err_msg)
                            ("Error parsing certificate",
                             ssl->info_cpy.app_data);
                     gnutls_x509_crt_deinit (cert);
                     return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
              }


              if (gnutls_x509_crt_get_expiration_time(cert) < time(NULL))
              {
                     (*ssl->info_cpy.tls_err_msg)
                            ("Expired certificate",
                             ssl->info_cpy.app_data);
                     gnutls_x509_crt_deinit (cert);
                     return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
              }

              if (gnutls_x509_crt_get_activation_time(cert) > time(NULL))
              {
                     (*ssl->info_cpy.tls_err_msg)
                            ("Certificate not activated",
                             ssl->info_cpy.app_data);
                     gnutls_x509_crt_deinit (cert);
                     return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
              }

              if (ssl->info_cpy.peer_verify_domain &&
                  *ssl->info_cpy.peer_verify_domain &&
                  !gnutls_x509_crt_check_hostname(cert,
                                              ssl->info_cpy
                                              .peer_verify_domain
                                              ))
              {
                     char hostname[256];
                     size_t hostname_size=sizeof(hostname);
                     const char *errmsg_txt="Certificate owner mismatch: ";
                     char *errmsg_buf;

                     if (gnutls_x509_crt_get_dn_by_oid(cert,
                                                   "2.5.4.3", 0,
                                                   0, hostname,
                                                   &hostname_size) < 0)
                            strcpy(hostname,"(unknown)");

                     errmsg_buf=malloc(strlen(errmsg_txt)+
                                     strlen(hostname)+10);

                     if (errmsg_buf)
                            strcat(strcpy(errmsg_buf, errmsg_txt),
                                   hostname);

                     (*ssl->info_cpy.tls_err_msg)
                            (errmsg_buf ? errmsg_buf: strerror(errno),
                             ssl->info_cpy.app_data);
                     gnutls_x509_crt_deinit (cert);

                     if (errmsg_buf)
                            free(errmsg_buf);
                     return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
              }

              gnutls_x509_crt_deinit (cert);
       }
       else if (gnutls_certificate_type_get(ssl->session)==GNUTLS_CRT_OPENPGP)
       {
              gnutls_openpgp_key_t cert;

              if (gnutls_openpgp_key_init(&cert) < 0)
              {
                     (*ssl->info_cpy.tls_err_msg)
                            ("Error initializing certificate",
                             ssl->info_cpy.app_data);
                     gnutls_openpgp_key_deinit(cert);
                     return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
              }

              if (gnutls_openpgp_key_import(cert, &cert_list[0],
                                         GNUTLS_OPENPGP_FMT_RAW) < 0)
              {
                     (*ssl->info_cpy.tls_err_msg)
                            ("Error parsing certificate",
                             ssl->info_cpy.app_data);
                     gnutls_openpgp_key_deinit (cert);
                     return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
              }

              if (gnutls_openpgp_key_get_creation_time(cert) > time(NULL))
              {
                     (*ssl->info_cpy.tls_err_msg)
                            ("Certificate not activated",
                             ssl->info_cpy.app_data);
                     gnutls_openpgp_key_deinit (cert);
                     return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
              }

              if (gnutls_openpgp_key_get_expiration_time(cert) < time(NULL))
              {
                     (*ssl->info_cpy.tls_err_msg)
                            ("Expired certificate",
                             ssl->info_cpy.app_data);
                     gnutls_openpgp_key_deinit (cert);
                     return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
              }

              if (ssl->info_cpy.peer_verify_domain &&
                  *ssl->info_cpy.peer_verify_domain &&
                  !gnutls_openpgp_key_check_hostname(cert,
                                                 ssl->info_cpy
                                                 .peer_verify_domain))
                                                
              {
                     char *hostname;
                     size_t hostnamesiz=0;
                     const char *errmsg_txt=
                            "Certificate owner mismatch: ";
                     char *errmsg_buf;

                     gnutls_openpgp_key_get_name(cert, 0, NULL,
                                              &hostnamesiz);

                     hostname=malloc(hostnamesiz);

                     if (hostname)
                     {
                            *hostname=0;
                            gnutls_openpgp_key_get_name(cert,
                                                     0, hostname,
                                                     &hostnamesiz);
                     }

                     errmsg_buf=malloc(strlen(errmsg_txt)+
                                     strlen(hostname ?
                                           hostname:"")+100);

                     if (errmsg_buf)
                            strcat(strcpy(errmsg_buf, errmsg_txt),
                                          hostname ?
                                          hostname:"(unknown)");

                     (*ssl->info_cpy.tls_err_msg)
                            (errmsg_buf ? errmsg_buf:strerror(errno),
                             ssl->info_cpy.app_data);
                     if (errmsg_buf)
                            free(errmsg_buf);
                     if (hostname)
                            free(hostname);
                     gnutls_openpgp_key_deinit (cert);
                     return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
              }
              gnutls_openpgp_key_deinit (cert);
       }
       else
       {
              (*ssl->info_cpy.tls_err_msg)
                     ("No certificate supplied by peer",
                      ssl->info_cpy.app_data);
              return GNUTLS_E_INSUFFICIENT_CREDENTIALS;
       }

       ssl->info_cpy.certificate_verified=1;
       return 0;
}

Here is the caller graph for this function:


Variable Documentation

struct intmap all_certs[] [static]
struct intmap all_ciphers[] [static]
struct intmap all_comps[] [static]
struct intmap all_kxs[] [static]
struct oid_name[] [static]

Definition at line 59 of file libcouriergnutls.c.