getgrent.c revision bf1e3bee1b13b3a914f0dd817a04f6e0ce8e0691
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* nisplus/getgrent.c -- NIS+ backend for nsswitch "group" database
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <grp.h>
#include <string.h>
#include <stdlib.h>
#include <pwd.h>
#include "nisplus_common.h"
#include "nisplus_tables.h"
struct memdata {
const char *uname;
int numgids;
int maxgids;
};
extern uint_t __nis_force_hard_lookups;
static int gr_cback();
static nss_status_t
void *a;
{
}
static nss_status_t
void *a;
{
}
static nss_status_t
getbymember(be, a)
void *a;
{
nis_result *r;
char buf[NIS_MAXNAMELEN];
/*
* not in NIS or NIS+
* If we don't do this, a hung name-service may cause
* a root login or su to hang.
* 1251680: Also, we should not allow empty strings to be
* passed to NIS+ backend or application will dump core.
*/
return (NSS_NOTFOUND);
}
/*
* If force_slow_way is not set then we can use the local creds
* for the group information. This assumes that there are admin
* procedures in place to keep the local creds and group table
* in sync with each other.
*/
case NSS_SUCCESS:
/*
* Return SUCCESS only if array is full.
* Explained in <nss_dbdefs.h>.
*/
: NSS_NOTFOUND);
case NSS_NOTFOUND:
case NSS_UNAVAIL:
/*
* Failover to group map seach if no luck with local
* creds (netid).
*/
break;
case NSS_TRYAGAIN:
return (NSS_TRYAGAIN);
}
}
/*
* Newer versions of rpc.nisd will let us do a "multivalue" search
* on the members column of the group table. The server will return
* any entries that have the member name listed somewhere in the
* list of members. Since that is fairly efficient, we try that
* first. If the server returns NIS_BADATTRIBUTE, then it doesn't
* support this feature and we fail over to the slow way of
* dumping all of the group entries and searching from the member
* name on our own.
*/
if (r && r->status != NIS_BADATTRIBUTE) {
if (r)
nis_freeresult(r);
/*
* Return SUCCESS only if array is full.
* Explained in <nss_dbdefs.h>.
*/
: NSS_NOTFOUND);
}
if (r == 0)
return (NSS_NOTFOUND);
nis_freeresult(r);
/*
* Return SUCCESS only if array is full.
* Explained in <nss_dbdefs.h>.
*/
: NSS_NOTFOUND);
}
/*
* convert the nisplus object into files format
* Returns NSS_STR_PARSE_{SUCCESS, ERANGE, PARSE}
*
* This routine does not tolerate non-numeric gr_gid. It
* will immediately flag a PARSE error and return.
*/
/*ARGSUSED*/
static int
int nobj;
{
char *endnum;
/*
* If we got more than one nis_object, we just ignore it.
* Although it should never have happened.
*
* ASSUMPTION: All the columns in the NIS+ tables are
* null terminated.
*/
return (NSS_STR_PARSE_PARSE);
}
/* name: group name */
/*
* passwd: group passwd
* empty password ("") is gladly accepted.
*/
/* gid: group id */
return (NSS_STR_PARSE_PARSE);
/* members: gid list */
return (NSS_STR_PARSE_PARSE);
/* exclude the trailing null from length */
} else {
return (NSS_STR_PARSE_ERANGE);
}
#ifdef DEBUG
#endif /* DEBUG */
return (NSS_STR_PARSE_SUCCESS);
}
static nisplus_backend_op_t gr_ops[] = {
};
/*ARGSUSED*/
{
return (_nss_nisplus_constr(gr_ops,
}
#define NEXT 0
/*ARGSUSED*/
static int
struct memdata *g;
{
char *val;
int len;
char *p;
char *endp;
int i;
/* ==== should check entry type? */
/*
* We've found one bad entry, so throw up our hands
* and say that we don't like any of the entries (?!)
*/
g->nss_err = NSS_NOTFOUND;
return (DONE);
}
if (len == 0) {
return (NEXT);
}
/* Found uname */
break;
}
}
if (p == 0) {
return (NEXT);
}
if (len == 0) {
return (NEXT); /* Actually pretty curdled, but not enough */
/* for us to abort the callback sequence */
}
if (*endp != '\0') {
return (NEXT); /* Again, somewhat curdled */
}
i = g->numgids;
while (i-- > 0) {
return (NEXT); /* We've already got it, presumably */
/* from another name service (!?) */
}
}
return (NEXT);
} else {
return (DONE); /* Filled up gid_array, so quit iterating */
}
}
static nss_status_t
{
char pwbuf[NSS_BUFLEN_PASSWD];
nis_result *r;
char buf[NIS_MAXNAMELEN];
/*
* We need to get the users uid given their name as we can't
* assume that their NIS+ principle name is username.`domainname`
*
* We also need to workout which cred.org_dir table to use but the
* backend pointer (be) we have is to a group.org_dir table.
*/
return (NSS_NOTFOUND);
}
/*
* NOTE: We are explicitly NOT saying ALL_RESULTS here because
* the cred table must NEVER be linked or pathed this is documented
* in the Answerbook.
*/
r = __nis_list_localcb(buf,
if (r == 0)
return (NSS_NOTFOUND);
switch (r->status) {
case NIS_SUCCESS:
case NIS_CBRESULTS:
nis_freeresult(r);
return (NSS_SUCCESS);
case NIS_TRYAGAIN:
return (NSS_TRYAGAIN);
case NIS_UNAVAIL:
return (NSS_UNAVAIL);
case NIS_NOTFOUND:
return (NSS_NOTFOUND);
default:
return (NSS_NOTFOUND);
}
}
/*ARGSUSED*/
static int
{
char *val;
char *val_next;
int vallen;
int i;
long value;
/*
* Badly formed LOCAL cred entry
*/
g->nss_err = NSS_NOTFOUND;
return (DONE);
}
if (vallen == 0) {
return (NEXT);
}
/* val should now point to a comma-separated list of gids */
while (*val != '\0') {
errno = 0;
return (NSS_STR_PARSE_PARSE);
return (NSS_STR_PARSE_ERANGE);
}
i = g->numgids;
while (i-- > 0) {
goto do_next_entry;
}
} else {
return (DONE);
}
if (*val == ',') {
val++;
}
}
return (NEXT);
} else {
return (DONE);
}
}