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