Beispiel #1
0
static enum nss_status
internal_nisplus_getgrent_r (struct group *gr, char *buffer, size_t buflen,
			     int *errnop)
{
  int parse_res = -1;
  enum nss_status retval = NSS_STATUS_SUCCESS;

  /* Get the next entry until we found a correct one. */
  do
    {
      nis_error status;
      nis_result result;
      memset (&result, '\0', sizeof (result));

      if (cursor.n_bytes == NULL)
	{
	  if (ibreq == NULL)
	    {
	      retval = internal_setgrent (errnop);
	      if (retval != NSS_STATUS_SUCCESS)
		return retval;
	    }

	  status = __do_niscall3 (&bptr, NIS_IBFIRST,
				  (xdrproc_t) _xdr_ib_request,
				  (caddr_t) ibreq,
				  (xdrproc_t) _xdr_nis_result,
				  (caddr_t) &result,
				  0, NULL);
	}
      else
	{
	  ibreq->ibr_cookie.n_bytes = cursor.n_bytes;
	  ibreq->ibr_cookie.n_len = cursor.n_len;

	  status = __do_niscall3 (&bptr, NIS_IBNEXT,
				  (xdrproc_t) _xdr_ib_request,
				  (caddr_t) ibreq,
				  (xdrproc_t) _xdr_nis_result,
				  (caddr_t) &result,
				  0, NULL);

	  ibreq->ibr_cookie.n_bytes = NULL;
	  ibreq->ibr_cookie.n_len = 0;
	}

      if (status != NIS_SUCCESS)
	return niserr2nss (status);

      if (NIS_RES_STATUS (&result) == NIS_NOTFOUND)
	{
	  /* No more entries on this server.  This means we have to go
	     to the next server on the path.  */
	  status = __follow_path (&tablepath, &tableptr, ibreq, &bptr);
	  if (status != NIS_SUCCESS)
	    return niserr2nss (status);

	  directory_obj *newdir = NULL;
	  dir_binding newbptr;
	  status = __prepare_niscall (ibreq->ibr_name, &newdir, &newbptr, 0);
	  if (status != NIS_SUCCESS)
	    return niserr2nss (status);

	  nis_free_directory (dir);
	  dir = newdir;
	  __nisbind_destroy (&bptr);
	  bptr = newbptr;

	  xdr_free ((xdrproc_t) xdr_netobj, (char *) &result.cookie);
	  result.cookie.n_bytes = NULL;
	  result.cookie.n_len = 0;
	  parse_res = 0;
	  goto next;
	}
      else if (NIS_RES_STATUS (&result) != NIS_SUCCESS)
	return niserr2nss (NIS_RES_STATUS (&result));

      parse_res = _nss_nisplus_parse_grent (&result, gr,
					    buffer, buflen, errnop);
      if (__glibc_unlikely (parse_res == -1))
	{
	  *errnop = ERANGE;
	  retval = NSS_STATUS_TRYAGAIN;
	  goto freeres;
	}

    next:
      /* Free the old cursor.  */
      xdr_free ((xdrproc_t) xdr_netobj, (char *) &cursor);
      /* Remember the new one.  */
      cursor.n_bytes = result.cookie.n_bytes;
      cursor.n_len = result.cookie.n_len;
      /* Free the result structure.  NB: we do not remove the cookie.  */
      result.cookie.n_bytes = NULL;
      result.cookie.n_len = 0;
    freeres:
      xdr_free ((xdrproc_t) _xdr_nis_result, (char *) &result);
      memset (&result, '\0', sizeof (result));
    }
  while (!parse_res);

  return retval;
}
Beispiel #2
0
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 (__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 (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 (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 (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;
}