[BACK]Return to ssh-pkcs11-helper.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Annotation of src/usr.bin/ssh/ssh-pkcs11-helper.c, Revision 1.23

1.23    ! markus      1: /* $OpenBSD: ssh-pkcs11-helper.c,v 1.22 2020/01/25 00:03:36 djm Exp $ */
1.1       markus      2: /*
                      3:  * Copyright (c) 2010 Markus Friedl.  All rights reserved.
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17:
1.9       djm        18: #include <sys/types.h>
1.1       markus     19: #include <sys/queue.h>
                     20: #include <sys/time.h>
                     21:
1.20      djm        22: #include <stdlib.h>
1.17      djm        23: #include <errno.h>
                     24: #include <poll.h>
1.1       markus     25: #include <stdarg.h>
                     26: #include <string.h>
                     27: #include <unistd.h>
                     28:
                     29: #include "xmalloc.h"
1.14      markus     30: #include "sshbuf.h"
1.1       markus     31: #include "log.h"
                     32: #include "misc.h"
1.14      markus     33: #include "sshkey.h"
1.1       markus     34: #include "authfd.h"
                     35: #include "ssh-pkcs11.h"
1.14      markus     36: #include "ssherr.h"
1.1       markus     37:
1.21      djm        38: #ifdef WITH_OPENSSL
                     39:
1.1       markus     40: /* borrows code from sftp-server and ssh-agent */
                     41:
                     42: struct pkcs11_keyinfo {
1.13      markus     43:        struct sshkey   *key;
1.22      djm        44:        char            *providername, *label;
1.1       markus     45:        TAILQ_ENTRY(pkcs11_keyinfo) next;
                     46: };
                     47:
                     48: TAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist;
                     49:
                     50: #define MAX_MSG_LENGTH         10240 /*XXX*/
                     51:
                     52: /* input and output queue */
1.14      markus     53: struct sshbuf *iqueue;
                     54: struct sshbuf *oqueue;
1.1       markus     55:
                     56: static void
1.22      djm        57: add_key(struct sshkey *k, char *name, char *label)
1.1       markus     58: {
                     59:        struct pkcs11_keyinfo *ki;
                     60:
                     61:        ki = xcalloc(1, sizeof(*ki));
                     62:        ki->providername = xstrdup(name);
                     63:        ki->key = k;
1.22      djm        64:        ki->label = xstrdup(label);
1.1       markus     65:        TAILQ_INSERT_TAIL(&pkcs11_keylist, ki, next);
                     66: }
                     67:
                     68: static void
                     69: del_keys_by_name(char *name)
                     70: {
                     71:        struct pkcs11_keyinfo *ki, *nxt;
                     72:
                     73:        for (ki = TAILQ_FIRST(&pkcs11_keylist); ki; ki = nxt) {
                     74:                nxt = TAILQ_NEXT(ki, next);
                     75:                if (!strcmp(ki->providername, name)) {
                     76:                        TAILQ_REMOVE(&pkcs11_keylist, ki, next);
1.6       djm        77:                        free(ki->providername);
1.22      djm        78:                        free(ki->label);
1.14      markus     79:                        sshkey_free(ki->key);
1.1       markus     80:                        free(ki);
                     81:                }
                     82:        }
                     83: }
                     84:
                     85: /* lookup matching 'private' key */
1.13      markus     86: static struct sshkey *
                     87: lookup_key(struct sshkey *k)
1.1       markus     88: {
                     89:        struct pkcs11_keyinfo *ki;
                     90:
                     91:        TAILQ_FOREACH(ki, &pkcs11_keylist, next) {
1.22      djm        92:                debug("check %p %s %s", ki, ki->providername, ki->label);
1.14      markus     93:                if (sshkey_equal(k, ki->key))
1.1       markus     94:                        return (ki->key);
                     95:        }
                     96:        return (NULL);
                     97: }
                     98:
                     99: static void
1.14      markus    100: send_msg(struct sshbuf *m)
1.1       markus    101: {
1.14      markus    102:        int r;
1.1       markus    103:
1.14      markus    104:        if ((r = sshbuf_put_stringb(oqueue, m)) != 0)
                    105:                fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.1       markus    106: }
                    107:
                    108: static void
                    109: process_add(void)
                    110: {
                    111:        char *name, *pin;
1.15      djm       112:        struct sshkey **keys = NULL;
1.14      markus    113:        int r, i, nkeys;
1.1       markus    114:        u_char *blob;
1.14      markus    115:        size_t blen;
                    116:        struct sshbuf *msg;
1.22      djm       117:        char **labels = NULL;
1.1       markus    118:
1.14      markus    119:        if ((msg = sshbuf_new()) == NULL)
                    120:                fatal("%s: sshbuf_new failed", __func__);
                    121:        if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
                    122:            (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
                    123:                fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.22      djm       124:        if ((nkeys = pkcs11_add_provider(name, pin, &keys, &labels)) > 0) {
1.14      markus    125:                if ((r = sshbuf_put_u8(msg,
                    126:                    SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
                    127:                    (r = sshbuf_put_u32(msg, nkeys)) != 0)
                    128:                        fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.1       markus    129:                for (i = 0; i < nkeys; i++) {
1.14      markus    130:                        if ((r = sshkey_to_blob(keys[i], &blob, &blen)) != 0) {
                    131:                                debug("%s: sshkey_to_blob: %s",
                    132:                                    __func__, ssh_err(r));
1.7       djm       133:                                continue;
1.14      markus    134:                        }
                    135:                        if ((r = sshbuf_put_string(msg, blob, blen)) != 0 ||
1.22      djm       136:                            (r = sshbuf_put_cstring(msg, labels[i])) != 0)
1.14      markus    137:                                fatal("%s: buffer error: %s",
                    138:                                    __func__, ssh_err(r));
1.6       djm       139:                        free(blob);
1.22      djm       140:                        add_key(keys[i], name, labels[i]);
                    141:                        free(labels[i]);
1.1       markus    142:                }
                    143:        } else {
1.14      markus    144:                if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
                    145:                        fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.15      djm       146:                if ((r = sshbuf_put_u32(msg, -nkeys)) != 0)
                    147:                        fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.1       markus    148:        }
1.22      djm       149:        free(labels);
                    150:        free(keys); /* keys themselves are transferred to pkcs11_keylist */
1.6       djm       151:        free(pin);
                    152:        free(name);
1.14      markus    153:        send_msg(msg);
                    154:        sshbuf_free(msg);
1.1       markus    155: }
                    156:
                    157: static void
                    158: process_del(void)
                    159: {
                    160:        char *name, *pin;
1.14      markus    161:        struct sshbuf *msg;
                    162:        int r;
1.1       markus    163:
1.14      markus    164:        if ((msg = sshbuf_new()) == NULL)
                    165:                fatal("%s: sshbuf_new failed", __func__);
                    166:        if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
                    167:            (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
                    168:                fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.1       markus    169:        del_keys_by_name(name);
1.14      markus    170:        if ((r = sshbuf_put_u8(msg, pkcs11_del_provider(name) == 0 ?
                    171:            SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0)
                    172:                fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.6       djm       173:        free(pin);
                    174:        free(name);
1.14      markus    175:        send_msg(msg);
                    176:        sshbuf_free(msg);
1.1       markus    177: }
                    178:
                    179: static void
                    180: process_sign(void)
                    181: {
                    182:        u_char *blob, *data, *signature = NULL;
1.14      markus    183:        size_t blen, dlen, slen = 0;
                    184:        int r, ok = -1;
1.13      markus    185:        struct sshkey *key, *found;
1.14      markus    186:        struct sshbuf *msg;
1.1       markus    187:
1.14      markus    188:        /* XXX support SHA2 signature flags */
                    189:        if ((r = sshbuf_get_string(iqueue, &blob, &blen)) != 0 ||
                    190:            (r = sshbuf_get_string(iqueue, &data, &dlen)) != 0 ||
                    191:            (r = sshbuf_get_u32(iqueue, NULL)) != 0)
                    192:                fatal("%s: buffer error: %s", __func__, ssh_err(r));
                    193:
                    194:        if ((r = sshkey_from_blob(blob, blen, &key)) != 0)
                    195:                error("%s: sshkey_from_blob: %s", __func__, ssh_err(r));
                    196:        else {
1.1       markus    197:                if ((found = lookup_key(key)) != NULL) {
1.8       djm       198: #ifdef WITH_OPENSSL
                    199:                        int ret;
                    200:
1.15      djm       201:                        if (key->type == KEY_RSA) {
                    202:                                slen = RSA_size(key->rsa);
                    203:                                signature = xmalloc(slen);
                    204:                                ret = RSA_private_encrypt(dlen, data, signature,
                    205:                                    found->rsa, RSA_PKCS1_PADDING);
                    206:                                if (ret != -1) {
                    207:                                        slen = ret;
                    208:                                        ok = 0;
                    209:                                }
                    210:                        } else if (key->type == KEY_ECDSA) {
1.18      dtucker   211:                                u_int xslen = ECDSA_size(key->ecdsa);
                    212:
1.15      djm       213:                                signature = xmalloc(xslen);
                    214:                                /* "The parameter type is ignored." */
                    215:                                ret = ECDSA_sign(-1, data, dlen, signature,
                    216:                                    &xslen, found->ecdsa);
                    217:                                if (ret != 0)
                    218:                                        ok = 0;
                    219:                                else
                    220:                                        error("%s: ECDSA_sign"
                    221:                                            " returns %d", __func__, ret);
                    222:                                slen = xslen;
                    223:                        } else
                    224:                                error("%s: don't know how to sign with key "
                    225:                                    "type %d", __func__, (int)key->type);
1.8       djm       226: #endif /* WITH_OPENSSL */
1.1       markus    227:                }
1.14      markus    228:                sshkey_free(key);
1.1       markus    229:        }
1.14      markus    230:        if ((msg = sshbuf_new()) == NULL)
                    231:                fatal("%s: sshbuf_new failed", __func__);
1.1       markus    232:        if (ok == 0) {
1.14      markus    233:                if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
                    234:                    (r = sshbuf_put_string(msg, signature, slen)) != 0)
                    235:                        fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.1       markus    236:        } else {
1.14      markus    237:                if ((r = sshbuf_put_u8(msg, SSH2_AGENT_FAILURE)) != 0)
                    238:                        fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.1       markus    239:        }
1.6       djm       240:        free(data);
                    241:        free(blob);
                    242:        free(signature);
1.14      markus    243:        send_msg(msg);
                    244:        sshbuf_free(msg);
1.1       markus    245: }
                    246:
                    247: static void
                    248: process(void)
                    249: {
                    250:        u_int msg_len;
                    251:        u_int buf_len;
                    252:        u_int consumed;
1.14      markus    253:        u_char type;
                    254:        const u_char *cp;
                    255:        int r;
1.1       markus    256:
1.14      markus    257:        buf_len = sshbuf_len(iqueue);
1.1       markus    258:        if (buf_len < 5)
                    259:                return;         /* Incomplete message. */
1.14      markus    260:        cp = sshbuf_ptr(iqueue);
1.1       markus    261:        msg_len = get_u32(cp);
                    262:        if (msg_len > MAX_MSG_LENGTH) {
                    263:                error("bad message len %d", msg_len);
                    264:                cleanup_exit(11);
                    265:        }
                    266:        if (buf_len < msg_len + 4)
                    267:                return;
1.14      markus    268:        if ((r = sshbuf_consume(iqueue, 4)) != 0 ||
                    269:            (r = sshbuf_get_u8(iqueue, &type)) != 0)
                    270:                fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.1       markus    271:        buf_len -= 4;
                    272:        switch (type) {
                    273:        case SSH_AGENTC_ADD_SMARTCARD_KEY:
                    274:                debug("process_add");
                    275:                process_add();
                    276:                break;
                    277:        case SSH_AGENTC_REMOVE_SMARTCARD_KEY:
                    278:                debug("process_del");
                    279:                process_del();
                    280:                break;
                    281:        case SSH2_AGENTC_SIGN_REQUEST:
                    282:                debug("process_sign");
                    283:                process_sign();
                    284:                break;
                    285:        default:
                    286:                error("Unknown message %d", type);
                    287:                break;
                    288:        }
                    289:        /* discard the remaining bytes from the current packet */
1.14      markus    290:        if (buf_len < sshbuf_len(iqueue)) {
1.1       markus    291:                error("iqueue grew unexpectedly");
                    292:                cleanup_exit(255);
                    293:        }
1.14      markus    294:        consumed = buf_len - sshbuf_len(iqueue);
1.1       markus    295:        if (msg_len < consumed) {
                    296:                error("msg_len %d < consumed %d", msg_len, consumed);
                    297:                cleanup_exit(255);
                    298:        }
1.14      markus    299:        if (msg_len > consumed) {
                    300:                if ((r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
                    301:                        fatal("%s: buffer error: %s", __func__, ssh_err(r));
                    302:        }
1.1       markus    303: }
                    304:
                    305: void
                    306: cleanup_exit(int i)
                    307: {
                    308:        /* XXX */
                    309:        _exit(i);
                    310: }
                    311:
1.16      djm       312:
1.1       markus    313: int
                    314: main(int argc, char **argv)
                    315: {
1.23    ! markus    316:        int r, ch, in, out, log_stderr = 0;
1.17      djm       317:        ssize_t len;
1.1       markus    318:        SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
                    319:        LogLevel log_level = SYSLOG_LEVEL_ERROR;
                    320:        char buf[4*4096];
1.2       deraadt   321:        extern char *__progname;
1.17      djm       322:        struct pollfd pfd[2];
1.1       markus    323:
                    324:        TAILQ_INIT(&pkcs11_keylist);
                    325:
                    326:        log_init(__progname, log_level, log_facility, log_stderr);
                    327:
1.16      djm       328:        while ((ch = getopt(argc, argv, "v")) != -1) {
                    329:                switch (ch) {
                    330:                case 'v':
                    331:                        log_stderr = 1;
                    332:                        if (log_level == SYSLOG_LEVEL_ERROR)
                    333:                                log_level = SYSLOG_LEVEL_DEBUG1;
                    334:                        else if (log_level < SYSLOG_LEVEL_DEBUG3)
                    335:                                log_level++;
                    336:                        break;
                    337:                default:
                    338:                        fprintf(stderr, "usage: %s [-v]\n", __progname);
                    339:                        exit(1);
                    340:                }
                    341:        }
                    342:
                    343:        log_init(__progname, log_level, log_facility, log_stderr);
                    344:
                    345:        pkcs11_init(0);
1.1       markus    346:        in = STDIN_FILENO;
                    347:        out = STDOUT_FILENO;
                    348:
1.14      markus    349:        if ((iqueue = sshbuf_new()) == NULL)
                    350:                fatal("%s: sshbuf_new failed", __func__);
                    351:        if ((oqueue = sshbuf_new()) == NULL)
                    352:                fatal("%s: sshbuf_new failed", __func__);
1.1       markus    353:
1.17      djm       354:        while (1) {
                    355:                memset(pfd, 0, sizeof(pfd));
                    356:                pfd[0].fd = in;
                    357:                pfd[1].fd = out;
1.1       markus    358:
                    359:                /*
                    360:                 * Ensure that we can read a full buffer and handle
                    361:                 * the worst-case length packet it can generate,
                    362:                 * otherwise apply backpressure by stopping reads.
                    363:                 */
1.14      markus    364:                if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
                    365:                    (r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
1.17      djm       366:                        pfd[0].events = POLLIN;
1.14      markus    367:                else if (r != SSH_ERR_NO_BUFFER_SPACE)
                    368:                        fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.1       markus    369:
1.17      djm       370:                if (sshbuf_len(oqueue) > 0)
                    371:                        pfd[1].events = POLLOUT;
1.1       markus    372:
1.17      djm       373:                if ((r = poll(pfd, 2, -1 /* INFTIM */)) <= 0) {
                    374:                        if (r == 0 || errno == EINTR)
1.1       markus    375:                                continue;
1.17      djm       376:                        fatal("poll: %s", strerror(errno));
1.1       markus    377:                }
                    378:
                    379:                /* copy stdin to iqueue */
1.17      djm       380:                if ((pfd[0].revents & (POLLIN|POLLERR)) != 0) {
1.1       markus    381:                        len = read(in, buf, sizeof buf);
                    382:                        if (len == 0) {
                    383:                                debug("read eof");
                    384:                                cleanup_exit(0);
                    385:                        } else if (len < 0) {
                    386:                                error("read: %s", strerror(errno));
                    387:                                cleanup_exit(1);
1.14      markus    388:                        } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
                    389:                                fatal("%s: buffer error: %s",
                    390:                                    __func__, ssh_err(r));
1.1       markus    391:                        }
                    392:                }
                    393:                /* send oqueue to stdout */
1.17      djm       394:                if ((pfd[1].revents & (POLLOUT|POLLHUP)) != 0) {
                    395:                        len = write(out, sshbuf_ptr(oqueue),
                    396:                            sshbuf_len(oqueue));
1.1       markus    397:                        if (len < 0) {
                    398:                                error("write: %s", strerror(errno));
                    399:                                cleanup_exit(1);
1.14      markus    400:                        } else if ((r = sshbuf_consume(oqueue, len)) != 0) {
                    401:                                fatal("%s: buffer error: %s",
                    402:                                    __func__, ssh_err(r));
1.1       markus    403:                        }
                    404:                }
                    405:
                    406:                /*
                    407:                 * Process requests from client if we can fit the results
                    408:                 * into the output buffer, otherwise stop processing input
                    409:                 * and let the output queue drain.
                    410:                 */
1.14      markus    411:                if ((r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
1.1       markus    412:                        process();
1.14      markus    413:                else if (r != SSH_ERR_NO_BUFFER_SPACE)
                    414:                        fatal("%s: buffer error: %s", __func__, ssh_err(r));
1.1       markus    415:        }
                    416: }
1.21      djm       417:
                    418: #else /* WITH_OPENSSL */
                    419: void
                    420: cleanup_exit(int i)
                    421: {
                    422:        _exit(i);
                    423: }
                    424:
                    425: int
                    426: main(int argc, char **argv)
                    427: {
                    428:        fprintf(stderr, "PKCS#11 code is not enabled\n");
                    429:        return 1;
                    430: }
                    431: #endif /* WITH_OPENSSL */