diff options
Diffstat (limited to 'ssh-keysign.c')
-rw-r--r-- | ssh-keysign.c | 120 |
1 files changed, 68 insertions, 52 deletions
diff --git a/ssh-keysign.c b/ssh-keysign.c index 821939997..8af13fa89 100644 --- a/ssh-keysign.c +++ b/ssh-keysign.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: ssh-keysign.c,v 1.45 2015/01/08 10:14:08 djm Exp $ */ | 1 | /* $OpenBSD: ssh-keysign.c,v 1.46 2015/01/15 09:40:00 djm Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2002 Markus Friedl. All rights reserved. | 3 | * Copyright (c) 2002 Markus Friedl. All rights reserved. |
4 | * | 4 | * |
@@ -43,11 +43,11 @@ | |||
43 | 43 | ||
44 | #include "xmalloc.h" | 44 | #include "xmalloc.h" |
45 | #include "log.h" | 45 | #include "log.h" |
46 | #include "key.h" | 46 | #include "sshkey.h" |
47 | #include "ssh.h" | 47 | #include "ssh.h" |
48 | #include "ssh2.h" | 48 | #include "ssh2.h" |
49 | #include "misc.h" | 49 | #include "misc.h" |
50 | #include "buffer.h" | 50 | #include "sshbuf.h" |
51 | #include "authfile.h" | 51 | #include "authfile.h" |
52 | #include "msg.h" | 52 | #include "msg.h" |
53 | #include "canohost.h" | 53 | #include "canohost.h" |
@@ -63,64 +63,73 @@ uid_t original_real_uid; | |||
63 | extern char *__progname; | 63 | extern char *__progname; |
64 | 64 | ||
65 | static int | 65 | static int |
66 | valid_request(struct passwd *pw, char *host, Key **ret, u_char *data, | 66 | valid_request(struct passwd *pw, char *host, struct sshkey **ret, |
67 | u_int datalen) | 67 | u_char *data, size_t datalen) |
68 | { | 68 | { |
69 | Buffer b; | 69 | struct sshbuf *b; |
70 | Key *key = NULL; | 70 | struct sshkey *key = NULL; |
71 | u_char *pkblob; | 71 | u_char type, *pkblob; |
72 | u_int blen, len; | 72 | char *p; |
73 | char *pkalg, *p; | 73 | size_t blen, len; |
74 | int pktype, fail; | 74 | char *pkalg, *luser; |
75 | int r, pktype, fail; | ||
75 | 76 | ||
76 | if (ret != NULL) | 77 | if (ret != NULL) |
77 | *ret = NULL; | 78 | *ret = NULL; |
78 | fail = 0; | 79 | fail = 0; |
79 | 80 | ||
80 | buffer_init(&b); | 81 | if ((b = sshbuf_from(data, datalen)) == NULL) |
81 | buffer_append(&b, data, datalen); | 82 | fatal("%s: sshbuf_from failed", __func__); |
82 | 83 | ||
83 | /* session id, currently limited to SHA1 (20 bytes) or SHA256 (32) */ | 84 | /* session id, currently limited to SHA1 (20 bytes) or SHA256 (32) */ |
84 | p = buffer_get_string(&b, &len); | 85 | if ((r = sshbuf_get_string(b, NULL, &len)) != 0) |
86 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
85 | if (len != 20 && len != 32) | 87 | if (len != 20 && len != 32) |
86 | fail++; | 88 | fail++; |
87 | free(p); | ||
88 | 89 | ||
89 | if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) | 90 | if ((r = sshbuf_get_u8(b, &type)) != 0) |
91 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
92 | if (type != SSH2_MSG_USERAUTH_REQUEST) | ||
90 | fail++; | 93 | fail++; |
91 | 94 | ||
92 | /* server user */ | 95 | /* server user */ |
93 | buffer_skip_string(&b); | 96 | if ((r = sshbuf_skip_string(b)) != 0) |
97 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
94 | 98 | ||
95 | /* service */ | 99 | /* service */ |
96 | p = buffer_get_string(&b, NULL); | 100 | if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0) |
101 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
97 | if (strcmp("ssh-connection", p) != 0) | 102 | if (strcmp("ssh-connection", p) != 0) |
98 | fail++; | 103 | fail++; |
99 | free(p); | 104 | free(p); |
100 | 105 | ||
101 | /* method */ | 106 | /* method */ |
102 | p = buffer_get_string(&b, NULL); | 107 | if ((r = sshbuf_get_cstring(b, &p, NULL)) != 0) |
108 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
103 | if (strcmp("hostbased", p) != 0) | 109 | if (strcmp("hostbased", p) != 0) |
104 | fail++; | 110 | fail++; |
105 | free(p); | 111 | free(p); |
106 | 112 | ||
107 | /* pubkey */ | 113 | /* pubkey */ |
108 | pkalg = buffer_get_string(&b, NULL); | 114 | if ((r = sshbuf_get_cstring(b, &pkalg, NULL)) != 0 || |
109 | pkblob = buffer_get_string(&b, &blen); | 115 | (r = sshbuf_get_string(b, &pkblob, &blen)) != 0) |
116 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
110 | 117 | ||
111 | pktype = key_type_from_name(pkalg); | 118 | pktype = sshkey_type_from_name(pkalg); |
112 | if (pktype == KEY_UNSPEC) | 119 | if (pktype == KEY_UNSPEC) |
113 | fail++; | 120 | fail++; |
114 | else if ((key = key_from_blob(pkblob, blen)) == NULL) | 121 | else if ((r = sshkey_from_blob(pkblob, blen, &key)) != 0) { |
122 | error("%s: bad key blob: %s", __func__, ssh_err(r)); | ||
115 | fail++; | 123 | fail++; |
116 | else if (key->type != pktype) | 124 | } else if (key->type != pktype) |
117 | fail++; | 125 | fail++; |
118 | free(pkalg); | 126 | free(pkalg); |
119 | free(pkblob); | 127 | free(pkblob); |
120 | 128 | ||
121 | /* client host name, handle trailing dot */ | 129 | /* client host name, handle trailing dot */ |
122 | p = buffer_get_string(&b, &len); | 130 | if ((r = sshbuf_get_cstring(b, &p, &len)) != 0) |
123 | debug2("valid_request: check expect chost %s got %s", host, p); | 131 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
132 | debug2("%s: check expect chost %s got %s", __func__, host, p); | ||
124 | if (strlen(host) != len - 1) | 133 | if (strlen(host) != len - 1) |
125 | fail++; | 134 | fail++; |
126 | else if (p[len - 1] != '.') | 135 | else if (p[len - 1] != '.') |
@@ -130,21 +139,22 @@ valid_request(struct passwd *pw, char *host, Key **ret, u_char *data, | |||
130 | free(p); | 139 | free(p); |
131 | 140 | ||
132 | /* local user */ | 141 | /* local user */ |
133 | p = buffer_get_string(&b, NULL); | 142 | if ((r = sshbuf_get_cstring(b, &luser, NULL)) != 0) |
143 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
134 | 144 | ||
135 | if (strcmp(pw->pw_name, p) != 0) | 145 | if (strcmp(pw->pw_name, luser) != 0) |
136 | fail++; | 146 | fail++; |
137 | free(p); | 147 | free(luser); |
138 | 148 | ||
139 | /* end of message */ | 149 | /* end of message */ |
140 | if (buffer_len(&b) != 0) | 150 | if (sshbuf_len(b) != 0) |
141 | fail++; | 151 | fail++; |
142 | buffer_free(&b); | 152 | sshbuf_free(b); |
143 | 153 | ||
144 | debug3("valid_request: fail %d", fail); | 154 | debug3("%s: fail %d", __func__, fail); |
145 | 155 | ||
146 | if (fail && key != NULL) | 156 | if (fail && key != NULL) |
147 | key_free(key); | 157 | sshkey_free(key); |
148 | else | 158 | else |
149 | *ret = key; | 159 | *ret = key; |
150 | 160 | ||
@@ -154,15 +164,15 @@ valid_request(struct passwd *pw, char *host, Key **ret, u_char *data, | |||
154 | int | 164 | int |
155 | main(int argc, char **argv) | 165 | main(int argc, char **argv) |
156 | { | 166 | { |
157 | Buffer b; | 167 | struct sshbuf *b; |
158 | Options options; | 168 | Options options; |
159 | #define NUM_KEYTYPES 4 | 169 | #define NUM_KEYTYPES 4 |
160 | Key *keys[NUM_KEYTYPES], *key = NULL; | 170 | struct sshkey *keys[NUM_KEYTYPES], *key = NULL; |
161 | struct passwd *pw; | 171 | struct passwd *pw; |
162 | int r, key_fd[NUM_KEYTYPES], i, found, version = 2, fd; | 172 | int r, key_fd[NUM_KEYTYPES], i, found, version = 2, fd; |
163 | u_char *signature, *data; | 173 | u_char *signature, *data, rver; |
164 | char *host, *fp; | 174 | char *host, *fp; |
165 | u_int slen, dlen; | 175 | size_t slen, dlen; |
166 | #ifdef WITH_OPENSSL | 176 | #ifdef WITH_OPENSSL |
167 | u_int32_t rnd[256]; | 177 | u_int32_t rnd[256]; |
168 | #endif | 178 | #endif |
@@ -232,18 +242,23 @@ main(int argc, char **argv) | |||
232 | if (!found) | 242 | if (!found) |
233 | fatal("no hostkey found"); | 243 | fatal("no hostkey found"); |
234 | 244 | ||
235 | buffer_init(&b); | 245 | if ((b = sshbuf_new()) == NULL) |
236 | if (ssh_msg_recv(STDIN_FILENO, &b) < 0) | 246 | fatal("%s: sshbuf_new failed", __func__); |
247 | if (ssh_msg_recv(STDIN_FILENO, b) < 0) | ||
237 | fatal("ssh_msg_recv failed"); | 248 | fatal("ssh_msg_recv failed"); |
238 | if (buffer_get_char(&b) != version) | 249 | if ((r = sshbuf_get_u8(b, &rver)) != 0) |
239 | fatal("bad version"); | 250 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
240 | fd = buffer_get_int(&b); | 251 | if (rver != version) |
241 | if ((fd == STDIN_FILENO) || (fd == STDOUT_FILENO)) | 252 | fatal("bad version: received %d, expected %d", rver, version); |
253 | if ((r = sshbuf_get_u32(b, (u_int *)&fd)) != 0) | ||
254 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
255 | if (fd < 0 || fd == STDIN_FILENO || fd == STDOUT_FILENO) | ||
242 | fatal("bad fd"); | 256 | fatal("bad fd"); |
243 | if ((host = get_local_name(fd)) == NULL) | 257 | if ((host = get_local_name(fd)) == NULL) |
244 | fatal("cannot get local name for fd"); | 258 | fatal("cannot get local name for fd"); |
245 | 259 | ||
246 | data = buffer_get_string(&b, &dlen); | 260 | if ((r = sshbuf_get_string(b, &data, &dlen)) != 0) |
261 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); | ||
247 | if (valid_request(pw, host, &key, data, dlen) < 0) | 262 | if (valid_request(pw, host, &key, data, dlen) < 0) |
248 | fatal("not a valid request"); | 263 | fatal("not a valid request"); |
249 | free(host); | 264 | free(host); |
@@ -251,26 +266,27 @@ main(int argc, char **argv) | |||
251 | found = 0; | 266 | found = 0; |
252 | for (i = 0; i < NUM_KEYTYPES; i++) { | 267 | for (i = 0; i < NUM_KEYTYPES; i++) { |
253 | if (keys[i] != NULL && | 268 | if (keys[i] != NULL && |
254 | key_equal_public(key, keys[i])) { | 269 | sshkey_equal_public(key, keys[i])) { |
255 | found = 1; | 270 | found = 1; |
256 | break; | 271 | break; |
257 | } | 272 | } |
258 | } | 273 | } |
259 | if (!found) { | 274 | if (!found) { |
260 | fp = key_fingerprint(key, options.fingerprint_hash, | 275 | fp = sshkey_fingerprint(key, options.fingerprint_hash, |
261 | SSH_FP_DEFAULT); | 276 | SSH_FP_DEFAULT); |
262 | fatal("no matching hostkey found for key %s %s", | 277 | fatal("no matching hostkey found for key %s %s", |
263 | key_type(key), fp); | 278 | sshkey_type(key), fp ? fp : ""); |
264 | } | 279 | } |
265 | 280 | ||
266 | if (key_sign(keys[i], &signature, &slen, data, dlen) != 0) | 281 | if ((r = sshkey_sign(keys[i], &signature, &slen, data, dlen, 0)) != 0) |
267 | fatal("key_sign failed"); | 282 | fatal("sshkey_sign failed: %s", ssh_err(r)); |
268 | free(data); | 283 | free(data); |
269 | 284 | ||
270 | /* send reply */ | 285 | /* send reply */ |
271 | buffer_clear(&b); | 286 | sshbuf_reset(b); |
272 | buffer_put_string(&b, signature, slen); | 287 | if ((r = sshbuf_put_string(b, signature, slen)) != 0) |
273 | if (ssh_msg_send(STDOUT_FILENO, version, &b) == -1) | 288 | fatal("%s: buffer error: %s", __func__, ssh_err(r)); |
289 | if (ssh_msg_send(STDOUT_FILENO, version, b) == -1) | ||
274 | fatal("ssh_msg_send failed"); | 290 | fatal("ssh_msg_send failed"); |
275 | 291 | ||
276 | return (0); | 292 | return (0); |