Annotation of embedaddon/strongswan/src/charon-cmd/cmd/cmd_creds.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2013 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * Copyright (C) 2013 Martin Willi
                      6:  * Copyright (C) 2013 revosec AG
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify it
                      9:  * under the terms of the GNU General Public License as published by the
                     10:  * Free Software Foundation; either version 2 of the License, or (at your
                     11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     16:  * for more details.
                     17:  */
                     18: 
                     19: #include "cmd_creds.h"
                     20: 
                     21: #include <unistd.h>
                     22: 
                     23: #include <utils/debug.h>
                     24: #include <credentials/sets/mem_cred.h>
                     25: #include <credentials/containers/pkcs12.h>
                     26: #include <credentials/sets/callback_cred.h>
                     27: 
                     28: typedef struct private_cmd_creds_t private_cmd_creds_t;
                     29: 
                     30: /**
                     31:  * Private data of an cmd_creds_t object.
                     32:  */
                     33: struct private_cmd_creds_t {
                     34: 
                     35:        /**
                     36:         * Public cmd_creds_t interface.
                     37:         */
                     38:        cmd_creds_t public;
                     39: 
                     40:        /**
                     41:         * Reused in-memory credential set
                     42:         */
                     43:        mem_cred_t *creds;
                     44: 
                     45:        /**
                     46:         * Callback credential set to get secrets
                     47:         */
                     48:        callback_cred_t *cb;
                     49: 
                     50:        /**
                     51:         * Kind of secret we recently prompted
                     52:         */
                     53:        shared_key_type_t prompted;
                     54: 
                     55:        /**
                     56:         * Path to ssh-agent socket
                     57:         */
                     58:        char *agent;
                     59: 
                     60:        /**
                     61:         * Local identity
                     62:         */
                     63:        char *identity;
                     64: };
                     65: 
                     66: /**
                     67:  * Callback function to prompt for secret
                     68:  */
                     69: static shared_key_t* callback_shared(private_cmd_creds_t *this,
                     70:                                                                shared_key_type_t type,
                     71:                                                                identification_t *me, identification_t *other,
                     72:                                                                id_match_t *match_me, id_match_t *match_other)
                     73: {
                     74:        shared_key_t *shared;
                     75:        char *label, *pwd = NULL;
                     76: 
                     77:        if (type == this->prompted)
                     78:        {
                     79:                return NULL;
                     80:        }
                     81:        switch (type)
                     82:        {
                     83:                case SHARED_EAP:
                     84:                        label = "EAP password: ";
                     85:                        break;
                     86:                case SHARED_IKE:
                     87:                        label = "Preshared Key: ";
                     88:                        break;
                     89:                case SHARED_PRIVATE_KEY_PASS:
                     90:                        label = "Password: ";
                     91:                        break;
                     92:                case SHARED_PIN:
                     93:                        label = "PIN: ";
                     94:                        break;
                     95:                default:
                     96:                        return NULL;
                     97:        }
                     98: #ifdef HAVE_GETPASS
                     99:        pwd = getpass(label);
                    100: #endif
                    101:        if (!pwd || strlen(pwd) == 0)
                    102:        {
                    103:                return NULL;
                    104:        }
                    105:        this->prompted = type;
                    106:        if (match_me)
                    107:        {
                    108:                *match_me = ID_MATCH_PERFECT;
                    109:        }
                    110:        if (match_other)
                    111:        {
                    112:                *match_other = ID_MATCH_PERFECT;
                    113:        }
                    114:        shared = shared_key_create(type, chunk_clone(chunk_from_str(pwd)));
                    115:        /* cache password in case it is required more than once */
                    116:        this->creds->add_shared(this->creds, shared, NULL);
                    117:        return shared->get_ref(shared);
                    118: }
                    119: 
                    120: /**
                    121:  * Load a trusted certificate from path
                    122:  */
                    123: static void load_cert(private_cmd_creds_t *this, char *path)
                    124: {
                    125:        certificate_t *cert;
                    126: 
                    127:        cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
                    128:                                                          BUILD_FROM_FILE, path, BUILD_END);
                    129:        if (!cert)
                    130:        {
                    131:                DBG1(DBG_CFG, "loading certificate from '%s' failed", path);
                    132:                exit(1);
                    133:        }
                    134:        this->creds->add_cert(this->creds, TRUE, cert);
                    135: }
                    136: 
                    137: /**
                    138:  * Load a private key of given kind from path
                    139:  */
                    140: static void load_key(private_cmd_creds_t *this, key_type_t type, char *path)
                    141: {
                    142:        private_key_t *privkey;
                    143: 
                    144:        privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
                    145:                                                                 BUILD_FROM_FILE, path, BUILD_END);
                    146:        if (!privkey)
                    147:        {
                    148:                DBG1(DBG_CFG, "loading %N private key from '%s' failed",
                    149:                         key_type_names, type, path);
                    150:                exit(1);
                    151:        }
                    152:        this->creds->add_key(this->creds, privkey);
                    153: }
                    154: 
                    155: /**
                    156:  * Load a private and public key via ssh-agent
                    157:  */
                    158: static void load_agent(private_cmd_creds_t *this)
                    159: {
                    160:        private_key_t *privkey;
                    161:        public_key_t *pubkey;
                    162:        identification_t *id;
                    163:        certificate_t *cert;
                    164: 
                    165:        privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
                    166:                                                                 BUILD_AGENT_SOCKET, this->agent, BUILD_END);
                    167:        if (!privkey)
                    168:        {
                    169:                DBG1(DBG_CFG, "failed to load private key from ssh-agent");
                    170:                exit(1);
                    171:        }
                    172:        pubkey = privkey->get_public_key(privkey);
                    173:        if (!pubkey)
                    174:        {
                    175:                DBG1(DBG_CFG, "failed to load public key from ssh-agent");
                    176:                privkey->destroy(privkey);
                    177:                exit(1);
                    178:        }
                    179:        id = identification_create_from_string(this->identity);
                    180:        cert = lib->creds->create(lib->creds, CRED_CERTIFICATE,
                    181:                                                          CERT_TRUSTED_PUBKEY, BUILD_PUBLIC_KEY, pubkey,
                    182:                                                          BUILD_SUBJECT, id, BUILD_END);
                    183:        pubkey->destroy(pubkey);
                    184:        id->destroy(id);
                    185:        if (!cert)
                    186:        {
                    187:                DBG1(DBG_CFG, "failed to create certificate for ssh-agent public key");
                    188:                privkey->destroy(privkey);
                    189:                exit(1);
                    190:        }
                    191:        this->creds->add_cert(this->creds, TRUE, cert);
                    192:        this->creds->add_key(this->creds, privkey);
                    193: }
                    194: 
                    195: /**
                    196:  * Load a PKCS#12 file from path
                    197:  */
                    198: static void load_pkcs12(private_cmd_creds_t *this, char *path)
                    199: {
                    200:        enumerator_t *enumerator;
                    201:        certificate_t *cert;
                    202:        private_key_t *key;
                    203:        container_t *container;
                    204:        pkcs12_t *pkcs12;
                    205: 
                    206:        container = lib->creds->create(lib->creds, CRED_CONTAINER, CONTAINER_PKCS12,
                    207:                                                                   BUILD_FROM_FILE, path, BUILD_END);
                    208:        if (!container)
                    209:        {
                    210:                DBG1(DBG_CFG, "loading PKCS#12 file '%s' failed", path);
                    211:                exit(1);
                    212:        }
                    213:        pkcs12 = (pkcs12_t*)container;
                    214:        enumerator = pkcs12->create_cert_enumerator(pkcs12);
                    215:        while (enumerator->enumerate(enumerator, &cert))
                    216:        {
                    217:                this->creds->add_cert(this->creds, TRUE, cert->get_ref(cert));
                    218:        }
                    219:        enumerator->destroy(enumerator);
                    220:        enumerator = pkcs12->create_key_enumerator(pkcs12);
                    221:        while (enumerator->enumerate(enumerator, &key))
                    222:        {
                    223:                this->creds->add_key(this->creds, key->get_ref(key));
                    224:        }
                    225:        enumerator->destroy(enumerator);
                    226:        container->destroy(container);
                    227: }
                    228: 
                    229: METHOD(cmd_creds_t, handle, bool,
                    230:        private_cmd_creds_t *this, cmd_option_type_t opt, char *arg)
                    231: {
                    232:        switch (opt)
                    233:        {
                    234:                case CMD_OPT_CERT:
                    235:                        load_cert(this, arg);
                    236:                        break;
                    237:                case CMD_OPT_RSA:
                    238:                        load_key(this, KEY_RSA, arg);
                    239:                        break;
                    240:                case CMD_OPT_PKCS12:
                    241:                        load_pkcs12(this, arg);
                    242:                        break;
                    243:                case CMD_OPT_IDENTITY:
                    244:                        this->identity = arg;
                    245:                        break;
                    246:                case CMD_OPT_AGENT:
                    247:                        this->agent = arg ?: getenv("SSH_AUTH_SOCK");
                    248:                        if (!this->agent)
                    249:                        {
                    250:                                DBG1(DBG_CFG, "no ssh-agent socket defined");
                    251:                                exit(1);
                    252:                        }
                    253:                        break;
                    254:                default:
                    255:                        return FALSE;
                    256:        }
                    257:        if (this->agent && this->identity)
                    258:        {
                    259:                load_agent(this);
                    260:                /* only do this once */
                    261:                this->agent = NULL;
                    262:        }
                    263:        return TRUE;
                    264: }
                    265: 
                    266: METHOD(cmd_creds_t, destroy, void,
                    267:        private_cmd_creds_t *this)
                    268: {
                    269:        lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
                    270:        lib->credmgr->remove_set(lib->credmgr, &this->cb->set);
                    271:        this->creds->destroy(this->creds);
                    272:        this->cb->destroy(this->cb);
                    273:        free(this);
                    274: }
                    275: 
                    276: /**
                    277:  * See header
                    278:  */
                    279: cmd_creds_t *cmd_creds_create()
                    280: {
                    281:        private_cmd_creds_t *this;
                    282: 
                    283:        INIT(this,
                    284:                .public = {
                    285:                        .handle = _handle,
                    286:                        .destroy = _destroy,
                    287:                },
                    288:                .creds = mem_cred_create(),
                    289:                .prompted = SHARED_ANY,
                    290:        );
                    291:        this->cb = callback_cred_create_shared((void*)callback_shared, this);
                    292: 
                    293:        lib->credmgr->add_set(lib->credmgr, &this->creds->set);
                    294:        lib->credmgr->add_set(lib->credmgr, &this->cb->set);
                    295: 
                    296:        return &this->public;
                    297: }

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