lists.arthurdejong.org
RSS feed

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

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

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



Author: arthur
Date: Fri May  7 23:45:06 2010
New Revision: 1088
URL: http://arthurdejong.org/viewvc/nss-pam-ldapd?view=rev&revision=1088

Log:
implement an authz_search option to test whether the user is authorised

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

Modified: nss-pam-ldapd/man/nslcd.conf.5.xml
==============================================================================
--- nss-pam-ldapd/man/nslcd.conf.5.xml  Fri May  7 23:25:05 2010        (r1087)
+++ nss-pam-ldapd/man/nslcd.conf.5.xml  Fri May  7 23:45:06 2010        (r1088)
@@ -642,6 +642,37 @@
      </listitem>
     </varlistentry>
 
+    <varlistentry>
+     <term><option>authz_search</option>
+           <replaceable>FILTER</replaceable></term>
+     <listitem>
+      <para>
+       This option allows flexible fine tuning of the authorisation check that
+       should be performed. The search filter specified is executed and
+       if any entries match, access is granted, otherwise access is denied.
+      </para>
+      <para>
+       The search filter can contain the following variable references:
+         <literal>$username</literal>, <literal>$service</literal>,
+         <literal>$ruser</literal>, <literal>$rhost</literal>,
+         <literal>$tty</literal>, <literal>$hostname</literal>,
+         <literal>$dn</literal>, and <literal>$uid</literal>.
+       These references are substituted in the search filter using the
+       same syntax as described in the section on attribute mapping
+       expressions below.
+      </para>
+      <para>
+       For example, to check that the user has a proper authorizedService
+       value if the attribute is present:
+       
<literal>(&amp;(objectClass=posixAccount)(uid=$username)(|(authorizedService=$service)(!(authorizedService=*))))</literal>
+      </para>
+      <para>
+       The default behaviour is not to do this extra search and always
+       grant access.
+      </para>
+     </listitem>
+    </varlistentry>
+
    </variablelist>
   </refsect2>
 

Modified: nss-pam-ldapd/man/pam_ldap.8.xml
==============================================================================
--- nss-pam-ldapd/man/pam_ldap.8.xml    Fri May  7 23:25:05 2010        (r1087)
+++ nss-pam-ldapd/man/pam_ldap.8.xml    Fri May  7 23:45:06 2010        (r1088)
@@ -166,8 +166,8 @@
  <refsect1 id="moduleservices">
   <title>Module Services Provided</title>
   <para>
-   All services are provided by this module but currently only authentication
-   (auth) and password change (password) are implemented in the nslcd daemon.
+   All services are provided by this module but currently sessions changes
+   are not implemented in the nslcd daemon.
   </para>
  </refsect1>
 

Modified: nss-pam-ldapd/nslcd/cfg.c
==============================================================================
--- nss-pam-ldapd/nslcd/cfg.c   Fri May  7 23:25:05 2010        (r1087)
+++ nss-pam-ldapd/nslcd/cfg.c   Fri May  7 23:45:06 2010        (r1088)
@@ -119,6 +119,7 @@
   cfg->ldc_restart=1;
   cfg->ldc_pagesize=0;
   cfg->ldc_nss_initgroups_ignoreusers=NULL;
+  cfg->ldc_authz_search=NULL;
 }
 
 /* simple strdup wrapper */
@@ -1020,6 +1021,11 @@
     {
       
parse_nss_initgroups_ignoreusers_statement(filename,lnr,keyword,line,cfg);
     }
+    else if (strcasecmp(keyword,"authz_search")==0)
+    {
+      check_argumentcount(filename,lnr,keyword,(line!=NULL)&&(*line!='\0'));
+      cfg->ldc_authz_search=xstrdup(line);
+    }
 #ifdef ENABLE_CONFIGFILE_CHECKING
     /* fallthrough */
     else

Modified: nss-pam-ldapd/nslcd/cfg.h
==============================================================================
--- nss-pam-ldapd/nslcd/cfg.h   Fri May  7 23:25:05 2010        (r1087)
+++ nss-pam-ldapd/nslcd/cfg.h   Fri May  7 23:45:06 2010        (r1088)
@@ -136,6 +136,8 @@
   /* the users for which no initgroups() searches should be done
      Note: because we use a set here comparisons will be case-insensitive */
   SET *ldc_nss_initgroups_ignoreusers;
+  /* the search that should be performed to do autorisation checks */
+  char *ldc_authz_search;
 };
 
 /* this is a pointer to the global configuration, it should be available

Modified: nss-pam-ldapd/nslcd/pam.c
==============================================================================
--- nss-pam-ldapd/nslcd/pam.c   Fri May  7 23:25:05 2010        (r1087)
+++ nss-pam-ldapd/nslcd/pam.c   Fri May  7 23:45:06 2010        (r1088)
@@ -28,12 +28,19 @@
 #ifdef HAVE_STDINT_H
 #include <stdint.h>
 #endif /* HAVE_STDINT_H */
+#include <unistd.h>
 
 #include "common.h"
 #include "log.h"
 #include "myldap.h"
 #include "cfg.h"
 #include "attmap.h"
+#include "common/dict.h"
+#include "common/expr.h"
+
+#ifndef HOST_NAME_MAX
+#define HOST_NAME_MAX 255
+#endif /* not HOST_NAME_MAX */
 
 /* set up a connection and try to bind with the specified DN and password
    returns a NSLCD_PAM_* error code */
@@ -170,6 +177,92 @@
   return 0;
 }
 
+static void autzsearch_var_add(DICT *dict,const char *name,const char *value)
+{
+  size_t sz;
+  char *escaped_value;
+  /* allocate memory for escaped string */
+  sz=((strlen(value)+8)*120)/100;
+  escaped_value=(char *)malloc(sz);
+  if (escaped_value==NULL)
+  {
+    log_log(LOG_CRIT,"autzsearch_var_add(): malloc() failed to allocate 
memory");
+    return;
+  }
+  /* perform escaping of the value */
+  if(myldap_escape(value,escaped_value,sz))
+  {
+    log_log(LOG_CRIT,"autzsearch_var_add(): myldap_escape() failed to fit in 
buffer");
+    return;
+  }
+  /* add to dict */
+  dict_put(dict,name,escaped_value);
+}
+
+static void autzsearch_vars_free(DICT *dict)
+{
+  int i;
+  const char **keys;
+  void *value;
+  /* go over all keys and free all the values
+     (they were allocated in autzsearch_var_add) */
+  /* loop over dictionary contents */
+  keys=dict_keys(dict);
+  for (i=0;keys[i]!=NULL;i++)
+  {
+    value=dict_get(dict,keys[i]);
+    if (value)
+      free(value);
+  }
+  free(keys);
+  /* after this values from the dict should obviously no longer be used */
+}
+
+static const char *autzsearch_var_get(const char *name,void *expander_attr)
+{
+  DICT *dict=(DICT *)expander_attr;
+  return (const char *)dict_get(dict,name);
+  /* TODO: if not set use entry to get attribute name (entry can be an
+           element in the dict) */
+}
+
+static int try_autzsearch(MYLDAP_SESSION *session,DICT *dict,const char 
*searchfilter)
+{
+  char filter_buffer[1024];
+  MYLDAP_SEARCH *search;
+  MYLDAP_ENTRY *entry;
+  static const char *attrs[2];
+  int rc;
+  /* build the search filter */
+  if (expr_parse(searchfilter,filter_buffer,sizeof(filter_buffer),
+                 autzsearch_var_get,(void *)dict)==NULL)
+  {
+    log_log(LOG_ERR,"authorisation search \"%s\" is invalid",searchfilter);
+    return -1;
+  }
+  /* perform the search */
+  attrs[0]="dn";
+  attrs[1]=NULL;
+  /* FIXME: this only searches the first base */
+  search=myldap_search(session,nslcd_cfg->ldc_bases[0],LDAP_SCOPE_SUB,
+                       filter_buffer,attrs,&rc);
+  if (search==NULL)
+  {
+    log_log(LOG_ERR,"authorisation search \"%s\" failed: %s",
+            filter_buffer,ldap_err2string(rc));
+    return -1;
+  }
+  /* try to get an entry */
+  entry=myldap_get_entry(search,NULL);
+  if (entry==NULL)
+  {
+    log_log(LOG_ERR,"no entry found");
+    return -1;
+  }
+  /* we've found an entry so it's OK */
+  return 0;
+}
+
 /* check authorisation of the user */
 int nslcd_pam_authz(TFILE *fp,MYLDAP_SESSION *session)
 {
@@ -180,6 +273,8 @@
   char ruser[32];
   char rhost[256];
   char tty[256];
+  char hostname[HOST_NAME_MAX+1];
+  DICT *dict;
   /* read request parameters */
   READ_STRING(fp,username);
   READ_STRING(fp,userdn);
@@ -199,7 +294,33 @@
     WRITE_INT32(fp,NSLCD_RESULT_END);
     return -1;
   }
-  /* TODO: perform any authorisation checks */
+  if (nslcd_cfg->ldc_authz_search)
+  {
+    /* TODO: perform any authorisation checks */
+    dict=dict_new();
+    autzsearch_var_add(dict,"username",username);
+    autzsearch_var_add(dict,"service",servicename);
+    autzsearch_var_add(dict,"ruser",ruser);
+    autzsearch_var_add(dict,"rhost",rhost);
+    autzsearch_var_add(dict,"tty",tty);
+    if (gethostname(hostname,sizeof(hostname))==0)
+      autzsearch_var_add(dict,"hostname",hostname);
+    /* TODO: fqdn */
+    autzsearch_var_add(dict,"dn",userdn);
+    autzsearch_var_add(dict,"uid",username);
+    if (try_autzsearch(session,dict,nslcd_cfg->ldc_authz_search))
+    {
+      log_log(LOG_DEBUG,"LDAP authorisation check failed");
+      WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
+      WRITE_STRING(fp,username);
+      WRITE_STRING(fp,userdn);
+      WRITE_INT32(fp,NSLCD_PAM_PERM_DENIED);  /* authz */
+      WRITE_STRING(fp,"LDAP authorisation check failed"); /* authzmsg */
+      WRITE_INT32(fp,NSLCD_RESULT_END);
+    }
+    autzsearch_vars_free(dict);
+    dict_free(dict);
+  }
   /* write response */
   WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
   WRITE_STRING(fp,username);
--
To unsubscribe send an email to
nss-pam-ldapd-commits-unsubscribe@lists.arthurdejong.org or see
http://lists.arthurdejong.org/nss-pam-ldapd-commits