[BACK]Return to conn-ssl.c CVS log [TXT][DIR] Up to [local] / ircnowd / src / ngircd

Annotation of ircnowd/src/ngircd/conn-ssl.c, Revision 1.1.1.1

1.1       tomglok     1: /*
                      2:  * ngIRCd -- The Next Generation IRC Daemon
                      3:  * Copyright (c)2005-2008 Florian Westphal (fw@strlen.de).
                      4:  * Copyright (c)2008-2014 Alexander Barton (alex@barton.de) and Contributors.
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify
                      7:  * it under the terms of the GNU General Public License as published by
                      8:  * the Free Software Foundation; either version 2 of the License, or
                      9:  * (at your option) any later version.
                     10:  * Please read the file COPYING, README and AUTHORS for more information.
                     11:  */
                     12:
                     13: #include "portab.h"
                     14:
                     15: /**
                     16:  * @file
                     17:  * SSL wrapper functions
                     18:  */
                     19:
                     20: #include "conf-ssl.h"
                     21:
                     22: #ifdef SSL_SUPPORT
                     23:
                     24: #include "io.h"
                     25: #include <assert.h>
                     26: #include <stdio.h>
                     27: #include <string.h>
                     28: #include <stdlib.h>
                     29: #include <errno.h>
                     30:
                     31: #define CONN_MODULE
                     32: #include "conn.h"
                     33: #include "conf.h"
                     34: #include "conn-func.h"
                     35: #include "conn-ssl.h"
                     36: #include "log.h"
                     37:
                     38: #include "defines.h"
                     39:
                     40: extern struct SSLOptions Conf_SSLOptions;
                     41:
                     42: #ifdef HAVE_LIBSSL
                     43: #include <openssl/err.h>
                     44: #include <openssl/rand.h>
                     45: #include <openssl/dh.h>
                     46:
                     47: static SSL_CTX * ssl_ctx;
                     48: static DH *dh_params;
                     49:
                     50: static bool ConnSSL_LoadServerKey_openssl PARAMS(( SSL_CTX *c ));
                     51: #endif
                     52:
                     53: #ifdef HAVE_LIBGNUTLS
                     54: #include <sys/types.h>
                     55: #include <sys/stat.h>
                     56: #include <fcntl.h>
                     57: #include <unistd.h>
                     58: #include <gnutls/x509.h>
                     59:
                     60: #define DH_BITS 2048
                     61: #define DH_BITS_MIN 1024
                     62:
                     63: #define MAX_HASH_SIZE  64      /* from gnutls-int.h */
                     64:
                     65: typedef struct {
                     66:        int refcnt;
                     67:        gnutls_certificate_credentials_t x509_cred;
                     68:        gnutls_dh_params_t dh_params;
                     69: } x509_cred_slot;
                     70:
                     71: static array x509_creds = INIT_ARRAY;
                     72: static size_t x509_cred_idx;
                     73:
                     74: static gnutls_dh_params_t dh_params;
                     75: static gnutls_priority_t priorities_cache = NULL;
                     76: static bool ConnSSL_LoadServerKey_gnutls PARAMS(( void ));
                     77: #endif
                     78:
                     79: #define SHA256_STRING_LEN      (32 * 2 + 1)
                     80:
                     81: static bool ConnSSL_Init_SSL PARAMS(( CONNECTION *c ));
                     82: static int ConnectAccept PARAMS(( CONNECTION *c, bool connect ));
                     83: static int ConnSSL_HandleError PARAMS(( CONNECTION *c, const int code, const char *fname ));
                     84:
                     85: #ifdef HAVE_LIBGNUTLS
                     86: static char * openreadclose(const char *name, size_t *len)
                     87: {
                     88:        char *buf = NULL;
                     89:        struct stat s;
                     90:        ssize_t br;
                     91:        int fd = open(name, O_RDONLY);
                     92:        if (fd < 0) {
                     93:                Log(LOG_ERR, "Could not open %s: %s", name, strerror(errno));
                     94:                return NULL;
                     95:        }
                     96:        if (fstat(fd, &s)) {
                     97:                Log(LOG_ERR, "Could not fstat %s: %s", name, strerror(errno));
                     98:                goto out;
                     99:        }
                    100:        if (!S_ISREG(s.st_mode)) {
                    101:                Log(LOG_ERR, "%s: Not a regular file", name);
                    102:                goto out;
                    103:        }
                    104:        if (s.st_size <= 0) {
                    105:                Log(LOG_ERR, "%s: invalid file length (size %ld <= 0)", name, (long) s.st_size);
                    106:                goto out;
                    107:        }
                    108:        buf = malloc(s.st_size);
                    109:        if (!buf) {
                    110:                Log(LOG_ERR, "Could not malloc %lu bytes for file %s: %s", s.st_size, name, strerror(errno));
                    111:                goto out;
                    112:        }
                    113:        br = read(fd, buf, s.st_size);
                    114:        if (br != (ssize_t)s.st_size) {
                    115:                Log(LOG_ERR, "Could not read file %s: read returned %ld, expected %ld: %s",
                    116:                        name, (long) br, (long) s.st_size, br == -1 ? strerror(errno):"short read?!");
                    117:                memset(buf, 0, s.st_size);
                    118:                free(buf);
                    119:                buf = NULL;
                    120:        } else {
                    121:                *len = br;
                    122:        }
                    123: out:
                    124:        close(fd);
                    125:        return buf;
                    126: }
                    127: #endif
                    128:
                    129:
                    130: #ifdef HAVE_LIBSSL
                    131: /**
                    132:  * Log OpenSSL error message.
                    133:  *
                    134:  * @param msg The error message.
                    135:  * @param info Additional information text or NULL.
                    136:  */
                    137: static void
                    138: LogOpenSSLError(const char *error, const char *info)
                    139: {
                    140:        unsigned long err = ERR_get_error();
                    141:        char * errmsg = err
                    142:                ? ERR_error_string(err, NULL)
                    143:                : "Unable to determine error";
                    144:
                    145:        assert(error != NULL);
                    146:
                    147:        if (info)
                    148:                Log(LOG_ERR, "%s: %s (%s)", error, info, errmsg);
                    149:        else
                    150:                Log(LOG_ERR, "%s: %s", error, errmsg);
                    151: }
                    152:
                    153:
                    154: static int
                    155: pem_passwd_cb(char *buf, int size, int rwflag, void *password)
                    156: {
                    157:        array *pass = password;
                    158:        int passlen;
                    159:
                    160:        (void)rwflag;           /* rwflag is unused if DEBUG is not set. */
                    161:        assert(rwflag == 0);    /* 0 -> callback used for decryption.
                    162:                                 * See SSL_CTX_set_default_passwd_cb(3) */
                    163:
                    164:        passlen = (int) array_bytes(pass);
                    165:
                    166:        LogDebug("pem_passwd_cb buf size %d, array size %d", size, passlen);
                    167:        assert(passlen >= 0);
                    168:        if (passlen <= 0) {
                    169:                Log(LOG_ERR, "PEM password required but not set [in pem_passwd_cb()]!");
                    170:                return 0;
                    171:        }
                    172:        size = passlen > size ? size : passlen;
                    173:        memcpy(buf, (char *)(array_start(pass)), size);
                    174:        return size;
                    175: }
                    176:
                    177:
                    178: static int
                    179: Verify_openssl(UNUSED int preverify_ok, UNUSED X509_STORE_CTX *x509_ctx)
                    180: {
                    181:        return 1;
                    182: }
                    183: #endif
                    184:
                    185:
                    186: static bool
                    187: Load_DH_params(void)
                    188: {
                    189: #ifdef HAVE_LIBSSL
                    190:        FILE *fp;
                    191:        bool ret = true;
                    192:
                    193:        if (!Conf_SSLOptions.DHFile) {
                    194:                Log(LOG_NOTICE, "Configuration option \"DHFile\" not set!");
                    195:                return false;
                    196:        }
                    197:        fp = fopen(Conf_SSLOptions.DHFile, "r");
                    198:        if (!fp) {
                    199:                Log(LOG_ERR, "%s: %s", Conf_SSLOptions.DHFile, strerror(errno));
                    200:                return false;
                    201:        }
                    202:        dh_params = PEM_read_DHparams(fp, NULL, NULL, NULL);
                    203:        if (!dh_params) {
                    204:                Log(LOG_ERR, "%s: Failed to read SSL DH parameters!",
                    205:                    Conf_SSLOptions.DHFile);
                    206:                ret = false;
                    207:        }
                    208:        fclose(fp);
                    209:        return ret;
                    210: #endif
                    211: #ifdef HAVE_LIBGNUTLS
                    212:        bool need_dhgenerate = true;
                    213:        int err;
                    214:        gnutls_dh_params_t tmp_dh_params;
                    215:
                    216:        err = gnutls_dh_params_init(&tmp_dh_params);
                    217:        if (err < 0) {
                    218:                Log(LOG_ERR, "Failed to initialize SSL DH parameters: %s",
                    219:                    gnutls_strerror(err));
                    220:                return false;
                    221:        }
                    222:        if (Conf_SSLOptions.DHFile) {
                    223:                gnutls_datum_t dhparms;
                    224:                size_t size;
                    225:                dhparms.data = (unsigned char *) openreadclose(Conf_SSLOptions.DHFile, &size);
                    226:                if (dhparms.data) {
                    227:                        dhparms.size = size;
                    228:                        err = gnutls_dh_params_import_pkcs3(tmp_dh_params, &dhparms, GNUTLS_X509_FMT_PEM);
                    229:                        if (err == 0)
                    230:                                need_dhgenerate = false;
                    231:                        else
                    232:                                Log(LOG_ERR,
                    233:                                    "Failed to initialize SSL DH parameters: %s",
                    234:                                    gnutls_strerror(err));
                    235:
                    236:                        memset(dhparms.data, 0, size);
                    237:                        free(dhparms.data);
                    238:                }
                    239:        }
                    240:        if (need_dhgenerate) {
                    241:                Log(LOG_WARNING,
                    242:                    "DHFile not set, generating %u bit DH parameters. This may take a while ...",
                    243:                    DH_BITS);
                    244:                err = gnutls_dh_params_generate2(tmp_dh_params, DH_BITS);
                    245:                if (err < 0) {
                    246:                        Log(LOG_ERR, "Failed to generate SSL DH parameters: %s",
                    247:                            gnutls_strerror(err));
                    248:                        return false;
                    249:                }
                    250:         }
                    251:        dh_params = tmp_dh_params;
                    252:        return true;
                    253: #endif
                    254: }
                    255:
                    256:
                    257: void ConnSSL_Free(CONNECTION *c)
                    258: {
                    259: #ifdef HAVE_LIBSSL
                    260:        SSL *ssl = c->ssl_state.ssl;
                    261:        if (ssl) {
                    262:                SSL_shutdown(ssl);
                    263:                SSL_free(ssl);
                    264:                c->ssl_state.ssl = NULL;
                    265:                if (c->ssl_state.fingerprint) {
                    266:                        free(c->ssl_state.fingerprint);
                    267:                        c->ssl_state.fingerprint = NULL;
                    268:                }
                    269:        }
                    270: #endif
                    271: #ifdef HAVE_LIBGNUTLS
                    272:        gnutls_session_t sess = c->ssl_state.gnutls_session;
                    273:        if (Conn_OPTION_ISSET(c, CONN_SSL)) {
                    274:                gnutls_bye(sess, GNUTLS_SHUT_RDWR);
                    275:                gnutls_deinit(sess);
                    276:        }
                    277:        x509_cred_slot *slot = array_get(&x509_creds, sizeof(x509_cred_slot), c->ssl_state.x509_cred_idx);
                    278:        assert(slot != NULL);
                    279:        assert(slot->refcnt > 0);
                    280:        assert(slot->x509_cred != NULL);
                    281:        slot->refcnt--;
                    282:        if ((c->ssl_state.x509_cred_idx != x509_cred_idx) && (slot->refcnt <= 0)) {
                    283:                Log(LOG_INFO, "Discarding X509 certificate credentials from slot %zd.",
                    284:                    c->ssl_state.x509_cred_idx);
                    285:                gnutls_certificate_free_keys(slot->x509_cred);
                    286:                gnutls_certificate_free_credentials(slot->x509_cred);
                    287:                slot->x509_cred = NULL;
                    288:                gnutls_dh_params_deinit(slot->dh_params);
                    289:                slot->dh_params = NULL;
                    290:                slot->refcnt = 0;
                    291:        }
                    292: #endif
                    293:        assert(Conn_OPTION_ISSET(c, CONN_SSL));
                    294:        /* can't just set bitmask to 0 -- there are other, non-ssl related flags, e.g. CONN_ZIP. */
                    295:        Conn_OPTION_DEL(c, CONN_SSL_FLAGS_ALL);
                    296: }
                    297:
                    298:
                    299: bool
                    300: ConnSSL_InitLibrary( void )
                    301: {
                    302:        if (!Conf_SSLInUse()) {
                    303:                LogDebug("SSL not in use, skipping initialization.");
                    304:                return true;
                    305:        }
                    306:
                    307: #ifdef HAVE_LIBSSL
                    308:        SSL_CTX *newctx;
                    309:
                    310: #if OPENSSL_API_COMPAT < 0x10100000L
                    311:        if (!ssl_ctx) {
                    312:                SSL_library_init();
                    313:                SSL_load_error_strings();
                    314:        }
                    315: #endif
                    316:
                    317:        if (!RAND_status()) {
                    318:                Log(LOG_ERR, "OpenSSL PRNG not seeded: /dev/urandom missing?");
                    319:                /*
                    320:                 * it is probably best to fail and let the user install EGD or
                    321:                 * a similar program if no kernel random device is available.
                    322:                 * According to OpenSSL RAND_egd(3): "The automatic query of
                    323:                 * /var/run/egd-pool et al was added in OpenSSL 0.9.7";
                    324:                 * so it makes little sense to deal with PRNGD seeding ourselves.
                    325:                 */
                    326:                array_free(&Conf_SSLOptions.ListenPorts);
                    327:                return false;
                    328:        }
                    329:
                    330:        newctx = SSL_CTX_new(SSLv23_method());
                    331:        if (!newctx) {
                    332:                LogOpenSSLError("Failed to create SSL context", NULL);
                    333:                array_free(&Conf_SSLOptions.ListenPorts);
                    334:                return false;
                    335:        }
                    336:
                    337:        if (!ConnSSL_LoadServerKey_openssl(newctx)) {
                    338:                /* Failed to read new key but an old ssl context
                    339:                 * already exists -> reuse old context */
                    340:                if (ssl_ctx) {
                    341:                        SSL_CTX_free(newctx);
                    342:                        Log(LOG_WARNING,
                    343:                        "Re-Initializing of SSL failed, using old keys!");
                    344:                        return true;
                    345:                }
                    346:                /* No preexisting old context -> error. */
                    347:                goto out;
                    348:        }
                    349:
                    350:        if (SSL_CTX_set_cipher_list(newctx, Conf_SSLOptions.CipherList) == 0) {
                    351:                Log(LOG_ERR, "Failed to apply OpenSSL cipher list \"%s\"!",
                    352:                    Conf_SSLOptions.CipherList);
                    353:                goto out;
                    354:        }
                    355:
                    356:        SSL_CTX_set_session_id_context(newctx, (unsigned char *)"ngircd", 6);
                    357:        SSL_CTX_set_options(newctx, SSL_OP_SINGLE_DH_USE|SSL_OP_NO_SSLv2);
                    358:        SSL_CTX_set_mode(newctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
                    359:        SSL_CTX_set_verify(newctx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
                    360:                           Verify_openssl);
                    361:        SSL_CTX_free(ssl_ctx);
                    362:        ssl_ctx = newctx;
                    363:        Log(LOG_INFO, "%s initialized.", OpenSSL_version(OPENSSL_VERSION));
                    364:        return true;
                    365: out:
                    366:        SSL_CTX_free(newctx);
                    367:        array_free(&Conf_SSLOptions.ListenPorts);
                    368:        return false;
                    369: #endif
                    370: #ifdef HAVE_LIBGNUTLS
                    371:        int err;
                    372:        static bool initialized;
                    373:
                    374:        if (!initialized) {
                    375:                err = gnutls_global_init();
                    376:                if (err) {
                    377:                        Log(LOG_ERR, "Failed to initialize GnuTLS: %s",
                    378:                            gnutls_strerror(err));
                    379:                        goto out;
                    380:                }
                    381:        }
                    382:
                    383:        if (!ConnSSL_LoadServerKey_gnutls())
                    384:                goto out;
                    385:
                    386:        if (priorities_cache != NULL) {
                    387:                gnutls_priority_deinit(priorities_cache);
                    388:        }
                    389:        if (gnutls_priority_init(&priorities_cache, Conf_SSLOptions.CipherList,
                    390:                                 NULL) != GNUTLS_E_SUCCESS) {
                    391:                Log(LOG_ERR,
                    392:                    "Failed to apply GnuTLS cipher list \"%s\"!",
                    393:                    Conf_SSLOptions.CipherList);
                    394:                goto out;
                    395:        }
                    396:
                    397:        Log(LOG_INFO, "GnuTLS %s initialized.", gnutls_check_version(NULL));
                    398:        initialized = true;
                    399:        return true;
                    400: out:
                    401:        array_free(&Conf_SSLOptions.ListenPorts);
                    402:        return false;
                    403: #endif
                    404: }
                    405:
                    406:
                    407: #ifdef HAVE_LIBGNUTLS
                    408: static bool
                    409: ConnSSL_LoadServerKey_gnutls(void)
                    410: {
                    411:        int err;
                    412:        const char *cert_file;
                    413:
                    414:        x509_cred_slot *slot = NULL;
                    415:        gnutls_certificate_credentials_t x509_cred;
                    416:
                    417:        err = gnutls_certificate_allocate_credentials(&x509_cred);
                    418:        if (err < 0) {
                    419:                Log(LOG_ERR, "Failed to allocate certificate credentials: %s",
                    420:                    gnutls_strerror(err));
                    421:                return false;
                    422:        }
                    423:
                    424:        cert_file = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile:Conf_SSLOptions.KeyFile;
                    425:        if (!cert_file) {
                    426:                Log(LOG_ERR, "No SSL server key configured!");
                    427:                return false;
                    428:        }
                    429:
                    430:        if (array_bytes(&Conf_SSLOptions.KeyFilePassword))
                    431:                Log(LOG_WARNING,
                    432:                    "Ignoring SSL \"KeyFilePassword\": Not supported by GnuTLS.");
                    433:
                    434:        if (!Load_DH_params())
                    435:                return false;
                    436:
                    437:        gnutls_certificate_set_dh_params(x509_cred, dh_params);
                    438:        err = gnutls_certificate_set_x509_key_file(x509_cred, cert_file, Conf_SSLOptions.KeyFile, GNUTLS_X509_FMT_PEM);
                    439:        if (err < 0) {
                    440:                Log(LOG_ERR,
                    441:                    "Failed to set certificate key file (cert %s, key %s): %s",
                    442:                    cert_file,
                    443:                    Conf_SSLOptions.KeyFile ? Conf_SSLOptions.KeyFile : "(NULL)",
                    444:                    gnutls_strerror(err));
                    445:                return false;
                    446:        }
                    447:
                    448:        /* Free currently active x509 context (if any) unless it is still in use */
                    449:        slot = array_get(&x509_creds, sizeof(x509_cred_slot), x509_cred_idx);
                    450:        if ((slot != NULL) && (slot->refcnt <= 0) && (slot->x509_cred != NULL)) {
                    451:                Log(LOG_INFO, "Discarding X509 certificate credentials from slot %zd.", x509_cred_idx);
                    452:                gnutls_certificate_free_keys(slot->x509_cred);
                    453:                gnutls_certificate_free_credentials(slot->x509_cred);
                    454:                slot->x509_cred = NULL;
                    455:                gnutls_dh_params_deinit(slot->dh_params);
                    456:                slot->dh_params = NULL;
                    457:                slot->refcnt = 0;
                    458:        }
                    459:
                    460:        /* Find free slot */
                    461:        x509_cred_idx = (size_t) -1;
                    462:        size_t i;
                    463:        for (slot = array_start(&x509_creds), i = 0;
                    464:             i < array_length(&x509_creds, sizeof(x509_cred_slot));
                    465:             slot++, i++) {
                    466:                if (slot->refcnt <= 0) {
                    467:                        x509_cred_idx = i;
                    468:                        break;
                    469:                }
                    470:        }
                    471:        /* ... allocate new slot otherwise. */
                    472:        if (x509_cred_idx == (size_t) -1) {
                    473:                x509_cred_idx = array_length(&x509_creds, sizeof(x509_cred_slot));
                    474:                slot = array_alloc(&x509_creds, sizeof(x509_cred_slot), x509_cred_idx);
                    475:                if (slot == NULL) {
                    476:                        Log(LOG_ERR, "Failed to allocate new slot for certificate credentials");
                    477:                        return false;
                    478:                }
                    479:        }
                    480:        Log(LOG_INFO, "Storing new X509 certificate credentials in slot %zd.", x509_cred_idx);
                    481:        slot->x509_cred = x509_cred;
                    482:        slot->refcnt = 0;
                    483:
                    484:        return true;
                    485: }
                    486: #endif
                    487:
                    488:
                    489: #ifdef HAVE_LIBSSL
                    490: static bool
                    491: ConnSSL_LoadServerKey_openssl(SSL_CTX *ctx)
                    492: {
                    493:        char *cert_key;
                    494:
                    495:        assert(ctx);
                    496:        if (!Conf_SSLOptions.KeyFile) {
                    497:                Log(LOG_ERR, "No SSL server key configured!");
                    498:                return false;
                    499:        }
                    500:
                    501:        SSL_CTX_set_default_passwd_cb(ctx, pem_passwd_cb);
                    502:        SSL_CTX_set_default_passwd_cb_userdata(ctx, &Conf_SSLOptions.KeyFilePassword);
                    503:
                    504:        if (SSL_CTX_use_PrivateKey_file(ctx, Conf_SSLOptions.KeyFile, SSL_FILETYPE_PEM) != 1) {
                    505:                array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
                    506:                LogOpenSSLError("Failed to add private key", Conf_SSLOptions.KeyFile);
                    507:                return false;
                    508:        }
                    509:
                    510:        cert_key = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile:Conf_SSLOptions.KeyFile;
                    511:        if (SSL_CTX_use_certificate_chain_file(ctx, cert_key) != 1) {
                    512:                array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
                    513:                LogOpenSSLError("Failed to load certificate chain", cert_key);
                    514:                return false;
                    515:        }
                    516:
                    517:        array_free_wipe(&Conf_SSLOptions.KeyFilePassword);
                    518:
                    519:        if (!SSL_CTX_check_private_key(ctx)) {
                    520:                LogOpenSSLError("Server private key does not match certificate", NULL);
                    521:                return false;
                    522:        }
                    523:        if (Load_DH_params()) {
                    524:                if (SSL_CTX_set_tmp_dh(ctx, dh_params) != 1)
                    525:                        LogOpenSSLError("Error setting DH parameters", Conf_SSLOptions.DHFile);
                    526:                /* don't return false here: the non-DH modes will still work */
                    527:                DH_free(dh_params);
                    528:                dh_params = NULL;
                    529:        }
                    530:        return true;
                    531: }
                    532:
                    533:
                    534: #endif
                    535: static bool
                    536: ConnSSL_Init_SSL(CONNECTION *c)
                    537: {
                    538:        int ret;
                    539:
                    540:        LogDebug("Initializing SSL ...");
                    541:        assert(c != NULL);
                    542:
                    543: #ifdef HAVE_LIBSSL
                    544:        if (!ssl_ctx) {
                    545:                Log(LOG_ERR,
                    546:                    "Can't initialize SSL context, OpenSSL initialization failed at startup!");
                    547:                return false;
                    548:        }
                    549:        assert(c->ssl_state.ssl == NULL);
                    550:        assert(c->ssl_state.fingerprint == NULL);
                    551:
                    552:        c->ssl_state.ssl = SSL_new(ssl_ctx);
                    553:        if (!c->ssl_state.ssl) {
                    554:                LogOpenSSLError("Failed to create SSL structure", NULL);
                    555:                return false;
                    556:        }
                    557:        Conn_OPTION_ADD(c, CONN_SSL);
                    558:
                    559:        ret = SSL_set_fd(c->ssl_state.ssl, c->sock);
                    560:        if (ret != 1) {
                    561:                LogOpenSSLError("Failed to set SSL file descriptor", NULL);
                    562:                ConnSSL_Free(c);
                    563:                return false;
                    564:        }
                    565: #endif
                    566: #ifdef HAVE_LIBGNUTLS
                    567:        Conn_OPTION_ADD(c, CONN_SSL);
                    568:        ret = gnutls_priority_set(c->ssl_state.gnutls_session, priorities_cache);
                    569:        if (ret != GNUTLS_E_SUCCESS) {
                    570:                Log(LOG_ERR, "Failed to set GnuTLS session priorities: %s",
                    571:                    gnutls_strerror(ret));
                    572:                ConnSSL_Free(c);
                    573:                return false;
                    574:        }
                    575:        /*
                    576:         * The intermediate (long) cast is here to avoid a warning like:
                    577:         * "cast to pointer from integer of different size" on 64-bit platforms.
                    578:         * There doesn't seem to be an alternate GNUTLS API we could use instead, see e.g.
                    579:         * http://www.mail-archive.com/help-gnutls@gnu.org/msg00286.html
                    580:         */
                    581:        gnutls_transport_set_ptr(c->ssl_state.gnutls_session,
                    582:                                 (gnutls_transport_ptr_t) (long) c->sock);
                    583:        gnutls_certificate_server_set_request(c->ssl_state.gnutls_session,
                    584:                                              GNUTLS_CERT_REQUEST);
                    585:
                    586:        Log(LOG_INFO, "Using X509 credentials from slot %zd", x509_cred_idx);
                    587:        c->ssl_state.x509_cred_idx = x509_cred_idx;
                    588:        x509_cred_slot *slot = array_get(&x509_creds, sizeof(x509_cred_slot), x509_cred_idx);
                    589:        slot->refcnt++;
                    590:        ret = gnutls_credentials_set(c->ssl_state.gnutls_session,
                    591:                                     GNUTLS_CRD_CERTIFICATE, slot->x509_cred);
                    592:        if (ret != 0) {
                    593:                Log(LOG_ERR, "Failed to set SSL credentials: %s",
                    594:                    gnutls_strerror(ret));
                    595:                ConnSSL_Free(c);
                    596:                return false;
                    597:        }
                    598:        gnutls_dh_set_prime_bits(c->ssl_state.gnutls_session, DH_BITS_MIN);
                    599: #endif
                    600:        return true;
                    601: }
                    602:
                    603:
                    604: bool
                    605: ConnSSL_PrepareConnect(CONNECTION *c, UNUSED CONF_SERVER *s)
                    606: {
                    607:        bool ret;
                    608: #ifdef HAVE_LIBGNUTLS
                    609:        int err;
                    610:
                    611:        err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_CLIENT);
                    612:        if (err) {
                    613:                Log(LOG_ERR, "Failed to initialize new SSL session: %s",
                    614:                    gnutls_strerror(err));
                    615:                return false;
                    616:         }
                    617: #endif
                    618:        ret = ConnSSL_Init_SSL(c);
                    619:        if (!ret)
                    620:                return false;
                    621:        Conn_OPTION_ADD(c, CONN_SSL_CONNECT);
                    622: #ifdef HAVE_LIBSSL
                    623:        assert(c->ssl_state.ssl);
                    624:        SSL_set_verify(c->ssl_state.ssl, SSL_VERIFY_NONE, NULL);
                    625: #endif
                    626:        return true;
                    627: }
                    628:
                    629:
                    630: /**
                    631:  * Check and handle error return codes after failed calls to SSL functions.
                    632:  *
                    633:  * OpenSSL:
                    634:  * SSL_connect(), SSL_accept(), SSL_do_handshake(), SSL_read(), SSL_peek(), or
                    635:  * SSL_write() on ssl.
                    636:  *
                    637:  * GnuTLS:
                    638:  * gnutlsssl_read(), gnutls_write() or gnutls_handshake().
                    639:  *
                    640:  * @param c The connection handle.
                    641:  * @prarm code The return code.
                    642:  * @param fname The name of the function in which the error occurred.
                    643:  * @return -1 on fatal errors, 0 if we can try again later.
                    644:  */
                    645: static int
                    646: ConnSSL_HandleError(CONNECTION * c, const int code, const char *fname)
                    647: {
                    648: #ifdef HAVE_LIBSSL
                    649:        int ret = SSL_ERROR_SYSCALL;
                    650:        unsigned long sslerr;
                    651:        int real_errno = errno;
                    652:
                    653:        ret = SSL_get_error(c->ssl_state.ssl, code);
                    654:
                    655:        switch (ret) {
                    656:        case SSL_ERROR_WANT_READ:
                    657:                io_event_del(c->sock, IO_WANTWRITE);
                    658:                Conn_OPTION_ADD(c, CONN_SSL_WANT_READ);
                    659:                return 0;       /* try again later */
                    660:        case SSL_ERROR_WANT_WRITE:
                    661:                io_event_del(c->sock, IO_WANTREAD);
                    662:                Conn_OPTION_ADD(c, CONN_SSL_WANT_WRITE); /* fall through */
                    663:        case SSL_ERROR_NONE:
                    664:                return 0;       /* try again later */
                    665:        case SSL_ERROR_ZERO_RETURN:
                    666:                LogDebug("SSL connection shut down normally.");
                    667:                break;
                    668:        case SSL_ERROR_SYSCALL:
                    669:                /* SSL_ERROR_WANT_CONNECT, SSL_ERROR_WANT_ACCEPT,
                    670:                 * and SSL_ERROR_WANT_X509_LOOKUP */
                    671:                sslerr = ERR_get_error();
                    672:                if (sslerr) {
                    673:                        Log(LOG_ERR, "SSL error: %s [in %s()]!",
                    674:                            ERR_error_string(sslerr, NULL), fname);
                    675:                } else {
                    676:                        switch (code) { /* EOF that violated protocol */
                    677:                        case 0:
                    678:                                Log(LOG_ERR,
                    679:                                    "SSL error, client disconnected [in %s()]!",
                    680:                                    fname);
                    681:                                break;
                    682:                        case -1:        /* low level socket I/O error, check errno */
                    683:                                Log(LOG_ERR, "SSL error: %s [in %s()]!",
                    684:                                    strerror(real_errno), fname);
                    685:                        }
                    686:                }
                    687:                break;
                    688:        case SSL_ERROR_SSL:
                    689:                LogOpenSSLError("SSL protocol error", fname);
                    690:                break;
                    691:        default:
                    692:                Log(LOG_ERR, "Unknown SSL error %d [in %s()]!", ret, fname);
                    693:        }
                    694:        ConnSSL_Free(c);
                    695:        return -1;
                    696: #endif
                    697: #ifdef HAVE_LIBGNUTLS
                    698:        switch (code) {
                    699:        case GNUTLS_E_AGAIN:
                    700:        case GNUTLS_E_INTERRUPTED:
                    701:                if (gnutls_record_get_direction(c->ssl_state.gnutls_session)) {
                    702:                        Conn_OPTION_ADD(c, CONN_SSL_WANT_WRITE);
                    703:                        io_event_del(c->sock, IO_WANTREAD);
                    704:                } else {
                    705:                        Conn_OPTION_ADD(c, CONN_SSL_WANT_READ);
                    706:                        io_event_del(c->sock, IO_WANTWRITE);
                    707:                }
                    708:                break;
                    709:        default:
                    710:                assert(code < 0);
                    711:                if (gnutls_error_is_fatal(code)) {
                    712:                        Log(LOG_ERR, "SSL error: %s [%s].",
                    713:                            gnutls_strerror(code), fname);
                    714:                        ConnSSL_Free(c);
                    715:                        return -1;
                    716:                }
                    717:        }
                    718:        return 0;
                    719: #endif
                    720: }
                    721:
                    722:
                    723: static void
                    724: ConnSSL_LogCertInfo( CONNECTION *c )
                    725: {
                    726: #ifdef HAVE_LIBSSL
                    727:        SSL *ssl = c->ssl_state.ssl;
                    728:
                    729:        assert(ssl);
                    730:
                    731:        Log(LOG_INFO, "Connection %d: initialized %s using cipher %s.",
                    732:                c->sock, SSL_get_version(ssl), SSL_get_cipher(ssl));
                    733: #endif
                    734: #ifdef HAVE_LIBGNUTLS
                    735:        gnutls_session_t sess = c->ssl_state.gnutls_session;
                    736:        gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(sess);
                    737:
                    738:        Log(LOG_INFO, "Connection %d: initialized %s using cipher %s-%s.",
                    739:            c->sock,
                    740:            gnutls_protocol_get_name(gnutls_protocol_get_version(sess)),
                    741:            gnutls_cipher_get_name(cipher),
                    742:            gnutls_mac_get_name(gnutls_mac_get(sess)));
                    743: #endif
                    744: }
                    745:
                    746:
                    747: /*
                    748:  Accept incoming SSL connection.
                    749:  Return Values:
                    750:         1: SSL Connection established
                    751:         0: try again
                    752:        -1: SSL Connection not established due to fatal error.
                    753: */
                    754: int
                    755: ConnSSL_Accept( CONNECTION *c )
                    756: {
                    757:        assert(c != NULL);
                    758:        if (!Conn_OPTION_ISSET(c, CONN_SSL)) {
                    759: #ifdef HAVE_LIBGNUTLS
                    760:                int err = gnutls_init(&c->ssl_state.gnutls_session, GNUTLS_SERVER);
                    761:                if (err) {
                    762:                        Log(LOG_ERR, "Failed to initialize new SSL session: %s",
                    763:                            gnutls_strerror(err));
                    764:                        return false;
                    765:                }
                    766: #endif
                    767:                if (!ConnSSL_Init_SSL(c))
                    768:                        return -1;
                    769:        }
                    770:        return ConnectAccept(c, false );
                    771: }
                    772:
                    773:
                    774: int
                    775: ConnSSL_Connect( CONNECTION *c )
                    776: {
                    777:        assert(c != NULL);
                    778: #ifdef HAVE_LIBSSL
                    779:        assert(c->ssl_state.ssl);
                    780: #endif
                    781:        assert(Conn_OPTION_ISSET(c, CONN_SSL));
                    782:        return ConnectAccept(c, true);
                    783: }
                    784:
                    785: static int
                    786: ConnSSL_InitCertFp( CONNECTION *c )
                    787: {
                    788:        const char hex[] = "0123456789abcdef";
                    789:        int i;
                    790:
                    791: #ifdef HAVE_LIBSSL
                    792:        unsigned char digest[EVP_MAX_MD_SIZE];
                    793:        unsigned int digest_size;
                    794:        X509 *cert;
                    795:
                    796:        cert = SSL_get_peer_certificate(c->ssl_state.ssl);
                    797:        if (!cert)
                    798:                return 0;
                    799:
                    800:        if (!X509_digest(cert, EVP_sha256(), digest, &digest_size)) {
                    801:                X509_free(cert);
                    802:                return 0;
                    803:        }
                    804:
                    805:        X509_free(cert);
                    806: #endif /* HAVE_LIBSSL */
                    807: #ifdef HAVE_LIBGNUTLS
                    808:        gnutls_x509_crt_t cert;
                    809:        unsigned int cert_list_size;
                    810:        const gnutls_datum_t *cert_list;
                    811:        unsigned char digest[MAX_HASH_SIZE];
                    812:        size_t digest_size;
                    813:
                    814:        if (gnutls_certificate_type_get(c->ssl_state.gnutls_session) !=
                    815:                                        GNUTLS_CRT_X509)
                    816:                return 0;
                    817:
                    818:        if (gnutls_x509_crt_init(&cert) != GNUTLS_E_SUCCESS)
                    819:                return 0;
                    820:
                    821:        cert_list_size = 0;
                    822:        cert_list = gnutls_certificate_get_peers(c->ssl_state.gnutls_session,
                    823:                                                 &cert_list_size);
                    824:        if (!cert_list) {
                    825:                gnutls_x509_crt_deinit(cert);
                    826:                return 0;
                    827:        }
                    828:
                    829:        if (gnutls_x509_crt_import(cert, &cert_list[0],
                    830:                                   GNUTLS_X509_FMT_DER) != GNUTLS_E_SUCCESS) {
                    831:                gnutls_x509_crt_deinit(cert);
                    832:                return 0;
                    833:        }
                    834:
                    835:        digest_size = sizeof(digest);
                    836:        if (gnutls_x509_crt_get_fingerprint(cert, GNUTLS_DIG_SHA256, digest,
                    837:                                            &digest_size)) {
                    838:                gnutls_x509_crt_deinit(cert);
                    839:                return 0;
                    840:        }
                    841:
                    842:        gnutls_x509_crt_deinit(cert);
                    843: #endif /* HAVE_LIBGNUTLS */
                    844:
                    845:        assert(c->ssl_state.fingerprint == NULL);
                    846:
                    847:        c->ssl_state.fingerprint = malloc(SHA256_STRING_LEN);
                    848:        if (!c->ssl_state.fingerprint)
                    849:                return 0;
                    850:
                    851:        for (i = 0; i < (int)digest_size; i++) {
                    852:                c->ssl_state.fingerprint[i * 2] = hex[digest[i] / 16];
                    853:                c->ssl_state.fingerprint[i * 2 + 1] = hex[digest[i] % 16];
                    854:        }
                    855:        c->ssl_state.fingerprint[i * 2] = '\0';
                    856:
                    857:        return 1;
                    858: }
                    859:
                    860: /* accept/connect wrapper. if connect is true, connect to peer, otherwise wait for incoming connection */
                    861: static int
                    862: ConnectAccept( CONNECTION *c, bool connect)
                    863: {
                    864:        int ret;
                    865: #ifdef HAVE_LIBSSL
                    866:        SSL *ssl = c->ssl_state.ssl;
                    867:        assert(ssl != NULL);
                    868:
                    869:        ret = connect ? SSL_connect(ssl) : SSL_accept(ssl);
                    870:        if (1 != ret)
                    871:                return ConnSSL_HandleError(c, ret, connect ? "SSL_connect": "SSL_accept");
                    872: #endif
                    873: #ifdef HAVE_LIBGNUTLS
                    874:        (void) connect;
                    875:        ret = gnutls_handshake(c->ssl_state.gnutls_session);
                    876:        if (ret)
                    877:                return ConnSSL_HandleError(c, ret, "gnutls_handshake");
                    878: #endif /* _GNUTLS */
                    879:        (void)ConnSSL_InitCertFp(c);
                    880:
                    881:        Conn_OPTION_DEL(c, (CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT));
                    882:        ConnSSL_LogCertInfo(c);
                    883:
                    884:        Conn_StartLogin(CONNECTION2ID(c));
                    885:        return 1;
                    886: }
                    887:
                    888:
                    889: ssize_t
                    890: ConnSSL_Write(CONNECTION *c, const void *buf, size_t count)
                    891: {
                    892:        ssize_t bw;
                    893:
                    894:        Conn_OPTION_DEL(c, CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ);
                    895:
                    896:        assert(count > 0);
                    897: #ifdef HAVE_LIBSSL
                    898:        bw = (ssize_t) SSL_write(c->ssl_state.ssl, buf, count);
                    899: #endif
                    900: #ifdef HAVE_LIBGNUTLS
                    901:        bw = gnutls_write(c->ssl_state.gnutls_session, buf, count);
                    902: #endif
                    903:        if (bw > 0)
                    904:                return bw;
                    905:        if (ConnSSL_HandleError( c, bw, "ConnSSL_Write") == 0)
                    906:                errno = EAGAIN; /* try again */
                    907:        return -1;
                    908: }
                    909:
                    910:
                    911: ssize_t
                    912: ConnSSL_Read(CONNECTION *c, void * buf, size_t count)
                    913: {
                    914:        ssize_t br;
                    915:
                    916:        Conn_OPTION_DEL(c, CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ);
                    917: #ifdef HAVE_LIBSSL
                    918:         br = (ssize_t) SSL_read(c->ssl_state.ssl, buf, count);
                    919:        if (br > 0)     /* on EOF we have to call ConnSSL_HandleError(), see SSL_read(3) */
                    920:                return br;
                    921: #endif
                    922: #ifdef HAVE_LIBGNUTLS
                    923:        br = gnutls_read(c->ssl_state.gnutls_session, buf, count);
                    924:        if (br >= 0)    /* on EOF we must _not_ call ConnSSL_HandleError, see gnutls_record_recv(3) */
                    925:                return br;
                    926: #endif
                    927:        /* error on read: switch ConnSSL_HandleError() return values -> 0 is "try again", so return -1 and set EAGAIN */
                    928:        if (ConnSSL_HandleError(c, br, "ConnSSL_Read") == 0) {
                    929:                errno = EAGAIN;
                    930:                return -1;
                    931:        }
                    932:        return 0;
                    933: }
                    934:
                    935:
                    936: bool
                    937: ConnSSL_GetCipherInfo(CONNECTION *c, char *buf, size_t len)
                    938: {
                    939: #ifdef HAVE_LIBSSL
                    940:        char *nl;
                    941:        SSL *ssl = c->ssl_state.ssl;
                    942:
                    943:        if (!ssl)
                    944:                return false;
                    945:        *buf = 0;
                    946:        SSL_CIPHER_description(SSL_get_current_cipher(ssl), buf, len);
                    947:        nl = strchr(buf, '\n');
                    948:        if (nl)
                    949:                *nl = 0;
                    950:        return true;
                    951: #endif
                    952: #ifdef HAVE_LIBGNUTLS
                    953:        if (Conn_OPTION_ISSET(c, CONN_SSL)) {
                    954:                const char *name_cipher, *name_mac, *name_proto, *name_keyexchange;
                    955:                unsigned keysize;
                    956:
                    957:                gnutls_session_t sess = c->ssl_state.gnutls_session;
                    958:                gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(sess);
                    959:                name_cipher = gnutls_cipher_get_name(cipher);
                    960:                name_mac = gnutls_mac_get_name(gnutls_mac_get(sess));
                    961:                keysize = gnutls_cipher_get_key_size(cipher) * 8;
                    962:                name_proto = gnutls_protocol_get_name(gnutls_protocol_get_version(sess));
                    963:                name_keyexchange = gnutls_kx_get_name(gnutls_kx_get(sess));
                    964:
                    965:                return snprintf(buf, len, "%s-%s%15s Kx=%s      Enc=%s(%u) Mac=%s",
                    966:                        name_cipher, name_mac, name_proto, name_keyexchange, name_cipher, keysize, name_mac) > 0;
                    967:        }
                    968:        return false;
                    969: #endif
                    970: }
                    971:
                    972: char *
                    973: ConnSSL_GetCertFp(CONNECTION *c)
                    974: {
                    975:        return c->ssl_state.fingerprint;
                    976: }
                    977:
                    978: bool
                    979: ConnSSL_SetCertFp(CONNECTION *c, const char *fingerprint)
                    980: {
                    981:        assert (c != NULL);
                    982:        c->ssl_state.fingerprint = strndup(fingerprint, SHA256_STRING_LEN - 1);
                    983:        return c->ssl_state.fingerprint != NULL;
                    984: }
                    985: #else
                    986:
                    987: bool
                    988: ConnSSL_InitLibrary(void)
                    989: {
                    990:        return true;
                    991: }
                    992:
                    993: #endif /* SSL_SUPPORT */
                    994: /* -eof- */

CVSweb