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