Changeset View
Changeset View
Standalone View
Standalone View
contrib/tcp_wrappers/options.c
Show First 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | |||||
static void allow_option(); /* execute "allow" option */ | static void allow_option(); /* execute "allow" option */ | ||||
static void deny_option(); /* execute "deny" option */ | static void deny_option(); /* execute "deny" option */ | ||||
static void banners_option(); /* execute "banners path" option */ | static void banners_option(); /* execute "banners path" option */ | ||||
/* Structure of the options table. */ | /* Structure of the options table. */ | ||||
struct option { | struct option { | ||||
char *name; /* keyword name, case is ignored */ | char *name; /* keyword name, case is ignored */ | ||||
void (*func) (); /* function that does the real work */ | void (*func) (char *value, struct request_info *request); | ||||
/* function that does the real work */ | |||||
int flags; /* see below... */ | int flags; /* see below... */ | ||||
}; | }; | ||||
#define NEED_ARG (1<<1) /* option requires argument */ | #define NEED_ARG (1<<1) /* option requires argument */ | ||||
#define USE_LAST (1<<2) /* option must be last */ | #define USE_LAST (1<<2) /* option must be last */ | ||||
#define OPT_ARG (1<<3) /* option has optional argument */ | #define OPT_ARG (1<<3) /* option has optional argument */ | ||||
#define EXPAND_ARG (1<<4) /* do %x expansion on argument */ | #define EXPAND_ARG (1<<4) /* do %x expansion on argument */ | ||||
Show All 20 Lines | static struct option option_table[] = { | ||||
"allow", allow_option, USE_LAST, | "allow", allow_option, USE_LAST, | ||||
"deny", deny_option, USE_LAST, | "deny", deny_option, USE_LAST, | ||||
"banners", banners_option, NEED_ARG, | "banners", banners_option, NEED_ARG, | ||||
0, | 0, | ||||
}; | }; | ||||
/* process_options - process access control options */ | /* process_options - process access control options */ | ||||
void process_options(options, request) | void process_options(char *options, struct request_info *request) | ||||
char *options; | |||||
struct request_info *request; | |||||
{ | { | ||||
char *key; | char *key; | ||||
char *value; | char *value; | ||||
char *curr_opt; | char *curr_opt; | ||||
char *next_opt; | char *next_opt; | ||||
struct option *op; | struct option *op; | ||||
char bf[BUFSIZ]; | char bf[BUFSIZ]; | ||||
▲ Show 20 Lines • Show All 67 Lines • ▼ Show 20 Lines | |||||
char *value; | char *value; | ||||
struct request_info *request; | struct request_info *request; | ||||
{ | { | ||||
longjmp(tcpd_buf, AC_DENY); | longjmp(tcpd_buf, AC_DENY); | ||||
} | } | ||||
/* banners_option - expand %<char>, terminate each line with CRLF */ | /* banners_option - expand %<char>, terminate each line with CRLF */ | ||||
static void banners_option(value, request) | static void banners_option(char *value, struct request_info *request) | ||||
char *value; | |||||
struct request_info *request; | |||||
{ | { | ||||
char path[MAXPATHNAMELEN]; | char path[MAXPATHNAMELEN]; | ||||
char ibuf[BUFSIZ]; | char ibuf[BUFSIZ]; | ||||
char obuf[2 * BUFSIZ]; | char obuf[2 * BUFSIZ]; | ||||
struct stat st; | struct stat st; | ||||
int ch; | int ch; | ||||
FILE *fp; | FILE *fp; | ||||
Show All 13 Lines | static void banners_option(char *value, struct request_info *request) | ||||
tcpd_warn("%s: %m", value); | tcpd_warn("%s: %m", value); | ||||
} | } | ||||
} | } | ||||
/* group_option - switch group id */ | /* group_option - switch group id */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void group_option(value, request) | static void group_option(char *value, struct request_info *request) | ||||
char *value; | |||||
struct request_info *request; | |||||
{ | { | ||||
struct group *grp; | struct group *grp; | ||||
struct group *getgrnam(); | struct group *getgrnam(); | ||||
if ((grp = getgrnam(value)) == 0) | if ((grp = getgrnam(value)) == 0) | ||||
tcpd_jump("unknown group: \"%s\"", value); | tcpd_jump("unknown group: \"%s\"", value); | ||||
endgrent(); | endgrent(); | ||||
if (dry_run == 0 && setgid(grp->gr_gid)) | if (dry_run == 0 && setgid(grp->gr_gid)) | ||||
tcpd_jump("setgid(%s): %m", value); | tcpd_jump("setgid(%s): %m", value); | ||||
} | } | ||||
/* user_option - switch user id */ | /* user_option - switch user id */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void user_option(value, request) | static void user_option(char *value, struct request_info *request) | ||||
char *value; | |||||
struct request_info *request; | |||||
{ | { | ||||
struct passwd *pwd; | struct passwd *pwd; | ||||
struct passwd *getpwnam(); | struct passwd *getpwnam(); | ||||
char *group; | char *group; | ||||
if ((group = split_at(value, '.')) != 0) | if ((group = split_at(value, '.')) != 0) | ||||
group_option(group, request); | group_option(group, request); | ||||
if ((pwd = getpwnam(value)) == 0) | if ((pwd = getpwnam(value)) == 0) | ||||
tcpd_jump("unknown user: \"%s\"", value); | tcpd_jump("unknown user: \"%s\"", value); | ||||
endpwent(); | endpwent(); | ||||
if (dry_run == 0 && setuid(pwd->pw_uid)) | if (dry_run == 0 && setuid(pwd->pw_uid)) | ||||
tcpd_jump("setuid(%s): %m", value); | tcpd_jump("setuid(%s): %m", value); | ||||
} | } | ||||
/* umask_option - set file creation mask */ | /* umask_option - set file creation mask */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void umask_option(value, request) | static void umask_option(char *value, struct request_info *request) | ||||
char *value; | |||||
struct request_info *request; | |||||
{ | { | ||||
unsigned mask; | unsigned mask; | ||||
char junk; | char junk; | ||||
if (sscanf(value, "%o%c", &mask, &junk) != 1 || (mask & 0777) != mask) | if (sscanf(value, "%o%c", &mask, &junk) != 1 || (mask & 0777) != mask) | ||||
tcpd_jump("bad umask value: \"%s\"", value); | tcpd_jump("bad umask value: \"%s\"", value); | ||||
(void) umask(mask); | (void) umask(mask); | ||||
} | } | ||||
/* spawn_option - spawn a shell command and wait */ | /* spawn_option - spawn a shell command and wait */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void spawn_option(value, request) | static void spawn_option(char *value, struct request_info *request) | ||||
char *value; | |||||
struct request_info *request; | |||||
{ | { | ||||
if (dry_run == 0) | if (dry_run == 0) | ||||
shell_cmd(value); | shell_cmd(value); | ||||
} | } | ||||
/* linger_option - set the socket linger time (Marc Boucher <marc@cam.org>) */ | /* linger_option - set the socket linger time (Marc Boucher <marc@cam.org>) */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void linger_option(value, request) | static void linger_option(char *value, struct request_info *request) | ||||
char *value; | |||||
struct request_info *request; | |||||
{ | { | ||||
struct linger linger; | struct linger linger; | ||||
char junk; | char junk; | ||||
if (sscanf(value, "%d%c", &linger.l_linger, &junk) != 1 | if (sscanf(value, "%d%c", &linger.l_linger, &junk) != 1 | ||||
|| linger.l_linger < 0) | || linger.l_linger < 0) | ||||
tcpd_jump("bad linger value: \"%s\"", value); | tcpd_jump("bad linger value: \"%s\"", value); | ||||
if (dry_run == 0) { | if (dry_run == 0) { | ||||
linger.l_onoff = (linger.l_linger != 0); | linger.l_onoff = (linger.l_linger != 0); | ||||
if (setsockopt(request->fd, SOL_SOCKET, SO_LINGER, (char *) &linger, | if (setsockopt(request->fd, SOL_SOCKET, SO_LINGER, (char *) &linger, | ||||
sizeof(linger)) < 0) | sizeof(linger)) < 0) | ||||
tcpd_warn("setsockopt SO_LINGER %d: %m", linger.l_linger); | tcpd_warn("setsockopt SO_LINGER %d: %m", linger.l_linger); | ||||
} | } | ||||
} | } | ||||
/* keepalive_option - set the socket keepalive option */ | /* keepalive_option - set the socket keepalive option */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void keepalive_option(value, request) | static void keepalive_option(char *value, struct request_info *request) | ||||
char *value; | |||||
struct request_info *request; | |||||
{ | { | ||||
static int on = 1; | static int on = 1; | ||||
if (dry_run == 0 && setsockopt(request->fd, SOL_SOCKET, SO_KEEPALIVE, | if (dry_run == 0 && setsockopt(request->fd, SOL_SOCKET, SO_KEEPALIVE, | ||||
(char *) &on, sizeof(on)) < 0) | (char *) &on, sizeof(on)) < 0) | ||||
tcpd_warn("setsockopt SO_KEEPALIVE: %m"); | tcpd_warn("setsockopt SO_KEEPALIVE: %m"); | ||||
} | } | ||||
/* nice_option - set nice value */ | /* nice_option - set nice value */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void nice_option(value, request) | static void nice_option(char *value, struct request_info *request) | ||||
char *value; | |||||
struct request_info *request; | |||||
{ | { | ||||
int niceval = 10; | int niceval = 10; | ||||
char junk; | char junk; | ||||
if (value != 0 && sscanf(value, "%d%c", &niceval, &junk) != 1) | if (value != 0 && sscanf(value, "%d%c", &niceval, &junk) != 1) | ||||
tcpd_jump("bad nice value: \"%s\"", value); | tcpd_jump("bad nice value: \"%s\"", value); | ||||
if (dry_run == 0 && nice(niceval) < 0) | if (dry_run == 0 && nice(niceval) < 0) | ||||
tcpd_warn("nice(%d): %m", niceval); | tcpd_warn("nice(%d): %m", niceval); | ||||
} | } | ||||
/* twist_option - replace process by shell command */ | /* twist_option - replace process by shell command */ | ||||
static void twist_option(value, request) | static void twist_option(char *value, struct request_info *request) | ||||
char *value; | |||||
struct request_info *request; | |||||
{ | { | ||||
char *error; | char *error; | ||||
if (dry_run != 0) { | if (dry_run != 0) { | ||||
dry_run = 0; | dry_run = 0; | ||||
} else { | } else { | ||||
if (resident > 0) | if (resident > 0) | ||||
tcpd_jump("twist option in resident process"); | tcpd_jump("twist option in resident process"); | ||||
Show All 19 Lines | #define maybe_dup2(from, to) ((from == to) ? to : (close(to), dup(from))) | ||||
tcpd_warn(error); | tcpd_warn(error); | ||||
clean_exit(request); | clean_exit(request); | ||||
} | } | ||||
} | } | ||||
/* rfc931_option - look up remote user name */ | /* rfc931_option - look up remote user name */ | ||||
static void rfc931_option(value, request) | static void rfc931_option(char *value, struct request_info *request) | ||||
char *value; | |||||
struct request_info *request; | |||||
{ | { | ||||
int timeout; | int timeout; | ||||
char junk; | char junk; | ||||
if (value != 0) { | if (value != 0) { | ||||
if (sscanf(value, "%d%c", &timeout, &junk) != 1 || timeout <= 0) | if (sscanf(value, "%d%c", &timeout, &junk) != 1 || timeout <= 0) | ||||
tcpd_jump("bad rfc931 timeout: \"%s\"", value); | tcpd_jump("bad rfc931 timeout: \"%s\"", value); | ||||
rfc931_timeout = timeout; | rfc931_timeout = timeout; | ||||
} | } | ||||
(void) eval_user(request); | (void) eval_user(request); | ||||
} | } | ||||
/* setenv_option - set environment variable */ | /* setenv_option - set environment variable */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void setenv_option(value, request) | static void setenv_option(char *value, struct request_info *request) | ||||
char *value; | |||||
struct request_info *request; | |||||
{ | { | ||||
char *var_value; | char *var_value; | ||||
if (*(var_value = value + strcspn(value, whitespace))) | if (*(var_value = value + strcspn(value, whitespace))) | ||||
*var_value++ = 0; | *var_value++ = 0; | ||||
if (setenv(chop_string(value), chop_string(var_value), 1)) | if (setenv(chop_string(value), chop_string(var_value), 1)) | ||||
tcpd_jump("memory allocation failure"); | tcpd_jump("memory allocation failure"); | ||||
} | } | ||||
/* severity_map - lookup facility or severity value */ | /* severity_map - lookup facility or severity value */ | ||||
static int severity_map(table, name) | static int severity_map(const CODE *table, char *name) | ||||
const CODE *table; | |||||
char *name; | |||||
{ | { | ||||
const CODE *t; | const CODE *t; | ||||
int ret = -1; | int ret = -1; | ||||
for (t = table; t->c_name; t++) | for (t = table; t->c_name; t++) | ||||
if (STR_EQ(t->c_name, name)) { | if (STR_EQ(t->c_name, name)) { | ||||
ret = t->c_val; | ret = t->c_val; | ||||
break; | break; | ||||
} | } | ||||
if (ret == -1) | if (ret == -1) | ||||
tcpd_jump("bad syslog facility or severity: \"%s\"", name); | tcpd_jump("bad syslog facility or severity: \"%s\"", name); | ||||
return (ret); | return (ret); | ||||
} | } | ||||
/* severity_option - change logging severity for this event (Dave Mitchell) */ | /* severity_option - change logging severity for this event (Dave Mitchell) */ | ||||
/* ARGSUSED */ | /* ARGSUSED */ | ||||
static void severity_option(value, request) | static void severity_option(char *value, struct request_info *request) | ||||
char *value; | |||||
struct request_info *request; | |||||
{ | { | ||||
char *level = split_at(value, '.'); | char *level = split_at(value, '.'); | ||||
allow_severity = deny_severity = level ? | allow_severity = deny_severity = level ? | ||||
severity_map(facilitynames, value) | severity_map(prioritynames, level) | severity_map(facilitynames, value) | severity_map(prioritynames, level) | ||||
: severity_map(prioritynames, value); | : severity_map(prioritynames, value); | ||||
} | } | ||||
/* get_field - return pointer to next field in string */ | /* get_field - return pointer to next field in string */ | ||||
static char *get_field(string) | static char *get_field(char *string) | ||||
char *string; | |||||
{ | { | ||||
static char *last = ""; | static char *last = ""; | ||||
char *src; | char *src; | ||||
char *dst; | char *dst; | ||||
char *ret; | char *ret; | ||||
int ch; | int ch; | ||||
/* | /* | ||||
Show All 25 Lines | *dst++ = *src++; | ||||
} | } | ||||
last = src; | last = src; | ||||
*dst = 0; | *dst = 0; | ||||
return (ret); | return (ret); | ||||
} | } | ||||
/* chop_string - strip leading and trailing blanks from string */ | /* chop_string - strip leading and trailing blanks from string */ | ||||
static char *chop_string(string) | static char *chop_string(register char *string) | ||||
register char *string; | |||||
{ | { | ||||
char *start = 0; | char *start = 0; | ||||
char *end; | char *end; | ||||
char *cp; | char *cp; | ||||
for (cp = string; *cp; cp++) { | for (cp = string; *cp; cp++) { | ||||
if (!isspace(*cp)) { | if (!isspace(*cp)) { | ||||
if (start == 0) | if (start == 0) | ||||
start = cp; | start = cp; | ||||
end = cp; | end = cp; | ||||
} | } | ||||
} | } | ||||
return (start ? (end[1] = 0, start) : cp); | return (start ? (end[1] = 0, start) : cp); | ||||
} | } |