Hi, in ldapd and ldapctl the "-r directory" command line argument does not work:
ldapd fork/execs itself but the directory command line argument is not given to the execvp call which then uses the default data directory. ldapctl has a thinko/typo which causes the data_db to be always opened in the default directory for indexing. The patch below removes the command line argument and corresponding global variable and instead uses a configuration file directive "datadir". Incidentally removes the global 'datadir' variable used before. Best regards Robert ----------------------------------------------- commit 6a71c90c19b5dc5850305c15696af3f14d26c168 (master) from: Robert Klein <rokl...@roklein.de> date: Mon Mar 2 18:50:12 2020 UTC fix ldapd/ldapctl data directory handling -r directive didn't work as intended in both ldapd and ldapctl. this patch replaces command line argument '-r directory' with a configuration file directive 'datadir'. diff f62b80b397c780e8273b5cc67d544b951c4c9d1f 35bb29194b2067dab925ec4566dfb82f9bf34d65 blob - 48cff01b435bca0deebf28f55e6f71675c5752f2 blob + 231af2ddbbee2da446d2f03c9c48e679e216e993 --- usr.sbin/ldapctl/ldapctl.8 +++ usr.sbin/ldapctl/ldapctl.8 @@ -24,7 +24,6 @@ .Nm ldapctl .Op Fl v .Op Fl f Ar file -.Op Fl r Ar directory .Op Fl s Ar socket .Ar command .Op Ar argument ... @@ -42,11 +41,6 @@ Use .Ar file as the configuration file, instead of the default .Pa /etc/ldapd.conf . -.It Fl r Ar directory -Store and read database files in -.Ar directory , -instead of the default -.Pa /var/db/ldap . .It Fl s Ar socket Use .Ar socket blob - c8564c5543f518a720e049c559556f87edda6b8a blob + 6830a603d153794390faafbc9aadc8ef0bd985c0 --- usr.sbin/ldapctl/ldapctl.c +++ usr.sbin/ldapctl/ldapctl.c @@ -58,10 +58,10 @@ void show_stats(struct imsg *imsg); void show_dbstats(const char *prefix, struct btree_stat *st); void show_nsstats(struct imsg *imsg); int compact_db(const char *path); -int compact_namespace(struct namespace *ns, const char *datadir); -int compact_namespaces(const char *datadir); -int index_namespace(struct namespace *ns, const char *datadir); -int index_namespaces(const char *datadir); +int compact_namespace(struct namespace *ns); +int compact_namespaces(void); +int index_namespace(struct namespace *ns); +int index_namespaces(void); int ssl_load_certfile(struct ldapd_config *, const char *, u_int8_t); __dead void @@ -70,7 +70,7 @@ usage(void) extern char *__progname; fprintf(stderr, - "usage: %s [-v] [-f file] [-r directory] [-s socket] " + "usage: %s [-v] [-f file] [-s socket] " "command [argument ...]\n", __progname); exit(1); @@ -97,11 +97,11 @@ compact_db(const char *path) } int -compact_namespace(struct namespace *ns, const char *datadir) +compact_namespace(struct namespace *ns) { char *path; - if (asprintf(&path, "%s/%s_data.db", datadir, ns->suffix) == -1) + if (asprintf(&path, "%s/%s_data.db", conf->datadir, ns->suffix) == -1) return -1; if (compact_db(path) != 0) { log_warn("%s", path); @@ -110,7 +110,7 @@ compact_namespace(struct namespace *ns, const char *da } free(path); - if (asprintf(&path, "%s/%s_indx.db", datadir, ns->suffix) == -1) + if (asprintf(&path, "%s/%s_indx.db", conf->datadir, ns->suffix) == -1) return -1; if (compact_db(path) != 0) { log_warn("%s", path); @@ -123,14 +123,14 @@ compact_namespace(struct namespace *ns, const char *da } int -compact_namespaces(const char *datadir) +compact_namespaces() { struct namespace *ns; TAILQ_FOREACH(ns, &conf->namespaces, next) { if (SLIST_EMPTY(&ns->referrals)) continue; - if (compact_namespace(ns, datadir) != 0) + if (compact_namespace(ns) != 0) return -1; } @@ -138,7 +138,7 @@ compact_namespaces(const char *datadir) } int -index_namespace(struct namespace *ns, const char *datadir) +index_namespace(struct namespace *ns) { struct btval key, val; struct btree *data_db, *indx_db; @@ -150,14 +150,14 @@ index_namespace(struct namespace *ns, const char *data log_info("indexing namespace %s", ns->suffix); - if (asprintf(&path, "%s/%s_data.db", DATADIR, ns->suffix) == -1) + if (asprintf(&path, "%s/%s_data.db", conf->datadir, ns->suffix) == -1) return -1; data_db = btree_open(path, BT_NOSYNC | BT_REVERSEKEY, 0644); free(path); if (data_db == NULL) return -1; - if (asprintf(&path, "%s/%s_indx.db", datadir, ns->suffix) == -1) + if (asprintf(&path, "%s/%s_indx.db", conf->datadir, ns->suffix) == -1) return -1; indx_db = btree_open(path, BT_NOSYNC, 0644); free(path); @@ -219,14 +219,14 @@ index_namespace(struct namespace *ns, const char *data } int -index_namespaces(const char *datadir) +index_namespaces() { struct namespace *ns; TAILQ_FOREACH(ns, &conf->namespaces, next) { if (SLIST_EMPTY(&ns->referrals)) continue; - if (index_namespace(ns, datadir) != 0) + if (index_namespace(ns) != 0) return -1; } @@ -247,7 +247,6 @@ main(int argc, char *argv[]) ssize_t n; int ch; enum action action = NONE; - const char *datadir = DATADIR; struct stat sb; const char *sock = LDAPD_SOCKET; char *conffile = CONFFILE; @@ -262,9 +261,6 @@ main(int argc, char *argv[]) case 'f': conffile = optarg; break; - case 'r': - datadir = optarg; - break; case 's': sock = optarg; break; @@ -282,11 +278,6 @@ main(int argc, char *argv[]) if (argc == 0) usage(); - if (stat(datadir, &sb) == -1) - err(1, "%s", datadir); - if (!S_ISDIR(sb.st_mode)) - errx(1, "%s is not a directory", datadir); - ldap_loginit(NULL, 1, verbose); if (strcmp(argv[0], "stats") == 0) @@ -311,13 +302,22 @@ main(int argc, char *argv[]) if (parse_config(conffile) != 0) exit(2); + if (conf->datadir == NULL) { + if (asprintf(&conf->datadir, "%s", LDAPD_DATADIR) == -1) + errx(1, "malloc failed"); + } + if (stat(conf->datadir, &sb) == -1) + err(1, "%s", conf->datadir); + if (!S_ISDIR(sb.st_mode)) + errx(1, "%s is not a directory", conf->datadir); + if (pledge("stdio rpath wpath cpath flock", NULL) == -1) err(1, "pledge"); if (action == COMPACT_DB) - return compact_namespaces(datadir); + return compact_namespaces(); else - return index_namespaces(datadir); + return index_namespaces(); } /* connect to ldapd control socket */ blob - db5a0be5ad93c11c0dd773d342ea131328dcaa82 blob + 8588bbe3dc5ffd81b91967cf809681b1998cbd69 --- usr.sbin/ldapd/ldapd.8 +++ usr.sbin/ldapd/ldapd.8 @@ -27,7 +27,6 @@ .Fl D Ar macro Ns = Ns Ar value .Oc .Op Fl f Ar file -.Op Fl r Ar directory .Op Fl s Ar file .Sh DESCRIPTION .Nm @@ -61,11 +60,6 @@ as the configuration file, instead of the default .It Fl n Configtest mode. Only check the configuration file for validity. -.It Fl r Ar directory -Store and read database files in -.Ar directory , -instead of the default -.Pa /var/db/ldap . .It Fl s Ar file Specify an alternative location for the socket file. .It Fl v blob - 797a36f89f33233c2d9655a307ec5e727b9fbaa1 blob + 69ae065ae99ba9ab326afd1fe0db5eeb820ea629 --- usr.sbin/ldapd/ldapd.c +++ usr.sbin/ldapd/ldapd.c @@ -55,7 +55,6 @@ static pid_t start_child(enum ldapd_process, char *, struct ldapd_stats stats; pid_t ldape_pid; -const char *datadir = DATADIR; void usage(void) @@ -63,7 +62,7 @@ usage(void) extern char *__progname; fprintf(stderr, "usage: %s [-dnv] [-D macro=value] " - "[-f file] [-r directory] [-s file]\n", __progname); + "[-f file] [-s file]\n", __progname); exit(1); } @@ -151,9 +150,6 @@ main(int argc, char *argv[]) case 'n': configtest = 1; break; - case 'r': - datadir = optarg; - break; case 's': csockpath = optarg; break; @@ -193,15 +189,20 @@ main(int argc, char *argv[]) exit(0); } + if (conf->datadir == NULL) { + if (asprintf(&conf->datadir, "%s", LDAPD_DATADIR) == -1) + errx(1, "malloc failed"); + } + log_init(debug, LOG_DAEMON); if (eflag) ldape(debug, verbose, csockpath); - if (stat(datadir, &sb) == -1) - err(1, "%s", datadir); + if (stat(conf->datadir, &sb) == -1) + err(1, "%s", conf->datadir); if (!S_ISDIR(sb.st_mode)) - errx(1, "%s is not a directory", datadir); + errx(1, "%s is not a directory", conf->datadir); if (!debug) { if (daemon(1, 0) == -1) @@ -213,7 +214,7 @@ main(int argc, char *argv[]) if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, PF_UNSPEC, pipe_parent2ldap) != 0) fatal("socketpair"); - + ldape_pid = start_child(PROC_LDAP_SERVER, saved_argv0, pipe_parent2ldap[1], debug, verbose, csockpath, conffile); @@ -392,7 +393,7 @@ ldapd_open_request(struct imsgev *iev, struct imsg *im /* make sure path is null-terminated */ oreq->path[PATH_MAX] = '\0'; - if (strncmp(oreq->path, datadir, strlen(datadir)) != 0) { + if (strncmp(oreq->path, conf->datadir, strlen(conf->datadir)) != 0) { log_warnx("refusing to open file %s", oreq->path); fatal("ldape sent invalid open request"); } @@ -459,7 +460,7 @@ start_child(enum ldapd_process p, char *argv0, int fd, argv[argc++] = "-f"; argv[argc++] = conffile; } - + argv[argc++] = NULL; execvp(argv0, argv); blob - 3da0137e137e8b3bc64f6351579fcd6a9344b1f8 blob + 31c894c3e39ab70f3324415ecac5efc1301e0a54 --- usr.sbin/ldapd/ldapd.conf.5 +++ usr.sbin/ldapd/ldapd.conf.5 @@ -130,6 +130,11 @@ The URL has the following format: ldap://ldap.example.com ldaps://ldap.example.com:3890 .Ed +.It datadir Ar directory +Store and read database files in +.Ar directory , +instead of the default +.Pa /var/db/ldap . .It rootdn Ar dn Specify the distinguished name of the root user for all namespaces. The root user is always allowed to read and write entries in all blob - 3f995d184b442f094a95f089e3bb4a727eabf559 blob + 2736d366bf5f92e3579f915f4ceb2a3610d27d54 --- usr.sbin/ldapd/ldapd.h +++ usr.sbin/ldapd/ldapd.h @@ -41,7 +41,7 @@ #define CONFFILE "/etc/ldapd.conf" #define LDAPD_USER "_ldapd" #define LDAPD_SOCKET "/var/run/ldapd.sock" -#define DATADIR "/var/db/ldap" +#define LDAPD_DATADIR "/var/db/ldap" #define LDAP_PORT 389 #define LDAPS_PORT 636 #define LDAPD_SESSION_TIMEOUT 30 @@ -252,6 +252,7 @@ struct ldapd_config struct schema *schema; char *rootdn; char *rootpw; + char *datadir; }; struct ldapd_stats blob - 2259f57bde3c2918a8b200747c194e5768ae40f1 blob + 2e39abf6cc94ac6f301876df996a6229a032a7b7 --- usr.sbin/ldapd/namespace.c +++ usr.sbin/ldapd/namespace.c @@ -29,8 +29,6 @@ #include "ldapd.h" #include "log.h" -extern const char *datadir; - /* Maximum number of requests to queue per namespace during compaction. * After this many requests, we return LDAP_BUSY. */ @@ -118,7 +116,8 @@ namespace_open(struct namespace *ns) if (ns->sync == 0) db_flags |= BT_NOSYNC; - if (asprintf(&ns->data_path, "%s/%s_data.db", datadir, ns->suffix) == -1) + if (asprintf(&ns->data_path, "%s/%s_data.db", conf->datadir, + ns->suffix) == -1) return -1; log_info("opening namespace %s", ns->suffix); ns->data_db = btree_open(ns->data_path, db_flags | BT_REVERSEKEY, 0644); @@ -127,7 +126,8 @@ namespace_open(struct namespace *ns) btree_set_cache_size(ns->data_db, ns->cache_size); - if (asprintf(&ns->indx_path, "%s/%s_indx.db", datadir, ns->suffix) == -1) + if (asprintf(&ns->indx_path, "%s/%s_indx.db", conf->datadir, + ns->suffix) == -1) return -1; ns->indx_db = btree_open(ns->indx_path, db_flags, 0644); if (ns->indx_db == NULL) blob - bad9bc630403e5280e3b0db41d8ec1247db70352 blob + b72e4d89324b332498f8e5e0d1d8db822d4588f9 --- usr.sbin/ldapd/parse.y +++ usr.sbin/ldapd/parse.y @@ -117,7 +117,7 @@ static struct namespace *current_ns = NULL; %} %token ERROR LISTEN ON TLS LDAPS PORT NAMESPACE ROOTDN ROOTPW INDEX -%token SECURE RELAX STRICT SCHEMA USE COMPRESSION LEVEL +%token SECURE RELAX STRICT SCHEMA USE COMPRESSION LEVEL DATADIR %token INCLUDE CERTIFICATE FSYNC CACHE_SIZE INDEX_CACHE_SIZE %token DENY ALLOW READ WRITE BIND ACCESS TO ROOT REFERRAL %token ANY CHILDREN OF ATTRIBUTE IN SUBTREE BY SELF @@ -225,6 +225,7 @@ conf_main : LISTEN ON STRING port ssl certname { normalize_dn(conf->rootdn); } | ROOTPW STRING { conf->rootpw = $2; } + | DATADIR STRING { conf->datadir = $2; } ; namespace : NAMESPACE STRING '{' '\n' { @@ -441,6 +442,7 @@ lookup(char *s) { "certificate", CERTIFICATE }, { "children", CHILDREN }, { "compression", COMPRESSION }, + { "datadir", DATADIR }, { "deny", DENY }, { "fsync", FSYNC }, { "in", IN },