Annotation of embedaddon/strongswan/src/libtls/tls_server.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2010 Martin Willi
        !             3:  * Copyright (C) 2010 revosec AG
        !             4:  *
        !             5:  * This program is free software; you can redistribute it and/or modify it
        !             6:  * under the terms of the GNU General Public License as published by the
        !             7:  * Free Software Foundation; either version 2 of the License, or (at your
        !             8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !             9:  *
        !            10:  * This program is distributed in the hope that it will be useful, but
        !            11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            13:  * for more details.
        !            14:  */
        !            15: 
        !            16: #include "tls_server.h"
        !            17: 
        !            18: #include <time.h>
        !            19: 
        !            20: #include <utils/debug.h>
        !            21: #include <credentials/certificates/x509.h>
        !            22: 
        !            23: typedef struct private_tls_server_t private_tls_server_t;
        !            24: 
        !            25: /**
        !            26:  * Size of a session ID
        !            27:  */
        !            28: #define SESSION_ID_SIZE 16
        !            29: 
        !            30: typedef enum {
        !            31:        STATE_INIT,
        !            32:        STATE_HELLO_RECEIVED,
        !            33:        STATE_HELLO_SENT,
        !            34:        STATE_CERT_SENT,
        !            35:        STATE_KEY_EXCHANGE_SENT,
        !            36:        STATE_CERTREQ_SENT,
        !            37:        STATE_HELLO_DONE,
        !            38:        STATE_CERT_RECEIVED,
        !            39:        STATE_KEY_EXCHANGE_RECEIVED,
        !            40:        STATE_CERT_VERIFY_RECEIVED,
        !            41:        STATE_CIPHERSPEC_CHANGED_IN,
        !            42:        STATE_FINISHED_RECEIVED,
        !            43:        STATE_CIPHERSPEC_CHANGED_OUT,
        !            44:        STATE_FINISHED_SENT,
        !            45: } server_state_t;
        !            46: 
        !            47: /**
        !            48:  * Private data of an tls_server_t object.
        !            49:  */
        !            50: struct private_tls_server_t {
        !            51: 
        !            52:        /**
        !            53:         * Public tls_server_t interface.
        !            54:         */
        !            55:        tls_server_t public;
        !            56: 
        !            57:        /**
        !            58:         * TLS stack
        !            59:         */
        !            60:        tls_t *tls;
        !            61: 
        !            62:        /**
        !            63:         * TLS crypto context
        !            64:         */
        !            65:        tls_crypto_t *crypto;
        !            66: 
        !            67:        /**
        !            68:         * TLS alert handler
        !            69:         */
        !            70:        tls_alert_t *alert;
        !            71: 
        !            72:        /**
        !            73:         * Server identity
        !            74:         */
        !            75:        identification_t *server;
        !            76: 
        !            77:        /**
        !            78:         * Peer identity, NULL for no client authentication
        !            79:         */
        !            80:        identification_t *peer;
        !            81: 
        !            82:        /**
        !            83:         * Is it acceptable if we couldn't verify the peer certificate?
        !            84:         */
        !            85:        bool peer_auth_optional;
        !            86: 
        !            87:        /**
        !            88:         * State we are in
        !            89:         */
        !            90:        server_state_t state;
        !            91: 
        !            92:        /**
        !            93:         * Hello random data selected by client
        !            94:         */
        !            95:        char client_random[32];
        !            96: 
        !            97:        /**
        !            98:         * Hello random data selected by server
        !            99:         */
        !           100:        char server_random[32];
        !           101: 
        !           102:        /**
        !           103:         * Auth helper for peer authentication
        !           104:         */
        !           105:        auth_cfg_t *peer_auth;
        !           106: 
        !           107:        /**
        !           108:         * Auth helper for server authentication
        !           109:         */
        !           110:        auth_cfg_t *server_auth;
        !           111: 
        !           112:        /**
        !           113:         * Peer private key
        !           114:         */
        !           115:        private_key_t *private;
        !           116: 
        !           117:        /**
        !           118:         * DHE exchange
        !           119:         */
        !           120:        diffie_hellman_t *dh;
        !           121: 
        !           122:        /**
        !           123:         * Selected TLS cipher suite
        !           124:         */
        !           125:        tls_cipher_suite_t suite;
        !           126: 
        !           127:        /**
        !           128:         * Offered TLS version of the client
        !           129:         */
        !           130:        tls_version_t client_version;
        !           131: 
        !           132:        /**
        !           133:         * TLS session identifier
        !           134:         */
        !           135:        chunk_t session;
        !           136: 
        !           137:        /**
        !           138:         * Do we resume a session?
        !           139:         */
        !           140:        bool resume;
        !           141: 
        !           142:        /**
        !           143:         * Hash and signature algorithms supported by peer
        !           144:         */
        !           145:        chunk_t hashsig;
        !           146: 
        !           147:        /**
        !           148:         * Elliptic curves supported by peer
        !           149:         */
        !           150:        chunk_t curves;
        !           151: 
        !           152:        /**
        !           153:         * Did we receive the curves from the client?
        !           154:         */
        !           155:        bool curves_received;
        !           156: };
        !           157: 
        !           158: /**
        !           159:  * Find a cipher suite and a server key
        !           160:  */
        !           161: static bool select_suite_and_key(private_tls_server_t *this,
        !           162:                                                                 tls_cipher_suite_t *suites, int count)
        !           163: {
        !           164:        private_key_t *key;
        !           165:        key_type_t type;
        !           166: 
        !           167:        key = lib->credmgr->get_private(lib->credmgr, KEY_ANY, this->server,
        !           168:                                                                        this->server_auth);
        !           169:        if (!key)
        !           170:        {
        !           171:                DBG1(DBG_TLS, "no usable TLS server certificate found for '%Y'",
        !           172:                         this->server);
        !           173:                return FALSE;
        !           174:        }
        !           175:        this->suite = this->crypto->select_cipher_suite(this->crypto,
        !           176:                                                                                        suites, count, key->get_type(key));
        !           177:        if (!this->suite)
        !           178:        {       /* no match for this key, try to find another type */
        !           179:                if (key->get_type(key) == KEY_ECDSA)
        !           180:                {
        !           181:                        type = KEY_RSA;
        !           182:                }
        !           183:                else
        !           184:                {
        !           185:                        type = KEY_ECDSA;
        !           186:                }
        !           187:                key->destroy(key);
        !           188: 
        !           189:                this->suite = this->crypto->select_cipher_suite(this->crypto,
        !           190:                                                                                        suites, count, type);
        !           191:                if (!this->suite)
        !           192:                {
        !           193:                        DBG1(DBG_TLS, "received cipher suites unacceptable");
        !           194:                        return FALSE;
        !           195:                }
        !           196:                this->server_auth->destroy(this->server_auth);
        !           197:                this->server_auth = auth_cfg_create();
        !           198:                key = lib->credmgr->get_private(lib->credmgr, type, this->server,
        !           199:                                                                                this->server_auth);
        !           200:                if (!key)
        !           201:                {
        !           202:                        DBG1(DBG_TLS, "received cipher suites unacceptable");
        !           203:                        return FALSE;
        !           204:                }
        !           205:        }
        !           206:        this->private = key;
        !           207:        return TRUE;
        !           208: }
        !           209: 
        !           210: /**
        !           211:  * Process client hello message
        !           212:  */
        !           213: static status_t process_client_hello(private_tls_server_t *this,
        !           214:                                                                         bio_reader_t *reader)
        !           215: {
        !           216:        uint16_t version, extension;
        !           217:        chunk_t random, session, ciphers, compression, ext = chunk_empty;
        !           218:        bio_reader_t *extensions;
        !           219:        tls_cipher_suite_t *suites;
        !           220:        int count, i;
        !           221:        rng_t *rng;
        !           222: 
        !           223:        this->crypto->append_handshake(this->crypto,
        !           224:                                                                   TLS_CLIENT_HELLO, reader->peek(reader));
        !           225: 
        !           226:        if (!reader->read_uint16(reader, &version) ||
        !           227:                !reader->read_data(reader, sizeof(this->client_random), &random) ||
        !           228:                !reader->read_data8(reader, &session) ||
        !           229:                !reader->read_data16(reader, &ciphers) ||
        !           230:                !reader->read_data8(reader, &compression) ||
        !           231:                (reader->remaining(reader) && !reader->read_data16(reader, &ext)))
        !           232:        {
        !           233:                DBG1(DBG_TLS, "received invalid ClientHello");
        !           234:                this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
        !           235:                return NEED_MORE;
        !           236:        }
        !           237: 
        !           238:        if (ext.len)
        !           239:        {
        !           240:                extensions = bio_reader_create(ext);
        !           241:                while (extensions->remaining(extensions))
        !           242:                {
        !           243:                        if (!extensions->read_uint16(extensions, &extension) ||
        !           244:                                !extensions->read_data16(extensions, &ext))
        !           245:                        {
        !           246:                                DBG1(DBG_TLS, "received invalid ClientHello Extensions");
        !           247:                                this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
        !           248:                                extensions->destroy(extensions);
        !           249:                                return NEED_MORE;
        !           250:                        }
        !           251:                        DBG2(DBG_TLS, "received TLS '%N' extension",
        !           252:                                 tls_extension_names, extension);
        !           253:                        DBG3(DBG_TLS, "%B", &ext);
        !           254:                        switch (extension)
        !           255:                        {
        !           256:                                case TLS_EXT_SIGNATURE_ALGORITHMS:
        !           257:                                        this->hashsig = chunk_clone(ext);
        !           258:                                        break;
        !           259:                                case TLS_EXT_ELLIPTIC_CURVES:
        !           260:                                        this->curves_received = TRUE;
        !           261:                                        this->curves = chunk_clone(ext);
        !           262:                                        break;
        !           263:                                default:
        !           264:                                        break;
        !           265:                        }
        !           266:                }
        !           267:                extensions->destroy(extensions);
        !           268:        }
        !           269: 
        !           270:        memcpy(this->client_random, random.ptr, sizeof(this->client_random));
        !           271: 
        !           272:        htoun32(&this->server_random, time(NULL));
        !           273:        rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
        !           274:        if (!rng ||
        !           275:                !rng->get_bytes(rng, sizeof(this->server_random) - 4,
        !           276:                                                this->server_random + 4))
        !           277:        {
        !           278:                DBG1(DBG_TLS, "failed to generate server random");
        !           279:                this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           280:                DESTROY_IF(rng);
        !           281:                return NEED_MORE;
        !           282:        }
        !           283:        rng->destroy(rng);
        !           284: 
        !           285:        if (!this->tls->set_version(this->tls, version))
        !           286:        {
        !           287:                DBG1(DBG_TLS, "negotiated version %N not supported",
        !           288:                         tls_version_names, version);
        !           289:                this->alert->add(this->alert, TLS_FATAL, TLS_PROTOCOL_VERSION);
        !           290:                return NEED_MORE;
        !           291:        }
        !           292: 
        !           293:        this->client_version = version;
        !           294:        this->suite = this->crypto->resume_session(this->crypto, session, this->peer,
        !           295:                                                                                chunk_from_thing(this->client_random),
        !           296:                                                                                chunk_from_thing(this->server_random));
        !           297:        if (this->suite)
        !           298:        {
        !           299:                this->session = chunk_clone(session);
        !           300:                this->resume = TRUE;
        !           301:                DBG1(DBG_TLS, "resumed %N using suite %N",
        !           302:                         tls_version_names, this->tls->get_version(this->tls),
        !           303:                         tls_cipher_suite_names, this->suite);
        !           304:        }
        !           305:        else
        !           306:        {
        !           307:                count = ciphers.len / sizeof(uint16_t);
        !           308:                suites = alloca(count * sizeof(tls_cipher_suite_t));
        !           309:                DBG2(DBG_TLS, "received %d TLS cipher suites:", count);
        !           310:                for (i = 0; i < count; i++)
        !           311:                {
        !           312:                        suites[i] = untoh16(&ciphers.ptr[i * sizeof(uint16_t)]);
        !           313:                        DBG2(DBG_TLS, "  %N", tls_cipher_suite_names, suites[i]);
        !           314:                }
        !           315:                if (!select_suite_and_key(this, suites, count))
        !           316:                {
        !           317:                        this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
        !           318:                        return NEED_MORE;
        !           319:                }
        !           320:                rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
        !           321:                if (!rng || !rng->allocate_bytes(rng, SESSION_ID_SIZE, &this->session))
        !           322:                {
        !           323:                        DBG1(DBG_TLS, "generating TLS session identifier failed, skipped");
        !           324:                }
        !           325:                DESTROY_IF(rng);
        !           326:                DBG1(DBG_TLS, "negotiated %N using suite %N",
        !           327:                         tls_version_names, this->tls->get_version(this->tls),
        !           328:                         tls_cipher_suite_names, this->suite);
        !           329:        }
        !           330:        this->state = STATE_HELLO_RECEIVED;
        !           331:        return NEED_MORE;
        !           332: }
        !           333: 
        !           334: /**
        !           335:  * Process certificate
        !           336:  */
        !           337: static status_t process_certificate(private_tls_server_t *this,
        !           338:                                                                        bio_reader_t *reader)
        !           339: {
        !           340:        certificate_t *cert;
        !           341:        bio_reader_t *certs;
        !           342:        chunk_t data;
        !           343:        bool first = TRUE;
        !           344: 
        !           345:        this->crypto->append_handshake(this->crypto,
        !           346:                                                                   TLS_CERTIFICATE, reader->peek(reader));
        !           347: 
        !           348:        if (!reader->read_data24(reader, &data))
        !           349:        {
        !           350:                DBG1(DBG_TLS, "certificate message header invalid");
        !           351:                this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
        !           352:                return NEED_MORE;
        !           353:        }
        !           354:        certs = bio_reader_create(data);
        !           355:        while (certs->remaining(certs))
        !           356:        {
        !           357:                if (!certs->read_data24(certs, &data))
        !           358:                {
        !           359:                        DBG1(DBG_TLS, "certificate message invalid");
        !           360:                        this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
        !           361:                        certs->destroy(certs);
        !           362:                        return NEED_MORE;
        !           363:                }
        !           364:                cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
        !           365:                                                                  BUILD_BLOB_ASN1_DER, data, BUILD_END);
        !           366:                if (cert)
        !           367:                {
        !           368:                        if (first)
        !           369:                        {
        !           370:                                this->peer_auth->add(this->peer_auth,
        !           371:                                                                         AUTH_HELPER_SUBJECT_CERT, cert);
        !           372:                                DBG1(DBG_TLS, "received TLS peer certificate '%Y'",
        !           373:                                         cert->get_subject(cert));
        !           374:                                first = FALSE;
        !           375:                                if (this->peer == NULL)
        !           376:                                {       /* apply identity to authenticate */
        !           377:                                        this->peer = cert->get_subject(cert);
        !           378:                                        this->peer = this->peer->clone(this->peer);
        !           379:                                        this->peer_auth_optional = TRUE;
        !           380:                                }
        !           381:                        }
        !           382:                        else
        !           383:                        {
        !           384:                                DBG1(DBG_TLS, "received TLS intermediate certificate '%Y'",
        !           385:                                         cert->get_subject(cert));
        !           386:                                this->peer_auth->add(this->peer_auth, AUTH_HELPER_IM_CERT, cert);
        !           387:                        }
        !           388:                }
        !           389:                else
        !           390:                {
        !           391:                        DBG1(DBG_TLS, "parsing TLS certificate failed, skipped");
        !           392:                        this->alert->add(this->alert, TLS_WARNING, TLS_BAD_CERTIFICATE);
        !           393:                }
        !           394:        }
        !           395:        certs->destroy(certs);
        !           396:        this->state = STATE_CERT_RECEIVED;
        !           397:        return NEED_MORE;
        !           398: }
        !           399: 
        !           400: /**
        !           401:  * Process Client Key Exchange, using premaster encryption
        !           402:  */
        !           403: static status_t process_key_exchange_encrypted(private_tls_server_t *this,
        !           404:                                                                                           bio_reader_t *reader)
        !           405: {
        !           406:        chunk_t encrypted, decrypted;
        !           407:        char premaster[48];
        !           408:        rng_t *rng;
        !           409: 
        !           410:        this->crypto->append_handshake(this->crypto,
        !           411:                                                                   TLS_CLIENT_KEY_EXCHANGE, reader->peek(reader));
        !           412: 
        !           413:        if (!reader->read_data16(reader, &encrypted))
        !           414:        {
        !           415:                DBG1(DBG_TLS, "received invalid Client Key Exchange");
        !           416:                this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
        !           417:                return NEED_MORE;
        !           418:        }
        !           419: 
        !           420:        htoun16(premaster, this->client_version);
        !           421:        /* pre-randomize premaster for failure cases */
        !           422:        rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
        !           423:        if (!rng || !rng->get_bytes(rng, sizeof(premaster) - 2, premaster + 2))
        !           424:        {
        !           425:                DBG1(DBG_TLS, "failed to generate premaster secret");
        !           426:                this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           427:                DESTROY_IF(rng);
        !           428:                return NEED_MORE;
        !           429:        }
        !           430:        rng->destroy(rng);
        !           431: 
        !           432:        if (this->private &&
        !           433:                this->private->decrypt(this->private,
        !           434:                                                           ENCRYPT_RSA_PKCS1, encrypted, &decrypted))
        !           435:        {
        !           436:                if (decrypted.len == sizeof(premaster) &&
        !           437:                        untoh16(decrypted.ptr) == this->client_version)
        !           438:                {
        !           439:                        memcpy(premaster + 2, decrypted.ptr + 2, sizeof(premaster) - 2);
        !           440:                }
        !           441:                else
        !           442:                {
        !           443:                        DBG1(DBG_TLS, "decrypted premaster has invalid length/version");
        !           444:                }
        !           445:                chunk_clear(&decrypted);
        !           446:        }
        !           447:        else
        !           448:        {
        !           449:                DBG1(DBG_TLS, "decrypting Client Key Exchange failed");
        !           450:        }
        !           451: 
        !           452:        if (!this->crypto->derive_secrets(this->crypto, chunk_from_thing(premaster),
        !           453:                                                                          this->session, this->peer,
        !           454:                                                                          chunk_from_thing(this->client_random),
        !           455:                                                                          chunk_from_thing(this->server_random)))
        !           456:        {
        !           457:                this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           458:                return NEED_MORE;
        !           459:        }
        !           460: 
        !           461:        this->state = STATE_KEY_EXCHANGE_RECEIVED;
        !           462:        return NEED_MORE;
        !           463: }
        !           464: 
        !           465: /**
        !           466:  * Process client key exchange, using DHE exchange
        !           467:  */
        !           468: static status_t process_key_exchange_dhe(private_tls_server_t *this,
        !           469:                                                                                 bio_reader_t *reader)
        !           470: {
        !           471:        chunk_t premaster, pub;
        !           472:        bool ec;
        !           473: 
        !           474:        this->crypto->append_handshake(this->crypto,
        !           475:                                                                   TLS_CLIENT_KEY_EXCHANGE, reader->peek(reader));
        !           476: 
        !           477:        ec = diffie_hellman_group_is_ec(this->dh->get_dh_group(this->dh));
        !           478:        if ((ec && !reader->read_data8(reader, &pub)) ||
        !           479:                (!ec && (!reader->read_data16(reader, &pub) || pub.len == 0)))
        !           480:        {
        !           481:                DBG1(DBG_TLS, "received invalid Client Key Exchange");
        !           482:                this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
        !           483:                return NEED_MORE;
        !           484:        }
        !           485: 
        !           486:        if (ec)
        !           487:        {
        !           488:                if (pub.ptr[0] != TLS_ANSI_UNCOMPRESSED)
        !           489:                {
        !           490:                        DBG1(DBG_TLS, "DH point format '%N' not supported",
        !           491:                                 tls_ansi_point_format_names, pub.ptr[0]);
        !           492:                        this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           493:                        return NEED_MORE;
        !           494:                }
        !           495:                pub = chunk_skip(pub, 1);
        !           496:        }
        !           497:        if (!this->dh->set_other_public_value(this->dh, pub))
        !           498:        {
        !           499:                DBG1(DBG_TLS, "applying DH public value failed");
        !           500:                this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           501:                return NEED_MORE;
        !           502:        }
        !           503:        if (!this->dh->get_shared_secret(this->dh, &premaster))
        !           504:        {
        !           505:                DBG1(DBG_TLS, "calculating premaster from DH failed");
        !           506:                this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           507:                return NEED_MORE;
        !           508:        }
        !           509: 
        !           510:        if (!this->crypto->derive_secrets(this->crypto, premaster,
        !           511:                                                                          this->session, this->peer,
        !           512:                                                                          chunk_from_thing(this->client_random),
        !           513:                                                                          chunk_from_thing(this->server_random)))
        !           514:        {
        !           515:                this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           516:                chunk_clear(&premaster);
        !           517:                return NEED_MORE;
        !           518:        }
        !           519:        chunk_clear(&premaster);
        !           520: 
        !           521:        this->state = STATE_KEY_EXCHANGE_RECEIVED;
        !           522:        return NEED_MORE;
        !           523: }
        !           524: 
        !           525: /**
        !           526:  * Process Client Key Exchange
        !           527:  */
        !           528: static status_t process_key_exchange(private_tls_server_t *this,
        !           529:                                                                         bio_reader_t *reader)
        !           530: {
        !           531:        if (this->dh)
        !           532:        {
        !           533:                return process_key_exchange_dhe(this, reader);
        !           534:        }
        !           535:        return process_key_exchange_encrypted(this, reader);
        !           536: }
        !           537: 
        !           538: /**
        !           539:  * Process Certificate verify
        !           540:  */
        !           541: static status_t process_cert_verify(private_tls_server_t *this,
        !           542:                                                                        bio_reader_t *reader)
        !           543: {
        !           544:        bool verified = FALSE;
        !           545:        enumerator_t *enumerator;
        !           546:        public_key_t *public;
        !           547:        auth_cfg_t *auth;
        !           548:        bio_reader_t *sig;
        !           549: 
        !           550:        enumerator = lib->credmgr->create_public_enumerator(lib->credmgr,
        !           551:                                                                        KEY_ANY, this->peer, this->peer_auth, TRUE);
        !           552:        while (enumerator->enumerate(enumerator, &public, &auth))
        !           553:        {
        !           554:                sig = bio_reader_create(reader->peek(reader));
        !           555:                verified = this->crypto->verify_handshake(this->crypto, public, sig);
        !           556:                sig->destroy(sig);
        !           557:                if (verified)
        !           558:                {
        !           559:                        this->peer_auth->merge(this->peer_auth, auth, FALSE);
        !           560:                        break;
        !           561:                }
        !           562:                DBG1(DBG_TLS, "signature verification failed, trying another key");
        !           563:        }
        !           564:        enumerator->destroy(enumerator);
        !           565: 
        !           566:        if (!verified)
        !           567:        {
        !           568:                DBG1(DBG_TLS, "no trusted certificate found for '%Y' to verify TLS peer",
        !           569:                         this->peer);
        !           570:                if (!this->peer_auth_optional)
        !           571:                {       /* client authentication is required */
        !           572:                        this->alert->add(this->alert, TLS_FATAL, TLS_CERTIFICATE_UNKNOWN);
        !           573:                        return NEED_MORE;
        !           574:                }
        !           575:                /* reset peer identity, we couldn't authenticate it */
        !           576:                this->peer->destroy(this->peer);
        !           577:                this->peer = NULL;
        !           578:                this->state = STATE_KEY_EXCHANGE_RECEIVED;
        !           579:        }
        !           580:        else
        !           581:        {
        !           582:                this->state = STATE_CERT_VERIFY_RECEIVED;
        !           583:        }
        !           584:        this->crypto->append_handshake(this->crypto,
        !           585:                                                                   TLS_CERTIFICATE_VERIFY, reader->peek(reader));
        !           586:        return NEED_MORE;
        !           587: }
        !           588: 
        !           589: /**
        !           590:  * Process finished message
        !           591:  */
        !           592: static status_t process_finished(private_tls_server_t *this,
        !           593:                                                                 bio_reader_t *reader)
        !           594: {
        !           595:        chunk_t received;
        !           596:        char buf[12];
        !           597: 
        !           598:        if (!reader->read_data(reader, sizeof(buf), &received))
        !           599:        {
        !           600:                DBG1(DBG_TLS, "received client finished too short");
        !           601:                this->alert->add(this->alert, TLS_FATAL, TLS_DECODE_ERROR);
        !           602:                return NEED_MORE;
        !           603:        }
        !           604:        if (!this->crypto->calculate_finished(this->crypto, "client finished", buf))
        !           605:        {
        !           606:                DBG1(DBG_TLS, "calculating client finished failed");
        !           607:                this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           608:                return NEED_MORE;
        !           609:        }
        !           610:        if (!chunk_equals_const(received, chunk_from_thing(buf)))
        !           611:        {
        !           612:                DBG1(DBG_TLS, "received client finished invalid");
        !           613:                this->alert->add(this->alert, TLS_FATAL, TLS_DECRYPT_ERROR);
        !           614:                return NEED_MORE;
        !           615:        }
        !           616: 
        !           617:        this->crypto->append_handshake(this->crypto, TLS_FINISHED, received);
        !           618:        this->state = STATE_FINISHED_RECEIVED;
        !           619:        return NEED_MORE;
        !           620: }
        !           621: 
        !           622: METHOD(tls_handshake_t, process, status_t,
        !           623:        private_tls_server_t *this, tls_handshake_type_t type, bio_reader_t *reader)
        !           624: {
        !           625:        tls_handshake_type_t expected;
        !           626: 
        !           627:        switch (this->state)
        !           628:        {
        !           629:                case STATE_INIT:
        !           630:                        if (type == TLS_CLIENT_HELLO)
        !           631:                        {
        !           632:                                return process_client_hello(this, reader);
        !           633:                        }
        !           634:                        expected = TLS_CLIENT_HELLO;
        !           635:                        break;
        !           636:                case STATE_HELLO_DONE:
        !           637:                        if (type == TLS_CERTIFICATE)
        !           638:                        {
        !           639:                                return process_certificate(this, reader);
        !           640:                        }
        !           641:                        if (this->peer)
        !           642:                        {
        !           643:                                expected = TLS_CERTIFICATE;
        !           644:                                break;
        !           645:                        }
        !           646:                        /* otherwise fall through to next state */
        !           647:                case STATE_CERT_RECEIVED:
        !           648:                        if (type == TLS_CLIENT_KEY_EXCHANGE)
        !           649:                        {
        !           650:                                return process_key_exchange(this, reader);
        !           651:                        }
        !           652:                        expected = TLS_CLIENT_KEY_EXCHANGE;
        !           653:                        break;
        !           654:                case STATE_KEY_EXCHANGE_RECEIVED:
        !           655:                        if (type == TLS_CERTIFICATE_VERIFY)
        !           656:                        {
        !           657:                                return process_cert_verify(this, reader);
        !           658:                        }
        !           659:                        if (this->peer)
        !           660:                        {
        !           661:                                expected = TLS_CERTIFICATE_VERIFY;
        !           662:                                break;
        !           663:                        }
        !           664:                        return INVALID_STATE;
        !           665:                case STATE_CIPHERSPEC_CHANGED_IN:
        !           666:                        if (type == TLS_FINISHED)
        !           667:                        {
        !           668:                                return process_finished(this, reader);
        !           669:                        }
        !           670:                        expected = TLS_FINISHED;
        !           671:                        break;
        !           672:                default:
        !           673:                        DBG1(DBG_TLS, "TLS %N not expected in current state",
        !           674:                                 tls_handshake_type_names, type);
        !           675:                        this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE);
        !           676:                        return NEED_MORE;
        !           677:        }
        !           678:        DBG1(DBG_TLS, "TLS %N expected, but received %N",
        !           679:                 tls_handshake_type_names, expected, tls_handshake_type_names, type);
        !           680:        this->alert->add(this->alert, TLS_FATAL, TLS_UNEXPECTED_MESSAGE);
        !           681:        return NEED_MORE;
        !           682: }
        !           683: 
        !           684: /**
        !           685:  * Send ServerHello message
        !           686:  */
        !           687: static status_t send_server_hello(private_tls_server_t *this,
        !           688:                                                        tls_handshake_type_t *type, bio_writer_t *writer)
        !           689: {
        !           690:        /* TLS version */
        !           691:        writer->write_uint16(writer, this->tls->get_version(this->tls));
        !           692:        writer->write_data(writer, chunk_from_thing(this->server_random));
        !           693: 
        !           694:        /* session identifier if we have one */
        !           695:        writer->write_data8(writer, this->session);
        !           696: 
        !           697:        /* add selected TLS cipher suite */
        !           698:        writer->write_uint16(writer, this->suite);
        !           699: 
        !           700:        /* NULL compression only */
        !           701:        writer->write_uint8(writer, 0);
        !           702: 
        !           703:        *type = TLS_SERVER_HELLO;
        !           704:        this->state = STATE_HELLO_SENT;
        !           705:        this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
        !           706:        return NEED_MORE;
        !           707: }
        !           708: 
        !           709: /**
        !           710:  * Send Certificate
        !           711:  */
        !           712: static status_t send_certificate(private_tls_server_t *this,
        !           713:                                                        tls_handshake_type_t *type, bio_writer_t *writer)
        !           714: {
        !           715:        enumerator_t *enumerator;
        !           716:        certificate_t *cert;
        !           717:        auth_rule_t rule;
        !           718:        bio_writer_t *certs;
        !           719:        chunk_t data;
        !           720: 
        !           721:        /* generate certificate payload */
        !           722:        certs = bio_writer_create(256);
        !           723:        cert = this->server_auth->get(this->server_auth, AUTH_RULE_SUBJECT_CERT);
        !           724:        if (cert)
        !           725:        {
        !           726:                if (cert->get_encoding(cert, CERT_ASN1_DER, &data))
        !           727:                {
        !           728:                        DBG1(DBG_TLS, "sending TLS server certificate '%Y'",
        !           729:                                 cert->get_subject(cert));
        !           730:                        certs->write_data24(certs, data);
        !           731:                        free(data.ptr);
        !           732:                }
        !           733:        }
        !           734:        enumerator = this->server_auth->create_enumerator(this->server_auth);
        !           735:        while (enumerator->enumerate(enumerator, &rule, &cert))
        !           736:        {
        !           737:                if (rule == AUTH_RULE_IM_CERT)
        !           738:                {
        !           739:                        if (cert->get_encoding(cert, CERT_ASN1_DER, &data))
        !           740:                        {
        !           741:                                DBG1(DBG_TLS, "sending TLS intermediate certificate '%Y'",
        !           742:                                         cert->get_subject(cert));
        !           743:                                certs->write_data24(certs, data);
        !           744:                                free(data.ptr);
        !           745:                        }
        !           746:                }
        !           747:        }
        !           748:        enumerator->destroy(enumerator);
        !           749: 
        !           750:        writer->write_data24(writer, certs->get_buf(certs));
        !           751:        certs->destroy(certs);
        !           752: 
        !           753:        *type = TLS_CERTIFICATE;
        !           754:        this->state = STATE_CERT_SENT;
        !           755:        this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
        !           756:        return NEED_MORE;
        !           757: }
        !           758: 
        !           759: /**
        !           760:  * Send Certificate Request
        !           761:  */
        !           762: static status_t send_certificate_request(private_tls_server_t *this,
        !           763:                                                        tls_handshake_type_t *type, bio_writer_t *writer)
        !           764: {
        !           765:        bio_writer_t *authorities, *supported;
        !           766:        enumerator_t *enumerator;
        !           767:        certificate_t *cert;
        !           768:        x509_t *x509;
        !           769:        identification_t *id;
        !           770: 
        !           771:        supported = bio_writer_create(4);
        !           772:        /* we propose both RSA and ECDSA */
        !           773:        supported->write_uint8(supported, TLS_RSA_SIGN);
        !           774:        supported->write_uint8(supported, TLS_ECDSA_SIGN);
        !           775:        writer->write_data8(writer, supported->get_buf(supported));
        !           776:        supported->destroy(supported);
        !           777:        if (this->tls->get_version(this->tls) >= TLS_1_2)
        !           778:        {
        !           779:                this->crypto->get_signature_algorithms(this->crypto, writer);
        !           780:        }
        !           781: 
        !           782:        authorities = bio_writer_create(64);
        !           783:        enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
        !           784:                                                                                                CERT_X509, KEY_RSA, NULL, TRUE);
        !           785:        while (enumerator->enumerate(enumerator, &cert))
        !           786:        {
        !           787:                x509 = (x509_t*)cert;
        !           788:                if (x509->get_flags(x509) & X509_CA)
        !           789:                {
        !           790:                        id = cert->get_subject(cert);
        !           791:                        DBG1(DBG_TLS, "sending TLS cert request for '%Y'", id);
        !           792:                        authorities->write_data16(authorities, id->get_encoding(id));
        !           793:                }
        !           794:        }
        !           795:        enumerator->destroy(enumerator);
        !           796:        writer->write_data16(writer, authorities->get_buf(authorities));
        !           797:        authorities->destroy(authorities);
        !           798: 
        !           799:        *type = TLS_CERTIFICATE_REQUEST;
        !           800:        this->state = STATE_CERTREQ_SENT;
        !           801:        this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
        !           802:        return NEED_MORE;
        !           803: }
        !           804: 
        !           805: /**
        !           806:  * Get the TLS curve of a given EC DH group
        !           807:  */
        !           808: static tls_named_curve_t ec_group_to_curve(private_tls_server_t *this,
        !           809:                                                                                   diffie_hellman_group_t group)
        !           810: {
        !           811:        diffie_hellman_group_t current;
        !           812:        tls_named_curve_t curve;
        !           813:        enumerator_t *enumerator;
        !           814: 
        !           815:        enumerator = this->crypto->create_ec_enumerator(this->crypto);
        !           816:        while (enumerator->enumerate(enumerator, &current, &curve))
        !           817:        {
        !           818:                if (current == group)
        !           819:                {
        !           820:                        enumerator->destroy(enumerator);
        !           821:                        return curve;
        !           822:                }
        !           823:        }
        !           824:        enumerator->destroy(enumerator);
        !           825:        return 0;
        !           826: }
        !           827: 
        !           828: /**
        !           829:  * Check if the peer supports a given TLS curve
        !           830:  */
        !           831: bool peer_supports_curve(private_tls_server_t *this, tls_named_curve_t curve)
        !           832: {
        !           833:        bio_reader_t *reader;
        !           834:        uint16_t current;
        !           835: 
        !           836:        if (!this->curves_received)
        !           837:        {       /* none received, assume yes */
        !           838:                return TRUE;
        !           839:        }
        !           840:        reader = bio_reader_create(this->curves);
        !           841:        while (reader->remaining(reader) && reader->read_uint16(reader, &current))
        !           842:        {
        !           843:                if (current == curve)
        !           844:                {
        !           845:                        reader->destroy(reader);
        !           846:                        return TRUE;
        !           847:                }
        !           848:        }
        !           849:        reader->destroy(reader);
        !           850:        return FALSE;
        !           851: }
        !           852: 
        !           853: /**
        !           854:  * Try to find a curve supported by both, client and server
        !           855:  */
        !           856: static bool find_supported_curve(private_tls_server_t *this,
        !           857:                                                                 tls_named_curve_t *curve)
        !           858: {
        !           859:        tls_named_curve_t current;
        !           860:        enumerator_t *enumerator;
        !           861: 
        !           862:        enumerator = this->crypto->create_ec_enumerator(this->crypto);
        !           863:        while (enumerator->enumerate(enumerator, NULL, &current))
        !           864:        {
        !           865:                if (peer_supports_curve(this, current))
        !           866:                {
        !           867:                        *curve = current;
        !           868:                        enumerator->destroy(enumerator);
        !           869:                        return TRUE;
        !           870:                }
        !           871:        }
        !           872:        enumerator->destroy(enumerator);
        !           873:        return FALSE;
        !           874: }
        !           875: 
        !           876: /**
        !           877:  * Send Server key Exchange
        !           878:  */
        !           879: static status_t send_server_key_exchange(private_tls_server_t *this,
        !           880:                                                        tls_handshake_type_t *type, bio_writer_t *writer,
        !           881:                                                        diffie_hellman_group_t group)
        !           882: {
        !           883:        diffie_hellman_params_t *params = NULL;
        !           884:        tls_named_curve_t curve;
        !           885:        chunk_t chunk;
        !           886: 
        !           887:        if (diffie_hellman_group_is_ec(group))
        !           888:        {
        !           889:                curve = ec_group_to_curve(this, group);
        !           890:                if (!curve || (!peer_supports_curve(this, curve) &&
        !           891:                                           !find_supported_curve(this, &curve)))
        !           892:                {
        !           893:                        DBG1(DBG_TLS, "no EC group supported by client and server");
        !           894:                        this->alert->add(this->alert, TLS_FATAL, TLS_HANDSHAKE_FAILURE);
        !           895:                        return NEED_MORE;
        !           896:                }
        !           897:                DBG2(DBG_TLS, "selected ECDH group %N", tls_named_curve_names, curve);
        !           898:                writer->write_uint8(writer, TLS_ECC_NAMED_CURVE);
        !           899:                writer->write_uint16(writer, curve);
        !           900:        }
        !           901:        else
        !           902:        {
        !           903:                params = diffie_hellman_get_params(group);
        !           904:                if (!params)
        !           905:                {
        !           906:                        DBG1(DBG_TLS, "no parameters found for DH group %N",
        !           907:                                 diffie_hellman_group_names, group);
        !           908:                        this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           909:                        return NEED_MORE;
        !           910:                }
        !           911:                DBG2(DBG_TLS, "selected DH group %N", diffie_hellman_group_names, group);
        !           912:                writer->write_data16(writer, params->prime);
        !           913:                writer->write_data16(writer, params->generator);
        !           914:        }
        !           915:        this->dh = lib->crypto->create_dh(lib->crypto, group);
        !           916:        if (!this->dh)
        !           917:        {
        !           918:                DBG1(DBG_TLS, "DH group %N not supported",
        !           919:                         diffie_hellman_group_names, group);
        !           920:                this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           921:                return NEED_MORE;
        !           922:        }
        !           923:        if (!this->dh->get_my_public_value(this->dh, &chunk))
        !           924:        {
        !           925:                this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           926:                return NEED_MORE;
        !           927:        }
        !           928:        if (params)
        !           929:        {
        !           930:                writer->write_data16(writer, chunk);
        !           931:        }
        !           932:        else
        !           933:        {       /* ECP uses 8bit length header only, but a point format */
        !           934:                writer->write_uint8(writer, chunk.len + 1);
        !           935:                writer->write_uint8(writer, TLS_ANSI_UNCOMPRESSED);
        !           936:                writer->write_data(writer, chunk);
        !           937:        }
        !           938:        free(chunk.ptr);
        !           939: 
        !           940:        chunk = chunk_cat("ccc", chunk_from_thing(this->client_random),
        !           941:                                chunk_from_thing(this->server_random), writer->get_buf(writer));
        !           942:        if (!this->private || !this->crypto->sign(this->crypto, this->private,
        !           943:                                                                                          writer, chunk, this->hashsig))
        !           944:        {
        !           945:                DBG1(DBG_TLS, "signing DH parameters failed");
        !           946:                this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           947:                free(chunk.ptr);
        !           948:                return NEED_MORE;
        !           949:        }
        !           950:        free(chunk.ptr);
        !           951:        *type = TLS_SERVER_KEY_EXCHANGE;
        !           952:        this->state = STATE_KEY_EXCHANGE_SENT;
        !           953:        this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
        !           954:        return NEED_MORE;
        !           955: }
        !           956: 
        !           957: /**
        !           958:  * Send Hello Done
        !           959:  */
        !           960: static status_t send_hello_done(private_tls_server_t *this,
        !           961:                                                        tls_handshake_type_t *type, bio_writer_t *writer)
        !           962: {
        !           963:        *type = TLS_SERVER_HELLO_DONE;
        !           964:        this->state = STATE_HELLO_DONE;
        !           965:        this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
        !           966:        return NEED_MORE;
        !           967: }
        !           968: 
        !           969: /**
        !           970:  * Send Finished
        !           971:  */
        !           972: static status_t send_finished(private_tls_server_t *this,
        !           973:                                                          tls_handshake_type_t *type, bio_writer_t *writer)
        !           974: {
        !           975:        char buf[12];
        !           976: 
        !           977:        if (!this->crypto->calculate_finished(this->crypto, "server finished", buf))
        !           978:        {
        !           979:                DBG1(DBG_TLS, "calculating server finished data failed");
        !           980:                this->alert->add(this->alert, TLS_FATAL, TLS_INTERNAL_ERROR);
        !           981:                return FAILED;
        !           982:        }
        !           983: 
        !           984:        writer->write_data(writer, chunk_from_thing(buf));
        !           985: 
        !           986:        *type = TLS_FINISHED;
        !           987:        this->state = STATE_FINISHED_SENT;
        !           988:        this->crypto->append_handshake(this->crypto, *type, writer->get_buf(writer));
        !           989: 
        !           990:        return NEED_MORE;
        !           991: }
        !           992: 
        !           993: METHOD(tls_handshake_t, build, status_t,
        !           994:        private_tls_server_t *this, tls_handshake_type_t *type, bio_writer_t *writer)
        !           995: {
        !           996:        diffie_hellman_group_t group;
        !           997: 
        !           998:        switch (this->state)
        !           999:        {
        !          1000:                case STATE_HELLO_RECEIVED:
        !          1001:                        return send_server_hello(this, type, writer);
        !          1002:                case STATE_HELLO_SENT:
        !          1003:                        return send_certificate(this, type, writer);
        !          1004:                case STATE_CERT_SENT:
        !          1005:                        group = this->crypto->get_dh_group(this->crypto);
        !          1006:                        if (group)
        !          1007:                        {
        !          1008:                                return send_server_key_exchange(this, type, writer, group);
        !          1009:                        }
        !          1010:                        /* otherwise fall through to next state */
        !          1011:                case STATE_KEY_EXCHANGE_SENT:
        !          1012:                        return send_certificate_request(this, type, writer);
        !          1013:                case STATE_CERTREQ_SENT:
        !          1014:                        return send_hello_done(this, type, writer);
        !          1015:                case STATE_CIPHERSPEC_CHANGED_OUT:
        !          1016:                        return send_finished(this, type, writer);
        !          1017:                case STATE_FINISHED_SENT:
        !          1018:                        return INVALID_STATE;
        !          1019:                default:
        !          1020:                        return INVALID_STATE;
        !          1021:        }
        !          1022: }
        !          1023: 
        !          1024: METHOD(tls_handshake_t, cipherspec_changed, bool,
        !          1025:        private_tls_server_t *this, bool inbound)
        !          1026: {
        !          1027:        if (inbound)
        !          1028:        {
        !          1029:                if (this->resume)
        !          1030:                {
        !          1031:                        return this->state == STATE_FINISHED_SENT;
        !          1032:                }
        !          1033:                if (this->peer)
        !          1034:                {
        !          1035:                        return this->state == STATE_CERT_VERIFY_RECEIVED;
        !          1036:                }
        !          1037:                return this->state == STATE_KEY_EXCHANGE_RECEIVED;
        !          1038:        }
        !          1039:        else
        !          1040:        {
        !          1041:                if (this->resume)
        !          1042:                {
        !          1043:                        return this->state == STATE_HELLO_SENT;
        !          1044:                }
        !          1045:                return this->state == STATE_FINISHED_RECEIVED;
        !          1046:        }
        !          1047:        return FALSE;
        !          1048: }
        !          1049: 
        !          1050: METHOD(tls_handshake_t, change_cipherspec, void,
        !          1051:        private_tls_server_t *this, bool inbound)
        !          1052: {
        !          1053:        this->crypto->change_cipher(this->crypto, inbound);
        !          1054:        if (inbound)
        !          1055:        {
        !          1056:                this->state = STATE_CIPHERSPEC_CHANGED_IN;
        !          1057:        }
        !          1058:        else
        !          1059:        {
        !          1060:                this->state = STATE_CIPHERSPEC_CHANGED_OUT;
        !          1061:        }
        !          1062: }
        !          1063: 
        !          1064: METHOD(tls_handshake_t, finished, bool,
        !          1065:        private_tls_server_t *this)
        !          1066: {
        !          1067:        if (this->resume)
        !          1068:        {
        !          1069:                return this->state == STATE_FINISHED_RECEIVED;
        !          1070:        }
        !          1071:        return this->state == STATE_FINISHED_SENT;
        !          1072: }
        !          1073: 
        !          1074: METHOD(tls_handshake_t, get_peer_id, identification_t*,
        !          1075:        private_tls_server_t *this)
        !          1076: {
        !          1077:        return this->peer;
        !          1078: }
        !          1079: 
        !          1080: METHOD(tls_handshake_t, get_server_id, identification_t*,
        !          1081:        private_tls_server_t *this)
        !          1082: {
        !          1083:        return this->server;
        !          1084: }
        !          1085: 
        !          1086: METHOD(tls_handshake_t, get_auth, auth_cfg_t*,
        !          1087:        private_tls_server_t *this)
        !          1088: {
        !          1089:        return this->peer_auth;
        !          1090: }
        !          1091: 
        !          1092: METHOD(tls_handshake_t, destroy, void,
        !          1093:        private_tls_server_t *this)
        !          1094: {
        !          1095:        DESTROY_IF(this->private);
        !          1096:        DESTROY_IF(this->dh);
        !          1097:        DESTROY_IF(this->peer);
        !          1098:        this->server->destroy(this->server);
        !          1099:        this->peer_auth->destroy(this->peer_auth);
        !          1100:        this->server_auth->destroy(this->server_auth);
        !          1101:        free(this->hashsig.ptr);
        !          1102:        free(this->curves.ptr);
        !          1103:        free(this->session.ptr);
        !          1104:        free(this);
        !          1105: }
        !          1106: 
        !          1107: /**
        !          1108:  * See header
        !          1109:  */
        !          1110: tls_server_t *tls_server_create(tls_t *tls,
        !          1111:                                                tls_crypto_t *crypto, tls_alert_t *alert,
        !          1112:                                                identification_t *server, identification_t *peer)
        !          1113: {
        !          1114:        private_tls_server_t *this;
        !          1115: 
        !          1116:        INIT(this,
        !          1117:                .public = {
        !          1118:                        .handshake = {
        !          1119:                                .process = _process,
        !          1120:                                .build = _build,
        !          1121:                                .cipherspec_changed = _cipherspec_changed,
        !          1122:                                .change_cipherspec = _change_cipherspec,
        !          1123:                                .finished = _finished,
        !          1124:                                .get_peer_id = _get_peer_id,
        !          1125:                                .get_server_id = _get_server_id,
        !          1126:                                .get_auth = _get_auth,
        !          1127:                                .destroy = _destroy,
        !          1128:                        },
        !          1129:                },
        !          1130:                .tls = tls,
        !          1131:                .crypto = crypto,
        !          1132:                .alert = alert,
        !          1133:                .server = server->clone(server),
        !          1134:                .peer = peer ? peer->clone(peer) : NULL,
        !          1135:                .state = STATE_INIT,
        !          1136:                .peer_auth = auth_cfg_create(),
        !          1137:                .server_auth = auth_cfg_create(),
        !          1138:        );
        !          1139: 
        !          1140:        return &this->public;
        !          1141: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>