nis_subr.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
*
* This module contains the subroutines used by the server to manipulate
* objects and names.
*/
#include "mt.h"
#include <pwd.h>
#include <grp.h>
#include <syslog.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <unistd.h>
#include <tiuser.h>
#include <netconfig.h>
#include <netdir.h>
#include <rpc/rpcb_clnt.h>
#include <rpc/pmap_clnt.h>
#include <rpcsvc/nis_dhext.h>
#include "nis_clnt.h"
#include <sys/systeminfo.h>
#include "nis_local.h"
#include <nsswitch.h>
static char *PKTABLE = "cred.org_dir";
#define PKTABLE_LEN 12
/*
* send and receive buffer size used for clnt_tli_create if not specified.
* This is only used for "UDP" connection.
* This limit can be changed from the application if this value is too
* small for the application. To use the maximum value for the transport,
* set this value to 0.
*/
int __nisipbufsize = 8192;
/* Error result returned by nis_make_error() when malloc fails */
0, 0, 0, 0};
extern int __readColdStartFile();
/*
* Static function prototypes.
*/
static struct local_names *__get_local_names(void);
/* __nis_data_directory is READ ONLY, so no locking is needed */
/* Note: We make it static, so external caller can not access it */
/* i.e we make sure it stay read only */
/* These macros make the code easier to read */
#ifdef NOTIME
#define __start_clock(n)
#define __stop_clock(n) n
#else
#define LOOP_UADDR "127.0.0.1.0.0"
/*
* __start_clock()
*
* This function will start the "stopwatch" on the function calls.
* It uses an array of time vals to keep track of the time. The
* sister call __stop_clock() will return the number of microseconds
* since the clock was started. This allows for keeping statistics
* on the NIS calls and tuning the service. If the clock in question
* is not "stopped" this function returns an error.
*/
int
int clk) /* The clock we want to start */
{
return (FALSE);
return (TRUE);
}
__stop_clock(int clk)
{
return (0);
secs--; /* adjusted 'cuz we added a second above */
} else {
}
return (micros);
}
#endif /* no time */
/*
* nis_dir_cmp() -- the results can be read as:
* "Name 'n1' is a $result than name 'n2'"
*/
{
return (BAD_NAME);
/* In this routine we're lenient and don't require a trailing '.' */
/* so we need to ignore it if it does appear. */
/* ==== That's what the previous version did so this one does */
/* too, but why? Is this inconsistent with rest of system? */
--l1;
}
--l2;
}
result = LOWER_NAME;
}
/* Now l1 >= l2 in all cases */
if (l2 == 0) {
/* Special case for n2 == "." or "" */
return (result);
}
return (NOT_SEQUENTIAL);
}
}
return (result);
}
return (NOT_SEQUENTIAL);
}
struct principal_list {
char principal[LN_BUFSIZE];
struct principal_list *next;
};
struct local_names {
char domain[LN_BUFSIZE];
char host[LN_BUFSIZE];
char *rpcdomain;
struct principal_list *principal_map;
char group[LN_BUFSIZE];
};
static struct local_names *__get_local_names1();
static struct local_names *
__get_local_names(void)
{
struct local_names *names;
names = __get_local_names1();
return (names);
}
static
char *
{
enum __nsw_parse_err pserr;
struct __nsw_switchconfig *conf;
static int checked_domain = 0;
static char *nisdomain = 0;
if (!checked_domain) {
checked_domain = 1;
/*
* Check that nisplus is first in nsswitch.conf for publickey.
*/
return (NULL);
if (conf->num_lookups <= 0)
return (NULL);
return (NULL);
/*
* Read cold-start file to determine directory where
* the machine's credentials are stored.
*/
if (!__readColdStartFile(&dobj))
return (NULL);
}
return (nisdomain);
}
static struct local_names *
__get_local_names1(void)
{
char *t;
/* Second and subsequent calls go this way */
return (ln);
}
/* First call goes this way */
return (NULL);
}
return (ln);
/* If no dot exists, add one. */
return (ln);
/*
* Check for fully qualified hostname. If it's a fully qualified
* hostname, strip off the domain part. We always use the local
* domainname for the host principal name.
*/
if (t)
*t = 0;
} else {
}
t = getenv("NIS_GROUP");
if (t == NULL) {
} else {
char *temp; /* temp marker */
/*
* Copy <= maximum characters from NIS_GROUP; strncpy()
* doesn't terminate, so we do that manually. #1223323
* Also check to see if it's "". If it's the null string,
* we return because we don't want to add ".domain".
*/
return (ln);
}
/* Is the group name somewhat fully-qualified? */
/* If not, we need to add ".domain" to the group */
/* truncate to make room for ".domain" */
/* concat '.' if domain doesn't already have it */
}
}
}
return (ln);
}
/*
* nis_local_group()
*
* Return's the group name of the current user.
*/
nis_local_group(void)
{
/* LOCK NOTE: Warning, after initialization, "ln" is expected */
/* to stay constant, So no need to lock here. If this assumption */
/* is changed, this code must be protected. */
if (!ln)
return (NULL);
}
/*
* __nis_nextsep_of()
*
* This internal funtion will accept a pointer to a NIS name string and
* return a pointer to the next separator occurring in it (it will point
* just past the first label). It allows for labels to be "quoted" to
* prevent the the dot character within them to be interpreted as a
* separator, also the quote character itself can be quoted by using
* it twice. If the the name contains only one label and no trailing
* dot character, a pointer to the terminating NULL is returned.
*/
__nis_nextsep_of(char *s)
{
char *d;
quote_quote = FALSE;
if (!s)
return (NULL);
for (d = s; (in_quotes && (*d != '\0')) ||
quote_quote = FALSE;
if (*d == '.')
break;
quote_quote = FALSE;
} else if (quote_quote && (*d != '"')) {
quote_quote = FALSE;
} else if (quote_quote && (*d == '"')) {
quote_quote = FALSE;
} else if (in_quotes && (*d == '"')) {
quote_quote = TRUE;
} else if (!in_quotes && (*d == '"')) {
quote_quote = TRUE;
}
}
if (quote_quote || in_quotes) {
"Mismatched quotes in %s", s);
}
return (d);
}
/*
* nis_domain_of()
*
* This internal funtion will accept a pointer to a NIS name string and
* return a pointer to the "domain" part of it.
*
* ==== We don't need nis_domain_of_r(), but should we provide one for
* uniformity?
*/
nis_domain_of(char *s)
{
char *d;
d = __nis_nextsep_of(s);
if (d == NULL)
return (NULL);
if (*d == '.')
d++;
if (*d == '\0') /* Don't return a zero length string */
return ("."); /* return root domain instead */
return (d);
}
/*
* nis_leaf_of()
*
* Returns the first label of a name. (other half of __domain_of)
*/
const nis_name s,
char *buf,
{
const char *d = __nis_nextsep_of((char *)s);
if (d == 0) {
return (0);
}
nchars = d - s;
return (0);
}
return (buf);
}
static pthread_key_t buf_key;
static char buf_main[LN_BUFSIZE];
nis_leaf_of(char *s)
{
return (NULL);
}
/*
* nis_name_of()
* This internal function will remove from the NIS name, the domain
* name of the current server, this will leave the unique part in
* the name this becomes the "internal" version of the name. If this
* function returns NULL then the name we were given to resolve is
* bad somehow.
* NB: Uses static storage and this is a no-no with threads. XXX
*/
char *s, /* string with the name in it. */
char *buf,
{
char *d;
name_pos p;
#ifdef lint
#endif /* lint */
if ((!s) || (!ln))
return (NULL); /* No string, this can't continue */
return (NULL);
sl++;
}
return (buf);
}
p = nis_dir_cmp(buf, d);
/* 's' is above 'd' in the tree */
return (NULL);
/* Insert a NUL where the domain name starts in the string */
/* Don't return a zero length name */
if (buf[0] == '\0')
return (NULL);
return (buf);
}
char *s) /* string with the name in it. */
{
if (!buf)
return (NULL);
}
/*
* nis_local_directory()
*
* Return a pointer to a string with the local directory name in it.
*/
nis_local_directory(void)
{
/* LOCK NOTE: Warning, after initialization, "ln" is expected */
/* to stay constant, So no need to lock here. If this assumption */
/* is changed, this code must be protected. */
return (NULL);
}
/*
* __nis_rpc_domain()
*
* Return a pointer to a string with the rpc domain name in it.
*/
{
/* LOCK NOTE: Warning, after initialization, "ln" is expected */
/* to stay constant, So no need to lock here. If this assumption */
/* is changed, this code must be protected. */
return (NULL);
}
/*
* nis_getprincipal:
* Return the prinicipal name of the given uid in string supplied.
* Returns status obtained from nis+.
*
* Look up the LOCAL mapping in the local cred table. Note that if the
* server calls this, then the version of nis_list that will
* will be bound here is the 'safe' one in the server code.
*
* The USE_DGRAM + NO_AUTHINFO is required to prevent a
* recursion through the getnetname() interface which is
* called by authseccreate_pk and authdes_pk_create().
*
* NOTE that if you really want to get the nis+ principal name,
* you should not use this call. You should do something similar
* but use an authenticated handle.
*/
int
{
char buf[NIS_MAXNAMELEN];
int status;
(size_t)NIS_MAXNAMELEN) {
return (NIS_BADNAME);
}
/*
* More than one principal with same uid?
* something wrong with cred table. Should be unique
* Warn user and continue.
*/
"nis_principal: LOCAL entry for %d in directory %s not unique",
}
(void) strcpy(principal_name,
}
return (status);
}
/*
* nis_local_principal()
* Generate the principal name for this user by looking it up its LOCAL
* entry in the cred table of the local direectory.
* Does not use an authenticated call (to prevent recursion because
* this is called by user2netname).
*
* NOTE: the principal strings returned by nis_local_principal are
* never changed and never freed, so there is no need to copy them.
* Also note that nis_local_principal can return NULL.
*/
nis_local_principal(void)
{
int status;
char *dirname;
struct principal_list *p;
return (NULL);
p = ln->principal_map;
while (p) {
return (p->principal);
}
p = p->next;
}
if (uid == 0) {
}
if (p == NULL)
return (NULL);
if (!ln->principal_map) {
ln->principal_map = p;
}
return (p->principal);
}
case NIS_SUCCESS:
case NIS_S_SUCCESS:
break;
case NIS_NOTFOUND:
case NIS_PARTIAL:
case NIS_NOSUCHNAME:
case NIS_NOSUCHTABLE:
break;
default:
/*
* XXX We should return 'nobody', but
* should we be remembering 'nobody' as our
* principal name here? Some errors might be
* transient.
*/
"nis_local_principal: %s",
}
return (p->principal);
}
/*
* nis_local_host()
* Generate the principal name for this host, "hostname"+"domainname"
* unless the hostname already has "dots" in its name.
*/
nis_local_host(void)
{
/* LOCK NOTE: Warning, after initialization, "ln" is expected */
/* to stay constant, So no need to lock here. If this assumption */
/* is changed, this code must be protected. */
return (NULL);
}
/*
* nis_destroy_object()
* This function takes a pointer to a NIS object and deallocates it. This
* is the inverse of __clone_object below. It must be able to correctly
* deallocate partially allocated objects because __clone_object will call
* it if it runs out of memory and has to abort. Everything is freed,
* INCLUDING the pointer that is passed.
*/
void
{
if (obj == 0)
return;
} /* nis_destroy_object */
static void
destroy_nis_sdata(void *p)
{
}
/* XXX Why are these static ? */
/* static XDR in_xdrs, out_xdrs; */
/*
* __clone_object_r()
* This function takes a pointer to a NIS object and clones it. This
* duplicate object is now available for use in the local context.
*/
struct nis_sdata *clone_buf_ptr)
{
int status; /* a counter variable */
return (NULL);
/* Allocate a basic NIS object structure */
if (dest) {
} else
return (NULL);
/* Encode our object into the clone buffer */
(void) xdr_setpos(&in_xdrs, 0);
return (NULL);
/* Now decode the buffer into our result pointer ... */
(void) xdr_setpos(&out_xdrs, 0);
return (NULL);
/* presto changeo, a new object */
return (result);
} /* __clone_object_r */
{
static pthread_key_t clone_buf_key;
static struct nis_sdata clone_buf_main;
struct nis_sdata *clone_buf_ptr;
} /* __clone_object */
/*
* __break_name() converts a NIS name into it's components, returns an
* array of char pointers pointing to the components and INVERTS there
* order so that they are root first, then down. The list is terminated
* with a null pointer. Returned memory can be freed by freeing the last
* pointer in the list and the pointer returned.
*/
char **
int *levels)
{
char **pieces; /* pointer to the pieces */
char *s; /* Temporary */
char *data; /* actual data and first piece pointer. */
int components; /* Number of estimated components */
int i;
/* First check to see that name is not NULL */
if (!name)
return (NULL);
return (NULL); /* Null string */
if (!data)
return (NULL); /* No memory! */
/* Kill the optional trailing dot */
namelen--;
}
s = data;
components = 1;
while (*s != '\0') {
if (*s == '.') {
*s = '\0';
components++;
s++;
} else if (*s == '"') {
if (*(s+1) == '"') { /* escaped quote */
s += 2;
} else {
/* skip quoted string */
s++;
while ((*s != '"') && (*s != '\0'))
s++;
if (*s == '"') {
s++;
}
}
} else {
s++;
}
}
if (! pieces) {
return (NULL);
}
/* store in pieces in inverted order */
*(pieces+i) = s;
while (*s != '\0')
s++;
s++;
}
*levels = components;
return (pieces);
}
void
{
}
int
char **targ, /* The target name */
char **test) /* the test name */
{
int distance = 0;
/* Don't count common components */
targ++;
test++;
}
/* count off the legs of each name */
test++;
distance++;
}
targ++;
distance++;
}
return (distance);
}
int
{
/* skip common components */
targ++;
test++;
}
}
void
{
int i;
for (i = levels-1; i >= 0; --i)
}
/*
* For returning errors in a NIS result structure
*/
{
if (!nres)
return ((nis_result *)&__nomem_nis_result);
return (nres);
}
/*
* __cvt2attr()
*
* This function converts a search criteria of the form :
* [ <key>=<value>, <key>=<value>, ... ]
* Into an array of nis_attr structures.
*/
nis_attr *
int *na, /* Number of attributes */
char **attrs) /* Strings associated with them */
{
int i;
char *s;
if (! zattrs)
return (NULL);
for (i = 0; i < *na; i++) {
if (*s == '=') {
*s = '\0';
s++;
break;
} else if (*s == '"') {
/* advance s to matching quote */
s++;
while ((*s != '"') && (*s != '\0'))
s++;
if (*s == '\0') {
/* unterminated quote */
return (NULL);
}
}
}
/*
* POLICY : Missing value for an index name is an
* error. The other alternative is the missing
* value means "is present" unfortunately there
* is no standard "is present" indicator in the
* existing databases.
* ANSWER : Always return an error.
*/
return (NULL);
}
}
return (zattrs);
}
/*
* nis_free_request()
*
* Free memory associated with a constructed list request.
*/
void
{
/* free the string memory */
/* free the nis_attr array */
}
}
/*
* nis_get_request()
*
* This function takes a NIS name, and converts it into an ib_request
* structure. The request can then be used in a call to the nis service
* functions. If the name wasn't parseable it returns an appropriate
* error. This function ends up allocating an array of nis_attr structures
* and a duplicate of the name string passed. To free this memory you
* can call nis_free_request(), or you can simply free the first nis_attr
* zattr_ndx pointer (the string memory) and the nis_attr pointer which
* is the array.
*/
{
char *s, *t; /* Some string pointer temps */
char *p; /* temp var */
char **attr; /* Intermediate attributes */
int i; /* Counter variable */
char *data; /* pointer to malloc'd string */
int zn = 0; /* Count of attributes */
char namebuf[NIS_MAXNAMELEN];
/*
* a boolean to indicate the current parse
* location is within the attribute value
* - so that we can stop deleting white
* space within an attribute value
*/
/*
* if we're passed an object but no name, use the name from
* the object instead.
*/
sizeof (namebuf)) {
return (NIS_BADNAME);
}
}
return (NIS_BADNAME);
s = name;
/* Move to the start of the components */
while (isspace(*s))
s++;
if (*s == '[') {
s++; /* Point past the opening bracket */
if (!data)
return (NIS_NOMEMORY);
t = data; /* Point to the databuffer */
while ((*s != '\0') && (*s != ']')) {
while (isspace(*s)) {
s++;
}
/* Check to see if we finished off the string */
if ((*s == '\0') || (*s == ']'))
break;
/* If *s == comma its a null criteria */
if (*s == COMMA) {
s++;
continue;
}
/* Not a space and not a comma, process an attr */
zn++;
within_attr_val = 0; /* not within attr_val right now */
if (*s == '"') {
if (*(s+1) == '"') { /* escaped quote */
*t++ = *s; /* copy one quote */
s += 2;
} else {
/* skip quoted string */
s++;
while ((*s != '"') &&
(*s != '\0'))
*t++ = *s++;
if (*s == '"') {
s++;
}
}
} else if (*s == '=') {
*t++ = *s++;
within_attr_val = 1;
} else if (isspace(*s) && !within_attr_val) {
s++;
} else
*t++ = *s++;
}
*t++ = '\0'; /* terminate the attribute */
if (*s == COMMA)
s++;
}
if (*s == '\0') {
return (NIS_BADATTRIBUTE);
}
/* It wasn't a '\0' so it must be the closing bracket. */
s++;
/* Skip any intervening white space and "comma" */
s++;
}
/* Copy the name into our malloc'd buffer */
(void) strcpy(t, s);
/*
* If we found any attributes we process them, the
* data string at this point is completely nulled
* out except for attribute data. We recover this
* data by scanning the string (we know how long it
* is) and saving to each chunk of non-null data.
*/
if (zn) {
/* Save this as the table name */
if (! attr) {
return (NIS_NOMEMORY);
}
/* store in pieces in attr array */
*(attr+i) = s;
/* Advance s past this component */
while (*s != '\0')
s++;
s++;
}
} else {
}
} else {
/* Null search criteria */
}
if (zn) {
return (NIS_BADATTRIBUTE);
}
}
/* check for correct quotes in ibr_name (but leave them in) */
if (*p == '"') {
/* advance p to the matching quote */
p++;
while (*p != '"' && *p != '\0') {
p++;
}
if (*p == '\0') {
return (NIS_BADNAME);
}
}
}
if (obj) {
}
if (cookie) {
}
return (NIS_SUCCESS);
}
/* Various subroutines used by the server code */
nis_read_obj(char *f) /* name of the object to read */
{
int status; /* Status of the XDR decoding */
if (! res)
return (NULL);
/* This is ok if we are the root of roots. */
return (NULL);
}
/* Now read in the object */
xdr_destroy(&xdrs);
if (!status) {
return (NULL);
}
return (res);
}
int
char *f, /* name of the object to read */
nis_object *o) /* The object to write */
{
int status; /* Status of the XDR decoding */
return (0);
}
/* Now encode the object */
xdr_destroy(&xdrs);
return (status);
}
/*
* nis_make_rpchandle()
*
* This is a generic version of clnt_creat() for NIS. It localizes
* _all_ of the changes needed to port to TLI RPC into this one
* section of code.
*/
/*
* Transport INDEPENDENT RPC code. This code assumes you
* a ping handle on top of a datagram transport.
*/
/*
* __map_addr()
*
* This is our internal function that replaces rpcb_getaddr(). We
* build our own to prevent calling netdir_getbyname() which could
* recurse to the nameservice.
*/
static char *
char *uaddr, /* RPCBIND address */
{
/*
* If using "udp", use __nisipbufsize if inbuf and outbuf are set to 0.
*/
/* for udp only */
} else {
}
if (! client) {
return (NULL);
}
/*
* Now make the call to get the NIS service address.
* We set the retry timeout to 3 seconds so that we
* will retry a few times. Retries should be rare
* because we are usually only called when we know
* a server is available.
*/
if (clnt_st == RPC_SUCCESS) {
if (*ua == '\0') {
return (NULL);
}
return (res);
} else if (((clnt_st == RPC_PROGVERSMISMATCH) ||
(clnt_st == RPC_PROGUNAVAIL)) &&
/*
* version 3 not available. Try version 2
* The assumption here is that the netbuf
* is arranged in the sockaddr_in
* style for IP cases.
*
* Note: If the remote host doesn't support version 3,
* we assume it doesn't know IPv6 either.
*/
struct sockaddr_in *sa;
int protocol;
char buf[32];
if (port != 0) {
port & 0xff);
} else
return (res);
}
if (clnt_st == RPC_TIMEDOUT)
else
return (NULL);
}
char *
{
}
#define MAX_EP (20)
int
{
int i;
int n;
int st;
int nep = 0;
struct nd_hostserv hs;
struct nd_addrlist *addrs;
struct nd_mergearg ma;
void *lh;
void *nch;
if (eps == 0)
return (0);
nch = setnetconfig();
continue;
continue;
if (st != 0)
continue;
/*
* The netdir_merge code does not work very well
* for inet if the client and server are not
* on the same network. Instead, we try each local
* address.
*
* For other protocol families and for servers on a
* local network, we use the regular merge code.
*/
n = __inet_address_count(lh);
for (i = 0; i < n; i++) {
"__nis_get_callback_addresses: too many endpoints");
goto full;
}
continue;
continue;
}
nep++;
}
} else {
"__nis_get_callback_addresses: too many endpoints");
goto full;
}
nep++;
}
}
full:
(void) endnetconfig(nch);
return (nep);
}
/*
* Try to create a RPC GSS security context (flavor RPCSEC_GSS).
* Returns auth handle on success, else NULL. Set flag 'try_auth_des'
* to TRUE if the AUTH_DES compat line is found in the security conf file
* or no valid mech entries are found in the conf file.
*/
static AUTH *
char *gss_svc,
{
*try_auth_des = FALSE;
mechanism_t **mpp;
/* Check RPC GSS service name buf size. */
"nis_make_rpchandle_gss_svc: RPC GSS service name too long");
return (NULL);
}
/* RPC GSS service names are of the form svc@host.dom */
/*
* Loop thru all the available mech entries until an
* RPC GSS security context is established or until
* the AUTH_DES compat entry is found.
*/
if (AUTH_DES_COMPAT_CHK(mp)) {
*try_auth_des = TRUE;
return (NULL);
}
if (! VALID_MECH_ENTRY(mp)) {
"%s: invalid mechanism entry name '%s'",
continue;
}
/*
* If the mechanism is of the public key crypto
* technology variety, let's make sure the server's
* public key exists and the clients secret key is set
* before going thru the expense of a RPC GSS security
* context creation attempt.
*/
if (MECH_PK_TECH(mp) &&
#ifdef DHEXT_DEBUG
"nis_make_rpchandle_gss_svc: srv keytype = %d: No keys, skip mech '%s' ...\n",
#endif
continue;
}
#ifdef DHEXT_DEBUG
} else {
"nis_make_rpchandle_gss_svc: RPCGSS_SecCreat fail: gerr = %d serr = %d\n",
#endif /* DHEXT_DEBUG */
}
}
} else {
/* no valid mechs, fallback to AUTH_DES */
*try_auth_des = TRUE;
}
return (NULL);
}
CLIENT *
int cback, /* Boolean indicating callback address */
int inbuf, /* Preferred buffer sizes */
int outbuf) /* for input and output */
{
}
CLIENT *
int cback, /* Boolean indicating callback address */
int inbuf, /* Preferred buffer sizes */
int outbuf, /* for input and output */
char *uaddr) /* optional address of server */
{
}
CLIENT *
char *svc_addr;
int freeaddr = 0;
/* Sanity check */
return (0);
}
/*
* Check if we have a useable interface for this address family.
* This check properly belongs in RPC (or even further down),
* but until they provide it, we roll our own.
*/
return (0);
}
if (domapaddr) {
if (svc_addr == 0)
return (0);
freeaddr = 1;
} else if (addr == 0) {
freeaddr = 1;
}
if (addr == 0) {
return (0);
}
if (clnt) {
/* make it "close on exec" */
}
if (freeaddr)
return (clnt);
}
typedef struct {
} alt_ep_t;
/*
* Construct an rpc handle.
*
* If the gss_svc arg is NULL, then default to "nisd" (rpc.nisd).
*/
static CLIENT *
int cback, /* Boolean indicating callback address */
int inbuf, /* Preferred buffer sizes */
int outbuf, /* for input and output */
char *uaddr, /* optional address of server */
char *gss_svc, /* RPC GSS service name */
int use_realid) /* 1: Use REAL id, 0: use Eff. ids */
{
void *nc_handle; /* Netconfig "state" */
int epl, i; /* counters */
nc_handle = (void *) setnetconfig();
if (! nc_handle)
return (NULL);
if (uaddr) {
/* Is it a visible transport ? */
continue;
/* Does the protocol family match the uaddr ? */
continue;
for (i = 0; i < epl; i++) {
break;
}
}
/* Did we find a matching endpoint ? */
if (i < epl)
break;
}
if (nc == 0) {
"nis_make_rpchandle: can't find netconfig entry for %s, %s",
return (0);
}
} else {
/*
* The transport policies :
* Selected transport must be visible.
* Must have requested or better semantics.
* Must be correct protocol.
*/
/* Is it a visible transport ? */
continue;
/* If we asked for a virtual circuit, is it ? */
continue;
/* Check to see is we talk this protofmly, protocol */
for (i = 0; i < epl; i++) {
break;
}
/* Was it one of our transports ? */
if (i == epl)
continue; /* No */
/*
* If it is one of our supported transports, but isn't
* a datagram and we want a datagram, keep looking but
* remember this one as a possibility.
*/
altep != 0) {
continue;
}
/* We've got a candidate; see if it works */
outbuf);
if (clnt != 0)
break;
}
/* If primary choices failed, try the alternates */
continue;
outbuf);
}
}
}
/* Done with the netconfig handle regardless */
/* If we still don't have a client handle, we're sunk */
if (clnt == 0) {
return (0);
}
/*
* No auth requested or it's a callback (which is not authenticated),
* so we're done.
*/
return (clnt);
/*
* Setup authentication. Try the RPCSEC_GSS flavor first, then
* fallback to AUTH_DES (if requested) and, if need be, AUTH_SYS.
*/
return (clnt);
if (! try_auth_des)
/* XXXX what's the meaning of going into a switch stmt??? */
goto auth_sys;
case NIS_PK_DHEXT :
/*
* We're doing AUTH_DES, but the server might
* have multiple keys so let's get the 192-0 one.
*/
192, 0)) == NULL)
goto auth_sys;
/*FALLTHROUGH*/
case NIS_PK_DH :
break;
/*FALLTHROUGH*/
case NIS_PK_NONE :
break;
/*FALLTHROUGH*/
default :
break;
"nis_make_rpchandle_uaddr: cannot create cred.");
abort();
break;
}
return (clnt);
return (NULL);
}
CLIENT *
char *gss_svc)
{
}
CLIENT *
char *gss_svc)
{
}
int __nis_ss_used = 0;
/*
* nis_get_static_storage()
*
* This function is used by various functions in their effort to minimize the
* hassles of memory management in an RPC daemon. Because the service doesn't
* implement any hard limits, this function allows people to get automatically
* growing buffers that meet their storage requirements. It returns the
* pointer in the nis_sdata structure.
*
*/
void *
{
if (! bs)
return (NULL);
return (NULL);
__nis_ss_used += sz;
int size_delta;
/* check the result of malloc() first */
/* then update the statistic. */
return (NULL);
size_delta += sz;
}
}
char *
char *s,
{
char *buf;
char temp[1024];
if (! buf)
return (NULL);
/*
* this saving of 's' is because the routines that call nis_data()
* are not very careful about what they pass in. Sometimes what they
* pass in are 'static' returned from some of the routines called
* below nis_leaf_of(), nis_local_host() and so on.
*/
if (s) {
return (NULL);
}
return (NULL);
if (s)
for (s = buf; *s; s++) {
if (isupper(*s))
*s = tolower(*s);
}
return (buf);
}
char *
nis_old_data(char *s)
{
static pthread_key_t bs_key;
return (nis_old_data_r(s, bs_ptr));
}
char *
{
char *buf;
char temp[1024];
if (! buf)
return (NULL);
/*
* this saving of 's' is because the routines that call nis_data()
* are not very careful about what they pass in. Sometimes what they
* pass in are 'static' returned from some of the routines called
* below nis_leaf_of(), nis_local_host() and so on.
*/
if (s) {
return (NULL);
}
return (NULL);
if (s)
for (s = buf; *s; s++) {
if (isupper(*s))
*s = tolower(*s);
}
return (buf);
}
char *
nis_data(char *s)
{
static pthread_key_t bs_key;
return (nis_data_r(s, bs_ptr));
}
/*
* Return the directory name of the root_domain of the caller's NIS+
* domain.
*
* This routine is a temporary implementation and should be
* provided as part of the the NIS+ project. See RFE: 1103216
* Required for root replication.
*
* XXX MT safing: local_root_lock protects the local_root structure.
*
* It tries to determine the root domain
* name by "walking" the path up the NIS+ directory tree, starting
* at nis_local_directory() until a NIS_NOSUCHNAME or NIS_NOTFOUND error
* is obtained. Returns 0 on fatal errors obtained before this point,
* or if it exhausts the domain name without ever obtaining one of
* of these errors.
*/
static nis_name local_root = 0;
__nis_local_root(void)
{
char *dir;
int found_root = 0;
int try_count = 0;
int fatal_error = 0;
char *prev_testdir;
char *testdir;
if (local_root) {
return (local_root);
}
if (!local_root) {
return (0);
}
/* walk up NIS+ tree till we find the root. */
prev_testdir = dir;
/* try lookup */
/* handle return status */
case NIS_SUCCESS:
case NIS_S_SUCCESS:
try_count = 0;
break;
case NIS_NOSUCHNAME:
case NIS_NOTFOUND:
case NIS_NOT_ME:
case NIS_FOREIGNNS:
found_root = 1;
break;
case NIS_TRYAGAIN:
case NIS_CACHEEXPIRED:
/* sleep 1 second and try same name again, up to 10 times */
/* REMIND: This is arbitrary! BAD! */
_sleep(1);
break;
case NIS_NAMEUNREACHABLE:
case NIS_SYSTEMERROR:
case NIS_RPCERROR:
case NIS_NOMEMORY:
default:
fatal_error = 1;
break;
}
}
if (!found_root) {
return (0);
}
return (local_root);
}
extern int bin2hex(int, unsigned char *, char *);
/*
* __nis_cache_server_pkeys
*
* Add the public keys for the servers of the directory object to the
* per-process public key cache.
*/
void
int i;
uint_t s;
return;
case NIS_PK_DH:
}
break;
case NIS_PK_DHEXT:
break;
algtype_t a;
if (k == 0)
break;
}
}
break;
default:
break;
}
}
}