summaryrefslogtreecommitdiff
path: root/ssh-pkcs11-helper.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2018-04-03 08:20:28 +0100
committerColin Watson <cjwatson@debian.org>2018-04-03 08:20:28 +0100
commited6ae9c1a014a08ff5db3d768f01f2e427eeb476 (patch)
tree601025e307745d351946c01ab13f419ddb6dae29 /ssh-pkcs11-helper.c
parent62f54f20bf351468e0124f63cc2902ee40d9b0e9 (diff)
parenta0349a1cc4a18967ad1dbff5389bcdf9da098814 (diff)
Import openssh_7.7p1.orig.tar.gz
Diffstat (limited to 'ssh-pkcs11-helper.c')
-rw-r--r--ssh-pkcs11-helper.c183
1 files changed, 105 insertions, 78 deletions
diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c
index fd3039c14..6301033c5 100644
--- a/ssh-pkcs11-helper.c
+++ b/ssh-pkcs11-helper.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11-helper.c,v 1.13 2017/05/30 08:52:19 markus Exp $ */ 1/* $OpenBSD: ssh-pkcs11-helper.c,v 1.14 2018/01/08 15:18:46 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * 4 *
@@ -30,12 +30,13 @@
30#include <errno.h> 30#include <errno.h>
31 31
32#include "xmalloc.h" 32#include "xmalloc.h"
33#include "buffer.h" 33#include "sshbuf.h"
34#include "log.h" 34#include "log.h"
35#include "misc.h" 35#include "misc.h"
36#include "key.h" 36#include "sshkey.h"
37#include "authfd.h" 37#include "authfd.h"
38#include "ssh-pkcs11.h" 38#include "ssh-pkcs11.h"
39#include "ssherr.h"
39 40
40#ifdef ENABLE_PKCS11 41#ifdef ENABLE_PKCS11
41 42
@@ -51,13 +52,9 @@ TAILQ_HEAD(, pkcs11_keyinfo) pkcs11_keylist;
51 52
52#define MAX_MSG_LENGTH 10240 /*XXX*/ 53#define MAX_MSG_LENGTH 10240 /*XXX*/
53 54
54/* helper */
55#define get_int() buffer_get_int(&iqueue);
56#define get_string(lenp) buffer_get_string(&iqueue, lenp);
57
58/* input and output queue */ 55/* input and output queue */
59Buffer iqueue; 56struct sshbuf *iqueue;
60Buffer oqueue; 57struct sshbuf *oqueue;
61 58
62static void 59static void
63add_key(struct sshkey *k, char *name) 60add_key(struct sshkey *k, char *name)
@@ -80,7 +77,7 @@ del_keys_by_name(char *name)
80 if (!strcmp(ki->providername, name)) { 77 if (!strcmp(ki->providername, name)) {
81 TAILQ_REMOVE(&pkcs11_keylist, ki, next); 78 TAILQ_REMOVE(&pkcs11_keylist, ki, next);
82 free(ki->providername); 79 free(ki->providername);
83 key_free(ki->key); 80 sshkey_free(ki->key);
84 free(ki); 81 free(ki);
85 } 82 }
86 } 83 }
@@ -94,20 +91,19 @@ lookup_key(struct sshkey *k)
94 91
95 TAILQ_FOREACH(ki, &pkcs11_keylist, next) { 92 TAILQ_FOREACH(ki, &pkcs11_keylist, next) {
96 debug("check %p %s", ki, ki->providername); 93 debug("check %p %s", ki, ki->providername);
97 if (key_equal(k, ki->key)) 94 if (sshkey_equal(k, ki->key))
98 return (ki->key); 95 return (ki->key);
99 } 96 }
100 return (NULL); 97 return (NULL);
101} 98}
102 99
103static void 100static void
104send_msg(Buffer *m) 101send_msg(struct sshbuf *m)
105{ 102{
106 int mlen = buffer_len(m); 103 int r;
107 104
108 buffer_put_int(&oqueue, mlen); 105 if ((r = sshbuf_put_stringb(oqueue, m)) != 0)
109 buffer_append(&oqueue, buffer_ptr(m), mlen); 106 fatal("%s: buffer error: %s", __func__, ssh_err(r));
110 buffer_consume(m, mlen);
111} 107}
112 108
113static void 109static void
@@ -115,69 +111,85 @@ process_add(void)
115{ 111{
116 char *name, *pin; 112 char *name, *pin;
117 struct sshkey **keys; 113 struct sshkey **keys;
118 int i, nkeys; 114 int r, i, nkeys;
119 u_char *blob; 115 u_char *blob;
120 u_int blen; 116 size_t blen;
121 Buffer msg; 117 struct sshbuf *msg;
122 118
123 buffer_init(&msg); 119 if ((msg = sshbuf_new()) == NULL)
124 name = get_string(NULL); 120 fatal("%s: sshbuf_new failed", __func__);
125 pin = get_string(NULL); 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));
126 if ((nkeys = pkcs11_add_provider(name, pin, &keys)) > 0) { 124 if ((nkeys = pkcs11_add_provider(name, pin, &keys)) > 0) {
127 buffer_put_char(&msg, SSH2_AGENT_IDENTITIES_ANSWER); 125 if ((r = sshbuf_put_u8(msg,
128 buffer_put_int(&msg, nkeys); 126 SSH2_AGENT_IDENTITIES_ANSWER)) != 0 ||
127 (r = sshbuf_put_u32(msg, nkeys)) != 0)
128 fatal("%s: buffer error: %s", __func__, ssh_err(r));
129 for (i = 0; i < nkeys; i++) { 129 for (i = 0; i < nkeys; i++) {
130 if (key_to_blob(keys[i], &blob, &blen) == 0) 130 if ((r = sshkey_to_blob(keys[i], &blob, &blen)) != 0) {
131 debug("%s: sshkey_to_blob: %s",
132 __func__, ssh_err(r));
131 continue; 133 continue;
132 buffer_put_string(&msg, blob, blen); 134 }
133 buffer_put_cstring(&msg, name); 135 if ((r = sshbuf_put_string(msg, blob, blen)) != 0 ||
136 (r = sshbuf_put_cstring(msg, name)) != 0)
137 fatal("%s: buffer error: %s",
138 __func__, ssh_err(r));
134 free(blob); 139 free(blob);
135 add_key(keys[i], name); 140 add_key(keys[i], name);
136 } 141 }
137 free(keys); 142 free(keys);
138 } else { 143 } else {
139 buffer_put_char(&msg, SSH_AGENT_FAILURE); 144 if ((r = sshbuf_put_u8(msg, SSH_AGENT_FAILURE)) != 0)
145 fatal("%s: buffer error: %s", __func__, ssh_err(r));
140 } 146 }
141 free(pin); 147 free(pin);
142 free(name); 148 free(name);
143 send_msg(&msg); 149 send_msg(msg);
144 buffer_free(&msg); 150 sshbuf_free(msg);
145} 151}
146 152
147static void 153static void
148process_del(void) 154process_del(void)
149{ 155{
150 char *name, *pin; 156 char *name, *pin;
151 Buffer msg; 157 struct sshbuf *msg;
152 158 int r;
153 buffer_init(&msg); 159
154 name = get_string(NULL); 160 if ((msg = sshbuf_new()) == NULL)
155 pin = get_string(NULL); 161 fatal("%s: sshbuf_new failed", __func__);
162 if ((r = sshbuf_get_cstring(iqueue, &name, NULL)) != 0 ||
163 (r = sshbuf_get_cstring(iqueue, &pin, NULL)) != 0)
164 fatal("%s: buffer error: %s", __func__, ssh_err(r));
156 del_keys_by_name(name); 165 del_keys_by_name(name);
157 if (pkcs11_del_provider(name) == 0) 166 if ((r = sshbuf_put_u8(msg, pkcs11_del_provider(name) == 0 ?
158 buffer_put_char(&msg, SSH_AGENT_SUCCESS); 167 SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE)) != 0)
159 else 168 fatal("%s: buffer error: %s", __func__, ssh_err(r));
160 buffer_put_char(&msg, SSH_AGENT_FAILURE);
161 free(pin); 169 free(pin);
162 free(name); 170 free(name);
163 send_msg(&msg); 171 send_msg(msg);
164 buffer_free(&msg); 172 sshbuf_free(msg);
165} 173}
166 174
167static void 175static void
168process_sign(void) 176process_sign(void)
169{ 177{
170 u_char *blob, *data, *signature = NULL; 178 u_char *blob, *data, *signature = NULL;
171 u_int blen, dlen, slen = 0; 179 size_t blen, dlen, slen = 0;
172 int ok = -1; 180 int r, ok = -1;
173 struct sshkey *key, *found; 181 struct sshkey *key, *found;
174 Buffer msg; 182 struct sshbuf *msg;
175 183
176 blob = get_string(&blen); 184 /* XXX support SHA2 signature flags */
177 data = get_string(&dlen); 185 if ((r = sshbuf_get_string(iqueue, &blob, &blen)) != 0 ||
178 (void)get_int(); /* XXX ignore flags */ 186 (r = sshbuf_get_string(iqueue, &data, &dlen)) != 0 ||
187 (r = sshbuf_get_u32(iqueue, NULL)) != 0)
188 fatal("%s: buffer error: %s", __func__, ssh_err(r));
179 189
180 if ((key = key_from_blob(blob, blen)) != NULL) { 190 if ((r = sshkey_from_blob(blob, blen, &key)) != 0)
191 error("%s: sshkey_from_blob: %s", __func__, ssh_err(r));
192 else {
181 if ((found = lookup_key(key)) != NULL) { 193 if ((found = lookup_key(key)) != NULL) {
182#ifdef WITH_OPENSSL 194#ifdef WITH_OPENSSL
183 int ret; 195 int ret;
@@ -191,20 +203,23 @@ process_sign(void)
191 } 203 }
192#endif /* WITH_OPENSSL */ 204#endif /* WITH_OPENSSL */
193 } 205 }
194 key_free(key); 206 sshkey_free(key);
195 } 207 }
196 buffer_init(&msg); 208 if ((msg = sshbuf_new()) == NULL)
209 fatal("%s: sshbuf_new failed", __func__);
197 if (ok == 0) { 210 if (ok == 0) {
198 buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); 211 if ((r = sshbuf_put_u8(msg, SSH2_AGENT_SIGN_RESPONSE)) != 0 ||
199 buffer_put_string(&msg, signature, slen); 212 (r = sshbuf_put_string(msg, signature, slen)) != 0)
213 fatal("%s: buffer error: %s", __func__, ssh_err(r));
200 } else { 214 } else {
201 buffer_put_char(&msg, SSH_AGENT_FAILURE); 215 if ((r = sshbuf_put_u8(msg, SSH2_AGENT_FAILURE)) != 0)
216 fatal("%s: buffer error: %s", __func__, ssh_err(r));
202 } 217 }
203 free(data); 218 free(data);
204 free(blob); 219 free(blob);
205 free(signature); 220 free(signature);
206 send_msg(&msg); 221 send_msg(msg);
207 buffer_free(&msg); 222 sshbuf_free(msg);
208} 223}
209 224
210static void 225static void
@@ -213,13 +228,14 @@ process(void)
213 u_int msg_len; 228 u_int msg_len;
214 u_int buf_len; 229 u_int buf_len;
215 u_int consumed; 230 u_int consumed;
216 u_int type; 231 u_char type;
217 u_char *cp; 232 const u_char *cp;
233 int r;
218 234
219 buf_len = buffer_len(&iqueue); 235 buf_len = sshbuf_len(iqueue);
220 if (buf_len < 5) 236 if (buf_len < 5)
221 return; /* Incomplete message. */ 237 return; /* Incomplete message. */
222 cp = buffer_ptr(&iqueue); 238 cp = sshbuf_ptr(iqueue);
223 msg_len = get_u32(cp); 239 msg_len = get_u32(cp);
224 if (msg_len > MAX_MSG_LENGTH) { 240 if (msg_len > MAX_MSG_LENGTH) {
225 error("bad message len %d", msg_len); 241 error("bad message len %d", msg_len);
@@ -227,9 +243,10 @@ process(void)
227 } 243 }
228 if (buf_len < msg_len + 4) 244 if (buf_len < msg_len + 4)
229 return; 245 return;
230 buffer_consume(&iqueue, 4); 246 if ((r = sshbuf_consume(iqueue, 4)) != 0 ||
247 (r = sshbuf_get_u8(iqueue, &type)) != 0)
248 fatal("%s: buffer error: %s", __func__, ssh_err(r));
231 buf_len -= 4; 249 buf_len -= 4;
232 type = buffer_get_char(&iqueue);
233 switch (type) { 250 switch (type) {
234 case SSH_AGENTC_ADD_SMARTCARD_KEY: 251 case SSH_AGENTC_ADD_SMARTCARD_KEY:
235 debug("process_add"); 252 debug("process_add");
@@ -248,17 +265,19 @@ process(void)
248 break; 265 break;
249 } 266 }
250 /* discard the remaining bytes from the current packet */ 267 /* discard the remaining bytes from the current packet */
251 if (buf_len < buffer_len(&iqueue)) { 268 if (buf_len < sshbuf_len(iqueue)) {
252 error("iqueue grew unexpectedly"); 269 error("iqueue grew unexpectedly");
253 cleanup_exit(255); 270 cleanup_exit(255);
254 } 271 }
255 consumed = buf_len - buffer_len(&iqueue); 272 consumed = buf_len - sshbuf_len(iqueue);
256 if (msg_len < consumed) { 273 if (msg_len < consumed) {
257 error("msg_len %d < consumed %d", msg_len, consumed); 274 error("msg_len %d < consumed %d", msg_len, consumed);
258 cleanup_exit(255); 275 cleanup_exit(255);
259 } 276 }
260 if (msg_len > consumed) 277 if (msg_len > consumed) {
261 buffer_consume(&iqueue, msg_len - consumed); 278 if ((r = sshbuf_consume(iqueue, msg_len - consumed)) != 0)
279 fatal("%s: buffer error: %s", __func__, ssh_err(r));
280 }
262} 281}
263 282
264void 283void
@@ -272,7 +291,7 @@ int
272main(int argc, char **argv) 291main(int argc, char **argv)
273{ 292{
274 fd_set *rset, *wset; 293 fd_set *rset, *wset;
275 int in, out, max, log_stderr = 0; 294 int r, in, out, max, log_stderr = 0;
276 ssize_t len, olen, set_size; 295 ssize_t len, olen, set_size;
277 SyslogFacility log_facility = SYSLOG_FACILITY_AUTH; 296 SyslogFacility log_facility = SYSLOG_FACILITY_AUTH;
278 LogLevel log_level = SYSLOG_LEVEL_ERROR; 297 LogLevel log_level = SYSLOG_LEVEL_ERROR;
@@ -298,8 +317,10 @@ main(int argc, char **argv)
298 if (out > max) 317 if (out > max)
299 max = out; 318 max = out;
300 319
301 buffer_init(&iqueue); 320 if ((iqueue = sshbuf_new()) == NULL)
302 buffer_init(&oqueue); 321 fatal("%s: sshbuf_new failed", __func__);
322 if ((oqueue = sshbuf_new()) == NULL)
323 fatal("%s: sshbuf_new failed", __func__);
303 324
304 set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask); 325 set_size = howmany(max + 1, NFDBITS) * sizeof(fd_mask);
305 rset = xmalloc(set_size); 326 rset = xmalloc(set_size);
@@ -314,11 +335,13 @@ main(int argc, char **argv)
314 * the worst-case length packet it can generate, 335 * the worst-case length packet it can generate,
315 * otherwise apply backpressure by stopping reads. 336 * otherwise apply backpressure by stopping reads.
316 */ 337 */
317 if (buffer_check_alloc(&iqueue, sizeof(buf)) && 338 if ((r = sshbuf_check_reserve(iqueue, sizeof(buf))) == 0 &&
318 buffer_check_alloc(&oqueue, MAX_MSG_LENGTH)) 339 (r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
319 FD_SET(in, rset); 340 FD_SET(in, rset);
341 else if (r != SSH_ERR_NO_BUFFER_SPACE)
342 fatal("%s: buffer error: %s", __func__, ssh_err(r));
320 343
321 olen = buffer_len(&oqueue); 344 olen = sshbuf_len(oqueue);
322 if (olen > 0) 345 if (olen > 0)
323 FD_SET(out, wset); 346 FD_SET(out, wset);
324 347
@@ -338,18 +361,20 @@ main(int argc, char **argv)
338 } else if (len < 0) { 361 } else if (len < 0) {
339 error("read: %s", strerror(errno)); 362 error("read: %s", strerror(errno));
340 cleanup_exit(1); 363 cleanup_exit(1);
341 } else { 364 } else if ((r = sshbuf_put(iqueue, buf, len)) != 0) {
342 buffer_append(&iqueue, buf, len); 365 fatal("%s: buffer error: %s",
366 __func__, ssh_err(r));
343 } 367 }
344 } 368 }
345 /* send oqueue to stdout */ 369 /* send oqueue to stdout */
346 if (FD_ISSET(out, wset)) { 370 if (FD_ISSET(out, wset)) {
347 len = write(out, buffer_ptr(&oqueue), olen); 371 len = write(out, sshbuf_ptr(oqueue), olen);
348 if (len < 0) { 372 if (len < 0) {
349 error("write: %s", strerror(errno)); 373 error("write: %s", strerror(errno));
350 cleanup_exit(1); 374 cleanup_exit(1);
351 } else { 375 } else if ((r = sshbuf_consume(oqueue, len)) != 0) {
352 buffer_consume(&oqueue, len); 376 fatal("%s: buffer error: %s",
377 __func__, ssh_err(r));
353 } 378 }
354 } 379 }
355 380
@@ -358,8 +383,10 @@ main(int argc, char **argv)
358 * into the output buffer, otherwise stop processing input 383 * into the output buffer, otherwise stop processing input
359 * and let the output queue drain. 384 * and let the output queue drain.
360 */ 385 */
361 if (buffer_check_alloc(&oqueue, MAX_MSG_LENGTH)) 386 if ((r = sshbuf_check_reserve(oqueue, MAX_MSG_LENGTH)) == 0)
362 process(); 387 process();
388 else if (r != SSH_ERR_NO_BUFFER_SPACE)
389 fatal("%s: buffer error: %s", __func__, ssh_err(r));
363 } 390 }
364} 391}
365#else /* ENABLE_PKCS11 */ 392#else /* ENABLE_PKCS11 */