1 | /* |
---|
2 | * Copyright 2002 Niels Provos <provos@citi.umich.edu> |
---|
3 | * Copyright 2002 Markus Friedl <markus@openbsd.org> |
---|
4 | * All rights reserved. |
---|
5 | * |
---|
6 | * Redistribution and use in source and binary forms, with or without |
---|
7 | * modification, are permitted provided that the following conditions |
---|
8 | * are met: |
---|
9 | * 1. Redistributions of source code must retain the above copyright |
---|
10 | * notice, this list of conditions and the following disclaimer. |
---|
11 | * 2. Redistributions in binary form must reproduce the above copyright |
---|
12 | * notice, this list of conditions and the following disclaimer in the |
---|
13 | * documentation and/or other materials provided with the distribution. |
---|
14 | * |
---|
15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
---|
16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
---|
17 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
---|
18 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
---|
19 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
---|
20 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
---|
21 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
---|
22 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
---|
23 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
---|
24 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
---|
25 | */ |
---|
26 | |
---|
27 | #include "includes.h" |
---|
28 | RCSID("$OpenBSD: monitor_wrap.c,v 1.19 2002/09/26 11:38:43 markus Exp $"); |
---|
29 | |
---|
30 | #include <openssl/bn.h> |
---|
31 | #include <openssl/dh.h> |
---|
32 | |
---|
33 | #include "ssh.h" |
---|
34 | #include "dh.h" |
---|
35 | #include "kex.h" |
---|
36 | #include "auth.h" |
---|
37 | #include "buffer.h" |
---|
38 | #include "bufaux.h" |
---|
39 | #include "packet.h" |
---|
40 | #include "mac.h" |
---|
41 | #include "log.h" |
---|
42 | #include "zlib.h" |
---|
43 | #include "monitor.h" |
---|
44 | #include "monitor_wrap.h" |
---|
45 | #include "xmalloc.h" |
---|
46 | #include "atomicio.h" |
---|
47 | #include "monitor_fdpass.h" |
---|
48 | #include "getput.h" |
---|
49 | |
---|
50 | #include "auth.h" |
---|
51 | #include "channels.h" |
---|
52 | #include "session.h" |
---|
53 | |
---|
54 | #ifdef GSSAPI |
---|
55 | #include "ssh-gss.h" |
---|
56 | #endif |
---|
57 | |
---|
58 | /* Imports */ |
---|
59 | extern int compat20; |
---|
60 | extern Newkeys *newkeys[]; |
---|
61 | extern z_stream incoming_stream; |
---|
62 | extern z_stream outgoing_stream; |
---|
63 | extern struct monitor *pmonitor; |
---|
64 | extern Buffer input, output; |
---|
65 | |
---|
66 | void |
---|
67 | mm_request_send(int socket, enum monitor_reqtype type, Buffer *m) |
---|
68 | { |
---|
69 | u_int mlen = buffer_len(m); |
---|
70 | u_char buf[5]; |
---|
71 | |
---|
72 | debug3("%s entering: type %d", __func__, type); |
---|
73 | |
---|
74 | PUT_32BIT(buf, mlen + 1); |
---|
75 | buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */ |
---|
76 | if (atomicio(write, socket, buf, sizeof(buf)) != sizeof(buf)) |
---|
77 | fatal("%s: write", __func__); |
---|
78 | if (atomicio(write, socket, buffer_ptr(m), mlen) != mlen) |
---|
79 | fatal("%s: write", __func__); |
---|
80 | } |
---|
81 | |
---|
82 | void |
---|
83 | mm_request_receive(int socket, Buffer *m) |
---|
84 | { |
---|
85 | u_char buf[4]; |
---|
86 | u_int msg_len; |
---|
87 | ssize_t res; |
---|
88 | |
---|
89 | debug3("%s entering", __func__); |
---|
90 | |
---|
91 | res = atomicio(read, socket, buf, sizeof(buf)); |
---|
92 | if (res != sizeof(buf)) { |
---|
93 | if (res == 0) |
---|
94 | fatal_cleanup(); |
---|
95 | fatal("%s: read: %ld", __func__, (long)res); |
---|
96 | } |
---|
97 | msg_len = GET_32BIT(buf); |
---|
98 | if (msg_len > 256 * 1024) |
---|
99 | fatal("%s: read: bad msg_len %d", __func__, msg_len); |
---|
100 | buffer_clear(m); |
---|
101 | buffer_append_space(m, msg_len); |
---|
102 | res = atomicio(read, socket, buffer_ptr(m), msg_len); |
---|
103 | if (res != msg_len) |
---|
104 | fatal("%s: read: %ld != msg_len", __func__, (long)res); |
---|
105 | } |
---|
106 | |
---|
107 | void |
---|
108 | mm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m) |
---|
109 | { |
---|
110 | u_char rtype; |
---|
111 | |
---|
112 | debug3("%s entering: type %d", __func__, type); |
---|
113 | |
---|
114 | mm_request_receive(socket, m); |
---|
115 | rtype = buffer_get_char(m); |
---|
116 | if (rtype != type) |
---|
117 | fatal("%s: read: rtype %d != type %d", __func__, |
---|
118 | rtype, type); |
---|
119 | } |
---|
120 | |
---|
121 | DH * |
---|
122 | mm_choose_dh(int min, int nbits, int max) |
---|
123 | { |
---|
124 | BIGNUM *p, *g; |
---|
125 | int success = 0; |
---|
126 | Buffer m; |
---|
127 | |
---|
128 | buffer_init(&m); |
---|
129 | buffer_put_int(&m, min); |
---|
130 | buffer_put_int(&m, nbits); |
---|
131 | buffer_put_int(&m, max); |
---|
132 | |
---|
133 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_MODULI, &m); |
---|
134 | |
---|
135 | debug3("%s: waiting for MONITOR_ANS_MODULI", __func__); |
---|
136 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_MODULI, &m); |
---|
137 | |
---|
138 | success = buffer_get_char(&m); |
---|
139 | if (success == 0) |
---|
140 | fatal("%s: MONITOR_ANS_MODULI failed", __func__); |
---|
141 | |
---|
142 | if ((p = BN_new()) == NULL) |
---|
143 | fatal("%s: BN_new failed", __func__); |
---|
144 | if ((g = BN_new()) == NULL) |
---|
145 | fatal("%s: BN_new failed", __func__); |
---|
146 | buffer_get_bignum2(&m, p); |
---|
147 | buffer_get_bignum2(&m, g); |
---|
148 | |
---|
149 | debug3("%s: remaining %d", __func__, buffer_len(&m)); |
---|
150 | buffer_free(&m); |
---|
151 | |
---|
152 | return (dh_new_group(g, p)); |
---|
153 | } |
---|
154 | |
---|
155 | int |
---|
156 | mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) |
---|
157 | { |
---|
158 | Kex *kex = *pmonitor->m_pkex; |
---|
159 | Buffer m; |
---|
160 | |
---|
161 | debug3("%s entering", __func__); |
---|
162 | |
---|
163 | buffer_init(&m); |
---|
164 | buffer_put_int(&m, kex->host_key_index(key)); |
---|
165 | buffer_put_string(&m, data, datalen); |
---|
166 | |
---|
167 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SIGN, &m); |
---|
168 | |
---|
169 | debug3("%s: waiting for MONITOR_ANS_SIGN", __func__); |
---|
170 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SIGN, &m); |
---|
171 | *sigp = buffer_get_string(&m, lenp); |
---|
172 | buffer_free(&m); |
---|
173 | |
---|
174 | return (0); |
---|
175 | } |
---|
176 | |
---|
177 | struct passwd * |
---|
178 | mm_getpwnamallow(const char *login) |
---|
179 | { |
---|
180 | Buffer m; |
---|
181 | struct passwd *pw; |
---|
182 | u_int pwlen; |
---|
183 | |
---|
184 | debug3("%s entering", __func__); |
---|
185 | |
---|
186 | buffer_init(&m); |
---|
187 | buffer_put_cstring(&m, login); |
---|
188 | |
---|
189 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PWNAM, &m); |
---|
190 | |
---|
191 | debug3("%s: waiting for MONITOR_ANS_PWNAM", __func__); |
---|
192 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PWNAM, &m); |
---|
193 | |
---|
194 | if (buffer_get_char(&m) == 0) { |
---|
195 | buffer_free(&m); |
---|
196 | return (NULL); |
---|
197 | } |
---|
198 | pw = buffer_get_string(&m, &pwlen); |
---|
199 | if (pwlen != sizeof(struct passwd)) |
---|
200 | fatal("%s: struct passwd size mismatch", __func__); |
---|
201 | pw->pw_name = buffer_get_string(&m, NULL); |
---|
202 | pw->pw_passwd = buffer_get_string(&m, NULL); |
---|
203 | pw->pw_gecos = buffer_get_string(&m, NULL); |
---|
204 | #ifdef HAVE_PW_CLASS_IN_PASSWD |
---|
205 | pw->pw_class = buffer_get_string(&m, NULL); |
---|
206 | #endif |
---|
207 | pw->pw_dir = buffer_get_string(&m, NULL); |
---|
208 | pw->pw_shell = buffer_get_string(&m, NULL); |
---|
209 | buffer_free(&m); |
---|
210 | |
---|
211 | return (pw); |
---|
212 | } |
---|
213 | |
---|
214 | char *mm_auth2_read_banner(void) |
---|
215 | { |
---|
216 | Buffer m; |
---|
217 | char *banner; |
---|
218 | |
---|
219 | debug3("%s entering", __func__); |
---|
220 | |
---|
221 | buffer_init(&m); |
---|
222 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTH2_READ_BANNER, &m); |
---|
223 | buffer_clear(&m); |
---|
224 | |
---|
225 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTH2_READ_BANNER, &m); |
---|
226 | banner = buffer_get_string(&m, NULL); |
---|
227 | buffer_free(&m); |
---|
228 | |
---|
229 | return (banner); |
---|
230 | } |
---|
231 | |
---|
232 | /* Inform the privileged process about service and style */ |
---|
233 | |
---|
234 | void |
---|
235 | mm_inform_authserv(char *service, char *style) |
---|
236 | { |
---|
237 | Buffer m; |
---|
238 | |
---|
239 | debug3("%s entering", __func__); |
---|
240 | |
---|
241 | buffer_init(&m); |
---|
242 | buffer_put_cstring(&m, service); |
---|
243 | buffer_put_cstring(&m, style ? style : ""); |
---|
244 | |
---|
245 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHSERV, &m); |
---|
246 | |
---|
247 | buffer_free(&m); |
---|
248 | } |
---|
249 | |
---|
250 | /* Do the password authentication */ |
---|
251 | int |
---|
252 | mm_auth_password(Authctxt *authctxt, char *password) |
---|
253 | { |
---|
254 | Buffer m; |
---|
255 | int authenticated = 0; |
---|
256 | |
---|
257 | debug3("%s entering", __func__); |
---|
258 | |
---|
259 | buffer_init(&m); |
---|
260 | buffer_put_cstring(&m, password); |
---|
261 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_AUTHPASSWORD, &m); |
---|
262 | |
---|
263 | debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __func__); |
---|
264 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_AUTHPASSWORD, &m); |
---|
265 | |
---|
266 | authenticated = buffer_get_int(&m); |
---|
267 | |
---|
268 | buffer_free(&m); |
---|
269 | |
---|
270 | debug3("%s: user %sauthenticated", |
---|
271 | __func__, authenticated ? "" : "not "); |
---|
272 | return (authenticated); |
---|
273 | } |
---|
274 | |
---|
275 | int |
---|
276 | mm_user_key_allowed(struct passwd *pw, Key *key) |
---|
277 | { |
---|
278 | return (mm_key_allowed(MM_USERKEY, NULL, NULL, key)); |
---|
279 | } |
---|
280 | |
---|
281 | int |
---|
282 | mm_hostbased_key_allowed(struct passwd *pw, char *user, char *host, |
---|
283 | Key *key) |
---|
284 | { |
---|
285 | return (mm_key_allowed(MM_HOSTKEY, user, host, key)); |
---|
286 | } |
---|
287 | |
---|
288 | int |
---|
289 | mm_auth_rhosts_rsa_key_allowed(struct passwd *pw, char *user, |
---|
290 | char *host, Key *key) |
---|
291 | { |
---|
292 | int ret; |
---|
293 | |
---|
294 | key->type = KEY_RSA; /* XXX hack for key_to_blob */ |
---|
295 | ret = mm_key_allowed(MM_RSAHOSTKEY, user, host, key); |
---|
296 | key->type = KEY_RSA1; |
---|
297 | return (ret); |
---|
298 | } |
---|
299 | |
---|
300 | static void |
---|
301 | mm_send_debug(Buffer *m) |
---|
302 | { |
---|
303 | char *msg; |
---|
304 | |
---|
305 | while (buffer_len(m)) { |
---|
306 | msg = buffer_get_string(m, NULL); |
---|
307 | debug3("%s: Sending debug: %s", __func__, msg); |
---|
308 | packet_send_debug("%s", msg); |
---|
309 | xfree(msg); |
---|
310 | } |
---|
311 | } |
---|
312 | |
---|
313 | int |
---|
314 | mm_key_allowed(enum mm_keytype type, char *user, char *host, Key *key) |
---|
315 | { |
---|
316 | Buffer m; |
---|
317 | u_char *blob; |
---|
318 | u_int len; |
---|
319 | int allowed = 0; |
---|
320 | |
---|
321 | debug3("%s entering", __func__); |
---|
322 | |
---|
323 | /* Convert the key to a blob and the pass it over */ |
---|
324 | if (!key_to_blob(key, &blob, &len)) |
---|
325 | return (0); |
---|
326 | |
---|
327 | buffer_init(&m); |
---|
328 | buffer_put_int(&m, type); |
---|
329 | buffer_put_cstring(&m, user ? user : ""); |
---|
330 | buffer_put_cstring(&m, host ? host : ""); |
---|
331 | buffer_put_string(&m, blob, len); |
---|
332 | xfree(blob); |
---|
333 | |
---|
334 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYALLOWED, &m); |
---|
335 | |
---|
336 | debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __func__); |
---|
337 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYALLOWED, &m); |
---|
338 | |
---|
339 | allowed = buffer_get_int(&m); |
---|
340 | |
---|
341 | /* Send potential debug messages */ |
---|
342 | mm_send_debug(&m); |
---|
343 | |
---|
344 | buffer_free(&m); |
---|
345 | |
---|
346 | return (allowed); |
---|
347 | } |
---|
348 | |
---|
349 | /* |
---|
350 | * This key verify needs to send the key type along, because the |
---|
351 | * privileged parent makes the decision if the key is allowed |
---|
352 | * for authentication. |
---|
353 | */ |
---|
354 | |
---|
355 | int |
---|
356 | mm_key_verify(Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen) |
---|
357 | { |
---|
358 | Buffer m; |
---|
359 | u_char *blob; |
---|
360 | u_int len; |
---|
361 | int verified = 0; |
---|
362 | |
---|
363 | debug3("%s entering", __func__); |
---|
364 | |
---|
365 | /* Convert the key to a blob and the pass it over */ |
---|
366 | if (!key_to_blob(key, &blob, &len)) |
---|
367 | return (0); |
---|
368 | |
---|
369 | buffer_init(&m); |
---|
370 | buffer_put_string(&m, blob, len); |
---|
371 | buffer_put_string(&m, sig, siglen); |
---|
372 | buffer_put_string(&m, data, datalen); |
---|
373 | xfree(blob); |
---|
374 | |
---|
375 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYVERIFY, &m); |
---|
376 | |
---|
377 | debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __func__); |
---|
378 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KEYVERIFY, &m); |
---|
379 | |
---|
380 | verified = buffer_get_int(&m); |
---|
381 | |
---|
382 | buffer_free(&m); |
---|
383 | |
---|
384 | return (verified); |
---|
385 | } |
---|
386 | |
---|
387 | /* Export key state after authentication */ |
---|
388 | Newkeys * |
---|
389 | mm_newkeys_from_blob(u_char *blob, int blen) |
---|
390 | { |
---|
391 | Buffer b; |
---|
392 | u_int len; |
---|
393 | Newkeys *newkey = NULL; |
---|
394 | Enc *enc; |
---|
395 | Mac *mac; |
---|
396 | Comp *comp; |
---|
397 | |
---|
398 | debug3("%s: %p(%d)", __func__, blob, blen); |
---|
399 | #ifdef DEBUG_PK |
---|
400 | dump_base64(stderr, blob, blen); |
---|
401 | #endif |
---|
402 | buffer_init(&b); |
---|
403 | buffer_append(&b, blob, blen); |
---|
404 | |
---|
405 | newkey = xmalloc(sizeof(*newkey)); |
---|
406 | enc = &newkey->enc; |
---|
407 | mac = &newkey->mac; |
---|
408 | comp = &newkey->comp; |
---|
409 | |
---|
410 | /* Enc structure */ |
---|
411 | enc->name = buffer_get_string(&b, NULL); |
---|
412 | buffer_get(&b, &enc->cipher, sizeof(enc->cipher)); |
---|
413 | enc->enabled = buffer_get_int(&b); |
---|
414 | enc->block_size = buffer_get_int(&b); |
---|
415 | enc->key = buffer_get_string(&b, &enc->key_len); |
---|
416 | enc->iv = buffer_get_string(&b, &len); |
---|
417 | if (len != enc->block_size) |
---|
418 | fatal("%s: bad ivlen: expected %u != %u", __func__, |
---|
419 | enc->block_size, len); |
---|
420 | |
---|
421 | if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher) |
---|
422 | fatal("%s: bad cipher name %s or pointer %p", __func__, |
---|
423 | enc->name, enc->cipher); |
---|
424 | |
---|
425 | /* Mac structure */ |
---|
426 | mac->name = buffer_get_string(&b, NULL); |
---|
427 | if (mac->name == NULL || mac_init(mac, mac->name) == -1) |
---|
428 | fatal("%s: can not init mac %s", __func__, mac->name); |
---|
429 | mac->enabled = buffer_get_int(&b); |
---|
430 | mac->key = buffer_get_string(&b, &len); |
---|
431 | if (len > mac->key_len) |
---|
432 | fatal("%s: bad mac key length: %u > %d", __func__, len, |
---|
433 | mac->key_len); |
---|
434 | mac->key_len = len; |
---|
435 | |
---|
436 | /* Comp structure */ |
---|
437 | comp->type = buffer_get_int(&b); |
---|
438 | comp->enabled = buffer_get_int(&b); |
---|
439 | comp->name = buffer_get_string(&b, NULL); |
---|
440 | |
---|
441 | len = buffer_len(&b); |
---|
442 | if (len != 0) |
---|
443 | error("newkeys_from_blob: remaining bytes in blob %u", len); |
---|
444 | buffer_free(&b); |
---|
445 | return (newkey); |
---|
446 | } |
---|
447 | |
---|
448 | int |
---|
449 | mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp) |
---|
450 | { |
---|
451 | Buffer b; |
---|
452 | int len; |
---|
453 | Enc *enc; |
---|
454 | Mac *mac; |
---|
455 | Comp *comp; |
---|
456 | Newkeys *newkey = newkeys[mode]; |
---|
457 | |
---|
458 | debug3("%s: converting %p", __func__, newkey); |
---|
459 | |
---|
460 | if (newkey == NULL) { |
---|
461 | error("%s: newkey == NULL", __func__); |
---|
462 | return 0; |
---|
463 | } |
---|
464 | enc = &newkey->enc; |
---|
465 | mac = &newkey->mac; |
---|
466 | comp = &newkey->comp; |
---|
467 | |
---|
468 | buffer_init(&b); |
---|
469 | /* Enc structure */ |
---|
470 | buffer_put_cstring(&b, enc->name); |
---|
471 | /* The cipher struct is constant and shared, you export pointer */ |
---|
472 | buffer_append(&b, &enc->cipher, sizeof(enc->cipher)); |
---|
473 | buffer_put_int(&b, enc->enabled); |
---|
474 | buffer_put_int(&b, enc->block_size); |
---|
475 | buffer_put_string(&b, enc->key, enc->key_len); |
---|
476 | packet_get_keyiv(mode, enc->iv, enc->block_size); |
---|
477 | buffer_put_string(&b, enc->iv, enc->block_size); |
---|
478 | |
---|
479 | /* Mac structure */ |
---|
480 | buffer_put_cstring(&b, mac->name); |
---|
481 | buffer_put_int(&b, mac->enabled); |
---|
482 | buffer_put_string(&b, mac->key, mac->key_len); |
---|
483 | |
---|
484 | /* Comp structure */ |
---|
485 | buffer_put_int(&b, comp->type); |
---|
486 | buffer_put_int(&b, comp->enabled); |
---|
487 | buffer_put_cstring(&b, comp->name); |
---|
488 | |
---|
489 | len = buffer_len(&b); |
---|
490 | if (lenp != NULL) |
---|
491 | *lenp = len; |
---|
492 | if (blobp != NULL) { |
---|
493 | *blobp = xmalloc(len); |
---|
494 | memcpy(*blobp, buffer_ptr(&b), len); |
---|
495 | } |
---|
496 | memset(buffer_ptr(&b), 0, len); |
---|
497 | buffer_free(&b); |
---|
498 | return len; |
---|
499 | } |
---|
500 | |
---|
501 | static void |
---|
502 | mm_send_kex(Buffer *m, Kex *kex) |
---|
503 | { |
---|
504 | buffer_put_string(m, kex->session_id, kex->session_id_len); |
---|
505 | buffer_put_int(m, kex->we_need); |
---|
506 | buffer_put_int(m, kex->hostkey_type); |
---|
507 | buffer_put_int(m, kex->kex_type); |
---|
508 | buffer_put_string(m, buffer_ptr(&kex->my), buffer_len(&kex->my)); |
---|
509 | buffer_put_string(m, buffer_ptr(&kex->peer), buffer_len(&kex->peer)); |
---|
510 | buffer_put_int(m, kex->flags); |
---|
511 | buffer_put_cstring(m, kex->client_version_string); |
---|
512 | buffer_put_cstring(m, kex->server_version_string); |
---|
513 | } |
---|
514 | |
---|
515 | void |
---|
516 | mm_send_keystate(struct monitor *pmonitor) |
---|
517 | { |
---|
518 | Buffer m; |
---|
519 | u_char *blob, *p; |
---|
520 | u_int bloblen, plen; |
---|
521 | |
---|
522 | buffer_init(&m); |
---|
523 | |
---|
524 | if (!compat20) { |
---|
525 | u_char iv[24]; |
---|
526 | u_char *key; |
---|
527 | u_int ivlen, keylen; |
---|
528 | |
---|
529 | buffer_put_int(&m, packet_get_protocol_flags()); |
---|
530 | |
---|
531 | buffer_put_int(&m, packet_get_ssh1_cipher()); |
---|
532 | |
---|
533 | debug3("%s: Sending ssh1 KEY+IV", __func__); |
---|
534 | keylen = packet_get_encryption_key(NULL); |
---|
535 | key = xmalloc(keylen+1); /* add 1 if keylen == 0 */ |
---|
536 | keylen = packet_get_encryption_key(key); |
---|
537 | buffer_put_string(&m, key, keylen); |
---|
538 | memset(key, 0, keylen); |
---|
539 | xfree(key); |
---|
540 | |
---|
541 | ivlen = packet_get_keyiv_len(MODE_OUT); |
---|
542 | packet_get_keyiv(MODE_OUT, iv, ivlen); |
---|
543 | buffer_put_string(&m, iv, ivlen); |
---|
544 | ivlen = packet_get_keyiv_len(MODE_OUT); |
---|
545 | packet_get_keyiv(MODE_IN, iv, ivlen); |
---|
546 | buffer_put_string(&m, iv, ivlen); |
---|
547 | goto skip; |
---|
548 | } else { |
---|
549 | /* Kex for rekeying */ |
---|
550 | mm_send_kex(&m, *pmonitor->m_pkex); |
---|
551 | } |
---|
552 | |
---|
553 | debug3("%s: Sending new keys: %p %p", |
---|
554 | __func__, newkeys[MODE_OUT], newkeys[MODE_IN]); |
---|
555 | |
---|
556 | /* Keys from Kex */ |
---|
557 | if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen)) |
---|
558 | fatal("%s: conversion of newkeys failed", __func__); |
---|
559 | |
---|
560 | buffer_put_string(&m, blob, bloblen); |
---|
561 | xfree(blob); |
---|
562 | |
---|
563 | if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen)) |
---|
564 | fatal("%s: conversion of newkeys failed", __func__); |
---|
565 | |
---|
566 | buffer_put_string(&m, blob, bloblen); |
---|
567 | xfree(blob); |
---|
568 | |
---|
569 | buffer_put_int(&m, packet_get_seqnr(MODE_OUT)); |
---|
570 | buffer_put_int(&m, packet_get_seqnr(MODE_IN)); |
---|
571 | |
---|
572 | debug3("%s: New keys have been sent", __func__); |
---|
573 | skip: |
---|
574 | /* More key context */ |
---|
575 | plen = packet_get_keycontext(MODE_OUT, NULL); |
---|
576 | p = xmalloc(plen+1); |
---|
577 | packet_get_keycontext(MODE_OUT, p); |
---|
578 | buffer_put_string(&m, p, plen); |
---|
579 | xfree(p); |
---|
580 | |
---|
581 | plen = packet_get_keycontext(MODE_IN, NULL); |
---|
582 | p = xmalloc(plen+1); |
---|
583 | packet_get_keycontext(MODE_IN, p); |
---|
584 | buffer_put_string(&m, p, plen); |
---|
585 | xfree(p); |
---|
586 | |
---|
587 | /* Compression state */ |
---|
588 | debug3("%s: Sending compression state", __func__); |
---|
589 | buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream)); |
---|
590 | buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream)); |
---|
591 | |
---|
592 | /* Network I/O buffers */ |
---|
593 | buffer_put_string(&m, buffer_ptr(&input), buffer_len(&input)); |
---|
594 | buffer_put_string(&m, buffer_ptr(&output), buffer_len(&output)); |
---|
595 | |
---|
596 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KEYEXPORT, &m); |
---|
597 | debug3("%s: Finished sending state", __func__); |
---|
598 | |
---|
599 | buffer_free(&m); |
---|
600 | } |
---|
601 | |
---|
602 | int |
---|
603 | mm_pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, int namebuflen) |
---|
604 | { |
---|
605 | Buffer m; |
---|
606 | char *p; |
---|
607 | int success = 0; |
---|
608 | |
---|
609 | buffer_init(&m); |
---|
610 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTY, &m); |
---|
611 | |
---|
612 | debug3("%s: waiting for MONITOR_ANS_PTY", __func__); |
---|
613 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_PTY, &m); |
---|
614 | |
---|
615 | success = buffer_get_int(&m); |
---|
616 | if (success == 0) { |
---|
617 | debug3("%s: pty alloc failed", __func__); |
---|
618 | buffer_free(&m); |
---|
619 | return (0); |
---|
620 | } |
---|
621 | p = buffer_get_string(&m, NULL); |
---|
622 | buffer_free(&m); |
---|
623 | |
---|
624 | strlcpy(namebuf, p, namebuflen); /* Possible truncation */ |
---|
625 | xfree(p); |
---|
626 | |
---|
627 | *ptyfd = mm_receive_fd(pmonitor->m_recvfd); |
---|
628 | *ttyfd = mm_receive_fd(pmonitor->m_recvfd); |
---|
629 | |
---|
630 | /* Success */ |
---|
631 | return (1); |
---|
632 | } |
---|
633 | |
---|
634 | void |
---|
635 | mm_session_pty_cleanup2(void *session) |
---|
636 | { |
---|
637 | Session *s = session; |
---|
638 | Buffer m; |
---|
639 | |
---|
640 | if (s->ttyfd == -1) |
---|
641 | return; |
---|
642 | buffer_init(&m); |
---|
643 | buffer_put_cstring(&m, s->tty); |
---|
644 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PTYCLEANUP, &m); |
---|
645 | buffer_free(&m); |
---|
646 | |
---|
647 | /* closed dup'ed master */ |
---|
648 | if (close(s->ptymaster) < 0) |
---|
649 | error("close(s->ptymaster): %s", strerror(errno)); |
---|
650 | |
---|
651 | /* unlink pty from session */ |
---|
652 | s->ttyfd = -1; |
---|
653 | } |
---|
654 | |
---|
655 | #ifdef USE_PAM |
---|
656 | void |
---|
657 | mm_start_pam(char *user) |
---|
658 | { |
---|
659 | Buffer m; |
---|
660 | |
---|
661 | debug3("%s entering", __func__); |
---|
662 | |
---|
663 | buffer_init(&m); |
---|
664 | buffer_put_cstring(&m, user); |
---|
665 | |
---|
666 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_PAM_START, &m); |
---|
667 | |
---|
668 | buffer_free(&m); |
---|
669 | } |
---|
670 | #endif /* USE_PAM */ |
---|
671 | |
---|
672 | /* Request process termination */ |
---|
673 | |
---|
674 | void |
---|
675 | mm_terminate(void) |
---|
676 | { |
---|
677 | Buffer m; |
---|
678 | |
---|
679 | buffer_init(&m); |
---|
680 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_TERM, &m); |
---|
681 | buffer_free(&m); |
---|
682 | } |
---|
683 | |
---|
684 | int |
---|
685 | mm_ssh1_session_key(BIGNUM *num) |
---|
686 | { |
---|
687 | int rsafail; |
---|
688 | Buffer m; |
---|
689 | |
---|
690 | buffer_init(&m); |
---|
691 | buffer_put_bignum2(&m, num); |
---|
692 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSKEY, &m); |
---|
693 | |
---|
694 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SESSKEY, &m); |
---|
695 | |
---|
696 | rsafail = buffer_get_int(&m); |
---|
697 | buffer_get_bignum2(&m, num); |
---|
698 | |
---|
699 | buffer_free(&m); |
---|
700 | |
---|
701 | return (rsafail); |
---|
702 | } |
---|
703 | |
---|
704 | static void |
---|
705 | mm_chall_setup(char **name, char **infotxt, u_int *numprompts, |
---|
706 | char ***prompts, u_int **echo_on) |
---|
707 | { |
---|
708 | *name = xstrdup(""); |
---|
709 | *infotxt = xstrdup(""); |
---|
710 | *numprompts = 1; |
---|
711 | *prompts = xmalloc(*numprompts * sizeof(char *)); |
---|
712 | *echo_on = xmalloc(*numprompts * sizeof(u_int)); |
---|
713 | (*echo_on)[0] = 0; |
---|
714 | } |
---|
715 | |
---|
716 | int |
---|
717 | mm_bsdauth_query(void *ctx, char **name, char **infotxt, |
---|
718 | u_int *numprompts, char ***prompts, u_int **echo_on) |
---|
719 | { |
---|
720 | Buffer m; |
---|
721 | int res; |
---|
722 | char *challenge; |
---|
723 | |
---|
724 | debug3("%s: entering", __func__); |
---|
725 | |
---|
726 | buffer_init(&m); |
---|
727 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHQUERY, &m); |
---|
728 | |
---|
729 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_BSDAUTHQUERY, |
---|
730 | &m); |
---|
731 | res = buffer_get_int(&m); |
---|
732 | if (res == -1) { |
---|
733 | debug3("%s: no challenge", __func__); |
---|
734 | buffer_free(&m); |
---|
735 | return (-1); |
---|
736 | } |
---|
737 | |
---|
738 | /* Get the challenge, and format the response */ |
---|
739 | challenge = buffer_get_string(&m, NULL); |
---|
740 | buffer_free(&m); |
---|
741 | |
---|
742 | mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); |
---|
743 | (*prompts)[0] = challenge; |
---|
744 | |
---|
745 | debug3("%s: received challenge: %s", __func__, challenge); |
---|
746 | |
---|
747 | return (0); |
---|
748 | } |
---|
749 | |
---|
750 | int |
---|
751 | mm_bsdauth_respond(void *ctx, u_int numresponses, char **responses) |
---|
752 | { |
---|
753 | Buffer m; |
---|
754 | int authok; |
---|
755 | |
---|
756 | debug3("%s: entering", __func__); |
---|
757 | if (numresponses != 1) |
---|
758 | return (-1); |
---|
759 | |
---|
760 | buffer_init(&m); |
---|
761 | buffer_put_cstring(&m, responses[0]); |
---|
762 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_BSDAUTHRESPOND, &m); |
---|
763 | |
---|
764 | mm_request_receive_expect(pmonitor->m_recvfd, |
---|
765 | MONITOR_ANS_BSDAUTHRESPOND, &m); |
---|
766 | |
---|
767 | authok = buffer_get_int(&m); |
---|
768 | buffer_free(&m); |
---|
769 | |
---|
770 | return ((authok == 0) ? -1 : 0); |
---|
771 | } |
---|
772 | |
---|
773 | int |
---|
774 | mm_skey_query(void *ctx, char **name, char **infotxt, |
---|
775 | u_int *numprompts, char ***prompts, u_int **echo_on) |
---|
776 | { |
---|
777 | Buffer m; |
---|
778 | int len, res; |
---|
779 | char *p, *challenge; |
---|
780 | |
---|
781 | debug3("%s: entering", __func__); |
---|
782 | |
---|
783 | buffer_init(&m); |
---|
784 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYQUERY, &m); |
---|
785 | |
---|
786 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_SKEYQUERY, |
---|
787 | &m); |
---|
788 | res = buffer_get_int(&m); |
---|
789 | if (res == -1) { |
---|
790 | debug3("%s: no challenge", __func__); |
---|
791 | buffer_free(&m); |
---|
792 | return (-1); |
---|
793 | } |
---|
794 | |
---|
795 | /* Get the challenge, and format the response */ |
---|
796 | challenge = buffer_get_string(&m, NULL); |
---|
797 | buffer_free(&m); |
---|
798 | |
---|
799 | debug3("%s: received challenge: %s", __func__, challenge); |
---|
800 | |
---|
801 | mm_chall_setup(name, infotxt, numprompts, prompts, echo_on); |
---|
802 | |
---|
803 | len = strlen(challenge) + strlen(SKEY_PROMPT) + 1; |
---|
804 | p = xmalloc(len); |
---|
805 | strlcpy(p, challenge, len); |
---|
806 | strlcat(p, SKEY_PROMPT, len); |
---|
807 | (*prompts)[0] = p; |
---|
808 | xfree(challenge); |
---|
809 | |
---|
810 | return (0); |
---|
811 | } |
---|
812 | |
---|
813 | int |
---|
814 | mm_skey_respond(void *ctx, u_int numresponses, char **responses) |
---|
815 | { |
---|
816 | Buffer m; |
---|
817 | int authok; |
---|
818 | |
---|
819 | debug3("%s: entering", __func__); |
---|
820 | if (numresponses != 1) |
---|
821 | return (-1); |
---|
822 | |
---|
823 | buffer_init(&m); |
---|
824 | buffer_put_cstring(&m, responses[0]); |
---|
825 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SKEYRESPOND, &m); |
---|
826 | |
---|
827 | mm_request_receive_expect(pmonitor->m_recvfd, |
---|
828 | MONITOR_ANS_SKEYRESPOND, &m); |
---|
829 | |
---|
830 | authok = buffer_get_int(&m); |
---|
831 | buffer_free(&m); |
---|
832 | |
---|
833 | return ((authok == 0) ? -1 : 0); |
---|
834 | } |
---|
835 | |
---|
836 | void |
---|
837 | mm_ssh1_session_id(u_char session_id[16]) |
---|
838 | { |
---|
839 | Buffer m; |
---|
840 | int i; |
---|
841 | |
---|
842 | debug3("%s entering", __func__); |
---|
843 | |
---|
844 | buffer_init(&m); |
---|
845 | for (i = 0; i < 16; i++) |
---|
846 | buffer_put_char(&m, session_id[i]); |
---|
847 | |
---|
848 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_SESSID, &m); |
---|
849 | buffer_free(&m); |
---|
850 | } |
---|
851 | |
---|
852 | int |
---|
853 | mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) |
---|
854 | { |
---|
855 | Buffer m; |
---|
856 | Key *key; |
---|
857 | u_char *blob; |
---|
858 | u_int blen; |
---|
859 | int allowed = 0; |
---|
860 | |
---|
861 | debug3("%s entering", __func__); |
---|
862 | |
---|
863 | buffer_init(&m); |
---|
864 | buffer_put_bignum2(&m, client_n); |
---|
865 | |
---|
866 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSAKEYALLOWED, &m); |
---|
867 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSAKEYALLOWED, &m); |
---|
868 | |
---|
869 | allowed = buffer_get_int(&m); |
---|
870 | |
---|
871 | if (allowed && rkey != NULL) { |
---|
872 | blob = buffer_get_string(&m, &blen); |
---|
873 | if ((key = key_from_blob(blob, blen)) == NULL) |
---|
874 | fatal("%s: key_from_blob failed", __func__); |
---|
875 | *rkey = key; |
---|
876 | xfree(blob); |
---|
877 | } |
---|
878 | mm_send_debug(&m); |
---|
879 | buffer_free(&m); |
---|
880 | |
---|
881 | return (allowed); |
---|
882 | } |
---|
883 | |
---|
884 | BIGNUM * |
---|
885 | mm_auth_rsa_generate_challenge(Key *key) |
---|
886 | { |
---|
887 | Buffer m; |
---|
888 | BIGNUM *challenge; |
---|
889 | u_char *blob; |
---|
890 | u_int blen; |
---|
891 | |
---|
892 | debug3("%s entering", __func__); |
---|
893 | |
---|
894 | if ((challenge = BN_new()) == NULL) |
---|
895 | fatal("%s: BN_new failed", __func__); |
---|
896 | |
---|
897 | key->type = KEY_RSA; /* XXX cheat for key_to_blob */ |
---|
898 | if (key_to_blob(key, &blob, &blen) == 0) |
---|
899 | fatal("%s: key_to_blob failed", __func__); |
---|
900 | key->type = KEY_RSA1; |
---|
901 | |
---|
902 | buffer_init(&m); |
---|
903 | buffer_put_string(&m, blob, blen); |
---|
904 | xfree(blob); |
---|
905 | |
---|
906 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSACHALLENGE, &m); |
---|
907 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSACHALLENGE, &m); |
---|
908 | |
---|
909 | buffer_get_bignum2(&m, challenge); |
---|
910 | buffer_free(&m); |
---|
911 | |
---|
912 | return (challenge); |
---|
913 | } |
---|
914 | |
---|
915 | int |
---|
916 | mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16]) |
---|
917 | { |
---|
918 | Buffer m; |
---|
919 | u_char *blob; |
---|
920 | u_int blen; |
---|
921 | int success = 0; |
---|
922 | |
---|
923 | debug3("%s entering", __func__); |
---|
924 | |
---|
925 | key->type = KEY_RSA; /* XXX cheat for key_to_blob */ |
---|
926 | if (key_to_blob(key, &blob, &blen) == 0) |
---|
927 | fatal("%s: key_to_blob failed", __func__); |
---|
928 | key->type = KEY_RSA1; |
---|
929 | |
---|
930 | buffer_init(&m); |
---|
931 | buffer_put_string(&m, blob, blen); |
---|
932 | buffer_put_string(&m, response, 16); |
---|
933 | xfree(blob); |
---|
934 | |
---|
935 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_RSARESPONSE, &m); |
---|
936 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_RSARESPONSE, &m); |
---|
937 | |
---|
938 | success = buffer_get_int(&m); |
---|
939 | buffer_free(&m); |
---|
940 | |
---|
941 | return (success); |
---|
942 | } |
---|
943 | |
---|
944 | #ifdef KRB4 |
---|
945 | int |
---|
946 | mm_auth_krb4(Authctxt *authctxt, void *_auth, char **client, void *_reply) |
---|
947 | { |
---|
948 | KTEXT auth, reply; |
---|
949 | Buffer m; |
---|
950 | u_int rlen; |
---|
951 | int success = 0; |
---|
952 | char *p; |
---|
953 | |
---|
954 | debug3("%s entering", __func__); |
---|
955 | auth = _auth; |
---|
956 | reply = _reply; |
---|
957 | |
---|
958 | buffer_init(&m); |
---|
959 | buffer_put_string(&m, auth->dat, auth->length); |
---|
960 | |
---|
961 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB4, &m); |
---|
962 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB4, &m); |
---|
963 | |
---|
964 | success = buffer_get_int(&m); |
---|
965 | if (success) { |
---|
966 | *client = buffer_get_string(&m, NULL); |
---|
967 | p = buffer_get_string(&m, &rlen); |
---|
968 | if (rlen >= MAX_KTXT_LEN) |
---|
969 | fatal("%s: reply from monitor too large", __func__); |
---|
970 | reply->length = rlen; |
---|
971 | memcpy(reply->dat, p, rlen); |
---|
972 | memset(p, 0, rlen); |
---|
973 | xfree(p); |
---|
974 | } |
---|
975 | buffer_free(&m); |
---|
976 | return (success); |
---|
977 | } |
---|
978 | #endif |
---|
979 | |
---|
980 | #ifdef KRB5 |
---|
981 | int |
---|
982 | mm_auth_krb5(void *ctx, void *argp, char **userp, void *resp) |
---|
983 | { |
---|
984 | krb5_data *tkt, *reply; |
---|
985 | Buffer m; |
---|
986 | int success; |
---|
987 | |
---|
988 | debug3("%s entering", __func__); |
---|
989 | tkt = (krb5_data *) argp; |
---|
990 | reply = (krb5_data *) resp; |
---|
991 | |
---|
992 | buffer_init(&m); |
---|
993 | buffer_put_string(&m, tkt->data, tkt->length); |
---|
994 | |
---|
995 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_KRB5, &m); |
---|
996 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_KRB5, &m); |
---|
997 | |
---|
998 | success = buffer_get_int(&m); |
---|
999 | if (success) { |
---|
1000 | u_int len; |
---|
1001 | |
---|
1002 | *userp = buffer_get_string(&m, NULL); |
---|
1003 | reply->data = buffer_get_string(&m, &len); |
---|
1004 | reply->length = len; |
---|
1005 | } else { |
---|
1006 | memset(reply, 0, sizeof(*reply)); |
---|
1007 | *userp = NULL; |
---|
1008 | } |
---|
1009 | |
---|
1010 | buffer_free(&m); |
---|
1011 | return (success); |
---|
1012 | } |
---|
1013 | #endif |
---|
1014 | |
---|
1015 | #ifdef GSSAPI |
---|
1016 | OM_uint32 |
---|
1017 | mm_ssh_gssapi_server_ctx(Gssctxt **ctx, gss_OID oid) { |
---|
1018 | Buffer m; |
---|
1019 | OM_uint32 major; |
---|
1020 | |
---|
1021 | /* Client doesn't get to see the context */ |
---|
1022 | *ctx=NULL; |
---|
1023 | |
---|
1024 | buffer_init(&m); |
---|
1025 | buffer_put_string(&m,oid->elements,oid->length); |
---|
1026 | |
---|
1027 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSETUP, &m); |
---|
1028 | |
---|
1029 | debug3("%s: waiting for MONITOR_ANS_GSSSETUP",__func__); |
---|
1030 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSETUP, &m); |
---|
1031 | major=buffer_get_int(&m); |
---|
1032 | |
---|
1033 | return(major); |
---|
1034 | } |
---|
1035 | |
---|
1036 | OM_uint32 |
---|
1037 | mm_ssh_gssapi_accept_ctx(Gssctxt *ctx, gss_buffer_desc *in, |
---|
1038 | gss_buffer_desc *out, OM_uint32 *flags) { |
---|
1039 | |
---|
1040 | Buffer m; |
---|
1041 | OM_uint32 major; |
---|
1042 | |
---|
1043 | buffer_init(&m); |
---|
1044 | buffer_put_string(&m, in->value, in->length); |
---|
1045 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSTEP, &m); |
---|
1046 | |
---|
1047 | debug3("%s: waiting for MONITOR_ANS_GSSSTEP", __func__); |
---|
1048 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSTEP, &m); |
---|
1049 | |
---|
1050 | major=buffer_get_int(&m); |
---|
1051 | out->value=buffer_get_string(&m,&out->length); |
---|
1052 | if (flags) *flags=buffer_get_int(&m); |
---|
1053 | |
---|
1054 | return(major); |
---|
1055 | } |
---|
1056 | |
---|
1057 | int |
---|
1058 | mm_ssh_gssapi_userok(char *user) { |
---|
1059 | Buffer m; |
---|
1060 | int authenticated = 0; |
---|
1061 | |
---|
1062 | buffer_init(&m); |
---|
1063 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSUSEROK, &m); |
---|
1064 | |
---|
1065 | debug3("%s: waiting for MONTIOR_ANS_GSSUSEROK", __func__); |
---|
1066 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSUSEROK, |
---|
1067 | &m); |
---|
1068 | |
---|
1069 | authenticated = buffer_get_int(&m); |
---|
1070 | |
---|
1071 | buffer_free(&m); |
---|
1072 | debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); |
---|
1073 | return(authenticated); |
---|
1074 | } |
---|
1075 | |
---|
1076 | OM_uint32 |
---|
1077 | mm_ssh_gssapi_sign(Gssctxt *ctx, gss_buffer_desc *data, gss_buffer_desc *hash) { |
---|
1078 | Buffer m; |
---|
1079 | OM_uint32 major; |
---|
1080 | |
---|
1081 | buffer_init(&m); |
---|
1082 | buffer_put_string(&m, data->value, data->length); |
---|
1083 | |
---|
1084 | mm_request_send(pmonitor->m_recvfd, MONITOR_REQ_GSSSIGN, &m); |
---|
1085 | |
---|
1086 | debug3("%s: waiting for MONITOR_ANS_GSSSIGN",__func__); |
---|
1087 | mm_request_receive_expect(pmonitor->m_recvfd, MONITOR_ANS_GSSSIGN, &m); |
---|
1088 | major=buffer_get_int(&m); |
---|
1089 | hash->value = buffer_get_string(&m, &hash->length); |
---|
1090 | |
---|
1091 | return(major); |
---|
1092 | } |
---|
1093 | #endif /* GSSAPI */ |
---|