monitor.c revision 1.4
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" 28RCSID("$OpenBSD: monitor.c,v 1.4 2002/03/19 14:27:39 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 */ 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 116static Authctxt *authctxt; 117static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ 118 119/* local state for key verify */ 120static u_char *key_blob = NULL; 121static u_int key_bloblen = 0; 122static int key_blobtype = MM_NOKEY; 123static u_char *hostbased_cuser = NULL; 124static u_char *hostbased_chost = NULL; 125static char *auth_method = "unknown"; 126 127struct 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 141struct 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 160struct 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 169struct 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 189struct 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 196struct mon_table *mon_dispatch; 197 198/* Specifies if a certain message is allowed at the moment */ 199 200static void 201monitor_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 213static void 214monitor_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 227Authctxt * 228monitor_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 280void 281monitor_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 304void 305monitor_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 311int 312monitor_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\n", __FUNCTION__, type); 353 354 /* NOTREACHED */ 355 return (-1); 356} 357 358/* allowed key state */ 359static int 360monitor_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 369static void 370monitor_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 386int 387mm_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 421int 422mm_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 461int 462mm_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 buffer_put_cstring(m, pwent->pw_class); 498 buffer_put_cstring(m, pwent->pw_dir); 499 buffer_put_cstring(m, pwent->pw_shell); 500 501 out: 502 debug3("%s: sending MONITOR_ANS_PWNAM: %d", __FUNCTION__, allowed); 503 mm_request_send(socket, MONITOR_ANS_PWNAM, m); 504 505 /* For SSHv1 allow authentication now */ 506 if (!compat20) 507 monitor_permit_authentications(1); 508 else 509 /* Allow service/style information on the auth context */ 510 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); 511 512 513 return (0); 514} 515 516int 517mm_answer_authserv(int socket, Buffer *m) 518{ 519 monitor_permit_authentications(1); 520 521 authctxt->service = buffer_get_string(m, NULL); 522 authctxt->style = buffer_get_string(m, NULL); 523 if (strlen(authctxt->style) == 0) { 524 xfree(authctxt->style); 525 authctxt->style = NULL; 526 } 527 528 debug3("%s: service=%s, style=%s", 529 __FUNCTION__, authctxt->service, authctxt->style); 530 531 return (0); 532} 533 534int 535mm_answer_authpassword(int socket, Buffer *m) 536{ 537 static int call_count; 538 char *passwd; 539 int authenticated, plen; 540 541 passwd = buffer_get_string(m, &plen); 542 /* Only authenticate if the context is valid */ 543 authenticated = authctxt->valid && auth_password(authctxt, passwd); 544 memset(passwd, 0, strlen(passwd)); 545 xfree(passwd); 546 547 buffer_clear(m); 548 buffer_put_int(m, authenticated); 549 550 debug3("%s: sending result %d", __FUNCTION__, authenticated); 551 mm_request_send(socket, MONITOR_ANS_AUTHPASSWORD, m); 552 553 call_count++; 554 if (plen == 0 && call_count == 1) 555 auth_method = "none"; 556 else 557 auth_method = "password"; 558 559 /* Causes monitor loop to terminate if authenticated */ 560 return (authenticated); 561} 562 563#ifdef BSD_AUTH 564int 565mm_answer_bsdauthquery(int socket, Buffer *m) 566{ 567 char *name, *infotxt; 568 u_int numprompts; 569 u_int *echo_on; 570 char **prompts; 571 int res; 572 573 res = bsdauth_query(authctxt, &name, &infotxt, &numprompts, 574 &prompts, &echo_on); 575 576 buffer_clear(m); 577 buffer_put_int(m, res); 578 if (res != -1) 579 buffer_put_cstring(m, prompts[0]); 580 581 debug3("%s: sending challenge res: %d", __FUNCTION__, res); 582 mm_request_send(socket, MONITOR_ANS_BSDAUTHQUERY, m); 583 584 if (res != -1) { 585 xfree(name); 586 xfree(infotxt); 587 xfree(prompts); 588 xfree(echo_on); 589 } 590 591 return (0); 592} 593 594int 595mm_answer_bsdauthrespond(int socket, Buffer *m) 596{ 597 char *response; 598 int authok; 599 600 if (authctxt->as == 0) 601 fatal("%s: no bsd auth session", __FUNCTION__); 602 603 response = buffer_get_string(m, NULL); 604 authok = auth_userresponse(authctxt->as, response, 0); 605 authctxt->as = NULL; 606 debug3("%s: <%s> = <%d>", __FUNCTION__, response, authok); 607 xfree(response); 608 609 buffer_clear(m); 610 buffer_put_int(m, authok); 611 612 debug3("%s: sending authenticated: %d", __FUNCTION__, authok); 613 mm_request_send(socket, MONITOR_ANS_BSDAUTHRESPOND, m); 614 615 auth_method = "bsdauth"; 616 617 return (authok != 0); 618} 619#endif 620 621#ifdef SKEY 622int 623mm_answer_skeyquery(int socket, Buffer *m) 624{ 625 struct skey skey; 626 char challenge[1024]; 627 int res; 628 629 res = skeychallenge(&skey, authctxt->user, challenge); 630 631 buffer_clear(m); 632 buffer_put_int(m, res); 633 if (res != -1) 634 buffer_put_cstring(m, challenge); 635 636 debug3("%s: sending challenge res: %d", __FUNCTION__, res); 637 mm_request_send(socket, MONITOR_ANS_SKEYQUERY, m); 638 639 return (0); 640} 641 642int 643mm_answer_skeyrespond(int socket, Buffer *m) 644{ 645 char *response; 646 int authok; 647 648 response = buffer_get_string(m, NULL); 649 650 authok = (authctxt->valid && 651 skey_haskey(authctxt->pw->pw_name) == 0 && 652 skey_passcheck(authctxt->pw->pw_name, response) != -1); 653 654 xfree(response); 655 656 buffer_clear(m); 657 buffer_put_int(m, authok); 658 659 debug3("%s: sending authenticated: %d", __FUNCTION__, authok); 660 mm_request_send(socket, MONITOR_ANS_SKEYRESPOND, m); 661 662 auth_method = "skey"; 663 664 return (authok != 0); 665} 666#endif 667 668static void 669mm_append_debug(Buffer *m) 670{ 671 if (auth_debug_init && buffer_len(&auth_debug)) { 672 debug3("%s: Appending debug messages for child", __FUNCTION__); 673 buffer_append(m, buffer_ptr(&auth_debug), 674 buffer_len(&auth_debug)); 675 buffer_clear(&auth_debug); 676 } 677} 678 679int 680mm_answer_keyallowed(int socket, Buffer *m) 681{ 682 Key *key; 683 u_char *cuser, *chost, *blob; 684 u_int bloblen; 685 enum mm_keytype type = 0; 686 int allowed = 0; 687 688 debug3("%s entering", __FUNCTION__); 689 690 type = buffer_get_int(m); 691 cuser = buffer_get_string(m, NULL); 692 chost = buffer_get_string(m, NULL); 693 blob = buffer_get_string(m, &bloblen); 694 695 key = key_from_blob(blob, bloblen); 696 697 if ((compat20 && type == MM_RSAHOSTKEY) || 698 (!compat20 && type != MM_RSAHOSTKEY)) 699 fatal("%s: key type and protocol mismatch", __FUNCTION__); 700 701 debug3("%s: key_from_blob: %p", __FUNCTION__, key); 702 703 if (key != NULL && authctxt->pw != NULL) { 704 switch(type) { 705 case MM_USERKEY: 706 allowed = user_key_allowed(authctxt->pw, key); 707 break; 708 case MM_HOSTKEY: 709 allowed = hostbased_key_allowed(authctxt->pw, 710 cuser, chost, key); 711 break; 712 case MM_RSAHOSTKEY: 713 key->type = KEY_RSA1; /* XXX */ 714 allowed = auth_rhosts_rsa_key_allowed(authctxt->pw, 715 cuser, chost, key); 716 break; 717 default: 718 fatal("%s: unknown key type %d", __FUNCTION__, type); 719 break; 720 } 721 key_free(key); 722 } 723 724 /* clear temporarily storage (used by verify) */ 725 monitor_reset_key_state(); 726 727 if (allowed) { 728 /* Save temporarily for comparison in verify */ 729 key_blob = blob; 730 key_bloblen = bloblen; 731 key_blobtype = type; 732 hostbased_cuser = cuser; 733 hostbased_chost = chost; 734 } 735 736 debug3("%s: key %p is %s", 737 __FUNCTION__, key, allowed ? "allowed" : "disallowed"); 738 739 buffer_clear(m); 740 buffer_put_int(m, allowed); 741 742 mm_append_debug(m); 743 744 mm_request_send(socket, MONITOR_ANS_KEYALLOWED, m); 745 746 if (type == MM_RSAHOSTKEY) 747 monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); 748 749 return (0); 750} 751 752static int 753monitor_valid_userblob(u_char *data, u_int datalen) 754{ 755 Buffer b; 756 u_char *p; 757 u_int len; 758 int fail = 0; 759 int session_id2_len = 20 /*XXX should get from [net] */; 760 761 buffer_init(&b); 762 buffer_append(&b, data, datalen); 763 764 if (datafellows & SSH_OLD_SESSIONID) { 765 buffer_consume(&b, session_id2_len); 766 } else { 767 xfree(buffer_get_string(&b, &len)); 768 if (len != session_id2_len) 769 fail++; 770 } 771 if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) 772 fail++; 773 p = buffer_get_string(&b, NULL); 774 if (strcmp(authctxt->user, p) != 0) { 775 log("wrong user name passed to monitor: expected %s != %.100s", 776 authctxt->user, p); 777 fail++; 778 } 779 xfree(p); 780 buffer_skip_string(&b); 781 if (datafellows & SSH_BUG_PKAUTH) { 782 if (!buffer_get_char(&b)) 783 fail++; 784 } else { 785 p = buffer_get_string(&b, NULL); 786 if (strcmp("publickey", p) != 0) 787 fail++; 788 xfree(p); 789 if (!buffer_get_char(&b)) 790 fail++; 791 buffer_skip_string(&b); 792 } 793 buffer_skip_string(&b); 794 if (buffer_len(&b) != 0) 795 fail++; 796 buffer_free(&b); 797 return (fail == 0); 798} 799 800static int 801monitor_valid_hostbasedblob(u_char *data, u_int datalen, u_char *cuser, 802 u_char *chost) 803{ 804 Buffer b; 805 u_char *p; 806 u_int len; 807 int fail = 0; 808 int session_id2_len = 20 /*XXX should get from [net] */; 809 810 buffer_init(&b); 811 buffer_append(&b, data, datalen); 812 813 xfree(buffer_get_string(&b, &len)); 814 if (len != session_id2_len) 815 fail++; 816 if (buffer_get_char(&b) != SSH2_MSG_USERAUTH_REQUEST) 817 fail++; 818 p = buffer_get_string(&b, NULL); 819 if (strcmp(authctxt->user, p) != 0) { 820 log("wrong user name passed to monitor: expected %s != %.100s", 821 authctxt->user, p); 822 fail++; 823 } 824 xfree(p); 825 buffer_skip_string(&b); /* service */ 826 p = buffer_get_string(&b, NULL); 827 if (strcmp(p, "hostbased") != 0) 828 fail++; 829 xfree(p); 830 buffer_skip_string(&b); /* pkalg */ 831 buffer_skip_string(&b); /* pkblob */ 832 833 /* verify client host, strip trailing dot if necessary */ 834 p = buffer_get_string(&b, NULL); 835 if (((len = strlen(p)) > 0) && p[len - 1] == '.') 836 p[len - 1] = '\0'; 837 if (strcmp(p, chost) != 0) 838 fail++; 839 xfree(p); 840 841 /* verify client user */ 842 p = buffer_get_string(&b, NULL); 843 if (strcmp(p, cuser) != 0) 844 fail++; 845 xfree(p); 846 847 if (buffer_len(&b) != 0) 848 fail++; 849 buffer_free(&b); 850 return (fail == 0); 851} 852 853int 854mm_answer_keyverify(int socket, Buffer *m) 855{ 856 Key *key; 857 u_char *signature, *data, *blob; 858 u_int signaturelen, datalen, bloblen; 859 int verified = 0; 860 int valid_data = 0; 861 862 blob = buffer_get_string(m, &bloblen); 863 signature = buffer_get_string(m, &signaturelen); 864 data = buffer_get_string(m, &datalen); 865 866 if (hostbased_cuser == NULL || hostbased_chost == NULL || 867 monitor_allowed_key(blob, bloblen) == NULL) 868 fatal("%s: bad key, not previously allowed", __FUNCTION__); 869 870 key = key_from_blob(blob, bloblen); 871 if (key == NULL) 872 fatal("%s: bad public key blob", __FUNCTION__); 873 874 switch (key_blobtype) { 875 case MM_USERKEY: 876 valid_data = monitor_valid_userblob(data, datalen); 877 break; 878 case MM_HOSTKEY: 879 valid_data = monitor_valid_hostbasedblob(data, datalen, 880 hostbased_cuser, hostbased_chost); 881 break; 882 default: 883 valid_data = 0; 884 break; 885 } 886 if (!valid_data) 887 fatal("%s: bad signature data blob", __FUNCTION__); 888 889 verified = key_verify(key, signature, signaturelen, data, datalen); 890 debug3("%s: key %p signature %s", 891 __FUNCTION__, key, verified ? "verified" : "unverified"); 892 893 key_free(key); 894 xfree(blob); 895 xfree(signature); 896 xfree(data); 897 898 monitor_reset_key_state(); 899 900 buffer_clear(m); 901 buffer_put_int(m, verified); 902 mm_request_send(socket, MONITOR_ANS_KEYVERIFY, m); 903 904 auth_method = "publickey"; 905 906 return (verified); 907} 908 909static void 910mm_record_login(Session *s, struct passwd *pw) 911{ 912 socklen_t fromlen; 913 struct sockaddr_storage from; 914 915 /* 916 * Get IP address of client. If the connection is not a socket, let 917 * the address be 0.0.0.0. 918 */ 919 memset(&from, 0, sizeof(from)); 920 if (packet_connection_is_on_socket()) { 921 fromlen = sizeof(from); 922 if (getpeername(packet_get_connection_in(), 923 (struct sockaddr *) & from, &fromlen) < 0) { 924 debug("getpeername: %.100s", strerror(errno)); 925 fatal_cleanup(); 926 } 927 } 928 /* Record that there was a login on that tty from the remote host. */ 929 record_login(s->pid, s->tty, pw->pw_name, pw->pw_uid, 930 get_remote_name_or_ip(utmp_len, options.verify_reverse_mapping), 931 (struct sockaddr *)&from); 932} 933 934static void 935mm_session_close(Session *s) 936{ 937 debug3("%s: session %d pid %d", __FUNCTION__, s->self, s->pid); 938 if (s->ttyfd != -1) { 939 debug3("%s: tty %s ptyfd %d", __FUNCTION__, s->tty, s->ptyfd); 940 fatal_remove_cleanup(session_pty_cleanup2, (void *)s); 941 session_pty_cleanup2(s); 942 } 943 s->used = 0; 944} 945 946int 947mm_answer_pty(int socket, Buffer *m) 948{ 949 extern struct monitor *monitor; 950 Session *s; 951 int res, fd0; 952 953 debug3("%s entering", __FUNCTION__); 954 955 buffer_clear(m); 956 s = session_new(); 957 if (s == NULL) 958 goto error; 959 s->authctxt = authctxt; 960 s->pw = authctxt->pw; 961 s->pid = monitor->m_pid; 962 res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); 963 if (res == 0) 964 goto error; 965 fatal_add_cleanup(session_pty_cleanup2, (void *)s); 966 pty_setowner(authctxt->pw, s->tty); 967 968 buffer_put_int(m, 1); 969 buffer_put_cstring(m, s->tty); 970 mm_request_send(socket, MONITOR_ANS_PTY, m); 971 972 mm_send_fd(socket, s->ptyfd); 973 mm_send_fd(socket, s->ttyfd); 974 975 /* We need to trick ttyslot */ 976 if (dup2(s->ttyfd, 0) == -1) 977 fatal("%s: dup2", __FUNCTION__); 978 979 mm_record_login(s, authctxt->pw); 980 981 /* Now we can close the file descriptor again */ 982 close(0); 983 984 /* make sure nothing uses fd 0 */ 985 if ((fd0 = open(_PATH_DEVNULL, O_RDONLY)) < 0) 986 fatal("%s: open(/dev/null): %s", __FUNCTION__, strerror(errno)); 987 if (fd0 != 0) 988 error("%s: fd0 %d != 0", __FUNCTION__, fd0); 989 990 /* slave is not needed */ 991 close(s->ttyfd); 992 s->ttyfd = s->ptyfd; 993 /* no need to dup() because nobody closes ptyfd */ 994 s->ptymaster = s->ptyfd; 995 996 debug3("%s: tty %s ptyfd %d", __FUNCTION__, s->tty, s->ttyfd); 997 998 return (0); 999 1000 error: 1001 if (s != NULL) 1002 mm_session_close(s); 1003 buffer_put_int(m, 0); 1004 mm_request_send(socket, MONITOR_ANS_PTY, m); 1005 return (0); 1006} 1007 1008int 1009mm_answer_pty_cleanup(int socket, Buffer *m) 1010{ 1011 Session *s; 1012 char *tty; 1013 1014 debug3("%s entering", __FUNCTION__); 1015 1016 tty = buffer_get_string(m, NULL); 1017 if ((s = session_by_tty(tty)) != NULL) 1018 mm_session_close(s); 1019 buffer_clear(m); 1020 xfree(tty); 1021 return (0); 1022} 1023 1024int 1025mm_answer_sesskey(int socket, Buffer *m) 1026{ 1027 BIGNUM *p; 1028 int rsafail; 1029 1030 /* Turn off permissions */ 1031 monitor_permit(mon_dispatch, MONITOR_REQ_SESSKEY, 1); 1032 1033 if ((p = BN_new()) == NULL) 1034 fatal("%s: BN_new", __FUNCTION__); 1035 1036 buffer_get_bignum2(m, p); 1037 1038 rsafail = ssh1_session_key(p); 1039 1040 buffer_clear(m); 1041 buffer_put_int(m, rsafail); 1042 buffer_put_bignum2(m, p); 1043 1044 BN_clear_free(p); 1045 1046 mm_request_send(socket, MONITOR_ANS_SESSKEY, m); 1047 1048 /* Turn on permissions for sessid passing */ 1049 monitor_permit(mon_dispatch, MONITOR_REQ_SESSID, 1); 1050 1051 return (0); 1052} 1053 1054int 1055mm_answer_sessid(int socket, Buffer *m) 1056{ 1057 int i; 1058 1059 debug3("%s entering", __FUNCTION__); 1060 1061 if (buffer_len(m) != 16) 1062 fatal("%s: bad ssh1 session id", __FUNCTION__); 1063 for (i = 0; i < 16; i++) 1064 session_id[i] = buffer_get_char(m); 1065 1066 /* Turn on permissions for getpwnam */ 1067 monitor_permit(mon_dispatch, MONITOR_REQ_PWNAM, 1); 1068 1069 return (0); 1070} 1071 1072int 1073mm_answer_rsa_keyallowed(int socket, Buffer *m) 1074{ 1075 BIGNUM *client_n; 1076 Key *key = NULL; 1077 u_char *blob = NULL; 1078 u_int blen = 0; 1079 int allowed = 0; 1080 1081 debug3("%s entering", __FUNCTION__); 1082 1083 if (authctxt->valid) { 1084 if ((client_n = BN_new()) == NULL) 1085 fatal("%s: BN_new", __FUNCTION__); 1086 buffer_get_bignum2(m, client_n); 1087 allowed = auth_rsa_key_allowed(authctxt->pw, client_n, &key); 1088 BN_clear_free(client_n); 1089 } 1090 buffer_clear(m); 1091 buffer_put_int(m, allowed); 1092 1093 /* clear temporarily storage (used by generate challenge) */ 1094 monitor_reset_key_state(); 1095 1096 if (allowed && key != NULL) { 1097 key->type = KEY_RSA; /* cheat for key_to_blob */ 1098 if (key_to_blob(key, &blob, &blen) == 0) 1099 fatal("%s: key_to_blob failed", __FUNCTION__); 1100 buffer_put_string(m, blob, blen); 1101 1102 /* Save temporarily for comparison in verify */ 1103 key_blob = blob; 1104 key_bloblen = blen; 1105 key_blobtype = MM_RSAUSERKEY; 1106 key_free(key); 1107 } 1108 1109 mm_append_debug(m); 1110 1111 mm_request_send(socket, MONITOR_ANS_RSAKEYALLOWED, m); 1112 1113 monitor_permit(mon_dispatch, MONITOR_REQ_RSACHALLENGE, allowed); 1114 monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 0); 1115 return (0); 1116} 1117 1118int 1119mm_answer_rsa_challenge(int socket, Buffer *m) 1120{ 1121 Key *key = NULL; 1122 u_char *blob; 1123 u_int blen; 1124 1125 debug3("%s entering", __FUNCTION__); 1126 1127 if (!authctxt->valid) 1128 fatal("%s: authctxt not valid", __FUNCTION__); 1129 blob = buffer_get_string(m, &blen); 1130 if (!monitor_allowed_key(blob, blen)) 1131 fatal("%s: bad key, not previously allowed", __FUNCTION__); 1132 if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) 1133 fatal("%s: key type mismatch", __FUNCTION__); 1134 if ((key = key_from_blob(blob, blen)) == NULL) 1135 fatal("%s: received bad key", __FUNCTION__); 1136 1137 if (ssh1_challenge) 1138 BN_clear_free(ssh1_challenge); 1139 ssh1_challenge = auth_rsa_generate_challenge(key); 1140 1141 buffer_clear(m); 1142 buffer_put_bignum2(m, ssh1_challenge); 1143 1144 debug3("%s sending reply", __FUNCTION__); 1145 mm_request_send(socket, MONITOR_ANS_RSACHALLENGE, m); 1146 1147 1148 monitor_permit(mon_dispatch, MONITOR_REQ_RSARESPONSE, 1); 1149 return (0); 1150} 1151 1152int 1153mm_answer_rsa_response(int socket, Buffer *m) 1154{ 1155 Key *key = NULL; 1156 u_char *blob, *response; 1157 u_int blen, len; 1158 int success; 1159 1160 debug3("%s entering", __FUNCTION__); 1161 1162 if (!authctxt->valid) 1163 fatal("%s: authctxt not valid", __FUNCTION__); 1164 if (ssh1_challenge == NULL) 1165 fatal("%s: no ssh1_challenge", __FUNCTION__); 1166 1167 blob = buffer_get_string(m, &blen); 1168 if (!monitor_allowed_key(blob, blen)) 1169 fatal("%s: bad key, not previously allowed", __FUNCTION__); 1170 if (key_blobtype != MM_RSAUSERKEY && key_blobtype != MM_RSAHOSTKEY) 1171 fatal("%s: key type mismatch: %d", __FUNCTION__, key_blobtype); 1172 if ((key = key_from_blob(blob, blen)) == NULL) 1173 fatal("%s: received bad key", __FUNCTION__); 1174 response = buffer_get_string(m, &len); 1175 if (len != 16) 1176 fatal("%s: received bad response to challenge", __FUNCTION__); 1177 success = auth_rsa_verify_response(key, ssh1_challenge, response); 1178 1179 key_free(key); 1180 xfree(response); 1181 1182 auth_method = key_blobtype == MM_RSAUSERKEY ? "rsa" : "rhosts-rsa"; 1183 1184 /* reset state */ 1185 BN_clear_free(ssh1_challenge); 1186 ssh1_challenge = NULL; 1187 monitor_reset_key_state(); 1188 1189 buffer_clear(m); 1190 buffer_put_int(m, success); 1191 mm_request_send(socket, MONITOR_ANS_RSARESPONSE, m); 1192 1193 return (success); 1194} 1195 1196int 1197mm_answer_term(int socket, Buffer *req) 1198{ 1199 extern struct monitor *monitor; 1200 int res, status; 1201 1202 debug3("%s: tearing down sessions", __FUNCTION__); 1203 1204 /* The child is terminating */ 1205 session_destroy_all(&mm_session_close); 1206 1207 if (waitpid(monitor->m_pid, &status, 0) == -1) 1208 exit(1); 1209 1210 res = WIFEXITED(status) ? WEXITSTATUS(status) : 1; 1211 1212 /* Terminate process */ 1213 exit (res); 1214} 1215 1216void 1217monitor_apply_keystate(struct monitor *monitor) 1218{ 1219 if (compat20) { 1220 set_newkeys(MODE_IN); 1221 set_newkeys(MODE_OUT); 1222 } else { 1223 u_char key[256]; 1224 packet_set_protocol_flags(child_state.ssh1protoflags); 1225 packet_set_encryption_key(key, SSH_SESSION_KEY_LENGTH, 1226 child_state.ssh1cipher); 1227 } 1228 1229 packet_set_keycontext(MODE_OUT, child_state.keyout); 1230 xfree(child_state.keyout); 1231 packet_set_keycontext(MODE_IN, child_state.keyin); 1232 xfree(child_state.keyin); 1233 1234 if (!compat20) { 1235 packet_set_iv(MODE_OUT, child_state.ivout); 1236 xfree(child_state.ivout); 1237 packet_set_iv(MODE_IN, child_state.ivin); 1238 xfree(child_state.ivin); 1239 } 1240 1241 memcpy(&incoming_stream, &child_state.incoming, 1242 sizeof(incoming_stream)); 1243 memcpy(&outgoing_stream, &child_state.outgoing, 1244 sizeof(outgoing_stream)); 1245 1246 /* Update with new address */ 1247 mm_init_compression(monitor->m_zlib); 1248 1249 /* Network I/O buffers */ 1250 /* XXX inefficient for large buffers, need: buffer_init_from_string */ 1251 buffer_clear(&input); 1252 buffer_append(&input, child_state.input, child_state.ilen); 1253 memset(child_state.input, 0, child_state.ilen); 1254 xfree(child_state.input); 1255 1256 buffer_clear(&output); 1257 buffer_append(&output, child_state.output, child_state.olen); 1258 memset(child_state.output, 0, child_state.olen); 1259 xfree(child_state.output); 1260} 1261 1262static Kex * 1263mm_get_kex(Buffer *m) 1264{ 1265 Kex *kex; 1266 void *blob; 1267 u_int bloblen; 1268 1269 kex = xmalloc(sizeof(*kex)); 1270 memset(kex, 0, sizeof(*kex)); 1271 kex->session_id = buffer_get_string(m, &kex->session_id_len); 1272 kex->we_need = buffer_get_int(m); 1273 kex->server = 1; 1274 kex->hostkey_type = buffer_get_int(m); 1275 kex->kex_type = buffer_get_int(m); 1276 blob = buffer_get_string(m, &bloblen); 1277 buffer_init(&kex->my); 1278 buffer_append(&kex->my, blob, bloblen); 1279 xfree(blob); 1280 blob = buffer_get_string(m, &bloblen); 1281 buffer_init(&kex->peer); 1282 buffer_append(&kex->peer, blob, bloblen); 1283 xfree(blob); 1284 kex->done = 1; 1285 kex->flags = buffer_get_int(m); 1286 kex->client_version_string = buffer_get_string(m, NULL); 1287 kex->server_version_string = buffer_get_string(m, NULL); 1288 kex->load_host_key=&get_hostkey_by_type; 1289 kex->host_key_index=&get_hostkey_index; 1290 1291 return (kex); 1292} 1293 1294/* This function requries careful sanity checking */ 1295 1296void 1297mm_get_keystate(struct monitor *monitor) 1298{ 1299 Buffer m; 1300 u_char *blob, *p; 1301 u_int bloblen, plen; 1302 1303 debug3("%s: Waiting for new keys", __FUNCTION__); 1304 1305 buffer_init(&m); 1306 mm_request_receive_expect(monitor->m_sendfd, MONITOR_REQ_KEYEXPORT, &m); 1307 if (!compat20) { 1308 child_state.ssh1protoflags = buffer_get_int(&m); 1309 child_state.ssh1cipher = buffer_get_int(&m); 1310 child_state.ivout = buffer_get_string(&m, 1311 &child_state.ivoutlen); 1312 child_state.ivin = buffer_get_string(&m, &child_state.ivinlen); 1313 goto skip; 1314 } else { 1315 /* Get the Kex for rekeying */ 1316 *monitor->m_pkex = mm_get_kex(&m); 1317 } 1318 1319 blob = buffer_get_string(&m, &bloblen); 1320 current_keys[MODE_OUT] = mm_newkeys_from_blob(blob, bloblen); 1321 xfree(blob); 1322 1323 debug3("%s: Waiting for second key", __FUNCTION__); 1324 blob = buffer_get_string(&m, &bloblen); 1325 current_keys[MODE_IN] = mm_newkeys_from_blob(blob, bloblen); 1326 xfree(blob); 1327 1328 /* Now get sequence numbers for the packets */ 1329 packet_set_seqnr(MODE_OUT, buffer_get_int(&m)); 1330 packet_set_seqnr(MODE_IN, buffer_get_int(&m)); 1331 1332 skip: 1333 /* Get the key context */ 1334 child_state.keyout = buffer_get_string(&m, &child_state.keyoutlen); 1335 child_state.keyin = buffer_get_string(&m, &child_state.keyinlen); 1336 1337 debug3("%s: Getting compression state", __FUNCTION__); 1338 /* Get compression state */ 1339 p = buffer_get_string(&m, &plen); 1340 if (plen != sizeof(child_state.outgoing)) 1341 fatal("%s: bad request size", __FUNCTION__); 1342 memcpy(&child_state.outgoing, p, sizeof(child_state.outgoing)); 1343 xfree(p); 1344 1345 p = buffer_get_string(&m, &plen); 1346 if (plen != sizeof(child_state.incoming)) 1347 fatal("%s: bad request size", __FUNCTION__); 1348 memcpy(&child_state.incoming, p, sizeof(child_state.incoming)); 1349 xfree(p); 1350 1351 /* Network I/O buffers */ 1352 debug3("%s: Getting Network I/O buffers", __FUNCTION__); 1353 child_state.input = buffer_get_string(&m, &child_state.ilen); 1354 child_state.output = buffer_get_string(&m, &child_state.olen); 1355 1356 buffer_free(&m); 1357} 1358 1359 1360/* Allocation functions for zlib */ 1361void * 1362mm_zalloc(struct mm_master *mm, u_int ncount, u_int size) 1363{ 1364 void *address; 1365 1366 address = mm_malloc(mm, size * ncount); 1367 1368 return (address); 1369} 1370 1371void 1372mm_zfree(struct mm_master *mm, void *address) 1373{ 1374 mm_free(mm, address); 1375} 1376 1377void 1378mm_init_compression(struct mm_master *mm) 1379{ 1380 outgoing_stream.zalloc = (alloc_func)mm_zalloc; 1381 outgoing_stream.zfree = (free_func)mm_zfree; 1382 outgoing_stream.opaque = mm; 1383 1384 incoming_stream.zalloc = (alloc_func)mm_zalloc; 1385 incoming_stream.zfree = (free_func)mm_zfree; 1386 incoming_stream.opaque = mm; 1387} 1388 1389/* XXX */ 1390 1391#define FD_CLOSEONEXEC(x) do { \ 1392 if (fcntl(x, F_SETFD, 1) == -1) \ 1393 fatal("fcntl(%d, F_SETFD)", x); \ 1394} while (0) 1395 1396static void 1397monitor_socketpair(int *pair) 1398{ 1399 if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair) == -1) 1400 fatal("%s: socketpair", __FUNCTION__); 1401 FD_CLOSEONEXEC(pair[0]); 1402 FD_CLOSEONEXEC(pair[1]); 1403} 1404 1405#define MM_MEMSIZE 65536 1406 1407struct monitor * 1408monitor_init(void) 1409{ 1410 struct monitor *mon; 1411 int pair[2]; 1412 1413 mon = xmalloc(sizeof(*mon)); 1414 1415 monitor_socketpair(pair); 1416 1417 mon->m_recvfd = pair[0]; 1418 mon->m_sendfd = pair[1]; 1419 1420 /* Used to share zlib space across processes */ 1421 mon->m_zback = mm_create(NULL, MM_MEMSIZE); 1422 mon->m_zlib = mm_create(mon->m_zback, 20 * MM_MEMSIZE); 1423 1424 /* Compression needs to share state across borders */ 1425 mm_init_compression(mon->m_zlib); 1426 1427 return mon; 1428} 1429 1430void 1431monitor_reinit(struct monitor *mon) 1432{ 1433 int pair[2]; 1434 1435 monitor_socketpair(pair); 1436 1437 mon->m_recvfd = pair[0]; 1438 mon->m_sendfd = pair[1]; 1439} 1440