diff --git a/contrib/bsnmp/snmpd/main.c b/contrib/bsnmp/snmpd/main.c index 8331a835303f..01a5818a0e8c 100644 --- a/contrib/bsnmp/snmpd/main.c +++ b/contrib/bsnmp/snmpd/main.c @@ -1026,34 +1026,31 @@ snmp_input_consume(struct port_input *pi) pi->length -= pi->consumed; } -struct credmsg { - struct cmsghdr hdr; - struct cmsgcred cred; -}; +static void +check_priv_dgram(struct port_input *pi, struct sockcred *cred) +{ + + /* process explicitly sends credentials */ + if (cred) + pi->priv = (cred->sc_euid == 0); + else + pi->priv = 0; +} static void -check_priv(struct port_input *pi, struct msghdr *msg) +check_priv_stream(struct port_input *pi) { - struct credmsg *cmsg; struct xucred ucred; socklen_t ucredlen; - pi->priv = 0; - - if (msg->msg_controllen == sizeof(*cmsg)) { - /* process explicitly sends credentials */ - - cmsg = (struct credmsg *)msg->msg_control; - pi->priv = (cmsg->cred.cmcred_euid == 0); - return; - } - - /* ok, obtain the accept time credentials */ + /* obtain the accept time credentials */ ucredlen = sizeof(ucred); if (getsockopt(pi->fd, 0, LOCAL_PEERCRED, &ucred, &ucredlen) == 0 && ucredlen >= sizeof(ucred) && ucred.cr_version == XUCRED_VERSION) pi->priv = (ucred.cr_uid == 0); + else + pi->priv = 0; } /* @@ -1065,7 +1062,6 @@ recv_stream(struct port_input *pi) struct msghdr msg; struct iovec iov[1]; ssize_t len; - struct credmsg cmsg; if (pi->buf == NULL) { /* no buffer yet - allocate one */ @@ -1084,17 +1080,8 @@ recv_stream(struct port_input *pi) msg.msg_namelen = pi->peerlen; msg.msg_iov = iov; msg.msg_iovlen = 1; - if (pi->cred) { - msg.msg_control = &cmsg; - msg.msg_controllen = sizeof(cmsg); - - cmsg.hdr.cmsg_len = sizeof(cmsg); - cmsg.hdr.cmsg_level = SOL_SOCKET; - cmsg.hdr.cmsg_type = SCM_CREDS; - } else { - msg.msg_control = NULL; - msg.msg_controllen = 0; - } + msg.msg_control = NULL; + msg.msg_controllen = 0; msg.msg_flags = 0; iov[0].iov_base = pi->buf + pi->length; @@ -1109,7 +1096,7 @@ recv_stream(struct port_input *pi) pi->length += len; if (pi->cred) - check_priv(pi, &msg); + check_priv_stream(pi); return (0); } @@ -1122,10 +1109,12 @@ static int recv_dgram(struct port_input *pi) { u_char embuf[1000]; + char cbuf[CMSG_SPACE(SOCKCREDSIZE(CMGROUP_MAX))]; struct msghdr msg; struct iovec iov[1]; ssize_t len; - struct credmsg cmsg; + struct cmsghdr *cmsg; + struct sockcred *cred = NULL; if (pi->buf == NULL) { /* no buffer yet - allocate one */ @@ -1145,17 +1134,9 @@ recv_dgram(struct port_input *pi) msg.msg_namelen = pi->peerlen; msg.msg_iov = iov; msg.msg_iovlen = 1; - if (pi->cred) { - msg.msg_control = &cmsg; - msg.msg_controllen = sizeof(cmsg); - - cmsg.hdr.cmsg_len = sizeof(cmsg); - cmsg.hdr.cmsg_level = SOL_SOCKET; - cmsg.hdr.cmsg_type = SCM_CREDS; - } else { - msg.msg_control = NULL; - msg.msg_controllen = 0; - } + memset(cbuf, 0, sizeof(cbuf)); + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); msg.msg_flags = 0; iov[0].iov_base = pi->buf; @@ -1176,8 +1157,15 @@ recv_dgram(struct port_input *pi) pi->length = (size_t)len; + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; + cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_SOCKET && + cmsg->cmsg_type == SCM_CREDS) + cred = (struct sockcred *)CMSG_DATA(cmsg); + } + if (pi->cred) - check_priv(pi, &msg); + check_priv_dgram(pi, cred); return (0); } diff --git a/contrib/bsnmp/snmpd/trans_lsock.c b/contrib/bsnmp/snmpd/trans_lsock.c index 2cddd48904be..30b66f75ac0f 100644 --- a/contrib/bsnmp/snmpd/trans_lsock.c +++ b/contrib/bsnmp/snmpd/trans_lsock.c @@ -343,6 +343,7 @@ lsock_init_port(struct tport *tp) } } else { struct lsock_peer *peer; + const int on = 1; peer = LIST_FIRST(&p->peers); @@ -351,6 +352,14 @@ lsock_init_port(struct tport *tp) return (SNMP_ERR_RES_UNAVAIL); } + if (setsockopt(peer->input.fd, 0, LOCAL_CREDS, &on, + sizeof(on)) == -1) { + syslog(LOG_ERR, "setsockopt(LOCAL_CREDS): %m"); + close(peer->input.fd); + peer->input.fd = -1; + return (SNMP_ERR_GENERR); + } + strcpy(sa.sun_path, p->name); sa.sun_family = AF_LOCAL; sa.sun_len = strlen(p->name) +