1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 22 * Use is subject to license terms. 23 */ 24 25 #pragma ident "%Z%%M% %I% %E% SMI" 26 27 #include "includes.h" 28 #include "atomicio.h" 29 #include "auth.h" 30 #include "bufaux.h" 31 #include "buffer.h" 32 #include "cipher.h" 33 #include "compat.h" 34 #include "dispatch.h" 35 #include "getput.h" 36 #include "kex.h" 37 #include "log.h" 38 #include "mac.h" 39 #include "packet.h" 40 #include "uidswap.h" 41 #include "ssh2.h" 42 #include "sshlogin.h" 43 #include "xmalloc.h" 44 #include "altprivsep.h" 45 #include <fcntl.h> 46 #include <sys/types.h> 47 #include <sys/types.h> 48 #include <sys/stat.h> 49 #include <sys/socket.h> 50 51 extern Kex *xxx_kex; 52 53 static Buffer to_monitor; 54 static Buffer from_monitor; 55 56 /* 57 * Sun's Alternative Privilege Separation basics: 58 * 59 * Abstract 60 * -------- 61 * 62 * sshd(1M) fork()s and drops privs in the child while retaining privs 63 * in the parent (a.k.a., the monitor). The unprivileged sshd and the 64 * monitor talk over a pipe using a simple protocol. 65 * 66 * The monitor protocol is all about having the monitor carry out the 67 * only operations that require privileges OR access to privileged 68 * resources. These are: utmpx/wtmpx record keeping, auditing, and 69 * SSHv2 re-keying. 70 * 71 * Re-Keying 72 * --------- 73 * 74 * Re-keying is the only protocol version specific aspect of sshd in 75 * which the monitor gets involved. 76 * 77 * The monitor processes all SSHv2 re-key protocol packets, but the 78 * unprivileged sshd process does the transport layer crypto for those 79 * packets. 80 * 81 * The monitor and its unprivileged sshd child process treat 82 * SSH_MSG_NEWKEYS SSH2 messages specially: a) the monitor does not call 83 * set_newkeys(), but b) the child asks the monitor for the set of 84 * negotiated algorithms, key, IV and what not for the relevant 85 * transport direction and then calls set_newkeys(). 86 * 87 * Monitor Protocol 88 * ---------------- 89 * 90 * Monitor IPC message formats are similar to SSHv2 messages, minus 91 * compression, encryption, padding and MACs: 92 * 93 * - 4 octet message length 94 * - message data 95 * - 1 octet message type 96 * - message data 97 * 98 * In broad strokes: 99 * 100 * - IPC: pipe, exit(2)/wait4(2) 101 * 102 * - threads: the monitor and child are single-threaded 103 * 104 * - monitor main loop: a variant of server_loop2(), for re-keying only 105 * - unpriv child main loop: server_loop2(), as usual 106 * 107 * - protocol: 108 * - key exchange packets are always forwarded as is to the monitor 109 * - newkeys, record_login(), record_logout() are special packets 110 * using the packet type range reserved for local extensions 111 * 112 * - the child drops privs and runs like a normal sshd, except that it 113 * sets dispatch handlers for key exchange packets that forward the 114 * packets to the monitor 115 * 116 * Event loops: 117 * 118 * - all monitor protocols are synchronous: because the SSHv2 rekey 119 * protocols are synchronous and because the other monitor operations 120 * are synchronous (or have no replies), 121 * 122 * - server_loop2() is modified to check the monitor pipe for rekey 123 * packets to forward to the client 124 * 125 * - and dispatch handlers are set, upon receipt of KEXINIT (and reset 126 * when NEWKEYS is sent out) to forward incoming rekey packets to the 127 * monitor. 128 * 129 * - the monitor runs an event loop not unlike server_loop2() and runs 130 * key exchanges almost exactly as a pre-altprivsep sshd would 131 * 132 * - unpriv sshd exit -> monitor cleanup (including audit logout) and exit 133 * 134 * - fatal() in monitor -> forcibly shutdown() socket and kill/wait for 135 * child (so that the audit event for the logout better reflects 136 * reality -- i.e., logged out means logged out, but for bg jobs) 137 * 138 * Message formats: 139 * 140 * - key exchange packets/replies forwarded "as is" 141 * 142 * - all other monitor requests are sent as SSH2_PRIV_MSG_ALTPRIVSEP and have a 143 * sub-type identifier (one octet) 144 * - private request sub-types include: 145 * - get new shared secret from last re-key 146 * - record login (utmpx/wtmpx), request data contains three arguments: 147 * pid, ttyname, program name 148 * - record logout (utmpx/wtmpx), request data contains one argument: pid 149 * 150 * Reply sub-types include: 151 * 152 * - NOP (for record_login/logout) 153 * - new shared secret from last re-key 154 */ 155 156 static int aps_started = 0; 157 static int is_monitor = 0; 158 159 static pid_t monitor_pid, child_pid; 160 static int pipe_fds[2]; 161 static int pipe_fd = -1; 162 static Buffer input_pipe, output_pipe; /* for pipe I/O */ 163 164 static Authctxt *xxx_authctxt; 165 166 /* Monitor functions */ 167 extern void aps_monitor_loop(Authctxt *authctxt, int pipe, pid_t child_pid); 168 static void aps_record_login(void); 169 static void aps_record_logout(void); 170 static void aps_start_rekex(void); 171 172 /* Altprivsep packet utilities for communication with the monitor */ 173 static void altprivsep_packet_start(u_char); 174 static int altprivsep_packet_send(void); 175 static int altprivsep_fwd_packet(u_char type); 176 177 static int altprivsep_packet_read(void); 178 static void altprivsep_packet_read_expect(int type); 179 180 static void altprivsep_packet_put_char(int ch); 181 static void altprivsep_packet_put_int(u_int value); 182 static void altprivsep_packet_put_cstring(const char *str); 183 static void altprivsep_packet_put_raw(const void *buf, u_int len); 184 185 static u_int altprivsep_packet_get_char(void); 186 static void *altprivsep_packet_get_raw(u_int *length_ptr); 187 static void *altprivsep_packet_get_string(u_int *length_ptr); 188 189 /* 190 * Start monitor from privileged sshd process. 191 * 192 * Return values are like fork(2); the parent is the monitor. The caller should 193 * fatal() on error. 194 * 195 * Privileges are dropped, on the unprivileged side, upon success. 196 */ 197 pid_t 198 altprivsep_start_monitor(Authctxt *authctxt) 199 { 200 pid_t pid; 201 int junk; 202 203 if (aps_started || authctxt == NULL || authctxt->pw == NULL) 204 fatal("Monitor startup failed: missing state"); 205 206 xxx_authctxt = authctxt; 207 208 packet_set_server(); 209 210 buffer_init(&output_pipe); 211 buffer_init(&input_pipe); 212 213 if (pipe(pipe_fds) != 0) { 214 error("Monitor startup failure: could not create pipes: %s", 215 strerror(errno)); 216 return (-1); 217 } 218 219 (void) fcntl(pipe_fds[0], F_SETFD, FD_CLOEXEC); 220 (void) fcntl(pipe_fds[1], F_SETFD, FD_CLOEXEC); 221 222 monitor_pid = getpid(); 223 224 if ((pid = fork()) > 0) { 225 /* parent */ 226 child_pid = pid; 227 228 debug2("Monitor pid %ld, unprivileged child pid %ld", 229 monitor_pid, child_pid); 230 231 (void) close(pipe_fds[1]); 232 233 pipe_fd = pipe_fds[0]; 234 235 if (fcntl(pipe_fd, F_SETFL, O_NONBLOCK) < 0) 236 error("fcntl O_NONBLOCK: %.100s", strerror(errno)); 237 238 /* signal readiness of monitor */ 239 (void) write(pipe_fd, &pid, sizeof (pid)); 240 241 aps_started = 1; 242 is_monitor = 1; 243 244 debug2("Monitor started"); 245 246 set_log_txt_prefix("monitor "); 247 248 return (pid); 249 250 } 251 252 if (pid < 0) { 253 debug2("Monitor startup failure: could not fork unprivileged" 254 " process: %s", strerror(errno)); 255 return (pid); 256 } 257 258 /* caller should drop privs */ 259 260 (void) close(pipe_fds[0]); 261 262 pipe_fd = pipe_fds[1]; 263 264 /* wait for monitor to be ready */ 265 debug2("Waiting for monitor"); 266 (void) read(pipe_fd, &junk, sizeof (junk)); 267 debug2("Monitor signalled readiness"); 268 269 if (fcntl(pipe_fd, F_SETFL, O_NONBLOCK) < 0) 270 error("fcntl O_NONBLOCK: %.100s", strerror(errno)); 271 272 buffer_init(&to_monitor); 273 buffer_init(&from_monitor); 274 275 if (compat20) { 276 debug3("Setting handler to forward re-key packets to monitor"); 277 dispatch_range(SSH2_MSG_KEXINIT, SSH2_MSG_TRANSPORT_MAX, 278 &altprivsep_rekey); 279 } 280 281 /* AltPrivSep interfaces are set up */ 282 aps_started = 1; 283 return (pid); 284 } 285 286 int 287 altprivsep_get_pipe_fd(void) 288 { 289 return (pipe_fd); 290 } 291 292 void 293 altprivsep_rekey(int type, u_int32_t seq, void *ctxt) 294 { 295 Kex *kex = (Kex *)ctxt; 296 297 if (kex == NULL) 298 fatal("Missing key exchange context in unprivileged process"); 299 300 debug2("Forwarding re-key packet (%d) to monitor", type); 301 302 if (type != SSH2_MSG_NEWKEYS) 303 if (!altprivsep_fwd_packet(type)) 304 fatal("Monitor not responding"); 305 306 /* tell server_loop2() that we're re-keying */ 307 kex->done = 0; 308 309 /* NEWKEYS is special: get the new keys for client->server direction */ 310 if (type == SSH2_MSG_NEWKEYS) { 311 debug2("Getting new inbound keystate from monitor"); 312 altprivsep_get_newkeys(MODE_IN); 313 kex->done = 1; 314 } 315 } 316 317 void 318 altprivsep_process_input(fd_set *rset) 319 { 320 void *data; 321 int type; 322 u_int dlen; 323 324 debug2("Reading from pipe to monitor (%d)", pipe_fd); 325 326 if (pipe_fd == -1) 327 return; 328 329 if (!FD_ISSET(pipe_fd, rset)) 330 return; 331 332 if ((type = altprivsep_packet_read()) == -1) 333 fatal("Monitor not responding"); 334 335 if (!compat20) 336 return; /* shouldn't happen! but be safe */ 337 338 if (type == 0) 339 return; /* EOF -- nothing to do here */ 340 341 if (type >= SSH2_MSG_MAX) 342 fatal("Received garbage from monitor"); 343 344 debug2("Read packet type %d from pipe to monitor", (u_int)type); 345 346 if (type == SSH2_PRIV_MSG_ALTPRIVSEP) 347 return; /* shouldn't happen! */ 348 349 /* NEWKEYS is special: get the new keys for server->client direction */ 350 if (type == SSH2_MSG_NEWKEYS) { 351 debug2("Getting new outbound keystate from monitor"); 352 packet_start(SSH2_MSG_NEWKEYS); 353 packet_send(); 354 altprivsep_get_newkeys(MODE_OUT); 355 return; 356 } 357 358 data = altprivsep_packet_get_raw(&dlen); 359 360 packet_start((u_char)type); 361 362 if (data != NULL && dlen > 0) 363 packet_put_raw(data, dlen); 364 365 packet_send(); 366 } 367 368 void 369 altprivsep_do_monitor(Authctxt *authctxt, pid_t child_pid) 370 { 371 aps_monitor_loop(authctxt, pipe_fd, child_pid); 372 } 373 374 int 375 altprivsep_started(void) 376 { 377 return (aps_started); 378 } 379 380 int 381 altprivsep_is_monitor(void) 382 { 383 return (is_monitor); 384 } 385 386 /* 387 * A fatal cleanup function to forcibly shutdown the connection socket 388 */ 389 void 390 altprivsep_shutdown_sock(void *arg) 391 { 392 int sock; 393 394 if (arg == NULL) 395 return; 396 397 sock = *(int *)arg; 398 399 (void) shutdown(sock, SHUT_RDWR); 400 } 401 402 /* Calls _to_ monitor from unprivileged process */ 403 static 404 int 405 altprivsep_fwd_packet(u_char type) 406 { 407 u_int len; 408 void *data; 409 410 altprivsep_packet_start(type); 411 data = packet_get_raw(&len); 412 altprivsep_packet_put_raw(data, len); 413 414 /* packet_send()s any replies from the monitor to the client */ 415 return (altprivsep_packet_send()); 416 } 417 418 extern Newkeys *current_keys[MODE_MAX]; 419 420 /* To be called from packet.c:set_newkeys() before referencing current_keys */ 421 void 422 altprivsep_get_newkeys(enum kex_modes mode) 423 { 424 Newkeys *newkeys; 425 Comp *comp; 426 Enc *enc; 427 Mac *mac; 428 u_int len; 429 430 if (!altprivsep_started()) 431 return; 432 433 if (altprivsep_is_monitor()) 434 return; /* shouldn't happen */ 435 436 /* request new keys */ 437 altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); 438 altprivsep_packet_put_char(APS_MSG_NEWKEYS_REQ); 439 altprivsep_packet_put_int((u_int)mode); 440 altprivsep_packet_send(); 441 altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP); 442 if (altprivsep_packet_get_char() != APS_MSG_NEWKEYS_REP) 443 fatal("Received garbage from monitor during re-keying"); 444 445 newkeys = xmalloc(sizeof (*newkeys)); 446 memset(newkeys, 0, sizeof (*newkeys)); 447 448 enc = &newkeys->enc; 449 mac = &newkeys->mac; 450 comp = &newkeys->comp; 451 452 /* Cipher name, key, IV */ 453 enc->name = altprivsep_packet_get_string(NULL); 454 if ((enc->cipher = cipher_by_name(enc->name)) == NULL) 455 fatal("Monitor negotiated an unknown cipher during re-key"); 456 457 enc->key = altprivsep_packet_get_string(&enc->key_len); 458 enc->iv = altprivsep_packet_get_string(&enc->block_size); 459 460 /* MAC name */ 461 mac->name = altprivsep_packet_get_string(NULL); 462 if (mac_init(mac, mac->name) < 0) 463 fatal("Monitor negotiated an unknown MAC algorithm " 464 "during re-key"); 465 466 mac->key = altprivsep_packet_get_string(&len); 467 if (len > mac->key_len) 468 fatal("%s: bad mac key length: %d > %d", __func__, len, 469 mac->key_len); 470 471 /* Compression algorithm name */ 472 comp->name = altprivsep_packet_get_string(NULL); 473 if (strcmp(comp->name, "zlib") != 0 && strcmp(comp->name, "none") != 0) 474 fatal("Monitor negotiated an unknown compression " 475 "algorithm during re-key"); 476 477 comp->type = 0; 478 comp->enabled = 0; /* forces compression re-init, as per-spec */ 479 if (strcmp(comp->name, "zlib") == 0) 480 comp->type = 1; 481 482 /* 483 * Now install new keys 484 * 485 * For now abuse kex.c/packet.c non-interfaces. Someday, when 486 * the many internal interfaces are parametrized, made reentrant 487 * and thread-safe, made more consistent, and when necessary-but- 488 * currently-missing interfaces are added then this bit of 489 * ugliness can be revisited. 490 * 491 * The ugliness is in the set_newkeys(), its name and the lack 492 * of a (Newkeys *) parameter, which forces us to pass the 493 * newkeys through current_keys[mode]. But this saves us some 494 * lines of code for now, though not comments. 495 * 496 * Also, we've abused, in the code above, knowledge of what 497 * set_newkeys() expects the current_keys[mode] to contain. 498 */ 499 current_keys[mode] = newkeys; 500 set_newkeys(mode); 501 502 } 503 504 void 505 altprivsep_record_login(pid_t pid, const char *ttyname) 506 { 507 altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); 508 altprivsep_packet_put_char(APS_MSG_RECORD_LOGIN); 509 altprivsep_packet_put_int(pid); 510 altprivsep_packet_put_cstring(ttyname); 511 altprivsep_packet_send(); 512 altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP); 513 } 514 515 void 516 altprivsep_record_logout(pid_t pid) 517 { 518 altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); 519 altprivsep_packet_put_char(APS_MSG_RECORD_LOGOUT); 520 altprivsep_packet_put_int(pid); 521 altprivsep_packet_send(); 522 altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP); 523 } 524 525 void 526 altprivsep_start_rekex(void) 527 { 528 altprivsep_packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); 529 altprivsep_packet_put_char(APS_MSG_START_REKEX); 530 altprivsep_packet_send(); 531 altprivsep_packet_read_expect(SSH2_PRIV_MSG_ALTPRIVSEP); 532 } 533 534 static void aps_send_newkeys(void); 535 536 /* Monitor side dispatch handler for SSH2_PRIV_MSG_ALTPRIVSEP */ 537 /* ARGSUSED */ 538 void 539 aps_input_altpriv_msg(int type, u_int32_t seq, void *ctxt) 540 { 541 u_char req_type; 542 543 req_type = packet_get_char(); 544 545 switch (req_type) { 546 case APS_MSG_NEWKEYS_REQ: 547 aps_send_newkeys(); 548 break; 549 case APS_MSG_RECORD_LOGIN: 550 aps_record_login(); 551 break; 552 case APS_MSG_RECORD_LOGOUT: 553 aps_record_logout(); 554 break; 555 case APS_MSG_START_REKEX: 556 aps_start_rekex(); 557 break; 558 default: 559 break; 560 } 561 } 562 563 /* Monitor-side handlers for APS_MSG_* */ 564 static 565 void 566 aps_send_newkeys(void) 567 { 568 Newkeys *newkeys; 569 Enc *enc; 570 Mac *mac; 571 Comp *comp; 572 enum kex_modes mode; 573 574 /* get direction for which newkeys are wanted */ 575 mode = (enum kex_modes) packet_get_int(); 576 packet_check_eom(); 577 578 /* get those newkeys */ 579 newkeys = kex_get_newkeys(mode); 580 enc = &newkeys->enc; 581 mac = &newkeys->mac; 582 comp = &newkeys->comp; 583 584 /* 585 * Negotiated algorithms, client->server and server->client, for 586 * cipher, mac and compression. 587 */ 588 packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); 589 packet_put_char(APS_MSG_NEWKEYS_REP); 590 packet_put_cstring(enc->name); 591 packet_put_string(enc->key, enc->key_len); 592 packet_put_string(enc->iv, enc->block_size); 593 packet_put_cstring(mac->name); 594 packet_put_string(mac->key, mac->key_len); 595 packet_put_cstring(comp->name); 596 597 packet_send(); 598 free_keys(newkeys); 599 } 600 601 struct _aps_login_rec { 602 pid_t lr_pid; 603 char *lr_tty; 604 struct _aps_login_rec *next; 605 }; 606 607 typedef struct _aps_login_rec aps_login_rec; 608 609 static aps_login_rec *aps_login_list = NULL; 610 611 static 612 void 613 aps_record_login(void) 614 { 615 aps_login_rec *new_rec; 616 struct stat sbuf; 617 size_t proc_path_len; 618 char *proc_path; 619 620 new_rec = xmalloc(sizeof (aps_login_rec)); 621 memset(new_rec, 0, sizeof (aps_login_rec)); 622 623 new_rec->lr_pid = packet_get_int(); 624 new_rec->lr_tty = packet_get_string(NULL); 625 626 proc_path_len = snprintf(NULL, 0, "/proc/%d", new_rec->lr_pid); 627 proc_path = xmalloc(proc_path_len + 1); 628 (void) snprintf(proc_path, proc_path_len + 1, "/proc/%d", 629 new_rec->lr_pid); 630 631 if (stat(proc_path, &sbuf) || 632 sbuf.st_uid != xxx_authctxt->pw->pw_uid || 633 stat(new_rec->lr_tty, &sbuf) < 0 || 634 sbuf.st_uid != xxx_authctxt->pw->pw_uid) { 635 debug2("Spurious record_login request from unprivileged sshd"); 636 xfree(proc_path); 637 xfree(new_rec->lr_tty); 638 xfree(new_rec); 639 return; 640 } 641 642 /* Insert new record on list */ 643 new_rec->next = aps_login_list; 644 aps_login_list = new_rec; 645 646 record_login(new_rec->lr_pid, new_rec->lr_tty, NULL, 647 xxx_authctxt->user); 648 649 packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); 650 packet_send(); 651 652 xfree(proc_path); 653 } 654 655 static 656 void 657 aps_record_logout(void) 658 { 659 aps_login_rec **p, *q; 660 pid_t pid; 661 662 pid = packet_get_int(); 663 packet_check_eom(); 664 665 for (p = &aps_login_list; *p != NULL; p = &q->next) { 666 q = *p; 667 if (q->lr_pid == pid) { 668 record_logout(q->lr_pid, q->lr_tty, NULL, 669 xxx_authctxt->user); 670 671 /* dequeue */ 672 *p = q->next; 673 xfree(q->lr_tty); 674 xfree(q); 675 break; 676 } 677 } 678 679 packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); 680 packet_send(); 681 } 682 683 static 684 void 685 aps_start_rekex(void) 686 { 687 /* 688 * Send confirmation. We could implement it without that but it doesn't 689 * bring any harm to do that and we are consistent with other subtypes 690 * of our private SSH2_PRIV_MSG_ALTPRIVSEP message type. 691 */ 692 packet_start(SSH2_PRIV_MSG_ALTPRIVSEP); 693 packet_send(); 694 695 /* 696 * KEX_INIT message could be the one that reached the limit. In that 697 * case, it was already forwarded to us from the unnprivileged child, 698 * and maybe even acted upon. Obviously we must not send another 699 * KEX_INIT message. 700 */ 701 if (!(xxx_kex->flags & KEX_INIT_SENT)) 702 kex_send_kexinit(xxx_kex); 703 else 704 debug2("rekeying already in progress"); 705 } 706 707 708 /* Utilities for communication with the monitor */ 709 static 710 void 711 altprivsep_packet_start(u_char type) 712 { 713 buffer_clear(&to_monitor); 714 buffer_put_char(&to_monitor, type); 715 } 716 static 717 void 718 altprivsep_packet_put_char(int ch) 719 { 720 buffer_put_char(&to_monitor, ch); 721 } 722 static 723 void 724 altprivsep_packet_put_int(u_int value) 725 { 726 buffer_put_int(&to_monitor, value); 727 } 728 static 729 void 730 altprivsep_packet_put_cstring(const char *str) 731 { 732 buffer_put_cstring(&to_monitor, str); 733 } 734 static 735 void 736 altprivsep_packet_put_raw(const void *buf, u_int len) 737 { 738 buffer_append(&to_monitor, buf, len); 739 } 740 741 /* 742 * Send a monitor packet to the monitor. This function is blocking. 743 * 744 * Returns -1 if the monitor pipe has been closed earlier, fatal()s if 745 * there's any other problems. 746 */ 747 static 748 int 749 altprivsep_packet_send(void) 750 { 751 ssize_t len; 752 u_int32_t plen; /* packet length */ 753 u_char plen_buf[sizeof (plen)]; 754 u_char padlen; /* padding length */ 755 fd_set *setp; 756 757 if (pipe_fd == -1) 758 return (-1); 759 760 if ((plen = buffer_len(&to_monitor)) == 0) 761 return (0); 762 763 /* 764 * We talk the SSHv2 binary packet protocol to the monitor, 765 * using the none cipher, mac and compression algorithms. 766 * 767 * But, interestingly, the none cipher has a block size of 8 768 * bytes, thus we must pad the packet. 769 * 770 * Also, encryption includes the packet length, so the padding 771 * must account for that field. I.e., (sizeof (packet length) + 772 * sizeof (padding length) + packet length + padding length) % 773 * block_size must == 0. 774 * 775 * Also, there must be at least four (4) bytes of padding. 776 */ 777 padlen = (8 - ((plen + sizeof (plen) + sizeof (padlen)) % 8)) % 8; 778 if (padlen < 4) 779 padlen += 8; 780 781 /* packet length counts padding and padding length field */ 782 plen += padlen + sizeof (padlen); 783 784 PUT_32BIT(plen_buf, plen); 785 786 setp = xmalloc(howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask)); 787 memset(setp, 0, howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask)); 788 FD_SET(pipe_fd, setp); 789 790 while (select(pipe_fd + 1, NULL, setp, NULL, NULL) == -1) { 791 if (errno == EAGAIN || errno == EINTR) 792 continue; 793 else 794 goto pipe_gone; 795 } 796 797 xfree(setp); 798 799 /* packet length field */ 800 len = atomicio(write, pipe_fd, plen_buf, sizeof (plen)); 801 802 if (len != sizeof (plen)) 803 goto pipe_gone; 804 805 /* padding length field */ 806 len = atomicio(write, pipe_fd, &padlen, sizeof (padlen)); 807 808 if (len != sizeof (padlen)) 809 goto pipe_gone; 810 811 len = atomicio(write, pipe_fd, buffer_ptr(&to_monitor), plen - 1); 812 813 if (len != (plen - 1)) 814 goto pipe_gone; 815 816 buffer_clear(&to_monitor); 817 818 return (1); 819 820 pipe_gone: 821 822 (void) close(pipe_fd); 823 824 pipe_fd = -1; 825 826 fatal("Monitor not responding"); 827 828 /* NOTREACHED */ 829 return (0); 830 } 831 832 /* 833 * Read a monitor packet from the monitor. This function is blocking. 834 */ 835 static 836 int 837 altprivsep_packet_read(void) 838 { 839 ssize_t len = -1; 840 u_int32_t plen; 841 u_char plen_buf[sizeof (plen)]; 842 u_char padlen; 843 fd_set *setp; 844 845 if (pipe_fd == -1) 846 return (-1); 847 848 setp = xmalloc(howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask)); 849 memset(setp, 0, howmany(pipe_fd + 1, NFDBITS) * sizeof (fd_mask)); 850 FD_SET(pipe_fd, setp); 851 852 while (select(pipe_fd + 1, setp, NULL, NULL, NULL) == -1) { 853 if (errno == EAGAIN || errno == EINTR) 854 continue; 855 else 856 goto pipe_gone; 857 } 858 859 xfree(setp); 860 861 /* packet length field */ 862 len = atomicio(read, pipe_fd, plen_buf, sizeof (plen)); 863 864 plen = GET_32BIT(plen_buf); 865 866 if (len != sizeof (plen)) 867 goto pipe_gone; 868 869 /* padding length field */ 870 len = atomicio(read, pipe_fd, &padlen, sizeof (padlen)); 871 872 if (len != sizeof (padlen)) 873 goto pipe_gone; 874 875 plen -= sizeof (padlen); 876 877 buffer_clear(&from_monitor); 878 buffer_append_space(&from_monitor, plen); 879 880 /* packet data + padding */ 881 len = atomicio(read, pipe_fd, buffer_ptr(&from_monitor), plen); 882 883 if (len != plen) 884 goto pipe_gone; 885 886 /* remove padding */ 887 if (padlen > 0) 888 buffer_consume_end(&from_monitor, padlen); 889 890 /* packet type */ 891 return (buffer_get_char(&from_monitor)); 892 893 pipe_gone: 894 895 (void) close(pipe_fd); 896 897 pipe_fd = -1; 898 899 if (len < 0) 900 fatal("Monitor not responding"); 901 902 debug2("Monitor pipe closed by monitor"); 903 return (0); 904 } 905 906 static 907 void 908 altprivsep_packet_read_expect(int expected) 909 { 910 int type; 911 912 type = altprivsep_packet_read(); 913 914 if (type <= 0) 915 fatal("Monitor not responding"); 916 917 if (type != expected) 918 fatal("Protocol error in privilege separation; expected " 919 "packet type %d, got %d", expected, type); 920 } 921 922 static 923 u_int 924 altprivsep_packet_get_char(void) 925 { 926 return (buffer_get_char(&from_monitor)); 927 } 928 void 929 *altprivsep_packet_get_raw(u_int *length_ptr) 930 { 931 if (length_ptr != NULL) 932 *length_ptr = buffer_len(&from_monitor); 933 934 return (buffer_ptr(&from_monitor)); 935 } 936 void 937 *altprivsep_packet_get_string(u_int *length_ptr) 938 { 939 return (buffer_get_string(&from_monitor, length_ptr)); 940 } 941