xref: /illumos-gate/usr/src/lib/passwdutil/nis_attr.c (revision 36e852a1)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*36e852a1SRaja Andra  * Common Development and Distribution License (the "License").
6*36e852a1SRaja Andra  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*36e852a1SRaja Andra  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdio.h>
277c478bd9Sstevel@tonic-gate #include <errno.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate #include <sys/errno.h>
317c478bd9Sstevel@tonic-gate #include <pwd.h>
327c478bd9Sstevel@tonic-gate #include <unistd.h>
337c478bd9Sstevel@tonic-gate #include <syslog.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #include <netdb.h>
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
387c478bd9Sstevel@tonic-gate #include <rpcsvc/yppasswd.h>
397c478bd9Sstevel@tonic-gate #include <rpcsvc/ypclnt.h>
407c478bd9Sstevel@tonic-gate #include <rpcsvc/yp_prot.h>
417c478bd9Sstevel@tonic-gate 
427c478bd9Sstevel@tonic-gate #include "passwdutil.h"
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate int nis_getattr(char *name, attrlist *item, pwu_repository_t *rep);
457c478bd9Sstevel@tonic-gate int nis_getpwnam(char *name, attrlist *items, pwu_repository_t *rep,
467c478bd9Sstevel@tonic-gate     void **buf);
477c478bd9Sstevel@tonic-gate int nis_update(attrlist *items, pwu_repository_t *rep, void *buf);
48*36e852a1SRaja Andra int nis_putpwnam(char *name, char *oldpw, pwu_repository_t *rep, void *buf);
497c478bd9Sstevel@tonic-gate int nis_user_to_authenticate(char *user, pwu_repository_t *rep,
507c478bd9Sstevel@tonic-gate 	char **auth_user, int *privileged);
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate  * nis function pointer table, used by passwdutil_init to initialize
547c478bd9Sstevel@tonic-gate  * the global Repository-OPerations table "rops"
557c478bd9Sstevel@tonic-gate  */
567c478bd9Sstevel@tonic-gate struct repops nis_repops = {
577c478bd9Sstevel@tonic-gate 	NULL,	/* checkhistory */
587c478bd9Sstevel@tonic-gate 	nis_getattr,
597c478bd9Sstevel@tonic-gate 	nis_getpwnam,
607c478bd9Sstevel@tonic-gate 	nis_update,
617c478bd9Sstevel@tonic-gate 	nis_putpwnam,
627c478bd9Sstevel@tonic-gate 	nis_user_to_authenticate,
637c478bd9Sstevel@tonic-gate 	NULL,	/* lock */
647c478bd9Sstevel@tonic-gate 	NULL	/* unlock */
657c478bd9Sstevel@tonic-gate };
667c478bd9Sstevel@tonic-gate 
677c478bd9Sstevel@tonic-gate /*
687c478bd9Sstevel@tonic-gate  * structure used to keep state between get/update/put calls
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate typedef struct {
717c478bd9Sstevel@tonic-gate 	char *domain;
727c478bd9Sstevel@tonic-gate 	char *master;
737c478bd9Sstevel@tonic-gate 	char *scratch;
747c478bd9Sstevel@tonic-gate 	int scratchlen;
757c478bd9Sstevel@tonic-gate 	char *c2scratch;
767c478bd9Sstevel@tonic-gate 	int c2scratchlen;
777c478bd9Sstevel@tonic-gate 	struct passwd *pwd;
787c478bd9Sstevel@tonic-gate } nisbuf_t;
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate /*
817c478bd9Sstevel@tonic-gate  * Are we a 'privileged' process? Yes if we are running on the
827c478bd9Sstevel@tonic-gate  * NIS server AND we are root...
837c478bd9Sstevel@tonic-gate  */
847c478bd9Sstevel@tonic-gate int
nis_privileged(nisbuf_t * nisbuf)857c478bd9Sstevel@tonic-gate nis_privileged(nisbuf_t *nisbuf)
867c478bd9Sstevel@tonic-gate {
877c478bd9Sstevel@tonic-gate 	char thishost[MAXHOSTNAMELEN];
887c478bd9Sstevel@tonic-gate 	if (gethostname(thishost, sizeof (thishost)) == -1) {
897c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "passwdutil.so: Can't get hostname");
907c478bd9Sstevel@tonic-gate 		return (0);
917c478bd9Sstevel@tonic-gate 	}
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 	if (strcmp(nisbuf->master, thishost) != 0)
947c478bd9Sstevel@tonic-gate 		return (0);
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 	/* We're running on the NIS server. */
977c478bd9Sstevel@tonic-gate 	return (getuid() == 0);
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate /*
1017c478bd9Sstevel@tonic-gate  * nis_to_pwd()
1027c478bd9Sstevel@tonic-gate  *
1037c478bd9Sstevel@tonic-gate  * convert password-entry-line to "struct passwd"
1047c478bd9Sstevel@tonic-gate  */
1057c478bd9Sstevel@tonic-gate void
nis_to_pwd(char * nis,struct passwd * pwd)1067c478bd9Sstevel@tonic-gate nis_to_pwd(char *nis, struct passwd *pwd)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	pwd->pw_name = strsep(&nis, ":");
1097c478bd9Sstevel@tonic-gate 	pwd->pw_passwd = strsep(&nis, ":");
1107c478bd9Sstevel@tonic-gate 	pwd->pw_uid = atoi(strsep(&nis, ":"));
1117c478bd9Sstevel@tonic-gate 	pwd->pw_gid = atoi(strsep(&nis, ":"));
1127c478bd9Sstevel@tonic-gate 	pwd->pw_gecos = strsep(&nis, ":");
1137c478bd9Sstevel@tonic-gate 	pwd->pw_dir = strsep(&nis, ":");
1147c478bd9Sstevel@tonic-gate 	pwd->pw_shell = nis;
1157c478bd9Sstevel@tonic-gate 	if (pwd->pw_shell[0])
1167c478bd9Sstevel@tonic-gate 		pwd->pw_shell[strlen(pwd->pw_shell)-1] = '\0';
1177c478bd9Sstevel@tonic-gate }
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate /*
1207c478bd9Sstevel@tonic-gate  * nis_user_to_authenticate(name, rep, auth_user, privileged)
1217c478bd9Sstevel@tonic-gate  *
1227c478bd9Sstevel@tonic-gate  */
1237c478bd9Sstevel@tonic-gate /*ARGSUSED*/
1247c478bd9Sstevel@tonic-gate int
nis_user_to_authenticate(char * user,pwu_repository_t * rep,char ** auth_user,int * privileged)1257c478bd9Sstevel@tonic-gate nis_user_to_authenticate(char *user, pwu_repository_t *rep,
1267c478bd9Sstevel@tonic-gate 	char **auth_user, int *privileged)
1277c478bd9Sstevel@tonic-gate {
1287c478bd9Sstevel@tonic-gate 	nisbuf_t *buf = NULL;
1297c478bd9Sstevel@tonic-gate 	int res;
1307c478bd9Sstevel@tonic-gate 	attrlist attr_tmp[1];
1317c478bd9Sstevel@tonic-gate 	uid_t uid;
1327c478bd9Sstevel@tonic-gate 
1337c478bd9Sstevel@tonic-gate 	/*
1347c478bd9Sstevel@tonic-gate 	 * special NIS case: don't bother to get "root" from NIS
1357c478bd9Sstevel@tonic-gate 	 */
1367c478bd9Sstevel@tonic-gate 	if (strcmp(user, "root") == 0)
1377c478bd9Sstevel@tonic-gate 		return (PWU_NOT_FOUND);
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	attr_tmp[0].type = ATTR_UID;
1407c478bd9Sstevel@tonic-gate 	attr_tmp[0].next = NULL;
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	res = nis_getpwnam(user, &attr_tmp[0], rep, (void **)&buf);
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	if (res != PWU_SUCCESS)
1457c478bd9Sstevel@tonic-gate 		return (res);
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 	if (nis_privileged(buf)) {
1487c478bd9Sstevel@tonic-gate 		*privileged = 1;
1497c478bd9Sstevel@tonic-gate 		*auth_user = NULL;
1507c478bd9Sstevel@tonic-gate 		res = PWU_SUCCESS;
1517c478bd9Sstevel@tonic-gate 	} else {
1527c478bd9Sstevel@tonic-gate 		uid = getuid();
1537c478bd9Sstevel@tonic-gate 
1547c478bd9Sstevel@tonic-gate 		*privileged = (uid == (uid_t)0);
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 		/* root, or user herself can change attributes */
1577c478bd9Sstevel@tonic-gate 		if (uid == 0 || uid == buf->pwd->pw_uid) {
1587c478bd9Sstevel@tonic-gate 			*auth_user = strdup(user);
1597c478bd9Sstevel@tonic-gate 			res = PWU_SUCCESS;
1607c478bd9Sstevel@tonic-gate 		} else {
1617c478bd9Sstevel@tonic-gate 			res = PWU_DENIED;
1627c478bd9Sstevel@tonic-gate 		}
1637c478bd9Sstevel@tonic-gate 	}
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 	/*
1667c478bd9Sstevel@tonic-gate 	 * Do not release buf->domain.
1677c478bd9Sstevel@tonic-gate 	 * It's been set by yp_get_default_domain()
1687c478bd9Sstevel@tonic-gate 	 * and must not be freed.
1697c478bd9Sstevel@tonic-gate 	 * See man page yp_get_default_domain(3NSL)
1707c478bd9Sstevel@tonic-gate 	 * for details.
1717c478bd9Sstevel@tonic-gate 	 */
1727c478bd9Sstevel@tonic-gate 	if (buf->master)
1737c478bd9Sstevel@tonic-gate 		free(buf->master);
1747c478bd9Sstevel@tonic-gate 	if (buf->scratch)
1757c478bd9Sstevel@tonic-gate 		free(buf->scratch);
1767c478bd9Sstevel@tonic-gate 	if (buf->c2scratch)
1777c478bd9Sstevel@tonic-gate 		free(buf->c2scratch);
1787c478bd9Sstevel@tonic-gate 	free(buf->pwd);
1797c478bd9Sstevel@tonic-gate 	free(buf);
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	return (res);
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate  * nis_getattr(name, items, rep)
1877c478bd9Sstevel@tonic-gate  *
1887c478bd9Sstevel@tonic-gate  * get account attributes specified in 'items'
1897c478bd9Sstevel@tonic-gate  */
1907c478bd9Sstevel@tonic-gate int
nis_getattr(char * name,attrlist * items,pwu_repository_t * rep)1917c478bd9Sstevel@tonic-gate nis_getattr(char *name, attrlist *items, pwu_repository_t *rep)
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 	nisbuf_t *nisbuf = NULL;
1947c478bd9Sstevel@tonic-gate 	struct passwd *pw;
1957c478bd9Sstevel@tonic-gate 	attrlist *w;
1967c478bd9Sstevel@tonic-gate 	int res;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	res = nis_getpwnam(name, items, rep, (void **)&nisbuf);
1997c478bd9Sstevel@tonic-gate 	if (res != PWU_SUCCESS)
2007c478bd9Sstevel@tonic-gate 		return (res);
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 	pw = nisbuf->pwd;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 	for (w = items; w != NULL; w = w->next) {
2057c478bd9Sstevel@tonic-gate 		switch (w->type) {
2067c478bd9Sstevel@tonic-gate 		case ATTR_NAME:
2077c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_name)) == NULL)
2087c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
2097c478bd9Sstevel@tonic-gate 			break;
2107c478bd9Sstevel@tonic-gate 		case ATTR_COMMENT:
2117c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_comment)) == NULL)
2127c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
2137c478bd9Sstevel@tonic-gate 			break;
2147c478bd9Sstevel@tonic-gate 		case ATTR_GECOS:
2157c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_gecos)) == NULL)
2167c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
2177c478bd9Sstevel@tonic-gate 			break;
2187c478bd9Sstevel@tonic-gate 		case ATTR_HOMEDIR:
2197c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_dir)) == NULL)
2207c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
2217c478bd9Sstevel@tonic-gate 			break;
2227c478bd9Sstevel@tonic-gate 		case ATTR_SHELL:
2237c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_shell)) == NULL)
2247c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
2257c478bd9Sstevel@tonic-gate 			break;
2267c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD:
2277c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD_SERVER_POLICY:
2287c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup(pw->pw_passwd)) == NULL)
2297c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
2307c478bd9Sstevel@tonic-gate 			break;
2317c478bd9Sstevel@tonic-gate 		case ATTR_REP_NAME:
2327c478bd9Sstevel@tonic-gate 			if ((w->data.val_s = strdup("nis")) == NULL)
2337c478bd9Sstevel@tonic-gate 				res = PWU_NOMEM;
2347c478bd9Sstevel@tonic-gate 			break;
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 		/* integer values */
2377c478bd9Sstevel@tonic-gate 		case ATTR_UID:
2387c478bd9Sstevel@tonic-gate 			w->data.val_i = nisbuf->pwd->pw_uid;
2397c478bd9Sstevel@tonic-gate 			break;
2407c478bd9Sstevel@tonic-gate 		case ATTR_GID:
2417c478bd9Sstevel@tonic-gate 			w->data.val_i = nisbuf->pwd->pw_gid;
2427c478bd9Sstevel@tonic-gate 			break;
2437c478bd9Sstevel@tonic-gate 		case ATTR_LSTCHG:
2447c478bd9Sstevel@tonic-gate 		case ATTR_MIN:
2457c478bd9Sstevel@tonic-gate 		case ATTR_MAX:
2467c478bd9Sstevel@tonic-gate 		case ATTR_WARN:
2477c478bd9Sstevel@tonic-gate 		case ATTR_INACT:
2487c478bd9Sstevel@tonic-gate 		case ATTR_EXPIRE:
2497c478bd9Sstevel@tonic-gate 		case ATTR_FLAG:
2507c478bd9Sstevel@tonic-gate 		case ATTR_AGE:
2517c478bd9Sstevel@tonic-gate 			w->data.val_i = -1;	/* not used for NIS */
2527c478bd9Sstevel@tonic-gate 			break;
2537c478bd9Sstevel@tonic-gate 		default:
2547c478bd9Sstevel@tonic-gate 			break;
2557c478bd9Sstevel@tonic-gate 		}
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 	/*
2597c478bd9Sstevel@tonic-gate 	 * Do not release nisbuf->domain.
2607c478bd9Sstevel@tonic-gate 	 * It's been set by yp_get_default_domain()
2617c478bd9Sstevel@tonic-gate 	 * and must not be freed.
2627c478bd9Sstevel@tonic-gate 	 * See man page yp_get_default_domain(3NSL)
2637c478bd9Sstevel@tonic-gate 	 * for details.
2647c478bd9Sstevel@tonic-gate 	 */
2657c478bd9Sstevel@tonic-gate 	if (nisbuf->master)
2667c478bd9Sstevel@tonic-gate 		free(nisbuf->master);
2677c478bd9Sstevel@tonic-gate 	if (nisbuf->scratch)
2687c478bd9Sstevel@tonic-gate 		free(nisbuf->scratch);
2697c478bd9Sstevel@tonic-gate 	if (nisbuf->c2scratch)
2707c478bd9Sstevel@tonic-gate 		free(nisbuf->c2scratch);
2717c478bd9Sstevel@tonic-gate 	free(nisbuf->pwd);
2727c478bd9Sstevel@tonic-gate 	free(nisbuf);
2737c478bd9Sstevel@tonic-gate 
2747c478bd9Sstevel@tonic-gate 	return (res);
2757c478bd9Sstevel@tonic-gate }
2767c478bd9Sstevel@tonic-gate 
2777c478bd9Sstevel@tonic-gate /*
2787c478bd9Sstevel@tonic-gate  * nis_getpwnam(name, items, rep)
2797c478bd9Sstevel@tonic-gate  *
2807c478bd9Sstevel@tonic-gate  * Get the account information of user 'name'
2817c478bd9Sstevel@tonic-gate  */
2827c478bd9Sstevel@tonic-gate /*ARGSUSED*/
2837c478bd9Sstevel@tonic-gate int
nis_getpwnam(char * name,attrlist * items,pwu_repository_t * rep,void ** buf)2847c478bd9Sstevel@tonic-gate nis_getpwnam(char *name, attrlist *items, pwu_repository_t *rep,
2857c478bd9Sstevel@tonic-gate     void **buf)
2867c478bd9Sstevel@tonic-gate {
2877c478bd9Sstevel@tonic-gate 	nisbuf_t *nisbuf;
2887c478bd9Sstevel@tonic-gate 	int nisresult;
2897c478bd9Sstevel@tonic-gate 
2907c478bd9Sstevel@tonic-gate 	nisbuf = calloc(sizeof (*nisbuf), 1);
2917c478bd9Sstevel@tonic-gate 	if (nisbuf == NULL)
2927c478bd9Sstevel@tonic-gate 		return (PWU_NOMEM);
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	nisbuf->pwd = malloc(sizeof (struct passwd));
2957c478bd9Sstevel@tonic-gate 	if (nisbuf->pwd == NULL) {
2967c478bd9Sstevel@tonic-gate 		free(nisbuf);
2977c478bd9Sstevel@tonic-gate 		return (PWU_NOMEM);
2987c478bd9Sstevel@tonic-gate 	}
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	/*
3017c478bd9Sstevel@tonic-gate 	 * Do not release nisbuf->domain.
3027c478bd9Sstevel@tonic-gate 	 * It is going to be set by yp_get_default_domain()
3037c478bd9Sstevel@tonic-gate 	 * and must not be freed.
3047c478bd9Sstevel@tonic-gate 	 * See man page yp_get_default_domain(3NSL)
3057c478bd9Sstevel@tonic-gate 	 * for details.
3067c478bd9Sstevel@tonic-gate 	 */
3077c478bd9Sstevel@tonic-gate 	if (yp_get_default_domain(&nisbuf->domain) != 0) {
3087c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "passwdutil.so: can't get domain");
3097c478bd9Sstevel@tonic-gate 		free(nisbuf->pwd);
3107c478bd9Sstevel@tonic-gate 		free(nisbuf);
3117c478bd9Sstevel@tonic-gate 		return (PWU_SERVER_ERROR);
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	if (yp_master(nisbuf->domain, "passwd.byname", &nisbuf->master) != 0) {
3157c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
316*36e852a1SRaja Andra 		    "passwdutil.so: can't get master for passwd map");
3177c478bd9Sstevel@tonic-gate 		if (nisbuf->master)
3187c478bd9Sstevel@tonic-gate 			free(nisbuf->master);
3197c478bd9Sstevel@tonic-gate 		free(nisbuf->pwd);
3207c478bd9Sstevel@tonic-gate 		free(nisbuf);
3217c478bd9Sstevel@tonic-gate 		return (PWU_SERVER_ERROR);
3227c478bd9Sstevel@tonic-gate 	}
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate 	nisresult = yp_match(nisbuf->domain, "passwd.byname", name,
325*36e852a1SRaja Andra 	    strlen(name), &(nisbuf->scratch),
326*36e852a1SRaja Andra 	    &(nisbuf->scratchlen));
3277c478bd9Sstevel@tonic-gate 	if (nisresult != 0) {
3287c478bd9Sstevel@tonic-gate 		(void) free(nisbuf->pwd);
3297c478bd9Sstevel@tonic-gate 		if (nisbuf->scratch)
3307c478bd9Sstevel@tonic-gate 			(void) free(nisbuf->scratch);
3317c478bd9Sstevel@tonic-gate 		if (nisbuf->master)
3327c478bd9Sstevel@tonic-gate 			(void) free(nisbuf->master);
3337c478bd9Sstevel@tonic-gate 		(void) free(nisbuf);
3347c478bd9Sstevel@tonic-gate 		return (PWU_NOT_FOUND);
3357c478bd9Sstevel@tonic-gate 	}
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	nis_to_pwd(nisbuf->scratch, nisbuf->pwd);
3387c478bd9Sstevel@tonic-gate 
3397c478bd9Sstevel@tonic-gate 	/*
3407c478bd9Sstevel@tonic-gate 	 * check for the C2 security flag "##" in the passwd field.
3417c478bd9Sstevel@tonic-gate 	 * If the first 2 chars in the passwd field is "##", get
3427c478bd9Sstevel@tonic-gate 	 * the user's passwd from passwd.adjunct.byname map.
3437c478bd9Sstevel@tonic-gate 	 * The lookup to this passwd.adjunct.byname map will only
3447c478bd9Sstevel@tonic-gate 	 * succeed if the caller's uid is 0 because only root user
3457c478bd9Sstevel@tonic-gate 	 * can use privilege port.
3467c478bd9Sstevel@tonic-gate 	 */
3477c478bd9Sstevel@tonic-gate 	if (nisbuf->pwd->pw_passwd[0] == '#' &&
3487c478bd9Sstevel@tonic-gate 	    nisbuf->pwd->pw_passwd[1] == '#') {
3497c478bd9Sstevel@tonic-gate 		char *key = &nisbuf->pwd->pw_passwd[2];
3507c478bd9Sstevel@tonic-gate 		int keylen;
3517c478bd9Sstevel@tonic-gate 		char *p;
3527c478bd9Sstevel@tonic-gate 
3537c478bd9Sstevel@tonic-gate 		keylen = strlen(key);
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 		nisresult = yp_match(nisbuf->domain, "passwd.adjunct.byname",
356*36e852a1SRaja Andra 		    key, keylen, &(nisbuf->c2scratch),
357*36e852a1SRaja Andra 		    &(nisbuf->c2scratchlen));
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 		if (nisresult == 0 && nisbuf->c2scratch != NULL) {
3607c478bd9Sstevel@tonic-gate 			/* Skip username (first field), and pick up password */
3617c478bd9Sstevel@tonic-gate 			p = nisbuf->c2scratch;
3627c478bd9Sstevel@tonic-gate 			(void) strsep(&p, ":");
3637c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_passwd = strsep(&p, ":");
3647c478bd9Sstevel@tonic-gate 		}
3657c478bd9Sstevel@tonic-gate 	}
3667c478bd9Sstevel@tonic-gate 
3677c478bd9Sstevel@tonic-gate 	*buf = (void *)nisbuf;
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	return (PWU_SUCCESS);
3707c478bd9Sstevel@tonic-gate }
3717c478bd9Sstevel@tonic-gate 
3727c478bd9Sstevel@tonic-gate /*
3737c478bd9Sstevel@tonic-gate  * nis_update(items, rep, buf)
3747c478bd9Sstevel@tonic-gate  *
3757c478bd9Sstevel@tonic-gate  * update the information in "buf" with the attribute/values
3767c478bd9Sstevel@tonic-gate  * specified in "items".
3777c478bd9Sstevel@tonic-gate  */
3787c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3797c478bd9Sstevel@tonic-gate int
nis_update(attrlist * items,pwu_repository_t * rep,void * buf)3807c478bd9Sstevel@tonic-gate nis_update(attrlist *items, pwu_repository_t *rep, void *buf)
3817c478bd9Sstevel@tonic-gate {
3827c478bd9Sstevel@tonic-gate 	attrlist *p;
3837c478bd9Sstevel@tonic-gate 	nisbuf_t *nisbuf = (nisbuf_t *)buf;
3847c478bd9Sstevel@tonic-gate 	char *salt;
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate 	for (p = items; p != NULL; p = p->next) {
3877c478bd9Sstevel@tonic-gate 		switch (p->type) {
3887c478bd9Sstevel@tonic-gate 		case ATTR_NAME:
3897c478bd9Sstevel@tonic-gate 			break;
3907c478bd9Sstevel@tonic-gate 		/*
3917c478bd9Sstevel@tonic-gate 		 * Nothing special needs to be done for
3927c478bd9Sstevel@tonic-gate 		 * server policy
3937c478bd9Sstevel@tonic-gate 		 */
3947c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD:
3957c478bd9Sstevel@tonic-gate 		case ATTR_PASSWD_SERVER_POLICY:
3967c478bd9Sstevel@tonic-gate 			salt = crypt_gensalt(
3977c478bd9Sstevel@tonic-gate 			    nisbuf->pwd->pw_passwd, nisbuf->pwd);
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 			if (salt == NULL) {
4007c478bd9Sstevel@tonic-gate 				if (errno == ENOMEM)
4017c478bd9Sstevel@tonic-gate 					return (PWU_NOMEM);
4027c478bd9Sstevel@tonic-gate 				else {
4037c478bd9Sstevel@tonic-gate 					/* algorithm problem? */
4047c478bd9Sstevel@tonic-gate 					syslog(LOG_AUTH | LOG_ALERT,
4057c478bd9Sstevel@tonic-gate 					    "passwdutil: crypt_gensalt "
4067c478bd9Sstevel@tonic-gate 					    "%m");
4077c478bd9Sstevel@tonic-gate 					return (PWU_UPDATE_FAILED);
4087c478bd9Sstevel@tonic-gate 				}
4097c478bd9Sstevel@tonic-gate 			}
4107c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_passwd = crypt(p->data.val_s, salt);
4117c478bd9Sstevel@tonic-gate 			free(salt);
4127c478bd9Sstevel@tonic-gate 			break;
4137c478bd9Sstevel@tonic-gate 		case ATTR_UID:
4147c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_uid = (uid_t)p->data.val_i;
4157c478bd9Sstevel@tonic-gate 			break;
4167c478bd9Sstevel@tonic-gate 		case ATTR_GID:
4177c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_gid = (gid_t)p->data.val_i;
4187c478bd9Sstevel@tonic-gate 			break;
4197c478bd9Sstevel@tonic-gate 		case ATTR_AGE:
4207c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_age = p->data.val_s;
4217c478bd9Sstevel@tonic-gate 			break;
4227c478bd9Sstevel@tonic-gate 		case ATTR_COMMENT:
4237c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_comment = p->data.val_s;
4247c478bd9Sstevel@tonic-gate 			break;
4257c478bd9Sstevel@tonic-gate 		case ATTR_GECOS:
4267c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_gecos = p->data.val_s;
4277c478bd9Sstevel@tonic-gate 			break;
4287c478bd9Sstevel@tonic-gate 		case ATTR_HOMEDIR:
4297c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_dir = p->data.val_s;
4307c478bd9Sstevel@tonic-gate 			break;
4317c478bd9Sstevel@tonic-gate 		case ATTR_SHELL:
4327c478bd9Sstevel@tonic-gate 			nisbuf->pwd->pw_shell = p->data.val_s;
4337c478bd9Sstevel@tonic-gate 			break;
4347c478bd9Sstevel@tonic-gate 		case ATTR_LSTCHG:
4357c478bd9Sstevel@tonic-gate 		case ATTR_MIN:
4367c478bd9Sstevel@tonic-gate 		case ATTR_MAX:
4377c478bd9Sstevel@tonic-gate 		case ATTR_WARN:
4387c478bd9Sstevel@tonic-gate 		case ATTR_INACT:
4397c478bd9Sstevel@tonic-gate 		case ATTR_EXPIRE:
4407c478bd9Sstevel@tonic-gate 		case ATTR_FLAG:
4417c478bd9Sstevel@tonic-gate 		default:
4427c478bd9Sstevel@tonic-gate 			break;
4437c478bd9Sstevel@tonic-gate 		}
4447c478bd9Sstevel@tonic-gate 	}
4457c478bd9Sstevel@tonic-gate 	return (PWU_SUCCESS);
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate /*
449*36e852a1SRaja Andra  * nis_putpwnam(name, oldpw, rep, buf)
4507c478bd9Sstevel@tonic-gate  *
4517c478bd9Sstevel@tonic-gate  * Update the NIS server. The passwd structure in buf will be sent to
4527c478bd9Sstevel@tonic-gate  * the server for user "name" authenticating with password "oldpw".
4537c478bd9Sstevel@tonic-gate  */
4547c478bd9Sstevel@tonic-gate /*ARGSUSED*/
4557c478bd9Sstevel@tonic-gate int
nis_putpwnam(char * name,char * oldpw,pwu_repository_t * rep,void * buf)456*36e852a1SRaja Andra nis_putpwnam(char *name, char *oldpw, pwu_repository_t *rep,
4577c478bd9Sstevel@tonic-gate 	void *buf)
4587c478bd9Sstevel@tonic-gate {
4597c478bd9Sstevel@tonic-gate 	nisbuf_t *nisbuf = (nisbuf_t *)buf;
4607c478bd9Sstevel@tonic-gate 	struct yppasswd yppasswd;
4617c478bd9Sstevel@tonic-gate 	struct netconfig *nconf;
4627c478bd9Sstevel@tonic-gate 	int ok;
4637c478bd9Sstevel@tonic-gate 	enum clnt_stat ans;
4647c478bd9Sstevel@tonic-gate 	CLIENT *client;
4657c478bd9Sstevel@tonic-gate 	struct timeval timeout;
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 	if (strcmp(name, "root") == 0)
4687c478bd9Sstevel@tonic-gate 		return (PWU_NOT_FOUND);
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 	yppasswd.oldpass = oldpw ? oldpw : "";
4717c478bd9Sstevel@tonic-gate 	yppasswd.newpw = *nisbuf->pwd;
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	/*
4747c478bd9Sstevel@tonic-gate 	 * If we are privileged, we create a ticlts connection to the
4757c478bd9Sstevel@tonic-gate 	 * NIS server so that it can check our credentials
4767c478bd9Sstevel@tonic-gate 	 */
4777c478bd9Sstevel@tonic-gate 	if (nis_privileged(nisbuf)) {
4787c478bd9Sstevel@tonic-gate 		nconf = getnetconfigent("ticlts");
4797c478bd9Sstevel@tonic-gate 		if (!nconf) {
4807c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR,
481*36e852a1SRaja Andra 			    "passwdutil.so: Couldn't get netconfig entry");
4827c478bd9Sstevel@tonic-gate 			return (PWU_SYSTEM_ERROR);
4837c478bd9Sstevel@tonic-gate 		}
4847c478bd9Sstevel@tonic-gate 		client = clnt_tp_create(nisbuf->master, YPPASSWDPROG,
485*36e852a1SRaja Andra 		    YPPASSWDVERS, nconf);
4867c478bd9Sstevel@tonic-gate 		freenetconfigent(nconf);
4877c478bd9Sstevel@tonic-gate 	} else {
4887c478bd9Sstevel@tonic-gate 		/* Try IPv6 first */
4897c478bd9Sstevel@tonic-gate 		client = clnt_create(nisbuf->master, YPPASSWDPROG,
490*36e852a1SRaja Andra 		    YPPASSWDVERS, "udp6");
4917c478bd9Sstevel@tonic-gate 		if (client == NULL)
4927c478bd9Sstevel@tonic-gate 			client = clnt_create(nisbuf->master, YPPASSWDPROG,
493*36e852a1SRaja Andra 			    YPPASSWDVERS, "udp");
4947c478bd9Sstevel@tonic-gate 	}
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	if (client == NULL) {
4977c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR,
498*36e852a1SRaja Andra 		    "passwdutil.so: couldn't create client to YP master");
4997c478bd9Sstevel@tonic-gate 		return (PWU_SERVER_ERROR);
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate 	timeout.tv_usec = 0;
5037c478bd9Sstevel@tonic-gate 	timeout.tv_sec = 55;	/* ndp uses 55 seconds */
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate 	ans = CLNT_CALL(client, YPPASSWDPROC_UPDATE, xdr_yppasswd,
506*36e852a1SRaja Andra 	    (char *)&yppasswd, xdr_int, (char *)&ok, timeout);
5077c478bd9Sstevel@tonic-gate 
5087c478bd9Sstevel@tonic-gate 	if (nisbuf->pwd)
5097c478bd9Sstevel@tonic-gate 		(void) free(nisbuf->pwd);
5107c478bd9Sstevel@tonic-gate 	if (nisbuf->master)
5117c478bd9Sstevel@tonic-gate 		(void) free(nisbuf->master);
5127c478bd9Sstevel@tonic-gate 	if (nisbuf->scratch)
5137c478bd9Sstevel@tonic-gate 		(void) free(nisbuf->scratch);
5147c478bd9Sstevel@tonic-gate 	if (nisbuf->c2scratch)
5157c478bd9Sstevel@tonic-gate 		(void) free(nisbuf->c2scratch);
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	(void) clnt_destroy(client);
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	if (ans != RPC_SUCCESS) {
5207c478bd9Sstevel@tonic-gate 		return (PWU_UPDATE_FAILED);
5217c478bd9Sstevel@tonic-gate 	}
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 	/* These errors are obtained from the yppasswdd.c code */
5247c478bd9Sstevel@tonic-gate 	switch (ok) {
5257c478bd9Sstevel@tonic-gate 		case 2: return (PWU_DENIED);
5267c478bd9Sstevel@tonic-gate 		case 8: return (PWU_BUSY);
5277c478bd9Sstevel@tonic-gate 		case 9: return (PWU_SERVER_ERROR);
5287c478bd9Sstevel@tonic-gate 		case 4: return (PWU_NOT_FOUND);
5297c478bd9Sstevel@tonic-gate 		case 3: return (PWU_NO_CHANGE);
5307c478bd9Sstevel@tonic-gate 		case 7: return (PWU_DENIED);
5317c478bd9Sstevel@tonic-gate 		case 0: return (PWU_SUCCESS);
5327c478bd9Sstevel@tonic-gate 		default: return (PWU_SYSTEM_ERROR);
5337c478bd9Sstevel@tonic-gate 	}
5347c478bd9Sstevel@tonic-gate }
535