diff --git a/CHANGELOG b/CHANGELOG index b0bec85..818b294 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -26,6 +26,10 @@ - fix master map lexer to admit "." in macro values (Mike Matera). - make ldap attribute match case insensitive. - add missed man page update for APPEND_OPTIONS config option. +- add ldaps protocol support. + - note: it's no longer possible to multiple hosts in an ldap map spec. + - note: if this is needed use only the map name and configure the URI + entry in the ldap client configuration. 20/2/2007 autofs-5.0.1 ---------------------- diff --git a/daemon/lookup.c b/daemon/lookup.c index acf2e98..06fcecc 100644 --- a/daemon/lookup.c +++ b/daemon/lookup.c @@ -169,20 +169,30 @@ int lookup_nss_read_master(struct master *master, time_t age) char source[10]; memset(source, 0, 10); - /* TODO: ldaps is not yet handled by ldap module */ - /* TODO: must tighten up this test */ - if (!strncmp(name, "file", 4) || - !strncmp(name, "yp", 2) || - !strncmp(name, "nis", 3) || - !strncmp(name, "nisplus", 7) || - !strncmp(name, "ldap", 4)) { + if (!strncmp(name, "file:", 5) || + !strncmp(name, "yp:", 3) || + !strncmp(name, "nis:", 4) || + !strncmp(name, "nisplus:", 8) || + !strncmp(name, "ldap:", 5) || + !strncmp(name, "ldaps:", 6)) { strncpy(source, name, tmp - name); - master->name = tmp + 1; - - debug(LOGOPT_NONE, - "reading master %s %s", - source, master->name); + /* + * If it's an ldap map leave the source in the + * name so the lookup module can work out if + * ldaps has been requested. + */ + if (strncmp(name, "ldap", 4)) { + master->name = tmp + 1; + debug(LOGOPT_NONE, + "reading master %s %s", + source, master->name); + } else { + master->name = name; + debug(LOGOPT_NONE, + "reading master %s %s", + source, tmp + 1); + } result = do_read_master(master, source, age); master->name = name; diff --git a/include/lookup_ldap.h b/include/lookup_ldap.h index d33bda9..e1c5b4e 100644 --- a/include/lookup_ldap.h +++ b/include/lookup_ldap.h @@ -13,6 +13,7 @@ struct lookup_context { char *mapname; char *server; + int port; char *base; char *qdn; diff --git a/lib/master_parse.y b/lib/master_parse.y index 7e98a4e..8d2be02 100644 --- a/lib/master_parse.y +++ b/lib/master_parse.y @@ -288,6 +288,19 @@ map: PATH local_free_vars(); YYABORT; } + /* Add back the type for lookup_ldap.c to handle ldaps */ + if (*local_argv[0]) { + tmp = malloc(strlen(type) + strlen(local_argv[0]) + 2); + if (!tmp) { + local_free_vars(); + YYABORT; + } + strcpy(tmp, type); + strcat(tmp, ":"); + strcat(tmp, local_argv[0]); + free(local_argv[0]); + local_argv[0] = tmp; + } } ; @@ -341,12 +354,12 @@ dnattrs: DNATTR EQUAL DNNAME strcat($$, ","); strcat($$, $5); } - | DNATTR + | DNNAME { - master_notify($1); - YYABORT; + /* Matches map in old style syntax ldap:server:map */ + strcpy($$, $1); } - | DNNAME + | DNATTR { master_notify($1); YYABORT; diff --git a/lib/master_tok.l b/lib/master_tok.l index 28d7d0d..e872245 100644 --- a/lib/master_tok.l +++ b/lib/master_tok.l @@ -110,7 +110,7 @@ DNATTRSTR {AT_CN}|{AT_NMN}|{AT_AMN}|{AT_OU}|{AT_DC}|{AT_O}|{AT_C} DNNAMESTR ([[:alnum:]_.\-]+) INTMAP (-hosts|-null) -MTYPE ((file|program|yp|nis|nisplus|ldap|hesiod|userdir)(,(sun|hesiod))?) +MTYPE ((file|program|yp|nis|nisplus|ldap|ldaps|hesiod|userdir)(,(sun|hesiod))?) OPTTOUT (-t{OPTWS}|-t{OPTWS}={OPTWS}|--timeout{OPTWS}|--timeout{OPTWS}={OPTWS}) diff --git a/man/auto.master.5.in b/man/auto.master.5.in index 382507b..0e36a6f 100644 --- a/man/auto.master.5.in +++ b/man/auto.master.5.in @@ -100,8 +100,9 @@ The map is a hesiod database whose .B filsys entries are used for maps. .TP -.B ldap -The map is stored in an LDAP directory. +.B ldap \fPor\fB ldaps +The map is stored in an LDAP directory. If \fBldaps\fP is used the +appropriate certificate must be configured in the LDAP client. .RE .TP \fBformat\fP diff --git a/modules/Makefile b/modules/Makefile index d8f53d1..0d12f01 100644 --- a/modules/Makefile +++ b/modules/Makefile @@ -63,6 +63,7 @@ install: all -rm -f $(INSTALLROOT)$(autofslibdir)/mount_smbfs.so ln -fs lookup_file.so $(INSTALLROOT)$(autofslibdir)/lookup_files.so ln -fs lookup_yp.so $(INSTALLROOT)$(autofslibdir)/lookup_nis.so + ln -fs lookup_ldap.so $(INSTALLROOT)$(autofslibdir)/lookup_ldaps.so ln -fs mount_nfs.so $(INSTALLROOT)$(autofslibdir)/mount_nfs4.so ifeq ($(EXT2FS), 1) ifeq ($(EXT3FS), 1) diff --git a/modules/lookup_ldap.c b/modules/lookup_ldap.c index 29ba0c8..ac3a272 100644 --- a/modules/lookup_ldap.c +++ b/modules/lookup_ldap.c @@ -100,14 +100,8 @@ LDAP *init_ldap_connection(struct lookup_context *ctxt) ctxt->version = 3; /* Initialize the LDAP context. */ - /* LDAP_PORT should not be hard-coded, here. If we are going to - * parse ldap strings ourselves, then we can put the port specified - * in the host:port format here. Otherwise, we can just pass the - * host:port string to the ldap_init call and let the library handle - * it. -JM - */ - ldap = ldap_init(ctxt->server, LDAP_PORT); - if (!ldap) { + rv = ldap_initialize(&ldap, ctxt->server); + if (rv != LDAP_OPT_SUCCESS) { crit(LOGOPT_ANY, MODPREFIX "couldn't initialize LDAP connection to %s", ctxt->server ? ctxt->server : "default server"); @@ -348,7 +342,7 @@ int parse_ldap_config(struct lookup_context *ctxt) goto out; } - if (!usetls) + if (!usetls || ctxt->port == LDAPS_PORT) use_tls = LDAP_TLS_DONT_USE; else { if (!strcasecmp(usetls, "yes")) @@ -551,16 +545,31 @@ int auth_init(struct lookup_context *ctxt) */ static int parse_server_string(const char *url, struct lookup_context *ctxt) { - char buf[MAX_ERR_BUF], *tmp = NULL; - const char *ptr; - int l; + char buf[MAX_ERR_BUF], *tmp = NULL, proto[9]; + const char *ptr, *name; + int l, al_len; + *proto = '\0'; ptr = url; debug(LOGOPT_NONE, MODPREFIX "Attempting to parse LDAP information from string \"%s\".", ptr); + ctxt->port = LDAP_PORT; + if (!strncmp(ptr, "ldap:", 5) || !strncmp(ptr, "ldaps:", 6)) { + if (*(ptr + 4) == 's') { + ctxt->port = LDAPS_PORT; + memcpy(proto, ptr, 6); + strcat(proto, "//"); + ptr += 6; + } else { + memcpy(proto, ptr, 5); + strcat(proto, "//"); + ptr += 5; + } + } + if (!strncmp(ptr, "//", 2)) { const char *s = ptr + 2; const char *q = NULL; @@ -568,7 +577,13 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) /* Isolate the server(s). */ if ((q = strchr(s, '/'))) { l = q - s; - tmp = malloc(l + 1); + if (*proto) { + al_len = l + strlen(proto) + 2; + tmp = malloc(al_len); + } else { + al_len = l + 1; + tmp = malloc(al_len); + } if (!tmp) { char *estr; estr = strerror_r(errno, buf, MAX_ERR_BUF); @@ -576,8 +591,13 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) return 0; } ctxt->server = tmp; - memset(ctxt->server, 0, l + 1); - memcpy(ctxt->server, s, l); + memset(ctxt->server, 0, al_len); + if (*proto) { + strcpy(ctxt->server, proto); + memcpy(ctxt->server + strlen(proto), s, l); + strcat(ctxt->server, "/"); + } else + memcpy(ctxt->server, s, l); ptr = q + 1; } else { crit(LOGOPT_ANY, @@ -613,8 +633,14 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) } l = q - ptr; + if (proto) { + al_len = l + strlen(proto) + 2; + tmp = malloc(al_len); + } else { + al_len = l + 1; + tmp = malloc(al_len); + } /* Isolate the server's name. */ - tmp = malloc(l + 1); if (!tmp) { char *estr; estr = strerror_r(errno, buf, MAX_ERR_BUF); @@ -622,8 +648,13 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) return 0; } ctxt->server = tmp; - memset(ctxt->server, 0, l + 1); - memcpy(ctxt->server, ptr, l); + memset(ctxt->server, 0, al_len); + if (*proto) { + strcpy(ctxt->server, proto); + memcpy(ctxt->server + strlen(proto), ptr, l); + strcat(ctxt->server, "/"); + } else + memcpy(ctxt->server, ptr, l); ptr += l + 1; } @@ -639,29 +670,41 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) * the later LDAP calls will fail. */ l = strlen(ptr); - if (strchr(ptr, '=')) { + if ((name = strchr(ptr, '='))) { char *base; + /* + * An '=' with no ',' means a mapname has been given so just + * grab it alone to keep it independent of schema otherwize + * we expect a full dn. + */ if (!strchr(ptr, ',')) { - debug(LOGOPT_NONE, - MODPREFIX "LDAP dn not fuly specified"); - if (ctxt->server) - free(ctxt->server); - return 0; - } - - base = malloc(l + 1); - if (!base) { - char *estr; - estr = strerror_r(errno, buf, MAX_ERR_BUF); - crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); - if (ctxt->server) - free(ctxt->server); - return 0; + char *map = strdup(name + 1); + if (map) + ctxt->mapname = map; + else { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); + crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); + if (ctxt->server) + free(ctxt->server); + return 0; + } + + } else { + base = malloc(l + 1); + if (!base) { + char *estr; + estr = strerror_r(errno, buf, MAX_ERR_BUF); + crit(LOGOPT_ANY, MODPREFIX "malloc: %s", estr); + if (ctxt->server) + free(ctxt->server); + return 0; + } + ctxt->base = base; + memset(ctxt->base, 0, l + 1); + memcpy(ctxt->base, ptr, l); } - ctxt->base = base; - memset(ctxt->base, 0, l + 1); - memcpy(ctxt->base, ptr, l); } else { char *map = malloc(l + 1); if (!map) { @@ -676,6 +719,14 @@ static int parse_server_string(const char *url, struct lookup_context *ctxt) memset(ctxt->mapname, 0, l + 1); memcpy(map, ptr, l); } + + if (!ctxt->server && *proto) { + if (!strncmp(proto, "ldaps", 5)) { + warn(LOGOPT_ANY, MODPREFIX + "server must be given to force ldaps, connection " + "will use LDAP client configured protocol"); + } + } done: if (ctxt->mapname) debug(LOGOPT_NONE, MODPREFIX "mapname %s", ctxt->mapname);