Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
path: root/nslcd/pam.c
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2009-06-03 12:31:00 +0200
committerArthur de Jong <arthur@arthurdejong.org>2009-06-03 12:31:00 +0200
commit2f5385fd69808d42dd1e0537695838100e50642b (patch)
tree9a10d7133e93eb5df4d42bca44e4b3425b138c0f /nslcd/pam.c
parent1eacf48835bcf7c28670aea30d981f170a0a2e73 (diff)
import preliminary version of PAM functionality into nslcd
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-ldapd@923 ef36b2f9-881f-0410-afb5-c4e39611909c
Diffstat (limited to 'nslcd/pam.c')
-rw-r--r--nslcd/pam.c286
1 files changed, 286 insertions, 0 deletions
diff --git a/nslcd/pam.c b/nslcd/pam.c
new file mode 100644
index 0000000..fc543ed
--- /dev/null
+++ b/nslcd/pam.c
@@ -0,0 +1,286 @@
+/*
+ pam.c - pam processing routines
+
+ Copyright (C) 2009 Howard Chu
+ Copyright (C) 2009 Arthur de Jong
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ 02110-1301 USA
+*/
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif /* HAVE_STDINT_H */
+
+#include "common.h"
+#include "log.h"
+#include "myldap.h"
+#include "cfg.h"
+#include "attmap.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 (just to do any kind of search) */
+ username=lookup_dn2uid(session,userdn,&rc);
+ 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;
+ }
+}
+
+/* ensure that both userdn and username are filled in from the entry */
+static int validate_user(MYLDAP_SESSION *session,char *userdn,size_t userdnsz,
+ char *username,size_t usernamesz)
+{
+ MYLDAP_ENTRY *entry=NULL;
+ const char *value;
+ /* check username for validity */
+ if (!isvalidname(username))
+ {
+ log_log(LOG_WARNING,"\"%s\": invalid user name",username);
+ return -1;
+ }
+ /* look up user DN if not known */
+ if (userdn[0]=='\0')
+ {
+ /* get the user entry based on the username */
+ entry=uid2entry(session,username);
+ if (entry==NULL)
+ {
+ log_log(LOG_WARNING,"\"%s\": user not found",username);
+ return -1;
+ }
+ /* get the DN */
+ myldap_cpy_dn(entry,userdn,userdnsz);
+ if (strcasecmp(userdn,"unknown")==0)
+ {
+ log_log(LOG_WARNING,"\"%s\": user has no DN",username);
+ return -1;
+ }
+ /* get the "real" username */
+ value=myldap_get_rdn_value(entry,attmap_passwd_uid);
+ if ((value==NULL)||!isvalidname(value)||strlen(value)>=usernamesz)
+ {
+ log_log(LOG_WARNING,"\"%s\": DN %s has invalid username",username,userdn);
+ return -1;
+ }
+ /* check if the username is different and update it if needed */
+ if (strcmp(username,value)!=0)
+ {
+ log_log(LOG_INFO,"username changed from \"%s\" to \"%s\"",username,value);
+ strcpy(username,value);
+ }
+ }
+ /* all check passed */
+ return 0;
+}
+
+/* check authentication credentials of the user */
+int nslcd_pam_authc(TFILE *fp,MYLDAP_SESSION *session)
+{
+ int32_t tmpint32;
+ int rc;
+ char username[256];
+ char userdn[256];
+ char servicename[64];
+ char password[64];
+ /* read request parameters */
+ READ_STRING(fp,username);
+ READ_STRING(fp,userdn);
+ READ_STRING(fp,servicename);
+ READ_STRING(fp,password);
+ /* log call */
+ 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);
+ /* validate request and fill in the blanks */
+ if (validate_user(session,userdn,sizeof(userdn),username,sizeof(username)))
+ {
+ WRITE_INT32(fp,NSLCD_RESULT_END);
+ return -1;
+ }
+ /* try authentication */
+ rc=try_bind(userdn,password);
+ /* write response */
+ WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
+ WRITE_STRING(fp,username);
+ 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)
+{
+ int32_t tmpint32;
+ char username[256];
+ char userdn[256];
+ char servicename[64];
+ char ruser[32];
+ char rhost[256];
+ char tty[256];
+ /* read request parameters */
+ READ_STRING(fp,username);
+ READ_STRING(fp,userdn);
+ READ_STRING(fp,servicename);
+ READ_STRING(fp,ruser);
+ READ_STRING(fp,rhost);
+ READ_STRING(fp,tty);
+ /* log call */
+ log_log(LOG_DEBUG,"nslcd_pam_authz(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\")",
+ username,userdn,servicename,ruser,rhost,tty);
+ /* write the response header */
+ WRITE_INT32(fp,NSLCD_VERSION);
+ WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ);
+ /* validate request and fill in the blanks */
+ if (validate_user(session,userdn,sizeof(userdn),username,sizeof(username)))
+ {
+ WRITE_INT32(fp,NSLCD_RESULT_END);
+ return -1;
+ }
+ /* TODO: perform any authorisation checks */
+ /* write response */
+ WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
+ WRITE_STRING(fp,username);
+ WRITE_STRING(fp,userdn);
+ WRITE_INT32(fp,NSLCD_PAM_SUCCESS); /* authz */
+ WRITE_STRING(fp,""); /* authzmsg */
+ WRITE_INT32(fp,NSLCD_RESULT_END);
+ return 0;
+}
+
+int nslcd_pam_sess_o(TFILE *fp,MYLDAP_SESSION *session)
+{
+ int32_t tmpint32;
+ char username[256];
+ char userdn[256];
+ char servicename[64];
+ char tty[64],rhost[64],ruser[256];
+ int32_t sessionid;
+ /* read request parameters */
+ READ_STRING(fp,username);
+ READ_STRING(fp,userdn);
+ READ_STRING(fp,servicename);
+ READ_STRING(fp,tty);
+ READ_STRING(fp,rhost);
+ READ_STRING(fp,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)
+{
+ int32_t tmpint32;
+ char username[256];
+ char userdn[256];
+ char servicename[64];
+ char tty[64],rhost[64],ruser[256];
+ int32_t sessionid;
+ /* read request parameters */
+ READ_STRING(fp,username);
+ READ_STRING(fp,userdn);
+ READ_STRING(fp,servicename);
+ READ_STRING(fp,tty);
+ READ_STRING(fp,rhost);
+ READ_STRING(fp,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;
+}
+
+int nslcd_pam_pwmod(TFILE *fp,MYLDAP_SESSION *session)
+{
+/*
+ struct berval dn, uid, opw, npw;
+ int32_t tmpint32;
+ char dnc[1024];
+ char uidc[256];
+ char opwc[256];
+ char npwc[256];
+
+ READ_STRING(fp,dnc);
+ dn.bv_val = dnc;
+ dn.bv_len = tmpint32;
+ READ_STRING(fp,uidc);
+ uid.bv_val = uidc;
+ uid.bv_len = tmpint32;
+ READ_STRING(fp,opwc);
+ opw.bv_val = opwc;
+ opw.bv_len = tmpint32;
+ READ_STRING(fp,npwc);
+ npw.bv_val = npwc;
+ npw.bv_len = tmpint32;
+
+ Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(%s), %s\n",dn.bv_val,uid.bv_val,0);
+
+ BER_BVZERO(&npw);
+ WRITE_INT32(fp,NSLCD_VERSION);
+ WRITE_INT32(fp,NSLCD_ACTION_PAM_PWMOD);
+ WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
+ WRITE_INT32(fp,PAM_SUCCESS);
+ WRITE_BERVAL(fp,&npw);
+*/
+ return 0;
+}