lists.arthurdejong.org
RSS feed

nss-pam-ldapd commit: r1206 - in nss-pam-ldapd: man nslcd pam

[Date Prev][Date Next] [Thread Prev][Thread Next]

nss-pam-ldapd commit: r1206 - in nss-pam-ldapd: man nslcd pam



Author: arthur
Date: Sun Sep  5 11:30:44 2010
New Revision: 1206
URL: http://arthurdejong.org/viewvc/nss-pam-ldapd?view=rev&revision=1206

Log:
implement a rootpwmodpw option that allows root users to change user passwords 
without a password prompt

Modified:
   nss-pam-ldapd/man/nslcd.conf.5.xml
   nss-pam-ldapd/nslcd/cfg.c
   nss-pam-ldapd/nslcd/cfg.h
   nss-pam-ldapd/nslcd/common.h
   nss-pam-ldapd/nslcd/nslcd.c
   nss-pam-ldapd/nslcd/pam.c
   nss-pam-ldapd/pam/pam.c

Modified: nss-pam-ldapd/man/nslcd.conf.5.xml
==============================================================================
--- nss-pam-ldapd/man/nslcd.conf.5.xml  Sat Aug 28 21:46:37 2010        (r1205)
+++ nss-pam-ldapd/man/nslcd.conf.5.xml  Sun Sep  5 11:30:44 2010        (r1206)
@@ -192,8 +192,24 @@
      <listitem>
       <para>
        Specifies the distinguished name to use when the root user tries to
-       modify a user's password using the PAM module. The PAM module prompts
-       the user for the admin password instead of the user's password.
+       modify a user's password using the PAM module.
+      </para>
+     </listitem>
+    </varlistentry>
+
+    <varlistentry>
+     <term><option>rootpwmodpw</option> 
<replaceable>PASSWORD</replaceable></term>
+     <listitem>
+      <para>
+       Specifies the clear text credentials with which to bind if the root
+       user tries to change a user's password.
+       This option is only applicable when used with
+       <option>rootpwmoddn</option> above.
+       If this option is not specified the PAM module prompts the user for
+       this password.
+       If you set this option you should consider changing the permissions
+       of the <filename>nslcd.conf</filename> file to only grant access to
+       the root user.
       </para>
      </listitem>
     </varlistentry>

Modified: nss-pam-ldapd/nslcd/cfg.c
==============================================================================
--- nss-pam-ldapd/nslcd/cfg.c   Sat Aug 28 21:46:37 2010        (r1205)
+++ nss-pam-ldapd/nslcd/cfg.c   Sun Sep  5 11:30:44 2010        (r1206)
@@ -97,6 +97,7 @@
   cfg->ldc_binddn=NULL;
   cfg->ldc_bindpw=NULL;
   cfg->ldc_rootpwmoddn=NULL;
+  cfg->ldc_rootpwmodpw=NULL;
   cfg->ldc_sasl_mech=NULL;
   cfg->ldc_sasl_realm=NULL;
   cfg->ldc_sasl_authcid=NULL;
@@ -377,6 +378,28 @@
   }
 }
 
+/* check that the file is not world readable */
+static void check_permissions(const char *filename,const char *keyword)
+{
+  struct stat sb;
+  /* get file status */
+  if (stat(filename,&sb))
+  {
+    log_log(LOG_ERR,"cannot stat() %s: %s",filename,strerror(errno));
+    exit(EXIT_FAILURE);
+  }
+  /* check permissions */
+  if ((sb.st_mode&0007)!=0)
+  {
+    if (keyword!=NULL)
+      log_log(LOG_ERR,"%s: file should not be world readable if %s is set",
+              filename, keyword);
+    else
+      log_log(LOG_ERR,"%s: file should not be world readable",filename);
+    exit(EXIT_FAILURE);
+  }
+}
+
 static void get_int(const char *filename,int lnr,
                     const char *keyword,char **line,
                     int *var)
@@ -811,12 +834,18 @@
     }
     else if (strcasecmp(keyword,"bindpw")==0)
     {
+      check_permissions(filename,keyword);
       get_restdup(filename,lnr,keyword,&line,&cfg->ldc_bindpw);
     }
     else if (strcasecmp(keyword,"rootpwmoddn")==0)
     {
       get_restdup(filename,lnr,keyword,&line,&cfg->ldc_rootpwmoddn);
     }
+    else if (strcasecmp(keyword,"rootpwmodpw")==0)
+    {
+      check_permissions(filename,keyword);
+      get_restdup(filename,lnr,keyword,&line,&cfg->ldc_rootpwmodpw);
+    }
     /* SASL authentication options */
     else if (strcasecmp(keyword,"use_sasl")==0)
     {
@@ -1055,6 +1084,8 @@
       exit(EXIT_FAILURE);
     }
   }
+  /* check permissions */
+  check_permissions(filename,NULL);
   /* read the first line */
   if (fgets(linebuf,sizeof(linebuf),fp)==NULL)
   {
@@ -1062,8 +1093,6 @@
     exit(EXIT_FAILURE);
   }
   /* chop the last char off and save the rest as bindpw */
-  i=strlen(linebuf);
-
   i=(int)strlen(linebuf);
   if ((i<=0)||(linebuf[i-1]!='\n'))
   {

Modified: nss-pam-ldapd/nslcd/cfg.h
==============================================================================
--- nss-pam-ldapd/nslcd/cfg.h   Sat Aug 28 21:46:37 2010        (r1205)
+++ nss-pam-ldapd/nslcd/cfg.h   Sun Sep  5 11:30:44 2010        (r1206)
@@ -95,6 +95,8 @@
   char *ldc_bindpw;
   /* bind DN for password modification by administrator */
   char *ldc_rootpwmoddn;
+  /* bind password for password modification by root */
+  char *ldc_rootpwmodpw;
   /* sasl mech */
   char *ldc_sasl_mech;
   /* sasl realm */

Modified: nss-pam-ldapd/nslcd/common.h
==============================================================================
--- nss-pam-ldapd/nslcd/common.h        Sat Aug 28 21:46:37 2010        (r1205)
+++ nss-pam-ldapd/nslcd/common.h        Sun Sep  5 11:30:44 2010        (r1206)
@@ -140,11 +140,11 @@
 int nslcd_service_all(TFILE *fp,MYLDAP_SESSION *session);
 int nslcd_shadow_byname(TFILE *fp,MYLDAP_SESSION *session);
 int nslcd_shadow_all(TFILE *fp,MYLDAP_SESSION *session);
-int nslcd_pam_authc(TFILE *fp,MYLDAP_SESSION *session);
+int nslcd_pam_authc(TFILE *fp,MYLDAP_SESSION *session,uid_t calleruid);
 int nslcd_pam_authz(TFILE *fp,MYLDAP_SESSION *session);
 int nslcd_pam_sess_o(TFILE *fp,MYLDAP_SESSION *session);
 int nslcd_pam_sess_c(TFILE *fp,MYLDAP_SESSION *session);
-int nslcd_pam_pwmod(TFILE *fp,MYLDAP_SESSION *session);
+int nslcd_pam_pwmod(TFILE *fp,MYLDAP_SESSION *session,uid_t calleruid);
 
 /* macros for generating service handling code */
 #define NSLCD_HANDLE(db,fn,readfn,logcall,action,mkfilter,writefn) \

Modified: nss-pam-ldapd/nslcd/nslcd.c
==============================================================================
--- nss-pam-ldapd/nslcd/nslcd.c Sat Aug 28 21:46:37 2010        (r1205)
+++ nss-pam-ldapd/nslcd/nslcd.c Sun Sep  5 11:30:44 2010        (r1206)
@@ -421,12 +421,11 @@
     case NSLCD_ACTION_SERVICE_ALL:      (void)nslcd_service_all(fp,session); 
break;
     case NSLCD_ACTION_SHADOW_BYNAME:    if (uid==0) 
(void)nslcd_shadow_byname(fp,session); break;
     case NSLCD_ACTION_SHADOW_ALL:       if (uid==0) 
(void)nslcd_shadow_all(fp,session); break;
-    case NSLCD_ACTION_PAM_AUTHC:        (void)nslcd_pam_authc(fp,session); 
break;
+    case NSLCD_ACTION_PAM_AUTHC:        (void)nslcd_pam_authc(fp,session,uid); 
break;
     case NSLCD_ACTION_PAM_AUTHZ:        (void)nslcd_pam_authz(fp,session); 
break;
     case NSLCD_ACTION_PAM_SESS_O:       (void)nslcd_pam_sess_o(fp,session); 
break;
     case NSLCD_ACTION_PAM_SESS_C:       (void)nslcd_pam_sess_c(fp,session); 
break;
-    case NSLCD_ACTION_PAM_PWMOD:        (void)nslcd_pam_pwmod(fp,session); 
break;
-      /* TODO: maybe only do pwmod for (suid) root users */
+    case NSLCD_ACTION_PAM_PWMOD:        (void)nslcd_pam_pwmod(fp,session,uid); 
break;
     default:
       log_log(LOG_WARNING,"invalid request id: %d",(int)action);
       break;

Modified: nss-pam-ldapd/nslcd/pam.c
==============================================================================
--- nss-pam-ldapd/nslcd/pam.c   Sat Aug 28 21:46:37 2010        (r1205)
+++ nss-pam-ldapd/nslcd/pam.c   Sun Sep  5 11:30:44 2010        (r1206)
@@ -129,7 +129,7 @@
 }
 
 /* check authentication credentials of the user */
-int nslcd_pam_authc(TFILE *fp,MYLDAP_SESSION *session)
+int nslcd_pam_authc(TFILE *fp,MYLDAP_SESSION *session,uid_t calleruid)
 {
   int32_t tmpint32;
   int rc;
@@ -158,6 +158,16 @@
       return -1;
     }
     strcpy(userdn,nslcd_cfg->ldc_rootpwmoddn);
+    /* if the caller is root we will allow the use of the rootpwmodpw option */
+    if ((*password=='\0')&&(calleruid==0)&&(nslcd_cfg->ldc_rootpwmodpw!=NULL))
+    {
+      if (strlen(nslcd_cfg->ldc_rootpwmodpw)>=sizeof(password))
+      {
+        log_log(LOG_ERR,"nslcd_pam_authc(): rootpwmodpw will not fit in 
password");
+        return -1;
+      }
+      strcpy(password,nslcd_cfg->ldc_rootpwmodpw);
+    }
   }
   else if 
(validate_user(session,userdn,sizeof(userdn),username,sizeof(username)))
   {
@@ -423,7 +433,7 @@
   return rc;
 }
 
-int nslcd_pam_pwmod(TFILE *fp,MYLDAP_SESSION *session)
+int nslcd_pam_pwmod(TFILE *fp,MYLDAP_SESSION *session,uid_t calleruid)
 {
   int32_t tmpint32;
   char username[256];
@@ -451,6 +461,16 @@
   {
     binddn=nslcd_cfg->ldc_rootpwmoddn;
     userdn[0]='\0'; /* cause validate_user() to get the user DN */
+    /* check if rootpwmodpw should be used */
+    if 
((*oldpassword=='\0')&&(calleruid==0)&&(nslcd_cfg->ldc_rootpwmodpw!=NULL))
+    {
+      if (strlen(nslcd_cfg->ldc_rootpwmodpw)>=sizeof(oldpassword))
+      {
+        log_log(LOG_ERR,"nslcd_pam_pwmod(): rootpwmodpw will not fit in 
oldpassword");
+        return -1;
+      }
+      strcpy(oldpassword,nslcd_cfg->ldc_rootpwmodpw);
+    }
   }
   /* validate request and fill in the blanks */
   if (validate_user(session,userdn,sizeof(userdn),username,sizeof(username)))

Modified: nss-pam-ldapd/pam/pam.c
==============================================================================
--- nss-pam-ldapd/pam/pam.c     Sat Aug 28 21:46:37 2010        (r1205)
+++ nss-pam-ldapd/pam/pam.c     Sun Sep  5 11:30:44 2010        (r1206)
@@ -513,6 +513,7 @@
   const char *username,*service;
   const char *oldpassword=NULL,*newpassword=NULL;
   struct passwd *pwent;
+  uid_t myuid;
   /* set up configuration */
   rc=init(pamh,flags,argc,argv,&cfg,&ctx,&username,&service);
   if (rc!=PAM_SUCCESS)
@@ -523,8 +524,17 @@
   {
     /* see if the user is trying to modify another user's password */
     pwent=getpwnam(username);
-    if ((pwent!=NULL)&&(pwent->pw_uid!=getuid()))
+    myuid=getuid();
+    if ((pwent!=NULL)&&(pwent->pw_uid!=myuid))
     {
+      /* we are root so we can test if nslcd will allow us to change the
+         user's password without the admin password */
+      if (myuid==0)
+      {
+        rc=nslcd_request_authc(pamh,ctx,&cfg,"",service,"");
+        if ((rc==PAM_SUCCESS)&&(ctx->authok==PAM_SUCCESS))
+          return pam_set_item(pamh,PAM_OLDAUTHTOK,"");
+      }
       /* try to  authenticate with the LDAP administrator password by passing
          an empty username to the authc request */
       rc=pam_get_authtok(pamh,PAM_OLDAUTHTOK,&oldpassword,"LDAP administrator 
password: ");
@@ -558,6 +568,9 @@
       pam_syslog(pamh,LOG_NOTICE,"%s; 
user=%s",pam_strerror(pamh,ctx->authok),username);
     else if (cfg.debug)
       pam_syslog(pamh,LOG_DEBUG,"authentication succeeded");
+    /* store password (needed if oldpassword was retreived from context) */
+    if (rc==PAM_SUCCESS)
+      return pam_set_item(pamh,PAM_OLDAUTHTOK,oldpassword);
     /* remap error code */
     return remap_pam_rc(ctx->authok,&cfg);
   }
--
To unsubscribe send an email to
nss-pam-ldapd-commits-unsubscribe@lists.arthurdejong.org or see
http://lists.arthurdejong.org/nss-pam-ldapd-commits