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