X-Git-Url: http://www.dolda2000.com/gitweb/?a=blobdiff_plain;f=src%2Fssl-gnutls.c;h=8e4ea5c304636dcc6a41d0a64fe814babf6cdd61;hb=349b25644067aa6754197a991c3ba00143d60a19;hp=5247f2a38c276de0614c702351f4c01797d22ec5;hpb=28b2e619843d9a9f6bf74ad2b0a632a41aa4e3f3;p=ashd.git diff --git a/src/ssl-gnutls.c b/src/ssl-gnutls.c index 5247f2a..8e4ea5c 100644 --- a/src/ssl-gnutls.c +++ b/src/ssl-gnutls.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -66,8 +67,6 @@ struct sslconn { struct charbuf in; }; -static gnutls_dh_params_t dhparams; - static int tlsblock(int fd, gnutls_session_t sess, time_t to) { if(gnutls_record_get_direction(sess)) @@ -137,6 +136,9 @@ static ssize_t sslwrite(void *cookie, const char *buf, size_t len) static int sslclose(void *cookie) { + struct sslconn *ssl = cookie; + + buffree(ssl->in); return(0); } @@ -259,6 +261,23 @@ out: free(pd); } +static gnutls_dh_params_t dhparams(void) +{ + static int inited = 0; + static gnutls_dh_params_t pars; + int ret; + + if(!inited) { + if(((ret = gnutls_dh_params_init(&pars)) != 0) || + ((ret = gnutls_dh_params_generate2(pars, 2048)) != 0)) { + flog(LOG_ERR, "GnuTLS could not generate Diffie-Hellman parameters: %s", gnutls_strerror(ret)); + exit(1); + } + inited = 1; + } + return(pars); +} + static void init(void) { static int inited = 0; @@ -271,11 +290,6 @@ static void init(void) flog(LOG_ERR, "could not initialize GnuTLS: %s", gnutls_strerror(ret)); exit(1); } - if(((ret = gnutls_dh_params_init(&dhparams)) != 0) || - ((ret = gnutls_dh_params_generate2(dhparams, 2048)) != 0)) { - flog(LOG_ERR, "GnuTLS could not generate Diffie-Hellman parameters: %s", gnutls_strerror(ret)); - exit(1); - } } static struct namedcreds *readncreds(char *file) @@ -345,10 +359,32 @@ static struct namedcreds *readncreds(char *file) flog(LOG_ERR, "ssl: could not use certificate from %s: %s", file, gnutls_strerror(ret)); exit(1); } - gnutls_certificate_set_dh_params(nc->creds, dhparams); + gnutls_certificate_set_dh_params(nc->creds, dhparams()); return(nc); } +static void readncdir(struct ncredbuf *buf, char *dir) +{ + DIR *d; + struct dirent *e; + size_t es; + + if((d = opendir(dir)) == NULL) { + flog(LOG_ERR, "ssl: could not read certificate directory %s: %s", dir, strerror(errno)); + exit(1); + } + while((e = readdir(d)) != NULL) { + if(e->d_name[0] == '.') + continue; + if((es = strlen(e->d_name)) <= 4) + continue; + if(strcmp(e->d_name + es - 4, ".crt")) + continue; + bufadd(*buf, readncreds(sprintf3("%s/%s", dir, e->d_name))); + } + closedir(d); +} + void handlegnussl(int argc, char **argp, char **argv) { int i, ret, port, fd; @@ -375,11 +411,24 @@ void handlegnussl(int argc, char **argp, char **argv) printf("\tcrl=CRL-FILE [no default]\n"); printf("\t\tThe name of a file to read revocation lists from.\n"); printf("\t\tMay be given multiple times.\n"); + printf("\tncert=CERT-FILE [no default]\n"); + printf("\t\tThe name of a file to read a named certificate from,\n"); + printf("\t\tfor use with SNI-enabled clients.\n"); + printf("\t\tMay be given multiple times.\n"); + printf("\tncertdir=DIR [no default]\n"); + printf("\t\tRead all *.crt files in the given directory as if they\n"); + printf("\t\twere given with `ncert' options.\n"); + printf("\t\tMay be given multiple times.\n"); printf("\tport=PORT [443]\n"); printf("\t\tThe TCP port to listen on.\n"); printf("\n"); printf("\tAll X.509 data files must be PEM-encoded.\n"); - printf("\tSee the manpage for information on specifying multiple\n\tcertificates to support SNI operation.\n"); + printf("\tIf any certificates were given with `ncert' options, they will be\n"); + printf("\tused if a client explicitly names one of them with a\n"); + printf("\tserver-name indication. If a client indicates no server name,\n"); + printf("\tor if a server-name indication does not match any given\n"); + printf("\tcertificate, the certificate given with the `cert' option will\n"); + printf("\tbe used instead.\n"); exit(0); } else if(!strcmp(argp[i], "cert")) { crtfile = argv[i]; @@ -411,6 +460,8 @@ void handlegnussl(int argc, char **argp, char **argv) port = atoi(argv[i]); } else if(!strcmp(argp[i], "ncert")) { bufadd(ncreds, readncreds(argv[i])); + } else if(!strcmp(argp[i], "ncertdir")) { + readncdir(&ncreds, argv[i]); } else { flog(LOG_ERR, "unknown parameter `%s' to ssl handler", argp[i]); exit(1); @@ -420,17 +471,17 @@ void handlegnussl(int argc, char **argp, char **argv) flog(LOG_ERR, "ssl: needs certificate file at the very least"); exit(1); } + if((fd = listensock6(port)) < 0) { + flog(LOG_ERR, "could not listen on IPv6 port (port %i): %s", port, strerror(errno)); + exit(1); + } if(keyfile == NULL) keyfile = crtfile; if((ret = gnutls_certificate_set_x509_key_file(creds, crtfile, keyfile, GNUTLS_X509_FMT_PEM)) != 0) { flog(LOG_ERR, "ssl: could not load certificate or key: %s", gnutls_strerror(ret)); exit(1); } - gnutls_certificate_set_dh_params(creds, dhparams); - if((fd = listensock6(port)) < 0) { - flog(LOG_ERR, "could not listen on IPv6 port (port %i): %s", port, strerror(errno)); - exit(1); - } + gnutls_certificate_set_dh_params(creds, dhparams()); bufadd(ncreds, NULL); omalloc(pd); pd->fd = fd;