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));
398
ldap_msgfree(result);
400
MODPREFIX "failed to find query dn under search base dns");
409
ldap_msgfree(result);
421
static struct ldap_schema *alloc_common_schema(struct ldap_schema *s)
423
struct ldap_schema *schema;
424
char *mc, *ma, *ec, *ea, *va;
426
mc = strdup(s->map_class);
430
ma = strdup(s->map_attr);
436
ec = strdup(s->entry_class);
443
ea = strdup(s->entry_attr);
451
va = strdup(s->value_attr);
460
schema = malloc(sizeof(struct ldap_schema));
470
schema->map_class = mc;
471
schema->map_attr = ma;
472
schema->entry_class = ec;
473
schema->entry_attr = ea;
474
schema->value_attr = va;
479
static int find_query_dn(unsigned logopt, LDAP *ldap, struct lookup_context *ctxt)
481
struct ldap_schema *schema;
487
for (i = 0; i < common_schema_count; i++) {
488
const char *class = common_schema[i].map_class;
489
const char *key = common_schema[i].map_attr;
490
if (get_query_dn(logopt, ldap, ctxt, class, key)) {
491
schema = alloc_common_schema(&common_schema[i]);
493
error(logopt, MODPREFIX "failed to allocate schema");
496
ctxt->schema = schema;
504
static int do_bind(unsigned logopt, LDAP *ldap, const char *uri, struct lookup_context *ctxt)
506
char *host = NULL, *nhost;
507
int rv, need_base = 1;
510
debug(logopt, MODPREFIX "auth_required: %d, sasl_mech %s",
511
ctxt->auth_required, ctxt->sasl_mech);
513
if (ctxt->auth_required & (LDAP_AUTH_REQUIRED|LDAP_AUTH_AUTODETECT)) {
514
rv = autofs_sasl_bind(logopt, ldap, ctxt);
515
debug(logopt, MODPREFIX "autofs_sasl_bind returned %d", rv);
517
rv = bind_ldap_anonymous(logopt, ldap, uri, ctxt);
518
debug(logopt, MODPREFIX "ldap anonymous bind returned %d", rv);
521
rv = bind_ldap_anonymous(logopt, ldap, uri, ctxt);
522
debug(logopt, MODPREFIX "ldap anonymous bind returned %d", rv);
528
rv = ldap_get_option(ldap, LDAP_OPT_HOST_NAME, &host);
529
if (rv != LDAP_SUCCESS || !host) {
530
debug(logopt, "failed to get hostname for connection");
534
nhost = strdup(host);
536
debug(logopt, "failed to alloc context for hostname");
541
if (!ctxt->cur_host) {
542
ctxt->cur_host = nhost;
543
/* Check if schema defined in conf first time only */
544
ctxt->schema = defaults_get_schema();
546
/* If connection host has changed update */
547
if (strcmp(ctxt->cur_host, nhost)) {
548
free(ctxt->cur_host);
549
ctxt->cur_host = nhost;
560
* If the schema isn't defined in the configuration then check for
561
* presence of a map dn with a the common schema. Then calculate the
562
* base dn for searches.
565
if (!find_query_dn(logopt, ldap, ctxt)) {
567
MODPREFIX "failed to find valid query dn");
571
const char *class = ctxt->schema->map_class;
572
const char *key = ctxt->schema->map_attr;
573
if (!get_query_dn(logopt, ldap, ctxt, class, key)) {
574
error(logopt, MODPREFIX "failed to get query dn");
582
static LDAP *do_connect(unsigned logopt, const char *uri, struct lookup_context *ctxt)
586
ldap = init_ldap_connection(logopt, uri, ctxt);
590
if (!do_bind(logopt, ldap, uri, ctxt)) {
591
unbind_ldap_connection(logopt, ldap, ctxt);
598
static LDAP *connect_to_server(unsigned logopt, const char *uri, struct lookup_context *ctxt)
602
ldap = do_connect(logopt, uri, ctxt);
605
MODPREFIX "couldn't connect to server %s",
606
uri ? uri : "default");
613
static LDAP *find_server(unsigned logopt, struct lookup_context *ctxt)
616
struct ldap_uri *this;
617
struct list_head *p, *first;
618
struct dclist *dclist = NULL;
621
uris_mutex_lock(ctxt);
623
dclist = ctxt->dclist;
624
if (ctxt->dclist->expire < time(NULL)) {
625
free_dclist(ctxt->dclist);
633
first = &ctxt->uri->list;
634
uris_mutex_unlock(ctxt);
637
/* Try each uri, save point in server list upon success */
641
if (p == ctxt->uris) {
645
this = list_entry(p, struct ldap_uri, list);
646
if (!strstr(this->uri, ":///"))
647
uri = strdup(this->uri);
650
uri = strdup(dclist->uri);
653
tmp = get_dc_list(logopt, this->uri);
659
uri = strdup(dclist->uri);
670
debug(logopt, "trying server uri %s", uri);
671
ldap = connect_to_server(logopt, uri, ctxt);
673
info(logopt, "connected to uri %s", uri);
686
uris_mutex_lock(ctxt);
691
ctxt->dclist = dclist;
693
if (ctxt->dclist != dclist) {
694
free_dclist(ctxt->dclist);
695
ctxt->dclist = dclist;
699
uris_mutex_unlock(ctxt);
704
static LDAP *do_reconnect(unsigned logopt, struct lookup_context *ctxt)
709
if (ctxt->server || !ctxt->uris) {
710
ldap = do_connect(logopt, ctxt->server, ctxt);
712
/* Dispose of the sasl authentication connection and try again. */
714
autofs_sasl_dispose(ctxt);
715
ldap = connect_to_server(logopt, ctxt->server, ctxt);
721
uris_mutex_lock(ctxt);
723
uri = strdup(ctxt->dclist->uri);
725
uri = strdup(ctxt->uri->uri);
726
uris_mutex_unlock(ctxt);
729
char buf[MAX_ERR_BUF];
730
char *estr = strerror_r(errno, buf, sizeof(buf));
731
crit(logopt, MODPREFIX "strdup: %s", estr);
735
ldap = do_connect(logopt, uri, ctxt);
738
* Dispose of the sasl authentication connection and try the
739
* current server again before trying other servers in the list.
742
autofs_sasl_dispose(ctxt);
743
ldap = connect_to_server(logopt, uri, ctxt);
751
/* Failed to connect, try to find a new server */
754
autofs_sasl_dispose(ctxt);
757
/* Current server failed connect, try the rest */
758
ldap = find_server(logopt, ctxt);
760
error(logopt, MODPREFIX "failed to find available server");
766
int get_property(unsigned logopt, xmlNodePtr node, const char *prop, char **value)
769
xmlChar *property = (xmlChar *) prop;
771
if (!(ret = xmlGetProp(node, property))) {
776
if (!(*value = strdup((char *) ret))) {
777
logerr(MODPREFIX "strdup failed with %d", errno);
787
* For plain text, login and digest-md5 authentication types, we need
788
* user and password credentials.
790
int authtype_requires_creds(const char *authtype)
792
if (!strncmp(authtype, "PLAIN", strlen("PLAIN")) ||
793
!strncmp(authtype, "DIGEST-MD5", strlen("DIGEST-MD5")) ||
794
!strncmp(authtype, "LOGIN", strlen("LOGIN")))
801
* -1 -- The permission on the file are not correct or
802
* the xml document was mal-formed
803
* 0 -- The file was non-existent
805
* the file contained valid data, which was filled into
806
* ctxt->sasl_mech, ctxt->user, and ctxt->secret
808
* The idea is that a -1 return value should abort the program. A 0
809
* return value requires more checking. If ctxt->authtype is filled in,
810
* then no further action is necessary. If it is not, the caller is free
811
* to then use another method to determine how to connect to the server.
813
int parse_ldap_config(unsigned logopt, struct lookup_context *ctxt)
815
int ret = 0, fallback = 0;
816
unsigned int auth_required = LDAP_AUTH_NOTREQUIRED;
817
unsigned int tls_required = 0, use_tls = 0;
819
xmlDocPtr doc = NULL;
820
xmlNodePtr root = NULL;
821
char *authrequired, *auth_conf, *authtype;
822
char *user = NULL, *secret = NULL;
823
char *client_princ = NULL, *client_cc = NULL;
824
char *usetls, *tlsrequired;
826
authtype = user = secret = NULL;
828
auth_conf = (char *) defaults_get_auth_conf_file();
831
MODPREFIX "failed to get auth config file name.");
836
* Here we check that the config file exists, and that we have
837
* permission to read it. The XML library does not specify why a
838
* parse happens to fail, so we have to do all of this checking
841
memset(&st, 0, sizeof(st));
842
if (stat(auth_conf, &st) == -1 || st.st_size == 0) {
843
/* Auth config doesn't exist so disable TLS and auth */
844
if (errno == ENOENT) {
845
ctxt->auth_conf = auth_conf;
846
ctxt->use_tls = LDAP_TLS_DONT_USE;
847
ctxt->tls_required = LDAP_TLS_DONT_USE;
848
ctxt->auth_required = LDAP_AUTH_NOTREQUIRED;
849
ctxt->sasl_mech = NULL;
852
ctxt->client_princ = NULL;
856
MODPREFIX "stat(2) failed with error %s.",
861
if (!S_ISREG(st.st_mode) ||
862
st.st_uid != 0 || st.st_gid != 0 ||
863
(st.st_mode & 0x01ff) != 0600) {
864
error(logopt, MODPREFIX
865
"Configuration file %s exists, but is not usable. "
866
"Please make sure that it is owned by root, group "
867
"is root, and the mode is 0600.",
872
doc = xmlParseFile(auth_conf);
874
error(logopt, MODPREFIX
875
"xmlParseFile failed for %s.", auth_conf);
879
root = xmlDocGetRootElement(doc);
881
debug(logopt, MODPREFIX
882
"empty xml document (%s).", auth_conf);
887
if (xmlStrcmp(root->name, (const xmlChar *)"autofs_ldap_sasl_conf")) {
888
error(logopt, MODPREFIX
889
"The root node of the XML document %s is not "
890
"autofs_ldap_sasl_conf.", auth_conf);
894
ret = get_property(logopt, root, "usetls", &usetls);
898
"Failed read the usetls property from "
899
"the configuration file %s.", auth_conf);
903
if (!usetls || ctxt->port == LDAPS_PORT)
904
use_tls = LDAP_TLS_DONT_USE;
906
if (!strcasecmp(usetls, "yes"))
907
use_tls = LDAP_TLS_INIT;
908
else if (!strcasecmp(usetls, "no"))
909
use_tls = LDAP_TLS_DONT_USE;
913
"The usetls property must have value "
914
"\"yes\" or \"no\".");
921
ret = get_property(logopt, root, "tlsrequired", &tlsrequired);
925
"Failed read the tlsrequired property from "
926
"the configuration file %s.", auth_conf);
931
tls_required = LDAP_TLS_DONT_USE;
933
if (!strcasecmp(tlsrequired, "yes"))
934
tls_required = LDAP_TLS_REQUIRED;
935
else if (!strcasecmp(tlsrequired, "no"))
936
tls_required = LDAP_TLS_DONT_USE;
940
"The tlsrequired property must have value "
941
"\"yes\" or \"no\".");
948
ret = get_property(logopt, root, "authrequired", &authrequired);
952
"Failed read the authrequired property from "
953
"the configuration file %s.", auth_conf);
958
auth_required = LDAP_AUTH_NOTREQUIRED;
960
if (!strcasecmp(authrequired, "yes"))
961
auth_required = LDAP_AUTH_REQUIRED;
962
else if (!strcasecmp(authrequired, "no"))
963
auth_required = LDAP_AUTH_NOTREQUIRED;
964
else if (!strcasecmp(authrequired, "autodetect"))
965
auth_required = LDAP_AUTH_AUTODETECT;
969
"The authrequired property must have value "
970
"\"yes\", \"no\" or \"autodetect\".");
977
ret = get_property(logopt, root, "authtype", &authtype);
981
"Failed read the authtype property from the "
982
"configuration file %s.", auth_conf);
986
if (authtype && authtype_requires_creds(authtype)) {
987
ret = get_property(logopt, root, "user", &user);
988
ret |= get_property(logopt, root, "secret", &secret);
989
if (ret != 0 || (!user || !secret)) {
992
"%s authentication type requires a username "
993
"and a secret. Please fix your configuration "
994
"in %s.", authtype, auth_conf);
1007
* We allow the admin to specify the principal to use for the
1008
* client. The default is "autofsclient/hostname@REALM".
1010
(void)get_property(logopt, root, "clientprinc", &client_princ);
1011
(void)get_property(logopt, root, "credentialcache", &client_cc);
1013
ctxt->auth_conf = auth_conf;
1014
ctxt->use_tls = use_tls;
1015
ctxt->tls_required = tls_required;
1016
ctxt->auth_required = auth_required;
1017
ctxt->sasl_mech = authtype;
1018
if (!authtype && (auth_required & LDAP_AUTH_REQUIRED))
1019
ctxt->auth_required |= LDAP_AUTH_AUTODETECT;
1021
ctxt->secret = secret;
1022
ctxt->client_princ = client_princ;
1023
ctxt->client_cc = client_cc;
1025
debug(logopt, MODPREFIX
1026
"ldap authentication configured with the following options:");
1027
debug(logopt, MODPREFIX
1029
"tls_required: %u, "
1030
"auth_required: %u, "
1032
use_tls, tls_required, auth_required, authtype);
1033
debug(logopt, MODPREFIX
1036
"client principal: %s "
1037
"credential cache: %s",
1038
user, secret ? "specified" : "unspecified",
1039
client_princ, client_cc);
1052
* Take an input string as specified in the master map, and break it
1053
* down into a server name and basedn.
1055
static int parse_server_string(unsigned logopt, const char *url, struct lookup_context *ctxt)
1057
char buf[MAX_ERR_BUF], *tmp = NULL, proto[9];
1058
const char *ptr, *name;
1061
memset(proto, 0, 9);
1064
debug(logopt, MODPREFIX
1065
"Attempting to parse LDAP information from string \"%s\".", ptr);
1067
ctxt->port = LDAP_PORT;
1068
if (!strncmp(ptr, "ldap:", 5) || !strncmp(ptr, "ldaps:", 6)) {
1069
if (*(ptr + 4) == 's') {
1070
ctxt->port = LDAPS_PORT;
1071
memcpy(proto, ptr, 6);
1072
strcat(proto, "//");
1075
memcpy(proto, ptr, 5);
1076
strcat(proto, "//");
1081
if (!strncmp(ptr, "//", 2)) {
1082
const char *s = ptr + 2;
1083
const char *q = NULL;
1085
/* Isolate the server(s). */
1086
if ((q = strchr(s, '/'))) {
1089
al_len = l + strlen(proto) + 2;
1090
tmp = malloc(al_len);
1093
tmp = malloc(al_len);
1097
estr = strerror_r(errno, buf, sizeof(buf));
1098
logerr(MODPREFIX "malloc: %s", estr);
1102
memset(ctxt->server, 0, al_len);
1104
strcpy(ctxt->server, proto);
1105
memcpy(ctxt->server + strlen(proto), s, l);
1106
strcat(ctxt->server, "/");
1108
memcpy(ctxt->server, s, l);
1112
MODPREFIX "invalid LDAP map syntax %s", ptr);
1114
/* TODO: why did I put this here, the parser shouldn't let this by
1116
tmp = malloc(l + 1);
1119
estr = strerror_r(errno, buf, sizeof(buf));
1120
crit(logopt, MODPREFIX "malloc: %s", estr);
1124
memset(ctxt->server, 0, l + 1);
1125
memcpy(ctxt->server, s, l);
1128
} else if (strchr(ptr, ':') != NULL || *ptr == '[') {
1129
const char *q = NULL;
1131
/* Isolate the server. Include the port spec */
1133
q = strchr(ptr, ':');
1136
while (*q == ':' || isxdigit(*q))
1139
crit(logopt, MODPREFIX
1140
"invalid LDAP map syntax %s", ptr);
1154
MODPREFIX "invalid LDAP map syntax %s", ptr);
1160
al_len = l + strlen(proto) + 2;
1161
tmp = malloc(al_len);
1164
tmp = malloc(al_len);
1166
/* Isolate the server's name. */
1169
estr = strerror_r(errno, buf, sizeof(buf));
1170
logerr(MODPREFIX "malloc: %s", estr);
1174
memset(ctxt->server, 0, al_len);
1176
strcpy(ctxt->server, proto);
1177
memcpy(ctxt->server + strlen(proto), ptr, l);
1178
strcat(ctxt->server, "/");
1180
memcpy(ctxt->server, ptr, l);
1184
/* TODO: why did I do this - how can the map name "and" base dn be missing? */
1189
* For nss support we can have a map name with no
1190
* type or dn info. If present a base dn must have
1191
* at least an "=" and a "," to be at all functional.
1192
* If a dn is given it must be fully specified or
1193
* the later LDAP calls will fail.
1196
if ((name = strchr(ptr, '='))) {
1200
* An '=' with no ',' means a mapname has been given so just
1201
* grab it alone to keep it independent of schema otherwize
1202
* we expect a full dn.
1204
if (!strchr(ptr, ',')) {
1205
char *map = strdup(name + 1);
1207
ctxt->mapname = map;
1210
estr = strerror_r(errno, buf, sizeof(buf));
1211
logerr(MODPREFIX "strdup: %s", estr);
1218
base = malloc(l + 1);
1221
estr = strerror_r(errno, buf, sizeof(buf));
1222
logerr(MODPREFIX "malloc: %s", estr);
1228
memset(ctxt->base, 0, l + 1);
1229
memcpy(ctxt->base, ptr, l);
1232
char *map = malloc(l + 1);
1235
estr = strerror_r(errno, buf, sizeof(buf));
1236
logerr(MODPREFIX "malloc: %s", estr);
1241
ctxt->mapname = map;
1242
memset(ctxt->mapname, 0, l + 1);
1243
memcpy(map, ptr, l);
1246
if (!ctxt->server && *proto) {
1247
if (!strncmp(proto, "ldaps", 5)) {
1248
info(logopt, MODPREFIX
1249
"server must be given to force ldaps, connection "
1250
"will use LDAP client configured protocol");
1255
debug(logopt, MODPREFIX "mapname %s", ctxt->mapname);
1257
debug(logopt, MODPREFIX "server \"%s\", base dn \"%s\"",
1258
ctxt->server ? ctxt->server : "(default)",
1264
static void free_context(struct lookup_context *ctxt)
1269
free(ctxt->schema->map_class);
1270
free(ctxt->schema->map_attr);
1271
free(ctxt->schema->entry_class);
1272
free(ctxt->schema->entry_attr);
1273
free(ctxt->schema->value_attr);
1276
if (ctxt->auth_conf)
1277
free(ctxt->auth_conf);
1278
if (ctxt->sasl_mech)
1279
free(ctxt->sasl_mech);
1284
if (ctxt->client_princ)
1285
free(ctxt->client_princ);
1286
if (ctxt->client_cc)
1287
free(ctxt->client_cc);
1289
free(ctxt->mapname);
1295
free(ctxt->cur_host);
1299
defaults_free_uris(ctxt->uris);
1300
ret = pthread_mutex_destroy(&ctxt->uris_mutex);
1304
defaults_free_searchdns(ctxt->sdns);
1306
free_dclist(ctxt->dclist);
1312
static void validate_uris(struct list_head *list)
1314
struct list_head *next;
1317
while (next != list) {
1318
struct ldap_uri *this;
1320
this = list_entry(next, struct ldap_uri, list);
1323
/* At least we get some basic validation */
1324
if (!ldap_is_ldap_url(this->uri)) {
1325
list_del(&this->list);
1335
* This initializes a context (persistent non-global data) for queries to
1336
* this module. Return zero if we succeed.
1338
int lookup_init(const char *mapfmt, int argc, const char *const *argv, void **context)
1340
struct lookup_context *ctxt;
1341
char buf[MAX_ERR_BUF];
1347
/* If we can't build a context, bail. */
1348
ctxt = malloc(sizeof(struct lookup_context));
1350
char *estr = strerror_r(errno, buf, sizeof(buf));
1351
logerr(MODPREFIX "malloc: %s", estr);
1354
memset(ctxt, 0, sizeof(struct lookup_context));
1356
ret = pthread_mutex_init(&ctxt->uris_mutex, NULL);
1358
error(LOGOPT_ANY, MODPREFIX "failed to init uris mutex");
1363
/* If a map type isn't explicitly given, parse it like sun entries. */
1365
mapfmt = MAPFMT_DEFAULT;
1368
* Parse out the server name and base dn, and fill them
1369
* into the proper places in the lookup context structure.
1371
if (!parse_server_string(LOGOPT_NONE, argv[0], ctxt)) {
1372
error(LOGOPT_ANY, MODPREFIX "cannot parse server string");
1377
ctxt->timeout = defaults_get_ldap_timeout();
1378
ctxt->network_timeout = defaults_get_ldap_network_timeout();
1380
if (!ctxt->server) {
1381
struct list_head *uris = defaults_get_uris();
1383
validate_uris(uris);
1384
if (!list_empty(uris))
1388
"no valid uris found in config list"
1389
", using default system config");
1397
* First, check to see if a preferred authentication method was
1398
* specified by the user. parse_ldap_config will return error
1399
* if the permissions on the file were incorrect, or if the
1400
* specified authentication type is not valid.
1402
ret = parse_ldap_config(LOGOPT_NONE, ctxt);
1408
/* Init the sasl callbacks */
1409
if (!autofs_sasl_client_init(LOGOPT_NONE)) {
1410
error(LOGOPT_ANY, "failed to init sasl client");
1416
if (ctxt->server || !ctxt->uris) {
1417
ldap = connect_to_server(LOGOPT_NONE, ctxt->server, ctxt);
1423
ldap = find_server(LOGOPT_NONE, ctxt);
1426
error(LOGOPT_ANY, MODPREFIX
1427
"failed to find available server");
1431
unbind_ldap_connection(LOGOPT_ANY, ldap, ctxt);
1433
/* Open the parser, if we can. */
1434
ctxt->parse = open_parse(mapfmt, MODPREFIX, argc - 1, argv + 1);
1437
logerr(MODPREFIX "failed to open parse context");
1445
int lookup_read_master(struct master *master, time_t age, void *context)
1447
struct lookup_context *ctxt = (struct lookup_context *) context;
1448
unsigned int timeout = master->default_timeout;
1449
unsigned int logging = master->default_logging;
1450
unsigned int logopt = master->logopt;
1452
char buf[MAX_ERR_BUF];
1453
char parse_buf[PARSE_MAX_BUF];
1455
LDAPMessage *result, *e;
1456
char *class, *info, *entry;
1457
char **keyValue = NULL;
1458
char **values = NULL;
1460
int scope = LDAP_SCOPE_SUBTREE;
1463
class = ctxt->schema->entry_class;
1464
entry = ctxt->schema->entry_attr;
1465
info = ctxt->schema->value_attr;
1471
l = strlen("(objectclass=)") + strlen(class) + 1;
1474
if (query == NULL) {
1475
char *estr = strerror_r(errno, buf, sizeof(buf));
1476
logerr(MODPREFIX "malloc: %s", estr);
1477
return NSS_STATUS_UNAVAIL;
1480
if (sprintf(query, "(objectclass=%s)", class) >= l) {
1481
error(logopt, MODPREFIX "error forming query string");
1483
return NSS_STATUS_UNAVAIL;
1486
/* Initialize the LDAP context. */
1487
ldap = do_reconnect(logopt, ctxt);
1490
return NSS_STATUS_UNAVAIL;
1495
MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn);
1497
rv = ldap_search_s(ldap, ctxt->qdn, scope, query, attrs, 0, &result);
1499
if ((rv != LDAP_SUCCESS) || !result) {
1500
error(logopt, MODPREFIX "query failed for %s: %s",
1501
query, ldap_err2string(rv));
1502
unbind_ldap_connection(logging, ldap, ctxt);
1504
return NSS_STATUS_NOTFOUND;
1507
e = ldap_first_entry(ldap, result);
1510
MODPREFIX "query succeeded, no matches for %s",
1512
ldap_msgfree(result);
1513
unbind_ldap_connection(logging, ldap, ctxt);
1515
return NSS_STATUS_NOTFOUND;
1517
debug(logopt, MODPREFIX "examining entries");
1523
keyValue = ldap_get_values(ldap, e, entry);
1525
if (!keyValue || !*keyValue) {
1526
e = ldap_next_entry(ldap, e);
1531
* By definition keys must be unique within
1534
count = ldap_count_values(keyValue);
1535
if (strcasecmp(class, "nisObject")) {
1537
error(logopt, MODPREFIX
1538
"key %s has duplicates - ignoring",
1542
key = strdup(keyValue[0]);
1544
error(logopt, MODPREFIX
1545
"failed to dup map key %s - ignoring",
1549
} else if (count == 1) {
1550
dec_len = decode_percent_hack(keyValue[0], &key);
1552
error(logopt, MODPREFIX
1553
"invalid map key %s - ignoring",
1558
dec_len = decode_percent_hack(keyValue[0], &key);
1560
error(logopt, MODPREFIX
1561
"invalid map key %s - ignoring",
1566
for (i = 1; i < count; i++) {
1568
dec_len = decode_percent_hack(keyValue[i], &k);
1570
error(logopt, MODPREFIX
1571
"invalid map key %s - ignoring",
1575
if (strcmp(key, k)) {
1576
error(logopt, MODPREFIX
1577
"key entry mismatch %s - ignoring",
1587
* Ignore keys beginning with '+' as plus map
1588
* inclusion is only valid in file maps.
1593
"ignoreing '+' map entry - not in file map");
1597
values = ldap_get_values(ldap, e, info);
1598
if (!values || !*values) {
1600
MODPREFIX "no %s defined for %s", info, query);
1605
* We require that there be only one value per key.
1607
count = ldap_count_values(values);
1611
"one value per key allowed in master map");
1612
ldap_value_free(values);
1616
if (snprintf(parse_buf, sizeof(parse_buf), "%s %s",
1617
key, *values) >= sizeof(parse_buf)) {
1618
error(logopt, MODPREFIX "map entry too long");
1619
ldap_value_free(values);
1622
ldap_value_free(values);
1624
master_parse_entry(parse_buf, timeout, logging, age);
1626
ldap_value_free(keyValue);
1629
e = ldap_next_entry(ldap, e);
1633
ldap_msgfree(result);
1634
unbind_ldap_connection(logopt, ldap, ctxt);
1637
return NSS_STATUS_SUCCESS;
1640
static int get_percent_decoded_len(const char *name)
1644
const char *tmp = name;
1645
int look_for_close = 0;
1649
/* assume escapes aren't interpreted inside brackets */
1650
if (look_for_close) {
1654
/* check for escaped % */
1668
} else if (*tmp == ']' && look_for_close) {
1679
assert(strlen(name) > escapes);
1680
return strlen(name) - escapes;
1684
* Try to catch heap corruption if our logic happens to be incorrect.
1686
static void validate_string_len(const char *orig, char *start,
1687
char *end, unsigned int len)
1689
debug(LOGOPT_NONE, MODPREFIX "string %s encoded as %s", orig, start);
1690
/* make sure we didn't overflow the allocated space */
1691
if (end - start > len + 1) {
1692
crit(LOGOPT_ANY, MODPREFIX "orig %s, len %d", orig, len);
1693
crit(LOGOPT_ANY, MODPREFIX "en/decoded %s, len %d", start,
1696
assert(end-start <= len + 1);
1700
* Deal with encode and decode of % hack.
1702
* 0 => % hack not present.
1703
* -1 => syntax error or alloc fail.
1704
* 1 transofrmed value returned.
1707
* Assumptions: %'s must be escaped by %'s. %'s are not used to escape
1708
* anything else except capital letters (so you can't escape a closing
1709
* bracket, for example).
1711
static int decode_percent_hack(const char *name, char **key)
1716
int escaped = 0, look_for_close = 0;
1723
len = get_percent_decoded_len(name);
1724
new = malloc(len + 1);
1734
if (!look_for_close)
1745
} else if (*tmp == ']' && look_for_close) {
1756
validate_string_len(name, new, ptr, len);
1761
* Calculate the length of a string replacing all capital letters with %letter.
1766
static int get_encoded_len_escaping_every_cap(const char *name)
1769
unsigned int escapes = 0; /* number of % escape characters */
1773
/* We'll need to escape percents */
1774
if (*tmp == '%' || isupper(*tmp))
1779
return strlen(name) + escapes;
1783
* Calculate the length of a string replacing sequences (1 or more) of capital
1784
* letters with %[letters]. For example:
1787
* WorksForMe -> %[W]orks%[F]or%[M]e
1788
* aaBBaa -> aa%[BB]aa
1790
static int get_encoded_len_escaping_sequences(const char *name)
1793
unsigned int escapes = 0;
1797
/* escape percents */
1800
else if (isupper(*tmp)) {
1801
/* start an escape block %[...] */
1802
escapes += 3; /* %[] */
1803
while (*tmp && isupper(*tmp))
1810
return strlen(name) + escapes;
1813
static void encode_individual(const char *name, char *new, unsigned int len)
1821
if (*tmp == '%' || isupper(*tmp))
1826
validate_string_len(name, new, ptr, len);
1829
static void encode_sequence(const char *name, char *new, unsigned int len)
1840
} else if (isupper(*tmp)) {
1845
while (*tmp && isupper(*tmp)) {
1854
validate_string_len(name, new, ptr, len);
1858
* use_class: 1 means encode string as %[CAPITALS], 0 means encode as
1861
static int encode_percent_hack(const char *name, char **key, unsigned int use_class)
1863
unsigned int len = 0;
1869
len = get_encoded_len_escaping_sequences(name);
1871
len = get_encoded_len_escaping_every_cap(name);
1873
/* If there is no escaping to be done, return 0 */
1874
if (len == strlen(name))
1877
*key = malloc(len + 1);
1882
encode_sequence(name, *key, len);
1884
encode_individual(name, *key, len);
1886
if (strlen(*key) != len)
1887
crit(LOGOPT_ANY, MODPREFIX "encoded key length mismatch: key "
1888
"%s len %d strlen %d", *key, len, strlen(*key));
1890
return strlen(*key);
1893
static int do_paged_query(struct ldap_search_params *sp, struct lookup_context *ctxt)
1895
struct autofs_point *ap = sp->ap;
1896
LDAPControl *pageControl=NULL, *controls[2] = { NULL, NULL };
1897
LDAPControl **returnedControls = NULL;
1898
static ber_int_t pageSize = 1000;
1899
static char pagingCriticality = 'T';
1900
int rv, scope = LDAP_SCOPE_SUBTREE;
1902
if (sp->morePages == TRUE)
1905
rv = ldap_search_s(sp->ldap, ctxt->qdn, scope, sp->query, sp->attrs, 0, &sp->result);
1906
if ((rv != LDAP_SUCCESS) || !sp->result) {
1908
* Check for Size Limit exceeded and force run through loop
1909
* and requery using page control.
1911
if (rv == LDAP_SIZELIMIT_EXCEEDED)
1912
sp->morePages = TRUE;
1915
MODPREFIX "query failed for %s: %s",
1916
sp->query, ldap_err2string(rv));
1923
/* we need to use page controls so requery LDAP */
1924
debug(ap->logopt, MODPREFIX "geting page of results");
1926
rv = ldap_create_page_control(sp->ldap, pageSize, sp->cookie,
1927
pagingCriticality, &pageControl);
1928
if (rv != LDAP_SUCCESS) {
1929
warn(ap->logopt, MODPREFIX "failed to create page control");
1933
/* Insert the control into a list to be passed to the search. */
1934
controls[0] = pageControl;
1936
/* Search for entries in the directory using the parmeters. */
1937
rv = ldap_search_ext_s(sp->ldap,
1938
ctxt->qdn, scope, sp->query, sp->attrs,
1939
0, controls, NULL, NULL, 0, &sp->result);
1940
if ((rv != LDAP_SUCCESS) && (rv != LDAP_PARTIAL_RESULTS)) {
1942
MODPREFIX "query failed for %s: %s",
1943
sp->query, ldap_err2string(rv));
1944
ldap_control_free(pageControl);
1948
/* Parse the results to retrieve the contols being returned. */
1949
rv = ldap_parse_result(sp->ldap, sp->result,
1950
NULL, NULL, NULL, NULL,
1951
&returnedControls, FALSE);
1952
if (sp->cookie != NULL) {
1953
ber_bvfree(sp->cookie);
1958
* Parse the page control returned to get the cookie and
1959
* determine whether there are more pages.
1961
rv = ldap_parse_page_control(sp->ldap,
1962
returnedControls, &sp->totalCount,
1964
if (sp->cookie && sp->cookie->bv_val && strlen(sp->cookie->bv_val))
1965
sp->morePages = TRUE;
1967
sp->morePages = FALSE;
1969
/* Cleanup the controls used. */
1970
if (returnedControls)
1971
ldap_controls_free(returnedControls);
1973
ldap_control_free(pageControl);
1978
static int do_get_entries(struct ldap_search_params *sp, struct map_source *source, struct lookup_context *ctxt)
1980
struct autofs_point *ap = sp->ap;
1981
struct mapent_cache *mc = source->mc;
1982
char buf[MAX_ERR_BUF];
1983
struct berval **bvKey;
1984
struct berval **bvValues;
1986
char *class, *info, *entry;
1990
class = ctxt->schema->entry_class;
1991
entry = ctxt->schema->entry_attr;
1992
info = ctxt->schema->value_attr;
1994
e = ldap_first_entry(sp->ldap, sp->result);
1997
MODPREFIX "query succeeded, no matches for %s",
1999
ret = ldap_parse_result(sp->ldap, sp->result,
2000
&rv, NULL, NULL, NULL, NULL, 0);
2001
if (ret == LDAP_SUCCESS)
2004
return LDAP_OPERATIONS_ERROR;
2006
debug(ap->logopt, MODPREFIX "examining entries");
2009
char *mapent = NULL;
2010
size_t mapent_len = 0;
2015
bvKey = ldap_get_values_len(sp->ldap, e, entry);
2016
if (!bvKey || !*bvKey) {
2017
e = ldap_next_entry(sp->ldap, e);
2019
debug(ap->logopt, MODPREFIX
2020
"failed to get next entry for query %s",
2022
ret = ldap_parse_result(sp->ldap,
2024
NULL, NULL, NULL, NULL, 0);
2025
if (ret == LDAP_SUCCESS)
2028
return LDAP_OPERATIONS_ERROR;
2034
* By definition keys should be unique within each map entry,
2035
* but as always there are exceptions.
2041
* Keys should be unique so, in general, there shouldn't be
2042
* more than one attribute value. We make an exception for
2043
* wildcard entries as people may have values for '*' or
2044
* '/' for compaibility reasons. We use the '/' as the
2045
* wildcard in LDAP but allow '*' as well to allow for
2046
* people using older schemas that allow '*' as a key
2047
* value. Another case where there can be multiple key
2048
* values is when people have used the "%" hack to specify
2049
* case matching ctriteria in a case insensitive attribute.
2051
count = ldap_count_values_len(bvKey);
2055
/* Check for the "/" and "*" and use as "/" if found */
2056
for (i = 0; i < count; i++) {
2057
bvKey[i]->bv_val[bvKey[i]->bv_len] = '\0';
2060
* If multiple entries are present they could
2061
* be the result of people using the "%" hack so
2064
if (strchr(bvKey[i]->bv_val, '%'))
2067
/* check for wildcard */
2068
if (bvKey[i]->bv_len == 1 &&
2069
(*bvKey[i]->bv_val == '/' ||
2070
*bvKey[i]->bv_val == '*')) {
2071
/* always use '/' internally */
2072
*bvKey[i]->bv_val = '/';
2073
k_val = bvKey[i]->bv_val;
2079
* We have a result from LDAP so this is a
2080
* valid entry. Set the result to the LDAP
2081
* key that isn't a wildcard and doesn't have
2082
* any "%" hack values present. This should be
2083
* the case insensitive match string for the
2084
* nis schema, the default value.
2086
k_val = bvKey[i]->bv_val;
2087
k_len = bvKey[i]->bv_len;
2094
MODPREFIX "invalid entry %.*s - ignoring",
2095
bvKey[0]->bv_len, bvKey[0]->bv_val);
2099
/* Check for the "*" and use as "/" if found */
2100
if (bvKey[0]->bv_len == 1 && *bvKey[0]->bv_val == '*')
2101
*bvKey[0]->bv_val = '/';
2102
k_val = bvKey[0]->bv_val;
2103
k_len = bvKey[0]->bv_len;
2107
* Ignore keys beginning with '+' as plus map
2108
* inclusion is only valid in file maps.
2110
if (*k_val == '+') {
2113
"ignoreing '+' map entry - not in file map");
2117
bvValues = ldap_get_values_len(sp->ldap, e, info);
2118
if (!bvValues || !*bvValues) {
2120
MODPREFIX "no %s defined for %s", info, sp->query);
2125
* We expect that there will be only one value because
2126
* questions of order of returned value entries but we
2127
* accumulate values to support simple multi-mounts.
2129
* If the ordering of a mount spec with another containing
2130
* options or the actual order of entries causes problems
2131
* it won't be supported. Perhaps someone can instruct us
2132
* how to force an ordering.
2134
count = ldap_count_values_len(bvValues);
2135
for (i = 0; i < count; i++) {
2136
char *v_val = bvValues[i]->bv_val;
2137
ber_len_t v_len = bvValues[i]->bv_len;
2140
mapent = malloc(v_len + 1);
2143
estr = strerror_r(errno, buf, sizeof(buf));
2144
logerr(MODPREFIX "malloc: %s", estr);
2145
ldap_value_free_len(bvValues);
2148
strncpy(mapent, v_val, v_len);
2149
mapent[v_len] = '\0';
2152
int new_size = mapent_len + v_len + 2;
2154
new_me = realloc(mapent, new_size);
2157
strcat(mapent, " ");
2158
strncat(mapent, v_val, v_len);
2159
mapent[new_size] = '\0';
2160
mapent_len = new_size;
2163
estr = strerror_r(errno, buf, sizeof(buf));
2164
logerr(MODPREFIX "realloc: %s", estr);
2168
ldap_value_free_len(bvValues);
2170
if (*k_val == '/' && k_len == 1) {
2171
if (ap->type == LKP_DIRECT)
2176
if (strcasecmp(class, "nisObject")) {
2177
s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
2182
int dec_len = decode_percent_hack(k_val, &dec_key);
2186
"could not use percent hack to decode key %s",
2192
s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
2194
s_key = sanitize_path(dec_key, dec_len, ap->type, ap->logopt);
2201
cache_writelock(mc);
2202
cache_update(mc, source, s_key, mapent, sp->age);
2212
ldap_value_free_len(bvKey);
2213
e = ldap_next_entry(sp->ldap, e);
2215
debug(ap->logopt, MODPREFIX
2216
"failed to get next entry for query %s",
2218
ret = ldap_parse_result(sp->ldap,
2220
NULL, NULL, NULL, NULL, 0);
2221
if (ret == LDAP_SUCCESS)
2224
return LDAP_OPERATIONS_ERROR;
2228
return LDAP_SUCCESS;
2232
static int read_one_map(struct autofs_point *ap,
2233
struct lookup_context *ctxt,
2234
time_t age, int *result_ldap)
2236
struct map_source *source;
2237
struct ldap_search_params sp;
2238
char buf[MAX_ERR_BUF];
2239
char *class, *info, *entry;
2243
source = ap->entry->current;
2244
ap->entry->current = NULL;
2245
master_source_current_signal(ap->entry);
2248
* If we don't need to create directories then there's no use
2249
* reading the map. We always need to read the whole map for
2250
* direct mounts in order to mount the triggers.
2252
if (!(ap->flags & MOUNT_FLAG_GHOST) && ap->type != LKP_DIRECT)
2253
return NSS_STATUS_SUCCESS;
2258
class = ctxt->schema->entry_class;
2259
entry = ctxt->schema->entry_attr;
2260
info = ctxt->schema->value_attr;
2267
/* Build a query string. */
2268
l = strlen("(objectclass=)") + strlen(class) + 1;
2270
sp.query = malloc(l);
2271
if (sp.query == NULL) {
2272
char *estr = strerror_r(errno, buf, sizeof(buf));
2273
logerr(MODPREFIX "malloc: %s", estr);
2274
return NSS_STATUS_UNAVAIL;
2277
if (sprintf(sp.query, "(objectclass=%s)", class) >= l) {
2278
error(ap->logopt, MODPREFIX "error forming query string");
2280
return NSS_STATUS_UNAVAIL;
2283
/* Initialize the LDAP context. */
2284
sp.ldap = do_reconnect(ap->logopt, ctxt);
2287
return NSS_STATUS_UNAVAIL;
2292
MODPREFIX "searching for \"%s\" under \"%s\"", sp.query, ctxt->qdn);
2295
sp.morePages = FALSE;
2300
rv = do_paged_query(&sp, ctxt);
2301
if (rv == LDAP_SIZELIMIT_EXCEEDED)
2303
debug(ap->logopt, MODPREFIX "result size exceed");
2305
ldap_msgfree(sp.result);
2310
if (rv != LDAP_SUCCESS || !sp.result) {
2311
unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
2314
return NSS_STATUS_UNAVAIL;
2317
rv = do_get_entries(&sp, source, ctxt);
2318
if (rv != LDAP_SUCCESS) {
2319
ldap_msgfree(sp.result);
2320
unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
2323
return NSS_STATUS_NOTFOUND;
2325
ldap_msgfree(sp.result);
2326
} while (sp.morePages == TRUE);
2328
debug(ap->logopt, MODPREFIX "done updating map");
2330
unbind_ldap_connection(ap->logopt, sp.ldap, ctxt);
2335
return NSS_STATUS_SUCCESS;
2338
int lookup_read_map(struct autofs_point *ap, time_t age, void *context)
2340
struct lookup_context *ctxt = (struct lookup_context *) context;
2341
int rv = LDAP_SUCCESS;
2344
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
2345
ret = read_one_map(ap, ctxt, age, &rv);
2346
if (ret != NSS_STATUS_SUCCESS) {
2348
case LDAP_SIZELIMIT_EXCEEDED:
2349
crit(ap->logopt, MODPREFIX
2350
"Unable to download entire LDAP map for: %s",
2352
case LDAP_UNWILLING_TO_PERFORM:
2353
pthread_setcancelstate(cur_state, NULL);
2354
return NSS_STATUS_UNAVAIL;
2357
pthread_setcancelstate(cur_state, NULL);
2362
static int lookup_one(struct autofs_point *ap,
2363
char *qKey, int qKey_len, struct lookup_context *ctxt)
2365
struct map_source *source;
2366
struct mapent_cache *mc;
2367
int rv, i, l, ql, count;
2368
char buf[MAX_ERR_BUF];
2369
time_t age = time(NULL);
2371
LDAPMessage *result, *e;
2372
char *class, *info, *entry;
2373
char *enc_key1, *enc_key2;
2374
int enc_len1 = 0, enc_len2 = 0;
2375
struct berval **bvKey;
2376
struct berval **bvValues;
2378
int scope = LDAP_SCOPE_SUBTREE;
2381
unsigned int wild = 0;
2382
int ret = CHE_MISSING;
2384
source = ap->entry->current;
2385
ap->entry->current = NULL;
2386
master_source_current_signal(ap->entry);
2391
crit(ap->logopt, MODPREFIX "context was NULL");
2395
class = ctxt->schema->entry_class;
2396
entry = ctxt->schema->entry_attr;
2397
info = ctxt->schema->value_attr;
2403
if (*qKey == '*' && qKey_len == 1)
2405
else if (!strcasecmp(class, "nisObject")) {
2406
enc_len1 = encode_percent_hack(qKey, &enc_key1, 0);
2409
"could not use percent hack encode key %s",
2413
if (enc_len1 != 0) {
2414
enc_len2 = encode_percent_hack(qKey, &enc_key2, 1);
2417
"could not use percent hack encode key %s",
2424
/* Build a query string. */
2425
l = strlen(class) + 3*strlen(entry) + strlen(qKey) + 35;
2427
l += 2*strlen(entry) + enc_len1 + enc_len2 + 6;
2430
if (query == NULL) {
2431
char *estr = strerror_r(errno, buf, sizeof(buf));
2432
crit(ap->logopt, MODPREFIX "malloc: %s", estr);
2442
* Look for an entry in class under ctxt-base
2443
* whose entry is equal to qKey.
2447
"(&(objectclass=%s)(|(%s=%s)(%s=/)(%s=\\2A)))",
2448
class, entry, qKey, entry, entry);
2452
"(&(objectclass=%s)"
2453
"(|(%s=%s)(%s=%s)(%s=%s)(%s=/)(%s=\\2A)))",
2455
entry, enc_key1, entry, enc_key2, entry, entry);
2460
"(&(objectclass=%s)"
2461
"(|(%s=%s)(%s=%s)(%s=/)(%s=\\2A)))",
2462
class, entry, qKey, entry, enc_key1, entry, entry);
2468
MODPREFIX "error forming query string");
2473
/* Initialize the LDAP context. */
2474
ldap = do_reconnect(ap->logopt, ctxt);
2481
MODPREFIX "searching for \"%s\" under \"%s\"", query, ctxt->qdn);
2483
rv = ldap_search_s(ldap, ctxt->qdn, scope, query, attrs, 0, &result);
2485
if ((rv != LDAP_SUCCESS) || !result) {
2486
crit(ap->logopt, MODPREFIX "query failed for %s", query);
2487
unbind_ldap_connection(ap->logopt, ldap, ctxt);
2493
MODPREFIX "getting first entry for %s=\"%s\"", entry, qKey);
2495
e = ldap_first_entry(ldap, result);
2498
MODPREFIX "got answer, but no entry for %s", query);
2499
ldap_msgfree(result);
2500
unbind_ldap_connection(ap->logopt, ldap, ctxt);
2506
char *mapent = NULL;
2507
size_t mapent_len = 0;
2512
bvKey = ldap_get_values_len(ldap, e, entry);
2513
if (!bvKey || !*bvKey) {
2514
e = ldap_next_entry(ldap, e);
2519
* By definition keys should be unique within each map entry,
2520
* but as always there are exceptions.
2526
* Keys must be unique so, in general, there shouldn't be
2527
* more than one attribute value. We make an exception for
2528
* wildcard entries as people may have values for '*' or
2529
* '/' for compaibility reasons. We use the '/' as the
2530
* wildcard in LDAP but allow '*' as well to allow for
2531
* people using older schemas that allow '*' as a key
2532
* value. Another case where there can be multiple key
2533
* values is when people have used the "%" hack to specify
2534
* case matching ctriteria in a caase insensitive attribute.
2536
count = ldap_count_values_len(bvKey);
2540
/* Check for the "/" and "*" and use as "/" if found */
2541
for (i = 0; i < count; i++) {
2542
bvKey[i]->bv_val[bvKey[i]->bv_len] = '\0';
2545
* If multiple entries are present they could
2546
* be the result of people using the "%" hack so
2549
if (strchr(bvKey[i]->bv_val, '%'))
2552
/* check for wildcard */
2553
if (bvKey[i]->bv_len == 1 &&
2554
(*bvKey[i]->bv_val == '/' ||
2555
*bvKey[i]->bv_val == '*')) {
2556
/* always use '/' internally */
2557
*bvKey[i]->bv_val = '/';
2558
k_val = bvKey[i]->bv_val;
2564
* The key was matched by LDAP so this is a
2565
* valid entry. Set the result key to the
2566
* lookup key to provide the mixed case
2567
* matching provided by the "%" hack.
2570
k_len = strlen(qKey);
2577
MODPREFIX "no valid key found for %.*s",
2583
/* Check for the "*" and use as "/" if found */
2584
if (bvKey[0]->bv_len == 1 && *bvKey[0]->bv_val == '*')
2585
*bvKey[0]->bv_val = '/';
2586
k_val = bvKey[0]->bv_val;
2587
k_len = bvKey[0]->bv_len;
2590
debug(ap->logopt, MODPREFIX "examining first entry");
2592
bvValues = ldap_get_values_len(ldap, e, info);
2593
if (!bvValues || !*bvValues) {
2595
MODPREFIX "no %s defined for %s", info, query);
2599
count = ldap_count_values_len(bvValues);
2600
for (i = 0; i < count; i++) {
2601
char *v_val = bvValues[i]->bv_val;
2602
ber_len_t v_len = bvValues[i]->bv_len;
2605
mapent = malloc(v_len + 1);
2608
estr = strerror_r(errno, buf, sizeof(buf));
2609
logerr(MODPREFIX "malloc: %s", estr);
2610
ldap_value_free_len(bvValues);
2613
strncpy(mapent, v_val, v_len);
2614
mapent[v_len] = '\0';
2617
int new_size = mapent_len + v_len + 2;
2619
new_me = realloc(mapent, new_size);
2622
strcat(mapent, " ");
2623
strncat(mapent, v_val, v_len);
2624
mapent[new_size] = '\0';
2625
mapent_len = new_size;
2628
estr = strerror_r(errno, buf, sizeof(buf));
2629
logerr(MODPREFIX "realloc: %s", estr);
2633
ldap_value_free_len(bvValues);
2635
if (*k_val == '/' && k_len == 1) {
2636
if (ap->type == LKP_DIRECT)
2639
cache_writelock(mc);
2640
cache_update(mc, source, "*", mapent, age);
2645
if (strcasecmp(class, "nisObject")) {
2646
s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
2651
int dec_len = decode_percent_hack(k_val, &dec_key);
2655
"could not use percent hack to decode key %s",
2661
s_key = sanitize_path(k_val, k_len, ap->type, ap->logopt);
2663
s_key = sanitize_path(dec_key, dec_len, ap->type, ap->logopt);
2670
cache_writelock(mc);
2671
ret = cache_update(mc, source, s_key, mapent, age);
2681
ldap_value_free_len(bvKey);
2682
e = ldap_next_entry(ldap, e);
2685
ldap_msgfree(result);
2686
unbind_ldap_connection(ap->logopt, ldap, ctxt);
2688
/* Failed to find wild entry, update cache if needed */
2689
pthread_cleanup_push(cache_lock_cleanup, mc);
2690
cache_writelock(mc);
2691
we = cache_lookup_distinct(mc, "*");
2693
/* Wildcard entry existed and is now gone */
2694
if (we->source == source && !wild) {
2695
cache_delete(mc, "*");
2699
/* Wildcard not in map but now is */
2703
/* Not found in the map but found in the cache */
2704
if (ret == CHE_MISSING) {
2705
struct mapent *exists = cache_lookup_distinct(mc, qKey);
2706
if (exists && exists->source == source) {
2707
if (exists->mapent) {
2708
free(exists->mapent);
2709
exists->mapent = NULL;
2715
pthread_cleanup_pop(1);
2721
static int check_map_indirect(struct autofs_point *ap,
2722
char *key, int key_len,
2723
struct lookup_context *ctxt)
2725
struct map_source *source;
2726
struct mapent_cache *mc;
2728
time_t now = time(NULL);
2732
source = ap->entry->current;
2733
ap->entry->current = NULL;
2734
master_source_current_signal(ap->entry);
2738
master_source_current_wait(ap->entry);
2739
ap->entry->current = source;
2741
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cur_state);
2742
ret = lookup_one(ap, key, key_len, ctxt);
2743
if (ret == CHE_FAIL) {
2744
pthread_setcancelstate(cur_state, NULL);
2745
return NSS_STATUS_NOTFOUND;
2746
} else if (ret == CHE_UNAVAIL) {
2748
* If the server is down and the entry exists in the cache
2749
* and belongs to this map return success and use the entry.
2751
struct mapent *exists = cache_lookup(mc, key);
2752
if (exists && exists->source == source) {
2753
pthread_setcancelstate(cur_state, NULL);
2754
return NSS_STATUS_SUCCESS;
2758
MODPREFIX "lookup for %s failed: connection failed", key);
2760
return NSS_STATUS_UNAVAIL;
2762
pthread_setcancelstate(cur_state, NULL);
2765
* Check for map change and update as needed for
2766
* following cache lookup.
2769
t_last_read = ap->exp_runfreq + 1;
2770
me = cache_lookup_first(mc);
2772
if (me->source == source) {
2773
t_last_read = now - me->age;
2776
me = cache_lookup_next(mc, me);
2780
if (t_last_read > ap->exp_runfreq && ret & CHE_UPDATED)
2784
me = cache_lookup_distinct(mc, "*");
2785
if (ret == CHE_MISSING && (!me || me->source != source)) {
2787
return NSS_STATUS_NOTFOUND;
2791
return NSS_STATUS_SUCCESS;
2794
int lookup_mount(struct autofs_point *ap, const char *name, int name_len, void *context)
2796
struct lookup_context *ctxt = (struct lookup_context *) context;
2797
struct map_source *source;
2798
struct mapent_cache *mc;
2800
char key[KEY_MAX_LEN + 1];
2802
char *mapent = NULL;
2803
char mapent_buf[MAPENT_MAX_LEN + 1];
2807
source = ap->entry->current;
2808
ap->entry->current = NULL;
2809
master_source_current_signal(ap->entry);
2813
debug(ap->logopt, MODPREFIX "looking up %s", name);
2815
key_len = snprintf(key, KEY_MAX_LEN + 1, "%s", name);
2816
if (key_len > KEY_MAX_LEN)
2817
return NSS_STATUS_NOTFOUND;
2819
/* Check if we recorded a mount fail for this key anywhere */
2820
me = lookup_source_mapent(ap, key, LKP_DISTINCT);
2822
if (me->status >= time(NULL)) {
2823
cache_unlock(me->mc);
2824
return NSS_STATUS_NOTFOUND;
2827
/* Negative timeout expired for non-existent entry. */
2829
cache_delete(me->mc, key);
2831
cache_unlock(me->mc);
2835
* We can't check the direct mount map as if it's not in
2836
* the map cache already we never get a mount lookup, so
2837
* we never know about it.
2839
if (ap->type == LKP_INDIRECT && *key != '/') {
2843
me = cache_lookup_distinct(mc, key);
2844
if (me && me->multi)
2845
lkp_key = strdup(me->multi->key);
2847
lkp_key = strdup(key);
2851
return NSS_STATUS_UNKNOWN;
2853
master_source_current_wait(ap->entry);
2854
ap->entry->current = source;
2856
status = check_map_indirect(ap, lkp_key, strlen(lkp_key), ctxt);
2863
me = cache_lookup(mc, key);
2864
/* Stale mapent => check for entry in alternate source or wildcard */
2865
if (me && !me->mapent) {
2866
while ((me = cache_lookup_key_next(me)))
2867
if (me->source == source)
2870
me = cache_lookup_distinct(mc, "*");
2872
if (me && (me->source == source || *me->key == '/')) {
2873
strcpy(mapent_buf, me->mapent);
2874
mapent = mapent_buf;
2879
return NSS_STATUS_TRYAGAIN;
2881
master_source_current_wait(ap->entry);
2882
ap->entry->current = source;
2884
debug(ap->logopt, MODPREFIX "%s -> %s", key, mapent);
2885
ret = ctxt->parse->parse_mount(ap, key, key_len,
2886
mapent, ctxt->parse->context);
2888
time_t now = time(NULL);
2891
/* Record the the mount fail in the cache */
2892
cache_writelock(mc);
2893
me = cache_lookup_distinct(mc, key);
2895
rv = cache_update(mc, source, key, NULL, now);
2896
if (rv != CHE_FAIL) {
2897
me = cache_lookup_distinct(mc, key);
2898
me->status = now + ap->negative_timeout;
2901
return NSS_STATUS_TRYAGAIN;
2904
return NSS_STATUS_SUCCESS;
2908
* This destroys a context for queries to this module. It releases the parser
2909
* structure (unloading the module) and frees the memory used by the context.
2911
int lookup_done(void *context)
2913
struct lookup_context *ctxt = (struct lookup_context *) context;
2914
int rv = close_parse(ctxt->parse);
2916
autofs_sasl_dispose(ctxt);