[PATCH 1/1] hostapd: Add support for PAM session management

Gernot Tenchio gernot.tenchio at securepoint.de
Wed Nov 24 07:57:36 EST 2010


This patch adds support for at least session accounting via PAM. It uses
stations MAC address for PAM_USER and the interface name for PAM_TTY and
PAM_RHOST. It can be enabled via CONFIG_PAM=y in .config.

Comments are welcome.
---
 hostapd/Makefile      |    5 ++++
 hostapd/defconfig     |    3 ++
 hostapd/main.c        |    3 ++
 src/ap/accounting.c   |   11 +++++++-
 src/ap/pam.c          |   57 +++++++++++++++++++++++++++++++++++++++++++++++++
 src/ap/pam.h          |    7 ++++++
 src/ap/sta_info.h     |    4 +++
 src/utils/wpa_debug.h |    1 +
 8 files changed, 89 insertions(+), 2 deletions(-)
 create mode 100644 src/ap/pam.c
 create mode 100644 src/ap/pam.h

diff --git a/hostapd/Makefile b/hostapd/Makefile
index 887a62f..2db0707 100644
--- a/hostapd/Makefile
+++ b/hostapd/Makefile
@@ -105,6 +105,11 @@ ifdef CONFIG_NO_ACCOUNTING
 CFLAGS += -DCONFIG_NO_ACCOUNTING
 else
 OBJS += ../src/ap/accounting.o
+ifdef CONFIG_PAM
+CFLAGS += -DCONFIG_PAM
+OBJS += ../src/ap/pam.o
+LIBS += -lpam
+endif
 endif
 
 ifdef CONFIG_NO_VLAN
diff --git a/hostapd/defconfig b/hostapd/defconfig
index 61793c4..fbdc158 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -147,6 +147,9 @@ CONFIG_IPV6=y
 # Remove support for RADIUS accounting
 #CONFIG_NO_ACCOUNTING=y
 
+# Add support for PAM session management
+#CONFIG_PAM=y
+
 # Remove support for RADIUS
 #CONFIG_NO_RADIUS=y
 
diff --git a/hostapd/main.c b/hostapd/main.c
index 9c532d4..8e0b6bc 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -107,6 +107,9 @@ static void hostapd_logger_cb(void *ctx, const u8 *addr, unsigned int module,
 	case HOSTAPD_MODULE_MLME:
 		module_str = "MLME";
 		break;
+	case HOSTAPD_MODULE_PAM:
+		module_str = "PAM";
+		break;
 	default:
 		module_str = NULL;
 		break;
diff --git a/src/ap/accounting.c b/src/ap/accounting.c
index 7939c68..c835b61 100644
--- a/src/ap/accounting.c
+++ b/src/ap/accounting.c
@@ -24,6 +24,9 @@
 #include "ap_config.h"
 #include "sta_info.h"
 #include "accounting.h"
+#ifdef CONFIG_PAM
+#include "pam.h"
+#endif
 
 
 /* Default interval in seconds for polling TX/RX octets from the driver if
@@ -236,7 +239,6 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
 {
 	struct radius_msg *msg;
 	int interval;
-
 	if (sta->acct_session_started)
 		return;
 
@@ -250,7 +252,9 @@ void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta)
 	sta->last_rx_bytes = sta->last_tx_bytes = 0;
 	sta->acct_input_gigawords = sta->acct_output_gigawords = 0;
 	hapd->drv.sta_clear_stats(hapd, sta->addr);
-
+#ifdef CONFIG_PAM
+	hapd_pam_session_open(hapd, sta);
+#endif
 	if (!hapd->conf->radius->acct_server)
 		return;
 
@@ -388,6 +392,9 @@ void accounting_sta_interim(struct hostapd_data *hapd, struct sta_info *sta)
  */
 void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta)
 {
+#ifdef CONFIG_PAM
+	hapd_pam_session_close(hapd, sta);
+#endif
 	if (sta->acct_session_started) {
 		accounting_sta_report(hapd, sta, 1);
 		eloop_cancel_timeout(accounting_interim_update, hapd, sta);
diff --git a/src/ap/pam.c b/src/ap/pam.c
new file mode 100644
index 0000000..5585b82
--- /dev/null
+++ b/src/ap/pam.c
@@ -0,0 +1,57 @@
+#include <security/pam_appl.h>
+
+#include "utils/includes.h"
+#include "utils/common.h"
+#include "utils/eloop.h"
+#include "hostapd.h"
+#include "ap_config.h"
+#include "sta_info.h"
+
+static struct pam_conv pam_conv_data = {
+    NULL
+};
+
+int hapd_pam_session_open(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	pam_handle_t *pamh = NULL;
+	int rc;
+	char macstr[18];
+
+	os_snprintf(macstr, 18, MACSTR, MAC2STR(sta->addr));
+
+	if (PAM_SUCCESS != (rc = pam_start("hostapd", macstr, &pam_conv_data, &pamh))) {
+	  /* fall through */
+	} else if (PAM_SUCCESS != (rc = pam_set_item(pamh, PAM_TTY, hapd->conf->iface))) {
+	  /* fall through */
+	} else if (PAM_SUCCESS != (rc = pam_set_item(pamh, PAM_RHOST, hapd->conf->iface))) {
+	  /* fall through */
+	} else if (PAM_SUCCESS == (rc = pam_open_session(pamh, PAM_SILENT))) {
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_PAM,
+			HOSTAPD_LEVEL_INFO,
+			"session opened");
+		sta->pamh = pamh;
+		return rc;
+	}
+
+	sta->pamh = NULL;
+	hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_PAM,
+		HOSTAPD_LEVEL_INFO,
+		"PAM session denied %s",
+		pam_strerror(pamh, rc));
+	return rc;
+}
+
+void hapd_pam_session_close(struct hostapd_data *hapd, struct sta_info *sta)
+{
+	if (sta->pamh != NULL) {
+		int rc;
+		pam_handle_t *pamh = (pam_handle_t *)sta->pamh;
+		
+		rc = pam_close_session(pamh, PAM_SILENT);
+		pam_end(pamh, rc);
+		sta->pamh = NULL;
+		hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_PAM,
+			HOSTAPD_LEVEL_INFO,
+			"session closed");
+	}
+}
diff --git a/src/ap/pam.h b/src/ap/pam.h
new file mode 100644
index 0000000..68a2827
--- /dev/null
+++ b/src/ap/pam.h
@@ -0,0 +1,7 @@
+#ifndef _PAM_H
+#define _PAM_H 1
+
+int hapd_pam_session_open(struct hostapd_data *hapd, struct sta_info *sta);
+void hapd_pam_session_close(struct hostapd_data *hapd, struct sta_info *sta);
+
+#endif
diff --git a/src/ap/sta_info.h b/src/ap/sta_info.h
index 51bd9d2..53312bc 100644
--- a/src/ap/sta_info.h
+++ b/src/ap/sta_info.h
@@ -82,6 +82,10 @@ struct sta_info {
 	u32 acct_input_gigawords; /* Acct-Input-Gigawords */
 	u32 acct_output_gigawords; /* Acct-Output-Gigawords */
 
+#ifdef CONFIG_PAM
+	void *pamh; /* PAM handle */
+#endif
+
 	u8 *challenge; /* IEEE 802.11 Shared Key Authentication Challenge */
 
 	struct wpa_state_machine *wpa_sm;
diff --git a/src/utils/wpa_debug.h b/src/utils/wpa_debug.h
index f2e8646..38eafc6 100644
--- a/src/utils/wpa_debug.h
+++ b/src/utils/wpa_debug.h
@@ -215,6 +215,7 @@ void hostapd_logger_register_cb(hostapd_logger_cb_func func);
 #define HOSTAPD_MODULE_DRIVER		0x00000010
 #define HOSTAPD_MODULE_IAPP		0x00000020
 #define HOSTAPD_MODULE_MLME		0x00000040
+#define HOSTAPD_MODULE_PAM              0x00000080
 
 enum hostapd_logger_level {
 	HOSTAPD_LEVEL_DEBUG_VERBOSE = 0,
-- 
1.7.2.3



More information about the HostAP mailing list