|
Lines 21-26
Link Here
|
| 21 |
#include <net/route.h> |
21 |
#include <net/route.h> |
| 22 |
|
22 |
|
| 23 |
#include <ctype.h> |
23 |
#include <ctype.h> |
|
|
24 |
#include <glob.h> |
| 24 |
#include <netdb.h> |
25 |
#include <netdb.h> |
| 25 |
#include <pwd.h> |
26 |
#include <pwd.h> |
| 26 |
#include <stdio.h> |
27 |
#include <stdio.h> |
|
Lines 60-65
static void add_listen_addr(ServerOptions *, const char *,
Link Here
|
| 60 |
const char *, int); |
61 |
const char *, int); |
| 61 |
static void add_one_listen_addr(ServerOptions *, const char *, |
62 |
static void add_one_listen_addr(ServerOptions *, const char *, |
| 62 |
const char *, int); |
63 |
const char *, int); |
|
|
64 |
void parse_server_config_depth(ServerOptions *options, const char *filename, |
| 65 |
struct sshbuf *conf, struct include_list *includes, |
| 66 |
struct connection_info *connectinfo, int flags, int *activep, int depth); |
| 63 |
|
67 |
|
| 64 |
/* Use of privilege separation or not */ |
68 |
/* Use of privilege separation or not */ |
| 65 |
extern int use_privsep; |
69 |
extern int use_privsep; |
|
Lines 492-498
typedef enum {
Link Here
|
| 492 |
sAcceptEnv, sSetEnv, sPermitTunnel, |
496 |
sAcceptEnv, sSetEnv, sPermitTunnel, |
| 493 |
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, |
497 |
sMatch, sPermitOpen, sPermitListen, sForceCommand, sChrootDirectory, |
| 494 |
sUsePrivilegeSeparation, sAllowAgentForwarding, |
498 |
sUsePrivilegeSeparation, sAllowAgentForwarding, |
| 495 |
sHostCertificate, |
499 |
sHostCertificate, sInclude, |
| 496 |
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, |
500 |
sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, |
| 497 |
sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, |
501 |
sAuthorizedPrincipalsCommand, sAuthorizedPrincipalsCommandUser, |
| 498 |
sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum, |
502 |
sKexAlgorithms, sCASignatureAlgorithms, sIPQoS, sVersionAddendum, |
|
Lines 504-512
typedef enum {
Link Here
|
| 504 |
sDeprecated, sIgnore, sUnsupported |
508 |
sDeprecated, sIgnore, sUnsupported |
| 505 |
} ServerOpCodes; |
509 |
} ServerOpCodes; |
| 506 |
|
510 |
|
| 507 |
#define SSHCFG_GLOBAL 0x01 /* allowed in main section of sshd_config */ |
511 |
#define SSHCFG_GLOBAL 0x01 /* allowed in main section of config */ |
| 508 |
#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ |
512 |
#define SSHCFG_MATCH 0x02 /* allowed inside a Match section */ |
| 509 |
#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) |
513 |
#define SSHCFG_ALL (SSHCFG_GLOBAL|SSHCFG_MATCH) |
|
|
514 |
#define SSHCFG_NEVERMATCH 0x04 /* Match never matches; internal only */ |
| 510 |
|
515 |
|
| 511 |
/* Textual representation of the tokens. */ |
516 |
/* Textual representation of the tokens. */ |
| 512 |
static struct { |
517 |
static struct { |
|
Lines 619-624
static struct {
Link Here
|
| 619 |
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, |
624 |
{ "trustedusercakeys", sTrustedUserCAKeys, SSHCFG_ALL }, |
| 620 |
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, |
625 |
{ "authorizedprincipalsfile", sAuthorizedPrincipalsFile, SSHCFG_ALL }, |
| 621 |
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, |
626 |
{ "kexalgorithms", sKexAlgorithms, SSHCFG_GLOBAL }, |
|
|
627 |
{ "include", sInclude, SSHCFG_ALL }, |
| 622 |
{ "ipqos", sIPQoS, SSHCFG_ALL }, |
628 |
{ "ipqos", sIPQoS, SSHCFG_ALL }, |
| 623 |
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, |
629 |
{ "authorizedkeyscommand", sAuthorizedKeysCommand, SSHCFG_ALL }, |
| 624 |
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, |
630 |
{ "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, |
|
Lines 1183-1195
static const struct multistate multistate_tcpfwd[] = {
Link Here
|
| 1183 |
{ NULL, -1 } |
1189 |
{ NULL, -1 } |
| 1184 |
}; |
1190 |
}; |
| 1185 |
|
1191 |
|
| 1186 |
int |
1192 |
static int |
| 1187 |
process_server_config_line(ServerOptions *options, char *line, |
1193 |
process_server_config_line_depth(ServerOptions *options, char *line, |
| 1188 |
const char *filename, int linenum, int *activep, |
1194 |
const char *filename, int linenum, int *activep, |
| 1189 |
struct connection_info *connectinfo) |
1195 |
struct connection_info *connectinfo, int inc_flags, int depth, |
|
|
1196 |
struct include_list *includes) |
| 1190 |
{ |
1197 |
{ |
| 1191 |
char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p; |
1198 |
char ch, *cp, ***chararrayptr, **charptr, *arg, *arg2, *p; |
| 1192 |
int cmdline = 0, *intptr, value, value2, n, port; |
1199 |
int cmdline = 0, *intptr, value, value2, n, port, oactive, r, found; |
| 1193 |
SyslogFacility *log_facility_ptr; |
1200 |
SyslogFacility *log_facility_ptr; |
| 1194 |
LogLevel *log_level_ptr; |
1201 |
LogLevel *log_level_ptr; |
| 1195 |
ServerOpCodes opcode; |
1202 |
ServerOpCodes opcode; |
|
Lines 1198-1203
process_server_config_line(ServerOptions *options, char *line,
Link Here
|
| 1198 |
long long val64; |
1205 |
long long val64; |
| 1199 |
const struct multistate *multistate_ptr; |
1206 |
const struct multistate *multistate_ptr; |
| 1200 |
const char *errstr; |
1207 |
const char *errstr; |
|
|
1208 |
struct include_item *item; |
| 1209 |
glob_t gbuf; |
| 1201 |
|
1210 |
|
| 1202 |
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */ |
1211 |
/* Strip trailing whitespace. Allow \f (form feed) at EOL only */ |
| 1203 |
if ((len = strlen(line)) == 0) |
1212 |
if ((len = strlen(line)) == 0) |
|
Lines 1224-1230
process_server_config_line(ServerOptions *options, char *line,
Link Here
|
| 1224 |
cmdline = 1; |
1233 |
cmdline = 1; |
| 1225 |
activep = &cmdline; |
1234 |
activep = &cmdline; |
| 1226 |
} |
1235 |
} |
| 1227 |
if (*activep && opcode != sMatch) |
1236 |
if (*activep && opcode != sMatch && opcode != sInclude) |
| 1228 |
debug3("%s:%d setting %s %s", filename, linenum, arg, cp); |
1237 |
debug3("%s:%d setting %s %s", filename, linenum, arg, cp); |
| 1229 |
if (*activep == 0 && !(flags & SSHCFG_MATCH)) { |
1238 |
if (*activep == 0 && !(flags & SSHCFG_MATCH)) { |
| 1230 |
if (connectinfo == NULL) { |
1239 |
if (connectinfo == NULL) { |
|
Lines 1891-1896
process_server_config_line(ServerOptions *options, char *line,
Link Here
|
| 1891 |
*intptr = value; |
1900 |
*intptr = value; |
| 1892 |
break; |
1901 |
break; |
| 1893 |
|
1902 |
|
|
|
1903 |
case sInclude: |
| 1904 |
if (cmdline) { |
| 1905 |
fatal("Include directive not supported as a " |
| 1906 |
"command-line option"); |
| 1907 |
} |
| 1908 |
value = 0; |
| 1909 |
while ((arg2 = strdelim(&cp)) != NULL && *arg2 != '\0') { |
| 1910 |
value++; |
| 1911 |
found = 0; |
| 1912 |
if (*arg2 != '/' && *arg2 != '~') { |
| 1913 |
xasprintf(&arg, "%s/%s", SSHDIR, arg); |
| 1914 |
} else |
| 1915 |
arg = xstrdup(arg2); |
| 1916 |
|
| 1917 |
/* |
| 1918 |
* Don't let included files clobber the containing |
| 1919 |
* file's Match state. |
| 1920 |
*/ |
| 1921 |
oactive = *activep; |
| 1922 |
|
| 1923 |
/* consult cache of include files */ |
| 1924 |
TAILQ_FOREACH(item, includes, entry) { |
| 1925 |
if (strcmp(item->selector, arg) != 0) |
| 1926 |
continue; |
| 1927 |
if (item->filename != NULL) { |
| 1928 |
parse_server_config_depth(options, |
| 1929 |
item->filename, item->contents, |
| 1930 |
includes, connectinfo, |
| 1931 |
(oactive ? 0 : SSHCFG_NEVERMATCH), |
| 1932 |
activep, depth + 1); |
| 1933 |
} |
| 1934 |
found = 1; |
| 1935 |
*activep = oactive; |
| 1936 |
} |
| 1937 |
if (found != 0) { |
| 1938 |
free(arg); |
| 1939 |
continue; |
| 1940 |
} |
| 1941 |
|
| 1942 |
/* requested glob was not in cache */ |
| 1943 |
debug2("%s line %d: new include %s", |
| 1944 |
filename, linenum, arg); |
| 1945 |
if ((r = glob(arg, 0, NULL, &gbuf)) != 0) { |
| 1946 |
if (r != GLOB_NOMATCH) { |
| 1947 |
fatal("%s line %d: include \"%s\" " |
| 1948 |
"glob failed", filename, |
| 1949 |
linenum, arg); |
| 1950 |
} |
| 1951 |
/* |
| 1952 |
* If no entry matched then record a |
| 1953 |
* placeholder to skip later glob calls. |
| 1954 |
*/ |
| 1955 |
debug2("%s line %d: no match for %s", |
| 1956 |
filename, linenum, arg); |
| 1957 |
item = xcalloc(1, sizeof(*item)); |
| 1958 |
item->selector = strdup(arg); |
| 1959 |
TAILQ_INSERT_TAIL(includes, |
| 1960 |
item, entry); |
| 1961 |
} |
| 1962 |
if (gbuf.gl_pathc > INT_MAX) |
| 1963 |
fatal("%s: too manu glob results", __func__); |
| 1964 |
for (n = 0; n < (int)gbuf.gl_pathc; n++) { |
| 1965 |
debug2("%s line %d: including %s", |
| 1966 |
filename, linenum, gbuf.gl_pathv[n]); |
| 1967 |
item = xcalloc(1, sizeof(*item)); |
| 1968 |
item->selector = strdup(arg); |
| 1969 |
item->filename = strdup(gbuf.gl_pathv[n]); |
| 1970 |
item->contents = sshbuf_new(); |
| 1971 |
load_server_config(item->filename, |
| 1972 |
item->contents); |
| 1973 |
parse_server_config_depth(options, |
| 1974 |
item->filename, item->contents, |
| 1975 |
includes, connectinfo, |
| 1976 |
(oactive ? 0 : SSHCFG_NEVERMATCH), |
| 1977 |
activep, depth + 1); |
| 1978 |
*activep = oactive; |
| 1979 |
TAILQ_INSERT_TAIL(includes, item, entry); |
| 1980 |
} |
| 1981 |
globfree(&gbuf); |
| 1982 |
free(arg); |
| 1983 |
} |
| 1984 |
if (value == 0) { |
| 1985 |
fatal("%s line %d: Include missing filename argument", |
| 1986 |
filename, linenum); |
| 1987 |
} |
| 1988 |
break; |
| 1989 |
|
| 1894 |
case sMatch: |
1990 |
case sMatch: |
| 1895 |
if (cmdline) |
1991 |
if (cmdline) |
| 1896 |
fatal("Match directive not supported as a command-line " |
1992 |
fatal("Match directive not supported as a command-line " |
|
Lines 1899-1905
process_server_config_line(ServerOptions *options, char *line,
Link Here
|
| 1899 |
if (value < 0) |
1995 |
if (value < 0) |
| 1900 |
fatal("%s line %d: Bad Match condition", filename, |
1996 |
fatal("%s line %d: Bad Match condition", filename, |
| 1901 |
linenum); |
1997 |
linenum); |
| 1902 |
*activep = value; |
1998 |
*activep = (inc_flags & SSHCFG_NEVERMATCH) ? 0 : value; |
| 1903 |
break; |
1999 |
break; |
| 1904 |
|
2000 |
|
| 1905 |
case sPermitListen: |
2001 |
case sPermitListen: |
|
Lines 2193-2198
process_server_config_line(ServerOptions *options, char *line,
Link Here
|
| 2193 |
return 0; |
2289 |
return 0; |
| 2194 |
} |
2290 |
} |
| 2195 |
|
2291 |
|
|
|
2292 |
int |
| 2293 |
process_server_config_line(ServerOptions *options, char *line, |
| 2294 |
const char *filename, int linenum, int *activep, |
| 2295 |
struct connection_info *connectinfo, struct include_list *includes) |
| 2296 |
{ |
| 2297 |
return process_server_config_line_depth(options, line, filename, |
| 2298 |
linenum, activep, connectinfo, 0, 0, includes); |
| 2299 |
} |
| 2300 |
|
| 2301 |
|
| 2196 |
/* Reads the server configuration file. */ |
2302 |
/* Reads the server configuration file. */ |
| 2197 |
|
2303 |
|
| 2198 |
void |
2304 |
void |
|
Lines 2231-2242
load_server_config(const char *filename, struct sshbuf *conf)
Link Here
|
| 2231 |
|
2337 |
|
| 2232 |
void |
2338 |
void |
| 2233 |
parse_server_match_config(ServerOptions *options, |
2339 |
parse_server_match_config(ServerOptions *options, |
| 2234 |
struct connection_info *connectinfo) |
2340 |
struct include_list *includes, struct connection_info *connectinfo) |
| 2235 |
{ |
2341 |
{ |
| 2236 |
ServerOptions mo; |
2342 |
ServerOptions mo; |
| 2237 |
|
2343 |
|
| 2238 |
initialize_server_options(&mo); |
2344 |
initialize_server_options(&mo); |
| 2239 |
parse_server_config(&mo, "reprocess config", cfg, connectinfo); |
2345 |
parse_server_config(&mo, "reprocess config", cfg, includes, |
|
|
2346 |
connectinfo); |
| 2240 |
copy_set_server_options(options, &mo, 0); |
2347 |
copy_set_server_options(options, &mo, 0); |
| 2241 |
} |
2348 |
} |
| 2242 |
|
2349 |
|
|
Lines 2380-2401
copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
Link Here
|
| 2380 |
#undef M_CP_STROPT |
2487 |
#undef M_CP_STROPT |
| 2381 |
#undef M_CP_STRARRAYOPT |
2488 |
#undef M_CP_STRARRAYOPT |
| 2382 |
|
2489 |
|
|
|
2490 |
#define SERVCONF_MAX_DEPTH 16 |
| 2383 |
void |
2491 |
void |
| 2384 |
parse_server_config(ServerOptions *options, const char *filename, |
2492 |
parse_server_config_depth(ServerOptions *options, const char *filename, |
| 2385 |
struct sshbuf *conf, struct connection_info *connectinfo) |
2493 |
struct sshbuf *conf, struct include_list *includes, |
|
|
2494 |
struct connection_info *connectinfo, int flags, int *activep, int depth) |
| 2386 |
{ |
2495 |
{ |
| 2387 |
int active, linenum, bad_options = 0; |
2496 |
int linenum, bad_options = 0; |
| 2388 |
char *cp, *obuf, *cbuf; |
2497 |
char *cp, *obuf, *cbuf; |
| 2389 |
|
2498 |
|
|
|
2499 |
if (depth < 0 || depth > SERVCONF_MAX_DEPTH) |
| 2500 |
fatal("Too many recursive configuration includes"); |
| 2501 |
|
| 2390 |
debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf)); |
2502 |
debug2("%s: config %s len %zu", __func__, filename, sshbuf_len(conf)); |
| 2391 |
|
2503 |
|
| 2392 |
if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) |
2504 |
if ((obuf = cbuf = sshbuf_dup_string(conf)) == NULL) |
| 2393 |
fatal("%s: sshbuf_dup_string failed", __func__); |
2505 |
fatal("%s: sshbuf_dup_string failed", __func__); |
| 2394 |
active = connectinfo ? 0 : 1; |
|
|
| 2395 |
linenum = 1; |
2506 |
linenum = 1; |
| 2396 |
while ((cp = strsep(&cbuf, "\n")) != NULL) { |
2507 |
while ((cp = strsep(&cbuf, "\n")) != NULL) { |
| 2397 |
if (process_server_config_line(options, cp, filename, |
2508 |
if (process_server_config_line_depth(options, cp, |
| 2398 |
linenum++, &active, connectinfo) != 0) |
2509 |
filename, linenum++, activep, connectinfo, flags, |
|
|
2510 |
depth, includes) != 0) |
| 2399 |
bad_options++; |
2511 |
bad_options++; |
| 2400 |
} |
2512 |
} |
| 2401 |
free(obuf); |
2513 |
free(obuf); |
|
Lines 2405-2410
parse_server_config(ServerOptions *options, const char *filename,
Link Here
|
| 2405 |
process_queued_listen_addrs(options); |
2517 |
process_queued_listen_addrs(options); |
| 2406 |
} |
2518 |
} |
| 2407 |
|
2519 |
|
|
|
2520 |
void |
| 2521 |
parse_server_config(ServerOptions *options, const char *filename, |
| 2522 |
struct sshbuf *conf, struct include_list *includes, |
| 2523 |
struct connection_info *connectinfo) |
| 2524 |
{ |
| 2525 |
int active = connectinfo ? 0 : 1; |
| 2526 |
parse_server_config_depth(options, filename, conf, includes, |
| 2527 |
connectinfo, 0, &active, 0); |
| 2528 |
} |
| 2529 |
|
| 2408 |
static const char * |
2530 |
static const char * |
| 2409 |
fmt_multistate_int(int val, const struct multistate *m) |
2531 |
fmt_multistate_int(int val, const struct multistate *m) |
| 2410 |
{ |
2532 |
{ |