getgrent.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 2004 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 SUCESS 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 (NSS_SUCCESS);
}
if (r == 0)
return (NSS_NOTFOUND);
nis_freeresult(r);
return (NSS_SUCCESS);
}
/*
* place the results from the nis_object structure into argp->buf.result
* 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;
{
int len;
char **memlist;
/*
* 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);
}
/*
* gr_name: group name
*/
if (len < 2)
return (NSS_STR_PARSE_PARSE);
return (NSS_STR_PARSE_ERANGE);
/*
* gr_passwd: group passwd
*
* POLICY: The empty password ("") is gladly accepted.
*/
if (len == 0) {
len = 1;
val = "";
}
return (NSS_STR_PARSE_ERANGE);
/*
* gr_gid: group id
*/
if (len == 0) {
return (NSS_STR_PARSE_PARSE);
} else {
if (*endnum != 0) {
return (NSS_STR_PARSE_PARSE);
}
}
/*
* gr_mem: gid list
*
* We first copy the field that looks like "grp1,grp2,..,grpn\0"
* into the buffer and advance the buffer in order to allocate
* for the gr_mem vector. We work on the group members in place
* in the buffer by replacing the "commas" with \0 and simulataneously
* advance the vector and point to a member.
*
* POLICY: We happily accept a null gid list. NIS+ tables store
* that as a single null character.
*/
if (len == 0) {
len = 1;
val = "";
}
return (NSS_STR_PARSE_ERANGE);
char c;
char *p = grstart;
if (*p != '\0') /* avoid empty string */
*memlist++ = p;
while ((c = *p) != '\0' && c != ',') {
p++;
}
if (*p == '\0') { /* all done */
*memlist = 0;
break;
}
*p++ = '\0';
grstart = p;
}
return (NSS_STR_PARSE_ERANGE);
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);
}
}
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);
}
}