[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