>From bacded95465c031514aec1535b97f64739194c83 Mon Sep 17 00:00:00 2001
From: Andreas Kempe <kempe@lysator.liu.se>
Date: Fri, 25 Mar 2022 00:49:53 +0100
Subject: [PATCH] nnrpd: add blacklistd support

Add support for blocking brute force attacks using blacklistd available
on FreeBSD.
---
 Makefile.global.in |  1 +
 configure.ac       |  2 ++
 nnrpd/Makefile     |  2 +-
 nnrpd/nnrpd.c      |  3 +++
 nnrpd/nnrpd.h      |  2 ++
 nnrpd/perm.c       | 39 +++++++++++++++++++++++++++++++++++++++
 6 files changed, 48 insertions(+), 1 deletion(-)

diff --git a/Makefile.global.in b/Makefile.global.in
index a1515c737..ece464036 100644
--- a/Makefile.global.in
+++ b/Makefile.global.in
@@ -113,6 +113,7 @@ CRYPT_LIBS	= @CRYPT_LIBS@
 PAM_LIBS	= @PAM_LIBS@
 REGEX_LIBS	= @REGEX_LIBS@
 SHADOW_LIBS	= @SHADOW_LIBS@
+BLACKLIST_LIBS = @BLACKLIST_LIBS@
 
 ##  Embedding support.	Additional flags and libraries used when compiling
 ##  or linking portions of INN that support embedded interpreters, set by
diff --git a/configure.ac b/configure.ac
index de467ef13..ce83faf14 100644
--- a/configure.ac
+++ b/configure.ac
@@ -454,6 +454,8 @@ AC_SEARCH_LIBS([inet_aton], [resolv])
 dnl Search for various additional libraries used by portions of INN.
 INN_SEARCH_AUX_LIBS([crypt], [crypt], [CRYPT_LIBS])
 INN_SEARCH_AUX_LIBS([getspnam], [shadow], [SHADOW_LIBS])
+INN_SEARCH_AUX_LIBS([blacklist_open], [blacklist], [BLACKLIST_LIBS],
+					[], [AC_MSG_ERROR([libblacklist not found])])
 
 dnl IRIX has a PAM library with the right symbols but no header files suitable
 dnl for use with it, so we have to check the header files first and then only
diff --git a/nnrpd/Makefile b/nnrpd/Makefile
index bc54eee02..c11851f4d 100644
--- a/nnrpd/Makefile
+++ b/nnrpd/Makefile
@@ -35,7 +35,7 @@ NNRPDLIBS	= $(LIBSTORAGE) $(LIBHIST) $(LIBINN) $(STORAGE_LIBS) \
 		  $(CANLOCK_LDFLAGS) $(CANLOCK_LIBS) \
 		  $(SSL_LDFLAGS) $(SSL_LIBS) \
 		  $(CRYPTO_LIBS) $(SASL_LDFLAGS) $(SASL_LIBS) \
-		  $(ZLIB_LDFLAGS) $(ZLIB_LIBS) $(LIBS)
+		  $(ZLIB_LDFLAGS) $(ZLIB_LIBS) $(BLACKLIST_LIBS) $(LIBS)
 
 .c.o:
 	$(CC) $(CFLAGS) -c $<
diff --git a/nnrpd/nnrpd.c b/nnrpd/nnrpd.c
index ffb0623cb..e9bfefea8 100644
--- a/nnrpd/nnrpd.c
+++ b/nnrpd/nnrpd.c
@@ -279,6 +279,8 @@ ExitWithStats(int x, bool readconf)
         TMRfree();
     }
 
+    PERMshutdownblacklist();
+
     if (LocalLogFileName != NULL)
         free(LocalLogFileName);
     closelog();
@@ -1374,6 +1376,7 @@ main(int argc, char *argv[])
     PERMgetinitialaccess(NNRPACCESS);
     PERMgetaccess(true);
     PERMgetpermissions();
+    PERMinitblacklist(STDIN_FILENO);
 
     if (!PERMcanread && !PERMcanpost && !PERMneedauth) {
         syslog(L_NOTICE, "%s no_permission", Client.host);
diff --git a/nnrpd/nnrpd.h b/nnrpd/nnrpd.h
index 820407591..1b7037cb2 100644
--- a/nnrpd/nnrpd.h
+++ b/nnrpd/nnrpd.h
@@ -250,6 +250,8 @@ extern bool PERMartok(void);
 extern void PERMgetinitialaccess(char *readersconf);
 extern void PERMgetaccess(bool initialconnection);
 extern void PERMgetpermissions(void);
+extern void PERMinitblacklist(int fd);
+extern void PERMshutdownblacklist(void);
 extern void PERMlogin(char *uname, char *pass, int *code, char *errorstr);
 extern bool PERMmatch(char **Pats, char **list);
 extern bool ParseDistlist(char ***argvp, char *list);
diff --git a/nnrpd/perm.c b/nnrpd/perm.c
index fe9ee8b4d..235a90fa1 100644
--- a/nnrpd/perm.c
+++ b/nnrpd/perm.c
@@ -8,6 +8,7 @@
 #include <netdb.h>
 #include <signal.h>
 #include <sys/wait.h>
+#include <blacklist.h>
 
 #include "conffile.h"
 #include "inn/innconf.h"
@@ -88,6 +89,8 @@ static void GrowArray(void *, void *);
 static void PERMvectortoaccess(ACCESSGROUP *acc, const char *name,
                                struct vector *acccess_vec) UNUSED;
 
+static void BlacklistReport(const char *user);
+
 /* Global variables. */
 static AUTHGROUP **auth_realms;
 static AUTHGROUP *success_auth;
@@ -96,6 +99,9 @@ static ACCESSGROUP **access_realms;
 static char *ConfigBit;
 static int ConfigBitsize;
 
+static struct blacklist *cookie;
+static int user_fd;
+
 #define PERMlbrace                     1
 #define PERMrbrace                     2
 #define PERMgroup                      3
@@ -2207,5 +2213,38 @@ AuthenticateUser(AUTHGROUP *auth, char *username, char *password,
         }
     }
     free(resdir);
+
+    BlacklistReport(user);
+
     return user;
 }
+
+void
+PERMinitblacklist(int fd)
+{
+    cookie = blacklist_open();
+    if (!cookie)
+        syslog(L_ERROR, "could not connect to blacklistd");
+
+    user_fd = fd;
+}
+
+void
+PERMshutdownblacklist()
+{
+    if (cookie)
+        blacklist_close(cookie);
+}
+
+void
+BlacklistReport(const char *user)
+{
+    if (!cookie)
+        return;
+
+    if (user)
+        blacklist_r(cookie, BLACKLIST_AUTH_OK, user_fd, "login successful");
+    else
+        blacklist_r(cookie, BLACKLIST_AUTH_FAIL, user_fd, "login failed");
+
+}
-- 
2.34.1

