2003-06-17  Thorsten Kukuk  <kukuk@suse.de>

	* nis/Makefile: Remove NIS/NIS+ files from nss_compat module.
	* nis/nss_compat/compat-grp.c: Don't use our own NIS/NIS+ functions,
	dlopen corresponding NSS module instead.
	* nis/nss_compat/compat-pwd.c: Likewise.
	* nis/nss_compat/compat-spwd.c: Likewise.
	* nis/nss_compat/compat-initgroups.c: Disabled for now.
	* nss/Versions: Export __nss_lookup_function.

2003-06-19  Daniel Jacobowitz  <drow@mvista.com>

	* sysdeps/unix/sysv/linux/kernel-features.h: Update kernel features
	for the SH architecture.

2003-06-25  Thorsten Kukuk  <kukuk@suse.de>

	* csu/Makefile: Use CPPFLAGS to find correct linux/version.h.
This commit is contained in:
Ulrich Drepper 2003-06-26 08:00:21 +00:00
parent 0af6a1d959
commit 1e2e27fd8b
12 changed files with 602 additions and 1773 deletions

View File

@ -1,3 +1,22 @@
2003-06-17 Thorsten Kukuk <kukuk@suse.de>
* nis/Makefile: Remove NIS/NIS+ files from nss_compat module.
* nis/nss_compat/compat-grp.c: Don't use our own NIS/NIS+ functions,
dlopen corresponding NSS module instead.
* nis/nss_compat/compat-pwd.c: Likewise.
* nis/nss_compat/compat-spwd.c: Likewise.
* nis/nss_compat/compat-initgroups.c: Disabled for now.
* nss/Versions: Export __nss_lookup_function.
2003-06-19 Daniel Jacobowitz <drow@mvista.com>
* sysdeps/unix/sysv/linux/kernel-features.h: Update kernel features
for the SH architecture.
2003-06-25 Thorsten Kukuk <kukuk@suse.de>
* csu/Makefile: Use CPPFLAGS to find correct linux/version.h.
2003-06-25 Andreas Jaeger <aj@suse.de> 2003-06-25 Andreas Jaeger <aj@suse.de>
* stdlib/tst-strtod.c (main): Declare constant long double as * stdlib/tst-strtod.c (main): Declare constant long double as

View File

@ -217,7 +217,7 @@ $(objpfx)version-info.h: $(common-objpfx)config.make $(all-Banner-files)
$(make-target-directory) $(make-target-directory)
(case $(config-os) in \ (case $(config-os) in \
linux*) version=`(echo -e "#include <linux/version.h>\nUTS_RELEASE"\ linux*) version=`(echo -e "#include <linux/version.h>\nUTS_RELEASE"\
| $(CC) -E -P - | \ | $(CC) $(CPPFLAGS) -E -P - | \
sed -e 's/"\([^"]*\)".*/\1/p' -e d) 2>/dev/null`;\ sed -e 's/"\([^"]*\)".*/\1/p' -e d) 2>/dev/null`;\
if [ -z "$$version" ]; then \ if [ -z "$$version" ]; then \
if [ -r /proc/version ]; then \ if [ -r /proc/version ]; then \

View File

@ -1,3 +1,10 @@
2003-06-25 Petter Reinholdtsen <pere@hungry.com>
* locales/an_ES: Change default charset from ISO-8859-1 to
ISO-8859-15 as the locale need the EURO sign.
* SUPPORTED (SUPPORTED-LOCALES): Add an_ES.ISO-8859-15.
2003-06-21 Petter Reinholdtsen <pere@hungry.com> 2003-06-21 Petter Reinholdtsen <pere@hungry.com>
* locales/no_NO [LC_COLLATE]: Add missing eth letter, sorted as * locales/no_NO [LC_COLLATE]: Add missing eth letter, sorted as

View File

@ -3,6 +3,7 @@
# appropriate message. # appropriate message.
SUPPORTED-LOCALES=\ SUPPORTED-LOCALES=\
af_ZA/ISO-8859-1 \ af_ZA/ISO-8859-1 \
an_ES/ISO-8859-15 \
ar_AE/ISO-8859-6 \ ar_AE/ISO-8859-6 \
ar_BH/ISO-8859-6 \ ar_BH/ISO-8859-6 \
ar_DZ/ISO-8859-6 \ ar_DZ/ISO-8859-6 \

View File

@ -12,7 +12,7 @@ escape_char /
% Date: 2003-05-22 % Date: 2003-05-22
% Application: general % Application: general
% Users: general % Users: general
% Charset: ISO-8859-1 % Charset: ISO-8859-15
% %
% This file is under the % This file is under the
% GNU General Public License. % GNU General Public License.

View File

@ -54,8 +54,7 @@ libnsl-routines = yp_xdr ypclnt ypupdate_xdr \
nis_findserv nis_callback nis_clone_dir nis_clone_obj\ nis_findserv nis_callback nis_clone_dir nis_clone_obj\
nis_clone_res nis_clone_res
libnss_compat-routines := $(addprefix compat-,grp pwd spwd initgroups) \ libnss_compat-routines := $(addprefix compat-,grp pwd spwd initgroups)
nisplus-parser nss-nis nss-nisplus
libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes)) libnss_compat-inhibit-o = $(filter-out .os,$(object-suffixes))
libnss_nis-routines := $(addprefix nis-,$(databases)) nis-initgroups \ libnss_nis-routines := $(addprefix nis-,$(databases)) nis-initgroups \

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1996,1997,1998,1999,2001,2002 Free Software Foundation, Inc. /* Copyright (C) 1996,1997,1998,1999,2001,2002, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
@ -24,18 +24,20 @@
#include <ctype.h> #include <ctype.h>
#include <bits/libc-lock.h> #include <bits/libc-lock.h>
#include <string.h> #include <string.h>
#include <rpcsvc/yp.h> #include <rpc/types.h>
#include <rpcsvc/ypclnt.h>
#include <rpcsvc/nis.h>
#include <nsswitch.h> #include <nsswitch.h>
#include "nss-nisplus.h"
#include "nisplus-parser.h"
static service_user *ni; static service_user *ni;
static bool_t use_nisplus; /* default: group_compat: nis */ static enum nss_status (*nss_setgrent) (int stayopen);
static nis_name grptable; /* Name of the group table */ static enum nss_status (*nss_getgrnam_r) (const char *name,
static size_t grptablelen; struct group * grp, char *buffer,
size_t buflen, int *errnop);
static enum nss_status (*nss_getgrgid_r) (gid_t gid, struct group * grp,
char *buffer, size_t buflen,
int *errnop);
static enum nss_status (*nss_getgrent_r) (struct group * grp, char *buffer,
size_t buflen, int *errnop);
static enum nss_status (*nss_endgrent) (void);
/* Get the declaration of the parser function. */ /* Get the declaration of the parser function. */
#define ENTNAME grent #define ENTNAME grent
@ -47,25 +49,22 @@ static size_t grptablelen;
#define BLACKLIST_INITIAL_SIZE 512 #define BLACKLIST_INITIAL_SIZE 512
#define BLACKLIST_INCREMENT 256 #define BLACKLIST_INCREMENT 256
struct blacklist_t struct blacklist_t
{ {
char *data; char *data;
int current; int current;
int size; int size;
}; };
struct ent_t struct ent_t
{ {
bool_t nis;
bool_t nis_first; bool_t nis_first;
char *oldkey; bool_t files;
int oldkeylen;
nis_result *result;
FILE *stream; FILE *stream;
struct blacklist_t blacklist; struct blacklist_t blacklist;
}; };
typedef struct ent_t ent_t; typedef struct ent_t ent_t;
static ent_t ext_ent = {0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0}}; static ent_t ext_ent = {0, TRUE, NULL, {NULL, 0, 0}};
/* Protect global state against multiple changers. */ /* Protect global state against multiple changers. */
__libc_lock_define_initialized (static, lock) __libc_lock_define_initialized (static, lock)
@ -74,56 +73,27 @@ __libc_lock_define_initialized (static, lock)
static void blacklist_store_name (const char *, ent_t *); static void blacklist_store_name (const char *, ent_t *);
static int in_blacklist (const char *, int, ent_t *); static int in_blacklist (const char *, int, ent_t *);
static enum nss_status /* Initialize the NSS interface/functions. The calling function must
_nss_first_init (void) hold the lock. */
static void
init_nss_interface (void)
{ {
if (ni == NULL) if (__nss_database_lookup ("group_compat", NULL, "nis", &ni) >= 0)
{ {
__nss_database_lookup ("group_compat", NULL, "nis", &ni); nss_setgrent = __nss_lookup_function (ni, "setgrent");
use_nisplus = (strcmp (ni->name, "nisplus") == 0); nss_getgrnam_r = __nss_lookup_function (ni, "getgrnam_r");
nss_getgrgid_r = __nss_lookup_function (ni, "getgrgid_r");
nss_getgrent_r = __nss_lookup_function (ni, "getgrent_r");
nss_endgrent = __nss_lookup_function (ni, "endgrent");
} }
if (grptable == NULL)
{
static const char key[] = "group.org_dir.";
const char *local_dir = nis_local_directory ();
size_t len_local_dir = strlen (local_dir);
grptable = malloc (sizeof (key) + len_local_dir);
if (grptable == NULL)
return NSS_STATUS_TRYAGAIN;
grptablelen = ((char *) mempcpy (mempcpy (grptable,
key, sizeof (key) - 1),
local_dir, len_local_dir + 1)
- grptable) - 1;
}
return NSS_STATUS_SUCCESS;
} }
static enum nss_status static enum nss_status
internal_setgrent (ent_t *ent) internal_setgrent (ent_t *ent, int stayopen)
{ {
enum nss_status status = NSS_STATUS_SUCCESS; enum nss_status status = NSS_STATUS_SUCCESS;
ent->nis = ent->nis_first = 0; ent->files = TRUE;
if (_nss_first_init () != NSS_STATUS_SUCCESS)
return NSS_STATUS_UNAVAIL;
if (ent->oldkey != NULL)
{
free (ent->oldkey);
ent->oldkey = NULL;
ent->oldkeylen = 0;
}
if (ent->result != NULL)
{
nis_freeresult (ent->result);
ent->result = NULL;
}
if (ent->blacklist.data != NULL) if (ent->blacklist.data != NULL)
{ {
@ -164,6 +134,9 @@ internal_setgrent (ent_t *ent)
else else
rewind (ent->stream); rewind (ent->stream);
if (status == NSS_STATUS_SUCCESS && nss_setgrent)
return nss_setgrent (stayopen);
return status; return status;
} }
@ -175,7 +148,10 @@ _nss_compat_setgrent (int stayopen)
__libc_lock_lock (lock); __libc_lock_lock (lock);
result = internal_setgrent (&ext_ent); if (ni == NULL)
init_nss_interface ();
result = internal_setgrent (&ext_ent, stayopen);
__libc_lock_unlock (lock); __libc_lock_unlock (lock);
@ -186,27 +162,15 @@ _nss_compat_setgrent (int stayopen)
static enum nss_status static enum nss_status
internal_endgrent (ent_t *ent) internal_endgrent (ent_t *ent)
{ {
if (nss_endgrent)
nss_endgrent ();
if (ent->stream != NULL) if (ent->stream != NULL)
{ {
fclose (ent->stream); fclose (ent->stream);
ent->stream = NULL; ent->stream = NULL;
} }
ent->nis = ent->nis_first = 0;
if (ent->oldkey != NULL)
{
free (ent->oldkey);
ent->oldkey = NULL;
ent->oldkeylen = 0;
}
if (ent->result != NULL)
{
nis_freeresult (ent->result);
ent->result = NULL;
}
if (ent->blacklist.data != NULL) if (ent->blacklist.data != NULL)
{ {
ent->blacklist.current = 1; ent->blacklist.current = 1;
@ -233,239 +197,44 @@ _nss_compat_endgrent (void)
return result; return result;
} }
/* get the next group from NSS (+ entry) */
static enum nss_status static enum nss_status
getgrent_next_nis (struct group *result, ent_t *ent, char *buffer, getgrent_next_nss (struct group *result, ent_t *ent, char *buffer,
size_t buflen, int *errnop) size_t buflen, int *errnop)
{ {
struct parser_data *data = (void *) buffer; if (!nss_getgrent_r)
char *domain;
char *outkey, *outval;
int outkeylen, outvallen, parse_res;
char *p;
if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
{
ent->nis = 0;
return NSS_STATUS_NOTFOUND;
}
do
{
char *save_oldkey;
int save_oldlen;
bool_t save_nis_first;
if (ent->nis_first)
{
if (yp_first (domain, "group.byname", &outkey, &outkeylen,
&outval, &outvallen) != YPERR_SUCCESS)
{
ent->nis = 0;
return NSS_STATUS_UNAVAIL; return NSS_STATUS_UNAVAIL;
}
if ( buflen < ((size_t) outvallen + 1))
{
free (outval);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
save_oldkey = ent->oldkey;
save_oldlen = ent->oldkeylen;
save_nis_first = TRUE;
ent->oldkey = outkey;
ent->oldkeylen = outkeylen;
ent->nis_first = FALSE;
}
else
{
if (yp_next (domain, "group.byname", ent->oldkey, ent->oldkeylen,
&outkey, &outkeylen, &outval, &outvallen)
!= YPERR_SUCCESS)
{
ent->nis = 0;
return NSS_STATUS_NOTFOUND;
}
if ( buflen < ((size_t) outvallen + 1))
{
free (outval);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
save_oldkey = ent->oldkey;
save_oldlen = ent->oldkeylen;
save_nis_first = FALSE;
ent->oldkey = outkey;
ent->oldkeylen = outkeylen;
}
/* Copy the found data to our buffer... */
p = strncpy (buffer, outval, buflen);
/* ...and free the data. */
free (outval);
while (isspace (*p))
++p;
parse_res = _nss_files_parse_grent (p, result, data, buflen, errnop);
if (parse_res == -1)
{
free (ent->oldkey);
ent->oldkey = save_oldkey;
ent->oldkeylen = save_oldlen;
ent->nis_first = save_nis_first;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
else
{
if (!save_nis_first)
free (save_oldkey);
}
if (parse_res &&
in_blacklist (result->gr_name, strlen (result->gr_name), ent))
parse_res = 0; /* if result->gr_name in blacklist,search next entry */
}
while (!parse_res);
return NSS_STATUS_SUCCESS;
}
static enum nss_status
getgrent_next_nisplus (struct group *result, ent_t *ent, char *buffer,
size_t buflen, int *errnop)
{
int parse_res;
do do
{ {
nis_result *save_oldres; enum nss_status status;
bool_t save_nis_first;
if (ent->nis_first) if ((status = nss_getgrent_r (result, buffer, buflen, errnop)) !=
{ NSS_STATUS_SUCCESS)
save_oldres = ent->result; return status;
save_nis_first = TRUE;
ent->result = nis_first_entry(grptable);
if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
{
ent->nis = 0;
return niserr2nss (ent->result->status);
} }
ent->nis_first = FALSE; while (in_blacklist (result->gr_name, strlen (result->gr_name), ent));
}
else
{
nis_result *res;
save_oldres = ent->result;
save_nis_first = FALSE;
res = nis_next_entry(grptable, &ent->result->cookie);
ent->result = res;
if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
{
ent->nis = 0;
return niserr2nss (ent->result->status);
}
}
parse_res = _nss_nisplus_parse_grent (ent->result, 0, result,
buffer, buflen, errnop);
if (parse_res == -1)
{
nis_freeresult (ent->result);
ent->result = save_oldres;
ent->nis_first = save_nis_first;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
else
{
if (!save_nis_first)
nis_freeresult (save_oldres);
}
if (parse_res &&
in_blacklist (result->gr_name, strlen (result->gr_name), ent))
parse_res = 0; /* if result->gr_name in blacklist,search next entry */
}
while (!parse_res);
return NSS_STATUS_SUCCESS; return NSS_STATUS_SUCCESS;
} }
/* This function handle the +group entrys in /etc/group */ /* This function handle the +group entrys in /etc/group */
static enum nss_status static enum nss_status
getgrnam_plusgroup (const char *name, struct group *result, char *buffer, getgrnam_plusgroup (const char *name, struct group *result, ent_t *ent,
size_t buflen, int *errnop) char *buffer, size_t buflen, int *errnop)
{ {
struct parser_data *data = (void *) buffer; if (!nss_getgrnam_r)
int parse_res; return NSS_STATUS_UNAVAIL;
if (use_nisplus) /* Do the NIS+ query here */ if (nss_getgrnam_r (name, result, buffer, buflen, errnop) !=
{ NSS_STATUS_SUCCESS)
nis_result *res;
char buf[strlen (name) + 24 + grptablelen];
sprintf(buf, "[name=%s],%s", name, grptable);
res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
{
enum nss_status status = niserr2nss (res->status);
nis_freeresult (res);
return status;
}
parse_res = _nss_nisplus_parse_grent (res, 0, result, buffer, buflen,
errnop);
if (parse_res == -1)
{
nis_freeresult (res);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
nis_freeresult (res);
}
else /* Use NIS */
{
char *domain, *outval, *p;
int outvallen;
if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
if (yp_match (domain, "group.byname", name, strlen (name), if (in_blacklist (result->gr_name, strlen (result->gr_name), ent))
&outval, &outvallen) != YPERR_SUCCESS)
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
if (buflen < ((size_t) outvallen + 1))
{
free (outval);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
/* Copy the found data to our buffer... */
p = strncpy (buffer, outval, buflen);
/* ... and free the data. */
free (outval);
while (isspace (*p))
++p;
parse_res = _nss_files_parse_grent (p, result, data, buflen, errnop);
if (parse_res == -1)
return NSS_STATUS_TRYAGAIN;
}
if (parse_res)
/* We found the entry. */ /* We found the entry. */
return NSS_STATUS_SUCCESS; return NSS_STATUS_SUCCESS;
else
return NSS_STATUS_RETURN;
} }
static enum nss_status static enum nss_status
@ -536,12 +305,11 @@ getgrent_next_file (struct group *result, ent_t *ent,
/* Store the group in the blacklist for the "+" at the end of /* Store the group in the blacklist for the "+" at the end of
/etc/group */ /etc/group */
blacklist_store_name (&result->gr_name[1], ent); blacklist_store_name (&result->gr_name[1], ent);
status = getgrnam_plusgroup (&result->gr_name[1], result, buffer, status = getgrnam_plusgroup (&result->gr_name[1], result, ent,
buflen, errnop); buffer, buflen, errnop);
if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
break; break;
else else if (status == NSS_STATUS_RETURN /* We couldn't parse the entry */
if (status == NSS_STATUS_RETURN /* We couldn't parse the entry */
|| status == NSS_STATUS_NOTFOUND) /* No group in NIS */ || status == NSS_STATUS_NOTFOUND) /* No group in NIS */
continue; continue;
else else
@ -559,13 +327,9 @@ getgrent_next_file (struct group *result, ent_t *ent,
/* +:... */ /* +:... */
if (result->gr_name[0] == '+' && result->gr_name[1] == '\0') if (result->gr_name[0] == '+' && result->gr_name[1] == '\0')
{ {
ent->nis = TRUE; ent->files = FALSE;
ent->nis_first = TRUE;
if (use_nisplus) return getgrent_next_nss (result, ent, buffer, buflen, errnop);
return getgrent_next_nisplus (result, ent, buffer, buflen, errnop);
else
return getgrent_next_nis (result, ent, buffer, buflen, errnop);
} }
} }
@ -573,39 +337,31 @@ getgrent_next_file (struct group *result, ent_t *ent,
} }
static enum nss_status
internal_getgrent_r (struct group *gr, ent_t *ent, char *buffer,
size_t buflen, int *errnop)
{
if (ent->nis)
{
if (use_nisplus)
return getgrent_next_nisplus (gr, ent, buffer, buflen, errnop);
else
return getgrent_next_nis (gr, ent, buffer, buflen, errnop);
}
else
return getgrent_next_file (gr, ent, buffer, buflen, errnop);
}
enum nss_status enum nss_status
_nss_compat_getgrent_r (struct group *grp, char *buffer, size_t buflen, _nss_compat_getgrent_r (struct group *grp, char *buffer, size_t buflen,
int *errnop) int *errnop)
{ {
enum nss_status status = NSS_STATUS_SUCCESS; enum nss_status result = NSS_STATUS_SUCCESS;
__libc_lock_lock (lock); __libc_lock_lock (lock);
/* Be prepared that the setgrent function was not called before. */ /* Be prepared that the setgrent function was not called before. */
if (ni == NULL)
init_nss_interface ();
if (ext_ent.stream == NULL) if (ext_ent.stream == NULL)
status = internal_setgrent (&ext_ent); result = internal_setgrent (&ext_ent, 1);
if (status == NSS_STATUS_SUCCESS)
status = internal_getgrent_r (grp, &ext_ent, buffer, buflen, errnop);
if (result == NSS_STATUS_SUCCESS)
{
if (ext_ent.files)
result = getgrent_next_file (grp, &ext_ent, buffer, buflen, errnop);
else
result = getgrent_next_nss (grp, &ext_ent, buffer, buflen, errnop);
}
__libc_lock_unlock (lock); __libc_lock_unlock (lock);
return status; return result;
} }
/* Searches in /etc/group and the NIS/NIS+ map for a special group */ /* Searches in /etc/group and the NIS/NIS+ map for a special group */
@ -681,8 +437,8 @@ internal_getgrnam_r (const char *name, struct group *result, ent_t *ent,
{ {
enum nss_status status; enum nss_status status;
status = getgrnam_plusgroup (name, result, buffer, buflen, status = getgrnam_plusgroup (name, result, ent,
errnop); buffer, buflen, errnop);
if (status == NSS_STATUS_RETURN) if (status == NSS_STATUS_RETURN)
/* We couldn't parse the entry */ /* We couldn't parse the entry */
continue; continue;
@ -695,7 +451,8 @@ internal_getgrnam_r (const char *name, struct group *result, ent_t *ent,
{ {
enum nss_status status; enum nss_status status;
status = getgrnam_plusgroup (name, result, buffer, buflen, errnop); status = getgrnam_plusgroup (name, result, ent,
buffer, buflen, errnop);
if (status == NSS_STATUS_RETURN) if (status == NSS_STATUS_RETURN)
/* We couldn't parse the entry */ /* We couldn't parse the entry */
continue; continue;
@ -711,99 +468,27 @@ enum nss_status
_nss_compat_getgrnam_r (const char *name, struct group *grp, _nss_compat_getgrnam_r (const char *name, struct group *grp,
char *buffer, size_t buflen, int *errnop) char *buffer, size_t buflen, int *errnop)
{ {
ent_t ent = {0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0}}; ent_t ent = {0, TRUE, NULL, {NULL, 0, 0}};
enum nss_status status; enum nss_status result;
if (name[0] == '-' || name[0] == '+') if (name[0] == '-' || name[0] == '+')
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
__libc_lock_lock (lock); __libc_lock_lock (lock);
status = internal_setgrent (&ent); if (ni == NULL)
init_nss_interface ();
__libc_lock_unlock (lock); __libc_lock_unlock (lock);
if (status != NSS_STATUS_SUCCESS) result = internal_setgrent (&ent, 0);
return status;
status = internal_getgrnam_r (name, grp, &ent, buffer, buflen, errnop); if (result == NSS_STATUS_SUCCESS)
result = internal_getgrnam_r (name, grp, &ent, buffer, buflen, errnop);
internal_endgrent (&ent); internal_endgrent (&ent);
return status; return result;
}
/* This function handle the + entry in /etc/group */
static enum nss_status
getgrgid_plusgroup (gid_t gid, struct group *result, char *buffer,
size_t buflen, int *errnop)
{
struct parser_data *data = (void *) buffer;
int parse_res;
if (use_nisplus) /* Do the NIS+ query here */
{
nis_result *res;
char buf[24 + grptablelen];
sprintf(buf, "[gid=%lu],%s", (unsigned long int) gid, grptable);
res = nis_list(buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
{
enum nss_status status = niserr2nss (res->status);
nis_freeresult (res);
return status;
}
if ((parse_res = _nss_nisplus_parse_grent (res, 0, result, buffer,
buflen, errnop)) == -1)
{
nis_freeresult (res);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
nis_freeresult (res);
}
else /* Use NIS */
{
char buf[24];
char *domain, *outval, *p;
int outvallen;
if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
return NSS_STATUS_NOTFOUND;
snprintf (buf, sizeof (buf), "%lu", (unsigned long int) gid);
if (yp_match (domain, "group.bygid", buf, strlen (buf),
&outval, &outvallen) != YPERR_SUCCESS)
return NSS_STATUS_NOTFOUND;
if (buflen < ((size_t) outvallen + 1))
{
free (outval);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
/* Copy the found data to our buffer... */
p = strncpy (buffer, outval, buflen);
/* ... and free the data. */
free (outval);
while (isspace (*p))
p++;
parse_res = _nss_files_parse_grent (p, result, data, buflen, errnop);
if (parse_res == -1)
return NSS_STATUS_TRYAGAIN;
}
if (parse_res)
/* We found the entry. */
return NSS_STATUS_SUCCESS;
else
return NSS_STATUS_RETURN;
} }
/* Searches in /etc/group and the NIS/NIS+ map for a special group id */ /* Searches in /etc/group and the NIS/NIS+ map for a special group id */
@ -878,8 +563,8 @@ internal_getgrgid_r (gid_t gid, struct group *result, ent_t *ent,
/* Store the group in the blacklist for the "+" at the end of /* Store the group in the blacklist for the "+" at the end of
/etc/group */ /etc/group */
blacklist_store_name (&result->gr_name[1], ent); blacklist_store_name (&result->gr_name[1], ent);
status = getgrnam_plusgroup (&result->gr_name[1], result, buffer, status = getgrnam_plusgroup (&result->gr_name[1], result, ent,
buflen, errnop); buffer, buflen, errnop);
if (status == NSS_STATUS_SUCCESS && result->gr_gid == gid) if (status == NSS_STATUS_SUCCESS && result->gr_gid == gid)
break; break;
else else
@ -890,7 +575,7 @@ internal_getgrgid_r (gid_t gid, struct group *result, ent_t *ent,
{ {
enum nss_status status; enum nss_status status;
status = getgrgid_plusgroup (gid, result, buffer, buflen, errnop); status = nss_getgrgid_r (gid, result, buffer, buflen, errnop);
if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
else else
@ -905,23 +590,24 @@ enum nss_status
_nss_compat_getgrgid_r (gid_t gid, struct group *grp, _nss_compat_getgrgid_r (gid_t gid, struct group *grp,
char *buffer, size_t buflen, int *errnop) char *buffer, size_t buflen, int *errnop)
{ {
ent_t ent = {0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0}}; ent_t ent = {0, TRUE, NULL, {NULL, 0, 0}};
enum nss_status status; enum nss_status result;
__libc_lock_lock (lock); __libc_lock_lock (lock);
status = internal_setgrent (&ent); if (ni == NULL)
init_nss_interface ();
__libc_lock_unlock (lock); __libc_lock_unlock (lock);
if (status != NSS_STATUS_SUCCESS) result = internal_setgrent (&ent, 0);
return status;
status = internal_getgrgid_r (gid, grp, &ent, buffer, buflen, errnop); if (result == NSS_STATUS_SUCCESS)
result = internal_getgrgid_r (gid, grp, &ent, buffer, buflen, errnop);
internal_endgrent (&ent); internal_endgrent (&ent);
return status; return result;
} }
@ -983,7 +669,7 @@ in_blacklist (const char *name, int namelen, ent_t *ent)
buf[0] = '|'; buf[0] = '|';
cp = stpcpy (&buf[1], name); cp = stpcpy (&buf[1], name);
*cp++= '|'; *cp++ = '|';
*cp = '\0'; *cp = '\0';
return strstr (ent->blacklist.data, buf) != NULL; return strstr (ent->blacklist.data, buf) != NULL;
} }

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998. Contributed by Thorsten Kukuk <kukuk@suse.de>, 1998.
@ -17,6 +17,8 @@
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */ 02111-1307 USA. */
#if 0 /* XXX this one needs to be rewritten. */
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <nss.h> #include <nss.h>
@ -718,3 +720,5 @@ in_blacklist (const char *name, int namelen, ent_t *ent)
*cp = '\0'; *cp = '\0';
return strstr (ent->blacklist.data, buf) != NULL; return strstr (ent->blacklist.data, buf) != NULL;
} }
#endif

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
/* Copyright (C) 1996,1997,1998,1999,2001,2002 Free Software Foundation, Inc. /* Copyright (C) 1996,1997,1998,1999,2001,2002,2003 Free Software Foundation, Inc.
This file is part of the GNU C Library. This file is part of the GNU C Library.
Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
@ -25,19 +25,20 @@
#include <shadow.h> #include <shadow.h>
#include <string.h> #include <string.h>
#include <bits/libc-lock.h> #include <bits/libc-lock.h>
#include <rpcsvc/yp.h> #include <rpc/types.h>
#include <rpcsvc/ypclnt.h> #include <rpcsvc/ypclnt.h>
#include <rpcsvc/nis.h>
#include <nsswitch.h> #include <nsswitch.h>
#include "netgroup.h" #include "netgroup.h"
#include "nss-nisplus.h"
#include "nisplus-parser.h"
static service_user *ni; static service_user *ni;
static bool_t use_nisplus; /* default: passwd_compat: nis */ static enum nss_status (*nss_setspent) (int stayopen);
static nis_name pwdtable; /* Name of the password table */ static enum nss_status (*nss_getspnam_r) (const char *name, struct spwd * sp,
static size_t pwdtablelen; char *buffer, size_t buflen,
int *errnop);
static enum nss_status (*nss_getspent_r) (struct spwd * sp, char *buffer,
size_t buflen, int *errnop);
static enum nss_status (*nss_endspent) (void);
/* Get the declaration of the parser function. */ /* Get the declaration of the parser function. */
#define ENTNAME spent #define ENTNAME spent
@ -49,28 +50,25 @@ static size_t pwdtablelen;
#define BLACKLIST_INITIAL_SIZE 512 #define BLACKLIST_INITIAL_SIZE 512
#define BLACKLIST_INCREMENT 256 #define BLACKLIST_INCREMENT 256
struct blacklist_t struct blacklist_t
{ {
char *data; char *data;
int current; int current;
int size; int size;
}; };
struct ent_t struct ent_t
{ {
bool_t netgroup; bool_t netgroup;
bool_t nis; bool_t files;
bool_t first; bool_t first;
char *oldkey;
int oldkeylen;
nis_result *result;
FILE *stream; FILE *stream;
struct blacklist_t blacklist; struct blacklist_t blacklist;
struct spwd pwd; struct spwd pwd;
struct __netgrent netgrdata; struct __netgrent netgrdata;
}; };
typedef struct ent_t ent_t; typedef struct ent_t ent_t;
static ent_t ext_ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0}, static ent_t ext_ent = {0, TRUE, 0, NULL, {NULL, 0, 0},
{NULL, NULL, 0, 0, 0, 0, 0, 0, 0}}; {NULL, NULL, 0, 0, 0, 0, 0, 0, 0}};
/* Protect global state against multiple changers. */ /* Protect global state against multiple changers. */
@ -80,6 +78,21 @@ __libc_lock_define_initialized (static, lock)
static void blacklist_store_name (const char *, ent_t *); static void blacklist_store_name (const char *, ent_t *);
static int in_blacklist (const char *, int, ent_t *); static int in_blacklist (const char *, int, ent_t *);
/* Initialize the NSS interface/functions. The calling function must
hold the lock. */
static void
init_nss_interface (void)
{
if (__nss_database_lookup ("shadow_compat", "passwd_compat",
"nis", &ni) >= 0)
{
nss_setspent = __nss_lookup_function (ni, "setspent");
nss_getspnam_r = __nss_lookup_function (ni, "getspnam_r");
nss_getspent_r = __nss_lookup_function (ni, "getspent_r");
nss_endspent = __nss_lookup_function (ni, "endspent");
}
}
static void static void
give_spwd_free (struct spwd *pwd) give_spwd_free (struct spwd *pwd)
{ {
@ -142,45 +155,17 @@ copy_spwd_changes (struct spwd *dest, struct spwd *src,
} }
static enum nss_status static enum nss_status
internal_setspent (ent_t *ent) internal_setspent (ent_t *ent, int stayopen)
{ {
enum nss_status status = NSS_STATUS_SUCCESS; enum nss_status status = NSS_STATUS_SUCCESS;
ent->nis = ent->first = ent->netgroup = 0; ent->first = ent->netgroup = 0;
ent->files = TRUE;
/* If something was left over free it. */ /* If something was left over free it. */
if (ent->netgroup) if (ent->netgroup)
__internal_endnetgrent (&ent->netgrdata); __internal_endnetgrent (&ent->netgrdata);
if (ent->oldkey != NULL)
{
free (ent->oldkey);
ent->oldkey = NULL;
ent->oldkeylen = 0;
}
if (ent->result != NULL)
{
nis_freeresult (ent->result);
ent->result = NULL;
}
if (pwdtable == NULL)
{
static const char key[] = "passwd.org_dir.";
const char *local_dir = nis_local_directory ();
size_t len_local_dir = strlen (local_dir);
pwdtable = malloc (sizeof (key) + len_local_dir);
if (pwdtable == NULL)
return NSS_STATUS_TRYAGAIN;
pwdtablelen = ((char *) mempcpy (mempcpy (pwdtable,
key, sizeof (key) - 1),
local_dir, len_local_dir + 1)
- pwdtable) - 1;
}
if (ent->blacklist.data != NULL) if (ent->blacklist.data != NULL)
{ {
ent->blacklist.current = 1; ent->blacklist.current = 1;
@ -222,6 +207,9 @@ internal_setspent (ent_t *ent)
give_spwd_free (&ent->pwd); give_spwd_free (&ent->pwd);
if (status == NSS_STATUS_SUCCESS && nss_setspent)
return nss_setspent (stayopen);
return status; return status;
} }
@ -234,12 +222,9 @@ _nss_compat_setspent (int stayopen)
__libc_lock_lock (lock); __libc_lock_lock (lock);
if (ni == NULL) if (ni == NULL)
{ init_nss_interface ();
__nss_database_lookup ("shadow_compat", "passwd_compat", "nis", &ni);
use_nisplus = (strcmp (ni->name, "nisplus") == 0);
}
result = internal_setspent (&ext_ent); result = internal_setspent (&ext_ent, stayopen);
__libc_lock_unlock (lock); __libc_lock_unlock (lock);
@ -250,6 +235,9 @@ _nss_compat_setspent (int stayopen)
static enum nss_status static enum nss_status
internal_endspent (ent_t *ent) internal_endspent (ent_t *ent)
{ {
if (nss_endspent)
nss_endspent ();
if (ent->stream != NULL) if (ent->stream != NULL)
{ {
fclose (ent->stream); fclose (ent->stream);
@ -259,20 +247,8 @@ internal_endspent (ent_t *ent)
if (ent->netgroup) if (ent->netgroup)
__internal_endnetgrent (&ent->netgrdata); __internal_endnetgrent (&ent->netgrdata);
ent->nis = ent->first = ent->netgroup = 0; ent->first = ent->netgroup = FALSE;
ent->files = TRUE;
if (ent->oldkey != NULL)
{
free (ent->oldkey);
ent->oldkey = NULL;
ent->oldkeylen = 0;
}
if (ent->result != NULL)
{
nis_freeresult (ent->result);
ent->result = NULL;
}
if (ent->blacklist.data != NULL) if (ent->blacklist.data != NULL)
{ {
@ -304,25 +280,27 @@ _nss_compat_endspent (void)
static enum nss_status static enum nss_status
getspent_next_nis_netgr (const char *name, struct spwd *result, ent_t *ent, getspent_next_nss_netgr (const char *name, struct spwd *result, ent_t *ent,
char *group, char *buffer, size_t buflen, int *errnop) char *group, char *buffer, size_t buflen,
int *errnop)
{ {
struct parser_data *data = (void *) buffer; char *curdomain, *host, *user, *domain, *p2;
char *ypdomain, *host, *user, *domain, *outval, *p, *p2;
int status, outvallen;
size_t p2len; size_t p2len;
if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS) if (!nss_getspnam_r)
return NSS_STATUS_UNAVAIL;
if (yp_get_default_domain (&curdomain) != YPERR_SUCCESS)
{ {
ent->netgroup = 0; ent->netgroup = FALSE;
ent->first = 0; ent->first = FALSE;
give_spwd_free (&ent->pwd); give_spwd_free (&ent->pwd);
return NSS_STATUS_UNAVAIL; return NSS_STATUS_UNAVAIL;
} }
if (ent->first == TRUE) if (ent->first == TRUE)
{ {
bzero (&ent->netgrdata, sizeof (struct __netgrent)); memset (&ent->netgrdata, 0, sizeof (struct __netgrent));
__internal_setnetgrent (group, &ent->netgrdata); __internal_setnetgrent (group, &ent->netgrdata);
ent->first = FALSE; ent->first = FALSE;
} }
@ -330,7 +308,7 @@ getspent_next_nis_netgr (const char *name, struct spwd *result, ent_t *ent,
while (1) while (1)
{ {
char *saved_cursor; char *saved_cursor;
int parse_res; enum nss_status status;
saved_cursor = ent->netgrdata.cursor; saved_cursor = ent->netgrdata.cursor;
status = __internal_getnetgrent_r (&host, &user, &domain, status = __internal_getnetgrent_r (&host, &user, &domain,
@ -339,7 +317,7 @@ getspent_next_nis_netgr (const char *name, struct spwd *result, ent_t *ent,
if (status != 1) if (status != 1)
{ {
__internal_endnetgrent (&ent->netgrdata); __internal_endnetgrent (&ent->netgrdata);
ent->netgroup = 0; ent->netgroup = FALSE;
give_spwd_free (&ent->pwd); give_spwd_free (&ent->pwd);
return NSS_STATUS_RETURN; return NSS_STATUS_RETURN;
} }
@ -347,106 +325,7 @@ getspent_next_nis_netgr (const char *name, struct spwd *result, ent_t *ent,
if (user == NULL || user[0] == '-') if (user == NULL || user[0] == '-')
continue; continue;
if (domain != NULL && strcmp (ypdomain, domain) != 0) if (domain != NULL && strcmp (curdomain, domain) != 0)
continue;
/* If name != NULL, we are called from getpwnam */
if (name != NULL)
if (strcmp (user, name) != 0)
continue;
if (yp_match (ypdomain, "shadow.byname", user,
strlen (user), &outval, &outvallen)
!= YPERR_SUCCESS)
continue;
p2len = spwd_need_buflen (&ent->pwd);
if (p2len > buflen)
{
free (outval);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
p2 = buffer + (buflen - p2len);
buflen -= p2len;
if (buflen < ((size_t) outval + 1))
{
free (outval);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
p = strncpy (buffer, outval, buflen);
while (isspace (*p))
p++;
free (outval);
parse_res = _nss_files_parse_spent (p, result, data, buflen, errnop);
if (parse_res == -1)
{
ent->netgrdata.cursor = saved_cursor;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
if (parse_res)
{
/* Store the User in the blacklist for the "+" at the end of
/etc/passwd */
blacklist_store_name (result->sp_namp, ent);
copy_spwd_changes (result, &ent->pwd, p2, p2len);
break;
}
}
return NSS_STATUS_SUCCESS;
}
static enum nss_status
getspent_next_nisplus_netgr (const char *name, struct spwd *result,
ent_t *ent, char *group, char *buffer,
size_t buflen, int *errnop)
{
char *ypdomain, *host, *user, *domain, *p2;
int status, parse_res;
size_t p2len;
nis_result *nisres;
/* Maybe we should use domainname here ? We need the current
domainname for the domain field in netgroups */
if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS)
{
ent->netgroup = 0;
ent->first = 0;
give_spwd_free (&ent->pwd);
return NSS_STATUS_UNAVAIL;
}
if (ent->first == TRUE)
{
bzero (&ent->netgrdata, sizeof (struct __netgrent));
__internal_setnetgrent (group, &ent->netgrdata);
ent->first = FALSE;
}
while (1)
{
char *saved_cursor;
saved_cursor = ent->netgrdata.cursor;
status = __internal_getnetgrent_r (&host, &user, &domain,
&ent->netgrdata, buffer, buflen,
errnop);
if (status != 1)
{
__internal_endnetgrent (&ent->netgrdata);
ent->netgroup = 0;
give_spwd_free (&ent->pwd);
return NSS_STATUS_RETURN;
}
if (user == NULL || user[0] == '-')
continue;
if (domain != NULL && strcmp (ypdomain, domain) != 0)
continue; continue;
/* If name != NULL, we are called from getpwnam */ /* If name != NULL, we are called from getpwnam */
@ -462,30 +341,15 @@ getspent_next_nisplus_netgr (const char *name, struct spwd *result,
} }
p2 = buffer + (buflen - p2len); p2 = buffer + (buflen - p2len);
buflen -= p2len; buflen -= p2len;
{
char buf[strlen (user) + 30 + pwdtablelen];
sprintf (buf, "[name=%s],%s", user, pwdtable);
nisres = nis_list (buf, FOLLOW_LINKS | FOLLOW_PATH, NULL, NULL);
}
if (niserr2nss (nisres->status) != NSS_STATUS_SUCCESS)
{
nis_freeresult (nisres);
continue;
}
parse_res = _nss_nisplus_parse_spent (nisres, result, buffer,
buflen, errnop);
if (parse_res == -1)
{
nis_freeresult (nisres);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
nis_freeresult (nisres);
if (parse_res) if (nss_getspnam_r (user, result, buffer, buflen, errnop) !=
NSS_STATUS_SUCCESS)
continue;
if (!in_blacklist (result->sp_namp, strlen (result->sp_namp), ent))
{ {
/* Store the User in the blacklist for the "+" at the end of /* Store the User in the blacklist for possible the "+" at the
/etc/passwd */ end of /etc/passwd */
blacklist_store_name (result->sp_namp, ent); blacklist_store_name (result->sp_namp, ent);
copy_spwd_changes (result, &ent->pwd, p2, p2len); copy_spwd_changes (result, &ent->pwd, p2, p2len);
break; break;
@ -495,100 +359,17 @@ getspent_next_nisplus_netgr (const char *name, struct spwd *result,
return NSS_STATUS_SUCCESS; return NSS_STATUS_SUCCESS;
} }
static enum nss_status
getspent_next_nisplus (struct spwd *result, ent_t *ent, char *buffer,
size_t buflen, int *errnop)
{
int parse_res;
size_t p2len;
char *p2;
p2len = spwd_need_buflen (&ent->pwd);
if (p2len > buflen)
{
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
p2 = buffer + (buflen - p2len);
buflen -= p2len;
do
{
bool_t saved_first;
nis_result *saved_res;
if (ent->first)
{
saved_first = TRUE;
saved_res = ent->result;
ent->result = nis_first_entry (pwdtable);
if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
{
ent->nis = 0;
give_spwd_free (&ent->pwd);
return niserr2nss (ent->result->status);
}
ent->first = FALSE;
}
else
{
nis_result *res;
saved_first = FALSE;
saved_res = ent->result;
res = nis_next_entry (pwdtable, &ent->result->cookie);
ent->result = res;
if (niserr2nss (ent->result->status) != NSS_STATUS_SUCCESS)
{
nis_freeresult (saved_res);
ent->nis = 0;
give_spwd_free (&ent->pwd);
return niserr2nss (ent->result->status);
}
}
parse_res = _nss_nisplus_parse_spent (ent->result, result, buffer,
buflen, errnop);
if (parse_res == -1)
{
ent->first = saved_first;
nis_freeresult (ent->result);
ent->result = saved_res;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
else
{
if (!saved_first)
nis_freeresult (saved_res);
}
if (parse_res &&
in_blacklist (result->sp_namp, strlen (result->sp_namp), ent))
parse_res = 0; /* if result->pw_name in blacklist,search next entry */
}
while (!parse_res);
copy_spwd_changes (result, &ent->pwd, p2, p2len);
return NSS_STATUS_SUCCESS;
}
static enum nss_status static enum nss_status
getspent_next_nis (struct spwd *result, ent_t *ent, getspent_next_nss (struct spwd *result, ent_t *ent,
char *buffer, size_t buflen, int *errnop) char *buffer, size_t buflen, int *errnop)
{ {
struct parser_data *data = (void *) buffer; enum nss_status status;
char *domain, *outkey, *outval, *p, *p2; char *p2;
int outkeylen, outvallen, parse_res;
size_t p2len; size_t p2len;
if (yp_get_default_domain (&domain) != YPERR_SUCCESS) if (!nss_getspent_r)
{
ent->nis = 0;
give_spwd_free (&ent->pwd);
return NSS_STATUS_UNAVAIL; return NSS_STATUS_UNAVAIL;
}
p2len = spwd_need_buflen (&ent->pwd); p2len = spwd_need_buflen (&ent->pwd);
if (p2len > buflen) if (p2len > buflen)
@ -600,87 +381,11 @@ getspent_next_nis (struct spwd *result, ent_t *ent,
buflen -= p2len; buflen -= p2len;
do do
{ {
bool_t saved_first; if ((status = nss_getspent_r (result, buffer, buflen, errnop)) !=
char *saved_oldkey; NSS_STATUS_SUCCESS)
int saved_oldlen; return status;
if (ent->first)
{
if (yp_first (domain, "shadow.byname", &outkey, &outkeylen,
&outval, &outvallen) != YPERR_SUCCESS)
{
ent->nis = 0;
give_spwd_free (&ent->pwd);
return NSS_STATUS_UNAVAIL;
} }
while (in_blacklist (result->sp_namp, strlen (result->sp_namp), ent));
if (buflen < ((size_t) outvallen + 1))
{
free (outval);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
saved_first = TRUE;
saved_oldkey = ent->oldkey;
saved_oldlen = ent->oldkeylen;
ent->oldkey = outkey;
ent->oldkeylen = outkeylen;
ent->first = FALSE;
}
else
{
if (yp_next (domain, "shadow.byname", ent->oldkey, ent->oldkeylen,
&outkey, &outkeylen, &outval, &outvallen)
!= YPERR_SUCCESS)
{
ent->nis = 0;
give_spwd_free (&ent->pwd);
return NSS_STATUS_NOTFOUND;
}
if (buflen < ((size_t) outvallen + 1))
{
free (outval);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
saved_first = FALSE;
saved_oldkey = ent->oldkey;
saved_oldlen = ent->oldkeylen;
ent->oldkey = outkey;
ent->oldkeylen = outkeylen;
}
/* Copy the found data to our buffer */
p = strncpy (buffer, outval, buflen);
/* ...and free the data. */
free (outval);
while (isspace (*p))
++p;
parse_res = _nss_files_parse_spent (p, result, data, buflen, errnop);
if (parse_res == -1)
{
free (ent->oldkey);
ent->oldkey = saved_oldkey;
ent->oldkeylen = saved_oldlen;
ent->first = saved_first;
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
else
{
if (!saved_first)
free (saved_oldkey);
}
if (parse_res &&
in_blacklist (result->sp_namp, strlen (result->sp_namp), ent))
parse_res = 0;
}
while (!parse_res);
copy_spwd_changes (result, &ent->pwd, p2, p2len); copy_spwd_changes (result, &ent->pwd, p2, p2len);
@ -689,15 +394,16 @@ getspent_next_nis (struct spwd *result, ent_t *ent,
/* This function handle the +user entrys in /etc/shadow */ /* This function handle the +user entrys in /etc/shadow */
static enum nss_status static enum nss_status
getspnam_plususer (const char *name, struct spwd *result, char *buffer, getspnam_plususer (const char *name, struct spwd *result, ent_t *ent,
size_t buflen, int *errnop) char *buffer, size_t buflen, int *errnop)
{ {
struct parser_data *data = (void *) buffer;
struct spwd pwd; struct spwd pwd;
int parse_res;
char *p; char *p;
size_t plen; size_t plen;
if (!nss_getspnam_r)
return NSS_STATUS_UNAVAIL;
memset (&pwd, '\0', sizeof (struct spwd)); memset (&pwd, '\0', sizeof (struct spwd));
pwd.sp_warn = -1; pwd.sp_warn = -1;
pwd.sp_inact = -1; pwd.sp_inact = -1;
@ -715,71 +421,16 @@ getspnam_plususer (const char *name, struct spwd *result, char *buffer,
p = buffer + (buflen - plen); p = buffer + (buflen - plen);
buflen -= plen; buflen -= plen;
if (use_nisplus) /* Do the NIS+ query here */ if (nss_getspnam_r (name, result, buffer, buflen, errnop) !=
{ NSS_STATUS_SUCCESS)
nis_result *res;
char buf[strlen (name) + 24 + pwdtablelen];
sprintf(buf, "[name=%s],%s", name, pwdtable);
res = nis_list(buf, 0, NULL, NULL);
if (niserr2nss (res->status) != NSS_STATUS_SUCCESS)
{
enum nss_status status = niserr2nss (res->status);
nis_freeresult (res);
return status;
}
parse_res = _nss_nisplus_parse_spent (res, result, buffer,
buflen, errnop);
if (parse_res == -1)
{
nis_freeresult (res);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
nis_freeresult (res);
}
else /* Use NIS */
{
char *domain, *outval, *ptr;
int outvallen;
if (yp_get_default_domain (&domain) != YPERR_SUCCESS)
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
if (yp_match (domain, "shadow.byname", name, strlen (name), if (in_blacklist (result->sp_namp, strlen (result->sp_namp), ent))
&outval, &outvallen) != YPERR_SUCCESS)
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
if (buflen < ((size_t) outvallen + 1))
{
free (outval);
*errnop = ERANGE;
return NSS_STATUS_TRYAGAIN;
}
ptr = strncpy (buffer, outval, buflen);
free (outval);
while (isspace (*ptr))
ptr++;
parse_res = _nss_files_parse_spent (ptr, result, data, buflen, errnop);
if (parse_res == -1)
return NSS_STATUS_TRYAGAIN;
}
if (parse_res)
{
copy_spwd_changes (result, &pwd, p, plen); copy_spwd_changes (result, &pwd, p, plen);
give_spwd_free (&pwd); give_spwd_free (&pwd);
/* We found the entry. */ /* We found the entry. */
return NSS_STATUS_SUCCESS;
}
else
{
/* Give buffer the old len back */
buflen += plen;
give_spwd_free (&pwd);
}
return NSS_STATUS_RETURN; return NSS_STATUS_RETURN;
} }
@ -863,12 +514,7 @@ getspent_next_file (struct spwd *result, ent_t *ent,
ent->first = TRUE; ent->first = TRUE;
copy_spwd_changes (&ent->pwd, result, NULL, 0); copy_spwd_changes (&ent->pwd, result, NULL, 0);
if (use_nisplus) status = getspent_next_nss_netgr (NULL, result, ent,
status = getspent_next_nisplus_netgr (NULL, result, ent,
&result->sp_namp[2],
buffer, buflen, errnop);
else
status = getspent_next_nis_netgr (NULL, result, ent,
&result->sp_namp[2], &result->sp_namp[2],
buffer, buflen, errnop); buffer, buflen, errnop);
if (status == NSS_STATUS_RETURN) if (status == NSS_STATUS_RETURN)
@ -894,12 +540,12 @@ getspent_next_file (struct spwd *result, ent_t *ent,
/* Store the User in the blacklist for the "+" at the end of /* Store the User in the blacklist for the "+" at the end of
/etc/passwd */ /etc/passwd */
blacklist_store_name (&result->sp_namp[1], ent); blacklist_store_name (&result->sp_namp[1], ent);
status = getspnam_plususer (&result->sp_namp[1], result, buffer, status = getspnam_plususer (&result->sp_namp[1], result, ent,
buflen, errnop); buffer, buflen, errnop);
if (status == NSS_STATUS_SUCCESS) /* We found the entry. */ if (status == NSS_STATUS_SUCCESS) /* We found the entry. */
break; break;
else else if (status == NSS_STATUS_RETURN /* We couldn't parse the entry */
if (status == NSS_STATUS_RETURN /* We couldn't parse the entry */
|| status == NSS_STATUS_NOTFOUND) /* entry doesn't exist */ || status == NSS_STATUS_NOTFOUND) /* entry doesn't exist */
continue; continue;
else else
@ -916,14 +562,11 @@ getspent_next_file (struct spwd *result, ent_t *ent,
/* +:... */ /* +:... */
if (result->sp_namp[0] == '+' && result->sp_namp[1] == '\0') if (result->sp_namp[0] == '+' && result->sp_namp[1] == '\0')
{ {
ent->nis = TRUE; ent->files = FALSE;
ent->first = TRUE; ent->first = TRUE;
copy_spwd_changes (&ent->pwd, result, NULL, 0); copy_spwd_changes (&ent->pwd, result, NULL, 0);
if (use_nisplus) return getspent_next_nss (result, ent, buffer, buflen, errnop);
return getspent_next_nisplus (result, ent, buffer, buflen, errnop);
else
return getspent_next_nis (result, ent, buffer, buflen, errnop);
} }
} }
@ -937,57 +580,45 @@ internal_getspent_r (struct spwd *pw, ent_t *ent,
{ {
if (ent->netgroup) if (ent->netgroup)
{ {
int status; enum nss_status status;
/* We are searching members in a netgroup */ /* We are searching members in a netgroup */
/* Since this is not the first call, we don't need the group name */ /* Since this is not the first call, we don't need the group name */
if (use_nisplus) status = getspent_next_nss_netgr (NULL, pw, ent, NULL, buffer,
status = getspent_next_nisplus_netgr (NULL, pw, ent, NULL, buffer,
buflen, errnop); buflen, errnop);
else
status = getspent_next_nis_netgr (NULL, pw, ent, NULL, buffer, buflen,
errnop);
if (status == NSS_STATUS_RETURN) if (status == NSS_STATUS_RETURN)
return getspent_next_file (pw, ent, buffer, buflen, errnop); return getspent_next_file (pw, ent, buffer, buflen, errnop);
else else
return status; return status;
} }
else else if (ent->files)
if (ent->nis)
{
if (use_nisplus)
return getspent_next_nisplus (pw, ent, buffer, buflen, errnop);
else
return getspent_next_nis (pw, ent, buffer, buflen, errnop);
}
else
return getspent_next_file (pw, ent, buffer, buflen, errnop); return getspent_next_file (pw, ent, buffer, buflen, errnop);
else
return getspent_next_nss (pw, ent, buffer, buflen, errnop);
} }
enum nss_status enum nss_status
_nss_compat_getspent_r (struct spwd *pwd, char *buffer, size_t buflen, _nss_compat_getspent_r (struct spwd *pwd, char *buffer, size_t buflen,
int *errnop) int *errnop)
{ {
enum nss_status status = NSS_STATUS_SUCCESS; enum nss_status result = NSS_STATUS_SUCCESS;
__libc_lock_lock (lock); __libc_lock_lock (lock);
/* Be prepared that the setpwent function was not called before. */
if (ni == NULL) if (ni == NULL)
{ init_nss_interface ();
__nss_database_lookup ("shadow_compat", "passwd_compat", "nis", &ni);
use_nisplus = (strcmp (ni->name, "nisplus") == 0);
}
/* Be prepared that the setspent function was not called before. */
if (ext_ent.stream == NULL) if (ext_ent.stream == NULL)
status = internal_setspent (&ext_ent); result = internal_setspent (&ext_ent, 1);
if (status == NSS_STATUS_SUCCESS) if (result == NSS_STATUS_SUCCESS)
status = internal_getspent_r (pwd, &ext_ent, buffer, buflen, errnop); result = internal_getspent_r (pwd, &ext_ent, buffer, buflen, errnop);
__libc_lock_unlock (lock); __libc_lock_unlock (lock);
return status; return result;
} }
/* Searches in /etc/passwd and the NIS/NIS+ map for a special user */ /* Searches in /etc/passwd and the NIS/NIS+ map for a special user */
@ -1046,6 +677,8 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent,
} }
/* -@netgroup */ /* -@netgroup */
/* If the loaded NSS module does not support this service, add
all users from a +@netgroup entry to the blacklist, too. */
if (result->sp_namp[0] == '-' && result->sp_namp[1] == '@' if (result->sp_namp[0] == '-' && result->sp_namp[1] == '@'
&& result->sp_namp[2] != '\0') && result->sp_namp[2] != '\0')
{ {
@ -1080,11 +713,7 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent,
do do
{ {
if (use_nisplus) status = getspent_next_nss_netgr (name, result, ent, buf,
status = getspent_next_nisplus_netgr (name, result, ent, buf,
buffer, buflen, errnop);
else
status = getspent_next_nis_netgr (name, result, ent, buf,
buffer, buflen, errnop); buffer, buflen, errnop);
if (status == NSS_STATUS_RETURN) if (status == NSS_STATUS_RETURN)
continue; continue;
@ -1092,7 +721,8 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent,
if (status == NSS_STATUS_SUCCESS if (status == NSS_STATUS_SUCCESS
&& strcmp (result->sp_namp, name) == 0) && strcmp (result->sp_namp, name) == 0)
return NSS_STATUS_SUCCESS; return NSS_STATUS_SUCCESS;
} while (status == NSS_STATUS_SUCCESS); }
while (status == NSS_STATUS_SUCCESS);
continue; continue;
} }
@ -1114,8 +744,9 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent,
{ {
enum nss_status status; enum nss_status status;
status = getspnam_plususer (name, result, buffer, buflen, status = getspnam_plususer (name, result, ent,
errnop); buffer, buflen, errnop);
if (status == NSS_STATUS_RETURN) if (status == NSS_STATUS_RETURN)
/* We couldn't parse the entry */ /* We couldn't parse the entry */
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
@ -1129,7 +760,9 @@ internal_getspnam_r (const char *name, struct spwd *result, ent_t *ent,
{ {
enum nss_status status; enum nss_status status;
status = getspnam_plususer (name, result, buffer, buflen, errnop); status = getspnam_plususer (name, result, ent,
buffer, buflen, errnop);
if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */ if (status == NSS_STATUS_RETURN) /* We couldn't parse the entry */
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
else else
@ -1143,28 +776,30 @@ enum nss_status
_nss_compat_getspnam_r (const char *name, struct spwd *pwd, _nss_compat_getspnam_r (const char *name, struct spwd *pwd,
char *buffer, size_t buflen, int *errnop) char *buffer, size_t buflen, int *errnop)
{ {
ent_t ent = {0, 0, 0, NULL, 0, NULL, NULL, {NULL, 0, 0}, enum nss_status result;
ent_t ent = {0, TRUE, 0, NULL, {NULL, 0, 0},
{NULL, NULL, 0, 0, 0, 0, 0, 0, 0}}; {NULL, NULL, 0, 0, 0, 0, 0, 0, 0}};
enum nss_status status;
if (name[0] == '-' || name[0] == '+') if (name[0] == '-' || name[0] == '+')
return NSS_STATUS_NOTFOUND; return NSS_STATUS_NOTFOUND;
__libc_lock_lock (lock);
if (ni == NULL) if (ni == NULL)
{ init_nss_interface ();
__nss_database_lookup ("shadow_compat", "passwd_compat", "nis", &ni);
use_nisplus = (strcmp (ni->name, "nisplus") == 0);
}
status = internal_setspent (&ent); __libc_lock_unlock (lock);
if (status != NSS_STATUS_SUCCESS)
return status;
status = internal_getspnam_r (name, pwd, &ent, buffer, buflen, errnop); result = internal_setspent (&ent, 0);
if (result != NSS_STATUS_SUCCESS)
return result;
result = internal_getspnam_r (name, pwd, &ent, buffer, buflen, errnop);
internal_endspent (&ent); internal_endspent (&ent);
return status; return result;
} }
/* Support routines for remembering -@netgroup and -user entries. /* Support routines for remembering -@netgroup and -user entries.
@ -1225,7 +860,7 @@ in_blacklist (const char *name, int namelen, ent_t *ent)
buf[0] = '|'; buf[0] = '|';
cp = stpcpy (&buf[1], name); cp = stpcpy (&buf[1], name);
*cp++= '|'; *cp++ = '|';
*cp = '\0'; *cp = '\0';
return strstr (ent->blacklist.data, buf) != NULL; return strstr (ent->blacklist.data, buf) != NULL;
} }

View File

@ -9,7 +9,7 @@ libc {
} }
GLIBC_PRIVATE { GLIBC_PRIVATE {
_nss_files_parse_grent; _nss_files_parse_pwent; _nss_files_parse_spent; _nss_files_parse_grent; _nss_files_parse_pwent; _nss_files_parse_spent;
__nss_disable_nscd; __nss_disable_nscd; __nss_lookup_function;
} }
} }

View File

@ -141,6 +141,11 @@
# define __ASSUME_IPC64 1 # define __ASSUME_IPC64 1
#endif #endif
/* We can use the LDTs for threading with Linux 2.3.99 and newer. */
#if __LINUX_KERNEL_VERSION >= 131939
# define __ASSUME_LDT_WORKS 1
#endif
/* Linux 2.4.0 on PPC introduced a correct IPC64. But PowerPC64 does not /* Linux 2.4.0 on PPC introduced a correct IPC64. But PowerPC64 does not
support a separate 64-bit sys call, already 64-bit */ support a separate 64-bit sys call, already 64-bit */
#if __LINUX_KERNEL_VERSION >= 132096 && defined __powerpc__ \ #if __LINUX_KERNEL_VERSION >= 132096 && defined __powerpc__ \
@ -148,15 +153,18 @@
# define __ASSUME_IPC64 1 # define __ASSUME_IPC64 1
#endif #endif
/* We can use the LDTs for threading with Linux 2.3.99 and newer. */ /* SH kernels got stat64, mmap2, and truncate64 during 2.4.0-test. */
#if __LINUX_KERNEL_VERSION >= 131939 #if __LINUX_KERNEL_VERSION >= 132096 && defined __sh__
# define __ASSUME_LDT_WORKS 1 # define __ASSUME_TRUNCATE64_SYSCALL 1
# define __ASSUME_MMAP2_SYSCALL 1
# define __ASSUME_STAT64_SYSCALL 1
#endif #endif
/* The changed st_ino field appeared in 2.4.0-test6. But we cannot /* The changed st_ino field appeared in 2.4.0-test6. But we cannot
distinguish this version from other 2.4.0 releases. Therefore play distinguish this version from other 2.4.0 releases. Therefore play
save and assume it available is for 2.4.1 and up. */ save and assume it available is for 2.4.1 and up. However, SH is lame,
#if __LINUX_KERNEL_VERSION >= 132097 && !defined __alpha__ and still does not have a 64-bit inode field. */
#if __LINUX_KERNEL_VERSION >= 132097 && !defined __alpha__ && !defined __sh__
# define __ASSUME_ST_INO_64_BIT 1 # define __ASSUME_ST_INO_64_BIT 1
#endif #endif