diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2012-07-08 08:26:32 +0000 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2012-07-08 08:26:32 +0000 |
commit | a7b45e56fd3515435bbbc2b57dae4d6f3b20113f (patch) | |
tree | 536db2d4c36e444351b00d41ec0efffdc395a18b | |
parent | c8f4cef2c40a3a84cb83badc65618afa16c9b3ab (diff) |
implement a pam_password_prohibit_message nslcd.conf option to deny password change introducing a NSLCD_ACTION_CONFIG_GET request thanks to Ted Cheng
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd@1715 ef36b2f9-881f-0410-afb5-c4e39611909c
-rw-r--r-- | man/nslcd.conf.5.xml | 13 | ||||
-rw-r--r-- | nslcd.h | 12 | ||||
-rw-r--r-- | nslcd/Makefile.am | 4 | ||||
-rw-r--r-- | nslcd/cfg.c | 22 | ||||
-rw-r--r-- | nslcd/cfg.h | 3 | ||||
-rw-r--r-- | nslcd/common.h | 1 | ||||
-rw-r--r-- | nslcd/config.c | 61 | ||||
-rw-r--r-- | nslcd/nslcd.c | 1 | ||||
-rw-r--r-- | nslcd/pam.c | 12 | ||||
-rw-r--r-- | pam/pam.c | 23 |
10 files changed, 149 insertions, 3 deletions
diff --git a/man/nslcd.conf.5.xml b/man/nslcd.conf.5.xml index 75ed385..4a3e442 100644 --- a/man/nslcd.conf.5.xml +++ b/man/nslcd.conf.5.xml @@ -757,6 +757,19 @@ </listitem> </varlistentry> + <varlistentry id="pam_password_prohibit_message"> + <term><option>pam_password_prohibit_message</option> + "<replaceable>MESSAGE</replaceable>"</term> + <listitem> + <para> + If this option is set password modification using pam_ldap will be + denied and the specified message will be presented to the user instead. + The message can be used to direct the user to an alternative means + of changing their password. + </para> + </listitem> + </varlistentry> + </variablelist> </refsect2> @@ -2,7 +2,7 @@ nslcd.h - file describing client/server protocol Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2009, 2010, 2011 Arthur de Jong + Copyright (C) 2006, 2007, 2009, 2010, 2011, 2012 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 @@ -71,6 +71,16 @@ 1.0 release of nss-pam-ldapd is made. */ #define NSLCD_VERSION 1 +/* Get a NSLCD configuration option. There is one request parameter: + INT32 NSLCD_CONFIG_* + the result value is: + STRING value, interpretation depending on request */ +#define NSLCD_ACTION_CONFIG_GET 20006 + +/* return the message, if any, that is presented to the user when password + modification through PAM is prohibited */ +#define NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE 852 + /* Email alias (/etc/aliases) NSS requests. The result values for a single entry are: STRING alias name diff --git a/nslcd/Makefile.am b/nslcd/Makefile.am index 7a1d4c7..4b866ae 100644 --- a/nslcd/Makefile.am +++ b/nslcd/Makefile.am @@ -1,7 +1,7 @@ # Makefile.am - use automake to generate Makefile.in # # Copyright (C) 2006, 2007 West Consulting -# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Arthur de Jong +# Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 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 @@ -31,7 +31,7 @@ nslcd_SOURCES = nslcd.c ../nslcd.h ../common/nslcd-prot.h \ cfg.c cfg.h \ attmap.c attmap.h \ nsswitch.c \ - alias.c ether.c group.c host.c netgroup.c network.c \ + alias.c config.c ether.c group.c host.c netgroup.c network.c \ passwd.c protocol.c rpc.c service.c shadow.c pam.c nslcd_LDADD = ../common/libtio.a ../common/libdict.a \ ../common/libexpr.a ../compat/libcompat.a \ diff --git a/nslcd/cfg.c b/nslcd/cfg.c index 4e828a1..b98ad38 100644 --- a/nslcd/cfg.c +++ b/nslcd/cfg.c @@ -131,6 +131,7 @@ static void cfg_defaults(struct ldap_config *cfg) cfg->ldc_nss_min_uid=0; parse_validnames_statement(__FILE__,__LINE__,"", "/^[a-z0-9._@$][a-z0-9._@$ \\~-]*[a-z0-9._@$~-]$/i",cfg); + cfg->pam_password_prohibit_message=NULL; } /* simple strdup wrapper */ @@ -639,6 +640,23 @@ static void parse_validnames_statement(const char *filename,int lnr, } } +static void parse_pam_password_prohibit_message_statement(const char *filename,int lnr, + const char *keyword,char *line,struct ldap_config *cfg) +{ + char *value; + int l; + /* the rest of the line should be a message */ + get_restdup(filename,lnr,keyword,&line,&value); + /* strip quotes if they are present */ + l=strlen(value); + if ((value[0]=='\"')&&(value[l-1]=='\"')) + { + value[l-1]='\0'; + value++; + } + cfg->pam_password_prohibit_message=value; +} + static void parse_base_statement(const char *filename,int lnr, const char *keyword,char *line, struct ldap_config *cfg) @@ -1142,6 +1160,10 @@ static void cfg_read(const char *filename,struct ldap_config *cfg) { parse_validnames_statement(filename,lnr,keyword,line,cfg); } + else if (strcasecmp(keyword,"pam_password_prohibit_message")==0) + { + parse_pam_password_prohibit_message_statement(filename,lnr,keyword,line,cfg); + } #ifdef ENABLE_CONFIGFILE_CHECKING /* fallthrough */ else diff --git a/nslcd/cfg.h b/nslcd/cfg.h index a7e08b4..0c432ee 100644 --- a/nslcd/cfg.h +++ b/nslcd/cfg.h @@ -147,6 +147,9 @@ struct ldap_config uid_t ldc_nss_min_uid; /* the regular expression to determine valid names */ regex_t validnames; + /* whether password changing should be denied and user prompted with + this message */ + char *pam_password_prohibit_message; }; /* this is a pointer to the global configuration, it should be available diff --git a/nslcd/common.h b/nslcd/common.h index bd30fee..1938c9f 100644 --- a/nslcd/common.h +++ b/nslcd/common.h @@ -182,6 +182,7 @@ void shadow_init(void); /* these are the different functions that handle the database specific actions, see nslcd.h for the action descriptions */ +int nslcd_config_get(TFILE *fp,MYLDAP_SESSION *session); int nslcd_alias_byname(TFILE *fp,MYLDAP_SESSION *session); int nslcd_alias_all(TFILE *fp,MYLDAP_SESSION *session); int nslcd_ether_byname(TFILE *fp,MYLDAP_SESSION *session); diff --git a/nslcd/config.c b/nslcd/config.c new file mode 100644 index 0000000..d493abc --- /dev/null +++ b/nslcd/config.c @@ -0,0 +1,61 @@ +/* + config.c - pam processing routines + + Copyright (C) 2012 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 <unistd.h> + +#include "common.h" +#include "log.h" +#include "cfg.h" + +int nslcd_config_get(TFILE *fp,MYLDAP_SESSION *session) +{ + int32_t tmpint32; + int32_t cfgopt; + /* read request parameters */ + READ_INT32(fp,cfgopt); + /* log call */ + log_setrequest("config=%d",(int)cfgopt); + log_log(LOG_DEBUG,"nslcd_config_get(%d)",(int)cfgopt); + /* write the response header */ + WRITE_INT32(fp,NSLCD_VERSION); + WRITE_INT32(fp,NSLCD_ACTION_CONFIG_GET); + WRITE_INT32(fp,NSLCD_RESULT_BEGIN); + /* validate request */ + switch (cfgopt) + { + case NSLCD_CONFIG_PAM_PASSWORD_PROHIBIT_MESSAGE: + WRITE_STRING(fp,nslcd_cfg->pam_password_prohibit_message); + break; + default: + /* all other config options are ignored */ + break; + } + WRITE_INT32(fp,NSLCD_RESULT_END); + return 0; +} diff --git a/nslcd/nslcd.c b/nslcd/nslcd.c index 732775c..773d6db 100644 --- a/nslcd/nslcd.c +++ b/nslcd/nslcd.c @@ -413,6 +413,7 @@ static void handleconnection(int sock,MYLDAP_SESSION *session) /* handle request */ switch (action) { + case NSLCD_ACTION_CONFIG_GET: (void)nslcd_config_get(fp,session); break; case NSLCD_ACTION_ALIAS_BYNAME: (void)nslcd_alias_byname(fp,session); break; case NSLCD_ACTION_ALIAS_ALL: (void)nslcd_alias_all(fp,session); break; case NSLCD_ACTION_ETHER_BYNAME: (void)nslcd_ether_byname(fp,session); break; diff --git a/nslcd/pam.c b/nslcd/pam.c index bcc5d4f..cef908d 100644 --- a/nslcd/pam.c +++ b/nslcd/pam.c @@ -647,6 +647,18 @@ int nslcd_pam_pwmod(TFILE *fp,MYLDAP_SESSION *session,uid_t calleruid) } return -1; } + /* check if pam_password_prohibit_message is set */ + if (nslcd_cfg->pam_password_prohibit_message!=NULL) + { + 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); + return 0; + } /* check if the the user passed the rootpwmoddn */ if (asroot) { @@ -363,6 +363,18 @@ static int nslcd_request_pwmod(pam_handle_t *pamh,struct pld_ctx *ctx,struct pld READ_BUF_STRING(fp,ctx->authzmsg);) } +static int nslcd_request_config_get(pam_handle_t *pamh,struct pld_ctx *ctx,struct pld_cfg *cfg, + int cfgopt,char **value) +{ + PAM_REQUEST(NSLCD_ACTION_CONFIG_GET, + /* log debug message */ + pam_syslog(pamh,LOG_DEBUG,"nslcd request config (%d)",cfgopt), + /* write the request parameter */ + WRITE_INT32(fp,cfgopt), + /* read the result entry */ + READ_BUF_STRING(fp,*value);) +} + /* remap the return code based on the configuration */ static int remap_pam_rc(int rc,struct pld_cfg *cfg) { @@ -550,6 +562,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc,const char **argv) struct pld_ctx *ctx; const char *username,*service; const char *oldpassword=NULL,*newpassword=NULL; + char *prohibit_message; struct passwd *pwent; uid_t myuid; /* set up configuration */ @@ -557,6 +570,16 @@ int pam_sm_chauthtok(pam_handle_t *pamh,int flags,int argc,const char **argv) rc=init(pamh,&cfg,&ctx,&username,&service); 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')) + { + /* we silently ignore errors to get the configuration option */ + pam_syslog(pamh,LOG_NOTICE,"password change prohibited: %s; user=%s",prohibit_message,username); + if (!cfg.no_warn) + pam_error(pamh,"%s",prohibit_message); + return remap_pam_rc(PAM_PERM_DENIED,&cfg); + } /* see if we are dealing with an LDAP user first */ if (ctx->dn==NULL) { |