From 8acfce5c8916bb98768e3e351b7614b4eaf5954a Mon Sep 17 00:00:00 2001 From: Luke Shumaker Date: Sat, 29 Nov 2014 02:08:49 -0500 Subject: wip --- nslcd/cfg.c | 425 +------------------------------------------------- nslcd/common.c | 22 --- nslcd/common.h | 3 +- nslcd/db_pam.c | 2 - nslcd/db_passwd.c | 8 +- nslcd/db_shadow.c | 222 +++++++------------------- nslcd/hackers_watch.h | 1 + nslcd/invalidator.c | 1 + nslcd/myldap.h | 179 --------------------- 9 files changed, 69 insertions(+), 794 deletions(-) delete mode 100644 nslcd/myldap.h diff --git a/nslcd/cfg.c b/nslcd/cfg.c index 7e172df..9a90003 100644 --- a/nslcd/cfg.c +++ b/nslcd/cfg.c @@ -56,7 +56,6 @@ #include "common.h" #include "log.h" #include "cfg.h" -#include "attmap.h" #include "common/expr.h" struct ldap_config *nslcd_cfg = NULL; @@ -602,244 +601,6 @@ static const char *print_map(enum ldap_map_selector map) } } -static void handle_base(const char *filename, int lnr, - const char *keyword, char *line, - struct ldap_config *cfg) -{ - const char **bases; - int i; - char *value; -#ifdef HAVE_LDAP_DOMAIN2DN - const char *domain = NULL; - char *domaindn = NULL; -#endif /* HAVE_LDAP_DOMAIN2DN */ - /* get the list of bases to update */ - bases = base_get_var(get_map(&line)); - if (bases == NULL) - bases = cfg->bases; - /* rest of the line is the value */ - value = get_linedup(filename, lnr, keyword, &line); - /* if the base is "DOMAIN" use the domain name */ - if (strcasecmp(value, "domain") == 0) - { -#ifdef HAVE_LDAP_DOMAIN2DN - free(value); - domain = cfg_getdomainname(filename, lnr); - ldap_domain2dn(domain, &domaindn); - log_log(LOG_DEBUG, "set_base(): setting base to %s from domain", - domaindn); - value = xstrdup(domaindn); -#else /* not HAVE_LDAP_DOMAIN2DN */ - log_log(LOG_ERR, "%s:%d: value %s not supported on platform", - filename, lnr, value); - exit(EXIT_FAILURE); -#endif /* not HAVE_LDAP_DOMAIN2DN */ - } - /* find the spot in the list of bases */ - for (i = 0; i < NSS_LDAP_CONFIG_MAX_BASES; i++) - if (bases[i] == NULL) - { - bases[i] = value; - return; - } - /* no free spot found */ - log_log(LOG_ERR, "%s:%d: maximum number of base options per map (%d) exceeded", - filename, lnr, NSS_LDAP_CONFIG_MAX_BASES); - exit(EXIT_FAILURE); -} - -static void handle_scope(const char *filename, int lnr, - const char *keyword, char *line, - struct ldap_config *cfg) -{ - char token[32]; - int *var; - var = scope_get_var(get_map(&line)); - check_argumentcount(filename, lnr, keyword, - get_token(&line, token, sizeof(token)) != NULL); - get_eol(filename, lnr, keyword, &line); - if (var == NULL) - var = &cfg->scope; - if ((strcasecmp(token, "sub") == 0) || (strcasecmp(token, "subtree") == 0)) - *var = LDAP_SCOPE_SUBTREE; - else if ((strcasecmp(token, "one") == 0) || (strcasecmp(token, "onelevel") == 0)) - *var = LDAP_SCOPE_ONELEVEL; - else if (strcasecmp(token, "base") == 0) - *var = LDAP_SCOPE_BASE; -#ifdef LDAP_SCOPE_CHILDREN - else if (strcasecmp(token, "children") == 0) - *var = LDAP_SCOPE_CHILDREN; -#endif /* LDAP_SCOPE_CHILDREN */ - else - { - log_log(LOG_ERR, "%s:%d: not a scope argument: '%s'", - filename, lnr, token); - exit(EXIT_FAILURE); - } -} - -static const char *print_scope(int scope) -{ - switch (scope) - { - case LDAP_SCOPE_SUBTREE: return "sub"; - case LDAP_SCOPE_ONELEVEL: return "one"; - case LDAP_SCOPE_BASE: return "base"; -#ifdef LDAP_SCOPE_CHILDREN - case LDAP_SCOPE_CHILDREN: return "children"; -#endif /* LDAP_SCOPE_CHILDREN */ - default: return "???"; - } -} - -static void handle_deref(const char *filename, int lnr, - const char *keyword, char *line, - struct ldap_config *cfg) -{ - char token[32]; - check_argumentcount(filename, lnr, keyword, - get_token(&line, token, sizeof(token)) != NULL); - get_eol(filename, lnr, keyword, &line); - if (strcasecmp(token, "never") == 0) - cfg->deref = LDAP_DEREF_NEVER; - else if (strcasecmp(token, "searching") == 0) - cfg->deref = LDAP_DEREF_SEARCHING; - else if (strcasecmp(token, "finding") == 0) - cfg->deref = LDAP_DEREF_FINDING; - else if (strcasecmp(token, "always") == 0) - cfg->deref = LDAP_DEREF_ALWAYS; - else - { - log_log(LOG_ERR, "%s:%d: wrong argument: '%s'", filename, lnr, token); - exit(EXIT_FAILURE); - } -} - -static const char *print_deref(int deref) -{ - switch (deref) - { - case LDAP_DEREF_NEVER: return "never"; - case LDAP_DEREF_SEARCHING: return "searching"; - case LDAP_DEREF_FINDING: return "finding"; - case LDAP_DEREF_ALWAYS: return "always"; - default: return "???"; - } -} - -static void handle_filter(const char *filename, int lnr, - const char *keyword, char *line) -{ - const char **var; - const char *map = line; - var = filter_get_var(get_map(&line)); - if (var == NULL) - { - log_log(LOG_ERR, "%s:%d: unknown map: '%s'", filename, lnr, map); - exit(EXIT_FAILURE); - } - check_argumentcount(filename, lnr, keyword, (line != NULL) && (*line != '\0')); - /* check if the value will be changed */ - if (strcmp(*var, line) != 0) - { - /* Note: we have a memory leak here if a single mapping is changed - multiple times in one config (deemed not a problem) */ - *var = xstrdup(line); - } -} - -/* this function modifies the statement argument passed */ -static void handle_map(const char *filename, int lnr, - const char *keyword, char *line) -{ - enum ldap_map_selector map; - const char **var; - char oldatt[32], newatt[1024]; - /* get the map */ - if ((map = get_map(&line)) == LM_NONE) - { - log_log(LOG_ERR, "%s:%d: unknown map: '%s'", filename, lnr, line); - exit(EXIT_FAILURE); - } - /* read the other tokens */ - check_argumentcount(filename, lnr, keyword, - (get_token(&line, oldatt, sizeof(oldatt)) != NULL) && - (get_token(&line, newatt, sizeof(newatt)) != NULL)); - /* check that there are no more tokens left on the line */ - get_eol(filename, lnr, keyword, &line); - /* change attribute mapping */ - var = attmap_get_var(map, oldatt); - if (var == NULL) - { - log_log(LOG_ERR, "%s:%d: unknown attribute to map: '%s'", - filename, lnr, oldatt); - exit(EXIT_FAILURE); - } - if (attmap_set_mapping(var, newatt) == NULL) - { - log_log(LOG_ERR, "%s:%d: attribute %s cannot be an expression", - filename, lnr, oldatt); - exit(EXIT_FAILURE); - } -} - -#ifdef LDAP_OPT_X_TLS -static const char *print_ssl(int ssl) -{ - switch (ssl) - { - case SSL_OFF: return "off"; - case SSL_START_TLS: return "start_tls"; - case SSL_LDAPS: return "on"; - default: return "???"; - } -} - -static void handle_tls_reqcert(const char *filename, int lnr, - const char *keyword, char *line) -{ - char token[16]; - int value, rc; - /* get token */ - check_argumentcount(filename, lnr, keyword, - get_token(&line, token, sizeof(token)) != NULL); - get_eol(filename, lnr, keyword, &line); - /* check if it is a valid value for tls_reqcert option */ - if ((strcasecmp(token, "never") == 0) || (strcasecmp(token, "no") == 0)) - value = LDAP_OPT_X_TLS_NEVER; - else if (strcasecmp(token, "allow") == 0) - value = LDAP_OPT_X_TLS_ALLOW; - else if (strcasecmp(token, "try") == 0) - value = LDAP_OPT_X_TLS_TRY; - else if ((strcasecmp(token, "demand") == 0) || - (strcasecmp(token, "yes") == 0)) - value = LDAP_OPT_X_TLS_DEMAND; - else if (strcasecmp(token, "hard") == 0) - value = LDAP_OPT_X_TLS_HARD; - else - { - log_log(LOG_ERR, "%s:%d: %s: invalid argument: '%s'", - filename, lnr, keyword, token); - exit(EXIT_FAILURE); - } - log_log(LOG_DEBUG, "ldap_set_option(LDAP_OPT_X_TLS_REQUIRE_CERT,%s)", token); - LDAP_SET_OPTION(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &value); -} - -static const char *print_tls_reqcert(int value) -{ - switch (value) - { - case LDAP_OPT_X_TLS_NEVER: return "never"; - case LDAP_OPT_X_TLS_ALLOW: return "allow"; - case LDAP_OPT_X_TLS_TRY: return "try"; - case LDAP_OPT_X_TLS_DEMAND: return "demand"; - case LDAP_OPT_X_TLS_HARD: return "hard"; - default: return "???"; - } -} -#endif /* LDAP_OPT_X_TLS */ - /* this function modifies the line argument passed */ static void handle_nss_initgroups_ignoreusers( const char *filename, int lnr, @@ -1068,58 +829,6 @@ static void handle_cache(const char *filename, int lnr, } } -/* This function tries to get the LDAP search base from the LDAP server. - Note that this returns a string that has been allocated with strdup(). - For this to work the myldap module needs enough configuration information - to make an LDAP connection. */ -static MUST_USE char *get_base_from_rootdse(void) -{ - MYLDAP_SESSION *session; - MYLDAP_SEARCH *search; - MYLDAP_ENTRY *entry; - const char *attrs[] = { "+", NULL }; - int i; - int rc; - const char **values; - char *base = NULL; - /* initialize session */ - session = myldap_create_session(); - assert(session != NULL); - /* perform search */ - search = myldap_search(session, "", LDAP_SCOPE_BASE, "(objectClass=*)", - attrs, NULL); - if (search == NULL) - { - myldap_session_close(session); - return NULL; - } - /* go over results */ - for (i = 0; (entry = myldap_get_entry(search, &rc)) != NULL; i++) - { - /* get defaultNamingContext */ - values = myldap_get_values(entry, "defaultNamingContext"); - if ((values != NULL) && (values[0] != NULL)) - { - base = xstrdup(values[0]); - log_log(LOG_DEBUG, "get_basedn_from_rootdse(): found attribute defaultNamingContext with value %s", - values[0]); - break; - } - /* get namingContexts */ - values = myldap_get_values(entry, "namingContexts"); - if ((values != NULL) && (values[0] != NULL)) - { - base = xstrdup(values[0]); - log_log(LOG_DEBUG, "get_basedn_from_rootdse(): found attribute namingContexts with value %s", - values[0]); - break; - } - } - /* clean up */ - myldap_session_close(session); - return base; -} - /* check that the file is not world readable */ static void check_permissions(const char *filename, const char *keyword) { @@ -1389,10 +1098,6 @@ static void cfg_read(const char *filename, struct ldap_config *cfg) { handle_filter(filename, lnr, keyword, line); } - else if (strcasecmp(keyword, "map") == 0) - { - handle_map(filename, lnr, keyword, line); - } /* timing/reconnect options */ else if (strcasecmp(keyword, "bind_timelimit") == 0) { @@ -1634,132 +1339,7 @@ static void cfg_dump(void) else log_log(LOG_DEBUG, "CFG: # gid not set"); log_log_config(); - for (i = 0; i < (NSS_LDAP_CONFIG_MAX_URIS + 1); i++) - if (nslcd_cfg->uris[i].uri != NULL) - log_log(LOG_DEBUG, "CFG: uri %s", nslcd_cfg->uris[i].uri); - log_log(LOG_DEBUG, "CFG: ldap_version %d", nslcd_cfg->ldap_version); - if (nslcd_cfg->binddn != NULL) - log_log(LOG_DEBUG, "CFG: binddn %s", nslcd_cfg->binddn); - if (nslcd_cfg->bindpw != NULL) - log_log(LOG_DEBUG, "CFG: bindpw ***"); - if (nslcd_cfg->rootpwmoddn != NULL) - log_log(LOG_DEBUG, "CFG: rootpwmoddn %s", nslcd_cfg->rootpwmoddn); - if (nslcd_cfg->rootpwmodpw != NULL) - log_log(LOG_DEBUG, "CFG: rootpwmodpw ***"); - if (nslcd_cfg->sasl_mech != NULL) - log_log(LOG_DEBUG, "CFG: sasl_mech %s", nslcd_cfg->sasl_mech); - if (nslcd_cfg->sasl_realm != NULL) - log_log(LOG_DEBUG, "CFG: sasl_realm %s", nslcd_cfg->sasl_realm); - if (nslcd_cfg->sasl_authcid != NULL) - log_log(LOG_DEBUG, "CFG: sasl_authcid %s", nslcd_cfg->sasl_authcid); - if (nslcd_cfg->sasl_authzid != NULL) - log_log(LOG_DEBUG, "CFG: sasl_authzid %s", nslcd_cfg->sasl_authzid); - if (nslcd_cfg->sasl_secprops != NULL) - log_log(LOG_DEBUG, "CFG: sasl_secprops %s", nslcd_cfg->sasl_secprops); -#ifdef LDAP_OPT_X_SASL_NOCANON - if (nslcd_cfg->sasl_canonicalize >= 0) - log_log(LOG_DEBUG, "CFG: sasl_canonicalize %s", print_boolean(nslcd_cfg->sasl_canonicalize)); -#endif /* LDAP_OPT_X_SASL_NOCANON */ - str = getenv("KRB5CCNAME"); - if (str != NULL) - log_log(LOG_DEBUG, "CFG: krb5_ccname %s", str); - for (i = 0; i < NSS_LDAP_CONFIG_MAX_BASES; i++) - if (nslcd_cfg->bases[i] != NULL) - log_log(LOG_DEBUG, "CFG: base %s", nslcd_cfg->bases[i]); - for (map = LM_ALIASES; map < LM_NONE; map++) - { - strp = base_get_var(map); - if (strp != NULL) - for (i = 0; i < NSS_LDAP_CONFIG_MAX_BASES; i++) - if (strp[i] != NULL) - log_log(LOG_DEBUG, "CFG: base %s %s", print_map(map), strp[i]); - } - log_log(LOG_DEBUG, "CFG: scope %s", print_scope(nslcd_cfg->scope)); - for (map = LM_ALIASES; map < LM_NONE; map++) - { - scopep = scope_get_var(map); - if ((scopep != NULL) && (*scopep != LDAP_SCOPE_DEFAULT)) - log_log(LOG_DEBUG, "CFG: scope %s %s", print_map(map), print_scope(*scopep)); - } - log_log(LOG_DEBUG, "CFG: deref %s", print_deref(nslcd_cfg->deref)); - log_log(LOG_DEBUG, "CFG: referrals %s", print_boolean(nslcd_cfg->referrals)); - for (map = LM_ALIASES; map < LM_NONE; map++) - { - strp = filter_get_var(map); - if ((strp != NULL) && (*strp != NULL)) - log_log(LOG_DEBUG, "CFG: filter %s %s", print_map(map), *strp); - } -#define LOG_ATTMAP(map, mapl, att) \ - if (strcmp(attmap_##mapl##_##att, __STRING(att)) != 0) \ - log_log(LOG_DEBUG, "CFG: map %s %s %s", \ - print_map(map), __STRING(att), attmap_##mapl##_##att); - LOG_ATTMAP(LM_ALIASES, alias, cn); - LOG_ATTMAP(LM_ALIASES, alias, rfc822MailMember); - LOG_ATTMAP(LM_ETHERS, ether, cn); - LOG_ATTMAP(LM_ETHERS, ether, macAddress); - LOG_ATTMAP(LM_GROUP, group, cn); - LOG_ATTMAP(LM_GROUP, group, userPassword); - LOG_ATTMAP(LM_GROUP, group, gidNumber); - LOG_ATTMAP(LM_GROUP, group, memberUid); - LOG_ATTMAP(LM_GROUP, group, member); - LOG_ATTMAP(LM_HOSTS, host, cn); - LOG_ATTMAP(LM_HOSTS, host, ipHostNumber); - LOG_ATTMAP(LM_NETGROUP, netgroup, cn); - LOG_ATTMAP(LM_NETGROUP, netgroup, nisNetgroupTriple); - LOG_ATTMAP(LM_NETGROUP, netgroup, memberNisNetgroup); - LOG_ATTMAP(LM_NETWORKS, network, cn); - LOG_ATTMAP(LM_NETWORKS, network, ipNetworkNumber); - LOG_ATTMAP(LM_PASSWD, passwd, uid); - LOG_ATTMAP(LM_PASSWD, passwd, userPassword); - LOG_ATTMAP(LM_PASSWD, passwd, uidNumber); - LOG_ATTMAP(LM_PASSWD, passwd, gidNumber); - LOG_ATTMAP(LM_PASSWD, passwd, gecos); - LOG_ATTMAP(LM_PASSWD, passwd, homeDirectory); - LOG_ATTMAP(LM_PASSWD, passwd, loginShell); - LOG_ATTMAP(LM_PROTOCOLS, protocol, cn); - LOG_ATTMAP(LM_PROTOCOLS, protocol, ipProtocolNumber); - LOG_ATTMAP(LM_RPC, rpc, cn); - LOG_ATTMAP(LM_RPC, rpc, oncRpcNumber); - LOG_ATTMAP(LM_SERVICES, service, cn); - LOG_ATTMAP(LM_SERVICES, service, ipServicePort); - LOG_ATTMAP(LM_SERVICES, service, ipServiceProtocol); - LOG_ATTMAP(LM_SHADOW, shadow, uid); - LOG_ATTMAP(LM_SHADOW, shadow, userPassword); - LOG_ATTMAP(LM_SHADOW, shadow, shadowLastChange); - LOG_ATTMAP(LM_SHADOW, shadow, shadowMin); - LOG_ATTMAP(LM_SHADOW, shadow, shadowMax); - LOG_ATTMAP(LM_SHADOW, shadow, shadowWarning); - LOG_ATTMAP(LM_SHADOW, shadow, shadowInactive); - LOG_ATTMAP(LM_SHADOW, shadow, shadowExpire); - LOG_ATTMAP(LM_SHADOW, shadow, shadowFlag); - log_log(LOG_DEBUG, "CFG: bind_timelimit %d", nslcd_cfg->bind_timelimit); - log_log(LOG_DEBUG, "CFG: timelimit %d", nslcd_cfg->timelimit); - log_log(LOG_DEBUG, "CFG: idle_timelimit %d", nslcd_cfg->idle_timelimit); - log_log(LOG_DEBUG, "CFG: reconnect_sleeptime %d", nslcd_cfg->reconnect_sleeptime); - log_log(LOG_DEBUG, "CFG: reconnect_retrytime %d", nslcd_cfg->reconnect_retrytime); -#ifdef LDAP_OPT_X_TLS - log_log(LOG_DEBUG, "CFG: ssl %s", print_ssl(nslcd_cfg->ssl)); - rc = ldap_get_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &i); - if (rc != LDAP_SUCCESS) - log_log(LOG_DEBUG, "CFG: # tls_reqcert ERROR: %s", ldap_err2string(rc)); - else - log_log(LOG_DEBUG, "CFG: tls_reqcert %s", print_tls_reqcert(i)); - #define LOG_LDAP_OPT_STRING(cfg, option) \ - str = NULL; \ - rc = ldap_get_option(NULL, option, &str); \ - if (rc != LDAP_SUCCESS) \ - log_log(LOG_DEBUG, "CFG: # %s ERROR: %s", cfg, ldap_err2string(rc)); \ - else if ((str != NULL) && (*str != '\0')) \ - log_log(LOG_DEBUG, "CFG: %s %s", cfg, str); \ - if (str != NULL) \ - ldap_memfree(str); - LOG_LDAP_OPT_STRING("tls_cacertdir", LDAP_OPT_X_TLS_CACERTDIR); - LOG_LDAP_OPT_STRING("tls_cacertfile", LDAP_OPT_X_TLS_CACERTFILE); - LOG_LDAP_OPT_STRING("tls_randfile", LDAP_OPT_X_TLS_RANDOM_FILE); - LOG_LDAP_OPT_STRING("tls_ciphers", LDAP_OPT_X_TLS_CIPHER_SUITE); - LOG_LDAP_OPT_STRING("tls_cert", LDAP_OPT_X_TLS_CERTFILE); - LOG_LDAP_OPT_STRING("tls_key", LDAP_OPT_X_TLS_KEYFILE); -#endif /* LDAP_OPT_X_TLS */ + log_log(LOG_DEBUG, "CFG: pagesize %d", nslcd_cfg->pagesize); if (nslcd_cfg->nss_initgroups_ignoreusers != NULL) { @@ -1852,9 +1432,6 @@ void cfg_init(const char *fname) } /* TODO: check that if some tls options are set the ssl option should be set to on (just warn) */ #endif /* LDAP_OPT_X_TLS */ - /* if basedn is not yet set, get if from the rootDSE */ - if (nslcd_cfg->bases[0] == NULL) - nslcd_cfg->bases[0] = get_base_from_rootdse(); /* TODO: handle the case gracefully when no LDAP server is available yet */ /* see if we have a valid basedn */ if ((nslcd_cfg->bases[0] == NULL) || (nslcd_cfg->bases[0][0] == '\0')) diff --git a/nslcd/common.c b/nslcd/common.c index 979be82..421e8a5 100644 --- a/nslcd/common.c +++ b/nslcd/common.c @@ -40,7 +40,6 @@ #include "nslcd.h" #include "common.h" #include "log.h" -#include "attmap.h" #include "cfg.h" /* simple wrapper around snptintf() to return non-zero in case @@ -180,27 +179,6 @@ const char *getfqdn(void) return fqdn; } -const char *get_userpassword(MYLDAP_ENTRY *entry, const char *attr, - char *buffer, size_t buflen) -{ - const char *tmpvalue; - /* get the value */ - tmpvalue = attmap_get_value(entry, attr, buffer, buflen); - if (tmpvalue == NULL) - return NULL; - /* go over the entries and return the remainder of the value if it - starts with {crypt} or crypt$ */ - if (strncasecmp(tmpvalue, "{crypt}", 7) == 0) - return tmpvalue + 7; - if (strncasecmp(tmpvalue, "crypt$", 6) == 0) - return tmpvalue + 6; - /* just return the first value completely */ - return tmpvalue; - /* TODO: support more password formats e.g. SMD5 - (which is $1$ but in a different format) - (any code for this is more than welcome) */ -} - /* Checks if the specified name seems to be a valid user or group name. */ int isvalidname(const char *name) { diff --git a/nslcd/common.h b/nslcd/common.h index 0f57c34..ac0fb71 100644 --- a/nslcd/common.h +++ b/nslcd/common.h @@ -36,8 +36,9 @@ #include "common/tio.h" #include "compat/attrs.h" #include "cfg.h" +#include "hackers_watch.h" -typedef struct ldap_session MYLDAP_SESSION; +#define MYLDAP_SESSION struct session #define MYLDAP_ENTRY void /* macros for basic read and write operations, the following diff --git a/nslcd/db_pam.c b/nslcd/db_pam.c index f47b331..8deb74b 100644 --- a/nslcd/db_pam.c +++ b/nslcd/db_pam.c @@ -33,9 +33,7 @@ #include "common.h" #include "log.h" -#include "myldap.h" #include "cfg.h" -#include "attmap.h" #include "common/dict.h" #include "common/expr.h" diff --git a/nslcd/db_passwd.c b/nslcd/db_passwd.c index 16490c2..b72d869 100644 --- a/nslcd/db_passwd.c +++ b/nslcd/db_passwd.c @@ -103,7 +103,8 @@ NSLCD_HANDLE_UID( static size_t i = 0; for (; i < session->cnt; i++) { - if (strcmp(name, session->users[i].pw_name)==0) { + if (session->users[i].pw_uid > 0 && + STR_CMP(name, session->users[i].pw_name)==0) { *rcp = 0; i = session->cnt; return &(session->users[i]); @@ -161,7 +162,10 @@ NSLCD_HANDLE_UID( static size_t i = 0; for (; i < session->cnt; i++) { - return &(session->users[i]); + if (session->users[i].pw_uid > 0) { + *rcp = 0; + return &(session->users[i]); + } } return NULL; ,/* write */ diff --git a/nslcd/db_shadow.c b/nslcd/db_shadow.c index 081738b..3764873 100644 --- a/nslcd/db_shadow.c +++ b/nslcd/db_shadow.c @@ -25,16 +25,8 @@ #include "config.h" -#include -#include -#include -#include - #include "common.h" #include "log.h" -#include "myldap.h" -#include "cfg.h" -#include "attmap.h" struct shadow { /* for the integers: a value < 0 means empty */ @@ -49,127 +41,24 @@ struct shadow { int32_t flag; /* unused on Linux/Glibc */ }; -static long to_date(const char *dn, const char *date, const char *attr) -{ - char buffer[32]; - long value; - char *tmp; - size_t l; - /* do some special handling for date values on AD */ - if (strcasecmp(attr, "pwdLastSet") == 0) - { - /* we expect an AD 64-bit datetime value; - we should do date=date/864000000000-134774 - but that causes problems on 32-bit platforms, - first we devide by 1000000000 by stripping the - last 9 digits from the string and going from there */ - l = strlen(date) - 9; - if (l > (sizeof(buffer) - 1)) - return -1; /* error */ - strncpy(buffer, date, l); - buffer[l] = '\0'; - errno = 0; - value = strtol(buffer, &tmp, 10); - if ((*date == '\0') || (*tmp != '\0')) - { - log_log(LOG_WARNING, "%s: %s: non-numeric", dn, attr); - return -1; - } - else if (errno != 0) - { - log_log(LOG_WARNING, "%s: %s: out of range", dn, attr); - return -1; - } - return value / 864 - 134774; - /* note that AD does not have expiry dates but a lastchangeddate - and some value that needs to be added */ - } - errno = 0; - value = strtol(date, &tmp, 10); - if ((*date == '\0') || (*tmp != '\0')) - { - log_log(LOG_WARNING, "%s: %s: non-numeric", dn, attr); - return -1; - } - else if (errno != 0) - { - log_log(LOG_WARNING, "%s: %s: out of range", dn, attr); - return -1; - } - return value; -} - -#ifndef UF_DONT_EXPIRE_PASSWD -#define UF_DONT_EXPIRE_PASSWD 0x10000 -#endif - -#define GET_OPTIONAL_LONG(var, att, fallback) \ - tmpvalue = attmap_get_value(entry, attmap_shadow_##att, \ - buffer, sizeof(buffer)); \ - if (tmpvalue == NULL) \ - tmpvalue = ""; \ - errno = 0; \ - var = strtol(tmpvalue, &tmp, 10); \ - if ((*(tmpvalue) == '\0') || (*tmp != '\0')) \ - { \ - log_log(LOG_WARNING, "%s: %s: non-numeric", \ - myldap_get_dn(entry), attmap_shadow_##att); \ - var = fallback; \ - } \ - else if (errno != 0) \ - { \ - log_log(LOG_WARNING, "%s: %s: out of range", \ - myldap_get_dn(entry), attmap_shadow_##att); \ - var = fallback; \ - } - -void get_shadow_properties(MYLDAP_ENTRY *entry, long *lastchangedate, - long *mindays, long *maxdays, long *warndays, - long *inactdays, long *expiredate, - unsigned long *flag) +static void passwd2shadow(struct passwd *p, struct shadow *s) { - char buffer[64]; - const char *tmpvalue; - char *tmp; - /* get lastchange date */ - tmpvalue = attmap_get_value(entry, attmap_shadow_shadowLastChange, - buffer, sizeof(buffer)); - if (tmpvalue == NULL) - tmpvalue = ""; - *lastchangedate = to_date(myldap_get_dn(entry), tmpvalue, attmap_shadow_shadowLastChange); - /* get other shadow properties */ - GET_OPTIONAL_LONG(*mindays, shadowMin, -1); - GET_OPTIONAL_LONG(*maxdays, shadowMax, -1); - GET_OPTIONAL_LONG(*warndays, shadowWarning, -1); - GET_OPTIONAL_LONG(*inactdays, shadowInactive, -1); - GET_OPTIONAL_LONG(*expiredate, shadowExpire, -1); - GET_OPTIONAL_LONG(*flag, shadowFlag, 0); - /* if we're using AD handle the flag specially */ - if (strcasecmp(attmap_shadow_shadowLastChange, "pwdLastSet") == 0) - { - if (*flag & UF_DONT_EXPIRE_PASSWD) - *maxdays = -1; - *flag = 0; - } -} + s->name = p->pw_name; + s->hash = p->pw_passwd; + s->lastchange_date = -1; + s->min_days = -1; + s->max_days = -1; + s->warn_days = -1; + s->inact_days = -1; + s->expire_date = -1; + s->flag = -1; +}; static int write_shadow(TFILE *fp, struct shadow *entry, uid_t calleruid) { int32_t tmpint32; - struct shadow _entry = { - .name = pentry->pw_name; - .hash = pentry->pw_passwd; - .lastchange_date = -1; - .min_days = -1; - .max_days = -1; - .warn_days = -1; - .inact_days = -1; - .expire_date = -1; - .flag = -1; - }; - struct shadow *entry = &_entry; - if (caller_uid == 0) + if (calleruid == 0) { WRITE_INT32(fp, NSLCD_RESULT_BEGIN); WRITE_STRING(fp, entry->name); @@ -185,55 +74,60 @@ static int write_shadow(TFILE *fp, struct shadow *entry, uid_t calleruid) return 0; } -MYLDAP_ENTRY *shadow_uid2entry(MYLDAP_SESSION *session, const char *username, - int *rcp) -{ - MYLDAP_SEARCH *search = NULL; - MYLDAP_ENTRY *entry = NULL; - const char *base; - char filter[BUFLEN_FILTER]; - int i; - /* if it isn't a valid username, just bail out now */ - if (!isvalidname(username)) +NSLCD_HANDLE_UID( + shadow, byname, NSLCD_ACTION_SHADOW_BYNAME + ,/* decls */ + char name[BUFLEN_NAME]; + struct shadow ret; + ,/* read */ + READ_STRING(fp, name); + log_setrequest("shadow=\"%s\"", name); + ,/* check */ + if (!isvalidname(name)) { - if (rcp != NULL) - *rcp = LDAP_INVALID_SYNTAX; - return NULL; + log_log(LOG_WARNING, "request denied by validnames option"); + return -1; } - /* we have to look up the entry */ - mkfilter_shadow_byname(username, filter, sizeof(filter)); - for (i = 0; (i < NSS_LDAP_CONFIG_MAX_BASES) && ((base = shadow_bases[i]) != NULL); i++) + ,/* search */ + struct shadow, + static size_t i = 0; + for (; i < session->cnt; i++) { - search = myldap_search(session, base, shadow_scope, filter, shadow_attrs, rcp); - if (search == NULL) + if (session->users[i].pw_uid > 0 && + STR_CMP(name, session->users[i].pw_name)==0) { - if ((rcp != NULL) && (*rcp == LDAP_SUCCESS)) - *rcp = LDAP_NO_SUCH_OBJECT; - return NULL; + *rcp = 0; + i = session->cnt; + passwd2shadow(&(session->users[i]), &ret); + return &ret; } - entry = myldap_get_entry(search, rcp); - if (entry != NULL) - return entry; } - if ((rcp != NULL) && (*rcp == LDAP_SUCCESS)) - *rcp = LDAP_NO_SUCH_OBJECT; return NULL; -} - -NSLCD_HANDLE_UID( - shadow, byname, NSLCD_ACTION_SHADOW_BYNAME, - char name[BUFLEN_NAME]; - char filter[BUFLEN_FILTER]; - READ_STRING(fp, name); - log_setrequest("shadow=\"%s\"", name);, - mkfilter_shadow_byname(name, filter, sizeof(filter)), - write_shadow(fp, entry, name, calleruid) + ,/* write */ + write_shadow(fp, entry, calleruid); + ,/* cleanup */ ) NSLCD_HANDLE_UID( - shadow, all, NSLCD_ACTION_SHADOW_ALL, - const char *filter; - log_setrequest("shadow(all)");, - (filter = shadow_filter, 0), - write_shadow(fp, entry, NULL, calleruid) + shadow, all, NSLCD_ACTION_SHADOW_ALL + ,/* decls */ + struct shadow ret; + ,/* read */ + log_setrequest("shadow(all)"); + ,/* check */ + ,/* search */ + struct shadow, + static size_t i = 0; + for (; i < session->cnt; i++) + { + if (session->users[i].pw_uid > 0) { + *rcp = 0; + passwd2shadow(&(session->users[i]), &ret); + return &ret; + } + } + return NULL; + ,/* write */ + write_shadow(fp, entry, calleruid); + ,/* cleanup */ ) diff --git a/nslcd/hackers_watch.h b/nslcd/hackers_watch.h index 156813e..09ff036 100644 --- a/nslcd/hackers_watch.h +++ b/nslcd/hackers_watch.h @@ -2,6 +2,7 @@ #define _HACKERS_WATCH_H #include +#include struct session { pthread_rwlock_t lock; diff --git a/nslcd/invalidator.c b/nslcd/invalidator.c index 7e8e415..7b9520b 100644 --- a/nslcd/invalidator.c +++ b/nslcd/invalidator.c @@ -22,6 +22,7 @@ #include "config.h" #include +#include #include #include #include diff --git a/nslcd/myldap.h b/nslcd/myldap.h deleted file mode 100644 index 952c68f..0000000 --- a/nslcd/myldap.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - myldap.h - simple interface to do LDAP requests - This file is part of the nss-pam-ldapd library. - - Copyright (C) 2007-2014 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 -*/ - -/* - This file describes the API of the myldap module which takes the complexity - out of using the OpenLDAP library. Memory management, paging, reconnect - logic, idle timeout of connections, etc is taken care of by the module. - - Use of this module is very straightforeward. You first have to create a - session (with myldap_create_session()), with this session you can start - searches (with myldap_search()), from a search you can get entries (with - myldap_get_entry()) from the LDAP database and from these entries you can - get attribute values (with myldap_get_values()). -*/ - -#ifndef NSLCD__MYLDAP_H -#define NSLCD__MYLDAP_H - -/* for size_t */ -#include -/* for LDAP_SCOPE_* */ -#include -#include - -#include "compat/attrs.h" - -#ifndef LDAP_SCOPE_DEFAULT -#define LDAP_SCOPE_DEFAULT LDAP_SCOPE_SUBTREE -#endif /* not LDAP_SCOPE_DEFAULT */ - -/* This a a generic session handle. */ -typedef struct ldap_session MYLDAP_SESSION; - -/* Note that this session handle may be used within one thread only. No - locking is performed to prevent concurrent modifications. Most LDAP - libraries also are not thread-safe in that a single connection may be - shared by multiple threads. It seems however that OpenLDAP at least does - not have any problems with an LDAP *ld per thread. - http://www.openldap.org/lists/openldap-software/200606/msg00252.html */ - -struct myldap_search { - MYLDAP_ENTRY *(*get_entry)(void *data, int *rcp); - void *data; -} -/* A result set as returned by myldap_search(). */ -typedef struct myldap_search MYLDAP_SEARCH; - -/* A single entry from the LDAP database as returned by myldap_get_entry(). */ -#define MYLDAP_ENTRY void; - -/* Create a new session, this does not yet connect to the LDAP server. The - connection to the server is made on-demand when a search is performed. This - uses the configuration to find the URLs to attempt connections to. */ -MUST_USE MYLDAP_SESSION *myldap_create_session(void); - -/* Set alternative credentials for the session. Returns 0 on success. */ -MUST_USE int myldap_set_credentials(MYLDAP_SESSION *session, const char *dn, - const char *password); - -/* Get bind ppolicy results from the last bind operation. This function - returns a NSLCD_PAM_* code and optional message. */ -void myldap_get_policy_response(MYLDAP_SESSION *session, int *response, - const char **message); - -/* Closes all pending searches and deallocates any memory that is allocated - 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); - -/* Mark all failing LDAP servers as needing quick retries. This ensures that the - reconnect_sleeptime and reconnect_retrytime sleeping period is cut short. */ -void myldap_immediate_reconnect(void); - -/* Do an LDAP search and return a reference to the results (returns NULL on - error). This function uses paging, and does reconnects to the configured - URLs transparently. The function returns an LDAP status code in the - location pointed to by rcp if it is non-NULL. */ -MUST_USE MYLDAP_SEARCH *myldap_search(MYLDAP_SESSION *session, - const char *base, int scope, - const char *filter, const char **attrs, - int *rcp); - -/* Close the specified search. This frees all the memory that was allocated - for the search and its results. */ -void myldap_search_close(MYLDAP_SEARCH *search); - -/* Get an entry from the result set, going over all results (returns NULL if - no more entries are available). Note that any memory allocated to return - information about the previous entry (e.g. with myldap_get_values()) is - freed with this call. The search is autoamtically closed when no more - results are available. The function returns an LDAP status code in the - location pointed to by rcp if it is non-NULL. */ -MUST_USE MYLDAP_ENTRY *myldap_get_entry(MYLDAP_SEARCH *search, int *rcp); - -/* Get the DN from the entry. This function does not return NULL (on error - "unknown" is returned). */ -MUST_USE const char *myldap_get_dn(MYLDAP_ENTRY *entry); - -/* Just like myldap_get_dn() but copies the result into the buffer. */ -char *myldap_cpy_dn(MYLDAP_ENTRY *entry, char *buf, size_t buflen); - -/* Get the attribute values from a certain entry as a NULL terminated list. - May return NULL or an empty array. */ -MUST_USE const char **myldap_get_values(MYLDAP_ENTRY *entry, const char *attr); - -/* Get the attribute values from a certain entry as a NULL terminated list. - May return NULL or an empty array. */ -MUST_USE const char **myldap_get_values_len(MYLDAP_ENTRY *entry, const char *attr); - -/* Checks to see if the entry has the specified object class. */ -MUST_USE int myldap_has_objectclass(MYLDAP_ENTRY *entry, const char *objectclass); - -/* See if the entry has any deref controls attached to it and deref attr - derefattr to get the getattr values. Will return two lists of attribute - values. One list of deref'ed attribute values and one list of original - attribute values that could not be deref'ed. */ -MUST_USE const char ***myldap_get_deref_values(MYLDAP_ENTRY *entry, - const char *derefattr, const char *getattr); - -/* Get the RDN's value: eg. if the DN was cn=lukeh, ou=People, dc=example, - dc=com getrdnvalue(entry, cn) would return lukeh. If the attribute was not - found in the DN or if some error occurs NULL is returned. This method may - be used to get the "most authorative" value for an attribute. */ -MUST_USE const char *myldap_get_rdn_value(MYLDAP_ENTRY *entry, const char *attr); - -/* Just like myldap_get_rdn_value() but use the supplied character sequence - and copies the result into the buffer. - Returns a pointer to the start of the string on success and NULL on - failure. */ -MUST_USE const char *myldap_cpy_rdn_value(const char *dn, const char *attr, - char *buf, size_t buflen); - -/* Escapes characters in a string for use in a search filter. */ -MUST_USE int myldap_escape(const char *src, char *buffer, size_t buflen); - -/* Set the debug level globally. Returns an LDAP status code. */ -int myldap_set_debuglevel(int level); - -/* Perform an EXOP password modification call. Returns an LDAP status code. */ -int myldap_passwd(MYLDAP_SESSION *session, - const char *userdn, const char *oldpassword, - const char *newpasswd); - -/* Perform an LDAP modification request. Returns an LDAP status code. */ -int myldap_modify(MYLDAP_SESSION *session, const char *dn, LDAPMod * mods[]); - -/* Get an LDAP error message from the supplied rc and optionally any extra - information in the connection. */ -int myldap_error_message(MYLDAP_SESSION *session, int rc, - char *buffer, size_t buflen); - -#endif /* not NSLCD__MYLDAP_H */ -- cgit v1.2.3