lists.arthurdejong.org
RSS feed

nss-pam-ldapd commit: r1865 - in nss-pam-ldapd: . nslcd pam

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

nss-pam-ldapd commit: r1865 - in nss-pam-ldapd: . nslcd pam



Author: arthur
Date: Sun Dec 16 16:17:42 2012
New Revision: 1865
URL: http://arthurdejong.org/viewvc/nss-pam-ldapd?revision=1865&view=revision

Log:
change PAM protocol to be more consistent and simpler

Modified:
   nss-pam-ldapd/nslcd.h
   nss-pam-ldapd/nslcd/pam.c
   nss-pam-ldapd/pam/common.h
   nss-pam-ldapd/pam/pam.c

Modified: nss-pam-ldapd/nslcd.h
==============================================================================
--- nss-pam-ldapd/nslcd.h       Sun Dec 16 16:11:59 2012        (r1864)
+++ nss-pam-ldapd/nslcd.h       Sun Dec 16 16:17:42 2012        (r1865)
@@ -191,58 +191,58 @@
 /* PAM-related requests. The request parameters for all these requests
    begin with:
      STRING  user name
-     STRING  DN (if value is known already, otherwise empty)
      STRING  service name
-   all requests, except the SESSION requests start the result value with:
-     STRING  user name (cannonical name)
-     STRING  DN (can be used to speed up requests)
-   Some functions may return an authorisation message. This message, if
-   supplied will be used by the PAM module instead of a message that is
-   generated by the PAM module itself. */
+     STRING  ruser
+     STRING  rhost
+     STRING  tty
+   If the user is not known in LDAP no result may be returned (immediately
+   return NSLCD_RESULT_END instead of a PAM error code). */
 
 /* PAM authentication check request. The extra request values are:
      STRING  password
-   and the result value ends with:
+   and the result value consists of:
      INT32   authc NSLCD_PAM_* result code
+     STRING  user name (the cannonical user name)
      INT32   authz NSLCD_PAM_* result code
      STRING  authorisation error message
    If the username is empty in this request an attempt is made to
-   authenticate as the administrator (set using rootpwmoddn). The returned DN
-   is that of the administrator. */
-#define NSLCD_ACTION_PAM_AUTHC         20001
-
-/* PAM authorisation check request. The extra request values are:
-     STRING ruser
-     STRING rhost
-     STRING tty
-   and the result value ends with:
+   authenticate as the administrator (set using rootpwmoddn).
+   Some authorisation checks are already done during authentication so the
+   response also includes authorisation information. */
+#define NSLCD_ACTION_PAM_AUTHC         21001
+
+/* PAM authorisation check request. The result value consists of:
      INT32   authz NSLCD_PAM_* result code
-     STRING  authorisation error message */
-#define NSLCD_ACTION_PAM_AUTHZ         20002
+     STRING  authorisation error message
+   The authentication check may have already returned some authorisation
+   information. The authorisation error message, if supplied, will be used
+   by the PAM module instead of a message that is generated by the PAM
+   module itself. */
+#define NSLCD_ACTION_PAM_AUTHZ         21002
+
+/* PAM session open request. The result value consists of:
+     STRING   session id
+   This session id may be used to close this session with. */
+#define NSLCD_ACTION_PAM_SESS_O        21003
 
-/* PAM session open and close requests. These requests have the following
-   extra request values:
-     STRING tty
-     STRING rhost
-     STRING ruser
-     INT32 session id (ignored for SESS_O)
-   and these calls only return the session ID:
-     INT32 session id
-   The SESS_C must contain the ID that is retured by SESS_O to close the
-   correct session. */
-#define NSLCD_ACTION_PAM_SESS_O        20003
-#define NSLCD_ACTION_PAM_SESS_C        20004
+/* PAM session close request. This request has the following
+   extra request value:
+     STRING   session id
+   and this calls only returns an empty response value. */
+#define NSLCD_ACTION_PAM_SESS_C        21004
+
+/*
+Note: I'm not sure whether PAM result codes are required here.
+*/
 
 /* PAM password modification request. This requests has the following extra
    request values:
-     STRING old password
-     STRING new password
+     INT32   asroot: 0=oldpasswd is user passwd, 1=oldpasswd is root passwd
+     STRING  old password
+     STRING  new password
    and returns there extra result values:
-     INT32   authz NSLCD_PAM_* result code
-     STRING  authorisation error message
-   In this request the DN may be set to the administrator's DN. In this
-   case old password should be the administrator's password. This allows
-   the administrator to change any user's password. */
+     INT32   NSLCD_PAM_* result code
+     STRING  error message */
 #define NSLCD_ACTION_PAM_PWMOD         20005
 
 /* Request result codes. */

Modified: nss-pam-ldapd/nslcd/pam.c
==============================================================================
--- nss-pam-ldapd/nslcd/pam.c   Sun Dec 16 16:11:59 2012        (r1864)
+++ nss-pam-ldapd/nslcd/pam.c   Sun Dec 16 16:17:42 2012        (r1865)
@@ -244,8 +244,7 @@
 {
   int32_t tmpint32;
   int rc;
-  char username[256];
-  char servicename[64];
+  char username[256],service[64],ruser[256],rhost[HOST_NAME_MAX+1],tty[64];
   char password[64];
   const char *userdn;
   MYLDAP_ENTRY *entry;
@@ -254,13 +253,15 @@
   authzmsg[0]='\0';
   /* read request parameters */
   READ_STRING(fp,username);
-  SKIP_STRING(fp); /* DN */
-  READ_STRING(fp,servicename);
+  READ_STRING(fp,service);
+  READ_STRING(fp,ruser);
+  READ_STRING(fp,rhost);
+  READ_STRING(fp,tty);
   READ_STRING(fp,password);
   /* log call */
   log_setrequest("authc=\"%s\"",username);
   log_log(LOG_DEBUG,"nslcd_pam_authc(\"%s\",\"%s\",\"%s\")",
-                    username,servicename,*password?"***":"");
+                    username,service,*password?"***":"");
   /* write the response header */
   WRITE_INT32(fp,NSLCD_VERSION);
   WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHC);
@@ -312,9 +313,8 @@
     authzrc=check_shadow(session,username,authzmsg,sizeof(authzmsg),1,0);
   /* write response */
   WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
-  WRITE_STRING(fp,username);
-  WRITE_STRING(fp,userdn);
   WRITE_INT32(fp,rc);
+  WRITE_STRING(fp,username);
   WRITE_INT32(fp,authzrc);
   WRITE_STRING(fp,authzmsg);
   WRITE_INT32(fp,NSLCD_RESULT_END);
@@ -460,23 +460,20 @@
 {
   int32_t tmpint32;
   int rc;
-  char username[256];
-  char servicename[64];
-  char ruser[256],rhost[HOST_NAME_MAX+1],tty[64];
+  char username[256],service[64],ruser[256],rhost[HOST_NAME_MAX+1],tty[64];
   MYLDAP_ENTRY *entry;
   char authzmsg[1024];
   authzmsg[0]='\0';
   /* read request parameters */
   READ_STRING(fp,username);
-  SKIP_STRING(fp); /* DN */
-  READ_STRING(fp,servicename);
+  READ_STRING(fp,service);
   READ_STRING(fp,ruser);
   READ_STRING(fp,rhost);
   READ_STRING(fp,tty);
   /* log call */
   log_setrequest("authz=\"%s\"",username);
   log_log(LOG_DEBUG,"nslcd_pam_authz(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\")",
-            username,servicename,ruser,rhost,tty);
+            username,service,ruser,rhost,tty);
   /* write the response header */
   WRITE_INT32(fp,NSLCD_VERSION);
   WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ);
@@ -492,12 +489,10 @@
     return -1;
   }
   /* check authorisation search */
-  
rc=try_autzsearch(session,myldap_get_dn(entry),username,servicename,ruser,rhost,tty);
+  
rc=try_autzsearch(session,myldap_get_dn(entry),username,service,ruser,rhost,tty);
   if (rc!=LDAP_SUCCESS)
   {
     WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
-    WRITE_STRING(fp,username);
-    WRITE_STRING(fp,"");
     WRITE_INT32(fp,NSLCD_PAM_PERM_DENIED);
     WRITE_STRING(fp,"LDAP authorisation check failed");
     WRITE_INT32(fp,NSLCD_RESULT_END);
@@ -507,8 +502,6 @@
   rc=check_shadow(session,username,authzmsg,sizeof(authzmsg),0,0);
   /* write response */
   WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
-  WRITE_STRING(fp,username);
-  WRITE_STRING(fp,myldap_get_dn(entry));
   WRITE_INT32(fp,rc);
   WRITE_STRING(fp,authzmsg);
   WRITE_INT32(fp,NSLCD_RESULT_END);
@@ -518,28 +511,32 @@
 int nslcd_pam_sess_o(TFILE *fp,MYLDAP_SESSION *session)
 {
   int32_t tmpint32;
-  char username[256];
-  char servicename[64];
-  char tty[64],rhost[HOST_NAME_MAX+1],ruser[256];
-  int32_t sessionid;
+  char username[256],service[64],ruser[256],rhost[HOST_NAME_MAX+1],tty[64];
+  char sessionid[25];
+  static const char alphabet[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+                               "abcdefghijklmnopqrstuvwxyz"
+                               "01234567890";
+  int i;
   /* read request parameters */
   READ_STRING(fp,username);
-  SKIP_STRING(fp); /* DN */
-  READ_STRING(fp,servicename);
-  READ_STRING(fp,tty);
-  READ_STRING(fp,rhost);
+  READ_STRING(fp,service);
   READ_STRING(fp,ruser);
-  READ_INT32(fp,sessionid);
+  READ_STRING(fp,rhost);
+  READ_STRING(fp,tty);
+  /* generate pseudo-random session id */
+  for (i=0;i<(sizeof(sessionid)-1);i++)
+    sessionid[i]=alphabet[rand()%(sizeof(alphabet)-1)];
+  sessionid[i]='\0';
   /* log call */
   log_setrequest("sess_o=\"%s\"",username);
-  log_log(LOG_DEBUG,"nslcd_pam_sess_o(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\")",
-                    username,servicename,tty,rhost,ruser);
+  log_log(LOG_DEBUG,"nslcd_pam_sess_o(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\"): %s",
+                    username,service,tty,rhost,ruser,sessionid);
   /* 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_STRING(fp,sessionid);
   WRITE_INT32(fp,NSLCD_RESULT_END);
   return 0;
 }
@@ -547,28 +544,24 @@
 int nslcd_pam_sess_c(TFILE *fp,MYLDAP_SESSION *session)
 {
   int32_t tmpint32;
-  char username[256];
-  char servicename[64];
-  char tty[64],rhost[HOST_NAME_MAX+1],ruser[256];
-  int32_t sessionid;
+  char username[256],service[64],ruser[256],rhost[HOST_NAME_MAX+1],tty[64];
+  char sessionid[64];
   /* read request parameters */
   READ_STRING(fp,username);
-  SKIP_STRING(fp); /* DN */
-  READ_STRING(fp,servicename);
-  READ_STRING(fp,tty);
-  READ_STRING(fp,rhost);
+  READ_STRING(fp,service);
   READ_STRING(fp,ruser);
-  READ_INT32(fp,sessionid);
+  READ_STRING(fp,rhost);
+  READ_STRING(fp,tty);
+  READ_STRING(fp,sessionid);
   /* log call */
   log_setrequest("sess_c=\"%s\"",username);
-  log_log(LOG_DEBUG,"nslcd_pam_sess_c(\"%s\",\"%s\",%d)",
-                    username,servicename,(int)sessionid);
+  log_log(LOG_DEBUG,"nslcd_pam_sess_c(\"%s\",\"%s\",%s)",
+                    username,service,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;
 }
@@ -610,10 +603,8 @@
 {
   int32_t tmpint32;
   int rc;
-  char username[256];
-  char userdn[256];
+  char username[256],service[64],ruser[256],rhost[HOST_NAME_MAX+1],tty[64];
   int asroot;
-  char servicename[64];
   char oldpassword[64];
   char newpassword[64];
   const char *binddn=NULL; /* the user performing the modification */
@@ -622,16 +613,17 @@
   authzmsg[0]='\0';
   /* read request parameters */
   READ_STRING(fp,username);
-  READ_STRING(fp,userdn); /* we can't ignore userdn for now here because we
-                             need it to determine the modify-as-root case */
-  
asroot=(nslcd_cfg->ldc_rootpwmoddn!=NULL)&&(strcmp(userdn,nslcd_cfg->ldc_rootpwmoddn)==0);
-  READ_STRING(fp,servicename);
+  READ_STRING(fp,service);
+  READ_STRING(fp,ruser);
+  READ_STRING(fp,rhost);
+  READ_STRING(fp,tty);
+  READ_INT32(fp,asroot);
   READ_STRING(fp,oldpassword);
   READ_STRING(fp,newpassword);
   /* log call */
   log_setrequest("pwmod=\"%s\"",username);
   log_log(LOG_DEBUG,"nslcd_pam_pwmod(\"%s\",%s,\"%s\",\"%s\",\"%s\")",
-                    
username,asroot?"asroot":"asuser",servicename,*oldpassword?"***":"",
+                    
username,asroot?"asroot":"asuser",service,*oldpassword?"***":"",
                     *newpassword?"***":"");
   /* write the response header */
   WRITE_INT32(fp,NSLCD_VERSION);
@@ -652,8 +644,6 @@
   {
     log_log(LOG_NOTICE,"password change prohibited");
     WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
-    WRITE_STRING(fp,username);
-    WRITE_STRING(fp,"");
     WRITE_INT32(fp,NSLCD_PAM_PERM_DENIED);
     WRITE_STRING(fp,nslcd_cfg->pam_password_prohibit_message);
     WRITE_INT32(fp,NSLCD_RESULT_END);
@@ -682,8 +672,6 @@
     if (rc!=NSLCD_PAM_SUCCESS)
     {
       WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
-      WRITE_STRING(fp,username);
-      WRITE_STRING(fp,"");
       WRITE_INT32(fp,rc);
       WRITE_STRING(fp,authzmsg);
       WRITE_INT32(fp,NSLCD_RESULT_END);
@@ -696,8 +684,6 @@
   {
     mysnprintf(authzmsg,sizeof(authzmsg)-1,"password change failed: 
%s",ldap_err2string(rc));
     WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
-    WRITE_STRING(fp,username);
-    WRITE_STRING(fp,"");
     WRITE_INT32(fp,NSLCD_PAM_PERM_DENIED);
     WRITE_STRING(fp,authzmsg);
     WRITE_INT32(fp,NSLCD_RESULT_END);
@@ -706,8 +692,6 @@
   /* write response */
   log_log(LOG_NOTICE,"password changed for %s",myldap_get_dn(entry));
   WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
-  WRITE_STRING(fp,username);
-  WRITE_STRING(fp,myldap_get_dn(entry));
   WRITE_INT32(fp,NSLCD_PAM_SUCCESS);
   WRITE_STRING(fp,"");
   WRITE_INT32(fp,NSLCD_RESULT_END);

Modified: nss-pam-ldapd/pam/common.h
==============================================================================
--- nss-pam-ldapd/pam/common.h  Sun Dec 16 16:11:59 2012        (r1864)
+++ nss-pam-ldapd/pam/common.h  Sun Dec 16 16:17:42 2012        (r1865)
@@ -76,9 +76,6 @@
 #define PAM_REQUEST(action,debuglog,writefn,readfn) \
   TFILE *fp; \
   int32_t tmpint32; \
-  char *buffer=ctx->buf; \
-  size_t buflen=sizeof(ctx->buf); \
-  size_t bufptr=0; \
   if (cfg->debug) \
     debuglog; \
   /* open socket and write request */ \

Modified: nss-pam-ldapd/pam/pam.c
==============================================================================
--- nss-pam-ldapd/pam/pam.c     Sun Dec 16 16:11:59 2012        (r1864)
+++ nss-pam-ldapd/pam/pam.c     Sun Dec 16 16:17:42 2012        (r1865)
@@ -55,40 +55,41 @@
 /* the name we store our context under */
 #define PLD_CTX "PAM_LDAPD_CTX"
 
+/* structure that stores the results for an nslcd call */
+struct nslcd_resp {
+  int res;
+  char msg[1024];
+};
 
 /* this struct represents the context that the PAM module keeps
    between calls */
 struct pld_ctx {
-  char *user;
-  char *dn;
-  char *tmpluser;
-  char *authzmsg;
+  char *username;
+  struct nslcd_resp saved_authz;
+  struct nslcd_resp saved_session;
+  int asroot;
   char *oldpassword;
-  int authok;
-  int authz;
-  int sessid;
-  char buf[1024];
 };
 
 /* clear the context to all empty values */
 static void ctx_clear(struct pld_ctx *ctx)
 {
-  if (ctx->user)
+  if (ctx->username)
   {
-    free(ctx->user);
-    ctx->user=NULL;
+    free(ctx->username);
+    ctx->username=NULL;
   }
+  ctx->saved_authz.res=PAM_SUCCESS;
+  memset(ctx->saved_authz.msg,0,sizeof(ctx->saved_authz.msg));
+  ctx->saved_session.res=PAM_SUCCESS;
+  memset(ctx->saved_session.msg,0,sizeof(ctx->saved_session.msg));
+  ctx->asroot=0;
   if (ctx->oldpassword)
   {
     memset(ctx->oldpassword,0,strlen(ctx->oldpassword));
     free(ctx->oldpassword);
     ctx->oldpassword=NULL;
   }
-  ctx->dn=NULL;
-  ctx->tmpluser=NULL;
-  ctx->authzmsg=NULL;
-  ctx->authok=0;
-  ctx->authz=0;
 }
 
 /* free the context (this is installed as handler into PAM) */
@@ -109,7 +110,7 @@
   if ((rc==PAM_SUCCESS)&&(ctx!=NULL))
   {
     /* if the user is different clear the context */
-    if ((ctx->user!=NULL)&&(strcmp(ctx->user,username)!=0))
+    if ((ctx->username!=NULL)&&(strcmp(ctx->username,username)!=0))
       ctx_clear(ctx);
   }
   else
@@ -131,6 +132,9 @@
       return rc;
     }
   }
+  /* save the username in the context */
+  if (ctx->username==NULL)
+    ctx->username=strdup(username);
   /* return the context */
   *pctx=ctx;
   return PAM_SUCCESS;
@@ -187,7 +191,8 @@
 }
 
 static int init(pam_handle_t *pamh,struct pld_cfg *cfg,struct pld_ctx **ctx,
-                const char **username,const char **service)
+                const char **username,const char **service,const char **ruser,
+                const char **rhost,const char **tty)
 {
   int rc;
   struct passwd *pwent;
@@ -225,6 +230,10 @@
     pam_syslog(pamh,LOG_ERR,"failed to get service name: 
%s",pam_strerror(pamh,rc));
     return rc;
   }
+  /* get more PAM information (ignore errors) */
+  pam_get_item(pamh,PAM_RUSER,(const void **)ruser);
+  pam_get_item(pamh,PAM_RHOST,(const void **)rhost);
+  pam_get_item(pamh,PAM_TTY,(const void **)tty);
   return PAM_SUCCESS;
 }
 
@@ -263,7 +272,7 @@
     pam_syslog(pamh,LOG_DEBUG,"nslcd account check; user=%s",username),
     /* write the request parameters */
     WRITE_STRING(fp,username),
-    /* read the result entry */
+    /* read the result entry (skip it completely) */
     SKIP_STRING(fp); /* user name */
     SKIP_STRING(fp); /* passwd entry */
     SKIP(fp,sizeof(int32_t)); /* uid */
@@ -275,94 +284,125 @@
 }
 
 /* perform an authentication call over nslcd */
-static int nslcd_request_authc(pam_handle_t *pamh,struct pld_ctx *ctx,struct 
pld_cfg *cfg,
+static int nslcd_request_authc(pam_handle_t *pamh,struct pld_cfg *cfg,
                                const char *username,const char *service,
-                               const char *passwd)
+                               const char *ruser,const char *rhost,
+                               const char *tty,const char *passwd,
+                               struct nslcd_resp *authc_resp,
+                               struct nslcd_resp *authz_resp)
 {
   PAM_REQUEST(NSLCD_ACTION_PAM_AUTHC,
     /* log debug message */
     pam_syslog(pamh,LOG_DEBUG,"nslcd authentication; user=%s",username),
     /* write the request parameters */
     WRITE_STRING(fp,username);
-    WRITE_STRING(fp,ctx->dn);
     WRITE_STRING(fp,service);
+    WRITE_STRING(fp,ruser);
+    WRITE_STRING(fp,rhost);
+    WRITE_STRING(fp,tty);
     WRITE_STRING(fp,passwd),
     /* read the result entry */
-    READ_BUF_STRING(fp,ctx->tmpluser);
-    READ_BUF_STRING(fp,ctx->dn);
-    READ_PAM_CODE(fp,ctx->authok)
-    READ_PAM_CODE(fp,ctx->authz)
-    READ_BUF_STRING(fp,ctx->authzmsg);)
+    READ_PAM_CODE(fp,authc_resp->res);
+    READ_STRING(fp,authc_resp->msg); /* user name */
+    /* if we want the authorisation response, save it, otherwise skip it */
+    if (authz_resp!=NULL)
+    {
+      READ_PAM_CODE(fp,authz_resp->res);
+      READ_STRING(fp,authz_resp->msg);
+    }
+    else
+    {
+      SKIP(fp,sizeof(int32_t));
+      SKIP_STRING(fp);
+    })
 }
 
 /* perform an authorisation call over nslcd */
-static int nslcd_request_authz(pam_handle_t *pamh,struct pld_ctx *ctx,struct 
pld_cfg *cfg,
+static int nslcd_request_authz(pam_handle_t *pamh,struct pld_cfg *cfg,
                                const char *username,const char *service,
                                const char *ruser,const char *rhost,
-                               const char *tty)
+                               const char *tty,struct nslcd_resp *resp)
 {
   PAM_REQUEST(NSLCD_ACTION_PAM_AUTHZ,
     /* log debug message */
     pam_syslog(pamh,LOG_DEBUG,"nslcd authorisation; user=%s",username),
     /* write the request parameters */
     WRITE_STRING(fp,username);
-    WRITE_STRING(fp,ctx->dn);
     WRITE_STRING(fp,service);
     WRITE_STRING(fp,ruser);
     WRITE_STRING(fp,rhost);
     WRITE_STRING(fp,tty),
     /* read the result entry */
-    READ_BUF_STRING(fp,ctx->tmpluser);
-    READ_BUF_STRING(fp,ctx->dn);
-    READ_PAM_CODE(fp,ctx->authz);
-    READ_BUF_STRING(fp,ctx->authzmsg);)
+    READ_PAM_CODE(fp,resp->res);
+    READ_STRING(fp,resp->msg);)
 }
 
-/* do a session nslcd request (open or close) */
-static int nslcd_request_sess(pam_handle_t *pamh,struct pld_ctx *ctx,struct 
pld_cfg *cfg,int action,
-                              const char *username,const char *service,
-                              const char *tty,const char *rhost,
-                              const char *ruser)
+/* do a session open nslcd request */
+static int nslcd_request_sess_o(pam_handle_t *pamh,struct pld_cfg *cfg,
+                               const char *username,const char *service,
+                               const char *ruser,const char *rhost,
+                               const char *tty,struct nslcd_resp *resp)
 {
-  PAM_REQUEST(action,
+  PAM_REQUEST(NSLCD_ACTION_PAM_SESS_O,
     /* log debug message */
-    pam_syslog(pamh,LOG_DEBUG,"nslcd session %s; user=%s",
-          (action==NSLCD_ACTION_PAM_SESS_O)?"open":"close",username),
+    pam_syslog(pamh,LOG_DEBUG,"nslcd session open; user=%s",username),
     /* write the request parameters */
     WRITE_STRING(fp,username);
-    WRITE_STRING(fp,ctx->dn);
     WRITE_STRING(fp,service);
-    WRITE_STRING(fp,tty);
-    WRITE_STRING(fp,rhost);
     WRITE_STRING(fp,ruser);
-    WRITE_INT32(fp,ctx->sessid),
+    WRITE_STRING(fp,rhost);
+    WRITE_STRING(fp,tty),
     /* read the result entry */
-    READ_INT32(fp,ctx->sessid))
+    READ_STRING(fp,resp->msg))
+}
+
+/* do a session close nslcd request */
+static int nslcd_request_sess_c(pam_handle_t *pamh,struct pld_cfg *cfg,
+                               const char *username,const char *service,
+                               const char *ruser,const char *rhost,
+                               const char *tty,const char *sessid)
+{
+  PAM_REQUEST(NSLCD_ACTION_PAM_SESS_C,
+    /* log debug message */
+    pam_syslog(pamh,LOG_DEBUG,"nslcd session close; user=%s",username),
+    /* write the request parameters */
+    WRITE_STRING(fp,username);
+    WRITE_STRING(fp,service);
+    WRITE_STRING(fp,ruser);
+    WRITE_STRING(fp,rhost);
+    WRITE_STRING(fp,tty);
+    WRITE_STRING(fp,sessid),
+    /* no result entry to read */;)
 }
 
 /* do a password modification nslcd call */
-static int nslcd_request_pwmod(pam_handle_t *pamh,struct pld_ctx *ctx,struct 
pld_cfg *cfg,
+static int nslcd_request_pwmod(pam_handle_t *pamh,struct pld_cfg *cfg,
                                const char *username,const char *service,
-                               const char *oldpasswd,const char *newpasswd)
+                               const char *ruser,const char *rhost,
+                               const char *tty,
+                               int asroot,
+                               const char *oldpasswd,const char *newpasswd,
+                               struct nslcd_resp *resp)
 {
   PAM_REQUEST(NSLCD_ACTION_PAM_PWMOD,
     /* log debug message */
     pam_syslog(pamh,LOG_DEBUG,"nslcd password modify; user=%s",username),
     /* write the request parameters */
     WRITE_STRING(fp,username);
-    WRITE_STRING(fp,ctx->dn);
     WRITE_STRING(fp,service);
+    WRITE_STRING(fp,ruser);
+    WRITE_STRING(fp,rhost);
+    WRITE_STRING(fp,tty);
+    WRITE_INT32(fp,asroot);
     WRITE_STRING(fp,oldpasswd);
     WRITE_STRING(fp,newpasswd),
     /* read the result entry */
-    READ_BUF_STRING(fp,ctx->tmpluser);
-    READ_BUF_STRING(fp,ctx->dn);
-    READ_PAM_CODE(fp,ctx->authz);
-    READ_BUF_STRING(fp,ctx->authzmsg);)
+    READ_PAM_CODE(fp,resp->res);
+    READ_STRING(fp,resp->msg);)
 }
 
-static int nslcd_request_config_get(pam_handle_t *pamh,struct pld_ctx 
*ctx,struct pld_cfg *cfg,
-                               int cfgopt,char **value)
+static int nslcd_request_config_get(pam_handle_t *pamh,struct pld_cfg *cfg,
+                                    int cfgopt,struct nslcd_resp *resp)
 {
   PAM_REQUEST(NSLCD_ACTION_CONFIG_GET,
     /* log debug message */
@@ -370,7 +410,7 @@
     /* write the request parameter */
     WRITE_INT32(fp,cfgopt),
     /* read the result entry */
-    READ_BUF_STRING(fp,*value);)
+    READ_STRING(fp,resp->msg);)
 }
 
 /* remap the return code based on the configuration */
@@ -390,27 +430,28 @@
   struct pld_cfg cfg;
   struct pld_ctx *ctx;
   const char *username,*service;
-  char *prohibit_message;
+  const char *ruser=NULL,*rhost=NULL,*tty=NULL;
   char *passwd=NULL;
+  struct nslcd_resp resp;
   /* set up configuration */
   cfg_init(pamh,flags,argc,argv,&cfg);
-  rc=init(pamh,&cfg,&ctx,&username,&service);
+  rc=init(pamh,&cfg,&ctx,&username,&service,&ruser,&rhost,&tty);
   if (rc!=PAM_SUCCESS)
     return remap_pam_rc(rc,&cfg);
   /* if service is "passwd" and pwdmod is not allowed alert user */
   if (!strcmp(service,"passwd"))
   {
-    
rc=nslcd_request_config_get(pamh,ctx,&cfg,NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE,&prohibit_message);
-    if 
((rc==PAM_SUCCESS)&&(prohibit_message!=NULL)&&(prohibit_message[0]!='\0'))
+    
rc=nslcd_request_config_get(pamh,&cfg,NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE,&resp);
+    if ((rc==PAM_SUCCESS)&&(resp.msg!=NULL)&&(resp.msg[0]!='\0'))
     {
       /* we silently ignore errors to get the configuration option */
-      pam_syslog(pamh,LOG_NOTICE,"password change prohibited: %s; 
user=%s",prohibit_message,username);
+      pam_syslog(pamh,LOG_NOTICE,"password change prohibited: %s; 
user=%s",resp.msg,username);
       if (!cfg.no_warn)
-        pam_error(pamh,"%s",prohibit_message);
+        pam_error(pamh,"%s",resp.msg);
       return remap_pam_rc(PAM_PERM_DENIED,&cfg);
     }
   }
-  /* get the password */
+  /* prompt the user for a password */
   rc=pam_get_authtok(pamh,PAM_AUTHTOK,(const char **)&passwd,NULL);
   if (rc!=PAM_SUCCESS)
   {
@@ -425,30 +466,32 @@
     return PAM_AUTH_ERR;
   }
   /* do the nslcd request */
-  rc=nslcd_request_authc(pamh,ctx,&cfg,username,service,passwd);
+  
rc=nslcd_request_authc(pamh,&cfg,username,service,ruser,rhost,tty,passwd,&resp,&(ctx->saved_authz));
   if (rc!=PAM_SUCCESS)
     return remap_pam_rc(rc,&cfg);
   /* check the authentication result */
-  rc=ctx->authok;
-  if (rc!=PAM_SUCCESS)
+  if (resp.res!=PAM_SUCCESS)
   {
-    pam_syslog(pamh,LOG_NOTICE,"%s; user=%s",pam_strerror(pamh,rc),username);
-    return remap_pam_rc(rc,&cfg);
+    pam_syslog(pamh,LOG_NOTICE,"%s; 
user=%s",pam_strerror(pamh,resp.res),username);
+    return remap_pam_rc(resp.res,&cfg);
   }
   /* debug log */
   if (cfg.debug)
     pam_syslog(pamh,LOG_DEBUG,"authentication succeeded");
-  /* save username */
-  ctx->user=strdup(username);
   /* if password change is required, save old password in context */
-  if (ctx->authz==PAM_NEW_AUTHTOK_REQD)
+  if (resp.res==PAM_NEW_AUTHTOK_REQD)
     ctx->oldpassword=strdup(passwd);
   /* update caller's idea of the user name */
-  if ( ctx->tmpluser && ctx->tmpluser[0] && 
(strcmp(ctx->tmpluser,username)!=0) )
+  if ((resp.msg[0]!='\0') && (strcmp(resp.msg,username)!=0))
   {
-    pam_syslog(pamh,LOG_INFO,"username changed from %s to %s",username,
-               ctx->tmpluser);
-    rc=pam_set_item(pamh,PAM_USER,ctx->tmpluser);
+    pam_syslog(pamh,LOG_INFO,"username changed from %s to 
%s",username,resp.msg);
+    rc=pam_set_item(pamh,PAM_USER,resp.msg);
+    /* empty the username in the context to not loose our context */
+    if (ctx->username==NULL)
+    {
+      free(ctx->username);
+      ctx->username=NULL;
+    }
   }
   return rc;
 }
@@ -466,104 +509,100 @@
 {
   int rc;
   struct pld_cfg cfg;
-  struct pld_ctx *ctx=NULL,ctx2;
+  struct pld_ctx *ctx;
   const char *username,*service;
   const char *ruser=NULL,*rhost=NULL,*tty=NULL;
+  struct nslcd_resp authz_resp;
+  const char *msg;
   /* set up configuration */
   cfg_init(pamh,flags,argc,argv,&cfg);
-  rc=init(pamh,&cfg,&ctx,&username,&service);
+  rc=init(pamh,&cfg,&ctx,&username,&service,&ruser,&rhost,&tty);
   if (rc!=PAM_SUCCESS)
     return remap_pam_rc(rc,&cfg);
-  /* get more PAM information */
-  pam_get_item(pamh,PAM_RUSER,(const void **)&ruser);
-  pam_get_item(pamh,PAM_RHOST,(const void **)&rhost);
-  pam_get_item(pamh,PAM_TTY,(const void **)&tty);
-  /* call the function with a copy of the context to be able to keep the
-     original context */
-  ctx2.dn=ctx->dn;
-  ctx2.user=ctx->user;
   /* do the nslcd request */
-  rc=nslcd_request_authz(pamh,&ctx2,&cfg,username,service,ruser,rhost,tty);
+  
rc=nslcd_request_authz(pamh,&cfg,username,service,ruser,rhost,tty,&authz_resp);
   if (rc!=PAM_SUCCESS)
     return remap_pam_rc(rc,&cfg);
-  /* check the returned authorisation value */
-  if (ctx2.authz!=PAM_SUCCESS)
+  /* check the returned authorisation value and the value from authentication 
*/
+  if (authz_resp.res!=PAM_SUCCESS)
+  {
+    rc=authz_resp.res;
+    msg=authz_resp.msg;
+  }
+  else if (ctx->saved_authz.res!=PAM_SUCCESS)
+  {
+    rc=ctx->saved_authz.res;
+    msg=ctx->saved_authz.msg;
+  }
+  if (rc!=PAM_SUCCESS)
   {
     /* turn in to generic PAM error message if message is empty */
-    if ((ctx2.authzmsg==NULL)||(ctx2.authzmsg[0]=='\0'))
+    if ((msg==NULL)||(msg[0]=='\0'))
     {
-      ctx2.authzmsg=(char *)pam_strerror(pamh,ctx2.authz);
-      pam_syslog(pamh,LOG_NOTICE,"%s; user=%s",ctx2.authzmsg,username);
+      msg=pam_strerror(pamh,rc);
+      pam_syslog(pamh,LOG_NOTICE,"%s; user=%s",msg,username);
     }
     else
-      pam_syslog(pamh,LOG_NOTICE,"%s; user=%s; 
err=%s",ctx2.authzmsg,username,pam_strerror(pamh,rc));
-    rc=remap_pam_rc(ctx2.authz,&cfg);
-    if ((rc!=PAM_IGNORE)&&(!cfg.no_warn))
-      pam_error(pamh,"%s",ctx2.authzmsg);
-    return rc;
-  }
-  /* check the original authorisation check from authentication */
-  if (ctx->authz!=PAM_SUCCESS)
-  {
-    if ((ctx->authzmsg==NULL)||(ctx->authzmsg[0]=='\0'))
-      ctx->authzmsg=(char *)pam_strerror(pamh,ctx->authz);
-    pam_syslog(pamh,LOG_NOTICE,"%s; user=%s",ctx->authzmsg,username);
-    rc=remap_pam_rc(ctx->authz,&cfg);
+      pam_syslog(pamh,LOG_NOTICE,"%s; user=%s; 
err=%s",msg,username,pam_strerror(pamh,rc));
+    rc=remap_pam_rc(rc,&cfg);
     if ((rc!=PAM_IGNORE)&&(!cfg.no_warn))
-      pam_error(pamh,"%s",ctx->authzmsg);
+      pam_error(pamh,"%s",msg);
     return rc;
   }
   if (cfg.debug)
     pam_syslog(pamh,LOG_DEBUG,"authorization succeeded");
   /* present any informational messages to the user */
-  if ((ctx2.authzmsg!=NULL)&&(ctx2.authzmsg[0]!='\0')&&(!cfg.no_warn))
-    pam_info(pamh,"%s",ctx2.authzmsg);
-  if ((ctx->authzmsg!=NULL)&&(ctx->authzmsg[0]!='\0')&&(!cfg.no_warn))
-    pam_info(pamh,"%s",ctx->authzmsg);
+  if ((authz_resp.msg[0]!='\0')&&(!cfg.no_warn))
+    pam_info(pamh,"%s",authz_resp.msg);
+  if ((ctx->saved_authz.msg[0]!='\0')&&(!cfg.no_warn))
+    pam_info(pamh,"%s",ctx->saved_authz.msg);
   return PAM_SUCCESS;
 }
 
-/* PAM session open/close calls */
-static int pam_sm_session(pam_handle_t *pamh,int flags,int argc,
-                          const char **argv,int action)
+/* PAM session open call */
+int pam_sm_open_session(pam_handle_t *pamh,int flags,int argc,const char 
**argv)
 {
   int rc;
   struct pld_cfg cfg;
   struct pld_ctx *ctx;
   const char *username,*service;
-  const char *tty=NULL,*rhost=NULL,*ruser=NULL;
+  const char *ruser=NULL,*rhost=NULL,*tty=NULL;
   /* set up configuration */
   cfg_init(pamh,flags,argc,argv,&cfg);
-  rc=init(pamh,&cfg,&ctx,&username,&service);
+  rc=init(pamh,&cfg,&ctx,&username,&service,&ruser,&rhost,&tty);
   if (rc!=PAM_SUCCESS)
     return remap_pam_rc(rc,&cfg);
-  /* get more PAM information */
-  pam_get_item(pamh,PAM_TTY,(const void **)&tty);
-  pam_get_item(pamh,PAM_RHOST,(const void **)&rhost);
-  pam_get_item(pamh,PAM_RUSER,(const void **)&ruser);
   /* do the nslcd request */
-  rc=nslcd_request_sess(pamh,ctx,&cfg,action,username,service,tty,rhost,ruser);
+  
rc=nslcd_request_sess_o(pamh,&cfg,username,service,ruser,rhost,tty,&(ctx->saved_session));
   if (rc!=PAM_SUCCESS)
     return remap_pam_rc(rc,&cfg);
   /* debug log */
   if (cfg.debug)
-    pam_syslog(pamh,LOG_DEBUG,"session %s succeeded; session_id=%d",
-               (action==NSLCD_ACTION_PAM_SESS_O)?"open":"close",ctx->sessid);
+    pam_syslog(pamh,LOG_DEBUG,"session open succeeded; 
session_id=%s",ctx->saved_session.msg);
   return PAM_SUCCESS;
 }
 
-/* PAM session open call */
-int pam_sm_open_session(
-  pam_handle_t *pamh,int flags,int argc,const char **argv)
-{
-  return pam_sm_session(pamh,flags,argc,argv,NSLCD_ACTION_PAM_SESS_O);
-}
-
 /* PAM session close call */
-int pam_sm_close_session(
-  pam_handle_t *pamh,int flags,int argc,const char **argv)
+int pam_sm_close_session(pam_handle_t *pamh,int flags,int argc,const char 
**argv)
 {
-  return pam_sm_session(pamh,flags,argc,argv,NSLCD_ACTION_PAM_SESS_C);
+  int rc;
+  struct pld_cfg cfg;
+  struct pld_ctx *ctx;
+  const char *username,*service;
+  const char *ruser=NULL,*rhost=NULL,*tty=NULL;
+  /* set up configuration */
+  cfg_init(pamh,flags,argc,argv,&cfg);
+  rc=init(pamh,&cfg,&ctx,&username,&service,&ruser,&rhost,&tty);
+  if (rc!=PAM_SUCCESS)
+    return remap_pam_rc(rc,&cfg);
+  /* do the nslcd request */
+  
rc=nslcd_request_sess_c(pamh,&cfg,username,service,ruser,rhost,tty,ctx->saved_session.msg);
+  if (rc!=PAM_SUCCESS)
+    return remap_pam_rc(rc,&cfg);
+  /* debug log */
+  if (cfg.debug)
+    pam_syslog(pamh,LOG_DEBUG,"session close succeeded; 
session_id=%s",ctx->saved_session.msg);
+  return PAM_SUCCESS;
 }
 
 /* Change the password of the user. This function is first called with
@@ -577,37 +616,37 @@
   struct pld_cfg cfg;
   struct pld_ctx *ctx;
   const char *username,*service;
+  const char *ruser=NULL,*rhost=NULL,*tty=NULL;
   const char *oldpassword=NULL,*newpassword=NULL;
-  char *prohibit_message;
   struct passwd *pwent;
   uid_t myuid;
+  struct nslcd_resp resp;
+  const char *msg;
   /* set up configuration */
   cfg_init(pamh,flags,argc,argv,&cfg);
-  rc=init(pamh,&cfg,&ctx,&username,&service);
+  rc=init(pamh,&cfg,&ctx,&username,&service,&ruser,&rhost,&tty);
   if (rc!=PAM_SUCCESS)
     return remap_pam_rc(rc,&cfg);
   /* check if password modification is allowed */
-  
rc=nslcd_request_config_get(pamh,ctx,&cfg,NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE,&prohibit_message);
-  if ((rc==PAM_SUCCESS)&&(prohibit_message!=NULL)&&(prohibit_message[0]!='\0'))
+  
rc=nslcd_request_config_get(pamh,&cfg,NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE,&resp);
+  if ((rc==PAM_SUCCESS)&&(resp.msg!=NULL)&&(resp.msg[0]!='\0'))
   {
     /* we silently ignore errors to get the configuration option */
-    pam_syslog(pamh,LOG_NOTICE,"password change prohibited: %s; 
user=%s",prohibit_message,username);
+    pam_syslog(pamh,LOG_NOTICE,"password change prohibited: %s; 
user=%s",resp.msg,username);
     if (!cfg.no_warn)
-      pam_error(pamh,"%s",prohibit_message);
+      pam_error(pamh,"%s",resp.msg);
     return remap_pam_rc(PAM_PERM_DENIED,&cfg);
   }
   /* see if we are dealing with an LDAP user first */
-  if (ctx->dn==NULL)
-  {
-    rc=nslcd_request_exists(pamh,ctx,&cfg,username);
-    if (rc!=PAM_SUCCESS)
-      return remap_pam_rc(rc,&cfg);
-  }
-  /* prelimenary check, just see if we can connect to the LDAP server
-     and authenticate with the current password */
+  rc=nslcd_request_exists(pamh,ctx,&cfg,username);
+  if (rc!=PAM_SUCCESS)
+    return remap_pam_rc(rc,&cfg);
+  /* preliminary check, just see if we can authenticate with the current 
password */
   if (flags&PAM_PRELIM_CHECK)
   {
+    ctx->asroot=0;
     /* see if the user is trying to modify another user's password */
+    /* TODO: perhaps this can be combined with the nslcd_request_exists() call 
above */
     pwent=pam_modutil_getpwnam(args->pamh,username);
     myuid=getuid();
     if 
((pwent!=NULL)&&(pwent->pw_uid!=myuid)&&(!(flags&PAM_CHANGE_EXPIRED_AUTHTOK)))
@@ -616,15 +655,19 @@
          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))
+        
rc=nslcd_request_authc(pamh,&cfg,"",service,ruser,rhost,tty,"",&resp,NULL);
+        if ((rc==PAM_SUCCESS)&&(resp.res==PAM_SUCCESS))
+        {
+          ctx->asroot=1;
           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: ");
       if (rc!=PAM_SUCCESS)
         return rc;
+      ctx->asroot=1;
       username="";
     }
     else if ((ctx->oldpassword!=NULL)&&(*ctx->oldpassword!='\0'))
@@ -633,6 +676,7 @@
       oldpassword=ctx->oldpassword;
     else
     {
+      /* prompt the user for a password if needed */
       rc=pam_get_authtok(pamh,PAM_OLDAUTHTOK,(const char 
**)&oldpassword,"(current) LDAP Password: ");
       if (rc!=PAM_SUCCESS)
         return rc;
@@ -645,46 +689,49 @@
       return PAM_AUTH_ERR;
     }
     /* try authenticating */
-    rc=nslcd_request_authc(pamh,ctx,&cfg,username,service,oldpassword);
+    
rc=nslcd_request_authc(pamh,&cfg,username,service,ruser,rhost,tty,oldpassword,&resp,NULL);
     if (rc!=PAM_SUCCESS)
       return remap_pam_rc(rc,&cfg);
     /* handle authentication result */
-    if (ctx->authok!=PAM_SUCCESS)
-      pam_syslog(pamh,LOG_NOTICE,"%s; 
user=%s",pam_strerror(pamh,ctx->authok),username);
+    if (resp.res!=PAM_SUCCESS)
+      pam_syslog(pamh,LOG_NOTICE,"%s; 
user=%s",pam_strerror(pamh,resp.res),username);
     else if (cfg.debug)
       pam_syslog(pamh,LOG_DEBUG,"authentication succeeded");
     /* store password (needed if oldpassword was retreived from context) */
-    if (ctx->authok==PAM_SUCCESS)
+    if (resp.res==PAM_SUCCESS)
     {
       rc=pam_set_item(pamh,PAM_OLDAUTHTOK,oldpassword);
       if (rc!=PAM_SUCCESS)
         return remap_pam_rc(rc,&cfg);
     }
     /* remap error code */
-    return remap_pam_rc(ctx->authok,&cfg);
+    return remap_pam_rc(resp.res,&cfg);
   }
   /* get the old password (from the previous call) */
   rc=pam_get_item(pamh,PAM_OLDAUTHTOK,(const void **)&oldpassword);
   if (rc!=PAM_SUCCESS)
     return rc;
-  /* get the new password */
+  /* prompt for new password */
   rc=pam_get_authtok(pamh,PAM_AUTHTOK,&newpassword,NULL);
   if (rc!=PAM_SUCCESS)
     return rc;
   /* perform the password modification */
-  
rc=nslcd_request_pwmod(pamh,ctx,&cfg,username,service,oldpassword,newpassword);
-  if (rc==PAM_SUCCESS)
-    rc=ctx->authz;
+  
rc=nslcd_request_pwmod(pamh,&cfg,username,service,ruser,rhost,tty,ctx->asroot,oldpassword,newpassword,&resp);
+  if (rc!=PAM_SUCCESS)
+    msg=pam_strerror(pamh,rc);
   else
-    ctx->authzmsg=(char *)pam_strerror(pamh,rc);
+  {
+    rc=resp.res;
+    msg=resp.msg;
+  }
   /* remap error code */
   rc=remap_pam_rc(rc,&cfg);
   /* check the returned value */
   if (rc!=PAM_SUCCESS)
   {
-    pam_syslog(pamh,LOG_NOTICE,"password change failed: %s; 
user=%s",ctx->authzmsg,username);
+    pam_syslog(pamh,LOG_NOTICE,"password change failed: %s; 
user=%s",msg,username);
     if ((rc!=PAM_IGNORE)&&(!cfg.no_warn))
-      pam_error(pamh,"%s",ctx->authzmsg);
+      pam_error(pamh,"%s",msg);
     return rc;
   }
   pam_syslog(pamh,LOG_NOTICE,"password changed for %s",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/