diff options
Diffstat (limited to 'REORG.TODO/nss/nss_db')
-rw-r--r-- | REORG.TODO/nss/nss_db/db-XXX.c | 311 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_db/db-init.c | 47 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_db/db-initgroups.c | 142 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_db/db-netgrp.c | 122 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_db/db-open.c | 67 | ||||
-rw-r--r-- | REORG.TODO/nss/nss_db/nss_db.h | 69 |
6 files changed, 758 insertions, 0 deletions
diff --git a/REORG.TODO/nss/nss_db/db-XXX.c b/REORG.TODO/nss/nss_db/db-XXX.c new file mode 100644 index 0000000000..9849c36223 --- /dev/null +++ b/REORG.TODO/nss/nss_db/db-XXX.c @@ -0,0 +1,311 @@ +/* Common code for DB-based databases in nss_db module. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <fcntl.h> +#include <stdint.h> +#include <sys/mman.h> +#include <libc-lock.h> +#include "nsswitch.h" +#include "nss_db.h" + +/* The hashing function we use. */ +#include "../intl/hash-string.h" + +/* These symbols are defined by the including source file: + + ENTNAME -- database name of the structure and functions (hostent, pwent). + STRUCTURE -- struct name, define only if not ENTNAME (passwd, group). + DATABASE -- database file name, ("hosts", "passwd") + + NEED_H_ERRNO - defined iff an arg `int *herrnop' is used. +*/ + +#define ENTNAME_r CONCAT(ENTNAME,_r) + +#include <paths.h> +#define DBFILE _PATH_VARDB DATABASE ".db" + +#ifdef NEED_H_ERRNO +# define H_ERRNO_PROTO , int *herrnop +# define H_ERRNO_ARG , herrnop +# define H_ERRNO_SET(val) (*herrnop = (val)) +#else +# define H_ERRNO_PROTO +# define H_ERRNO_ARG +# define H_ERRNO_SET(val) ((void) 0) +#endif + +/* State for this database. */ +static struct nss_db_map state; +/* Lock to protect the state and global variables. */ +__libc_lock_define (static , lock); + +/* Maintenance of the shared handle open on the database. */ +static int keep_db; +static const char *entidx; + + +/* Open the database. */ +enum nss_status +CONCAT(_nss_db_set,ENTNAME) (int stayopen) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_setent (DBFILE, &state); + + if (status == NSS_STATUS_SUCCESS) + { + /* Remember STAYOPEN flag. */ + keep_db |= stayopen; + + /* Reset the sequential index. */ + entidx = NULL; + } + + __libc_lock_unlock (lock); + + return status; +} + + +/* Close it again. */ +enum nss_status +CONCAT(_nss_db_end,ENTNAME) (void) +{ + __libc_lock_lock (lock); + + internal_endent (&state); + + /* Reset STAYOPEN flag. */ + keep_db = 0; + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + + +/* Macro for defining lookup functions for this DB-based database. + + NAME is the name of the lookup; e.g. `pwnam'. + + DB_CHAR is index indicator for the database. + + KEYPATTERN gives `printf' args to construct a key string; + e.g. `("%d", id)'. + + KEYSIZE gives the allocation size of a buffer to construct it in; + e.g. `1 + sizeof (id) * 4'. + + PROTO is the potentially empty list of other parameters. + + BREAK_IF_MATCH is a block of code which compares `struct STRUCTURE *result' + to the lookup key arguments and does `break;' if they match. */ + +#define DB_LOOKUP(name, db_char, keysize, keypattern, break_if_match, proto...)\ +enum nss_status \ + _nss_db_get##name##_r (proto, struct STRUCTURE *result, \ + char *buffer, size_t buflen, int *errnop H_ERRNO_PROTO)\ +{ \ + struct parser_data *data = (void *) buffer; \ + \ + if (buflen < sizeof *data) \ + { \ + *errnop = ERANGE; \ + H_ERRNO_SET (NETDB_INTERNAL); \ + return NSS_STATUS_TRYAGAIN; \ + } \ + \ + struct nss_db_map state = { NULL, 0 }; \ + enum nss_status status = internal_setent (DBFILE, &state); \ + if (status != NSS_STATUS_SUCCESS) \ + { \ + *errnop = errno; \ + H_ERRNO_SET (NETDB_INTERNAL); \ + return status; \ + } \ + \ + const struct nss_db_header *header = state.header; \ + int i; \ + for (i = 0; i < header->ndbs; ++i) \ + if (header->dbs[i].id == db_char) \ + break; \ + if (i == header->ndbs) \ + { \ + status = NSS_STATUS_UNAVAIL; \ + goto out; \ + } \ + \ + char *key; \ + if (db_char == '.') \ + key = (char *) IGNOREPATTERN keypattern; \ + else \ + { \ + const size_t size = (keysize) + 1; \ + key = alloca (size); \ + \ + KEYPRINTF keypattern; \ + } \ + \ + const stridx_t *hashtable \ + = (const stridx_t *) ((const char *) header \ + + header->dbs[i].hashoffset); \ + const char *valstrtab = (const char *) header + header->valstroffset; \ + uint32_t hashval = __hash_string (key); \ + size_t hidx = hashval % header->dbs[i].hashsize; \ + size_t hval2 = 1 + hashval % (header->dbs[i].hashsize - 2); \ + \ + status = NSS_STATUS_NOTFOUND; \ + while (hashtable[hidx] != ~((stridx_t) 0)) \ + { \ + const char *valstr = valstrtab + hashtable[hidx]; \ + size_t len = strlen (valstr) + 1; \ + if (len > buflen) \ + { \ + /* No room to copy the data to. */ \ + *errnop = ERANGE; \ + H_ERRNO_SET (NETDB_INTERNAL); \ + status = NSS_STATUS_TRYAGAIN; \ + break; \ + } \ + \ + /* Copy the string to a place where it can be modified. */ \ + char *p = memcpy (buffer, valstr, len); \ + \ + int err = parse_line (p, result, data, buflen, errnop EXTRA_ARGS); \ + \ + /* Advance before break_if_match, lest it uses continue to skip + to the next entry. */ \ + if ((hidx += hval2) >= header->dbs[i].hashsize) \ + hidx -= header->dbs[i].hashsize; \ + \ + if (err > 0) \ + { \ + status = NSS_STATUS_SUCCESS; \ + break_if_match; \ + status = NSS_STATUS_NOTFOUND; \ + } \ + else if (err == -1) \ + { \ + H_ERRNO_SET (NETDB_INTERNAL); \ + status = NSS_STATUS_TRYAGAIN; \ + break; \ + } \ + } \ + \ + if (status == NSS_STATUS_NOTFOUND) \ + H_ERRNO_SET (HOST_NOT_FOUND); \ + \ + out: \ + internal_endent (&state); \ + \ + return status; \ +} + +#define KEYPRINTF(pattern, args...) snprintf (key, size, pattern ,##args) +#define IGNOREPATTERN(pattern, arg1, args...) (char *) (uintptr_t) arg1 + + + + +/* Return the next entry from the database file, doing locking. */ +enum nss_status +CONCAT(_nss_db_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer, + size_t buflen, int *errnop H_ERRNO_PROTO) +{ + /* Return next entry in host file. */ + enum nss_status status; + struct parser_data *data = (void *) buffer; + + if (buflen < sizeof *data) + { + *errnop = ERANGE; + H_ERRNO_SET (NETDB_INTERNAL); + return NSS_STATUS_TRYAGAIN; + } + + __libc_lock_lock (lock); + + if (state.header == NULL) + { + status = internal_setent (DBFILE, &state); + if (status != NSS_STATUS_SUCCESS) + { + *errnop = errno; + H_ERRNO_SET (NETDB_INTERNAL); + goto out; + } + entidx = NULL; + } + + /* Start from the beginning if freshly initialized or reset + requested by set*ent. */ + if (entidx == NULL) + entidx = (const char *) state.header + state.header->valstroffset; + + status = NSS_STATUS_UNAVAIL; + if (state.header != MAP_FAILED) + { + const char *const end = ((const char *) state.header + + state.header->valstroffset + + state.header->valstrlen); + while (entidx < end) + { + const char *next = rawmemchr (entidx, '\0') + 1; + size_t len = next - entidx; + + if (len > buflen) + { + /* No room to copy the data to. */ + *errnop = ERANGE; + H_ERRNO_SET (NETDB_INTERNAL); + status = NSS_STATUS_TRYAGAIN; + break; + } + + /* Copy the string to a place where it can be modified. */ + char *p = memcpy (buffer, entidx, len); + + int err = parse_line (p, result, data, buflen, errnop EXTRA_ARGS); + + if (err > 0) + { + status = NSS_STATUS_SUCCESS; + entidx = next; + break; + } + if (err < 0) + { + H_ERRNO_SET (NETDB_INTERNAL); + status = NSS_STATUS_TRYAGAIN; + break; + } + + /* Continue with the next record, this one is ill-formed. */ + entidx = next; + } + } + + out: + __libc_lock_unlock (lock); + + return status; +} diff --git a/REORG.TODO/nss/nss_db/db-init.c b/REORG.TODO/nss/nss_db/db-init.c new file mode 100644 index 0000000000..1a65c59119 --- /dev/null +++ b/REORG.TODO/nss/nss_db/db-init.c @@ -0,0 +1,47 @@ +/* Initialization in nss_db module. + Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifdef USE_NSCD + +#include <paths.h> +#include <nscd/nscd.h> +#include <string.h> + +#define PWD_FILENAME (_PATH_VARDB "passwd.db") +define_traced_file (pwd, PWD_FILENAME); + +#define GRP_FILENAME (_PATH_VARDB "group.db") +define_traced_file (grp, GRP_FILENAME); + +#define SERV_FILENAME (_PATH_VARDB "services.db") +define_traced_file (serv, SERV_FILENAME); + +void +_nss_db_init (void (*cb) (size_t, struct traced_file *)) +{ + init_traced_file (&pwd_traced_file.file, PWD_FILENAME, 0); + cb (pwddb, &pwd_traced_file.file); + + init_traced_file (&grp_traced_file.file, GRP_FILENAME, 0); + cb (grpdb, &grp_traced_file.file); + + init_traced_file (&serv_traced_file.file, SERV_FILENAME, 0); + cb (servdb, &serv_traced_file.file); +} + +#endif diff --git a/REORG.TODO/nss/nss_db/db-initgroups.c b/REORG.TODO/nss/nss_db/db-initgroups.c new file mode 100644 index 0000000000..11e6052453 --- /dev/null +++ b/REORG.TODO/nss/nss_db/db-initgroups.c @@ -0,0 +1,142 @@ +/* Initgroups handling in nss_db module. + Copyright (C) 2011-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@gmail.com>. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, see <http://www.gnu.org/licenses/>. */ + +#include <ctype.h> +#include <errno.h> +#include <grp.h> +#include <limits.h> +#include <paths.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <sys/param.h> + +#include "nss_db.h" + +/* The hashing function we use. */ +#include "../intl/hash-string.h" + + +enum nss_status +_nss_db_initgroups_dyn (const char *user, gid_t group, long int *start, + long int *size, gid_t **groupsp, long int limit, + int *errnop) +{ + struct nss_db_map state = { NULL, 0 }; + enum nss_status status = internal_setent (_PATH_VARDB "group.db", &state); + if (status != NSS_STATUS_SUCCESS) + { + *errnop = errno; + return status; + } + + const struct nss_db_header *header = state.header; + int i; + for (i = 0; i < header->ndbs; ++i) + if (header->dbs[i].id == ':') + break; + if (i == header->ndbs) + { + status = NSS_STATUS_UNAVAIL; + goto out; + } + + const stridx_t *hashtable + = (const stridx_t *) ((const char *) header + + header->dbs[i].hashoffset); + const char *valstrtab = (const char *) header + header->valstroffset; + size_t userlen = strlen (user); + uint32_t hashval = __hash_string (user); + size_t hidx = hashval % header->dbs[i].hashsize; + size_t hval2 = 1 + hashval % (header->dbs[i].hashsize - 2); + + gid_t *groups = *groupsp; + + status = NSS_STATUS_NOTFOUND; + while (hashtable[hidx] != ~((stridx_t) 0)) + { + const char *valstr = valstrtab + hashtable[hidx]; + while (isblank (*valstr)) + ++valstr; + + if (strncmp (valstr, user, userlen) == 0 && isblank (valstr[userlen])) + { + valstr += userlen + 1; + while (isblank (*valstr)) + ++valstr; + + while (*valstr != '\0') + { + errno = 0; + char *endp; + unsigned long int n = strtoul (valstr, &endp, 10); + if (*endp != ',' && *endp != '\0') + break; + valstr = *endp == '\0' ? endp : endp + 1; + + if (n != ULONG_MAX || errno != ERANGE) + { + /* Insert the group. */ + if (*start == *size) + { + /* Need a bigger buffer. */ + if (limit > 0 && *size == limit) + { + /* We reached the maximum. */ + status = NSS_STATUS_SUCCESS; + goto out; + } + + long int newsize; + if (limit <= 0) + newsize = 2 * *size; + else + newsize = MIN (limit, 2 * *size); + + gid_t *newgroups = realloc (groups, + newsize * sizeof (*groups)); + if (newgroups == NULL) + { + *errnop = ENOMEM; + status = NSS_STATUS_TRYAGAIN; + goto out; + } + + *groupsp = groups = newgroups; + *size = newsize; + } + + groups[*start] = n; + *start += 1; + } + } + + status = NSS_STATUS_SUCCESS; + break; + } + + if ((hidx += hval2) >= header->dbs[i].hashsize) + hidx -= header->dbs[i].hashsize; + } + + out: + internal_endent (&state); + + return status; +} diff --git a/REORG.TODO/nss/nss_db/db-netgrp.c b/REORG.TODO/nss/nss_db/db-netgrp.c new file mode 100644 index 0000000000..25530cc206 --- /dev/null +++ b/REORG.TODO/nss/nss_db/db-netgrp.c @@ -0,0 +1,122 @@ +/* Netgroup file parser in nss_db modules. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <ctype.h> +#include <dlfcn.h> +#include <errno.h> +#include <fcntl.h> +#include <netgroup.h> +#include <string.h> +#include <stdint.h> +#include <libc-lock.h> +#include <paths.h> +#include <stdlib.h> + +#include "nsswitch.h" +#include "nss_db.h" + +/* The hashing function we use. */ +#include "../intl/hash-string.h" + + +#define DBFILE _PATH_VARDB "netgroup.db" + +/* Maintenance of the shared handle open on the database. */ +enum nss_status +_nss_db_setnetgrent (const char *group, struct __netgrent *result) +{ + struct nss_db_map state; + enum nss_status status = internal_setent (DBFILE, &state); + + if (status == NSS_STATUS_SUCCESS) + { + const struct nss_db_header *header = state.header; + const stridx_t *hashtable + = (const stridx_t *) ((const char *) header + + header->dbs[0].hashoffset); + const char *valstrtab = (const char *) header + header->valstroffset; + uint32_t hashval = __hash_string (group); + size_t grouplen = strlen (group); + size_t hidx = hashval % header->dbs[0].hashsize; + size_t hval2 = 1 + hashval % (header->dbs[0].hashsize - 2); + + status = NSS_STATUS_NOTFOUND; + while (hashtable[hidx] != ~((stridx_t) 0)) + { + const char *valstr = valstrtab + hashtable[hidx]; + + if (strncmp (valstr, group, grouplen) == 0 + && isblank (valstr[grouplen])) + { + const char *cp = &valstr[grouplen + 1]; + while (isblank (*cp)) + ++cp; + if (*cp != '\0') + { + result->data = strdup (cp); + if (result->data == NULL) + status = NSS_STATUS_TRYAGAIN; + else + { + status = NSS_STATUS_SUCCESS; + result->cursor = result->data; + } + break; + } + } + + if ((hidx += hval2) >= header->dbs[0].hashsize) + hidx -= header->dbs[0].hashsize; + } + + internal_endent (&state); + } + + return status; + +} + + +enum nss_status +_nss_db_endnetgrent (struct __netgrent *result) +{ + free (result->data); + result->data = NULL; + result->data_size = 0; + result->cursor = NULL; + return NSS_STATUS_SUCCESS; +} + + +extern enum nss_status _nss_netgroup_parseline (char **cursor, + struct __netgrent *result, + char *buffer, size_t buflen, + int *errnop); + +enum nss_status +_nss_db_getnetgrent_r (struct __netgrent *result, char *buffer, size_t buflen, + int *errnop) +{ + enum nss_status status; + + status = _nss_netgroup_parseline (&result->cursor, result, buffer, buflen, + errnop); + + return status; +} diff --git a/REORG.TODO/nss/nss_db/db-open.c b/REORG.TODO/nss/nss_db/db-open.c new file mode 100644 index 0000000000..1c58bd1c54 --- /dev/null +++ b/REORG.TODO/nss/nss_db/db-open.c @@ -0,0 +1,67 @@ +/* Common database routines for nss_db. + Copyright (C) 2000-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <fcntl.h> +#include <dlfcn.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/mman.h> +#include <not-cancel.h> + +#include "nss_db.h" + +/* Open the database stored in FILE. If succesful, store either a + pointer to the mapped file or a file handle for the file in H and + return NSS_STATUS_SUCCESS. On failure, return the appropriate + lookup status. */ +enum nss_status +internal_setent (const char *file, struct nss_db_map *mapping) +{ + enum nss_status status = NSS_STATUS_UNAVAIL; + + int fd = open_not_cancel_2 (file, O_RDONLY | O_LARGEFILE | O_CLOEXEC); + if (fd != -1) + { + struct nss_db_header header; + + if (read (fd, &header, sizeof (header)) == sizeof (header)) + { + mapping->header = mmap (NULL, header.allocate, PROT_READ, + MAP_PRIVATE, fd, 0); + mapping->len = header.allocate; + if (mapping->header != MAP_FAILED) + status = NSS_STATUS_SUCCESS; + else if (errno == ENOMEM) + status = NSS_STATUS_TRYAGAIN; + } + + close_not_cancel_no_status (fd); + } + + return status; +} + + +/* Close the database. */ +void +internal_endent (struct nss_db_map *mapping) +{ + munmap (mapping->header, mapping->len); +} diff --git a/REORG.TODO/nss/nss_db/nss_db.h b/REORG.TODO/nss/nss_db/nss_db.h new file mode 100644 index 0000000000..6978cead07 --- /dev/null +++ b/REORG.TODO/nss/nss_db/nss_db.h @@ -0,0 +1,69 @@ +/* Common database open/close routines for nss_db. + Copyright (C) 1999-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _NSS_DB_H +#define _NSS_DB_H 1 + +#include <nss.h> +#include <stdint.h> +#include <libc-lock.h> + + +/* String table index type. */ +typedef uint32_t stridx_t; + +/* Database file header. */ +struct nss_db_header +{ + uint32_t magic; +#define NSS_DB_MAGIC 0xdd110601 + uint32_t ndbs; + uint64_t valstroffset; + uint64_t valstrlen; + uint64_t allocate; + struct + { + char id; + char pad[sizeof (uint32_t) - 1]; + uint32_t hashsize; + uint64_t hashoffset; + uint64_t keyidxoffset; + uint64_t keystroffset; + } dbs[0]; +}; + + +/* Information about mapped database. */ +struct nss_db_map +{ + struct nss_db_header *header; + size_t len; +}; + + +/* Open the database stored in FILE. If succesful, store the database + handle in *MAPPINGP or a file descriptor for the file in *FDP and + return NSS_STATUS_SUCCESS. On failure, return the appropriate + lookup status. */ +enum nss_status internal_setent (const char *file, + struct nss_db_map *mappingp); + +/* Close the database FD. */ +extern void internal_endent (struct nss_db_map *mapping); + +#endif /* nss_db.h */ |