summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2009-05-08 22:55:24 +0000
committerArthur de Jong <arthur@arthurdejong.org>2009-05-08 22:55:24 +0000
commit57af21c442f9dbd61525ba2ba77afc93dfcf81c3 (patch)
treed44875c4aedcb2d39a9361e9fe7f376bd2baddf0
parent5ccf22cdedf722d0de4ff283a85ee6575bb2e600 (diff)
set up basic PAM protocol handling and get authentication call working by binding to the server
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd@870 ef36b2f9-881f-0410-afb5-c4e39611909c
-rw-r--r--nslcd/common.h4
-rw-r--r--nslcd/myldap.c29
-rw-r--r--nslcd/myldap.h7
-rw-r--r--nslcd/pam.c290
-rw-r--r--nslcd/passwd.c10
5 files changed, 228 insertions, 112 deletions
diff --git a/nslcd/common.h b/nslcd/common.h
index d1c4c50..6013fa0 100644
--- a/nslcd/common.h
+++ b/nslcd/common.h
@@ -79,6 +79,10 @@ int read_address(TFILE *fp,char *addr,int *addrlen,int *af);
/* checks to see if the specified string is a valid user or group name */
MUST_USE int isvalidname(const char *name);
+/* Perform an LDAP lookup to translate the DN into a uid.
+ This function either returns NULL or a strdup()ed string. */
+char *lookup_dn2uid(MYLDAP_SESSION *session,const char *dn,int *rcp);
+
/* transforms the DN info a uid doing an LDAP lookup if needed */
MUST_USE char *dn2uid(MYLDAP_SESSION *session,const char *dn,char *buf,size_t buflen);
diff --git a/nslcd/myldap.c b/nslcd/myldap.c
index f4f4980..2afb8af 100644
--- a/nslcd/myldap.c
+++ b/nslcd/myldap.c
@@ -96,6 +96,10 @@ struct ldap_session
{
/* the connection */
LDAP *ld;
+ /* the username to bind with */
+ char binddn[256];
+ /* the password to bind with if any */
+ char bindpw[64];
/* timestamp of last activity */
time_t lastactivity;
/* index into ldc_uris: currently connected LDAP uri */
@@ -277,6 +281,8 @@ static MYLDAP_SESSION *myldap_session_new(void)
}
/* initialize the session */
session->ld=NULL;
+ session->binddn[0]='\0';
+ session->bindpw[0]='\0';
session->lastactivity=0;
session->current_uri=0;
for (i=0;i<MAX_SEARCHES_IN_SESSION;i++)
@@ -371,6 +377,7 @@ static int do_bind(MYLDAP_SESSION *session,const char *uri)
#ifndef HAVE_SASL_INTERACT_T
struct berval cred;
#endif /* not HAVE_SASL_INTERACT_T */
+#endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */
#ifdef LDAP_OPT_X_TLS
/* check if StartTLS is requested */
if (nslcd_cfg->ldc_ssl_on==SSL_START_TLS)
@@ -386,6 +393,15 @@ static int do_bind(MYLDAP_SESSION *session,const char *uri)
}
}
#endif /* LDAP_OPT_X_TLS */
+ /* check if the binddn and bindpw are overwritten in the session */
+ if (session->binddn[0]!='\0')
+ {
+ /* do a simple bind */
+ log_log(LOG_DEBUG,"ldap_simple_bind_s(\"%s\",%s) (uri=\"%s\")",session->binddn,
+ (session->bindpw[0]!='\0')?"\"*****\"":"empty",uri);
+ return ldap_simple_bind_s(session->ld,session->binddn,session->bindpw);
+ }
+#ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S
/* TODO: store this information in the session */
if (!nslcd_cfg->ldc_usesasl)
{
@@ -670,6 +686,19 @@ static int do_open(MYLDAP_SESSION *session)
return LDAP_SUCCESS;
}
+/* Set alternative credentials for the session. */
+int myldap_set_credentials(MYLDAP_SESSION *session,const char *dn,
+ const char *password)
+{
+ /* copy dn and password into session */
+ strncpy(session->binddn,dn,sizeof(session->binddn));
+ session->binddn[sizeof(session->binddn)-1]='\0';
+ strncpy(session->bindpw,password,sizeof(session->bindpw));
+ session->bindpw[sizeof(session->bindpw)-1]='\0';
+ /* try to open a connection */
+ return do_open(session);
+}
+
static int do_try_search(MYLDAP_SEARCH *search)
{
int rc;
diff --git a/nslcd/myldap.h b/nslcd/myldap.h
index 01ee55d..c990e86 100644
--- a/nslcd/myldap.h
+++ b/nslcd/myldap.h
@@ -68,6 +68,11 @@ typedef struct myldap_entry MYLDAP_ENTRY;
uses the configuration to find the URLs to attempt connections to. */
MUST_USE MYLDAP_SESSION *myldap_create_session(void);
+/* Set alternative credentials for the session and try to open a connection
+ with those credentials. Returns an LDAP status code. */
+int myldap_set_credentials(MYLDAP_SESSION *session,const char *dn,
+ const char *password);
+
/* Closes all pending searches and deallocates any memory that is allocated
with these searches. This does not close the session. */
void myldap_session_cleanup(MYLDAP_SESSION *session);
@@ -122,7 +127,7 @@ MUST_USE const char *myldap_cpy_rdn_value(const char *dn,const char *attr,
/* Escapes characters in a string for use in a search filter. */
MUST_USE int myldap_escape(const char *src,char *buffer,size_t buflen);
-/* Set the debug level globally. */
+/* Set the debug level globally. Returns an LDAP status code. */
int myldap_set_debuglevel(int i);
#endif /* not _MYLDAP_H */
diff --git a/nslcd/pam.c b/nslcd/pam.c
index 91a6416..33b6699 100644
--- a/nslcd/pam.c
+++ b/nslcd/pam.c
@@ -34,159 +34,231 @@
#include "myldap.h"
#include "cfg.h"
-/* for PAM status codes */
-#include <security/pam_modules.h>
+
+/* set up a connection and try to bind with the specified DN and password
+ returns a NSLCD_PAM_* error code */
+static int try_bind(const char *userdn,const char *password)
+{
+ MYLDAP_SESSION *session;
+ char *username;
+ int rc;
+ /* set up a new connection */
+ session=myldap_create_session();
+ if (session==NULL)
+ return NSLCD_PAM_AUTH_ERR;
+ /* set up credentials for the session */
+ rc=myldap_set_credentials(session,userdn,password);
+ /* TODO: test rc */
+ if (rc==LDAP_SUCCESS)
+ {
+ /* perform search for own object */
+ username=lookup_dn2uid(session,userdn,&rc);
+ /* TODO: return this as cannonical name */
+ if (username!=NULL)
+ free(username);
+ }
+ /* close the session */
+ myldap_session_close(session);
+ /* handle the results */
+ switch(rc)
+ {
+ case LDAP_SUCCESS: return NSLCD_PAM_SUCCESS;
+ case LDAP_INVALID_CREDENTIALS: return NSLCD_PAM_AUTH_ERR;
+ default: return NSLCD_PAM_AUTH_ERR;
+ }
+}
/* check authentication credentials of the user */
int nslcd_pam_authc(TFILE *fp,MYLDAP_SESSION *session)
{
- /* define common variables */
int32_t tmpint32;
- MYLDAP_SEARCH *search;
- MYLDAP_ENTRY *entry;
- int rc=PAM_AUTH_ERR;
- char uid[256];
- char svc[256];
- char pwd[256];
+ int rc;
+ char username[256];
char userdn[256];
+ char servicename[64];
+ char password[64];
/* read request parameters */
- READ_STRING_BUF2(fp,uid,sizeof(uid));
- if (!isvalidname(uid)) {
- log_log(LOG_WARNING,"nslcd_pam_authc(%s): invalid user name",uid);
- /* write a response message anyway */
- /* TODO: probably just write NSLCD_RESULT_END to indicate failure */
- WRITE_INT32(fp,NSLCD_VERSION);
- WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHC);
- WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
- WRITE_INT32(fp,PAM_USER_UNKNOWN); /* authok */
- WRITE_INT32(fp,PAM_SUCCESS); /* authz */
- WRITE_STRING(fp,""); /* dn */
- WRITE_STRING(fp,""); /* authzmsg */
- WRITE_STRING(fp,""); /* tmpluser */
- return -1;
- }
- READ_STRING_BUF2(fp,svc,sizeof(svc));
- READ_STRING_BUF2(fp,pwd,sizeof(pwd));
+ READ_STRING_BUF2(fp,username,sizeof(username));
+ READ_STRING_BUF2(fp,userdn,sizeof(userdn));
+ READ_STRING_BUF2(fp,servicename,sizeof(servicename));
+ READ_STRING_BUF2(fp,password,sizeof(password));
/* log call */
- log_log(LOG_DEBUG,"nslcd_pam_authc(%s,%s,passwd)",uid,svc);
+ log_log(LOG_DEBUG,"nslcd_pam_authc(\"%s\",\"%s\",\"%s\")",username,userdn,servicename);
/* write the response header */
WRITE_INT32(fp,NSLCD_VERSION);
WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHC);
- /* set up a new connection */
-
- /* FIXME: implement setting up connection, perform uid->DN expansion
- and bind with DN and pwd */
-
- /* maye use existing session for uid2dn lookup and make new connection
- just for binding, also be sure to clean up session (probably set up a
- session here, call another function to get the results, etc) */
-
- /* perform uid to DN translation */
- if (uid2dn(session,uid,userdn,sizeof(userdn))==NULL)
+ /* validate request */
+ if (!isvalidname(username))
{
- log_log(LOG_WARNING,"nslcd_pam_authc(%s): user not found",uid);
- /* return error to client */
- /* FIXME: probably return NSLCD_RESULT_END instead */
+ log_log(LOG_WARNING,"nslcd_pam_authc(\"%s\"): invalid user name",username);
+ /* write a response message anyway */
+ /* TODO: maybe just write NSLCD_RESULT_END to indicate failure */
WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
- WRITE_INT32(fp,PAM_USER_UNKNOWN); /* authok */
- WRITE_INT32(fp,PAM_SUCCESS); /* authz */
- WRITE_STRING(fp,""); /* dn */
- WRITE_STRING(fp,""); /* authzmsg */
- WRITE_STRING(fp,""); /* tmpluser */
+ WRITE_STRING(fp,username);
+ WRITE_STRING(fp,userdn);
+ WRITE_INT32(fp,NSLCD_PAM_USER_UNKNOWN); /* authc */
+ WRITE_INT32(fp,NSLCD_PAM_USER_UNKNOWN); /* authz */
+ WRITE_STRING(fp,"invalid username"); /* authzmsg */
+ WRITE_INT32(fp,NSLCD_RESULT_END);
return -1;
}
-
- /* TODO: perform bind
-
- switch(rs.sr_err) {
- case LDAP_SUCCESS: rc = PAM_SUCCESS; break;
- case LDAP_INVALID_CREDENTIALS: rc = PAM_AUTH_ERR; break;
- default: rc = PAM_AUTH_ERR; break;
- }*/
-
+ if (userdn[0]=='\0')
+ {
+ /* perform username to DN translation */
+ if (uid2dn(session,username,userdn,sizeof(userdn))==NULL)
+ {
+ log_log(LOG_WARNING,"nslcd_pam_authc(\"%s\"): user not found",username);
+ /* return error to client */
+ WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
+ WRITE_STRING(fp,username);
+ WRITE_STRING(fp,userdn);
+ WRITE_INT32(fp,NSLCD_PAM_USER_UNKNOWN); /* authc */
+ WRITE_INT32(fp,NSLCD_PAM_USER_UNKNOWN); /* authz */
+ WRITE_STRING(fp,"unknown username"); /* authzmsg */
+ WRITE_INT32(fp,NSLCD_RESULT_END);
+ return -1;
+ }
+ }
+ /* try authentication */
+ rc=try_bind(userdn,password);
+ /* write response */
WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
- WRITE_INT32(fp,rc); /* authok */
- WRITE_INT32(fp,PAM_SUCCESS); /* authz */
- WRITE_STRING(fp,userdn); /* dn */
- WRITE_STRING(fp,""); /* authzmsg */
- WRITE_STRING(fp,""); /* tmpluser */
-
+ WRITE_STRING(fp,username); /* TODO: get canonical name */
+ WRITE_STRING(fp,userdn);
+ WRITE_INT32(fp,rc); /* authc */
+ WRITE_INT32(fp,rc); /* authz */
+ WRITE_STRING(fp,""); /* authzmsg */
+ WRITE_INT32(fp,NSLCD_RESULT_END);
return 0;
}
/* check authorisation of the user */
int nslcd_pam_authz(TFILE *fp,MYLDAP_SESSION *session)
{
-/*
- struct berval dn, svc;
- struct berval authzmsg = BER_BVNULL;
int32_t tmpint32;
- char dnc[1024];
- char svcc[256];
-
- READ_STRING_BUF2(fp,dnc,sizeof(dnc));
- dn.bv_val = dnc;
- dn.bv_len = tmpint32;
- READ_STRING_BUF2(fp,svcc,sizeof(svcc));
- svc.bv_val = svcc;
- svc.bv_len = tmpint32;
-
- Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(%s)\n",dn.bv_val,0,0);
-
+ int rc;
+ char username[256];
+ char userdn[256];
+ char servicename[64];
+ /* read request parameters */
+ READ_STRING_BUF2(fp,username,sizeof(username));
+ READ_STRING_BUF2(fp,userdn,sizeof(userdn));
+ READ_STRING_BUF2(fp,servicename,sizeof(servicename));
+ /* log call */
+ log_log(LOG_DEBUG,"nslcd_pam_authz(\"%s\",\"%s\",\"%s\")",username,userdn,servicename);
+ /* write the response header */
WRITE_INT32(fp,NSLCD_VERSION);
WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ);
+ /* validate request */
+ if (!isvalidname(username))
+ {
+ log_log(LOG_WARNING,"nslcd_pam_authc(\"%s\"): invalid user name",username);
+ /* write a response message anyway */
+ /* TODO: maybe just write NSLCD_RESULT_END to indicate failure */
+ WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
+ WRITE_STRING(fp,username);
+ WRITE_STRING(fp,userdn);
+ WRITE_INT32(fp,NSLCD_PAM_USER_UNKNOWN); /* authz */
+ WRITE_STRING(fp,"invalid username"); /* authzmsg */
+ WRITE_INT32(fp,NSLCD_RESULT_END);
+ return -1;
+ }
+ if (userdn[0]=='\0')
+ {
+ /* perform username to DN translation */
+ if (uid2dn(session,username,userdn,sizeof(userdn))==NULL)
+ {
+ log_log(LOG_WARNING,"nslcd_pam_authc(\"%s\"): user not found",username);
+ /* return error to client */
+ WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
+ WRITE_STRING(fp,username);
+ WRITE_STRING(fp,userdn);
+ WRITE_INT32(fp,NSLCD_PAM_USER_UNKNOWN); /* authz */
+ WRITE_STRING(fp,"unknown username"); /* authzmsg */
+ WRITE_INT32(fp,NSLCD_RESULT_END);
+ return -1;
+ }
+ }
+ /* try dn to username lookup */
+ if (dn2uid(session,userdn,username,sizeof(username))==NULL)
+ {
+ log_log(LOG_WARNING,"nslcd_pam_authc(\"%s\"): username not found",userdn);
+ /* return error to client */
+ WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
+ WRITE_STRING(fp,username);
+ WRITE_STRING(fp,userdn);
+ WRITE_INT32(fp,NSLCD_PAM_USER_UNKNOWN); /* authz */
+ WRITE_STRING(fp,"unknown username"); /* authzmsg */
+ WRITE_INT32(fp,NSLCD_RESULT_END);
+ return -1;
+ }
+ /* write response */
WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
- WRITE_INT32(fp,PAM_SUCCESS);
- WRITE_BERVAL(fp,&authzmsg);
-*/
+ WRITE_STRING(fp,username);
+ WRITE_STRING(fp,userdn);
+ WRITE_INT32(fp,rc); /* authz */
+ WRITE_STRING(fp,""); /* authzmsg */
+ WRITE_INT32(fp,NSLCD_RESULT_END);
return 0;
}
int nslcd_pam_sess_o(TFILE *fp,MYLDAP_SESSION *session)
{
-/*
- struct berval dn, svc;
int32_t tmpint32;
- char dnc[1024];
- char svcc[256];
-
- READ_STRING_BUF2(fp,dnc,sizeof(dnc));
- dn.bv_val = dnc;
- dn.bv_len = tmpint32;
- READ_STRING_BUF2(fp,svcc,sizeof(svcc));
- svc.bv_val = svcc;
- svc.bv_len = tmpint32;
-
- Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_o(%s)\n",dn.bv_val,0,0);
-
+ int rc;
+ char username[256];
+ char userdn[256];
+ char servicename[64];
+ char tty[64],rhost[64],ruser[256];
+ int32_t sessionid;
+ /* read request parameters */
+ READ_STRING_BUF2(fp,username,sizeof(username));
+ READ_STRING_BUF2(fp,userdn,sizeof(userdn));
+ READ_STRING_BUF2(fp,servicename,sizeof(servicename));
+ READ_STRING_BUF2(fp,tty,sizeof(tty));
+ READ_STRING_BUF2(fp,rhost,sizeof(rhost));
+ READ_STRING_BUF2(fp,ruser,sizeof(ruser));
+ READ_INT32(fp,sessionid);
+ /* log call */
+ log_log(LOG_DEBUG,"nslcd_pam_sess_o(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\")",
+ username,userdn,servicename,tty,rhost,ruser);
+ /* write the response header */
WRITE_INT32(fp,NSLCD_VERSION);
WRITE_INT32(fp,NSLCD_ACTION_PAM_SESS_O);
+ /* write response */
WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
-*/
+ WRITE_INT32(fp,12345); /* session id */
+ WRITE_INT32(fp,NSLCD_RESULT_END);
return 0;
}
int nslcd_pam_sess_c(TFILE *fp,MYLDAP_SESSION *session)
{
-/*
- struct berval dn, svc;
int32_t tmpint32;
- char dnc[1024];
- char svcc[256];
-
- READ_STRING_BUF2(fp,dnc,sizeof(dnc));
- dn.bv_val = dnc;
- dn.bv_len = tmpint32;
- READ_STRING_BUF2(fp,svcc,sizeof(svcc));
- svc.bv_val = svcc;
- svc.bv_len = tmpint32;
-
- Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_c(%s)\n",dn.bv_val,0,0);
-
+ int rc;
+ char username[256];
+ char userdn[256];
+ char servicename[64];
+ char tty[64],rhost[64],ruser[256];
+ int32_t sessionid;
+ /* read request parameters */
+ READ_STRING_BUF2(fp,username,sizeof(username));
+ READ_STRING_BUF2(fp,userdn,sizeof(userdn));
+ READ_STRING_BUF2(fp,servicename,sizeof(servicename));
+ READ_STRING_BUF2(fp,tty,sizeof(tty));
+ READ_STRING_BUF2(fp,rhost,sizeof(rhost));
+ READ_STRING_BUF2(fp,ruser,sizeof(ruser));
+ READ_INT32(fp,sessionid);
+ /* log call */
+ log_log(LOG_DEBUG,"nslcd_pam_sess_c(\"%s\",\"%s\",\"%s\",%d)",
+ username,userdn,servicename,(int)sessionid);
+ /* write the response header */
WRITE_INT32(fp,NSLCD_VERSION);
WRITE_INT32(fp,NSLCD_ACTION_PAM_SESS_C);
+ /* write response */
WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
-*/
+ WRITE_INT32(fp,0); /* session id */
+ WRITE_INT32(fp,NSLCD_RESULT_END);
return 0;
}
diff --git a/nslcd/passwd.c b/nslcd/passwd.c
index a8cc603..1f2f657 100644
--- a/nslcd/passwd.c
+++ b/nslcd/passwd.c
@@ -139,7 +139,7 @@ struct dn2uid_cache_entry
/* Perform an LDAP lookup to translate the DN into a uid.
This function either returns NULL or a strdup()ed string. */
-static char *lookup_dn2uid(MYLDAP_SESSION *session,const char *dn)
+char *lookup_dn2uid(MYLDAP_SESSION *session,const char *dn,int *rcp)
{
MYLDAP_SEARCH *search;
MYLDAP_ENTRY *entry;
@@ -147,6 +147,8 @@ static char *lookup_dn2uid(MYLDAP_SESSION *session,const char *dn)
int rc;
const char **values;
char *uid;
+ if (rcp!=NULL)
+ *rcp=LDAP_SUCCESS;
/* we have to look up the entry */
attrs[0]=attmap_passwd_uid;
attrs[1]=NULL;
@@ -160,7 +162,11 @@ static char *lookup_dn2uid(MYLDAP_SESSION *session,const char *dn)
if (entry==NULL)
{
if (rc!=LDAP_SUCCESS)
+ {
log_log(LOG_WARNING,"lookup of user %s failed: %s",dn,ldap_err2string(rc));
+ if (rcp!=NULL)
+ *rcp=rc;
+ }
return NULL;
}
/* get uid (just use first one) */
@@ -213,7 +219,7 @@ char *dn2uid(MYLDAP_SESSION *session,const char *dn,char *buf,size_t buflen)
}
pthread_mutex_unlock(&dn2uid_cache_mutex);
/* look up the uid using an LDAP query */
- uid=lookup_dn2uid(session,dn);
+ uid=lookup_dn2uid(session,dn,NULL);
/* store the result in the cache */
pthread_mutex_lock(&dn2uid_cache_mutex);
if (cacheentry==NULL)