version 1.465, 2017/10/21 23:06:24 |
version 1.466, 2017/10/23 05:08:00 |
|
|
*/ |
*/ |
char *host; |
char *host; |
|
|
|
/* Various strings used to to percent_expand() arguments */ |
|
static char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; |
|
static char uidstr[32], *host_arg, *conn_hash_hex; |
|
|
/* socket address the host resolves to */ |
/* socket address the host resolves to */ |
struct sockaddr_storage hostaddr; |
struct sockaddr_storage hostaddr; |
|
|
|
|
exit(255); |
exit(255); |
} |
} |
|
|
static int ssh_session2(struct ssh *); |
static int ssh_session2(struct ssh *, struct passwd *); |
static void load_public_identity_files(void); |
static void load_public_identity_files(struct passwd *); |
static void main_sigchld_handler(int); |
static void main_sigchld_handler(int); |
|
|
/* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */ |
/* ~/ expand a list of paths. NB. assumes path[n] is heap-allocated. */ |
|
|
* file if the user specifies a config file on the command line. |
* file if the user specifies a config file on the command line. |
*/ |
*/ |
static void |
static void |
process_config_files(const char *host_arg, struct passwd *pw, int post_canon) |
process_config_files(const char *host_name, struct passwd *pw, int post_canon) |
{ |
{ |
char buf[PATH_MAX]; |
char buf[PATH_MAX]; |
int r; |
int r; |
|
|
if (config != NULL) { |
if (config != NULL) { |
if (strcasecmp(config, "none") != 0 && |
if (strcasecmp(config, "none") != 0 && |
!read_config_file(config, pw, host, host_arg, &options, |
!read_config_file(config, pw, host, host_name, &options, |
SSHCONF_USERCONF | (post_canon ? SSHCONF_POSTCANON : 0))) |
SSHCONF_USERCONF | (post_canon ? SSHCONF_POSTCANON : 0))) |
fatal("Can't open user config file %.100s: " |
fatal("Can't open user config file %.100s: " |
"%.100s", config, strerror(errno)); |
"%.100s", config, strerror(errno)); |
|
|
r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, |
r = snprintf(buf, sizeof buf, "%s/%s", pw->pw_dir, |
_PATH_SSH_USER_CONFFILE); |
_PATH_SSH_USER_CONFFILE); |
if (r > 0 && (size_t)r < sizeof(buf)) |
if (r > 0 && (size_t)r < sizeof(buf)) |
(void)read_config_file(buf, pw, host, host_arg, |
(void)read_config_file(buf, pw, host, host_name, |
&options, SSHCONF_CHECKPERM | SSHCONF_USERCONF | |
&options, SSHCONF_CHECKPERM | SSHCONF_USERCONF | |
(post_canon ? SSHCONF_POSTCANON : 0)); |
(post_canon ? SSHCONF_POSTCANON : 0)); |
|
|
/* Read systemwide configuration file after user config. */ |
/* Read systemwide configuration file after user config. */ |
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, |
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, |
host, host_arg, &options, |
host, host_name, &options, |
post_canon ? SSHCONF_POSTCANON : 0); |
post_canon ? SSHCONF_POSTCANON : 0); |
} |
} |
} |
} |
|
|
struct ssh *ssh = NULL; |
struct ssh *ssh = NULL; |
int i, r, opt, exit_status, use_syslog, direct, timeout_ms; |
int i, r, opt, exit_status, use_syslog, direct, timeout_ms; |
int config_test = 0, opt_terminated = 0; |
int config_test = 0, opt_terminated = 0; |
char *p, *cp, *line, *argv0, buf[PATH_MAX], *host_arg, *logfile; |
char *p, *cp, *line, *argv0, buf[PATH_MAX], *logfile; |
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; |
char cname[NI_MAXHOST]; |
char cname[NI_MAXHOST], uidstr[32], *conn_hash_hex; |
|
struct stat st; |
struct stat st; |
struct passwd *pw; |
struct passwd *pw; |
extern int optind, optreset; |
extern int optind, optreset; |
|
|
if (options.user == NULL) |
if (options.user == NULL) |
options.user = xstrdup(pw->pw_name); |
options.user = xstrdup(pw->pw_name); |
|
|
|
/* Set up strings used to percent_expand() arguments */ |
if (gethostname(thishost, sizeof(thishost)) == -1) |
if (gethostname(thishost, sizeof(thishost)) == -1) |
fatal("gethostname: %s", strerror(errno)); |
fatal("gethostname: %s", strerror(errno)); |
strlcpy(shorthost, thishost, sizeof(shorthost)); |
strlcpy(shorthost, thishost, sizeof(shorthost)); |
|
|
ssh_digest_free(md); |
ssh_digest_free(md); |
conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); |
conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1)); |
|
|
if (options.local_command != NULL) { |
/* |
debug3("expanding LocalCommand: %s", options.local_command); |
* Expand tokens in arguments. NB. LocalCommand is expanded later, |
cp = options.local_command; |
* after port-forwarding is set up, so it may pick up any local |
options.local_command = percent_expand(cp, |
* tunnel interface name allocated. |
"C", conn_hash_hex, |
*/ |
"L", shorthost, |
|
"d", pw->pw_dir, |
|
"h", host, |
|
"l", thishost, |
|
"n", host_arg, |
|
"p", portstr, |
|
"r", options.user, |
|
"u", pw->pw_name, |
|
(char *)NULL); |
|
debug3("expanded LocalCommand: %s", options.local_command); |
|
free(cp); |
|
} |
|
|
|
if (options.remote_command != NULL) { |
if (options.remote_command != NULL) { |
debug3("expanding RemoteCommand: %s", options.remote_command); |
debug3("expanding RemoteCommand: %s", options.remote_command); |
cp = options.remote_command; |
cp = options.remote_command; |
|
|
free(cp); |
free(cp); |
buffer_append(&command, options.remote_command, |
buffer_append(&command, options.remote_command, |
strlen(options.remote_command)); |
strlen(options.remote_command)); |
|
|
} |
} |
|
|
if (options.control_path != NULL) { |
if (options.control_path != NULL) { |
|
|
} |
} |
|
|
/* load options.identity_files */ |
/* load options.identity_files */ |
load_public_identity_files(); |
load_public_identity_files(pw); |
|
|
/* optionally set the SSH_AUTHSOCKET_ENV_NAME varibale */ |
/* optionally set the SSH_AUTHSOCKET_ENV_NAME varibale */ |
if (options.identity_agent && |
if (options.identity_agent && |
|
|
} |
} |
|
|
skip_connect: |
skip_connect: |
exit_status = ssh_session2(ssh); |
exit_status = ssh_session2(ssh, pw); |
packet_close(); |
packet_close(); |
|
|
if (options.control_path != NULL && muxserver_sock != -1) |
if (options.control_path != NULL && muxserver_sock != -1) |
|
|
} |
} |
|
|
static void |
static void |
ssh_init_forwarding(struct ssh *ssh) |
ssh_init_forwarding(struct ssh *ssh, char **ifname) |
{ |
{ |
int success = 0; |
int success = 0; |
int i; |
int i; |
|
|
|
|
/* Initiate tunnel forwarding. */ |
/* Initiate tunnel forwarding. */ |
if (options.tun_open != SSH_TUNMODE_NO) { |
if (options.tun_open != SSH_TUNMODE_NO) { |
if (client_request_tun_fwd(ssh, options.tun_open, |
if ((*ifname = client_request_tun_fwd(ssh, |
options.tun_local, options.tun_remote) == -1) { |
options.tun_open, options.tun_local, |
|
options.tun_remote)) == NULL) { |
if (options.exit_on_forward_failure) |
if (options.exit_on_forward_failure) |
fatal("Could not request tunnel forwarding."); |
fatal("Could not request tunnel forwarding."); |
else |
else |
|
|
} |
} |
|
|
static int |
static int |
ssh_session2(struct ssh *ssh) |
ssh_session2(struct ssh *ssh, struct passwd *pw) |
{ |
{ |
int id = -1; |
int id = -1; |
|
char *cp, *tun_fwd_ifname = NULL; |
|
|
/* XXX should be pre-session */ |
/* XXX should be pre-session */ |
if (!options.control_persist) |
if (!options.control_persist) |
ssh_init_stdio_forwarding(ssh); |
ssh_init_stdio_forwarding(ssh); |
ssh_init_forwarding(ssh); |
|
|
|
|
ssh_init_forwarding(ssh, &tun_fwd_ifname); |
|
|
|
if (options.local_command != NULL) { |
|
debug3("expanding LocalCommand: %s", options.local_command); |
|
cp = options.local_command; |
|
options.local_command = percent_expand(cp, |
|
"C", conn_hash_hex, |
|
"L", shorthost, |
|
"d", pw->pw_dir, |
|
"h", host, |
|
"l", thishost, |
|
"n", host_arg, |
|
"p", portstr, |
|
"r", options.user, |
|
"u", pw->pw_name, |
|
"T", tun_fwd_ifname == NULL ? "NONE" : tun_fwd_ifname, |
|
(char *)NULL); |
|
debug3("expanded LocalCommand: %s", options.local_command); |
|
free(cp); |
|
} |
|
|
/* Start listening for multiplex clients */ |
/* Start listening for multiplex clients */ |
if (!packet_get_mux()) |
if (!packet_get_mux()) |
muxserver_listen(ssh); |
muxserver_listen(ssh); |
|
|
|
|
/* Loads all IdentityFile and CertificateFile keys */ |
/* Loads all IdentityFile and CertificateFile keys */ |
static void |
static void |
load_public_identity_files(void) |
load_public_identity_files(struct passwd *pw) |
{ |
{ |
char *filename, *cp, thishost[NI_MAXHOST]; |
char *filename, *cp; |
char *pwdir = NULL, *pwname = NULL; |
|
struct sshkey *public; |
struct sshkey *public; |
struct passwd *pw; |
|
int i; |
int i; |
u_int n_ids, n_certs; |
u_int n_ids, n_certs; |
char *identity_files[SSH_MAX_IDENTITY_FILES]; |
char *identity_files[SSH_MAX_IDENTITY_FILES]; |
|
|
#endif /* ENABLE_PKCS11 */ |
#endif /* ENABLE_PKCS11 */ |
if ((pw = getpwuid(original_real_uid)) == NULL) |
if ((pw = getpwuid(original_real_uid)) == NULL) |
fatal("load_public_identity_files: getpwuid failed"); |
fatal("load_public_identity_files: getpwuid failed"); |
pwname = xstrdup(pw->pw_name); |
|
pwdir = xstrdup(pw->pw_dir); |
|
if (gethostname(thishost, sizeof(thishost)) == -1) |
|
fatal("load_public_identity_files: gethostname: %s", |
|
strerror(errno)); |
|
for (i = 0; i < options.num_identity_files; i++) { |
for (i = 0; i < options.num_identity_files; i++) { |
if (n_ids >= SSH_MAX_IDENTITY_FILES || |
if (n_ids >= SSH_MAX_IDENTITY_FILES || |
strcasecmp(options.identity_files[i], "none") == 0) { |
strcasecmp(options.identity_files[i], "none") == 0) { |
|
|
} |
} |
cp = tilde_expand_filename(options.identity_files[i], |
cp = tilde_expand_filename(options.identity_files[i], |
original_real_uid); |
original_real_uid); |
filename = percent_expand(cp, "d", pwdir, |
filename = percent_expand(cp, "d", pw->pw_dir, |
"u", pwname, "l", thishost, "h", host, |
"u", pw->pw_name, "l", thishost, "h", host, |
"r", options.user, (char *)NULL); |
"r", options.user, (char *)NULL); |
free(cp); |
free(cp); |
public = key_load_public(filename, NULL); |
public = key_load_public(filename, NULL); |
|
|
for (i = 0; i < options.num_certificate_files; i++) { |
for (i = 0; i < options.num_certificate_files; i++) { |
cp = tilde_expand_filename(options.certificate_files[i], |
cp = tilde_expand_filename(options.certificate_files[i], |
original_real_uid); |
original_real_uid); |
filename = percent_expand(cp, "d", pwdir, |
filename = percent_expand(cp, "d", pw->pw_dir, |
"u", pwname, "l", thishost, "h", host, |
"u", pw->pw_name, "l", thishost, "h", host, |
"r", options.user, (char *)NULL); |
"r", options.user, (char *)NULL); |
free(cp); |
free(cp); |
|
|
|
|
memcpy(options.certificate_files, |
memcpy(options.certificate_files, |
certificate_files, sizeof(certificate_files)); |
certificate_files, sizeof(certificate_files)); |
memcpy(options.certificates, certificates, sizeof(certificates)); |
memcpy(options.certificates, certificates, sizeof(certificates)); |
|
|
explicit_bzero(pwname, strlen(pwname)); |
|
free(pwname); |
|
explicit_bzero(pwdir, strlen(pwdir)); |
|
free(pwdir); |
|
} |
} |
|
|
static void |
static void |