1
0
mirror of https://github.com/openbsd/src.git synced 2024-12-22 16:42:56 -08:00

Replace gethostbyaddr(3) with getnameinfo(3). Remove the sigprocmask()

that was necessary for gethostbyaddr() because the latter is not
signal safe.  Change the return code semantics of priv_getnameinfo()
to match getnameinfo(3).
input and OK jca@
This commit is contained in:
bluhm 2014-08-20 20:10:17 +00:00
parent ea1c22cc5a
commit bd6df50781
3 changed files with 45 additions and 63 deletions

View File

@ -1,4 +1,4 @@
/* $OpenBSD: privsep.c,v 1.37 2014/08/20 19:16:27 bluhm Exp $ */
/* $OpenBSD: privsep.c,v 1.38 2014/08/20 20:10:17 bluhm Exp $ */
/*
* Copyright (c) 2003 Anil Madhavapeddy <anil@recoil.org>
@ -68,7 +68,7 @@ enum cmd_types {
PRIV_OPEN_CONFIG, /* open config file for reading only */
PRIV_CONFIG_MODIFIED, /* check if config file has been modified */
PRIV_GETADDRINFO, /* resolve host/service names */
PRIV_GETHOSTBYADDR, /* resolve numeric address into hostname */
PRIV_GETNAMEINFO, /* resolve numeric address into hostname */
PRIV_DONE_CONFIG_PARSE /* signal that the initial config parse is done */
};
@ -76,7 +76,7 @@ static int priv_fd = -1;
static volatile pid_t child_pid = -1;
static char config_file[MAXPATHLEN];
static struct stat cf_info;
static int allow_gethostbyaddr = 0;
static int allow_getnameinfo = 0;
static volatile sig_atomic_t cur_state = STATE_INIT;
/* Queue for the allowed logfiles */
@ -100,12 +100,12 @@ static int may_read(int, void *, size_t);
int
priv_init(char *conf, int numeric, int lockfd, int nullfd, char *argv[])
{
int i, fd, socks[2], cmd, addr_len, addr_af, result, restart;
int i, fd, socks[2], cmd, addr_len, result, restart;
size_t path_len, hostname_len, servname_len;
char path[MAXPATHLEN], hostname[MAXHOSTNAMELEN];
char servname[MAXHOSTNAMELEN];
struct sockaddr_storage addr;
struct stat cf_stat;
struct hostent *hp;
struct passwd *pw;
struct addrinfo hints, *res0;
struct sigaction sa;
@ -191,11 +191,11 @@ priv_init(char *conf, int numeric, int lockfd, int nullfd, char *argv[])
if (stat(config_file, &cf_info) < 0)
err(1, "stat config file failed");
/* Save whether or not the child can have access to gethostbyaddr(3) */
/* Save whether or not the child can have access to getnameinfo(3) */
if (numeric > 0)
allow_gethostbyaddr = 0;
allow_getnameinfo = 0;
else
allow_gethostbyaddr = 1;
allow_getnameinfo = 1;
TAILQ_INIT(&lognames);
increase_state(STATE_CONFIG);
@ -322,24 +322,24 @@ priv_init(char *conf, int numeric, int lockfd, int nullfd, char *argv[])
}
break;
case PRIV_GETHOSTBYADDR:
dprintf("[priv]: msg PRIV_GETHOSTBYADDR received\n");
if (!allow_gethostbyaddr)
errx(1, "rejected attempt to gethostbyaddr");
/* Expecting: length, address, address family */
case PRIV_GETNAMEINFO:
dprintf("[priv]: msg PRIV_GETNAMEINFO received\n");
if (!allow_getnameinfo)
errx(1, "rejected attempt to getnameinfo");
/* Expecting: length, sockaddr */
must_read(socks[0], &addr_len, sizeof(int));
if (addr_len <= 0 || addr_len > sizeof(hostname))
if (addr_len <= 0 || addr_len > sizeof(addr))
_exit(1);
must_read(socks[0], hostname, addr_len);
must_read(socks[0], &addr_af, sizeof(int));
hp = gethostbyaddr(hostname, addr_len, addr_af);
if (hp == NULL) {
must_read(socks[0], &addr, addr_len);
if (getnameinfo((struct sockaddr *)&addr, addr_len,
hostname, sizeof(hostname), NULL, 0,
NI_NOFQDN|NI_NAMEREQD|NI_DGRAM) != 0) {
addr_len = 0;
must_write(socks[0], &addr_len, sizeof(int));
} else {
addr_len = strlen(hp->h_name) + 1;
addr_len = strlen(hostname) + 1;
must_write(socks[0], &addr_len, sizeof(int));
must_write(socks[0], hp->h_name, addr_len);
must_write(socks[0], hostname, addr_len);
}
break;
default:
@ -656,8 +656,8 @@ priv_config_parse_done(void)
must_write(priv_fd, &cmd, sizeof(int));
}
/* Name/service to address translation. Response is placed into addr, and
* the length is returned (zero on error) */
/* Name/service to address translation. Response is placed into addr.
* Return 0 for success or < 0 for error like getaddrinfo(3) */
int
priv_getaddrinfo(char *host, char *serv, struct sockaddr *addr,
size_t addr_len)
@ -701,36 +701,36 @@ priv_getaddrinfo(char *host, char *serv, struct sockaddr *addr,
return (0);
}
/* Reverse address resolution; response is placed into res, and length of
* response is returned (zero on error) */
/* Reverse address resolution; response is placed into host.
* Return 0 for success or < 0 for error like getnameinfo(3) */
int
priv_gethostbyaddr(char *addr, int addr_len, int af, char *res, size_t res_len)
priv_getnameinfo(struct sockaddr *sa, socklen_t salen, char *host,
size_t hostlen)
{
int cmd, ret_len;
if (priv_fd < 0)
errx(1, "%s called from privileged portion", __func__);
cmd = PRIV_GETHOSTBYADDR;
cmd = PRIV_GETNAMEINFO;
must_write(priv_fd, &cmd, sizeof(int));
must_write(priv_fd, &addr_len, sizeof(int));
must_write(priv_fd, addr, addr_len);
must_write(priv_fd, &af, sizeof(int));
must_write(priv_fd, &salen, sizeof(int));
must_write(priv_fd, sa, salen);
/* Expect back an integer size, and then a string of that length */
must_read(priv_fd, &ret_len, sizeof(int));
/* Check there was no error (indicated by a return of 0) */
if (!ret_len)
return 0;
return (-1);
/* Check we don't overflow the passed in buffer */
if (res_len < ret_len)
if (hostlen < ret_len)
errx(1, "%s: overflow attempt in return", __func__);
/* Read the resolved hostname */
must_read(priv_fd, res, ret_len);
return ret_len;
must_read(priv_fd, host, ret_len);
return (0);
}
/* Pass the signal through to child */

View File

@ -1,4 +1,4 @@
/* $OpenBSD: syslogd.c,v 1.113 2014/08/20 19:16:27 bluhm Exp $ */
/* $OpenBSD: syslogd.c,v 1.114 2014/08/20 20:10:17 bluhm Exp $ */
/*
* Copyright (c) 1983, 1988, 1993, 1994
@ -250,7 +250,7 @@ volatile sig_atomic_t WantDie;
volatile sig_atomic_t DoInit;
struct filed *cfline(char *, char *);
void cvthname(struct sockaddr_in *, char *, size_t);
void cvthname(struct sockaddr *, char *, size_t);
int decode(const char *, const CODE *);
void dodie(int);
void doinit(int);
@ -587,7 +587,7 @@ main(int argc, char *argv[])
(struct sockaddr *)&frominet, &len);
if (i > 0) {
line[i] = '\0';
cvthname(&frominet, resolve,
cvthname((struct sockaddr *)&frominet, resolve,
sizeof resolve);
dprintf("cvthname res: %s\n", resolve);
printline(resolve, line);
@ -1096,38 +1096,20 @@ reapchild(int signo)
* Return a printable representation of a host address.
*/
void
cvthname(struct sockaddr_in *f, char *result, size_t res_len)
cvthname(struct sockaddr *f, char *result, size_t res_len)
{
sigset_t omask, nmask;
char *p, *ip;
int ret_len;
if (f->sin_family != AF_INET) {
if (getnameinfo(f, f->sa_len, result, res_len, NULL, 0,
NI_NUMERICHOST|NI_NUMERICSERV|NI_DGRAM) != 0) {
dprintf("Malformed from address\n");
strlcpy(result, "???", res_len);
return;
}
ip = inet_ntoa(f->sin_addr);
dprintf("cvthname(%s)\n", ip);
if (NoDNS) {
strlcpy(result, ip, res_len);
dprintf("cvthname(%s)\n", result);
if (NoDNS)
return;
}
sigemptyset(&nmask);
sigaddset(&nmask, SIGHUP);
sigprocmask(SIG_BLOCK, &nmask, &omask);
ret_len = priv_gethostbyaddr((char *)&f->sin_addr,
sizeof(struct in_addr), f->sin_family, result, res_len);
sigprocmask(SIG_SETMASK, &omask, NULL);
if (ret_len == 0) {
dprintf("Host name for your address (%s) unknown\n", ip);
strlcpy(result, ip, res_len);
} else if ((p = strchr(result, '.')) && strcmp(p + 1, LocalDomain) == 0)
*p = '\0';
if (priv_getnameinfo(f, f->sa_len, result, res_len) != 0)
dprintf("Host name for your address (%s) unknown\n", result);
}
void

View File

@ -1,4 +1,4 @@
/* $OpenBSD: syslogd.h,v 1.10 2014/08/20 19:33:43 bluhm Exp $ */
/* $OpenBSD: syslogd.h,v 1.11 2014/08/20 20:10:17 bluhm Exp $ */
/*
* Copyright (c) 2003 Anil Madhavapeddy <anil@recoil.org>
@ -29,7 +29,7 @@ FILE *priv_open_config(void);
void priv_config_parse_done(void);
int priv_config_modified(void);
int priv_getaddrinfo(char *, char *, struct sockaddr *, size_t);
int priv_gethostbyaddr(char *, int, int, char *, size_t);
int priv_getnameinfo(struct sockaddr *, socklen_t, char *, size_t);
/* Terminal message */
char *ttymsg(struct iovec *, int, char *, int);