diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2010-12-12 23:45:21 +0100 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2010-12-12 23:45:21 +0100 |
commit | 38b08af090769450018505a8547377709b93a9f6 (patch) | |
tree | 33ed5127dd8c8595151cc320895457f871199091 | |
parent | 7d9baf67b727c7b50c3666721821e38485d76332 (diff) | |
parent | 42490ca4bab185ac92db5203235ed7515111731a (diff) |
merge changes from trunk
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd-solaris@1329 ef36b2f9-881f-0410-afb5-c4e39611909c
-rw-r--r-- | compat/ldap_compat.h | 4 | ||||
-rw-r--r-- | configure.ac | 3 | ||||
-rw-r--r-- | debian/nslcd.config | 148 | ||||
-rw-r--r-- | debian/nslcd.postinst | 92 | ||||
-rw-r--r-- | debian/nslcd.templates | 76 | ||||
-rw-r--r-- | nslcd/alias.c | 7 | ||||
-rw-r--r-- | nslcd/common.h | 14 | ||||
-rw-r--r-- | nslcd/ether.c | 11 | ||||
-rw-r--r-- | nslcd/group.c | 19 | ||||
-rw-r--r-- | nslcd/host.c | 11 | ||||
-rw-r--r-- | nslcd/log.c | 45 | ||||
-rw-r--r-- | nslcd/log.h | 8 | ||||
-rw-r--r-- | nslcd/myldap.c | 45 | ||||
-rw-r--r-- | nslcd/myldap.h | 5 | ||||
-rw-r--r-- | nslcd/netgroup.c | 4 | ||||
-rw-r--r-- | nslcd/network.c | 11 | ||||
-rw-r--r-- | nslcd/nslcd.c | 58 | ||||
-rw-r--r-- | nslcd/pam.c | 109 | ||||
-rw-r--r-- | nslcd/passwd.c | 17 | ||||
-rw-r--r-- | nslcd/protocol.c | 11 | ||||
-rw-r--r-- | nslcd/rpc.c | 11 | ||||
-rw-r--r-- | nslcd/service.c | 11 | ||||
-rw-r--r-- | nslcd/shadow.c | 7 | ||||
-rw-r--r-- | pam/Makefile.am | 2 | ||||
-rw-r--r-- | pam/pam.c | 5 | ||||
-rw-r--r-- | tests/test_myldap.c | 2 |
26 files changed, 505 insertions, 231 deletions
diff --git a/compat/ldap_compat.h b/compat/ldap_compat.h index 15040c9..983cce6 100644 --- a/compat/ldap_compat.h +++ b/compat/ldap_compat.h @@ -57,5 +57,9 @@ int ldap_passwd_s(LDAP *ld,struct berval *user,struct berval *oldpw, LDAPControl **sctrls,LDAPControl **cctrls); #endif /* not HAVE_LDAP_PASSWD_S */ +/* compatibility definition */ +#ifndef LDAP_SASL_QUIET +#define LDAP_SASL_QUIET 2U +#endif /* not LDAP_SASL_QUIET */ #endif /* COMPAT__LDAP_COMPAT_H */ diff --git a/configure.ac b/configure.ac index 2d96f6d..e47926b 100644 --- a/configure.ac +++ b/configure.ac @@ -227,6 +227,7 @@ if test "x$NSS_LDAP_SONAME" = "xauto" then case "$target_os" in solaris*) NSS_LDAP_SONAME="nss_ldap.so.1" ;; + freebsd*) NSS_LDAP_SONAME="nss_ldap.so" ;; *) NSS_LDAP_SONAME="libnss_ldap.so.2" ;; esac fi @@ -438,7 +439,7 @@ then fi ;; *) - nss_ldap_so_LDFLAGS="-shared -Wl,-h,\$(NSS_LDAP_SONAME) -Wl,--version-script,\$(srcdir)/exports.glibc" + nss_ldap_so_LDFLAGS="-shared -Wl,-h,\$(NSS_LDAP_SONAME) -Wl,--version-script,\$(srcdir)/exports.$with_nss_flavour" ;; esac AC_SUBST(nss_ldap_so_LDFLAGS) diff --git a/debian/nslcd.config b/debian/nslcd.config index 2ac2a38..933c5e3 100644 --- a/debian/nslcd.config +++ b/debian/nslcd.config @@ -20,6 +20,23 @@ db_capb backup # default. # +# read a configuration value from the specified file +# (it takes care in not overwriting a previously written value) +read_config() +{ + debconf_param="$1" + cfg_param="$2" + # get debconf value to ensure we don't overwrite an already set value + db_get "$debconf_param" + if [ -z "$RET" ] + then + value=`sed -n 's/^'"$cfg_param"'[[:space:]]*\([^[:space:]].*[^[:space:]]\)[[:space:]]*$/\1/ip' "$cfgfile" | tail -n 1` + [ -n "$value" ] && db_set "$debconf_param" "$value" + fi + # we're done + return 0 +} + # check the system (non-LDAP configuration files) for some # reasonable defaults parsesys() @@ -91,27 +108,16 @@ parsecfg() fi [ -n "$uris" ] && db_set nslcd/ldap-uris "$uris" fi - # find base config - db_get nslcd/ldap-base - if [ -z "$RET" ] - then - searchbase=`sed -n 's/^base[[:space:]]*\([^[:space:]]*\)[[:space:]]*$/\1/ip' "$cfgfile" | tail -n 1` - [ -n "$searchbase" ] && db_set nslcd/ldap-base "$searchbase" - fi - # find binddn - db_get nslcd/ldap-binddn - if [ -z "$RET" ] - then - binddn=`sed -n 's/^binddn[[:space:]]*//ip' "$cfgfile" | tail -n 1` - db_set nslcd/ldap-binddn "$binddn" - fi - # find bindpw - db_get nslcd/ldap-bindpw - if [ -z "$RET" ] - then - bindpw=`sed -n 's/^bindpw[[:space:]]*//ip' "$cfgfile" | tail -n 1` - db_set nslcd/ldap-bindpw "$bindpw" - fi + # read simple options + read_config nslcd/ldap-base base + read_config nslcd/ldap-binddn binddn + read_config nslcd/ldap-bindpw bindpw + read_config nslcd/ldap-sasl-mech sasl_mech + read_config nslcd/ldap-sasl-realm sasl_realm + read_config nslcd/ldap-sasl-authcid sasl_authcid + read_config nslcd/ldap-sasl-authzid sasl_authzid + read_config nslcd/ldap-sasl-secprops sasl_secprops + read_config nslcd/ldap-sasl-krb5-ccname krb5_ccname # check ssl option db_get nslcd/ldap-starttls if [ -z "$RET" ] @@ -146,7 +152,13 @@ then db_set nslcd/ldap-base "" db_set nslcd/ldap-binddn "" db_set nslcd/ldap-bindpw "" + db_set nslcd/ldap-sasl-mech "" + db_set nslcd/ldap-sasl-realm "" + db_set nslcd/ldap-sasl-authcid "" + db_set nslcd/ldap-sasl-authzid "" + db_set nslcd/ldap-sasl-secprops "" db_set nslcd/ldap-starttls "" + db_set nslcd/ldap-reqcert "" # parse current configuration parsecfg "$CONFFILE" else @@ -160,13 +172,28 @@ else db_get nslcd/ldap-uris [ -z "$RET" ] && db_set nslcd/ldap-uris "ldap://127.0.0.1/" db_get nslcd/ldap-base - [ -z "$RET" ] && db_set nslcd/ldap-base "dc=example,dc=net/" + [ -z "$RET" ] && db_set nslcd/ldap-base "dc=example,dc=net" fi # fallback for starttls option db_get nslcd/ldap-starttls [ -z "$RET" ] && db_set nslcd/ldap-starttls "false" +# deduce auth-type from available information +db_get nslcd/ldap-sasl-mech +sasl_mech="$RET" +db_get nslcd/ldap-binddn +binddn="$RET" +if [ -n "$sasl_mech" ] +then + db_set nslcd/ldap-auth-type "SASL" +elif [ -n "$binddn" ] +then + db_set nslcd/ldap-auth-type "simple" +else + db_set nslcd/ldap-auth-type "none" +fi + # # This is the second part of the script. In this part the configurable # settings will be presented to the user for approval. The postinst @@ -182,31 +209,76 @@ do db_input high nslcd/ldap-uris || true db_input high nslcd/ldap-base || true # ask the questions, go to the next question or exit - state="binddn" + state="authtype" db_go || exit 1 # TODO: add error checking on options ;; - binddn) - # ask for login information - db_input medium nslcd/ldap-binddn || true + authtype) + # ask for authentication type + db_input medium nslcd/ldap-auth-type || true # ask the question, go to the next question or back - state="bindpw" + state="authentication" db_go || state="server" ;; - bindpw) - # only ask question if we have a binddn - db_get nslcd/ldap-binddn - if [ -n "$RET" ] + authentication) + # check which questions to ask, depending on the authentication type + db_get nslcd/ldap-auth-type + case "$RET" in + none) + # anonymous bind, nothing to ask (clear options) + db_set nslcd/ldap-binddn "" + db_set nslcd/ldap-bindpw "" + db_set nslcd/ldap-sasl-mech "" + state="starttls" + ;; + simple) + # ask for binddn and bindpw + db_input medium nslcd/ldap-binddn || true + db_input medium nslcd/ldap-bindpw || true + db_set nslcd/ldap-sasl-mech "" + state="starttls" + ;; + SASL) + # ask about SASL mechanism (other SASL questions depend on this) + db_input medium nslcd/ldap-sasl-mech || true + # RFC4313 if SASL, binddn should be disabled + db_set nslcd/ldap-binddn "" + state="sasloptions" + ;; + *) + exit 1 + ;; + esac + db_go || state="authtype" + ;; + sasloptions) + # get SASL mech + db_get nslcd/ldap-sasl-mech + sasl_mech="$RET" + # ask SASL questions + db_input medium nslcd/ldap-sasl-realm || true + if [ "$sasl_mech" != "GSSAPI" ] then - # ask for login information + db_input medium nslcd/ldap-sasl-authcid || true db_input medium nslcd/ldap-bindpw || true else - # clear password + db_set nslcd/ldap-sasl-authcid "" db_set nslcd/ldap-bindpw "" fi + db_input medium nslcd/ldap-sasl-authzid || true + db_input medium nslcd/ldap-sasl-secprops || true + if [ "$sasl_mech" = "GSSAPI" ] + then + # have a default for ldap-sasl-krb5-ccname + db_get nslcd/ldap-sasl-krb5-ccname + [ -z "$RET" ] && db_set nslcd/ldap-sasl-krb5-ccname "/var/run/nslcd/nslcd.tkt" + db_input low nslcd/ldap-sasl-krb5-ccname || true + else + db_set nslcd/ldap-sasl-krb5-ccname "" + fi # ask the question, go to the next question or back state="starttls" - db_go || state="binddn" + db_go || state="authentication" ;; starttls) # check if ldaps:// URL's are used @@ -221,8 +293,9 @@ do db_input medium nslcd/ldap-starttls || true fi # ask the question, go to the next question or back + # (we go back to authtype because the previous questions were optional) state="reqcert" - db_go || state="bindpw" + db_go || state="authtype" ;; reqcert) # check if ldaps:// URL's are used @@ -235,10 +308,13 @@ do then # ask whether to do certificate validation db_input high nslcd/ldap-reqcert || true + else + db_set nslcd/ldap-reqcert "" fi # ask the question, go to the next question or back + # (we go back to authtype because the previous questions were optional) state="done" - db_go || state="starttls" + db_go || state="authtype" ;; esac done diff --git a/debian/nslcd.postinst b/debian/nslcd.postinst index 358d749..53f54fc 100644 --- a/debian/nslcd.postinst +++ b/debian/nslcd.postinst @@ -45,6 +45,11 @@ cfg_set() cfg_disable() { parameter="$1" + # handle bindpw option specially by removing value from config first + if [ "$parameter" = "bindpw" ] && grep -i -q "^bindpw " $CONFFILE + then + cfg_set bindpw "*removed*" + fi # make matching of spaces better in parameter param_re=`echo "$parameter" | sed 's#^#[[:space:]]*#;s#[[:space:]][[:space:]]*#[[:space:]][[:space:]]*#g'` # lines to not match @@ -135,6 +140,21 @@ EOM return 0 } +# update a configuration parameter, based on the debconf key +update_config() +{ + debconf_param="$1" + cfg_param="$2" + # update configuration option based on debconf value + db_get "$debconf_param" + if [ -n "$RET" ] + then + cfg_set "$cfg_param" "$RET" + else + cfg_disable "$cfg_param" + fi +} + # real functions begin here if [ "$1" = "configure" ] then @@ -162,43 +182,32 @@ then fi # create a default configuration create_config - # set server uri - db_get nslcd/ldap-uris - cfg_uris "$RET" - # set search base - db_get nslcd/ldap-base - if [ -n "$RET" ] + # rename tls_checkpeer to tls_reqcert + if grep -qi '^tls_checkpeer[[:space:]]' $CONFFILE then - cfg_set base "$RET" - else - cfg_disable base + echo "Renaming tls_checkpeer to tls_reqcert in $CONFFILE..." >&2 + sed -i 's/^tls_checkpeer[[:space:]]/tls_reqcert /' "$CONFFILE" fi - # set bind dn/pw - db_get nslcd/ldap-binddn - if [ -n "$RET" ] + # rename reconnect_maxsleeptime to reconnect_retrytime + if grep -qi '^reconnect_maxsleeptime[[:space:]]' $CONFFILE then - cfg_set binddn "$RET" - db_get nslcd/ldap-bindpw - if [ -n "$RET" ] - then - cfg_set bindpw "$RET" - else - # no bindpw set - if grep -i -q "^bindpw " $CONFFILE - then - cfg_set bindpw "*removed*" - cfg_disable bindpw - fi - fi - else - # no binddn/pw, disable options - cfg_disable binddn - if grep -i -q "^bindpw " $CONFFILE - then - cfg_set bindpw "*removed*" - cfg_disable bindpw - fi + echo "Renaming reconnect_maxsleeptime to reconnect_retrytime in $CONFFILE..." >&2 + sed -i 's/^reconnect_maxsleeptime[[:space:]]/reconnect_retrytime /' "$CONFFILE" fi + # set server uri + db_get nslcd/ldap-uris + cfg_uris "$RET" + # update some options + update_config nslcd/ldap-base base + update_config nslcd/ldap-binddn binddn + update_config nslcd/ldap-bindpw bindpw + update_config nslcd/ldap-sasl-mech sasl_mech + update_config nslcd/ldap-sasl-realm sasl_realm + update_config nslcd/ldap-sasl-authcid sasl_authcid + update_config nslcd/ldap-sasl-authzid sasl_authzid + update_config nslcd/ldap-sasl-secprops sasl_secprops + update_config nslcd/ldap-sasl-krb5-ccname krb5_ccname + update_config nslcd/ldap-reqcert tls_reqcert # remove password from database db_set nslcd/ldap-bindpw "" # set ssl option @@ -210,25 +219,8 @@ then then cfg_disable ssl fi - # set tls_reqcert option - db_get nslcd/ldap-reqcert - if [ -n "$RET" ] - then - # rename any tls_checkpeer options - sed -i 's/^tls_checkpeer/tls_reqcert/i' "$CONFFILE" - # set tls_reqcert option - cfg_set tls_reqcert "$RET" - # clear debconf value so that this option is only set if the question is asked - db_set nslcd/ldap-reqcert "" - fi # we're done db_stop - # rename reconnect_maxsleeptime to reconnect_retrytime - if grep -qi '^reconnect_maxsleeptime[[:space:]]' $CONFFILE - then - echo "Renaming reconnect_maxsleeptime to reconnect_retrytime in $CONFFILE..." >&2 - sed -i 's/^reconnect_maxsleeptime[[:space:]]/reconnect_retrytime /' "$CONFFILE" - fi # fix permissions of configfile if upgrading from an old version if dpkg --compare-versions "$2" lt-nl "0.6.7.1" then diff --git a/debian/nslcd.templates b/debian/nslcd.templates index 0c0cc82..874a348 100644 --- a/debian/nslcd.templates +++ b/debian/nslcd.templates @@ -18,19 +18,87 @@ _Description: LDAP server search base: domain "example.net" would use "dc=example,dc=net" as the distinguished name of the search base. +Template: nslcd/ldap-auth-type +Type: select +__Choices: none, simple, SASL +Default: none +_Description: LDAP authentication to use: + If your LDAP database requires authentication you can choose which mechanism + should be used. Please choose the mechanism by which authentication should + be done: + * none: no authentication; + * simple: simple clear text binddn/password; + * SASL: one of the Simple Authentication and Security Layer + mechanisms. + Template: nslcd/ldap-binddn Type: string _Description: LDAP database user: - If the LDAP database requires a login for normal lookups, enter the name of - the account that will be used here. Leave it empty otherwise. - . - This value should be specified as a DN (distinguished name). + Enter the name of the account that will be used to log in to the LDAP + database. This value should be specified as a DN (distinguished name). Template: nslcd/ldap-bindpw Type: password _Description: LDAP user password: Enter the password that will be used to log in to the LDAP database. +Template: nslcd/ldap-sasl-mech +Type: select +__Choices: auto, LOGIN, PLAIN, NTLM, CRAM-MD5, DIGEST-MD5, GSSAPI, OTP +_Description: SASL mechanism to use: + Choose the SASL mechanism that will be used to authenticate to the LDAP + database: + * auto: autonegociation; + * LOGIN: deprecated in flavor of PLAIN; + * PLAIN: simple cleartext password mechanism; + * NTLM: NT LAN Manager authentication mechanism; + * CRAM-MD5: challenge-response scheme based on HMAC-MD5; + * DIGEST-MD5: HTTP Digest compatible challenge-response scheme; + * GSSAPI: used for Kerberos; + * OTP: a One Time Password mechanism. + +Template: nslcd/ldap-sasl-realm +Type: string +_Description: SASL realm: + Enter the SASL realm that will be used to authenticate to the LDAP + database. + . + If empty, the GSSAPI mechanism will use information from the Kerberos + credential cache. Others mechanisms may need @<REALM> suffixing sasl_authcid + and sasl_authzid. + . + The realm is appended to authentication and authorisation identities. + +Template: nslcd/ldap-sasl-authcid +Type: string +_Description: SASL authentication identity: + Enter the SASL authentication identity that will be used to authenticate to + the LDAP database. + . + This is the login used in LOGIN, PLAIN, CRAM-MD5 and DIGEST-MD5 mechanisms. + +Template: nslcd/ldap-sasl-authzid +Type: string +_Description: SASL proxy authorisation identity: + Enter the proxy authorisation identity that will be used to authenticate to + the LDAP database. + . + This is the object in the name of witch the LDAP request are done. + This value should be specified as a DN (distinguished name). + +Template: nslcd/ldap-sasl-secprops +Type: string +_Description: Cyrus SASL security properties: + Enter the Cyrus SASL security properties. + Allowed values are described in the ldap.conf(5) manual page + in the SASL OPTIONS section. + +Template: nslcd/ldap-sasl-krb5-ccname +Type: string +Default: /var/run/nslcd/nslcd.tkt +_Description: Kerberos credential cache file path: + Enter the GSSAPI/Kerberos credential cache file name that will be used. + Template: nslcd/ldap-starttls Type: boolean _Description: Use StartTLS? diff --git a/nslcd/alias.c b/nslcd/alias.c index e4d15d0..f20537c 100644 --- a/nslcd/alias.c +++ b/nslcd/alias.c @@ -123,8 +123,8 @@ NSLCD_HANDLE( alias,byname, char name[256]; char filter[1024]; - READ_STRING(fp,name);, - log_log(LOG_DEBUG,"nslcd_alias_byname(%s)",name);, + READ_STRING(fp,name); + log_setrequest("alias=\"%s\"",name);, NSLCD_ACTION_ALIAS_BYNAME, mkfilter_alias_byname(name,filter,sizeof(filter)), write_alias(fp,entry,name) @@ -133,8 +133,7 @@ NSLCD_HANDLE( NSLCD_HANDLE( alias,all, const char *filter; - /* no parameters to read */, - log_log(LOG_DEBUG,"nslcd_alias_all()");, + log_setrequest("alias(all)");, NSLCD_ACTION_ALIAS_ALL, (filter=alias_filter,0), write_alias(fp,entry,NULL) diff --git a/nslcd/common.h b/nslcd/common.h index a7cc18a..90e9b10 100644 --- a/nslcd/common.h +++ b/nslcd/common.h @@ -89,7 +89,7 @@ MUST_USE char *lookup_dn2uid(MYLDAP_SESSION *session,const char *dn,int *rcp,cha MUST_USE char *dn2uid(MYLDAP_SESSION *session,const char *dn,char *buf,size_t buflen); /* use the user id to lookup an LDAP entry */ -MYLDAP_ENTRY *uid2entry(MYLDAP_SESSION *session,const char *uid); +MYLDAP_ENTRY *uid2entry(MYLDAP_SESSION *session,const char *uid,int *rcp); /* transforms the uid into a DN by doing an LDAP lookup */ MUST_USE char *uid2dn(MYLDAP_SESSION *session,const char *uid,char *buf,size_t buflen); @@ -147,13 +147,13 @@ int nslcd_pam_sess_c(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) \ +#define NSLCD_HANDLE(db,fn,readfn,action,mkfilter,writefn) \ int nslcd_##db##_##fn(TFILE *fp,MYLDAP_SESSION *session) \ - NSLCD_HANDLE_BODY(db,fn,readfn,logcall,action,mkfilter,writefn) -#define NSLCD_HANDLE_UID(db,fn,readfn,logcall,action,mkfilter,writefn) \ + NSLCD_HANDLE_BODY(db,fn,readfn,action,mkfilter,writefn) +#define NSLCD_HANDLE_UID(db,fn,readfn,action,mkfilter,writefn) \ int nslcd_##db##_##fn(TFILE *fp,MYLDAP_SESSION *session,uid_t calleruid) \ - NSLCD_HANDLE_BODY(db,fn,readfn,logcall,action,mkfilter,writefn) -#define NSLCD_HANDLE_BODY(db,fn,readfn,logcall,action,mkfilter,writefn) \ + NSLCD_HANDLE_BODY(db,fn,readfn,action,mkfilter,writefn) +#define NSLCD_HANDLE_BODY(db,fn,readfn,action,mkfilter,writefn) \ { \ /* define common variables */ \ int32_t tmpint32; \ @@ -163,8 +163,6 @@ int nslcd_pam_pwmod(TFILE *fp,MYLDAP_SESSION *session,uid_t calleruid); int rc,i; \ /* read request parameters */ \ readfn; \ - /* log call */ \ - logcall; \ /* write the response header */ \ WRITE_INT32(fp,NSLCD_VERSION); \ WRITE_INT32(fp,action); \ diff --git a/nslcd/ether.c b/nslcd/ether.c index aef2b59..9176095 100644 --- a/nslcd/ether.c +++ b/nslcd/ether.c @@ -165,8 +165,8 @@ NSLCD_HANDLE( ether,byname, char name[256]; char filter[1024]; - READ_STRING(fp,name);, - log_log(LOG_DEBUG,"nslcd_ether_byname(%s)",name);, + READ_STRING(fp,name); + log_setrequest("ether=\"%s\"",name);, NSLCD_ACTION_ETHER_BYNAME, mkfilter_ether_byname(name,filter,sizeof(filter)), write_ether(fp,entry,name,NULL) @@ -179,8 +179,8 @@ NSLCD_HANDLE( char filter[1024]; READ_TYPE(fp,addr,uint8_t[6]); if (ether_ntoa_r(&addr,ether)==NULL) - return -1;, - log_log(LOG_DEBUG,"nslcd_ether_byether(%s)",ether);, + return -1; + log_setrequest("ether=%s",ether);, NSLCD_ACTION_ETHER_BYETHER, mkfilter_ether_byether(&addr,filter,sizeof(filter)), write_ether(fp,entry,NULL,ether) @@ -189,8 +189,7 @@ NSLCD_HANDLE( NSLCD_HANDLE( ether,all, const char *filter; - /* no parameters to read */, - log_log(LOG_DEBUG,"nslcd_ether_all()");, + log_setrequest("ether(all)");, NSLCD_ACTION_ETHER_ALL, (filter=ether_filter,0), write_ether(fp,entry,NULL,NULL) diff --git a/nslcd/group.c b/nslcd/group.c index afbd904..baf367e 100644 --- a/nslcd/group.c +++ b/nslcd/group.c @@ -282,11 +282,11 @@ NSLCD_HANDLE( char name[256]; char filter[1024]; READ_STRING(fp,name); + log_setrequest("group=\"%s\"",name); if (!isvalidname(name)) { - log_log(LOG_WARNING,"nslcd_group_byname(%s): invalid group name",name); + log_log(LOG_WARNING,"\"%s\": invalid group name",name); return -1; }, - log_log(LOG_DEBUG,"nslcd_group_byname(%s)",name);, NSLCD_ACTION_GROUP_BYNAME, mkfilter_group_byname(name,filter,sizeof(filter)), write_group(fp,entry,name,NULL,1,session) @@ -296,8 +296,8 @@ NSLCD_HANDLE( group,bygid, gid_t gid; char filter[1024]; - READ_TYPE(fp,gid,gid_t);, - log_log(LOG_DEBUG,"nslcd_group_bygid(%d)",(int)gid);, + READ_TYPE(fp,gid,gid_t); + log_setrequest("group=%d",(int)gid);, NSLCD_ACTION_GROUP_BYGID, mkfilter_group_bygid(gid,filter,sizeof(filter)), write_group(fp,entry,NULL,&gid,1,session) @@ -308,20 +308,22 @@ NSLCD_HANDLE( char name[256]; char filter[1024]; READ_STRING(fp,name); - if (!isvalidname(name)) { - log_log(LOG_WARNING,"nslcd_group_bymember(%s): invalid user name",name); + log_setrequest("group/member=\"%s\"",name); + if (!isvalidname(name)) + { + log_log(LOG_WARNING,"\"%s\": invalid user name",name); return -1; } if ((nslcd_cfg->ldc_nss_initgroups_ignoreusers!=NULL)&& set_contains(nslcd_cfg->ldc_nss_initgroups_ignoreusers,name)) { + log_log(LOG_DEBUG,"ignored group member"); /* just end the request, returning no results */ WRITE_INT32(fp,NSLCD_VERSION); WRITE_INT32(fp,NSLCD_ACTION_GROUP_BYMEMBER); WRITE_INT32(fp,NSLCD_RESULT_END); return 0; }, - log_log(LOG_DEBUG,"nslcd_group_bymember(%s)",name);, NSLCD_ACTION_GROUP_BYMEMBER, mkfilter_group_bymember(session,name,filter,sizeof(filter)), write_group(fp,entry,NULL,NULL,0,session) @@ -330,8 +332,7 @@ NSLCD_HANDLE( NSLCD_HANDLE( group,all, const char *filter; - /* no parameters to read */, - log_log(LOG_DEBUG,"nslcd_group_all()");, + log_setrequest("group(all)");, NSLCD_ACTION_GROUP_ALL, (filter=group_filter,0), write_group(fp,entry,NULL,NULL,1,session) diff --git a/nslcd/host.c b/nslcd/host.c index e166889..3ae5b12 100644 --- a/nslcd/host.c +++ b/nslcd/host.c @@ -155,8 +155,8 @@ NSLCD_HANDLE( host,byname, char name[256]; char filter[1024]; - READ_STRING(fp,name);, - log_log(LOG_DEBUG,"nslcd_host_byname(%s)",name);, + READ_STRING(fp,name); + log_setrequest("host=\"%s\"",name);, NSLCD_ACTION_HOST_BYNAME, mkfilter_host_byname(name,filter,sizeof(filter)), write_host(fp,entry) @@ -175,8 +175,8 @@ NSLCD_HANDLE( { log_log(LOG_WARNING,"unable to convert address to string"); return -1; - }, - log_log(LOG_DEBUG,"nslcd_host_byaddr(%s)",name);, + } + log_setrequest("host=%s",name);, NSLCD_ACTION_HOST_BYADDR, mkfilter_host_byaddr(name,filter,sizeof(filter)), write_host(fp,entry) @@ -185,8 +185,7 @@ NSLCD_HANDLE( NSLCD_HANDLE( host,all, const char *filter; - /* no parameters to read */, - log_log(LOG_DEBUG,"nslcd_host_all()");, + log_setrequest("host(all)");, NSLCD_ACTION_HOST_ALL, (filter=host_filter,0), write_host(fp,entry) diff --git a/nslcd/log.c b/nslcd/log.c index 2600779..6206d61 100644 --- a/nslcd/log.c +++ b/nslcd/log.c @@ -1,7 +1,7 @@ /* log.c - logging funtions - Copyright (C) 2002, 2003, 2008 Arthur de Jong + Copyright (C) 2002, 2003, 2008, 2010 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 @@ -56,6 +56,11 @@ static int prelogging_loglevel=LOG_INFO; static __thread char *sessionid=NULL; +/* the request identifier that is set for this thread */ +static __thread char *requestid=NULL; +#define MAX_REQUESTID_LENGTH 40 + + /* set loglevel when no logging is configured */ void log_setdefaultloglevel(int loglevel) { @@ -144,6 +149,32 @@ void log_newsession(void) } } sprintf(sessionid,"%06x",(int)(rand()&0xffffff)); + /* set the request id to empty */ + if (requestid!=NULL) + requestid[0]='\0'; +} + + +/* indicate that a request identifier should be included in the output + from this point on, until log_newsession() is called */ +void log_setrequest(const char *format, ...) +{ + va_list ap; + /* ensure that requestid can hold a string */ + if (requestid==NULL) + { + requestid=(char *)malloc(MAX_REQUESTID_LENGTH); + if (requestid==NULL) + { + fprintf(stderr,"malloc() failed: %s",strerror(errno)); + return; /* silently fail */ + } + } + /* make the message */ + va_start(ap,format); + vsnprintf(requestid,MAX_REQUESTID_LENGTH,format,ap); + requestid[MAX_REQUESTID_LENGTH-1]='\0'; + va_end(ap); } @@ -174,7 +205,9 @@ void log_log(int pri,const char *format, ...) /* if logging is not yet defined, log to stderr */ if (pri<=prelogging_loglevel) { - if (sessionid) + if ((requestid!=NULL)&&(requestid[0]!='\0')) + fprintf(stderr,"%s: [%s] <%s> %s%s\n",PACKAGE,sessionid,requestid,pri==LOG_DEBUG?"DEBUG: ":"",buffer); + else if (sessionid) fprintf(stderr,"%s: [%s] %s%s\n",PACKAGE,sessionid,pri==LOG_DEBUG?"DEBUG: ":"",buffer); else fprintf(stderr,"%s: %s%s\n",PACKAGE,pri==LOG_DEBUG?"DEBUG: ":"",buffer); @@ -188,14 +221,18 @@ void log_log(int pri,const char *format, ...) { if (lst->fp==NULL) /* syslog */ { - if (sessionid) + if ((requestid!=NULL)&&(requestid[0]!='\0')) + syslog(pri,"[%s] <%s> %s",sessionid,requestid,buffer); + else if (sessionid) syslog(pri,"[%s] %s",sessionid,buffer); else syslog(pri,"%s",buffer); } else /* file */ { - if (sessionid) + if ((requestid!=NULL)&&(requestid[0]!='\0')) + fprintf(lst->fp,"%s: [%s] <%s> %s\n",sessionid,requestid,PACKAGE,buffer); + else if (sessionid) fprintf(lst->fp,"%s: [%s] %s\n",sessionid,PACKAGE,buffer); else fprintf(lst->fp,"%s: %s\n",PACKAGE,buffer); diff --git a/nslcd/log.h b/nslcd/log.h index 3fa3d23..a979fb2 100644 --- a/nslcd/log.h +++ b/nslcd/log.h @@ -1,7 +1,7 @@ /* log.h - definitions of logging funtions - Copyright (C) 2002, 2003, 2007, 2008 Arthur de Jong + Copyright (C) 2002, 2003, 2007, 2008, 2010 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 @@ -54,6 +54,12 @@ void log_startlogging(void); void log_newsession(void); +/* indicate that a request identifier should be included in the output + from this point on, until log_newsession() is called */ +void log_setrequest(const char *format, ...) + LIKE_PRINTF(1,2); + + /* log the given message using the configured logging method */ void log_log(int pri,const char *format, ...) LIKE_PRINTF(2,3); diff --git a/nslcd/myldap.c b/nslcd/myldap.c index 92f0154..fb0f617 100644 --- a/nslcd/myldap.c +++ b/nslcd/myldap.c @@ -372,8 +372,10 @@ static int do_sasl_interact(LDAP UNUSED(*ld),unsigned UNUSED(flags),void *defaul } /* This function performs the authentication phase of opening a connection. - This returns an LDAP result code. */ -static int do_bind(MYLDAP_SESSION *session,const char *uri) + The binddn and bindpw parameters may be used to override the authentication + mechanism defined in the configuration. This returns an LDAP result + code. */ +static int do_bind(LDAP *ld,const char *binddn,const char *bindpw,const char *uri) { #ifdef LDAP_OPT_X_TLS int rc; @@ -389,7 +391,7 @@ static int do_bind(MYLDAP_SESSION *session,const char *uri) { log_log(LOG_DEBUG,"ldap_start_tls_s()"); errno=0; - rc=ldap_start_tls_s(session->ld,NULL,NULL); + rc=ldap_start_tls_s(ld,NULL,NULL); if (rc!=LDAP_SUCCESS) { log_log(LOG_WARNING,"ldap_start_tls_s() failed: %s%s%s (uri=\"%s\")", @@ -400,12 +402,12 @@ static int do_bind(MYLDAP_SESSION *session,const char *uri) } #endif /* LDAP_OPT_X_TLS */ /* check if the binddn and bindpw are overwritten in the session */ - if (session->binddn[0]!='\0') + if ((binddn!=NULL)&(binddn[0]!='\0')) { /* do a simple bind */ - log_log(LOG_DEBUG,"ldap_simple_bind_s(\"%s\",%s) (uri=\"%s\")",session->binddn, - (session->bindpw[0]!='\0')?"\"***\"":"\"\"",uri); - return ldap_simple_bind_s(session->ld,session->binddn,session->bindpw); + log_log(LOG_DEBUG,"ldap_simple_bind_s(\"%s\",%s) (uri=\"%s\")",binddn, + ((bindpw!=NULL)&&(bindpw[0]!='\0'))?"\"***\"":"\"\"",uri); + return ldap_simple_bind_s(ld,binddn,bindpw); } /* perform SASL bind if requested and available on platform */ #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S @@ -416,7 +418,7 @@ static int do_bind(MYLDAP_SESSION *session,const char *uri) if (nslcd_cfg->ldc_sasl_secprops!=NULL) { log_log(LOG_DEBUG,"ldap_set_option(LDAP_OPT_X_SASL_SECPROPS,\"%s\")",nslcd_cfg->ldc_sasl_secprops); - LDAP_SET_OPTION(session->ld,LDAP_OPT_X_SASL_SECPROPS,(void *)nslcd_cfg->ldc_sasl_secprops); + LDAP_SET_OPTION(ld,LDAP_OPT_X_SASL_SECPROPS,(void *)nslcd_cfg->ldc_sasl_secprops); } #ifdef HAVE_SASL_INTERACT_T if (nslcd_cfg->ldc_binddn!=NULL) @@ -425,7 +427,7 @@ static int do_bind(MYLDAP_SESSION *session,const char *uri) else log_log(LOG_DEBUG,"ldap_sasl_interactive_bind_s(NULL,\"%s\") (uri=\"%s\")", nslcd_cfg->ldc_sasl_mech,uri); - return ldap_sasl_interactive_bind_s(session->ld,nslcd_cfg->ldc_binddn,nslcd_cfg->ldc_sasl_mech,NULL,NULL, + return ldap_sasl_interactive_bind_s(ld,nslcd_cfg->ldc_binddn,nslcd_cfg->ldc_sasl_mech,NULL,NULL, LDAP_SASL_QUIET, do_sasl_interact,(void *)nslcd_cfg); #else /* HAVE_SASL_INTERACT_T */ @@ -447,7 +449,7 @@ static int do_bind(MYLDAP_SESSION *session,const char *uri) log_log(LOG_DEBUG,"ldap_sasl_bind_s(NULL,\"%s\",%s) (uri=\"%s\")", nslcd_cfg->ldc_sasl_mech, nslcd_cfg->ldc_bindpw?"\"***\"":"NULL",uri); - return ldap_sasl_bind_s(session->ld,nslcd_cfg->ldc_binddn,nslcd_cfg->ldc_sasl_mech,&cred,NULL,NULL,NULL); + return ldap_sasl_bind_s(ld,nslcd_cfg->ldc_binddn,nslcd_cfg->ldc_sasl_mech,&cred,NULL,NULL,NULL); #endif /* not HAVE_SASL_INTERACT_T */ } #endif /* HAVE_LDAP_SASL_INTERACTIVE_BIND_S */ @@ -458,18 +460,19 @@ static int do_bind(MYLDAP_SESSION *session,const char *uri) else log_log(LOG_DEBUG,"ldap_simple_bind_s(NULL,%s) (uri=\"%s\")", nslcd_cfg->ldc_bindpw?"\"***\"":"NULL",uri); - return ldap_simple_bind_s(session->ld,nslcd_cfg->ldc_binddn,nslcd_cfg->ldc_bindpw); + return ldap_simple_bind_s(ld,nslcd_cfg->ldc_binddn,nslcd_cfg->ldc_bindpw); } #ifdef HAVE_LDAP_SET_REBIND_PROC /* This function is called by the LDAP library when chasing referrals. It is configured with the ldap_set_rebind_proc() below. */ -static int do_rebind(LDAP UNUSED(*ld),LDAP_CONST char *url, +static int do_rebind(LDAP *ld,LDAP_CONST char *url, ber_tag_t UNUSED(request), ber_int_t UNUSED(msgid),void *arg) { + MYLDAP_SESSION *session=(MYLDAP_SESSION *)arg; log_log(LOG_DEBUG,"rebinding to %s",url); - return do_bind((MYLDAP_SESSION *)arg,url); + return do_bind(ld,session->binddn,session->bindpw,url); } #endif /* HAVE_LDAP_SET_REBIND_PROC */ @@ -600,10 +603,7 @@ static void do_close(MYLDAP_SESSION *session) } } -/* This checks the timeout value of the session and closes the connection - to the LDAP server if the timeout has expired and there are no pending - searches. */ -static void myldap_session_check(MYLDAP_SESSION *session) +void myldap_session_check(MYLDAP_SESSION *session) { int i; time_t current_time; @@ -673,7 +673,8 @@ static int do_open(MYLDAP_SESSION *session) } /* bind to the server */ errno=0; - rc=do_bind(session,nslcd_cfg->ldc_uris[session->current_uri].uri); + rc=do_bind(session->ld,session->binddn,session->bindpw, + nslcd_cfg->ldc_uris[session->current_uri].uri); if (rc!=LDAP_SUCCESS) { /* log actual LDAP error code */ @@ -883,7 +884,7 @@ static int do_retry_search(MYLDAP_SEARCH *search) if ((rc==LDAP_INVALID_CREDENTIALS)||(rc==LDAP_INSUFFICIENT_ACCESS)|| (rc==LDAP_AUTH_METHOD_NOT_SUPPORTED)) dotry[search->session->current_uri]=0; - /* check whether we should try this URI again */ + /* check when we should try this URI again */ else if (t <= (current_uri->firstfail+nslcd_cfg->ldc_reconnect_retrytime)) { t+=nslcd_cfg->ldc_reconnect_sleeptime; @@ -902,8 +903,10 @@ static int do_retry_search(MYLDAP_SEARCH *search) if (nexttry>=endtime) { if (search->session->binddn[0]=='\0') - log_log(LOG_ERR,"no available LDAP server found"); - return rc; + { + log_log(LOG_ERR,"no available LDAP server found: %s",ldap_err2string(rc)); + return LDAP_UNAVAILABLE; + } } /* sleep between tries */ sleeptime=nexttry-time(NULL); diff --git a/nslcd/myldap.h b/nslcd/myldap.h index 0a3bd0b..f7df4a3 100644 --- a/nslcd/myldap.h +++ b/nslcd/myldap.h @@ -76,6 +76,11 @@ void myldap_set_credentials(MYLDAP_SESSION *session,const char *dn, with these searches. This does not close the session. */ void myldap_session_cleanup(MYLDAP_SESSION *session); +/* This checks the timeout value of the session and closes the connection + to the LDAP server if the timeout has expired and there are no pending + searches. */ +void myldap_session_check(MYLDAP_SESSION *session); + /* Close the session and free all the resources allocated for the session. After a call to this function the referenced handle is invalid. */ void myldap_session_close(MYLDAP_SESSION *session); diff --git a/nslcd/netgroup.c b/nslcd/netgroup.c index 298b1ab..27bc531 100644 --- a/nslcd/netgroup.c +++ b/nslcd/netgroup.c @@ -241,8 +241,8 @@ NSLCD_HANDLE( netgroup,byname, char name[256]; char filter[1024]; - READ_STRING(fp,name);, - log_log(LOG_DEBUG,"nslcd_netgroup_byname(%s)",name);, + READ_STRING(fp,name); + log_setrequest("netgroup=\"%s\"",name);, NSLCD_ACTION_NETGROUP_BYNAME, mkfilter_netgroup_byname(name,filter,sizeof(filter)), write_netgroup(fp,entry,name) diff --git a/nslcd/network.c b/nslcd/network.c index 89e0bea..a87f478 100644 --- a/nslcd/network.c +++ b/nslcd/network.c @@ -153,8 +153,8 @@ NSLCD_HANDLE( network,byname, char name[256]; char filter[1024]; - READ_STRING(fp,name);, - log_log(LOG_DEBUG,"nslcd_network_byname(%s)",name);, + READ_STRING(fp,name); + log_setrequest("network=\"%s\"",name);, NSLCD_ACTION_NETWORK_BYNAME, mkfilter_network_byname(name,filter,sizeof(filter)), write_network(fp,entry) @@ -173,8 +173,8 @@ NSLCD_HANDLE( { log_log(LOG_WARNING,"unable to convert address to string"); return -1; - }, - log_log(LOG_DEBUG,"nslcd_network_byaddr(%s)",name);, + } + log_setrequest("network=%s",name);, NSLCD_ACTION_NETWORK_BYADDR, mkfilter_network_byaddr(name,filter,sizeof(filter)), write_network(fp,entry) @@ -183,8 +183,7 @@ NSLCD_HANDLE( NSLCD_HANDLE( network,all, const char *filter; - /* no parameters to read */, - log_log(LOG_DEBUG,"nslcd_network_all()");, + log_setrequest("network(all)");, NSLCD_ACTION_NETWORK_ALL, (filter=network_filter,0), write_network(fp,entry) diff --git a/nslcd/nslcd.c b/nslcd/nslcd.c index 83d4e95..d6bcc32 100644 --- a/nslcd/nslcd.c +++ b/nslcd/nslcd.c @@ -278,6 +278,7 @@ static void exithandler(void) static int create_socket(void) { int sock; + int i; struct sockaddr_un addr; /* create a socket */ if ( (sock=socket(PF_UNIX,SOCK_STREAM,0))<0 ) @@ -291,6 +292,21 @@ static int create_socket(void) log_log(LOG_DEBUG,"unlink() of "NSLCD_SOCKET" failed (ignored): %s", strerror(errno)); } + /* do not block on accept() */ + if ((i=fcntl(sock,F_GETFL,0))<0) + { + log_log(LOG_ERR,"fctnl(F_GETFL) failed: %s",strerror(errno)); + if (close(sock)) + log_log(LOG_WARNING,"problem closing socket: %s",strerror(errno)); + exit(1); + } + if (fcntl(sock,F_SETFL,i|O_NONBLOCK)<0) + { + log_log(LOG_ERR,"fctnl(F_SETFL,O_NONBLOCK) failed: %s",strerror(errno)); + if (close(sock)) + log_log(LOG_WARNING,"problem closing socket: %s",strerror(errno)); + exit(1); + } /* create socket address structure */ memset(&addr,0,sizeof(struct sockaddr_un)); addr.sun_family=AF_UNIX; @@ -520,6 +536,8 @@ static void *worker(void UNUSED(*arg)) int j; struct sockaddr_storage addr; socklen_t alen; + fd_set fds; + struct timeval tv; /* create a new LDAP session */ session=myldap_create_session(); /* clean up the session if we're done */ @@ -527,20 +545,40 @@ static void *worker(void UNUSED(*arg)) /* start waiting for incoming connections */ while (1) { + /* time out connection to LDAP server if needed */ + myldap_session_check(session); + /* set up the set of fds to wait on */ + FD_ZERO(&fds); + FD_SET(nslcd_serversocket,&fds); + /* set up our timeout value */ + tv.tv_sec=nslcd_cfg->ldc_idle_timelimit; + tv.tv_usec=0; /* wait for a new connection */ - alen=(socklen_t)sizeof(struct sockaddr_storage); - csock=accept(nslcd_serversocket,(struct sockaddr *)&addr,&alen); + j=select(nslcd_serversocket+1,&fds,NULL,NULL,nslcd_cfg->ldc_idle_timelimit>0?&tv:NULL); /* see if we should exit before doing anything else */ if (nslcd_exitsignal!=0) return NULL; + /* check result of select() */ + if (j<0) + { + if (errno==EINTR) + log_log(LOG_DEBUG,"debug: select() failed (ignored): %s",strerror(errno)); + else + log_log(LOG_ERR,"select() failed: %s",strerror(errno)); + continue; + } + /* see if our file descriptor is actually ready */ + if (!FD_ISSET(nslcd_serversocket,&fds)) + continue; + /* wait for a new connection */ + alen=(socklen_t)sizeof(struct sockaddr_storage); + csock=accept(nslcd_serversocket,(struct sockaddr *)&addr,&alen); if (csock<0) { if ((errno==EINTR)||(errno==EAGAIN)||(errno==EWOULDBLOCK)) - { log_log(LOG_DEBUG,"accept() failed (ignored): %s",strerror(errno)); - continue; - } - log_log(LOG_ERR,"accept() failed: %s",strerror(errno)); + else + log_log(LOG_ERR,"accept() failed: %s",strerror(errno)); continue; } /* make sure O_NONBLOCK is not inherited */ @@ -653,6 +691,14 @@ int main(int argc,char *argv[]) log_log(LOG_ERR,"daemon may already be active, cannot acquire lock (%s): %s",NSLCD_PIDFILE,strerror(errno)); exit(EXIT_FAILURE); } + /* close all file descriptors (except stdin/out/err) */ + i=sysconf(_SC_OPEN_MAX); + /* if the system does not have OPEN_MAX just close the first 32 and + hope we closed enough */ + if (i<0) + i=32; + for (;i>3;i--) + close(i); /* daemonize */ if ((!nslcd_debugging)&&(daemon(0,0)<0)) { diff --git a/nslcd/pam.c b/nslcd/pam.c index 0467280..f6d3877 100644 --- a/nslcd/pam.c +++ b/nslcd/pam.c @@ -42,37 +42,53 @@ #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 */ +/* set up a connection and try to bind with the specified DN and password, + returns an LDAP result code */ static int try_bind(const char *userdn,const char *password) { MYLDAP_SESSION *session; - char buffer[256]; + MYLDAP_SEARCH *search; + MYLDAP_ENTRY *entry; + static const char *attrs[2]; int rc; /* set up a new connection */ session=myldap_create_session(); if (session==NULL) - return NSLCD_PAM_AUTH_ERR; + return LDAP_UNAVAILABLE; /* set up credentials for the session */ myldap_set_credentials(session,userdn,password); /* perform search for own object (just to do any kind of search) */ - if ((lookup_dn2uid(session,userdn,&rc,buffer,sizeof(buffer))==NULL)&&(rc==LDAP_SUCCESS)) - rc=LDAP_LOCAL_ERROR; - /* close the session */ - myldap_session_close(session); - /* handle the results */ - switch(rc) + attrs[0]="dn"; + attrs[1]=NULL; + search=myldap_search(session,userdn,LDAP_SCOPE_BASE,"(objectClass=*)",attrs,&rc); + if ((search==NULL)||(rc!=LDAP_SUCCESS)) + { + if (rc==LDAP_SUCCESS) + rc=LDAP_LOCAL_ERROR; + log_log(LOG_WARNING,"lookup of %s failed: %s",userdn,ldap_err2string(rc)); + } + else { - case LDAP_SUCCESS: return NSLCD_PAM_SUCCESS; - case LDAP_INVALID_CREDENTIALS: return NSLCD_PAM_AUTH_ERR; - default: return NSLCD_PAM_AUTH_ERR; + entry=myldap_get_entry(search,&rc); + if ((entry==NULL)||(rc!=LDAP_SUCCESS)) + { + if (rc==LDAP_SUCCESS) + rc=LDAP_NO_RESULTS_RETURNED; + log_log(LOG_WARNING,"lookup of %s failed: %s",userdn,ldap_err2string(rc)); + } } + /* close the session */ + myldap_session_close(session); + /* return results */ + return rc; } -/* ensure that both userdn and username are filled in from the entry */ +/* ensure that both userdn and username are filled in from the entry, + returns an LDAP result code */ static int validate_user(MYLDAP_SESSION *session,char *userdn,size_t userdnsz, char *username,size_t usernamesz) { + int rc; MYLDAP_ENTRY *entry=NULL; const char *value; const char **values; @@ -80,24 +96,24 @@ static int validate_user(MYLDAP_SESSION *session,char *userdn,size_t userdnsz, if (!isvalidname(username)) { log_log(LOG_WARNING,"\"%s\": invalid user name",username); - return -1; + return LDAP_NO_SUCH_OBJECT; } /* look up user DN if not known */ if (userdn[0]=='\0') { /* get the user entry based on the username */ - entry=uid2entry(session,username); + entry=uid2entry(session,username,&rc); if (entry==NULL) { - log_log(LOG_WARNING,"\"%s\": user not found",username); - return -1; + log_log(LOG_WARNING,"\"%s\": user not found: %s",username,ldap_err2string(rc)); + return rc; } /* get the DN */ myldap_cpy_dn(entry,userdn,userdnsz); if (strcasecmp(userdn,"unknown")==0) { log_log(LOG_WARNING,"\"%s\": user has no DN",username); - return -1; + return LDAP_NO_SUCH_OBJECT; } /* get the "real" username */ value=myldap_get_rdn_value(entry,attmap_passwd_uid); @@ -114,7 +130,7 @@ static int validate_user(MYLDAP_SESSION *session,char *userdn,size_t userdnsz, if ((value==NULL)||!isvalidname(value)||strlen(value)>=usernamesz) { log_log(LOG_WARNING,"\"%s\": DN %s has invalid username",username,userdn); - return -1; + return LDAP_INVALID_SYNTAX; } /* check if the username is different and update it if needed */ if (strcmp(username,value)!=0) @@ -124,7 +140,7 @@ static int validate_user(MYLDAP_SESSION *session,char *userdn,size_t userdnsz, } } /* all check passed */ - return 0; + return LDAP_SUCCESS; } /* check authentication credentials of the user */ @@ -142,6 +158,7 @@ int nslcd_pam_authc(TFILE *fp,MYLDAP_SESSION *session,uid_t calleruid) READ_STRING(fp,servicename); READ_STRING(fp,password); /* log call */ + log_setrequest("pam_authc=\"%s\"",username); log_log(LOG_DEBUG,"nslcd_pam_authc(\"%s\",\"%s\",\"%s\",\"%s\")", username,userdn,servicename,*password?"***":""); /* write the response header */ @@ -168,22 +185,38 @@ int nslcd_pam_authc(TFILE *fp,MYLDAP_SESSION *session,uid_t calleruid) strcpy(password,nslcd_cfg->ldc_rootpwmodpw); } } - else if (validate_user(session,userdn,sizeof(userdn),username,sizeof(username))) + else if ((rc=validate_user(session,userdn,sizeof(userdn),username,sizeof(username)))!=LDAP_SUCCESS) { + if (rc!=LDAP_NO_SUCH_OBJECT) + { + WRITE_INT32(fp,NSLCD_RESULT_BEGIN); + WRITE_STRING(fp,username); + WRITE_STRING(fp,""); + WRITE_INT32(fp,NSLCD_PAM_AUTHINFO_UNAVAIL); /* authc */ + WRITE_INT32(fp,NSLCD_PAM_SUCCESS); /* authz */ + WRITE_STRING(fp,"LDAP server unavaiable"); /* authzmsg */ + } WRITE_INT32(fp,NSLCD_RESULT_END); return -1; } /* try authentication */ rc=try_bind(userdn,password); - if (rc==NSLCD_PAM_SUCCESS) + if (rc==LDAP_SUCCESS) log_log(LOG_DEBUG,"bind successful"); + /* map result code */ + switch (rc) + { + case LDAP_SUCCESS: rc=NSLCD_PAM_SUCCESS; break; + case LDAP_INVALID_CREDENTIALS: rc=NSLCD_PAM_AUTH_ERR; break; + default: rc=NSLCD_PAM_AUTH_ERR; + } /* write response */ WRITE_INT32(fp,NSLCD_RESULT_BEGIN); WRITE_STRING(fp,username); WRITE_STRING(fp,userdn); - WRITE_INT32(fp,rc); /* authc */ - WRITE_INT32(fp,rc); /* authz */ - WRITE_STRING(fp,""); /* authzmsg */ + WRITE_INT32(fp,rc); /* authc */ + WRITE_INT32(fp,NSLCD_PAM_SUCCESS); /* authz */ + WRITE_STRING(fp,""); /* authzmsg */ WRITE_INT32(fp,NSLCD_RESULT_END); return 0; } @@ -237,6 +270,7 @@ static const char *autzsearch_var_get(const char *name,void *expander_attr) element in the dict) */ } +/* perform an authorisation search, returns an LDAP status code */ static int try_autzsearch(MYLDAP_SESSION *session,DICT *dict,const char *searchfilter) { char filter_buffer[1024]; @@ -249,7 +283,7 @@ static int try_autzsearch(MYLDAP_SESSION *session,DICT *dict,const char *searchf autzsearch_var_get,(void *)dict)==NULL) { log_log(LOG_ERR,"pam_authz_search \"%s\" is invalid",searchfilter); - return -1; + return LDAP_LOCAL_ERROR; } log_log(LOG_DEBUG,"trying pam_authz_search \"%s\"",filter_buffer); /* perform the search */ @@ -262,18 +296,18 @@ static int try_autzsearch(MYLDAP_SESSION *session,DICT *dict,const char *searchf { log_log(LOG_ERR,"pam_authz_search \"%s\" failed: %s", filter_buffer,ldap_err2string(rc)); - return -1; + return rc; } /* try to get an entry */ - entry=myldap_get_entry(search,NULL); + entry=myldap_get_entry(search,&rc); if (entry==NULL) { log_log(LOG_ERR,"pam_authz_search \"%s\" found no matches",filter_buffer); - return -1; + return rc; } log_log(LOG_DEBUG,"pam_authz_search found \"%s\"",myldap_get_dn(entry)); /* we've found an entry so it's OK */ - return 0; + return LDAP_SUCCESS; } /* check authorisation of the user */ @@ -294,13 +328,14 @@ int nslcd_pam_authz(TFILE *fp,MYLDAP_SESSION *session) READ_STRING(fp,rhost); READ_STRING(fp,tty); /* log call */ + log_setrequest("pam_authz=\"%s\"",username); log_log(LOG_DEBUG,"nslcd_pam_authz(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\")", username,userdn,servicename,ruser,rhost,tty); /* write the response header */ WRITE_INT32(fp,NSLCD_VERSION); WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ); /* validate request and fill in the blanks */ - if (validate_user(session,userdn,sizeof(userdn),username,sizeof(username))) + if (validate_user(session,userdn,sizeof(userdn),username,sizeof(username))!=LDAP_SUCCESS) { WRITE_INT32(fp,NSLCD_RESULT_END); return -1; @@ -319,7 +354,7 @@ int nslcd_pam_authz(TFILE *fp,MYLDAP_SESSION *session) /* TODO: fqdn */ autzsearch_var_add(dict,"dn",userdn); autzsearch_var_add(dict,"uid",username); - if (try_autzsearch(session,dict,nslcd_cfg->ldc_pam_authz_search)) + if (try_autzsearch(session,dict,nslcd_cfg->ldc_pam_authz_search)!=LDAP_SUCCESS) { WRITE_INT32(fp,NSLCD_RESULT_BEGIN); WRITE_STRING(fp,username); @@ -358,6 +393,7 @@ int nslcd_pam_sess_o(TFILE *fp,MYLDAP_SESSION *session) READ_STRING(fp,ruser); READ_INT32(fp,sessionid); /* log call */ + log_setrequest("pam_sess_o=\"%s\"",username); log_log(LOG_DEBUG,"nslcd_pam_sess_o(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\",\"%s\")", username,userdn,servicename,tty,rhost,ruser); /* write the response header */ @@ -387,6 +423,7 @@ int nslcd_pam_sess_c(TFILE *fp,MYLDAP_SESSION *session) READ_STRING(fp,ruser); READ_INT32(fp,sessionid); /* log call */ + log_setrequest("pam_sess_c=\"%s\"",username); log_log(LOG_DEBUG,"nslcd_pam_sess_c(\"%s\",\"%s\",\"%s\",%d)", username,userdn,servicename,(int)sessionid); /* write the response header */ @@ -399,6 +436,7 @@ int nslcd_pam_sess_c(TFILE *fp,MYLDAP_SESSION *session) return 0; } +/* perform an LDAP password modification, returns an LDAP status code */ static int try_pwmod(const char *binddn,const char *userdn, const char *oldpassword,const char *newpassword) { @@ -408,7 +446,7 @@ static int try_pwmod(const char *binddn,const char *userdn, /* set up a new connection */ session=myldap_create_session(); if (session==NULL) - return NSLCD_PAM_AUTH_ERR; + return LDAP_UNAVAILABLE; /* set up credentials for the session */ myldap_set_credentials(session,binddn,oldpassword); /* perform search for own object (just to do any kind of search) */ @@ -443,6 +481,7 @@ int nslcd_pam_pwmod(TFILE *fp,MYLDAP_SESSION *session,uid_t calleruid) READ_STRING(fp,oldpassword); READ_STRING(fp,newpassword); /* log call */ + log_setrequest("pam_pwmod=\"%s\"",username); log_log(LOG_DEBUG,"nslcd_pam_pwmod(\"%s\",\"%s\",\"%s\",\"%s\",\"%s\")", username,userdn,servicename,*oldpassword?"***":"", *newpassword?"***":""); @@ -466,7 +505,7 @@ int nslcd_pam_pwmod(TFILE *fp,MYLDAP_SESSION *session,uid_t calleruid) } } /* validate request and fill in the blanks */ - if (validate_user(session,userdn,sizeof(userdn),username,sizeof(username))) + if (validate_user(session,userdn,sizeof(userdn),username,sizeof(username))!=LDAP_SUCCESS) { WRITE_INT32(fp,NSLCD_RESULT_END); return -1; diff --git a/nslcd/passwd.c b/nslcd/passwd.c index a0b61d7..f0dceb0 100644 --- a/nslcd/passwd.c +++ b/nslcd/passwd.c @@ -252,7 +252,7 @@ char *dn2uid(MYLDAP_SESSION *session,const char *dn,char *buf,size_t buflen) return uid; } -MYLDAP_ENTRY *uid2entry(MYLDAP_SESSION *session,const char *uid) +MYLDAP_ENTRY *uid2entry(MYLDAP_SESSION *session,const char *uid,int *rcp) { MYLDAP_SEARCH *search=NULL; MYLDAP_ENTRY *entry=NULL; @@ -270,7 +270,7 @@ MYLDAP_ENTRY *uid2entry(MYLDAP_SESSION *session,const char *uid) mkfilter_passwd_byname(uid,filter,sizeof(filter)); for (i=0;(i<NSS_LDAP_CONFIG_MAX_BASES)&&((base=passwd_bases[i])!=NULL);i++) { - search=myldap_search(session,base,passwd_scope,filter,attrs,NULL); + search=myldap_search(session,base,passwd_scope,filter,attrs,rcp); if (search==NULL) return NULL; entry=myldap_get_entry(search,NULL); @@ -284,7 +284,7 @@ char *uid2dn(MYLDAP_SESSION *session,const char *uid,char *buf,size_t buflen) { MYLDAP_ENTRY *entry; /* look up the entry */ - entry=uid2entry(session,uid); + entry=uid2entry(session,uid,NULL); if (entry==NULL) return NULL; /* get DN */ @@ -412,11 +412,11 @@ NSLCD_HANDLE_UID( char name[256]; char filter[1024]; READ_STRING(fp,name); + log_setrequest("passwd=\"%s\"",name); if (!isvalidname(name)) { - log_log(LOG_WARNING,"nslcd_passwd_byname(%s): invalid user name",name); + log_log(LOG_WARNING,"\"%s\": invalid user name",name); return -1; }, - log_log(LOG_DEBUG,"nslcd_passwd_byname(%s)",name);, NSLCD_ACTION_PASSWD_BYNAME, mkfilter_passwd_byname(name,filter,sizeof(filter)), write_passwd(fp,entry,name,NULL,calleruid) @@ -426,8 +426,8 @@ NSLCD_HANDLE_UID( passwd,byuid, uid_t uid; char filter[1024]; - READ_TYPE(fp,uid,uid_t);, - log_log(LOG_DEBUG,"nslcd_passwd_byuid(%d)",(int)uid);, + READ_TYPE(fp,uid,uid_t); + log_setrequest("passwd=%d",(int)uid);, NSLCD_ACTION_PASSWD_BYUID, mkfilter_passwd_byuid(uid,filter,sizeof(filter)), write_passwd(fp,entry,NULL,&uid,calleruid) @@ -436,8 +436,7 @@ NSLCD_HANDLE_UID( NSLCD_HANDLE_UID( passwd,all, const char *filter; - /* no parameters to read */, - log_log(LOG_DEBUG,"nslcd_passwd_all()");, + log_setrequest("passwd(all)");, NSLCD_ACTION_PASSWD_ALL, (filter=passwd_filter,0), write_passwd(fp,entry,NULL,NULL,calleruid) diff --git a/nslcd/protocol.c b/nslcd/protocol.c index 3760aa9..4efdd4a 100644 --- a/nslcd/protocol.c +++ b/nslcd/protocol.c @@ -162,8 +162,8 @@ NSLCD_HANDLE( protocol,byname, char name[256]; char filter[1024]; - READ_STRING(fp,name);, - log_log(LOG_DEBUG,"nslcd_protocol_byname(%s)",name);, + READ_STRING(fp,name); + log_setrequest("protocol=\"%s\"",name);, NSLCD_ACTION_PROTOCOL_BYNAME, mkfilter_protocol_byname(name,filter,sizeof(filter)), write_protocol(fp,entry,name) @@ -173,8 +173,8 @@ NSLCD_HANDLE( protocol,bynumber, int protocol; char filter[1024]; - READ_INT32(fp,protocol);, - log_log(LOG_DEBUG,"nslcd_protocol_bynumber(%d)",protocol);, + READ_INT32(fp,protocol); + log_setrequest("protocol=%d",protocol);, NSLCD_ACTION_PROTOCOL_BYNUMBER, mkfilter_protocol_bynumber(protocol,filter,sizeof(filter)), write_protocol(fp,entry,NULL) @@ -183,8 +183,7 @@ NSLCD_HANDLE( NSLCD_HANDLE( protocol,all, const char *filter; - /* no parameters to read */, - log_log(LOG_DEBUG,"nslcd_protocol_all()");, + log_setrequest("protocol(all)");, NSLCD_ACTION_PROTOCOL_ALL, (filter=protocol_filter,0), write_protocol(fp,entry,NULL) diff --git a/nslcd/rpc.c b/nslcd/rpc.c index 4ceb9c0..25f2fb9 100644 --- a/nslcd/rpc.c +++ b/nslcd/rpc.c @@ -163,8 +163,8 @@ NSLCD_HANDLE( rpc,byname, char name[256]; char filter[1024]; - READ_STRING(fp,name);, - log_log(LOG_DEBUG,"nslcd_rpc_byname(%s)",name);, + READ_STRING(fp,name); + log_setrequest("rpc=\"%s\"",name);, NSLCD_ACTION_RPC_BYNAME, mkfilter_rpc_byname(name,filter,sizeof(filter)), write_rpc(fp,entry,name) @@ -174,8 +174,8 @@ NSLCD_HANDLE( rpc,bynumber, int number; char filter[1024]; - READ_INT32(fp,number);, - log_log(LOG_DEBUG,"nslcd_rpc_bynumber(%d)",number);, + READ_INT32(fp,number); + log_setrequest("rpc=%d",number);, NSLCD_ACTION_RPC_BYNUMBER, mkfilter_rpc_bynumber(number,filter,sizeof(filter)), write_rpc(fp,entry,NULL) @@ -184,8 +184,7 @@ NSLCD_HANDLE( NSLCD_HANDLE( rpc,all, const char *filter; - /* no parameters to read */, - log_log(LOG_DEBUG,"nslcd_rpc_all()");, + log_setrequest("rpc(all)");, NSLCD_ACTION_RPC_ALL, (filter=rpc_filter,0), write_rpc(fp,entry,NULL) diff --git a/nslcd/service.c b/nslcd/service.c index d55647b..3c487f7 100644 --- a/nslcd/service.c +++ b/nslcd/service.c @@ -206,8 +206,8 @@ NSLCD_HANDLE( char protocol[256]; char filter[1024]; READ_STRING(fp,name); - READ_STRING(fp,protocol);, - log_log(LOG_DEBUG,"nslcd_service_byname(%s,%s)",name,protocol);, + READ_STRING(fp,protocol); + log_setrequest("service=\"%s\"/%s",name,protocol);, NSLCD_ACTION_SERVICE_BYNAME, mkfilter_service_byname(name,protocol,filter,sizeof(filter)), write_service(fp,entry,name,protocol) @@ -219,8 +219,8 @@ NSLCD_HANDLE( char protocol[256]; char filter[1024]; READ_INT32(fp,number); - READ_STRING(fp,protocol);, - log_log(LOG_DEBUG,"nslcd_service_bynumber(%d,%s)",number,protocol);, + READ_STRING(fp,protocol); + log_setrequest("service=%d/%s",number,protocol);, NSLCD_ACTION_SERVICE_BYNUMBER, mkfilter_service_bynumber(number,protocol,filter,sizeof(filter)), write_service(fp,entry,NULL,protocol) @@ -229,8 +229,7 @@ NSLCD_HANDLE( NSLCD_HANDLE( service,all, const char *filter; - /* no parameters to read */, - log_log(LOG_DEBUG,"nslcd_service_all()");, + log_setrequest("service(all)");, NSLCD_ACTION_SERVICE_ALL, (filter=service_filter,0), write_service(fp,entry,NULL,NULL) diff --git a/nslcd/shadow.c b/nslcd/shadow.c index 3ce09cc..a5c4a6d 100644 --- a/nslcd/shadow.c +++ b/nslcd/shadow.c @@ -240,8 +240,8 @@ NSLCD_HANDLE( shadow,byname, char name[256]; char filter[1024]; - READ_STRING(fp,name);, - log_log(LOG_DEBUG,"nslcd_shadow_byname(%s)",name);, + READ_STRING(fp,name); + log_setrequest("shadow=\"%s\"",name);, NSLCD_ACTION_SHADOW_BYNAME, mkfilter_shadow_byname(name,filter,sizeof(filter)), write_shadow(fp,entry,name) @@ -250,8 +250,7 @@ NSLCD_HANDLE( NSLCD_HANDLE( shadow,all, const char *filter; - /* no parameters to read */, - log_log(LOG_DEBUG,"nslcd_shadow_all()");, + log_setrequest("shadow(all)");, NSLCD_ACTION_SHADOW_ALL, (filter=shadow_filter,0), write_shadow(fp,entry,NULL) diff --git a/pam/Makefile.am b/pam/Makefile.am index dca583f..b374ca9 100644 --- a/pam/Makefile.am +++ b/pam/Makefile.am @@ -36,7 +36,7 @@ uninstall-local: uninstall-pam_ldap_so install-pam_ldap_so: pam_ldap.so -rm -f $(DESTDIR)/$(PAM_SECLIB_DIR)/$(PAM_LDAP_SONAME) $(mkinstalldirs) $(DESTDIR)/$(PAM_SECLIB_DIR) - $(INSTALL_PROGRAM) pam_ldap.so $(DESTDIR)$(libdir)/$(PAM_LDAP_SONAME) + $(INSTALL_PROGRAM) pam_ldap.so $(DESTDIR)$(PAM_SECLIB_DIR)/$(PAM_LDAP_SONAME) uninstall-pam_ldap_so: -rm -f $(DESTDIR)/$(PAM_SECLIB_DIR)/$(PAM_LDAP_SONAME) @@ -433,6 +433,9 @@ 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) { + /* turn in to generic PAM error message if message is empty */ + if ((ctx2.authzmsg==NULL)||(ctx2.authzmsg[0]=='\0')) + ctx2.authzmsg=(char *)pam_strerror(pamh,ctx2.authz); pam_syslog(pamh,LOG_NOTICE,"%s; user=%s",ctx2.authzmsg,username); rc=remap_pam_rc(ctx2.authz,&cfg); if ((rc!=PAM_IGNORE)&&(!cfg.no_warn)) @@ -442,6 +445,8 @@ 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) { + 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); if ((rc!=PAM_IGNORE)&&(!cfg.no_warn)) diff --git a/tests/test_myldap.c b/tests/test_myldap.c index 589138f..e292d50 100644 --- a/tests/test_myldap.c +++ b/tests/test_myldap.c @@ -104,6 +104,7 @@ static void test_search(void) printf("test_myldap: test_search(): ...\n"); } printf("test_myldap: test_search(): %d entries returned: %s\n",i,ldap_err2string(rc)); + assert(rc==LDAP_SUCCESS); /* perform another search */ printf("test_myldap: test_search(): doing search...\n"); search=myldap_search(session,nslcd_cfg->ldc_bases[0], @@ -121,6 +122,7 @@ static void test_search(void) printf("test_myldap: test_search(): ...\n"); } printf("test_myldap: test_search(): %d entries returned: %s\n",i,ldap_err2string(rc)); + assert(rc==LDAP_SUCCESS); /* clean up */ myldap_session_close(session); } |