comparison svr-chansession.c @ 165:0cfba3034be5

Fixed DEBUG_TRACE macro so that we don't get semicolons left about the place
author Matt Johnston <matt@ucc.asn.au>
date Sun, 02 Jan 2005 20:25:56 +0000
parents b4cfe976c8e1
children 8e68dbe8687b
comparison
equal deleted inserted replaced
161:b9d3f725e00b 165:0cfba3034be5
85 pid_t pid; 85 pid_t pid;
86 unsigned int i; 86 unsigned int i;
87 struct sigaction sa_chld; 87 struct sigaction sa_chld;
88 struct exitinfo *exit = NULL; 88 struct exitinfo *exit = NULL;
89 89
90 TRACE(("enter sigchld handler")); 90 TRACE(("enter sigchld handler"))
91 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) { 91 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
92 /* find the corresponding chansess */ 92 /* find the corresponding chansess */
93 for (i = 0; i < svr_ses.childpidsize; i++) { 93 for (i = 0; i < svr_ses.childpidsize; i++) {
94 if (svr_ses.childpids[i].pid == pid) { 94 if (svr_ses.childpids[i].pid == pid) {
95 95
124 124
125 125
126 sa_chld.sa_handler = sesssigchild_handler; 126 sa_chld.sa_handler = sesssigchild_handler;
127 sa_chld.sa_flags = SA_NOCLDSTOP; 127 sa_chld.sa_flags = SA_NOCLDSTOP;
128 sigaction(SIGCHLD, &sa_chld, NULL); 128 sigaction(SIGCHLD, &sa_chld, NULL);
129 TRACE(("leave sigchld handler")); 129 TRACE(("leave sigchld handler"))
130 } 130 }
131 131
132 /* send the exit status or the signal causing termination for a session */ 132 /* send the exit status or the signal causing termination for a session */
133 /* XXX server */ 133 /* XXX server */
134 static void send_exitsignalstatus(struct Channel *channel) { 134 static void send_exitsignalstatus(struct Channel *channel) {
246 246
247 chansess = (struct ChanSess*)channel->typedata; 247 chansess = (struct ChanSess*)channel->typedata;
248 248
249 send_exitsignalstatus(channel); 249 send_exitsignalstatus(channel);
250 250
251 TRACE(("enter closechansess")); 251 TRACE(("enter closechansess"))
252 if (chansess == NULL) { 252 if (chansess == NULL) {
253 TRACE(("leave closechansess: chansess == NULL")); 253 TRACE(("leave closechansess: chansess == NULL"))
254 return; 254 return;
255 } 255 }
256 256
257 m_free(chansess->cmd); 257 m_free(chansess->cmd);
258 m_free(chansess->term); 258 m_free(chansess->term);
278 278
279 /* clear child pid entries */ 279 /* clear child pid entries */
280 for (i = 0; i < svr_ses.childpidsize; i++) { 280 for (i = 0; i < svr_ses.childpidsize; i++) {
281 if (svr_ses.childpids[i].chansess == chansess) { 281 if (svr_ses.childpids[i].chansess == chansess) {
282 assert(svr_ses.childpids[i].pid > 0); 282 assert(svr_ses.childpids[i].pid > 0);
283 TRACE(("closing pid %d", svr_ses.childpids[i].pid)); 283 TRACE(("closing pid %d", svr_ses.childpids[i].pid))
284 TRACE(("exitpid = %d", chansess->exit.exitpid)); 284 TRACE(("exitpid = %d", chansess->exit.exitpid))
285 svr_ses.childpids[i].pid = -1; 285 svr_ses.childpids[i].pid = -1;
286 svr_ses.childpids[i].chansess = NULL; 286 svr_ses.childpids[i].chansess = NULL;
287 } 287 }
288 } 288 }
289 289
290 m_free(chansess); 290 m_free(chansess);
291 291
292 TRACE(("leave closechansess")); 292 TRACE(("leave closechansess"))
293 } 293 }
294 294
295 /* Handle requests for a channel. These can be execution requests, 295 /* Handle requests for a channel. These can be execution requests,
296 * or x11/authagent forwarding. These are passed to appropriate handlers */ 296 * or x11/authagent forwarding. These are passed to appropriate handlers */
297 static void chansessionrequest(struct Channel *channel) { 297 static void chansessionrequest(struct Channel *channel) {
300 unsigned int typelen; 300 unsigned int typelen;
301 unsigned char wantreply; 301 unsigned char wantreply;
302 int ret = 1; 302 int ret = 1;
303 struct ChanSess *chansess; 303 struct ChanSess *chansess;
304 304
305 TRACE(("enter chansessionrequest")); 305 TRACE(("enter chansessionrequest"))
306 306
307 type = buf_getstring(ses.payload, &typelen); 307 type = buf_getstring(ses.payload, &typelen);
308 wantreply = buf_getbyte(ses.payload); 308 wantreply = buf_getbyte(ses.payload);
309 309
310 if (typelen > MAX_NAME_LEN) { 310 if (typelen > MAX_NAME_LEN) {
311 TRACE(("leave chansessionrequest: type too long")); /* XXX send error?*/ 311 TRACE(("leave chansessionrequest: type too long")) /* XXX send error?*/
312 goto out; 312 goto out;
313 } 313 }
314 314
315 chansess = (struct ChanSess*)channel->typedata; 315 chansess = (struct ChanSess*)channel->typedata;
316 assert(chansess != NULL); 316 assert(chansess != NULL);
317 TRACE(("type is %s", type)); 317 TRACE(("type is %s", type))
318 318
319 if (strcmp(type, "window-change") == 0) { 319 if (strcmp(type, "window-change") == 0) {
320 ret = sessionwinchange(chansess); 320 ret = sessionwinchange(chansess);
321 } else if (strcmp(type, "shell") == 0) { 321 } else if (strcmp(type, "shell") == 0) {
322 ret = sessioncommand(channel, chansess, 0, 0); 322 ret = sessioncommand(channel, chansess, 0, 0);
349 send_msg_channel_failure(channel); 349 send_msg_channel_failure(channel);
350 } 350 }
351 } 351 }
352 352
353 m_free(type); 353 m_free(type);
354 TRACE(("leave chansessionrequest")); 354 TRACE(("leave chansessionrequest"))
355 } 355 }
356 356
357 357
358 /* Send a signal to a session's process as requested by the client*/ 358 /* Send a signal to a session's process as requested by the client*/
359 static int sessionsignal(struct ChanSess *chansess) { 359 static int sessionsignal(struct ChanSess *chansess) {
419 unsigned char opcode; 419 unsigned char opcode;
420 unsigned int value; 420 unsigned int value;
421 const struct TermCode * termcode; 421 const struct TermCode * termcode;
422 unsigned int len; 422 unsigned int len;
423 423
424 TRACE(("enter get_termmodes")); 424 TRACE(("enter get_termmodes"))
425 425
426 /* Term modes */ 426 /* Term modes */
427 /* We'll ignore errors and continue if we can't set modes. 427 /* We'll ignore errors and continue if we can't set modes.
428 * We're ignoring baud rates since they seem evil */ 428 * We're ignoring baud rates since they seem evil */
429 if (tcgetattr(chansess->master, &termio) == -1) { 429 if (tcgetattr(chansess->master, &termio) == -1) {
436 if (len != ses.payload->len - ses.payload->pos) { 436 if (len != ses.payload->len - ses.payload->pos) {
437 dropbear_exit("bad term mode string"); 437 dropbear_exit("bad term mode string");
438 } 438 }
439 439
440 if (len == 0) { 440 if (len == 0) {
441 TRACE(("leave get_termmodes: empty terminal modes string")); 441 TRACE(("leave get_termmodes: empty terminal modes string"))
442 } 442 }
443 443
444 while (((opcode = buf_getbyte(ses.payload)) != 0x00) && opcode <= 159) { 444 while (((opcode = buf_getbyte(ses.payload)) != 0x00) && opcode <= 159) {
445 445
446 /* must be before checking type, so that value is consumed even if 446 /* must be before checking type, so that value is consumed even if
498 } 498 }
499 } 499 }
500 if (tcsetattr(chansess->master, TCSANOW, &termio) < 0) { 500 if (tcsetattr(chansess->master, TCSANOW, &termio) < 0) {
501 dropbear_log(LOG_INFO, "error setting terminal attributes"); 501 dropbear_log(LOG_INFO, "error setting terminal attributes");
502 } 502 }
503 TRACE(("leave get_termmodes")); 503 TRACE(("leave get_termmodes"))
504 } 504 }
505 505
506 /* Set up a session pty which will be used to execute the shell or program. 506 /* Set up a session pty which will be used to execute the shell or program.
507 * The pty is allocated now, and kept for when the shell/program executes. 507 * The pty is allocated now, and kept for when the shell/program executes.
508 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */ 508 * Returns DROPBEAR_SUCCESS or DROPBEAR_FAILURE */
509 static int sessionpty(struct ChanSess * chansess) { 509 static int sessionpty(struct ChanSess * chansess) {
510 510
511 unsigned int termlen; 511 unsigned int termlen;
512 unsigned char namebuf[65]; 512 unsigned char namebuf[65];
513 513
514 TRACE(("enter sessionpty")); 514 TRACE(("enter sessionpty"))
515 chansess->term = buf_getstring(ses.payload, &termlen); 515 chansess->term = buf_getstring(ses.payload, &termlen);
516 if (termlen > MAX_TERM_LEN) { 516 if (termlen > MAX_TERM_LEN) {
517 /* TODO send disconnect ? */ 517 /* TODO send disconnect ? */
518 TRACE(("leave sessionpty: term len too long")); 518 TRACE(("leave sessionpty: term len too long"))
519 return DROPBEAR_FAILURE; 519 return DROPBEAR_FAILURE;
520 } 520 }
521 521
522 /* allocate the pty */ 522 /* allocate the pty */
523 if (chansess->master != -1) { 523 if (chansess->master != -1) {
524 dropbear_exit("multiple pty requests"); 524 dropbear_exit("multiple pty requests");
525 } 525 }
526 if (pty_allocate(&chansess->master, &chansess->slave, namebuf, 64) == 0) { 526 if (pty_allocate(&chansess->master, &chansess->slave, namebuf, 64) == 0) {
527 TRACE(("leave sessionpty: failed to allocate pty")); 527 TRACE(("leave sessionpty: failed to allocate pty"))
528 return DROPBEAR_FAILURE; 528 return DROPBEAR_FAILURE;
529 } 529 }
530 530
531 chansess->tty = (char*)m_strdup(namebuf); 531 chansess->tty = (char*)m_strdup(namebuf);
532 if (!chansess->tty) { 532 if (!chansess->tty) {
539 sessionwinchange(chansess); 539 sessionwinchange(chansess);
540 540
541 /* Read the terminal modes */ 541 /* Read the terminal modes */
542 get_termmodes(chansess); 542 get_termmodes(chansess);
543 543
544 TRACE(("leave sessionpty")); 544 TRACE(("leave sessionpty"))
545 return DROPBEAR_SUCCESS; 545 return DROPBEAR_SUCCESS;
546 } 546 }
547 547
548 /* Handle a command request from the client. This is used for both shell 548 /* Handle a command request from the client. This is used for both shell
549 * and command-execution requests, and passes the command to 549 * and command-execution requests, and passes the command to
553 int iscmd, int issubsys) { 553 int iscmd, int issubsys) {
554 554
555 unsigned int cmdlen; 555 unsigned int cmdlen;
556 int ret; 556 int ret;
557 557
558 TRACE(("enter sessioncommand")); 558 TRACE(("enter sessioncommand"))
559 559
560 if (chansess->cmd != NULL) { 560 if (chansess->cmd != NULL) {
561 /* Note that only one command can _succeed_. The client might try 561 /* Note that only one command can _succeed_. The client might try
562 * one command (which fails), then try another. Ie fallback 562 * one command (which fails), then try another. Ie fallback
563 * from sftp to scp */ 563 * from sftp to scp */
610 int outfds[2]; 610 int outfds[2];
611 int errfds[2]; 611 int errfds[2];
612 pid_t pid; 612 pid_t pid;
613 unsigned int i; 613 unsigned int i;
614 614
615 TRACE(("enter noptycommand")); 615 TRACE(("enter noptycommand"))
616 616
617 /* redirect stdin/stdout/stderr */ 617 /* redirect stdin/stdout/stderr */
618 if (pipe(infds) != 0) 618 if (pipe(infds) != 0)
619 return DROPBEAR_FAILURE; 619 return DROPBEAR_FAILURE;
620 if (pipe(outfds) != 0) 620 if (pipe(outfds) != 0)
633 #define FDIN 0 633 #define FDIN 0
634 #define FDOUT 1 634 #define FDOUT 1
635 if ((dup2(infds[FDIN], STDIN_FILENO) < 0) || 635 if ((dup2(infds[FDIN], STDIN_FILENO) < 0) ||
636 (dup2(outfds[FDOUT], STDOUT_FILENO) < 0) || 636 (dup2(outfds[FDOUT], STDOUT_FILENO) < 0) ||
637 (dup2(errfds[FDOUT], STDERR_FILENO) < 0)) { 637 (dup2(errfds[FDOUT], STDERR_FILENO) < 0)) {
638 TRACE(("leave noptycommand: error redirecting FDs")); 638 TRACE(("leave noptycommand: error redirecting FDs"))
639 return DROPBEAR_FAILURE; 639 return DROPBEAR_FAILURE;
640 } 640 }
641 641
642 close(infds[FDOUT]); 642 close(infds[FDOUT]);
643 close(infds[FDIN]); 643 close(infds[FDIN]);
649 execchild(chansess); 649 execchild(chansess);
650 /* not reached */ 650 /* not reached */
651 651
652 } else { 652 } else {
653 /* parent */ 653 /* parent */
654 TRACE(("continue noptycommand: parent")); 654 TRACE(("continue noptycommand: parent"))
655 chansess->pid = pid; 655 chansess->pid = pid;
656 656
657 addchildpid(chansess, pid); 657 addchildpid(chansess, pid);
658 658
659 if (svr_ses.lastexit.exitpid != -1) { 659 if (svr_ses.lastexit.exitpid != -1) {
685 685
686 } 686 }
687 #undef FDIN 687 #undef FDIN
688 #undef FDOUT 688 #undef FDOUT
689 689
690 TRACE(("leave noptycommand")); 690 TRACE(("leave noptycommand"))
691 return DROPBEAR_SUCCESS; 691 return DROPBEAR_SUCCESS;
692 } 692 }
693 693
694 /* Execute a command or shell within a pty environment, and set up 694 /* Execute a command or shell within a pty environment, and set up
695 * redirection as appropriate. 695 * redirection as appropriate.
703 int len; 703 int len;
704 struct stat sb; 704 struct stat sb;
705 char *hushpath = NULL; 705 char *hushpath = NULL;
706 #endif 706 #endif
707 707
708 TRACE(("enter ptycommand")); 708 TRACE(("enter ptycommand"))
709 709
710 /* we need to have a pty allocated */ 710 /* we need to have a pty allocated */
711 if (chansess->master == -1 || chansess->tty == NULL) { 711 if (chansess->master == -1 || chansess->tty == NULL) {
712 dropbear_log(LOG_WARNING, "no pty was allocated, couldn't execute"); 712 dropbear_log(LOG_WARNING, "no pty was allocated, couldn't execute");
713 return DROPBEAR_FAILURE; 713 return DROPBEAR_FAILURE;
726 pty_make_controlling_tty(&chansess->slave, chansess->tty); 726 pty_make_controlling_tty(&chansess->slave, chansess->tty);
727 727
728 if ((dup2(chansess->slave, STDIN_FILENO) < 0) || 728 if ((dup2(chansess->slave, STDIN_FILENO) < 0) ||
729 (dup2(chansess->slave, STDERR_FILENO) < 0) || 729 (dup2(chansess->slave, STDERR_FILENO) < 0) ||
730 (dup2(chansess->slave, STDOUT_FILENO) < 0)) { 730 (dup2(chansess->slave, STDOUT_FILENO) < 0)) {
731 TRACE(("leave ptycommand: error redirecting filedesc")); 731 TRACE(("leave ptycommand: error redirecting filedesc"))
732 return DROPBEAR_FAILURE; 732 return DROPBEAR_FAILURE;
733 } 733 }
734 734
735 close(chansess->slave); 735 close(chansess->slave);
736 736
774 execchild(chansess); 774 execchild(chansess);
775 /* not reached */ 775 /* not reached */
776 776
777 } else { 777 } else {
778 /* parent */ 778 /* parent */
779 TRACE(("continue ptycommand: parent")); 779 TRACE(("continue ptycommand: parent"))
780 chansess->pid = pid; 780 chansess->pid = pid;
781 781
782 /* add a child pid */ 782 /* add a child pid */
783 addchildpid(chansess, pid); 783 addchildpid(chansess, pid);
784 784
790 790
791 setnonblocking(chansess->master); 791 setnonblocking(chansess->master);
792 792
793 } 793 }
794 794
795 TRACE(("leave ptycommand")); 795 TRACE(("leave ptycommand"))
796 return DROPBEAR_SUCCESS; 796 return DROPBEAR_SUCCESS;
797 } 797 }
798 798
799 /* Add the pid of a child to the list for exit-handling */ 799 /* Add the pid of a child to the list for exit-handling */
800 static void addchildpid(struct ChanSess *chansess, pid_t pid) { 800 static void addchildpid(struct ChanSess *chansess, pid_t pid) {