[prev in list] [next in list] [prev in thread] [next in thread] 

List:       cyrus-sasl
Subject:    pam_sasldb - PAM module for sasldb
From:       Michail Vidiassov <master () iaas ! msu ! ru>
Date:       2003-02-17 11:30:58
[Download RAW message or body]

Dear SASL Guru,

I would like to remind you about a pam_sasldb module, developed by
Nalin Dahyabhai <nalin@redhat.com>, available at
http://people.redhat.com/nalin/test/pam_sasldb-20011022.tgz.

Why is it not in some "contributed" folder?

It may be used, for example, to keep in sync sasldb and WinNT passwords,
since MS Services For Unix ver 3 do it via PAM.
For less exotic uses of PAM - see relevant FAQ.

It seems the original module is for an older version of cyrus-sasl.
To make it work with current release, I had to:
 Add some minimal changes (stolen from saslpasswd) to write to sasldb.
 Copy the source directory into cyrus-sasl dir.
 Add to /etc/pam.conf
 passwd auth required pam_sasldb.so try_first_pass service=sasldb
 passwd password required pam_sasldb.so            service=sasldb
Some aspects may be scpecific to my system (FreeBSD 4).
		Sincerely, Michail
PS. If the idea of pam_sasldb does not attract public attention again -
 OK, I will be able to find my patch in the list archive in case of
 hard disk crash ;)
PPS. Is there a way to change sasldb password using exported API or
(better) remotely, by some sort of SASL aware client?
Does sasl_setpass call work for sasldb?

Makefile:
-------------------------------
LIB=		pam_sasldb
SRCS=		pam_sasldb.c
CFLAGS+=	-Wall
CFLAGS+=	-I/usr/local/include/sasl
LDADD+=		-lsasl2 -ldb3
LDADD+=		-L/usr/local/lib ../sasldb/allockey.o ../sasldb/db_berkeley.o
NOOBJ=		true
SHLIB_NAME=	${LIB}.so
MAN=		pam_sasldb.8

.include <bsd.lib.mk>
--------------------------------
pam_sasldb.c diff:

--- pam_sasldb.c.orig	Mon Oct 22 23:16:59 2001
+++ pam_sasldb.c	Mon Feb 17 08:00:34 2003
@@ -41,16 +41,23 @@
 #include <string.h>
 #include <syslog.h>
 #include <unistd.h>
+#include <sys/param.h>

-#define PAM_SM_AUTHENTICATE
-#define PAM_SM_CHAUTHTOK
+#define PAM_SM_AUTH
+#define PAM_SM_PASSWORD
 #include <security/pam_modules.h>

 #include <sasl.h>

+#include <saslplug.h>
+#include "../sasldb/sasldb.h"
+#include "../config.h"
+/* Cheating to make the utils work out right */
+extern const sasl_utils_t *sasl_global_utils;
+
 #define PREFIX "pam_sasldb: "
 #ifndef _PATH_SASLDB
-#define _PATH_SASLDB "/etc/sasldb"
+#define _PATH_SASLDB SASL_DB_PATH
 #endif

 PAM_EXTERN int
@@ -63,12 +70,11 @@
 	int debug = 0;

 	const char *service = NULL, *realm = NULL;
-	const char *error;
 	struct sasl_conn *conn;
 	struct sasl_callback cb = {
 		SASL_CB_LIST_END,
 		NULL,
-		NULL,
+		NULL
 	};

 	/* Find the conversation function.  This should never fail. */
@@ -105,6 +111,24 @@
 		}
 	}

+	if(!realm) {
+		char myhostname[MAXHOSTNAMELEN];
+		int result;
+
+		memset(myhostname, 0, MAXHOSTNAMELEN);
+		result = gethostname(myhostname, MAXHOSTNAMELEN-1);
+		if(result == -1) {
+			syslog(LOG_WARNING, PREFIX
+				"error determining realm by gethostname\n");
+			return PAM_SYSTEM_ERR;
+		} else if(!(realm=strdup(myhostname))) {
+			syslog(LOG_WARNING, PREFIX
+				"insufficient memory\n");
+			return PAM_SYSTEM_ERR;
+		}
+
+	}
+
 	/* Find the user.  This should never fail. */
 	ret = pam_get_user(pamh, (const char**)&user, "login: ");
 	if((ret != PAM_SUCCESS) || (user == NULL) || (strlen(user) == 0)) {
@@ -158,27 +182,27 @@
 	}

 	/* Initialize libsasl. */
-	error = NULL;
 	ret = sasl_server_init(&cb, service ?: "PAM");
 	if(ret != SASL_OK) {
 		syslog(LOG_WARNING, PREFIX "error initializing server: %s\n",
-		       error ?: sasl_errstring(ret, NULL, NULL));
+		       sasl_errstring(ret, NULL, NULL));
 		return PAM_SYSTEM_ERR;
 	}
 	if(debug) syslog(LOG_DEBUG, PREFIX "sasl_server_init\n");

 	/* Initialize a connection context. */
-	error = NULL;
 	ret = sasl_server_new(service,
 			      NULL,
 			      realm,
+			      NULL,
+			      NULL,
 			      &cb,
 			      SASL_SEC_NOANONYMOUS,
 			      &conn);
 	if(ret != SASL_OK) {
 		if(debug) syslog(LOG_DEBUG, PREFIX
 				 "error allocating server context: %s\n",
-				 error ?: sasl_errstring(ret, NULL, NULL));
+				 sasl_errstring(ret, NULL, NULL));
 		return PAM_SYSTEM_ERR;
 	}
 	if(debug) syslog(LOG_DEBUG, PREFIX "sasl_server_new\n");
@@ -186,11 +210,10 @@
 	/* Check the user's password. */
 	ret = sasl_checkpass(conn,
 			     user, strlen(user),
-			     password, strlen(password),
-			     &error);
+			     password, strlen(password));
 	if(ret != SASL_OK) {
 		syslog(LOG_WARNING, PREFIX "error checking password: %s\n",
-		       error ?: sasl_errstring(ret, NULL, NULL));
+		       sasl_errstring(ret, NULL, NULL));
 		sasl_dispose(&conn);
 		return PAM_AUTH_ERR;
 	}
@@ -216,7 +239,6 @@
 	struct pam_response *responses = NULL;

 	const char *service = NULL, *realm = NULL;
-	const char *error;
 	const char *sasldb = _PATH_SASLDB;
 	struct sasl_conn *conn;
 	struct sasl_callback cb = {
@@ -253,6 +275,24 @@
 		}
 	}

+	if(!realm) {
+		char myhostname[MAXHOSTNAMELEN];
+		int result;
+
+		memset(myhostname, 0, MAXHOSTNAMELEN);
+		result = gethostname(myhostname, MAXHOSTNAMELEN-1);
+		if(result == -1) {
+			syslog(LOG_WARNING, PREFIX
+				"error determining realm by gethostname\n");
+			return PAM_SYSTEM_ERR;
+		} else if(!(realm=strdup(myhostname))) {
+			syslog(LOG_WARNING, PREFIX
+				"insufficient memory\n");
+			return PAM_SYSTEM_ERR;
+		}
+
+	}
+
 	/* Get the conversation pointer.  This should never fail. */
 	ret = pam_get_item(pamh, PAM_CONV, (const void**)&conv);
 	if(ret != PAM_SUCCESS) {
@@ -321,44 +361,42 @@
 	}

 	/* Initialize libsasl. */
-	error = NULL;
 	ret = sasl_server_init(&cb, service ?: "PAM");
 	if(ret != SASL_OK) {
 		syslog(LOG_WARNING, PREFIX "error initializing server: %s\n",
-		       error ?: sasl_errstring(ret, NULL, NULL));
+		       sasl_errstring(ret, NULL, NULL));
 		return PAM_SYSTEM_ERR;
 	}
 	if(debug) syslog(LOG_DEBUG, PREFIX "sasl_server_init\n");

 	/* Allocate a new server structure. */
-	error = NULL;
 	ret = sasl_server_new(service,
 			      NULL,
 			      realm,
+			      NULL,
+			      NULL,
 			      &cb,
 			      SASL_SEC_NOANONYMOUS,
 			      &conn);
 	if(ret != SASL_OK) {
 		syslog(LOG_WARNING, PREFIX
 		       "error allocating server context: %s\n",
-		       error ?: sasl_errstring(ret, NULL, NULL));
+		       sasl_errstring(ret, NULL, NULL));
 		return PAM_SYSTEM_ERR;
 	}
 	if(debug) syslog(LOG_DEBUG, PREFIX "sasl_server_new\n");

-	error = NULL;
 	if(flags & PAM_PRELIM_CHECK) {
 		/* On the preliminary check, we got here because the user
 		 * can't write to the sasldb, so check the password. */
 		ret = sasl_checkpass(conn,
 				     user, strlen(user),
-				     password, strlen(password),
-				     &error);
+				     password, strlen(password));

 		if(ret != SASL_OK) {
 			syslog(LOG_WARNING, PREFIX
 			       "error checking password: %s\n",
-			       error ?: sasl_errstring(ret, NULL, NULL));
+			       sasl_errstring(ret, NULL, NULL));
 			sasl_dispose(&conn);
 			return PAM_AUTH_ERR;
 		}
@@ -373,14 +411,44 @@
 				   user,
 				   password,
 				   strlen(password),
-				   SASL_SEC_NOANONYMOUS,
-				   &error);
+				   NULL, 0, 0);
 		if(ret != SASL_OK) {
 			syslog(LOG_WARNING, PREFIX
 			       "error setting password for `%s': %s\n",
-			       user, error ?: sasl_errstring(ret, NULL, NULL));
+			       user, sasl_errstring(ret, NULL, NULL));
 			return PAM_SYSTEM_ERR;
 		}
+	{
+	/* set the password */
+	sasl_secret_t *sec = NULL;
+	size_t passlen = strlen(password);
+
+	ret = _sasl_check_db(sasl_global_utils,conn);
+
+	if (ret == SASL_OK) {
+	    /* Create the sasl_secret_t */
+	    sec = malloc(sizeof(sasl_secret_t) + passlen);
+	    if(!sec) ret = SASL_NOMEM;
+	    else {
+		memcpy(sec->data, password, passlen);
+		sec->data[passlen] = '\0';
+		sec->len = passlen;
+	    }
+	}
+	if (ret == SASL_OK) {
+	    ret = _sasldb_putsecret(sasl_global_utils,
+				    conn, user, realm, sec);
+	}
+	if ( ret != SASL_OK ) {
+	    syslog(LOG_INFO, PREFIX "Could not set secret for %s\n", user);
+	}
+	if (sec) {
+	    memset(sec->data, 0, sec->len);
+	    free(sec);
+	    sec = NULL;
+	}
+	}
+
 		sasl_dispose(&conn);
 		syslog(LOG_INFO, PREFIX "set password for `%s'\n", user);
 		return PAM_SUCCESS;
@@ -391,3 +459,5 @@
 	sasl_dispose(&conn);
 	return PAM_SYSTEM_ERR;
 }
+
+PAM_MODULE_ENTRY("pam_sasldb");

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic