diff options
Diffstat (limited to 'session.c')
-rw-r--r-- | session.c | 194 |
1 files changed, 91 insertions, 103 deletions
@@ -8,7 +8,7 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include "includes.h" | 10 | #include "includes.h" |
11 | RCSID("$OpenBSD: session.c,v 1.23 2000/07/11 08:11:33 deraadt Exp $"); | 11 | RCSID("$OpenBSD: session.c,v 1.25 2000/08/17 20:06:34 markus Exp $"); |
12 | 12 | ||
13 | #include "xmalloc.h" | 13 | #include "xmalloc.h" |
14 | #include "ssh.h" | 14 | #include "ssh.h" |
@@ -85,6 +85,7 @@ void session_pty_cleanup(Session *s); | |||
85 | void session_proctitle(Session *s); | 85 | void session_proctitle(Session *s); |
86 | void do_exec_pty(Session *s, const char *command, struct passwd * pw); | 86 | void do_exec_pty(Session *s, const char *command, struct passwd * pw); |
87 | void do_exec_no_pty(Session *s, const char *command, struct passwd * pw); | 87 | void do_exec_no_pty(Session *s, const char *command, struct passwd * pw); |
88 | void do_login(Session *s); | ||
88 | 89 | ||
89 | void | 90 | void |
90 | do_child(const char *command, struct passwd * pw, const char *term, | 91 | do_child(const char *command, struct passwd * pw, const char *term, |
@@ -101,6 +102,7 @@ static const char *__progname = "sshd"; | |||
101 | 102 | ||
102 | extern int log_stderr; | 103 | extern int log_stderr; |
103 | extern int debug_flag; | 104 | extern int debug_flag; |
105 | extern unsigned int utmp_len; | ||
104 | 106 | ||
105 | extern int startup_pipe; | 107 | extern int startup_pipe; |
106 | 108 | ||
@@ -523,35 +525,14 @@ do_exec_no_pty(Session *s, const char *command, struct passwd * pw) | |||
523 | void | 525 | void |
524 | do_exec_pty(Session *s, const char *command, struct passwd * pw) | 526 | do_exec_pty(Session *s, const char *command, struct passwd * pw) |
525 | { | 527 | { |
526 | FILE *f; | ||
527 | char buf[100], *time_string; | ||
528 | char line[256]; | ||
529 | const char *hostname; | ||
530 | int fdout, ptyfd, ttyfd, ptymaster; | 528 | int fdout, ptyfd, ttyfd, ptymaster; |
531 | int quiet_login; | ||
532 | pid_t pid; | 529 | pid_t pid; |
533 | socklen_t fromlen; | ||
534 | struct sockaddr_storage from; | ||
535 | struct stat st; | ||
536 | time_t last_login_time; | ||
537 | 530 | ||
538 | if (s == NULL) | 531 | if (s == NULL) |
539 | fatal("do_exec_pty: no session"); | 532 | fatal("do_exec_pty: no session"); |
540 | ptyfd = s->ptyfd; | 533 | ptyfd = s->ptyfd; |
541 | ttyfd = s->ttyfd; | 534 | ttyfd = s->ttyfd; |
542 | 535 | ||
543 | /* Get remote host name. */ | ||
544 | hostname = get_canonical_hostname(); | ||
545 | |||
546 | /* | ||
547 | * Get the time when the user last logged in. Buf will be set to | ||
548 | * contain the hostname the last login was from. | ||
549 | */ | ||
550 | if (!options.use_login) { | ||
551 | last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, | ||
552 | buf, sizeof(buf)); | ||
553 | } | ||
554 | |||
555 | #ifdef USE_PAM | 536 | #ifdef USE_PAM |
556 | do_pam_session(pw->pw_name, s->tty); | 537 | do_pam_session(pw->pw_name, s->tty); |
557 | do_pam_setcred(); | 538 | do_pam_setcred(); |
@@ -559,10 +540,7 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw) | |||
559 | 540 | ||
560 | /* Fork the child. */ | 541 | /* Fork the child. */ |
561 | if ((pid = fork()) == 0) { | 542 | if ((pid = fork()) == 0) { |
562 | pid = getpid(); | 543 | /* Child. Reinitialize the log because the pid has changed. */ |
563 | |||
564 | /* Child. Reinitialize the log because the pid has | ||
565 | changed. */ | ||
566 | log_init(__progname, options.log_level, options.log_facility, log_stderr); | 544 | log_init(__progname, options.log_level, options.log_facility, log_stderr); |
567 | 545 | ||
568 | /* Close the master side of the pseudo tty. */ | 546 | /* Close the master side of the pseudo tty. */ |
@@ -586,82 +564,10 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw) | |||
586 | /* Close the extra descriptor for the pseudo tty. */ | 564 | /* Close the extra descriptor for the pseudo tty. */ |
587 | close(ttyfd); | 565 | close(ttyfd); |
588 | 566 | ||
589 | /* XXXX ? move to do_child() ??*/ | 567 | /* record login, etc. similar to login(1) */ |
590 | /* | 568 | if (command == NULL && !options.use_login) |
591 | * Get IP address of client. This is needed because we want | 569 | do_login(s); |
592 | * to record where the user logged in from. If the | ||
593 | * connection is not a socket, let the ip address be 0.0.0.0. | ||
594 | */ | ||
595 | memset(&from, 0, sizeof(from)); | ||
596 | if (packet_connection_is_on_socket()) { | ||
597 | fromlen = sizeof(from); | ||
598 | if (getpeername(packet_get_connection_in(), | ||
599 | (struct sockaddr *) & from, &fromlen) < 0) { | ||
600 | debug("getpeername: %.100s", strerror(errno)); | ||
601 | fatal_cleanup(); | ||
602 | } | ||
603 | } | ||
604 | /* Record that there was a login on that terminal. */ | ||
605 | if (!options.use_login || command != NULL) | ||
606 | record_login(pid, s->tty, pw->pw_name, pw->pw_uid, | ||
607 | hostname, (struct sockaddr *)&from); | ||
608 | |||
609 | /* Check if .hushlogin exists. */ | ||
610 | snprintf(line, sizeof line, "%.200s/.hushlogin", pw->pw_dir); | ||
611 | quiet_login = stat(line, &st) >= 0; | ||
612 | 570 | ||
613 | #ifdef USE_PAM | ||
614 | if (!quiet_login) | ||
615 | print_pam_messages(); | ||
616 | #endif /* USE_PAM */ | ||
617 | |||
618 | /* | ||
619 | * If the user has logged in before, display the time of last | ||
620 | * login. However, don't display anything extra if a command | ||
621 | * has been specified (so that ssh can be used to execute | ||
622 | * commands on a remote machine without users knowing they | ||
623 | * are going to another machine). Login(1) will do this for | ||
624 | * us as well, so check if login(1) is used | ||
625 | */ | ||
626 | if (command == NULL && last_login_time != 0 && !quiet_login && | ||
627 | !options.use_login) { | ||
628 | /* Convert the date to a string. */ | ||
629 | time_string = ctime(&last_login_time); | ||
630 | /* Remove the trailing newline. */ | ||
631 | if (strchr(time_string, '\n')) | ||
632 | *strchr(time_string, '\n') = 0; | ||
633 | /* Display the last login time. Host if displayed | ||
634 | if known. */ | ||
635 | if (strcmp(buf, "") == 0) | ||
636 | printf("Last login: %s\r\n", time_string); | ||
637 | else | ||
638 | printf("Last login: %s from %s\r\n", time_string, buf); | ||
639 | } | ||
640 | /* | ||
641 | * Print /etc/motd unless a command was specified or printing | ||
642 | * it was disabled in server options or login(1) will be | ||
643 | * used. Note that some machines appear to print it in | ||
644 | * /etc/profile or similar. | ||
645 | */ | ||
646 | if (command == NULL && options.print_motd && !quiet_login && | ||
647 | !options.use_login) { | ||
648 | /* Print /etc/motd if it exists. */ | ||
649 | f = fopen("/etc/motd", "r"); | ||
650 | if (f) { | ||
651 | while (fgets(line, sizeof(line), f)) | ||
652 | fputs(line, stdout); | ||
653 | fclose(f); | ||
654 | } | ||
655 | } | ||
656 | #if defined(WITH_AIXAUTHENTICATE) | ||
657 | /* | ||
658 | * AIX handles the lastlog info differently. Display it here. | ||
659 | */ | ||
660 | if (command == NULL && aixloginmsg && *aixloginmsg && | ||
661 | !quiet_login && !options.use_login) { | ||
662 | printf("%s\n", aixloginmsg); | ||
663 | } | ||
664 | #endif | ||
665 | /* Do common processing for the child, such as execing the command. */ | 571 | /* Do common processing for the child, such as execing the command. */ |
666 | do_child(command, pw, s->term, s->display, s->auth_proto, | 572 | do_child(command, pw, s->term, s->display, s->auth_proto, |
667 | s->auth_data, s->tty); | 573 | s->auth_data, s->tty); |
@@ -699,6 +605,87 @@ do_exec_pty(Session *s, const char *command, struct passwd * pw) | |||
699 | } | 605 | } |
700 | } | 606 | } |
701 | 607 | ||
608 | const char * | ||
609 | get_remote_name_or_ip(void) | ||
610 | { | ||
611 | static const char *remote = ""; | ||
612 | if (utmp_len > 0) | ||
613 | remote = get_canonical_hostname(); | ||
614 | if (utmp_len == 0 || strlen(remote) > utmp_len) | ||
615 | remote = get_remote_ipaddr(); | ||
616 | return remote; | ||
617 | } | ||
618 | |||
619 | /* administrative, login(1)-like work */ | ||
620 | void | ||
621 | do_login(Session *s) | ||
622 | { | ||
623 | FILE *f; | ||
624 | char *time_string; | ||
625 | char buf[256]; | ||
626 | socklen_t fromlen; | ||
627 | struct sockaddr_storage from; | ||
628 | struct stat st; | ||
629 | time_t last_login_time; | ||
630 | struct passwd * pw = s->pw; | ||
631 | pid_t pid = getpid(); | ||
632 | |||
633 | /* | ||
634 | * Get IP address of client. If the connection is not a socket, let | ||
635 | * the address be 0.0.0.0. | ||
636 | */ | ||
637 | memset(&from, 0, sizeof(from)); | ||
638 | if (packet_connection_is_on_socket()) { | ||
639 | fromlen = sizeof(from); | ||
640 | if (getpeername(packet_get_connection_in(), | ||
641 | (struct sockaddr *) & from, &fromlen) < 0) { | ||
642 | debug("getpeername: %.100s", strerror(errno)); | ||
643 | fatal_cleanup(); | ||
644 | } | ||
645 | } | ||
646 | |||
647 | /* Record that there was a login on that tty from the remote host. */ | ||
648 | record_login(pid, s->tty, pw->pw_name, pw->pw_uid, | ||
649 | get_remote_name_or_ip(), (struct sockaddr *)&from); | ||
650 | |||
651 | /* Done if .hushlogin exists. */ | ||
652 | snprintf(buf, sizeof(buf), "%.200s/.hushlogin", pw->pw_dir); | ||
653 | if (stat(buf, &st) >= 0) | ||
654 | return; | ||
655 | |||
656 | #ifdef USE_PAM | ||
657 | print_pam_messages(); | ||
658 | #endif /* USE_PAM */ | ||
659 | #ifdef WITH_AIXAUTHENTICATE | ||
660 | if (aixloginmsg && *aixloginmsg) | ||
661 | printf("%s\n", aixloginmsg); | ||
662 | #endif /* WITH_AIXAUTHENTICATE */ | ||
663 | |||
664 | /* | ||
665 | * Get the time when the user last logged in. 'buf' will be set | ||
666 | * to contain the hostname the last login was from. | ||
667 | */ | ||
668 | last_login_time = get_last_login_time(pw->pw_uid, pw->pw_name, | ||
669 | buf, sizeof(buf)); | ||
670 | if (last_login_time != 0) { | ||
671 | time_string = ctime(&last_login_time); | ||
672 | if (strchr(time_string, '\n')) | ||
673 | *strchr(time_string, '\n') = 0; | ||
674 | if (strcmp(buf, "") == 0) | ||
675 | printf("Last login: %s\r\n", time_string); | ||
676 | else | ||
677 | printf("Last login: %s from %s\r\n", time_string, buf); | ||
678 | } | ||
679 | if (options.print_motd) { | ||
680 | f = fopen("/etc/motd", "r"); | ||
681 | if (f) { | ||
682 | while (fgets(buf, sizeof(buf), f)) | ||
683 | fputs(buf, stdout); | ||
684 | fclose(f); | ||
685 | } | ||
686 | } | ||
687 | } | ||
688 | |||
702 | /* | 689 | /* |
703 | * Sets the value of the given variable in the environment. If the variable | 690 | * Sets the value of the given variable in the environment. If the variable |
704 | * already exists, its value is overriden. | 691 | * already exists, its value is overriden. |
@@ -1265,8 +1252,9 @@ do_child(const char *command, struct passwd * pw, const char *term, | |||
1265 | } else { | 1252 | } else { |
1266 | /* Launch login(1). */ | 1253 | /* Launch login(1). */ |
1267 | 1254 | ||
1268 | execl(LOGIN_PROGRAM, "login", "-h", get_remote_ipaddr(), | 1255 | execl(LOGIN_PROGRAM, "login", |
1269 | "-p", "-f", "--", pw->pw_name, NULL); | 1256 | "-h", get_remote_name_or_ip(), |
1257 | "-p", "-f", "--", pw->pw_name, NULL); | ||
1270 | 1258 | ||
1271 | /* Login couldn't be executed, die. */ | 1259 | /* Login couldn't be executed, die. */ |
1272 | 1260 | ||