summaryrefslogtreecommitdiffstats
path: root/lib/nss.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/nss.c')
-rw-r--r--lib/nss.c138
1 files changed, 71 insertions, 67 deletions
diff --git a/lib/nss.c b/lib/nss.c
index 23d0518..779d825 100644
--- a/lib/nss.c
+++ b/lib/nss.c
@@ -1,3 +1,5 @@
+#include <config.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
@@ -6,10 +8,14 @@
#include <strings.h>
#include <ctype.h>
#include <stdatomic.h>
+
+#include "alloc.h"
#include "prototypes.h"
#include "../libsubid/subid.h"
#include "shadowlog_internal.h"
#include "shadowlog.h"
+#include "string/sprintf.h"
+
#define NSSWITCH "/etc/nsswitch.conf"
@@ -40,10 +46,12 @@ static void nss_exit(void) {
// nsswitch_path is an argument only to support testing.
void nss_init(const char *nsswitch_path) {
- FILE *nssfp = NULL;
- char *line = NULL, *p, *token, *saveptr;
- size_t len = 0;
- FILE *shadow_logfd = log_get_logfd();
+ char *line = NULL, *p, *token, *saveptr;
+ char libname[64];
+ FILE *nssfp = NULL;
+ FILE *shadow_logfd = log_get_logfd();
+ void *h;
+ size_t len = 0;
if (atomic_flag_test_and_set(&nss_init_started)) {
// Another thread has started nss_init, wait for it to complete
@@ -59,82 +67,78 @@ void nss_init(const char *nsswitch_path) {
// subid: files
nssfp = fopen(nsswitch_path, "r");
if (!nssfp) {
+ if (errno != ENOENT)
+ fprintf(shadow_logfd, "Failed opening %s: %m\n", nsswitch_path);
+
atomic_store(&nss_init_completed, true);
return;
}
- while ((getline(&line, &len, nssfp)) != -1) {
- if (line[0] == '\0' || line[0] == '#')
+ p = NULL;
+ while (getline(&line, &len, nssfp) != -1) {
+ if (line[0] == '#')
continue;
if (strlen(line) < 8)
continue;
if (strncasecmp(line, "subid:", 6) != 0)
continue;
p = &line[6];
- while ((*p) && isspace(*p))
+ while (isspace(*p))
p++;
- if (!*p)
- continue;
- for (token = strtok_r(p, " \n\t", &saveptr);
- token;
- token = strtok_r(NULL, " \n\t", &saveptr)) {
- char libname[65];
- void *h;
- if (strcmp(token, "files") == 0) {
- subid_nss = NULL;
- goto done;
- }
- if (strlen(token) > 50) {
- fprintf(shadow_logfd, "Subid NSS module name too long (longer than 50 characters): %s\n", token);
- fprintf(shadow_logfd, "Using files\n");
- subid_nss = NULL;
- goto done;
- }
- snprintf(libname, 64, "libsubid_%s.so", token);
- h = dlopen(libname, RTLD_LAZY);
- if (!h) {
- fprintf(shadow_logfd, "Error opening %s: %s\n", libname, dlerror());
- fprintf(shadow_logfd, "Using files\n");
- subid_nss = NULL;
- goto done;
- }
- subid_nss = malloc(sizeof(*subid_nss));
- if (!subid_nss) {
- dlclose(h);
- goto done;
- }
- subid_nss->has_range = dlsym(h, "shadow_subid_has_range");
- if (!subid_nss->has_range) {
- fprintf(shadow_logfd, "%s did not provide @has_range@\n", libname);
- dlclose(h);
- free(subid_nss);
- subid_nss = NULL;
- goto done;
- }
- subid_nss->list_owner_ranges = dlsym(h, "shadow_subid_list_owner_ranges");
- if (!subid_nss->list_owner_ranges) {
- fprintf(shadow_logfd, "%s did not provide @list_owner_ranges@\n", libname);
- dlclose(h);
- free(subid_nss);
- subid_nss = NULL;
- goto done;
- }
- subid_nss->find_subid_owners = dlsym(h, "shadow_subid_find_subid_owners");
- if (!subid_nss->find_subid_owners) {
- fprintf(shadow_logfd, "%s did not provide @find_subid_owners@\n", libname);
- dlclose(h);
- free(subid_nss);
- subid_nss = NULL;
- goto done;
- }
- subid_nss->handle = h;
- goto done;
- }
+ if (*p != '\0')
+ break;
+ p = NULL;
+ }
+ if (p == NULL) {
+ goto null_subid;
+ }
+ token = strtok_r(p, " \n\t", &saveptr);
+ if (token == NULL) {
fprintf(shadow_logfd, "No usable subid NSS module found, using files\n");
// subid_nss has to be null here, but to ease reviews:
- free(subid_nss);
- subid_nss = NULL;
- goto done;
+ goto null_subid;
}
+ if (strcmp(token, "files") == 0) {
+ goto null_subid;
+ }
+ if (strlen(token) > 50) {
+ fprintf(shadow_logfd, "Subid NSS module name too long (longer than 50 characters): %s\n", token);
+ fprintf(shadow_logfd, "Using files\n");
+ goto null_subid;
+ }
+ SNPRINTF(libname, "libsubid_%s.so", token);
+ h = dlopen(libname, RTLD_LAZY);
+ if (!h) {
+ fprintf(shadow_logfd, "Error opening %s: %s\n", libname, dlerror());
+ fprintf(shadow_logfd, "Using files\n");
+ goto null_subid;
+ }
+ subid_nss = MALLOC(1, struct subid_nss_ops);
+ if (!subid_nss) {
+ goto close_lib;
+ }
+ subid_nss->has_range = dlsym(h, "shadow_subid_has_range");
+ if (!subid_nss->has_range) {
+ fprintf(shadow_logfd, "%s did not provide @has_range@\n", libname);
+ goto close_lib;
+ }
+ subid_nss->list_owner_ranges = dlsym(h, "shadow_subid_list_owner_ranges");
+ if (!subid_nss->list_owner_ranges) {
+ fprintf(shadow_logfd, "%s did not provide @list_owner_ranges@\n", libname);
+ goto close_lib;
+ }
+ subid_nss->find_subid_owners = dlsym(h, "shadow_subid_find_subid_owners");
+ if (!subid_nss->find_subid_owners) {
+ fprintf(shadow_logfd, "%s did not provide @find_subid_owners@\n", libname);
+ goto close_lib;
+ }
+ subid_nss->handle = h;
+ goto done;
+
+close_lib:
+ dlclose(h);
+ free(subid_nss);
+null_subid:
+ subid_nss = NULL;
done:
atomic_store(&nss_init_completed, true);