📄 session.c
字号:
static intsession_pty_req(Session *s){ u_int len; int n_bytes; if (no_pty_flag) { debug("Allocating a pty not permitted for this authentication."); return 0; } if (s->ttyfd != -1) { packet_disconnect("Protocol error: you already have a pty."); return 0; } /* Get the time and hostname when the user last logged in. */ if (options.print_lastlog) { s->hostname[0] = '\0'; s->last_login_time = get_last_login_time(s->pw->pw_uid, s->pw->pw_name, s->hostname, sizeof(s->hostname)); } s->term = packet_get_string(&len); if (compat20) { s->col = packet_get_int(); s->row = packet_get_int(); } else { s->row = packet_get_int(); s->col = packet_get_int(); } s->xpixel = packet_get_int(); s->ypixel = packet_get_int(); if (strcmp(s->term, "") == 0) { xfree(s->term); s->term = NULL; } /* Allocate a pty and open it. */ debug("Allocating pty."); if (!PRIVSEP(pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)))) { if (s->term) xfree(s->term); s->term = NULL; s->ptyfd = -1; s->ttyfd = -1; error("session_pty_req: session %d alloc failed", s->self); return 0; } debug("session_pty_req: session %d alloc %s", s->self, s->tty); /* for SSH1 the tty modes length is not given */ if (!compat20) n_bytes = packet_remaining(); tty_parse_modes(s->ttyfd, &n_bytes); /* * Add a cleanup function to clear the utmp entry and record logout * time in case we call fatal() (e.g., the connection gets closed). */ fatal_add_cleanup(session_pty_cleanup, (void *)s); if (!use_privsep) pty_setowner(s->pw, s->tty); /* Set window size from the packet. */ pty_change_window_size(s->ptyfd, s->row, s->col, s->xpixel, s->ypixel); packet_check_eom(); session_proctitle(s); return 1;}static intsession_subsystem_req(Session *s){ struct stat st; u_int len; int success = 0; char *cmd, *subsys = packet_get_string(&len); int i; packet_check_eom(); log("subsystem request for %.100s", subsys); for (i = 0; i < options.num_subsystems; i++) { if (strcmp(subsys, options.subsystem_name[i]) == 0) { cmd = options.subsystem_command[i]; if (stat(cmd, &st) < 0) { error("subsystem: cannot stat %s: %s", cmd, strerror(errno)); break; } debug("subsystem: exec() %s", cmd); s->is_subsystem = 1; do_exec(s, cmd); success = 1; break; } } if (!success) log("subsystem request for %.100s failed, subsystem not found", subsys); xfree(subsys); return success;}static intsession_x11_req(Session *s){ int success; s->single_connection = packet_get_char(); s->auth_proto = packet_get_string(NULL); s->auth_data = packet_get_string(NULL); s->screen = packet_get_int(); packet_check_eom(); success = session_setup_x11fwd(s); if (!success) { xfree(s->auth_proto); xfree(s->auth_data); s->auth_proto = NULL; s->auth_data = NULL; } return success;}static intsession_shell_req(Session *s){ packet_check_eom(); do_exec(s, NULL); return 1;}static intsession_exec_req(Session *s){ u_int len; char *command = packet_get_string(&len); packet_check_eom(); do_exec(s, command); xfree(command); return 1;}static intsession_auth_agent_req(Session *s){ static int called = 0; packet_check_eom(); if (no_agent_forwarding_flag) { debug("session_auth_agent_req: no_agent_forwarding_flag"); return 0; } if (called) { return 0; } else { called = 1; return auth_input_request_forwarding(s->pw); }}intsession_input_channel_req(Channel *c, const char *rtype){ int success = 0; Session *s; if ((s = session_by_channel(c->self)) == NULL) { log("session_input_channel_req: no session %d req %.100s", c->self, rtype); return 0; } debug("session_input_channel_req: session %d req %s", s->self, rtype); /* * a session is in LARVAL state until a shell, a command * or a subsystem is executed */ if (c->type == SSH_CHANNEL_LARVAL) { if (strcmp(rtype, "shell") == 0) { success = session_shell_req(s); } else if (strcmp(rtype, "exec") == 0) { success = session_exec_req(s); } else if (strcmp(rtype, "pty-req") == 0) { success = session_pty_req(s); } else if (strcmp(rtype, "x11-req") == 0) { success = session_x11_req(s); } else if (strcmp(rtype, "auth-agent-req@openssh.com") == 0) { success = session_auth_agent_req(s); } else if (strcmp(rtype, "subsystem") == 0) { success = session_subsystem_req(s); } } if (strcmp(rtype, "window-change") == 0) { success = session_window_change_req(s); } return success;}voidsession_set_fds(Session *s, int fdin, int fdout, int fderr){ if (!compat20) fatal("session_set_fds: called for proto != 2.0"); /* * now that have a child and a pipe to the child, * we can activate our channel and register the fd's */ if (s->chanid == -1) fatal("no channel for session %d", s->self); channel_set_fds(s->chanid, fdout, fdin, fderr, fderr == -1 ? CHAN_EXTENDED_IGNORE : CHAN_EXTENDED_READ, 1, CHAN_SES_WINDOW_DEFAULT);}/* * Function to perform pty cleanup. Also called if we get aborted abnormally * (e.g., due to a dropped connection). */voidsession_pty_cleanup2(void *session){ Session *s = session; if (s == NULL) { error("session_pty_cleanup: no session"); return; } if (s->ttyfd == -1) return; debug("session_pty_cleanup: session %d release %s", s->self, s->tty); /* Record that the user has logged out. */ if (s->pid != 0) record_logout(s->pid, s->tty, s->pw->pw_name); /* Release the pseudo-tty. */ if (getuid() == 0) pty_release(s->tty); /* * Close the server side of the socket pairs. We must do this after * the pty cleanup, so that another process doesn't get this pty * while we're still cleaning up. */ if (close(s->ptymaster) < 0) error("close(s->ptymaster/%d): %s", s->ptymaster, strerror(errno)); /* unlink pty from session */ s->ttyfd = -1;}voidsession_pty_cleanup(void *session){ PRIVSEP(session_pty_cleanup2(session));}static voidsession_exit_message(Session *s, int status){ Channel *c; if ((c = channel_lookup(s->chanid)) == NULL) fatal("session_exit_message: session %d: no channel %d", s->self, s->chanid); debug("session_exit_message: session %d channel %d pid %ld", s->self, s->chanid, (long)s->pid); if (WIFEXITED(status)) { channel_request_start(s->chanid, "exit-status", 0); packet_put_int(WEXITSTATUS(status)); packet_send(); } else if (WIFSIGNALED(status)) { channel_request_start(s->chanid, "exit-signal", 0); packet_put_int(WTERMSIG(status));#ifdef WCOREDUMP packet_put_char(WCOREDUMP(status));#else /* WCOREDUMP */ packet_put_char(0);#endif /* WCOREDUMP */ packet_put_cstring(""); packet_put_cstring(""); packet_send(); } else { /* Some weird exit cause. Just exit. */ packet_disconnect("wait returned status %04x.", status); } /* disconnect channel */ debug("session_exit_message: release channel %d", s->chanid); channel_cancel_cleanup(s->chanid); /* * emulate a write failure with 'chan_write_failed', nobody will be * interested in data we write. * Note that we must not call 'chan_read_failed', since there could * be some more data waiting in the pipe. */ if (c->ostate != CHAN_OUTPUT_CLOSED) chan_write_failed(c); s->chanid = -1;}voidsession_close(Session *s){ debug("session_close: session %d pid %ld", s->self, (long)s->pid); if (s->ttyfd != -1) { fatal_remove_cleanup(session_pty_cleanup, (void *)s); session_pty_cleanup(s); } if (s->term) xfree(s->term); if (s->display) xfree(s->display); if (s->auth_display) xfree(s->auth_display); if (s->auth_data) xfree(s->auth_data); if (s->auth_proto) xfree(s->auth_proto); s->used = 0; session_proctitle(s);}voidsession_close_by_pid(pid_t pid, int status){ Session *s = session_by_pid(pid); if (s == NULL) { debug("session_close_by_pid: no session for pid %ld", (long)pid); return; } if (s->chanid != -1) session_exit_message(s, status); session_close(s);}/* * this is called when a channel dies before * the session 'child' itself dies */voidsession_close_by_channel(int id, void *arg){ Session *s = session_by_channel(id); if (s == NULL) { debug("session_close_by_channel: no session for id %d", id); return; } debug("session_close_by_channel: channel %d child %ld", id, (long)s->pid); if (s->pid != 0) { debug("session_close_by_channel: channel %d: has child", id); /* * delay detach of session, but release pty, since * the fd's to the child are already closed */ if (s->ttyfd != -1) { fatal_remove_cleanup(session_pty_cleanup, (void *)s); session_pty_cleanup(s); } return; } /* detach by removing callback */ channel_cancel_cleanup(s->chanid); s->chanid = -1; session_close(s);}voidsession_destroy_all(void (*closefunc)(Session *)){ int i; for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; if (s->used) { if (closefunc != NULL) closefunc(s); else session_close(s); } }}static char *session_tty_list(void){ static char buf[1024]; int i; buf[0] = '\0'; for (i = 0; i < MAX_SESSIONS; i++) { Session *s = &sessions[i]; if (s->used && s->ttyfd != -1) { if (buf[0] != '\0') strlcat(buf, ",", sizeof buf); strlcat(buf, strrchr(s->tty, '/') + 1, sizeof buf); } } if (buf[0] == '\0') strlcpy(buf, "notty", sizeof buf); return buf;}voidsession_proctitle(Session *s){ if (s->pw == NULL) error("no user for session %d", s->self); else setproctitle("%s@%s", s->pw->pw_name, session_tty_list());}intsession_setup_x11fwd(Session *s){ struct stat st; char display[512], auth_display[512]; char hostname[MAXHOSTNAMELEN]; if (no_x11_forwarding_flag) { packet_send_debug("X11 forwarding disabled in user configuration file."); return 0; } if (!options.x11_forwarding) { debug("X11 forwarding disabled in server configuration file."); return 0; } if (!options.xauth_location || (stat(options.xauth_location, &st) == -1)) { packet_send_debug("No xauth program; cannot forward with spoofing."); return 0; } if (options.use_login) { packet_send_debug("X11 forwarding disabled; " "not compatible with UseLogin=yes."); return 0; } if (s->display != NULL) { debug("X11 display already set."); return 0; } s->display_number = x11_create_display_inet(options.x11_display_offset, options.x11_use_localhost, s->single_connection); if (s->display_number == -1) { debug("x11_create_display_inet failed."); return 0; } /* Set up a suitable value for the DISPLAY variable. */ if (gethostname(hostname, sizeof(hostname)) < 0) fatal("gethostname: %.100s", strerror(errno)); /* * auth_display must be used as the displayname when the * authorization entry is added with xauth(1). This will be * different than the DISPLAY string for localhost displays. */ if (options.x11_use_localhost) { snprintf(display, sizeof display, "localhost:%d.%d", s->display_number, s->screen); snprintf(auth_display, sizeof auth_display, "unix:%d.%d", s->display_number, s->screen); s->display = xstrdup(display); s->auth_display = xstrdup(auth_display); } else {#ifdef IPADDR_IN_DISPLAY struct hostent *he; struct in_addr my_addr; he = gethostbyname(hostname); if (he == NULL) { error("Can't get IP address for X11 DISPLAY."); packet_send_debug("Can't get IP address for X11 DISPLAY."); return 0; } memcpy(&my_addr, he->h_addr_list[0], sizeof(struct in_addr)); snprintf(display, sizeof display, "%.50s:%d.%d", inet_ntoa(my_addr), s->display_number, s->screen);#else snprintf(display, sizeof display, "%.400s:%d.%d", hostname, s->display_number, s->screen);#endif s->display = xstrdup(display); s->auth_display = xstrdup(display); } return 1;}static voiddo_authenticated2(Authctxt *authctxt){ server_loop2(authctxt);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -