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,
3167c478bd9Sstevel@tonic-gate "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,
3257c478bd9Sstevel@tonic-gate strlen(name), &(nisbuf->scratch),
3267c478bd9Sstevel@tonic-gate &(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",
3567c478bd9Sstevel@tonic-gate key, keylen, &(nisbuf->c2scratch),
3577c478bd9Sstevel@tonic-gate &(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,
4817c478bd9Sstevel@tonic-gate "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,
4857c478bd9Sstevel@tonic-gate 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,
4907c478bd9Sstevel@tonic-gate YPPASSWDVERS, "udp6");
4917c478bd9Sstevel@tonic-gate if (client == NULL)
4927c478bd9Sstevel@tonic-gate client = clnt_create(nisbuf->master, YPPASSWDPROG,
4937c478bd9Sstevel@tonic-gate YPPASSWDVERS, "udp");
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate if (client == NULL) {
4977c478bd9Sstevel@tonic-gate syslog(LOG_ERR,
4987c478bd9Sstevel@tonic-gate "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,
5067c478bd9Sstevel@tonic-gate (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