Annotation of embedaddon/strongswan/src/pki/pki.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2012-2018 Tobias Brunner
                      3:  * Copyright (C) 2009 Martin Willi
                      4:  * HSR Hochschule fuer Technik Rapperswil
                      5:  *
                      6:  * This program is free software; you can redistribute it and/or modify it
                      7:  * under the terms of the GNU General Public License as published by the
                      8:  * Free Software Foundation; either version 2 of the License, or (at your
                      9:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     10:  *
                     11:  * This program is distributed in the hope that it will be useful, but
                     12:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     13:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     14:  * for more details.
                     15:  */
                     16: 
                     17: #define _GNU_SOURCE
                     18: #include "command.h"
                     19: #include "pki.h"
                     20: 
                     21: #include <time.h>
                     22: #include <unistd.h>
                     23: #include <fcntl.h>
                     24: 
                     25: #include <utils/debug.h>
                     26: #include <credentials/sets/mem_cred.h>
                     27: #include <credentials/sets/callback_cred.h>
                     28: 
                     29: /**
                     30:  * Convert a form string to a encoding type
                     31:  */
                     32: bool get_form(char *form, cred_encoding_type_t *enc, credential_type_t type)
                     33: {
                     34:        if (streq(form, "der"))
                     35:        {
                     36:                switch (type)
                     37:                {
                     38:                        case CRED_CERTIFICATE:
                     39:                                *enc = CERT_ASN1_DER;
                     40:                                return TRUE;
                     41:                        case CRED_PRIVATE_KEY:
                     42:                                *enc = PRIVKEY_ASN1_DER;
                     43:                                return TRUE;
                     44:                        case CRED_PUBLIC_KEY:
                     45:                                /* der encoded keys usually contain the complete
                     46:                                 * SubjectPublicKeyInfo */
                     47:                                *enc = PUBKEY_SPKI_ASN1_DER;
                     48:                                return TRUE;
                     49:                        default:
                     50:                                return FALSE;
                     51:                }
                     52:        }
                     53:        else if (streq(form, "pem"))
                     54:        {
                     55:                switch (type)
                     56:                {
                     57:                        case CRED_CERTIFICATE:
                     58:                                *enc = CERT_PEM;
                     59:                                return TRUE;
                     60:                        case CRED_PRIVATE_KEY:
                     61:                                *enc = PRIVKEY_PEM;
                     62:                                return TRUE;
                     63:                        case CRED_PUBLIC_KEY:
                     64:                                *enc = PUBKEY_PEM;
                     65:                                return TRUE;
                     66:                        default:
                     67:                                return FALSE;
                     68:                }
                     69:        }
                     70:        else if (streq(form, "pgp"))
                     71:        {
                     72:                switch (type)
                     73:                {
                     74:                        case CRED_PRIVATE_KEY:
                     75:                                *enc = PRIVKEY_PGP;
                     76:                                return TRUE;
                     77:                        case CRED_PUBLIC_KEY:
                     78:                                *enc = PUBKEY_PGP;
                     79:                                return TRUE;
                     80:                        default:
                     81:                                return FALSE;
                     82:                }
                     83:        }
                     84:        else if (streq(form, "dnskey"))
                     85:        {
                     86:                switch (type)
                     87:                {
                     88:                        case CRED_PUBLIC_KEY:
                     89:                                *enc = PUBKEY_DNSKEY;
                     90:                                return TRUE;
                     91:                        default:
                     92:                                return FALSE;
                     93:                }
                     94:        }
                     95:        else if (streq(form, "sshkey"))
                     96:        {
                     97:                switch (type)
                     98:                {
                     99:                        case CRED_PUBLIC_KEY:
                    100:                                *enc = PUBKEY_SSHKEY;
                    101:                                return TRUE;
                    102:                        default:
                    103:                                return FALSE;
                    104:                }
                    105:        }
                    106:        return FALSE;
                    107: }
                    108: 
                    109: /**
                    110:  * Convert a time string to struct tm using strptime format
                    111:  */
                    112: static bool convert_time(char *str, char *format, struct tm *tm)
                    113: {
                    114: #ifdef HAVE_STRPTIME
                    115: 
                    116:        char *end;
                    117: 
                    118:        if (!format)
                    119:        {
                    120:                format = "%d.%m.%y %T";
                    121:        }
                    122: 
                    123:        end = strptime(str, format, tm);
                    124:        if (end == NULL || *end != '\0')
                    125:        {
                    126:                return FALSE;
                    127:        }
                    128:        return TRUE;
                    129: 
                    130: #else /* !HAVE_STRPTIME */
                    131: 
                    132:        if (format)
                    133:        {
                    134:                fprintf(stderr, "custom datetime string format not supported\n");
                    135:                return FALSE;
                    136:        }
                    137: 
                    138:        if (sscanf(str, "%d.%d.%d %d:%d:%d",
                    139:                           &tm->tm_mday, &tm->tm_mon, &tm->tm_year,
                    140:                           &tm->tm_hour, &tm->tm_min, &tm->tm_sec) != 6)
                    141:        {
                    142:                return FALSE;
                    143:        }
                    144:        /* strptime() interprets two-digit years > 68 as 19xx, do the same here.
                    145:         * mktime() expects years based on 1900 */
                    146:        if (tm->tm_year <= 68)
                    147:        {
                    148:                tm->tm_year += 100;
                    149:        }
                    150:        else if (tm->tm_year >= 1900)
                    151:        {       /* looks like four digits? */
                    152:                tm->tm_year -= 1900;
                    153:        }
                    154:        /* month is specified from 0-11 */
                    155:        tm->tm_mon--;
                    156:        /* automatically detect daylight saving time */
                    157:        tm->tm_isdst = -1;
                    158:        return TRUE;
                    159: 
                    160: #endif /* !HAVE_STRPTIME */
                    161: }
                    162: 
                    163: /**
                    164:  * See header
                    165:  */
                    166: bool calculate_lifetime(char *format, char *nbstr, char *nastr, time_t span,
                    167:                                                time_t *nb, time_t *na)
                    168: {
                    169:        struct tm tm;
                    170:        time_t now;
                    171: 
                    172:        now = time(NULL);
                    173: 
                    174:        localtime_r(&now, &tm);
                    175:        if (nbstr)
                    176:        {
                    177:                if (!convert_time(nbstr, format, &tm))
                    178:                {
                    179:                        return FALSE;
                    180:                }
                    181:        }
                    182:        *nb = mktime(&tm);
                    183:        if (*nb == -1)
                    184:        {
                    185:                return FALSE;
                    186:        }
                    187: 
                    188:        localtime_r(&now, &tm);
                    189:        if (nastr)
                    190:        {
                    191:                if (!convert_time(nastr, format, &tm))
                    192:                {
                    193:                        return FALSE;
                    194:                }
                    195:        }
                    196:        *na = mktime(&tm);
                    197:        if (*na == -1)
                    198:        {
                    199:                return FALSE;
                    200:        }
                    201: 
                    202:        if (!nbstr && nastr)
                    203:        {
                    204:                *nb = *na - span;
                    205:        }
                    206:        else if (!nastr)
                    207:        {
                    208:                *na = *nb + span;
                    209:        }
                    210:        return TRUE;
                    211: }
                    212: 
                    213: /**
                    214:  * Set output file mode appropriate for credential encoding form on Windows
                    215:  */
                    216: void set_file_mode(FILE *stream, cred_encoding_type_t enc)
                    217: {
                    218: #ifdef WIN32
                    219:        int fd;
                    220: 
                    221:        switch (enc)
                    222:        {
                    223:                case CERT_PEM:
                    224:                case PRIVKEY_PEM:
                    225:                case PUBKEY_PEM:
                    226:                        /* keep default text mode */
                    227:                        return;
                    228:                default:
                    229:                        /* switch to binary mode */
                    230:                        break;
                    231:        }
                    232:        fd = fileno(stream);
                    233:        if (fd != -1)
                    234:        {
                    235:                _setmode(fd, _O_BINARY);
                    236:        }
                    237: #endif
                    238: }
                    239: 
                    240: /**
                    241:  * Determine a default hash algorithm for the given key
                    242:  */
                    243: static hash_algorithm_t get_default_digest(private_key_t *private)
                    244: {
                    245:        enumerator_t *enumerator;
                    246:        signature_params_t *params;
                    247:        hash_algorithm_t alg = HASH_UNKNOWN;
                    248: 
                    249:        enumerator = signature_schemes_for_key(private->get_type(private),
                    250:                                                                                   private->get_keysize(private));
                    251:        if (enumerator->enumerate(enumerator, &params))
                    252:        {
                    253:                alg = hasher_from_signature_scheme(params->scheme, params->params);
                    254:        }
                    255:        enumerator->destroy(enumerator);
                    256: 
                    257:        /* default to SHA-256 */
                    258:        return alg == HASH_UNKNOWN ? HASH_SHA256 : alg;
                    259: }
                    260: 
                    261: /*
                    262:  * Described in header
                    263:  */
                    264: signature_params_t *get_signature_scheme(private_key_t *private,
                    265:                                                                                 hash_algorithm_t digest, bool pss)
                    266: {
                    267:        signature_params_t *scheme, *selected = NULL;
                    268:        enumerator_t *enumerator;
                    269: 
                    270:        if (private->supported_signature_schemes)
                    271:        {
                    272:                enumerator = private->supported_signature_schemes(private);
                    273:                while (enumerator->enumerate(enumerator, &scheme))
                    274:                {
                    275:                        if (private->get_type(private) == KEY_RSA &&
                    276:                                pss != (scheme->scheme == SIGN_RSA_EMSA_PSS))
                    277:                        {
                    278:                                continue;
                    279:                        }
                    280:                        if (digest == HASH_UNKNOWN ||
                    281:                                digest == hasher_from_signature_scheme(scheme->scheme,
                    282:                                                                                                           scheme->params))
                    283:                        {
                    284:                                selected = signature_params_clone(scheme);
                    285:                                break;
                    286:                        }
                    287:                }
                    288:                enumerator->destroy(enumerator);
                    289:                return selected;
                    290:        }
                    291: 
                    292:        if (digest == HASH_UNKNOWN)
                    293:        {
                    294:                digest = get_default_digest(private);
                    295:        }
                    296:        if (private->get_type(private) == KEY_RSA && pss)
                    297:        {
                    298:                rsa_pss_params_t pss_params = {
                    299:                        .hash = digest,
                    300:                        .mgf1_hash = digest,
                    301:                        .salt_len = RSA_PSS_SALT_LEN_DEFAULT,
                    302:                };
                    303:                signature_params_t pss_scheme = {
                    304:                        .scheme = SIGN_RSA_EMSA_PSS,
                    305:                        .params = &pss_params,
                    306:                };
                    307:                rsa_pss_params_set_salt_len(&pss_params, 0);
                    308:                scheme = signature_params_clone(&pss_scheme);
                    309:        }
                    310:        else
                    311:        {
                    312:                INIT(scheme,
                    313:                        .scheme = signature_scheme_from_oid(
                    314:                                                                hasher_signature_algorithm_to_oid(digest,
                    315:                                                                                                private->get_type(private))),
                    316:                );
                    317:        }
                    318:        return scheme;
                    319: }
                    320: 
                    321: /*
                    322:  * Described in header
                    323:  */
                    324: traffic_selector_t* parse_ts(char *str)
                    325: {
                    326:        ts_type_t type = TS_IPV4_ADDR_RANGE;
                    327:        char *to, from[64];
                    328: 
                    329:        if (strchr(str, ':'))
                    330:        {
                    331:                type = TS_IPV6_ADDR_RANGE;
                    332:        }
                    333:        to = strchr(str, '-');
                    334:        if (to)
                    335:        {
                    336:                snprintf(from, sizeof(from), "%.*s", (int)(to - str), str);
                    337:                to++;
                    338:                return traffic_selector_create_from_string(0, type, from, 0, to, 65535);
                    339:        }
                    340:        return traffic_selector_create_from_cidr(str, 0, 0, 65535);
                    341: }
                    342: 
                    343: /**
                    344:  * Callback credential set pki uses
                    345:  */
                    346: static callback_cred_t *cb_set;
                    347: 
                    348: /**
                    349:  * Credential set to cache entered secrets
                    350:  */
                    351: static mem_cred_t *cb_creds;
                    352: 
                    353: static shared_key_type_t prompted;
                    354: 
                    355: /**
                    356:  * Callback function to receive credentials
                    357:  */
                    358: static shared_key_t* cb(void *data, shared_key_type_t type,
                    359:                                                identification_t *me, identification_t *other,
                    360:                                                id_match_t *match_me, id_match_t *match_other)
                    361: {
                    362:        char buf[64], *label, *secret = NULL;
                    363:        shared_key_t *shared;
                    364: 
                    365:        if (prompted == type)
                    366:        {
                    367:                return NULL;
                    368:        }
                    369:        switch (type)
                    370:        {
                    371:                case SHARED_PIN:
                    372:                        label = "Smartcard PIN";
                    373:                        break;
                    374:                case SHARED_PRIVATE_KEY_PASS:
                    375:                        label = "Private key passphrase";
                    376:                        break;
                    377:                default:
                    378:                        return NULL;
                    379:        }
                    380:        snprintf(buf, sizeof(buf), "%s: ", label);
                    381: #ifdef HAVE_GETPASS
                    382:        secret = getpass(buf);
                    383: #endif
                    384:        if (secret && strlen(secret))
                    385:        {
                    386:                prompted = type;
                    387:                if (match_me)
                    388:                {
                    389:                        *match_me = ID_MATCH_PERFECT;
                    390:                }
                    391:                if (match_other)
                    392:                {
                    393:                        *match_other = ID_MATCH_NONE;
                    394:                }
                    395:                shared = shared_key_create(type, chunk_clone(chunk_from_str(secret)));
                    396:                /* cache password in case it is required more than once */
                    397:                cb_creds->add_shared(cb_creds, shared, NULL);
                    398:                return shared->get_ref(shared);
                    399:        }
                    400:        return NULL;
                    401: }
                    402: 
                    403: /**
                    404:  * Register PIN/Passphrase callback function
                    405:  */
                    406: static void add_callback()
                    407: {
                    408:        cb_set = callback_cred_create_shared(cb, NULL);
                    409:        lib->credmgr->add_set(lib->credmgr, &cb_set->set);
                    410:        cb_creds = mem_cred_create();
                    411:        lib->credmgr->add_set(lib->credmgr, &cb_creds->set);
                    412: }
                    413: 
                    414: /**
                    415:  * Unregister PIN/Passphrase callback function
                    416:  */
                    417: static void remove_callback()
                    418: {
                    419:        lib->credmgr->remove_set(lib->credmgr, &cb_creds->set);
                    420:        cb_creds->destroy(cb_creds);
                    421:        lib->credmgr->remove_set(lib->credmgr, &cb_set->set);
                    422:        cb_set->destroy(cb_set);
                    423: }
                    424: 
                    425: /**
                    426:  * Library initialization and operation parsing
                    427:  */
                    428: int main(int argc, char *argv[])
                    429: {
                    430:        char *plugins;
                    431: 
                    432:        atexit(library_deinit);
                    433:        if (!library_init(NULL, "pki"))
                    434:        {
                    435:                exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
                    436:        }
                    437:        if (lib->integrity &&
                    438:                !lib->integrity->check_file(lib->integrity, "pki", argv[0]))
                    439:        {
                    440:                fprintf(stderr, "integrity check of pki failed\n");
                    441:                exit(SS_RC_DAEMON_INTEGRITY);
                    442:        }
                    443:        plugins = getenv("PKI_PLUGINS");
                    444:        if (!plugins)
                    445:        {
                    446:                plugins = lib->settings->get_str(lib->settings, "pki.load", PLUGINS);
                    447:        }
                    448:        if (!lib->plugins->load(lib->plugins, plugins))
                    449:        {
                    450:                exit(SS_RC_INITIALIZATION_FAILED);
                    451:        }
                    452: 
                    453:        add_callback();
                    454:        atexit(remove_callback);
                    455:        return command_dispatch(argc, argv);
                    456: }

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