[Date Prev][Date Next]
[Chronological]
[Thread]
[Top]
Re: ldap users auth to ldap ;)
On Tue, Sep 15, 1998 at 05:21:52PM -0700, Michael Thomas Cope wrote:
> On Tue, 15 Sep 1998, Jared Mauch wrote:
>
> >
> > Anyone doing this?
> >
> > What i am ideally trying to do is the following:
> >
> > for a cn=Luser
> >
> > they have cryptpw=XXXX
> >
> > and to bind they need to auth to that pw.
> >
> > (Yeah, i'm trying to avoid digging too far into source)
> >
> > - jared
> For just crypted passwords you should be fine with the appropritate
> defines in the Makefile.
> What I am more interested in is an authetication backend for LDAP, perhaps
> PAM that would allow pluggable authentication schemes. I hacked up our
> source to RADIUS as a backend but it's not a good solution long-term.
Attached is a patch I contributed to the Kiruna-LDAP effort, just before
it wrapped up. It adds two new config items to the back-end sections of
slapd.conf. These are:
pam-auth <on|off>
Specify whether you want to use PAM to handle authentication for
bind requests to this backend.
pam-auth-attr <attr-name>
Specifies the attribute which should contain the username to pass
to PAM during authentication. If pam-auth-attr is not specified,
the default is the uid attr.
I use this in our company directory. Each user's entry has a uid attr which
contains their username (which is the same across all machines, Linux
and NT).
The application name passed to PAM is 'slapd', so you can use /etc/pam.d/slapd
to configure the PAM module stack for your directory.
This will probably not apply to the OpenLDAP code, but I'm sure it can
be adapted. Unfortunately, I don't have time to do it right now. (I was
planning to contribute it in a few weeks time, but seeing as someone else
needs it, it's all yours!)
Kenn
> -Mike
> --
> Michael Cope: Harvey Mudd College '00; Armand Hammer UWC '96
> E-mail: Michael_Cope@hmc.edu
>
>
diff -urN ldap-980711/servers/slapd/Makefile.am ldap-980711-pam/servers/slapd/Makefile.am
--- ldap-980711/servers/slapd/Makefile.am Thu May 21 16:25:20 1998
+++ ldap-980711-pam/servers/slapd/Makefile.am Sun Jul 26 17:43:32 1998
@@ -20,7 +20,7 @@
$(top_srcdir)/libraries/libavl/libavl.a \
$(top_srcdir)/libraries/libldif/libldif.a \
$(top_srcdir)/libraries/liblthread/liblthread.a \
- -lgdbm
+ -lgdbm -lpam -ldl
slapd_SOURCES=\
main.c daemon.c connection.c search.c add.c \
diff -urN ldap-980711/servers/slapd/back-ldbm/back-ldbm.h ldap-980711-pam/servers/slapd/back-ldbm/back-ldbm.h
--- ldap-980711/servers/slapd/back-ldbm/back-ldbm.h Fri May 22 12:21:22 1998
+++ ldap-980711-pam/servers/slapd/back-ldbm/back-ldbm.h Sat Jul 25 21:12:02 1998
@@ -109,6 +109,8 @@
#ifdef USE_THREADS
pthread_cond_t li_dbcache_cv;
#endif
+ int li_use_pam_auth;
+ char *li_pam_auth_attr;
};
#ifdef NEEDPROTOS
diff -urN ldap-980711/servers/slapd/back-ldbm/bind.c ldap-980711-pam/servers/slapd/back-ldbm/bind.c
--- ldap-980711/servers/slapd/back-ldbm/bind.c Thu May 21 13:32:15 1998
+++ ldap-980711-pam/servers/slapd/back-ldbm/bind.c Sun Jul 26 17:44:16 1998
@@ -1,15 +1,18 @@
/* bind.c - ldbm backend bind and unbind routines */
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "slap.h"
#include "back-ldbm.h"
+#include <security/pam_appl.h>
#ifdef KERBEROS
#include "krb.h"
#endif
+
extern Entry *dn2entry();
extern Attribute *attr_find();
@@ -17,6 +20,9 @@
extern int krbv4_ldap_auth();
#endif
+static int do_pam_auth( Backend *be, Connection *conn, Operation *op,
+ char *dn, Entry *e, struct berval *cred, struct ldbminfo *li);
+
int
ldbm_back_bind(
Backend *be,
@@ -70,26 +76,34 @@
return( 0 );
}
- if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
- if ( be_isroot_pw( be, dn, cred ) ) {
- /* front end will send result */
- return( 0 );
+ if ( li->li_use_pam_auth ) {
+ if ( do_pam_auth( be, conn, op, dn, e, cred, li ) ) {
+ /* PAM auth failed. do_pam_auth() has
+ already called send_ldap_result() */
+ return( 1 );
+ }
+ } else {
+ if ( (a = attr_find( e->e_attrs, "userpassword" )) == NULL ) {
+ if ( be_isroot_pw( be, dn, cred ) ) {
+ /* front end will send result */
+ return( 0 );
+ }
+ send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
+ NULL, NULL );
+ cache_return_entry( &li->li_cache, e );
+ return( 1 );
}
- send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
- NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
- }
- if ( value_find( a->a_vals, cred, a->a_syntax, 0 ) != 0 ) {
- if ( be_isroot_pw( be, dn, cred ) ) {
- /* front end will send result */
- return( 0 );
+ if ( value_find( a->a_vals, cred, a->a_syntax, 0 ) != 0 ) {
+ if ( be_isroot_pw( be, dn, cred ) ) {
+ /* front end will send result */
+ return( 0 );
+ }
+ send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
+ NULL, NULL );
+ cache_return_entry( &li->li_cache, e );
+ return( 1 );
}
- send_ldap_result( conn, op, LDAP_INVALID_CREDENTIALS,
- NULL, NULL );
- cache_return_entry( &li->li_cache, e );
- return( 1 );
}
break;
@@ -148,3 +162,146 @@
/* success: front end will send result */
return( 0 );
}
+
+
+/* Use PAM to authenticate. First, a user ID is obtained from the
+ attribute specified by the pam-auth-attr config option (default
+ is the 'uid' attribute). Then the PAM library is called to
+ perform the authentication itself. The application name passed
+ to PAM is 'slapd'.
+
+ This code is based on Michael K Johnson's PAM auth code in
+ RedHat's IMAP server. */
+
+/* The pam_auth_info structure is used to pass info to the
+ PAM conversation function */
+
+struct pam_auth_info {
+ char *username;
+ char *password;
+ int pam_error;
+};
+
+/* Forward declaration of the PAM conversation function */
+static int pam_conv_func (int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *appdata_ptr);
+
+static int do_pam_auth( Backend *be, Connection *conn, Operation *op,
+ char *dn, Entry *e, struct berval *cred, struct ldbminfo *li)
+{
+ char *uid_attr = "uid";
+ Attribute *a;
+ char *uid;
+ pam_handle_t *pamh = NULL;
+ int pam_error;
+ struct pam_auth_info auth_info;
+ struct pam_conv pam_conv_info;
+
+ if (li->li_pam_auth_attr != NULL) {
+ uid_attr = li->li_pam_auth_attr;
+ }
+
+ if ( (a = attr_find( e->e_attrs, uid_attr )) == NULL ) {
+ if ( be_isroot_pw( be, dn, cred ) ) {
+ /* front end will send result */
+ return( 0 );
+ }
+ send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
+ NULL, NULL );
+ cache_return_entry( &li->li_cache, e );
+ return( 1 );
+ }
+
+ if ( (a->a_vals[0] == NULL) ||
+ ( (uid = a->a_vals[0]->bv_val) == NULL) ) {
+ send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH,
+ NULL, NULL );
+ cache_return_entry( &li->li_cache, e );
+ return( 1 );
+ }
+
+ auth_info.username = uid;
+ auth_info.password = cred->bv_val;
+ auth_info.pam_error = 0;
+
+ pam_conv_info.conv = pam_conv_func;
+ pam_conv_info.appdata_ptr = &auth_info;
+
+#define PAM_BAIL \
+ if (auth_info.pam_error || (pam_error != PAM_SUCCESS)) { \
+ pam_end(pamh, 0); \
+ send_ldap_result( conn, op, LDAP_INAPPROPRIATE_AUTH, \
+ NULL, NULL ); \
+ cache_return_entry( &li->li_cache, e ); \
+ return( 1 ); \
+ }
+
+ pam_error = pam_start("slapd", uid, &pam_conv_info, &pamh);
+ PAM_BAIL;
+
+ pam_error = pam_authenticate(pamh, 0);
+ PAM_BAIL;
+
+ pam_error = pam_acct_mgmt(pamh, 0);
+ PAM_BAIL;
+
+ /* I'm not sure if this call is really needed */
+ pam_error = pam_setcred(pamh, PAM_ESTABLISH_CRED);
+ PAM_BAIL;
+
+ pam_end(pamh, PAM_SUCCESS);
+
+ /* If we've got to here, then the uid and password were
+ successfully authenticated */
+
+ return( 0 );
+}
+
+/* PAM conversation function
+ * Here we assume (for now, at least) that echo on means login name, and
+ * echo off means password.
+ */
+static int pam_conv_func (int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *appdata_ptr)
+{
+ int replies = 0;
+ struct pam_response *reply = NULL;
+ struct pam_auth_info *auth_info;
+
+ auth_info = (struct pam_auth_info *) appdata_ptr;
+
+#define COPY_STRING(s) (s) ? strdup(s) : NULL
+
+ reply = malloc(sizeof(struct pam_response) * num_msg);
+ if (reply == NULL) return PAM_CONV_ERR;
+
+ for (replies = 0; replies < num_msg; replies++) {
+ switch (msg[replies]->msg_style) {
+ case PAM_PROMPT_ECHO_ON:
+ reply[replies].resp_retcode = PAM_SUCCESS;
+ reply[replies].resp = COPY_STRING(auth_info->username);
+ /* PAM frees resp */
+ break;
+ case PAM_PROMPT_ECHO_OFF:
+ reply[replies].resp_retcode = PAM_SUCCESS;
+ reply[replies].resp = COPY_STRING(auth_info->password);
+ /* PAM frees resp */
+ break;
+ case PAM_TEXT_INFO:
+ /* fall through */
+ case PAM_ERROR_MSG:
+ /* ignore it, but pam still wants a NULL response... */
+ reply[replies].resp_retcode = PAM_SUCCESS;
+ reply[replies].resp = NULL;
+ break;
+ default:
+ /* Must be an error of some sort... */
+ free (reply);
+ auth_info->pam_error = 1;
+ return PAM_CONV_ERR;
+ }
+ }
+ *resp = reply;
+ return PAM_SUCCESS;
+}
+
diff -urN ldap-980711/servers/slapd/back-ldbm/config.c ldap-980711-pam/servers/slapd/back-ldbm/config.c
--- ldap-980711/servers/slapd/back-ldbm/config.c Thu May 21 13:32:15 1998
+++ ldap-980711-pam/servers/slapd/back-ldbm/config.c Sun Jul 26 17:43:51 1998
@@ -77,6 +77,30 @@
}
li->li_dbcachesize = atoi( argv[1] );
+ /* should we use PAM for authentication? */
+ } else if ( strcasecmp( argv[0], "pam-auth" ) == 0 ) {
+ if ( argc < 2 ) {
+ fprintf( stderr,
+ "%s: line %d: missing on|off in \"pam-auth <on|off>\" line\n",
+ fname, lineno, 0 );
+ exit( 1 );
+ }
+ if ( strcasecmp( argv[1], "on" ) == 0 ) {
+ li->li_use_pam_auth = 1;
+ } else {
+ li->li_use_pam_auth = 0;
+ }
+
+ /* which attribute should we use as the user ID for PAM */
+ } else if ( strcasecmp( argv[0], "pam-auth-attr" ) == 0 ) {
+ if ( argc < 2 ) {
+ fprintf( stderr,
+ "%s: line %d: missing dir in \"pam-auth-attr <dir>\" line\n",
+ fname, lineno );
+ exit( 1 );
+ }
+ li->li_pam_auth_attr = strdup( argv[1] );
+
/* anything else */
} else {
fprintf( stderr,
diff -urN ldap-980711/servers/slapd/back-ldbm/init.c ldap-980711-pam/servers/slapd/back-ldbm/init.c
--- ldap-980711/servers/slapd/back-ldbm/init.c Fri May 22 12:21:23 1998
+++ ldap-980711-pam/servers/slapd/back-ldbm/init.c Sat Jul 25 22:45:22 1998
@@ -33,6 +33,10 @@
/* default database directory */
li->li_directory = DEFAULT_DB_DIRECTORY;
+ /* Default to not using PAM */
+ li->li_use_pam_auth = 0;
+ li->li_pam_auth_attr = 0;
+
/* always index dn, id2children, objectclass (used in some searches) */
argv[ 0 ] = "dn";
argv[ 1 ] = "dn";
diff -urN ldap-980711/servers/tools/Makefile.am ldap-980711-pam/servers/tools/Makefile.am
--- ldap-980711/servers/tools/Makefile.am Thu May 21 16:25:26 1998
+++ ldap-980711-pam/servers/tools/Makefile.am Sun Jul 26 19:38:09 1998
@@ -16,7 +16,7 @@
$(top_srcdir)/libraries/liblthread/liblthread.a \
../slapd/back-passwd/libbackpasswd.a \
../slapd/libslap.a \
- -lgdbm
+ -lgdbm -lpam -ldl
INCLUDES=-I$(top_srcdir)/include -I../slapd
diff -urN ldap-980711/servers/tools/Makefile.in ldap-980711-pam/servers/tools/Makefile.in
--- ldap-980711/servers/tools/Makefile.in Sun Jul 26 20:19:53 1998
+++ ldap-980711-pam/servers/tools/Makefile.in Sun Jul 26 20:20:53 1998
@@ -73,7 +73,7 @@
$(top_srcdir)/libraries/liblthread/liblthread.a \
../slapd/back-passwd/libbackpasswd.a \
../slapd/libslap.a \
- -lgdbm
+ -lgdbm -lpam -ldl
INCLUDES=-I$(top_srcdir)/include -I../slapd