mosquitto-auth-shadow: support libpam based authentication

This commit is contained in:
Vivek Kumar Dutta 2025-07-29 17:54:54 +05:30 committed by Vivek Dutta
parent a6b8987dac
commit 082452bfb5
4 changed files with 97 additions and 9 deletions

View file

@ -0,0 +1,7 @@
if PACKAGE_mosquitto-auth-shadow
config MOSQUITTO_AUTH_PAM_SUPPORT
bool "Enable support of Linux PAM module for Authentication"
default y
endif

View file

@ -14,12 +14,13 @@
include $(TOPDIR)/rules.mk include $(TOPDIR)/rules.mk
PKG_NAME:=mosquitto-auth-shadow PKG_NAME:=mosquitto-auth-shadow
PKG_VERSION:=1.0.1 PKG_VERSION:=1.1.0
PKG_MAINTAINER:=Erik Karlsson <erik.karlsson@genexis.eu> PKG_MAINTAINER:=Erik Karlsson <erik.karlsson@genexis.eu>
PKG_LICENSE:=EPL-2.0 PKG_LICENSE:=EPL-2.0
PKG_BUILD_PARALLEL:=1 PKG_BUILD_PARALLEL:=1
PKG_CONFIG_DEPENDS:=CONFIG_MOSQUITTO_AUTH_PAM_SUPPORT
include $(INCLUDE_DIR)/package.mk include $(INCLUDE_DIR)/package.mk
@ -27,7 +28,7 @@ define Package/mosquitto-auth-shadow
SECTION:=net SECTION:=net
CATEGORY:=Network CATEGORY:=Network
TITLE:=mosquitto - /etc/shadow authentication plugin TITLE:=mosquitto - /etc/shadow authentication plugin
DEPENDS:=+mosquitto-ssl DEPENDS:=+mosquitto-ssl +MOSQUITTO_AUTH_PAM_SUPPORT:libpam
USERID:=mosquitto=200:mosquitto=200 mosquitto=200:shadow=11 USERID:=mosquitto=200:mosquitto=200 mosquitto=200:shadow=11
endef endef
@ -36,6 +37,14 @@ define Package/mosquitto-auth-shadow/description
users using /etc/shadow users using /etc/shadow
endef endef
define Package/mosquitto-auth-shadow/config
source "$(SOURCE)/Config.in"
endef
ifeq ($(CONFIG_MOSQUITTO_AUTH_PAM_SUPPORT),y)
TARGET_CFLAGS+=-DENABLE_PAM_SUPPORT
endif
define Package/mosquitto-auth-shadow/install define Package/mosquitto-auth-shadow/install
$(INSTALL_DIR) $(1)/usr/lib $(INSTALL_DIR) $(1)/usr/lib
$(INSTALL_BIN) $(PKG_BUILD_DIR)/mosquitto_auth_shadow.so $(1)/usr/lib/ $(INSTALL_BIN) $(PKG_BUILD_DIR)/mosquitto_auth_shadow.so $(1)/usr/lib/

View file

@ -19,7 +19,7 @@ all: $(TARGETS)
$(CC) $(CFLAGS) -Wall -Werror -fPIC -c -o $@ $< $(CC) $(CFLAGS) -Wall -Werror -fPIC -c -o $@ $<
mosquitto_auth_shadow.so: mosquitto_auth_shadow.pic.o mosquitto_auth_shadow.so: mosquitto_auth_shadow.pic.o
$(CC) $(LDFLAGS) -shared -o $@ $^ $(CC) $(LDFLAGS) -shared -o $@ $^ $(if $(filter -DENABLE_PAM_SUPPORT,$(CFLAGS)),-lpam)
clean: clean:
rm -f *.o $(TARGETS) rm -f *.o $(TARGETS)

View file

@ -15,22 +15,78 @@
#include <string.h> #include <string.h>
#include <shadow.h> #include <shadow.h>
#include <crypt.h> #include <crypt.h>
#include <stdlib.h>
#include <mosquitto.h> #include <mosquitto.h>
#include <mosquitto_broker.h> #include <mosquitto_broker.h>
#include <mosquitto_plugin.h> #include <mosquitto_plugin.h>
static int basic_auth_callback(int event, void *event_data, void *userdata) #ifdef ENABLE_PAM_SUPPORT
#include <security/pam_appl.h>
static int pam_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
{
int i;
const char *pass = (const char *)appdata_ptr;
*resp = calloc(num_msg, sizeof(struct pam_response));
if (*resp == NULL) {
mosquitto_log_printf(MOSQ_LOG_ERR, "pam failed to allocate buffer for validation");
return PAM_BUF_ERR;
}
if (pass == NULL)
return PAM_SUCCESS;
for (i = 0; i < num_msg; ++i) {
if (msg[i]->msg_style == PAM_PROMPT_ECHO_OFF) {
(*resp)[i].resp = strdup(pass);
if ((*resp)[i].resp == NULL) {
for (int j = 0; j < i ; j++)
free((*resp)[j].resp);
free(*resp);
*resp = NULL;
mosquitto_log_printf(MOSQ_LOG_ERR, "pam failed in strdup");
return PAM_BUF_ERR;
}
}
}
return PAM_SUCCESS;
}
static int process_pam_auth_callback(struct mosquitto_evt_basic_auth *ed)
{
struct pam_conv conv;
int retval;
pam_handle_t *pamh = NULL;
conv.conv = pam_conversation;
conv.appdata_ptr = (void *)ed->password;
retval = pam_start("mosquitto", ed->username, &conv, &pamh);
if (retval != PAM_SUCCESS) {
mosquitto_log_printf(MOSQ_LOG_ERR, "pam start failed: %s", pam_strerror(pamh, retval));
return MOSQ_ERR_AUTH;
}
retval = pam_authenticate(pamh, 0);
pam_end(pamh, retval);
if (retval == PAM_SUCCESS) {
mosquitto_log_printf(MOSQ_LOG_NOTICE, "pam user [%s] logged in", ed->username);
return MOSQ_ERR_SUCCESS;
}
mosquitto_log_printf(MOSQ_LOG_NOTICE, "pam user [%s] failed authentication, err [%s]", ed->username, pam_strerror(pamh, retval));
return MOSQ_ERR_AUTH;
}
#else
static int process_shadow_auth_callback(struct mosquitto_evt_basic_auth *ed)
{ {
struct mosquitto_evt_basic_auth *ed = event_data;
struct spwd spbuf, *sp = NULL; struct spwd spbuf, *sp = NULL;
char buf[256]; char buf[256];
struct crypt_data data; struct crypt_data data;
char *hash; char *hash;
/* Let other plugins or broker decide about anonymous login */
if (ed->username == NULL)
return MOSQ_ERR_PLUGIN_DEFER;
getspnam_r(ed->username, &spbuf, buf, sizeof(buf), &sp); getspnam_r(ed->username, &spbuf, buf, sizeof(buf), &sp);
if (sp == NULL || sp->sp_pwdp == NULL) if (sp == NULL || sp->sp_pwdp == NULL)
@ -54,6 +110,22 @@ static int basic_auth_callback(int event, void *event_data, void *userdata)
return MOSQ_ERR_AUTH; return MOSQ_ERR_AUTH;
} }
#endif
static int basic_auth_callback(int event, void *event_data, void *userdata)
{
struct mosquitto_evt_basic_auth *ed = event_data;
/* Let other plugins or broker decide about anonymous login */
if (ed->username == NULL)
return MOSQ_ERR_PLUGIN_DEFER;
#ifdef ENABLE_PAM_SUPPORT
return process_pam_auth_callback(ed);
#else
return process_shadow_auth_callback(ed);
#endif
}
int mosquitto_plugin_version(int supported_version_count, int mosquitto_plugin_version(int supported_version_count,
const int *supported_versions) const int *supported_versions)