|
Lines 14-22
Link Here
|
| 14 |
#include <sys/types.h> |
14 |
#include <sys/types.h> |
| 15 |
#include <sys/socket.h> |
15 |
#include <sys/socket.h> |
| 16 |
#include <sys/queue.h> |
16 |
#include <sys/queue.h> |
|
|
17 |
#include <sys/sysctl.h> |
| 17 |
|
18 |
|
| 18 |
#include <netinet/in.h> |
19 |
#include <netinet/in.h> |
| 19 |
#include <netinet/ip.h> |
20 |
#include <netinet/ip.h> |
|
|
21 |
#include <net/route.h> |
| 20 |
|
22 |
|
| 21 |
#include <ctype.h> |
23 |
#include <ctype.h> |
| 22 |
#include <netdb.h> |
24 |
#include <netdb.h> |
|
Lines 53-60
Link Here
|
| 53 |
#include "myproposal.h" |
55 |
#include "myproposal.h" |
| 54 |
#include "digest.h" |
56 |
#include "digest.h" |
| 55 |
|
57 |
|
| 56 |
static void add_listen_addr(ServerOptions *, char *, int); |
58 |
static void add_listen_addr(ServerOptions *, const char *, |
| 57 |
static void add_one_listen_addr(ServerOptions *, char *, int); |
59 |
const char *, int); |
|
|
60 |
static void add_one_listen_addr(ServerOptions *, const char *, |
| 61 |
const char *, int); |
| 58 |
|
62 |
|
| 59 |
/* Use of privilege separation or not */ |
63 |
/* Use of privilege separation or not */ |
| 60 |
extern int use_privsep; |
64 |
extern int use_privsep; |
|
Lines 71-76
initialize_server_options(ServerOptions *options)
Link Here
|
| 71 |
options->queued_listen_addrs = NULL; |
75 |
options->queued_listen_addrs = NULL; |
| 72 |
options->num_queued_listens = 0; |
76 |
options->num_queued_listens = 0; |
| 73 |
options->listen_addrs = NULL; |
77 |
options->listen_addrs = NULL; |
|
|
78 |
options->num_listen_addrs = 0; |
| 74 |
options->address_family = -1; |
79 |
options->address_family = -1; |
| 75 |
options->num_host_key_files = 0; |
80 |
options->num_host_key_files = 0; |
| 76 |
options->num_host_cert_files = 0; |
81 |
options->num_host_cert_files = 0; |
|
Lines 235-241
fill_default_server_options(ServerOptions *options)
Link Here
|
| 235 |
if (options->address_family == -1) |
240 |
if (options->address_family == -1) |
| 236 |
options->address_family = AF_UNSPEC; |
241 |
options->address_family = AF_UNSPEC; |
| 237 |
if (options->listen_addrs == NULL) |
242 |
if (options->listen_addrs == NULL) |
| 238 |
add_listen_addr(options, NULL, 0); |
243 |
add_listen_addr(options, NULL, NULL, 0); |
| 239 |
if (options->pid_file == NULL) |
244 |
if (options->pid_file == NULL) |
| 240 |
options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE); |
245 |
options->pid_file = xstrdup(_PATH_SSH_DAEMON_PID_FILE); |
| 241 |
if (options->login_grace_time == -1) |
246 |
if (options->login_grace_time == -1) |
|
Lines 612-634
derelativise_path(const char *path)
Link Here
|
| 612 |
} |
617 |
} |
| 613 |
|
618 |
|
| 614 |
static void |
619 |
static void |
| 615 |
add_listen_addr(ServerOptions *options, char *addr, int port) |
620 |
add_listen_addr(ServerOptions *options, const char *addr, |
|
|
621 |
const char *rdomain, int port) |
| 616 |
{ |
622 |
{ |
| 617 |
u_int i; |
623 |
u_int i; |
| 618 |
|
624 |
|
| 619 |
if (port == 0) |
625 |
if (port > 0) |
| 620 |
for (i = 0; i < options->num_ports; i++) |
626 |
add_one_listen_addr(options, addr, rdomain, port); |
| 621 |
add_one_listen_addr(options, addr, options->ports[i]); |
627 |
else { |
| 622 |
else |
628 |
for (i = 0; i < options->num_ports; i++) { |
| 623 |
add_one_listen_addr(options, addr, port); |
629 |
add_one_listen_addr(options, addr, rdomain, |
|
|
630 |
options->ports[i]); |
| 631 |
} |
| 632 |
} |
| 624 |
} |
633 |
} |
| 625 |
|
634 |
|
| 626 |
static void |
635 |
static void |
| 627 |
add_one_listen_addr(ServerOptions *options, char *addr, int port) |
636 |
add_one_listen_addr(ServerOptions *options, const char *addr, |
|
|
637 |
const char *rdomain, int port) |
| 628 |
{ |
638 |
{ |
| 629 |
struct addrinfo hints, *ai, *aitop; |
639 |
struct addrinfo hints, *ai, *aitop; |
| 630 |
char strport[NI_MAXSERV]; |
640 |
char strport[NI_MAXSERV]; |
| 631 |
int gaierr; |
641 |
int gaierr; |
|
|
642 |
u_int i; |
| 643 |
|
| 644 |
/* Find listen_addrs entry for this rdomain */ |
| 645 |
for (i = 0; i < options->num_listen_addrs; i++) { |
| 646 |
if (rdomain == NULL && options->listen_addrs[i].rdomain == NULL) |
| 647 |
break; |
| 648 |
if (rdomain == NULL || options->listen_addrs[i].rdomain == NULL) |
| 649 |
continue; |
| 650 |
if (strcmp(rdomain, options->listen_addrs[i].rdomain) == 0) |
| 651 |
break; |
| 652 |
} |
| 653 |
if (i >= options->num_listen_addrs) { |
| 654 |
/* No entry for this rdomain; allocate one */ |
| 655 |
if (i >= INT_MAX) |
| 656 |
fatal("%s: too many listen addresses", __func__); |
| 657 |
options->listen_addrs = xrecallocarray(options->listen_addrs, |
| 658 |
options->num_listen_addrs, options->num_listen_addrs + 1, |
| 659 |
sizeof(*options->listen_addrs)); |
| 660 |
i = options->num_listen_addrs++; |
| 661 |
if (rdomain != NULL) |
| 662 |
options->listen_addrs[i].rdomain = xstrdup(rdomain); |
| 663 |
} |
| 664 |
/* options->listen_addrs[i] points to the addresses for this rdomain */ |
| 632 |
|
665 |
|
| 633 |
memset(&hints, 0, sizeof(hints)); |
666 |
memset(&hints, 0, sizeof(hints)); |
| 634 |
hints.ai_family = options->address_family; |
667 |
hints.ai_family = options->address_family; |
|
Lines 641-648
add_one_listen_addr(ServerOptions *options, char *addr, int port)
Link Here
|
| 641 |
ssh_gai_strerror(gaierr)); |
674 |
ssh_gai_strerror(gaierr)); |
| 642 |
for (ai = aitop; ai->ai_next; ai = ai->ai_next) |
675 |
for (ai = aitop; ai->ai_next; ai = ai->ai_next) |
| 643 |
; |
676 |
; |
| 644 |
ai->ai_next = options->listen_addrs; |
677 |
ai->ai_next = options->listen_addrs[i].addrs; |
| 645 |
options->listen_addrs = aitop; |
678 |
options->listen_addrs[i].addrs = aitop; |
|
|
679 |
} |
| 680 |
|
| 681 |
/* Returns nonzero if the routing domain name is valid */ |
| 682 |
static int |
| 683 |
valid_rdomain(const char *name) |
| 684 |
{ |
| 685 |
const char *errstr; |
| 686 |
long long num; |
| 687 |
struct rt_tableinfo info; |
| 688 |
int mib[6]; |
| 689 |
size_t miblen = sizeof(mib); |
| 690 |
|
| 691 |
if (name == NULL) |
| 692 |
return 1; |
| 693 |
|
| 694 |
num = strtonum(name, 0, 255, &errstr); |
| 695 |
if (errstr != NULL) |
| 696 |
return 0; |
| 697 |
|
| 698 |
/* Check whether the table actually exists */ |
| 699 |
memset(mib, 0, sizeof(mib)); |
| 700 |
mib[0] = CTL_NET; |
| 701 |
mib[1] = PF_ROUTE; |
| 702 |
mib[4] = NET_RT_TABLE; |
| 703 |
mib[5] = (int)num; |
| 704 |
if (sysctl(mib, 6, &info, &miblen, NULL, 0) == -1) |
| 705 |
return 0; |
| 706 |
|
| 707 |
return 1; |
| 646 |
} |
708 |
} |
| 647 |
|
709 |
|
| 648 |
/* |
710 |
/* |
|
Lines 650-667
add_one_listen_addr(ServerOptions *options, char *addr, int port)
Link Here
|
| 650 |
* and AddressFamily options. |
712 |
* and AddressFamily options. |
| 651 |
*/ |
713 |
*/ |
| 652 |
static void |
714 |
static void |
| 653 |
queue_listen_addr(ServerOptions *options, char *addr, int port) |
715 |
queue_listen_addr(ServerOptions *options, const char *addr, |
|
|
716 |
const char *rdomain, int port) |
| 654 |
{ |
717 |
{ |
| 655 |
options->queued_listen_addrs = xreallocarray( |
718 |
struct queued_listenaddr *qla; |
| 656 |
options->queued_listen_addrs, options->num_queued_listens + 1, |
719 |
|
| 657 |
sizeof(addr)); |
720 |
options->queued_listen_addrs = xrecallocarray( |
| 658 |
options->queued_listen_ports = xreallocarray( |
721 |
options->queued_listen_addrs, |
| 659 |
options->queued_listen_ports, options->num_queued_listens + 1, |
722 |
options->num_queued_listens, options->num_queued_listens + 1, |
| 660 |
sizeof(port)); |
723 |
sizeof(*options->queued_listen_addrs)); |
| 661 |
options->queued_listen_addrs[options->num_queued_listens] = |
724 |
qla = &options->queued_listen_addrs[options->num_queued_listens++]; |
| 662 |
xstrdup(addr); |
725 |
qla->addr = xstrdup(addr); |
| 663 |
options->queued_listen_ports[options->num_queued_listens] = port; |
726 |
qla->port = port; |
| 664 |
options->num_queued_listens++; |
727 |
qla->rdomain = rdomain == NULL ? NULL : xstrdup(rdomain); |
| 665 |
} |
728 |
} |
| 666 |
|
729 |
|
| 667 |
/* |
730 |
/* |
|
Lines 671-676
static void
Link Here
|
| 671 |
process_queued_listen_addrs(ServerOptions *options) |
734 |
process_queued_listen_addrs(ServerOptions *options) |
| 672 |
{ |
735 |
{ |
| 673 |
u_int i; |
736 |
u_int i; |
|
|
737 |
struct queued_listenaddr *qla; |
| 674 |
|
738 |
|
| 675 |
if (options->num_ports == 0) |
739 |
if (options->num_ports == 0) |
| 676 |
options->ports[options->num_ports++] = SSH_DEFAULT_PORT; |
740 |
options->ports[options->num_ports++] = SSH_DEFAULT_PORT; |
|
Lines 678-692
process_queued_listen_addrs(ServerOptions *options)
Link Here
|
| 678 |
options->address_family = AF_UNSPEC; |
742 |
options->address_family = AF_UNSPEC; |
| 679 |
|
743 |
|
| 680 |
for (i = 0; i < options->num_queued_listens; i++) { |
744 |
for (i = 0; i < options->num_queued_listens; i++) { |
| 681 |
add_listen_addr(options, options->queued_listen_addrs[i], |
745 |
qla = &options->queued_listen_addrs[i]; |
| 682 |
options->queued_listen_ports[i]); |
746 |
add_listen_addr(options, qla->addr, qla->rdomain, qla->port); |
| 683 |
free(options->queued_listen_addrs[i]); |
747 |
free(qla->addr); |
| 684 |
options->queued_listen_addrs[i] = NULL; |
748 |
free(qla->rdomain); |
| 685 |
} |
749 |
} |
| 686 |
free(options->queued_listen_addrs); |
750 |
free(options->queued_listen_addrs); |
| 687 |
options->queued_listen_addrs = NULL; |
751 |
options->queued_listen_addrs = NULL; |
| 688 |
free(options->queued_listen_ports); |
|
|
| 689 |
options->queued_listen_ports = NULL; |
| 690 |
options->num_queued_listens = 0; |
752 |
options->num_queued_listens = 0; |
| 691 |
} |
753 |
} |
| 692 |
|
754 |
|
|
Lines 1075-1094
process_server_config_line(ServerOptions *options, char *line,
Link Here
|
| 1075 |
/* check for bare IPv6 address: no "[]" and 2 or more ":" */ |
1137 |
/* check for bare IPv6 address: no "[]" and 2 or more ":" */ |
| 1076 |
if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL |
1138 |
if (strchr(arg, '[') == NULL && (p = strchr(arg, ':')) != NULL |
| 1077 |
&& strchr(p+1, ':') != NULL) { |
1139 |
&& strchr(p+1, ':') != NULL) { |
| 1078 |
queue_listen_addr(options, arg, 0); |
|
|
| 1079 |
break; |
| 1080 |
} |
| 1081 |
p = hpdelim(&arg); |
| 1082 |
if (p == NULL) |
| 1083 |
fatal("%s line %d: bad address:port usage", |
| 1084 |
filename, linenum); |
| 1085 |
p = cleanhostname(p); |
| 1086 |
if (arg == NULL) |
| 1087 |
port = 0; |
1140 |
port = 0; |
| 1088 |
else if ((port = a2port(arg)) <= 0) |
1141 |
p = arg; |
| 1089 |
fatal("%s line %d: bad port number", filename, linenum); |
1142 |
} else { |
|
|
1143 |
p = hpdelim(&arg); |
| 1144 |
if (p == NULL) |
| 1145 |
fatal("%s line %d: bad address:port usage", |
| 1146 |
filename, linenum); |
| 1147 |
p = cleanhostname(p); |
| 1148 |
if (arg == NULL) |
| 1149 |
port = 0; |
| 1150 |
else if ((port = a2port(arg)) <= 0) |
| 1151 |
fatal("%s line %d: bad port number", |
| 1152 |
filename, linenum); |
| 1153 |
} |
| 1154 |
/* Optional routing table */ |
| 1155 |
arg2 = NULL; |
| 1156 |
if ((arg = strdelim(&cp)) != NULL) { |
| 1157 |
if (strcmp(arg, "rdomain") != 0 || |
| 1158 |
(arg2 = strdelim(&cp)) == NULL) |
| 1159 |
fatal("%s line %d: bad ListenAddress syntax", |
| 1160 |
filename, linenum); |
| 1161 |
if (!valid_rdomain(arg2)) |
| 1162 |
fatal("%s line %d: bad routing domain", |
| 1163 |
filename, linenum); |
| 1164 |
} |
| 1090 |
|
1165 |
|
| 1091 |
queue_listen_addr(options, p, port); |
1166 |
queue_listen_addr(options, p, arg2, port); |
| 1092 |
|
1167 |
|
| 1093 |
break; |
1168 |
break; |
| 1094 |
|
1169 |
|
|
Lines 2199-2243
dump_cfg_strarray_oneline(ServerOpCodes code, u_int count, char **vals)
Link Here
|
| 2199 |
printf("\n"); |
2274 |
printf("\n"); |
| 2200 |
} |
2275 |
} |
| 2201 |
|
2276 |
|
| 2202 |
void |
2277 |
static char * |
| 2203 |
dump_config(ServerOptions *o) |
2278 |
format_listen_addrs(struct listenaddr *la) |
| 2204 |
{ |
2279 |
{ |
| 2205 |
u_int i; |
2280 |
int r; |
| 2206 |
int ret; |
|
|
| 2207 |
struct addrinfo *ai; |
2281 |
struct addrinfo *ai; |
| 2208 |
char addr[NI_MAXHOST], port[NI_MAXSERV], *s = NULL; |
2282 |
char addr[NI_MAXHOST], port[NI_MAXSERV]; |
| 2209 |
char *laddr1 = xstrdup(""), *laddr2 = NULL; |
2283 |
char *laddr1 = xstrdup(""), *laddr2 = NULL; |
| 2210 |
|
2284 |
|
| 2211 |
/* these are usually at the top of the config */ |
|
|
| 2212 |
for (i = 0; i < o->num_ports; i++) |
| 2213 |
printf("port %d\n", o->ports[i]); |
| 2214 |
dump_cfg_fmtint(sAddressFamily, o->address_family); |
| 2215 |
|
| 2216 |
/* |
2285 |
/* |
| 2217 |
* ListenAddress must be after Port. add_one_listen_addr pushes |
2286 |
* ListenAddress must be after Port. add_one_listen_addr pushes |
| 2218 |
* addresses onto a stack, so to maintain ordering we need to |
2287 |
* addresses onto a stack, so to maintain ordering we need to |
| 2219 |
* print these in reverse order. |
2288 |
* print these in reverse order. |
| 2220 |
*/ |
2289 |
*/ |
| 2221 |
for (ai = o->listen_addrs; ai; ai = ai->ai_next) { |
2290 |
for (ai = la->addrs; ai; ai = ai->ai_next) { |
| 2222 |
if ((ret = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, |
2291 |
if ((r = getnameinfo(ai->ai_addr, ai->ai_addrlen, addr, |
| 2223 |
sizeof(addr), port, sizeof(port), |
2292 |
sizeof(addr), port, sizeof(port), |
| 2224 |
NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { |
2293 |
NI_NUMERICHOST|NI_NUMERICSERV)) != 0) { |
| 2225 |
error("getnameinfo failed: %.100s", |
2294 |
error("getnameinfo: %.100s", ssh_gai_strerror(r)); |
| 2226 |
(ret != EAI_SYSTEM) ? gai_strerror(ret) : |
2295 |
continue; |
| 2227 |
strerror(errno)); |
2296 |
} |
|
|
2297 |
laddr2 = laddr1; |
| 2298 |
if (ai->ai_family == AF_INET6) { |
| 2299 |
xasprintf(&laddr1, "listenaddress [%s]:%s%s%s\n%s", |
| 2300 |
addr, port, |
| 2301 |
la->rdomain == NULL ? "" : " rdomain ", |
| 2302 |
la->rdomain == NULL ? "" : la->rdomain, |
| 2303 |
laddr2); |
| 2228 |
} else { |
2304 |
} else { |
| 2229 |
laddr2 = laddr1; |
2305 |
xasprintf(&laddr1, "listenaddress %s:%s%s%s\n%s", |
| 2230 |
if (ai->ai_family == AF_INET6) |
2306 |
addr, port, |
| 2231 |
xasprintf(&laddr1, "listenaddress [%s]:%s\n%s", |
2307 |
la->rdomain == NULL ? "" : " rdomain ", |
| 2232 |
addr, port, laddr2); |
2308 |
la->rdomain == NULL ? "" : la->rdomain, |
| 2233 |
else |
2309 |
laddr2); |
| 2234 |
xasprintf(&laddr1, "listenaddress %s:%s\n%s", |
|
|
| 2235 |
addr, port, laddr2); |
| 2236 |
free(laddr2); |
| 2237 |
} |
2310 |
} |
|
|
2311 |
free(laddr2); |
| 2312 |
} |
| 2313 |
return laddr1; |
| 2314 |
} |
| 2315 |
|
| 2316 |
void |
| 2317 |
dump_config(ServerOptions *o) |
| 2318 |
{ |
| 2319 |
char *s; |
| 2320 |
u_int i; |
| 2321 |
|
| 2322 |
/* these are usually at the top of the config */ |
| 2323 |
for (i = 0; i < o->num_ports; i++) |
| 2324 |
printf("port %d\n", o->ports[i]); |
| 2325 |
dump_cfg_fmtint(sAddressFamily, o->address_family); |
| 2326 |
|
| 2327 |
for (i = 0; i < o->num_listen_addrs; i++) { |
| 2328 |
s = format_listen_addrs(&o->listen_addrs[i]); |
| 2329 |
printf("%s", s); |
| 2330 |
free(s); |
| 2238 |
} |
2331 |
} |
| 2239 |
printf("%s", laddr1); |
|
|
| 2240 |
free(laddr1); |
| 2241 |
|
2332 |
|
| 2242 |
/* integer arguments */ |
2333 |
/* integer arguments */ |
| 2243 |
dump_cfg_int(sLoginGraceTime, o->login_grace_time); |
2334 |
dump_cfg_int(sLoginGraceTime, o->login_grace_time); |