version 1.407, 2014/07/17 07:22:19 |
version 1.408, 2014/10/08 22:20:25 |
|
|
* 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(struct passwd *pw) |
process_config_files(const char *host_arg, struct passwd *pw, int post_canon) |
{ |
{ |
char buf[MAXPATHLEN]; |
char buf[MAXPATHLEN]; |
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, &options, |
!read_config_file(config, pw, host, host_arg, &options, |
SSHCONF_USERCONF)) |
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)); |
} else { |
} else { |
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, &options, |
(void)read_config_file(buf, pw, host, host_arg, |
SSHCONF_CHECKPERM|SSHCONF_USERCONF); |
&options, SSHCONF_CHECKPERM | SSHCONF_USERCONF | |
|
(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, host, |
(void)read_config_file(_PATH_HOST_CONFIG_FILE, pw, |
&options, 0); |
host, host_arg, &options, |
|
post_canon ? SSHCONF_POSTCANON : 0); |
} |
} |
} |
} |
|
|
|
/* Rewrite the port number in an addrinfo list of addresses */ |
|
static void |
|
set_addrinfo_port(struct addrinfo *addrs, int port) |
|
{ |
|
struct addrinfo *addr; |
|
|
|
for (addr = addrs; addr != NULL; addr = addr->ai_next) { |
|
switch (addr->ai_family) { |
|
case AF_INET: |
|
((struct sockaddr_in *)addr->ai_addr)-> |
|
sin_port = htons(port); |
|
break; |
|
case AF_INET6: |
|
((struct sockaddr_in6 *)addr->ai_addr)-> |
|
sin6_port = htons(port); |
|
break; |
|
} |
|
} |
|
} |
|
|
/* |
/* |
* Main program for the ssh client. |
* Main program for the ssh client. |
*/ |
*/ |
int |
int |
main(int ac, char **av) |
main(int ac, char **av) |
{ |
{ |
int i, r, opt, exit_status, use_syslog; |
int i, r, opt, exit_status, use_syslog, config_test = 0; |
char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg, *logfile; |
char *p, *cp, *line, *argv0, buf[MAXPATHLEN], *host_arg, *logfile; |
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; |
char thishost[NI_MAXHOST], shorthost[NI_MAXHOST], portstr[NI_MAXSERV]; |
char cname[NI_MAXHOST]; |
char cname[NI_MAXHOST]; |
|
|
|
|
again: |
again: |
while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" |
while ((opt = getopt(ac, av, "1246ab:c:e:fgi:kl:m:no:p:qstvx" |
"ACD:E:F:I:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { |
"ACD:E:F:GI:KL:MNO:PQ:R:S:TVw:W:XYy")) != -1) { |
switch (opt) { |
switch (opt) { |
case '1': |
case '1': |
options.protocol = SSH_PROTO_1; |
options.protocol = SSH_PROTO_1; |
|
|
case 'E': |
case 'E': |
logfile = xstrdup(optarg); |
logfile = xstrdup(optarg); |
break; |
break; |
|
case 'G': |
|
config_test = 1; |
|
break; |
case 'Y': |
case 'Y': |
options.forward_x11 = 1; |
options.forward_x11 = 1; |
options.forward_x11_trusted = 1; |
options.forward_x11_trusted = 1; |
|
|
break; |
break; |
case 'o': |
case 'o': |
line = xstrdup(optarg); |
line = xstrdup(optarg); |
if (process_config_line(&options, pw, host ? host : "", |
if (process_config_line(&options, pw, |
line, "command-line", 0, NULL, SSHCONF_USERCONF) |
host ? host : "", host ? host : "", line, |
!= 0) |
"command-line", 0, NULL, SSHCONF_USERCONF) != 0) |
exit(255); |
exit(255); |
free(line); |
free(line); |
break; |
break; |
|
|
); |
); |
|
|
/* Parse the configuration files */ |
/* Parse the configuration files */ |
process_config_files(pw); |
process_config_files(host_arg, pw, 0); |
|
|
/* Hostname canonicalisation needs a few options filled. */ |
/* Hostname canonicalisation needs a few options filled. */ |
fill_default_options_for_canonicalization(&options); |
fill_default_options_for_canonicalization(&options); |
|
|
"h", host, (char *)NULL); |
"h", host, (char *)NULL); |
free(host); |
free(host); |
host = cp; |
host = cp; |
|
free(options.hostname); |
|
options.hostname = xstrdup(host); |
} |
} |
|
|
/* If canonicalization requested then try to apply it */ |
/* If canonicalization requested then try to apply it */ |
|
|
} |
} |
|
|
/* |
/* |
* If the target hostname has changed as a result of canonicalisation |
* If canonicalisation is enabled then re-parse the configuration |
* then re-parse the configuration files as new stanzas may match. |
* files as new stanzas may match. |
*/ |
*/ |
if (strcasecmp(host_arg, host) != 0) { |
if (options.canonicalize_hostname != 0) { |
debug("Hostname has changed; re-reading configuration"); |
debug("Re-reading configuration after hostname " |
process_config_files(pw); |
"canonicalisation"); |
|
free(options.hostname); |
|
options.hostname = xstrdup(host); |
|
process_config_files(host_arg, pw, 1); |
|
/* |
|
* Address resolution happens early with canonicalisation |
|
* enabled and the port number may have changed since, so |
|
* reset it in address list |
|
*/ |
|
if (addrs != NULL && options.port > 0) |
|
set_addrinfo_port(addrs, options.port); |
} |
} |
|
|
/* Fill configuration defaults. */ |
/* Fill configuration defaults. */ |
|
|
free(cp); |
free(cp); |
} |
} |
free(conn_hash_hex); |
free(conn_hash_hex); |
|
|
|
if (config_test) { |
|
dump_client_config(&options, host); |
|
exit(0); |
|
} |
|
|
if (muxclient_command != 0 && options.control_path == NULL) |
if (muxclient_command != 0 && options.control_path == NULL) |
fatal("No ControlPath specified for \"-O\" command"); |
fatal("No ControlPath specified for \"-O\" command"); |