diff options
Diffstat (limited to 'nis')
-rw-r--r-- | nis/Banner | 1 | ||||
-rw-r--r-- | nis/Makefile | 100 | ||||
-rw-r--r-- | nis/nss-nis.h | 58 | ||||
-rw-r--r-- | nis/nss_compat/compat-grp.c | 421 | ||||
-rw-r--r-- | nis/nss_compat/compat-pwd.c | 695 | ||||
-rw-r--r-- | nis/nss_compat/compat-spwd.c | 612 | ||||
-rw-r--r-- | nis/nss_nis/nis-alias.c | 269 | ||||
-rw-r--r-- | nis/nss_nis/nis-ethers.c | 264 | ||||
-rw-r--r-- | nis/nss_nis/nis-grp.c | 246 | ||||
-rw-r--r-- | nis/nss_nis/nis-hosts.c | 389 | ||||
-rw-r--r-- | nis/nss_nis/nis-netgrp.c | 128 | ||||
-rw-r--r-- | nis/nss_nis/nis-network.c | 292 | ||||
-rw-r--r-- | nis/nss_nis/nis-proto.c | 246 | ||||
-rw-r--r-- | nis/nss_nis/nis-publickey.c | 220 | ||||
-rw-r--r-- | nis/nss_nis/nis-pwd.c | 246 | ||||
-rw-r--r-- | nis/nss_nis/nis-rpc.c | 270 | ||||
-rw-r--r-- | nis/nss_nis/nis-service.c | 249 | ||||
-rw-r--r-- | nis/nss_nis/nis-spwd.c | 196 | ||||
-rw-r--r-- | nis/rpcsvc/yp.h | 611 | ||||
-rw-r--r-- | nis/rpcsvc/yp.x | 300 | ||||
-rw-r--r-- | nis/rpcsvc/yp_prot.h | 334 | ||||
-rw-r--r-- | nis/rpcsvc/ypclnt.h | 88 | ||||
-rw-r--r-- | nis/rpcsvc/ypupd.h | 88 | ||||
-rw-r--r-- | nis/yp_xdr.c | 342 | ||||
-rw-r--r-- | nis/ypclnt.c | 868 | ||||
-rw-r--r-- | nis/ypupdate_xdr.c | 73 |
26 files changed, 7606 insertions, 0 deletions
diff --git a/nis/Banner b/nis/Banner new file mode 100644 index 0000000000..be5280c5d4 --- /dev/null +++ b/nis/Banner @@ -0,0 +1 @@ +NIS(YP) NSS modules 0.8 by Thorsten Kukuk diff --git a/nis/Makefile b/nis/Makefile new file mode 100644 index 0000000000..475ee67175 --- /dev/null +++ b/nis/Makefile @@ -0,0 +1,100 @@ +# Copyright (C) 1996 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 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, +# write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# +# Makefile for NIS part. +# +subdir := nis + +headers := $(wildcard rpcsvc/*.[hx]) + +# These are the databases available for the nis (and perhaps later nisplus) +# service. This must be a superset of the services in nss. +databases = proto service hosts network grp pwd rpc ethers \ + spwd netgrp alias + +# Specify rules for the nss_* modules. Later we may have nisplus as well. +services := nis compat + +extra-libs = libnsl $(services:%=libnss_%) +# These libraries will be built in the `others' pass rather than +# the `lib' pass, because they depend on libc.so being built already. +extra-libs-others = $(extra-libs) + +others = ypcat ypmatch yppoll ypset ypwhich +install-bin = ypcat ypmatch ypwhich +install-sbin = ypset yppoll + +# The sources are found in the appropriate subdir. +subdir-dirs = bsd-tools $(services:%=nss_%) +vpath %.c $(subdir-dirs) + +libnsl-routines = yp_xdr ypclnt ypupdate_xdr + +libnss_compat-routines := $(addprefix compat-,grp pwd spwd) +libnss_compat-inhibit-o = $(filter-out .so,$(object-suffixes)) + +libnss_nis-routines := $(addprefix nis-,$(databases)) +libnss_nis-inhibit-o = $(filter-out .so,$(object-suffixes)) + + +# Sun's header files are not too clean. +CFLAGS-compat-pwd.c = -Wno-strict-prototypes +CFLAGS-compat-spwd.c = -Wno-strict-prototypes +CFLAGS-compat-grp.c = -Wno-strict-prototypes +CFLAGS-nis-alias.c = -Wno-strict-prototypes +CFLAGS-nis-ethers.c = -Wno-strict-prototypes +CFLAGS-nis-grp.c = -Wno-strict-prototypes +CFLAGS-nis-hosts.c = -Wno-strict-prototypes +CFLAGS-nis-netgrp.c = -Wno-strict-prototypes +CFLAGS-nis-network.c = -Wno-strict-prototypes +CFLAGS-nis-proto.c = -Wno-strict-prototypes +CFLAGS-nis-publickey.c = -Wno-strict-prototypes +CFLAGS-nis-pwd.c = -Wno-strict-prototypes +CFLAGS-nis-rpc.c = -Wno-strict-prototypes +CFLAGS-nis-service.c = -Wno-strict-prototypes +CFLAGS-nis-spwd.c = -Wno-strict-prototypes +CFLAGS-ypclnt.c = -Wno-strict-prototypes -Wno-write-strings +CFLAGS-yp_xdr.c = -Wno-strict-prototypes +CFLAGS-ypupdate_xdr.c = -Wno-strict-prototypes +CFLAGS-ypcat.c = -Wno-strict-prototypes +CFLAGS-ypmatch.c = -Wno-strict-prototypes +CFLAGS-ypwhich.c = -Wno-strict-prototypes +CFLAGS-ypset.c = -Wno-strict-prototypes +CFLAGS-yppoll.c = -Wno-strict-prototypes + + +include ../Rules + + +$(objpfx)libnss_compat.so: $(objpfx)libnsl.so$(libnsl.so-version) \ + $(common-objpfx)nss/libnss_files.so +$(objpfx)libnss_nis.so: $(objpfx)libnsl.so$(libnsl.so-version) \ + $(common-objpfx)nss/libnss_files.so + +# Depend on libc.so so a DT_NEEDED is generated in the shared objects. +# This ensures they will load libc.so for needed symbols if loaded by +# a statically-linked program that hasn't already loaded it. +$(services:%=$(objpfx)libnss_%.so): $(common-objpfx)libc.so + + +ifeq ($(build-shared),yes) +$(others:%=$(objpfx)%): $(objpfx)libnsl.so$(libnsl.so-version) +else +$(others:%=$(objpfx)%): $(objpfx)libnsl.a +endif diff --git a/nis/nss-nis.h b/nis/nss-nis.h new file mode 100644 index 0000000000..13ba62ed9f --- /dev/null +++ b/nis/nss-nis.h @@ -0,0 +1,58 @@ +/* Copyright (C) 1996 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 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _NIS_NSS_NIS_H +#define _NIS_NSS_NIS_H 1 + +#include <rpcsvc/ypclnt.h> + +#include "nsswitch.h" + + +/* Convert YP error number to NSS error number. */ +static enum nss_status yperr2nss_tab[] = +{ + [YPERR_SUCCESS] = NSS_STATUS_SUCCESS, + [YPERR_BADARGS] = NSS_STATUS_UNAVAIL, + [YPERR_RPC] = NSS_STATUS_UNAVAIL, + [YPERR_DOMAIN] = NSS_STATUS_UNAVAIL, + [YPERR_MAP] = NSS_STATUS_UNAVAIL, + [YPERR_KEY] = NSS_STATUS_NOTFOUND, + [YPERR_YPERR] = NSS_STATUS_UNAVAIL, + [YPERR_RESRC] = NSS_STATUS_TRYAGAIN, + [YPERR_NOMORE] = NSS_STATUS_NOTFOUND, + [YPERR_PMAP] = NSS_STATUS_UNAVAIL, + [YPERR_YPBIND] = NSS_STATUS_UNAVAIL, + [YPERR_YPSERV] = NSS_STATUS_UNAVAIL, + [YPERR_NODOM] = NSS_STATUS_UNAVAIL, + [YPERR_BADDB] = NSS_STATUS_UNAVAIL, + [YPERR_VERS] = NSS_STATUS_UNAVAIL, + [YPERR_ACCESS] = NSS_STATUS_UNAVAIL, + [YPERR_BUSY] = NSS_STATUS_TRYAGAIN +}; +#define YPERR_COUNT (sizeof (yperr2nss_tab) / sizeof (yperr2nss_tab[0])) + +static inline enum nss_status +yperr2nss (int errval) +{ + if ((unsigned int) errval > YPERR_COUNT) + return NSS_STATUS_UNAVAIL; + return yperr2nss_tab[errval]; +} + +#endif /* nis/nss-nis.h */ diff --git a/nis/nss_compat/compat-grp.c b/nis/nss_compat/compat-grp.c new file mode 100644 index 0000000000..0b4ed40e59 --- /dev/null +++ b/nis/nss_compat/compat-grp.c @@ -0,0 +1,421 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <errno.h> +#include <nss.h> +#include <grp.h> +#include <ctype.h> +#include <libc-lock.h> +#include <string.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +/* Structure for remembering -@netgroup and -user members ... */ +#define BLACKLIST_INITIAL_SIZE 512 +#define BLACKLIST_INCREMENT 256 +struct blacklist_t + { + char *data; + int current; + int size; + }; + +struct ent_t + { + bool_t nis; + bool_t nis_first; + char *oldkey; + int oldkeylen; + FILE *stream; + struct blacklist_t blacklist; + }; +typedef struct ent_t ent_t; + +static ent_t ext_ent = {0, 0, NULL, 0, NULL, {NULL, 0, 0}}; + +/* Protect global state against multiple changers. */ +__libc_lock_define_initialized (static, lock) + +/* Prototypes for local functions. */ +static void blacklist_store_name (const char *, ent_t *); +static int in_blacklist (const char *, int, ent_t *); + +static enum nss_status +internal_setgrent (ent_t *ent) +{ + enum nss_status status = NSS_STATUS_SUCCESS; + + ent->nis = ent->nis_first = 0; + + if (ent->oldkey != NULL) + { + free (ent->oldkey); + ent->oldkey = NULL; + ent->oldkeylen = 0; + } + + ent->blacklist.current = 0; + if (ent->blacklist.data != NULL) + ent->blacklist.data[0] = '\0'; + + if (ent->stream == NULL) + { + ent->stream = fopen ("/etc/group", "r"); + + if (ent->stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + } + else + rewind (ent->stream); + + return status; +} + + +enum nss_status +_nss_compat_setgrent (void) +{ + enum nss_status result; + + __libc_lock_lock (lock); + + result = internal_setgrent (&ext_ent); + + __libc_lock_unlock (lock); + + return result; +} + + +static enum nss_status +internal_endgrent (ent_t *ent) +{ + if (ent->stream != NULL) + { + fclose (ent->stream); + ent->stream = NULL; + } + + ent->nis = ent->nis_first = 0; + + if (ent->oldkey != NULL) + { + free (ent->oldkey); + ent->oldkey = NULL; + ent->oldkeylen = 0; + } + + ent->blacklist.current = 0; + if (ent->blacklist.data != NULL) + ent->blacklist.data[0] = '\0'; + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_compat_endgrent (void) +{ + enum nss_status result; + + __libc_lock_lock (lock); + + result = internal_endgrent (&ext_ent); + + __libc_lock_unlock (lock); + + return result; +} + +static enum nss_status +getgrent_next_nis (struct group *result, ent_t *ent, char *buffer, + size_t buflen) +{ + char *domain; + char *outkey, *outval; + int outkeylen, outvallen; + char *p; + + if (yp_get_default_domain (&domain) != YPERR_SUCCESS) + { + ent->nis = 0; + return NSS_STATUS_NOTFOUND; + } + + do + { + if (ent->nis_first) + { + if (yp_first (domain, "group.byname", &outkey, &outkeylen, + &outval, &outvallen) != YPERR_SUCCESS) + { + ent->nis = 0; + return NSS_STATUS_UNAVAIL; + } + + 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; + } + + free (ent->oldkey); + 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; + } + while (!_nss_files_parse_grent (p, result, buffer, buflen)); + + if (!in_blacklist (result->gr_name, strlen (result->gr_name), ent)) + return NSS_STATUS_SUCCESS; + else + return NSS_STATUS_NOTFOUND; +} + + +static enum nss_status +getgrent_next_file (struct group *result, ent_t *ent, + char *buffer, size_t buflen) +{ + while (1) + { + char *p; + + do + { + p = fgets (buffer, buflen, ent->stream); + if (p == NULL) + return NSS_STATUS_NOTFOUND; + + /* Terminate the line for any case. */ + buffer[buflen - 1] = '\0'; + + /* Skip leading blanks. */ + while (isspace (*p)) + ++p; + } + /* Ignore empty and comment lines. */ + while (*p == '\0' || *p == '#' || + /* Parse the line. If it is invalid, loop to + get the next line of the file to parse. */ + !_nss_files_parse_grent (p, result, buffer, buflen)); + + if (result->gr_name[0] != '+' && result->gr_name[0] != '-') + /* This is a real entry. */ + break; + + /* -group */ + if (result->gr_name[0] == '-' && result->gr_name[1] != '\0' + && result->gr_name[1] != '@') + { + blacklist_store_name (&result->gr_name[1], ent); + continue; + } + + /* +group */ + if (result->gr_name[0] == '+' && result->gr_name[1] != '\0' + && result->gr_name[1] != '@') + { + char *domain; + char *outval; + int outvallen; + + if (yp_get_default_domain (&domain) != YPERR_SUCCESS) + /* XXX Should we regard this as an fatal error? I don't + think so. Just continue working. --drepper@gnu */ + continue; + + if (yp_match (domain, "group.byname", &result->gr_name[1], + strlen (result->gr_name) - 1, &outval, &outvallen) + != YPERR_SUCCESS) + continue; + + p = strncpy (buffer, outval, buflen); + while (isspace (*p)) + p++; + free (outval); + if (_nss_files_parse_grent (p, result, buffer, buflen)) + /* We found the entry. */ + break; + } + + /* +:... */ + if (result->gr_name[0] == '+' && result->gr_name[1] == '\0') + { + ent->nis = TRUE; + ent->nis_first = TRUE; + + return getgrent_next_nis (result, ent, buffer, buflen); + } + } + + return NSS_STATUS_SUCCESS; +} + + +static enum nss_status +internal_getgrent_r (struct group *gr, ent_t *ent, char *buffer, + size_t buflen) +{ + if (ent->nis) + return getgrent_next_nis (gr, ent, buffer, buflen); + else + return getgrent_next_file (gr, ent, buffer, buflen); +} + +enum nss_status +_nss_compat_getgrent_r (struct group *grp, char *buffer, size_t buflen) +{ + enum nss_status status = NSS_STATUS_SUCCESS; + + __libc_lock_lock (lock); + + /* Be prepared that the setgrent function was not called before. */ + if (ext_ent.stream == NULL) + status = internal_setgrent (&ext_ent); + + if (status == NSS_STATUS_SUCCESS) + status = internal_getgrent_r (grp, &ext_ent, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + + +enum nss_status +_nss_compat_getgrnam_r (const char *name, struct group *grp, + char *buffer, size_t buflen) +{ + ent_t ent = {0, 0, NULL, 0, NULL, {NULL, 0, 0}}; + enum nss_status status; + + if (name[0] == '-' || name[0] == '+') + return NSS_STATUS_NOTFOUND; + + + status = internal_setgrent (&ent); + if (status != NSS_STATUS_SUCCESS) + return status; + + while ((status = internal_getgrent_r (grp, &ent, buffer, buflen)) + == NSS_STATUS_SUCCESS) + if (strcmp (grp->gr_name, name) == 0) + break; + + internal_endgrent (&ent); + return status; +} + + +enum nss_status +_nss_compat_getgrgid_r (gid_t gid, struct group *grp, + char *buffer, size_t buflen) +{ + ent_t ent = {0, 0, NULL, 0, NULL, {NULL, 0, 0}}; + enum nss_status status; + + status = internal_setgrent (&ent); + if (status != NSS_STATUS_SUCCESS) + return status; + + while ((status = internal_getgrent_r (grp, &ent, buffer, buflen)) + == NSS_STATUS_SUCCESS) + if (grp->gr_gid == gid && grp->gr_name[0] != '+' && grp->gr_name[0] != '-') + break; + + internal_endgrent (&ent); + return status; +} + + +/* Support routines for remembering -@netgroup and -user entries. + The names are stored in a single string with `|' as separator. */ +static void +blacklist_store_name (const char *name, ent_t *ent) +{ + int namelen = strlen (name); + char *tmp; + + /* first call, setup cache */ + if (ent->blacklist.size == 0) + { + ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); + ent->blacklist.data = malloc (ent->blacklist.size); + if (ent->blacklist.data == NULL) + return; + ent->blacklist.data[0] = '|'; + ent->blacklist.data[1] = '\0'; + ent->blacklist.current = 1; + } + else + { + if (in_blacklist (name, namelen, ent)) + return; /* no duplicates */ + + if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size) + { + ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen); + tmp = realloc (ent->blacklist.data, ent->blacklist.size); + if (tmp == NULL) + { + free (ent->blacklist.data); + ent->blacklist.size = 0; + return; + } + ent->blacklist.data = tmp; + } + } + + tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name); + *tmp++ = '|'; + *tmp = '\0'; + ent->blacklist.current += namelen + 1; + + return; +} + +/* returns TRUE if ent->blacklist contains name, else FALSE */ +static bool_t +in_blacklist (const char *name, int namelen, ent_t *ent) +{ + char buf[namelen + 3]; + + if (ent->blacklist.data == NULL) + return FALSE; + + stpcpy (stpcpy (stpcpy (buf, "|"), name), "|"); + return strstr (ent->blacklist.data, buf) != NULL; +} diff --git a/nis/nss_compat/compat-pwd.c b/nis/nss_compat/compat-pwd.c new file mode 100644 index 0000000000..503aafb51e --- /dev/null +++ b/nis/nss_compat/compat-pwd.c @@ -0,0 +1,695 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <pwd.h> +#include <errno.h> +#include <ctype.h> +#include <netdb.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +#include "netgroup.h" + +/* Structure for remembering -@netgroup and -user members ... */ +#define BLACKLIST_INITIAL_SIZE 512 +#define BLACKLIST_INCREMENT 256 +struct blacklist_t + { + char *data; + int current; + int size; + }; + +struct ent_t + { + bool_t netgroup; + bool_t nis; + bool_t first; + char *oldkey; + int oldkeylen; + FILE *stream; + struct blacklist_t blacklist; + struct passwd pwd; + struct __netgrent netgrdata; + }; +typedef struct ent_t ent_t; + +static ent_t ext_ent = {0, 0, 0, NULL, 0, NULL, {NULL, 0, 0}, + {NULL, NULL, 0, 0, NULL, NULL, NULL}}; + +/* Protect global state against multiple changers. */ +__libc_lock_define_initialized (static, lock) + +/* Prototypes for local functions. */ +static void blacklist_store_name (const char *, ent_t *); +static int in_blacklist (const char *, int, ent_t *); + +static void +give_pwd_free (struct passwd *pwd) +{ + if (pwd->pw_name != NULL) + free (pwd->pw_name); + if (pwd->pw_passwd != NULL) + free (pwd->pw_passwd); + if (pwd->pw_gecos != NULL) + free (pwd->pw_gecos); + if (pwd->pw_dir != NULL) + free (pwd->pw_dir); + if (pwd->pw_shell != NULL) + free (pwd->pw_shell); + + memset (pwd, '\0', sizeof (struct passwd)); +} + +static size_t +pwd_need_buflen (struct passwd *pwd) +{ + size_t len = 0; + + if (pwd->pw_passwd != NULL) + len += strlen (pwd->pw_passwd) + 1; + + if (pwd->pw_gecos != NULL) + len += strlen (pwd->pw_gecos) + 1; + + if (pwd->pw_dir != NULL) + len += strlen (pwd->pw_dir) + 1; + + if (pwd->pw_shell != NULL) + len += strlen (pwd->pw_shell) + 1; + + return len; +} + +static void +copy_pwd_changes (struct passwd *dest, struct passwd *src, + char *buffer, size_t buflen) +{ + if (src->pw_passwd != NULL && strlen (src->pw_passwd)) + { + if (buffer == NULL) + dest->pw_passwd = strdup (src->pw_passwd); + else if (dest->pw_passwd && + strlen (dest->pw_passwd) >= strlen (src->pw_passwd)) + strcpy (dest->pw_passwd, src->pw_passwd); + else + { + dest->pw_passwd = buffer; + strcpy (dest->pw_passwd, src->pw_passwd); + buffer += strlen (dest->pw_passwd) + 1; + buflen = buflen - (strlen (dest->pw_passwd) + 1); + } + } + + if (src->pw_gecos != NULL && strlen (src->pw_gecos)) + { + if (buffer == NULL) + dest->pw_gecos = strdup (src->pw_gecos); + else if (dest->pw_gecos && + strlen (dest->pw_gecos) >= strlen (src->pw_gecos)) + strcpy (dest->pw_gecos, src->pw_gecos); + else + { + dest->pw_gecos = buffer; + strcpy (dest->pw_gecos, src->pw_gecos); + buffer += strlen (dest->pw_gecos) + 1; + buflen = buflen - (strlen (dest->pw_gecos) + 1); + } + } + if (src->pw_dir != NULL && strlen (src->pw_dir)) + { + if (buffer == NULL) + dest->pw_dir = strdup (src->pw_dir); + else if (dest->pw_dir && + strlen (dest->pw_dir) >= strlen (src->pw_dir)) + strcpy (dest->pw_dir, src->pw_dir); + else + { + dest->pw_dir = buffer; + strcpy (dest->pw_dir, src->pw_dir); + buffer += strlen (dest->pw_dir) + 1; + buflen = buflen - (strlen (dest->pw_dir) + 1); + } + } + + if (src->pw_shell != NULL && strlen (src->pw_shell)) + { + if (buffer == NULL) + dest->pw_shell = strdup (src->pw_shell); + else if (dest->pw_shell && + strlen (dest->pw_shell) >= strlen (src->pw_shell)) + strcpy (dest->pw_shell, src->pw_shell); + else + { + dest->pw_shell = buffer; + strcpy (dest->pw_shell, src->pw_shell); + buffer += strlen (dest->pw_shell) + 1; + buflen = buflen - (strlen (dest->pw_shell) + 1); + } + } +} + +static enum nss_status +internal_setpwent (ent_t *ent) +{ + enum nss_status status = NSS_STATUS_SUCCESS; + + ent->nis = ent->first = ent->netgroup = 0; + + /* If something was left over free it. */ + if (ent->netgroup) + __internal_endnetgrent (&ent->netgrdata); + + if (ent->oldkey != NULL) + { + free (ent->oldkey); + ent->oldkey = NULL; + ent->oldkeylen = 0; + } + + ent->blacklist.current = 0; + if (ent->blacklist.data != NULL) + ent->blacklist.data[0] = '\0'; + + if (ent->stream == NULL) + { + ent->stream = fopen ("/etc/passwd", "r"); + + if (ent->stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + } + else + rewind (ent->stream); + + give_pwd_free (&ent->pwd); + + return status; +} + + +enum nss_status +_nss_compat_setpwent (void) +{ + enum nss_status result; + + __libc_lock_lock (lock); + + result = internal_setpwent (&ext_ent); + + __libc_lock_unlock (lock); + + return result; +} + + +static enum nss_status +internal_endpwent (ent_t *ent) +{ + if (ent->stream != NULL) + { + fclose (ent->stream); + ent->stream = NULL; + } + + ent->nis = ent->first = ent->netgroup = 0; + + if (ent->oldkey != NULL) + { + free (ent->oldkey); + ent->oldkey = NULL; + ent->oldkeylen = 0; + } + + ent->blacklist.current = 0; + if (ent->blacklist.data != NULL) + ent->blacklist.data[0] = '\0'; + + give_pwd_free (&ent->pwd); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_compat_endpwent (void) +{ + enum nss_status result; + + __libc_lock_lock (lock); + + if (ext_ent.netgroup) + __internal_endnetgrent (&ext_ent.netgrdata); + + result = internal_endpwent (&ext_ent); + + __libc_lock_unlock (lock); + + return result; +} + +static enum nss_status +getpwent_next_netgr (struct passwd *result, ent_t *ent, char *group, + char *buffer, size_t buflen) +{ + char *ypdomain, *host, *user, *domain, *outval, *p, *p2; + int status, outvallen, p2len; + + if (yp_get_default_domain (&ypdomain) != YPERR_SUCCESS) + { + ent->netgroup = 0; + ent->first = 0; + give_pwd_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) + { + status = __internal_getnetgrent (&host, &user, &domain, &ent->netgrdata, + buffer, buflen); + if (status != 1) + { + __internal_endnetgrent (&ent->netgrdata); + ent->netgroup = 0; + give_pwd_free (&ent->pwd); + return NSS_STATUS_RETURN; + } + + if (user == NULL || user[0] == '-') + continue; + + if (domain != NULL && strcmp (ypdomain, domain) != 0) + continue; + + if (yp_match (ypdomain, "passwd.byname", user, + strlen (user), &outval, &outvallen) + != YPERR_SUCCESS) + continue; + + p2len = pwd_need_buflen (&ent->pwd); + if (p2len > buflen) + { + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + p2 = buffer + (buflen - p2len); + buflen -= p2len; + p = strncpy (buffer, outval, buflen); + while (isspace (*p)) + p++; + free (outval); + if (_nss_files_parse_pwent (p, result, buffer, buflen)) + { + copy_pwd_changes (result, &ent->pwd, p2, p2len); + break; + } + } + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +getpwent_next_nis (struct passwd *result, ent_t *ent, char *buffer, + size_t buflen) +{ + char *domain, *outkey, *outval, *p, *p2; + int outkeylen, outvallen, p2len; + + if (yp_get_default_domain (&domain) != YPERR_SUCCESS) + { + ent->nis = 0; + give_pwd_free (&ent->pwd); + return NSS_STATUS_UNAVAIL; + } + + p2len = pwd_need_buflen (&ent->pwd); + if (p2len > buflen) + { + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + p2 = buffer + (buflen - p2len); + buflen -= p2len; + do + { + if (ent->first) + { + if (yp_first (domain, "passwd.byname", &outkey, &outkeylen, + &outval, &outvallen) != YPERR_SUCCESS) + { + ent->nis = 0; + give_pwd_free (&ent->pwd); + return NSS_STATUS_UNAVAIL; + } + + ent->oldkey = outkey; + ent->oldkeylen = outkeylen; + ent->first = FALSE; + } + else + { + if (yp_next (domain, "passwd.byname", ent->oldkey, ent->oldkeylen, + &outkey, &outkeylen, &outval, &outvallen) + != YPERR_SUCCESS) + { + ent->nis = 0; + give_pwd_free (&ent->pwd); + return NSS_STATUS_NOTFOUND; + } + + free (ent->oldkey); + 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; + } + while (!_nss_files_parse_pwent (p, result, buffer, buflen)); + + copy_pwd_changes (result, &ent->pwd, p2, p2len); + + if (!in_blacklist (result->pw_name, strlen (result->pw_name), ent)) + return NSS_STATUS_SUCCESS; + else + return NSS_STATUS_NOTFOUND; +} + + +static enum nss_status +getpwent_next_file (struct passwd *result, ent_t *ent, + char *buffer, size_t buflen) +{ + while (1) + { + char *p, *p2; + int p2len; + + do + { + p = fgets (buffer, buflen, ent->stream); + if (p == NULL) + return NSS_STATUS_NOTFOUND; + + /* Terminate the line for any case. */ + buffer[buflen - 1] = '\0'; + + /* Skip leading blanks. */ + while (isspace (*p)) + ++p; + } + while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ + /* Parse the line. If it is invalid, loop to + get the next line of the file to parse. */ + !_nss_files_parse_pwent (p, result, buffer, buflen)); + + if (result->pw_name[0] != '+' && result->pw_name[0] != '-') + /* This is a real entry. */ + break; + + /* -@netgroup */ + if (result->pw_name[0] == '-' && result->pw_name[1] == '@' + && result->pw_name[2] != '\0') + { + char *user, *host, *domain; + + setnetgrent (&result->pw_name[2]); + while (getnetgrent (&host, &user, &domain)) + { + if (user != NULL && user[0] != '-') + blacklist_store_name (user, ent); + } + endnetgrent (); + continue; + } + + /* +@netgroup */ + if (result->pw_name[0] == '+' && result->pw_name[1] == '@' + && result->pw_name[2] != '\0') + { + int status; + + ent->netgroup = TRUE; + ent->first = TRUE; + copy_pwd_changes (&ent->pwd, result, NULL, 0); + + status = getpwent_next_netgr (result, ent, &result->pw_name[2], + buffer, buflen); + if (status == NSS_STATUS_RETURN) + continue; + else + return status; + } + + /* -user */ + if (result->pw_name[0] == '-' && result->pw_name[1] != '\0' + && result->pw_name[1] != '@') + { + blacklist_store_name (&result->pw_name[1], ent); + continue; + } + + /* +user */ + if (result->pw_name[0] == '+' && result->pw_name[1] != '\0' + && result->pw_name[1] != '@') + { + char *domain; + char *outval; + int outvallen; + struct passwd pwd; + + memset (&pwd, '\0', sizeof (struct passwd)); + + if (yp_get_default_domain (&domain) != YPERR_SUCCESS) + /* XXX Should we regard this as an fatal error? I don't + think so. Just continue working. --drepper@gnu */ + continue; + + if (yp_match (domain, "passwd.byname", &result->pw_name[1], + strlen (result->pw_name) - 1, &outval, &outvallen) + != YPERR_SUCCESS) + continue; + + copy_pwd_changes (&pwd, result, NULL, 0); + + p2len = pwd_need_buflen (&pwd); + if (p2len > buflen) + { + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + p2 = buffer + (buflen - p2len); + buflen -= p2len; + p = strncpy (buffer, outval, buflen); + while (isspace (*p)) + p++; + free (outval); + if (_nss_files_parse_pwent (p, result, buffer, buflen)) + { + copy_pwd_changes (result, &pwd, p2, p2len); + give_pwd_free (&pwd); + /* We found the entry. */ + break; + } + else + { + /* Give buffer the old len back */ + buflen += p2len; + give_pwd_free (&pwd); + } + } + + /* +:... */ + if (result->pw_name[0] == '+' && result->pw_name[1] == '\0') + { + ent->nis = TRUE; + ent->first = TRUE; + copy_pwd_changes (&ent->pwd, result, NULL, 0); + + return getpwent_next_nis (result, ent, buffer, buflen); + } + } + + return NSS_STATUS_SUCCESS; +} + + +static enum nss_status +internal_getpwent_r (struct passwd *pw, ent_t *ent, char *buffer, + size_t buflen) +{ + if (ent->netgroup) + { + int status; + + /* We are searching members in a netgroup */ + /* Since this is not the first call, we don't need the group name */ + status = getpwent_next_netgr (pw, ent, NULL, buffer, buflen); + if (status == NSS_STATUS_RETURN) + return getpwent_next_file (pw, ent, buffer, buflen); + else + return status; + } + else if (ent->nis) + return getpwent_next_nis (pw, ent, buffer, buflen); + else + return getpwent_next_file (pw, ent, buffer, buflen); +} + +enum nss_status +_nss_compat_getpwent_r (struct passwd *pwd, char *buffer, + size_t buflen) +{ + enum nss_status status = NSS_STATUS_SUCCESS; + + __libc_lock_lock (lock); + + /* Be prepared that the setpwent function was not called before. */ + if (ext_ent.stream == NULL) + status = internal_setpwent (&ext_ent); + + if (status == NSS_STATUS_SUCCESS) + status = internal_getpwent_r (pwd, &ext_ent, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + + +enum nss_status +_nss_compat_getpwnam_r (const char *name, struct passwd *pwd, + char *buffer, size_t buflen) +{ + ent_t ent = {0, 0, 0, NULL, 0, NULL, {NULL, 0, 0}, + {NULL, NULL, 0, 0, NULL, NULL, NULL}}; + enum nss_status status; + + if (name[0] == '-' || name[0] == '+') + return NSS_STATUS_NOTFOUND; + + + status = internal_setpwent (&ent); + if (status != NSS_STATUS_SUCCESS) + return status; + + while ((status = internal_getpwent_r (pwd, &ent, buffer, buflen)) + == NSS_STATUS_SUCCESS) + if (strcmp (pwd->pw_name, name) == 0) + break; + + internal_endpwent (&ent); + return status; +} + + +enum nss_status +_nss_compat_getpwuid_r (uid_t uid, struct passwd *pwd, + char *buffer, size_t buflen) +{ + ent_t ent = {0, 0, 0, NULL, 0, NULL, {NULL, 0, 0}, + {NULL, NULL, 0, 0, NULL, NULL, NULL}}; + enum nss_status status; + + status = internal_setpwent (&ent); + if (status != NSS_STATUS_SUCCESS) + return status; + + while ((status = internal_getpwent_r (pwd, &ent, buffer, buflen)) + == NSS_STATUS_SUCCESS) + if (pwd->pw_uid == uid && pwd->pw_name[0] != '+' && pwd->pw_name[0] != '-') + break; + + internal_endpwent (&ent); + return status; +} + + +/* Support routines for remembering -@netgroup and -user entries. + The names are stored in a single string with `|' as separator. */ +static void +blacklist_store_name (const char *name, ent_t *ent) +{ + int namelen = strlen (name); + char *tmp; + + /* first call, setup cache */ + if (ent->blacklist.size == 0) + { + ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); + ent->blacklist.data = malloc (ent->blacklist.size); + if (ent->blacklist.data == NULL) + return; + ent->blacklist.data[0] = '|'; + ent->blacklist.data[1] = '\0'; + ent->blacklist.current = 1; + } + else + { + if (in_blacklist (name, namelen, ent)) + return; /* no duplicates */ + + if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size) + { + ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen); + tmp = realloc (ent->blacklist.data, ent->blacklist.size); + if (tmp == NULL) + { + free (ent->blacklist.data); + ent->blacklist.size = 0; + return; + } + ent->blacklist.data = tmp; + } + } + + tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name); + *tmp++ = '|'; + *tmp = '\0'; + ent->blacklist.current += namelen + 1; + + return; +} + +/* returns TRUE if ent->blacklist contains name, else FALSE */ +static bool_t +in_blacklist (const char *name, int namelen, ent_t *ent) +{ + char buf[namelen + 3]; + + if (ent->blacklist.data == NULL) + return FALSE; + + stpcpy (stpcpy (stpcpy (buf, "|"), name), "|"); + return strstr (ent->blacklist.data, buf) != NULL; +} diff --git a/nis/nss_compat/compat-spwd.c b/nis/nss_compat/compat-spwd.c new file mode 100644 index 0000000000..ba73b1846f --- /dev/null +++ b/nis/nss_compat/compat-spwd.c @@ -0,0 +1,612 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <errno.h> +#include <ctype.h> +#include <netdb.h> +#include <shadow.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +/* Structure for remembering -@netgroup and -user members ... */ +#define BLACKLIST_INITIAL_SIZE 512 +#define BLACKLIST_INCREMENT 256 +struct blacklist_t + { + char *data; + int current; + int size; + }; + +struct ent_t + { + bool_t netgroup; + bool_t nis; + bool_t first; + char *oldkey; + int oldkeylen; + FILE *stream; + struct blacklist_t blacklist; + struct spwd pwd; + }; +typedef struct ent_t ent_t; + +static ent_t ext_ent = {0, 0, 0, NULL, 0, NULL, {NULL, 0, 0}, + {NULL, NULL, 0, 0, 0, 0, 0, 0, 0}}; + +/* Protect global state against multiple changers. */ +__libc_lock_define_initialized (static, lock) + +/* Prototypes for local functions. */ +static void blacklist_store_name (const char *, ent_t *); +static int in_blacklist (const char *, int, ent_t *); + +static void +give_spwd_free (struct spwd *pwd) +{ + if (pwd->sp_namp != NULL) + free (pwd->sp_namp); + if (pwd->sp_pwdp != NULL) + free (pwd->sp_pwdp); + + memset (pwd, '\0', sizeof (struct spwd)); +} + +static int +spwd_need_buflen (struct spwd *pwd) +{ + int len = 0; + + if (pwd->sp_pwdp != NULL) + len += strlen (pwd->sp_pwdp) + 1; + + return len; +} + +static void +copy_spwd_changes (struct spwd *dest, struct spwd *src, + char *buffer, size_t buflen) +{ + if (src->sp_pwdp != NULL && strlen (src->sp_pwdp)) + { + if (buffer == NULL) + dest->sp_pwdp = strdup (src->sp_pwdp); + else if (dest->sp_pwdp && + strlen (dest->sp_pwdp) >= strlen (src->sp_pwdp)) + strcpy (dest->sp_pwdp, src->sp_pwdp); + else + { + dest->sp_pwdp = buffer; + strcpy (dest->sp_pwdp, src->sp_pwdp); + buffer += strlen (dest->sp_pwdp) + 1; + buflen = buflen - (strlen (dest->sp_pwdp) + 1); + } + } + if (src->sp_lstchg != 0) + dest->sp_lstchg = src->sp_lstchg; + if (src->sp_min != 0) + dest->sp_min = src->sp_min; + if (src->sp_max != 0) + dest->sp_max = src->sp_max; + if (src->sp_warn != 0) + dest->sp_warn = src->sp_warn; + if (src->sp_inact != 0) + dest->sp_inact = src->sp_inact; + if (src->sp_expire != 0) + dest->sp_expire = src->sp_expire; + if (src->sp_flag != 0) + dest->sp_flag = src->sp_flag; +} + +static enum nss_status +internal_setspent (ent_t *ent) +{ + enum nss_status status = NSS_STATUS_SUCCESS; + + ent->nis = ent->first = ent->netgroup = 0; + + if (ent->oldkey != NULL) + { + free (ent->oldkey); + ent->oldkey = NULL; + ent->oldkeylen = 0; + } + + ent->blacklist.current = 0; + if (ent->blacklist.data != NULL) + ent->blacklist.data[0] = '\0'; + + if (ent->stream == NULL) + { + ent->stream = fopen ("/etc/shadow", "r"); + + if (ent->stream == NULL) + status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; + } + else + rewind (ent->stream); + + give_spwd_free (&ent->pwd); + + return status; +} + + +enum nss_status +_nss_compat_setspent (void) +{ + enum nss_status result; + + __libc_lock_lock (lock); + + result = internal_setspent (&ext_ent); + + __libc_lock_unlock (lock); + + return result; +} + + +static enum nss_status +internal_endspent (ent_t *ent) +{ + if (ent->stream != NULL) + { + fclose (ent->stream); + ent->stream = NULL; + } + + ent->nis = ent->first = ent->netgroup = 0; + + if (ent->oldkey != NULL) + { + free (ent->oldkey); + ent->oldkey = NULL; + ent->oldkeylen = 0; + } + + ent->blacklist.current = 0; + if (ent->blacklist.data != NULL) + ent->blacklist.data[0] = '\0'; + + give_spwd_free (&ent->pwd); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_compat_endspent (void) +{ + enum nss_status result; + + __libc_lock_lock (lock); + + result = internal_endspent (&ext_ent); + + __libc_lock_unlock (lock); + + return result; +} + + +static enum nss_status +getspent_next_netgr (struct spwd *result, ent_t *ent, char *group, + char *buffer, size_t buflen) +{ + char *ypdomain, *host, *user, *domain, *outval, *p, *p2; + int status, outvallen; + size_t p2len; + + 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) + { + setnetgrent (group); + ent->first = FALSE; + } + + while (1) + { + if ((status = getnetgrent (&host, &user, &domain)) != 1) + { + endnetgrent (); + 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; + + if (yp_match (ypdomain, "shadow.byname", user, + strlen (user), &outval, &outvallen) + != YPERR_SUCCESS) + continue; + + p2len = spwd_need_buflen (&ent->pwd); + if (p2len > buflen) + { + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + p2 = buffer + (buflen - p2len); + buflen -= p2len; + p = strncpy (buffer, outval, buflen); + while (isspace (*p)) + p++; + free (outval); + if (_nss_files_parse_spent (p, result, buffer, buflen)) + { + copy_spwd_changes (result, &ent->pwd, p2, p2len); + break; + } + } + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +getspent_next_nis (struct spwd *result, ent_t *ent, + char *buffer, size_t buflen) +{ + char *domain, *outkey, *outval, *p, *p2; + int outkeylen, outvallen; + size_t p2len; + + if (yp_get_default_domain (&domain) != YPERR_SUCCESS) + { + ent->nis = 0; + give_spwd_free (&ent->pwd); + return NSS_STATUS_UNAVAIL; + } + + p2len = spwd_need_buflen (&ent->pwd); + if (p2len > buflen) + { + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + p2 = buffer + (buflen - p2len); + buflen -= p2len; + do + { + 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; + } + + 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; + } + + free (ent->oldkey); + 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; + } + while (!_nss_files_parse_spent (p, result, buffer, buflen)); + + copy_spwd_changes (result, &ent->pwd, p2, p2len); + + if (!in_blacklist (result->sp_namp, strlen (result->sp_namp), ent)) + return NSS_STATUS_SUCCESS; + else + return NSS_STATUS_NOTFOUND; +} + + +static enum nss_status +getspent_next_file (struct spwd *result, ent_t *ent, + char *buffer, size_t buflen) +{ + while (1) + { + char *p, *p2; + size_t p2len; + + do + { + p = fgets (buffer, buflen, ent->stream); + if (p == NULL) + return NSS_STATUS_NOTFOUND; + + /* Terminate the line for any case. */ + buffer[buflen - 1] = '\0'; + + /* Skip leading blanks. */ + while (isspace (*p)) + ++p; + } + while (*p == '\0' || *p == '#' || /* Ignore empty and comment lines. */ + /* Parse the line. If it is invalid, loop to + get the next line of the file to parse. */ + !_nss_files_parse_spent (p, result, buffer, buflen)); + + if (result->sp_namp[0] != '+' && result->sp_namp[0] != '-') + /* This is a real entry. */ + break; + + /* -@netgroup */ + if (result->sp_namp[0] == '-' && result->sp_namp[1] == '@' + && result->sp_namp[2] != '\0') + { + char *user, *host, *domain; + + setnetgrent (&result->sp_namp[2]); + while (getnetgrent (&host, &user, &domain)) + { + if (user != NULL && user[0] != '-') + blacklist_store_name (user, ent); + } + endnetgrent (); + continue; + } + + /* +@netgroup */ + if (result->sp_namp[0] == '+' && result->sp_namp[1] == '@' + && result->sp_namp[2] != '\0') + { + int status; + + ent->netgroup = TRUE; + ent->first = TRUE; + copy_spwd_changes (&ent->pwd, result, NULL, 0); + + status = getspent_next_netgr (result, ent, &result->sp_namp[2], + buffer, buflen); + if (status == NSS_STATUS_RETURN) + continue; + else + return status; + } + + /* -user */ + if (result->sp_namp[0] == '-' && result->sp_namp[1] != '\0' + && result->sp_namp[1] != '@') + { + blacklist_store_name (&result->sp_namp[1], ent); + continue; + } + + /* +user */ + if (result->sp_namp[0] == '+' && result->sp_namp[1] != '\0' + && result->sp_namp[1] != '@') + { + char *domain; + char *outval; + int outvallen; + struct spwd pwd; + + memset (&pwd, '\0', sizeof (struct spwd)); + + if (yp_get_default_domain (&domain) != YPERR_SUCCESS) + /* XXX Should we regard this as an fatal error? I don't + think so. Just continue working. --drepper@gnu */ + continue; + + if (yp_match (domain, "shadow.byname", &result->sp_namp[1], + strlen (result->sp_namp) - 1, &outval, &outvallen) + != YPERR_SUCCESS) + continue; + + copy_spwd_changes (&pwd, result, NULL, 0); + + p2len = spwd_need_buflen (&pwd); + if (p2len > buflen) + { + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + p2 = buffer + (buflen - p2len); + buflen -= p2len; + p = strncpy (buffer, outval, buflen); + while (isspace (*p)) + p++; + free (outval); + if (_nss_files_parse_spent (p, result, buffer, buflen)) + { + copy_spwd_changes (result, &pwd, p2, p2len); + give_spwd_free (&pwd); + /* We found the entry. */ + break; + } + else + { + /* Give buffer the old len back */ + buflen += p2len; + give_spwd_free (&pwd); + } + } + + /* +:... */ + if (result->sp_namp[0] == '+' && result->sp_namp[1] == '\0') + { + ent->nis = TRUE; + ent->first = TRUE; + copy_spwd_changes (&ent->pwd, result, NULL, 0); + + return getspent_next_nis (result, ent, buffer, buflen); + } + } + + return NSS_STATUS_SUCCESS; +} + + +static enum nss_status +internal_getspent_r (struct spwd *pw, ent_t *ent, + char *buffer, size_t buflen) +{ + if (ent->netgroup) + { + int status; + + /* We are searching members in a netgroup */ + /* Since this is not the first call, we don't need the group name */ + status = getspent_next_netgr (pw, ent, NULL, buffer, buflen); + if (status == NSS_STATUS_RETURN) + return getspent_next_file (pw, ent, buffer, buflen); + else + return status; + } + else if (ent->nis) + return getspent_next_nis (pw, ent, buffer, buflen); + else + return getspent_next_file (pw, ent, buffer, buflen); +} + +enum nss_status +_nss_compat_getspent_r (struct spwd *pwd, char *buffer, size_t buflen) +{ + enum nss_status status = NSS_STATUS_SUCCESS; + + __libc_lock_lock (lock); + + /* Be prepared that the setspent function was not called before. */ + if (ext_ent.stream == NULL) + status = internal_setspent (&ext_ent); + + if (status == NSS_STATUS_SUCCESS) + status = internal_getspent_r (pwd, &ext_ent, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + + +enum nss_status +_nss_compat_getspnam_r (const char *name, struct spwd *pwd, + char *buffer, size_t buflen) +{ + ent_t ent = {0, 0, 0, NULL, 0, NULL, {NULL, 0, 0}, + {NULL, NULL, 0, 0, 0, 0, 0, 0, 0}}; + enum nss_status status; + + if (name[0] == '-' || name[0] == '+') + return NSS_STATUS_NOTFOUND; + + status = internal_setspent (&ent); + if (status != NSS_STATUS_SUCCESS) + return status; + + while ((status = internal_getspent_r (pwd, &ent, buffer, buflen)) + == NSS_STATUS_SUCCESS) + if (strcmp (pwd->sp_namp, name) == 0) + break; + + internal_endspent (&ent); + return status; +} + +/* Support routines for remembering -@netgroup and -user entries. + The names are stored in a single string with `|' as separator. */ +static void +blacklist_store_name (const char *name, ent_t *ent) +{ + int namelen = strlen (name); + char *tmp; + + /* first call, setup cache */ + if (ent->blacklist.size == 0) + { + ent->blacklist.size = MAX (BLACKLIST_INITIAL_SIZE, 2 * namelen); + ent->blacklist.data = malloc (ent->blacklist.size); + if (ent->blacklist.data == NULL) + return; + ent->blacklist.data[0] = '|'; + ent->blacklist.data[1] = '\0'; + ent->blacklist.current = 1; + } + else + { + if (in_blacklist (name, namelen, ent)) + return; /* no duplicates */ + + if (ent->blacklist.current + namelen + 1 >= ent->blacklist.size) + { + ent->blacklist.size += MAX (BLACKLIST_INCREMENT, 2 * namelen); + tmp = realloc (ent->blacklist.data, ent->blacklist.size); + if (tmp == NULL) + { + free (ent->blacklist.data); + ent->blacklist.size = 0; + return; + } + ent->blacklist.data = tmp; + } + } + + tmp = stpcpy (ent->blacklist.data + ent->blacklist.current, name); + *tmp++ = '|'; + *tmp = '\0'; + ent->blacklist.current += namelen + 1; + + return; +} + +/* returns TRUE if ent->blacklist contains name, else FALSE */ +static bool_t +in_blacklist (const char *name, int namelen, ent_t *ent) +{ + char buf[namelen + 3]; + + if (ent->blacklist.data == NULL) + return FALSE; + + stpcpy (stpcpy (stpcpy (buf, "|"), name), "|"); + return strstr (ent->blacklist.data, buf) != NULL; +} diff --git a/nis/nss_nis/nis-alias.c b/nis/nss_nis/nis-alias.c new file mode 100644 index 0000000000..af83d9cd7c --- /dev/null +++ b/nis/nss_nis/nis-alias.c @@ -0,0 +1,269 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <aliases.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +#include "nss-nis.h" + +__libc_lock_define_initialized (static, lock) + +static bool_t new_start = 1; +static char *oldkey = NULL; +static int oldkeylen = 0; + +static int +_nss_nis_parse_aliasent (char *key, char *alias, struct aliasent *result, + char *buffer, size_t buflen) +{ + char *first_unused = buffer + strlen (alias) + 1; + size_t room_left = + buflen - (buflen % __alignof__ (char *)) - strlen (alias) - 2; + char *line; + char *cp; + + result->alias_members_len = 0; + *first_unused = '\0'; + first_unused++; + strcpy (first_unused, key); + + if (first_unused[room_left - 1] != '\0') + { + /* The line is too long for our buffer. */ + no_more_room: + __set_errno (ERANGE); + return -1; + } + + result->alias_name = first_unused; + + /* Terminate the line for any case. */ + cp = strpbrk (alias, "#\n"); + if (cp != NULL) + *cp = '\0'; + + first_unused += strlen (result->alias_name) + 1; + /* Adjust the pointer so it is aligned for + storing pointers. */ + first_unused += __alignof__ (char *) - 1; + first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *)); + result->alias_members = (char **) first_unused; + + line = alias; + + while (*line != '\0') + { + /* Skip leading blanks. */ + while (isspace (*line)) + line++; + + if (*line == '\0') + break; + + if (room_left < sizeof (char *)) + goto no_more_room; + room_left -= sizeof (char *); + result->alias_members[result->alias_members_len] = line; + + while (*line != '\0' && *line != ',') + line++; + + if (line != result->alias_members[result->alias_members_len]) + { + *line = '\0'; + line++; + result->alias_members_len++; + } + } + return result->alias_members_len == 0 ? 0 : 1; +} + +enum nss_status +_nss_nis_setaliasent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_endaliasent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nis_getaliasent_r (struct aliasent *alias, char *buffer, + size_t buflen) +{ + char *domain; + char *result; + int len; + char *outkey; + int keylen; + char *p; + int parse_res; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + alias->alias_local = 0; + + /* Get the next entry until we found a correct one. */ + do + { + enum nss_status retval; + + if (new_start) + retval = yperr2nss (yp_first (domain, "mail.aliases", + &outkey, &keylen, &result, &len)); + else + retval = yperr2nss ( yp_next (domain, "mail.aliases", oldkey, + oldkeylen, &outkey, &keylen, + &result, &len)); + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_nis_parse_aliasent (outkey, p, alias, buffer, buflen); + if (parse_res == -1) + { + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + free (oldkey); + oldkey = outkey; + oldkeylen = keylen; + new_start = 0; + } + while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getaliasent_r (struct aliasent *alias, char *buffer, size_t buflen) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_nis_getaliasent_r (alias, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nis_getaliasbyname_r (const char *name, struct aliasent *alias, + char *buffer, size_t buflen) +{ + enum nss_status retval; + int parse_res; + char *domain; + char *result; + int len; + char *p; + + if (name == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + retval = yperr2nss (yp_match (domain, "mail.aliases", name, strlen (name), + &result, &len)); + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + alias->alias_local = 0; + parse_res = _nss_nis_parse_aliasent (name, p, alias, buffer, buflen); + if (parse_res == -1) + return NSS_STATUS_TRYAGAIN; + else + if (parse_res == 0) + return NSS_STATUS_NOTFOUND; + else + return NSS_STATUS_SUCCESS; +} diff --git a/nis/nss_nis/nis-ethers.c b/nis/nss_nis/nis-ethers.c new file mode 100644 index 0000000000..26449720bb --- /dev/null +++ b/nis/nss_nis/nis-ethers.c @@ -0,0 +1,264 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> +#include <netinet/if_ether.h> + +#include "nss-nis.h" + +/* Protect global state against multiple changers */ +__libc_lock_define_initialized (static, lock) + +struct ether +{ + char *e_name; + struct ether_addr e_addr; +}; + +static bool_t new_start = 1; +static char *oldkey = NULL; +static int oldkeylen = 0; + +enum nss_status +_nss_nis_setetherent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_endetherent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nis_getetherent_r (struct ether *eth, char *buffer, size_t buflen) +{ + char *domain, *result, *outkey; + int len, keylen, parse_res; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + /* Get the next entry until we found a correct one. */ + do + { + enum nss_status retval; + char *p; + + if (new_start) + retval = yperr2nss (yp_first (domain, "ethers.byaddr", + &outkey, &keylen, &result, &len)); + else + retval = yperr2nss ( yp_next (domain, "ethers.byaddr", + oldkey, oldkeylen, + &outkey, &keylen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_etherent (p, eth, buffer, buflen); + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + + free (oldkey); + oldkey = outkey; + oldkeylen = keylen; + new_start = 0; + } + while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getetherent_r (struct ether *result, char *buffer, size_t buflen) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nis_getetherent_r (result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nis_getethernam_r (const char *name, struct ether *eth, + char *buffer, size_t buflen) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, parse_res; + + if (name == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + retval = yperr2nss (yp_match (domain, "ethers.byname", name, + strlen (name), &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_etherent (p, eth, buffer, buflen); + + if (!parse_res) + { + if (errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } + else + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getetherbyaddr_r (struct ether_addr *addr, struct ether *eth, + char *buffer, size_t buflen) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, nlen, parse_res; + char buf[33]; + + if (addr == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + nlen = sprintf (buf, "%x:%x:%x:%x:%x:%x", + (int) addr->ether_addr_octet[0], + (int) addr->ether_addr_octet[1], + (int) addr->ether_addr_octet[2], + (int) addr->ether_addr_octet[3], + (int) addr->ether_addr_octet[4], + (int) addr->ether_addr_octet[5]); + + retval = yperr2nss (yp_match (domain, "ethers.byaddr", buf, + nlen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_etherent (p, eth, buffer, buflen); + + if (!parse_res) + { + if (errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } + else + return NSS_STATUS_SUCCESS; +} diff --git a/nis/nss_nis/nis-grp.c b/nis/nss_nis/nis-grp.c new file mode 100644 index 0000000000..1bab862c2f --- /dev/null +++ b/nis/nss_nis/nis-grp.c @@ -0,0 +1,246 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <grp.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +#include "nss-nis.h" + +/* Protect global state against multiple changers */ +__libc_lock_define_initialized (static, lock) + +static bool_t new_start = 1; +static char *oldkey = NULL; +static int oldkeylen = 0; + +enum nss_status +_nss_nis_setgrent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_endgrent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nis_getgrent_r (struct group *grp, char *buffer, size_t buflen) +{ + char *domain, *result, *outkey; + int len, keylen, parse_res; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + /* Get the next entry until we found a correct one. */ + do + { + enum nss_status retval; + char *p; + + if (new_start) + retval = yperr2nss (yp_first (domain, "group.byname", + &outkey, &keylen, &result, &len)); + else + retval = yperr2nss ( yp_next (domain, "group.byname", + oldkey, oldkeylen, + &outkey, &keylen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_grent (p, grp, buffer, buflen); + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + + free (oldkey); + oldkey = outkey; + oldkeylen = keylen; + new_start = 0; + } + while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getgrent_r (struct group *result, char *buffer, size_t buflen) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nis_getgrent_r (result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nis_getgrnam_r (const char *name, struct group *grp, + char *buffer, size_t buflen) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, parse_res; + + if (name == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + retval = yperr2nss (yp_match (domain, "group.byname", name, + strlen (name), &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_grent (p, grp, buffer, buflen); + + if (!parse_res) + { + if (errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } + else + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getgrgid_r (gid_t gid, struct group *grp, + char *buffer, size_t buflen) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, nlen, parse_res; + char buf[32]; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + nlen = sprintf (buf, "%d", gid); + + retval = yperr2nss (yp_match (domain, "group.bygid", buf, + nlen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_grent (p, grp, buffer, buflen); + + if (!parse_res) + { + if (errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } + else + return NSS_STATUS_SUCCESS; +} diff --git a/nis/nss_nis/nis-hosts.c b/nis/nss_nis/nis-hosts.c new file mode 100644 index 0000000000..9adce18ca3 --- /dev/null +++ b/nis/nss_nis/nis-hosts.c @@ -0,0 +1,389 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <ctype.h> +#include <netdb.h> +#include <string.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <resolv.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +#include "nss-nis.h" + +/* Get implementation for some internal functions. */ +#include "../../resolv/mapv4v6addr.h" +#include "../../resolv/mapv4v6hostent.h" + +#define ENTNAME hostent +#define DATABASE "hosts" +#define NEED_H_ERRNO + +#define ENTDATA hostent_data +struct hostent_data + { + unsigned char host_addr[16]; /* IPv4 or IPv6 address. */ + char *h_addr_ptrs[2]; /* Points to that and null terminator. */ + }; + +#define TRAILING_LIST_MEMBER h_aliases +#define TRAILING_LIST_SEPARATOR_P isspace +#include "../../nss/nss_files/files-parse.c" +LINE_PARSER +("#", + { + char *addr; + + STRING_FIELD (addr, isspace, 1); + + /* Parse address. */ + if ((_res.options & RES_USE_INET6) + && inet_pton (AF_INET6, addr, entdata->host_addr) > 0) + { + result->h_addrtype = AF_INET6; + result->h_length = IN6ADDRSZ; + } + else + if (inet_pton (AF_INET, addr, entdata->host_addr) > 0) + { + if (_res.options & RES_USE_INET6) + { + map_v4v6_address ((char *) entdata->host_addr, + (char *) entdata->host_addr); + result->h_addrtype = AF_INET6; + result->h_length = IN6ADDRSZ; + } + else + { + result->h_addrtype = AF_INET; + result->h_length = INADDRSZ; + } + } + else + /* Illegal address: ignore line. */ + return 0; + + /* Store a pointer to the address in the expected form. */ + entdata->h_addr_ptrs[0] = entdata->host_addr; + entdata->h_addr_ptrs[1] = NULL; + result->h_addr_list = entdata->h_addr_ptrs; + + /* If we need the host entry in IPv6 form change it now. */ + if (_res.options & RES_USE_INET6) + { + char *bufptr = data->linebuffer; + size_t buflen = (char *) data + datalen - bufptr; + map_v4v6_hostent (result, &bufptr, &buflen); + } + + STRING_FIELD (result->h_name, isspace, 1); + } +) + +__libc_lock_define_initialized (static, lock) + +static bool_t new_start = 1; +static char *oldkey = NULL; +static int oldkeylen = 0; + +enum nss_status +_nss_nis_sethostent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_endhostent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nis_gethostent_r (struct hostent *host, char *buffer, + size_t buflen, int *h_errnop) +{ + char *domain; + char *result; + int len, parse_res; + char *outkey; + int keylen; + struct parser_data *data = (void *) buffer; + size_t linebuflen = buffer + buflen - data->linebuffer; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + if (buflen < sizeof *data + 1) + { + __set_errno (ERANGE); + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + /* Get the next entry until we found a correct one. */ + do + { + enum nss_status retval; + char *p; + + if (new_start) + retval = yperr2nss (yp_first (domain, "hosts.byname", + &outkey, &keylen, &result, &len)); + else + retval = yperr2nss ( yp_next (domain, "hosts.byname", + oldkey, oldkeylen, + &outkey, &keylen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + switch (retval) + { + case NSS_STATUS_TRYAGAIN: + __set_errno (EAGAIN); + *h_errnop = TRY_AGAIN; + break; + case NSS_STATUS_NOTFOUND: + *h_errnop = HOST_NOT_FOUND; + break; + default: + *h_errnop = NO_RECOVERY; + break; + } + return retval; + } + + if (len + 1 > linebuflen) + { + free (result); + *h_errnop = NETDB_INTERNAL; + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (data->linebuffer, result, len); + data->linebuffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = parse_line (p, host, data, buflen); + if (!parse_res && errno == ERANGE) + { + *h_errnop = NETDB_INTERNAL;; + return NSS_STATUS_TRYAGAIN; + } + free (oldkey); + oldkey = outkey; + oldkeylen = keylen; + new_start = 0; + } + while (!parse_res); + + *h_errnop = NETDB_SUCCESS; + return NSS_STATUS_SUCCESS; +} + +int +_nss_nis_gethostent_r (struct hostent *host, char *buffer, size_t buflen, + int *h_errnop) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nis_gethostent_r (host, buffer, buflen, h_errnop); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nis_gethostbyname_r (const char *name, struct hostent *host, + char *buffer, size_t buflen, int *h_errnop) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, parse_res; + struct parser_data *data = (void *) buffer; + size_t linebuflen = buffer + buflen - data->linebuffer; + + if (name == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + if (buflen < sizeof *data + 1) + { + *h_errnop = NETDB_INTERNAL; + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + retval = yperr2nss (yp_match (domain, "hosts.byname", name, + strlen (name), &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + { + *h_errnop = TRY_AGAIN; + __set_errno (EAGAIN); + } + if (retval == NSS_STATUS_NOTFOUND) + *h_errnop = HOST_NOT_FOUND; + return retval; + } + + if (len + 1 > linebuflen) + { + free (result); + *h_errnop = NETDB_INTERNAL; + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (data->linebuffer, result, len); + data->linebuffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = parse_line (p, host, data, buflen); + + if (!parse_res) + { + if (errno == ERANGE) + { + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + else + { + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } + } + + *h_errnop = NETDB_SUCCESS; + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_gethostbyaddr_r (char *addr, int addrlen, int type, + struct hostent *host, char *buffer, size_t buflen, + int *h_errnop) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, parse_res; + char *buf; + struct parser_data *data = (void *) buffer; + size_t linebuflen = buffer + buflen - data->linebuffer; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + if (buflen < sizeof *data + 1) + { + __set_errno (ERANGE); + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + buf = inet_ntoa (*(struct in_addr *) addr); + + retval = yperr2nss (yp_match (domain, "hosts.byaddr", buf, + strlen (buf), &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + { + *h_errnop = TRY_AGAIN; + __set_errno (EAGAIN); + } + if (retval == NSS_STATUS_NOTFOUND) + *h_errnop = HOST_NOT_FOUND; + return retval; + } + + if (len + 1 > linebuflen) + { + free (result); + __set_errno (ERANGE); + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (data->linebuffer, result, len); + data->linebuffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = parse_line (p, host, data, buflen); + + if (!parse_res) + { + if (errno == ERANGE) + { + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + else + { + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } + } + + *h_errnop = NETDB_SUCCESS; + return NSS_STATUS_SUCCESS; +} diff --git a/nis/nss_nis/nis-netgrp.c b/nis/nss_nis/nis-netgrp.c new file mode 100644 index 0000000000..7609ea08ed --- /dev/null +++ b/nis/nss_nis/nis-netgrp.c @@ -0,0 +1,128 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <ctype.h> +#include <errno.h> +#include <libc-lock.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <netgroup.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +#include "nss-nis.h" + +/* Locks the static variables in this file. */ +__libc_lock_define_initialized (static, lock) + +static char *data = NULL; +static size_t data_size = 0; +static char *cursor = NULL;; + +extern enum nss_status +_nss_netgroup_parseline (char **cursor, struct __netgrent *result, + char *buffer, size_t buflen); + +enum nss_status +_nss_nis_setnetgrent (char *group) +{ + char *domain; + char *result; + int len, group_len; + enum nss_status status; + + status = NSS_STATUS_SUCCESS; + + if (group[0] == '\0') + return NSS_STATUS_UNAVAIL; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + __libc_lock_lock (lock); + + if (data != NULL) + { + free (data); + data = NULL; + data_size = 0; + cursor = NULL; + } + + group_len = strlen (group); + + status = yperr2nss (yp_match (domain, "netgroup", group, group_len, + &result, &len)); + if (status == NSS_STATUS_SUCCESS) + { + if (len > 0) + { + data = malloc (len + 1); + data_size = len; + cursor = strncpy (data, result, len + 1); + data[len] = '\0'; + free (result); + } + else + status = NSS_STATUS_NOTFOUND; + } + + __libc_lock_unlock (lock); + + return status; +} + + +enum nss_status +_nss_nis_endnetgrent (void) +{ + __libc_lock_lock (lock); + + if (data != NULL) + { + free (data); + data = NULL; + data_size = 0; + cursor = NULL; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getnetgrent_r (struct __netgrent *result, char *buffer, size_t buflen) +{ + enum nss_status status; + + if (cursor == NULL) + return NSS_STATUS_NOTFOUND; + + __libc_lock_lock (lock); + + status = _nss_netgroup_parseline (&cursor, result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} diff --git a/nis/nss_nis/nis-network.c b/nis/nss_nis/nis-network.c new file mode 100644 index 0000000000..2795feb421 --- /dev/null +++ b/nis/nss_nis/nis-network.c @@ -0,0 +1,292 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <netdb.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +#include "nss-nis.h" + +__libc_lock_define_initialized (static, lock) + +static bool_t new_start = 1; +static char *oldkey = NULL; +static int oldkeylen = 0; + +enum nss_status +_nss_nis_setnetent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_endnetent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nis_getnetent_r (struct netent *net, char *buffer, size_t buflen, + int *herrnop) +{ + char *domain, *result, *outkey; + int len, keylen, parse_res; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + /* Get the next entry until we found a correct one. */ + do + { + enum nss_status retval; + char *p; + + if (new_start) + retval = yperr2nss (yp_first (domain, "networks.byname", + &outkey, &keylen, &result, &len)); + else + retval = yperr2nss ( yp_next (domain, "networks.byname", + oldkey, oldkeylen, + &outkey, &keylen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + { + *herrnop = NETDB_INTERNAL; + __set_errno (EAGAIN); + } + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_netent (p, net, buffer, buflen); + if (!parse_res && errno == ERANGE) + { + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + free (oldkey); + oldkey = outkey; + oldkeylen = keylen; + new_start = 0; + } + while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getnetent_r (struct netent *net, char *buffer, size_t buflen, + int *herrnop) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_nis_getnetent_r (net, buffer, buflen, herrnop); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nis_getnetbyname_r (const char *name, struct netent *net, + char *buffer, size_t buflen, int *herrnop) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, parse_res; + + if (name == NULL) + { + __set_errno (EINVAL); + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + retval = yperr2nss (yp_match (domain, "networks.byname", name, + strlen (name), &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + { + __set_errno (EAGAIN); + *herrnop = NETDB_INTERNAL; + } + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_netent (p, net, buffer, buflen); + + if (!parse_res) + { + *herrnop = NETDB_INTERNAL; + if (errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } + else + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getnetbyaddr_r (unsigned long addr, int type, struct netent *net, + char *buffer, size_t buflen, int *herrnop) +{ + char *domain; + char *result; + int len; + char buf[256]; + int blen; + struct in_addr in; + char *p; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + in = inet_makeaddr (addr, 0); + strcpy (buf, inet_ntoa (in)); + blen = strlen (buf); + + while (1) + { + enum nss_status retval; + int parse_res; + + retval = yperr2nss (yp_match (domain, "networks.byaddr", buf, + strlen (buf), &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_NOTFOUND) + { + if (buf[blen - 2] == '.' && buf[blen - 1] == '0') + { + /* Try again, but with trailing dot(s) + removed (one by one) */ + buf[blen - 2] = '\0'; + blen -= 2; + continue; + } + else + return NSS_STATUS_NOTFOUND; + } + else + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_netent (p, net, buffer, buflen); + + + if (!parse_res) + { + *herrnop = NETDB_INTERNAL; + if (errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } + else + return NSS_STATUS_SUCCESS; + } +} diff --git a/nis/nss_nis/nis-proto.c b/nis/nss_nis/nis-proto.c new file mode 100644 index 0000000000..f62dfb1492 --- /dev/null +++ b/nis/nss_nis/nis-proto.c @@ -0,0 +1,246 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <netdb.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +#include "nss-nis.h" + +__libc_lock_define_initialized (static, lock) + +static bool_t new_start = 1; +static char *oldkey = NULL; +static int oldkeylen = 0; + +enum nss_status +_nss_nis_setprotoent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_endprotoent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nis_getprotoent_r (struct protoent *proto, + char *buffer, size_t buflen) +{ + char *domain, *result, *outkey; + int len, keylen, parse_res; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + /* Get the next entry until we found a correct one. */ + do + { + enum nss_status retval; + char *p; + + if (new_start) + retval = yperr2nss (yp_first (domain, "protocols.bynumber", + &outkey, &keylen, &result, &len)); + else + retval = yperr2nss ( yp_next (domain, "protocols.bynumber", + oldkey, oldkeylen, + &outkey, &keylen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_protoent (p, proto, buffer, buflen); + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + + free (oldkey); + oldkey = outkey; + oldkeylen = keylen; + new_start = 0; + } + while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getprotoent_r (struct protoent *proto, char *buffer, size_t buflen) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_nis_getprotoent_r (proto, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nis_getprotobyname_r (const char *name, struct protoent *proto, + char *buffer, size_t buflen) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, parse_res; + + if (name == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + retval = yperr2nss (yp_match (domain, "protocols.byname", name, + strlen (name), &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_protoent (p, proto, buffer, buflen); + + if (!parse_res) + { + if (errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } + else + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getprotobynumber_r (int number, struct protoent *proto, + char *buffer, size_t buflen) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, nlen, parse_res; + char buf[32]; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + nlen = sprintf (buf, "%d", number); + + retval = yperr2nss (yp_match (domain, "protocols.bynumber", buf, + nlen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_protoent (p, proto, buffer, buflen); + + if (!parse_res) + { + if (errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } + else + return NSS_STATUS_SUCCESS; +} diff --git a/nis/nss_nis/nis-publickey.c b/nis/nss_nis/nis-publickey.c new file mode 100644 index 0000000000..b9eda6a742 --- /dev/null +++ b/nis/nss_nis/nis-publickey.c @@ -0,0 +1,220 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <syslog.h> +#include <libc-lock.h> +#include <rpc/key_prot.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +#include "nss-nis.h" + +extern int xdecrypt (char *, char *); + +/* If we found the entry, we give a SUCCESS and an empty key back. */ +enum nss_status +_nss_nis_getpublickey (const char *netname, char *pkey) +{ + enum nss_status retval; + char *domain, *result; + int len; + + pkey[0] = 0; + + if (netname == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + domain = strchr (netname, '@'); + if (!domain) + return NSS_STATUS_UNAVAIL; + domain++; + + retval = yperr2nss (yp_match (domain, "publickey.byname", netname, + strlen (netname), &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (result != NULL) + { + char *p = strchr (result, ':'); + if (p != NULL) + *p = 0; + strcpy (pkey, result); + } + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getsecretkey (const char *netname, char *skey, char *passwd) +{ + enum nss_status retval; + char buf[1024]; + char *domain, *result; + int len; + + skey[0] = 0; + + if (netname == NULL || passwd == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + domain = strchr (netname, '@'); + if (!domain) + return NSS_STATUS_UNAVAIL; + domain++; + + retval = yperr2nss (yp_match (domain, "publickey.byname", netname, + strlen (netname), &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (result != NULL) + { + char *p = strchr (result, ':'); + if (p == NULL) + return NSS_STATUS_SUCCESS; + + p++; + strcpy (buf, p); + if (!xdecrypt (buf, passwd)) + return NSS_STATUS_SUCCESS; + + if (memcmp (buf, &(buf[HEXKEYBYTES]), KEYCHECKSUMSIZE) != 0) + return NSS_STATUS_SUCCESS; + + buf[HEXKEYBYTES] = 0; + strcpy (skey, buf); + } + return NSS_STATUS_SUCCESS; +} + +/* Parse uid and group information from the passed string. + The format of the string passed is uid:gid,grp,grp, ... */ +static enum nss_status +parse_netid_str (const char *s, uid_t *uidp, gid_t *gidp, int *gidlenp, + gid_t *gidlist) +{ + char *p; + + if (!s || !isdigit (*s)) + { + syslog (LOG_ERR, "netname2user: expecting uid '%s'", s); + return NSS_STATUS_NOTFOUND; /* XXX need a better error */ + } + + /* Fetch the uid */ + *uidp = (atoi (s)); + + if (*uidp == 0) + { + syslog (LOG_ERR, "netname2user: should not have uid 0"); + return NSS_STATUS_NOTFOUND; + } + + /* Now get the group list */ + p = strchr (s, ':'); + if (!p) + { + syslog (LOG_ERR, "netname2user: missing group id list in '%s'", s); + return NSS_STATUS_NOTFOUND; + } + ++p; /* skip ':' */ + if (!p || (!isdigit (*p))) + { + syslog (LOG_ERR, "netname2user: missing group id list in '%s'.", p); + return NSS_STATUS_NOTFOUND; + } + + *gidp = (atoi (p)); + + *gidlenp = 0; +#if 0 + while ((p = strchr (p, ',')) != NULL) + { + p++; + gidlist[*gidlenp++] = atoi (p); + } +#endif + + return NSS_STATUS_SUCCESS; +} + + +enum nss_status +_nss_nis_netname2user (char netname[MAXNETNAMELEN + 1], uid_t *uidp, + gid_t *gidp, int *gidlenp, gid_t *gidlist) +{ + char *domain; + int yperr; + char *lookup; + int len; + + domain = strchr (netname, '@'); + if (!domain) + return NSS_STATUS_UNAVAIL; + + /* Point past the '@' character */ + domain++; + lookup = NULL; + yperr = yp_match (domain, "netid.byname", netname, strlen (netname), + &lookup, &len); + switch (yperr) + { + case YPERR_SUCCESS: + break; /* the successful case */ + case YPERR_DOMAIN: + case YPERR_KEY: + return NSS_STATUS_NOTFOUND; + case YPERR_MAP: + default: + return NSS_STATUS_UNAVAIL; + } + if (lookup) + { + enum nss_status err; + + lookup[len] = '\0'; + err = parse_netid_str (lookup, uidp, gidp, gidlenp, gidlist); + free (lookup); + return err; + } + else + return NSS_STATUS_NOTFOUND; + + return NSS_STATUS_SUCCESS; +} diff --git a/nis/nss_nis/nis-pwd.c b/nis/nss_nis/nis-pwd.c new file mode 100644 index 0000000000..afcc7a428e --- /dev/null +++ b/nis/nss_nis/nis-pwd.c @@ -0,0 +1,246 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <pwd.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +#include "nss-nis.h" + +/* Protect global state against multiple changers */ +__libc_lock_define_initialized (static, lock) + +static bool_t new_start = 1; +static char *oldkey = NULL; +static int oldkeylen = 0; + +enum nss_status +_nss_nis_setpwent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_endpwent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nis_getpwent_r (struct passwd *pwd, char *buffer, size_t buflen) +{ + char *domain, *result, *outkey; + int len, keylen, parse_res; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + /* Get the next entry until we found a correct one. */ + do + { + enum nss_status retval; + char *p; + + if (new_start) + retval = yperr2nss (yp_first (domain, "passwd.byname", + &outkey, &keylen, &result, &len)); + else + retval = yperr2nss ( yp_next (domain, "passwd.byname", + oldkey, oldkeylen, + &outkey, &keylen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_pwent (p, pwd, buffer, buflen); + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + + free (oldkey); + oldkey = outkey; + oldkeylen = keylen; + new_start = 0; + } + while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getpwent_r (struct passwd *result, char *buffer, size_t buflen) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nis_getpwent_r (result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nis_getpwnam_r (const char *name, struct passwd *pwd, + char *buffer, size_t buflen) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, parse_res; + + if (name == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + retval = yperr2nss (yp_match (domain, "passwd.byname", name, + strlen (name), &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_pwent (p, pwd, buffer, buflen); + + if (!parse_res) + { + if (errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } + else + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getpwuid_r (uid_t uid, struct passwd *pwd, + char *buffer, size_t buflen) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, nlen, parse_res; + char buf[32]; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + nlen = sprintf (buf, "%d", uid); + + retval = yperr2nss (yp_match (domain, "passwd.byuid", buf, + nlen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_pwent (p, pwd, buffer, buflen); + + if (!parse_res) + { + if (errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } + else + return NSS_STATUS_SUCCESS; +} diff --git a/nis/nss_nis/nis-rpc.c b/nis/nss_nis/nis-rpc.c new file mode 100644 index 0000000000..91f54be3a9 --- /dev/null +++ b/nis/nss_nis/nis-rpc.c @@ -0,0 +1,270 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <netdb.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +#include "nss-nis.h" + +__libc_lock_define_initialized (static, lock) + +struct intern_t +{ + bool_t new_start; + char *oldkey; + int oldkeylen; +}; +typedef struct intern_t intern_t; + +static intern_t intern = {TRUE, NULL, 0}; + +static enum nss_status +internal_nis_setrpcent (intern_t *data) +{ + data->new_start = 1; + if (data->oldkey != NULL) + { + free (data->oldkey); + data->oldkey = NULL; + data->oldkeylen = 0; + } + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_setrpcent (void) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_nis_setrpcent (&intern); + + __libc_lock_unlock (lock); + + return status; +} + +static enum nss_status +internal_nis_endrpcent (intern_t *data) +{ + data->new_start = 1; + if (data->oldkey != NULL) + { + free (data->oldkey); + data->oldkey = NULL; + data->oldkeylen = 0; + } + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_endrpcent (void) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_nis_endrpcent (&intern); + + __libc_lock_unlock (lock); + + return status; +} + +static enum nss_status +internal_nis_getrpcent_r (struct rpcent *rpc, char *buffer, size_t buflen, + intern_t *data) +{ + char *domain; + char *result; + int len, parse_res; + char *outkey; + int keylen; + char *p; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + /* Get the next entry until we found a correct one. */ + do + { + enum nss_status retval; + + if (data->new_start) + retval = yperr2nss (yp_first (domain, "rpc.bynumber", + &outkey, &keylen, &result, &len)); + else + retval = yperr2nss ( yp_next (domain, "rpc.bynumber", + data->oldkey, data->oldkeylen, + &outkey, &keylen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_rpcent (p, rpc, buffer, buflen); + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + + free (data->oldkey); + data->oldkey = outkey; + data->oldkeylen = keylen; + data->new_start = 0; + } + while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getrpcent_r (struct rpcent *rpc, char *buffer, size_t buflen) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_nis_getrpcent_r (rpc, buffer, buflen, &intern); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nis_getrpcbyname_r (const char *name, struct rpcent *rpc, + char *buffer, size_t buflen) +{ + intern_t data = {TRUE, NULL, 0}; + enum nss_status status; + int found; + + if (name == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + status = internal_nis_setrpcent (&data); + if (status != NSS_STATUS_SUCCESS) + return status; + + found = 0; + while (!found && + ((status = internal_nis_getrpcent_r (rpc, buffer, buflen, &data)) + == NSS_STATUS_SUCCESS)) + { + if (strcmp (rpc->r_name, name) == 0) + found = 1; + else + { + int i = 0; + + while (rpc->r_aliases[i] != NULL) + { + if (strcmp (rpc->r_aliases[i], name) == 0) + { + found = 1; + break; + } + else + ++i; + } + } + } + + internal_nis_endrpcent (&data); + + if (!found && status == NSS_STATUS_SUCCESS) + return NSS_STATUS_NOTFOUND; + else + return status; +} + +enum nss_status +_nss_nis_getrpcbynumber_r (int number, struct rpcent *rpc, + char *buffer, size_t buflen) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, nlen, parse_res; + char buf[32]; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + nlen = sprintf (buf, "%d", number); + + retval = yperr2nss (yp_match (domain, "rpc.bynumber", buf, + nlen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_rpcent (p, rpc, buffer, buflen); + + if (!parse_res) + { + if (errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } + else + return NSS_STATUS_SUCCESS; +} diff --git a/nis/nss_nis/nis-service.c b/nis/nss_nis/nis-service.c new file mode 100644 index 0000000000..03a9fbf48e --- /dev/null +++ b/nis/nss_nis/nis-service.c @@ -0,0 +1,249 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <netdb.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +#include "nss-nis.h" + +__libc_lock_define_initialized (static, lock) + +struct intern_t +{ + bool_t new_start; + char *oldkey; + int oldkeylen; +}; +typedef struct intern_t intern_t; + +static intern_t intern = {TRUE, NULL, 0}; + +static enum nss_status +internal_nis_setservent (intern_t * intern) +{ + intern->new_start = 1; + if (intern->oldkey != NULL) + { + free (intern->oldkey); + intern->oldkey = NULL; + intern->oldkeylen = 0; + } + return NSS_STATUS_SUCCESS; +} +enum nss_status +_nss_nis_setservent (void) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_nis_setservent (&intern); + + __libc_lock_unlock (lock); + + return status; +} + +static enum nss_status +internal_nis_endservent (intern_t * intern) +{ + intern->new_start = 1; + if (intern->oldkey != NULL) + { + free (intern->oldkey); + intern->oldkey = NULL; + intern->oldkeylen = 0; + } + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_endservent (void) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_nis_endservent (&intern); + + __libc_lock_unlock (lock); + + return status; +} + +static enum nss_status +internal_nis_getservent_r (struct servent *serv, char *buffer, + size_t buflen, intern_t *data) +{ + char *domain; + char *result; + int len, parse_res; + char *outkey; + int keylen; + char *p; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + /* Get the next entry until we found a correct one. */ + do + { + enum nss_status retval; + + if (data->new_start) + retval = yperr2nss (yp_first (domain, "services.byname", + &outkey, &keylen, &result, &len)); + else + retval = yperr2nss ( yp_next (domain, "services.byname", + data->oldkey, data->oldkeylen, + &outkey, &keylen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_servent (p, serv, buffer, buflen); + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + + free (data->oldkey); + data->oldkey = outkey; + data->oldkeylen = keylen; + data->new_start = 0; + } + while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getservent_r (struct servent *serv, char *buffer, size_t buflen) +{ + enum nss_status status; + + __libc_lock_lock (lock); + + status = internal_nis_getservent_r (serv, buffer, buflen, &intern); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nis_getservbyname_r (const char *name, char *protocol, + struct servent *serv, char *buffer, size_t buflen) +{ + intern_t data = {TRUE, NULL, 0}; + enum nss_status status; + int found; + + if (name == NULL || protocol == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + status = internal_nis_setservent (&data); + if (status != NSS_STATUS_SUCCESS) + return status; + + found = 0; + while (!found && + ((status = internal_nis_getservent_r (serv, buffer, buflen, &data)) + == NSS_STATUS_SUCCESS)) + { + if (strcmp (serv->s_name, name) == 0) + { + if (strcmp (serv->s_proto, protocol) == 0) + { + found = 1; + } + } + } + + internal_nis_endservent (&data); + + if (!found && status == NSS_STATUS_SUCCESS) + return NSS_STATUS_NOTFOUND; + else + return status; +} + +enum nss_status +_nss_nis_getservbyport_r (int port, char *protocol, struct servent *serv, + char *buffer, size_t buflen) +{ + intern_t data = {TRUE, NULL, 0}; + enum nss_status status; + int found; + + if (protocol == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + status = internal_nis_setservent (&data); + if (status != NSS_STATUS_SUCCESS) + return status; + + found = 0; + while (!found && + ((status = internal_nis_getservent_r (serv, buffer, buflen, &data)) + == NSS_STATUS_SUCCESS)) + { + if (htons (serv->s_port) == port) + { + if (strcmp (serv->s_proto, protocol) == 0) + { + found = 1; + } + } + } + + internal_nis_endservent (&data); + + if (!found && status == NSS_STATUS_SUCCESS) + return NSS_STATUS_NOTFOUND; + else + return status; +} diff --git a/nis/nss_nis/nis-spwd.c b/nis/nss_nis/nis-spwd.c new file mode 100644 index 0000000000..928489245b --- /dev/null +++ b/nis/nss_nis/nis-spwd.c @@ -0,0 +1,196 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <nss.h> +#include <ctype.h> +#include <errno.h> +#include <string.h> +#include <shadow.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> + +#include "nss-nis.h" + +/* Protect global state against multiple changers */ +__libc_lock_define_initialized (static, lock) + +static bool_t new_start = 1; +static char *oldkey = NULL; +static int oldkeylen = 0; + +enum nss_status +_nss_nis_setspent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_endspent (void) +{ + __libc_lock_lock (lock); + + new_start = 1; + if (oldkey != NULL) + { + free (oldkey); + oldkey = NULL; + oldkeylen = 0; + } + + __libc_lock_unlock (lock); + + return NSS_STATUS_SUCCESS; +} + +static enum nss_status +internal_nis_getspent_r (struct spwd *sp, char *buffer, size_t buflen) +{ + char *domain, *result, *outkey; + int len, keylen, parse_res; + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + /* Get the next entry until we found a correct one. */ + do + { + enum nss_status retval; + char *p; + + if (new_start) + retval = yperr2nss (yp_first (domain, "shadow.byname", + &outkey, &keylen, &result, &len)); + else + retval = yperr2nss ( yp_next (domain, "shadow.byname", + oldkey, oldkeylen, + &outkey, &keylen, &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_spent (p, sp, buffer, buflen); + if (!parse_res && errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + + free (oldkey); + oldkey = outkey; + oldkeylen = keylen; + new_start = 0; + } + while (!parse_res); + + return NSS_STATUS_SUCCESS; +} + +enum nss_status +_nss_nis_getspent_r (struct spwd *result, char *buffer, size_t buflen) +{ + int status; + + __libc_lock_lock (lock); + + status = internal_nis_getspent_r (result, buffer, buflen); + + __libc_lock_unlock (lock); + + return status; +} + +enum nss_status +_nss_nis_getspnam_r (const char *name, struct spwd *sp, + char *buffer, size_t buflen) +{ + enum nss_status retval; + char *domain, *result, *p; + int len, parse_res; + + if (name == NULL) + { + __set_errno (EINVAL); + return NSS_STATUS_UNAVAIL; + } + + if (yp_get_default_domain (&domain)) + return NSS_STATUS_UNAVAIL; + + retval = yperr2nss (yp_match (domain, "shadow.byname", name, + strlen (name), &result, &len)); + + if (retval != NSS_STATUS_SUCCESS) + { + if (retval == NSS_STATUS_TRYAGAIN) + __set_errno (EAGAIN); + return retval; + } + + if (len + 1 > buflen) + { + free (result); + __set_errno (ERANGE); + return NSS_STATUS_TRYAGAIN; + } + + p = strncpy (buffer, result, len); + buffer[len] = '\0'; + while (isspace (*p)) + ++p; + free (result); + + parse_res = _nss_files_parse_spent (p, sp, buffer, buflen); + + if (!parse_res) + { + if (errno == ERANGE) + return NSS_STATUS_TRYAGAIN; + else + return NSS_STATUS_NOTFOUND; + } + else + return NSS_STATUS_SUCCESS; +} diff --git a/nis/rpcsvc/yp.h b/nis/rpcsvc/yp.h new file mode 100644 index 0000000000..f625eced50 --- /dev/null +++ b/nis/rpcsvc/yp.h @@ -0,0 +1,611 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#ifndef __RPCSVC_YP_H__ +#define __RPCSVC_YP_H__ + +#include <rpc/rpc.h> + +#define YPMAXRECORD 1024 +#define YPMAXDOMAIN 64 +#define YPMAXMAP 64 +#define YPMAXPEER 64 + +enum ypstat { + YP_TRUE = 1, + YP_NOMORE = 2, + YP_FALSE = 0, + YP_NOMAP = -1, + YP_NODOM = -2, + YP_NOKEY = -3, + YP_BADOP = -4, + YP_BADDB = -5, + YP_YPERR = -6, + YP_BADARGS = -7, + YP_VERS = -8, +}; +typedef enum ypstat ypstat; +#ifdef __cplusplus +extern "C" bool_t xdr_ypstat(XDR *, ypstat*); +#elif __STDC__ +extern bool_t xdr_ypstat(XDR *, ypstat*); +#else /* Old Style C */ +bool_t xdr_ypstat(); +#endif /* Old Style C */ + + +enum ypxfrstat { + YPXFR_SUCC = 1, + YPXFR_AGE = 2, + YPXFR_NOMAP = -1, + YPXFR_NODOM = -2, + YPXFR_RSRC = -3, + YPXFR_RPC = -4, + YPXFR_MADDR = -5, + YPXFR_YPERR = -6, + YPXFR_BADARGS = -7, + YPXFR_DBM = -8, + YPXFR_FILE = -9, + YPXFR_SKEW = -10, + YPXFR_CLEAR = -11, + YPXFR_FORCE = -12, + YPXFR_XFRERR = -13, + YPXFR_REFUSED = -14, +}; +typedef enum ypxfrstat ypxfrstat; +#ifdef __cplusplus +extern "C" bool_t xdr_ypxfrstat(XDR *, ypxfrstat*); +#elif __STDC__ +extern bool_t xdr_ypxfrstat(XDR *, ypxfrstat*); +#else /* Old Style C */ +bool_t xdr_ypxfrstat(); +#endif /* Old Style C */ + + +typedef char *domainname; +#ifdef __cplusplus +extern "C" bool_t xdr_domainname(XDR *, domainname*); +#elif __STDC__ +extern bool_t xdr_domainname(XDR *, domainname*); +#else /* Old Style C */ +bool_t xdr_domainname(); +#endif /* Old Style C */ + + +typedef char *mapname; +#ifdef __cplusplus +extern "C" bool_t xdr_mapname(XDR *, mapname*); +#elif __STDC__ +extern bool_t xdr_mapname(XDR *, mapname*); +#else /* Old Style C */ +bool_t xdr_mapname(); +#endif /* Old Style C */ + + +typedef char *peername; +#ifdef __cplusplus +extern "C" bool_t xdr_peername(XDR *, peername*); +#elif __STDC__ +extern bool_t xdr_peername(XDR *, peername*); +#else /* Old Style C */ +bool_t xdr_peername(); +#endif /* Old Style C */ + + +typedef struct { + u_int keydat_len; + char *keydat_val; +} keydat; +#ifdef __cplusplus +extern "C" bool_t xdr_keydat(XDR *, keydat*); +#elif __STDC__ +extern bool_t xdr_keydat(XDR *, keydat*); +#else /* Old Style C */ +bool_t xdr_keydat(); +#endif /* Old Style C */ + + +typedef struct { + u_int valdat_len; + char *valdat_val; +} valdat; +#ifdef __cplusplus +extern "C" bool_t xdr_valdat(XDR *, valdat*); +#elif __STDC__ +extern bool_t xdr_valdat(XDR *, valdat*); +#else /* Old Style C */ +bool_t xdr_valdat(); +#endif /* Old Style C */ + + +struct ypmap_parms { + domainname domain; + mapname map; + u_int ordernum; + peername peer; +}; +typedef struct ypmap_parms ypmap_parms; +#ifdef __cplusplus +extern "C" bool_t xdr_ypmap_parms(XDR *, ypmap_parms*); +#elif __STDC__ +extern bool_t xdr_ypmap_parms(XDR *, ypmap_parms*); +#else /* Old Style C */ +bool_t xdr_ypmap_parms(); +#endif /* Old Style C */ + + +struct ypreq_key { + domainname domain; + mapname map; + keydat key; +}; +typedef struct ypreq_key ypreq_key; +#ifdef __cplusplus +extern "C" bool_t xdr_ypreq_key(XDR *, ypreq_key*); +#elif __STDC__ +extern bool_t xdr_ypreq_key(XDR *, ypreq_key*); +#else /* Old Style C */ +bool_t xdr_ypreq_key(); +#endif /* Old Style C */ + + +struct ypreq_nokey { + domainname domain; + mapname map; +}; +typedef struct ypreq_nokey ypreq_nokey; +#ifdef __cplusplus +extern "C" bool_t xdr_ypreq_nokey(XDR *, ypreq_nokey*); +#elif __STDC__ +extern bool_t xdr_ypreq_nokey(XDR *, ypreq_nokey*); +#else /* Old Style C */ +bool_t xdr_ypreq_nokey(); +#endif /* Old Style C */ + + +struct ypreq_xfr { + ypmap_parms map_parms; + u_int transid; + u_int prog; + u_int port; +}; +typedef struct ypreq_xfr ypreq_xfr; +#ifdef __cplusplus +extern "C" bool_t xdr_ypreq_xfr(XDR *, ypreq_xfr*); +#elif __STDC__ +extern bool_t xdr_ypreq_xfr(XDR *, ypreq_xfr*); +#else /* Old Style C */ +bool_t xdr_ypreq_xfr(); +#endif /* Old Style C */ + + +struct ypresp_val { + ypstat stat; + valdat val; +}; +typedef struct ypresp_val ypresp_val; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_val(XDR *, ypresp_val*); +#elif __STDC__ +extern bool_t xdr_ypresp_val(XDR *, ypresp_val*); +#else /* Old Style C */ +bool_t xdr_ypresp_val(); +#endif /* Old Style C */ + + +struct ypresp_key_val { + ypstat stat; + valdat val; + keydat key; +}; +typedef struct ypresp_key_val ypresp_key_val; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_key_val(XDR *, ypresp_key_val*); +#elif __STDC__ +extern bool_t xdr_ypresp_key_val(XDR *, ypresp_key_val*); +#else /* Old Style C */ +bool_t xdr_ypresp_key_val(); +#endif /* Old Style C */ + + +struct ypresp_master { + ypstat stat; + peername peer; +}; +typedef struct ypresp_master ypresp_master; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_master(XDR *, ypresp_master*); +#elif __STDC__ +extern bool_t xdr_ypresp_master(XDR *, ypresp_master*); +#else /* Old Style C */ +bool_t xdr_ypresp_master(); +#endif /* Old Style C */ + + +struct ypresp_order { + ypstat stat; + u_int ordernum; +}; +typedef struct ypresp_order ypresp_order; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_order(XDR *, ypresp_order*); +#elif __STDC__ +extern bool_t xdr_ypresp_order(XDR *, ypresp_order*); +#else /* Old Style C */ +bool_t xdr_ypresp_order(); +#endif /* Old Style C */ + + +struct ypresp_all { + bool_t more; + union { + ypresp_key_val val; + } ypresp_all_u; +}; +typedef struct ypresp_all ypresp_all; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_all(XDR *, ypresp_all*); +#elif __STDC__ +extern bool_t xdr_ypresp_all(XDR *, ypresp_all*); +#else /* Old Style C */ +bool_t xdr_ypresp_all(); +#endif /* Old Style C */ + + +struct ypresp_xfr { + u_int transid; + ypxfrstat xfrstat; +}; +typedef struct ypresp_xfr ypresp_xfr; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_xfr(XDR *, ypresp_xfr*); +#elif __STDC__ +extern bool_t xdr_ypresp_xfr(XDR *, ypresp_xfr*); +#else /* Old Style C */ +bool_t xdr_ypresp_xfr(); +#endif /* Old Style C */ + + +struct ypmaplist { + mapname map; + struct ypmaplist *next; +}; +typedef struct ypmaplist ypmaplist; +#ifdef __cplusplus +extern "C" bool_t xdr_ypmaplist(XDR *, ypmaplist*); +#elif __STDC__ +extern bool_t xdr_ypmaplist(XDR *, ypmaplist*); +#else /* Old Style C */ +bool_t xdr_ypmaplist(); +#endif /* Old Style C */ + + +struct ypresp_maplist { + ypstat stat; + ypmaplist *maps; +}; +typedef struct ypresp_maplist ypresp_maplist; +#ifdef __cplusplus +extern "C" bool_t xdr_ypresp_maplist(XDR *, ypresp_maplist*); +#elif __STDC__ +extern bool_t xdr_ypresp_maplist(XDR *, ypresp_maplist*); +#else /* Old Style C */ +bool_t xdr_ypresp_maplist(); +#endif /* Old Style C */ + + +enum yppush_status { + YPPUSH_SUCC = 1, + YPPUSH_AGE = 2, + YPPUSH_NOMAP = -1, + YPPUSH_NODOM = -2, + YPPUSH_RSRC = -3, + YPPUSH_RPC = -4, + YPPUSH_MADDR = -5, + YPPUSH_YPERR = -6, + YPPUSH_BADARGS = -7, + YPPUSH_DBM = -8, + YPPUSH_FILE = -9, + YPPUSH_SKEW = -10, + YPPUSH_CLEAR = -11, + YPPUSH_FORCE = -12, + YPPUSH_XFRERR = -13, + YPPUSH_REFUSED = -14, +}; +typedef enum yppush_status yppush_status; +#ifdef __cplusplus +extern "C" bool_t xdr_yppush_status(XDR *, yppush_status*); +#elif __STDC__ +extern bool_t xdr_yppush_status(XDR *, yppush_status*); +#else /* Old Style C */ +bool_t xdr_yppush_status(); +#endif /* Old Style C */ + + +struct yppushresp_xfr { + u_int transid; + yppush_status status; +}; +typedef struct yppushresp_xfr yppushresp_xfr; +#ifdef __cplusplus +extern "C" bool_t xdr_yppushresp_xfr(XDR *, yppushresp_xfr*); +#elif __STDC__ +extern bool_t xdr_yppushresp_xfr(XDR *, yppushresp_xfr*); +#else /* Old Style C */ +bool_t xdr_yppushresp_xfr(); +#endif /* Old Style C */ + + +enum ypbind_resptype { + YPBIND_SUCC_VAL = 1, + YPBIND_FAIL_VAL = 2, +}; +typedef enum ypbind_resptype ypbind_resptype; +#ifdef __cplusplus +extern "C" bool_t xdr_ypbind_resptype(XDR *, ypbind_resptype*); +#elif __STDC__ +extern bool_t xdr_ypbind_resptype(XDR *, ypbind_resptype*); +#else /* Old Style C */ +bool_t xdr_ypbind_resptype(); +#endif /* Old Style C */ + + +struct ypbind_binding { + char ypbind_binding_addr[4]; + char ypbind_binding_port[2]; +}; +typedef struct ypbind_binding ypbind_binding; +#ifdef __cplusplus +extern "C" bool_t xdr_ypbind_binding(XDR *, ypbind_binding*); +#elif __STDC__ +extern bool_t xdr_ypbind_binding(XDR *, ypbind_binding*); +#else /* Old Style C */ +bool_t xdr_ypbind_binding(); +#endif /* Old Style C */ + + +struct ypbind_resp { + ypbind_resptype ypbind_status; + union { + u_int ypbind_error; + ypbind_binding ypbind_bindinfo; + } ypbind_resp_u; +}; +typedef struct ypbind_resp ypbind_resp; +#ifdef __cplusplus +extern "C" bool_t xdr_ypbind_resp(XDR *, ypbind_resp*); +#elif __STDC__ +extern bool_t xdr_ypbind_resp(XDR *, ypbind_resp*); +#else /* Old Style C */ +bool_t xdr_ypbind_resp(); +#endif /* Old Style C */ + +#define YPBIND_ERR_ERR 1 +#define YPBIND_ERR_NOSERV 2 +#define YPBIND_ERR_RESC 3 + +struct ypbind_setdom { + domainname ypsetdom_domain; + ypbind_binding ypsetdom_binding; + u_int ypsetdom_vers; +}; +typedef struct ypbind_setdom ypbind_setdom; +#ifdef __cplusplus +extern "C" bool_t xdr_ypbind_setdom(XDR *, ypbind_setdom*); +#elif __STDC__ +extern bool_t xdr_ypbind_setdom(XDR *, ypbind_setdom*); +#else /* Old Style C */ +bool_t xdr_ypbind_setdom(); +#endif /* Old Style C */ + + +#define YPPROG ((u_long)100004) +#define YPVERS ((u_long)2) + +#ifdef __cplusplus +#define YPPROC_NULL ((u_long)0) +extern "C" void * ypproc_null_2(void *, CLIENT *); +extern "C" void * ypproc_null_2_svc(void *, struct svc_req *); +#define YPPROC_DOMAIN ((u_long)1) +extern "C" bool_t * ypproc_domain_2(domainname *, CLIENT *); +extern "C" bool_t * ypproc_domain_2_svc(domainname *, struct svc_req *); +#define YPPROC_DOMAIN_NONACK ((u_long)2) +extern "C" bool_t * ypproc_domain_nonack_2(domainname *, CLIENT *); +extern "C" bool_t * ypproc_domain_nonack_2_svc(domainname *, struct svc_req *); +#define YPPROC_MATCH ((u_long)3) +extern "C" ypresp_val * ypproc_match_2(ypreq_key *, CLIENT *); +extern "C" ypresp_val * ypproc_match_2_svc(ypreq_key *, struct svc_req *); +#define YPPROC_FIRST ((u_long)4) +extern "C" ypresp_key_val * ypproc_first_2(ypreq_key *, CLIENT *); +extern "C" ypresp_key_val * ypproc_first_2_svc(ypreq_key *, struct svc_req *); +#define YPPROC_NEXT ((u_long)5) +extern "C" ypresp_key_val * ypproc_next_2(ypreq_key *, CLIENT *); +extern "C" ypresp_key_val * ypproc_next_2_svc(ypreq_key *, struct svc_req *); +#define YPPROC_XFR ((u_long)6) +extern "C" ypresp_xfr * ypproc_xfr_2(ypreq_xfr *, CLIENT *); +extern "C" ypresp_xfr * ypproc_xfr_2_svc(ypreq_xfr *, struct svc_req *); +#define YPPROC_CLEAR ((u_long)7) +extern "C" void * ypproc_clear_2(void *, CLIENT *); +extern "C" void * ypproc_clear_2_svc(void *, struct svc_req *); +#define YPPROC_ALL ((u_long)8) +extern "C" ypresp_all * ypproc_all_2(ypreq_nokey *, CLIENT *); +extern "C" ypresp_all * ypproc_all_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_MASTER ((u_long)9) +extern "C" ypresp_master * ypproc_master_2(ypreq_nokey *, CLIENT *); +extern "C" ypresp_master * ypproc_master_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_ORDER ((u_long)10) +extern "C" ypresp_order * ypproc_order_2(ypreq_nokey *, CLIENT *); +extern "C" ypresp_order * ypproc_order_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_MAPLIST ((u_long)11) +extern "C" ypresp_maplist * ypproc_maplist_2(domainname *, CLIENT *); +extern "C" ypresp_maplist * ypproc_maplist_2_svc(domainname *, struct svc_req *); + +#elif __STDC__ +#define YPPROC_NULL ((u_long)0) +extern void * ypproc_null_2(void *, CLIENT *); +extern void * ypproc_null_2_svc(void *, struct svc_req *); +#define YPPROC_DOMAIN ((u_long)1) +extern bool_t * ypproc_domain_2(domainname *, CLIENT *); +extern bool_t * ypproc_domain_2_svc(domainname *, struct svc_req *); +#define YPPROC_DOMAIN_NONACK ((u_long)2) +extern bool_t * ypproc_domain_nonack_2(domainname *, CLIENT *); +extern bool_t * ypproc_domain_nonack_2_svc(domainname *, struct svc_req *); +#define YPPROC_MATCH ((u_long)3) +extern ypresp_val * ypproc_match_2(ypreq_key *, CLIENT *); +extern ypresp_val * ypproc_match_2_svc(ypreq_key *, struct svc_req *); +#define YPPROC_FIRST ((u_long)4) +extern ypresp_key_val * ypproc_first_2(ypreq_key *, CLIENT *); +extern ypresp_key_val * ypproc_first_2_svc(ypreq_key *, struct svc_req *); +#define YPPROC_NEXT ((u_long)5) +extern ypresp_key_val * ypproc_next_2(ypreq_key *, CLIENT *); +extern ypresp_key_val * ypproc_next_2_svc(ypreq_key *, struct svc_req *); +#define YPPROC_XFR ((u_long)6) +extern ypresp_xfr * ypproc_xfr_2(ypreq_xfr *, CLIENT *); +extern ypresp_xfr * ypproc_xfr_2_svc(ypreq_xfr *, struct svc_req *); +#define YPPROC_CLEAR ((u_long)7) +extern void * ypproc_clear_2(void *, CLIENT *); +extern void * ypproc_clear_2_svc(void *, struct svc_req *); +#define YPPROC_ALL ((u_long)8) +extern ypresp_all * ypproc_all_2(ypreq_nokey *, CLIENT *); +extern ypresp_all * ypproc_all_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_MASTER ((u_long)9) +extern ypresp_master * ypproc_master_2(ypreq_nokey *, CLIENT *); +extern ypresp_master * ypproc_master_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_ORDER ((u_long)10) +extern ypresp_order * ypproc_order_2(ypreq_nokey *, CLIENT *); +extern ypresp_order * ypproc_order_2_svc(ypreq_nokey *, struct svc_req *); +#define YPPROC_MAPLIST ((u_long)11) +extern ypresp_maplist * ypproc_maplist_2(domainname *, CLIENT *); +extern ypresp_maplist * ypproc_maplist_2_svc(domainname *, struct svc_req *); + +#else /* Old Style C */ +#define YPPROC_NULL ((u_long)0) +extern void * ypproc_null_2(); +extern void * ypproc_null_2_svc(); +#define YPPROC_DOMAIN ((u_long)1) +extern bool_t * ypproc_domain_2(); +extern bool_t * ypproc_domain_2_svc(); +#define YPPROC_DOMAIN_NONACK ((u_long)2) +extern bool_t * ypproc_domain_nonack_2(); +extern bool_t * ypproc_domain_nonack_2_svc(); +#define YPPROC_MATCH ((u_long)3) +extern ypresp_val * ypproc_match_2(); +extern ypresp_val * ypproc_match_2_svc(); +#define YPPROC_FIRST ((u_long)4) +extern ypresp_key_val * ypproc_first_2(); +extern ypresp_key_val * ypproc_first_2_svc(); +#define YPPROC_NEXT ((u_long)5) +extern ypresp_key_val * ypproc_next_2(); +extern ypresp_key_val * ypproc_next_2_svc(); +#define YPPROC_XFR ((u_long)6) +extern ypresp_xfr * ypproc_xfr_2(); +extern ypresp_xfr * ypproc_xfr_2_svc(); +#define YPPROC_CLEAR ((u_long)7) +extern void * ypproc_clear_2(); +extern void * ypproc_clear_2_svc(); +#define YPPROC_ALL ((u_long)8) +extern ypresp_all * ypproc_all_2(); +extern ypresp_all * ypproc_all_2_svc(); +#define YPPROC_MASTER ((u_long)9) +extern ypresp_master * ypproc_master_2(); +extern ypresp_master * ypproc_master_2_svc(); +#define YPPROC_ORDER ((u_long)10) +extern ypresp_order * ypproc_order_2(); +extern ypresp_order * ypproc_order_2_svc(); +#define YPPROC_MAPLIST ((u_long)11) +extern ypresp_maplist * ypproc_maplist_2(); +extern ypresp_maplist * ypproc_maplist_2_svc(); +#endif /* Old Style C */ + +#define YPPUSH_XFRRESPPROG ((u_long)0x40000000) +#define YPPUSH_XFRRESPVERS ((u_long)1) + +#ifdef __cplusplus +#define YPPUSHPROC_NULL ((u_long)0) +extern "C" void * yppushproc_null_1(void *, CLIENT *); +extern "C" void * yppushproc_null_1_svc(void *, struct svc_req *); +#define YPPUSHPROC_XFRRESP ((u_long)1) +extern "C" void * yppushproc_xfrresp_1(yppushresp_xfr *, CLIENT *); +extern "C" void * yppushproc_xfrresp_1_svc(yppushresp_xfr *, struct svc_req *); + +#elif __STDC__ +#define YPPUSHPROC_NULL ((u_long)0) +extern void * yppushproc_null_1(void *, CLIENT *); +extern void * yppushproc_null_1_svc(void *, struct svc_req *); +#define YPPUSHPROC_XFRRESP ((u_long)1) +extern void * yppushproc_xfrresp_1(yppushresp_xfr *, CLIENT *); +extern void * yppushproc_xfrresp_1_svc(yppushresp_xfr *, struct svc_req *); + +#else /* Old Style C */ +#define YPPUSHPROC_NULL ((u_long)0) +extern void * yppushproc_null_1(); +extern void * yppushproc_null_1_svc(); +#define YPPUSHPROC_XFRRESP ((u_long)1) +extern void * yppushproc_xfrresp_1(); +extern void * yppushproc_xfrresp_1_svc(); +#endif /* Old Style C */ + +#define YPBINDPROG ((u_long)100007) +#define YPBINDVERS ((u_long)2) + +#ifdef __cplusplus +#define YPBINDPROC_NULL ((u_long)0) +extern "C" void * ypbindproc_null_2(void *, CLIENT *); +extern "C" void * ypbindproc_null_2_svc(void *, struct svc_req *); +#define YPBINDPROC_DOMAIN ((u_long)1) +extern "C" ypbind_resp * ypbindproc_domain_2(domainname *, CLIENT *); +extern "C" ypbind_resp * ypbindproc_domain_2_svc(domainname *, struct svc_req *); +#define YPBINDPROC_SETDOM ((u_long)2) +extern "C" void * ypbindproc_setdom_2(ypbind_setdom *, CLIENT *); +extern "C" void * ypbindproc_setdom_2_svc(ypbind_setdom *, struct svc_req *); + +#elif __STDC__ +#define YPBINDPROC_NULL ((u_long)0) +extern void * ypbindproc_null_2(void *, CLIENT *); +extern void * ypbindproc_null_2_svc(void *, struct svc_req *); +#define YPBINDPROC_DOMAIN ((u_long)1) +extern ypbind_resp * ypbindproc_domain_2(domainname *, CLIENT *); +extern ypbind_resp * ypbindproc_domain_2_svc(domainname *, struct svc_req *); +#define YPBINDPROC_SETDOM ((u_long)2) +extern void * ypbindproc_setdom_2(ypbind_setdom *, CLIENT *); +extern void * ypbindproc_setdom_2_svc(ypbind_setdom *, struct svc_req *); + +#else /* Old Style C */ +#define YPBINDPROC_NULL ((u_long)0) +extern void * ypbindproc_null_2(); +extern void * ypbindproc_null_2_svc(); +#define YPBINDPROC_DOMAIN ((u_long)1) +extern ypbind_resp * ypbindproc_domain_2(); +extern ypbind_resp * ypbindproc_domain_2_svc(); +#define YPBINDPROC_SETDOM ((u_long)2) +extern void * ypbindproc_setdom_2(); +extern void * ypbindproc_setdom_2_svc(); +#endif /* Old Style C */ + +#endif /* !__RPCSVC_YP_H__ */ diff --git a/nis/rpcsvc/yp.x b/nis/rpcsvc/yp.x new file mode 100644 index 0000000000..be855df749 --- /dev/null +++ b/nis/rpcsvc/yp.x @@ -0,0 +1,300 @@ +/* @(#)yp.x 2.1 88/08/01 4.0 RPCSRC */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +/* + * Protocol description file for the Yellow Pages Service + */ + +const YPMAXRECORD = 1024; +const YPMAXDOMAIN = 64; +const YPMAXMAP = 64; +const YPMAXPEER = 64; + + +enum ypstat { + YP_TRUE = 1, + YP_NOMORE = 2, + YP_FALSE = 0, + YP_NOMAP = -1, + YP_NODOM = -2, + YP_NOKEY = -3, + YP_BADOP = -4, + YP_BADDB = -5, + YP_YPERR = -6, + YP_BADARGS = -7, + YP_VERS = -8 +}; + + +enum ypxfrstat { + YPXFR_SUCC = 1, + YPXFR_AGE = 2, + YPXFR_NOMAP = -1, + YPXFR_NODOM = -2, + YPXFR_RSRC = -3, + YPXFR_RPC = -4, + YPXFR_MADDR = -5, + YPXFR_YPERR = -6, + YPXFR_BADARGS = -7, + YPXFR_DBM = -8, + YPXFR_FILE = -9, + YPXFR_SKEW = -10, + YPXFR_CLEAR = -11, + YPXFR_FORCE = -12, + YPXFR_XFRERR = -13, + YPXFR_REFUSED = -14 +}; + + +typedef string domainname<YPMAXDOMAIN>; +typedef string mapname<YPMAXMAP>; +typedef string peername<YPMAXPEER>; +typedef opaque keydat<YPMAXRECORD>; +typedef opaque valdat<YPMAXRECORD>; + + +struct ypmap_parms { + domainname domain; + mapname map; + unsigned int ordernum; + peername peer; +}; + +struct ypreq_key { + domainname domain; + mapname map; + keydat key; +}; + +struct ypreq_nokey { + domainname domain; + mapname map; +}; + +struct ypreq_xfr { + ypmap_parms map_parms; + unsigned int transid; + unsigned int prog; + unsigned int port; +}; + + +struct ypresp_val { + ypstat stat; + valdat val; +}; + +struct ypresp_key_val { + ypstat stat; +#ifdef STUPID_SUN_BUG + keydat key; + valdat val; +#else + valdat val; + keydat key; +#endif +}; + + +struct ypresp_master { + ypstat stat; + peername peer; +}; + +struct ypresp_order { + ypstat stat; + unsigned int ordernum; +}; + +union ypresp_all switch (bool more) { +case TRUE: + ypresp_key_val val; +case FALSE: + void; +}; + +struct ypresp_xfr { + unsigned int transid; + ypxfrstat xfrstat; +}; + +struct ypmaplist { + mapname map; + ypmaplist *next; +}; + +struct ypresp_maplist { + ypstat stat; + ypmaplist *maps; +}; + +enum yppush_status { + YPPUSH_SUCC = 1, /* Success */ + YPPUSH_AGE = 2, /* Master's version not newer */ + YPPUSH_NOMAP = -1, /* Can't find server for map */ + YPPUSH_NODOM = -2, /* Domain not supported */ + YPPUSH_RSRC = -3, /* Local resource alloc failure */ + YPPUSH_RPC = -4, /* RPC failure talking to server */ + YPPUSH_MADDR = -5, /* Can't get master address */ + YPPUSH_YPERR = -6, /* YP server/map db error */ + YPPUSH_BADARGS = -7, /* Request arguments bad */ + YPPUSH_DBM = -8, /* Local dbm operation failed */ + YPPUSH_FILE = -9, /* Local file I/O operation failed */ + YPPUSH_SKEW = -10, /* Map version skew during transfer */ + YPPUSH_CLEAR = -11, /* Can't send "Clear" req to local ypserv */ + YPPUSH_FORCE = -12, /* No local order number in map use -f flag. */ + YPPUSH_XFRERR = -13, /* ypxfr error */ + YPPUSH_REFUSED = -14 /* Transfer request refused by ypserv */ +}; + +struct yppushresp_xfr { + unsigned transid; + yppush_status status; +}; + +/* + * Response structure and overall result status codes. Success and failure + * represent two separate response message types. + */ + +enum ypbind_resptype { + YPBIND_SUCC_VAL = 1, + YPBIND_FAIL_VAL = 2 +}; + +struct ypbind_binding { + opaque ypbind_binding_addr[4]; /* In network order */ + opaque ypbind_binding_port[2]; /* In network order */ +}; + +union ypbind_resp switch (ypbind_resptype ypbind_status) { +case YPBIND_FAIL_VAL: + unsigned ypbind_error; +case YPBIND_SUCC_VAL: + ypbind_binding ypbind_bindinfo; +}; + +/* Detailed failure reason codes for response field ypbind_error*/ + +const YPBIND_ERR_ERR = 1; /* Internal error */ +const YPBIND_ERR_NOSERV = 2; /* No bound server for passed domain */ +const YPBIND_ERR_RESC = 3; /* System resource allocation failure */ + + +/* + * Request data structure for ypbind "Set domain" procedure. + */ +struct ypbind_setdom { + domainname ypsetdom_domain; + ypbind_binding ypsetdom_binding; + unsigned ypsetdom_vers; +}; + + +/* + * YP access protocol + */ +program YPPROG { + version YPVERS { + void + YPPROC_NULL(void) = 0; + + bool + YPPROC_DOMAIN(domainname) = 1; + + bool + YPPROC_DOMAIN_NONACK(domainname) = 2; + + ypresp_val + YPPROC_MATCH(ypreq_key) = 3; + + ypresp_key_val + YPPROC_FIRST(ypreq_key) = 4; + + ypresp_key_val + YPPROC_NEXT(ypreq_key) = 5; + + ypresp_xfr + YPPROC_XFR(ypreq_xfr) = 6; + + void + YPPROC_CLEAR(void) = 7; + + ypresp_all + YPPROC_ALL(ypreq_nokey) = 8; + + ypresp_master + YPPROC_MASTER(ypreq_nokey) = 9; + + ypresp_order + YPPROC_ORDER(ypreq_nokey) = 10; + + ypresp_maplist + YPPROC_MAPLIST(domainname) = 11; + } = 2; +} = 100004; + + +/* + * YPPUSHPROC_XFRRESP is the callback routine for result of YPPROC_XFR + */ +program YPPUSH_XFRRESPPROG { + version YPPUSH_XFRRESPVERS { + void + YPPUSHPROC_NULL(void) = 0; + +#ifdef STUPID_SUN_BUG + yppushresp_xfr + YPPUSHPROC_XFRRESP(void) = 1; +#else + void + YPPUSHPROC_XFRRESP(yppushresp_xfr) = 1; +#endif + } = 1; +} = 0x40000000; /* transient: could be anything up to 0x5fffffff */ + +/* + * YP binding protocol + */ +program YPBINDPROG { + version YPBINDVERS { + void + YPBINDPROC_NULL(void) = 0; + + ypbind_resp + YPBINDPROC_DOMAIN(domainname) = 1; + + void + YPBINDPROC_SETDOM(ypbind_setdom) = 2; + } = 2; +} = 100007; + + diff --git a/nis/rpcsvc/yp_prot.h b/nis/rpcsvc/yp_prot.h new file mode 100644 index 0000000000..60c24a2f5f --- /dev/null +++ b/nis/rpcsvc/yp_prot.h @@ -0,0 +1,334 @@ +/* + * This file contains symbols and structures defining the rpc protocol + * between the NIS clients and the NIS servers. The servers + * are the NIS database servers, and the NIS binders. + */ + +#ifndef _RPCSVC_YP_PROT_H +#define _RPCSVC_YP_PROT_H + +#include <features.h> + +#include <rpc/rpc.h> +#include <rpcsvc/ypclnt.h> + +/* + * The following procedures are supported by the protocol: + * + * YPPROC_NULL() returns () takes nothing, returns nothing. This indicates + * that the NIS server is alive. + * + * YPPROC_DOMAIN (char *) returns (bool_t) TRUE. Indicates that the + * responding NIS server does serve the named domain; FALSE indicates no + * support. + * + * YPPROC_DOMAIN_NONACK (char *) returns (TRUE) if the NIS server does serve + * the named domain, otherwise does not return. Used in the broadcast case. + * + * YPPROC_MATCH (struct ypreq_key) returns (struct ypresp_val). Returns the + * right-hand value for a passed left-hand key, within a named map and + * domain. + * + * YPPROC_FIRST (struct ypreq_nokey) returns (struct ypresp_key_val). + * Returns the first key-value pair from a named domain and map. + * + * YPPROC_NEXT (struct ypreq_key) returns (struct ypresp_key_val). Returns + * the key-value pair following a passed key-value pair within a named + * domain and map. + * + * YPPROC_XFR (struct ypreq_xfr) returns nothing. Indicates to a server that + * a map should be updated. + * + * YPPROC_CLEAR takes nothing, returns nothing. Instructs a NIS server to + * close the current map, so that old versions of the disk file don't get + * held open. + * + * YPPROC_ALL (struct ypreq_nokey), returns + * union switch (bool_t more) { + * TRUE: (struct ypresp_key_val); + * FALSE: (struct) {}; + * } + * + * YPPROC_MASTER (struct ypreq_nokey), returns (ypresp_master) + * + * YPPROC_ORDER (struct ypreq_nokey), returns (ypresp_order) + * + * YPPROC_MAPLIST (char *), returns (struct ypmaplist *) + */ + +/* Program and version symbols, magic numbers */ + +#define YPPROG ((u_long)100004) +#define YPVERS ((u_long)2) +#define YPVERS_ORIG ((u_long)1) +#define YPMAXRECORD ((u_long)1024) +#define YPMAXDOMAIN ((u_long)256) +#define YPMAXMAP ((u_long)64) +#define YPMAXPEER ((u_long)256) + +/* byte size of a large NIS packet */ +#define YPMSGSZ 1600 + +#ifndef DATUM +typedef struct { + char *dptr; + int dsize; +} datum; +#define DATUM +#endif + +struct ypmap_parms { + char *domain; /* Null string means not available */ + char *map; /* Null string means not available */ + unsigned long int ordernum; /* 0 means not available */ + char *owner; /* Null string means not available */ +}; + +/* + * Request parameter structures + */ + +struct ypreq_key { + char *domain; + char *map; + datum keydat; +}; + +struct ypreq_nokey { + char *domain; + char *map; +}; + +struct ypreq_xfr { + struct ypmap_parms map_parms; + unsigned long transid; + unsigned long proto; + unsigned short port; +}; + +struct ypreq_newxfr { + struct ypmap_parms map_parms; + unsigned long transid; + unsigned long proto; + char *name; +}; + +#define ypxfr_domain map_parms.domain +#define ypxfr_map map_parms.map +#define ypxfr_ordernum map_parms.ordernum +#define ypxfr_owner map_parms.owner + +/* + * Response parameter structures + */ + +struct ypresp_val { + long unsigned status; + datum valdat; +}; + +struct ypresp_key_val { + long unsigned status; + datum keydat; + datum valdat; +}; + +struct ypresp_master { + long unsigned status; + char *master; +}; + +struct ypresp_order { + long unsigned status; + unsigned long int ordernum; +}; + +struct ypmaplist { + char ypml_name[YPMAXMAP + 1]; + struct ypmaplist *ypml_next; +}; + +struct ypresp_maplist { + long unsigned status; + struct ypmaplist *list; +}; + +/* + * Procedure symbols. YPPROC_NULL, YPPROC_DOMAIN, and YPPROC_DOMAIN_NONACK + * must keep the same values (0, 1, and 2) that they had in the first version + * of the protocol. + */ + +#define YPPROC_NULL ((u_long)0) +#define YPPROC_DOMAIN ((u_long)1) +#define YPPROC_DOMAIN_NONACK ((u_long)2) +#define YPPROC_MATCH ((u_long)3) +#define YPPROC_FIRST ((u_long)4) +#define YPPROC_NEXT ((u_long)5) +#define YPPROC_XFR ((u_long)6) +#define YPPROC_CLEAR ((u_long)7) +#define YPPROC_ALL ((u_long)8) +#define YPPROC_MASTER ((u_long)9) +#define YPPROC_ORDER ((u_long)10) +#define YPPROC_MAPLIST ((u_long)11) +#define YPPROC_NEWXFR ((u_long)12) + +/* Return status values */ + +#define YP_TRUE ((long)1) /* General purpose success code */ +#define YP_NOMORE ((long)2) /* No more entries in map */ +#define YP_FALSE ((long)0) /* General purpose failure code */ +#define YP_NOMAP ((long)-1) /* No such map in domain */ +#define YP_NODOM ((long)-2) /* Domain not supported */ +#define YP_NOKEY ((long)-3) /* No such key in map */ +#define YP_BADOP ((long)-4) /* Invalid operation */ +#define YP_BADDB ((long)-5) /* Server data base is bad */ +#define YP_YPERR ((long)-6) /* NIS server error */ +#define YP_BADARGS ((long)-7) /* Request arguments bad */ +#define YP_VERS ((long)-8) /* NIS server version mismatch - server + * can't supply requested service. */ +/* + * Protocol between clients and NIS binder servers + */ + +/* + * The following procedures are supported by the protocol: + * + * YPBINDPROC_NULL() returns () + * takes nothing, returns nothing + * + * YPBINDPROC_DOMAIN takes (char *) returns (struct ypbind_resp) + * + * YPBINDPROC_SETDOM takes (struct ypbind_setdom) returns nothing + */ + +/* Program and version symbols, magic numbers */ + +#define YPBINDPROG ((u_long)100007) +#define YPBINDVERS ((u_long)2) +#define YPBINDVERS_ORIG ((u_long)1) + +/* Procedure symbols */ + +#define YPBINDPROC_NULL ((u_long)0) +#define YPBINDPROC_DOMAIN ((u_long)1) +#define YPBINDPROC_SETDOM ((u_long)2) +/* + * Response structure and overall result status codes. Success and failure + * represent two separate response message types. + */ + +enum ypbind_resptype {YPBIND_SUCC_VAL = 1, YPBIND_FAIL_VAL = 2}; + +struct ypbind_binding { + struct in_addr ypbind_binding_addr; /* In network order */ + unsigned short int ypbind_binding_port; /* In network order */ +}; + +struct ypbind_resp { + enum ypbind_resptype ypbind_status; + union { + unsigned long ypbind_error; + struct ypbind_binding ypbind_bindinfo; + } ypbind_respbody; +}; + + +/* Detailed failure reason codes for response field ypbind_error*/ + +#define YPBIND_ERR_ERR 1 /* Internal error */ +#define YPBIND_ERR_NOSERV 2 /* No bound server for passed domain */ +#define YPBIND_ERR_RESC 3 /* System resource allocation failure */ + +/* + * Request data structure for ypbind "Set domain" procedure. + */ +struct ypbind_setdom { + char ypsetdom_domain[YPMAXDOMAIN + 1]; + struct ypbind_binding ypsetdom_binding; + unsigned short ypsetdom_vers; +}; +#define ypsetdom_addr ypsetdom_binding.ypbind_binding_addr +#define ypsetdom_port ypsetdom_binding.ypbind_binding_port + +/* + * Protocol between clients (ypxfr, only) and yppush + * yppush speaks a protocol in the transient range, which + * is supplied to ypxfr as a command-line parameter when it + * is activated by ypserv. + */ +#define YPPUSHVERS ((u_long) 1) +#define YPPUSHVERS_ORIG ((u_long)1) + +/* Procedure symbols */ + +#define YPPUSHPROC_NULL ((u_long)0) +#define YPPUSHPROC_XFRRESP ((u_long)1) + +struct yppushresp_xfr { + unsigned long transid; + unsigned long status; +}; + +/* Status values for yppushresp_xfr.status */ + +#define YPPUSH_SUCC ((long)1) /* Success */ +#define YPPUSH_AGE ((long)2) /* Master's version not newer */ +#define YPPUSH_NOMAP ((long)-1) /* Can't find server for map */ +#define YPPUSH_NODOM ((long)-2) /* Domain not supported */ +#define YPPUSH_RSRC ((long)-3) /* Local resouce alloc failure */ +#define YPPUSH_RPC ((long)-4) /* RPC failure talking to server */ +#define YPPUSH_MADDR ((long)-5) /* Can't get master address */ +#define YPPUSH_YPERR ((long)-6) /* NIS server/map db error */ +#define YPPUSH_BADARGS ((long)-7) /* Request arguments bad */ +#define YPPUSH_DBM ((long)-8) /* Local dbm operation failed */ +#define YPPUSH_FILE ((long)-9) /* Local file I/O operation failed */ +#define YPPUSH_SKEW ((long)-10) /* Map version skew during transfer */ +#define YPPUSH_CLEAR ((long)-11) /* Can't send "Clear" req to local + * ypserv */ +#define YPPUSH_FORCE ((long)-12) /* No local order number in map - + * use -f flag. */ +#define YPPUSH_XFRERR ((long)-13) /* ypxfr error */ +#define YPPUSH_REFUSED ((long)-14) /* Transfer request refused by ypserv */ +#define YPPUSH_NOALIAS ((long)-15) /* Alias not found for map or domain */ + +struct ypresp_all { + bool_t more; + union { + struct ypresp_key_val val; + } ypresp_all_u; +}; + +__BEGIN_DECLS + +extern bool_t xdr_datum __P ((XDR *__xdrs, datum * __objp)); +extern bool_t xdr_ypdomain_wrap_string __P ((XDR *__xdrs, char ** __objp)); +extern bool_t xdr_ypmap_wrap_string __P ((XDR *__xdrs, char ** __objp)); +extern bool_t xdr_ypreq_key __P ((XDR *__xdrs, struct ypreq_key * __objp)); +extern bool_t xdr_ypreq_nokey __P ((XDR *__xdrs, struct ypreq_nokey * __objp)); +extern bool_t xdr_ypreq_xfr __P ((XDR *__xdrs, struct ypreq_xfr * __objp)); +extern bool_t xdr_ypreq_newxfr __P ((XDR *__xdrs, struct ypreq_newxfr * __objp)); +extern bool_t xdr_ypresp_val __P ((XDR *__xdrs, struct ypresp_val * __objp)); +extern bool_t xdr_ypresp_key_val __P ((XDR *__xdrs, struct ypresp_key_val * __objp)); +extern bool_t xdr_ypbind_resp __P ((XDR *__xdrs, struct ypbind_resp * __objp)); +extern bool_t xdr_ypbind_setdom __P ((XDR *__xdrs, struct ypbind_setdom * __objp)); +extern bool_t xdr_ypmap_parms __P ((XDR *__xdrs, struct ypmap_parms * __objp)); +extern bool_t xdr_ypowner_wrap_string __P ((XDR *__xdrs, char ** __objp)); +extern bool_t xdr_yppushresp_xfr __P ((XDR *__xdrs, struct yppushresp_xfr * __objp)); +extern bool_t xdr_ypresp_order __P ((XDR *__xdrs, struct ypresp_order * __objp)); +extern bool_t xdr_ypresp_master __P ((XDR *__xdrs, struct ypresp_master * __objp)); +extern bool_t xdr_ypall __P ((XDR *__xdrs, struct ypall_callback * __objp)); +extern bool_t xdr_ypresp_maplist __P ((XDR *__xdrs, struct ypresp_maplist * __objp)); + +extern bool_t xdr_domainname_ypbind __P ((XDR *__xdrs, char * __objp)); +extern bool_t xdr_ypbind_binding __P ((XDR *__xdrs, struct ypbind_binding * __objp)); +extern bool_t xdr_ypbind_resptype __P ((XDR *__xdrs, enum ypbind_resptype * __objp)); +extern bool_t xdr_ypstat __P ((XDR *__xdrs, enum ypbind_resptype * __objp)); +extern bool_t xdr_ypresp_all __P ((XDR *__xdrs, struct ypresp_all * __objp)); +extern bool_t xdr_ypresp_all_seq __P ((XDR *__xdrs, u_long * __objp)); +extern bool_t xdr_ypmaplist_str __P ((XDR *__xdrs, char * __objp)); +extern bool_t xdr_ypmaplist __P ((XDR *__xdrs, struct ypmaplist * __objp)); + +__END_DECLS + +#endif /* _RPCSVC_YP_PROT_H */ diff --git a/nis/rpcsvc/ypclnt.h b/nis/rpcsvc/ypclnt.h new file mode 100644 index 0000000000..b61a498417 --- /dev/null +++ b/nis/rpcsvc/ypclnt.h @@ -0,0 +1,88 @@ +/* +** Copyright (c) 1996 Thorsten Kukuk, Germany +** +** This 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. +** +** This 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 this library; if not, write to the Free +** Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +** +** Author: Thorsten Kukuk <kukuk@vt.uni-paderborn.de> +** +*/ + +#ifndef __RPCSVC_YPCLNT_H__ +#define __RPCSVC_YPCLNT_H__ + +#include <features.h> + +/* some defines */ +#define YPERR_SUCCESS 0 /* There is no error */ +#define YPERR_BADARGS 1 /* Args to function are bad */ +#define YPERR_RPC 2 /* RPC failure */ +#define YPERR_DOMAIN 3 /* Can't bind to a server with this domain */ +#define YPERR_MAP 4 /* No such map in server's domain */ +#define YPERR_KEY 5 /* No such key in map */ +#define YPERR_YPERR 6 /* Internal yp server or client error */ +#define YPERR_RESRC 7 /* Local resource allocation failure */ +#define YPERR_NOMORE 8 /* No more records in map database */ +#define YPERR_PMAP 9 /* Can't communicate with portmapper */ +#define YPERR_YPBIND 10 /* Can't communicate with ypbind */ +#define YPERR_YPSERV 11 /* Can't communicate with ypserv */ +#define YPERR_NODOM 12 /* Local domain name not set */ +#define YPERR_BADDB 13 /* yp data base is bad */ +#define YPERR_VERS 14 /* YP version mismatch */ +#define YPERR_ACCESS 15 /* Access violation */ +#define YPERR_BUSY 16 /* Database is busy */ + +/* Types of update operations */ +#define YPOP_CHANGE 1 /* change, do not add */ +#define YPOP_INSERT 2 /* add, do not change */ +#define YPOP_DELETE 3 /* delete this entry */ +#define YPOP_STORE 4 /* add, or change */ + +__BEGIN_DECLS + +/* struct ypall_callback * is the arg which must be passed to yp_all */ +struct ypall_callback { + int (*foreach)(); + char *data; +}; + +/* External NIS client function references. */ +extern int yp_bind __P ((__const char *)); +extern void yp_unbind __P ((__const char *)); +extern int yp_get_default_domain __P ((char **)); +extern int yp_match __P ((__const char *, __const char *, __const char *, + __const int, char **, int *)); +extern int yp_first __P ((__const char *, __const char *, char **, + int *, char **, int *)); +extern int yp_next __P ((__const char *, __const char *, __const char *, + __const int, char **, int *, char **, int *)); +extern int yp_master __P ((__const char *, __const char *, char **)); +extern int yp_order __P ((__const char *, __const char *, unsigned int *)); +extern int yp_all __P ((__const char *, __const char *, + __const struct ypall_callback *)); +extern __const char *yperr_string __P ((__const int)); +extern __const char *ypbinderr_string __P ((__const int)); +extern int ypprot_err __P ((__const int)); +extern int yp_update __P ((char *, char *, unsigned, char *, + int, char *, int)); +#if 0 +extern int yp_maplist __P ((__const char *, struct ypmaplist **)); +#endif + +/* Exist only under BSD and Linux systems */ +extern int __yp_check __P ((char **)); + +__END_DECLS + +#endif /* __RPCSVC_YPCLNT_H__ */ diff --git a/nis/rpcsvc/ypupd.h b/nis/rpcsvc/ypupd.h new file mode 100644 index 0000000000..dace7824d4 --- /dev/null +++ b/nis/rpcsvc/ypupd.h @@ -0,0 +1,88 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (c) 1986, 1990 by Sun Microsystems, Inc. + */ +/* from @(#)ypupdate_prot.x 1.3 91/03/11 TIRPC 1.0 */ + +#ifndef __RPCSVC_YPUPD_H__ +#define __RPCSVC_YPUPD_H__ + +#include <features.h> + +#include <rpc/rpc.h> + +#define MAXMAPNAMELEN 255 +#define MAXYPDATALEN 1023 +#define MAXERRMSGLEN 255 + +__BEGIN_DECLS + +typedef struct { + u_int yp_buf_len; + char *yp_buf_val; +} yp_buf; + +extern bool_t xdr_yp_buf __P ((XDR *, yp_buf*)); + +struct ypupdate_args { + char *mapname; + yp_buf key; + yp_buf datum; +}; +typedef struct ypupdate_args ypupdate_args; + +extern bool_t xdr_ypupdate_args __P ((XDR *, ypupdate_args*)); + +struct ypdelete_args { + char *mapname; + yp_buf key; +}; +typedef struct ypdelete_args ypdelete_args; + +extern bool_t xdr_ypdelete_args __P ((XDR *, ypdelete_args*)); + +#define YPU_PROG ((u_long)100028) +#define YPU_VERS ((u_long)1) + +#define YPU_CHANGE ((u_long)1) +extern u_int * ypu_change_1 __P ((ypupdate_args *, CLIENT *)); +extern u_int * ypu_change_1_svc __P((ypupdate_args *, struct svc_req *)); +#define YPU_INSERT ((u_long)2) +extern u_int * ypu_insert_1 __P ((ypupdate_args *, CLIENT *)); +extern u_int * ypu_insert_1_svc __P ((ypupdate_args *, struct svc_req *)); +#define YPU_DELETE ((u_long)3) +extern u_int * ypu_delete_1 __P ((ypdelete_args *, CLIENT *)); +extern u_int * ypu_delete_1_svc __P ((ypdelete_args *, struct svc_req *)); +#define YPU_STORE ((u_long)4) +extern u_int * ypu_store_1 __P ((ypupdate_args *, CLIENT *)); +extern u_int * ypu_store_1_svc __P ((ypupdate_args *, struct svc_req *)); + +#endif /* !__RPCSVC_YPUPD_H__ */ diff --git a/nis/yp_xdr.c b/nis/yp_xdr.c new file mode 100644 index 0000000000..e6477be778 --- /dev/null +++ b/nis/yp_xdr.c @@ -0,0 +1,342 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ + +#include <rpcsvc/yp.h> + +bool_t +xdr_ypstat (XDR *xdrs, ypstat *objp) +{ + if (!xdr_enum(xdrs, (enum_t *)objp)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_ypxfrstat(XDR *xdrs, ypxfrstat *objp) +{ + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_domainname(XDR *xdrs, domainname *objp) +{ + if (!xdr_string(xdrs, objp, YPMAXDOMAIN)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_mapname(XDR *xdrs, mapname *objp) +{ + if (!xdr_string(xdrs, objp, YPMAXMAP)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_peername(XDR *xdrs, peername *objp) +{ + if (!xdr_string(xdrs, objp, YPMAXPEER)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_keydat(XDR *xdrs, keydat *objp) +{ + if (!xdr_bytes(xdrs, (char **)&objp->keydat_val, (u_int *)&objp->keydat_len, YPMAXRECORD)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_valdat(XDR *xdrs, valdat *objp) +{ + if (!xdr_bytes(xdrs, (char **)&objp->valdat_val, (u_int *)&objp->valdat_len, YPMAXRECORD)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypmap_parms(XDR *xdrs, ypmap_parms *objp) +{ + if (!xdr_domainname(xdrs, &objp->domain)) { + return (FALSE); + } + if (!xdr_mapname(xdrs, &objp->map)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->ordernum)) { + return (FALSE); + } + if (!xdr_peername(xdrs, &objp->peer)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypreq_key(XDR *xdrs, ypreq_key *objp) +{ + if (!xdr_domainname(xdrs, &objp->domain)) { + return (FALSE); + } + if (!xdr_mapname(xdrs, &objp->map)) { + return (FALSE); + } + if (!xdr_keydat(xdrs, &objp->key)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypreq_nokey(XDR *xdrs, ypreq_nokey *objp) +{ + if (!xdr_domainname(xdrs, &objp->domain)) { + return (FALSE); + } + if (!xdr_mapname(xdrs, &objp->map)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypreq_xfr(XDR *xdrs, ypreq_xfr *objp) +{ + if (!xdr_ypmap_parms(xdrs, &objp->map_parms)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->transid)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->prog)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->port)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypresp_val(XDR *xdrs, ypresp_val *objp) +{ + if (!xdr_ypstat(xdrs, &objp->stat)) { + return (FALSE); + } + if (!xdr_valdat(xdrs, &objp->val)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypresp_key_val(XDR *xdrs, ypresp_key_val *objp) +{ + if (!xdr_ypstat(xdrs, &objp->stat)) { + return (FALSE); + } + if (!xdr_valdat(xdrs, &objp->val)) { + return (FALSE); + } + if (!xdr_keydat(xdrs, &objp->key)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypresp_master(XDR *xdrs, ypresp_master *objp) +{ + if (!xdr_ypstat(xdrs, &objp->stat)) { + return (FALSE); + } + if (!xdr_peername(xdrs, &objp->peer)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypresp_order(XDR *xdrs, ypresp_order *objp) +{ + if (!xdr_ypstat(xdrs, &objp->stat)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->ordernum)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypresp_all(XDR *xdrs, ypresp_all *objp) +{ + if (!xdr_bool(xdrs, &objp->more)) { + return (FALSE); + } + switch (objp->more) { + case TRUE: + if (!xdr_ypresp_key_val(xdrs, &objp->ypresp_all_u.val)) { + return (FALSE); + } + break; + case FALSE: + break; + default: + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypresp_xfr(XDR *xdrs, ypresp_xfr *objp) +{ + if (!xdr_u_int(xdrs, &objp->transid)) { + return (FALSE); + } + if (!xdr_ypxfrstat(xdrs, &objp->xfrstat)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypmaplist(XDR *xdrs, ypmaplist *objp) +{ + if (!xdr_mapname(xdrs, &objp->map)) { + return (FALSE); + } + if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(ypmaplist), (xdrproc_t)xdr_ypmaplist)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypresp_maplist(XDR *xdrs, ypresp_maplist *objp) +{ + if (!xdr_ypstat(xdrs, &objp->stat)) { + return (FALSE); + } + if (!xdr_pointer(xdrs, (char **)&objp->maps, sizeof(ypmaplist), (xdrproc_t)xdr_ypmaplist)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_yppush_status(XDR *xdrs, yppush_status *objp) +{ + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_yppushresp_xfr(XDR *xdrs, yppushresp_xfr *objp) +{ + if (!xdr_u_int(xdrs, &objp->transid)) { + return (FALSE); + } + if (!xdr_yppush_status(xdrs, &objp->status)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypbind_resptype(XDR *xdrs, ypbind_resptype *objp) +{ + if (!xdr_enum(xdrs, (enum_t *)objp)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypbind_binding(XDR *xdrs, ypbind_binding *objp) +{ + if (!xdr_opaque(xdrs, objp->ypbind_binding_addr, 4)) { + return (FALSE); + } + if (!xdr_opaque(xdrs, objp->ypbind_binding_port, 2)) { + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypbind_resp(XDR *xdrs, ypbind_resp *objp) +{ + if (!xdr_ypbind_resptype(xdrs, &objp->ypbind_status)) { + return (FALSE); + } + switch (objp->ypbind_status) { + case YPBIND_FAIL_VAL: + if (!xdr_u_int(xdrs, &objp->ypbind_resp_u.ypbind_error)) { + return (FALSE); + } + break; + case YPBIND_SUCC_VAL: + if (!xdr_ypbind_binding(xdrs, &objp->ypbind_resp_u.ypbind_bindinfo)) { + return (FALSE); + } + break; + default: + return (FALSE); + } + return (TRUE); +} + +bool_t +xdr_ypbind_setdom(XDR *xdrs, ypbind_setdom *objp) +{ + if (!xdr_domainname(xdrs, &objp->ypsetdom_domain)) { + return (FALSE); + } + if (!xdr_ypbind_binding(xdrs, &objp->ypsetdom_binding)) { + return (FALSE); + } + if (!xdr_u_int(xdrs, &objp->ypsetdom_vers)) { + return (FALSE); + } + return (TRUE); +} diff --git a/nis/ypclnt.c b/nis/ypclnt.c new file mode 100644 index 0000000000..3e05cf984c --- /dev/null +++ b/nis/ypclnt.c @@ -0,0 +1,868 @@ +/* Copyright (C) 1996 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996. + + 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, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <libc-lock.h> +#include <rpcsvc/yp.h> +#include <rpcsvc/ypclnt.h> +#include <rpcsvc/ypupd.h> + +struct dom_binding + { + struct dom_binding *dom_pnext; + char dom_domain[YPMAXDOMAIN + 1]; + struct sockaddr_in dom_server_addr; + int dom_socket; + CLIENT *dom_client; + long int dom_vers; + }; +typedef struct dom_binding dom_binding; + +static struct timeval TIMEOUT = {25, 0}; +static int const MAXTRIES = 5; +static char __ypdomainname[MAXHOSTNAMELEN + 1] = "\0"; +__libc_lock_define_initialized (static, ypbindlist_lock) +static dom_binding *__ypbindlist = NULL; + +static int +__yp_bind (char *domain, dom_binding ** ypdb) +{ + struct sockaddr_in clnt_saddr; + struct ypbind_resp ypbr; + dom_binding *ysd; + int clnt_sock; + CLIENT *client; + int is_new = 0; + int try; + + if (ypdb != NULL) + *ypdb = NULL; + + if ((domain == NULL) || (strlen (domain) == 0)) + return YPERR_BADARGS; + + ysd = __ypbindlist; + while (ysd != NULL) + { + if (strcmp (domain, ysd->dom_domain) == 0) + break; + ysd = ysd->dom_pnext; + } + + if (ysd == NULL) + { + is_new = 1; + ysd = (dom_binding *) malloc (sizeof *ysd); + memset (ysd, '\0', sizeof *ysd); + ysd->dom_socket = -1; + ysd->dom_vers = -1; + } + + try = 0; + + do + { + try++; + if (try > MAXTRIES) + { + if (is_new) + free (ysd); + return YPERR_YPBIND; + } + + if (ysd->dom_vers == -1) + { + if(ysd->dom_client) + { + clnt_destroy(ysd->dom_client); + ysd->dom_client = NULL; + ysd->dom_socket = -1; + } + memset (&clnt_saddr, '\0', sizeof clnt_saddr); + clnt_saddr.sin_family = AF_INET; + clnt_saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + clnt_sock = RPC_ANYSOCK; + client = clnttcp_create (&clnt_saddr, YPBINDPROG, YPBINDVERS, + &clnt_sock, 0, 0); + if (client == NULL) + { + if (is_new) + free (ysd); + return YPERR_YPBIND; + } + /* + ** Check the port number -- should be < IPPORT_RESERVED. + ** If not, it's possible someone has registered a bogus + ** ypbind with the portmapper and is trying to trick us. + */ + if (ntohs(clnt_saddr.sin_port) >= IPPORT_RESERVED) + { + clnt_destroy(client); + if (is_new) + free(ysd); + return(YPERR_YPBIND); + } + + if (clnt_call (client, YPBINDPROC_DOMAIN, + (xdrproc_t) xdr_domainname, &domain, + (xdrproc_t) xdr_ypbind_resp, + &ypbr, TIMEOUT) != RPC_SUCCESS) + { + clnt_destroy (client); + if (is_new) + free (ysd); + return YPERR_YPBIND; + } + + clnt_destroy (client); + if (ypbr.ypbind_status != YPBIND_SUCC_VAL) + { + switch (ypbr.ypbind_resp_u.ypbind_error) + { + case YPBIND_ERR_ERR: + fputs (_("YPBINDPROC_DOMAIN: Internal error\n"), stderr); + break; + case YPBIND_ERR_NOSERV: + fprintf (stderr, + _("YPBINDPROC_DOMAIN: No server for domain %s\n"), + domain); + break; + case YPBIND_ERR_RESC: + fputs (_("YPBINDPROC_DOMAIN: Resource allocation failure\n"), + stderr); + break; + default: + fputs (_("YPBINDPROC_DOMAIN: Unknown error\n"), stderr); + break; + } + if (is_new) + free (ysd); + return YPERR_DOMAIN; + } + memset (&ysd->dom_server_addr, '\0', sizeof ysd->dom_server_addr); + ysd->dom_server_addr.sin_family = AF_INET; + memcpy (&ysd->dom_server_addr.sin_port, + ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port, + sizeof (ysd->dom_server_addr.sin_port)); + memcpy (&ysd->dom_server_addr.sin_addr.s_addr, + ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr, + sizeof (ysd->dom_server_addr.sin_addr.s_addr)); + ysd->dom_vers = YPVERS; + strcpy (ysd->dom_domain, domain); + } + + if (ysd->dom_client) + clnt_destroy (ysd->dom_client); + ysd->dom_socket = RPC_ANYSOCK; + ysd->dom_client = clntudp_create (&ysd->dom_server_addr, YPPROG, YPVERS, + TIMEOUT, &ysd->dom_socket); + if (ysd->dom_client == NULL) + ysd->dom_vers = -1; + + } + while (ysd->dom_client == NULL); + + /* If the program exists, close the socket */ + if (fcntl (ysd->dom_socket, F_SETFD, 1) == -1) + perror (_("fcntl: F_SETFD")); + + if (is_new) + { + ysd->dom_pnext = __ypbindlist; + __ypbindlist = ysd; + } + + if (NULL != ypdb) + *ypdb = ysd; + + return YPERR_SUCCESS; +} + +static void +__yp_unbind (dom_binding *ydb) +{ + clnt_destroy (ydb->dom_client); + ydb->dom_client = NULL; + ydb->dom_socket = -1; +} + +static int +do_ypcall (const char *domain, u_long prog, xdrproc_t xargs, + caddr_t req, xdrproc_t xres, caddr_t resp) +{ + dom_binding *ydb = NULL; + int try, result; + + try = 0; + result = YPERR_YPERR; + + while (try < MAXTRIES && result != RPC_SUCCESS) + { + __libc_lock_lock (ypbindlist_lock); + + if (__yp_bind (domain, &ydb) != 0) + { + __libc_lock_unlock (ypbindlist_lock); + return YPERR_DOMAIN; + } + + result = clnt_call (ydb->dom_client, prog, + xargs, req, xres, resp, TIMEOUT); + + if (result != RPC_SUCCESS) + { + clnt_perror (ydb->dom_client, "do_ypcall: clnt_call"); + ydb->dom_vers = -1; + __yp_unbind (ydb); + result = YPERR_RPC; + } + + __libc_lock_unlock (ypbindlist_lock); + + try++; + } + + return result; +} + +int +yp_bind (const char *indomain) +{ + int status; + + __libc_lock_lock (ypbindlist_lock); + + status = __yp_bind (indomain, NULL); + + __libc_lock_unlock (ypbindlist_lock); + + return status; +} + +void +yp_unbind (const char *indomain) +{ + dom_binding *ydbptr, *ydbptr2; + + __libc_lock_lock (ypbindlist_lock); + + ydbptr2 = NULL; + ydbptr = __ypbindlist; + while (ydbptr != NULL) + { + if (strcmp (ydbptr->dom_domain, indomain) == 0) + { + dom_binding *work; + + work = ydbptr; + if (ydbptr2 == NULL) + __ypbindlist = __ypbindlist->dom_pnext; + else + ydbptr2 = ydbptr->dom_pnext; + __yp_unbind (work); + free (work); + break; + } + ydbptr2 = ydbptr; + ydbptr = ydbptr->dom_pnext; + } + + __libc_lock_unlock (ypbindlist_lock); + + return; +} + +__libc_lock_define_initialized (static, domainname_lock) + +int +yp_get_default_domain (char **outdomain) +{ + int result = YPERR_SUCCESS;; + *outdomain = NULL; + + __libc_lock_lock (domainname_lock); + + if (__ypdomainname[0] == '\0') + { + if (getdomainname (__ypdomainname, MAXHOSTNAMELEN)) + result = YPERR_NODOM; + else + *outdomain = __ypdomainname; + } + else + *outdomain = __ypdomainname; + + __libc_lock_unlock (domainname_lock); + + return result; +} + +int +__yp_check (char **domain) +{ + char *unused; + + if (__ypdomainname[0] == '\0') + if (yp_get_default_domain (&unused)) + return 0; + else if (strcmp (__ypdomainname, "(none)") == 0) + return 0; + + if (domain) + *domain = __ypdomainname; + + if (yp_bind (__ypdomainname) == 0) + return 1; + return 0; +} + +int +yp_match (const char *indomain, const char *inmap, const char *inkey, + const int inkeylen, char **outval, int *outvallen) +{ + ypreq_key req; + ypresp_val resp; + int result; + + if (indomain == NULL || indomain[0] == '\0' || + inmap == NULL || inmap[0] == '\0' || + inkey == NULL || inkey[0] == '\0' || inkeylen <= 0) + return YPERR_BADARGS; + + req.domain = indomain; + req.map = inmap; + req.key.keydat_val = inkey; + req.key.keydat_len = inkeylen; + + *outval = NULL; + *outvallen = 0; + memset (&resp, '\0', sizeof (resp)); + + result = do_ypcall (indomain, YPPROC_MATCH, (xdrproc_t) xdr_ypreq_key, + (caddr_t) & req, (xdrproc_t) xdr_ypresp_val, + (caddr_t) & resp); + + if (result != RPC_SUCCESS) + return result; + if (resp.stat != YP_TRUE) + return ypprot_err (resp.stat); + + *outvallen = resp.val.valdat_len; + *outval = malloc (*outvallen + 1); + memcpy (*outval, resp.val.valdat_val, *outvallen); + (*outval)[*outvallen] = '\0'; + + xdr_free ((xdrproc_t) xdr_ypresp_val, (char *) &resp); + + return YPERR_SUCCESS; +} + +int +yp_first (const char *indomain, const char *inmap, char **outkey, + int *outkeylen, char **outval, int *outvallen) +{ + ypreq_nokey req; + ypresp_key_val resp; + int result; + + if (indomain == NULL || indomain[0] == '\0' || + inmap == NULL || inmap[0] == '\0') + return YPERR_BADARGS; + + req.domain = indomain; + req.map = inmap; + + *outkey = *outval = NULL; + *outkeylen = *outvallen = 0; + memset (&resp, '\0', sizeof (resp)); + + result = do_ypcall (indomain, YPPROC_FIRST, (xdrproc_t) xdr_ypreq_nokey, + (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val, + (caddr_t) & resp); + + if (result != RPC_SUCCESS) + return result; + if (resp.stat != YP_TRUE) + return ypprot_err (resp.stat); + + *outkeylen = resp.key.keydat_len; + *outkey = malloc (*outkeylen + 1); + memcpy (*outkey, resp.key.keydat_val, *outkeylen); + (*outkey)[*outkeylen] = '\0'; + *outvallen = resp.val.valdat_len; + *outval = malloc (*outvallen + 1); + memcpy (*outval, resp.val.valdat_val, *outvallen); + (*outval)[*outvallen] = '\0'; + + xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp); + + return YPERR_SUCCESS; +} + +int +yp_next (const char *indomain, const char *inmap, const char *inkey, + const int inkeylen, char **outkey, int *outkeylen, char **outval, + int *outvallen) +{ + ypreq_key req; + ypresp_key_val resp; + int result; + + if (indomain == NULL || indomain[0] == '\0' || + inmap == NULL || inmap[0] == '\0' || + inkeylen <= 0 || inkey == NULL || inkey[0] == '\0') + return YPERR_BADARGS; + + req.domain = indomain; + req.map = inmap; + req.key.keydat_val = inkey; + req.key.keydat_len = inkeylen; + + *outkey = *outval = NULL; + *outkeylen = *outvallen = 0; + memset (&resp, '\0', sizeof (resp)); + + result = do_ypcall (indomain, YPPROC_NEXT, (xdrproc_t) xdr_ypreq_key, + (caddr_t) & req, (xdrproc_t) xdr_ypresp_key_val, + (caddr_t) & resp); + + if (result != RPC_SUCCESS) + return result; + if (resp.stat != YP_TRUE) + return ypprot_err (resp.stat); + + *outkeylen = resp.key.keydat_len; + *outkey = malloc (*outkeylen + 1); + memcpy (*outkey, resp.key.keydat_val, *outkeylen); + (*outkey)[*outkeylen] = '\0'; + *outvallen = resp.val.valdat_len; + *outval = malloc (*outvallen + 1); + memcpy (*outval, resp.val.valdat_val, *outvallen); + (*outval)[*outvallen] = '\0'; + + xdr_free ((xdrproc_t) xdr_ypresp_key_val, (char *) &resp); + + return YPERR_SUCCESS; +} + +int +yp_master (const char *indomain, const char *inmap, char **outname) +{ + ypreq_nokey req; + ypresp_master resp; + int result; + + if (indomain == NULL || indomain[0] == '\0' || + inmap == NULL || inmap[0] == '\0') + return YPERR_BADARGS; + + req.domain = indomain; + req.map = inmap; + + memset (&resp, '\0', sizeof (ypresp_master)); + + result = do_ypcall (indomain, YPPROC_MASTER, (xdrproc_t) xdr_ypreq_nokey, + (caddr_t) & req, (xdrproc_t) xdr_ypresp_master, (caddr_t) & resp); + + if (result != RPC_SUCCESS) + return result; + if (resp.stat != YP_TRUE) + return ypprot_err (resp.stat); + + *outname = strdup (resp.peer); + xdr_free ((xdrproc_t) xdr_ypresp_master, (char *) &resp); + + return YPERR_SUCCESS; +} + +int +yp_order (const char *indomain, const char *inmap, unsigned int *outorder) +{ + struct ypreq_nokey req; + struct ypresp_order resp; + int result; + + if (indomain == NULL || indomain[0] == '\0' || + inmap == NULL || inmap == '\0') + return YPERR_BADARGS; + + req.domain = indomain; + req.map = inmap; + + memset (&resp, '\0', sizeof (resp)); + + result = do_ypcall (indomain, YPPROC_ORDER, (xdrproc_t) xdr_ypreq_nokey, + (caddr_t) & req, (xdrproc_t) xdr_ypresp_order, (caddr_t) & resp); + + if (result != RPC_SUCCESS) + return result; + if (resp.stat != YP_TRUE) + return ypprot_err (resp.stat); + + *outorder = resp.ordernum; + xdr_free ((xdrproc_t) xdr_ypresp_order, (char *) &resp); + + return YPERR_SUCCESS; +} + +static void *ypall_data; +static int (*ypall_foreach) (); + +static bool_t +__xdr_ypresp_all (XDR * xdrs, u_long * objp) +{ + while (1) + { + struct ypresp_all resp; + + memset (&resp, '\0', sizeof (struct ypresp_all)); + if (!xdr_ypresp_all (xdrs, &resp)) + { + xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); + *objp = YP_YPERR; + return (FALSE); + } + if (resp.more == 0) + { + xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); + *objp = YP_NOMORE; + return (FALSE); + } + + switch (resp.ypresp_all_u.val.stat) + { + case YP_TRUE: + { + char key[resp.ypresp_all_u.val.key.keydat_len + 1]; + char val[resp.ypresp_all_u.val.val.valdat_len + 1]; + int keylen = resp.ypresp_all_u.val.key.keydat_len; + int vallen = resp.ypresp_all_u.val.val.valdat_len; + + *objp = YP_TRUE; + memcpy (key, resp.ypresp_all_u.val.key.keydat_val, keylen); + key[keylen] = '\0'; + memcpy (val, resp.ypresp_all_u.val.val.valdat_val, vallen); + val[vallen] = '\0'; + xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); + if ((*ypall_foreach) (*objp, key, keylen, + val, vallen, ypall_data)) + return TRUE; + } + break; + case YP_NOMORE: + *objp = YP_NOMORE; + xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); + return TRUE; + break; + default: + *objp = resp.ypresp_all_u.val.stat; + xdr_free ((xdrproc_t) xdr_ypresp_all, (char *) &resp); + return TRUE; + } + } +} + +int +yp_all (const char *indomain, const char *inmap, + const struct ypall_callback *incallback) +{ + struct ypreq_nokey req; + dom_binding *ydb; + int try, result; + struct sockaddr_in clnt_sin; + CLIENT *clnt; + unsigned long status; + int clnt_sock; + + if (indomain == NULL || indomain[0] == '\0' || + inmap == NULL || inmap == '\0') + return YPERR_BADARGS; + + try = 0; + result = YPERR_YPERR; + + while (try < MAXTRIES && result != RPC_SUCCESS) + { + __libc_lock_lock (ypbindlist_lock); + + if (__yp_bind (indomain, &ydb) != 0) + { + __libc_lock_unlock (ypbindlist_lock); + return YPERR_DOMAIN; + } + + /* YPPROC_ALL get its own TCP channel to ypserv */ + clnt_sock = RPC_ANYSOCK; + clnt_sin = ydb->dom_server_addr; + clnt_sin.sin_port = 0; + clnt = clnttcp_create (&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0); + if (clnt == NULL) + { + puts ("yp_all: clnttcp_create failed"); + __libc_lock_unlock (ypbindlist_lock); + return YPERR_PMAP; + } + req.domain = indomain; + req.map = inmap; + + ypall_foreach = incallback->foreach; + ypall_data = (void *) incallback->data; + + result = clnt_call (clnt, YPPROC_ALL, (xdrproc_t) xdr_ypreq_nokey, &req, + (xdrproc_t) __xdr_ypresp_all, &status, TIMEOUT); + + if (result != RPC_SUCCESS) + { + clnt_perror (ydb->dom_client, "yp_all: clnt_call"); + clnt_destroy (clnt); + __yp_unbind (ydb); + result = YPERR_RPC; + } + else + { + clnt_destroy (clnt); + result = YPERR_SUCCESS; + } + + __libc_lock_unlock (ypbindlist_lock); + + if (status != YP_NOMORE) + return ypprot_err (status); + try++; + } + + return result; +} + +int +yp_maplist (const char *indomain, struct ypmaplist **outmaplist) +{ + struct ypresp_maplist resp; + int result; + + if (indomain == NULL || indomain[0] == '\0') + return YPERR_BADARGS; + + memset (&resp, '\0', sizeof (resp)); + + result = do_ypcall (indomain, YPPROC_MAPLIST, (xdrproc_t) xdr_domainname, + (caddr_t) & indomain, (xdrproc_t) xdr_ypresp_maplist, (caddr_t) & resp); + + if (result != RPC_SUCCESS) + return result; + if (resp.stat != YP_TRUE) + return ypprot_err (resp.stat); + + *outmaplist = resp.maps; + /* We give the list not free, this will be done by ypserv + xdr_free((xdrproc_t)xdr_ypresp_maplist, (char *)&resp); */ + + return YPERR_SUCCESS; +} + +const char * +yperr_string (const int error) +{ + switch (error) + { + case YPERR_SUCCESS: + return _("Success"); + case YPERR_BADARGS: + return _("Request arguments bad"); + case YPERR_RPC: + return _("RPC failure on NIS operation"); + case YPERR_DOMAIN: + return _("Can't bind to server which serves this domain"); + case YPERR_MAP: + return _("No such map in server's domain"); + case YPERR_KEY: + return _("No such key in map"); + case YPERR_YPERR: + return _("Internal NIS error"); + case YPERR_RESRC: + return _("Local resource allocation failure"); + case YPERR_NOMORE: + return _("No more records in map database"); + case YPERR_PMAP: + return _("Can't communicate with portmapper"); + case YPERR_YPBIND: + return _("Can't communicate with ypbind"); + case YPERR_YPSERV: + return _("Can't communicate with ypserv"); + case YPERR_NODOM: + return _("Local domain name not set"); + case YPERR_BADDB: + return _("NIS map data base is bad"); + case YPERR_VERS: + return _("NIS client/server version mismatch - can't supply service"); + case YPERR_ACCESS: + return _("Permission denied"); + case YPERR_BUSY: + return _("Database is busy"); + } + return _("Unknown NIS error code"); +} + +int +ypprot_err (const int code) +{ + switch (code) + { + case YP_TRUE: + return YPERR_SUCCESS; + case YP_NOMORE: + return YPERR_NOMORE; + case YP_FALSE: + return YPERR_YPERR; + case YP_NOMAP: + return YPERR_MAP; + case YP_NODOM: + return YPERR_DOMAIN; + case YP_NOKEY: + return YPERR_KEY; + case YP_BADOP: + return YPERR_YPERR; + case YP_BADDB: + return YPERR_BADDB; + case YP_YPERR: + return YPERR_YPERR; + case YP_BADARGS: + return YPERR_BADARGS; + case YP_VERS: + return YPERR_VERS; + } + return YPERR_YPERR; +} + +const char * +ypbinderr_string (const int error) +{ + switch (error) + { + case 0: + return _("Success"); + case YPBIND_ERR_ERR: + return _("Internal ypbind error"); + case YPBIND_ERR_NOSERV: + return _("Domain not bound"); + case YPBIND_ERR_RESC: + return _("System resource allocation failure"); + default: + return _("Unknown ypbind error"); + } +} + + +#define WINDOW 60 + +int +yp_update (char *domain, char *map, unsigned ypop, + char *key, int keylen, char *data, int datalen) +{ +#if 0 + union + { + ypupdate_args update_args; + ypdelete_args delete_args; + } + args; + xdrproc_t xdr_argument; + unsigned res = 0; + CLIENT *clnt; + char *master; + struct sockaddr saddr; + char servername[MAXNETNAMELEN + 1]; + int r; + + if (!domain || !map || !key || (ypop != YPOP_DELETE && !data)) + return YPERR_BADARGS; + + args.update_args.mapname = map; + args.update_args.key.yp_buf_len = keylen; + args.update_args.key.yp_buf_val = key; + args.update_args.datum.yp_buf_len = datalen; + args.update_args.datum.yp_buf_val = data; + + if ((r = yp_master (domain, map, &master)) != 0) + return r; + + if (!host2netname (servername, master, domain)) + { + fputs (_("yp_update: cannot convert host to netname\n"), stderr); + return YPERR_YPERR; + } + + if ((clnt = clnt_create (master, YPU_PROG, YPU_VERS, "tcp")) == NULL) + { + clnt_pcreateerror ("yp_update: clnt_create"); + return YPERR_RPC; + } + + if (!clnt_control (clnt, CLGET_SERVER_ADDR, (char *) &saddr)) + { + fputs (_("yp_update: cannot get server address\n"), stderr); + return YPERR_RPC; + } + + switch (ypop) + { + case YPOP_CHANGE: + case YPOP_INSERT: + case YPOP_STORE: + xdr_argument = (xdrproc_t) xdr_ypupdate_args; + break; + case YPOP_DELETE: + xdr_argument = (xdrproc_t) xdr_ypdelete_args; + break; + default: + return YPERR_BADARGS; + break; + } + + clnt->cl_auth = authdes_create (servername, WINDOW, &saddr, NULL); + + if (clnt->cl_auth == NULL) + clnt->cl_auth = authunix_create_default (); + +again: + r = clnt_call (clnt, ypop, xdr_argument, &args, + (xdrproc_t) xdr_u_int, &res, TIMEOUT); + + if (r == RPC_AUTHERROR) + { + if (clnt->cl_auth->ah_cred.oa_flavor == AUTH_DES) + { + clnt->cl_auth = authunix_create_default (); + goto again; + } + else + return YPERR_ACCESS; + } + if (r != RPC_SUCCESS) + { + clnt_perror (clnt, "yp_update: clnt_call"); + return YPERR_RPC; + } + return res; +#else + return YPERR_YPERR; +#endif +} diff --git a/nis/ypupdate_xdr.c b/nis/ypupdate_xdr.c new file mode 100644 index 0000000000..53624337ab --- /dev/null +++ b/nis/ypupdate_xdr.c @@ -0,0 +1,73 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part. Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California 94043 + */ +/* + * Copyright (c) 1986, 1990 by Sun Microsystems, Inc. + */ + +/* from @(#)ypupdate_prot.x 1.3 91/03/11 TIRPC 1.0 */ + +/* + * Compiled from ypupdate_prot.x using rpcgen + * This is NOT source code! + * DO NOT EDIT THIS FILE! + */ + + +#include <rpcsvc/ypupd.h> + +bool_t +xdr_yp_buf (XDR * xdrs, yp_buf * objp) +{ + if (!xdr_bytes (xdrs, (char **) &objp->yp_buf_val, (u_int *) & objp->yp_buf_len, MAXYPDATALEN)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_ypupdate_args (XDR * xdrs, ypupdate_args * objp) +{ + if (!xdr_string (xdrs, &objp->mapname, MAXMAPNAMELEN)) + return (FALSE); + if (!xdr_yp_buf (xdrs, &objp->key)) + return (FALSE); + if (!xdr_yp_buf (xdrs, &objp->datum)) + return (FALSE); + return (TRUE); +} + +bool_t +xdr_ypdelete_args (XDR * xdrs, ypdelete_args * objp) +{ + if (!xdr_string (xdrs, &objp->mapname, MAXMAPNAMELEN)) + return (FALSE); + if (!xdr_yp_buf (xdrs, &objp->key)) + return (FALSE); + return (TRUE); +} |