From f6aa7e9b26297e3aacacfc47da2dcd9b7a2e9ff6 Mon Sep 17 00:00:00 2001 From: Reyk Floeter Date: Fri, 26 Sep 2008 15:19:56 +0000 Subject: allow to add an additional restricted control socket for trap sending only (not even show commands). this allows to place a socket for traps in another daemon's chroot. (based on restricted socket support from bgpd) --- usr.sbin/snmpctl/snmpctl.8 | 16 +++++++++--- usr.sbin/snmpctl/snmpctl.c | 12 ++++++--- usr.sbin/snmpd/control.c | 62 +++++++++++++++++++++++++++------------------- usr.sbin/snmpd/snmpd.8 | 18 +++++++++++--- usr.sbin/snmpd/snmpd.c | 20 +++++++++++---- usr.sbin/snmpd/snmpd.h | 21 ++++++++++------ usr.sbin/snmpd/snmpe.c | 10 +++++--- 7 files changed, 107 insertions(+), 52 deletions(-) diff --git a/usr.sbin/snmpctl/snmpctl.8 b/usr.sbin/snmpctl/snmpctl.8 index ed46d31fde6..d04e0a7599a 100644 --- a/usr.sbin/snmpctl/snmpctl.8 +++ b/usr.sbin/snmpctl/snmpctl.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: snmpctl.8,v 1.8 2008/05/17 23:31:52 sobrado Exp $ +.\" $OpenBSD: snmpctl.8,v 1.9 2008/09/26 15:19:55 reyk Exp $ .\" .\" Copyright (c) 2007, 2008 Reyk Floeter .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: May 17 2008 $ +.Dd $Mdocdate: September 26 2008 $ .Dt SNMPCTL 8 .Os .Sh NAME @@ -23,6 +23,7 @@ .Sh SYNOPSIS .Nm .Op Fl n +.Op Fl s Ar socket .Ar command .Op Ar arg ... .Sh DESCRIPTION @@ -36,6 +37,13 @@ The options are as follows: .Bl -tag -width Ds .It Fl n Show numeric OID values instead of their symbolic names. +.It Fl s Ar socket +Use +.Ar socket +instead of the default +.Pa /var/run/snmpd.sock +to communicate with +.Xr snmpd 8 . .El .Pp The following commands are available: @@ -97,8 +105,8 @@ An string describing an Object ID, for example .Sh FILES .Bl -tag -width "/var/run/snmpd.sockXX" -compact .It /var/run/snmpd.sock -Unix-domain socket used for communication with -.Xr snmpd 8 . +default UNIX-domain socket used for communication with +.Xr snmpd 8 .El .Sh SEE ALSO .Xr snmpd 8 diff --git a/usr.sbin/snmpctl/snmpctl.c b/usr.sbin/snmpctl/snmpctl.c index 41a8f3d9efb..89210679866 100644 --- a/usr.sbin/snmpctl/snmpctl.c +++ b/usr.sbin/snmpctl/snmpctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpctl.c,v 1.8 2008/05/17 23:31:52 sobrado Exp $ */ +/* $OpenBSD: snmpctl.c,v 1.9 2008/09/26 15:19:55 reyk Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter @@ -95,16 +95,20 @@ main(int argc, char *argv[]) int done = 0; int n; int ch; + const char *sock = SNMPD_SOCKET; if ((env = calloc(1, sizeof(struct snmpd *))) == NULL) err(1, "calloc"); gettimeofday(&env->sc_starttime, NULL); - while ((ch = getopt(argc, argv, "n")) != -1) { + while ((ch = getopt(argc, argv, "ns:")) != -1) { switch (ch) { case 'n': env->sc_flags |= SNMPD_F_NONAMES; break; + case 's': + sock = optarg; + break; default: usage(); /* NOTREACHED */ @@ -140,7 +144,7 @@ main(int argc, char *argv[]) bzero(&sun, sizeof(sun)); sun.sun_family = AF_UNIX; - strlcpy(sun.sun_path, SNMPD_SOCKET, sizeof(sun.sun_path)); + strlcpy(sun.sun_path, sock, sizeof(sun.sun_path)); reconnect: if (connect(ctl_sock, (struct sockaddr *)&sun, sizeof(sun)) == -1) { /* Keep retrying if running in monitor mode */ @@ -149,7 +153,7 @@ main(int argc, char *argv[]) usleep(100); goto reconnect; } - err(1, "connect: %s", SNMPD_SOCKET); + err(1, "connect: %s", sock); } if (res->ibuf != NULL) diff --git a/usr.sbin/snmpd/control.c b/usr.sbin/snmpd/control.c index 646d181d126..bde9dd16ef9 100644 --- a/usr.sbin/snmpd/control.c +++ b/usr.sbin/snmpd/control.c @@ -1,4 +1,4 @@ -/* $OpenBSD: control.c,v 1.7 2008/02/07 11:33:26 reyk Exp $ */ +/* $OpenBSD: control.c,v 1.8 2008/09/26 15:19:55 reyk Exp $ */ /* * Copyright (c) 2003, 2004 Henning Brauer @@ -43,14 +43,15 @@ struct ctl_connlist ctl_conns; struct ctl_conn *control_connbyfd(int); void control_close(int); -struct imsgbuf *ibuf_parent = NULL; - int -control_init(void) +control_init(struct control_sock *cs) { struct sockaddr_un sun; int fd; - mode_t old_umask; + mode_t old_umask, mode; + + if (cs->cs_name == NULL) + return (0); if ((fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { log_warn("control_init: socket"); @@ -58,74 +59,84 @@ control_init(void) } sun.sun_family = AF_UNIX; - if (strlcpy(sun.sun_path, SNMPD_SOCKET, + if (strlcpy(sun.sun_path, cs->cs_name, sizeof(sun.sun_path)) >= sizeof(sun.sun_path)) { - log_warn("control_init: %s name too long", SNMPD_SOCKET); + log_warn("control_init: %s name too long", cs->cs_name); close(fd); return (-1); } - if (unlink(SNMPD_SOCKET) == -1) + if (unlink(cs->cs_name) == -1) if (errno != ENOENT) { - log_warn("control_init: unlink %s", SNMPD_SOCKET); + log_warn("control_init: unlink %s", cs->cs_name); close(fd); return (-1); } - old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH); + if (cs->cs_restricted) { + old_umask = umask(S_IXUSR|S_IXGRP|S_IXOTH); + mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH; + } else { + old_umask = umask(S_IXUSR|S_IXGRP|S_IWOTH|S_IROTH|S_IXOTH); + mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP; + } + if (bind(fd, (struct sockaddr *)&sun, sizeof(sun)) == -1) { - log_warn("control_init: bind: %s", SNMPD_SOCKET); + log_warn("control_init: bind: %s", cs->cs_name); close(fd); (void)umask(old_umask); return (-1); } (void)umask(old_umask); - if (chmod(SNMPD_SOCKET, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) == -1) { + if (chmod(cs->cs_name, mode) == -1) { log_warn("control_init: chmod"); close(fd); - (void)unlink(SNMPD_SOCKET); + (void)unlink(cs->cs_name); return (-1); } session_socket_blockmode(fd, BM_NONBLOCK); - control_state.fd = fd; + cs->cs_fd = fd; return (0); } int -control_listen(struct snmpd *env, struct imsgbuf *parent) +control_listen(struct control_sock *cs) { - ibuf_parent = parent; + if (cs->cs_name == NULL) + return (0); - if (listen(control_state.fd, CONTROL_BACKLOG) == -1) { + if (listen(cs->cs_fd, CONTROL_BACKLOG) == -1) { log_warn("control_listen: listen"); return (-1); } - event_set(&control_state.ev, control_state.fd, EV_READ | EV_PERSIST, - control_accept, env); - event_add(&control_state.ev, NULL); + event_set(&cs->cs_ev, cs->cs_fd, EV_READ | EV_PERSIST, + control_accept, cs); + event_add(&cs->cs_ev, NULL); return (0); } void -control_cleanup(void) +control_cleanup(struct control_sock *cs) { - (void)unlink(SNMPD_SOCKET); + if (cs->cs_name == NULL) + return; + (void)unlink(cs->cs_name); } /* ARGSUSED */ void control_accept(int listenfd, short event, void *arg) { + struct control_sock *cs = (struct control_sock *)arg; int connfd; socklen_t len; struct sockaddr_un sun; struct ctl_conn *c; - struct snmpd *env = arg; len = sizeof(sun); if ((connfd = accept(listenfd, @@ -146,7 +157,7 @@ control_accept(int listenfd, short event, void *arg) imsg_init(&c->ibuf, connfd, control_dispatch_imsg); c->ibuf.events = EV_READ; event_set(&c->ibuf.ev, c->ibuf.fd, c->ibuf.events, - c->ibuf.handler, env); + c->ibuf.handler, cs); event_add(&c->ibuf.ev, NULL); TAILQ_INSERT_TAIL(&ctl_conns, c, entry); @@ -184,6 +195,7 @@ control_close(int fd) void control_dispatch_imsg(int fd, short event, void *arg) { + struct control_sock *cs = (struct control_sock *)arg; struct ctl_conn *c; struct imsg imsg; int n; @@ -220,7 +232,7 @@ control_dispatch_imsg(int fd, short event, void *arg) if (n == 0) break; - if (c->flags & CTL_CONN_LOCKED) { + if (cs->cs_restricted || (c->flags & CTL_CONN_LOCKED)) { switch (imsg.hdr.type) { case IMSG_SNMP_TRAP: case IMSG_SNMP_ELEMENT: diff --git a/usr.sbin/snmpd/snmpd.8 b/usr.sbin/snmpd/snmpd.8 index 94611664dea..3b93e946828 100644 --- a/usr.sbin/snmpd/snmpd.8 +++ b/usr.sbin/snmpd/snmpd.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: snmpd.8,v 1.8 2008/03/30 17:56:27 martin Exp $ +.\" $OpenBSD: snmpd.8,v 1.9 2008/09/26 15:19:55 reyk Exp $ .\" .\" Copyright (c) 2007, 2008 Reyk Floeter .\" @@ -14,7 +14,7 @@ .\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF .\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. .\" -.Dd $Mdocdate: March 30 2008 $ +.Dd $Mdocdate: September 26 2008 $ .Dt SNMPD 8 .Os .Sh NAME @@ -27,6 +27,7 @@ .Fl D Ar macro Ns = Ns Ar value Oc .Xc .Op Fl f Ar file +.Op Fl r Ar path .Sh DESCRIPTION .Nm is a daemon which implements the SNMP protocol. @@ -55,15 +56,26 @@ Show numeric OID values instead of their symbolic names. .It Fl n Configtest mode. Only check the configuration file for validity. +.It Fl r Ar path +Open a second, restricted, control socket that +.Xr snmpctl 8 +can use. +Only +.Em trap +requests are allowed on this socket. .It Fl v Produce more verbose output. .El .Sh FILES -.Bl -tag -width "/etc/snmpd.confXXX" -compact +.Bl -tag -width "/var/run/snmpd.sockXXX" -compact .It Pa /etc/snmpd.conf default .Nm configuration file +.It Pa /var/run/snmpd.sock +default +.Nm +control socket .El .Sh SEE ALSO .Xr snmpd.conf 5 , diff --git a/usr.sbin/snmpd/snmpd.c b/usr.sbin/snmpd/snmpd.c index 4835b92a6f1..fad785ecabf 100644 --- a/usr.sbin/snmpd/snmpd.c +++ b/usr.sbin/snmpd/snmpd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpd.c,v 1.7 2008/05/12 19:15:02 pyr Exp $ */ +/* $OpenBSD: snmpd.c,v 1.8 2008/09/26 15:19:55 reyk Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter @@ -84,8 +84,8 @@ usage(void) { extern char *__progname; - fprintf(stderr, "usage: %s [-dNnv] [-D macro=value] [-f file]\n", - __progname); + fprintf(stderr, "usage: %s [-dNnv] [-D macro=value] " + "[-f file] [-r path]\n", __progname); exit(1); } @@ -102,12 +102,13 @@ main(int argc, char *argv[]) u_int flags = 0; int noaction = 0; const char *conffile = CONF_FILE; + const char *rcsock = NULL; smi_init(); log_init(1); /* log to stderr until daemonized */ - while ((c = getopt(argc, argv, "dD:nNf:v")) != -1) { + while ((c = getopt(argc, argv, "dD:nNf:r:v")) != -1) { switch (c) { case 'd': debug = 1; @@ -126,6 +127,9 @@ main(int argc, char *argv[]) case 'f': conffile = optarg; break; + case 'r': + rcsock = optarg; + break; case 'v': flags |= SNMPD_F_VERBOSE; break; @@ -154,6 +158,11 @@ main(int argc, char *argv[]) if (getpwnam(SNMPD_USER) == NULL) errx(1, "unknown user %s", SNMPD_USER); + /* Configure the control sockets */ + env->sc_csock.cs_name = SNMPD_SOCKET; + env->sc_rcsock.cs_name = rcsock; + env->sc_rcsock.cs_restricted = 1; + log_init(debug); if (!debug) { @@ -218,7 +227,8 @@ snmpd_shutdown(struct snmpd *env) fatal("wait"); } while (pid != -1 || (pid == -1 && errno == EINTR)); - control_cleanup(); + control_cleanup(&env->sc_csock); + control_cleanup(&env->sc_rcsock); log_info("terminating"); exit(0); } diff --git a/usr.sbin/snmpd/snmpd.h b/usr.sbin/snmpd/snmpd.h index 16969ebf1dd..36960ba50a3 100644 --- a/usr.sbin/snmpd/snmpd.h +++ b/usr.sbin/snmpd/snmpd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpd.h,v 1.20 2008/07/18 12:30:06 reyk Exp $ */ +/* $OpenBSD: snmpd.h,v 1.21 2008/09/26 15:19:55 reyk Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter @@ -118,10 +118,12 @@ enum { } snmpd_process; /* initially control.h */ -struct { - struct event ev; - int fd; -} control_state; +struct control_sock { + const char *cs_name; + struct event cs_ev; + int cs_fd; + int cs_restricted; +}; enum blockmodes { BM_NORMAL, @@ -322,6 +324,9 @@ struct snmpd { struct event sc_ev; struct timeval sc_starttime; + struct control_sock sc_csock; + struct control_sock sc_rcsock; + char sc_rdcommunity[SNMPD_MAXCOMMUNITYLEN]; char sc_rwcommunity[SNMPD_MAXCOMMUNITYLEN]; char sc_trcommunity[SNMPD_MAXCOMMUNITYLEN]; @@ -332,12 +337,12 @@ struct snmpd { }; /* control.c */ -int control_init(void); -int control_listen(struct snmpd *, struct imsgbuf *); +int control_init(struct control_sock *); +int control_listen(struct control_sock *); void control_accept(int, short, void *); void control_dispatch_imsg(int, short, void *); void control_imsg_forward(struct imsg *); -void control_cleanup(void); +void control_cleanup(struct control_sock *); void session_socket_blockmode(int, enum blockmodes); diff --git a/usr.sbin/snmpd/snmpe.c b/usr.sbin/snmpd/snmpe.c index 37f4b6d9901..62623104f70 100644 --- a/usr.sbin/snmpd/snmpe.c +++ b/usr.sbin/snmpd/snmpe.c @@ -1,4 +1,4 @@ -/* $OpenBSD: snmpe.c,v 1.20 2008/09/03 13:41:49 jsg Exp $ */ +/* $OpenBSD: snmpe.c,v 1.21 2008/09/26 15:19:55 reyk Exp $ */ /* * Copyright (c) 2007, 2008 Reyk Floeter @@ -88,8 +88,10 @@ snmpe(struct snmpd *x_env, int pipe_parent2snmpe[2]) env = x_env; - if (control_init() == -1) + if (control_init(&env->sc_csock) == -1) fatalx("snmpe: control socket setup failed"); + if (control_init(&env->sc_rcsock) == -1) + fatalx("snmpe: restricted control socket setup failed"); if ((env->sc_sock = snmpe_bind(&env->sc_address)) == -1) fatalx("snmpe: failed to bind SNMP UDP socket"); @@ -147,8 +149,10 @@ snmpe(struct snmpd *x_env, int pipe_parent2snmpe[2]) TAILQ_INIT(&ctl_conns); - if (control_listen(env, ibuf_parent) == -1) + if (control_listen(&env->sc_csock) == -1) fatalx("snmpe: control socket listen failed"); + if (control_listen(&env->sc_rcsock) == -1) + fatalx("snmpe: restricted control socket listen failed"); event_set(&env->sc_ev, env->sc_sock, EV_READ|EV_PERSIST, snmpe_recvmsg, env); -- cgit v1.2.3