📄 ssh.c
字号:
case 'm': if (mac_valid(optarg)) options.macs = xstrdup(optarg); else { fprintf(stderr, "Unknown mac type '%s'\n", optarg); exit(1); } break; case 'p': options.port = a2port(optarg); if (options.port == 0) { fprintf(stderr, "Bad port '%s'\n", optarg); exit(1); } break; case 'l': options.user = optarg; break; case 'L': case 'R': if (sscanf(optarg, "%5[0-9]:%255[^:]:%5[0-9]", sfwd_port, buf, sfwd_host_port) != 3 && sscanf(optarg, "%5[0-9]/%255[^/]/%5[0-9]", sfwd_port, buf, sfwd_host_port) != 3) { fprintf(stderr, "Bad forwarding specification '%s'\n", optarg); usage(); /* NOTREACHED */ } if ((fwd_port = a2port(sfwd_port)) == 0 || (fwd_host_port = a2port(sfwd_host_port)) == 0) { fprintf(stderr, "Bad forwarding port(s) '%s'\n", optarg); exit(1); } if (opt == 'L') add_local_forward(&options, fwd_port, buf, fwd_host_port); else if (opt == 'R') add_remote_forward(&options, fwd_port, buf, fwd_host_port); break; case 'D': fwd_port = a2port(optarg); if (fwd_port == 0) { fprintf(stderr, "Bad dynamic port '%s'\n", optarg); exit(1); } add_local_forward(&options, fwd_port, "socks4", 0); break; case 'C': options.compression = 1; break; case 'N': no_shell_flag = 1; no_tty_flag = 1; break; case 'T': no_tty_flag = 1; break; case 'o': dummy = 1; if (process_config_line(&options, host ? host : "", optarg, "command-line", 0, &dummy) != 0) exit(1); break; case 's': subsystem_flag = 1; break; case 'b': options.bind_address = optarg; break; case 'F': config = optarg; break; default: usage(); } } ac -= optind; av += optind; if (ac > 0 && !host && **av != '-') { if (strrchr(*av, '@')) { p = xstrdup(*av); cp = strrchr(p, '@'); if (cp == NULL || cp == p) usage(); options.user = p; *cp = '\0'; host = ++cp; } else host = *av; if (ac > 1) { optind = optreset = 1; goto again; } ac--, av++; } /* Check that we got a host name. */ if (!host) usage(); SSLeay_add_all_algorithms(); ERR_load_crypto_strings(); channel_set_af(IPv4or6); /* Initialize the command to execute on remote host. */ buffer_init(&command); /* * Save the command to execute on the remote host in a buffer. There * is no limit on the length of the command, except by the maximum * packet size. Also sets the tty flag if there is no command. */ if (!ac) { /* No command specified - execute shell on a tty. */ tty_flag = 1; if (subsystem_flag) { fprintf(stderr, "You must specify a subsystem to invoke.\n"); usage(); } } else { /* A command has been specified. Store it into the buffer. */ for (i = 0; i < ac; i++) { if (i) buffer_append(&command, " ", 1); buffer_append(&command, av[i], strlen(av[i])); } } /* Cannot fork to background if no command. */ if (fork_after_authentication_flag && buffer_len(&command) == 0 && !no_shell_flag) fatal("Cannot fork into background without a command to execute."); /* Allocate a tty by default if no command specified. */ if (buffer_len(&command) == 0) tty_flag = 1; /* Force no tty */ if (no_tty_flag) tty_flag = 0; /* Do not allocate a tty if stdin is not a tty. */ if (!isatty(fileno(stdin)) && !force_tty_flag) { if (tty_flag) log("Pseudo-terminal will not be allocated because stdin is not a terminal."); tty_flag = 0; } /* * Initialize "log" output. Since we are the client all output * actually goes to stderr. */ log_init(av[0], options.log_level == -1 ? SYSLOG_LEVEL_INFO : options.log_level, SYSLOG_FACILITY_USER, 1); /* * Read per-user configuration file. Ignore the system wide config * file if the user specifies a config file on the command line. */ if (config != NULL) { if (!read_config_file(config, host, &options)) fatal("Can't open user config file %.100s: " "%.100s", config, strerror(errno)); } else { snprintf(buf, sizeof buf, "%.100s/%.100s", pw->pw_dir, _PATH_SSH_USER_CONFFILE); (void)read_config_file(buf, host, &options); /* Read systemwide configuration file after use config. */ (void)read_config_file(_PATH_HOST_CONFIG_FILE, host, &options); } /* Fill configuration defaults. */ fill_default_options(&options); /* reinit */ log_init(av[0], options.log_level, SYSLOG_FACILITY_USER, 1); if (options.user == NULL) options.user = xstrdup(pw->pw_name); if (options.hostname != NULL) host = options.hostname; if (options.proxy_command != NULL && strcmp(options.proxy_command, "none") == 0) options.proxy_command = NULL; /* Disable rhosts authentication if not running as root. */ if (original_effective_uid != 0 || !options.use_privileged_port) { debug("Rhosts Authentication disabled, " "originating port will not be trusted."); options.rhosts_authentication = 0; } /* Open a connection to the remote host. */ if (ssh_connect(host, &hostaddr, options.port, IPv4or6, options.connection_attempts, original_effective_uid == 0 && options.use_privileged_port, options.proxy_command) != 0) exit(1); /* * If we successfully made the connection, load the host private key * in case we will need it later for combined rsa-rhosts * authentication. This must be done before releasing extra * privileges, because the file is only readable by root. * If we cannot access the private keys, load the public keys * instead and try to execute the ssh-keysign helper instead. */ sensitive_data.nkeys = 0; sensitive_data.keys = NULL; sensitive_data.external_keysign = 0; if (options.rhosts_rsa_authentication || options.hostbased_authentication) { sensitive_data.nkeys = 3; sensitive_data.keys = xmalloc(sensitive_data.nkeys * sizeof(Key)); PRIV_START; sensitive_data.keys[0] = key_load_private_type(KEY_RSA1, _PATH_HOST_KEY_FILE, "", NULL); sensitive_data.keys[1] = key_load_private_type(KEY_DSA, _PATH_HOST_DSA_KEY_FILE, "", NULL); sensitive_data.keys[2] = key_load_private_type(KEY_RSA, _PATH_HOST_RSA_KEY_FILE, "", NULL); PRIV_END; if (options.hostbased_authentication == 1 && sensitive_data.keys[0] == NULL && sensitive_data.keys[1] == NULL && sensitive_data.keys[2] == NULL) { sensitive_data.keys[1] = key_load_public( _PATH_HOST_DSA_KEY_FILE, NULL); sensitive_data.keys[2] = key_load_public( _PATH_HOST_RSA_KEY_FILE, NULL); sensitive_data.external_keysign = 1; } } /* * Get rid of any extra privileges that we may have. We will no * longer need them. Also, extra privileges could make it very hard * to read identity files and other non-world-readable files from the * user's home directory if it happens to be on a NFS volume where * root is mapped to nobody. */ seteuid(original_real_uid); setuid(original_real_uid); /* * Now that we are back to our own permissions, create ~/.ssh * directory if it doesn\'t already exist. */ snprintf(buf, sizeof buf, "%.100s%s%.100s", pw->pw_dir, strcmp(pw->pw_dir, "/") ? "/" : "", _PATH_SSH_USER_DIR); if (stat(buf, &st) < 0) if (mkdir(buf, 0700) < 0) error("Could not create directory '%.200s'.", buf); /* load options.identity_files */ load_public_identity_files(); /* Expand ~ in known host file names. */ /* XXX mem-leaks: */ options.system_hostfile = tilde_expand_filename(options.system_hostfile, original_real_uid); options.user_hostfile = tilde_expand_filename(options.user_hostfile, original_real_uid); options.system_hostfile2 = tilde_expand_filename(options.system_hostfile2, original_real_uid); options.user_hostfile2 = tilde_expand_filename(options.user_hostfile2, original_real_uid); signal(SIGPIPE, SIG_IGN); /* ignore SIGPIPE early */ /* Log into the remote system. This never returns if the login fails. */ ssh_login(&sensitive_data, host, (struct sockaddr *)&hostaddr, pw); /* We no longer need the private host keys. Clear them now. */ if (sensitive_data.nkeys != 0) { for (i = 0; i < sensitive_data.nkeys; i++) { if (sensitive_data.keys[i] != NULL) { /* Destroys contents safely */ debug3("clear hostkey %d", i); key_free(sensitive_data.keys[i]); sensitive_data.keys[i] = NULL; } } xfree(sensitive_data.keys); } for (i = 0; i < options.num_identity_files; i++) { if (options.identity_files[i]) { xfree(options.identity_files[i]); options.identity_files[i] = NULL; } if (options.identity_keys[i]) { key_free(options.identity_keys[i]); options.identity_keys[i] = NULL; } } exit_status = compat20 ? ssh_session2() : ssh_session(); packet_close(); /* * Send SIGHUP to proxy command if used. We don't wait() in * case it hangs and instead rely on init to reap the child */ if (proxy_command_pid > 1) kill(proxy_command_pid, SIGHUP); return exit_status;}static voidx11_get_proto(char **_proto, char **_data){ char line[512]; static char proto[512], data[512]; FILE *f; int got_data = 0, i; char *display; struct stat st; *_proto = proto; *_data = data; proto[0] = data[0] = '\0'; if (!options.xauth_location || (stat(options.xauth_location, &st) == -1)) { debug("No xauth program."); } else { if ((display = getenv("DISPLAY")) == NULL) { debug("x11_get_proto: DISPLAY not set"); return; } /* Try to get Xauthority information for the display. */ if (strncmp(display, "localhost:", 10) == 0) /* * Handle FamilyLocal case where $DISPLAY does * not match an authorization entry. For this we * just try "xauth list unix:displaynum.screennum". * XXX: "localhost" match to determine FamilyLocal * is not perfect. */ snprintf(line, sizeof line, "%s list unix:%s 2>" _PATH_DEVNULL, options.xauth_location, display+10); else snprintf(line, sizeof line, "%s list %.200s 2>" _PATH_DEVNULL, options.xauth_location, display); debug2("x11_get_proto: %s", line); f = popen(line, "r"); if (f && fgets(line, sizeof(line), f) && sscanf(line, "%*s %511s %511s", proto, data) == 2) got_data = 1; if (f) pclose(f); } /* * If we didn't get authentication data, just make up some * data. The forwarding code will check the validity of the * response anyway, and substitute this data. The X11 * server, however, will ignore this fake data and use * whatever authentication mechanisms it was using otherwise * for the local connection. */ if (!got_data) { u_int32_t rand = 0; log("Warning: No xauth data; using fake authentication data for X11 forwarding."); strlcpy(proto, "MIT-MAGIC-COOKIE-1", sizeof proto); for (i = 0; i < 16; i++) { if (i % 4 == 0) rand = arc4random(); snprintf(data + 2 * i, sizeof data - 2 * i, "%02x", rand & 0xff); rand >>= 8; } }}static voidssh_init_forwarding(void){ int success = 0; int i;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -