diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/bl.c | 116 | ||||
-rw-r--r-- | lib/blocklist.c | 15 | ||||
-rw-r--r-- | lib/libblocklist.3 | 52 | ||||
-rw-r--r-- | lib/shlib_version | 2 |
5 files changed, 117 insertions, 70 deletions
diff --git a/lib/Makefile b/lib/Makefile index 43da41f83b90..147f311c4782 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.6 2016/01/05 13:07:46 christos Exp $ +# $NetBSD: Makefile,v 1.1.1.1 2020/06/15 01:52:53 christos Exp $ .include <bsd.own.mk> @@ -1,4 +1,4 @@ -/* $NetBSD: bl.c,v 1.29 2020/03/10 13:36:08 roy Exp $ */ +/* $NetBSD: bl.c,v 1.9 2025/03/30 01:53:59 christos Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -32,8 +32,10 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: bl.c,v 1.29 2020/03/10 13:36:08 roy Exp $"); +#endif +__RCSID("$NetBSD: bl.c,v 1.9 2025/03/30 01:53:59 christos Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -57,6 +59,10 @@ __RCSID("$NetBSD: bl.c,v 1.29 2020/03/10 13:36:08 roy Exp $"); #include <pthread.h> #endif +#if defined(SO_RECVUCRED) +#include <ucred.h> +#endif + #include "bl.h" typedef struct { @@ -82,7 +88,8 @@ struct blocklist { int b_fd; int b_connected; struct sockaddr_un b_sun; - void (*b_fun)(int, const char *, va_list); + struct syslog_data b_syslog_data; + void (*b_fun)(int, struct syslog_data *, const char *, va_list); bl_info_t b_info; }; @@ -115,14 +122,16 @@ bl_reset(bl_t b, bool locked) } static void -bl_log(void (*fun)(int, const char *, va_list), int level, - const char *fmt, ...) +bl_log(bl_t b, int level, const char *fmt, ...) { va_list ap; int serrno = errno; + if (b->b_fun == NULL) + return; + va_start(ap, fmt); - (*fun)(level, fmt, ap); + (*b->b_fun)(level, &b->b_syslog_data, fmt, ap); va_end(ap); errno = serrno; } @@ -152,7 +161,7 @@ bl_init(bl_t b, bool srv) b->b_fd = socket(PF_LOCAL, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK|SOCK_NOSIGPIPE, 0); if (b->b_fd == -1) { - bl_log(b->b_fun, LOG_ERR, "%s: socket failed (%s)", + bl_log(b, LOG_ERR, "%s: socket failed (%s)", __func__, strerror(errno)); BL_UNLOCK(b); return -1; @@ -186,7 +195,7 @@ bl_init(bl_t b, bool srv) rv = connect(b->b_fd, (const void *)sun, (socklen_t)sizeof(*sun)); if (rv == 0) { if (srv) { - bl_log(b->b_fun, LOG_ERR, + bl_log(b, LOG_ERR, "%s: another daemon is handling `%s'", __func__, sun->sun_path); goto out; @@ -199,7 +208,7 @@ bl_init(bl_t b, bool srv) * and only log once. */ if (b->b_connected != 1) { - bl_log(b->b_fun, LOG_DEBUG, + bl_log(b, LOG_DEBUG, "%s: connect failed for `%s' (%s)", __func__, sun->sun_path, strerror(errno)); b->b_connected = 1; @@ -207,8 +216,7 @@ bl_init(bl_t b, bool srv) BL_UNLOCK(b); return -1; } - bl_log(b->b_fun, LOG_DEBUG, "Connected to blocklist server", - __func__); + bl_log(b, LOG_DEBUG, "Connected to blocklist server", __func__); } if (srv) { @@ -219,8 +227,7 @@ bl_init(bl_t b, bool srv) (void)umask(om); errno = serrno; if (rv == -1) { - bl_log(b->b_fun, LOG_ERR, - "%s: bind failed for `%s' (%s)", + bl_log(b, LOG_ERR, "%s: bind failed for `%s' (%s)", __func__, sun->sun_path, strerror(errno)); goto out; } @@ -231,8 +238,8 @@ bl_init(bl_t b, bool srv) #if defined(LOCAL_CREDS) #define CRED_LEVEL 0 #define CRED_NAME LOCAL_CREDS -#define CRED_SC_UID sc_euid -#define CRED_SC_GID sc_egid +#define CRED_SC_UID(x) (x)->sc_euid +#define CRED_SC_GID(x) (x)->sc_egid #define CRED_MESSAGE SCM_CREDS #define CRED_SIZE SOCKCREDSIZE(NGROUPS_MAX) #define CRED_TYPE struct sockcred @@ -240,12 +247,21 @@ bl_init(bl_t b, bool srv) #elif defined(SO_PASSCRED) #define CRED_LEVEL SOL_SOCKET #define CRED_NAME SO_PASSCRED -#define CRED_SC_UID uid -#define CRED_SC_GID gid +#define CRED_SC_UID(x) (x)->uid +#define CRED_SC_GID(x) (x)->gid #define CRED_MESSAGE SCM_CREDENTIALS #define CRED_SIZE sizeof(struct ucred) #define CRED_TYPE struct ucred #define GOT_CRED 2 +#elif defined(SO_RECVUCRED) +#define CRED_LEVEL SOL_SOCKET +#define CRED_NAME SO_RECVUCRED +#define CRED_SC_UID(x) ucred_geteuid(x) +#define CRED_SC_GID(x) ucred_getegid(x) +#define CRED_MESSAGE SCM_UCRED +#define CRED_SIZE ucred_size() +#define CRED_TYPE ucred_t +#define GOT_CRED 2 #else #define GOT_CRED 0 /* @@ -259,7 +275,7 @@ bl_init(bl_t b, bool srv) #ifdef CRED_LEVEL if (setsockopt(b->b_fd, CRED_LEVEL, CRED_NAME, &one, (socklen_t)sizeof(one)) == -1) { - bl_log(b->b_fun, LOG_ERR, "%s: setsockopt %s " + bl_log(b, LOG_ERR, "%s: setsockopt %s " "failed (%s)", __func__, __STRING(CRED_NAME), strerror(errno)); goto out; @@ -275,12 +291,15 @@ out: } bl_t -bl_create(bool srv, const char *path, void (*fun)(int, const char *, va_list)) +bl_create(bool srv, const char *path, + void (*fun)(int, struct syslog_data *, const char *, va_list)) { + static struct syslog_data sd = SYSLOG_DATA_INIT; bl_t b = calloc(1, sizeof(*b)); if (b == NULL) - goto out; - b->b_fun = fun == NULL ? vsyslog : fun; + return NULL; + b->b_fun = fun; + b->b_syslog_data = sd; b->b_fd = -1; b->b_connected = -1; BL_INIT(b); @@ -295,11 +314,6 @@ bl_create(bool srv, const char *path, void (*fun)(int, const char *, va_list)) bl_init(b, srv); return b; -out: - free(b); - bl_log(fun, LOG_ERR, "%s: malloc failed (%s)", __func__, - strerror(errno)); - return NULL; } void @@ -327,7 +341,7 @@ bl_getsock(bl_t b, struct sockaddr_storage *ss, const struct sockaddr *sa, family = AF_INET6; break; default: - bl_log(b->b_fun, LOG_ERR, "%s: invalid socket len %u (%s)", + bl_log(b, LOG_ERR, "%s: invalid socket len %u (%s)", __func__, (unsigned)slen, ctx); errno = EINVAL; return -1; @@ -336,7 +350,7 @@ bl_getsock(bl_t b, struct sockaddr_storage *ss, const struct sockaddr *sa, memcpy(ss, sa, slen); if (ss->ss_family != family) { - bl_log(b->b_fun, LOG_INFO, + bl_log(b, LOG_INFO, "%s: correcting socket family %d to %d (%s)", __func__, ss->ss_family, family, ctx); ss->ss_family = family; @@ -344,7 +358,7 @@ bl_getsock(bl_t b, struct sockaddr_storage *ss, const struct sockaddr *sa, #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN if (ss->ss_len != slen) { - bl_log(b->b_fun, LOG_INFO, + bl_log(b, LOG_INFO, "%s: correcting socket len %u to %u (%s)", __func__, ss->ss_len, (unsigned)slen, ctx); ss->ss_len = (uint8_t)slen; @@ -424,16 +438,18 @@ bl_recv(bl_t b) union { char ctrl[CMSG_SPACE(sizeof(int)) + CMSG_SPACE(CRED_SIZE)]; uint32_t fd; - CRED_TYPE sc; } ua; struct cmsghdr *cmsg; +#if GOT_CRED != 0 CRED_TYPE *sc; +#endif union { bl_message_t bl; char buf[512]; } ub; int got; ssize_t rlen; + size_t rem; bl_info_t *bi = &b->b_info; got = 0; @@ -449,18 +465,18 @@ bl_recv(bl_t b) msg.msg_flags = 0; msg.msg_control = ua.ctrl; - msg.msg_controllen = sizeof(ua.ctrl) + 100; + msg.msg_controllen = sizeof(ua.ctrl); rlen = recvmsg(b->b_fd, &msg, 0); if (rlen == -1) { - bl_log(b->b_fun, LOG_ERR, "%s: recvmsg failed (%s)", __func__, + bl_log(b, LOG_ERR, "%s: recvmsg failed (%s)", __func__, strerror(errno)); return NULL; } for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level != SOL_SOCKET) { - bl_log(b->b_fun, LOG_ERR, + bl_log(b, LOG_ERR, "%s: unexpected cmsg_level %d", __func__, cmsg->cmsg_level); continue; @@ -468,10 +484,15 @@ bl_recv(bl_t b) switch (cmsg->cmsg_type) { case SCM_RIGHTS: if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { - bl_log(b->b_fun, LOG_ERR, + int *fd = (void *)CMSG_DATA(cmsg); + size_t len = cmsg->cmsg_len / sizeof(int); + bl_log(b, LOG_ERR, "%s: unexpected cmsg_len %d != %zu", __func__, cmsg->cmsg_len, - CMSG_LEN(2 * sizeof(int))); + CMSG_LEN(sizeof(int))); + + for (size_t i = 0; i < len; i++) + (void)close(fd[i]); continue; } memcpy(&bi->bi_fd, CMSG_DATA(cmsg), sizeof(bi->bi_fd)); @@ -480,13 +501,13 @@ bl_recv(bl_t b) #ifdef CRED_MESSAGE case CRED_MESSAGE: sc = (void *)CMSG_DATA(cmsg); - bi->bi_uid = sc->CRED_SC_UID; - bi->bi_gid = sc->CRED_SC_GID; + bi->bi_uid = CRED_SC_UID(sc); + bi->bi_gid = CRED_SC_GID(sc); got |= GOT_CRED; break; #endif default: - bl_log(b->b_fun, LOG_ERR, + bl_log(b, LOG_ERR, "%s: unexpected cmsg_type %d", __func__, cmsg->cmsg_type); continue; @@ -495,7 +516,7 @@ bl_recv(bl_t b) } if (got != (GOT_CRED|GOT_FD)) { - bl_log(b->b_fun, LOG_ERR, "message missing %s %s", + bl_log(b, LOG_ERR, "message missing %s %s", #if GOT_CRED != 0 (got & GOT_CRED) == 0 ? "cred" : #endif @@ -503,13 +524,15 @@ bl_recv(bl_t b) return NULL; } - if ((size_t)rlen <= sizeof(ub.bl)) { - bl_log(b->b_fun, LOG_ERR, "message too short %zd", rlen); + rem = (size_t)rlen; + if (rem < sizeof(ub.bl)) { + bl_log(b, LOG_ERR, "message too short %zd", rlen); return NULL; } + rem -= sizeof(ub.bl); if (ub.bl.bl_version != BL_VERSION) { - bl_log(b->b_fun, LOG_ERR, "bad version %d", ub.bl.bl_version); + bl_log(b, LOG_ERR, "bad version %d", ub.bl.bl_version); return NULL; } @@ -520,7 +543,12 @@ bl_recv(bl_t b) bi->bi_uid = -1; bi->bi_gid = -1; #endif - strlcpy(bi->bi_msg, ub.bl.bl_data, MIN(sizeof(bi->bi_msg), - ((size_t)rlen - sizeof(ub.bl) + 1))); + if (rem == 0) + bi->bi_msg[0] = '\0'; + else { + rem = MIN(sizeof(bi->bi_msg) - 1, rem); + memcpy(bi->bi_msg, ub.bl.bl_data, rem); + bi->bi_msg[rem] = '\0'; + } return bi; } diff --git a/lib/blocklist.c b/lib/blocklist.c index 9c09f4186ba6..139fc4342626 100644 --- a/lib/blocklist.c +++ b/lib/blocklist.c @@ -1,4 +1,4 @@ -/* $NetBSD: blocklist.c,v 1.6 2019/11/06 20:50:01 christos Exp $ */ +/* $NetBSD: blocklist.c,v 1.4 2025/02/11 17:48:30 christos Exp $ */ /*- * Copyright (c) 2014 The NetBSD Foundation, Inc. @@ -32,8 +32,10 @@ #include "config.h" #endif +#ifdef HAVE_SYS_CDEFS_H #include <sys/cdefs.h> -__RCSID("$NetBSD: blocklist.c,v 1.6 2019/11/06 20:50:01 christos Exp $"); +#endif +__RCSID("$NetBSD: blocklist.c,v 1.4 2025/02/11 17:48:30 christos Exp $"); #include <stdio.h> #include <bl.h> @@ -98,7 +100,14 @@ blocklist_r(struct blocklist *bl, int action, int rfd, const char *msg) struct blocklist * blocklist_open(void) { - return bl_create(false, NULL, vsyslog); + return bl_create(false, NULL, vsyslog_r); +} + +struct blocklist * +blocklist_open2( + void (*logger)(int, struct syslog_data *, const char *, va_list)) +{ + return bl_create(false, NULL, logger); } void diff --git a/lib/libblocklist.3 b/lib/libblocklist.3 index 8368624dbc6a..7a016625a047 100644 --- a/lib/libblocklist.3 +++ b/lib/libblocklist.3 @@ -1,4 +1,4 @@ -.\" $NetBSD: libblocklist.3,v 1.10 2020/03/30 15:47:15 christos Exp $ +.\" $NetBSD: libblocklist.3,v 1.7 2025/02/05 20:14:30 christos Exp $ .\" .\" Copyright (c) 2015 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -27,23 +27,26 @@ .\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE .\" POSSIBILITY OF SUCH DAMAGE. .\" -.Dd March 30, 2020 +.Dd February 5, 2025 .Dt LIBBLOCKLIST 3 .Os .Sh NAME .Nm blocklist_open , +.Nm blocklist_open2 , .Nm blocklist_close , .Nm blocklist_r , .Nm blocklist , .Nm blocklist_sa , .Nm blocklist_sa_r -.Nd Blacklistd notification library +.Nd Blocklistd notification library .Sh LIBRARY .Lb libblocklist .Sh SYNOPSIS .In blocklist.h .Ft struct blocklist * .Fn blocklist_open "void" +.Ft struct blocklist * +.Fn blocklist_open2 "void (*logger)(int, struct syslog_data *, va_list)" .Ft void .Fn blocklist_close "struct blocklist *cookie" .Ft int @@ -68,6 +71,19 @@ and returns a pointer to it, or .Dv NULL on failure. .Pp +The function +.Fn blocklist_open2 +is similar to +.Fn blocklist_open +but allows a +.Fa logger +to be specified. +If the +.Fa logger +is +.Dv NULL , +then no logging is performed. +.Pp The .Fn blocklist_close function frees all memory and resources used. @@ -89,27 +105,21 @@ argument. The .Ar action parameter can take these values: -.Bl -tag -width ".Va BLOCKLIST_ABUSIVE_BEHAVIOR" +.Bl -tag -width ".Dv BLOCKLIST_ABUSIVE_BEHAVIOR" +.It Va BLOCKLIST_BAD_USER +The sending daemon has determined the username presented for +authentication is invalid. +This is considered as one failure count. .It Va BLOCKLIST_AUTH_FAIL There was an unsuccessful authentication attempt. -.It Va BLOCKLIST_AUTH_OK -A user successfully authenticated. +This is considered as two failure counts together. .It Va BLOCKLIST_ABUSIVE_BEHAVIOR -The sending daemon has detected abusive behavior -from the remote system. -The remote address should -be blocked as soon as possible. -.It Va BLOCKLIST_BAD_USER -The sending daemon has determined the username -presented for authentication is invalid. -The -.Xr blocklistd 8 -daemon compares the username to a configured list of forbidden -usernames and -blocks the address immediately if a forbidden username matches. -(The -.Ar BLOCKLIST_BAD_USER -support is not currently available.) +The sending daemon has detected abusive behavior from the remote system. +This is considered as a total immediate failure. +The remote address will be blocked as soon as possible. +.It Va BLOCKLIST_AUTH_OK +A valid user successfully authenticated. +Any entry for the remote address will be removed as soon as possible. .El .Pp The diff --git a/lib/shlib_version b/lib/shlib_version index 97c9f92d6b8f..3d7c908e43d6 100644 --- a/lib/shlib_version +++ b/lib/shlib_version @@ -1,2 +1,2 @@ major=0 -minor=0 +minor=1 |