diff options
Diffstat (limited to 'REORG.TODO/nis/nis_table.c')
-rw-r--r-- | REORG.TODO/nis/nis_table.c | 813 |
1 files changed, 813 insertions, 0 deletions
diff --git a/REORG.TODO/nis/nis_table.c b/REORG.TODO/nis/nis_table.c new file mode 100644 index 0000000000..88eb6797e6 --- /dev/null +++ b/REORG.TODO/nis/nis_table.c @@ -0,0 +1,813 @@ +/* Copyright (c) 1997-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@suse.de>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <assert.h> +#include <string.h> +#include <rpcsvc/nis.h> +#include <libc-diag.h> +#include <shlib-compat.h> + +#include "nis_xdr.h" +#include "nis_intern.h" +#include "libnsl.h" + + +struct ib_request * +__create_ib_request (const_nis_name name, unsigned int flags) +{ + struct ib_request *ibreq = calloc (1, sizeof (struct ib_request)); + nis_attr *search_val = NULL; + size_t search_len = 0; + size_t size = 0; + + if (ibreq == NULL) + return NULL; + + ibreq->ibr_flags = flags; + + char *cptr = strdupa (name); + + /* Not of "[key=value,key=value,...],foo.." format? */ + if (cptr[0] != '[') + { + ibreq->ibr_name = strdup (cptr); + if (ibreq->ibr_name == NULL) + { + free (ibreq); + return NULL; + } + return ibreq; + } + + /* "[key=value,...],foo" format */ + ibreq->ibr_name = strchr (cptr, ']'); + if (ibreq->ibr_name == NULL || ibreq->ibr_name[1] != ',') + { + /* The object has not really been built yet so we use free. */ + free (ibreq); + return NULL; + } + + /* Check if we have an entry of "[key=value,],bar". If, remove the "," */ + if (ibreq->ibr_name[-1] == ',') + ibreq->ibr_name[-1] = '\0'; + else + ibreq->ibr_name[0] = '\0'; + ibreq->ibr_name += 2; + ibreq->ibr_name = strdup (ibreq->ibr_name); + if (ibreq->ibr_name == NULL) + { + free_null: + while (search_len-- > 0) + { + free (search_val[search_len].zattr_ndx); + free (search_val[search_len].zattr_val.zattr_val_val); + } + free (search_val); + nis_free_request (ibreq); + return NULL; + } + + ++cptr; /* Remove "[" */ + + while (cptr != NULL && cptr[0] != '\0') + { + char *key = cptr; + char *val = strchr (cptr, '='); + + cptr = strchr (key, ','); + if (cptr != NULL) + *cptr++ = '\0'; + + if (__glibc_unlikely (val == NULL)) + { + nis_free_request (ibreq); + return NULL; + } + *val++ = '\0'; + if (search_len + 1 >= size) + { + size += 1; + nis_attr *newp = realloc (search_val, size * sizeof (nis_attr)); + if (newp == NULL) + goto free_null; + search_val = newp; + } + search_val[search_len].zattr_ndx = strdup (key); + if (search_val[search_len].zattr_ndx == NULL) + goto free_null; + + search_val[search_len].zattr_val.zattr_val_len = strlen (val) + 1; + search_val[search_len].zattr_val.zattr_val_val = strdup (val); + if (search_val[search_len].zattr_val.zattr_val_val == NULL) + { + free (search_val[search_len].zattr_ndx); + goto free_null; + } + + ++search_len; + } + + ibreq->ibr_srch.ibr_srch_val = search_val; + ibreq->ibr_srch.ibr_srch_len = search_len; + + return ibreq; +} +libnsl_hidden_nolink_def (__create_ib_request, GLIBC_PRIVATE) + +static const struct timeval RPCTIMEOUT = {10, 0}; + +static char * +get_tablepath (char *name, dir_binding *bptr) +{ + enum clnt_stat result; + nis_result res; + struct ns_request req; + + memset (&res, '\0', sizeof (res)); + + req.ns_name = name; + req.ns_object.ns_object_len = 0; + req.ns_object.ns_object_val = NULL; + + result = clnt_call (bptr->clnt, NIS_LOOKUP, (xdrproc_t) _xdr_ns_request, + (caddr_t) &req, (xdrproc_t) _xdr_nis_result, + (caddr_t) &res, RPCTIMEOUT); + + const char *cptr; + if (result == RPC_SUCCESS && NIS_RES_STATUS (&res) == NIS_SUCCESS + && __type_of (NIS_RES_OBJECT (&res)) == NIS_TABLE_OBJ) + cptr = NIS_RES_OBJECT (&res)->TA_data.ta_path; + else + cptr = ""; + + char *str = strdup (cptr); + + if (result == RPC_SUCCESS) + xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &res); + + return str; +} + + +nis_error +__follow_path (char **tablepath, char **tableptr, struct ib_request *ibreq, + dir_binding *bptr) +{ + if (*tablepath == NULL) + { + *tablepath = get_tablepath (ibreq->ibr_name, bptr); + if (*tablepath == NULL) + return NIS_NOMEMORY; + + *tableptr = *tablepath; + } + + /* Since tableptr is only set here, and it's set when tablepath is NULL, + which it is initially defined as, we know it will always be set here. */ + DIAG_PUSH_NEEDS_COMMENT; + DIAG_IGNORE_NEEDS_COMMENT (4.7, "-Wmaybe-uninitialized"); + + if (*tableptr == NULL) + return NIS_NOTFOUND; + + char *newname = strsep (tableptr, ":"); + if (newname[0] == '\0') + return NIS_NOTFOUND; + + DIAG_POP_NEEDS_COMMENT; + + newname = strdup (newname); + if (newname == NULL) + return NIS_NOMEMORY; + + free (ibreq->ibr_name); + ibreq->ibr_name = newname; + + return NIS_SUCCESS; +} +libnsl_hidden_nolink_def (__follow_path, GLIBC_PRIVATE) + + +nis_result * +nis_list (const_nis_name name, unsigned int flags, + int (*callback) (const_nis_name name, + const nis_object *object, + const void *userdata), + const void *userdata) +{ + nis_result *res = malloc (sizeof (nis_result)); + ib_request *ibreq; + int status; + enum clnt_stat clnt_status; + int count_links = 0; /* We will only follow NIS_MAXLINKS links! */ + int done = 0; + nis_name *names; + nis_name namebuf[2] = {NULL, NULL}; + int name_nr = 0; + nis_cb *cb = NULL; + char *tableptr; + char *tablepath = NULL; + int first_try = 0; /* Do we try the old binding at first ? */ + nis_result *allres = NULL; + + if (res == NULL) + return NULL; + + if (name == NULL) + { + status = NIS_BADNAME; + err_out: + nis_freeresult (allres); + memset (res, '\0', sizeof (nis_result)); + NIS_RES_STATUS (res) = status; + return res; + } + + ibreq = __create_ib_request (name, flags); + if (ibreq == NULL) + { + status = NIS_BADNAME; + goto err_out; + } + + if ((flags & EXPAND_NAME) + && ibreq->ibr_name[strlen (ibreq->ibr_name) - 1] != '.') + { + names = nis_getnames (ibreq->ibr_name); + free (ibreq->ibr_name); + ibreq->ibr_name = NULL; + if (names == NULL) + { + nis_free_request (ibreq); + status = NIS_BADNAME; + goto err_out; + } + ibreq->ibr_name = strdup (names[name_nr]); + if (ibreq->ibr_name == NULL) + { + nis_freenames (names); + nis_free_request (ibreq); + status = NIS_NOMEMORY; + goto err_out; + } + } + else + { + names = namebuf; + names[name_nr] = ibreq->ibr_name; + } + + cb = NULL; + + while (!done) + { + dir_binding bptr; + directory_obj *dir = NULL; + + memset (res, '\0', sizeof (nis_result)); + + status = __nisfind_server (ibreq->ibr_name, + ibreq->ibr_srch.ibr_srch_val != NULL, + &dir, &bptr, flags & ~MASTER_ONLY); + if (status != NIS_SUCCESS) + { + NIS_RES_STATUS (res) = status; + goto fail3; + } + + while (__nisbind_connect (&bptr) != NIS_SUCCESS) + if (__glibc_unlikely (__nisbind_next (&bptr) != NIS_SUCCESS)) + { + NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE; + goto fail; + } + + if (callback != NULL) + { + assert (cb == NULL); + cb = __nis_create_callback (callback, userdata, flags); + ibreq->ibr_cbhost.ibr_cbhost_len = 1; + ibreq->ibr_cbhost.ibr_cbhost_val = cb->serv; + } + + again: + clnt_status = clnt_call (bptr.clnt, NIS_IBLIST, + (xdrproc_t) _xdr_ib_request, (caddr_t) ibreq, + (xdrproc_t) _xdr_nis_result, + (caddr_t) res, RPCTIMEOUT); + + if (__glibc_unlikely (clnt_status != RPC_SUCCESS)) + NIS_RES_STATUS (res) = NIS_RPCERROR; + else + switch (NIS_RES_STATUS (res)) + { /* start switch */ + case NIS_PARTIAL: + case NIS_SUCCESS: + case NIS_S_SUCCESS: + if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ + && (flags & FOLLOW_LINKS)) /* We are following links. */ + { + free (ibreq->ibr_name); + ibreq->ibr_name = NULL; + /* If we hit the link limit, bail. */ + if (__glibc_unlikely (count_links > NIS_MAXLINKS)) + { + NIS_RES_STATUS (res) = NIS_LINKNAMEERROR; + ++done; + break; + } + ++count_links; + ibreq->ibr_name = + strdup (NIS_RES_OBJECT (res)->LI_data.li_name); + if (ibreq->ibr_name == NULL) + { + NIS_RES_STATUS (res) = NIS_NOMEMORY; + fail: + __nisbind_destroy (&bptr); + nis_free_directory (dir); + fail3: + free (tablepath); + if (cb) + { + __nis_destroy_callback (cb); + ibreq->ibr_cbhost.ibr_cbhost_len = 0; + ibreq->ibr_cbhost.ibr_cbhost_val = NULL; + } + if (names != namebuf) + nis_freenames (names); + nis_free_request (ibreq); + nis_freeresult (allres); + return res; + } + if (NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len) + if (ibreq->ibr_srch.ibr_srch_len == 0) + { + ibreq->ibr_srch.ibr_srch_len = + NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_len; + ibreq->ibr_srch.ibr_srch_val = + NIS_RES_OBJECT (res)->LI_data.li_attrs.li_attrs_val; + } + /* The following is a non-obvious optimization. A + nis_freeresult call would call xdr_free as the + following code. But it also would unnecessarily + free the result structure. We avoid this here + along with the necessary tests. */ + xdr_free ((xdrproc_t) _xdr_nis_result, (char *)res); + memset (res, '\0', sizeof (*res)); + first_try = 1; /* Try at first the old binding */ + goto again; + } + else if ((flags & FOLLOW_PATH) + && NIS_RES_STATUS (res) == NIS_PARTIAL) + { + enum nis_error err = __follow_path (&tablepath, &tableptr, + ibreq, &bptr); + if (err != NIS_SUCCESS) + { + if (err == NIS_NOMEMORY) + NIS_RES_STATUS (res) = err; + ++done; + } + else + { + /* The following is a non-obvious optimization. A + nis_freeresult call would call xdr_free as the + following code. But it also would unnecessarily + free the result structure. We avoid this here + along with the necessary tests. */ + xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res); + memset (res, '\0', sizeof (*res)); + first_try = 1; + goto again; + } + } + else if ((flags & (FOLLOW_PATH | ALL_RESULTS)) + == (FOLLOW_PATH | ALL_RESULTS)) + { + if (allres == NULL) + { + allres = res; + res = malloc (sizeof (nis_result)); + if (res == NULL) + { + res = allres; + allres = NULL; + NIS_RES_STATUS (res) = NIS_NOMEMORY; + goto fail; + } + NIS_RES_STATUS (res) = NIS_RES_STATUS (allres); + } + else + { + nis_object *objects_val + = realloc (NIS_RES_OBJECT (allres), + (NIS_RES_NUMOBJ (allres) + + NIS_RES_NUMOBJ (res)) + * sizeof (nis_object)); + if (objects_val == NULL) + { + NIS_RES_STATUS (res) = NIS_NOMEMORY; + goto fail; + } + NIS_RES_OBJECT (allres) = objects_val; + memcpy (NIS_RES_OBJECT (allres) + NIS_RES_NUMOBJ (allres), + NIS_RES_OBJECT (res), + NIS_RES_NUMOBJ (res) * sizeof (nis_object)); + NIS_RES_NUMOBJ (allres) += NIS_RES_NUMOBJ (res); + NIS_RES_NUMOBJ (res) = 0; + free (NIS_RES_OBJECT (res)); + NIS_RES_OBJECT (res) = NULL; + NIS_RES_STATUS (allres) = NIS_RES_STATUS (res); + xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res); + } + enum nis_error err = __follow_path (&tablepath, &tableptr, + ibreq, &bptr); + if (err != NIS_SUCCESS) + { + /* Prepare for the nis_freeresult call. */ + memset (res, '\0', sizeof (*res)); + + if (err == NIS_NOMEMORY) + NIS_RES_STATUS (allres) = err; + ++done; + } + } + else + ++done; + break; + case NIS_CBRESULTS: + if (cb != NULL) + { + __nis_do_callback (&bptr, &res->cookie, cb); + NIS_RES_STATUS (res) = cb->result; + + if (!(flags & ALL_RESULTS)) + ++done; + else + { + enum nis_error err + = __follow_path (&tablepath, &tableptr, ibreq, &bptr); + if (err != NIS_SUCCESS) + { + if (err == NIS_NOMEMORY) + NIS_RES_STATUS (res) = err; + ++done; + } + } + } + break; + case NIS_SYSTEMERROR: + case NIS_NOSUCHNAME: + case NIS_NOT_ME: + /* If we had first tried the old binding, do nothing, but + get a new binding */ + if (!first_try) + { + if (__nisbind_next (&bptr) != NIS_SUCCESS) + { + ++done; + break; /* No more servers to search */ + } + while (__nisbind_connect (&bptr) != NIS_SUCCESS) + { + if (__nisbind_next (&bptr) != NIS_SUCCESS) + { + ++done; + break; /* No more servers to search */ + } + } + goto again; + } + break; + default: + if (!first_try) + { + /* Try the next domainname if we don't follow a link. */ + free (ibreq->ibr_name); + ibreq->ibr_name = NULL; + if (__glibc_unlikely (count_links)) + { + NIS_RES_STATUS (res) = NIS_LINKNAMEERROR; + ++done; + break; + } + ++name_nr; + if (names[name_nr] == NULL) + { + ++done; + break; + } + ibreq->ibr_name = strdup (names[name_nr]); + if (ibreq->ibr_name == NULL) + { + NIS_RES_STATUS (res) = NIS_NOMEMORY; + goto fail; + } + first_try = 1; /* Try old binding at first */ + goto again; + } + break; + } + first_try = 0; + + if (cb) + { + __nis_destroy_callback (cb); + ibreq->ibr_cbhost.ibr_cbhost_len = 0; + ibreq->ibr_cbhost.ibr_cbhost_val = NULL; + cb = NULL; + } + + __nisbind_destroy (&bptr); + nis_free_directory (dir); + } + + free (tablepath); + + if (names != namebuf) + nis_freenames (names); + + nis_free_request (ibreq); + + if (allres) + { + nis_freeresult (res); + return allres; + } + + return res; +} +libnsl_hidden_nolink_def (nis_list, GLIBC_2_1) + +nis_result * +nis_add_entry (const_nis_name name, const nis_object *obj2, unsigned int flags) +{ + nis_result *res = calloc (1, sizeof (nis_result)); + if (res == NULL) + return NULL; + + if (name == NULL) + { + NIS_RES_STATUS (res) = NIS_BADNAME; + return res; + } + + ib_request *ibreq = __create_ib_request (name, flags); + if (ibreq == NULL) + { + NIS_RES_STATUS (res) = NIS_BADNAME; + return res; + } + + nis_object obj; + memcpy (&obj, obj2, sizeof (nis_object)); + + size_t namelen = strlen (name); + char buf1[namelen + 20]; + char buf4[namelen + 20]; + + if (obj.zo_name == NULL || strlen (obj.zo_name) == 0) + obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1)); + + if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0) + obj.zo_owner = nis_local_principal (); + + if (obj.zo_group == NULL || strlen (obj.zo_group) == 0) + obj.zo_group = nis_local_group (); + + obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4)); + + ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL); + if (ibreq->ibr_obj.ibr_obj_val == NULL) + { + nis_free_request (ibreq); + NIS_RES_STATUS (res) = NIS_NOMEMORY; + return res; + } + ibreq->ibr_obj.ibr_obj_len = 1; + + nis_error status = __do_niscall (ibreq->ibr_name, NIS_IBADD, + (xdrproc_t) _xdr_ib_request, + (caddr_t) ibreq, + (xdrproc_t) _xdr_nis_result, + (caddr_t) res, 0, NULL); + if (__glibc_unlikely (status != NIS_SUCCESS)) + NIS_RES_STATUS (res) = status; + + nis_free_request (ibreq); + + return res; +} +libnsl_hidden_nolink_def (nis_add_entry, GLIBC_2_1) + +nis_result * +nis_modify_entry (const_nis_name name, const nis_object *obj2, + unsigned int flags) +{ + nis_object obj; + nis_result *res; + nis_error status; + ib_request *ibreq; + size_t namelen = strlen (name); + char buf1[namelen + 20]; + char buf4[namelen + 20]; + + res = calloc (1, sizeof (nis_result)); + if (res == NULL) + return NULL; + + ibreq = __create_ib_request (name, flags); + if (ibreq == NULL) + { + NIS_RES_STATUS (res) = NIS_BADNAME; + return res; + } + + memcpy (&obj, obj2, sizeof (nis_object)); + + if (obj.zo_name == NULL || strlen (obj.zo_name) == 0) + obj.zo_name = nis_leaf_of_r (name, buf1, sizeof (buf1)); + + if (obj.zo_owner == NULL || strlen (obj.zo_owner) == 0) + obj.zo_owner = nis_local_principal (); + + if (obj.zo_group == NULL || strlen (obj.zo_group) == 0) + obj.zo_group = nis_local_group (); + + obj.zo_domain = nis_domain_of_r (name, buf4, sizeof (buf4)); + + ibreq->ibr_obj.ibr_obj_val = nis_clone_object (&obj, NULL); + if (ibreq->ibr_obj.ibr_obj_val == NULL) + { + nis_free_request (ibreq); + NIS_RES_STATUS (res) = NIS_NOMEMORY; + return res; + } + ibreq->ibr_obj.ibr_obj_len = 1; + + status = __do_niscall (ibreq->ibr_name, NIS_IBMODIFY, + (xdrproc_t) _xdr_ib_request, + (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result, + (caddr_t) res, 0, NULL); + if (__glibc_unlikely (status != NIS_SUCCESS)) + NIS_RES_STATUS (res) = status; + + nis_free_request (ibreq); + + return res; +} +libnsl_hidden_nolink_def (nis_modify_entry, GLIBC_2_1) + +nis_result * +nis_remove_entry (const_nis_name name, const nis_object *obj, + unsigned int flags) +{ + nis_result *res; + ib_request *ibreq; + nis_error status; + + res = calloc (1, sizeof (nis_result)); + if (res == NULL) + return NULL; + + if (name == NULL) + { + NIS_RES_STATUS (res) = NIS_BADNAME; + return res; + } + + ibreq = __create_ib_request (name, flags); + if (ibreq == NULL) + { + NIS_RES_STATUS (res) = NIS_BADNAME; + return res; + } + + if (obj != NULL) + { + ibreq->ibr_obj.ibr_obj_val = nis_clone_object (obj, NULL); + if (ibreq->ibr_obj.ibr_obj_val == NULL) + { + nis_free_request (ibreq); + NIS_RES_STATUS (res) = NIS_NOMEMORY; + return res; + } + ibreq->ibr_obj.ibr_obj_len = 1; + } + + if ((status = __do_niscall (ibreq->ibr_name, NIS_IBREMOVE, + (xdrproc_t) _xdr_ib_request, + (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result, + (caddr_t) res, 0, NULL)) != NIS_SUCCESS) + NIS_RES_STATUS (res) = status; + + nis_free_request (ibreq); + + return res; +} +libnsl_hidden_nolink_def (nis_remove_entry, GLIBC_2_1) + +nis_result * +nis_first_entry (const_nis_name name) +{ + nis_result *res; + ib_request *ibreq; + nis_error status; + + res = calloc (1, sizeof (nis_result)); + if (res == NULL) + return NULL; + + if (name == NULL) + { + NIS_RES_STATUS (res) = NIS_BADNAME; + return res; + } + + ibreq = __create_ib_request (name, 0); + if (ibreq == NULL) + { + NIS_RES_STATUS (res) = NIS_BADNAME; + return res; + } + + status = __do_niscall (ibreq->ibr_name, NIS_IBFIRST, + (xdrproc_t) _xdr_ib_request, + (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result, + (caddr_t) res, 0, NULL); + + if (__glibc_unlikely (status != NIS_SUCCESS)) + NIS_RES_STATUS (res) = status; + + nis_free_request (ibreq); + + return res; +} +libnsl_hidden_nolink_def (nis_first_entry, GLIBC_2_1) + +nis_result * +nis_next_entry (const_nis_name name, const netobj *cookie) +{ + nis_result *res; + ib_request *ibreq; + nis_error status; + + res = calloc (1, sizeof (nis_result)); + if (res == NULL) + return NULL; + + if (name == NULL) + { + NIS_RES_STATUS (res) = NIS_BADNAME; + return res; + } + + ibreq = __create_ib_request (name, 0); + if (ibreq == NULL) + { + NIS_RES_STATUS (res) = NIS_BADNAME; + return res; + } + + if (cookie != NULL) + { + ibreq->ibr_cookie.n_bytes = cookie->n_bytes; + ibreq->ibr_cookie.n_len = cookie->n_len; + } + + status = __do_niscall (ibreq->ibr_name, NIS_IBNEXT, + (xdrproc_t) _xdr_ib_request, + (caddr_t) ibreq, (xdrproc_t) _xdr_nis_result, + (caddr_t) res, 0, NULL); + + if (__glibc_unlikely (status != NIS_SUCCESS)) + NIS_RES_STATUS (res) = status; + + if (cookie != NULL) + { + /* Don't give cookie free, it is not from us */ + ibreq->ibr_cookie.n_bytes = NULL; + ibreq->ibr_cookie.n_len = 0; + } + + nis_free_request (ibreq); + + return res; +} +libnsl_hidden_nolink_def (nis_next_entry, GLIBC_2_1) |