Back to index

courier  0.68.2
Classes | Defines | Typedefs | Functions
libcouriertls.h File Reference
#include "config.h"
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Classes

struct  tls_info
struct  tls_transfer_info

Defines

#define tls_transfer_init(i)   memset((i), 0, sizeof(*i));
#define tls_inprogress(s)
#define tls_closing(s)   ((s)->shutdown_interrupted=1)
#define tls_isclosing(s)   ((s)->shutdown_interrupted)
#define tls_isclosed(s)   ((s)->shutdown)

Typedefs

typedef struct ssl_context_tssl_context
typedef struct ssl_handle_tssl_handle

Functions

struct tls_infotls_get_default_info ()
ssl_context tls_create (int isserver, const struct tls_info *)
void tls_destroy (ssl_context ctx)
ssl_handle tls_connect (ssl_context ctx, int fd)
void tls_disconnect (ssl_handle ssl, int fd)
int tls_connecting (ssl_handle)
int tls_certificate_verified (ssl_handle)
int tls_transfer (struct tls_transfer_info *info, ssl_handle ssl, int fd, fd_set *r, fd_set *w)
void tls_dump_connection_info (ssl_handle ssl, int server, void(*dump_func)(const char *, int cnt, void *), void *dump_arg)
char * tls_get_encryption_desc (ssl_handle ssl)
char * tls_cert_name (const char *buf, size_t buf_size)
int tls_validate_pem_cert (const char *buf, size_t buf_size)

Class Documentation

struct tls_transfer_info

Definition at line 231 of file libcouriertls.h.

Class Members
int read_interrupted
size_t readleft
char * readptr
int shutdown
int shutdown_interrupted
int write_interrupted
size_t writeleft
const char * writeptr

Define Documentation

#define tls_closing (   s)    ((s)->shutdown_interrupted=1)

Definition at line 290 of file libcouriertls.h.

#define tls_inprogress (   s)
Value:
((s)->read_interrupted || (s)->write_interrupted || \
                     (s)->shutdown_interrupted)

Definition at line 274 of file libcouriertls.h.

#define tls_isclosed (   s)    ((s)->shutdown)

Definition at line 292 of file libcouriertls.h.

#define tls_isclosing (   s)    ((s)->shutdown_interrupted)

Definition at line 291 of file libcouriertls.h.

#define tls_transfer_init (   i)    memset((i), 0, sizeof(*i));

Definition at line 246 of file libcouriertls.h.


Typedef Documentation

typedef struct ssl_context_t* ssl_context

Definition at line 38 of file libcouriertls.h.

typedef struct ssl_handle_t* ssl_handle

Definition at line 39 of file libcouriertls.h.


Function Documentation

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;
}

Here is the call graph for this function:

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:

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  
)

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 call graph for this function:

Here is the caller graph for this function:

void tls_destroy ( ssl_context  ctx)

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 call graph for this function:

Here is the caller graph for this function:

struct tls_info* tls_get_default_info ( ) [read]

Definition at line 28 of file tlsinfo.c.

{
       return &default_info;
}

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 call graph for this function:

Here is the caller graph for this function:

int tls_transfer ( struct tls_transfer_info info,
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);
}

Here is the call graph for this function: