summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--monitor.c656
-rw-r--r--monitor.h57
-rw-r--r--monitor_fdpass.c89
-rw-r--r--monitor_fdpass.h32
-rw-r--r--monitor_mm.c329
-rw-r--r--monitor_mm.h64
-rw-r--r--monitor_wrap.c538
7 files changed, 0 insertions, 1765 deletions
diff --git a/monitor.c b/monitor.c
deleted file mode 100644
index b85790271..000000000
--- a/monitor.c
+++ /dev/null
@@ -1,656 +0,0 @@
1/*
2 * Copyright 2001 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
27RCSID("$OpenBSD$");
28
29#include <openssl/dh.h>
30
31#include "ssh.h"
32#include "auth.h"
33#include "kex.h"
34#include "dh.h"
35#include "zlib.h"
36#include "packet.h"
37#include "auth-options.h"
38#include "sshpty.h"
39#include "channels.h"
40#include "session.h"
41#include "log.h"
42#include "monitor.h"
43#include "monitor_mm.h"
44#include "monitor_wrap.h"
45#include "monitor_fdpass.h"
46#include "xmalloc.h"
47#include "misc.h"
48#include "buffer.h"
49#include "bufaux.h"
50
51/* Imports */
52extern Newkeys *current_keys[];
53extern z_stream incoming_stream;
54extern z_stream outgoing_stream;
55extern int compat20;
56extern int mm_sendfd;
57
58/* State exported from the child */
59
60struct {
61 z_stream incoming;
62 z_stream outgoing;
63 u_char *keyin;
64 u_int keyinlen;
65 u_char *keyout;
66 u_int keyoutlen;
67} child_state;
68
69/* Prototype for authentication functions */
70
71int hostbased_key_allowed(struct passwd *, const char *, char *, Key *);
72int user_key_allowed(struct passwd *, Key *);
73Key *get_hostkey_by_index(int);
74
75void session_pty_cleanup(void *);
76
77static Authctxt *authctxt;
78
79struct mon_table {
80 enum monitor_reqtype type;
81 int flags;
82 int (*f)(int, Buffer *);
83};
84
85#define MON_PROTOONE 0x0001 /* Used in protocol 1 */
86#define MON_PROTOTWO 0x0002 /* Used in protocol 2 */
87#define MON_AUTH 0x0004 /* Authentication Request */
88
89#define MON_BOTH (MON_PROTOONE|MON_PROTOTWO)
90
91#define MON_PERMIT 0x1000 /* Request is permitted */
92
93struct mon_table mon_dispatch_proto20[] = {
94 {MONITOR_REQ_MODULI, MON_PROTOTWO, mm_answer_moduli},
95 {MONITOR_REQ_SIGN, MON_PROTOTWO, mm_answer_sign},
96 {MONITOR_REQ_PWNAM, MON_BOTH, mm_answer_pwnamallow},
97 {MONITOR_REQ_AUTHSERV, MON_BOTH, mm_answer_authserv},
98 {MONITOR_REQ_AUTHPASSWORD, MON_BOTH | MON_AUTH, mm_answer_authpassword},
99 {MONITOR_REQ_KEYALLOWED, MON_BOTH | MON_AUTH, mm_answer_keyallowed},
100 {MONITOR_REQ_KEYVERIFY, MON_BOTH | MON_AUTH, mm_answer_keyverify},
101 {0, 0, NULL}
102};
103
104struct mon_table mon_dispatch_postauth20[] = {
105 {MONITOR_REQ_MODULI, MON_PROTOTWO, mm_answer_moduli},
106 {MONITOR_REQ_SIGN, MON_PROTOTWO, mm_answer_sign},
107 {MONITOR_REQ_PTY, MON_BOTH, mm_answer_pty},
108 {MONITOR_REQ_TERM, MON_BOTH, mm_answer_term},
109 {0, 0, NULL}
110};
111
112struct mon_table mon_dispatch_proto15[] = {
113 {0, 0, NULL}
114};
115
116struct mon_table *mon_dispatch;
117
118/* Specifies if a certain message is allowed at the moment */
119
120void
121monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit)
122{
123 while (ent->f != NULL) {
124 if (ent->type == type) {
125 ent->flags &= ~MON_PERMIT;
126 ent->flags |= permit ? MON_PERMIT : 0;
127 return;
128 }
129 ent++;
130 }
131}
132
133void
134monitor_permit_authentications(int permit)
135{
136 struct mon_table *ent = mon_dispatch;
137
138 while (ent->f != NULL) {
139 if (ent->flags & MON_AUTH) {
140 ent->flags &= ~MON_PERMIT;
141 ent->flags |= permit ? MON_PERMIT : 0;
142 }
143 ent++;
144 }
145}
146
147#define FD_CLOSEONEXEC(x) do { \
148 if (fcntl(x, F_SETFD, 1) == -1) \
149 fatal("fcntl(%d, F_SETFD)", x); \
150} while (0)
151
152void
153monitor_socketpair(int *pair)
154{
155 if (socketpair(PF_LOCAL, SOCK_STREAM, 0, pair) == -1)
156 fatal("%s: socketpair", __FUNCTION__);
157 FD_CLOSEONEXEC(pair[0]);
158 FD_CLOSEONEXEC(pair[1]);
159}
160
161Authctxt *
162monitor_child_preauth(int socket)
163{
164 debug3("preauth child monitor started");
165
166 if (compat20) {
167 mon_dispatch = mon_dispatch_proto20;
168
169 /* Permit requests for moduli and signatures */
170 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
171 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
172 } else
173 mon_dispatch = mon_dispatch_proto15;
174
175 authctxt = authctxt_new();
176
177 /* The first few requests do not require asynchronous access */
178 for (;;) {
179 if (monitor_read(socket, mon_dispatch))
180 break;
181 }
182
183 debug("%s: %s has been authenticated by privileged process",
184 __FUNCTION__, authctxt->user);
185
186 if (compat20) {
187 mm_get_keystate(socket);
188 } else {
189 fatal("Use loose");
190 }
191
192 return (authctxt);
193}
194
195void
196monitor_child_postauth(int socket)
197{
198 if (compat20) {
199 mon_dispatch = mon_dispatch_postauth20;
200
201 /* Permit requests for moduli and signatures */
202 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
203 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
204 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
205
206 if (!no_pty_flag)
207 monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
208 } else
209 mon_dispatch = mon_dispatch_proto15;
210
211 for (;;) {
212 if (monitor_read(socket, mon_dispatch))
213 break;
214 }
215}
216
217int
218monitor_read(int socket, struct mon_table *ent)
219{
220 Buffer m;
221 int ret;
222 u_char type;
223
224 buffer_init(&m);
225
226 mm_request_receive(socket, &m);
227 type = buffer_get_char(&m);
228
229 debug3("%s: checking request %d", __FUNCTION__, type);
230
231 while (ent->f != NULL) {
232 if (ent->type == type)
233 break;
234 ent++;
235 }
236
237 if (ent->f != NULL) {
238 if (!(ent->flags & MON_PERMIT))
239 fatal("%s: unpermitted request %d", __FUNCTION__,
240 type);
241 ret = (*ent->f)(socket, &m);
242 buffer_free(&m);
243 return ret;
244 }
245
246 fatal("%s: unsupported request: %d\n", __FUNCTION__, type);
247
248 /* NOTREACHED */
249 return (-1);
250}
251
252int
253mm_answer_moduli(int socket, Buffer *m)
254{
255 DH *dh;
256 int min, want, max;
257
258 /* Turn off requests for moduli */
259 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 0);
260
261 min = buffer_get_int(m);
262 want = buffer_get_int(m);
263 max = buffer_get_int(m);
264
265 debug3("%s: got parameters: %d %d %d",
266 __FUNCTION__, min, want, max);
267 /* We need to check here, too, in case the child got corrupted */
268 if (max < min || want < min || max < want)
269 fatal("%s: bad parameters: %d %d %d",
270 __FUNCTION__, min, want, max);
271
272 buffer_clear(m);
273
274 dh = choose_dh(min, want, max);
275 if (dh == NULL) {
276 buffer_put_char(m, 0);
277 return (0);
278 } else {
279 /* Send first bignum */
280 buffer_put_char(m, 1);
281 buffer_put_bignum2(m, dh->p);
282 buffer_put_bignum2(m, dh->g);
283
284 DH_free(dh);
285 }
286 mm_request_send(socket, MONITOR_ANS_MODULI, m);
287 return (0);
288}
289
290int
291mm_answer_sign(int socket, Buffer *m)
292{
293 Key *key;
294 u_char *p;
295 u_char *signature;
296 u_int siglen, datlen;
297 int keyid;
298
299 debug3("%s", __FUNCTION__);
300
301 keyid = buffer_get_int(m);
302 p = buffer_get_string(m, &datlen);
303
304 if ((key = get_hostkey_by_index(keyid)) == NULL)
305 fatal("%s: no hostkey from index %d", __FUNCTION__, keyid);
306 if (key_sign(key, &signature, &siglen, p, datlen) < 0)
307 fatal("%s: key_sign failed", __FUNCTION__);
308
309 debug3("%s: signature %p(%d)", __FUNCTION__, signature, siglen);
310
311 buffer_clear(m);
312 buffer_put_string(m, signature, siglen);
313
314 xfree(p);
315 xfree(signature);
316
317 /* Turn on permissions for getpwnam */
318 monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
319
320 mm_request_send(socket, MONITOR_ANS_SIGN, m);
321 return (0);
322}
323
324/* Retrieves the password entry and also checks if the user is permitted */
325
326int
327mm_answer_pwnamallow(int socket, Buffer *m)
328{
329 char *login;
330 struct passwd *pwent;
331 int allowed;
332
333 debug3("%s", __FUNCTION__);
334
335 if (authctxt->attempt++ != 0)
336 fatal("%s: multiple attempts for getpwnam", __FUNCTION__);
337
338 login = buffer_get_string(m, NULL);
339
340 /* XXX - probably latch the username here */
341 pwent = getpwnam(login);
342 authctxt->user = xstrdup(login);
343 setproctitle("%s [priv]", pwent ? login : "unknown");
344 xfree(login);
345
346 /* Allow service/style information on the auth context */
347 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
348
349 buffer_clear(m);
350
351 if (pwent == NULL) {
352 buffer_put_char(m, 0);
353 mm_request_send(socket, MONITOR_ANS_PWNAM, m);
354 return (0);
355 }
356
357 /* Check if we permit this user */
358 allowed = allowed_user(pwent);
359
360 if (allowed) {
361 authctxt->pw = pwcopy(pwent);
362 authctxt->valid = 1;
363 }
364 buffer_put_char(m, allowed);
365 buffer_put_string(m, pwent, sizeof(struct passwd));
366 buffer_put_cstring(m, pwent->pw_name);
367 buffer_put_cstring(m, "*");
368 buffer_put_cstring(m, pwent->pw_gecos);
369 buffer_put_cstring(m, pwent->pw_class);
370 buffer_put_cstring(m, pwent->pw_dir);
371 buffer_put_cstring(m, pwent->pw_shell);
372
373 debug3("%s: sending MONITOR_ANS_PWNAM: %d", __FUNCTION__, allowed);
374 mm_request_send(socket, MONITOR_ANS_PWNAM, m);
375
376 return (0);
377}
378
379int
380mm_answer_authserv(int socket, Buffer *m)
381{
382 /* Disallow service/style information on the auth context */
383 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 0);
384
385 monitor_permit_authentications(1);
386
387 authctxt->service = buffer_get_string(m, NULL);
388 authctxt->style = buffer_get_string(m, NULL);
389 if (strlen(authctxt->style) == 0) {
390 xfree(authctxt->style);
391 authctxt->style = NULL;
392 }
393
394 debug3("%s: service=%s, style=%s",
395 __FUNCTION__, authctxt->service, authctxt->style);
396
397 return (0);
398}
399
400int
401mm_answer_authpassword(int socket, Buffer *m)
402{
403 char *passwd;
404 int authenticated;
405
406 passwd = buffer_get_string(m, NULL);
407 /* Only authenticate if the context is valid */
408 authenticated = authctxt->valid && auth_password(authctxt, passwd);
409 memset(passwd, 0, strlen(passwd));
410 xfree(passwd);
411
412 buffer_clear(m);
413 buffer_put_int(m, authenticated);
414
415 debug3("%s: sending result %d", __FUNCTION__, authenticated);
416 mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m);
417
418 /* Causes monitor loop to terminate if authenticated */
419 return (authenticated);
420}
421
422int
423mm_answer_keyallowed(int socket, Buffer *m)
424{
425 Key *key;
426 u_char *cuser, *chost, *blob;
427 u_int bloblen;
428 enum mm_keytype type = 0;
429 int allowed = 0;
430
431 debug3("%s entering", __FUNCTION__);
432
433 type = buffer_get_int(m);
434 cuser = buffer_get_string(m, NULL);
435 chost = buffer_get_string(m, NULL);
436 blob = buffer_get_string(m, &bloblen);
437
438 key = key_from_blob(blob, bloblen);
439
440 debug3("%s: key_from_blob: %p", __FUNCTION__, key);
441
442 if (key != NULL && authctxt->pw != NULL) {
443 switch(type) {
444 case MM_USERKEY:
445 allowed = user_key_allowed(authctxt->pw, key);
446 break;
447 case MM_HOSTKEY:
448 allowed = hostbased_key_allowed(authctxt->pw,
449 cuser, chost, key);
450 break;
451 default:
452 fatal("%s: unknown key type %d", __FUNCTION__,
453 type);
454 break;
455 }
456 key_free(key);
457 }
458 xfree(chost);
459 xfree(cuser);
460 xfree(blob);
461
462 debug3("%s: key %p is %s",
463 __FUNCTION__, key, allowed ? "allowed" : "disallowed");
464
465 buffer_clear(m);
466 buffer_put_int(m, allowed);
467
468 mm_request_send(socket, MONITOR_ANS_KEYALLOWED, m);
469 return (0);
470}
471
472int
473mm_answer_keyverify(int socket, Buffer *m)
474{
475 Key *key;
476 u_char *signature, *data, *cuser, *chost, *blob;
477 u_int signaturelen, datalen, bloblen;
478 int type;
479 int verified = 0;
480
481 type = buffer_get_int(m);
482 cuser = buffer_get_string(m, NULL);
483 chost = buffer_get_string(m, NULL);
484 blob = buffer_get_string(m, &bloblen);
485 signature = buffer_get_string(m, &signaturelen);
486 data = buffer_get_string(m, &datalen);
487
488 key = key_from_blob(blob, bloblen);
489 if (key == NULL)
490 fatal("%s: bad public key blob", __FUNCTION__);
491
492 if (authctxt->pw == NULL || !user_key_allowed(authctxt->pw, key))
493 fatal("%s: user not allowed", __FUNCTION__);
494 verified = key_verify(key, signature, signaturelen, data, datalen);
495 debug3("%s: key %p signature %s",
496 __FUNCTION__, key, verified ? "verified" : "unverified");
497
498 key_free(key);
499 xfree(chost);
500 xfree(cuser);
501 xfree(blob);
502 xfree(signature);
503 xfree(data);
504
505 buffer_clear(m);
506 buffer_put_int(m, verified);
507 mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m);
508
509 return (verified);
510}
511
512int
513mm_answer_pty(int socket, Buffer *m)
514{
515 Session *s;
516 int res;
517
518 debug3("%s entering", __FUNCTION__);
519
520 buffer_clear(m);
521 s = session_new();
522 if (s == NULL)
523 goto error;
524 s->authctxt = authctxt;
525 s->pw = authctxt->pw;
526 res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
527 if (res == 0)
528 goto error;
529 fatal_add_cleanup(session_pty_cleanup, (void *)s);
530 pty_setowner(authctxt->pw, s->tty);
531
532 buffer_put_int(m, 1);
533 buffer_put_cstring(m, s->tty);
534 mm_request_send(socket, MONITOR_ANS_PTY, m);
535
536 mm_send_fd(mm_sendfd, s->ptyfd);
537 mm_send_fd(mm_sendfd, s->ttyfd);
538 return (0);
539
540 error:
541 if (s != NULL)
542 session_close(s);
543 buffer_put_int(m, 0);
544 mm_request_send(socket, MONITOR_ANS_PTY, m);
545 return (0);
546}
547
548int
549mm_answer_term(int socket, Buffer *req)
550{
551 debug3("%s: tearing down sessions", __FUNCTION__);
552
553 /* The child is terminating */
554 session_destroy_all();
555
556 return (1);
557}
558
559void
560mm_apply_keystate(struct mm_master *mm)
561{
562 /* XXX - delegate to child? */
563 set_newkeys(MODE_IN);
564 set_newkeys(MODE_OUT);
565
566 packet_set_keycontext(MODE_OUT, child_state.keyout);
567 xfree(child_state.keyout);
568 packet_set_keycontext(MODE_IN, child_state.keyin);
569 xfree(child_state.keyin);
570
571 memcpy(&incoming_stream, &child_state.incoming,
572 sizeof(incoming_stream));
573 memcpy(&outgoing_stream, &child_state.outgoing,
574 sizeof(outgoing_stream));
575
576 /* Update with new address */
577 mm_init_compression(mm);
578}
579
580/* This function requries careful sanity checking */
581
582void
583mm_get_keystate(int socket)
584{
585 Buffer m;
586 u_char *blob, *p;
587 u_int bloblen, plen;
588
589 debug3("%s: Waiting for new keys", __FUNCTION__);
590
591 buffer_init(&m);
592 mm_request_receive_expect(socket, MONITOR_REQ_KEYEXPORT, &m);
593
594 blob = buffer_get_string(&m, &bloblen);
595 current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
596 xfree(blob);
597
598 debug3("%s: Waiting for second key", __FUNCTION__);
599 blob = buffer_get_string(&m, &bloblen);
600 current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
601 xfree(blob);
602
603 /* Now get sequence numbers for the packets */
604 packet_set_seqnr(MODE_OUT, buffer_get_int(&m));
605 packet_set_seqnr(MODE_IN, buffer_get_int(&m));
606
607 /* Get the key context */
608 child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);
609 child_state.keyin = buffer_get_string(&m, &child_state.keyinlen);
610
611 debug3("%s: Getting compression state", __FUNCTION__);
612 /* Get compression state */
613 p = buffer_get_string(&m, &plen);
614 if (plen != sizeof(child_state.outgoing))
615 fatal("%s: bad request size", __FUNCTION__);
616 memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));
617 xfree(p);
618
619 p = buffer_get_string(&m, &plen);
620 if (plen != sizeof(child_state.incoming))
621 fatal("%s: bad request size", __FUNCTION__);
622 memcpy(&child_state.incoming, p, sizeof(child_state.incoming));
623 xfree(p);
624
625 buffer_free(&m);
626}
627
628
629/* Allocation functions for zlib */
630void *
631mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
632{
633 void *address;
634
635 address = mm_malloc(mm, size * ncount);
636
637 return (address);
638}
639
640void
641mm_zfree(struct mm_master *mm, void *address)
642{
643 mm_free(mm, address);
644}
645
646void
647mm_init_compression(struct mm_master *mm)
648{
649 outgoing_stream.zalloc = (alloc_func)mm_zalloc;
650 outgoing_stream.zfree = (free_func)mm_zfree;
651 outgoing_stream.opaque = mm;
652
653 incoming_stream.zalloc = (alloc_func)mm_zalloc;
654 incoming_stream.zfree = (free_func)mm_zfree;
655 incoming_stream.opaque = mm;
656}
diff --git a/monitor.h b/monitor.h
deleted file mode 100644
index 7568603fe..000000000
--- a/monitor.h
+++ /dev/null
@@ -1,57 +0,0 @@
1/*
2 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef _MONITOR_H_
27#define _MONITOR_H_
28
29enum monitor_reqtype {
30 MONITOR_REQ_MODULI, MONITOR_ANS_MODULI,
31 MONITOR_REQ_FREE, MONITOR_REQ_AUTHSERV,
32 MONITOR_REQ_SIGN, MONITOR_ANS_SIGN,
33 MONITOR_REQ_PWNAM, MONITOR_ANS_PWNAM,
34 MONITOR_REQ_AUTHPASSWORD, MONITOR_ANS_AUTHPASSWORD,
35 MONITOR_REQ_KEYALLOWED, MONITOR_ANS_KEYALLOWED,
36 MONITOR_REQ_KEYVERIFY, MONITOR_ANS_KEYVERIFY,
37 MONITOR_REQ_KEYEXPORT,
38 MONITOR_REQ_PTY, MONITOR_ANS_PTY,
39 MONITOR_REQ_TERM
40};
41
42struct monitor_req {
43 enum monitor_reqtype type;
44 void *address;
45 size_t size;
46};
47
48void monitor_socketpair(int *pair);
49
50struct Authctxt;
51struct Authctxt *monitor_child_preauth(int);
52void monitor_child_postauth(int);
53
54struct mon_table;
55int monitor_read(int, struct mon_table *);
56
57#endif /* _MONITOR_H_ */
diff --git a/monitor_fdpass.c b/monitor_fdpass.c
deleted file mode 100644
index 46087ae66..000000000
--- a/monitor_fdpass.c
+++ /dev/null
@@ -1,89 +0,0 @@
1/*
2 * Copyright 2001 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
27RCSID("$OpenBSD$");
28
29#include <sys/uio.h>
30
31#include "ssh.h"
32#include "log.h"
33#include "xmalloc.h"
34#include "misc.h"
35#include "monitor_fdpass.h"
36
37void
38mm_send_fd(int socket, int fd)
39{
40 struct msghdr msg;
41 char tmp[CMSG_SPACE(sizeof(int))];
42 struct cmsghdr *cmsg;
43 struct iovec vec;
44 char ch;
45
46 memset(&msg, 0, sizeof(msg));
47 msg.msg_control = (caddr_t)tmp;
48 msg.msg_controllen = CMSG_LEN(sizeof(int));
49 cmsg = CMSG_FIRSTHDR(&msg);
50 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
51 cmsg->cmsg_level = SOL_SOCKET;
52 cmsg->cmsg_type = SCM_RIGHTS;
53 *(int *)CMSG_DATA(cmsg) = fd;
54
55 vec.iov_base = &ch;
56 vec.iov_len = 1;
57 msg.msg_iov = &vec;
58 msg.msg_iovlen = 1;
59
60 if (sendmsg(socket, &msg, 0) == -1)
61 fatal("%s: sendmsg(%d)", __FUNCTION__, fd);
62}
63
64int
65mm_receive_fd(int socket)
66{
67 struct msghdr msg;
68 char tmp[CMSG_SPACE(sizeof(int))];
69 struct cmsghdr *cmsg;
70 struct iovec vec;
71 char ch;
72
73 memset(&msg, 0, sizeof(msg));
74 vec.iov_base = &ch;
75 vec.iov_len = 1;
76 msg.msg_iov = &vec;
77 msg.msg_iovlen = 1;
78 msg.msg_control = tmp;
79 msg.msg_controllen = sizeof(tmp);
80
81 if (recvmsg(socket, &msg, 0) == -1)
82 fatal("%s: recvmsg", __FUNCTION__);
83
84 cmsg = CMSG_FIRSTHDR(&msg);
85 if (cmsg->cmsg_type != SCM_RIGHTS)
86 fatal("%s: expected type %d got %d", __FUNCTION__,
87 SCM_RIGHTS, cmsg->cmsg_type);
88 return (*(int *)CMSG_DATA(cmsg));
89}
diff --git a/monitor_fdpass.h b/monitor_fdpass.h
deleted file mode 100644
index cb6b71c93..000000000
--- a/monitor_fdpass.h
+++ /dev/null
@@ -1,32 +0,0 @@
1/*
2 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef _MM_FDPASS_H_
27#define _MM_FDPASS_H_
28
29void mm_send_fd(int, int);
30int mm_receive_fd(int);
31
32#endif /* _MM_FDPASS_H_ */
diff --git a/monitor_mm.c b/monitor_mm.c
deleted file mode 100644
index 111c97d90..000000000
--- a/monitor_mm.c
+++ /dev/null
@@ -1,329 +0,0 @@
1/*
2 * Copyright 2001 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
27RCSID("$OpenBSD$");
28
29#include <sys/mman.h>
30
31#include "ssh.h"
32#include "xmalloc.h"
33#include "log.h"
34#include "monitor_mm.h"
35
36static int
37mm_compare(struct mm_share *a, struct mm_share *b)
38{
39 return (a->address - b->address);
40}
41
42RB_GENERATE(mmtree, mm_share, next, mm_compare);
43
44static struct mm_share *
45mm_make_entry(struct mm_master *mm, struct mmtree *head,
46 void *address, size_t size)
47{
48 struct mm_share *tmp, *tmp2;
49
50 if (mm->mmalloc == NULL)
51 tmp = xmalloc(sizeof(struct mm_share));
52 else
53 tmp = mm_xmalloc(mm->mmalloc, sizeof(struct mm_share));
54 tmp->address = address;
55 tmp->size = size;
56
57 tmp2 = RB_INSERT(mmtree, head, tmp);
58 if (tmp2 != NULL)
59 fatal("mm_make_entry(%p): double address %p->%p(%d)",
60 mm, tmp2, address, size);
61
62 return (tmp);
63}
64
65/* Creates a shared memory area of a certain size */
66
67struct mm_master *
68mm_create(struct mm_master *mmalloc, size_t size)
69{
70 void *address;
71 struct mm_master *mm;
72
73 if (mmalloc == NULL)
74 mm = xmalloc(sizeof(struct mm_master));
75 else
76 mm = mm_xmalloc(mmalloc, sizeof(struct mm_master));
77
78 /*
79 * If the memory map has a mm_master it can be completely
80 * shared including authentication between the child
81 * and the client.
82 */
83 mm->mmalloc = mmalloc;
84
85 address = mmap(NULL, size, PROT_WRITE|PROT_READ, MAP_ANON|MAP_SHARED,
86 -1, 0);
87 if (address == MAP_FAILED)
88 fatal("mmap(%d)", size);
89
90 mm->address = address;
91 mm->size = size;
92
93 RB_INIT(&mm->rb_free);
94 RB_INIT(&mm->rb_allocated);
95
96 mm_make_entry(mm, &mm->rb_free, address, size);
97
98 return (mm);
99}
100
101/* Frees either the allocated or the free list */
102
103void
104mm_freelist(struct mm_master *mmalloc, struct mmtree *head)
105{
106 struct mm_share *mms, *next;
107
108 for (mms = RB_ROOT(head); mms; mms = next) {
109 next = RB_NEXT(mmtree, head, mms);
110 RB_REMOVE(mmtree, head, mms);
111 if (mmalloc == NULL)
112 xfree(mms);
113 else
114 mm_free(mmalloc, mms);
115 }
116}
117
118/* Destroys a memory mapped area */
119
120void
121mm_destroy(struct mm_master *mm)
122{
123 mm_freelist(mm->mmalloc, &mm->rb_free);
124 mm_freelist(mm->mmalloc, &mm->rb_allocated);
125
126 if (munmap(mm->address, mm->size) == -1)
127 fatal("munmap(%p, %d)", mm->address, mm->size);
128 if (mm->mmalloc == NULL)
129 xfree(mm);
130 else
131 mm_free(mm->mmalloc, mm);
132}
133
134void *
135mm_xmalloc(struct mm_master *mm, size_t size)
136{
137 void *address;
138
139 address = mm_malloc(mm, size);
140 if (address == NULL)
141 fatal("%s: mm_malloc(%d)", __FUNCTION__, size);
142 return (address);
143}
144
145
146/* Allocates data from a memory mapped area */
147
148void *
149mm_malloc(struct mm_master *mm, size_t size)
150{
151 struct mm_share *mms, *tmp;
152
153 if (size == 0)
154 fatal("mm_malloc: try to allocate 0 space");
155
156 size = ((size + MM_MINSIZE - 1) / MM_MINSIZE) * MM_MINSIZE;
157
158 RB_FOREACH(mms, mmtree, &mm->rb_free) {
159 if (mms->size >= size)
160 break;
161 }
162
163 if (mms == NULL)
164 return (NULL);
165
166 /* Debug */
167 memset(mms->address, 0xd0, size);
168
169 tmp = mm_make_entry(mm, &mm->rb_allocated, mms->address, size);
170
171 /* Does not change order in RB tree */
172 mms->size -= size;
173 mms->address = (u_char *)mms->address + size;
174
175 if (mms->size == 0) {
176 RB_REMOVE(mmtree, &mm->rb_free, mms);
177 if (mm->mmalloc == NULL)
178 xfree(mms);
179 else
180 mm_free(mm->mmalloc, mms);
181 }
182
183 return (tmp->address);
184}
185
186/* Frees memory in a memory mapped area */
187
188void
189mm_free(struct mm_master *mm, void *address)
190{
191 struct mm_share *mms, *prev, tmp;
192
193 tmp.address = address;
194 mms = RB_FIND(mmtree, &mm->rb_allocated, &tmp);
195 if (mms == NULL)
196 fatal("mm_free(%p): can not find %p", mm, address);
197
198 /* Debug */
199 memset(mms->address, 0xd0, mms->size);
200
201 /* Remove from allocated list and insert in free list */
202 RB_REMOVE(mmtree, &mm->rb_allocated, mms);
203 if (RB_INSERT(mmtree, &mm->rb_free, mms) != NULL)
204 fatal("mm_free(%p): double address %p", mm, address);
205
206 /* Find previous entry */
207 prev = mms;
208 if (RB_LEFT(prev, next)) {
209 prev = RB_LEFT(prev, next);
210 while (RB_RIGHT(prev, next))
211 prev = RB_RIGHT(prev, next);
212 } else {
213 if (RB_PARENT(prev, next) &&
214 (prev == RB_RIGHT(RB_PARENT(prev, next), next)))
215 prev = RB_PARENT(prev, next);
216 else {
217 while (RB_PARENT(prev, next) &&
218 (prev == RB_LEFT(RB_PARENT(prev, next), next)))
219 prev = RB_PARENT(prev, next);
220 prev = RB_PARENT(prev, next);
221 }
222 }
223
224 /* Check if range does not overlap */
225 if (prev != NULL && MM_ADDRESS_END(prev) > address)
226 fatal("mm_free: memory corruption: %p(%d) > %p",
227 prev->address, prev->size, address);
228
229 /* See if we can merge backwards */
230 if (prev != NULL && MM_ADDRESS_END(prev) == address) {
231 prev->size += mms->size;
232 RB_REMOVE(mmtree, &mm->rb_free, mms);
233 if (mm->mmalloc == NULL)
234 xfree(mms);
235 else
236 mm_free(mm->mmalloc, mms);
237 } else
238 prev = mms;
239
240 if (prev == NULL)
241 return;
242
243 /* Check if we can merge forwards */
244 mms = RB_NEXT(mmtree, &mm->rb_free, prev);
245 if (mms == NULL)
246 return;
247
248 if (MM_ADDRESS_END(prev) > mms->address)
249 fatal("mm_free: memory corruption: %p < %p(%d)",
250 mms->address, prev->address, prev->size);
251 if (MM_ADDRESS_END(prev) != mms->address)
252 return;
253
254 prev->size += mms->size;
255 RB_REMOVE(mmtree, &mm->rb_free, mms);
256
257 if (mm->mmalloc == NULL)
258 xfree(mms);
259 else
260 mm_free(mm->mmalloc, mms);
261}
262
263void
264mm_sync_list(struct mmtree *oldtree, struct mmtree *newtree,
265 struct mm_master *mm, struct mm_master *mmold)
266{
267 struct mm_master *mmalloc = mm->mmalloc;
268 struct mm_share *mms, *new;
269
270 /* Sync free list */
271 RB_FOREACH(mms, mmtree, oldtree) {
272 /* Check the values */
273 mm_memvalid(mmold, mms, sizeof(struct mm_share));
274 mm_memvalid(mm, mms->address, mms->size);
275
276 new = mm_xmalloc(mmalloc, sizeof(struct mm_share));
277 memcpy(new, mms, sizeof(struct mm_share));
278 RB_INSERT(mmtree, newtree, new);
279 }
280}
281
282void
283mm_share_sync(struct mm_master **pmm, struct mm_master **pmmalloc)
284{
285 struct mm_master *mm;
286 struct mm_master *mmalloc;
287 struct mm_master *mmold;
288 struct mmtree rb_free, rb_allocated;
289
290 debug3("%s: Share sync", __FUNCTION__);
291
292 mm = *pmm;
293 mmold = mm->mmalloc;
294 mm_memvalid(mmold, mm, sizeof(*mm));
295
296 mmalloc = mm_create(NULL, mm->size);
297 mm = mm_xmalloc(mmalloc, sizeof(struct mm_master));
298 memcpy(mm, *pmm, sizeof(struct mm_master));
299 mm->mmalloc = mmalloc;
300
301 rb_free = mm->rb_free;
302 rb_allocated = mm->rb_allocated;
303
304 RB_INIT(&mm->rb_free);
305 RB_INIT(&mm->rb_allocated);
306
307 mm_sync_list(&rb_free, &mm->rb_free, mm, mmold);
308 mm_sync_list(&rb_allocated, &mm->rb_allocated, mm, mmold);
309
310 mm_destroy(mmold);
311
312 *pmm = mm;
313 *pmmalloc = mmalloc;
314
315 debug3("%s: Share sync end", __FUNCTION__);
316}
317
318void
319mm_memvalid(struct mm_master *mm, void *address, size_t size)
320{
321 void *end = (u_char *)address + size;
322
323 if (address < mm->address)
324 fatal("mm_memvalid: address too small: %p", address);
325 if (end < address)
326 fatal("mm_memvalid: end < address: %p < %p", end, address);
327 if (end > (void *)((u_char *)mm->address + mm->size))
328 fatal("mm_memvalid: address too large: %p", address);
329}
diff --git a/monitor_mm.h b/monitor_mm.h
deleted file mode 100644
index 5b4b789ca..000000000
--- a/monitor_mm.h
+++ /dev/null
@@ -1,64 +0,0 @@
1/*
2 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef _MM_H_
27#define _MM_H_
28#include <sys/tree.h>
29
30struct mm_share {
31 RB_ENTRY(mm_share) next;
32 void *address;
33 size_t size;
34};
35
36struct mm_master {
37 RB_HEAD(mmtree, mm_share) rb_free;
38 struct mmtree rb_allocated;
39 void *address;
40 size_t size;
41
42 struct mm_master *mmalloc; /* Used to completely share */
43
44 int write; /* used to writing to other party */
45 int read; /* used for reading from other party */
46};
47
48RB_PROTOTYPE(mmtree, mm_share, next, mm_compare);
49
50#define MM_MINSIZE 128
51
52#define MM_ADDRESS_END(x) (void *)((u_char *)(x)->address + (x)->size)
53
54struct mm_master *mm_create(struct mm_master *, size_t);
55void mm_destroy(struct mm_master *);
56
57void mm_share_sync(struct mm_master **, struct mm_master **);
58
59void *mm_malloc(struct mm_master *, size_t);
60void *mm_xmalloc(struct mm_master *, size_t);
61void mm_free(struct mm_master *, void *);
62
63void mm_memvalid(struct mm_master *, void *, size_t);
64#endif /* _MM_H_ */
diff --git a/monitor_wrap.c b/monitor_wrap.c
deleted file mode 100644
index 798e9353d..000000000
--- a/monitor_wrap.c
+++ /dev/null
@@ -1,538 +0,0 @@
1/*
2 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
27RCSID("$OpenBSD$");
28
29#include <openssl/bn.h>
30#include <openssl/dh.h>
31
32#include "ssh.h"
33#include "dh.h"
34#include "kex.h"
35#include "buffer.h"
36#include "bufaux.h"
37#include "packet.h"
38#include "mac.h"
39#include "log.h"
40#include "zlib.h"
41#include "monitor.h"
42#include "monitor_wrap.h"
43#include "xmalloc.h"
44#include "atomicio.h"
45#include "monitor_fdpass.h"
46#include "getput.h"
47
48/* Imports */
49extern Newkeys *newkeys[];
50extern z_stream incoming_stream;
51extern z_stream outgoing_stream;
52
53void
54mm_request_send(int socket, enum monitor_reqtype type, Buffer *m)
55{
56 u_char buf[5];
57 u_int mlen = buffer_len(m);
58
59 debug3("%s entering: type %d", __FUNCTION__, type);
60
61 PUT_32BIT(buf, mlen + 1);
62 buf[4] = (u_char) type; /* 1st byte of payload is mesg-type */
63 if (atomicio(write, socket, buf, sizeof(buf)) != sizeof(buf))
64 fatal("%s: write", __FUNCTION__);
65 if (atomicio(write, socket, buffer_ptr(m), mlen) != mlen)
66 fatal("%s: write", __FUNCTION__);
67}
68
69void
70mm_request_receive(int socket, Buffer *m)
71{
72 u_char buf[4];
73 ssize_t res;
74 u_int msg_len;
75
76 debug3("%s entering", __FUNCTION__);
77
78 res = atomicio(read, socket, buf, sizeof(buf));
79 if (res != sizeof(buf))
80 fatal("%s: read: %d", __FUNCTION__, res);
81 msg_len = GET_32BIT(buf);
82 if (msg_len > 256 * 1024)
83 fatal("%s: read: bad msg_len %d", __FUNCTION__, msg_len);
84 buffer_clear(m);
85 buffer_append_space(m, msg_len);
86 res = atomicio(read, socket, buffer_ptr(m), msg_len);
87 if (res != msg_len)
88 fatal("%s: read: %d != msg_len", __FUNCTION__, res);
89}
90
91void
92mm_request_receive_expect(int socket, enum monitor_reqtype type, Buffer *m)
93{
94 u_char rtype;
95
96 debug3("%s entering: type %d", __FUNCTION__, type);
97
98 mm_request_receive(socket, m);
99 rtype = buffer_get_char(m);
100 if (rtype != type)
101 fatal("%s: read: rtype %d != type %d", __FUNCTION__,
102 rtype, type);
103}
104
105DH *
106mm_choose_dh(int socket, int min, int nbits, int max)
107{
108 BIGNUM *p, *g;
109 int success = 0;
110 Buffer m;
111
112 buffer_init(&m);
113 buffer_put_int(&m, min);
114 buffer_put_int(&m, nbits);
115 buffer_put_int(&m, max);
116
117 mm_request_send(socket, MONITOR_REQ_MODULI, &m);
118
119 debug3("%s: waiting for MONITOR_ANS_MODULI", __FUNCTION__);
120 mm_request_receive_expect(socket, MONITOR_ANS_MODULI, &m);
121
122 success = buffer_get_char(&m);
123 if (success == 0)
124 fatal("%s: MONITOR_ANS_MODULI failed", __FUNCTION__);
125
126 if ((p = BN_new()) == NULL)
127 fatal("%s: BN_new failed", __FUNCTION__);
128 if ((g = BN_new()) == NULL)
129 fatal("%s: BN_new failed", __FUNCTION__);
130 buffer_get_bignum2(&m, p);
131 buffer_get_bignum2(&m, g);
132
133 debug3("%s: remaining %d", __FUNCTION__, buffer_len(&m));
134 buffer_free(&m);
135
136 return (dh_new_group(g, p));
137}
138
139int
140mm_key_sign(int socket, int keyind, u_char **sigp, u_int *lenp,
141 u_char *data, u_int datalen)
142{
143 Buffer m;
144
145 debug3("%s entering", __FUNCTION__);
146
147 buffer_init(&m);
148 buffer_put_int(&m, keyind);
149 buffer_put_string(&m, data, datalen);
150
151 mm_request_send(socket, MONITOR_REQ_SIGN, &m);
152
153 debug3("%s: waiting for MONITOR_ANS_SIGN", __FUNCTION__);
154 mm_request_receive_expect(socket, MONITOR_ANS_SIGN, &m);
155 *sigp = buffer_get_string(&m, lenp);
156 buffer_free(&m);
157
158 return (0);
159}
160
161struct passwd *
162mm_getpwnamallow(int socket, const char *login, int *allowed)
163{
164 Buffer m;
165 struct passwd *pw;
166 u_int pwlen;
167
168 debug3("%s entering", __FUNCTION__);
169
170 buffer_init(&m);
171 buffer_put_cstring(&m, login);
172
173 mm_request_send(socket, MONITOR_REQ_PWNAM, &m);
174
175 debug3("%s: waiting for MONITOR_ANS_PWNAM", __FUNCTION__);
176 mm_request_receive_expect(socket, MONITOR_ANS_PWNAM, &m);
177
178 *allowed = buffer_get_char(&m);
179 if (*allowed == 0) {
180 buffer_free(&m);
181 return (NULL);
182 }
183 pw = buffer_get_string(&m, &pwlen);
184 if (pwlen != sizeof(struct passwd))
185 fatal("%s: struct passwd size mismatch", __FUNCTION__);
186 pw->pw_name = buffer_get_string(&m, NULL);
187 pw->pw_passwd = buffer_get_string(&m, NULL);
188 pw->pw_gecos = buffer_get_string(&m, NULL);
189 pw->pw_class = buffer_get_string(&m, NULL);
190 pw->pw_dir = buffer_get_string(&m, NULL);
191 pw->pw_shell = buffer_get_string(&m, NULL);
192 buffer_free(&m);
193
194 return (pw);
195}
196
197void
198pwfree(struct passwd *pw)
199{
200 xfree(pw->pw_name);
201 xfree(pw->pw_passwd);
202 xfree(pw->pw_gecos);
203 xfree(pw->pw_class);
204 xfree(pw->pw_dir);
205 xfree(pw->pw_shell);
206 xfree(pw);
207}
208
209/* Inform the privileged process about service and style */
210
211void
212mm_inform_authserv(int socket, char *service, char *style)
213{
214 Buffer m;
215
216 debug3("%s entering", __FUNCTION__);
217
218 buffer_init(&m);
219 buffer_put_cstring(&m, service);
220 buffer_put_cstring(&m, style ? style : "");
221
222 mm_request_send(socket, MONITOR_REQ_AUTHSERV, &m);
223
224 buffer_free(&m);
225}
226
227/* Do the password authentication */
228int
229mm_auth_password(int socket, char *password)
230{
231 Buffer m;
232 int authenticated = 0;
233
234 debug3("%s entering", __FUNCTION__);
235
236 buffer_init(&m);
237 buffer_put_cstring(&m, password);
238 mm_request_send(socket, MONITOR_REQ_AUTHPASSWORD, &m);
239
240 debug3("%s: waiting for MONITOR_ANS_AUTHPASSWORD", __FUNCTION__);
241 mm_request_receive_expect(socket, MONITOR_ANS_AUTHPASSWORD, &m);
242
243 authenticated = buffer_get_int(&m);
244
245 buffer_free(&m);
246
247 debug3("%s: user %sauthenticated",
248 __FUNCTION__, authenticated ? "" : "not ");
249 return (authenticated);
250}
251
252int
253mm_key_allowed(int socket, enum mm_keytype type, char *user, char *host,
254 Key *key)
255{
256 Buffer m;
257 u_char *blob;
258 u_int len;
259 int allowed = 0;
260
261 debug3("%s entering", __FUNCTION__);
262
263 /* Convert the key to a blob and the pass it over */
264 if (!key_to_blob(key, &blob, &len))
265 return (0);
266
267 buffer_init(&m);
268 buffer_put_int(&m, type);
269 buffer_put_cstring(&m, user ? user : "");
270 buffer_put_cstring(&m, host ? host : "");
271 buffer_put_string(&m, blob, len);
272 xfree(blob);
273
274 mm_request_send(socket, MONITOR_REQ_KEYALLOWED, &m);
275
276 debug3("%s: waiting for MONITOR_ANS_KEYALLOWED", __FUNCTION__);
277 mm_request_receive_expect(socket, MONITOR_ANS_KEYALLOWED, &m);
278
279 allowed = buffer_get_int(&m);
280
281 buffer_free(&m);
282
283 return (allowed);
284}
285
286/*
287 * This key verify needs to send the key type along, because the
288 * privileged parent makes the decision if the key is allowed
289 * for authentication.
290 */
291
292int
293mm_key_verify(int socket, enum mm_keytype type, char *user, char *host,
294 Key *key, u_char *sig, u_int siglen, u_char *data, u_int datalen)
295{
296 Buffer m;
297 u_char *blob;
298 u_int len;
299 int verified = 0;
300
301 debug3("%s entering", __FUNCTION__);
302
303 /* Convert the key to a blob and the pass it over */
304 if (!key_to_blob(key, &blob, &len))
305 return (0);
306
307 buffer_init(&m);
308 buffer_put_int(&m, type);
309 buffer_put_cstring(&m, user ? user : "");
310 buffer_put_cstring(&m, host ? host : "");
311 buffer_put_string(&m, blob, len);
312 buffer_put_string(&m, sig, siglen);
313 buffer_put_string(&m, data, datalen);
314 xfree(blob);
315
316 mm_request_send(socket, MONITOR_REQ_KEYVERIFY, &m);
317
318 debug3("%s: waiting for MONITOR_ANS_KEYVERIFY", __FUNCTION__);
319 mm_request_receive_expect(socket, MONITOR_ANS_KEYVERIFY, &m);
320
321 verified = buffer_get_int(&m);
322
323 buffer_free(&m);
324
325 return (verified);
326}
327
328/* Export key state after authentication */
329Newkeys *
330mm_newkeys_from_blob(u_char *blob, int blen)
331{
332 Buffer b;
333 int rlen;
334 Newkeys *newkey = NULL;
335 Enc *enc;
336 Mac *mac;
337 Comp *comp;
338
339 debug3("%s: %p(%d)", __FUNCTION__, blob, blen);
340#ifdef DEBUG_PK
341 dump_base64(stderr, blob, blen);
342#endif
343 buffer_init(&b);
344 buffer_append(&b, blob, blen);
345
346 newkey = xmalloc(sizeof(*newkey));
347 enc = &newkey->enc;
348 mac = &newkey->mac;
349 comp = &newkey->comp;
350
351 /* Enc structure */
352 enc->name = buffer_get_string(&b, NULL);
353 buffer_get(&b, &enc->cipher, sizeof(enc->cipher));
354 enc->enabled = buffer_get_int(&b);
355 enc->key_len = buffer_get_int(&b);
356 enc->block_size = buffer_get_int(&b);
357 enc->key = xmalloc(enc->key_len);
358 buffer_get(&b, enc->key, enc->key_len);
359 enc->iv = xmalloc(enc->block_size);
360 buffer_get(&b, enc->iv, enc->block_size);
361
362 if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
363 fatal("%s: bad cipher name %s or pointer %p", __FUNCTION__,
364 enc->name, enc->cipher);
365
366 /* Mac structure */
367 mac->name = buffer_get_string(&b, NULL);
368 if (mac->name == NULL || mac_init(mac, mac->name) == -1)
369 fatal("%s: can not init mac %s", __FUNCTION__, mac->name);
370 mac->enabled = buffer_get_int(&b);
371 mac->key = xmalloc(mac->key_len);
372 buffer_get(&b, mac->key, mac->key_len);
373
374 /* Comp structure */
375 comp->type = buffer_get_int(&b);
376 comp->enabled = buffer_get_int(&b);
377 comp->name = buffer_get_string(&b, NULL);
378
379 rlen = buffer_len(&b);
380 if (rlen != 0)
381 error("newkeys_from_blob: remaining bytes in blob %d", rlen);
382 buffer_free(&b);
383 return (newkey);
384}
385
386int
387mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
388{
389 Buffer b;
390 int len;
391 u_char *buf;
392 Enc *enc;
393 Mac *mac;
394 Comp *comp;
395 Newkeys *newkey = newkeys[mode];
396
397 debug3("%s: converting %p", __FUNCTION__, newkey);
398
399 if (newkey == NULL) {
400 error("%s: newkey == NULL", __FUNCTION__);
401 return 0;
402 }
403 enc = &newkey->enc;
404 mac = &newkey->mac;
405 comp = &newkey->comp;
406
407 buffer_init(&b);
408 /* Enc structure */
409 buffer_put_cstring(&b, enc->name);
410 /* The cipher struct is constant and shared, you export pointer */
411 buffer_append(&b, &enc->cipher, sizeof(enc->cipher));
412 buffer_put_int(&b, enc->enabled);
413 buffer_put_int(&b, enc->key_len);
414 buffer_put_int(&b, enc->block_size);
415 buffer_append(&b, enc->key, enc->key_len);
416 packet_get_keyiv(mode, enc->iv, enc->block_size);
417 buffer_append(&b, enc->iv, enc->block_size);
418
419 /* Mac structure */
420 buffer_put_cstring(&b, mac->name);
421 buffer_put_int(&b, mac->enabled);
422 buffer_append(&b, mac->key, mac->key_len);
423
424 /* Comp structure */
425 buffer_put_int(&b, comp->type);
426 buffer_put_int(&b, comp->enabled);
427 buffer_put_cstring(&b, comp->name);
428
429 len = buffer_len(&b);
430 buf = xmalloc(len);
431 memcpy(buf, buffer_ptr(&b), len);
432 memset(buffer_ptr(&b), 0, len);
433 buffer_free(&b);
434 if (lenp != NULL)
435 *lenp = len;
436 if (blobp != NULL)
437 *blobp = buf;
438 return len;
439}
440
441void
442mm_send_keystate(int socket)
443{
444 Buffer m;
445 u_char *blob, *p;
446 u_int bloblen, plen;
447
448 debug3("%s: Sending new keys: %p %p",
449 __FUNCTION__, newkeys[MODE_OUT], newkeys[MODE_IN]);
450
451 buffer_init(&m);
452
453 /* Keys from Kex */
454 if (!mm_newkeys_to_blob(MODE_OUT, &blob, &bloblen))
455 fatal("%s: conversion of newkeys failed", __FUNCTION__);
456
457 buffer_put_string(&m, blob, bloblen);
458 xfree(blob);
459
460 if (!mm_newkeys_to_blob(MODE_IN, &blob, &bloblen))
461 fatal("%s: conversion of newkeys failed", __FUNCTION__);
462
463 buffer_put_string(&m, blob, bloblen);
464 xfree(blob);
465
466 buffer_put_int(&m, packet_get_seqnr(MODE_OUT));
467 buffer_put_int(&m, packet_get_seqnr(MODE_IN));
468
469 debug3("%s: New keys have been sent", __FUNCTION__);
470
471 /* More key context */
472 plen = packet_get_keycontext(MODE_OUT, NULL);
473 p = xmalloc(plen+1);
474 packet_get_keycontext(MODE_OUT, p);
475 buffer_put_string(&m, p, plen);
476 xfree(p);
477
478 plen = packet_get_keycontext(MODE_IN, NULL);
479 p = xmalloc(plen+1);
480 packet_get_keycontext(MODE_IN, p);
481 buffer_put_string(&m, p, plen);
482 xfree(p);
483
484 /* Compression state */
485 debug3("%s: Sending compression state", __FUNCTION__);
486 buffer_put_string(&m, &outgoing_stream, sizeof(outgoing_stream));
487 buffer_put_string(&m, &incoming_stream, sizeof(incoming_stream));
488
489 mm_request_send(socket, MONITOR_REQ_KEYEXPORT, &m);
490 debug3("%s: Finished sending state", __FUNCTION__);
491
492 buffer_free(&m);
493}
494
495int
496mm_pty_allocown(int socket, int *ptyfd, int *ttyfd,
497 char *namebuf, int namebuflen)
498{
499 Buffer m;
500 u_char *p;
501 int success = 0;
502
503 buffer_init(&m);
504 mm_request_send(socket, MONITOR_REQ_PTY, &m);
505
506 debug3("%s: waiting for MONITOR_ANS_PTY", __FUNCTION__);
507 mm_request_receive_expect(socket, MONITOR_ANS_PTY, &m);
508
509 success = buffer_get_int(&m);
510 if (success == 0) {
511 debug3("%s: pty alloc failed", __FUNCTION__);
512 buffer_free(&m);
513 return (0);
514 }
515 p = buffer_get_string(&m, NULL);
516 buffer_free(&m);
517
518 strlcpy(namebuf, p, namebuflen); /* Possible truncation */
519 xfree(p);
520
521 *ptyfd = mm_receive_fd(socket);
522 *ttyfd = mm_receive_fd(socket);
523
524 /* Success */
525 return (1);
526}
527
528/* Request process termination */
529
530void
531mm_terminate(int socket)
532{
533 Buffer m;
534
535 buffer_init(&m);
536 mm_request_send(socket, MONITOR_REQ_TERM, &m);
537 buffer_free(&m);
538}