2
* lookup_ldap.c - Module for Linux automountd to access automount
3
* maps in LDAP directories.
5
* Copyright 2001-2003 Ian Kent <raven@themaw.net>
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
10
* USA; either version 2 of the License, or (at your option) any later
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
20
#include <sys/types.h>
27
#include <netinet/in.h>
28
#include <arpa/nameser.h>
34
#include "automount.h"
36
#include "lookup_ldap.h"
38
#define MAPFMT_DEFAULT "sun"
40
#define MODPREFIX "lookup(ldap): "
42
int lookup_version = AUTOFS_LOOKUP_VERSION; /* Required by protocol */
44
static struct ldap_schema common_schema[] = {
45
{"nisMap", "nisMapName", "nisObject", "cn", "nisMapEntry"},
46
{"automountMap", "ou", "automount", "cn", "automountInformation"},
47
{"automountMap", "automountMapName", "automount", "automountKey", "automountInformation"},
49
static unsigned int common_schema_count = sizeof(common_schema)/sizeof(struct ldap_schema);
51
struct ldap_search_params {
52
struct autofs_point *ap;
55
struct berval *cookie;
62
static int decode_percent_hack(const char *, char **);
64
#ifndef HAVE_LDAP_CREATE_PAGE_CONTROL
65
int ldap_create_page_control(LDAP *ldap, ber_int_t pagesize,
66
struct berval *cookie, char isCritical,
73
return LDAP_PARAM_ERROR;
75
ber = ber_alloc_t(LBER_USE_DER);
77
return LDAP_NO_MEMORY;
79
if (ber_printf(ber, "{io}", pagesize,
80
(cookie && cookie->bv_val) ? cookie->bv_val : "",
81
(cookie && cookie->bv_val) ? cookie->bv_len : 0)
84
return LDAP_ENCODING_ERROR;
87
rc = ldap_create_control(LDAP_CONTROL_PAGEDRESULTS, ber, isCritical, output);
91
#endif /* HAVE_LDAP_CREATE_PAGE_CONTROL */
93
#ifndef HAVE_LDAP_PARSE_PAGE_CONTROL
94
int ldap_parse_page_control(LDAP *ldap, LDAPControl **controls,
95
ber_int_t *totalcount, struct berval **cookie)
99
LDAPControl *listCtrlp;
101
for (i = 0; controls[i] != NULL; i++) {
102
if (strcmp(controls[i]->ldctl_oid, LDAP_CONTROL_PAGEDRESULTS) == 0) {
103
listCtrlp = controls[i];
105
theBer = ber_init(&listCtrlp->ldctl_value);
107
return LDAP_NO_MEMORY;
109
rc = ber_scanf(theBer, "{iO}", totalcount, cookie);
110
if (rc == LBER_ERROR) {
112
return LDAP_DECODING_ERROR;
120
return LDAP_CONTROL_NOT_FOUND;
122
#endif /* HAVE_LDAP_PARSE_PAGE_CONTROL */
124
static void uris_mutex_lock(struct lookup_context *ctxt)
126
int status = pthread_mutex_lock(&ctxt->uris_mutex);
132
static void uris_mutex_unlock(struct lookup_context *ctxt)
134
int status = pthread_mutex_unlock(&ctxt->uris_mutex);
140
int bind_ldap_anonymous(unsigned logopt, LDAP *ldap, const char *uri, struct lookup_context *ctxt)
144
if (ctxt->version == 2)
145
rv = ldap_simple_bind_s(ldap, ctxt->base, NULL);
147
rv = ldap_simple_bind_s(ldap, NULL, NULL);
149
if (rv != LDAP_SUCCESS) {
151
crit(logopt, MODPREFIX
152
"Unable to bind to the LDAP server: "
153
"%s, error %s", ctxt->server ? "" : "(default)",
154
ldap_err2string(rv));
156
info(logopt, MODPREFIX "Unable to bind to the LDAP server: "
157
"%s, error %s", uri, ldap_err2string(rv));
165
int unbind_ldap_connection(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
171
* The OpenSSL library can't handle having its message and error
172
* string database loaded multiple times and segfaults if the
173
* TLS environment is not reset at the right times. As there
174
* is no ldap_stop_tls call in the openldap library we have
175
* to do the job ourselves, here and in lookup_done when the
178
if (ctxt->use_tls == LDAP_TLS_RELEASE) {
180
ctxt->use_tls = LDAP_TLS_INIT;
182
autofs_sasl_unbind(ctxt);
185
rv = ldap_unbind_ext(ldap, NULL, NULL);
186
if (rv != LDAP_SUCCESS)
187
error(logopt, "unbind failed: %s", ldap_err2string(rv));
192
LDAP *init_ldap_connection(unsigned logopt, const char *uri, struct lookup_context *ctxt)
195
struct timeval timeout = { ctxt->timeout, 0 };
196
struct timeval net_timeout = { ctxt->network_timeout, 0 };
201
/* Initialize the LDAP context. */
202
rv = ldap_initialize(&ldap, uri);
203
if (rv != LDAP_OPT_SUCCESS) {
204
info(logopt, MODPREFIX
205
"couldn't initialize LDAP connection to %s",
206
uri ? uri : "default");
211
rv = ldap_set_option(ldap, LDAP_OPT_PROTOCOL_VERSION, &ctxt->version);
212
if (rv != LDAP_OPT_SUCCESS) {
213
/* fall back to LDAPv2 */
214
ldap_unbind_ext(ldap, NULL, NULL);
215
rv = ldap_initialize(&ldap, uri);
216
if (rv != LDAP_OPT_SUCCESS) {
217
crit(logopt, MODPREFIX "couldn't initialize LDAP");
224
if (ctxt->timeout != -1) {
225
/* Set synchronous call timeout */
226
rv = ldap_set_option(ldap, LDAP_OPT_TIMEOUT, &timeout);
227
if (rv != LDAP_OPT_SUCCESS)
228
info(logopt, MODPREFIX
229
"failed to set synchronous call timeout to %d",
233
/* Sane network timeout */
234
rv = ldap_set_option(ldap, LDAP_OPT_NETWORK_TIMEOUT, &net_timeout);
235
if (rv != LDAP_OPT_SUCCESS)
236
info(logopt, MODPREFIX "failed to set connection timeout to %d",
241
if (ctxt->version == 2) {
242
if (ctxt->tls_required) {
243
error(logopt, MODPREFIX
244
"TLS required but connection is version 2");
245
ldap_unbind_ext(ldap, NULL, NULL);
251
rv = ldap_start_tls_s(ldap, NULL, NULL);
252
if (rv != LDAP_SUCCESS) {
253
unbind_ldap_connection(logopt, ldap, ctxt);
254
if (ctxt->tls_required) {
255
error(logopt, MODPREFIX
256
"TLS required but START_TLS failed: %s",
257
ldap_err2string(rv));
260
ctxt->use_tls = LDAP_TLS_DONT_USE;
261
ldap = init_ldap_connection(logopt, uri, ctxt);
263
ctxt->use_tls = LDAP_TLS_INIT;
266
ctxt->use_tls = LDAP_TLS_RELEASE;
273
static int get_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt, const char *class, const char *key)
275
char buf[MAX_ERR_BUF];
276
char *query, *dn, *qdn;
277
LDAPMessage *result, *e;
278
struct ldap_searchdn *sdns = NULL;
280
struct berval **value;
284
attrs[0] = (char *) key;
287
if (!ctxt->mapname && !ctxt->base) {
288
error(logopt, MODPREFIX "no master map to lookup");
292
/* Build a query string. */
293
l = strlen("(objectclass=)") + strlen(class) + 1;
295
l += strlen(key) + strlen(ctxt->mapname) + strlen("(&(=))");
299
char *estr = strerror_r(errno, buf, sizeof(buf));
300
crit(logopt, MODPREFIX "malloc: %s", estr);
301
return NSS_STATUS_UNAVAIL;
305
* If we have a master mapname construct a query using it
306
* otherwise assume the base dn will catch it.
309
if (sprintf(query, "(&(objectclass=%s)(%s=%.*s))", class,
310
key, (int) strlen(ctxt->mapname), ctxt->mapname) >= l) {
312
MODPREFIX "error forming query string");
316
scope = LDAP_SCOPE_SUBTREE;
318
if (sprintf(query, "(objectclass=%s)", class) >= l) {
320
MODPREFIX "error forming query string");
324
scope = LDAP_SCOPE_SUBTREE;
328
sdns = defaults_get_searchdns();
331
defaults_free_searchdns(ctxt->sdns);
338
rv = ldap_search_s(ldap, ctxt->base,
339
scope, query, attrs, 0, &result);
340
if ((rv != LDAP_SUCCESS) || !result) {
342
MODPREFIX "query failed for %s: %s",
343
query, ldap_err2string(rv));
348
e = ldap_first_entry(ldap, result);
349
if (e && (value = ldap_get_values_len(ldap, e, key))) {
350
ldap_value_free_len(value);
351
dn = ldap_get_dn(ldap, e);
352
debug(logopt, MODPREFIX "found query dn %s", dn);
355
MODPREFIX "query succeeded, no matches for %s",
357
ldap_msgfree(result);
362
struct ldap_searchdn *this = ctxt->sdns;
364
debug(logopt, MODPREFIX "check search base list");
368
rv = ldap_search_s(ldap, this->basedn,
369
scope, query, attrs, 0, &result);
370
if ((rv == LDAP_SUCCESS) && result) {
371
debug(logopt, MODPREFIX
372
"found search base under %s",
375
e = ldap_first_entry(ldap, result);
376
if (e && (value = ldap_get_values_len(ldap, e, key))) {
377
ldap_value_free_len(value);
378
dn = ldap_get_dn(ldap, e);
379
debug(logopt, MODPREFIX "found query dn %s", dn);
383
MODPREFIX "query succeeded, no matches for %s",
385
ldap_msgfree(result);
390
MODPREFIX "query failed for search dn %s: %s",
391
this->basedn, ldap_err2string(rv));
393
ldap_msgfree(result);
403
MODPREFIX "failed to find query dn under search base dns");
412
ldap_msgfree(result);
424
static struct ldap_schema *alloc_common_schema(struct ldap_schema *s)
426
struct ldap_schema *schema;
427
char *mc, *ma, *ec, *ea, *va;
429
mc = strdup(s->map_class);
433
ma = strdup(s->map_attr);
439
ec = strdup(s->entry_class);
446
ea = strdup(s->entry_attr);
454
va = strdup(s->value_attr);
463
schema = malloc(sizeof(struct ldap_schema));
473
schema->map_class = mc;
474
schema->map_attr = ma;
475
schema->entry_class = ec;
476
schema->entry_attr = ea;
477
schema->value_attr = va;
482
static int find_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
484
struct ldap_schema *schema;
490
for (i = 0; i < common_schema_count; i++) {
491
const char *class = common_schema[i].map_class;
492
const char *key = common_schema[i].map_attr;
493
if (get_query_dn(logopt, ldap, ctxt, class, key)) {
494
schema = alloc_common_schema(&common_schema[i]);
496
error(logopt, MODPREFIX "failed to allocate schema");
499
ctxt->schema = schema;
507
static int do_bind(unsigned logopt, LDAP *ldap, const char *uri, struct lookup_context *ctxt)
509
char *host = NULL, *nhost;
510
int rv, need_base = 1;
513
debug(logopt, MODPREFIX "auth_required: %d, sasl_mech %s",
514
ctxt->auth_required, ctxt->sasl_mech);
516
if (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT)) {
517
rv = autofs_sasl_bind(logopt, ldap, ctxt);
518
debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv);
520
rv = bind_ldap_anonymous(logopt, ldap, uri, ctxt);
521
debug(logopt, MODPREFIX "ldap anonymous bind returned %d", rv);
524
rv = bind_ldap_anonymous(logopt, ldap, uri, ctxt);
525
debug(logopt, MODPREFIX "ldap anonymous bind returned %d", rv);
531
rv = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host);
532
if (rv != LDAP_SUCCESS || !host) {
533
debug(logopt, "failed to get hostname for connection");
537
nhost = strdup(host);
539
debug(logopt, "failed to alloc context for hostname");
544
if (!ctxt->cur_host) {
545
ctxt->cur_host = nhost;
546
/* Check if schema defined in conf first time only */
547
ctxt->schema = defaults_get_schema();
549
/* If connection host has changed update */
550
if (strcmp(ctxt->cur_host, nhost)) {
551
free(ctxt->cur_host);
552
ctxt->cur_host = nhost;
559
if (ctxt->schema && !need_base)
563
* If the schema isn't defined in the configuration then check for
564
* presence of a map dn with a the common schema. Then calculate the
565
* base dn for searches.
568
if (!find_query_dn(logopt, ldap, ctxt)) {
570
MODPREFIX "failed to find valid query dn");
574
const char *class = ctxt->schema->map_class;
575
const char *key = ctxt->schema->map_attr;
576
if (!get_query_dn(logopt, ldap, ctxt, class, key)) {
577
error(logopt, MODPREFIX "failed to get query dn");
585
static LDAP *do_connect(unsigned logopt, const char *uri, struct lookup_context *ctxt)
589
ldap = init_ldap_connection(logopt, uri, ctxt);
593
if (!do_bind(logopt, ldap, uri, ctxt)) {
594
unbind_ldap_connection(logopt, ldap, ctxt);
601
static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_context *ctxt)
605
ldap = do_connect(logopt, uri, ctxt);
608
MODPREFIX "couldn't connect to server %s",
609
uri ? uri : "default");
616
static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt)
619
struct ldap_uri *this;
620
struct list_head *p, *first;
621
struct dclist *dclist = NULL;
624
uris_mutex_lock(ctxt);
626
dclist = ctxt->dclist;
627
if (ctxt->dclist->expire < time(NULL)) {
628
free_dclist(ctxt->dclist);
636
first = &ctxt->uri->list;
637
uris_mutex_unlock(ctxt);
640
/* Try each uri, save point in server list upon success */
644
if (p == ctxt->uris) {
648
this = list_entry(p, struct ldap_uri, list);
649
if (!strstr(this->uri, ":///"))
650
uri = strdup(this->uri);
653
uri = strdup(dclist->uri);
656
tmp = get_dc_list(logopt, this->uri);
662
uri = strdup(dclist->uri);
673
debug(logopt, "trying server uri %s", uri);
674
ldap = connect_to_server(logopt, uri, ctxt);
676
info(logopt, "connected to uri %s", uri);
689
uris_mutex_lock(ctxt);
694
ctxt->dclist = dclist;
696
if (ctxt->dclist != dclist) {
697
free_dclist(ctxt->dclist);
698
ctxt->dclist = dclist;
702
uris_mutex_unlock(ctxt);
707
static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt)
712
if (ctxt->server || !ctxt->uris) {
713
ldap = do_connect(logopt, ctxt->server, ctxt);
715
/* Dispose of the sasl authentication connection and try again. */
717
autofs_sasl_dispose(ctxt);
718
ldap = connect_to_server(logopt, ctxt->server, ctxt);
724
uris_mutex_lock(ctxt);
726
uri = strdup(ctxt->dclist->uri);
728
uri = strdup(ctxt->uri->uri);
730
uris_mutex_unlock(ctxt);
733
uris_mutex_unlock(ctxt);
736
char buf[MAX_ERR_BUF];
737
char *estr = strerror_r(errno, buf, sizeof(buf));
738
crit(logopt, MODPREFIX "strdup: %s", estr);
742
ldap = do_connect(logopt, uri, ctxt);
745
* Dispose of the sasl authentication connection and try the
746
* current server again before trying other servers in the list.
749
autofs_sasl_dispose(ctxt);
750
ldap = connect_to_server(logopt, uri, ctxt);
758
/* Failed to connect, try to find a new server */
761
autofs_sasl_dispose(ctxt);
765
/* Current server failed connect, try the rest */
766
ldap = find_server(logopt, ctxt);
768
error(logopt, MODPREFIX "failed to find available server");
774
int get_property(unsigned logopt, xmlNodePtr node, const char *prop, char **value)
777
xmlChar *property = (xmlChar *) prop;
779
if (!(ret = xmlGetProp(node, property))) {
784
if (!(*value = strdup((char *) ret))) {
785
logerr(MODPREFIX "strdup failed with %d", errno);
795
* For plain text, login and digest-md5 authentication types, we need
796
* user and password credentials.
798
int authtype_requires_creds(const char *authtype)
800
if (!strncmp(authtype, "PLAIN", strlen("PLAIN")) ||
801
!strncmp(authtype, "DIGEST-MD5", strlen("DIGEST-MD5")) ||
802
!strncmp(authtype, "LOGIN", strlen("LOGIN")))
809
* -1 -- The permission on the file are not correct or
810
* the xml document was mal-formed
811
* 0 -- The file was non-existent
813
* the file contained valid data, which was filled into
814
* ctxt->sasl_mech, ctxt->user, and ctxt->secret
816
* The idea is that a -1 return value should abort the program. A 0
817
* return value requires more checking. If ctxt->authtype is filled in,
818
* then no further action is necessary. If it is not, the caller is free
819
* to then use another method to determine how to connect to the server.
821
int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt)
823
int ret = 0, fallback = 0;
824
unsigned int auth_required = LDAP_AUTH_NOTREQUIRED;
825
unsigned int tls_required = 0, use_tls = 0;
827
xmlDocPtr doc = NULL;
828
xmlNodePtr root = NULL;
829
char *authrequired, *auth_conf, *authtype;
830
char *user = NULL, *secret = NULL;
831
char *client_princ = NULL, *client_cc = NULL;
832
char *usetls, *tlsrequired;
834
authtype = user = secret = NULL;
836
auth_conf = (char *) defaults_get_auth_conf_file();
839
MODPREFIX "failed to get auth config file name.");
844
* Here we check that the config file exists, and that we have
845
* permission to read it. The XML library does not specify why a
846
* parse happens to fail, so we have to do all of this checking
849
memset(&st, 0, sizeof(st));
850
if (stat(auth_conf, &st) == -1 || st.st_size == 0) {
851
/* Auth config doesn't exist so disable TLS and auth */
852
if (errno == ENOENT) {
853
ctxt->auth_conf = auth_conf;
854
ctxt->use_tls = LDAP_TLS_DONT_USE;
855
ctxt->tls_required = LDAP_TLS_DONT_USE;
856
ctxt->auth_required = LDAP_AUTH_NOTREQUIRED;
857
ctxt->sasl_mech = NULL;
860
ctxt->client_princ = NULL;
864
MODPREFIX "stat(2) failed with error %s.",
869
if (!S_ISREG(st.st_mode) ||
870
st.st_uid != 0 || st.st_gid != 0 ||
871
(st.st_mode & 0x01ff) != 0600) {
872
error(logopt, MODPREFIX
873
"Configuration file %s exists, but is not usable. "
874
"Please make sure that it is owned by root, group "
875
"is root, and the mode is 0600.",
880
doc = xmlParseFile(auth_conf);
882
error(logopt, MODPREFIX
883
"xmlParseFile failed for %s.", auth_conf);
887
root = xmlDocGetRootElement(doc);
889
debug(logopt, MODPREFIX
890
"empty xml document (%s).", auth_conf);
895
if (xmlStrcmp(root->name, (const xmlChar *)"autofs_ldap_sasl_conf")) {
896
error(logopt, MODPREFIX
897
"The root node of the XML document %s is not "
898
"autofs_ldap_sasl_conf.", auth_conf);
902
ret = get_property(logopt, root, "usetls", &usetls);
906
"Failed read the usetls property from "
907
"the configuration file %s.", auth_conf);
911
if (!usetls || ctxt->port == LDAPS_PORT)
912
use_tls = LDAP_TLS_DONT_USE;
914
if (!strcasecmp(usetls, "yes"))
915
use_tls = LDAP_TLS_INIT;
916
else if (!strcasecmp(usetls, "no"))
917
use_tls = LDAP_TLS_DONT_USE;
921
"The usetls property must have value "
922
"\"yes\" or \"no\".");
929
ret = get_property(logopt, root, "tlsrequired", &tlsrequired);
933
"Failed read the tlsrequired property from "
934
"the configuration file %s.", auth_conf);
939
tls_required = LDAP_TLS_DONT_USE;
941
if (!strcasecmp(tlsrequired, "yes"))
942
tls_required = LDAP_TLS_REQUIRED;
943
else if (!strcasecmp(tlsrequired, "no"))
944
tls_required = LDAP_TLS_DONT_USE;
948
"The tlsrequired property must have value "
949
"\"yes\" or \"no\".");
956
ret = get_property(logopt, root, "authrequired", &authrequired);
960
"Failed read the authrequired property from "
961
"the configuration file %s.", auth_conf);
966
auth_required = LDAP_AUTH_NOTREQUIRED;
968
if (!strcasecmp(authrequired, "yes"))
969
auth_required = LDAP_AUTH_REQUIRED;
970
else if (!strcasecmp(authrequired, "no"))
971
auth_required = LDAP_AUTH_NOTREQUIRED;
972
else if (!strcasecmp(authrequired, "autodetect"))
973
auth_required = LDAP_AUTH_AUTODETECT;
977
"The authrequired property must have value "
978
"\"yes\", \"no\" or \"autodetect\".");
985
ret = get_property(logopt, root, "authtype", &authtype);
989
"Failed read the authtype property from the "
990
"configuration file %s.", auth_conf);
994
if (authtype && authtype_requires_creds(authtype)) {
995
ret = get_property(logopt, root, "user", &user);
996
ret |= get_property(logopt, root, "secret", &secret);
997
if (ret != 0 || (!user || !secret)) {
1000
"%s authentication type requires a username "
1001
"and a secret. Please fix your configuration "
1002
"in %s.", authtype, auth_conf);
1015
* We allow the admin to specify the principal to use for the
1016
* client. The default is "autofsclient/hostname@REALM".
1018
(void)get_property(logopt, root, "clientprinc", &client_princ);
1019
(void)get_property(logopt, root, "credentialcache", &client_cc);
1021
ctxt->auth_conf = auth_conf;
1022
ctxt->use_tls = use_tls;
1023
ctxt->tls_required = tls_required;
1024
ctxt->auth_required = auth_required;
1025
ctxt->sasl_mech = authtype;
1026
if (!authtype && (auth_required & LDAP_AUTH_REQUIRED))
1027
ctxt->auth_required |= LDAP_AUTH_AUTODETECT;
1029
ctxt->secret = secret;
1030
ctxt->client_princ = client_princ;
1031
ctxt->client_cc = client_cc;
1033
debug(logopt, MODPREFIX
1034
"ldap authentication configured with the following options:");
1035
debug(logopt, MODPREFIX
1037
"tls_required: %u, "
1038
"auth_required: %u, "
1040
use_tls, tls_required, auth_required, authtype);
1041
debug(logopt, MODPREFIX
1044
"client principal: %s "
1045
"credential cache: %s",
1046
user, secret ? "specified" : "unspecified",
1047
client_princ, client_cc);
1060
* Take an input string as specified in the master map, and break it
1061
* down into a server name and basedn.
1063
static int parse_server_string(unsigned logopt, const char *url, struct lookup_context *ctxt)
1065
char buf[MAX_ERR_BUF], *tmp = NULL, proto[9];
1066
const char *ptr, *name;
1069
memset(proto, 0, 9);
1072
debug(logopt, MODPREFIX
1073
"Attempting to parse LDAP information from string \"%s\".", ptr);
1075
ctxt->port = LDAP_PORT;
1076
if (!strncmp(ptr, "ldap:", 5) || !strncmp(ptr, "ldaps:", 6)) {
1077
if (*(ptr + 4) == 's') {
1078
ctxt->port = LDAPS_PORT;
1079
memcpy(proto, ptr, 6);
1080
strcat(proto, "//");
1083
memcpy(proto, ptr, 5);
1084
strcat(proto, "//");
1089
if (!strncmp(ptr, "//", 2)) {
1090
const char *s = ptr + 2;
1091
const char *q = NULL;
1093
/* Isolate the server(s). */
1094
if ((q = strchr(s, '/'))) {
1097
al_len = l + strlen(proto) + 2;
1098
tmp = malloc(al_len);
1101
tmp = malloc(al_len);
1105
estr = strerror_r(errno, buf, sizeof(buf));
1106
logerr(MODPREFIX "malloc: %s", estr);
1110
memset(ctxt->server, 0, al_len);
1112
strcpy(ctxt->server, proto);
1113
memcpy(ctxt->server + strlen(proto), s, l);
1114
strcat(ctxt->server, "/");
1116
memcpy(ctxt->server, s, l);
1120
MODPREFIX "invalid LDAP map syntax %s", ptr);
1122
/* TODO: why did I put this here, the parser shouldn't let this by
1124
tmp = malloc(l + 1);
1127
estr = strerror_r(errno, buf, sizeof(buf));
1128
crit(logopt, MODPREFIX "malloc: %s", estr);
1132
memset(ctxt->server, 0, l + 1);
1133
memcpy(ctxt->server, s, l);
1136
} else if (strchr(ptr, ':') != NULL || *ptr == '[') {
1137
const char *q = NULL;
1139
/* Isolate the server. Include the port spec */
1141
q = strchr(ptr, ':');
1144
while (*q == ':' || isxdigit(*q))
1147
crit(logopt, MODPREFIX
1148
"invalid LDAP map syntax %s", ptr);
1162
MODPREFIX "invalid LDAP map syntax %s", ptr);
1168
al_len = l + strlen(proto) + 2;
1169
tmp = malloc(al_len);
1172
tmp = malloc(al_len);
1174
/* Isolate the server's name. */
1177
estr = strerror_r(errno, buf, sizeof(buf));
1178
logerr(MODPREFIX "malloc: %s", estr);
1182
memset(ctxt->server, 0, al_len);
1184
strcpy(ctxt->server, proto);
1185
memcpy(ctxt->server + strlen(proto), ptr, l);
1186
strcat(ctxt->server, "/");
1188
memcpy(ctxt->server, ptr, l);
1192
/* TODO: why did I do this - how can the map name "and" base dn be missing? */
1197
* For nss support we can have a map name with no
1198
* type or dn info. If present a base dn must have
1199
* at least an "=" and a "," to be at all functional.
1200
* If a dn is given it must be fully specified or
1201
* the later LDAP calls will fail.
1204
if ((name = strchr(ptr, '='))) {
1208
* An '=' with no ',' means a mapname has been given so just
1209
* grab it alone to keep it independent of schema otherwize
1210
* we expect a full dn.
1212
if (!strchr(ptr, ',')) {
1213
char *map = strdup(name + 1);
1215
ctxt->mapname = map;
1218
estr = strerror_r(errno, buf, sizeof(buf));
1219
logerr(MODPREFIX "strdup: %s", estr);
1226
base = malloc(l + 1);
1229
estr = strerror_r(errno, buf, sizeof(buf));
1230
logerr(MODPREFIX "malloc: %s", estr);
1236
memset(ctxt->base, 0, l + 1);
1237
memcpy(ctxt->base, ptr, l);
1240
char *map = malloc(l + 1);
1243
estr = strerror_r(errno, buf, sizeof(buf));
1244
logerr(MODPREFIX "malloc: %s", estr);
1249
ctxt->mapname = map;
1250
memset(ctxt->mapname, 0, l + 1);
1251
memcpy(map, ptr, l);
1254
if (!ctxt->server && *proto) {
1255
if (!strncmp(proto, "ldaps", 5)) {
1256
info(logopt, MODPREFIX
1257
"server must be given to force ldaps, connection "
1258
"will use LDAP client configured protocol");
1263
debug(logopt, MODPREFIX "mapname %s", ctxt->mapname);
1265
debug(logopt, MODPREFIX "server \"%s\", base dn \"%s\"",
1266
ctxt->server ? ctxt->server : "(default)",
1272
static void free_context(struct lookup_context *ctxt)
1277
free(ctxt->schema->map_class);
1278
free(ctxt->schema->map_attr);
1279
free(ctxt->schema->entry_class);
1280
free(ctxt->schema->entry_attr);
1281
free(ctxt->schema->value_attr);
1284
if (ctxt->auth_conf)
1285
free(ctxt->auth_conf);
1286
if (ctxt->sasl_mech)
1287
free(ctxt->sasl_mech);
1292
if (ctxt->client_princ)
1293
free(ctxt->client_princ);
1294
if (ctxt->client_cc)
1295
free(ctxt->client_cc);
1297
free(ctxt->mapname);
1303
free(ctxt->cur_host);
1307
defaults_free_uris(ctxt->uris);
1308
ret = pthread_mutex_destroy(&ctxt->uris_mutex);
1312
defaults_free_searchdns(ctxt->sdns);
1314
free_dclist(ctxt->dclist);
1320
static void validate_uris(struct list_head *list)
1322
struct list_head *next;
1325
while (next != list) {
1326
struct ldap_uri *this;
1328
this = list_entry(next, struct ldap_uri, list);
1331
/* At least we get some basic validation */
1332
if (!ldap_is_ldap_url(this->uri)) {
1333
list_del(&this->list);
1343
* This initializes a context (persistent non-global data) for queries to
1344
* this module. Return zero if we succeed.
1346
int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context)
1348
struct lookup_context *ctxt;
1349
char buf[MAX_ERR_BUF];
1354
/* If we can't build a context, bail. */
1355
ctxt = malloc(sizeof(struct lookup_context));
1357
char *estr = strerror_r(errno, buf, sizeof(buf));
1358
logerr(MODPREFIX "malloc: %s", estr);
1361
memset(ctxt, 0, sizeof(struct lookup_context));
1363
ret = pthread_mutex_init(&ctxt->uris_mutex, NULL);
1365
error(LOGOPT_ANY, MODPREFIX "failed to init uris mutex");
1370
/* If a map type isn't explicitly given, parse it like sun entries. */
1372
mapfmt = MAPFMT_DEFAULT;
1375
* Parse out the server name and base dn, and fill them
1376
* into the proper places in the lookup context structure.
1378
if (!parse_server_string(LOGOPT_NONE, argv[0], ctxt)) {
1379
error(LOGOPT_ANY, MODPREFIX "cannot parse server string");
1384
ctxt->timeout = defaults_get_ldap_timeout();
1385
ctxt->network_timeout = defaults_get_ldap_network_timeout();
1387
if (!ctxt->server) {
1388
struct list_head *uris = defaults_get_uris();
1390
validate_uris(uris);
1391
if (!list_empty(uris))
1395
"no valid uris found in config list"
1396
", using default system config");
1404
* First, check to see if a preferred authentication method was
1405
* specified by the user. parse_ldap_config will return error
1406
* if the permissions on the file were incorrect, or if the
1407
* specified authentication type is not valid.
1409
ret = parse_ldap_config(LOGOPT_NONE, ctxt);
1415
/* Init the sasl callbacks */
1416
if (!autofs_sasl_client_init(LOGOPT_NONE)) {
1417
error(LOGOPT_ANY, "failed to init sasl client");
1423
/* Open the parser, if we can. */
1424
ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
1427
logerr(MODPREFIX "failed to open parse context");
1435
int lookup_read_master(struct master *master, time_t age, void *context)
1437
struct lookup_context *ctxt = (struct lookup_context *) context;
1438
unsigned int timeout = master->default_timeout;
1439
unsigned int logging = master->default_logging;
1440
unsigned int logopt = master->logopt;
1442
char buf[MAX_ERR_BUF];
1443
char parse_buf[PARSE_MAX_BUF];
1445
LDAPMessage *result, *e;
1446
char *class, *info, *entry;
1447
char **keyValue = NULL;
1448
char **values = NULL;
1450
int scope = LDAP_SCOPE_SUBTREE;
1453
/* Initialize the LDAP context. */
1454
ldap = do_reconnect(logopt, ctxt);
1456
return NSS_STATUS_UNAVAIL;
1458
class = ctxt->schema->entry_class;
1459
entry = ctxt->schema->entry_attr;
1460
info = ctxt->schema->value_attr;
1466
l = strlen("(objectclass=)") + strlen(class) + 1;
1469
if (query == NULL) {
1470
char *estr = strerror_r(errno, buf, sizeof(buf));
1471
logerr(MODPREFIX "malloc: %s", estr);
1472
return NSS_STATUS_UNAVAIL;
1475
if (sprintf(query, "(objectclass=%s)", class) >= l) {
1476
error(logopt, MODPREFIX "error forming query string");
1478
return NSS_STATUS_UNAVAIL;
1483
MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn);
1485
rv = ldap_search_s(ldap, ctxt->qdn, scope, query, attrs, 0, &result);
1487
if ((rv != LDAP_SUCCESS) || !result) {
1488
error(logopt, MODPREFIX "query failed for %s: %s",
1489
query, ldap_err2string(rv));
1490
unbind_ldap_connection(logging, ldap, ctxt);
1492
return NSS_STATUS_NOTFOUND;
1495
e = ldap_first_entry(ldap, result);
1498
MODPREFIX "query succeeded, no matches for %s",
1500
ldap_msgfree(result);
1501
unbind_ldap_connection(logging, ldap, ctxt);
1503
return NSS_STATUS_NOTFOUND;
1505
debug(logopt, MODPREFIX "examining entries");
1511
keyValue = ldap_get_values(ldap, e, entry);
1513
if (!keyValue || !*keyValue) {
1514
e = ldap_next_entry(ldap, e);
1519
* By definition keys must be unique within
1522
count = ldap_count_values(keyValue);
1523
if (strcasecmp(class, "nisObject")) {
1525
error(logopt, MODPREFIX
1526
"key %s has duplicates - ignoring",
1530
key = strdup(keyValue[0]);
1532
error(logopt, MODPREFIX
1533
"failed to dup map key %s - ignoring",
1537
} else if (count == 1) {
1538
dec_len = decode_percent_hack(keyValue[0], &key);
1540
error(logopt, MODPREFIX
1541
"invalid map key %s - ignoring",
1546
dec_len = decode_percent_hack(keyValue[0], &key);
1548
error(logopt, MODPREFIX
1549
"invalid map key %s - ignoring",
1554
for (i = 1; i < count; i++) {
1556
dec_len = decode_percent_hack(keyValue[i], &k);
1558
error(logopt, MODPREFIX
1559
"invalid map key %s - ignoring",
1563
if (strcmp(key, k)) {
1564
error(logopt, MODPREFIX
1565
"key entry mismatch %s - ignoring",
1575
* Ignore keys beginning with '+' as plus map
1576
* inclusion is only valid in file maps.
1581
"ignoreing '+' map entry - not in file map");
1585
values = ldap_get_values(ldap, e, info);
1586
if (!values || !*values) {
1588
MODPREFIX "no %s defined for %s", info, query);
1593
* We require that there be only one value per key.
1595
count = ldap_count_values(values);
1599
"one value per key allowed in master map");
1600
ldap_value_free(values);
1604
if (snprintf(parse_buf, sizeof(parse_buf), "%s %s",
1605
key, *values) >= sizeof(parse_buf)) {
1606
error(logopt, MODPREFIX "map entry too long");
1607
ldap_value_free(values);
1610
ldap_value_free(values);
1612
master_parse_entry(parse_buf, timeout, logging, age);
1614
ldap_value_free(keyValue);
1617
e = ldap_next_entry(ldap, e);
1621
ldap_msgfree(result);
1622
unbind_ldap_connection(logopt, ldap, ctxt);
1625
return NSS_STATUS_SUCCESS;
1628
static int get_percent_decoded_len(const char *name)
1632
const char *tmp = name;
1633
int look_for_close = 0;
1637
/* assume escapes aren't interpreted inside brackets */
1638
if (look_for_close) {
1642
/* check for escaped % */
1656
} else if (*tmp == ']' && look_for_close) {
1667
assert(strlen(name) > escapes);
1668
return strlen(name) - escapes;
1672
* Try to catch heap corruption if our logic happens to be incorrect.
1674
static void validate_string_len(const char *orig, char *start,
1675
char *end, unsigned int len)
1677
debug(LOGOPT_NONE, MODPREFIX "string %s encoded as %s", orig, start);
1678
/* make sure we didn't overflow the allocated space */
1679
if (end - start > len + 1) {
1680
crit(LOGOPT_ANY, MODPREFIX "orig %s, len %d", orig, len);
1681
crit(LOGOPT_ANY, MODPREFIX "en/decoded %s, len %d", start,
1684
assert(end-start <= len + 1);
1688
* Deal with encode and decode of % hack.
1690
* 0 => % hack not present.
1691
* -1 => syntax error or alloc fail.
1692
* 1 transofrmed value returned.
1695
* Assumptions: %'s must be escaped by %'s. %'s are not used to escape
1696
* anything else except capital letters (so you can't escape a closing
1697
* bracket, for example).
1699
static int decode_percent_hack(const char *name, char **key)
1704
int escaped = 0, look_for_close = 0;
1711
len = get_percent_decoded_len(name);
1712
new = malloc(len + 1);
1722
if (!look_for_close)
1733
} else if (*tmp == ']' && look_for_close) {
1744
validate_string_len(name, new, ptr, len);
1749
* Calculate the length of a string replacing all capital letters with %letter.
1754
static int get_encoded_len_escaping_every_cap(const char *name)
1757
unsigned int escapes = 0; /* number of % escape characters */
1761
/* We'll need to escape percents */
1762
if (*tmp == '%' || isupper(*tmp))
1767
return strlen(name) + escapes;
1771
* Calculate the length of a string replacing sequences (1 or more) of capital
1772
* letters with %[letters]. For example:
1775
* WorksForMe -> %[W]orks%[F]or%[M]e
1776
* aaBBaa -> aa%[BB]aa
1778
static int get_encoded_len_escaping_sequences(const char *name)
1781
unsigned int escapes = 0;
1785
/* escape percents */
1788
else if (isupper(*tmp)) {
1789
/* start an escape block %[...] */
1790
escapes += 3; /* %[] */
1791
while (*tmp && isupper(*tmp))
1798
return strlen(name) + escapes;
1801
static void encode_individual(const char *name, char *new, unsigned int len)
1809
if (*tmp == '%' || isupper(*tmp))
1814
validate_string_len(name, new, ptr, len);
1817
static void encode_sequence(const char *name, char *new, unsigned int len)
1828
} else if (isupper(*tmp)) {
1833
while (*tmp && isupper(*tmp)) {
1842
validate_string_len(name, new, ptr, len);
1846
* use_class: 1 means encode string as %[CAPITALS], 0 means encode as
1849
static int encode_percent_hack(const char *name, char **key, unsigned int use_class)
1851
unsigned int len = 0;
1857
len = get_encoded_len_escaping_sequences(name);
1859
len = get_encoded_len_escaping_every_cap(name);
1861
/* If there is no escaping to be done, return 0 */
1862
if (len == strlen(name))
1865
*key = malloc(len + 1);
1870
encode_sequence(name, *key, len);
1872
encode_individual(name, *key, len);
1874
if (strlen(*key) != len)
1875
crit(LOGOPT_ANY, MODPREFIX "encoded key length mismatch: key "
1876
"%s len %d strlen %d", *key, len, strlen(*key));
1878
return strlen(*key);
1881
static int do_paged_query(struct ldap_search_params *sp, struct lookup_context *ctxt)
1883
struct autofs_point *ap = sp->ap;
1884
LDAPControl *pageControl=NULL, *controls[2] = { NULL, NULL };
1885
LDAPControl **returnedControls = NULL;
1886
static ber_int_t pageSize = 1000;
1887
static char pagingCriticality = 'T';
1888
int rv, scope = LDAP_SCOPE_SUBTREE;
1890
if (sp->morePages == TRUE)
1893
rv = ldap_search_s(sp->ldap, ctxt->qdn, scope, sp->query, sp->attrs, 0, &sp->result);
1894
if ((rv != LDAP_SUCCESS) || !sp->result) {
1896
* Check for Size Limit exceeded and force run through loop
1897
* and requery using page control.
1899
if (rv == LDAP_SIZELIMIT_EXCEEDED)
1900
sp->morePages = TRUE;
1903
MODPREFIX "query failed for %s: %s",
1904
sp->query, ldap_err2string(rv));
1911
/* we need to use page controls so requery LDAP */
1912
debug(ap->logopt, MODPREFIX "geting page of results");
1914
rv = ldap_create_page_control(sp->ldap, pageSize, sp->cookie,
1915
pagingCriticality, &pageControl);
1916
if (rv != LDAP_SUCCESS) {
1917
warn(ap->logopt, MODPREFIX "failed to create page control");
1921
/* Insert the control into a list to be passed to the search. */
1922
controls[0] = pageControl;
1924
/* Search for entries in the directory using the parmeters. */
1925
rv = ldap_search_ext_s(sp->ldap,
1926
ctxt->qdn, scope, sp->query, sp->attrs,
1927
0, controls, NULL, NULL, 0, &sp->result);
1928
if ((rv != LDAP_SUCCESS) && (rv != LDAP_PARTIAL_RESULTS)) {
1930
MODPREFIX "query failed for %s: %s",
1931
sp->query, ldap_err2string(rv));
1932
ldap_control_free(pageControl);
1936
/* Parse the results to retrieve the contols being returned. */
1937
rv = ldap_parse_result(sp->ldap, sp->result,
1938
NULL, NULL, NULL, NULL,
1939
&returnedControls, FALSE);
1940
if (sp->cookie != NULL) {
1941
ber_bvfree(sp->cookie);
1945
if (rv != LDAP_SUCCESS) {
1947
MODPREFIX "ldap_parse_result failed with %d", rv);
1952
* Parse the page control returned to get the cookie and
1953
* determine whether there are more pages.
1955
rv = ldap_parse_page_control(sp->ldap,
1956
returnedControls, &sp->totalCount,
1958
if (sp->cookie && sp->cookie->bv_val && strlen(sp->cookie->bv_val))
1959
sp->morePages = TRUE;
1961
sp->morePages = FALSE;
1963
/* Cleanup the controls used. */
1964
if (returnedControls)
1965
ldap_controls_free(returnedControls);
1968
ldap_control_free(pageControl);
1972
static int do_get_entries(struct ldap_search_params *sp, struct map_source *source, struct lookup_context *ctxt)
1974
struct autofs_point *ap = sp->ap;
1975
struct mapent_cache *mc = source->mc;
1976
char buf[MAX_ERR_BUF];
1977
struct berval **bvKey;
1978
struct berval **bvValues;
1980
char *class, *info, *entry;
1984
class = ctxt->schema->entry_class;
1985
entry = ctxt->schema->entry_attr;
1986
info = ctxt->schema->value_attr;
1988
e = ldap_first_entry(sp->ldap, sp->result);
1991
MODPREFIX "query succeeded, no matches for %s",
1993
ret = ldap_parse_result(sp->ldap, sp->result,
1994
&rv, NULL, NULL, NULL, NULL, 0);
1995
if (ret == LDAP_SUCCESS)
1998
return LDAP_OPERATIONS_ERROR;
2000
debug(ap->logopt, MODPREFIX "examining entries");
2003
char *mapent = NULL;
2004
size_t mapent_len = 0;
2009
bvKey = ldap_get_values_len(sp->ldap, e, entry);
2010
if (!bvKey || !*bvKey) {
2011
e = ldap_next_entry(sp->ldap, e);
2013
debug(ap->logopt, MODPREFIX
2014
"failed to get next entry for query %s",
2016
ret = ldap_parse_result(sp->ldap,
2018
NULL, NULL, NULL, NULL, 0);
2019
if (ret == LDAP_SUCCESS)
2022
return LDAP_OPERATIONS_ERROR;
2028
* By definition keys should be unique within each map entry,
2029
* but as always there are exceptions.
2035
* Keys should be unique so, in general, there shouldn't be
2036
* more than one attribute value. We make an exception for
2037
* wildcard entries as people may have values for '*' or
2038
* '/' for compaibility reasons. We use the '/' as the
2039
* wildcard in LDAP but allow '*' as well to allow for
2040
* people using older schemas that allow '*' as a key
2041
* value. Another case where there can be multiple key
2042
* values is when people have used the "%" hack to specify
2043
* case matching ctriteria in a case insensitive attribute.
2045
count = ldap_count_values_len(bvKey);
2049
/* Check for the "/" and "*" and use as "/" if found */
2050
for (i = 0; i < count; i++) {
2051
bvKey[i]->bv_val[bvKey[i]->bv_len] = '\0';
2054
* If multiple entries are present they could
2055
* be the result of people using the "%" hack so
2058
if (strchr(bvKey[i]->bv_val, '%'))
2061
/* check for wildcard */
2062
if (bvKey[i]->bv_len == 1 &&
2063
(*bvKey[i]->bv_val == '/' ||
2064
*bvKey[i]->bv_val == '*')) {
2065
/* always use '/' internally */
2066
*bvKey[i]->bv_val = '/';
2067
k_val = bvKey[i]->bv_val;
2073
* We have a result from LDAP so this is a
2074
* valid entry. Set the result to the LDAP
2075
* key that isn't a wildcard and doesn't have
2076
* any "%" hack values present. This should be
2077
* the case insensitive match string for the
2078
* nis schema, the default value.
2080
k_val = bvKey[i]->bv_val;
2081
k_len = bvKey[i]->bv_len;
2088
MODPREFIX "invalid entry %.*s - ignoring",
2089
bvKey[0]->bv_len, bvKey[0]->bv_val);
2093
/* Check for the "*" and use as "/" if found */
2094
if (bvKey[0]->bv_len == 1 && *bvKey[0]->bv_val == '*')
2095
*bvKey[0]->bv_val = '/';
2096
k_val = bvKey[0]->bv_val;
2097
k_len = bvKey[0]->bv_len;
2101
* Ignore keys beginning with '+' as plus map
2102
* inclusion is only valid in file maps.
2104
if (*k_val == '+') {
2107
"ignoreing '+' map entry - not in file map");
2111
bvValues = ldap_get_values_len(sp->ldap, e, info);
2112
if (!bvValues || !*bvValues) {
2114
MODPREFIX "no %s defined for %s", info, sp->query);
2119
* We expect that there will be only one value because
2120
* questions of order of returned value entries but we
2121
* accumulate values to support simple multi-mounts.
2123
* If the ordering of a mount spec with another containing
2124
* options or the actual order of entries causes problems
2125
* it won't be supported. Perhaps someone can instruct us
2126
* how to force an ordering.
2128
count = ldap_count_values_len(bvValues);
2129
for (i = 0; i < count; i++) {
2130
char *v_val = bvValues[i]->bv_val;
2131
ber_len_t v_len = bvValues[i]->bv_len;
2134
mapent = malloc(v_len + 1);
2137
estr = strerror_r(errno, buf, sizeof(buf));
2138
logerr(MODPREFIX "malloc: %s", estr);
2139
ldap_value_free_len(bvValues);
2142
strncpy(mapent, v_val, v_len);
2143
mapent[v_len] = '\0';
2146
int new_size = mapent_len + v_len + 2;
2148
new_me = realloc(mapent, new_size);
2151
strcat(mapent, " ");
2152
strncat(mapent, v_val, v_len);
2153
mapent[new_size] = '\0';
2154
mapent_len = new_size;
2157
estr = strerror_r(errno, buf, sizeof(buf));
2158
logerr(MODPREFIX "realloc: %s", estr);
2162
ldap_value_free_len(bvValues);
2164
if (*k_val == '/' && k_len == 1) {
2165
if (ap->type == LKP_DIRECT)
2170
if (strcasecmp(class, "nisObject")) {
2171
s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
2176
int dec_len = decode_percent_hack(k_val, &dec_key);
2180
"could not use percent hack to decode key %s",
2186
s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
2188
s_key = sanitize_path(dec_key, dec_len, ap->type, ap->logopt);
2195
cache_writelock(mc);
2196
cache_update(mc, source, s_key, mapent, sp->age);
2206
ldap_value_free_len(bvKey);
2207
e = ldap_next_entry(sp->ldap, e);
2209
debug(ap->logopt, MODPREFIX
2210
"failed to get next entry for query %s",
2212
ret = ldap_parse_result(sp->ldap,
2214
NULL, NULL, NULL, NULL, 0);
2215
if (ret == LDAP_SUCCESS)
2218
return LDAP_OPERATIONS_ERROR;
2222
return LDAP_SUCCESS;
2226
static int read_one_map(struct autofs_point *ap,
2227
struct lookup_context *ctxt,
2228
time_t age, int *result_ldap)
2230
struct map_source *source;
2231
struct ldap_search_params sp;
2232
char buf[MAX_ERR_BUF];
2233
char *class, *info, *entry;
2237
source = ap->entry->current;
2238
ap->entry->current = NULL;
2239
master_source_current_signal(ap->entry);
2242
* If we don't need to create directories then there's no use
2243
* reading the map. We always need to read the whole map for
2244
* direct mounts in order to mount the triggers.
2246
if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
2247
return NSS_STATUS_SUCCESS;
2252
/* Initialize the LDAP context. */
2253
sp.ldap = do_reconnect(ap->logopt, ctxt);
2255
return NSS_STATUS_UNAVAIL;
2257
class = ctxt->schema->entry_class;
2258
entry = ctxt->schema->entry_attr;
2259
info = ctxt->schema->value_attr;
2266
/* Build a query string. */
2267
l = strlen("(objectclass=)") + strlen(class) + 1;
2269
sp.query = malloc(l);
2270
if (sp.query == NULL) {
2271
char *estr = strerror_r(errno, buf, sizeof(buf));
2272
logerr(MODPREFIX "malloc: %s", estr);
2273
return NSS_STATUS_UNAVAIL;
2276
if (sprintf(sp.query, "(objectclass=%s)", class) >= l) {
2277
error(ap->logopt, MODPREFIX "error forming query string");
2279
return NSS_STATUS_UNAVAIL;
2284
MODPREFIX "searching for \"%s\" under \"%s\"", sp.query, ctxt->qdn);
2287
sp.morePages = FALSE;
2292
rv = do_paged_query(&sp, ctxt);
2293
if (rv == LDAP_SIZELIMIT_EXCEEDED)
2295
debug(ap->logopt, MODPREFIX "result size exceed");
2297
ldap_msgfree(sp.result);
2302
if (rv != LDAP_SUCCESS || !sp.result) {
2303
unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
2306
return NSS_STATUS_UNAVAIL;
2309
rv = do_get_entries(&sp, source, ctxt);
2310
if (rv != LDAP_SUCCESS) {
2311
ldap_msgfree(sp.result);
2312
unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
2315
return NSS_STATUS_NOTFOUND;
2317
ldap_msgfree(sp.result);
2318
} while (sp.morePages == TRUE);
2320
debug(ap->logopt, MODPREFIX "done updating map");
2322
unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
2327
return NSS_STATUS_SUCCESS;
2330
int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
2332
struct lookup_context *ctxt = (struct lookup_context *) context;
2333
int rv = LDAP_SUCCESS;
2336
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
2337
ret = read_one_map(ap, ctxt, age, &rv);
2338
if (ret != NSS_STATUS_SUCCESS) {
2340
case LDAP_SIZELIMIT_EXCEEDED:
2341
crit(ap->logopt, MODPREFIX
2342
"Unable to download entire LDAP map for: %s",
2344
case LDAP_UNWILLING_TO_PERFORM:
2345
pthread_setcancelstate(cur_state, NULL);
2346
return NSS_STATUS_UNAVAIL;
2349
pthread_setcancelstate(cur_state, NULL);
2354
static int lookup_one(struct autofs_point *ap,
2355
char *qKey, int qKey_len, struct lookup_context *ctxt)
2357
struct map_source *source;
2358
struct mapent_cache *mc;
2359
int rv, i, l, ql, count;
2360
char buf[MAX_ERR_BUF];
2361
time_t age = time(NULL);
2363
LDAPMessage *result, *e;
2364
char *class, *info, *entry;
2365
char *enc_key1, *enc_key2;
2366
int enc_len1 = 0, enc_len2 = 0;
2367
struct berval **bvKey;
2368
struct berval **bvValues;
2370
int scope = LDAP_SCOPE_SUBTREE;
2373
unsigned int wild = 0;
2374
int ret = CHE_MISSING;
2376
source = ap->entry->current;
2377
ap->entry->current = NULL;
2378
master_source_current_signal(ap->entry);
2383
crit(ap->logopt, MODPREFIX "context was NULL");
2387
/* Initialize the LDAP context. */
2388
ldap = do_reconnect(ap->logopt, ctxt);
2392
class = ctxt->schema->entry_class;
2393
entry = ctxt->schema->entry_attr;
2394
info = ctxt->schema->value_attr;
2400
if (*qKey == '*' && qKey_len == 1)
2402
else if (!strcasecmp(class, "nisObject")) {
2403
enc_len1 = encode_percent_hack(qKey, &enc_key1, 0);
2406
"could not use percent hack encode key %s",
2410
if (enc_len1 != 0) {
2411
enc_len2 = encode_percent_hack(qKey, &enc_key2, 1);
2414
"could not use percent hack encode key %s",
2421
/* Build a query string. */
2422
l = strlen(class) + 3*strlen(entry) + strlen(qKey) + 35;
2424
l += 2*strlen(entry) + enc_len1 + enc_len2 + 6;
2427
if (query == NULL) {
2428
char *estr = strerror_r(errno, buf, sizeof(buf));
2429
crit(ap->logopt, MODPREFIX "malloc: %s", estr);
2439
* Look for an entry in class under ctxt-base
2440
* whose entry is equal to qKey.
2444
"(&(objectclass=%s)(|(%s=%s)(%s=/)(%s=\\2A)))",
2445
class, entry, qKey, entry, entry);
2449
"(&(objectclass=%s)"
2450
"(|(%s=%s)(%s=%s)(%s=%s)(%s=/)(%s=\\2A)))",
2452
entry, enc_key1, entry, enc_key2, entry, entry);
2457
"(&(objectclass=%s)"
2458
"(|(%s=%s)(%s=%s)(%s=/)(%s=\\2A)))",
2459
class, entry, qKey, entry, enc_key1, entry, entry);
2465
MODPREFIX "error forming query string");
2471
MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn);
2473
rv = ldap_search_s(ldap, ctxt->qdn, scope, query, attrs, 0, &result);
2475
if ((rv != LDAP_SUCCESS) || !result) {
2476
crit(ap->logopt, MODPREFIX "query failed for %s", query);
2477
unbind_ldap_connection(ap->logopt, ldap, ctxt);
2483
MODPREFIX "getting first entry for %s=\"%s\"", entry, qKey);
2485
e = ldap_first_entry(ldap, result);
2488
MODPREFIX "got answer, but no entry for %s", query);
2489
ldap_msgfree(result);
2490
unbind_ldap_connection(ap->logopt, ldap, ctxt);
2496
char *mapent = NULL;
2497
size_t mapent_len = 0;
2502
bvKey = ldap_get_values_len(ldap, e, entry);
2503
if (!bvKey || !*bvKey) {
2504
e = ldap_next_entry(ldap, e);
2509
* By definition keys should be unique within each map entry,
2510
* but as always there are exceptions.
2516
* Keys must be unique so, in general, there shouldn't be
2517
* more than one attribute value. We make an exception for
2518
* wildcard entries as people may have values for '*' or
2519
* '/' for compaibility reasons. We use the '/' as the
2520
* wildcard in LDAP but allow '*' as well to allow for
2521
* people using older schemas that allow '*' as a key
2522
* value. Another case where there can be multiple key
2523
* values is when people have used the "%" hack to specify
2524
* case matching ctriteria in a caase insensitive attribute.
2526
count = ldap_count_values_len(bvKey);
2530
/* Check for the "/" and "*" and use as "/" if found */
2531
for (i = 0; i < count; i++) {
2532
bvKey[i]->bv_val[bvKey[i]->bv_len] = '\0';
2535
* If multiple entries are present they could
2536
* be the result of people using the "%" hack so
2539
if (strchr(bvKey[i]->bv_val, '%'))
2542
/* check for wildcard */
2543
if (bvKey[i]->bv_len == 1 &&
2544
(*bvKey[i]->bv_val == '/' ||
2545
*bvKey[i]->bv_val == '*')) {
2546
/* always use '/' internally */
2547
*bvKey[i]->bv_val = '/';
2548
k_val = bvKey[i]->bv_val;
2554
* The key was matched by LDAP so this is a
2555
* valid entry. Set the result key to the
2556
* lookup key to provide the mixed case
2557
* matching provided by the "%" hack.
2560
k_len = strlen(qKey);
2567
MODPREFIX "no valid key found for %.*s",
2573
/* Check for the "*" and use as "/" if found */
2574
if (bvKey[0]->bv_len == 1 && *bvKey[0]->bv_val == '*')
2575
*bvKey[0]->bv_val = '/';
2576
k_val = bvKey[0]->bv_val;
2577
k_len = bvKey[0]->bv_len;
2580
debug(ap->logopt, MODPREFIX "examining first entry");
2582
bvValues = ldap_get_values_len(ldap, e, info);
2583
if (!bvValues || !*bvValues) {
2585
MODPREFIX "no %s defined for %s", info, query);
2589
count = ldap_count_values_len(bvValues);
2590
for (i = 0; i < count; i++) {
2591
char *v_val = bvValues[i]->bv_val;
2592
ber_len_t v_len = bvValues[i]->bv_len;
2595
mapent = malloc(v_len + 1);
2598
estr = strerror_r(errno, buf, sizeof(buf));
2599
logerr(MODPREFIX "malloc: %s", estr);
2600
ldap_value_free_len(bvValues);
2603
strncpy(mapent, v_val, v_len);
2604
mapent[v_len] = '\0';
2607
int new_size = mapent_len + v_len + 2;
2609
new_me = realloc(mapent, new_size);
2612
strcat(mapent, " ");
2613
strncat(mapent, v_val, v_len);
2614
mapent[new_size] = '\0';
2615
mapent_len = new_size;
2618
estr = strerror_r(errno, buf, sizeof(buf));
2619
logerr(MODPREFIX "realloc: %s", estr);
2623
ldap_value_free_len(bvValues);
2625
if (*k_val == '/' && k_len == 1) {
2626
if (ap->type == LKP_DIRECT)
2629
cache_writelock(mc);
2630
cache_update(mc, source, "*", mapent, age);
2635
if (strcasecmp(class, "nisObject")) {
2636
s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
2641
int dec_len = decode_percent_hack(k_val, &dec_key);
2645
"could not use percent hack to decode key %s",
2651
s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
2653
s_key = sanitize_path(dec_key, dec_len, ap->type, ap->logopt);
2660
cache_writelock(mc);
2661
ret = cache_update(mc, source, s_key, mapent, age);
2671
ldap_value_free_len(bvKey);
2672
e = ldap_next_entry(ldap, e);
2675
ldap_msgfree(result);
2676
unbind_ldap_connection(ap->logopt, ldap, ctxt);
2678
/* Failed to find wild entry, update cache if needed */
2679
pthread_cleanup_push(cache_lock_cleanup, mc);
2680
cache_writelock(mc);
2681
we = cache_lookup_distinct(mc, "*");
2683
/* Wildcard entry existed and is now gone */
2684
if (we->source == source && !wild) {
2685
cache_delete(mc, "*");
2689
/* Wildcard not in map but now is */
2693
/* Not found in the map but found in the cache */
2694
if (ret == CHE_MISSING) {
2695
struct mapent *exists = cache_lookup_distinct(mc, qKey);
2696
if (exists && exists->source == source) {
2697
if (exists->mapent) {
2698
free(exists->mapent);
2699
exists->mapent = NULL;
2705
pthread_cleanup_pop(1);
2711
static int check_map_indirect(struct autofs_point *ap,
2712
char *key, int key_len,
2713
struct lookup_context *ctxt)
2715
struct map_source *source;
2716
struct mapent_cache *mc;
2718
time_t now = time(NULL);
2722
source = ap->entry->current;
2723
ap->entry->current = NULL;
2724
master_source_current_signal(ap->entry);
2728
master_source_current_wait(ap->entry);
2729
ap->entry->current = source;
2731
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
2732
ret = lookup_one(ap, key, key_len, ctxt);
2733
if (ret == CHE_FAIL) {
2734
pthread_setcancelstate(cur_state, NULL);
2735
return NSS_STATUS_NOTFOUND;
2736
} else if (ret == CHE_UNAVAIL) {
2738
* If the server is down and the entry exists in the cache
2739
* and belongs to this map return success and use the entry.
2741
struct mapent *exists = cache_lookup(mc, key);
2742
if (exists && exists->source == source) {
2743
pthread_setcancelstate(cur_state, NULL);
2744
return NSS_STATUS_SUCCESS;
2748
MODPREFIX "lookup for %s failed: connection failed", key);
2750
return NSS_STATUS_UNAVAIL;
2752
pthread_setcancelstate(cur_state, NULL);
2755
* Check for map change and update as needed for
2756
* following cache lookup.
2759
t_last_read = ap->exp_runfreq + 1;
2760
me = cache_lookup_first(mc);
2762
if (me->source == source) {
2763
t_last_read = now - me->age;
2766
me = cache_lookup_next(mc, me);
2770
if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED)
2774
me = cache_lookup_distinct(mc, "*");
2775
if (ret == CHE_MISSING && (!me || me->source != source)) {
2777
return NSS_STATUS_NOTFOUND;
2781
return NSS_STATUS_SUCCESS;
2784
int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context)
2786
struct lookup_context *ctxt = (struct lookup_context *) context;
2787
struct map_source *source;
2788
struct mapent_cache *mc;
2790
char key[KEY_MAX_LEN + 1];
2792
char *mapent = NULL;
2793
char mapent_buf[MAPENT_MAX_LEN + 1];
2797
source = ap->entry->current;
2798
ap->entry->current = NULL;
2799
master_source_current_signal(ap->entry);
2803
debug(ap->logopt, MODPREFIX "looking up %s", name);
2805
key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name);
2806
if (key_len > KEY_MAX_LEN)
2807
return NSS_STATUS_NOTFOUND;
2809
/* Check if we recorded a mount fail for this key anywhere */
2810
me = lookup_source_mapent(ap, key, LKP_DISTINCT);
2812
if (me->status >= time(NULL)) {
2813
cache_unlock(me->mc);
2814
return NSS_STATUS_NOTFOUND;
2817
/* Negative timeout expired for non-existent entry. */
2819
cache_delete(me->mc, key);
2821
cache_unlock(me->mc);
2825
* We can't check the direct mount map as if it's not in
2826
* the map cache already we never get a mount lookup, so
2827
* we never know about it.
2829
if (ap->type == LKP_INDIRECT && *key != '/') {
2833
me = cache_lookup_distinct(mc, key);
2834
if (me && me->multi)
2835
lkp_key = strdup(me->multi->key);
2837
lkp_key = strdup(key);
2841
return NSS_STATUS_UNKNOWN;
2843
master_source_current_wait(ap->entry);
2844
ap->entry->current = source;
2846
status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt);
2853
me = cache_lookup(mc, key);
2854
/* Stale mapent => check for entry in alternate source or wildcard */
2855
if (me && !me->mapent) {
2856
while ((me = cache_lookup_key_next(me)))
2857
if (me->source == source)
2860
me = cache_lookup_distinct(mc, "*");
2862
if (me && (me->source == source || *me->key == '/')) {
2863
strcpy(mapent_buf, me->mapent);
2864
mapent = mapent_buf;
2869
return NSS_STATUS_TRYAGAIN;
2871
master_source_current_wait(ap->entry);
2872
ap->entry->current = source;
2874
debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent);
2875
ret = ctxt->parse->parse_mount(ap, key, key_len,
2876
mapent, ctxt->parse->context);
2878
time_t now = time(NULL);
2881
/* Record the the mount fail in the cache */
2882
cache_writelock(mc);
2883
me = cache_lookup_distinct(mc, key);
2885
rv = cache_update(mc, source, key, NULL, now);
2886
if (rv != CHE_FAIL) {
2887
me = cache_lookup_distinct(mc, key);
2888
me->status = now + ap->negative_timeout;
2891
return NSS_STATUS_TRYAGAIN;
2894
return NSS_STATUS_SUCCESS;
2898
* This destroys a context for queries to this module. It releases the parser
2899
* structure (unloading the module) and frees the memory used by the context.
2901
int lookup_done(void *context)
2903
struct lookup_context *ctxt = (struct lookup_context *) context;
2904
int rv = close_parse(ctxt->parse);
2906
autofs_sasl_dispose(ctxt);