@@ -25,6 +25,10 @@
#include <libc-lock.h>
#endif
+/* Open DATABASE for reading. */
+FILE *__nss_files_fopen_database (const char *database);
+libc_hidden_proto (__nss_files_fopen_database)
+
/* Open PATH for reading, as a data source for nss_files. */
FILE *__nss_files_fopen (const char *path);
libc_hidden_proto (__nss_files_fopen)
@@ -89,7 +93,7 @@ enum nss_files_file
null. */
enum nss_status __nss_files_data_open (struct nss_files_per_file_data **pdata,
enum nss_files_file file,
- const char *path,
+ const char *database,
int *errnop, int *herrnop);
libc_hidden_proto (__nss_files_data_open)
@@ -101,7 +105,7 @@ libc_hidden_proto (__nss_files_data_put)
/* Performs the set*ent operation for FILE. PATH is the file to
open. */
enum nss_status __nss_files_data_setent (enum nss_files_file file,
- const char *path);
+ const char *database);
libc_hidden_proto (__nss_files_data_setent)
/* Performs the end*ent operation for FILE. */
@@ -108,7 +108,7 @@ libc {
__nss_passwd_lookup2; __nss_group_lookup2; __nss_hosts_lookup2;
__nss_services_lookup2; __nss_next2; __nss_lookup;
__nss_hash; __nss_database_get;
- __nss_files_fopen; __nss_readline; __nss_parse_line_result;
+ __nss_files_fopen; __nss_files_fopen_database; __nss_readline; __nss_parse_line_result;
__nss_files_data_endent;
__nss_files_data_open;
__nss_files_data_put;
@@ -108,7 +108,7 @@ internal_setgrent (ent_t *ent, int stayopen, int needent)
if (ent->stream == NULL)
{
- ent->stream = __nss_files_fopen ("/etc/group");
+ ent->stream = __nss_files_fopen_database ("group");
if (ent->stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
@@ -122,7 +122,7 @@ internal_setgrent (ent_t *ent)
else
ent->blacklist.current = 0;
- ent->stream = __nss_files_fopen ("/etc/group");
+ ent->stream = __nss_files_fopen_database ("group");
if (ent->stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
@@ -223,7 +223,7 @@ internal_setpwent (ent_t *ent, int stayopen, int needent)
if (ent->stream == NULL)
{
- ent->stream = __nss_files_fopen ("/etc/passwd");
+ ent->stream = __nss_files_fopen_database ("passwd");
if (ent->stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
@@ -178,7 +178,7 @@ internal_setspent (ent_t *ent, int stayopen, int needent)
if (ent->stream == NULL)
{
- ent->stream = __nss_files_fopen ("/etc/shadow");
+ ent->stream = __nss_files_fopen_database ("shadow");
if (ent->stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
@@ -39,8 +39,6 @@
#define ENTNAME_r CONCAT(ENTNAME,_r)
-#define DATAFILE "/etc/" DATABASE
-
#ifdef NEED_H_ERRNO
# include <netdb.h>
# define H_ERRNO_PROTO , int *herrnop
@@ -73,7 +71,7 @@ internal_setent (FILE **stream)
if (*stream == NULL)
{
- *stream = __nss_files_fopen (DATAFILE);
+ *stream = __nss_files_fopen_database (DATABASE);
if (*stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
@@ -89,7 +87,7 @@ internal_setent (FILE **stream)
enum nss_status
CONCAT(_nss_files_set,ENTNAME) (int stayopen)
{
- return __nss_files_data_setent (CONCAT (nss_file_, ENTNAME), DATAFILE);
+ return __nss_files_data_setent (CONCAT (nss_file_, ENTNAME), DATABASE);
}
libc_hidden_def (CONCAT (_nss_files_set,ENTNAME))
@@ -170,7 +168,7 @@ CONCAT(_nss_files_get,ENTNAME_r) (struct STRUCTURE *result, char *buffer,
struct nss_files_per_file_data *data;
enum nss_status status = __nss_files_data_open (&data,
CONCAT (nss_file_, ENTNAME),
- DATAFILE,
+ DATABASE,
errnop, H_ERRNO_ARG_OR_NULL);
if (status != NSS_STATUS_SUCCESS)
return status;
@@ -42,7 +42,7 @@ internal_setent (FILE **stream)
if (*stream == NULL)
{
- *stream = __nss_files_fopen ("/etc/aliases");
+ *stream = __nss_files_fopen_database ("aliases");
if (*stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
@@ -58,7 +58,7 @@ internal_setent (FILE **stream)
enum nss_status
_nss_files_setaliasent (void)
{
- return __nss_files_data_setent (nss_file_aliasent, "/etc/aliases");
+ return __nss_files_data_setent (nss_file_aliasent, "aliases");
}
libc_hidden_def (_nss_files_setaliasent)
@@ -338,7 +338,8 @@ _nss_files_getaliasent_r (struct aliasent *result, char *buffer, size_t buflen,
struct nss_files_per_file_data *data;
enum nss_status status = __nss_files_data_open (&data, nss_file_aliasent,
- "/etc/aliases", errnop, NULL);
+ "aliases",
+ errnop, NULL);
if (status != NSS_STATUS_SUCCESS)
return status;
@@ -33,7 +33,7 @@ _nss_files_initgroups_dyn (const char *user, gid_t group, long int *start,
long int *size, gid_t **groupsp, long int limit,
int *errnop)
{
- FILE *stream = __nss_files_fopen ("/etc/group");
+ FILE *stream = __nss_files_fopen_database ("group");
if (stream == NULL)
{
*errnop = errno;
@@ -27,7 +27,7 @@
#include "netgroup.h"
#include <nss_files.h>
-#define DATAFILE "/etc/netgroup"
+#define DATABASE "netgroup"
libc_hidden_proto (_nss_files_endnetgrent)
@@ -62,7 +62,7 @@ _nss_files_setnetgrent (const char *group, struct __netgrent *result)
return NSS_STATUS_UNAVAIL;
/* Find the netgroups file and open it. */
- fp = __nss_files_fopen (DATAFILE);
+ fp = __nss_files_fopen_database (DATABASE);
if (fp == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
else
@@ -74,13 +74,13 @@ __nss_files_data_get (struct nss_files_per_file_data **pdata,
/* Helper function for opening the backing file at PATH. */
static enum nss_status
__nss_files_data_internal_open (struct nss_files_per_file_data *data,
- const char *path)
+ const char *database)
{
enum nss_status status = NSS_STATUS_SUCCESS;
if (data->stream == NULL)
{
- data->stream = __nss_files_fopen (path);
+ data->stream = __nss_files_fopen_database (database);
if (data->stream == NULL)
status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL;
@@ -92,7 +92,7 @@ __nss_files_data_internal_open (struct nss_files_per_file_data *data,
enum nss_status
__nss_files_data_open (struct nss_files_per_file_data **pdata,
- enum nss_files_file file, const char *path,
+ enum nss_files_file file, const char *database,
int *errnop, int *herrnop)
{
enum nss_status status = __nss_files_data_get (pdata, file, errnop, herrnop);
@@ -103,7 +103,7 @@ __nss_files_data_open (struct nss_files_per_file_data **pdata,
if ((*pdata)->stream == NULL)
{
int saved_errno = errno;
- status = __nss_files_data_internal_open (*pdata, path);
+ status = __nss_files_data_internal_open (*pdata, database);
__set_errno (saved_errno);
if (status != NSS_STATUS_SUCCESS)
__nss_files_data_put (*pdata);
@@ -122,7 +122,7 @@ __nss_files_data_put (struct nss_files_per_file_data *data)
libc_hidden_def (__nss_files_data_put)
enum nss_status
-__nss_files_data_setent (enum nss_files_file file, const char *path)
+__nss_files_data_setent (enum nss_files_file file, const char *database)
{
struct nss_files_per_file_data *data;
enum nss_status status = __nss_files_data_get (&data, file, NULL, NULL);
@@ -130,7 +130,7 @@ __nss_files_data_setent (enum nss_files_file file, const char *path)
return status;
if (data->stream == NULL)
- status = __nss_files_data_internal_open (data, path);
+ status = __nss_files_data_internal_open (data, database);
else
rewind (data->stream);
@@ -21,6 +21,9 @@
#include <errno.h>
#include <stdio_ext.h>
+#define PRIMARY_PREFIX "/etc/"
+#define FALLBACK_PREFIX "/usr/share/nss/"
+
FILE *
__nss_files_fopen (const char *path)
{
@@ -45,3 +48,40 @@ __nss_files_fopen (const char *path)
return fp;
}
libc_hidden_def (__nss_files_fopen)
+
+FILE *
+__nss_files_fopen_database (const char *database)
+{
+ char buf[sizeof(FALLBACK_PREFIX) + NAME_MAX];
+
+ /* Protect against string overflow */
+ size_t n = strlen (database);
+ if (n > NAME_MAX)
+ {
+ __set_errno (EINVAL);
+ return NULL;
+ }
+
+ strcpy (stpcpy (buf, PRIMARY_PREFIX), database);
+ FILE *fp = __nss_files_fopen (buf);
+ if (fp != NULL)
+ return fp;
+ switch (errno)
+ {
+ case ENOENT:
+ case EISDIR:
+ case ENOTDIR:
+ case ELOOP:
+ /* If the path does not exist or is incorrectly set up, let's try to use the fallback database */
+ break;
+
+ default:
+ /* Propagate all other errors (in particular EACCESS) to the caller, since we shouldn't accidentally use
+ * the wrong database just because some MAC (or so) prohibited access to the primary database. */
+ return NULL;
+ }
+
+ strcpy (stpcpy (buf, FALLBACK_PREFIX), database);
+ return __nss_files_fopen (buf);
+}
+libc_hidden_def (__nss_files_fopen_database)