From f0fcc1abd2daa07ccada23621d8a957df42e5801 Mon Sep 17 00:00:00 2001 From: Hannes Reinecke Date: Mon, 8 Nov 2010 12:20:27 +0100 Subject: [PATCH] Enable passing of sender credentials We need to verify that only root is able to send control messages to lldpad, so we should enable passing of sender credentials here. Signed-off-by: Hannes Reinecke diff --git a/Makefile.am b/Makefile.am index 99202b0..45eacc2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,6 +8,9 @@ noinst_PROGRAMS = nltest # pass the value of ${sysconfdir} to the C pre-processor as SYSCONFDIR AM_CPPFLAGS = -I${srcdir}/include -DSYSCONFDIR="\"${sysconfdir}\"" +# Always define _GNU_SOURCE +AM_CPPFLAGS += -D_GNU_SOURCE + if BUILTIN_LIBCONFIG ## force generation of recursive rules SUBDIRS = . diff --git a/ctrl_iface.c b/ctrl_iface.c index 63977be..7d21471 100644 --- a/ctrl_iface.c +++ b/ctrl_iface.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "common.h" #include "lldpad.h" #include "eloop.h" @@ -353,6 +354,11 @@ static void ctrl_iface_receive(int sock, void *eloop_ctx, { struct clif_data *clifd = eloop_ctx; char buf[MAX_CLIF_MSGBUF]; + struct msghdr smsg; + struct cmsghdr *cmsg; + struct iovec iov; + struct ucred *cred; + char cred_msg[CMSG_SPACE(sizeof(struct ucred))]; int res; struct sockaddr_un from; socklen_t fromlen = sizeof(from); @@ -360,18 +366,49 @@ static void ctrl_iface_receive(int sock, void *eloop_ctx, const int reply_size = MAX_CLIF_MSGBUF; int reply_len; - res = recvfrom(sock, buf, sizeof(buf) - 1, MSG_DONTWAIT, - (struct sockaddr *) &from, &fromlen); + memset(&buf, 0x00, sizeof(buf)); + iov.iov_base = buf; + iov.iov_len = sizeof(buf) - 1; + + memset(&smsg, 0x00, sizeof(struct msghdr)); + smsg.msg_name = &from; + smsg.msg_namelen = fromlen; + smsg.msg_iov = &iov; + smsg.msg_iovlen = 1; + smsg.msg_control = cred_msg; + smsg.msg_controllen = sizeof(cred_msg); + + res = recvmsg(sock, &smsg, 0); if (res < 0) { perror("recvfrom(ctrl_iface)"); return; } + cmsg = CMSG_FIRSTHDR(&smsg); + fromlen = smsg.msg_namelen; + cred = (struct ucred *)CMSG_DATA(cmsg); + + if (cmsg == NULL || cmsg->cmsg_type != SCM_CREDENTIALS) { + wpa_printf(MSG_INFO, "%s: No sender credentials, ignoring", + __FUNCTION__); + sprintf(buf,"R%02x", cmd_bad_params); + sendto(sock, buf, 3, 0, (struct sockaddr *) &from, fromlen); + return; + } + if (cred->uid != 0) { + wpa_printf(MSG_INFO, "%s: sender uid=%i, ignoring", + __FUNCTION__, cred->uid); + sprintf(buf,"R%02x", cmd_no_access); + sendto(sock, buf, 3, 0, (struct sockaddr *) &from, + fromlen); + return; + } + buf[res] = '\0'; wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) buf, res); reply = malloc(reply_size); if (reply == NULL) { - sendto(sock, "FAIL", 4, 0, (struct sockaddr *) &from, + sendto(sock, "R01", 3, 0, (struct sockaddr *) &from, fromlen); return; } @@ -395,6 +432,7 @@ int ctrl_iface_init(struct clif_data *clifd) struct sockaddr_un addr; int s = -1; socklen_t addrlen; + const int feature_on = 1; clifd->ctrl_sock = -1; clifd->ctrl_dst = NULL; @@ -414,6 +452,9 @@ int ctrl_iface_init(struct clif_data *clifd) perror("bind(AF_LOCAL)"); goto fail; } + /* enable receiving of the sender credentials */ + setsockopt(s, SOL_SOCKET, SO_PASSCRED, + &feature_on, sizeof(feature_on)); wpa_printf(MSG_DEBUG, "bound ctrl iface to %s", &addr.sun_path[1]); clifd->ctrl_sock = s; diff --git a/dcbtool_cmds.c b/dcbtool_cmds.c index 237e35d..3e56729 100644 --- a/dcbtool_cmds.c +++ b/dcbtool_cmds.c @@ -80,6 +80,9 @@ static char *print_status(cmd_status status) case cmd_not_capable: str = "Device not capable"; break; + case cmd_no_access: + str = "Access denied"; + break; default: str = "Unknown status"; break; diff --git a/include/clif_msgs.h b/include/clif_msgs.h index 6448938..0dcd720 100644 --- a/include/clif_msgs.h +++ b/include/clif_msgs.h @@ -110,6 +110,7 @@ typedef enum { cmd_ctrl_vers_not_compatible, cmd_not_capable, cmd_not_applicable, + cmd_no_access, } cmd_status; #define SHOW_NO_OUTPUT 0x00 diff --git a/lldptool_cmds.c b/lldptool_cmds.c index 25d8d5d..01345e2 100644 --- a/lldptool_cmds.c +++ b/lldptool_cmds.c @@ -210,6 +210,9 @@ static char *print_status(cmd_status status) case cmd_not_capable: str = "Device not capable"; break; + case cmd_no_access: + str = "Access denied"; + break; default: str = "Unknown status"; break;