summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--compat/pam_compat.h9
-rw-r--r--configure.ac2
-rw-r--r--man/pam_ldap.8.xml8
-rw-r--r--pam/common.h13
-rw-r--r--pam/pam.c103
5 files changed, 106 insertions, 29 deletions
diff --git a/compat/pam_compat.h b/compat/pam_compat.h
index 7556b36..7bb4081 100644
--- a/compat/pam_compat.h
+++ b/compat/pam_compat.h
@@ -67,4 +67,13 @@ int pam_prompt(pam_handle_t *pamh,int style,char **response,const char *format,.
#define pam_modutil_getpwnam(pamh,user) getpwnam(user)
#endif /* not HAVE_PAM_MODUTIL_GETGWNAM */
+/* fall back to using syslog() if pam_syslog() doesn't exist */
+#ifndef HAVE_PAM_SYSLOG
+#ifndef LOG_AUTHPRIV
+#define LOG_AUTHPRIV LOG_AUTH
+#endif /* not LOG_AUTHPRIV */
+#define pam_syslog(pamh,priority,format,args...) \
+ syslog(LOG_AUTHPRIV|(priority),format,##args)
+#endif /* not HAVE_PAM_SYSLOG */
+
#endif /* _COMPAT_LDAP_COMPAT_H */
diff --git a/configure.ac b/configure.ac
index cf238b1..cbdd843 100644
--- a/configure.ac
+++ b/configure.ac
@@ -310,7 +310,7 @@ then
AC_SEARCH_LIBS(pam_get_data,pam,,AC_MSG_ERROR(no PAM library available))
# replace some PAM functions if they are unavailable
AC_REPLACE_FUNCS(pam_get_authtok pam_prompt)
- AC_CHECK_FUNCS(pam_modutil_getpwnam)
+ AC_CHECK_FUNCS(pam_modutil_getpwnam pam_syslog)
# restore CFLAGS and LIBS
CFLAGS="$save_CFLAGS"
LIBS="$save_LIBS"
diff --git a/man/pam_ldap.8.xml b/man/pam_ldap.8.xml
index cf69514..88890a2 100644
--- a/man/pam_ldap.8.xml
+++ b/man/pam_ldap.8.xml
@@ -143,7 +143,9 @@
</term>
<listitem>
<para>
- This option is ignored.
+ This option causes the <acronym>PAM</acronym> module to log debugging
+ information to
+ <citerefentry><refentrytitle>syslog</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para>
</listitem>
</varlistentry>
@@ -155,8 +157,8 @@
<para>
This option causes the <acronym>PAM</acronym> module to ignore the user
if the user id is lower than the specified value. This can be used to
- only authenticate normal users (non-system users) using
- <acronym>LDAP</acronym> (e.g. by setting it to <literal>1000</literal>).
+ bypass <acronym>LDAP</acronym> checks for system users
+ (e.g. by setting it to <literal>1000</literal>).
</para>
</listitem>
</varlistentry>
diff --git a/pam/common.h b/pam/common.h
index e1e6bbe..6dc8996 100644
--- a/pam/common.h
+++ b/pam/common.h
@@ -35,27 +35,34 @@
/* Macro is called to handle errors in opening a client connection. */
#define ERROR_OUT_OPENERROR \
+ pam_syslog(pamh,LOG_ERR,"error opening connection to nslcd: %s",strerror(errno)); \
return PAM_AUTHINFO_UNAVAIL;
/* Macro is called to handle errors on read operations. */
#define ERROR_OUT_READERROR(fp) \
+ pam_syslog(pamh,LOG_ERR,"error reading from nslcd: %s",strerror(errno)); \
(void)tio_close(fp); \
return PAM_AUTHINFO_UNAVAIL;
/* Macro is called to handle problems with too small a buffer. */
#define ERROR_OUT_BUFERROR(fp) \
+ pam_syslog(pamh,LOG_CRIT,"buffer %d bytes too small",tmpint32); \
(void)tio_close(fp); \
return PAM_SYSTEM_ERR;
/* This macro is called if there was a problem with a write
operation. */
#define ERROR_OUT_WRITEERROR(fp) \
- ERROR_OUT_READERROR(fp)
+ pam_syslog(pamh,LOG_ERR,"error writing to nslcd: %s",strerror(errno)); \
+ (void)tio_close(fp); \
+ return PAM_AUTHINFO_UNAVAIL;
/* This macro is called if the read status code is not
NSLCD_RESULT_BEGIN. */
#define ERROR_OUT_NOSUCCESS(fp) \
(void)tio_close(fp); \
+ if (cfg->debug) \
+ pam_syslog(pamh,LOG_DEBUG,"request not handled by nslcd"); \
return PAM_USER_UNKNOWN;
/* This is a generic PAM request generation macro. The action
@@ -66,12 +73,14 @@
the result structure, the user buffer with length and the
errno to return. This macro should be called through some of
the customized ones below. */
-#define PAM_REQUEST(action,writefn,readfn) \
+#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 */ \
NSLCD_REQUEST(fp,action,writefn); \
/* read response code */ \
diff --git a/pam/pam.c b/pam/pam.c
index 3d8daa5..ee3cc34 100644
--- a/pam/pam.c
+++ b/pam/pam.c
@@ -55,11 +55,6 @@
/* the name we store our context under */
#define PLD_CTX "PAM_LDAPD_CTX"
-/* some systems don't have LOG_AUTHPRIV */
-#ifndef LOG_AUTHPRIV
-#define LOG_AUTHPRIV LOG_AUTH
-#endif /* not LOG_AUTHPRIV */
-
/* this struct represents the context that the PAM module keeps
between calls */
@@ -122,13 +117,17 @@ static int ctx_get(pam_handle_t *pamh,const char *username,struct pld_ctx **pctx
/* allocate a new context */
ctx=calloc(1,sizeof(struct pld_ctx));
if (ctx==NULL)
+ {
+ pam_syslog(pamh,LOG_CRIT,"calloc(): failed to allocate memory: %s",strerror(errno));
return PAM_BUF_ERR;
+ }
ctx_clear(ctx);
/* store the new context with the handler to free it */
rc=pam_set_data(pamh,PLD_CTX,ctx,ctx_free);
if (rc!=PAM_SUCCESS)
{
ctx_free(pamh,ctx,0);
+ pam_syslog(pamh,LOG_ERR,"failed to store context: %s",pam_strerror(pamh,rc));
return rc;
}
}
@@ -185,7 +184,7 @@ static int init(pam_handle_t *pamh,int flags,int argc,const char **argv,
else if (strncmp(argv[i], "minimum_uid=", 12) == 0)
cfg->minimum_uid=(uid_t)atoi(argv[i]+12);
else
- syslog(LOG_AUTHPRIV|LOG_ERR,"unknown option: %s",argv[i]);
+ pam_syslog(pamh,LOG_ERR,"unknown option: %s",argv[i]);
}
/* check flags */
if (flags&PAM_SILENT)
@@ -193,15 +192,25 @@ static int init(pam_handle_t *pamh,int flags,int argc,const char **argv,
/* get user name */
rc=pam_get_user(pamh,username,NULL);
if (rc!=PAM_SUCCESS)
+ {
+ pam_syslog(pamh,LOG_ERR,"failed to get user name: %s",pam_strerror(pamh,rc));
return rc;
+ }
if ((*username==NULL)||((*username)[0]=='\0'))
+ {
+ pam_syslog(pamh,LOG_ERR,"got empty user name");
return PAM_USER_UNKNOWN;
+ }
/* check uid */
if (cfg->minimum_uid>0)
{
pwent=pam_modutil_getpwnam(args->pamh,*username);
if ((pwent!=NULL)&&(pwent->pw_uid<cfg->minimum_uid))
+ {
+ if (cfg->debug)
+ pam_syslog(pamh,LOG_DEBUG,"uid below minimum_uid; user=%s uid=%d",*username,(int)pwent->pw_uid);
return cfg->ignore_unknown_user?PAM_IGNORE:PAM_USER_UNKNOWN;
+ }
}
/* get our context */
rc=ctx_get(pamh,*username,ctx);
@@ -210,7 +219,10 @@ static int init(pam_handle_t *pamh,int flags,int argc,const char **argv,
/* get service name */
rc=pam_get_item(pamh,PAM_SERVICE,(const void **)service);
if (rc!=PAM_SUCCESS)
+ {
+ pam_syslog(pamh,LOG_ERR,"failed to get service name: %s",pam_strerror(pamh,rc));
return rc;
+ }
return PAM_SUCCESS;
}
@@ -237,10 +249,13 @@ static int nslcd2pam_rc(int rc)
}
/* perform an authentication call over nslcd */
-static int nslcd_request_authc(struct pld_ctx *ctx,const char *username,
- const char *service,const char *passwd)
+static int nslcd_request_authc(pam_handle_t *pamh,struct pld_ctx *ctx,struct pld_cfg *cfg,
+ const char *username, const char *service,
+ const char *passwd)
{
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);
@@ -255,11 +270,14 @@ static int nslcd_request_authc(struct pld_ctx *ctx,const char *username,
}
/* perform an authorisation call over nslcd */
-static int nslcd_request_authz(struct pld_ctx *ctx,const char *username,
- const char *service,const char *ruser,
- const char *rhost,const char *tty)
+static int nslcd_request_authz(pam_handle_t *pamh,struct pld_ctx *ctx,struct pld_cfg *cfg,
+ const char *username, const char *service,
+ const char *ruser,const char *rhost,
+ const char *tty)
{
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);
@@ -275,12 +293,15 @@ static int nslcd_request_authz(struct pld_ctx *ctx,const char *username,
}
/* do a session nslcd request (open or close) */
-static int nslcd_request_sess(struct pld_ctx *ctx,int action,
+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)
{
PAM_REQUEST(action,
+ /* log debug message */
+ pam_syslog(pamh,LOG_DEBUG,"nslcd session %s; user=%s",
+ (action==NSLCD_ACTION_PAM_SESS_O)?"open":"clode",username),
/* write the request parameters */
WRITE_STRING(fp,username);
WRITE_STRING(fp,ctx->dn);
@@ -294,11 +315,13 @@ static int nslcd_request_sess(struct pld_ctx *ctx,int action,
}
/* do a password modification nslcd call */
-static int nslcd_request_pwmod(struct pld_ctx *ctx,const char *username,
- const char *service,const char *oldpasswd,
- const char *newpasswd)
+static int nslcd_request_pwmod(pam_handle_t *pamh,struct pld_ctx *ctx,struct pld_cfg *cfg,
+ const char *username,const char *service,
+ const char *oldpasswd,const char *newpasswd)
{
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);
@@ -332,16 +355,28 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,const char **argv)
{
rc=pam_get_authtok(pamh,PAM_AUTHTOK,(const char **)&passwd,i==0?"Password: ":"LDAP Password: ");
if (rc!=PAM_SUCCESS)
+ {
+ pam_syslog(pamh,LOG_ERR,"failed to get password: %s",pam_strerror(pamh,rc));
return rc;
+ }
/* exit loop after trying this password */
i=2;
}
rc=pam_get_item(pamh,PAM_AUTHTOK,(const void **)&passwd);
+ if (rc!=PAM_SUCCESS)
+ pam_syslog(pamh,LOG_ERR,"failed to get password: %s",pam_strerror(pamh,rc));
if (rc==PAM_SUCCESS)
{
- rc=nslcd_request_authc(ctx,username,service,passwd);
+ rc=nslcd_request_authc(pamh,ctx,&cfg,username,service,passwd);
if (rc==PAM_SUCCESS)
+ {
rc=ctx->authok;
+ if (rc!=PAM_SUCCESS)
+ pam_syslog(pamh,LOG_NOTICE,"%s; user=%s",pam_strerror(pamh,rc),username);
+ else if (cfg.debug)
+ pam_syslog(pamh,LOG_DEBUG,"authentication succeeded");
+ }
+ /* remap error code */
if ((rc==PAM_AUTHINFO_UNAVAIL)&&cfg.ignore_authinfo_unavail)
rc=PAM_IGNORE;
else if ((rc==PAM_USER_UNKNOWN)&&cfg.ignore_unknown_user)
@@ -362,7 +397,11 @@ int pam_sm_authenticate(pam_handle_t *pamh,int flags,int argc,const char **argv)
/* update caller's idea of the user name */
if ( (rc==PAM_SUCCESS) && ctx->tmpluser && ctx->tmpluser[0] &&
(strcmp(ctx->tmpluser,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);
+ }
return rc;
}
@@ -394,7 +433,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc,const char **argv)
original context */
ctx2.dn=ctx->dn;
ctx2.user=ctx->user;
- rc=nslcd_request_authz(&ctx2,username,service,ruser,rhost,tty);
+ rc=nslcd_request_authz(pamh,&ctx2,&cfg,username,service,ruser,rhost,tty);
/* remap error code */
if ((rc==PAM_AUTHINFO_UNAVAIL)&&cfg.ignore_authinfo_unavail)
rc=PAM_IGNORE;
@@ -410,6 +449,7 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc,const char **argv)
/* check the returned authorisation value */
if (ctx2.authz!=PAM_SUCCESS)
{
+ pam_syslog(pamh,LOG_NOTICE,"%s; user=%s",ctx2.authzmsg,username);
if (!cfg.no_warn)
pam_error(pamh,"%s",ctx2.authzmsg);
return ctx2.authz;
@@ -417,10 +457,13 @@ int pam_sm_acct_mgmt(pam_handle_t *pamh,int flags,int argc,const char **argv)
/* check the original authorisation check from authentication */
if (ctx->authz!=PAM_SUCCESS)
{
+ pam_syslog(pamh,LOG_NOTICE,"%s; user=%s",ctx->authzmsg,username);
if (!cfg.no_warn)
pam_error(pamh,"%s",ctx->authzmsg);
return ctx->authz;
}
+ 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);
@@ -447,7 +490,12 @@ static int pam_sm_session(pam_handle_t *pamh,int flags,int argc,
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(ctx,action,username,service,tty,rhost,ruser);
+ rc=nslcd_request_sess(pamh,ctx,&cfg,action,username,service,tty,rhost,ruser);
+ if (rc!=PAM_SUCCESS)
+ pam_syslog(pamh,LOG_NOTICE,"%s; user=%s",pam_strerror(pamh,rc),username);
+ else if (cfg.debug)
+ pam_syslog(pamh,LOG_DEBUG,"session %s succeeded; session_id=%d",
+ (action==NSLCD_ACTION_PAM_SESS_O)?"open":"clode",ctx->sessid);
/* remap error code */
if ((rc==PAM_AUTHINFO_UNAVAIL)&&cfg.ignore_authinfo_unavail)
rc=PAM_IGNORE;
@@ -517,9 +565,10 @@ int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc,const char **argv)
return rc;
}
/* try authenticating */
- rc=nslcd_request_authc(ctx,username,service,oldpassword);
+ rc=nslcd_request_authc(pamh,ctx,&cfg,username,service,oldpassword);
if (rc==PAM_SUCCESS)
rc=ctx->authok;
+ /* remap error code */
if ((rc==PAM_AUTHINFO_UNAVAIL)&&cfg.ignore_authinfo_unavail)
rc=PAM_IGNORE;
else if ((rc==PAM_USER_UNKNOWN)&&cfg.ignore_unknown_user)
@@ -537,18 +586,26 @@ int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc,const char **argv)
if (rc!=PAM_SUCCESS)
return rc;
/* perform the password modification */
- rc=nslcd_request_pwmod(ctx,username,service,oldpassword,newpassword);
+ rc=nslcd_request_pwmod(pamh,ctx,&cfg,username,service,oldpassword,newpassword);
if (rc==PAM_SUCCESS)
rc=ctx->authz;
else
ctx->authzmsg=(char *)pam_strerror(pamh,rc);
+ /* remap error code */
if ((rc==PAM_AUTHINFO_UNAVAIL)&&cfg.ignore_authinfo_unavail)
rc=PAM_IGNORE;
else if ((rc==PAM_USER_UNKNOWN)&&cfg.ignore_unknown_user)
rc=PAM_IGNORE;
- else if (!cfg.no_warn)
- pam_error(pamh,"%s",ctx->authzmsg);
- return rc;
+ /* check the returned value */
+ if (rc!=PAM_SUCCESS)
+ {
+ pam_syslog(pamh,LOG_NOTICE,"password change failed: %s; user=%s",ctx->authzmsg,username);
+ if ((rc!=PAM_IGNORE)&&(!cfg.no_warn))
+ pam_error(pamh,"%s",ctx->authzmsg);
+ return rc;
+ }
+ pam_syslog(pamh,LOG_NOTICE,"password changed for %s",username);
+ return PAM_SUCCESS;
}
#ifdef PAM_STATIC