]> andersk Git - openssh.git/blob - monitor.c
- stevesk@cvs.openbsd.org 2002/03/24 23:20:00
[openssh.git] / monitor.c
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.c,v 1.7 2002/03/24 23:20:00 stevesk Exp $");
29
30 #include <openssl/dh.h>
31
32 #ifdef SKEY
33 #include <skey.h>
34 #endif
35
36 #include "ssh.h"
37 #include "auth.h"
38 #include "kex.h"
39 #include "dh.h"
40 #include "zlib.h"
41 #include "packet.h"
42 #include "auth-options.h"
43 #include "sshpty.h"
44 #include "channels.h"
45 #include "session.h"
46 #include "sshlogin.h"
47 #include "canohost.h"
48 #include "log.h"
49 #include "servconf.h"
50 #include "monitor.h"
51 #include "monitor_mm.h"
52 #include "monitor_wrap.h"
53 #include "monitor_fdpass.h"
54 #include "xmalloc.h"
55 #include "misc.h"
56 #include "buffer.h"
57 #include "bufaux.h"
58 #include "compat.h"
59 #include "ssh2.h"
60 #include "mpaux.h"
61
62 /* Imports */
63 extern ServerOptions options;
64 extern u_int utmp_len;
65 extern Newkeys *current_keys[];
66 extern z_stream incoming_stream;
67 extern z_stream outgoing_stream;
68 extern u_char session_id[];
69 extern Buffer input, output;
70 extern Buffer auth_debug;
71 extern int auth_debug_init;
72
73 /* State exported from the child */
74
75 struct {
76         z_stream incoming;
77         z_stream outgoing;
78         u_char *keyin;
79         u_int keyinlen;
80         u_char *keyout;
81         u_int keyoutlen;
82         u_char *ivin;
83         u_int ivinlen;
84         u_char *ivout;
85         u_int ivoutlen;
86         int ssh1cipher;
87         int ssh1protoflags;
88         u_char *input;
89         u_int ilen;
90         u_char *output;
91         u_int olen;
92 } child_state;
93
94 /* Functions on the montior that answer unprivileged requests */
95
96 int mm_answer_moduli(int, Buffer *);
97 int mm_answer_sign(int, Buffer *);
98 int mm_answer_pwnamallow(int, Buffer *);
99 int mm_answer_authserv(int, Buffer *);
100 int mm_answer_authpassword(int, Buffer *);
101 int mm_answer_bsdauthquery(int, Buffer *);
102 int mm_answer_bsdauthrespond(int, Buffer *);
103 int mm_answer_skeyquery(int, Buffer *);
104 int mm_answer_skeyrespond(int, Buffer *);
105 int mm_answer_keyallowed(int, Buffer *);
106 int mm_answer_keyverify(int, Buffer *);
107 int mm_answer_pty(int, Buffer *);
108 int mm_answer_pty_cleanup(int, Buffer *);
109 int mm_answer_term(int, Buffer *);
110 int mm_answer_rsa_keyallowed(int, Buffer *);
111 int mm_answer_rsa_challenge(int, Buffer *);
112 int mm_answer_rsa_response(int, Buffer *);
113 int mm_answer_sesskey(int, Buffer *);
114 int mm_answer_sessid(int, Buffer *);
115
116 static Authctxt *authctxt;
117 static BIGNUM *ssh1_challenge = NULL;   /* used for ssh1 rsa auth */
118
119 /* local state for key verify */
120 static u_char *key_blob = NULL;
121 static u_int key_bloblen = 0;
122 static int key_blobtype = MM_NOKEY;
123 static u_char *hostbased_cuser = NULL;
124 static u_char *hostbased_chost = NULL;
125 static char *auth_method = "unknown";
126
127 struct mon_table {
128         enum monitor_reqtype type;
129         int flags;
130         int (*f)(int, Buffer *);
131 };
132
133 #define MON_ISAUTH      0x0004  /* Required for Authentication */
134 #define MON_AUTHDECIDE  0x0008  /* Decides Authentication */
135 #define MON_ONCE        0x0010  /* Disable after calling */
136
137 #define MON_AUTH        (MON_ISAUTH|MON_AUTHDECIDE)
138
139 #define MON_PERMIT      0x1000  /* Request is permitted */
140
141 struct mon_table mon_dispatch_proto20[] = {
142     {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
143     {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
144     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
145     {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
146     {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
147 #ifdef BSD_AUTH
148     {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
149     {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond},
150 #endif
151 #ifdef SKEY
152     {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
153     {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
154 #endif
155     {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
156     {MONITOR_REQ_KEYVERIFY, MON_AUTH, mm_answer_keyverify},
157     {0, 0, NULL}
158 };
159
160 struct mon_table mon_dispatch_postauth20[] = {
161     {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
162     {MONITOR_REQ_SIGN, 0, mm_answer_sign},
163     {MONITOR_REQ_PTY, 0, mm_answer_pty},
164     {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
165     {MONITOR_REQ_TERM, 0, mm_answer_term},
166     {0, 0, NULL}
167 };
168
169 struct mon_table mon_dispatch_proto15[] = {
170     {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
171     {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
172     {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
173     {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
174     {MONITOR_REQ_RSAKEYALLOWED, MON_ISAUTH, mm_answer_rsa_keyallowed},
175     {MONITOR_REQ_KEYALLOWED, MON_ISAUTH, mm_answer_keyallowed},
176     {MONITOR_REQ_RSACHALLENGE, MON_ONCE, mm_answer_rsa_challenge},
177     {MONITOR_REQ_RSARESPONSE, MON_ONCE|MON_AUTHDECIDE, mm_answer_rsa_response},
178 #ifdef BSD_AUTH
179     {MONITOR_REQ_BSDAUTHQUERY, MON_ISAUTH, mm_answer_bsdauthquery},
180     {MONITOR_REQ_BSDAUTHRESPOND, MON_AUTH,mm_answer_bsdauthrespond},
181 #endif
182 #ifdef SKEY
183     {MONITOR_REQ_SKEYQUERY, MON_ISAUTH, mm_answer_skeyquery},
184     {MONITOR_REQ_SKEYRESPOND, MON_AUTH, mm_answer_skeyrespond},
185 #endif
186     {0, 0, NULL}
187 };
188
189 struct mon_table mon_dispatch_postauth15[] = {
190     {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
191     {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
192     {MONITOR_REQ_TERM, 0, mm_answer_term},
193     {0, 0, NULL}
194 };
195
196 struct mon_table *mon_dispatch;
197
198 /* Specifies if a certain message is allowed at the moment */
199
200 static void
201 monitor_permit(struct mon_table *ent, enum monitor_reqtype type, int permit)
202 {
203         while (ent->f != NULL) {
204                 if (ent->type == type) {
205                         ent->flags &= ~MON_PERMIT;
206                         ent->flags |= permit ? MON_PERMIT : 0;
207                         return;
208                 }
209                 ent++;
210         }
211 }
212
213 static void
214 monitor_permit_authentications(int permit)
215 {
216         struct mon_table *ent = mon_dispatch;
217
218         while (ent->f != NULL) {
219                 if (ent->flags & MON_AUTH) {
220                         ent->flags &= ~MON_PERMIT;
221                         ent->flags |= permit ? MON_PERMIT : 0;
222                 }
223                 ent++;
224         }
225 }
226
227 Authctxt *
228 monitor_child_preauth(struct monitor *monitor)
229 {
230         struct mon_table *ent;
231         int authenticated = 0;
232
233         debug3("preauth child monitor started");
234
235         if (compat20) {
236                 mon_dispatch = mon_dispatch_proto20;
237
238                 /* Permit requests for moduli and signatures */
239                 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
240                 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
241         } else {
242                 mon_dispatch = mon_dispatch_proto15;
243
244                 monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
245         }
246
247         authctxt = authctxt_new();
248
249         /* The first few requests do not require asynchronous access */
250         while (!authenticated) {
251                 authenticated = monitor_read(monitor, mon_dispatch, &ent);
252                 if (authenticated) {
253                         if (!(ent->flags & MON_AUTHDECIDE))
254                                 fatal("%s: unexpected authentication from %d",
255                                     __FUNCTION__, ent->type);
256                         if (authctxt->pw->pw_uid == 0 &&
257                             !auth_root_allowed(auth_method))
258                                 authenticated = 0;
259                 }
260
261                 if (ent->flags & MON_AUTHDECIDE) {
262                         auth_log(authctxt, authenticated, auth_method,
263                             compat20 ? " ssh2" : "");
264                         if (!authenticated)
265                                 authctxt->failures++;
266                 }
267         }
268
269         if (!authctxt->valid)
270                 fatal("%s: authenticated invalid user", __FUNCTION__);
271
272         debug("%s: %s has been authenticated by privileged process",
273             __FUNCTION__, authctxt->user);
274
275         mm_get_keystate(monitor);
276
277         return (authctxt);
278 }
279
280 void
281 monitor_child_postauth(struct monitor *monitor)
282 {
283         if (compat20) {
284                 mon_dispatch = mon_dispatch_postauth20;
285
286                 /* Permit requests for moduli and signatures */
287                 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
288                 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
289                 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
290
291         } else {
292                 mon_dispatch = mon_dispatch_postauth15;
293                 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
294         }
295         if (!no_pty_flag) {
296                 monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
297                 monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
298         }
299
300         for (;;)
301                 monitor_read(monitor, mon_dispatch, NULL);
302 }
303
304 void
305 monitor_sync(struct monitor *monitor)
306 {
307         /* The member allocation is not visible, so sync it */
308         mm_share_sync(&monitor->m_zlib, &monitor->m_zback);
309 }
310
311 int
312 monitor_read(struct monitor *monitor, struct mon_table *ent,
313     struct mon_table **pent)
314 {
315         Buffer m;
316         int ret;
317         u_char type;
318
319         buffer_init(&m);
320
321         mm_request_receive(monitor->m_sendfd, &m);
322         type = buffer_get_char(&m);
323
324         debug3("%s: checking request %d", __FUNCTION__, type);
325
326         while (ent->f != NULL) {
327                 if (ent->type == type)
328                         break;
329                 ent++;
330         }
331
332         if (ent->f != NULL) {
333                 if (!(ent->flags & MON_PERMIT))
334                         fatal("%s: unpermitted request %d", __FUNCTION__,
335                             type);
336                 ret = (*ent->f)(monitor->m_sendfd, &m);
337                 buffer_free(&m);
338
339                 /* The child may use this request only once, disable it */
340                 if (ent->flags & MON_ONCE) {
341                         debug2("%s: %d used once, disabling now", __FUNCTION__,
342                             type);
343                         ent->flags &= ~MON_PERMIT;
344                 }
345
346                 if (pent != NULL)
347                         *pent = ent;
348
349                 return ret;
350         }
351
352         fatal("%s: unsupported request: %d", __FUNCTION__, type);
353
354         /* NOTREACHED */
355         return (-1);
356 }
357
358 /* allowed key state */
359 static int
360 monitor_allowed_key(u_char *blob, u_int bloblen)
361 {
362         /* make sure key is allowed */
363         if (key_blob == NULL || key_bloblen != bloblen ||
364             memcmp(key_blob, blob, key_bloblen))
365                 return (0);
366         return (1);
367 }
368
369 static void
370 monitor_reset_key_state(void)
371 {
372         /* reset state */
373         if (key_blob != NULL)
374                 xfree(key_blob);
375         if (hostbased_cuser != NULL)
376                 xfree(hostbased_cuser);
377         if (hostbased_chost != NULL)
378                 xfree(hostbased_chost);
379         key_blob = NULL;
380         key_bloblen = 0;
381         key_blobtype = MM_NOKEY;
382         hostbased_cuser = NULL;
383         hostbased_chost = NULL;
384 }
385
386 int
387 mm_answer_moduli(int socket, Buffer *m)
388 {
389         DH *dh;
390         int min, want, max;
391
392         min = buffer_get_int(m);
393         want = buffer_get_int(m);
394         max = buffer_get_int(m);
395
396         debug3("%s: got parameters: %d %d %d",
397             __FUNCTION__, min, want, max);
398         /* We need to check here, too, in case the child got corrupted */
399         if (max < min || want < min || max < want)
400                 fatal("%s: bad parameters: %d %d %d",
401                     __FUNCTION__, min, want, max);
402
403         buffer_clear(m);
404
405         dh = choose_dh(min, want, max);
406         if (dh == NULL) {
407                 buffer_put_char(m, 0);
408                 return (0);
409         } else {
410                 /* Send first bignum */
411                 buffer_put_char(m, 1);
412                 buffer_put_bignum2(m, dh->p);
413                 buffer_put_bignum2(m, dh->g);
414
415                 DH_free(dh);
416         }
417         mm_request_send(socket, MONITOR_ANS_MODULI, m);
418         return (0);
419 }
420
421 int
422 mm_answer_sign(int socket, Buffer *m)
423 {
424         Key *key;
425         u_char *p;
426         u_char *signature;
427         u_int siglen, datlen;
428         int keyid;
429
430         debug3("%s", __FUNCTION__);
431
432         keyid = buffer_get_int(m);
433         p = buffer_get_string(m, &datlen);
434
435         if (datlen != 20)
436                 fatal("%s: data length incorrect: %d", __FUNCTION__, datlen);
437
438         if ((key = get_hostkey_by_index(keyid)) == NULL)
439                 fatal("%s: no hostkey from index %d", __FUNCTION__, keyid);
440         if (key_sign(key, &signature, &siglen, p, datlen) < 0)
441                 fatal("%s: key_sign failed", __FUNCTION__);
442
443         debug3("%s: signature %p(%d)", __FUNCTION__, signature, siglen);
444
445         buffer_clear(m);
446         buffer_put_string(m, signature, siglen);
447
448         xfree(p);
449         xfree(signature);
450
451         mm_request_send(socket, MONITOR_ANS_SIGN, m);
452
453         /* Turn on permissions for getpwnam */
454         monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
455
456         return (0);
457 }
458
459 /* Retrieves the password entry and also checks if the user is permitted */
460
461 int
462 mm_answer_pwnamallow(int socket, Buffer *m)
463 {
464         char *login;
465         struct passwd *pwent;
466         int allowed = 0;
467
468         debug3("%s", __FUNCTION__);
469
470         if (authctxt->attempt++ != 0)
471                 fatal("%s: multiple attempts for getpwnam", __FUNCTION__);
472
473         login = buffer_get_string(m, NULL);
474
475         pwent = getpwnamallow(login);
476
477         authctxt->user = xstrdup(login);
478         setproctitle("%s [priv]", pwent ? login : "unknown");
479         xfree(login);
480
481         buffer_clear(m);
482
483         if (pwent == NULL) {
484                 buffer_put_char(m, 0);
485                 goto out;
486         }
487
488         allowed = 1;
489         authctxt->pw = pwent;
490         authctxt->valid = 1;
491
492         buffer_put_char(m, 1);
493         buffer_put_string(m, pwent, sizeof(struct passwd));
494         buffer_put_cstring(m, pwent->pw_name);
495         buffer_put_cstring(m, "*");
496         buffer_put_cstring(m, pwent->pw_gecos);
497 #ifdef HAVE_PW_CLASS_IN_PASSWD
498         buffer_put_cstring(m, pwent->pw_class);
499 #endif
500         buffer_put_cstring(m, pwent->pw_dir);
501         buffer_put_cstring(m, pwent->pw_shell);
502
503  out:
504         debug3("%s: sending MONITOR_ANS_PWNAM: %d", __FUNCTION__, allowed);
505         mm_request_send(socket, MONITOR_ANS_PWNAM, m);
506
507         /* For SSHv1 allow authentication now */
508         if (!compat20)
509                 monitor_permit_authentications(1);
510         else
511                 /* Allow service/style information on the auth context */
512                 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
513
514
515         return (0);
516 }
517
518 int
519 mm_answer_authserv(int socket, Buffer *m)
520 {
521         monitor_permit_authentications(1);
522
523         authctxt->service = buffer_get_string(m, NULL);
524         authctxt->style = buffer_get_string(m, NULL);
525         debug3("%s: service=%s, style=%s",
526             __FUNCTION__, authctxt->service, authctxt->style);
527
528         if (strlen(authctxt->style) == 0) {
529                 xfree(authctxt->style);
530                 authctxt->style = NULL;
531         }
532
533         return (0);
534 }
535
536 int
537 mm_answer_authpassword(int socket, Buffer *m)
538 {
539         static int call_count;
540         char *passwd;
541         int authenticated, plen;
542
543         passwd = buffer_get_string(m, &plen);
544         /* Only authenticate if the context is valid */
545         authenticated = authctxt->valid && auth_password(authctxt, passwd);
546         memset(passwd, 0, strlen(passwd));
547         xfree(passwd);
548
549         buffer_clear(m);
550         buffer_put_int(m, authenticated);
551
552         debug3("%s: sending result %d", __FUNCTION__, authenticated);
553         mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m);
554
555         call_count++;
556         if (plen == 0 && call_count == 1)
557                 auth_method = "none";
558         else
559                 auth_method = "password";
560
561         /* Causes monitor loop to terminate if authenticated */
562         return (authenticated);
563 }
564
565 #ifdef BSD_AUTH
566 int
567 mm_answer_bsdauthquery(int socket, Buffer *m)
568 {
569         char *name, *infotxt;
570         u_int numprompts;
571         u_int *echo_on;
572         char **prompts;
573         int res;
574
575         res = bsdauth_query(authctxt, &name, &infotxt, &numprompts,
576             &prompts, &echo_on);
577
578         buffer_clear(m);
579         buffer_put_int(m, res);
580         if (res != -1)
581                 buffer_put_cstring(m, prompts[0]);
582
583         debug3("%s: sending challenge res: %d", __FUNCTION__, res);
584         mm_request_send(socket, MONITOR_ANS_BSDAUTHQUERY, m);
585
586         if (res != -1) {
587                 xfree(name);
588                 xfree(infotxt);
589                 xfree(prompts);
590                 xfree(echo_on);
591         }
592
593         return (0);
594 }
595
596 int
597 mm_answer_bsdauthrespond(int socket, Buffer *m)
598 {
599         char *response;
600         int authok;
601
602         if (authctxt->as == 0)
603                 fatal("%s: no bsd auth session", __FUNCTION__);
604
605         response = buffer_get_string(m, NULL);
606         authok = auth_userresponse(authctxt->as, response, 0);
607         authctxt->as = NULL;
608         debug3("%s: <%s> = <%d>", __FUNCTION__, response, authok);
609         xfree(response);
610
611         buffer_clear(m);
612         buffer_put_int(m, authok);
613
614         debug3("%s: sending authenticated: %d", __FUNCTION__, authok);
615         mm_request_send(socket, MONITOR_ANS_BSDAUTHRESPOND, m);
616
617         auth_method = "bsdauth";
618
619         return (authok != 0);
620 }
621 #endif
622
623 #ifdef SKEY
624 int
625 mm_answer_skeyquery(int socket, Buffer *m)
626 {
627         struct skey skey;
628         char challenge[1024];
629         int res;
630
631         res = skeychallenge(&skey, authctxt->user, challenge);
632
633         buffer_clear(m);
634         buffer_put_int(m, res);
635         if (res != -1)
636                 buffer_put_cstring(m, challenge);
637
638         debug3("%s: sending challenge res: %d", __FUNCTION__, res);
639         mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m);
640
641         return (0);
642 }
643
644 int
645 mm_answer_skeyrespond(int socket, Buffer *m)
646 {
647         char *response;
648         int authok;
649
650         response = buffer_get_string(m, NULL);
651
652         authok = (authctxt->valid &&
653             skey_haskey(authctxt->pw->pw_name) == 0 &&
654             skey_passcheck(authctxt->pw->pw_name, response) != -1);
655
656         xfree(response);
657
658         buffer_clear(m);
659         buffer_put_int(m, authok);
660
661         debug3("%s: sending authenticated: %d", __FUNCTION__, authok);
662         mm_request_send(socket, MONITOR_ANS_SKEYRESPOND, m);
663
664         auth_method = "skey";
665
666         return (authok != 0);
667 }
668 #endif
669
670 static void
671 mm_append_debug(Buffer *m)
672 {
673         if (auth_debug_init && buffer_len(&auth_debug)) {
674                 debug3("%s: Appending debug messages for child", __FUNCTION__);
675                 buffer_append(m, buffer_ptr(&auth_debug),
676                     buffer_len(&auth_debug));
677                 buffer_clear(&auth_debug);
678         }
679 }
680
681 int
682 mm_answer_keyallowed(int socket, Buffer *m)
683 {
684         Key *key;
685         u_char *cuser, *chost, *blob;
686         u_int bloblen;
687         enum mm_keytype type = 0;
688         int allowed = 0;
689
690         debug3("%s entering", __FUNCTION__);
691
692         type = buffer_get_int(m);
693         cuser = buffer_get_string(m, NULL);
694         chost = buffer_get_string(m, NULL);
695         blob = buffer_get_string(m, &bloblen);
696
697         key = key_from_blob(blob, bloblen);
698
699         if ((compat20 && type == MM_RSAHOSTKEY) ||
700             (!compat20 && type != MM_RSAHOSTKEY))
701                 fatal("%s: key type and protocol mismatch", __FUNCTION__);
702
703         debug3("%s: key_from_blob: %p", __FUNCTION__, key);
704
705         if (key != NULL && authctxt->pw != NULL) {
706                 switch(type) {
707                 case MM_USERKEY:
708                         allowed = user_key_allowed(authctxt->pw, key);
709                         break;
710                 case MM_HOSTKEY:
711                         allowed = hostbased_key_allowed(authctxt->pw,
712                             cuser, chost, key);
713                         break;
714                 case MM_RSAHOSTKEY:
715                         key->type = KEY_RSA1; /* XXX */
716                         allowed = auth_rhosts_rsa_key_allowed(authctxt->pw,
717                             cuser, chost, key);
718                         break;
719                 default:
720                         fatal("%s: unknown key type %d", __FUNCTION__, type);
721                         break;
722                 }
723                 key_free(key);
724         }
725
726         /* clear temporarily storage (used by verify) */
727         monitor_reset_key_state();
728
729         if (allowed) {
730                 /* Save temporarily for comparison in verify */
731                 key_blob = blob;
732                 key_bloblen = bloblen;
733                 key_blobtype = type;
734                 hostbased_cuser = cuser;
735                 hostbased_chost = chost;
736         }
737
738         debug3("%s: key %p is %s",
739             __FUNCTION__, key, allowed ? "allowed" : "disallowed");
740
741         buffer_clear(m);
742         buffer_put_int(m, allowed);
743
744         mm_append_debug(m);
745
746         mm_request_send(socket, MONITOR_ANS_KEYALLOWED, m);
747
748         if (type == MM_RSAHOSTKEY)
749                 monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
750
751         return (0);
752 }
753
754 static int
755 monitor_valid_userblob(u_char *data, u_int datalen)
756 {
757         Buffer b;
758         u_char *p;
759         u_int len;
760         int fail = 0;
761         int session_id2_len = 20 /*XXX should get from [net] */;
762
763         buffer_init(&b);
764         buffer_append(&b, data, datalen);
765
766         if (datafellows & SSH_OLD_SESSIONID) {
767                 buffer_consume(&b, session_id2_len);
768         } else {
769                 xfree(buffer_get_string(&b, &len));
770                 if (len != session_id2_len)
771                         fail++;
772         }
773         if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
774                 fail++;
775         p = buffer_get_string(&b, NULL);
776         if (strcmp(authctxt->user, p) != 0) {
777                 log("wrong user name passed to monitor: expected %s != %.100s",
778                     authctxt->user, p);
779                 fail++;
780         }
781         xfree(p);
782         buffer_skip_string(&b);
783         if (datafellows & SSH_BUG_PKAUTH) {
784                 if (!buffer_get_char(&b))
785                         fail++;
786         } else {
787                 p = buffer_get_string(&b, NULL);
788                 if (strcmp("publickey", p) != 0)
789                         fail++;
790                 xfree(p);
791                 if (!buffer_get_char(&b))
792                         fail++;
793                 buffer_skip_string(&b);
794         }
795         buffer_skip_string(&b);
796         if (buffer_len(&b) != 0)
797                 fail++;
798         buffer_free(&b);
799         return (fail == 0);
800 }
801
802 static int
803 monitor_valid_hostbasedblob(u_char *data, u_int datalen, u_char *cuser,
804     u_char *chost)
805 {
806         Buffer b;
807         u_char *p;
808         u_int len;
809         int fail = 0;
810         int session_id2_len = 20 /*XXX should get from [net] */;
811
812         buffer_init(&b);
813         buffer_append(&b, data, datalen);
814
815         xfree(buffer_get_string(&b, &len));
816         if (len != session_id2_len)
817                 fail++;
818         if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST)
819                 fail++;
820         p = buffer_get_string(&b, NULL);
821         if (strcmp(authctxt->user, p) != 0) {
822                 log("wrong user name passed to monitor: expected %s != %.100s",
823                     authctxt->user, p);
824                 fail++;
825         }
826         xfree(p);
827         buffer_skip_string(&b); /* service */
828         p = buffer_get_string(&b, NULL);
829         if (strcmp(p, "hostbased") != 0)
830                 fail++;
831         xfree(p);
832         buffer_skip_string(&b); /* pkalg */
833         buffer_skip_string(&b); /* pkblob */
834
835         /* verify client host, strip trailing dot if necessary */
836         p = buffer_get_string(&b, NULL);
837         if (((len = strlen(p)) > 0) && p[len - 1] == '.')
838                 p[len - 1] = '\0';
839         if (strcmp(p, chost) != 0)
840                 fail++;
841         xfree(p);
842
843         /* verify client user */
844         p = buffer_get_string(&b, NULL);
845         if (strcmp(p, cuser) != 0)
846                 fail++;
847         xfree(p);
848
849         if (buffer_len(&b) != 0)
850                 fail++;
851         buffer_free(&b);
852         return (fail == 0);
853 }
854
855 int
856 mm_answer_keyverify(int socket, Buffer *m)
857 {
858         Key *key;
859         u_char *signature, *data, *blob;
860         u_int signaturelen, datalen, bloblen;
861         int verified = 0;
862         int valid_data = 0;
863
864         blob = buffer_get_string(m, &bloblen);
865         signature = buffer_get_string(m, &signaturelen);
866         data = buffer_get_string(m, &datalen);
867
868         if (hostbased_cuser == NULL || hostbased_chost == NULL ||
869            monitor_allowed_key(blob, bloblen) == NULL)
870                 fatal("%s: bad key, not previously allowed", __FUNCTION__);
871
872         key = key_from_blob(blob, bloblen);
873         if (key == NULL)
874                 fatal("%s: bad public key blob", __FUNCTION__);
875
876         switch (key_blobtype) {
877         case MM_USERKEY:
878                 valid_data = monitor_valid_userblob(data, datalen);
879                 break;
880         case MM_HOSTKEY:
881                 valid_data = monitor_valid_hostbasedblob(data, datalen,
882                     hostbased_cuser, hostbased_chost);
883                 break;
884         default:
885                 valid_data = 0;
886                 break;
887         }
888         if (!valid_data)
889                 fatal("%s: bad signature data blob", __FUNCTION__);
890
891         verified = key_verify(key, signature, signaturelen, data, datalen);
892         debug3("%s: key %p signature %s",
893             __FUNCTION__, key, verified ? "verified" : "unverified");
894
895         key_free(key);
896         xfree(blob);
897         xfree(signature);
898         xfree(data);
899
900         monitor_reset_key_state();
901
902         buffer_clear(m);
903         buffer_put_int(m, verified);
904         mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m);
905
906         auth_method = "publickey";
907
908         return (verified);
909 }
910
911 static void
912 mm_record_login(Session *s, struct passwd *pw)
913 {
914         socklen_t fromlen;
915         struct sockaddr_storage from;
916
917         /*
918          * Get IP address of client. If the connection is not a socket, let
919          * the address be 0.0.0.0.
920          */
921         memset(&from, 0, sizeof(from));
922         if (packet_connection_is_on_socket()) {
923                 fromlen = sizeof(from);
924                 if (getpeername(packet_get_connection_in(),
925                         (struct sockaddr *) & from, &fromlen) < 0) {
926                         debug("getpeername: %.100s", strerror(errno));
927                         fatal_cleanup();
928                 }
929         }
930         /* Record that there was a login on that tty from the remote host. */
931         record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid,
932             get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping),
933             (struct sockaddr *)&from);
934 }
935
936 static void
937 mm_session_close(Session *s)
938 {
939         debug3("%s: session %d pid %d", __FUNCTION__, s->self, s->pid);
940         if (s->ttyfd != -1) {
941                 debug3("%s: tty %s ptyfd %d",  __FUNCTION__, s->tty, s->ptyfd);
942                 fatal_remove_cleanup(session_pty_cleanup2, (void *)s);
943                 session_pty_cleanup2(s);
944         }
945         s->used = 0;
946 }
947
948 int
949 mm_answer_pty(int socket, Buffer *m)
950 {
951         extern struct monitor *monitor;
952         Session *s;
953         int res, fd0;
954
955         debug3("%s entering", __FUNCTION__);
956
957         buffer_clear(m);
958         s = session_new();
959         if (s == NULL)
960                 goto error;
961         s->authctxt = authctxt;
962         s->pw = authctxt->pw;
963         s->pid = monitor->m_pid;
964         res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
965         if (res == 0)
966                 goto error;
967         fatal_add_cleanup(session_pty_cleanup2, (void *)s);
968         pty_setowner(authctxt->pw, s->tty);
969
970         buffer_put_int(m, 1);
971         buffer_put_cstring(m, s->tty);
972         mm_request_send(socket, MONITOR_ANS_PTY, m);
973
974         mm_send_fd(socket, s->ptyfd);
975         mm_send_fd(socket, s->ttyfd);
976
977         /* We need to trick ttyslot */
978         if (dup2(s->ttyfd, 0) == -1)
979                 fatal("%s: dup2", __FUNCTION__);
980
981         mm_record_login(s, authctxt->pw);
982
983         /* Now we can close the file descriptor again */
984         close(0);
985
986         /* make sure nothing uses fd 0 */
987         if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0)
988                 fatal("%s: open(/dev/null): %s", __FUNCTION__, strerror(errno));
989         if (fd0 != 0)
990                 error("%s: fd0 %d != 0", __FUNCTION__, fd0);
991
992         /* slave is not needed */
993         close(s->ttyfd);
994         s->ttyfd = s->ptyfd;
995         /* no need to dup() because nobody closes ptyfd */
996         s->ptymaster = s->ptyfd;
997
998         debug3("%s: tty %s ptyfd %d",  __FUNCTION__, s->tty, s->ttyfd);
999
1000         return (0);
1001
1002  error:
1003         if (s != NULL)
1004                 mm_session_close(s);
1005         buffer_put_int(m, 0);
1006         mm_request_send(socket, MONITOR_ANS_PTY, m);
1007         return (0);
1008 }
1009
1010 int
1011 mm_answer_pty_cleanup(int socket, Buffer *m)
1012 {
1013         Session *s;
1014         char *tty;
1015
1016         debug3("%s entering", __FUNCTION__);
1017
1018         tty = buffer_get_string(m, NULL);
1019         if ((s = session_by_tty(tty)) != NULL)
1020                 mm_session_close(s);
1021         buffer_clear(m);
1022         xfree(tty);
1023         return (0);
1024 }
1025
1026 int
1027 mm_answer_sesskey(int socket, Buffer *m)
1028 {
1029         BIGNUM *p;
1030         int rsafail;
1031
1032         /* Turn off permissions */
1033         monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1);
1034
1035         if ((p = BN_new()) == NULL)
1036                 fatal("%s: BN_new", __FUNCTION__);
1037
1038         buffer_get_bignum2(m, p);
1039
1040         rsafail = ssh1_session_key(p);
1041
1042         buffer_clear(m);
1043         buffer_put_int(m, rsafail);
1044         buffer_put_bignum2(m, p);
1045
1046         BN_clear_free(p);
1047
1048         mm_request_send(socket, MONITOR_ANS_SESSKEY, m);
1049
1050         /* Turn on permissions for sessid passing */
1051         monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1);
1052
1053         return (0);
1054 }
1055
1056 int
1057 mm_answer_sessid(int socket, Buffer *m)
1058 {
1059         int i;
1060
1061         debug3("%s entering", __FUNCTION__);
1062
1063         if (buffer_len(m) != 16)
1064                 fatal("%s: bad ssh1 session id", __FUNCTION__);
1065         for (i = 0; i < 16; i++)
1066                 session_id[i] = buffer_get_char(m);
1067
1068         /* Turn on permissions for getpwnam */
1069         monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1);
1070
1071         return (0);
1072 }
1073
1074 int
1075 mm_answer_rsa_keyallowed(int socket, Buffer *m)
1076 {
1077         BIGNUM *client_n;
1078         Key *key = NULL;
1079         u_char *blob = NULL;
1080         u_int blen = 0;
1081         int allowed = 0;
1082
1083         debug3("%s entering", __FUNCTION__);
1084
1085         if (authctxt->valid) {
1086                 if ((client_n = BN_new()) == NULL)
1087                         fatal("%s: BN_new", __FUNCTION__);
1088                 buffer_get_bignum2(m, client_n);
1089                 allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key);
1090                 BN_clear_free(client_n);
1091         }
1092         buffer_clear(m);
1093         buffer_put_int(m, allowed);
1094
1095         /* clear temporarily storage (used by generate challenge) */
1096         monitor_reset_key_state();
1097
1098         if (allowed && key != NULL) {
1099                 key->type = KEY_RSA;    /* cheat for key_to_blob */
1100                 if (key_to_blob(key, &blob, &blen) == 0)
1101                         fatal("%s: key_to_blob failed", __FUNCTION__);
1102                 buffer_put_string(m, blob, blen);
1103
1104                 /* Save temporarily for comparison in verify */
1105                 key_blob = blob;
1106                 key_bloblen = blen;
1107                 key_blobtype = MM_RSAUSERKEY;
1108                 key_free(key);
1109         }
1110
1111         mm_append_debug(m);
1112
1113         mm_request_send(socket, MONITOR_ANS_RSAKEYALLOWED, m);
1114
1115         monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed);
1116         monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0);
1117         return (0);
1118 }
1119
1120 int
1121 mm_answer_rsa_challenge(int socket, Buffer *m)
1122 {
1123         Key *key = NULL;
1124         u_char *blob;
1125         u_int blen;
1126
1127         debug3("%s entering", __FUNCTION__);
1128
1129         if (!authctxt->valid)
1130                 fatal("%s: authctxt not valid", __FUNCTION__);
1131         blob = buffer_get_string(m, &blen);
1132         if (!monitor_allowed_key(blob, blen))
1133                 fatal("%s: bad key, not previously allowed", __FUNCTION__);
1134         if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
1135                 fatal("%s: key type mismatch", __FUNCTION__);
1136         if ((key = key_from_blob(blob, blen)) == NULL)
1137                 fatal("%s: received bad key", __FUNCTION__);
1138
1139         if (ssh1_challenge)
1140                 BN_clear_free(ssh1_challenge);
1141         ssh1_challenge = auth_rsa_generate_challenge(key);
1142
1143         buffer_clear(m);
1144         buffer_put_bignum2(m, ssh1_challenge);
1145
1146         debug3("%s sending reply", __FUNCTION__);
1147         mm_request_send(socket, MONITOR_ANS_RSACHALLENGE, m);
1148
1149         monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1);
1150         return (0);
1151 }
1152
1153 int
1154 mm_answer_rsa_response(int socket, Buffer *m)
1155 {
1156         Key *key = NULL;
1157         u_char *blob, *response;
1158         u_int blen, len;
1159         int success;
1160
1161         debug3("%s entering", __FUNCTION__);
1162
1163         if (!authctxt->valid)
1164                 fatal("%s: authctxt not valid", __FUNCTION__);
1165         if (ssh1_challenge == NULL)
1166                 fatal("%s: no ssh1_challenge", __FUNCTION__);
1167
1168         blob = buffer_get_string(m, &blen);
1169         if (!monitor_allowed_key(blob, blen))
1170                 fatal("%s: bad key, not previously allowed", __FUNCTION__);
1171         if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY)
1172                 fatal("%s: key type mismatch: %d", __FUNCTION__, key_blobtype);
1173         if ((key = key_from_blob(blob, blen)) == NULL)
1174                 fatal("%s: received bad key", __FUNCTION__);
1175         response = buffer_get_string(m, &len);
1176         if (len != 16)
1177                 fatal("%s: received bad response to challenge", __FUNCTION__);
1178         success = auth_rsa_verify_response(key, ssh1_challenge, response);
1179
1180         key_free(key);
1181         xfree(response);
1182
1183         auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa";
1184
1185         /* reset state */
1186         BN_clear_free(ssh1_challenge);
1187         ssh1_challenge = NULL;
1188         monitor_reset_key_state();
1189
1190         buffer_clear(m);
1191         buffer_put_int(m, success);
1192         mm_request_send(socket, MONITOR_ANS_RSARESPONSE, m);
1193
1194         return (success);
1195 }
1196
1197 int
1198 mm_answer_term(int socket, Buffer *req)
1199 {
1200         extern struct monitor *monitor;
1201         int res, status;
1202
1203         debug3("%s: tearing down sessions", __FUNCTION__);
1204
1205         /* The child is terminating */
1206         session_destroy_all(&mm_session_close);
1207
1208         if (waitpid(monitor->m_pid, &status, 0) == -1)
1209                 exit(1);
1210
1211         res = WIFEXITED(status) ? WEXITSTATUS(status) : 1;
1212
1213         /* Terminate process */
1214         exit (res);
1215 }
1216
1217 void
1218 monitor_apply_keystate(struct monitor *monitor)
1219 {
1220         if (compat20) {
1221                 set_newkeys(MODE_IN);
1222                 set_newkeys(MODE_OUT);
1223         } else {
1224                 u_char key[SSH_SESSION_KEY_LENGTH];
1225
1226                 memset(key, 'a', sizeof(key));
1227                 packet_set_protocol_flags(child_state.ssh1protoflags);
1228                 packet_set_encryption_key(key, SSH_SESSION_KEY_LENGTH,
1229                     child_state.ssh1cipher);
1230         }
1231
1232         packet_set_keycontext(MODE_OUT, child_state.keyout);
1233         xfree(child_state.keyout);
1234         packet_set_keycontext(MODE_IN, child_state.keyin);
1235         xfree(child_state.keyin);
1236
1237         if (!compat20) {
1238                 packet_set_iv(MODE_OUT, child_state.ivout);
1239                 xfree(child_state.ivout);
1240                 packet_set_iv(MODE_IN, child_state.ivin);
1241                 xfree(child_state.ivin);
1242         }
1243
1244         memcpy(&incoming_stream, &child_state.incoming,
1245             sizeof(incoming_stream));
1246         memcpy(&outgoing_stream, &child_state.outgoing,
1247             sizeof(outgoing_stream));
1248
1249         /* Update with new address */
1250         mm_init_compression(monitor->m_zlib);
1251
1252         /* Network I/O buffers */
1253         /* XXX inefficient for large buffers, need: buffer_init_from_string */
1254         buffer_clear(&input);
1255         buffer_append(&input, child_state.input, child_state.ilen);
1256         memset(child_state.input, 0, child_state.ilen);
1257         xfree(child_state.input);
1258
1259         buffer_clear(&output);
1260         buffer_append(&output, child_state.output, child_state.olen);
1261         memset(child_state.output, 0, child_state.olen);
1262         xfree(child_state.output);
1263 }
1264
1265 static Kex *
1266 mm_get_kex(Buffer *m)
1267 {
1268         Kex *kex;
1269         void *blob;
1270         u_int bloblen;
1271
1272         kex = xmalloc(sizeof(*kex));
1273         memset(kex, 0, sizeof(*kex));
1274         kex->session_id = buffer_get_string(m, &kex->session_id_len);
1275         kex->we_need = buffer_get_int(m);
1276         kex->server = 1;
1277         kex->hostkey_type = buffer_get_int(m);
1278         kex->kex_type = buffer_get_int(m);
1279         blob = buffer_get_string(m, &bloblen);
1280         buffer_init(&kex->my);
1281         buffer_append(&kex->my, blob, bloblen);
1282         xfree(blob);
1283         blob = buffer_get_string(m, &bloblen);
1284         buffer_init(&kex->peer);
1285         buffer_append(&kex->peer, blob, bloblen);
1286         xfree(blob);
1287         kex->done = 1;
1288         kex->flags = buffer_get_int(m);
1289         kex->client_version_string = buffer_get_string(m, NULL);
1290         kex->server_version_string = buffer_get_string(m, NULL);
1291         kex->load_host_key=&get_hostkey_by_type;
1292         kex->host_key_index=&get_hostkey_index;
1293
1294         return (kex);
1295 }
1296
1297 /* This function requries careful sanity checking */
1298
1299 void
1300 mm_get_keystate(struct monitor *monitor)
1301 {
1302         Buffer m;
1303         u_char *blob, *p;
1304         u_int bloblen, plen;
1305
1306         debug3("%s: Waiting for new keys", __FUNCTION__);
1307
1308         buffer_init(&m);
1309         mm_request_receive_expect(monitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m);
1310         if (!compat20) {
1311                 child_state.ssh1protoflags = buffer_get_int(&m);
1312                 child_state.ssh1cipher = buffer_get_int(&m);
1313                 child_state.ivout = buffer_get_string(&m,
1314                     &child_state.ivoutlen);
1315                 child_state.ivin = buffer_get_string(&m, &child_state.ivinlen);
1316                 goto skip;
1317         } else {
1318                 /* Get the Kex for rekeying */
1319                 *monitor->m_pkex = mm_get_kex(&m);
1320         }
1321
1322         blob = buffer_get_string(&m, &bloblen);
1323         current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen);
1324         xfree(blob);
1325
1326         debug3("%s: Waiting for second key", __FUNCTION__);
1327         blob = buffer_get_string(&m, &bloblen);
1328         current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen);
1329         xfree(blob);
1330
1331         /* Now get sequence numbers for the packets */
1332         packet_set_seqnr(MODE_OUT, buffer_get_int(&m));
1333         packet_set_seqnr(MODE_IN, buffer_get_int(&m));
1334
1335  skip:
1336         /* Get the key context */
1337         child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen);
1338         child_state.keyin  = buffer_get_string(&m, &child_state.keyinlen);
1339
1340         debug3("%s: Getting compression state", __FUNCTION__);
1341         /* Get compression state */
1342         p = buffer_get_string(&m, &plen);
1343         if (plen != sizeof(child_state.outgoing))
1344                 fatal("%s: bad request size", __FUNCTION__);
1345         memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing));
1346         xfree(p);
1347
1348         p = buffer_get_string(&m, &plen);
1349         if (plen != sizeof(child_state.incoming))
1350                 fatal("%s: bad request size", __FUNCTION__);
1351         memcpy(&child_state.incoming, p, sizeof(child_state.incoming));
1352         xfree(p);
1353
1354         /* Network I/O buffers */
1355         debug3("%s: Getting Network I/O buffers", __FUNCTION__);
1356         child_state.input = buffer_get_string(&m, &child_state.ilen);
1357         child_state.output = buffer_get_string(&m, &child_state.olen);
1358
1359         buffer_free(&m);
1360 }
1361
1362
1363 /* Allocation functions for zlib */
1364 void *
1365 mm_zalloc(struct mm_master *mm, u_int ncount, u_int size)
1366 {
1367         void *address;
1368
1369         address = mm_malloc(mm, size * ncount);
1370
1371         return (address);
1372 }
1373
1374 void
1375 mm_zfree(struct mm_master *mm, void *address)
1376 {
1377         mm_free(mm, address);
1378 }
1379
1380 void
1381 mm_init_compression(struct mm_master *mm)
1382 {
1383         outgoing_stream.zalloc = (alloc_func)mm_zalloc;
1384         outgoing_stream.zfree = (free_func)mm_zfree;
1385         outgoing_stream.opaque = mm;
1386
1387         incoming_stream.zalloc = (alloc_func)mm_zalloc;
1388         incoming_stream.zfree = (free_func)mm_zfree;
1389         incoming_stream.opaque = mm;
1390 }
1391
1392 /* XXX */
1393
1394 #define FD_CLOSEONEXEC(x) do { \
1395         if (fcntl(x, F_SETFD, 1) == -1) \
1396                 fatal("fcntl(%d, F_SETFD)", x); \
1397 } while (0)
1398
1399 static void
1400 monitor_socketpair(int *pair)
1401 {
1402         if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1)
1403                 fatal("%s: socketpair", __FUNCTION__);
1404         FD_CLOSEONEXEC(pair[0]);
1405         FD_CLOSEONEXEC(pair[1]);
1406 }
1407
1408 #define MM_MEMSIZE      65536
1409
1410 struct monitor *
1411 monitor_init(void)
1412 {
1413         struct monitor *mon;
1414         int pair[2];
1415
1416         mon = xmalloc(sizeof(*mon));
1417
1418         monitor_socketpair(pair);
1419
1420         mon->m_recvfd = pair[0];
1421         mon->m_sendfd = pair[1];
1422
1423         /* Used to share zlib space across processes */
1424         mon->m_zback = mm_create(NULL, MM_MEMSIZE);
1425         mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE);
1426
1427         /* Compression needs to share state across borders */
1428         mm_init_compression(mon->m_zlib);
1429
1430         return mon;
1431 }
1432
1433 void
1434 monitor_reinit(struct monitor *mon)
1435 {
1436         int pair[2];
1437
1438         monitor_socketpair(pair);
1439
1440         mon->m_recvfd = pair[0];
1441         mon->m_sendfd = pair[1];
1442 }
This page took 0.146087 seconds and 5 git commands to generate.