summaryrefslogtreecommitdiff
path: root/usr/src/cmd/rpcsvc/nis/utils/nisaddcred/makelocalcred.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/cmd/rpcsvc/nis/utils/nisaddcred/makelocalcred.c')
-rw-r--r--usr/src/cmd/rpcsvc/nis/utils/nisaddcred/makelocalcred.c296
1 files changed, 296 insertions, 0 deletions
diff --git a/usr/src/cmd/rpcsvc/nis/utils/nisaddcred/makelocalcred.c b/usr/src/cmd/rpcsvc/nis/utils/nisaddcred/makelocalcred.c
new file mode 100644
index 0000000000..be352ed3dd
--- /dev/null
+++ b/usr/src/cmd/rpcsvc/nis/utils/nisaddcred/makelocalcred.c
@@ -0,0 +1,296 @@
+/*
+ * 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
+ * or http://www.opensolaris.org/os/licensing.
+ * 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
+ */
+/*
+ * makelocalcred.c
+ *
+ * Copyright (c) 1988-1992 Sun Microsystems Inc
+ * All Rights Reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * makelocalcred.c
+ *
+ * Make a "local" credential. The local credential is used to map from
+ * a UID in the nis_local_directory() to a principal name in some other
+ * NIS+ directory. Needless to say the principal name is required and
+ * this function must be run as the NIS+ administrator.
+ */
+
+#include <stdio.h>
+#include <pwd.h>
+#include <limits.h>
+#include <rpcsvc/nis.h>
+#include "nisaddcred.h"
+
+/*
+ * _getgroupsbymember(uname, gid_array, maxgids, numgids):
+ * This function can be found in libc/port/gen/getgrnam_r.c.
+ * It's a private interface mainly for initgroups(). It returns the
+ * group ids of groups of which the specified user is a member.
+ */
+extern int _getgroupsbymember(const char *, gid_t[], int, int);
+
+#define EVAL(e, c) (ENTRY_LEN(e, c) > 0 ? ENTRY_VAL(e, c) : "")
+
+struct cback_info {
+ char *username;
+ int gidcnt;
+ int maxgids;
+ gid_t *gidlist;
+};
+
+static
+int
+add_gidval(info, gid)
+ struct cback_info *info;
+ gid_t gid;
+{
+ int i;
+
+ for (i = 0; i < info->gidcnt; i++) {
+ if (info->gidlist[i] == gid)
+ return (1); /* don't insert dup, but not error */
+ }
+ if (info->gidcnt >= info->maxgids)
+ return (0); /* no room */
+
+ info->gidlist[info->gidcnt] = gid;
+ info->gidcnt++;
+
+ return (1);
+}
+
+int
+cback(table, entry, udata)
+ nis_name table;
+ nis_object *entry;
+ void *udata;
+{
+ struct cback_info *info = (struct cback_info *)udata;
+ char *username = info->username;
+ int len;
+ char *p;
+ char *members;
+ char *gid;
+ char *gname;
+ int gidval;
+
+ len = strlen(username);
+
+ members = EVAL(entry, 3);
+ while (*members) {
+ while (*members && isspace(*members))
+ members++;
+ if (*members == '\0')
+ break;
+
+ p = members;
+ while (*members && *members != ',')
+ members++;
+
+ if (members - p == len && strncmp(p, username, len) == 0) {
+ gid = EVAL(entry, 2);
+ if (isdigit(gid[0])) {
+ gidval = atoi(gid);
+ if (! add_gidval(info, gidval))
+ return (1); /* no more room */
+ }
+ }
+
+ if (*members == ',')
+ members++;
+ }
+
+ return (0);
+}
+
+/*
+ * Get groups from an NIS+ domain. If that doesn't yield any
+ * groups and the domain was not specified on the command line,
+ * then we try the local routines for getting group ids.
+ */
+static
+int
+__getnisgroupsbymember(domain, uid, username, basegid, maxgids, gidlist)
+ char *domain;
+ uid_t uid;
+ char *username;
+ gid_t basegid;
+ int maxgids;
+ gid_t *gidlist;
+{
+ struct cback_info info;
+ nis_result *res;
+ char name[1024];
+ u_long flags = EXPAND_NAME|MASTER_ONLY|FOLLOW_PATH|FOLLOW_LINKS;
+
+ info.username = username;
+ info.gidcnt = 0;
+ info.maxgids = NGROUPS_MAX;
+ info.gidlist = gidlist;
+
+ add_gidval(&info, basegid);
+
+ sprintf(name, "group.org_dir.%s", domain);
+ res = nis_list(name, flags, cback, (void *)&info);
+ nis_freeresult(res);
+
+#ifdef USE_LOCAL_INFO
+ /*
+ * If no domain was specified on the command line and we didn't get
+ * any extra gids from NIS+, then try getting them locally.
+ */
+ if (! explicit_domain && info.gidcnt == 1) {
+ if (uid == my_uid)
+ info.gidcnt = getgroups(info.maxgids, info.gidlist);
+ else
+ info.gidcnt = _getgroupsbymember(username, info.gidlist,
+ info.maxgids, 1);
+
+ /* if getgroups failed, put basegid back in list */
+ if (info.gidcnt <= 0) {
+ info.gidcnt = 0;
+ add_gidval(&info, basegid);
+ }
+ }
+#endif /* USE_LOCAL_INFO */
+
+ return (info.gidcnt);
+}
+
+int
+make_local_cred(nisprinc, uidstr, domain, flavor)
+ char *nisprinc;
+ char *uidstr;
+ char *domain;
+ char *flavor; /* Ignored. */
+{
+ nis_object *obj = init_entry();
+ nis_error err;
+ int i, gidlen;
+ uid_t uid;
+ gid_t gidlist[NGROUPS_MAX];
+ struct passwd *pw;
+ char nisname[NIS_MAXNAMELEN+1],
+ pdata[NIS_MAXATTRVAL+1],
+ gidstr[MAXIPRINT+1];
+ int status, addition;
+ struct passwd *domain_getpwuid();
+
+ if (!isdigit(*uidstr)) {
+ fprintf(stderr,
+ "%s: invalid local principal '%s' (must be number)\n",
+ program_name, uidstr);
+ return (0);
+ }
+
+ uid = (uid_t)atoi(uidstr);
+ if (uid == 0) {
+ fprintf(stderr, "%s: need not add LOCAL entry for root\n",
+ program_name);
+ return (0);
+ }
+
+ pw = domain_getpwuid(domain, uid);
+ if (!pw)
+ return (0);
+
+ if (nisprinc == 0)
+ sprintf(nisname, "%s.%s", pw->pw_name, domain);
+ else
+ strcpy(nisname, nisprinc);
+
+ /* Another principal owns same credentials? (exits if that happens) */
+ (void) auth_exists(nisname, uidstr, "LOCAL", domain);
+
+ addition = (cred_exists(nisname, "LOCAL", domain) == NIS_NOTFOUND);
+
+ /* build up list of group ids */
+ if ((gidlen = __getnisgroupsbymember(domain, uid,
+ pw->pw_name, pw->pw_gid, NGROUPS_MAX, gidlist)) <= 0) {
+ fprintf(stderr,
+ "Failed to get group information for user %s\n", pw->pw_name);
+ return (0);
+ }
+ pdata[0] = '\0';
+ for (i = 0; i < gidlen; i++) {
+ if ((i + 1) < gidlen)
+ sprintf(gidstr, "%d,", gidlist[i]);
+ else
+ sprintf(gidstr, "%d", gidlist[i]);
+ strcat(pdata, gidstr);
+ }
+
+ ENTRY_VAL(obj, 0) = nisname;
+ ENTRY_LEN(obj, 0) = strlen(nisname) + 1;
+
+ ENTRY_VAL(obj, 1) = "LOCAL";
+ ENTRY_LEN(obj, 1) = 6;
+
+ ENTRY_VAL(obj, 2) = uidstr;
+ ENTRY_LEN(obj, 2) = strlen(uidstr)+1;
+
+ ENTRY_VAL(obj, 3) = pdata;
+ ENTRY_LEN(obj, 3) = strlen(pdata) + 1;
+
+ ENTRY_VAL(obj, 4) = "";
+ ENTRY_LEN(obj, 4) = 0;
+
+ if (addition) {
+ obj->zo_owner = my_nisname;
+ obj->zo_group = my_group;
+ obj->zo_domain = domain;
+ /* owner: rmcd, group: rmcd */
+ obj->zo_access = ((NIS_READ_ACC|NIS_MODIFY_ACC|
+ NIS_CREATE_ACC|NIS_DESTROY_ACC)<<8) |
+ ((NIS_READ_ACC|NIS_MODIFY_ACC|
+ NIS_CREATE_ACC|NIS_DESTROY_ACC)<<16);
+ status = add_cred_obj(obj, domain);
+ } else {
+ /* columns that could have changed */
+ obj->EN_data.en_cols.en_cols_val[2].ec_flags |= EN_MODIFIED;
+ obj->EN_data.en_cols.en_cols_val[3].ec_flags |= EN_MODIFIED;
+
+ status = modify_cred_obj(obj, domain);
+ }
+ return (status);
+}
+
+
+
+
+/*
+ * Return a string representation of the "LOCAL" authentication name.
+ * In this case it is easy, its our uid.
+ */
+char *
+get_local_cred(domain, flavor)
+ char *domain; /* ignored for local case */
+ char *flavor; /* ignored */
+{
+ static char myname[MAXIPRINT];
+
+ sprintf(myname, "%d", my_uid);
+ return (myname);
+}